Merge
dev/tsunami_pchip.cc: SCCS merged --HG-- extra : convert_revision : 064e3bab82aacf813d1f049d72429fd990608044
This commit is contained in:
commit
07448480fc
4 changed files with 165 additions and 87 deletions
168
dev/ide_disk.cc
168
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;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +330,13 @@ IdeDisk::dmaPrdReadDone()
|
||||||
physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
|
physmem->dma_addr(curPrdAddr, sizeof(PrdEntry_t)),
|
||||||
sizeof(PrdEntry_t));
|
sizeof(PrdEntry_t));
|
||||||
|
|
||||||
curPrdAddr += sizeof(PrdEntry_t);
|
DPRINTF(IdeDisk, "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
|
||||||
|
curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
|
||||||
|
curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
|
||||||
|
curPrd.getEOT(), curSector);
|
||||||
|
|
||||||
|
// make sure the new curPrdAddr is properly translated from PCI to system
|
||||||
|
curPrdAddr = pciToDma(curPrdAddr + sizeof(PrdEntry_t));
|
||||||
|
|
||||||
if (dmaRead)
|
if (dmaRead)
|
||||||
doDmaRead();
|
doDmaRead();
|
||||||
|
@ -598,7 +619,8 @@ 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 = pciToDma((Addr)prdTableBase);
|
// PRD base address is given by bits 31:2
|
||||||
|
curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
|
||||||
|
|
||||||
dmaState = Dma_Transfer;
|
dmaState = Dma_Transfer;
|
||||||
|
|
||||||
|
@ -625,9 +647,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 +675,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 +686,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 +704,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 +722,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 +738,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 +786,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 +823,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 +861,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 +922,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 +945,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 +994,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 +1022,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 +1041,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 +1098,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 +1110,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 +1150,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 +1161,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);
|
||||||
|
|
|
@ -40,8 +40,8 @@
|
||||||
|
|
||||||
#define DMA_BACKOFF_PERIOD 200
|
#define DMA_BACKOFF_PERIOD 200
|
||||||
|
|
||||||
#define MAX_DMA_SIZE (131072) // 256 * SectorSize (512)
|
#define MAX_DMA_SIZE (65536) // 64K
|
||||||
#define MAX_MULTSECT (128)
|
#define MAX_MULTSECT (128)
|
||||||
|
|
||||||
#define PRD_BASE_MASK 0xfffffffe
|
#define PRD_BASE_MASK 0xfffffffe
|
||||||
#define PRD_COUNT_MASK 0xfffe
|
#define PRD_COUNT_MASK 0xfffe
|
||||||
|
@ -62,7 +62,7 @@ class PrdTableEntry {
|
||||||
return (entry.baseAddr & PRD_BASE_MASK);
|
return (entry.baseAddr & PRD_BASE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getByteCount()
|
uint32_t getByteCount()
|
||||||
{
|
{
|
||||||
return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
|
return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
|
||||||
(entry.byteCount & PRD_COUNT_MASK));
|
(entry.byteCount & PRD_COUNT_MASK));
|
||||||
|
@ -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 command;
|
||||||
uint8_t status;
|
|
||||||
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()
|
||||||
|
|
|
@ -62,6 +62,9 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
|
||||||
tba[i] = 0;
|
tba[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize pchip control register
|
||||||
|
pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
|
||||||
|
|
||||||
//Set back pointer in tsunami
|
//Set back pointer in tsunami
|
||||||
tsunami->pchip = this;
|
tsunami->pchip = this;
|
||||||
}
|
}
|
||||||
|
@ -115,8 +118,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
|
||||||
*(uint64_t*)data = tba[3];
|
*(uint64_t*)data = tba[3];
|
||||||
return No_Fault;
|
return No_Fault;
|
||||||
case TSDEV_PC_PCTL:
|
case TSDEV_PC_PCTL:
|
||||||
// might want to change the clock??
|
*(uint64_t*)data = pctl;
|
||||||
*(uint64_t*)data = 0x00; // try this
|
|
||||||
return No_Fault;
|
return No_Fault;
|
||||||
case TSDEV_PC_PLAT:
|
case TSDEV_PC_PLAT:
|
||||||
panic("PC_PLAT not implemented\n");
|
panic("PC_PLAT not implemented\n");
|
||||||
|
@ -205,7 +207,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
|
||||||
tba[3] = *(uint64_t*)data;
|
tba[3] = *(uint64_t*)data;
|
||||||
return No_Fault;
|
return No_Fault;
|
||||||
case TSDEV_PC_PCTL:
|
case TSDEV_PC_PCTL:
|
||||||
// might want to change the clock??
|
pctl = *(uint64_t*)data;
|
||||||
return No_Fault;
|
return No_Fault;
|
||||||
case TSDEV_PC_PLAT:
|
case TSDEV_PC_PLAT:
|
||||||
panic("PC_PLAT not implemented\n");
|
panic("PC_PLAT not implemented\n");
|
||||||
|
@ -260,12 +262,29 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||||
Addr pteAddr;
|
Addr pteAddr;
|
||||||
Addr dmaAddr;
|
Addr dmaAddr;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
|
||||||
|
i, wsba[i], wsm[i]);
|
||||||
|
|
||||||
windowBase = wsba[i];
|
windowBase = wsba[i];
|
||||||
windowMask = ~wsm[i] & (0x7ff << 20);
|
windowMask = ~wsm[i] & (ULL(0xfff) << 20);
|
||||||
|
|
||||||
if ((busAddr & windowMask) == (windowBase & windowMask)) {
|
if ((busAddr & windowMask) == (windowBase & windowMask)) {
|
||||||
|
DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
|
||||||
|
i, windowBase, windowMask, (busAddr & windowMask),
|
||||||
|
(windowBase & windowMask));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
|
||||||
|
windowBase = wsba[i];
|
||||||
|
windowMask = ~wsm[i] & (ULL(0xfff) << 20);
|
||||||
|
|
||||||
|
if ((busAddr & windowMask) == (windowBase & windowMask)) {
|
||||||
|
|
||||||
if (wsba[i] & 0x1) { // see if enabled
|
if (wsba[i] & 0x1) { // see if enabled
|
||||||
if (wsba[i] & 0x2) { // see if SG bit is set
|
if (wsba[i] & 0x2) { // see if SG bit is set
|
||||||
|
@ -279,8 +298,8 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||||
to create an address for the SG page
|
to create an address for the SG page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff);
|
tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
|
||||||
baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13);
|
baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
|
||||||
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
|
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
|
||||||
|
|
||||||
memcpy((void *)&pteEntry,
|
memcpy((void *)&pteEntry,
|
||||||
|
@ -288,10 +307,10 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||||
physmem->dma_addr(pteAddr, sizeof(uint64_t)),
|
physmem->dma_addr(pteAddr, sizeof(uint64_t)),
|
||||||
sizeof(uint64_t));
|
sizeof(uint64_t));
|
||||||
|
|
||||||
dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff);
|
dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff;
|
baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
|
||||||
tbaMask = ~baMask;
|
tbaMask = ~baMask;
|
||||||
dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
|
dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
|
||||||
}
|
}
|
||||||
|
@ -301,12 +320,14 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
// if no match was found, then return the original address
|
||||||
|
return busAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TsunamiPChip::serialize(std::ostream &os)
|
TsunamiPChip::serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
|
SERIALIZE_SCALAR(pctl);
|
||||||
SERIALIZE_ARRAY(wsba, 4);
|
SERIALIZE_ARRAY(wsba, 4);
|
||||||
SERIALIZE_ARRAY(wsm, 4);
|
SERIALIZE_ARRAY(wsm, 4);
|
||||||
SERIALIZE_ARRAY(tba, 4);
|
SERIALIZE_ARRAY(tba, 4);
|
||||||
|
@ -315,6 +336,7 @@ TsunamiPChip::serialize(std::ostream &os)
|
||||||
void
|
void
|
||||||
TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion)
|
TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
{
|
{
|
||||||
|
UNSERIALIZE_SCALAR(pctl);
|
||||||
UNSERIALIZE_ARRAY(wsba, 4);
|
UNSERIALIZE_ARRAY(wsba, 4);
|
||||||
UNSERIALIZE_ARRAY(wsm, 4);
|
UNSERIALIZE_ARRAY(wsm, 4);
|
||||||
UNSERIALIZE_ARRAY(tba, 4);
|
UNSERIALIZE_ARRAY(tba, 4);
|
||||||
|
|
|
@ -56,6 +56,9 @@ class TsunamiPChip : public FunctionalMemory
|
||||||
*/
|
*/
|
||||||
Tsunami *tsunami;
|
Tsunami *tsunami;
|
||||||
|
|
||||||
|
/** Pchip control register */
|
||||||
|
uint64_t pctl;
|
||||||
|
|
||||||
/** Window Base addresses */
|
/** Window Base addresses */
|
||||||
uint64_t wsba[4];
|
uint64_t wsba[4];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue