summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Schultz <alschult@umich.edu>2004-05-12 16:55:49 -0400
committerAndrew Schultz <alschult@umich.edu>2004-05-12 16:55:49 -0400
commitab9415a2bd608246501b33f5670d2a3ecc746dde (patch)
tree5934840c601813776fd0e1f9c34cdcda57b9fb97
parentc5ec5bf3a746ae5ccbd80e5959807cf35e1d4b93 (diff)
downloadgem5-ab9415a2bd608246501b33f5670d2a3ecc746dde.tar.xz
Fixes to DMA writing (still unverified) and added serialize/unserialize
dev/ide_ctrl.cc: Added serialize/unserialize functions and move some inlined functions to regular functions dev/ide_ctrl.hh: Change inlined functions to regular functions dev/ide_disk.cc: Changes to dmaWrite and also add serialize/unserialize functions dev/ide_disk.hh: Support for serializing/unserializing --HG-- extra : convert_revision : 40e016dc7f6637b033fe33409338437c985a05f4
-rw-r--r--dev/ide_ctrl.cc108
-rw-r--r--dev/ide_ctrl.hh61
-rw-r--r--dev/ide_disk.cc223
-rw-r--r--dev/ide_disk.hh20
4 files changed, 332 insertions, 80 deletions
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index f038aceca..a21cf12d7 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -127,6 +127,72 @@ IdeController::~IdeController()
}
////
+// Utility functions
+///
+
+void
+IdeController::parseAddr(const Addr &addr, Addr &offset, bool &primary,
+ RegType_t &type)
+{
+ offset = addr;
+
+ if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
+ offset -= pri_cmd_addr;
+ type = COMMAND_BLOCK;
+ primary = true;
+ } else if (addr >= pri_ctrl_addr &&
+ addr < (pri_ctrl_addr + pri_ctrl_size)) {
+ offset -= pri_ctrl_addr;
+ type = CONTROL_BLOCK;
+ primary = true;
+ } else if (addr >= sec_cmd_addr &&
+ addr < (sec_cmd_addr + sec_cmd_size)) {
+ offset -= sec_cmd_addr;
+ type = COMMAND_BLOCK;
+ primary = false;
+ } else if (addr >= sec_ctrl_addr &&
+ addr < (sec_ctrl_addr + sec_ctrl_size)) {
+ offset -= sec_ctrl_addr;
+ type = CONTROL_BLOCK;
+ primary = false;
+ } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
+ offset -= bmi_addr;
+ type = BMI_BLOCK;
+ primary = (offset < BMIC1) ? true : false;
+ } else {
+ panic("IDE controller access to invalid address: %#x\n", addr);
+ }
+}
+
+int
+IdeController::getDisk(bool primary)
+{
+ int disk = 0;
+ uint8_t *devBit = &dev[0];
+
+ if (!primary) {
+ disk += 2;
+ devBit = &dev[1];
+ }
+
+ disk += *devBit;
+
+ assert(*devBit == 0 || *devBit == 1);
+
+ return disk;
+}
+
+int
+IdeController::getDisk(IdeDisk *diskPtr)
+{
+ for (int i = 0; i < 4; i++) {
+ if ((long)diskPtr == (long)disks[i])
+ return i;
+ }
+ return -1;
+}
+
+////
// Command completion
////
@@ -523,11 +589,53 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
void
IdeController::serialize(std::ostream &os)
{
+ // Serialize register addresses and sizes
+ SERIALIZE_SCALAR(pri_cmd_addr);
+ SERIALIZE_SCALAR(pri_cmd_size);
+ SERIALIZE_SCALAR(pri_ctrl_addr);
+ SERIALIZE_SCALAR(pri_ctrl_size);
+ SERIALIZE_SCALAR(sec_cmd_addr);
+ SERIALIZE_SCALAR(sec_cmd_size);
+ SERIALIZE_SCALAR(sec_ctrl_addr);
+ SERIALIZE_SCALAR(sec_ctrl_size);
+ SERIALIZE_SCALAR(bmi_addr);
+ SERIALIZE_SCALAR(bmi_size);
+
+ // Serialize registers
+ SERIALIZE_ARRAY(bmi_regs, 16);
+ SERIALIZE_ARRAY(dev, 2);
+ SERIALIZE_ARRAY(pci_regs, 8);
+
+ // Serialize internal state
+ SERIALIZE_SCALAR(io_enabled);
+ SERIALIZE_SCALAR(bm_enabled);
+ SERIALIZE_ARRAY(cmd_in_progress, 4);
}
void
IdeController::unserialize(Checkpoint *cp, const std::string &section)
{
+ // Unserialize register addresses and sizes
+ UNSERIALIZE_SCALAR(pri_cmd_addr);
+ UNSERIALIZE_SCALAR(pri_cmd_size);
+ UNSERIALIZE_SCALAR(pri_ctrl_addr);
+ UNSERIALIZE_SCALAR(pri_ctrl_size);
+ UNSERIALIZE_SCALAR(sec_cmd_addr);
+ UNSERIALIZE_SCALAR(sec_cmd_size);
+ UNSERIALIZE_SCALAR(sec_ctrl_addr);
+ UNSERIALIZE_SCALAR(sec_ctrl_size);
+ UNSERIALIZE_SCALAR(bmi_addr);
+ UNSERIALIZE_SCALAR(bmi_size);
+
+ // Unserialize registers
+ UNSERIALIZE_ARRAY(bmi_regs, 16);
+ UNSERIALIZE_ARRAY(dev, 2);
+ UNSERIALIZE_ARRAY(pci_regs, 8);
+
+ // Unserialize internal state
+ UNSERIALIZE_SCALAR(io_enabled);
+ UNSERIALIZE_SCALAR(bm_enabled);
+ UNSERIALIZE_ARRAY(cmd_in_progress, 4);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index b4de97036..9698724c1 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -27,7 +27,8 @@
*/
/** @file
- * Simple PCI IDE controller with bus mastering capability
+ * Simple PCI IDE controller with bus mastering capability and UDMA
+ * modeled after controller in the Intel PIIX4 chip
*/
#ifndef __IDE_CTRL_HH__
@@ -139,65 +140,13 @@ class IdeController : public PciDev
private:
/** Parse the access address to pass on to device */
void parseAddr(const Addr &addr, Addr &offset, bool &primary,
- RegType_t &type)
- {
- offset = addr;
-
- if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
- offset -= pri_cmd_addr;
- type = COMMAND_BLOCK;
- primary = true;
- } else if (addr >= pri_ctrl_addr &&
- addr < (pri_ctrl_addr + pri_ctrl_size)) {
- offset -= pri_ctrl_addr;
- type = CONTROL_BLOCK;
- primary = true;
- } else if (addr >= sec_cmd_addr &&
- addr < (sec_cmd_addr + sec_cmd_size)) {
- offset -= sec_cmd_addr;
- type = COMMAND_BLOCK;
- primary = false;
- } else if (addr >= sec_ctrl_addr &&
- addr < (sec_ctrl_addr + sec_ctrl_size)) {
- offset -= sec_ctrl_addr;
- type = CONTROL_BLOCK;
- primary = false;
- } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
- offset -= bmi_addr;
- type = BMI_BLOCK;
- primary = (offset < BMIC1) ? true : false;
- } else {
- panic("IDE controller access to invalid address: %#x\n", addr);
- }
- };
+ RegType_t &type);
/** Select the disk based on the channel and device bit */
- int getDisk(bool primary)
- {
- int disk = 0;
- uint8_t *devBit = &dev[0];
-
- if (!primary) {
- disk += 2;
- devBit = &dev[1];
- }
-
- disk += *devBit;
-
- assert(*devBit == 0 || *devBit == 1);
-
- return disk;
- };
+ int getDisk(bool primary);
/** Select the disk based on a pointer */
- int getDisk(IdeDisk *diskPtr)
- {
- for (int i = 0; i < 4; i++) {
- if ((long)diskPtr == (long)disks[i])
- return i;
- }
- return -1;
- }
+ int getDisk(IdeDisk *diskPtr);
public:
/**
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 38d6a919b..0d12e797d 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -61,6 +61,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this)
{
+ // calculate disk delay in microseconds
diskDelay = (delay * ticksPerSecond / 100000);
// initialize the data buffer and shadow registers
@@ -70,6 +71,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+ dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
curCommand = 0;
@@ -154,8 +156,12 @@ IdeDisk::~IdeDisk()
delete [] dataBuffer;
}
+////
+// Utility functions
+////
+
Addr
-IdeDisk::pciToDma(Addr &pciAddr)
+IdeDisk::pciToDma(Addr pciAddr)
{
if (ctrl)
return ctrl->tsunami->pchip->translatePciToDma(pciAddr);
@@ -163,6 +169,29 @@ IdeDisk::pciToDma(Addr &pciAddr)
panic("Access to unset controller!\n");
}
+uint32_t
+IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
+{
+ uint32_t bytesInPage = 0;
+
+ // First calculate how many bytes could be in the page
+ if (bytesLeft > ALPHA_PGBYTES)
+ bytesInPage = ALPHA_PGBYTES;
+ else
+ bytesInPage = bytesLeft;
+
+ // Next, see if we have crossed a page boundary, and adjust
+ Addr upperBound = curAddr + bytesInPage;
+ Addr pageBound = alpha_trunc_page(curAddr) + ALPHA_PGBYTES;
+
+ assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
+
+ if (upperBound >= pageBound)
+ bytesInPage = pageBound - curAddr;
+
+ return bytesInPage;
+}
+
////
// Device registers read/write
////
@@ -297,7 +326,7 @@ IdeDisk::dmaPrdReadDone()
void
IdeDisk::doDmaRead()
{
- Tick totalDiskDelay = diskDelay * (curPrd.getByteCount() / SectorSize);
+ Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
if (dmaInterface) {
if (dmaInterface->busy()) {
@@ -306,9 +335,14 @@ IdeDisk::doDmaRead()
return;
}
- Addr dmaAddr =
- ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr());
- dmaInterface->doDMA(Read, dmaAddr, curPrd.getByteCount(),
+ Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
+
+ uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
+ (uint32_t)curPrd.getByteCount());
+
+ dmaInterfaceBytes = bytesInPage;
+
+ dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
curTick + totalDiskDelay, &dmaReadEvent);
} else {
// schedule dmaReadEvent with sectorDelay (dmaReadDone)
@@ -323,6 +357,28 @@ IdeDisk::dmaReadDone()
Addr curAddr = 0, dmaAddr = 0;
uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 0;
+ // continue to use the DMA interface until all pages are read
+ if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
+ // see if the interface is busy
+ if (dmaInterface->busy()) {
+ // reschedule after waiting period
+ dmaReadEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+ return;
+ }
+
+ uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
+ curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
+ dmaAddr = pciToDma(curAddr);
+
+ bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
+ dmaInterfaceBytes += bytesInPage;
+
+ dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
+ curTick, &dmaReadEvent);
+
+ return;
+ }
+
// set initial address
curAddr = curPrd.getBaseAddr();
@@ -338,15 +394,9 @@ IdeDisk::dmaReadDone()
// calculate how many bytes are in the current page
bytesLeft = curPrd.getByteCount() - bytesWritten;
- bytesInPage = (bytesLeft > ALPHA_PGBYTES) ? ALPHA_PGBYTES : bytesLeft;
- // check to make sure we don't cross a page boundary
- if ((curAddr + bytesInPage) >
- (alpha_trunc_page(curAddr) + ALPHA_PGBYTES))
-
- bytesInPage = alpha_round_page(curAddr) - curAddr;
+ bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
// copy the data from memory into the data buffer
- /** @todo Use real DMA with interfaces here */
memcpy((void *)(dataBuffer + bytesWritten),
physmem->dma_addr(dmaAddr, bytesInPage),
bytesInPage);
@@ -359,9 +409,10 @@ IdeDisk::dmaReadDone()
// write the data to the disk image
for (bytesWritten = 0;
bytesWritten < curPrd.getByteCount();
- bytesWritten += SectorSize)
+ bytesWritten += SectorSize) {
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
+ }
#if 0
// actually copy the data from memory to data buffer
@@ -397,7 +448,7 @@ IdeDisk::dmaReadDone()
void
IdeDisk::doDmaWrite()
{
- Tick totalDiskDelay = diskDelay * (curPrd.getByteCount() / SectorSize);
+ Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
if (dmaInterface) {
if (dmaInterface->busy()) {
@@ -406,10 +457,15 @@ IdeDisk::doDmaWrite()
return;
}
- Addr dmaAddr =
- ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr());
+ Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
+
+ uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
+ (uint32_t)curPrd.getByteCount());
+
+ dmaInterfaceBytes = bytesInPage;
+
dmaInterface->doDMA(WriteInvalidate, dmaAddr,
- curPrd.getByteCount(), curTick + totalDiskDelay,
+ bytesInPage, curTick + totalDiskDelay,
&dmaWriteEvent);
} else {
// schedule event with disk delay (dmaWriteDone)
@@ -423,6 +479,29 @@ IdeDisk::dmaWriteDone()
Addr curAddr = 0, pageAddr = 0, dmaAddr = 0;
uint32_t bytesRead = 0, bytesInPage = 0;
+ // continue to use the DMA interface until all pages are read
+ if (dmaInterface && (dmaInterfaceBytes < curPrd.getByteCount())) {
+ // see if the interface is busy
+ if (dmaInterface->busy()) {
+ // reschedule after waiting period
+ dmaWriteEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+ return;
+ }
+
+ uint32_t bytesLeft = curPrd.getByteCount() - dmaInterfaceBytes;
+ curAddr = curPrd.getBaseAddr() + dmaInterfaceBytes;
+ dmaAddr = pciToDma(curAddr);
+
+ bytesInPage = bytesInDmaPage(curAddr, bytesLeft);
+ dmaInterfaceBytes += bytesInPage;
+
+ dmaInterface->doDMA(WriteInvalidate, dmaAddr,
+ bytesInPage, curTick,
+ &dmaWriteEvent);
+
+ return;
+ }
+
// setup the initial page and DMA address
curAddr = curPrd.getBaseAddr();
pageAddr = alpha_trunc_page(curAddr);
@@ -435,7 +514,6 @@ IdeDisk::dmaWriteDone()
// see if we have crossed into a new page
if (pageAddr != alpha_trunc_page(curAddr)) {
// write the data to memory
- /** @todo Do real DMA using interfaces here */
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage);
@@ -459,7 +537,6 @@ IdeDisk::dmaWriteDone()
}
// write the last page worth read to memory
- /** @todo Do real DMA using interfaces here */
if (bytesInPage != 0) {
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
@@ -521,7 +598,7 @@ IdeDisk::startDma(const uint32_t &prdTableBase)
if (devState != Transfer_Data_Dma)
panic("Inconsistent device state for DMA start!\n");
- curPrdAddr = ctrl->tsunami->pchip->translatePciToDma(prdTableBase);
+ curPrdAddr = pciToDma((Addr)prdTableBase);
dmaState = Dma_Transfer;
@@ -927,11 +1004,115 @@ IdeDisk::updateState(DevAction_t action)
void
IdeDisk::serialize(ostream &os)
{
+ // Check all outstanding events to see if they are scheduled
+ // these are all mutually exclusive
+ Tick reschedule = 0;
+ Events_t event = None;
+
+ if (dmaTransferEvent.scheduled()) {
+ reschedule = dmaTransferEvent.when();
+ event = Transfer;
+ } else if (dmaReadWaitEvent.scheduled()) {
+ reschedule = dmaReadWaitEvent.when();
+ event = ReadWait;
+ } else if (dmaWriteWaitEvent.scheduled()) {
+ reschedule = dmaWriteWaitEvent.when();
+ event = WriteWait;
+ } else if (dmaPrdReadEvent.scheduled()) {
+ reschedule = dmaPrdReadEvent.when();
+ event = PrdRead;
+ } else if (dmaReadEvent.scheduled()) {
+ reschedule = dmaReadEvent.when();
+ event = DmaRead;
+ } else if (dmaWriteEvent.scheduled()) {
+ reschedule = dmaWriteEvent.when();
+ event = DmaWrite;
+ }
+
+ SERIALIZE_SCALAR(reschedule);
+ SERIALIZE_ENUM(event);
+
+ // Serialize device registers
+ SERIALIZE_SCALAR(cmdReg.data0);
+ SERIALIZE_SCALAR(cmdReg.data1);
+ SERIALIZE_SCALAR(cmdReg.sec_count);
+ SERIALIZE_SCALAR(cmdReg.sec_num);
+ SERIALIZE_SCALAR(cmdReg.cyl_low);
+ SERIALIZE_SCALAR(cmdReg.cyl_high);
+ SERIALIZE_SCALAR(cmdReg.drive);
+ SERIALIZE_SCALAR(cmdReg.status);
+ SERIALIZE_SCALAR(nIENBit);
+ SERIALIZE_SCALAR(devID);
+
+ // Serialize the PRD related information
+ SERIALIZE_SCALAR(curPrd.entry.baseAddr);
+ SERIALIZE_SCALAR(curPrd.entry.byteCount);
+ SERIALIZE_SCALAR(curPrd.entry.endOfTable);
+ SERIALIZE_SCALAR(curPrdAddr);
+
+ // Serialize current transfer related information
+ SERIALIZE_SCALAR(cmdBytesLeft);
+ SERIALIZE_SCALAR(drqBytesLeft);
+ SERIALIZE_SCALAR(curSector);
+ SERIALIZE_SCALAR(curCommand);
+ SERIALIZE_SCALAR(dmaRead);
+ SERIALIZE_SCALAR(dmaInterfaceBytes);
+ SERIALIZE_SCALAR(intrPending);
+ SERIALIZE_ENUM(devState);
+ SERIALIZE_ENUM(dmaState);
+ SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
}
void
IdeDisk::unserialize(Checkpoint *cp, const string &section)
{
+ // Reschedule events that were outstanding
+ // these are all mutually exclusive
+ Tick reschedule = 0;
+ Events_t event = None;
+
+ UNSERIALIZE_SCALAR(reschedule);
+ UNSERIALIZE_ENUM(event);
+
+ switch (event) {
+ case None : break;
+ case Transfer : dmaTransferEvent.schedule(reschedule); break;
+ case ReadWait : dmaReadWaitEvent.schedule(reschedule); break;
+ case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break;
+ case PrdRead : dmaPrdReadEvent.schedule(reschedule); break;
+ case DmaRead : dmaReadEvent.schedule(reschedule); break;
+ case DmaWrite : dmaWriteEvent.schedule(reschedule); break;
+ }
+
+ // Unserialize device registers
+ UNSERIALIZE_SCALAR(cmdReg.data0);
+ UNSERIALIZE_SCALAR(cmdReg.data1);
+ UNSERIALIZE_SCALAR(cmdReg.sec_count);
+ UNSERIALIZE_SCALAR(cmdReg.sec_num);
+ UNSERIALIZE_SCALAR(cmdReg.cyl_low);
+ UNSERIALIZE_SCALAR(cmdReg.cyl_high);
+ UNSERIALIZE_SCALAR(cmdReg.drive);
+ UNSERIALIZE_SCALAR(cmdReg.status);
+ UNSERIALIZE_SCALAR(nIENBit);
+ UNSERIALIZE_SCALAR(devID);
+
+ // Unserialize the PRD related information
+ UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);
+ UNSERIALIZE_SCALAR(curPrd.entry.byteCount);
+ UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
+ UNSERIALIZE_SCALAR(curPrdAddr);
+
+ // Unserialize current transfer related information
+ UNSERIALIZE_SCALAR(cmdBytesLeft);
+ UNSERIALIZE_SCALAR(drqBytesLeft);
+ UNSERIALIZE_SCALAR(curSector);
+ UNSERIALIZE_SCALAR(curCommand);
+ UNSERIALIZE_SCALAR(dmaRead);
+ UNSERIALIZE_SCALAR(dmaInterfaceBytes);
+ UNSERIALIZE_SCALAR(intrPending);
+ UNSERIALIZE_ENUM(devState);
+ UNSERIALIZE_ENUM(dmaState);
+ UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -950,7 +1131,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"),
INIT_PARAM(driveID, "Drive ID (0=master 1=slave)"),
- INIT_PARAM_DFLT(disk_delay, "Fixed disk delay in milliseconds", 0)
+ INIT_PARAM_DFLT(disk_delay, "Fixed disk delay in microseconds", 1)
END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
index 88a492cbc..35e7404d5 100644
--- a/dev/ide_disk.hh
+++ b/dev/ide_disk.hh
@@ -94,7 +94,7 @@ class PrdTableEntry {
#define STATUS_BSY_BIT 0x80
#define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT 0x08
-#define DRIVE_LBA_BIT 0x40
+#define DRIVE_LBA_BIT 0x40
#define DEV0 (0)
#define DEV1 (1)
@@ -120,6 +120,16 @@ typedef struct CommandReg {
};
} CommandReg_t;
+typedef enum Events {
+ None = 0,
+ Transfer,
+ ReadWait,
+ WriteWait,
+ PrdRead,
+ DmaRead,
+ DmaWrite
+} Events_t;
+
typedef enum DevAction {
ACT_NONE = 0,
ACT_CMD_WRITE,
@@ -184,7 +194,7 @@ class IdeDisk : public SimObject
PhysicalMemory *physmem;
protected:
- /** The disk delay in milliseconds. */
+ /** The disk delay in microseconds. */
int diskDelay;
private:
@@ -214,6 +224,8 @@ class IdeDisk : public SimObject
uint32_t curPrdAddr;
/** PRD entry */
PrdTableEntry curPrd;
+ /** Number of bytes transfered by DMA interface for current transfer */
+ uint32_t dmaInterfaceBytes;
/** Device ID (master=0/slave=1) */
int devID;
/** Interrupt pending */
@@ -313,7 +325,9 @@ class IdeDisk : public SimObject
(cmdReg.cyl_low << 8) | (cmdReg.sec_num));
}
- inline Addr pciToDma(Addr &pciAddr);
+ inline Addr pciToDma(Addr pciAddr);
+
+ uint32_t bytesInDmaPage(Addr curAddr, uint32_t bytesLeft);
/**
* Serialize this object to the given output stream.