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
This commit is contained in:
Andrew Schultz 2004-05-12 16:55:49 -04:00
parent c5ec5bf3a7
commit ab9415a2bd
4 changed files with 332 additions and 80 deletions

View file

@ -126,6 +126,72 @@ IdeController::~IdeController()
delete disks[i]; delete disks[i];
} }
////
// 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 // Command completion
//// ////
@ -523,11 +589,53 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
void void
IdeController::serialize(std::ostream &os) 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 void
IdeController::unserialize(Checkpoint *cp, const std::string &section) 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 #ifndef DOXYGEN_SHOULD_SKIP_THIS

View file

@ -27,7 +27,8 @@
*/ */
/** @file /** @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__ #ifndef __IDE_CTRL_HH__
@ -139,65 +140,13 @@ class IdeController : public PciDev
private: private:
/** Parse the access address to pass on to device */ /** Parse the access address to pass on to device */
void parseAddr(const Addr &addr, Addr &offset, bool &primary, void parseAddr(const Addr &addr, Addr &offset, bool &primary,
RegType_t &type) 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);
}
};
/** Select the disk based on the channel and device bit */ /** Select the disk based on the channel and device bit */
int getDisk(bool primary) 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;
};
/** Select the disk based on a pointer */ /** Select the disk based on a pointer */
int getDisk(IdeDisk *diskPtr) int getDisk(IdeDisk *diskPtr);
{
for (int i = 0; i < 4; i++) {
if ((long)diskPtr == (long)disks[i])
return i;
}
return -1;
}
public: public:
/** /**

View file

@ -61,6 +61,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
dmaWriteWaitEvent(this), dmaPrdReadEvent(this), dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
dmaReadEvent(this), dmaWriteEvent(this) dmaReadEvent(this), dmaWriteEvent(this)
{ {
// calculate disk delay in microseconds
diskDelay = (delay * ticksPerSecond / 100000); diskDelay = (delay * ticksPerSecond / 100000);
// initialize the data buffer and shadow registers // 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(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t)); memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
dmaInterfaceBytes = 0;
curPrdAddr = 0; curPrdAddr = 0;
curSector = 0; curSector = 0;
curCommand = 0; curCommand = 0;
@ -154,8 +156,12 @@ IdeDisk::~IdeDisk()
delete [] dataBuffer; delete [] dataBuffer;
} }
////
// Utility functions
////
Addr Addr
IdeDisk::pciToDma(Addr &pciAddr) IdeDisk::pciToDma(Addr pciAddr)
{ {
if (ctrl) if (ctrl)
return ctrl->tsunami->pchip->translatePciToDma(pciAddr); return ctrl->tsunami->pchip->translatePciToDma(pciAddr);
@ -163,6 +169,29 @@ IdeDisk::pciToDma(Addr &pciAddr)
panic("Access to unset controller!\n"); 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 // Device registers read/write
//// ////
@ -297,7 +326,7 @@ IdeDisk::dmaPrdReadDone()
void void
IdeDisk::doDmaRead() IdeDisk::doDmaRead()
{ {
Tick totalDiskDelay = diskDelay * (curPrd.getByteCount() / SectorSize); Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
if (dmaInterface) { if (dmaInterface) {
if (dmaInterface->busy()) { if (dmaInterface->busy()) {
@ -306,9 +335,14 @@ IdeDisk::doDmaRead()
return; return;
} }
Addr dmaAddr = Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr());
dmaInterface->doDMA(Read, dmaAddr, curPrd.getByteCount(), uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
(uint32_t)curPrd.getByteCount());
dmaInterfaceBytes = bytesInPage;
dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
curTick + totalDiskDelay, &dmaReadEvent); curTick + totalDiskDelay, &dmaReadEvent);
} else { } else {
// schedule dmaReadEvent with sectorDelay (dmaReadDone) // schedule dmaReadEvent with sectorDelay (dmaReadDone)
@ -323,6 +357,28 @@ IdeDisk::dmaReadDone()
Addr curAddr = 0, dmaAddr = 0; Addr curAddr = 0, dmaAddr = 0;
uint32_t bytesWritten = 0, bytesInPage = 0, bytesLeft = 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 // set initial address
curAddr = curPrd.getBaseAddr(); curAddr = curPrd.getBaseAddr();
@ -338,15 +394,9 @@ IdeDisk::dmaReadDone()
// calculate how many bytes are in the current page // calculate how many bytes are in the current page
bytesLeft = curPrd.getByteCount() - bytesWritten; bytesLeft = curPrd.getByteCount() - bytesWritten;
bytesInPage = (bytesLeft > ALPHA_PGBYTES) ? ALPHA_PGBYTES : bytesLeft; bytesInPage = bytesInDmaPage(curAddr, 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;
// copy the data from memory into the data buffer // copy the data from memory into the data buffer
/** @todo Use real DMA with interfaces here */
memcpy((void *)(dataBuffer + bytesWritten), memcpy((void *)(dataBuffer + bytesWritten),
physmem->dma_addr(dmaAddr, bytesInPage), physmem->dma_addr(dmaAddr, bytesInPage),
bytesInPage); bytesInPage);
@ -359,9 +409,10 @@ IdeDisk::dmaReadDone()
// write the data to the disk image // write the data to the disk image
for (bytesWritten = 0; for (bytesWritten = 0;
bytesWritten < curPrd.getByteCount(); bytesWritten < curPrd.getByteCount();
bytesWritten += SectorSize) bytesWritten += SectorSize) {
writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten)); writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
}
#if 0 #if 0
// actually copy the data from memory to data buffer // actually copy the data from memory to data buffer
@ -397,7 +448,7 @@ IdeDisk::dmaReadDone()
void void
IdeDisk::doDmaWrite() IdeDisk::doDmaWrite()
{ {
Tick totalDiskDelay = diskDelay * (curPrd.getByteCount() / SectorSize); Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
if (dmaInterface) { if (dmaInterface) {
if (dmaInterface->busy()) { if (dmaInterface->busy()) {
@ -406,10 +457,15 @@ IdeDisk::doDmaWrite()
return; return;
} }
Addr dmaAddr = Addr dmaAddr = pciToDma(curPrd.getBaseAddr());
ctrl->tsunami->pchip->translatePciToDma(curPrd.getBaseAddr());
uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
(uint32_t)curPrd.getByteCount());
dmaInterfaceBytes = bytesInPage;
dmaInterface->doDMA(WriteInvalidate, dmaAddr, dmaInterface->doDMA(WriteInvalidate, dmaAddr,
curPrd.getByteCount(), curTick + totalDiskDelay, bytesInPage, curTick + totalDiskDelay,
&dmaWriteEvent); &dmaWriteEvent);
} else { } else {
// schedule event with disk delay (dmaWriteDone) // schedule event with disk delay (dmaWriteDone)
@ -423,6 +479,29 @@ IdeDisk::dmaWriteDone()
Addr curAddr = 0, pageAddr = 0, dmaAddr = 0; Addr curAddr = 0, pageAddr = 0, dmaAddr = 0;
uint32_t bytesRead = 0, bytesInPage = 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 // setup the initial page and DMA address
curAddr = curPrd.getBaseAddr(); curAddr = curPrd.getBaseAddr();
pageAddr = alpha_trunc_page(curAddr); pageAddr = alpha_trunc_page(curAddr);
@ -435,7 +514,6 @@ IdeDisk::dmaWriteDone()
// see if we have crossed into a new page // see if we have crossed into a new page
if (pageAddr != alpha_trunc_page(curAddr)) { if (pageAddr != alpha_trunc_page(curAddr)) {
// write the data to memory // write the data to memory
/** @todo Do real DMA using interfaces here */
memcpy(physmem->dma_addr(dmaAddr, bytesInPage), memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)), (void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage); bytesInPage);
@ -459,7 +537,6 @@ IdeDisk::dmaWriteDone()
} }
// write the last page worth read to memory // write the last page worth read to memory
/** @todo Do real DMA using interfaces here */
if (bytesInPage != 0) { if (bytesInPage != 0) {
memcpy(physmem->dma_addr(dmaAddr, bytesInPage), memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)), (void *)(dataBuffer + (bytesRead - bytesInPage)),
@ -521,7 +598,7 @@ IdeDisk::startDma(const uint32_t &prdTableBase)
if (devState != Transfer_Data_Dma) if (devState != Transfer_Data_Dma)
panic("Inconsistent device state for DMA start!\n"); panic("Inconsistent device state for DMA start!\n");
curPrdAddr = ctrl->tsunami->pchip->translatePciToDma(prdTableBase); curPrdAddr = pciToDma((Addr)prdTableBase);
dmaState = Dma_Transfer; dmaState = Dma_Transfer;
@ -927,11 +1004,115 @@ IdeDisk::updateState(DevAction_t action)
void void
IdeDisk::serialize(ostream &os) 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 void
IdeDisk::unserialize(Checkpoint *cp, const string &section) 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 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@ -950,7 +1131,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"), INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"), INIT_PARAM(physmem, "Physical memory"),
INIT_PARAM(driveID, "Drive ID (0=master 1=slave)"), 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) END_INIT_SIM_OBJECT_PARAMS(IdeDisk)

View file

@ -94,7 +94,7 @@ class PrdTableEntry {
#define STATUS_BSY_BIT 0x80 #define STATUS_BSY_BIT 0x80
#define STATUS_DRDY_BIT 0x40 #define STATUS_DRDY_BIT 0x40
#define STATUS_DRQ_BIT 0x08 #define STATUS_DRQ_BIT 0x08
#define DRIVE_LBA_BIT 0x40 #define DRIVE_LBA_BIT 0x40
#define DEV0 (0) #define DEV0 (0)
#define DEV1 (1) #define DEV1 (1)
@ -120,6 +120,16 @@ typedef struct CommandReg {
}; };
} CommandReg_t; } CommandReg_t;
typedef enum Events {
None = 0,
Transfer,
ReadWait,
WriteWait,
PrdRead,
DmaRead,
DmaWrite
} Events_t;
typedef enum DevAction { typedef enum DevAction {
ACT_NONE = 0, ACT_NONE = 0,
ACT_CMD_WRITE, ACT_CMD_WRITE,
@ -184,7 +194,7 @@ class IdeDisk : public SimObject
PhysicalMemory *physmem; PhysicalMemory *physmem;
protected: protected:
/** The disk delay in milliseconds. */ /** The disk delay in microseconds. */
int diskDelay; int diskDelay;
private: private:
@ -214,6 +224,8 @@ class IdeDisk : public SimObject
uint32_t curPrdAddr; uint32_t curPrdAddr;
/** PRD entry */ /** PRD entry */
PrdTableEntry curPrd; PrdTableEntry curPrd;
/** Number of bytes transfered by DMA interface for current transfer */
uint32_t dmaInterfaceBytes;
/** Device ID (master=0/slave=1) */ /** Device ID (master=0/slave=1) */
int devID; int devID;
/** Interrupt pending */ /** Interrupt pending */
@ -313,7 +325,9 @@ class IdeDisk : public SimObject
(cmdReg.cyl_low << 8) | (cmdReg.sec_num)); (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. * Serialize this object to the given output stream.