diff options
Diffstat (limited to 'dev/ide_ctrl.cc')
-rw-r--r-- | dev/ide_ctrl.cc | 221 |
1 files changed, 130 insertions, 91 deletions
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index 785f18ae8..a2b27d01a 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -76,10 +76,10 @@ IdeController::IdeController(Params *p) // zero out all of the registers memset(bmi_regs, 0, sizeof(bmi_regs)); - memset(pci_regs, 0, sizeof(pci_regs)); + memset(pci_config_regs.data, 0, sizeof(pci_config_regs.data)); // setup initial values - *(uint32_t *)&pci_regs[IDETIM] = 0x80008000; // enable both channels + pci_config_regs.idetim = htoa((uint32_t)0x80008000); // enable both channels *(uint8_t *)&bmi_regs[BMIS0] = 0x60; *(uint8_t *)&bmi_regs[BMIS1] = 0x60; @@ -251,93 +251,77 @@ IdeController::cacheAccess(MemReqPtr &req) void IdeController::ReadConfig(int offset, int size, uint8_t *data) { + 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 >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) { - offset -= PCI_IDE_TIMING; - offset += IDETIM; - - if ((offset + size) > (IDETIM + 4)) - panic("PCI read of IDETIM with invalid size\n"); - } else if (offset == PCI_SLAVE_TIMING) { - offset -= PCI_SLAVE_TIMING; - offset += SIDETIM; - - if ((offset + size) > (SIDETIM + 1)) - panic("PCI read of SIDETIM with invalid size\n"); - } else if (offset == PCI_UDMA33_CTRL) { - offset -= PCI_UDMA33_CTRL; - offset += UDMACTL; - - if ((offset + size) > (UDMACTL + 1)) - panic("PCI read of UDMACTL with invalid size\n"); - } else if (offset >= PCI_UDMA33_TIMING && - offset < (PCI_UDMA33_TIMING + 2)) { - offset -= PCI_UDMA33_TIMING; - offset += UDMATIM; - - if ((offset + size) > (UDMATIM + 2)) - panic("PCI read of UDMATIM with invalid size\n"); - } else { - panic("PCI read of unimplemented register: %x\n", offset); + } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { + + config_offset = offset - IDE_CTRL_CONFIG_START; + dword = 0; + + switch (size) { + case sizeof(uint8_t): + memcpy(&byte, &pci_config_regs.data[config_offset], size); + *data = byte; + break; + case sizeof(uint16_t): + memcpy(&byte, &pci_config_regs.data[config_offset], size); + *(uint16_t*)data = htoa(word); + break; + case sizeof(uint32_t): + memcpy(&byte, &pci_config_regs.data[config_offset], size); + *(uint32_t*)data = htoa(dword); + break; + default: + panic("Invalid PCI configuration read size!\n"); } - memcpy((void *)data, (void *)&pci_regs[offset], size); - } + DPRINTF(IdeCtrl, "PCI read offset: %#x size: %#x data: %#x\n", + offset, size, htoa(dword)); - DPRINTF(IdeCtrl, "PCI read offset: %#x (%#x) size: %#x data: %#x\n", - origOffset, offset, size, - (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - size))); + } else { + panic("Read of unimplemented PCI config. register: %x\n", offset); + } } void IdeController::WriteConfig(int offset, int size, uint32_t data) { - DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n", - offset, size, data & (0xffffffff >> 8 * (4 - size))); + int config_offset; + uint32_t write_data; - // do standard write stuff if in standard PCI space if (offset < PCI_DEVICE_SPECIFIC) { PciDev::WriteConfig(offset, size, data); - } else { - if (offset >= PCI_IDE_TIMING && offset < (PCI_IDE_TIMING + 4)) { - offset -= PCI_IDE_TIMING; - offset += IDETIM; - - if ((offset + size) > (IDETIM + 4)) - panic("PCI write to IDETIM with invalid size\n"); - } else if (offset == PCI_SLAVE_TIMING) { - offset -= PCI_SLAVE_TIMING; - offset += SIDETIM; - - if ((offset + size) > (SIDETIM + 1)) - panic("PCI write to SIDETIM with invalid size\n"); - } else if (offset == PCI_UDMA33_CTRL) { - offset -= PCI_UDMA33_CTRL; - offset += UDMACTL; - - if ((offset + size) > (UDMACTL + 1)) - panic("PCI write to UDMACTL with invalid size\n"); - } else if (offset >= PCI_UDMA33_TIMING && - offset < (PCI_UDMA33_TIMING + 2)) { - offset -= PCI_UDMA33_TIMING; - offset += UDMATIM; - - if ((offset + size) > (UDMATIM + 2)) - panic("PCI write to UDMATIM with invalid size\n"); - } else { - panic("PCI write to unimplemented register: %x\n", offset); - } + } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { - memcpy((void *)&pci_regs[offset], (void *)&data, size); + config_offset = offset - IDE_CTRL_CONFIG_START; + + write_data = htoa(data); + + switch(size) { + case sizeof(uint8_t): + 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); + // Catch the writes to specific PCI registers that have side affects // (like updating the PIO ranges) switch (offset) { @@ -414,36 +398,91 @@ IdeController::read(MemReqPtr &req, uint8_t *data) { Addr offset; bool primary; - bool byte; - bool cmdBlk; RegType_t type; int disk; + + /* union + * +-- --+-- --+-- --+-- --+ + * | 0 | 1 | 2 | 3 | + * +-- --+-- --+-- --+-- --+ + * | byte | .. | .. | .. | + * +-- --+-- --+-- --+-- --+ + * | word0 | word1 | + * +-- --+-- --+ + * | dword | + * +-- --+ + */ + union { + uint8_t byte; + uint16_t word[2]; + uint32_t dword; + }; + + dword = 0; + parseAddr(req->paddr, offset, primary, type); - byte = (req->size == sizeof(uint8_t)) ? true : false; - cmdBlk = (type == COMMAND_BLOCK) ? true : false; if (!io_enabled) return No_Fault; - // sanity check the size (allows byte, word, or dword access) - if (req->size != sizeof(uint8_t) && req->size != sizeof(uint16_t) && - req->size != sizeof(uint32_t)) - panic("IDE controller read of invalid size: %#x\n", req->size); - - if (type != BMI_BLOCK) { - assert(req->size != sizeof(uint32_t)); + switch (type) { + case BMI_BLOCK: + switch (req->size) { + case sizeof(uint8_t): + memcpy(&byte, &bmi_regs[offset], sizeof(uint8_t)); + *data = byte; + break; + case sizeof(uint16_t): + memcpy(&byte, &bmi_regs[offset], sizeof(uint16_t)); + *(uint16_t*)data = htoa(word[0]); + break; + case sizeof(uint32_t): + memcpy(&byte, &bmi_regs[offset], sizeof(uint32_t)); + *(uint32_t*)data = htoa(dword); + break; + default: + panic("IDE read of BMI reg invalid size: %#x\n", req->size); + } + break; + case COMMAND_BLOCK: + case CONTROL_BLOCK: disk = getDisk(primary); - if (disks[disk]) - disks[disk]->read(offset, byte, cmdBlk, data); - } else { - memcpy((void *)data, &bmi_regs[offset], req->size); + + 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); + } + 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; } @@ -462,7 +501,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) byte = (req->size == sizeof(uint8_t)) ? true : false; cmdBlk = (type == COMMAND_BLOCK) ? true : false; - DPRINTF(IdeCtrl, "write from offset: %#x size: %#x data: %#x\n", + DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", offset, req->size, (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size))); @@ -620,7 +659,7 @@ IdeController::serialize(std::ostream &os) // Serialize registers SERIALIZE_ARRAY(bmi_regs, 16); SERIALIZE_ARRAY(dev, 2); - SERIALIZE_ARRAY(pci_regs, 8); + SERIALIZE_ARRAY(pci_config_regs.data, 22); // Serialize internal state SERIALIZE_SCALAR(io_enabled); @@ -649,7 +688,7 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) // Unserialize registers UNSERIALIZE_ARRAY(bmi_regs, 16); UNSERIALIZE_ARRAY(dev, 2); - UNSERIALIZE_ARRAY(pci_regs, 8); + UNSERIALIZE_ARRAY(pci_config_regs.data, 22); // Unserialize internal state UNSERIALIZE_SCALAR(io_enabled); |