dev/tsunami_pchip.cc:
    SCCS merged

--HG--
extra : convert_revision : 064e3bab82aacf813d1f049d72429fd990608044
This commit is contained in:
Ali Saidi 2004-06-04 13:46:04 -04:00
commit 07448480fc
4 changed files with 165 additions and 87 deletions

View file

@ -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 &section)
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 &section)
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);

View file

@ -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()

View file

@ -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 &section) TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
{ {
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);

View file

@ -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];