Fixes to the state machine to properly support software reset and to fix
PIO writes. This was mainly related to not shadowing the status register properly, and also not setting some of the status bits expected by the operating system for the PIO write protocol. --HG-- extra : convert_revision : fcdfd588be6e4f237aa6057889f0b3bdf4ea7631
This commit is contained in:
parent
ac27e69ef9
commit
7bbb00d80f
2 changed files with 119 additions and 73 deletions
157
dev/ide_disk.cc
157
dev/ide_disk.cc
|
@ -61,25 +61,12 @@ 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)
|
||||||
{
|
{
|
||||||
|
// Reset the device state
|
||||||
|
reset(id);
|
||||||
|
|
||||||
// calculate disk delay in microseconds
|
// calculate disk delay in microseconds
|
||||||
diskDelay = (delay * ticksPerSecond / 100000);
|
diskDelay = (delay * ticksPerSecond / 100000);
|
||||||
|
|
||||||
// initialize the data buffer and shadow registers
|
|
||||||
dataBuffer = new uint8_t[MAX_DMA_SIZE];
|
|
||||||
|
|
||||||
memset(dataBuffer, 0, MAX_DMA_SIZE);
|
|
||||||
memset(&cmdReg, 0, sizeof(CommandReg_t));
|
|
||||||
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
|
|
||||||
|
|
||||||
dmaInterfaceBytes = 0;
|
|
||||||
curPrdAddr = 0;
|
|
||||||
curSector = 0;
|
|
||||||
curCommand = 0;
|
|
||||||
cmdBytesLeft = 0;
|
|
||||||
drqBytesLeft = 0;
|
|
||||||
dmaRead = false;
|
|
||||||
intrPending = false;
|
|
||||||
|
|
||||||
// fill out the drive ID structure
|
// fill out the drive ID structure
|
||||||
memset(&driveID, 0, sizeof(struct hd_driveid));
|
memset(&driveID, 0, sizeof(struct hd_driveid));
|
||||||
|
|
||||||
|
@ -132,6 +119,32 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
|
||||||
driveID.dma_ultra = 0x10;
|
driveID.dma_ultra = 0x10;
|
||||||
// Statically set hardware config word
|
// Statically set hardware config word
|
||||||
driveID.hw_config = 0x4001;
|
driveID.hw_config = 0x4001;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdeDisk::~IdeDisk()
|
||||||
|
{
|
||||||
|
// destroy the data buffer
|
||||||
|
delete [] dataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IdeDisk::reset(int id)
|
||||||
|
{
|
||||||
|
// initialize the data buffer and shadow registers
|
||||||
|
dataBuffer = new uint8_t[MAX_DMA_SIZE];
|
||||||
|
|
||||||
|
memset(dataBuffer, 0, MAX_DMA_SIZE);
|
||||||
|
memset(&cmdReg, 0, sizeof(CommandReg_t));
|
||||||
|
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
|
||||||
|
|
||||||
|
dmaInterfaceBytes = 0;
|
||||||
|
curPrdAddr = 0;
|
||||||
|
curSector = 0;
|
||||||
|
cmdBytes = 0;
|
||||||
|
cmdBytesLeft = 0;
|
||||||
|
drqBytesLeft = 0;
|
||||||
|
dmaRead = false;
|
||||||
|
intrPending = false;
|
||||||
|
|
||||||
// set the device state to idle
|
// set the device state to idle
|
||||||
dmaState = Dma_Idle;
|
dmaState = Dma_Idle;
|
||||||
|
@ -147,13 +160,7 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the device ready bit
|
// set the device ready bit
|
||||||
cmdReg.status |= STATUS_DRDY_BIT;
|
status = STATUS_DRDY_BIT;
|
||||||
}
|
|
||||||
|
|
||||||
IdeDisk::~IdeDisk()
|
|
||||||
{
|
|
||||||
// destroy the data buffer
|
|
||||||
delete [] dataBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
@ -216,6 +223,7 @@ IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
|
||||||
// determine if an action needs to be taken on the state machine
|
// determine if an action needs to be taken on the state machine
|
||||||
if (offset == STATUS_OFFSET) {
|
if (offset == STATUS_OFFSET) {
|
||||||
action = ACT_STAT_READ;
|
action = ACT_STAT_READ;
|
||||||
|
*data = status; // status is in a shadow, explicity copy
|
||||||
} else if (offset == DATA_OFFSET) {
|
} else if (offset == DATA_OFFSET) {
|
||||||
if (byte)
|
if (byte)
|
||||||
action = ACT_DATA_READ_BYTE;
|
action = ACT_DATA_READ_BYTE;
|
||||||
|
@ -230,7 +238,7 @@ IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
|
||||||
if (!byte)
|
if (!byte)
|
||||||
panic("Invalid 16-bit read from control block\n");
|
panic("Invalid 16-bit read from control block\n");
|
||||||
|
|
||||||
*data = ((uint8_t *)&cmdReg)[STATUS_OFFSET];
|
*data = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action != ACT_NONE)
|
if (action != ACT_NONE)
|
||||||
|
@ -262,6 +270,8 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
|
||||||
action = ACT_DATA_WRITE_BYTE;
|
action = ACT_DATA_WRITE_BYTE;
|
||||||
else
|
else
|
||||||
action = ACT_DATA_WRITE_SHORT;
|
action = ACT_DATA_WRITE_SHORT;
|
||||||
|
} else if (offset == SELECT_OFFSET) {
|
||||||
|
action = ACT_SELECT_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,8 +281,13 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
|
||||||
if (!byte)
|
if (!byte)
|
||||||
panic("Invalid 16-bit write to control block\n");
|
panic("Invalid 16-bit write to control block\n");
|
||||||
|
|
||||||
if (*data & CONTROL_RST_BIT)
|
if (*data & CONTROL_RST_BIT) {
|
||||||
panic("Software reset not supported!\n");
|
// force the device into the reset state
|
||||||
|
devState = Device_Srst;
|
||||||
|
action = ACT_SRST_SET;
|
||||||
|
} else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) {
|
||||||
|
action = ACT_SRST_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
|
nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
|
||||||
}
|
}
|
||||||
|
@ -625,9 +640,6 @@ IdeDisk::startCommand()
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
dmaRead = false;
|
dmaRead = false;
|
||||||
|
|
||||||
// copy the command to the shadow
|
|
||||||
curCommand = cmdReg.command;
|
|
||||||
|
|
||||||
// Decode commands
|
// Decode commands
|
||||||
switch (cmdReg.command) {
|
switch (cmdReg.command) {
|
||||||
// Supported non-data commands
|
// Supported non-data commands
|
||||||
|
@ -656,7 +668,7 @@ IdeDisk::startCommand()
|
||||||
|
|
||||||
// Supported PIO data-in commands
|
// Supported PIO data-in commands
|
||||||
case WIN_IDENTIFY:
|
case WIN_IDENTIFY:
|
||||||
cmdBytesLeft = sizeof(struct hd_driveid);
|
cmdBytes = cmdBytesLeft = sizeof(struct hd_driveid);
|
||||||
devState = Prepare_Data_In;
|
devState = Prepare_Data_In;
|
||||||
action = ACT_DATA_READY;
|
action = ACT_DATA_READY;
|
||||||
break;
|
break;
|
||||||
|
@ -667,9 +679,9 @@ IdeDisk::startCommand()
|
||||||
panic("Attempt to perform CHS access, only supports LBA\n");
|
panic("Attempt to perform CHS access, only supports LBA\n");
|
||||||
|
|
||||||
if (cmdReg.sec_count == 0)
|
if (cmdReg.sec_count == 0)
|
||||||
cmdBytesLeft = (256 * SectorSize);
|
cmdBytes = cmdBytesLeft = (256 * SectorSize);
|
||||||
else
|
else
|
||||||
cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
||||||
|
|
||||||
curSector = getLBABase();
|
curSector = getLBABase();
|
||||||
|
|
||||||
|
@ -685,9 +697,9 @@ IdeDisk::startCommand()
|
||||||
panic("Attempt to perform CHS access, only supports LBA\n");
|
panic("Attempt to perform CHS access, only supports LBA\n");
|
||||||
|
|
||||||
if (cmdReg.sec_count == 0)
|
if (cmdReg.sec_count == 0)
|
||||||
cmdBytesLeft = (256 * SectorSize);
|
cmdBytes = cmdBytesLeft = (256 * SectorSize);
|
||||||
else
|
else
|
||||||
cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
||||||
|
|
||||||
curSector = getLBABase();
|
curSector = getLBABase();
|
||||||
|
|
||||||
|
@ -703,9 +715,9 @@ IdeDisk::startCommand()
|
||||||
panic("Attempt to perform CHS access, only supports LBA\n");
|
panic("Attempt to perform CHS access, only supports LBA\n");
|
||||||
|
|
||||||
if (cmdReg.sec_count == 0)
|
if (cmdReg.sec_count == 0)
|
||||||
cmdBytesLeft = (256 * SectorSize);
|
cmdBytes = cmdBytesLeft = (256 * SectorSize);
|
||||||
else
|
else
|
||||||
cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
|
||||||
|
|
||||||
curSector = getLBABase();
|
curSector = getLBABase();
|
||||||
|
|
||||||
|
@ -719,9 +731,11 @@ IdeDisk::startCommand()
|
||||||
|
|
||||||
if (action != ACT_NONE) {
|
if (action != ACT_NONE) {
|
||||||
// set the BSY bit
|
// set the BSY bit
|
||||||
cmdReg.status |= STATUS_BSY_BIT;
|
status |= STATUS_BSY_BIT;
|
||||||
// clear the DRQ bit
|
// clear the DRQ bit
|
||||||
cmdReg.status &= ~STATUS_DRQ_BIT;
|
status &= ~STATUS_DRQ_BIT;
|
||||||
|
// clear the DF bit
|
||||||
|
status &= ~STATUS_DF_BIT;
|
||||||
|
|
||||||
updateState(action);
|
updateState(action);
|
||||||
}
|
}
|
||||||
|
@ -765,16 +779,30 @@ void
|
||||||
IdeDisk::updateState(DevAction_t action)
|
IdeDisk::updateState(DevAction_t action)
|
||||||
{
|
{
|
||||||
switch (devState) {
|
switch (devState) {
|
||||||
|
case Device_Srst:
|
||||||
|
if (action == ACT_SRST_SET) {
|
||||||
|
// set the BSY bit
|
||||||
|
status |= STATUS_BSY_BIT;
|
||||||
|
} else if (action == ACT_SRST_CLEAR) {
|
||||||
|
// clear the BSY bit
|
||||||
|
status &= ~STATUS_BSY_BIT;
|
||||||
|
|
||||||
|
// reset the device state
|
||||||
|
reset(devID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Device_Idle_S:
|
case Device_Idle_S:
|
||||||
if (!isDEVSelect())
|
if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
|
||||||
devState = Device_Idle_NS;
|
devState = Device_Idle_NS;
|
||||||
else if (action == ACT_CMD_WRITE)
|
} else if (action == ACT_CMD_WRITE) {
|
||||||
startCommand();
|
startCommand();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Device_Idle_SI:
|
case Device_Idle_SI:
|
||||||
if (!isDEVSelect()) {
|
if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
|
||||||
devState = Device_Idle_NS;
|
devState = Device_Idle_NS;
|
||||||
intrClear();
|
intrClear();
|
||||||
} else if (action == ACT_STAT_READ || isIENSet()) {
|
} else if (action == ACT_STAT_READ || isIENSet()) {
|
||||||
|
@ -788,7 +816,7 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Device_Idle_NS:
|
case Device_Idle_NS:
|
||||||
if (isDEVSelect()) {
|
if (action == ACT_SELECT_WRITE && isDEVSelect()) {
|
||||||
if (!isIENSet() && intrPending) {
|
if (!isIENSet() && intrPending) {
|
||||||
devState = Device_Idle_SI;
|
devState = Device_Idle_SI;
|
||||||
intrPost();
|
intrPost();
|
||||||
|
@ -826,12 +854,12 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
}
|
}
|
||||||
} else if (action == ACT_DATA_READY) {
|
} else if (action == ACT_DATA_READY) {
|
||||||
// clear the BSY bit
|
// clear the BSY bit
|
||||||
cmdReg.status &= ~STATUS_BSY_BIT;
|
status &= ~STATUS_BSY_BIT;
|
||||||
// set the DRQ bit
|
// set the DRQ bit
|
||||||
cmdReg.status |= STATUS_DRQ_BIT;
|
status |= STATUS_DRQ_BIT;
|
||||||
|
|
||||||
// copy the data into the data buffer
|
// copy the data into the data buffer
|
||||||
if (curCommand == WIN_IDENTIFY) {
|
if (cmdReg.command == WIN_IDENTIFY) {
|
||||||
// Reset the drqBytes for this block
|
// Reset the drqBytes for this block
|
||||||
drqBytesLeft = sizeof(struct hd_driveid);
|
drqBytesLeft = sizeof(struct hd_driveid);
|
||||||
|
|
||||||
|
@ -887,9 +915,9 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
} else {
|
} else {
|
||||||
devState = Prepare_Data_In;
|
devState = Prepare_Data_In;
|
||||||
// set the BSY_BIT
|
// set the BSY_BIT
|
||||||
cmdReg.status |= STATUS_BSY_BIT;
|
status |= STATUS_BSY_BIT;
|
||||||
// clear the DRQ_BIT
|
// clear the DRQ_BIT
|
||||||
cmdReg.status &= ~STATUS_DRQ_BIT;
|
status &= ~STATUS_DRQ_BIT;
|
||||||
|
|
||||||
/** @todo change this to a scheduled event to simulate
|
/** @todo change this to a scheduled event to simulate
|
||||||
disk delay */
|
disk delay */
|
||||||
|
@ -910,20 +938,23 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
} else {
|
} else {
|
||||||
devState = Device_Idle_S;
|
devState = Device_Idle_S;
|
||||||
}
|
}
|
||||||
} else if (cmdBytesLeft != 0) {
|
} else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
|
||||||
// clear the BSY bit
|
// clear the BSY bit
|
||||||
cmdReg.status &= ~STATUS_BSY_BIT;
|
status &= ~STATUS_BSY_BIT;
|
||||||
// set the DRQ bit
|
// set the DRQ bit
|
||||||
cmdReg.status |= STATUS_DRQ_BIT;
|
status |= STATUS_DRQ_BIT;
|
||||||
|
|
||||||
// clear the data buffer to get it ready for writes
|
// clear the data buffer to get it ready for writes
|
||||||
memset(dataBuffer, 0, MAX_DMA_SIZE);
|
memset(dataBuffer, 0, MAX_DMA_SIZE);
|
||||||
|
|
||||||
if (!isIENSet()) {
|
// reset the drqBytes for this block
|
||||||
|
drqBytesLeft = SectorSize;
|
||||||
|
|
||||||
|
if (cmdBytesLeft == cmdBytes || isIENSet()) {
|
||||||
|
devState = Transfer_Data_Out;
|
||||||
|
} else {
|
||||||
devState = Data_Ready_INTRQ_Out;
|
devState = Data_Ready_INTRQ_Out;
|
||||||
intrPost();
|
intrPost();
|
||||||
} else {
|
|
||||||
devState = Transfer_Data_Out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -956,9 +987,11 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
writeDisk(curSector++, dataBuffer);
|
writeDisk(curSector++, dataBuffer);
|
||||||
|
|
||||||
// set the BSY bit
|
// set the BSY bit
|
||||||
cmdReg.status |= STATUS_BSY_BIT;
|
status |= STATUS_BSY_BIT;
|
||||||
|
// set the seek bit
|
||||||
|
status |= STATUS_SEEK_BIT;
|
||||||
// clear the DRQ bit
|
// clear the DRQ bit
|
||||||
cmdReg.status &= ~STATUS_DRQ_BIT;
|
status &= ~STATUS_DRQ_BIT;
|
||||||
|
|
||||||
devState = Prepare_Data_Out;
|
devState = Prepare_Data_Out;
|
||||||
|
|
||||||
|
@ -982,9 +1015,9 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
}
|
}
|
||||||
} else if (action == ACT_DMA_READY) {
|
} else if (action == ACT_DMA_READY) {
|
||||||
// clear the BSY bit
|
// clear the BSY bit
|
||||||
cmdReg.status &= ~STATUS_BSY_BIT;
|
status &= ~STATUS_BSY_BIT;
|
||||||
// set the DRQ bit
|
// set the DRQ bit
|
||||||
cmdReg.status |= STATUS_DRQ_BIT;
|
status |= STATUS_DRQ_BIT;
|
||||||
|
|
||||||
devState = Transfer_Data_Dma;
|
devState = Transfer_Data_Dma;
|
||||||
|
|
||||||
|
@ -1001,7 +1034,7 @@ IdeDisk::updateState(DevAction_t action)
|
||||||
// clear the BSY bit
|
// clear the BSY bit
|
||||||
setComplete();
|
setComplete();
|
||||||
// set the seek bit
|
// set the seek bit
|
||||||
cmdReg.status |= 0x10;
|
status |= STATUS_SEEK_BIT;
|
||||||
// clear the controller state for DMA transfer
|
// clear the controller state for DMA transfer
|
||||||
ctrl->setDmaComplete(this);
|
ctrl->setDmaComplete(this);
|
||||||
|
|
||||||
|
@ -1058,7 +1091,7 @@ IdeDisk::serialize(ostream &os)
|
||||||
SERIALIZE_SCALAR(cmdReg.cyl_low);
|
SERIALIZE_SCALAR(cmdReg.cyl_low);
|
||||||
SERIALIZE_SCALAR(cmdReg.cyl_high);
|
SERIALIZE_SCALAR(cmdReg.cyl_high);
|
||||||
SERIALIZE_SCALAR(cmdReg.drive);
|
SERIALIZE_SCALAR(cmdReg.drive);
|
||||||
SERIALIZE_SCALAR(cmdReg.status);
|
SERIALIZE_SCALAR(status);
|
||||||
SERIALIZE_SCALAR(nIENBit);
|
SERIALIZE_SCALAR(nIENBit);
|
||||||
SERIALIZE_SCALAR(devID);
|
SERIALIZE_SCALAR(devID);
|
||||||
|
|
||||||
|
@ -1070,9 +1103,9 @@ IdeDisk::serialize(ostream &os)
|
||||||
|
|
||||||
// Serialize current transfer related information
|
// Serialize current transfer related information
|
||||||
SERIALIZE_SCALAR(cmdBytesLeft);
|
SERIALIZE_SCALAR(cmdBytesLeft);
|
||||||
|
SERIALIZE_SCALAR(cmdBytes);
|
||||||
SERIALIZE_SCALAR(drqBytesLeft);
|
SERIALIZE_SCALAR(drqBytesLeft);
|
||||||
SERIALIZE_SCALAR(curSector);
|
SERIALIZE_SCALAR(curSector);
|
||||||
SERIALIZE_SCALAR(curCommand);
|
|
||||||
SERIALIZE_SCALAR(dmaRead);
|
SERIALIZE_SCALAR(dmaRead);
|
||||||
SERIALIZE_SCALAR(dmaInterfaceBytes);
|
SERIALIZE_SCALAR(dmaInterfaceBytes);
|
||||||
SERIALIZE_SCALAR(intrPending);
|
SERIALIZE_SCALAR(intrPending);
|
||||||
|
@ -1110,7 +1143,7 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion)
|
||||||
UNSERIALIZE_SCALAR(cmdReg.cyl_low);
|
UNSERIALIZE_SCALAR(cmdReg.cyl_low);
|
||||||
UNSERIALIZE_SCALAR(cmdReg.cyl_high);
|
UNSERIALIZE_SCALAR(cmdReg.cyl_high);
|
||||||
UNSERIALIZE_SCALAR(cmdReg.drive);
|
UNSERIALIZE_SCALAR(cmdReg.drive);
|
||||||
UNSERIALIZE_SCALAR(cmdReg.status);
|
UNSERIALIZE_SCALAR(status);
|
||||||
UNSERIALIZE_SCALAR(nIENBit);
|
UNSERIALIZE_SCALAR(nIENBit);
|
||||||
UNSERIALIZE_SCALAR(devID);
|
UNSERIALIZE_SCALAR(devID);
|
||||||
|
|
||||||
|
@ -1121,10 +1154,10 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion)
|
||||||
UNSERIALIZE_SCALAR(curPrdAddr);
|
UNSERIALIZE_SCALAR(curPrdAddr);
|
||||||
|
|
||||||
// Unserialize current transfer related information
|
// Unserialize current transfer related information
|
||||||
|
UNSERIALIZE_SCALAR(cmdBytes);
|
||||||
UNSERIALIZE_SCALAR(cmdBytesLeft);
|
UNSERIALIZE_SCALAR(cmdBytesLeft);
|
||||||
UNSERIALIZE_SCALAR(drqBytesLeft);
|
UNSERIALIZE_SCALAR(drqBytesLeft);
|
||||||
UNSERIALIZE_SCALAR(curSector);
|
UNSERIALIZE_SCALAR(curSector);
|
||||||
UNSERIALIZE_SCALAR(curCommand);
|
|
||||||
UNSERIALIZE_SCALAR(dmaRead);
|
UNSERIALIZE_SCALAR(dmaRead);
|
||||||
UNSERIALIZE_SCALAR(dmaInterfaceBytes);
|
UNSERIALIZE_SCALAR(dmaInterfaceBytes);
|
||||||
UNSERIALIZE_SCALAR(intrPending);
|
UNSERIALIZE_SCALAR(intrPending);
|
||||||
|
|
|
@ -94,6 +94,8 @@ 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 STATUS_SEEK_BIT 0x10
|
||||||
|
#define STATUS_DF_BIT 0x20
|
||||||
#define DRIVE_LBA_BIT 0x40
|
#define DRIVE_LBA_BIT 0x40
|
||||||
|
|
||||||
#define DEV0 (0)
|
#define DEV0 (0)
|
||||||
|
@ -114,10 +116,7 @@ typedef struct CommandReg {
|
||||||
uint8_t drive;
|
uint8_t drive;
|
||||||
uint8_t head;
|
uint8_t head;
|
||||||
};
|
};
|
||||||
union {
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
};
|
|
||||||
} CommandReg_t;
|
} CommandReg_t;
|
||||||
|
|
||||||
typedef enum Events {
|
typedef enum Events {
|
||||||
|
@ -135,6 +134,7 @@ typedef enum DevAction {
|
||||||
ACT_CMD_WRITE,
|
ACT_CMD_WRITE,
|
||||||
ACT_CMD_COMPLETE,
|
ACT_CMD_COMPLETE,
|
||||||
ACT_CMD_ERROR,
|
ACT_CMD_ERROR,
|
||||||
|
ACT_SELECT_WRITE,
|
||||||
ACT_STAT_READ,
|
ACT_STAT_READ,
|
||||||
ACT_DATA_READY,
|
ACT_DATA_READY,
|
||||||
ACT_DATA_READ_BYTE,
|
ACT_DATA_READ_BYTE,
|
||||||
|
@ -142,7 +142,9 @@ typedef enum DevAction {
|
||||||
ACT_DATA_WRITE_BYTE,
|
ACT_DATA_WRITE_BYTE,
|
||||||
ACT_DATA_WRITE_SHORT,
|
ACT_DATA_WRITE_SHORT,
|
||||||
ACT_DMA_READY,
|
ACT_DMA_READY,
|
||||||
ACT_DMA_DONE
|
ACT_DMA_DONE,
|
||||||
|
ACT_SRST_SET,
|
||||||
|
ACT_SRST_CLEAR
|
||||||
} DevAction_t;
|
} DevAction_t;
|
||||||
|
|
||||||
typedef enum DevState {
|
typedef enum DevState {
|
||||||
|
@ -151,6 +153,9 @@ typedef enum DevState {
|
||||||
Device_Idle_SI,
|
Device_Idle_SI,
|
||||||
Device_Idle_NS,
|
Device_Idle_NS,
|
||||||
|
|
||||||
|
// Software reset
|
||||||
|
Device_Srst,
|
||||||
|
|
||||||
// Non-data commands
|
// Non-data commands
|
||||||
Command_Execution,
|
Command_Execution,
|
||||||
|
|
||||||
|
@ -202,6 +207,8 @@ class IdeDisk : public SimObject
|
||||||
struct hd_driveid driveID;
|
struct hd_driveid driveID;
|
||||||
/** Data buffer for transfers */
|
/** Data buffer for transfers */
|
||||||
uint8_t *dataBuffer;
|
uint8_t *dataBuffer;
|
||||||
|
/** Number of bytes in command data transfer */
|
||||||
|
uint32_t cmdBytes;
|
||||||
/** Number of bytes left in command data transfer */
|
/** Number of bytes left in command data transfer */
|
||||||
uint32_t cmdBytesLeft;
|
uint32_t cmdBytesLeft;
|
||||||
/** Number of bytes left in DRQ block */
|
/** Number of bytes left in DRQ block */
|
||||||
|
@ -210,8 +217,8 @@ class IdeDisk : public SimObject
|
||||||
uint32_t curSector;
|
uint32_t curSector;
|
||||||
/** Command block registers */
|
/** Command block registers */
|
||||||
CommandReg_t cmdReg;
|
CommandReg_t cmdReg;
|
||||||
/** Shadow of the current command code */
|
/** Status register */
|
||||||
uint8_t curCommand;
|
uint8_t status;
|
||||||
/** Interrupt enable bit */
|
/** Interrupt enable bit */
|
||||||
bool nIENBit;
|
bool nIENBit;
|
||||||
/** Device state */
|
/** Device state */
|
||||||
|
@ -248,6 +255,11 @@ class IdeDisk : public SimObject
|
||||||
*/
|
*/
|
||||||
~IdeDisk();
|
~IdeDisk();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the device state
|
||||||
|
*/
|
||||||
|
void reset(int id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the controller for this device
|
* Set the controller for this device
|
||||||
* @param c The IDE controller
|
* @param c The IDE controller
|
||||||
|
@ -306,17 +318,18 @@ class IdeDisk : public SimObject
|
||||||
void updateState(DevAction_t action);
|
void updateState(DevAction_t action);
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
bool isBSYSet() { return (cmdReg.status & STATUS_BSY_BIT); }
|
bool isBSYSet() { return (status & STATUS_BSY_BIT); }
|
||||||
bool isIENSet() { return nIENBit; }
|
bool isIENSet() { return nIENBit; }
|
||||||
bool isDEVSelect() { return ((cmdReg.drive & SELECT_DEV_BIT) == devID); }
|
bool isDEVSelect() { return ((cmdReg.drive & SELECT_DEV_BIT) == devID); }
|
||||||
|
|
||||||
void setComplete()
|
void setComplete()
|
||||||
{
|
{
|
||||||
// clear out the status byte
|
// clear out the status byte
|
||||||
cmdReg.status = 0;
|
status = 0;
|
||||||
|
|
||||||
// set the DRDY bit
|
// set the DRDY bit
|
||||||
cmdReg.status |= STATUS_DRDY_BIT;
|
status |= STATUS_DRDY_BIT;
|
||||||
|
// set the SEEK bit
|
||||||
|
status |= STATUS_SEEK_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getLBABase()
|
uint32_t getLBABase()
|
||||||
|
|
Loading…
Reference in a new issue