55 #include "arch/isa_traits.hh" 59 #include "debug/IdeDisk.hh" 66 :
SimObject(p), ctrl(NULL), image(p->image), diskDelay(p->delay),
88 if (lba_size >= 16383*16*63) {
95 else if (lba_size == 0)
96 panic(
"Bad IDE image size: 0\n");
100 if ((lba_size / sectors) >= 16)
103 heads = (lba_size / sectors);
105 cylinders = lba_size / (heads * sectors);
170 }
else if (
id ==
DEV1) {
174 panic(
"Invalid device ID: %#x\n",
id);
201 panic(
"Access to unset controller!\n");
212 if (size ==
sizeof(uint16_t)) {
214 }
else if (size ==
sizeof(uint32_t)) {
219 panic(
"Data read of unsupported size %d.\n", size);
224 assert(size ==
sizeof(uint8_t));
249 panic(
"Invalid IDE command register offset: %#x\n", offset);
251 DPRINTF(
IdeDisk,
"Read to disk at offset: %#x data %#x\n", offset, *data);
257 assert(size ==
sizeof(uint8_t));
260 panic(
"Invalid IDE control register offset: %#x\n", offset);
261 DPRINTF(
IdeDisk,
"Read to disk at offset: %#x data %#x\n", offset, *data);
268 if (size ==
sizeof(uint16_t)) {
270 }
else if (size ==
sizeof(uint32_t)) {
275 panic(
"Data write of unsupported size %d.\n", size);
281 assert(size ==
sizeof(uint8_t));
306 panic(
"Invalid IDE command register offset: %#x\n", offset);
308 DPRINTF(
IdeDisk,
"Write to disk at offset: %#x data %#x\n", offset,
316 panic(
"Invalid IDE control register offset: %#x\n", offset);
328 DPRINTF(
IdeDisk,
"Write to disk at offset: %#x data %#x\n", offset,
346 panic(
"Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
367 "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
398 using namespace Stats;
400 .
name(
name() +
".dma_read_full_pages")
401 .
desc(
"Number of full page size DMA reads (not PRD).")
405 .
desc(
"Number of bytes transfered via DMA reads (not PRD).")
409 .
desc(
"Number of DMA read transactions (not PRD).")
413 .
name(
name() +
".dma_write_full_pages")
414 .
desc(
"Number of full page size DMA writes.")
418 .
desc(
"Number of bytes transfered via DMA writes.")
422 .
desc(
"Number of DMA write transactions.")
468 uint32_t bytesWritten = 0;
493 uint32_t bytesRead = 0;
495 DPRINTF(
IdeDisk,
"doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
535 DPRINTF(
IdeDisk,
"doDmaWrite: not done curPrd byte count %d, eot %#x\n",
543 DPRINTF(
IdeDisk,
"doDmaWrite: done curPrd byte count %d, eot %#x\n",
555 DPRINTF(
IdeDisk,
"doWriteDone: curPrd byte count %d, eot %#x cmd bytes left:%d\n",
574 uint32_t bytesRead =
image->
read(data, sector);
577 panic(
"Can't read from %s. Only %d of %d read. errno=%d\n",
584 uint32_t bytesWritten =
image->
write(data, sector);
587 panic(
"Can't write to %s. Only %d of %d written. errno=%d\n",
599 panic(
"Inconsistent DMA state, should be in Dma_Start!\n");
602 panic(
"Inconsistent device state for DMA start!\n");
617 panic(
"Inconsistent DMA state, should be Start or Transfer!");
620 panic(
"Inconsistent device state, should be Transfer or Prepare!\n");
670 panic(
"Attempt to perform CHS access, only supports LBA\n");
688 panic(
"Attempt to perform CHS access, only supports LBA\n");
707 panic(
"Attempt to perform CHS access, only supports LBA\n");
746 panic(
"Attempt to post an interrupt with one pending\n");
761 panic(
"Attempt to clear a non-pending interrupt\n");
895 panic(
"DEBUG: READING DATA ONE BYTE AT A TIME!\n");
971 panic(
"DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
1022 panic(
"Inconsistent DMA state, should be Dma_Idle\n");
1065 DPRINTF(
IdeDisk,
"Disk still busy aborting previous DMA command\n");
1115 assert(eventCount <= 1);
1206 IdeDiskParams::create()
#define panic(...)
This implements a cprintf based panic() function.
bool nIENBit
Interrupt enable bit.
bool next()
Advance generator to next chunk.
void reset(int id)
Reset the device state.
void writeCommand(const Addr offset, int size, const uint8_t *data)
~IdeDisk()
Delete the data buffer.
DmaState_t dmaState
Dma state.
Addr pciToDma(Addr pci_addr) const
ChunkGenerator * dmaWriteCG
EventFunctionWrapper dmaReadEvent
uint8_t atap_piomode_supp
Tick when() const
Get the time that the event is scheduled.
bool isDiskSelected(IdeDisk *diskPtr)
See if a disk is selected based on its pointer.
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
struct PrdEntry PrdEntry_t
uint32_t curPrdAddr
PRD table base address.
void regStats() override
Register Statistics.
void serialize(CheckpointOut &cp) const override
Serialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Device model for an IDE disk.
uint8_t atap_capabilities1
#define WDCC_STANDBY_IMMED
DrainState drainState() const
Return the current drain state of an object.
int devID
Device ID (master=0/slave=1)
DiskImage * image
The image that contains the data of this disk.
virtual void regStats()
Callback to set stat parameters.
Simple PCI IDE controller with bus mastering capability and UDMA modeled after controller in the Inte...
bool dmaAborted
DMA Aborted.
uint16_t atap_hwreset_res
uint32_t drqBytesLeft
Number of bytes left in DRQ block.
void updateState(DevAction_t action)
Stats::Scalar dmaWriteBytes
virtual std::streampos size() const =0
uint8_t atap_curmulti_valid
#define UNSERIALIZE_SCALAR(scalar)
unsigned size() const
Return size in bytes of current chunk.
Tick curTick()
The current simulated tick.
bool scheduled() const
Determine if the current event is scheduled.
uint32_t cmdBytesLeft
Number of bytes left in command data transfer.
void readCommand(const Addr offset, int size, uint8_t *data)
#define WDSF_READ_NATIVE_MAX
uint64_t Tick
Tick count type.
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, uint32_t sid, uint32_t ssid, Tick delay=0)
Stats::Scalar dmaReadBytes
This class takes an arbitrary memory region (address/length pair) and generates a series of appropria...
uint8_t atap_udmamode_supp
virtual std::streampos write(const uint8_t *data, std::streampos offset)=0
#define SERIALIZE_ARRAY(member, size)
struct ataparams driveID
Drive identification structure for this disk.
EventFunctionWrapper dmaWriteEvent
void writeControl(const Addr offset, int size, const uint8_t *data)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
#define ULL(N)
uint64_t constant
virtual const std::string name() const
#define DMA_BACKOFF_PERIOD
bool done() const
Are we done? That is, did the last call to next() advance past the end of the region?
uint32_t curSector
Current sector in access.
Addr pageBytes
Size of OS pages.
uint8_t status
Status register.
EventFunctionWrapper dmaPrdReadEvent
DevState_t devState
Device state.
#define SERIALIZE_SCALAR(scalar)
EventFunctionWrapper dmaWriteWaitEvent
#define UNSERIALIZE_ENUM(scalar)
#define UNSERIALIZE_ARRAY(member, size)
enum DevAction DevAction_t
ChunkGenerator * dmaReadCG
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
uint32_t cmdBytes
Number of bytes in command data transfer.
void reschedule(Event &event, Tick when, bool always=false)
PrdTableEntry curPrd
PRD entry.
CommandReg_t cmdReg
Command block registers.
bool intrPending
Interrupt pending.
std::ostream CheckpointOut
unsigned complete() const
Number of bytes we have already chunked up.
EventFunctionWrapper dmaReadWaitEvent
virtual std::streampos read(uint8_t *data, std::streampos offset) const =0
bool dmaRead
Dma transaction is a read.
void startDma(const uint32_t &prdTableBase)
Addr pciToDma(Addr pciAddr)
#define ATAPI_IDENTIFY_DEVICE
Stats::Scalar dmaReadFullPages
void schedule(Event &event, Tick when)
IdeController * ctrl
The IDE controller for this disk.
void writeDisk(uint32_t sector, uint8_t *data)
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
EventFunctionWrapper dmaTransferEvent
uint8_t * dataBuffer
Data buffer for transfers.
Addr addr() const
Return starting address of current chunk.
Declaration and inline definition of ChunkGenerator object.
void readControl(const Addr offset, int size, uint8_t *data)
uint8_t atap_dmamode_supp
void readDisk(uint32_t sector, uint8_t *data)
void setDmaComplete(IdeDisk *disk)
Stats::Scalar dmaWriteFullPages
Abstract superclass for simulation objects.
int diskDelay
The disk delay in microseconds.
#define SERIALIZE_ENUM(scalar)
Stats::Scalar dmaWriteTxs