summaryrefslogtreecommitdiff
path: root/dev/ide_disk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dev/ide_disk.cc')
-rw-r--r--dev/ide_disk.cc134
1 files changed, 91 insertions, 43 deletions
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 23d04bb5e..74d2ae6de 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -116,6 +116,9 @@ IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
driveID.atap_udmamode_supp = 0x10;
// Statically set hardware config word
driveID.atap_hwreset_res = 0x4001;
+
+ //arbitrary for now...
+ driveID.atap_ata_major = WDC_VER_ATA7;
}
IdeDisk::~IdeDisk()
@@ -158,6 +161,8 @@ IdeDisk::reset(int id)
// set the device ready bit
status = STATUS_DRDY_BIT;
+
+ cmdReg.error = 0x1;
}
////
@@ -207,41 +212,58 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
////
void
-IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
+IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
{
DevAction_t action = ACT_NONE;
- if (cmdBlk) {
- if (offset < 0 || offset > sizeof(CommandReg_t))
- panic("Invalid disk command register offset: %#x\n", offset);
-
- if (!byte && offset != DATA_OFFSET)
- panic("Invalid 16-bit read, only allowed on data reg\n");
-
- if (!byte)
- *(uint16_t *)data = *(uint16_t *)&cmdReg.data0;
- else
- *data = ((uint8_t *)&cmdReg)[offset];
-
- // determine if an action needs to be taken on the state machine
- if (offset == STATUS_OFFSET) {
+ switch (type) {
+ case COMMAND_BLOCK:
+ if (offset == STATUS_OFFSET)
action = ACT_STAT_READ;
- *data = status; // status is in a shadow, explicity copy
- } else if (offset == DATA_OFFSET) {
- if (byte)
- action = ACT_DATA_READ_BYTE;
- else
- action = ACT_DATA_READ_SHORT;
+ else if (offset == DATA_OFFSET)
+ action = ACT_DATA_READ_SHORT;
+
+ switch (offset) {
+ // Data transfers occur 16 bits at a time
+ case DATA_OFFSET:
+ // use memcpy to preserve IDE's little-endianess
+ memcpy(data, &cmdReg.data, sizeof(uint16_t));
+ break;
+ // All other transfers are 8-bit
+ case ERROR_OFFSET:
+ *data = cmdReg.error;
+ break;
+ case NSECTOR_OFFSET:
+ *data = cmdReg.sec_count;
+ break;
+ case SECTOR_OFFSET:
+ *data = cmdReg.sec_num;
+ break;
+ case LCYL_OFFSET:
+ *data = cmdReg.cyl_low;
+ break;
+ case HCYL_OFFSET:
+ *data = cmdReg.cyl_high;
+ break;
+ case DRIVE_OFFSET:
+ *data = cmdReg.drive;
+ break;
+ case STATUS_OFFSET:
+ *data = status;
+ break;
+ default:
+ panic("Invalid IDE command register offset: %#x\n", offset);
}
+ break;
+ case CONTROL_BLOCK:
+ if (offset == ALTSTAT_OFFSET)
+ *data = status;
+ else
+ panic("Invalid IDE control register offset: %#x\n", offset);
+ break;
- } else {
- if (offset != ALTSTAT_OFFSET)
- panic("Invalid disk control register offset: %#x\n", offset);
-
- if (!byte)
- panic("Invalid 16-bit read from control block\n");
-
- *data = status;
+ default:
+ panic("Unknown register block!\n");
}
if (action != ACT_NONE)
@@ -254,16 +276,42 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
DevAction_t action = ACT_NONE;
if (cmdBlk) {
- if (offset < 0 || offset > sizeof(CommandReg_t))
- panic("Invalid disk command register offset: %#x\n", offset);
if (!byte && offset != DATA_OFFSET)
panic("Invalid 16-bit write, only allowed on data reg\n");
if (!byte)
- *((uint16_t *)&cmdReg.data0) = *(uint16_t *)data;
- else
- ((uint8_t *)&cmdReg)[offset] = *data;
+ *((uint16_t *)&cmdReg.data) = *(uint16_t *)data;
+ else {
+ switch (offset) {
+ case DATA_OFFSET:
+ memcpy(&cmdReg.data, data, sizeof(uint16_t));
+ break;
+ case FEATURES_OFFSET:
+ //cmdReg.features = *data;
+ break;
+ case NSECTOR_OFFSET:
+ cmdReg.sec_count = *data;
+ break;
+ case SECTOR_OFFSET:
+ cmdReg.sec_num = *data;
+ break;
+ case LCYL_OFFSET:
+ cmdReg.cyl_low = *data;
+ break;
+ case HCYL_OFFSET:
+ cmdReg.cyl_high = *data;
+ break;
+ case DRIVE_OFFSET:
+ cmdReg.drive = *data;
+ break;
+ case COMMAND_OFFSET:
+ cmdReg.command = *data;
+ break;
+ default:
+ panic("Invalid IDE command register offset: %#x\n", offset);
+ }
+ }
// determine if an action needs to be taken on the state machine
if (offset == COMMAND_OFFSET) {
@@ -273,7 +321,7 @@ IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
action = ACT_DATA_WRITE_BYTE;
else
action = ACT_DATA_WRITE_SHORT;
- } else if (offset == SELECT_OFFSET) {
+ } else if (offset == DRIVE_OFFSET) {
action = ACT_SELECT_WRITE;
}
@@ -744,8 +792,10 @@ IdeDisk::intrPost()
intrPending = true;
// talk to controller to set interrupt
- if (ctrl)
+ if (ctrl) {
+ ctrl->bmi_regs[BMIS0] |= IDEINTS;
ctrl->intrPost();
+ }
}
void
@@ -864,7 +914,7 @@ IdeDisk::updateState(DevAction_t action)
}
// put the first two bytes into the data register
- memcpy((void *)&cmdReg.data0, (void *)dataBuffer,
+ memcpy((void *)&cmdReg.data, (void *)dataBuffer,
sizeof(uint16_t));
if (!isIENSet()) {
@@ -893,7 +943,7 @@ IdeDisk::updateState(DevAction_t action)
// copy next short into data registers
if (drqBytesLeft)
- memcpy((void *)&cmdReg.data0,
+ memcpy((void *)&cmdReg.data,
(void *)&dataBuffer[SectorSize - drqBytesLeft],
sizeof(uint16_t));
}
@@ -966,7 +1016,7 @@ IdeDisk::updateState(DevAction_t action)
} else {
// copy the latest short into the data buffer
memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
- (void *)&cmdReg.data0,
+ (void *)&cmdReg.data,
sizeof(uint16_t));
drqBytesLeft -= 2;
@@ -1090,8 +1140,7 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_ENUM(event);
// Serialize device registers
- SERIALIZE_SCALAR(cmdReg.data0);
- SERIALIZE_SCALAR(cmdReg.data1);
+ SERIALIZE_SCALAR(cmdReg.data);
SERIALIZE_SCALAR(cmdReg.sec_count);
SERIALIZE_SCALAR(cmdReg.sec_num);
SERIALIZE_SCALAR(cmdReg.cyl_low);
@@ -1143,8 +1192,7 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
}
// Unserialize device registers
- UNSERIALIZE_SCALAR(cmdReg.data0);
- UNSERIALIZE_SCALAR(cmdReg.data1);
+ UNSERIALIZE_SCALAR(cmdReg.data);
UNSERIALIZE_SCALAR(cmdReg.sec_count);
UNSERIALIZE_SCALAR(cmdReg.sec_num);
UNSERIALIZE_SCALAR(cmdReg.cyl_low);