diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index defeb641b..6636a5ff6 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,6 +251,7 @@ IdeController::cacheAccess(MemReqPtr &req) void IdeController::ReadConfig(int offset, int size, uint8_t *data) { + int config_offset; #if TRACING_ON Addr origOffset = offset; @@ -258,85 +259,66 @@ IdeController::ReadConfig(int offset, int size, uint8_t *data) 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; + } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { - 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; + config_offset = offset - IDE_CTRL_CONFIG_START; - 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; + switch(size) { + case sizeof(uint32_t): + memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint32_t)); + *(uint32_t*)data = htoa(*(uint32_t*)data); + break; - 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; + case sizeof(uint16_t): + memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint16_t)); + *(uint16_t*)data = htoa(*(uint16_t*)data); + break; - if ((offset + size) > (UDMATIM + 2)) - panic("PCI read of UDMATIM with invalid size\n"); - } else { - panic("PCI read of unimplemented register: %x\n", offset); + case sizeof(uint8_t): + memcpy(data, &pci_config_regs.data[config_offset], sizeof(uint8_t)); + break; + + default: + panic("Invalid PCI configuration read size!\n"); } - - memcpy((void *)data, (void *)&pci_regs[offset], size); + } 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))); + *(uint32_t *)data & (0xffffffff >> 8 * (4 - size))); } void IdeController::WriteConfig(int offset, int size, uint32_t data) { + int config_offset; + + if (offset < PCI_DEVICE_SPECIFIC) { + PciDev::WriteConfig(offset, size, data); + } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { + + config_offset = offset - IDE_CTRL_CONFIG_START; + + switch(size) { + case sizeof(uint32_t): + case sizeof(uint16_t): + case sizeof(uint8_t): + memcpy(&pci_config_regs.data[config_offset], &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))); - // 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); - } - - memcpy((void *)&pci_regs[offset], (void *)&data, size); - } // Catch the writes to specific PCI registers that have side affects // (like updating the PIO ranges) @@ -423,17 +405,22 @@ IdeController::read(MemReqPtr &req, uint8_t *data) 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)) + switch (req->size) { + case sizeof(uint8_t): + case sizeof(uint16_t): + case sizeof(uint32_t): + break; + default: panic("IDE controller read of invalid size: %#x\n", req->size); + } if (type != BMI_BLOCK) { disk = getDisk(primary); if (disks[disk]) if (req->size == sizeof(uint32_t) && offset == DATA_OFFSET) { - *((uint16_t*)data) = disks[disk]->read(offset, type); - *((uint16_t*)data + 1) = disks[disk]->read(offset, type); + ((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) { panic("IDE read of data reg invalid size: %#x\n", req->size); @@ -624,7 +611,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); @@ -653,7 +640,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); diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index 4b54c3d57..2164f2f4a 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -64,15 +64,9 @@ #define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET // PCI device specific register byte offsets -#define PCI_IDE_TIMING 0x40 -#define PCI_SLAVE_TIMING 0x44 -#define PCI_UDMA33_CTRL 0x48 -#define PCI_UDMA33_TIMING 0x4a +#define IDE_CTRL_CONFIG_START 0x40 +#define IDE_CTRL_CONFIG_END ((IDE_CTRL_CONFIG_START) + sizeof(pci_config_regs)) -#define IDETIM (0) -#define SIDETIM (4) -#define UDMACTL (5) -#define UDMATIM (6) typedef enum RegType { COMMAND_BLOCK = 0, @@ -119,8 +113,30 @@ class IdeController : public PciDev uint8_t bmi_regs[16]; /** Shadows of the device select bit */ uint8_t dev[2]; - /** Registers used in PCI configuration */ - uint8_t pci_regs[8]; + /** Registers used in device specific PCI configuration */ + union { + uint8_t data[22]; + + struct { + uint32_t idetim; + uint8_t sidetim; + uint8_t reserved_45; + uint8_t reserved_46; + uint8_t reserved_47; + uint8_t udmactl; + uint8_t reserved_49; + uint16_t udmatim; + uint8_t reserved_4c; + uint8_t reserved_4d; + uint8_t reserved_4e; + uint8_t reserved_4f; + uint8_t reserved_50; + uint8_t reserved_51; + uint8_t reserved_52; + uint8_t reserved_53; + uint16_t ideconfig; + }; + } pci_config_regs; // Internal management variables bool io_enabled; diff --git a/dev/pcidev.cc b/dev/pcidev.cc index 93200a8c7..7f4acea1c 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -78,33 +78,35 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data) switch(size) { case sizeof(uint32_t): - memcpy((uint8_t*)data, config.data + offset, 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*)(config.data + offset)); + *(uint32_t*)data); break; case sizeof(uint16_t): - memcpy((uint8_t*)data, config.data + offset, 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*)(config.data + offset)); + *(uint16_t*)data); break; case sizeof(uint8_t): - memcpy((uint8_t*)data, config.data + offset, 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, - (uint16_t)(*(uint8_t*)(config.data + offset))); + *data); break; default: - panic("Invalid Read Size"); + panic("Invalid PCI configuration read size!\n"); } } diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index 963bdc321..6e517d431 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -59,17 +59,18 @@ TsunamiIO::RTCEvent::RTCEvent(Tsunami* t, Tick i) : Event(&mainEventQueue), tsunami(t), interval(i) { DPRINTF(MC146818, "RTC Event Initilizing\n"); + intr_count = 0; schedule(curTick + interval); } void TsunamiIO::RTCEvent::process() { - static int intr_count = 0; DPRINTF(MC146818, "RTC Timer Interrupt\n"); schedule(curTick + interval); //Actually interrupt the processor here tsunami->cchip->postRTC(); + if (intr_count == 1023) tm.tm_sec = (tm.tm_sec + 1) % 60; @@ -113,10 +114,10 @@ TsunamiIO::ClockEvent::ClockEvent() DPRINTF(Tsunami, "Clock Event Initilizing\n"); mode = 0; - current_count.whole = 0; - latched_count.whole = 0; + current_count = 0; + latched_count = 0; latch_on = false; - read_msb = false; + read_byte = READ_LSB; } void @@ -128,7 +129,7 @@ TsunamiIO::ClockEvent::process() else schedule(curTick + interval); - current_count.whole--; //decrement count + current_count--; //decrement count } void @@ -138,7 +139,7 @@ TsunamiIO::ClockEvent::Program(int count) schedule(curTick + count * interval); status = 0; - current_count.whole = count; + current_count = (uint16_t)count; } const char * @@ -162,32 +163,45 @@ TsunamiIO::ClockEvent::Status() void TsunamiIO::ClockEvent::LatchCount() { + // behave like a real latch if(!latch_on) { latch_on = true; - read_msb = false; - latched_count.whole = current_count.whole; + read_byte = READ_LSB; + latched_count = current_count; } } uint8_t TsunamiIO::ClockEvent::Read() { + uint8_t result = 0; + if(latch_on) { - if(!read_msb) { - read_msb = true; - return latched_count.half.lsb; - } else { + switch (read_byte) { + case READ_LSB: + read_byte = READ_MSB; + result = (uint8_t)latched_count; + break; + case READ_MSB: + read_byte = READ_LSB; latch_on = false; - return latched_count.half.msb; + result = latched_count >> 8; + break; } } else { - if(!read_msb) { - read_msb = true; - return current_count.half.lsb; - } else { - return current_count.half.msb; + switch (read_byte) { + case READ_LSB: + read_byte = READ_MSB; + result = (uint8_t)current_count; + break; + case READ_MSB: + read_byte = READ_LSB; + result = current_count >> 8; + break; } } + + return result; } diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh index dca651d4b..4b28635e8 100644 --- a/dev/tsunami_io.hh +++ b/dev/tsunami_io.hh @@ -75,18 +75,14 @@ class TsunamiIO : public PioDevice uint8_t mode; /** The status of the PIT */ uint8_t status; - /** The counts (current and latched) of the PIT */ - union { - uint16_t whole; - struct { - uint8_t msb; - uint8_t lsb; - } half; - } current_count, latched_count; - - /** Thse state of the output latch of the PIT */ + /** The current count of the PIT */ + uint16_t current_count; + /** The latched count of the PIT */ + uint16_t latched_count; + /** The state of the output latch of the PIT */ bool latch_on; - bool read_msb; + /** The next count half (byte) to read */ + enum {READ_LSB, READ_MSB} read_byte; public: /** @@ -158,6 +154,9 @@ class TsunamiIO : public PioDevice Tsunami* tsunami; Tick interval; + /** Count of the number of RTC interrupts that have occured */ + uint32_t intr_count; + public: /** * RTC Event initializes the RTC event by scheduling an event diff --git a/kern/freebsd/freebsd_system.cc b/kern/freebsd/freebsd_system.cc index bce746a83..2eb80b8e9 100644 --- a/kern/freebsd/freebsd_system.cc +++ b/kern/freebsd/freebsd_system.cc @@ -88,8 +88,8 @@ FreebsdSystem::doCalibrateClocks(ExecContext *xc) uint8_t *ppc = physmem->dma_addr(ppc_paddr, sizeof(uint32_t)); uint8_t *timer = physmem->dma_addr(timer_paddr, sizeof(uint32_t)); - *(uint32_t *)ppc = 2000000000; - *(uint32_t *)timer = 1193180; + *(uint32_t *)ppc = htoa((uint32_t)2000000000); + *(uint32_t *)timer = htoa((uint32_t)1193180); }