diff options
-rw-r--r-- | dev/ide_ctrl.cc | 154 | ||||
-rw-r--r-- | dev/ide_ctrl.hh | 17 | ||||
-rw-r--r-- | dev/ide_disk.cc | 125 | ||||
-rw-r--r-- | dev/ide_disk.hh | 2 | ||||
-rw-r--r-- | dev/pcidev.cc | 12 | ||||
-rw-r--r-- | dev/rtcreg.h | 14 | ||||
-rw-r--r-- | dev/tsunami_io.cc | 62 | ||||
-rw-r--r-- | dev/tsunami_io.hh | 11 | ||||
-rw-r--r-- | dev/uart8250.cc | 4 | ||||
-rw-r--r-- | dev/uart8250.hh | 3 | ||||
-rw-r--r-- | kern/freebsd/freebsd_system.cc | 1 | ||||
-rw-r--r-- | kern/freebsd/freebsd_system.hh | 2 |
12 files changed, 223 insertions, 184 deletions
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc index a2b27d01a..2c86d27c7 100644 --- a/dev/ide_ctrl.cc +++ b/dev/ide_ctrl.cc @@ -75,13 +75,13 @@ IdeController::IdeController(Params *p) bmi_size = BARSize[4]; // zero out all of the registers - memset(bmi_regs, 0, sizeof(bmi_regs)); + memset(bmi_regs.data, 0, sizeof(bmi_regs)); memset(pci_config_regs.data, 0, sizeof(pci_config_regs.data)); // setup initial values pci_config_regs.idetim = htoa((uint32_t)0x80008000); // enable both channels - *(uint8_t *)&bmi_regs[BMIS0] = 0x60; - *(uint8_t *)&bmi_regs[BMIS1] = 0x60; + bmi_regs.bmis0 = DMA1CAP | DMA0CAP; + bmi_regs.bmis1 = DMA1CAP | DMA0CAP; // reset all internal variables io_enabled = false; @@ -218,18 +218,18 @@ IdeController::setDmaComplete(IdeDisk *disk) if (diskNum < 2) { // clear the start/stop bit in the command register - bmi_regs[BMIC0] &= ~SSBM; + bmi_regs.bmic0 &= ~SSBM; // clear the bus master active bit in the status register - bmi_regs[BMIS0] &= ~BMIDEA; + bmi_regs.bmis0 &= ~BMIDEA; // set the interrupt bit - bmi_regs[BMIS0] |= IDEINTS; + bmi_regs.bmis0 |= IDEINTS; } else { // clear the start/stop bit in the command register - bmi_regs[BMIC1] &= ~SSBM; + bmi_regs.bmic1 &= ~SSBM; // clear the bus master active bit in the status register - bmi_regs[BMIS1] &= ~BMIDEA; + bmi_regs.bmis1 &= ~BMIDEA; // set the interrupt bit - bmi_regs[BMIS1] |= IDEINTS; + bmi_regs.bmis1 |= IDEINTS; } } @@ -261,7 +261,8 @@ IdeController::ReadConfig(int offset, int size, uint8_t *data) if (offset < PCI_DEVICE_SPECIFIC) { PciDev::ReadConfig(offset, size, data); - } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { + } else if (offset >= IDE_CTRL_CONFIG_START && + (offset + size) <= IDE_CTRL_CONFIG_END) { config_offset = offset - IDE_CTRL_CONFIG_START; dword = 0; @@ -299,7 +300,8 @@ IdeController::WriteConfig(int offset, int size, uint32_t data) if (offset < PCI_DEVICE_SPECIFIC) { PciDev::WriteConfig(offset, size, data); - } else if (offset >= IDE_CTRL_CONFIG_START && (offset + size) <= IDE_CTRL_CONFIG_END) { + } else if (offset >= IDE_CTRL_CONFIG_START && + (offset + size) <= IDE_CTRL_CONFIG_END) { config_offset = offset - IDE_CTRL_CONFIG_START; @@ -401,7 +403,6 @@ IdeController::read(MemReqPtr &req, uint8_t *data) RegType_t type; int disk; - /* union * +-- --+-- --+-- --+-- --+ * | 0 | 1 | 2 | 3 | @@ -430,15 +431,15 @@ IdeController::read(MemReqPtr &req, uint8_t *data) case BMI_BLOCK: switch (req->size) { case sizeof(uint8_t): - memcpy(&byte, &bmi_regs[offset], sizeof(uint8_t)); + memcpy(&byte, &bmi_regs.data[offset], sizeof(uint8_t)); *data = byte; break; case sizeof(uint16_t): - memcpy(&byte, &bmi_regs[offset], sizeof(uint16_t)); + memcpy(&byte, &bmi_regs.data[offset], sizeof(uint16_t)); *(uint16_t*)data = htoa(word[0]); break; case sizeof(uint32_t): - memcpy(&byte, &bmi_regs[offset], sizeof(uint32_t)); + memcpy(&byte, &bmi_regs.data[offset], sizeof(uint32_t)); *(uint32_t*)data = htoa(dword); break; default: @@ -479,6 +480,8 @@ IdeController::read(MemReqPtr &req, uint8_t *data) panic("IDE read of command reg of invalid size: %#x\n", req->size); } break; + default: + panic("IDE controller read of unknown register block type!\n"); } DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", @@ -492,40 +495,29 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) { Addr offset; bool primary; - bool byte; - bool cmdBlk; RegType_t type; int disk; - parseAddr(req->paddr, offset, primary, type); - byte = (req->size == sizeof(uint8_t)) ? true : false; - cmdBlk = (type == COMMAND_BLOCK) ? true : false; + union { + uint8_t byte; + uint16_t word[2]; + uint32_t dword; + }; - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, req->size, - (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size))); + dword = 0; + + parseAddr(req->paddr, offset, primary, type); uint8_t oldVal, newVal; if (!io_enabled) return No_Fault; - if (type == BMI_BLOCK && !bm_enabled) - return No_Fault; - - if (type != BMI_BLOCK) { - // shadow the dev bit - if (type == COMMAND_BLOCK && offset == IDE_SELECT_OFFSET) { - uint8_t *devBit = (primary ? &dev[0] : &dev[1]); - *devBit = ((*data & IDE_SELECT_DEV_BIT) ? 1 : 0); - } - - assert(req->size != sizeof(uint32_t)); + switch (type) { + case BMI_BLOCK: + if (!bm_enabled) + return No_Fault; - disk = getDisk(primary); - if (disks[disk]) - disks[disk]->write(offset, byte, cmdBlk, data); - } else { switch (offset) { // Bus master IDE command register case BMIC1: @@ -536,8 +528,9 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) // select the current disk based on DEV bit disk = getDisk(primary); - oldVal = bmi_regs[offset]; - newVal = *data; + oldVal = bmi_regs.data[offset]; + byte = *data; + newVal = byte; // if a DMA transfer is in progress, R/W control cannot change if (oldVal & SSBM) { @@ -553,7 +546,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); // clear the BMIDEA bit - bmi_regs[offset + 0x2] &= ~BMIDEA; + bmi_regs.data[offset + 0x2] &= ~BMIDEA; if (disks[disk] == NULL) panic("DMA stop for disk %d which does not exist\n", @@ -566,7 +559,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) DPRINTF(IdeCtrl, "Starting DMA transfer\n"); // set the BMIDEA bit - bmi_regs[offset + 0x2] |= BMIDEA; + bmi_regs.data[offset + 0x2] |= BMIDEA; if (disks[disk] == NULL) panic("DMA start for disk %d which does not exist\n", @@ -574,14 +567,14 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) // inform the disk of the DMA transfer start if (primary) - disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP0]); + disks[disk]->startDma(bmi_regs.bmidtp0); else - disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP1]); + disks[disk]->startDma(bmi_regs.bmidtp1); } } // update the register value - bmi_regs[offset] = newVal; + bmi_regs.data[offset] = newVal; break; // Bus master IDE status register @@ -590,8 +583,9 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) if (req->size != sizeof(uint8_t)) panic("Invalid BMIS write size: %x\n", req->size); - oldVal = bmi_regs[offset]; - newVal = *data; + oldVal = bmi_regs.data[offset]; + byte = *data; + newVal = byte; // the BMIDEA bit is RO newVal |= (oldVal & BMIDEA); @@ -607,7 +601,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) else (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; - bmi_regs[offset] = newVal; + bmi_regs.data[offset] = newVal; break; // Bus master IDE descriptor table pointer register @@ -616,7 +610,8 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) if (req->size != sizeof(uint32_t)) panic("Invalid BMIDTP write size: %x\n", req->size); - *(uint32_t *)&bmi_regs[offset] = *(uint32_t *)data & ~0x3; + dword = htoa(*(uint32_t *)data & ~0x3); + *(uint32_t *)&bmi_regs.data[offset] = dword; break; default: @@ -627,10 +622,53 @@ IdeController::write(MemReqPtr &req, const uint8_t *data) req->size); // do a default copy of data into the registers - memcpy((void *)&bmi_regs[offset], data, req->size); + memcpy((void *)&bmi_regs.data[offset], data, req->size); + } + break; + case COMMAND_BLOCK: + if (offset == IDE_SELECT_OFFSET) { + uint8_t *devBit = (primary ? &dev[0] : &dev[1]); + *devBit = ((*data & IDE_SELECT_DEV_BIT) ? 1 : 0); } + // fall-through ok! + case CONTROL_BLOCK: + disk = getDisk(primary); + + if (disks[disk] == NULL) + break; + + switch (offset) { + case DATA_OFFSET: + switch (req->size) { + case sizeof(uint16_t): + word[0] = htoa(*(uint16_t*)data); + disks[disk]->write(offset, type, (uint8_t*)&word[0]); + break; + + case sizeof(uint32_t): + dword = htoa(*(uint32_t*)data); + disks[disk]->write(offset, type, (uint8_t*)&word[0]); + disks[disk]->write(offset, type, (uint8_t*)&word[1]); + break; + default: + panic("IDE write of data reg invalid size: %#x\n", req->size); + } + break; + default: + if (req->size == sizeof(uint8_t)) { + byte = *data; + disks[disk]->write(offset, type, &byte); + } else + panic("IDE write of command reg of invalid size: %#x\n", req->size); + } + break; + default: + panic("IDE controller write of unknown register block type!\n"); } + DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", + offset, req->size, dword); + return No_Fault; } @@ -657,14 +695,14 @@ IdeController::serialize(std::ostream &os) SERIALIZE_SCALAR(bmi_size); // Serialize registers - SERIALIZE_ARRAY(bmi_regs, 16); - SERIALIZE_ARRAY(dev, 2); - SERIALIZE_ARRAY(pci_config_regs.data, 22); + SERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs)); + SERIALIZE_ARRAY(dev, sizeof(dev)); + SERIALIZE_ARRAY(pci_config_regs.data, sizeof(pci_config_regs)); // Serialize internal state SERIALIZE_SCALAR(io_enabled); SERIALIZE_SCALAR(bm_enabled); - SERIALIZE_ARRAY(cmd_in_progress, 4); + SERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress)); } void @@ -686,14 +724,14 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(bmi_size); // Unserialize registers - UNSERIALIZE_ARRAY(bmi_regs, 16); - UNSERIALIZE_ARRAY(dev, 2); - UNSERIALIZE_ARRAY(pci_config_regs.data, 22); + UNSERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs)); + UNSERIALIZE_ARRAY(dev, sizeof(dev)); + UNSERIALIZE_ARRAY(pci_config_regs.data, sizeof(pci_config_regs)); // Unserialize internal state UNSERIALIZE_SCALAR(io_enabled); UNSERIALIZE_SCALAR(bm_enabled); - UNSERIALIZE_ARRAY(cmd_in_progress, 4); + UNSERIALIZE_ARRAY(cmd_in_progress, sizeof(cmd_in_progress)); if (pioInterface) { pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size)); diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh index 2164f2f4a..51bdd93b1 100644 --- a/dev/ide_ctrl.hh +++ b/dev/ide_ctrl.hh @@ -110,7 +110,22 @@ class IdeController : public PciDev private: /** Registers used for bus master interface */ - uint8_t bmi_regs[16]; + union { + uint8_t data[16]; + + struct { + uint8_t bmic0; + uint8_t padding_0; + uint8_t bmis0; + uint8_t padding_1; + uint32_t bmidtp0; + uint8_t bmic1; + uint8_t padding_2; + uint8_t bmis1; + uint8_t padding_3; + uint32_t bmidtp1; + }; + } bmi_regs; /** Shadows of the device select bit */ uint8_t dev[2]; /** Registers used in device specific PCI configuration */ diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc index 74d2ae6de..39eb2e698 100644 --- a/dev/ide_disk.cc +++ b/dev/ide_disk.cc @@ -218,18 +218,12 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data) 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 + // Data transfers occur two bytes at a time case DATA_OFFSET: - // use memcpy to preserve IDE's little-endianess memcpy(data, &cmdReg.data, sizeof(uint16_t)); + action = ACT_DATA_READ_SHORT; break; - // All other transfers are 8-bit case ERROR_OFFSET: *data = cmdReg.error; break; @@ -250,6 +244,7 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data) break; case STATUS_OFFSET: *data = status; + action = ACT_STAT_READ; break; default: panic("Invalid IDE command register offset: %#x\n", offset); @@ -261,7 +256,6 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data) else panic("Invalid IDE control register offset: %#x\n", offset); break; - default: panic("Unknown register block!\n"); } @@ -271,76 +265,59 @@ IdeDisk::read(const Addr &offset, RegType_t type, uint8_t *data) } void -IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data) +IdeDisk::write(const Addr &offset, RegType_t type, const uint8_t *data) { DevAction_t action = ACT_NONE; - if (cmdBlk) { - - if (!byte && offset != DATA_OFFSET) - panic("Invalid 16-bit write, only allowed on data reg\n"); - - if (!byte) - *((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) { - action = ACT_CMD_WRITE; - } else if (offset == DATA_OFFSET) { - if (byte) - action = ACT_DATA_WRITE_BYTE; - else - action = ACT_DATA_WRITE_SHORT; - } else if (offset == DRIVE_OFFSET) { + switch (type) { + case COMMAND_BLOCK: + switch (offset) { + case DATA_OFFSET: + memcpy(&cmdReg.data, data, sizeof(uint16_t)); + action = ACT_DATA_WRITE_SHORT; + break; + case FEATURES_OFFSET: + 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; action = ACT_SELECT_WRITE; + break; + case COMMAND_OFFSET: + cmdReg.command = *data; + action = ACT_CMD_WRITE; + break; + default: + panic("Invalid IDE command register offset: %#x\n", offset); } - - } else { - if (offset != CONTROL_OFFSET) - panic("Invalid disk control register offset: %#x\n", offset); - - if (!byte) - panic("Invalid 16-bit write to control block\n"); - - if (*data & CONTROL_RST_BIT) { - // 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; + break; + case CONTROL_BLOCK: + if (offset == CONTROL_OFFSET) { + if (*data & CONTROL_RST_BIT) { + // 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; + else + panic("Invalid IDE control register offset: %#x\n", offset); + break; + default: + panic("Unknown register block!\n"); } if (action != ACT_NONE) @@ -793,7 +770,7 @@ IdeDisk::intrPost() // talk to controller to set interrupt if (ctrl) { - ctrl->bmi_regs[BMIS0] |= IDEINTS; + ctrl->bmi_regs.bmis0 |= IDEINTS; ctrl->intrPost(); } } diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh index 9799e2d38..ceec11925 100644 --- a/dev/ide_disk.hh +++ b/dev/ide_disk.hh @@ -271,7 +271,7 @@ class IdeDisk : public SimObject // Device register read/write void read(const Addr &offset, RegType_t type, uint8_t *data); - void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data); + void write(const Addr &offset, RegType_t type, const uint8_t *data); // Start/abort functions void startDma(const uint32_t &prdTableBase); diff --git a/dev/pcidev.cc b/dev/pcidev.cc index 31c44bffa..c74fb035c 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -115,10 +115,6 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) uint32_t barnum; - uint8_t byte_value; - uint16_t half_value; - uint32_t word_value; - DPRINTF(PCIDEV, "write device: %#x function: %#x reg: %#x size: %d data: %#x\n", params()->deviceNum, params()->functionNum, offset, size, @@ -128,7 +124,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) switch (size) { case sizeof(uint8_t): // 1-byte access - byte_value = data; + uint8_t byte_value = data; switch (offset) { case PCI0_INTERRUPT_LINE: case PCI_CACHE_LINE_SIZE: @@ -148,7 +144,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) break; case sizeof(uint16_t): // 2-byte access - half_value = data; + uint16_t half_value = data; switch (offset) { case PCI_COMMAND: case PCI_STATUS: @@ -162,7 +158,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) break; case sizeof(uint32_t): // 4-byte access - word_value = data; + uint32_t word_value = data; switch (offset) { case PCI0_BASE_ADDR0: case PCI0_BASE_ADDR1: @@ -194,7 +190,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) htoa((word_value & ~0x3) | (htoa(config.data[offset]) & 0x3)); - if (word_value != 0x1) { + if (word_value &= ~0x1) { Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO; Addr base_size = BARSize[barnum]; diff --git a/dev/rtcreg.h b/dev/rtcreg.h index 0b33c25b2..032e22ab5 100644 --- a/dev/rtcreg.h +++ b/dev/rtcreg.h @@ -36,8 +36,22 @@ #define RTC_DOM 0x07 #define RTC_MON 0x08 #define RTC_YEAR 0x09 + #define RTC_CNTRL_REGA 0x0A +#define RTCA_1024HZ 0x06 /* 1024Hz periodic interrupt frequency */ +#define RTCA_32768HZ 0x20 /* 22-stage divider, 32.768KHz timebase */ +#define RTCA_UIP 0x80 /* 1 = date and time update in progress */ + #define RTC_CNTRL_REGB 0x0B +#define RTCB_DST 0x01 /* USA Daylight Savings Time enable */ +#define RTCB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */ +#define RTCB_BIN 0x04 /* 0 = BCD, 1 = Binary coded time */ +#define RTCB_SQWE 0x08 /* 1 = output sqare wave at SQW pin */ +#define RTCB_UPDT_IE 0x10 /* 1 = enable update-ended interrupt */ +#define RTCB_ALRM_IE 0x20 /* 1 = enable alarm interrupt */ +#define RTCB_PRDC_IE 0x40 /* 1 = enable periodic clock interrupt */ +#define RTCB_NO_UPDT 0x80 /* stop clock updates */ + #define RTC_CNTRL_REGC 0x0C #define RTC_CNTRL_REGD 0x0D diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc index 82fe40e0a..f9dcbb8e0 100644 --- a/dev/tsunami_io.cc +++ b/dev/tsunami_io.cc @@ -52,14 +52,11 @@ using namespace std; #define UNIX_YEAR_OFFSET 52 -struct tm TsunamiIO::tm = { 0 }; - // Timer Event for Periodic interrupt of RTC 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); } @@ -70,11 +67,6 @@ TsunamiIO::RTCEvent::process() schedule(curTick + interval); //Actually interrupt the processor here tsunami->cchip->postRTC(); - - if (intr_count == 1023) - tm.tm_sec = (tm.tm_sec + 1) % 60; - - intr_count = (intr_count + 1) % 1024; } const char * @@ -98,6 +90,11 @@ TsunamiIO::RTCEvent::unserialize(Checkpoint *cp, const std::string §ion) reschedule(time); } +void +TsunamiIO::RTCEvent::scheduleIntr() +{ + schedule(curTick + interval); +} // Timer Event for PIT Timers TsunamiIO::ClockEvent::ClockEvent() @@ -125,10 +122,8 @@ TsunamiIO::ClockEvent::process() DPRINTF(Tsunami, "Timer Interrupt\n"); if (mode == 0) status = 0x20; // set bit that linux is looking for - else - schedule(curTick + interval); - - current_count--; //decrement count + else if (mode == 2) + schedule(curTick + current_count*interval); } void @@ -301,12 +296,12 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) case TSDEV_RTC_DATA: switch(RTCAddress) { case RTC_CNTRL_REGA: - *(uint8_t*)data = uip << 7 | 0x26; + *(uint8_t*)data = uip << 7 | RTCA_32768HZ | RTCA_1024HZ; uip = !uip; return No_Fault; case RTC_CNTRL_REGB: // DM and 24/12 and UIE - *(uint8_t*)data = 0x46; + *(uint8_t*)data = RTCB_PRDC_IE | RTCB_BIN | RTCB_24HR; return No_Fault; case RTC_CNTRL_REGC: // If we want to support RTC user access in linux @@ -331,7 +326,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) *(uint8_t *)data = tm.tm_hour; return No_Fault; case RTC_DOW: - *(uint8_t *)data = tm.tm_wday; + *(uint8_t *)data = tm.tm_wday + 1; return No_Fault; case RTC_DOM: *(uint8_t *)data = tm.tm_mday; @@ -340,20 +335,11 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data) *(uint8_t *)data = tm.tm_mon + 1; return No_Fault; case RTC_YEAR: - *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET; + *(uint8_t *)data = tm.tm_year; return No_Fault; default: panic("Unknown RTC Address\n"); } - - /* Added for keyboard reads */ - case TSDEV_KBD: - *(uint8_t *)data = 0x00; - return No_Fault; - /* Added for ATA PCI DMA */ - case ATA_PCI_DMA: - *(uint8_t *)data = 0x00; - return No_Fault; default: panic("I/O Read - va%#x size %d\n", req->vaddr, req->size); } @@ -447,10 +433,10 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) switch(*(uint8_t*)data >> 6) { case 0: timer0.LatchCount(); - break; + return No_Fault; case 2: timer2.LatchCount(); - break; + return No_Fault; default: panic("Read Back Command not implemented\n"); } @@ -488,9 +474,10 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) /* two writes before we actually start the Timer so I set a flag in the timerData */ if(timerData & 0x1000) { - timerData &= 0x1000; + timerData &= ~0x1000; timerData += *(uint8_t*)data << 8; timer0.Program(timerData); + timerData = 0; } else { timerData = *(uint8_t*)data; timerData |= 0x1000; @@ -504,12 +491,26 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) case TSDEV_RTC_DATA: switch(RTCAddress) { case RTC_CNTRL_REGA: + if (*data != (RTCA_32768HZ | RTCA_1024HZ)) + panic("Unimplemented RTC register A value write!\n"); return No_Fault; case RTC_CNTRL_REGB: + if ((*data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) + panic("Write to RTC reg B bits that are not implemented!\n"); + + if (*data & RTCB_PRDC_IE) { + if (!rtc.scheduled()) + rtc.scheduleIntr(); + } else { + if (rtc.scheduled()) + rtc.deschedule(); + } return No_Fault; case RTC_CNTRL_REGC: + panic("Write to RTC reg C not implemented!\n"); return No_Fault; case RTC_CNTRL_REGD: + panic("Write to RTC reg D not implemented!\n"); return No_Fault; case RTC_SEC: tm.tm_sec = *(uint8_t *)data; @@ -527,12 +528,11 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data) tm.tm_mday = *(uint8_t *)data; return No_Fault; case RTC_MON: - tm.tm_mon = *(uint8_t *)data - 1; + tm.tm_mon = *(uint8_t *)data; return No_Fault; case RTC_YEAR: - tm.tm_year = *(uint8_t *)data + UNIX_YEAR_OFFSET; + tm.tm_year = *(uint8_t *)data; return No_Fault; - //panic("RTC Write not implmented (rtc.o won't work)\n"); } default: panic("I/O Write - va%#x size %d\n", req->vaddr, req->size); diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh index 4b28635e8..7054b4ff4 100644 --- a/dev/tsunami_io.hh +++ b/dev/tsunami_io.hh @@ -51,7 +51,7 @@ class TsunamiIO : public PioDevice /** The size of mappad from the above address */ static const Addr size = 0xff; - static struct tm tm; + struct tm tm; /** * In Tsunami RTC only has two i/o ports one for data and one for @@ -154,9 +154,6 @@ 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 @@ -165,7 +162,7 @@ class TsunamiIO : public PioDevice RTCEvent(Tsunami* t, Tick i); /** - * Interrupth the processor and reschedule the event. + * Interrupt the processor and reschedule the event. */ virtual void process(); @@ -187,6 +184,8 @@ class TsunamiIO : public PioDevice * @param section The section name of this object */ virtual void unserialize(Checkpoint *cp, const std::string §ion); + + void scheduleIntr(); }; /** uip UpdateInProgess says that the rtc is updating, but we just fake it @@ -243,7 +242,7 @@ class TsunamiIO : public PioDevice * This variable contains a flag as to how many writes have happened, and * the time so far. */ - uint32_t timerData; + uint16_t timerData; public: /** diff --git a/dev/uart8250.cc b/dev/uart8250.cc index ad3232686..013cbfd00 100644 --- a/dev/uart8250.cc +++ b/dev/uart8250.cc @@ -148,9 +148,9 @@ Uart8250::read(MemReqPtr &req, uint8_t *data) DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); status &= ~TX_INT; if (status & RX_INT) - *(uint8_t*)data = 0x4; + *(uint8_t*)data = IIR_RXID; else - *(uint8_t*)data = 0x1; + *(uint8_t*)data = IIR_NOPEND; break; case 0x3: // Line Control Register (LCR) *(uint8_t*)data = LCR; diff --git a/dev/uart8250.hh b/dev/uart8250.hh index 06a798e26..e85ad72c8 100644 --- a/dev/uart8250.hh +++ b/dev/uart8250.hh @@ -38,6 +38,9 @@ #include "dev/io_device.hh" #include "dev/uart.hh" +#define IIR_NOPEND 0x1 +#define IIR_RXID 0x4 + class SimConsole; class Platform; diff --git a/kern/freebsd/freebsd_system.cc b/kern/freebsd/freebsd_system.cc index 2eb80b8e9..3ff5f18ce 100644 --- a/kern/freebsd/freebsd_system.cc +++ b/kern/freebsd/freebsd_system.cc @@ -60,7 +60,6 @@ FreebsdSystem::FreebsdSystem(Params *p) skipCalibrateClocks = new FreebsdSkipCalibrateClocksEvent(&pcEventQueue, "calibrate_clocks"); if (kernelSymtab->findAddress("calibrate_clocks", addr)) skipCalibrateClocks->schedule(addr + sizeof(MachInst) * 2); - } diff --git a/kern/freebsd/freebsd_system.hh b/kern/freebsd/freebsd_system.hh index 6b236e52e..6429b5690 100644 --- a/kern/freebsd/freebsd_system.hh +++ b/kern/freebsd/freebsd_system.hh @@ -34,9 +34,7 @@ class FreebsdSystem : public System { private: - SkipFuncEvent *skipDelayEvent; - FreebsdSkipCalibrateClocksEvent *skipCalibrateClocks; public: |