void
IdeController::ReadConfig(int offset, int size, uint8_t *data)
{
- int config_offset;
+ union {
+ uint8_t byte;
+ uint16_t word;
+ uint32_t dword;
+ };
-#if TRACING_ON
- Addr origOffset = offset;
-#endif
+ int config_offset;
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::ReadConfig(offset, size, data);
} else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) {
config_offset = offset - IDE_CTRL_CONFIG_START;
+ dword = 0;
- switch(size) {
+ switch (size) {
+ case sizeof(uint8_t):
+ case sizeof(uint16_t):
case sizeof(uint32_t):
- memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint32_t));
- *(uint32_t*)data = htoa(*(uint32_t*)data);
+ memcpy(&byte, &pci_config_regs.data[config_offset], size);
break;
- case sizeof(uint16_t):
- memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint16_t));
- *(uint16_t*)data = htoa(*(uint16_t*)data);
- break;
+ default:
+ panic("Invalid PCI configuration read size!\n");
+ }
+ switch (size) {
case sizeof(uint8_t):
- memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint8_t));
+ *data = byte;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t*)data = htoa(word);
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t*)data = htoa(dword);
break;
-
- default:
- panic("Invalid PCI configuration read size!\n");
}
+
+ DPRINTF(IdeCtrl, "PCI read offset: %#x size: %#x data: %#x\n",
+ offset, size, htoa(dword));
+
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
-
- DPRINTF(IdeCtrl, "PCI read offset: %#x (%#x) size: %#x data: %#x\n",
- origOffset, offset, size,
- *(uint32_t *)data & (0xffffffff >> 8 * (4 - size)));
}
void
IdeController::WriteConfig(int offset, int size, uint32_t data)
{
int config_offset;
+ uint32_t write_data;
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::WriteConfig(offset, size, data);
config_offset = offset - IDE_CTRL_CONFIG_START;
+ write_data = htoa(data);
+
switch(size) {
- case sizeof(uint32_t):
- case sizeof(uint16_t):
case sizeof(uint8_t):
- memcpy(&pci_config_regs.data[config_offset], &data, size);
+ case sizeof(uint16_t):
+ case sizeof(uint32_t):
+ memcpy(&pci_config_regs.data[config_offset], &write_data, size);
break;
default:
panic("Invalid PCI configuration write size!\n");
}
-
} else {
panic("Write of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n",
- offset, size, data & (0xffffffff >> 8 * (4 - size)));
-
+ offset, size, data);
// Catch the writes to specific PCI registers that have side affects
// (like updating the PIO ranges)
RegType_t type;
int disk;
+ union {
+ uint8_t byte;
+ uint16_t word[2];
+ uint32_t dword;
+ };
+
parseAddr(req->paddr, offset, primary, type);
if (!io_enabled)
panic("IDE controller read of invalid size: %#x\n", req->size);
}
- if (type != BMI_BLOCK) {
+ switch (type) {
+ case BMI_BLOCK:
+ memcpy(&byte, &bmi_regs[offset], req->size);
+ switch (req->size) {
+ case sizeof(uint8_t):
+ *data = byte;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t*)data = htoa(word[0]);
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t*)data = htoa(dword);
+ break;
+ }
+ break;
+ case COMMAND_BLOCK:
+ case CONTROL_BLOCK:
disk = getDisk(primary);
- if (disks[disk])
- if (req->size == sizeof(uint32_t) && offset == DATA_OFFSET) {
- ((uint16_t*)data)[0] = disks[disk]->read(offset, type);
- ((uint16_t*)data)[1] = disks[disk]->read(offset, type);
- }
- else if (req->size == sizeof(uint8_t) && offset == DATA_OFFSET) {
+
+ if (disks[disk] == NULL)
+ break;
+
+ switch (offset) {
+ case DATA_OFFSET:
+ switch (req->size) {
+ case sizeof(uint16_t):
+ disks[disk]->read(offset, type, (uint8_t*)&word[0]);
+ *(uint16_t*)data = htoa(word[0]);
+ break;
+
+ case sizeof(uint32_t):
+ disks[disk]->read(offset, type, (uint8_t*)&word[0]);
+ disks[disk]->read(offset, type, (uint8_t*)&word[1]);
+ *(uint32_t*)data = htoa(dword);
+ break;
+
+ default:
panic("IDE read of data reg invalid size: %#x\n", req->size);
}
- else {
- *data = disks[disk]->read(offset, type);
- }
- } else {
- memcpy((void *)data, &bmi_regs[offset], req->size);
+ break;
+ default:
+ if (req->size == sizeof(uint8_t)) {
+ disks[disk]->read(offset, type, &byte);
+ *data = byte;
+ } else
+ panic("IDE read of command reg of invalid size: %#x\n", req->size);
+ }
+ break;
}
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size,
- (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size)));
+ offset, req->size, htoa(dword));
return No_Fault;
}
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()
memset(&cmdReg, 0, sizeof(CommandReg_t));
memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
- cmdReg.error = 1;
dmaInterfaceBytes = 0;
curPrdAddr = 0;
curSector = 0;
// set the device ready bit
status = STATUS_DRDY_BIT;
+
+ cmdReg.error = 0x1;
}
////
// Device registers read/write
////
-uint16_t
-IdeDisk::read(const Addr &offset, RegType_t type)
+void
+IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data)
{
- uint16_t data;
DevAction_t action = ACT_NONE;
- if (type == COMMAND_BLOCK) {
-
+ switch (type) {
+ case COMMAND_BLOCK:
if (offset == STATUS_OFFSET)
action = ACT_STAT_READ;
else if (offset == DATA_OFFSET)
action = ACT_DATA_READ_SHORT;
switch (offset) {
+ // Data transfers occur 16 bits at a time
case DATA_OFFSET:
- data = cmdReg.data;
+ // use memcpy to preserve little-endianess
+ memcpy(data, &cmdReg.data, sizeof(uint16_t));
break;
+ // All other transfers are 8 bit
case ERROR_OFFSET:
- data = cmdReg.error;
+ *data = cmdReg.error;
break;
case NSECTOR_OFFSET:
- data = cmdReg.sec_count;
+ *data = cmdReg.sec_count;
break;
case SECTOR_OFFSET:
- data = cmdReg.sec_num;
+ *data = cmdReg.sec_num;
break;
case LCYL_OFFSET:
- data = cmdReg.cyl_low;
+ *data = cmdReg.cyl_low;
break;
case HCYL_OFFSET:
- data = cmdReg.cyl_high;
+ *data = cmdReg.cyl_high;
break;
- case SELECT_OFFSET:
- data = cmdReg.drive;
+ case DRIVE_OFFSET:
+ *data = cmdReg.drive;
break;
case STATUS_OFFSET:
- data = status;
+ *data = status;
break;
default:
panic("Invalid IDE command register offset: %#x\n", offset);
}
- }
- else if (type == CONTROL_BLOCK) {
- if (offset != ALTSTAT_OFFSET)
+ break;
+ case CONTROL_BLOCK:
+ if (offset == ALTSTAT_OFFSET)
+ *data = status;
+ else
panic("Invalid IDE control register offset: %#x\n", offset);
+ break;
- data = status;
- }
- else {
- panic("Invalid IDE register type: %#x\n", type);
+ default:
+ panic("Unknown register block!\n");
}
if (action != ACT_NONE)
updateState(action);
-
- return data;
}
void
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");
else {
switch (offset) {
case DATA_OFFSET:
- cmdReg.data = *data;
+ memcpy(&cmdReg.data, data, sizeof(uint16_t));
break;
case FEATURES_OFFSET:
- cmdReg.features = *data;
+ //cmdReg.features = *data;
break;
case NSECTOR_OFFSET:
cmdReg.sec_count = *data;
case HCYL_OFFSET:
cmdReg.cyl_high = *data;
break;
- case SELECT_OFFSET:
+ case DRIVE_OFFSET:
cmdReg.drive = *data;
break;
case COMMAND_OFFSET:
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;
}
#define LCYL_OFFSET (4)
#define HCYL_OFFSET (5)
#define SELECT_OFFSET (6)
+#define DRIVE_OFFSET (6)
#define STATUS_OFFSET (7)
#define COMMAND_OFFSET (7)
typedef struct CommandReg {
uint16_t data;
- union {
- uint8_t error;
- uint8_t features;
- };
+ uint8_t error;
uint8_t sec_count;
uint8_t sec_num;
uint8_t cyl_low;
}
// Device register read/write
- uint16_t read(const Addr &offset, RegType_t type);
+ void read(const Addr &offset, RegType_t type, uint8_t *data);
void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data);
// Start/abort functions
int func = (daddr >> 8) & 0x7;
int reg = daddr & 0xFF;
- union {
- uint8_t byte_value;
- uint16_t half_value;
- uint32_t word_value;
- };
+ uint32_t word_value = 0;
if (devices[device][func] == NULL)
panic("Attempting to write to config space on non-existant device\n");
else {
switch (req->size) {
case sizeof(uint8_t):
- byte_value = *(uint8_t*)data;
+ word_value = *(uint8_t*)data & 0x000000FF;
break;
case sizeof(uint16_t):
- half_value = *(uint16_t*)data;
+ word_value = *(uint16_t*)data & 0x0000FFFF;
break;
case sizeof(uint32_t):
word_value = *(uint32_t*)data;
void
PciDev::ReadConfig(int offset, int size, uint8_t *data)
{
+ union {
+ uint8_t byte;
+ uint16_t word;
+ uint32_t dword;
+ };
+
+ dword = 0;
+
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
switch(size) {
+ case sizeof(uint8_t):
+ case sizeof(uint16_t):
case sizeof(uint32_t):
- memcpy(data, &config.data[offset], sizeof(uint32_t));
- *(uint32_t*)data = htoa(*(uint32_t*)data);
-
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, size,
- *(uint32_t*)data);
+ memcpy(&byte, &config.data[offset], size);
break;
- case sizeof(uint16_t):
- memcpy(data, &config.data[offset], sizeof(uint16_t));
- *(uint16_t*)data = htoa(*(uint16_t*)data);
-
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, size,
- *(uint16_t*)data);
- break;
+ default:
+ panic("Invalid PCI configuration read size!\n");
+ }
+ switch(size) {
case sizeof(uint8_t):
- memcpy(data, &config.data[offset], sizeof(uint8_t));
- DPRINTF(PCIDEV,
- "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- params()->deviceNum, params()->functionNum, offset, size,
- *data);
+ *data = byte;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t*)data = htoa(word);
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t*)data = htoa(dword);
break;
-
- default:
- panic("Invalid PCI configuration read size!\n");
}
+
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, size,
+ htoa(dword));
}
void
uint32_t barnum;
- union {
- uint8_t byte_value;
- uint16_t half_value;
- uint32_t word_value;
- };
- word_value = data;
+ uint8_t byte_value = data;
+ uint16_t half_value = data;
+ uint32_t word_value = data;
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
params()->deviceNum, params()->functionNum, offset, size,
- word_value);
+ data);
barnum = (offset - PCI0_BASE_ADDR0) >> 2;
}
break;
- case sizeof(uint16_t)+1: // 3-byte access
- panic("invalid access size");
-
case sizeof(uint32_t): // 4-byte access
switch (offset) {
case PCI0_BASE_ADDR0:
// This is I/O Space, bottom two bits are read only
if (htoa(config.data[offset]) & 0x1) {
*(uint32_t *)&config.data[offset] = htoa(
- ~(BARSize[barnum] - 1) |
+ (~(BARSize[barnum] - 1) & ~0x3) |
(htoa(config.data[offset]) & 0x3));
} else {
// This is memory space, bottom four bits are read only
*(uint32_t *)&config.data[offset] = htoa(
- ~(BARSize[barnum] - 1) |
+ (~(BARSize[barnum] - 1) & ~0xF) |
(htoa(config.data[offset]) & 0xF));
}
} else {
DPRINTF(PCIDEV, "Writing to a read only register");
}
break;
+
+ default:
+ panic("invalid access size");
}
}
protected:
/** The current config space. Unlike the PciConfigData this is
- * updated during simulation while continues to refelect what was
+ * updated during simulation while continues to reflect what was
* in the config file.
*/
PCIConfig config;
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff);
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) + 0x20;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
case RTC_SEC:
*(uint8_t *)data = tm.tm_sec;
return No_Fault;
+ case RTC_SEC_ALRM:
+ case RTC_MIN_ALRM:
+ case RTC_HR_ALRM:
+ // RTC alarm functionality is not currently implemented
+ *(uint8_t *)data = 0x00;
+ return No_Fault;
case RTC_MIN:
*(uint8_t *)data = tm.tm_min;
return No_Fault;
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff, dt64);
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) + 0x20;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
case sizeof(uint8_t):
void
Uart8250::IntrEvent::scheduleIntr()
{
- static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 450);
+ static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 600);
DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit,
curTick + interval);
if (!scheduled())
break;
case 0x2: // Intr Identification Register (IIR)
DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
- if (status)
- *(uint8_t*)data = 0;
+ status &= ~TX_INT;
+ if (status & RX_INT)
+ *(uint8_t*)data = 0x4;
else
- *(uint8_t*)data = 1;
+ *(uint8_t*)data = 0x1;
break;
case 0x3: // Line Control Register (LCR)
*(uint8_t*)data = LCR;