Changes for getting FreeBSD to run.
authorMiguel Serrano <mserrano@umich.edu>
Mon, 15 Aug 2005 20:59:58 +0000 (16:59 -0400)
committerMiguel Serrano <mserrano@umich.edu>
Mon, 15 Aug 2005 20:59:58 +0000 (16:59 -0400)
SConscript:
    Added more files to compile: dev/pcifake.cc, dev/isa_fake.cc, kern/freebsd/freebsd_system.cc, kern/freebsd/freebsd_events.cc.
arch/alpha/isa_traits.hh:
    Added constant for argument register 2 as it is needed by FreebsdSystem::doCalibrateClocks().
cpu/exec_context.hh:
cpu/o3/alpha_cpu.hh:
    Replaced htoa()s with gtoh() and htog().
cpu/o3/fetch_impl.hh:
cpu/simple/cpu.cc:
    Replaced htoa() with gtoh().
dev/disk_image.cc:
    Replaced htoa()s with letoh()s.
dev/ide_ctrl.cc:
    Got rid of magic numbers.
    Added IdeChannel and IdeRegType type names where necessary.
dev/ide_ctrl.hh:
    Got rid of unnecessary macros.
    Changed RegType_t to IdeRegType.
    Changed bmi_regs to allow accessing registers by name instead of just by array index.
    Added IdeChannel enum type to use in place of bool variables which were used to specify IDE channel.
dev/ide_disk.cc:
    Rewrote IdeDisk::read and IdeDisk::write functions to specify registers by name instead of indexing through an array.
dev/ide_disk.hh:
    Updated command register struct.
dev/ns_gige.cc:
dev/ns_gige.hh:
    Made ReadConfig and WriteConfig begin with a lower-case letter.
    writeConfig() now takes a pointer to data as a parameter instead of a copy of data.
dev/pciconfigall.cc:
    writeConfig() now takes a pointer to data as a parameter instead of a copy of data.
dev/pcidev.cc:
    Cleaned up readConfig() and writeConfig() functions.
dev/pcidev.hh:
    Added macros to make code that works with the BARs (base adress registers) more readable. writeConfig() now takes a pointer to data.
dev/pcireg.h:
    Changed PCIConfig struct to make accessing elements more straight forward. Removed type 1 (for PCI-to-PCI bridges) PCI configuration space struct since it is not used.
dev/rtcreg.h:
    Added macros for bit fields in RTC status registers A & B.
dev/sinic.cc:
    Function name change: WriteConfig --> writeConfig.
    writeConfig() now takes a pointer to data instead of a copy of data.
    The accessing of elements of PCIConfig structure is updated.
dev/sinic.hh:
    Function name change: WriteConfig --> writeConfig.
    writeConfig() now takes a pointer to data instead of a copy of data.
dev/tsunami_io.cc:
    Added implementation of new RTC and PIT classes.
dev/tsunami_io.hh:
    Added classes for RTC and PIT modules.
dev/tsunamireg.h:
    Added macros for DMA ports used by Tsunami-Tru64.
dev/uart8250.cc:
    Got rid of a magic number.
    Transmit (Tx) interrupts should clear upon a read of the Interrupt ID register.
dev/uart8250.hh:
    Added comments and macros dealing with the UART Interrupt ID register.
kern/linux/linux_system.cc:
    Replaced htoa() with htog().
python/m5/objects/Pci.py:
    PciFake is a python class for Pci Devices that do nothing.
python/m5/objects/Tsunami.py:
    TsunamiFake was renamed as IsaFake.
sim/system.cc:
    Replaced htoa()s with htog()s.
dev/isa_fake.cc:
    New BitKeeper file ``dev/isa_fake.cc''
    TsunamiFake was renamed as IsaFake.
dev/isa_fake.hh:
    New BitKeeper file ``dev/isa_fake.hh''
    TsunmaiFake was renamed as IsaFake.
dev/pitreg.h:
    New BitKeeper file ``dev/pitreg.h''
    Useful macros for working with PIT (Periodic Interval Timer) registers.

--HG--
extra : convert_revision : 33f3a8a1034af4f6c71b32dd743e371c8613e780

32 files changed:
SConscript
arch/alpha/isa_traits.hh
cpu/exec_context.hh
cpu/o3/alpha_cpu.hh
cpu/o3/fetch_impl.hh
cpu/simple/cpu.cc
dev/disk_image.cc
dev/ide_ctrl.cc
dev/ide_ctrl.hh
dev/ide_disk.cc
dev/ide_disk.hh
dev/isa_fake.cc [new file with mode: 0755]
dev/isa_fake.hh [new file with mode: 0755]
dev/ns_gige.cc
dev/ns_gige.hh
dev/pciconfigall.cc
dev/pcidev.cc
dev/pcidev.hh
dev/pcireg.h
dev/pitreg.h [new file with mode: 0644]
dev/rtcreg.h
dev/sinic.cc
dev/sinic.hh
dev/tsunami_io.cc
dev/tsunami_io.hh
dev/tsunamireg.h
dev/uart8250.cc
dev/uart8250.hh
kern/linux/linux_system.cc
python/m5/objects/Pci.py
python/m5/objects/Tsunami.py
sim/system.cc

index ddca8b057fee88d25bc1899a0864f93851479221..8a983840d11d63e355da8f0f3a118d8730f06ebc 100644 (file)
@@ -265,13 +265,14 @@ full_system_sources = Split('''
        dev/ns_gige.cc
        dev/pciconfigall.cc
        dev/pcidev.cc
+       dev/pcifake.cc
        dev/pktfifo.cc
         dev/platform.cc
        dev/sinic.cc
        dev/simple_disk.cc
        dev/tsunami.cc
        dev/tsunami_cchip.cc
-       dev/tsunami_fake.cc
+       dev/isa_fake.cc
        dev/tsunami_io.cc
        dev/tsunami_pchip.cc
        dev/uart.cc
@@ -280,6 +281,8 @@ full_system_sources = Split('''
        kern/kernel_binning.cc
        kern/kernel_stats.cc
        kern/system_events.cc
+       kern/freebsd/freebsd_system.cc
+       kern/freebsd/freebsd_events.cc
        kern/linux/linux_events.cc
        kern/linux/linux_syscalls.cc
        kern/linux/linux_system.cc
index 9c7709a6042a1f87f85e406d781a65923f0bbd82..6c0c09b7a432067a8fc8d7f5bae561a24eabf0df 100644 (file)
@@ -287,6 +287,7 @@ const int ReturnAddressReg = TheISA::ReturnAddressReg;
 const int ReturnValueReg = TheISA::ReturnValueReg;
 const int ArgumentReg0 = TheISA::ArgumentReg0;
 const int ArgumentReg1 = TheISA::ArgumentReg1;
+const int ArgumentReg2 = TheISA::ArgumentReg2;
 const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
 const int MaxAddr = (Addr)-1;
 
index e9ff3e1813b809975a6e8d12ddaf55ec1e686796..5e105c44d6bc095bea6724611b99bcb962c86426 100644 (file)
@@ -263,7 +263,7 @@ class ExecContext
 
         Fault error;
         error = mem->read(req, data);
-        data = htoa(data);
+        data = gtoh(data);
         return error;
     }
 
@@ -313,7 +313,7 @@ class ExecContext
         }
 
 #endif
-        return mem->write(req, (T)htoa(data));
+        return mem->write(req, (T)htog(data));
     }
 
     virtual bool misspeculating();
index 3c679c3b2f7ca33f4994a11ccc17bc6a18452062..545165b2b49be6ad12c27bfb3891a308aa8ddc66 100644 (file)
@@ -220,7 +220,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
 
         Fault error;
         error = this->mem->read(req, data);
-        data = htoa(data);
+        data = gtoh(data);
         return error;
     }
 
@@ -277,7 +277,7 @@ class AlphaFullCPU : public FullO3CPU<Impl>
 
 #endif
 
-        return this->mem->write(req, (T)htoa(data));
+        return this->mem->write(req, (T)htog(data));
     }
 
     template <class T>
index 83d7a02e516a867134f765d01cb95dc2aba31555..75b6abb3dfbfdb77dd93c0d6a3a1a6f10868ad2c 100644 (file)
@@ -535,7 +535,7 @@ SimpleFetch<Impl>::fetch()
             assert(offset <= cacheBlkSize - instSize);
 
             // Get the instruction from the array of the cache line.
-            inst = htoa(*reinterpret_cast<MachInst *>
+            inst = gtoh(*reinterpret_cast<MachInst *>
                         (&cacheData[offset]));
 
             // Create a new DynInst from the instruction fetched.
index 1164e35a418d4161a5c3d3bf3af78802887b432a..c5e12990b8ad8552cdb920bf1f165a8e40ce21c7 100644 (file)
@@ -738,7 +738,7 @@ SimpleCPU::tick()
         comInstEventQueue[0]->serviceEvents(numInst);
 
         // decode the instruction
-        inst = htoa(inst);
+        inst = gtoh(inst);
         curStaticInst = StaticInst<TheISA>::decode(inst);
 
         traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst,
index 4ad2e912b42fa70feae47d2c77f83cb89dea99ab..106723c554d50ecacdd0f817d14d5b306fd3967b 100644 (file)
@@ -237,7 +237,7 @@ void
 SafeReadSwap(ifstream &stream, T &data)
 {
     SafeRead(stream, &data, sizeof(data));
-    data = htoa(data);
+    data = letoh(data); //is this the proper byte order conversion?
 }
 
 bool
@@ -319,7 +319,7 @@ template<class T>
 void
 SafeWriteSwap(ofstream &stream, const T &data)
 {
-    T swappeddata = htoa(data);
+    T swappeddata = letoh(data); //is this the proper byte order conversion?
     SafeWrite(stream, &swappeddata, sizeof(data));
 }
 void
index 785f18ae86c289425a9d4217c876644f6afe8279..6ad80e69d0eb00a341f3f2bf63f68816e06dc0c1 100644 (file)
@@ -75,13 +75,15 @@ IdeController::IdeController(Params *p)
     bmi_size = BARSize[4];
 
     // zero out all of the registers
-    memset(bmi_regs, 0, sizeof(bmi_regs));
-    memset(pci_regs, 0, sizeof(pci_regs));
+    memset(bmi_regs.data, 0, sizeof(bmi_regs));
+    memset(config_regs.data, 0, sizeof(config_regs.data));
 
     // setup initial values
-    *(uint32_t *)&pci_regs[IDETIM] = 0x80008000; // enable both channels
-    *(uint8_t *)&bmi_regs[BMIS0] = 0x60;
-    *(uint8_t *)&bmi_regs[BMIS1] = 0x60;
+    // enable both channels
+    config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN);
+    config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN);
+    bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
+    bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
 
     // reset all internal variables
     io_enabled = false;
@@ -127,46 +129,46 @@ IdeController::~IdeController()
 ///
 
 void
-IdeController::parseAddr(const Addr &addr, Addr &offset, bool &primary,
-                         RegType_t &type)
+IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
+                         IdeRegType &reg_type)
 {
     offset = addr;
 
     if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
         offset -= pri_cmd_addr;
-        type = COMMAND_BLOCK;
-        primary = true;
+        reg_type = COMMAND_BLOCK;
+        channel = PRIMARY;
     } else if (addr >= pri_ctrl_addr &&
                addr < (pri_ctrl_addr + pri_ctrl_size)) {
         offset -= pri_ctrl_addr;
-        type = CONTROL_BLOCK;
-        primary = true;
+        reg_type = CONTROL_BLOCK;
+        channel = PRIMARY;
     } else if (addr >= sec_cmd_addr &&
                addr < (sec_cmd_addr + sec_cmd_size)) {
         offset -= sec_cmd_addr;
-        type = COMMAND_BLOCK;
-        primary = false;
+        reg_type = COMMAND_BLOCK;
+        channel = SECONDARY;
     } else if (addr >= sec_ctrl_addr &&
                addr < (sec_ctrl_addr + sec_ctrl_size)) {
         offset -= sec_ctrl_addr;
-        type = CONTROL_BLOCK;
-        primary = false;
+        reg_type = CONTROL_BLOCK;
+        channel = SECONDARY;
     } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
         offset -= bmi_addr;
-        type = BMI_BLOCK;
-        primary = (offset < BMIC1) ? true : false;
+        reg_type = BMI_BLOCK;
+        channel = (offset < BMIC1) ? PRIMARY : SECONDARY;
     } else {
         panic("IDE controller access to invalid address: %#x\n", addr);
     }
 }
 
 int
-IdeController::getDisk(bool primary)
+IdeController::getDisk(IdeChannel channel)
 {
     int disk = 0;
     uint8_t *devBit = &dev[0];
 
-    if (!primary) {
+    if (channel == SECONDARY) {
         disk += 2;
         devBit = &dev[1];
     }
@@ -218,18 +220,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;
     }
 }
 
@@ -249,105 +251,79 @@ IdeController::cacheAccess(MemReqPtr &req)
 ////
 
 void
-IdeController::ReadConfig(int offset, int size, uint8_t *data)
+IdeController::readConfig(int offset, int size, uint8_t *data)
 {
-
-#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);
+        PciDev::readConfig(offset, size, data);
+    } else if (offset >= IDE_CTRL_CONF_START &&
+               (offset + size) <= IDE_CTRL_CONF_END) {
+
+        config_offset = offset - IDE_CTRL_CONF_START;
+
+        switch (size) {
+          case sizeof(uint8_t):
+            *data = config_regs.data[config_offset];
+            break;
+          case sizeof(uint16_t):
+            *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset];
+            break;
+          case sizeof(uint32_t):
+            *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset];
+            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, *(uint32_t*)data);
 
-    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)
+IdeController::writeConfig(int offset, int size, const uint8_t *data)
 {
-    DPRINTF(IdeCtrl, "PCI write offset: %#x size: %#x data: %#x\n",
-            offset, size, data & (0xffffffff >> 8 * (4 - size)));
+    int config_offset;
 
-    // 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);
+        PciDev::writeConfig(offset, size, data);
+    } else if (offset >= IDE_CTRL_CONF_START &&
+               (offset + size) <= IDE_CTRL_CONF_END) {
+
+        config_offset = offset - IDE_CTRL_CONF_START;
+
+        switch(size) {
+          case sizeof(uint8_t):
+            config_regs.data[config_offset] = *data;
+          case sizeof(uint16_t):
+            *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data;
+          case sizeof(uint32_t):
+            *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data;
+            break;
+          default:
+            panic("Invalid PCI configuration write size!\n");
         }
-
-        memcpy((void *)&pci_regs[offset], (void *)&data, size);
+    } 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) {
       case PCI_COMMAND:
-        if (config.data[offset] & PCI_CMD_IOSE)
+        if (letoh(config.command) & PCI_CMD_IOSE)
             io_enabled = true;
         else
             io_enabled = false;
 
-        if (config.data[offset] & PCI_CMD_BME)
+        if (letoh(config.command) & PCI_CMD_BME)
             bm_enabled = true;
         else
             bm_enabled = false;
@@ -413,37 +389,68 @@ Fault
 IdeController::read(MemReqPtr &req, uint8_t *data)
 {
     Addr offset;
-    bool primary;
-    bool byte;
-    bool cmdBlk;
-    RegType_t type;
+    IdeChannel channel;
+    IdeRegType reg_type;
     int disk;
 
-    parseAddr(req->paddr, offset, primary, type);
-    byte = (req->size == sizeof(uint8_t)) ? true : false;
-    cmdBlk = (type == COMMAND_BLOCK) ? true : false;
+    parseAddr(req->paddr, offset, channel, reg_type);
 
     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);
+    switch (reg_type) {
+      case BMI_BLOCK:
+        switch (req->size) {
+          case sizeof(uint8_t):
+            *data = bmi_regs.data[offset];
+            break;
+          case sizeof(uint16_t):
+            *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset];
+            break;
+          case sizeof(uint32_t):
+            *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset];
+            break;
+          default:
+            panic("IDE read of BMI reg invalid size: %#x\n", req->size);
+        }
+        break;
+
+      case COMMAND_BLOCK:
+      case CONTROL_BLOCK:
+        disk = getDisk(channel);
 
-    if (type != BMI_BLOCK) {
-        assert(req->size != sizeof(uint32_t));
+        if (disks[disk] == NULL)
+            break;
 
-        disk = getDisk(primary);
-        if (disks[disk])
-            disks[disk]->read(offset, byte, cmdBlk, data);
-    } else {
-        memcpy((void *)data, &bmi_regs[offset], req->size);
+        switch (offset) {
+          case DATA_OFFSET:
+            switch (req->size) {
+              case sizeof(uint16_t):
+                disks[disk]->read(offset, reg_type, data);
+                break;
+
+              case sizeof(uint32_t):
+                disks[disk]->read(offset, reg_type, data);
+                disks[disk]->read(offset, reg_type, &data[2]);
+                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, reg_type, data);
+            } else
+                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",
-            offset, req->size,
-            (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size)));
+            offset, req->size, *(uint32_t*)data);
 
     return No_Fault;
 }
@@ -452,41 +459,21 @@ Fault
 IdeController::write(MemReqPtr &req, const uint8_t *data)
 {
     Addr offset;
-    bool primary;
-    bool byte;
-    bool cmdBlk;
-    RegType_t type;
+    IdeChannel channel;
+    IdeRegType reg_type;
     int disk;
-
-    parseAddr(req->paddr, offset, primary, type);
-    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",
-            offset, req->size,
-            (*(uint32_t *)data) & (0xffffffff >> 8 * (4 - req->size)));
-
     uint8_t oldVal, newVal;
 
-    if (!io_enabled)
-        return No_Fault;
+    parseAddr(req->paddr, offset, channel, reg_type);
 
-    if (type == BMI_BLOCK && !bm_enabled)
+    if (!io_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 (reg_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:
@@ -495,10 +482,10 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
                 panic("Invalid BMIC write size: %x\n", req->size);
 
             // select the current disk based on DEV bit
-            disk = getDisk(primary);
+            disk = getDisk(channel);
 
-            oldVal = bmi_regs[offset];
-            newVal = *data;
+            oldVal = letoh(bmi_regs.chan[channel].bmic);
+            newVal = letoh(*data);
 
             // if a DMA transfer is in progress, R/W control cannot change
             if (oldVal & SSBM) {
@@ -514,7 +501,8 @@ 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.chan[channel].bmis = letoh(
+                        letoh(bmi_regs.chan[channel].bmis) & ~BMIDEA);
 
                     if (disks[disk] == NULL)
                         panic("DMA stop for disk %d which does not exist\n",
@@ -527,22 +515,20 @@ 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.chan[channel].bmis = letoh(
+                        letoh(bmi_regs.chan[channel].bmis) | BMIDEA);
 
                     if (disks[disk] == NULL)
                         panic("DMA start for disk %d which does not exist\n",
                               disk);
 
                     // inform the disk of the DMA transfer start
-                    if (primary)
-                        disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP0]);
-                    else
-                        disks[disk]->startDma(*(uint32_t *)&bmi_regs[BMIDTP1]);
+                    disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp));
                 }
             }
 
             // update the register value
-            bmi_regs[offset] = newVal;
+            bmi_regs.chan[channel].bmic = letoh(newVal);
             break;
 
             // Bus master IDE status register
@@ -551,8 +537,8 @@ 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 = letoh(bmi_regs.chan[channel].bmis);
+            newVal = letoh(*data);
 
             // the BMIDEA bit is RO
             newVal |= (oldVal & BMIDEA);
@@ -568,7 +554,7 @@ IdeController::write(MemReqPtr &req, const uint8_t *data)
             else
                 (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
 
-            bmi_regs[offset] = newVal;
+            bmi_regs.chan[channel].bmis = letoh(newVal);
             break;
 
             // Bus master IDE descriptor table pointer register
@@ -577,7 +563,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;
+            bmi_regs.chan[channel].bmidtp = letoh(
+                letoh(*(uint32_t*)data) & ~0x3);
             break;
 
           default:
@@ -588,10 +575,50 @@ 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(&bmi_regs.data[offset], data, req->size);
+        }
+        break;
+      case COMMAND_BLOCK:
+        if (offset == IDE_SELECT_OFFSET) {
+            uint8_t *devBit = &dev[channel];
+            *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0;
         }
+        // fall-through ok!
+      case CONTROL_BLOCK:
+        disk = getDisk(channel);
+
+        if (disks[disk] == NULL)
+            break;
+
+        switch (offset) {
+          case DATA_OFFSET:
+            switch (req->size) {
+              case sizeof(uint16_t):
+                disks[disk]->write(offset, reg_type, data);
+                break;
+
+              case sizeof(uint32_t):
+                disks[disk]->write(offset, reg_type, data);
+                disks[disk]->write(offset, reg_type, &data[2]);
+                break;
+              default:
+                panic("IDE write of data reg invalid size: %#x\n", req->size);
+            }
+            break;
+          default:
+            if (req->size == sizeof(uint8_t)) {
+                disks[disk]->write(offset, reg_type, data);
+            } 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, *(uint32_t*)data);
+
     return No_Fault;
 }
 
@@ -618,14 +645,14 @@ IdeController::serialize(std::ostream &os)
     SERIALIZE_SCALAR(bmi_size);
 
     // Serialize registers
-    SERIALIZE_ARRAY(bmi_regs, 16);
-    SERIALIZE_ARRAY(dev, 2);
-    SERIALIZE_ARRAY(pci_regs, 8);
+    SERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs));
+    SERIALIZE_ARRAY(dev, sizeof(dev));
+    SERIALIZE_ARRAY(config_regs.data, sizeof(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
@@ -647,14 +674,14 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(bmi_size);
 
     // Unserialize registers
-    UNSERIALIZE_ARRAY(bmi_regs, 16);
-    UNSERIALIZE_ARRAY(dev, 2);
-    UNSERIALIZE_ARRAY(pci_regs, 8);
+    UNSERIALIZE_ARRAY(bmi_regs.data, sizeof(bmi_regs));
+    UNSERIALIZE_ARRAY(dev, sizeof(dev));
+    UNSERIALIZE_ARRAY(config_regs.data, sizeof(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));
index 4b54c3d57913309564c847f8d015b7288ad202fc..d50dbbeb1583fb07536f4a6fd5c121ac397b3add 100644 (file)
 #define IDE_FEATURE_OFFSET      IDE_ERROR_OFFSET
 #define IDE_COMMAND_OFFSET      IDE_STATUS_OFFSET
 
+// IDE Timing Register bit fields
+#define IDETIM_DECODE_EN 0x8000
+
 // 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 IDETIM  (0)
-#define SIDETIM (4)
-#define UDMACTL (5)
-#define UDMATIM (6)
-
-typedef enum RegType {
-    COMMAND_BLOCK = 0,
+#define IDE_CTRL_CONF_START 0x40
+#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs))
+
+
+enum IdeRegType {
+    COMMAND_BLOCK,
     CONTROL_BLOCK,
     BMI_BLOCK
-} RegType_t;
+};
 
 class BaseInterface;
 class Bus;
@@ -97,6 +94,11 @@ class IdeController : public PciDev
 {
     friend class IdeDisk;
 
+    enum IdeChannel {
+        PRIMARY = 0,
+        SECONDARY = 1
+    };
+
   private:
     /** Primary command block registers */
     Addr pri_cmd_addr;
@@ -116,11 +118,49 @@ 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 reserved_0;
+            uint8_t bmis0;
+            uint8_t reserved_1;
+            uint32_t bmidtp0;
+            uint8_t bmic1;
+            uint8_t reserved_2;
+            uint8_t bmis1;
+            uint8_t reserved_3;
+            uint32_t bmidtp1;
+        };
+
+        struct {
+            uint8_t bmic;
+            uint8_t reserved_4;
+            uint8_t bmis;
+            uint8_t reserved_5;
+            uint32_t bmidtp;
+        } chan[2];
+
+    } bmi_regs;
     /** 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 {
+            uint16_t idetim0;
+            uint16_t idetim1;
+            uint8_t sidetim;
+            uint8_t reserved_0[3];
+            uint8_t udmactl;
+            uint8_t reserved_1;
+            uint16_t udmatim;
+            uint8_t reserved_2[8];
+            uint16_t ideconfig;
+        };
+    } config_regs;
 
     // Internal management variables
     bool io_enabled;
@@ -133,11 +173,11 @@ class IdeController : public PciDev
 
   private:
     /** Parse the access address to pass on to device */
-    void parseAddr(const Addr &addr, Addr &offset, bool &primary,
-                   RegType_t &type);
+    void parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
+                   IdeRegType &reg_type);
 
     /** Select the disk based on the channel and device bit */
-    int getDisk(bool primary);
+    int getDisk(IdeChannel channel);
 
     /** Select the disk based on a pointer */
     int getDisk(IdeDisk *diskPtr);
@@ -161,8 +201,8 @@ class IdeController : public PciDev
     IdeController(Params *p);
     ~IdeController();
 
-    virtual void WriteConfig(int offset, int size, uint32_t data);
-    virtual void ReadConfig(int offset, int size, uint8_t *data);
+    virtual void writeConfig(int offset, int size, const uint8_t *data);
+    virtual void readConfig(int offset, int size, uint8_t *data);
 
     void setDmaComplete(IdeDisk *disk);
 
index 23d04bb5ecfe9459ae11bdfc98a23c556dcb489b..bd9aac8ea3cdcbd015512cd94c5f2f1607803a14 100644 (file)
@@ -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,10 @@ IdeDisk::reset(int id)
 
     // set the device ready bit
     status = STATUS_DRDY_BIT;
+
+    /* The error register must be set to 0x1 on start-up to
+       indicate that no diagnostic error was detected */
+    cmdReg.error = 0x1;
 }
 
 ////
@@ -207,41 +214,52 @@ 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, IdeRegType reg_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 (reg_type) {
+      case COMMAND_BLOCK:
+        switch (offset) {
+          // Data transfers occur two bytes at a time
+          case DATA_OFFSET:
+            *(uint16_t*)data = cmdReg.data;
+            action = ACT_DATA_READ_SHORT;
+            break;
+          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;
             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;
+            break;
+          default:
+            panic("Invalid IDE command register offset: %#x\n", offset);
         }
-
-    } 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;
+        break;
+      case CONTROL_BLOCK:
+        if (offset == ALTSTAT_OFFSET)
+            *data = status;
+        else
+            panic("Invalid IDE control register offset: %#x\n", offset);
+        break;
+      default:
+        panic("Unknown register block!\n");
     }
 
     if (action != ACT_NONE)
@@ -249,50 +267,59 @@ IdeDisk::read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data)
 }
 
 void
-IdeDisk::write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data)
+IdeDisk::write(const Addr &offset, IdeRegType reg_type, 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;
-
-        // 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 == SELECT_OFFSET) {
+    switch (reg_type) {
+      case COMMAND_BLOCK:
+        switch (offset) {
+          case DATA_OFFSET:
+            cmdReg.data = *(uint16_t*)data;
+            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)
@@ -744,8 +771,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 +893,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 +922,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 +995,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 +1119,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 +1171,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);
index 506f0c7cbf1d301e163bb72a5172dbcc86932fbd..a656ca464ef8c14ae52a5480fa0ecc9800ffbf60 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "dev/disk_image.hh"
 #include "dev/ide_atareg.h"
+#include "dev/ide_ctrl.hh"
 #include "dev/ide_wdcreg.h"
 #include "dev/io_device.hh"
 #include "sim/eventq.hh"
@@ -83,6 +84,7 @@ class PrdTableEntry {
 #define LCYL_OFFSET     (4)
 #define HCYL_OFFSET     (5)
 #define SELECT_OFFSET   (6)
+#define DRIVE_OFFSET    (6)
 #define STATUS_OFFSET   (7)
 #define COMMAND_OFFSET  (7)
 
@@ -103,12 +105,8 @@ class PrdTableEntry {
 #define DEV1 (1)
 
 typedef struct CommandReg {
-    uint8_t data0;
-    union {
-        uint8_t data1;
-        uint8_t error;
-        uint8_t features;
-    };
+    uint16_t data;
+    uint8_t error;
     uint8_t sec_count;
     uint8_t sec_num;
     uint8_t cyl_low;
@@ -272,8 +270,8 @@ class IdeDisk : public SimObject
     }
 
     // Device register read/write
-    void read(const Addr &offset, bool byte, bool cmdBlk, uint8_t *data);
-    void write(const Addr &offset, bool byte, bool cmdBlk, const uint8_t *data);
+    void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
+    void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);
 
     // Start/abort functions
     void startDma(const uint32_t &prdTableBase);
diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc
new file mode 100755 (executable)
index 0000000..af8005f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Isa Fake Device implementation
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "dev/isa_fake.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
+#include "mem/functional/memory_control.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+IsaFake::IsaFake(const string &name, Addr a, MemoryController *mmu,
+                         HierParams *hier, Bus *bus, Addr size)
+    : PioDevice(name, NULL), addr(a)
+{
+    mmu->add_child(this, RangeSize(addr, size));
+
+    if (bus) {
+        pioInterface = newPioInterface(name, hier, bus, this,
+                                      &IsaFake::cacheAccess);
+        pioInterface->addAddrRange(RangeSize(addr, size));
+    }
+}
+
+Fault
+IsaFake::read(MemReqPtr &req, uint8_t *data)
+{
+    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
+            req->vaddr, req->size);
+
+#if TRACING_ON
+    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+#endif
+
+    switch (req->size) {
+
+      case sizeof(uint64_t):
+         *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL;
+         return No_Fault;
+      case sizeof(uint32_t):
+         *(uint32_t*)data = 0xFFFFFFFF;
+         return No_Fault;
+      case sizeof(uint16_t):
+         *(uint16_t*)data = 0xFFFF;
+         return No_Fault;
+      case sizeof(uint8_t):
+         *(uint8_t*)data = 0xFF;
+         return No_Fault;
+
+      default:
+        panic("invalid access size(?) for PCI configspace!\n");
+    }
+    DPRINTFN("Isa FakeSMC  ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
+
+    return No_Fault;
+}
+
+Fault
+IsaFake::write(MemReqPtr &req, const uint8_t *data)
+{
+    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
+            req->vaddr, req->size);
+
+    //:Addr daddr = (req->paddr & addr_mask) >> 6;
+
+    return No_Fault;
+}
+
+Tick
+IsaFake::cacheAccess(MemReqPtr &req)
+{
+    return curTick;
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
+
+    SimObjectParam<MemoryController *> mmu;
+    Param<Addr> addr;
+    SimObjectParam<Bus*> io_bus;
+    Param<Tick> pio_latency;
+    SimObjectParam<HierParams *> hier;
+    Param<Addr> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake)
+
+    INIT_PARAM(mmu, "Memory Controller"),
+    INIT_PARAM(addr, "Device Address"),
+    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
+    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
+    INIT_PARAM_DFLT(size, "Size of address range", 0x8)
+
+END_INIT_SIM_OBJECT_PARAMS(IsaFake)
+
+CREATE_SIM_OBJECT(IsaFake)
+{
+    return new IsaFake(getInstanceName(), addr, mmu, hier, io_bus, size);
+}
+
+REGISTER_SIM_OBJECT("IsaFake", IsaFake)
diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh
new file mode 100755 (executable)
index 0000000..d3d37b0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Declaration of a fake device.
+ */
+
+#ifndef __ISA_FAKE_HH__
+#define __ISA_FAKE_HH__
+
+#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+/**
+ * IsaFake is a device that returns -1 on all reads and
+ * accepts all writes. It is meant to be placed at an address range
+ * so that an mcheck doesn't occur when an os probes a piece of hw
+ * that doesn't exist (e.g. UARTs1-3).
+ */
+class IsaFake : public PioDevice
+{
+  private:
+    /** The address in memory that we respond to */
+    Addr addr;
+
+  public:
+    /**
+      * The constructor for Tsunmami Fake just registers itself with the MMU.
+      * @param name name of this device.
+      * @param a address to respond to.
+      * @param mmu the mmu we register with.
+      * @param size number of addresses to respond to
+      */
+    IsaFake(const std::string &name, Addr a, MemoryController *mmu,
+                HierParams *hier, Bus *bus, Addr size = 0x8);
+
+    /**
+     * This read always returns -1.
+     * @param req The memory request.
+     * @param data Where to put the data.
+     */
+    virtual Fault read(MemReqPtr &req, uint8_t *data);
+
+    /**
+     * All writes are simply ignored.
+     * @param req The memory request.
+     * @param data the data to not write.
+     */
+    virtual Fault write(MemReqPtr &req, const uint8_t *data);
+
+    /**
+     * Return how long this access will take.
+     * @param req the memory request to calcuate
+     * @return Tick when the request is done
+     */
+    Tick cacheAccess(MemReqPtr &req);
+};
+
+#endif // __ISA_FAKE_HH__
index 4e7deba90c6877930240272ae4175d0a9d277824..03942cb620b591a5b7b0c89761406352dfe21121 100644 (file)
@@ -491,10 +491,10 @@ NSGigE::regStats()
  * This is to read the PCI general configuration registers
  */
 void
-NSGigE::ReadConfig(int offset, int size, uint8_t *data)
+NSGigE::readConfig(int offset, int size, uint8_t *data)
 {
     if (offset < PCI_DEVICE_SPECIFIC)
-        PciDev::ReadConfig(offset, size, data);
+        PciDev::readConfig(offset, size, data);
     else
         panic("Device specific PCI config space not implemented!\n");
 }
@@ -503,10 +503,10 @@ NSGigE::ReadConfig(int offset, int size, uint8_t *data)
  * This is to write to the PCI general configuration registers
  */
 void
-NSGigE::WriteConfig(int offset, int size, uint32_t data)
+NSGigE::writeConfig(int offset, int size, const uint8_t* data)
 {
     if (offset < PCI_DEVICE_SPECIFIC)
-        PciDev::WriteConfig(offset, size, data);
+        PciDev::writeConfig(offset, size, data);
     else
         panic("Device specific PCI config space not implemented!\n");
 
@@ -577,7 +577,7 @@ NSGigE::read(MemReqPtr &req, uint8_t *data)
     if (daddr > LAST && daddr <=  RESERVED) {
         panic("Accessing reserved register");
     } else if (daddr > RESERVED && daddr <= 0x3FC) {
-        ReadConfig(daddr & 0xff, req->size, data);
+        readConfig(daddr & 0xff, req->size, data);
         return No_Fault;
     } else if (daddr >= MIB_START && daddr <= MIB_END) {
         // don't implement all the MIB's.  hopefully the kernel
@@ -783,7 +783,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
     if (daddr > LAST && daddr <=  RESERVED) {
         panic("Accessing reserved register");
     } else if (daddr > RESERVED && daddr <= 0x3FC) {
-        WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data);
+        writeConfig(daddr & 0xff, req->size, data);
         return No_Fault;
     } else if (daddr > 0x3FC)
         panic("Something is messed up!\n");
@@ -1360,7 +1360,7 @@ void
 NSGigE::regsReset()
 {
     memset(&regs, 0, sizeof(regs));
-    regs.config = CFGR_LNKSTS;
+    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
     regs.mear = 0x22;
     regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
                         // fill threshold to 32 bytes
index 143460b6424d519a86ccdfddfd9377d5d0499039..805d4c8cbec216c7ef8ad7bde8ef12f61a3c852b 100644 (file)
@@ -99,7 +99,7 @@ class Bus;
 class PciConfigAll;
 
 /**
- * NS DP82830 Ethernet device model
+ * NS DP83820 Ethernet device model
  */
 class NSGigE : public PciDev
 {
@@ -353,8 +353,8 @@ class NSGigE : public PciDev
     ~NSGigE();
     const Params *params() const { return (const Params *)_params; }
 
-    virtual void WriteConfig(int offset, int size, uint32_t data);
-    virtual void ReadConfig(int offset, int size, uint8_t *data);
+    virtual void writeConfig(int offset, int size, const uint8_t *data);
+    virtual void readConfig(int offset, int size, uint8_t *data);
 
     virtual Fault read(MemReqPtr &req, uint8_t *data);
     virtual Fault write(MemReqPtr &req, const uint8_t *data);
index 7d86c3e1b88b8c52f9f914901d60dde92ae7996b..6a5b2e56f7d600544626e332357f5265a7326774 100644 (file)
@@ -65,7 +65,7 @@ PciConfigAll::PciConfigAll(const string &name,
     // Make all the pointers to devices null
     for(int x=0; x < MAX_PCI_DEV; x++)
         for(int y=0; y < MAX_PCI_FUNC; y++)
-          devices[x][y] = NULL;
+            devices[x][y] = NULL;
 }
 
 // If two interrupts share the same line largely bad things will happen.
@@ -130,7 +130,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
             case sizeof(uint32_t):
             case sizeof(uint16_t):
             case sizeof(uint8_t):
-                devices[device][func]->ReadConfig(reg, req->size, data);
+                devices[device][func]->readConfig(reg, req->size, data);
                 return No_Fault;
             default:
                 panic("invalid access size(?) for PCI configspace!\n");
@@ -152,34 +152,17 @@ PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
     int func = (daddr >> 8) & 0x7;
     int reg = daddr & 0xFF;
 
-    union {
-        uint8_t byte_value;
-        uint16_t half_value;
-        uint32_t word_value;
-    };
-
     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;
-                break;
-            case sizeof(uint16_t):
-                half_value = *(uint16_t*)data;
-                break;
-            case sizeof(uint32_t):
-                word_value = *(uint32_t*)data;
-                break;
-            default:
-                panic("invalid access size(?) for PCI configspace!\n");
-            }
-    }
+    else if (req->size != sizeof(uint8_t) &&
+             req->size != sizeof(uint16_t) &&
+             req->size != sizeof(uint32_t))
+        panic("invalid access size(?) for PCI configspace!\n");
 
     DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
-            req->vaddr, req->size, word_value);
+            req->vaddr, req->size, *(uint32_t*)data);
 
-    devices[device][func]->WriteConfig(reg, req->size, word_value);
+    devices[device][func]->writeConfig(reg, req->size, data);
 
     return No_Fault;
 }
index f2bce33cac4b90e9bc34835bc7ab07cc7e5d47e5..04a38151e1f5257af93c234c0f06ed58a9b391ca 100644 (file)
@@ -71,74 +71,62 @@ PciDev::PciDev(Params *p)
 }
 
 void
-PciDev::ReadConfig(int offset, int size, uint8_t *data)
+PciDev::readConfig(int offset, int size, uint8_t *data)
 {
     if (offset >= PCI_DEVICE_SPECIFIC)
         panic("Device specific PCI config space not implemented!\n");
 
     switch(size) {
-      case sizeof(uint32_t):
-        memcpy((uint8_t*)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));
+      case sizeof(uint8_t):
+        *data = config.data[offset];
         break;
-
       case sizeof(uint16_t):
-        memcpy((uint8_t*)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 = *(uint16_t*)&config.data[offset];
         break;
-
-      case sizeof(uint8_t):
-        memcpy((uint8_t*)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)));
+      case sizeof(uint32_t):
+        *(uint32_t*)data = *(uint32_t*)&config.data[offset];
         break;
-
       default:
-        panic("Invalid Read Size");
+        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,
+            *(uint32_t*)data);
 }
 
 void
-PciDev::WriteConfig(int offset, int size, uint32_t data)
+PciDev::writeConfig(int offset, int size, const uint8_t *data)
 {
     if (offset >= PCI_DEVICE_SPECIFIC)
         panic("Device specific PCI config space not implemented!\n");
 
-    uint32_t barnum;
-
-    union {
-        uint8_t byte_value;
-        uint16_t half_value;
-        uint32_t word_value;
-    };
-    word_value = data;
+    uint8_t &data8 = *(uint8_t*)data;
+    uint16_t &data16 = *(uint16_t*)data;
+    uint32_t &data32 = *(uint32_t*)data;
 
     DPRINTF(PCIDEV,
             "write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
-            params()->deviceNum, params()->functionNum, offset, size,
-            word_value);
-
-    barnum = (offset - PCI0_BASE_ADDR0) >> 2;
+            params()->deviceNum, params()->functionNum, offset, size, data32);
 
     switch (size) {
       case sizeof(uint8_t): // 1-byte access
         switch (offset) {
           case PCI0_INTERRUPT_LINE:
+            config.interruptLine = data8;
           case PCI_CACHE_LINE_SIZE:
+            config.cacheLineSize = data8;
           case PCI_LATENCY_TIMER:
-            *(uint8_t *)&config.data[offset] = htoa(byte_value);
+            config.latencyTimer = data8;
+            break;
+          /* Do nothing for these read-only registers */
+          case PCI0_INTERRUPT_PIN:
+          case PCI0_MINIMUM_GRANT:
+          case PCI0_MAXIMUM_LATENCY:
+          case PCI_CLASS_CODE:
+          case PCI_REVISION_ID:
             break;
-
           default:
             panic("writing to a read only register");
         }
@@ -147,19 +135,17 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
       case sizeof(uint16_t): // 2-byte access
         switch (offset) {
           case PCI_COMMAND:
+            config.command = data16;
           case PCI_STATUS:
+            config.status = data16;
           case PCI_CACHE_LINE_SIZE:
-            *(uint16_t *)&config.data[offset] = htoa(half_value);
+            config.cacheLineSize = data16;
             break;
-
           default:
             panic("writing to a read only register");
         }
         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:
@@ -168,110 +154,91 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
           case PCI0_BASE_ADDR3:
           case PCI0_BASE_ADDR4:
           case PCI0_BASE_ADDR5:
+
+            uint32_t barnum, bar_mask;
+            Addr base_addr, base_size, space_base;
+
+            barnum = BAR_NUMBER(offset);
+
+            if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
+                bar_mask = BAR_IO_MASK;
+                space_base = TSUNAMI_PCI0_IO;
+            } else {
+                bar_mask = BAR_MEM_MASK;
+                space_base = TSUNAMI_PCI0_MEMORY;
+            }
+
             // Writing 0xffffffff to a BAR tells the card to set the
-            // value of the bar
-            // to size of memory it needs
-            if (word_value == 0xffffffff) {
+            // value of the bar to size of memory it needs
+            if (letoh(data32) == 0xffffffff) {
                 // 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) |
-                        (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) |
-                        (htoa(config.data[offset]) & 0xF));
-                }
+
+                config.baseAddr[barnum] = letoh(
+                        (~(BARSize[barnum] - 1) & ~bar_mask) |
+                        (letoh(config.baseAddr[barnum]) & bar_mask));
             } else {
                 MemoryController *mmu = params()->mmu;
 
-                // This is I/O Space, bottom two bits are read only
-                if(htoa(config.data[offset]) & 0x1) {
-                    *(uint32_t *)&config.data[offset] =
-                        htoa((word_value & ~0x3) |
-                        (htoa(config.data[offset]) & 0x3));
-
-                    if (word_value & ~0x1) {
-                        Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO;
-                        Addr base_size = BARSize[barnum];
-
-                        // It's never been set
-                        if (BARAddrs[barnum] == 0)
-                            mmu->add_child((FunctionalMemory *)this,
-                                           RangeSize(base_addr, base_size));
-                        else
-                            mmu->update_child((FunctionalMemory *)this,
-                                              RangeSize(BARAddrs[barnum],
-                                                        base_size),
-                                              RangeSize(base_addr, base_size));
-
-                        BARAddrs[barnum] = base_addr;
-                    }
-
-                } else {
-                    // This is memory space, bottom four bits are read only
-                    *(uint32_t *)&config.data[offset] =
-                        htoa((word_value & ~0xF) |
-                        (htoa(config.data[offset]) & 0xF));
-
-                    if (word_value & ~0x3) {
-                        Addr base_addr = (word_value & ~0x3) +
-                            TSUNAMI_PCI0_MEMORY;
-
-                        Addr base_size = BARSize[barnum];
-
-                        // It's never been set
-                        if (BARAddrs[barnum] == 0)
-                            mmu->add_child((FunctionalMemory *)this,
-                                           RangeSize(base_addr, base_size));
-                        else
-                            mmu->update_child((FunctionalMemory *)this,
-                                              RangeSize(BARAddrs[barnum],
-                                                        base_size),
-                                              RangeSize(base_addr, base_size));
-
-                        BARAddrs[barnum] = base_addr;
-                    }
-                 }
+                config.baseAddr[barnum] = letoh(
+                    (letoh(data32) & ~bar_mask) |
+                    (letoh(config.baseAddr[barnum]) & bar_mask));
+
+                if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
+                    base_addr = (letoh(data32) & ~bar_mask) + space_base;
+                    base_size = BARSize[barnum];
+
+                    // It's never been set
+                    if (BARAddrs[barnum] == 0)
+                        mmu->add_child((FunctionalMemory *)this,
+                                       RangeSize(base_addr, base_size));
+                    else
+                        mmu->update_child((FunctionalMemory *)this,
+                                          RangeSize(BARAddrs[barnum], base_size),
+                                          RangeSize(base_addr, base_size));
+
+                    BARAddrs[barnum] = base_addr;
+                }
             }
             break;
 
           case PCI0_ROM_BASE_ADDR:
-            if (word_value == 0xfffffffe)
-                *(uint32_t *)&config.data[offset] = 0xffffffff;
+            if (letoh(data32) == 0xfffffffe)
+                config.expansionROM = letoh(0xffffffff);
             else
-                *(uint32_t *)&config.data[offset] = htoa(word_value);
+                config.expansionROM = data32;
             break;
 
           case PCI_COMMAND:
             // This could also clear some of the error bits in the Status
             // register. However they should never get set, so lets ignore
             // it for now
-            *(uint16_t *)&config.data[offset] = htoa(half_value);
+            config.command = data16;
             break;
 
           default:
             DPRINTF(PCIDEV, "Writing to a read only register");
         }
         break;
+
+      default:
+        panic("invalid access size");
     }
 }
 
 void
 PciDev::serialize(ostream &os)
 {
-    SERIALIZE_ARRAY(BARSize, 6);
-    SERIALIZE_ARRAY(BARAddrs, 6);
-    SERIALIZE_ARRAY(config.data, 64);
+    SERIALIZE_ARRAY(BARSize, sizeof(BARSize));
+    SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs));
+    SERIALIZE_ARRAY(config.data, sizeof(config.data));
 }
 
 void
 PciDev::unserialize(Checkpoint *cp, const std::string &section)
 {
-    UNSERIALIZE_ARRAY(BARSize, 6);
-    UNSERIALIZE_ARRAY(BARAddrs, 6);
-    UNSERIALIZE_ARRAY(config.data, 64);
+    UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize));
+    UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs));
+    UNSERIALIZE_ARRAY(config.data, sizeof(config.data));
 
     // Add the MMU mappings for the BARs
     for (int i=0; i < 6; i++) {
@@ -360,33 +327,33 @@ CREATE_SIM_OBJECT(PciConfigData)
 {
     PciConfigData *data = new PciConfigData(getInstanceName());
 
-    data->config.hdr.vendor = htoa(VendorID);
-    data->config.hdr.device = htoa(DeviceID);
-    data->config.hdr.command = htoa(Command);
-    data->config.hdr.status = htoa(Status);
-    data->config.hdr.revision = htoa(Revision);
-    data->config.hdr.progIF = htoa(ProgIF);
-    data->config.hdr.subClassCode = htoa(SubClassCode);
-    data->config.hdr.classCode = htoa(ClassCode);
-    data->config.hdr.cacheLineSize = htoa(CacheLineSize);
-    data->config.hdr.latencyTimer = htoa(LatencyTimer);
-    data->config.hdr.headerType = htoa(HeaderType);
-    data->config.hdr.bist = htoa(BIST);
-
-    data->config.hdr.pci0.baseAddr0 = htoa(BAR0);
-    data->config.hdr.pci0.baseAddr1 = htoa(BAR1);
-    data->config.hdr.pci0.baseAddr2 = htoa(BAR2);
-    data->config.hdr.pci0.baseAddr3 = htoa(BAR3);
-    data->config.hdr.pci0.baseAddr4 = htoa(BAR4);
-    data->config.hdr.pci0.baseAddr5 = htoa(BAR5);
-    data->config.hdr.pci0.cardbusCIS = htoa(CardbusCIS);
-    data->config.hdr.pci0.subsystemVendorID = htoa(SubsystemVendorID);
-    data->config.hdr.pci0.subsystemID = htoa(SubsystemVendorID);
-    data->config.hdr.pci0.expansionROM = htoa(ExpansionROM);
-    data->config.hdr.pci0.interruptLine = htoa(InterruptLine);
-    data->config.hdr.pci0.interruptPin = htoa(InterruptPin);
-    data->config.hdr.pci0.minimumGrant = htoa(MinimumGrant);
-    data->config.hdr.pci0.maximumLatency = htoa(MaximumLatency);
+    data->config.vendor = htole(VendorID);
+    data->config.device = htole(DeviceID);
+    data->config.command = htole(Command);
+    data->config.status = htole(Status);
+    data->config.revision = htole(Revision);
+    data->config.progIF = htole(ProgIF);
+    data->config.subClassCode = htole(SubClassCode);
+    data->config.classCode = htole(ClassCode);
+    data->config.cacheLineSize = htole(CacheLineSize);
+    data->config.latencyTimer = htole(LatencyTimer);
+    data->config.headerType = htole(HeaderType);
+    data->config.bist = htole(BIST);
+
+    data->config.baseAddr0 = htole(BAR0);
+    data->config.baseAddr1 = htole(BAR1);
+    data->config.baseAddr2 = htole(BAR2);
+    data->config.baseAddr3 = htole(BAR3);
+    data->config.baseAddr4 = htole(BAR4);
+    data->config.baseAddr5 = htole(BAR5);
+    data->config.cardbusCIS = htole(CardbusCIS);
+    data->config.subsystemVendorID = htole(SubsystemVendorID);
+    data->config.subsystemID = htole(SubsystemVendorID);
+    data->config.expansionROM = htole(ExpansionROM);
+    data->config.interruptLine = htole(InterruptLine);
+    data->config.interruptPin = htole(InterruptPin);
+    data->config.minimumGrant = htole(MinimumGrant);
+    data->config.maximumLatency = htole(MaximumLatency);
 
     data->BARSize[0] = BAR0Size;
     data->BARSize[1] = BAR1Size;
index 091a365e393ea61d8aa3b865c4f7b883b94a2379..4293c59b9626208366a5b0c502bc0b00c7d93aeb 100644 (file)
 #include "dev/pcireg.h"
 #include "dev/platform.hh"
 
+#define BAR_IO_MASK 0x3
+#define BAR_MEM_MASK 0xF
+#define BAR_IO_SPACE_BIT 0x1
+#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
+#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
+
 class PciConfigAll;
 class MemoryController;
 
@@ -136,15 +142,15 @@ class PciDev : public DmaDevice
 
     void
     intrPost()
-    { plat->postPciInt(configData->config.hdr.pci0.interruptLine); }
+    { plat->postPciInt(configData->config.interruptLine); }
 
     void
     intrClear()
-    { plat->clearPciInt(configData->config.hdr.pci0.interruptLine); }
+    { plat->clearPciInt(configData->config.interruptLine); }
 
     uint8_t
     interruptLine()
-    { return configData->config.hdr.pci0.interruptLine; }
+    { return configData->config.interruptLine; }
 
   public:
     /**
@@ -169,7 +175,7 @@ class PciDev : public DmaDevice
      * @param size the size of the write
      * @param data the data to write
      */
-    virtual void WriteConfig(int offset, int size, uint32_t data);
+    virtual void writeConfig(int offset, int size, const uint8_t* data);
 
 
     /**
@@ -180,7 +186,7 @@ class PciDev : public DmaDevice
      * @param size the size of the read
      * @param data pointer to the location where the read value should be stored
      */
-    virtual void ReadConfig(int offset, int size, uint8_t *data);
+    virtual void readConfig(int offset, int size, uint8_t *data);
 
     /**
      * Serialize this object to the given output stream.
index 2f71a46baa140c143b683a65d9f53680ed94689c..9d2737c20bfb3d1bc0e69d36f5d17d460ec928b4 100644 (file)
 #include <sys/types.h>
 
 union PCIConfig {
-    uint8_t    data[64];
-
-    struct hdr {
-        uint16_t       vendor;
-        uint16_t       device;
-        uint16_t       command;
-        uint16_t       status;
-        uint8_t                revision;
-        uint8_t                progIF;
-        uint8_t                subClassCode;
-        uint8_t                classCode;
-        uint8_t                cacheLineSize;
-        uint8_t                latencyTimer;
-        uint8_t                headerType;
-        uint8_t                bist;
+    uint8_t data[64];
 
+    struct {
+        uint16_t vendor;
+        uint16_t device;
+        uint16_t command;
+        uint16_t status;
+        uint8_t revision;
+        uint8_t progIF;
+        uint8_t subClassCode;
+        uint8_t classCode;
+        uint8_t cacheLineSize;
+        uint8_t latencyTimer;
+        uint8_t headerType;
+        uint8_t bist;
         union {
-            struct {
-                uint32_t       baseAddr0;
-                uint32_t       baseAddr1;
-                uint32_t       baseAddr2;
-                uint32_t       baseAddr3;
-                uint32_t       baseAddr4;
-                uint32_t       baseAddr5;
-                uint32_t       cardbusCIS;
-                uint16_t       subsystemVendorID;
-                uint16_t       subsystemID;
-                uint32_t       expansionROM;
-                uint32_t       reserved0;
-                uint32_t       reserved1;
-                uint8_t                interruptLine;
-                uint8_t                interruptPin;
-                uint8_t                minimumGrant;
-                uint8_t                maximumLatency;
-            } pci0;
+            uint32_t baseAddr[6];
 
             struct {
-                uint32_t       baseAddr0;
-                uint32_t       baseAddr1;
-                uint8_t                priBusNum;
-                uint8_t                secBusNum;
-                uint8_t                subBusNum;
-                uint8_t                secLatency;
-                uint8_t                ioBase;
-                uint8_t                minimumGrantioLimit;
-                uint16_t       secStatus;
-                uint16_t       memBase;
-                uint16_t       memLimit;
-                uint16_t       prefetchMemBase;
-                uint16_t       prefetchMemLimit;
-                uint32_t       prfBaseUpper32;
-                uint32_t       prfLimitUpper32;
-                uint16_t       ioBaseUpper16;
-                uint16_t       ioLimitUpper16;
-                uint32_t       reserved0;
-                uint32_t       expansionROM;
-                uint8_t                interruptLine;
-                uint8_t                interruptPin;
-                uint16_t       bridgeControl;
-            } pci1;
+                uint32_t baseAddr0;
+                uint32_t baseAddr1;
+                uint32_t baseAddr2;
+                uint32_t baseAddr3;
+                uint32_t baseAddr4;
+                uint32_t baseAddr5;
+            };
         };
-    } hdr;
+        uint32_t cardbusCIS;
+        uint16_t subsystemVendorID;
+        uint16_t subsystemID;
+        uint32_t expansionROM;
+        uint32_t reserved0;
+        uint32_t reserved1;
+        uint8_t interruptLine;
+        uint8_t interruptPin;
+        uint8_t minimumGrant;
+        uint8_t maximumLatency;
+    };
 };
 
 // Common PCI offsets
diff --git a/dev/pitreg.h b/dev/pitreg.h
new file mode 100644 (file)
index 0000000..5fe1cf0
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @file
+ * Device register definitions for a device's PCI config space
+ */
+
+#ifndef __PITREG_H__
+#define __PITREG_H__
+
+#include <sys/types.h>
+
+// Control Word Format
+
+#define PIT_SEL_SHFT  0x6
+#define PIT_RW_SHFT   0x4
+#define PIT_MODE_SHFT 0x1
+#define PIT_BCD_SHFT  0x0
+
+#define PIT_SEL_MASK  0x3
+#define PIT_RW_MASK   0x3
+#define PIT_MODE_MASK 0x7
+#define PIT_BCD_MASK  0x1
+
+#define GET_CTRL_FIELD(x, s, m) (((x) >> s) & m)
+#define GET_CTRL_SEL(x) GET_CTRL_FIELD(x, PIT_SEL_SHFT, PIT_SEL_MASK)
+#define GET_CTRL_RW(x) GET_CTRL_FIELD(x, PIT_RW_SHFT, PIT_RW_MASK)
+#define GET_CTRL_MODE(x) GET_CTRL_FIELD(x, PIT_MODE_SHFT, PIT_MODE_MASK)
+#define GET_CTRL_BCD(x) GET_CTRL_FIELD(x, PIT_BCD_SHFT, PIT_BCD_MASK)
+
+#define PIT_READ_BACK 0x3
+
+#define PIT_RW_LATCH_COMMAND 0x0
+#define PIT_RW_LSB_ONLY      0x1
+#define PIT_RW_MSB_ONLY      0x2
+#define PIT_RW_16BIT         0x3
+
+#define PIT_MODE_INTTC    0x0
+#define PIT_MODE_ONESHOT  0x1
+#define PIT_MODE_RATEGEN  0x2
+#define PIT_MODE_SQWAVE   0x3
+#define PIT_MODE_SWSTROBE 0x4
+#define PIT_MODE_HWSTROBE 0x5
+
+#define PIT_BCD_FALSE 0x0
+#define PIT_BCD_TRUE  0x1
+
+#endif // __PITREG_H__
index 0b33c25b25f628d122e95521bf37f36ad7ae124d..5025a0e959af4b39b8768dc322a72fa35ab8ade8 100644 (file)
 #define RTC_DOM                 0x07
 #define RTC_MON                 0x08
 #define RTC_YEAR                0x09
-#define RTC_CNTRL_REGA          0x0A
-#define RTC_CNTRL_REGB          0x0B
-#define RTC_CNTRL_REGC          0x0C
-#define RTC_CNTRL_REGD          0x0D
+
+#define RTC_STAT_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_STAT_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_STAT_REGC           0x0C
+#define RTC_STAT_REGD           0x0D
 
index f8e070e951086166675c44e17633dc2e7a7b301a..d30303835f25703893f05e14df6b439fcd3c5cf4 100644 (file)
@@ -296,12 +296,12 @@ Device::regStats()
  * This is to write to the PCI general configuration registers
  */
 void
-Device::WriteConfig(int offset, int size, uint32_t data)
+Device::writeConfig(int offset, int size, const uint8_t *data)
 {
     switch (offset) {
       case PCI0_BASE_ADDR0:
         // Need to catch writes to BARs to update the PIO interface
-        PciDev::WriteConfig(offset, size, data);
+        PciDev::writeConfig(offset, size, data);
         if (BARAddrs[0] != 0) {
             if (pioInterface)
                 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
@@ -311,7 +311,7 @@ Device::WriteConfig(int offset, int size, uint32_t data)
         break;
 
       default:
-        PciDev::WriteConfig(offset, size, data);
+        PciDev::writeConfig(offset, size, data);
     }
 }
 
@@ -322,7 +322,7 @@ Device::WriteConfig(int offset, int size, uint32_t data)
 Fault
 Device::read(MemReqPtr &req, uint8_t *data)
 {
-    assert(config.hdr.command & PCI_CMD_MSE);
+    assert(config.command & PCI_CMD_MSE);
 
     //The mask is to give you only the offset into the device register file
     Addr daddr = req->paddr & 0xfff;
@@ -409,7 +409,7 @@ Device::read(MemReqPtr &req, uint8_t *data)
 Fault
 Device::write(MemReqPtr &req, const uint8_t *data)
 {
-    assert(config.hdr.command & PCI_CMD_MSE);
+    assert(config.command & PCI_CMD_MSE);
     Addr daddr = req->paddr & 0xfff;
 
     if (Regs::regSize(daddr) == 0)
index 4fab67b2960e6cba5faaa0906dd13cbb36f33474..d190746a47206e1b01a906c4ef9bac102e41ca48 100644 (file)
@@ -238,7 +238,7 @@ class Device : public Base
  * PCI Configuration interface
  */
   public:
-    virtual void WriteConfig(int offset, int size, uint32_t data);
+    virtual void writeConfig(int offset, int size, const uint8_t *data);
 
 /**
  * Memory Interface
index da1062237ef558473008c274aacbbf912725ac64..569bb46cbf6b4d61d4cf94a428b72dd8f3351d42 100644 (file)
@@ -39,6 +39,7 @@
 #include "base/trace.hh"
 #include "dev/tsunami_io.hh"
 #include "dev/tsunami.hh"
+#include "dev/pitreg.h"
 #include "mem/bus/bus.hh"
 #include "mem/bus/pio_interface.hh"
 #include "mem/bus/pio_interface_impl.hh"
 
 using namespace std;
 
-#define UNIX_YEAR_OFFSET 52
+TsunamiIO::RTC::RTC(Tsunami* t, Tick i)
+    : SimObject("RTC"), event(t, i), addr(0)
+{
+    memset(clock_data, 0, sizeof(clock_data));
+    stat_regA = RTCA_32768HZ | RTCA_1024HZ;
+    stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
+}
+
+void
+TsunamiIO::RTC::set_time(time_t t)
+{
+    struct tm tm;
+    gmtime_r(&t, &tm);
+
+    sec = tm.tm_sec;
+    min = tm.tm_min;
+    hour = tm.tm_hour;
+    wday = tm.tm_wday + 1;
+    mday = tm.tm_mday;
+    mon = tm.tm_mon + 1;
+    year = tm.tm_year;
+
+    DPRINTFN("Real-time clock set to %s", asctime(&tm));
+}
+
+void
+TsunamiIO::RTC::writeAddr(const uint8_t *data)
+{
+    if (*data <= RTC_STAT_REGD)
+        addr = *data;
+    else
+        panic("RTC addresses over 0xD are not implemented.\n");
+}
+
+void
+TsunamiIO::RTC::writeData(const uint8_t *data)
+{
+    if (addr < RTC_STAT_REGA)
+        clock_data[addr] = *data;
+    else {
+        switch (addr) {
+          case RTC_STAT_REGA:
+            if (*data != (RTCA_32768HZ | RTCA_1024HZ))
+                panic("Unimplemented RTC register A value write!\n");
+            stat_regA = *data;
+            break;
+          case RTC_STAT_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 (!event.scheduled())
+                    event.scheduleIntr();
+            } else {
+                if (event.scheduled())
+                    event.deschedule();
+            }
+            stat_regB = *data;
+            break;
+          case RTC_STAT_REGC:
+          case RTC_STAT_REGD:
+            panic("RTC status registers C and D are not implemented.\n");
+            break;
+        }
+    }
+}
+
+void
+TsunamiIO::RTC::readData(uint8_t *data)
+{
+    if (addr < RTC_STAT_REGA)
+        *data = clock_data[addr];
+    else {
+        switch (addr) {
+          case RTC_STAT_REGA:
+            // toggle UIP bit for linux
+            stat_regA ^= RTCA_UIP;
+            *data = stat_regA;
+            break;
+          case RTC_STAT_REGB:
+            *data = stat_regB;
+            break;
+          case RTC_STAT_REGC:
+          case RTC_STAT_REGD:
+            *data = 0x00;
+            break;
+        }
+    }
+}
+
+void
+TsunamiIO::RTC::serialize(std::ostream &os)
+{
+    SERIALIZE_SCALAR(addr);
+    SERIALIZE_ARRAY(clock_data, sizeof(clock_data));
+    SERIALIZE_SCALAR(stat_regA);
+    SERIALIZE_SCALAR(stat_regB);
+
+    // serialize the RTC event
+    nameOut(os, csprintf("%s.event", name()));
+    event.serialize(os);
+}
+
+void
+TsunamiIO::RTC::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(addr);
+    UNSERIALIZE_ARRAY(clock_data, sizeof(clock_data));
+    UNSERIALIZE_SCALAR(stat_regA);
+    UNSERIALIZE_SCALAR(stat_regB);
+
+    // unserialze the event
+    event.unserialize(cp, csprintf("%s.event", section));
+}
 
-// Timer Event for Periodic interrupt of RTC
-TsunamiIO::RTCEvent::RTCEvent(Tsunami* t, Tick i)
+TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i)
     : Event(&mainEventQueue), tsunami(t), interval(i)
 {
     DPRINTF(MC146818, "RTC Event Initilizing\n");
@@ -61,7 +174,13 @@ TsunamiIO::RTCEvent::RTCEvent(Tsunami* t, Tick i)
 }
 
 void
-TsunamiIO::RTCEvent::process()
+TsunamiIO::RTC::RTCEvent::scheduleIntr()
+{
+  schedule(curTick + interval);
+}
+
+void
+TsunamiIO::RTC::RTCEvent::process()
 {
     DPRINTF(MC146818, "RTC Timer Interrupt\n");
     schedule(curTick + interval);
@@ -70,95 +189,256 @@ TsunamiIO::RTCEvent::process()
 }
 
 const char *
-TsunamiIO::RTCEvent::description()
+TsunamiIO::RTC::RTCEvent::description()
 {
     return "tsunami RTC interrupt";
 }
 
 void
-TsunamiIO::RTCEvent::serialize(std::ostream &os)
+TsunamiIO::RTC::RTCEvent::serialize(std::ostream &os)
 {
     Tick time = when();
     SERIALIZE_SCALAR(time);
 }
 
 void
-TsunamiIO::RTCEvent::unserialize(Checkpoint *cp, const std::string &section)
+TsunamiIO::RTC::RTCEvent::unserialize(Checkpoint *cp, const std::string &section)
 {
     Tick time;
     UNSERIALIZE_SCALAR(time);
     reschedule(time);
 }
 
+TsunamiIO::PITimer::PITimer()
+    : SimObject("PITimer"), counter0(counter[0]), counter1(counter[1]),
+      counter2(counter[2])
+{
 
-// Timer Event for PIT Timers
-TsunamiIO::ClockEvent::ClockEvent()
-    : Event(&mainEventQueue)
+}
+
+void
+TsunamiIO::PITimer::writeControl(const uint8_t *data)
 {
-    /* This is the PIT Tick Rate. A constant for the 8254 timer. The
-     * Tsunami platform has one of these cycle counters on the Cypress
-     * South Bridge and it is used by linux for estimating the cycle
-     * frequency of the machine it is running on. --Ali
-     */
-    interval = (Tick)(Clock::Float::s / 1193180.0);
+    int rw;
+    int sel;
+
+    sel = GET_CTRL_SEL(*data);
+
+    if (sel == PIT_READ_BACK)
+       panic("PITimer Read-Back Command is not implemented.\n");
 
-    DPRINTF(Tsunami, "Clock Event Initilizing\n");
-    mode = 0;
+    rw = GET_CTRL_RW(*data);
+
+    if (rw == PIT_RW_LATCH_COMMAND)
+        counter[sel].latchCount();
+    else {
+        counter[sel].setRW(rw);
+        counter[sel].setMode(GET_CTRL_MODE(*data));
+        counter[sel].setBCD(GET_CTRL_BCD(*data));
+    }
 }
 
 void
-TsunamiIO::ClockEvent::process()
+TsunamiIO::PITimer::serialize(std::ostream &os)
 {
-    DPRINTF(Tsunami, "Timer Interrupt\n");
-    if (mode == 0)
-        status = 0x20; // set bit that linux is looking for
-    else
-        schedule(curTick + interval);
+    // serialize the counters
+    nameOut(os, csprintf("%s.counter0", name()));
+    counter0.serialize(os);
+
+    nameOut(os, csprintf("%s.counter1", name()));
+    counter1.serialize(os);
+
+    nameOut(os, csprintf("%s.counter2", name()));
+    counter2.serialize(os);
 }
 
 void
-TsunamiIO::ClockEvent::Program(int count)
+TsunamiIO::PITimer::unserialize(Checkpoint *cp, const std::string &section)
 {
-    DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * interval);
-    schedule(curTick + count * interval);
-    status = 0;
+    // unserialze the counters
+    counter0.unserialize(cp, csprintf("%s.counter0", section));
+    counter1.unserialize(cp, csprintf("%s.counter1", section));
+    counter2.unserialize(cp, csprintf("%s.counter2", section));
 }
 
-const char *
-TsunamiIO::ClockEvent::description()
+TsunamiIO::PITimer::Counter::Counter()
+    : SimObject("Counter"), event(this), count(0), latched_count(0), period(0),
+      mode(0), output_high(false), latch_on(false), read_byte(LSB),
+      write_byte(LSB)
 {
-    return "tsunami 8254 Interval timer";
+
+}
+
+void
+TsunamiIO::PITimer::Counter::latchCount()
+{
+    // behave like a real latch
+    if(!latch_on) {
+        latch_on = true;
+        read_byte = LSB;
+        latched_count = count;
+    }
+}
+
+void
+TsunamiIO::PITimer::Counter::read(uint8_t *data)
+{
+    if (latch_on) {
+        switch (read_byte) {
+          case LSB:
+            read_byte = MSB;
+            *data = (uint8_t)latched_count;
+            break;
+          case MSB:
+            read_byte = LSB;
+            latch_on = false;
+            *data = latched_count >> 8;
+            break;
+        }
+    } else {
+        switch (read_byte) {
+          case LSB:
+            read_byte = MSB;
+            *data = (uint8_t)count;
+            break;
+          case MSB:
+            read_byte = LSB;
+            *data = count >> 8;
+            break;
+        }
+    }
+}
+
+void
+TsunamiIO::PITimer::Counter::write(const uint8_t *data)
+{
+    switch (write_byte) {
+      case LSB:
+        count = (count & 0xFF00) | *data;
+
+        if (event.scheduled())
+          event.deschedule();
+        output_high = false;
+        write_byte = MSB;
+        break;
+
+      case MSB:
+        count = (count & 0x00FF) | (*data << 8);
+        period = count;
+
+        if (period > 0) {
+            DPRINTF(Tsunami, "Timer set to curTick + %d\n", count * event.interval);
+            event.schedule(curTick + count * event.interval);
+        }
+        write_byte = LSB;
+        break;
+    }
+}
+
+void
+TsunamiIO::PITimer::Counter::setRW(int rw_val)
+{
+    if (rw_val != PIT_RW_16BIT)
+        panic("Only LSB/MSB read/write is implemented.\n");
+}
+
+void
+TsunamiIO::PITimer::Counter::setMode(int mode_val)
+{
+    if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
+       mode_val != PIT_MODE_SQWAVE)
+        panic("PIT mode %#x is not implemented: \n", mode_val);
+
+    mode = mode_val;
+}
+
+void
+TsunamiIO::PITimer::Counter::setBCD(int bcd_val)
+{
+    if (bcd_val != PIT_BCD_FALSE)
+        panic("PITimer does not implement BCD counts.\n");
+}
+
+bool
+TsunamiIO::PITimer::Counter::outputHigh()
+{
+    return output_high;
 }
 
 void
-TsunamiIO::ClockEvent::ChangeMode(uint8_t md)
+TsunamiIO::PITimer::Counter::serialize(std::ostream &os)
 {
-    mode = md;
+    SERIALIZE_SCALAR(count);
+    SERIALIZE_SCALAR(latched_count);
+    SERIALIZE_SCALAR(period);
+    SERIALIZE_SCALAR(mode);
+    SERIALIZE_SCALAR(output_high);
+    SERIALIZE_SCALAR(latch_on);
+    SERIALIZE_SCALAR(read_byte);
+    SERIALIZE_SCALAR(write_byte);
+
+    // serialize the counter event
+    nameOut(os, csprintf("%s.event", name()));
+    event.serialize(os);
+}
+
+void
+TsunamiIO::PITimer::Counter::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(count);
+    UNSERIALIZE_SCALAR(latched_count);
+    UNSERIALIZE_SCALAR(period);
+    UNSERIALIZE_SCALAR(mode);
+    UNSERIALIZE_SCALAR(output_high);
+    UNSERIALIZE_SCALAR(latch_on);
+    UNSERIALIZE_SCALAR(read_byte);
+    UNSERIALIZE_SCALAR(write_byte);
+
+    // unserialze the counter event
+    event.unserialize(cp, csprintf("%s.event", section));
+}
+
+TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
+    : Event(&mainEventQueue)
+{
+    interval = (Tick)(Clock::Float::s / 1193180.0);
+    counter = c_ptr;
+}
+
+void
+TsunamiIO::PITimer::Counter::CounterEvent::process()
+{
+    DPRINTF(Tsunami, "Timer Interrupt\n");
+    switch (counter->mode) {
+      case PIT_MODE_INTTC:
+        counter->output_high = true;
+      case PIT_MODE_RATEGEN:
+      case PIT_MODE_SQWAVE:
+        break;
+      default:
+        panic("Unimplemented PITimer mode.\n");
+    }
 }
 
-uint8_t
-TsunamiIO::ClockEvent::Status()
+const char *
+TsunamiIO::PITimer::Counter::CounterEvent::description()
 {
-    return status;
+    return "tsunami 8254 Interval timer";
 }
 
 void
-TsunamiIO::ClockEvent::serialize(std::ostream &os)
+TsunamiIO::PITimer::Counter::CounterEvent::serialize(std::ostream &os)
 {
     Tick time = scheduled() ? when() : 0;
     SERIALIZE_SCALAR(time);
-    SERIALIZE_SCALAR(status);
-    SERIALIZE_SCALAR(mode);
     SERIALIZE_SCALAR(interval);
 }
 
 void
-TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string &section)
+TsunamiIO::PITimer::Counter::CounterEvent::unserialize(Checkpoint *cp, const std::string &section)
 {
     Tick time;
     UNSERIALIZE_SCALAR(time);
-    UNSERIALIZE_SCALAR(status);
-    UNSERIALIZE_SCALAR(mode);
     UNSERIALIZE_SCALAR(interval);
     if (time)
         schedule(time);
@@ -182,8 +462,7 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
     tsunami->io = this;
 
     timerData = 0;
-    set_time(init_time == 0 ? time(NULL) : init_time);
-    uip = 1;
+    rtc.set_time(init_time == 0 ? time(NULL) : init_time);
     picr = 0;
     picInterrupting = false;
 }
@@ -194,13 +473,6 @@ TsunamiIO::frequency() const
     return Clock::Frequency / clockInterval;
 }
 
-void
-TsunamiIO::set_time(time_t t)
-{
-    gmtime_r(&t, &tm);
-    DPRINTFN("Real-time clock set to %s", asctime(&tm));
-}
-
 Fault
 TsunamiIO::read(MemReqPtr &req, uint8_t *data)
 {
@@ -213,6 +485,13 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
     switch(req->size) {
       case sizeof(uint8_t):
         switch(daddr) {
+          // PIC1 mask read
+          case TSDEV_PIC1_MASK:
+            *(uint8_t*)data = ~mask1;
+            return No_Fault;
+          case TSDEV_PIC2_MASK:
+            *(uint8_t*)data = ~mask2;
+            return No_Fault;
           case TSDEV_PIC1_ISR:
               // !!! If this is modified 64bit case needs to be too
               // Pal code has to do a 64 bit physical read because there is
@@ -223,50 +502,24 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
               // PIC2 not implemnted... just return 0
               *(uint8_t*)data = 0x00;
               return No_Fault;
-          case TSDEV_TMR_CTL:
-            *(uint8_t*)data = timer2.Status();
+          case TSDEV_TMR0_DATA:
+            pitimer.counter0.read(data);
+            return No_Fault;
+          case TSDEV_TMR1_DATA:
+            pitimer.counter1.read(data);
+            return No_Fault;
+          case TSDEV_TMR2_DATA:
+            pitimer.counter2.read(data);
             return No_Fault;
           case TSDEV_RTC_DATA:
-            switch(RTCAddress) {
-              case RTC_CNTRL_REGA:
-                *(uint8_t*)data = uip << 7 | 0x26;
-                uip = !uip;
-                return No_Fault;
-              case RTC_CNTRL_REGB:
-                // DM and 24/12 and UIE
-                *(uint8_t*)data = 0x46;
-                return No_Fault;
-              case RTC_CNTRL_REGC:
-                // If we want to support RTC user access in linux
-                // This won't work, but for now it's fine
-                *(uint8_t*)data = 0x00;
-                return No_Fault;
-              case RTC_CNTRL_REGD:
-                panic("RTC Control Register D not implemented");
-              case RTC_SEC:
-                *(uint8_t *)data = tm.tm_sec;
-                return No_Fault;
-              case RTC_MIN:
-                *(uint8_t *)data = tm.tm_min;
-                return No_Fault;
-              case RTC_HR:
-                *(uint8_t *)data = tm.tm_hour;
-                return No_Fault;
-              case RTC_DOW:
-                *(uint8_t *)data = tm.tm_wday;
-                return No_Fault;
-              case RTC_DOM:
-                *(uint8_t *)data = tm.tm_mday;
-              case RTC_MON:
-                *(uint8_t *)data = tm.tm_mon + 1;
-                return No_Fault;
-              case RTC_YEAR:
-                *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET;
-                return No_Fault;
-              default:
-                panic("Unknown RTC Address\n");
-            }
-
+            rtc.readData(data);
+            return No_Fault;
+          case TSDEV_CTRL_PORTB:
+            if (pitimer.counter2.outputHigh())
+                *data = PORTB_SPKR_HIGH;
+            else
+                *data = 0x00;
+            return No_Fault;
           default:
             panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
         }
@@ -337,6 +590,14 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
             if (!(picr & mask1))
                 tsunami->cchip->clearDRIR(55);
             return No_Fault;
+          case TSDEV_DMA1_CMND:
+            return No_Fault;
+          case TSDEV_DMA2_CMND:
+            return No_Fault;
+          case TSDEV_DMA1_MMASK:
+            return No_Fault;
+          case TSDEV_DMA2_MMASK:
+            return No_Fault;
           case TSDEV_PIC2_ACK:
             return No_Fault;
           case TSDEV_DMA1_RESET:
@@ -352,54 +613,31 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
           case TSDEV_DMA1_MASK:
           case TSDEV_DMA2_MASK:
             return No_Fault;
-          case TSDEV_TMR_CTL:
+          case TSDEV_TMR0_DATA:
+            pitimer.counter0.write(data);
             return No_Fault;
-          case TSDEV_TMR2_CTL:
-            if ((*(uint8_t*)data & 0x30) != 0x30)
-                panic("Only L/M write supported\n");
-
-            switch(*(uint8_t*)data >> 6) {
-              case 0:
-                timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
-                break;
-              case 2:
-                timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
-                break;
-              default:
-                panic("Read Back Command not implemented\n");
-            }
+          case TSDEV_TMR1_DATA:
+            pitimer.counter1.write(data);
             return No_Fault;
           case TSDEV_TMR2_DATA:
-            /* two writes before we actually start the Timer
-               so I set a flag in the timerData */
-            if(timerData & 0x1000) {
-                timerData &= 0x1000;
-                timerData += *(uint8_t*)data << 8;
-                timer2.Program(timerData);
-            } else {
-                timerData = *(uint8_t*)data;
-                timerData |= 0x1000;
-            }
+            pitimer.counter2.write(data);
             return No_Fault;
-          case TSDEV_TMR0_DATA:
-            /* two writes before we actually start the Timer
-               so I set a flag in the timerData */
-            if(timerData & 0x1000) {
-                timerData &= 0x1000;
-                timerData += *(uint8_t*)data << 8;
-                timer0.Program(timerData);
-            } else {
-                timerData = *(uint8_t*)data;
-                timerData |= 0x1000;
-            }
+          case TSDEV_TMR_CTRL:
+            pitimer.writeControl(data);
             return No_Fault;
           case TSDEV_RTC_ADDR:
-            RTCAddress = *(uint8_t*)data;
+            rtc.writeAddr(data);
+            return No_Fault;
+          case TSDEV_KBD:
             return No_Fault;
           case TSDEV_RTC_DATA:
-            panic("RTC Write not implmented (rtc.o won't work)\n");
+            rtc.writeData(data);
+            return No_Fault;
+          case TSDEV_CTRL_PORTB:
+            // System Control Port B not implemented
+            return No_Fault;
           default:
-            panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
+            panic("I/O Write - va%#x size %d data %#x\n", req->vaddr, req->size, (int)*data);
         }
       case sizeof(uint16_t):
       case sizeof(uint32_t):
@@ -445,20 +683,16 @@ void
 TsunamiIO::serialize(std::ostream &os)
 {
     SERIALIZE_SCALAR(timerData);
-    SERIALIZE_SCALAR(uip);
     SERIALIZE_SCALAR(mask1);
     SERIALIZE_SCALAR(mask2);
     SERIALIZE_SCALAR(mode1);
     SERIALIZE_SCALAR(mode2);
     SERIALIZE_SCALAR(picr);
     SERIALIZE_SCALAR(picInterrupting);
-    SERIALIZE_SCALAR(RTCAddress);
 
     // Serialize the timers
-    nameOut(os, csprintf("%s.timer0", name()));
-    timer0.serialize(os);
-    nameOut(os, csprintf("%s.timer2", name()));
-    timer2.serialize(os);
+    nameOut(os, csprintf("%s.pitimer", name()));
+    pitimer.serialize(os);
     nameOut(os, csprintf("%s.rtc", name()));
     rtc.serialize(os);
 }
@@ -467,18 +701,15 @@ void
 TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_SCALAR(timerData);
-    UNSERIALIZE_SCALAR(uip);
     UNSERIALIZE_SCALAR(mask1);
     UNSERIALIZE_SCALAR(mask2);
     UNSERIALIZE_SCALAR(mode1);
     UNSERIALIZE_SCALAR(mode2);
     UNSERIALIZE_SCALAR(picr);
     UNSERIALIZE_SCALAR(picInterrupting);
-    UNSERIALIZE_SCALAR(RTCAddress);
 
     // Unserialize the timers
-    timer0.unserialize(cp, csprintf("%s.timer0", section));
-    timer2.unserialize(cp, csprintf("%s.timer2", section));
+    pitimer.unserialize(cp, csprintf("%s.pitimer", section));
     rtc.unserialize(cp, csprintf("%s.rtc", section));
 }
 
index d5d106db3b9c37802ab4d48347b67135c44ce292..5f20cbf4ad5533889a03ec78011d2ccaf64c7125 100644 (file)
@@ -53,105 +53,223 @@ class TsunamiIO : public PioDevice
 
     struct tm tm;
 
-    /**
-     * In Tsunami RTC only has two i/o ports one for data and one for
-     * address, so you write the address and then read/write the
-     * data. This store the address you are going to be reading from
-     * on a read.
-     */
-    uint8_t RTCAddress;
-
   protected:
 
-    /**
-     * The ClockEvent is handles the PIT interrupts
-     */
-    class ClockEvent : public Event
+    /** Real-Time Clock (MC146818) */
+    class RTC : public SimObject
     {
-      protected:
-        /** how often the PIT fires */
-        Tick interval;
-        /** The mode of the PIT */
-        uint8_t mode;
-        /** The status of the PIT */
-        uint8_t status;
+      /** Event for RTC periodic interrupt */
+      class RTCEvent : public Event
+      {
+        private:
+          /** A pointer back to tsunami to create interrupt the processor. */
+          Tsunami* tsunami;
+          Tick interval;
+
+        public:
+          RTCEvent(Tsunami* t, Tick i);
+
+          /** Schedule the RTC periodic interrupt */
+          void scheduleIntr();
+
+          /** Event process to occur at interrupt*/
+          virtual void process();
+
+          /** Event description */
+          virtual const char *description();
+
+          /**
+           * Serialize this object to the given output stream.
+           * @param os The stream to serialize to.
+           */
+          virtual void serialize(std::ostream &os);
+
+          /**
+           * Reconstruct the state of this object from a checkpoint.
+           * @param cp The checkpoint use.
+           * @param section The section name of this object
+           */
+          virtual void unserialize(Checkpoint *cp, const std::string &section);
+      };
+
+      private:
+        /** RTC periodic interrupt event */
+        RTCEvent event;
+
+        /** Current RTC register address/index */
+        int addr;
+
+        /** Data for real-time clock function */
+        union {
+            uint8_t clock_data[10];
+
+            struct {
+                uint8_t sec;
+                uint8_t sec_alrm;
+                uint8_t min;
+                uint8_t min_alrm;
+                uint8_t hour;
+                uint8_t hour_alrm;
+                uint8_t wday;
+                uint8_t mday;
+                uint8_t mon;
+                uint8_t year;
+            };
+        };
+
+        /** RTC status register A */
+        uint8_t stat_regA;
+
+        /** RTC status register B */
+        uint8_t stat_regB;
 
       public:
-        /**
-         * Just set the mode to 0
-         */
-        ClockEvent();
+        RTC(Tsunami* t, Tick i);
 
-        /**
-         * processs the timer event
-         */
-        virtual void process();
+        /** Set the initial RTC time/date */
+        void set_time(time_t t);
 
-        /**
-         * Returns a description of this event
-         * @return the description
-         */
-        virtual const char *description();
-
-        /**
-         * Schedule a timer interrupt to occur sometime in the future.
-         */
-        void Program(int count);
+        /** RTC address port: write address of RTC RAM data to access */
+        void writeAddr(const uint8_t *data);
 
-        /**
-         * Write the mode bits of the PIT.
-         * @param mode the new mode
-         */
-        void ChangeMode(uint8_t mode);
+        /** RTC write data */
+        void writeData(const uint8_t *data);
 
-        /**
-         * The current PIT status.
-         * @return the status of the PIT
-         */
-        uint8_t Status();
+        /** RTC read data */
+        void readData(uint8_t *data);
 
         /**
-         * Serialize this object to the given output stream.
-         * @param os The stream to serialize to.
-         */
+          * Serialize this object to the given output stream.
+          * @param os The stream to serialize to.
+          */
         virtual void serialize(std::ostream &os);
 
-
         /**
          * Reconstruct the state of this object from a checkpoint.
          * @param cp The checkpoint use.
          * @param section The section name of this object
          */
         virtual void unserialize(Checkpoint *cp, const std::string &section);
-     };
+    };
 
-    /**
-     * Process RTC timer events and generate interrupts appropriately.
-     */
-    class RTCEvent : public Event
+    /** Programmable Interval Timer (Intel 8254) */
+    class PITimer : public SimObject
     {
-      protected:
-        /** A pointer back to tsunami to create interrupt the processor. */
-        Tsunami* tsunami;
-        Tick interval;
+        /** Counter element for PIT */
+        class Counter : public SimObject
+        {
+            /** Event for counter interrupt */
+            class CounterEvent : public Event
+            {
+              private:
+                /** Pointer back to Counter */
+                Counter* counter;
+                Tick interval;
+
+              public:
+                CounterEvent(Counter*);
+
+                /** Event process */
+                virtual void process();
+
+                /** Event description */
+                virtual const char *description();
+
+                /**
+                 * Serialize this object to the given output stream.
+                 * @param os The stream to serialize to.
+                 */
+                virtual void serialize(std::ostream &os);
+
+                /**
+                 * Reconstruct the state of this object from a checkpoint.
+                 * @param cp The checkpoint use.
+                 * @param section The section name of this object
+                 */
+                virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+                friend class Counter;
+            };
+
+          private:
+            CounterEvent event;
+
+            /** Current count value */
+            uint16_t count;
+
+            /** Latched count */
+            uint16_t latched_count;
+
+            /** Interrupt period */
+            uint16_t period;
+
+            /** Current mode of operation */
+            uint8_t mode;
+
+            /** Output goes high when the counter reaches zero */
+            bool output_high;
+
+            /** State of the count latch */
+            bool latch_on;
+
+            /** Set of values for read_byte and write_byte */
+            enum {LSB, MSB};
+
+            /** Determine which byte of a 16-bit count value to read/write */
+            uint8_t read_byte, write_byte;
+
+          public:
+            Counter();
+
+            /** Latch the current count (if one is not already latched) */
+            void latchCount();
+
+            /** Set the read/write mode */
+            void setRW(int rw_val);
+
+            /** Set operational mode */
+            void setMode(int mode_val);
+
+            /** Set count encoding */
+            void setBCD(int bcd_val);
+
+            /** Read a count byte */
+            void read(uint8_t *data);
+
+            /** Write a count byte */
+            void write(const uint8_t *data);
+
+            /** Is the output high? */
+            bool outputHigh();
+
+            /**
+             * Serialize this object to the given output stream.
+             * @param os The stream to serialize to.
+             */
+            virtual void serialize(std::ostream &os);
+
+            /**
+             * Reconstruct the state of this object from a checkpoint.
+             * @param cp The checkpoint use.
+             * @param section The section name of this object
+             */
+            virtual void unserialize(Checkpoint *cp, const std::string &section);
+        };
+
+      private:
+        /** PIT has three seperate counters */
+        Counter counter[3];
 
       public:
-        /**
-         * RTC Event initializes the RTC event by scheduling an event
-         * RTC_RATE times pre second.
-         */
-        RTCEvent(Tsunami* t, Tick i);
+        /** Public way to access individual counters (avoid array accesses) */
+        Counter &counter0;
+        Counter &counter1;
+        Counter &counter2;
 
-        /**
-         * Interrupth the processor and reschedule the event.
-         */
-        virtual void process();
+        PITimer();
 
-        /**
-         * Return a description of this event.
-         * @return a description
-         */
-        virtual const char *description();
+        /** Write control word */
+        void writeControl(const uint8_t* data);
 
         /**
          * Serialize this object to the given output stream.
@@ -167,13 +285,6 @@ class TsunamiIO : public PioDevice
         virtual void unserialize(Checkpoint *cp, const std::string &section);
     };
 
-    /** uip UpdateInProgess says that the rtc is updating, but we just fake it
-     * by alternating it on every read of the bit since we are going to
-     * override the loop_per_jiffy time that it is trying to use the UIP to
-     * calculate.
-     */
-    uint8_t uip;
-
     /** Mask of the PIC1 */
     uint8_t mask1;
 
@@ -197,31 +308,16 @@ class TsunamiIO : public PioDevice
     /** A pointer to the Tsunami device which be belong to */
     Tsunami *tsunami;
 
-    /**
-     * This timer is initilized, but after I wrote the code
-     * it doesn't seem to be used again, and best I can tell
-     * it too is not connected to any interrupt port
-     */
-    ClockEvent timer0;
-
-    /**
-     * This timer is used to control the speaker, which
-     * we normally could care less about, however it is
-     * also used to calculated the clockspeed and hense
-     * bogomips which is kinda important to the scheduler
-     * so we need to implemnt it although after boot I can't
-     * imagine we would be playing with the PC speaker much
-     */
-    ClockEvent timer2;
+    /** Intel 8253 Periodic Interval Timer */
+    PITimer pitimer;
 
-    /** This is the event used to interrupt the cpu like an RTC.  */
-    RTCEvent rtc;
+    RTC rtc;
 
     /** The interval is set via two writes to the PIT.
      * This variable contains a flag as to how many writes have happened, and
      * the time so far.
      */
-    uint32_t timerData;
+    uint16_t timerData;
 
   public:
     /**
@@ -242,11 +338,6 @@ class TsunamiIO : public PioDevice
               Addr a, MemoryController *mmu, HierParams *hier, Bus *bus,
               Tick pio_latency, Tick ci);
 
-    /**
-     * Create the tm struct from seconds since 1970
-     */
-    void set_time(time_t t);
-
     /**
       * Process a read to one of the devices we are emulating.
       * @param req Contains the address to read from.
index 5fbfd5c31ede0dd037ecd8af51d9d52632fe5607..583ff78b44c7d956ea35d2822d7309b197242597 100644 (file)
 #define TSDEV_DMA2_MODE     0xD6
 #define TSDEV_DMA1_MASK     0x0A
 #define TSDEV_DMA2_MASK     0xD4
-#define TSDEV_TMR_CTL       0x61
-#define TSDEV_TMR2_CTL      0x43
-#define TSDEV_TMR2_DATA     0x42
+#define TSDEV_CTRL_PORTB    0x61
 #define TSDEV_TMR0_DATA     0x40
+#define TSDEV_TMR1_DATA     0x41
+#define TSDEV_TMR2_DATA     0x42
+#define TSDEV_TMR_CTRL      0x43
+#define TSDEV_KBD           0x64
+#define TSDEV_DMA1_CMND     0x08
+#define TSDEV_DMA1_STAT     TSDEV_DMA1_CMND
+#define TSDEV_DMA2_CMND     0xD0
+#define TSDEV_DMA2_STAT     TSDEV_DMA2_CMND
+#define TSDEV_DMA1_MMASK    0x0F
+#define TSDEV_DMA2_MMASK    0xDE
 
 #define TSDEV_RTC_ADDR      0x70
 #define TSDEV_RTC_DATA      0x71
 
 #define UART_MCR_LOOP   0x10
 
+// System Control PortB Status Bits
+#define PORTB_SPKR_HIGH 0x20
+
 #endif // __TSUNAMIREG_H__
index 99e3bd01711507fa268b8084570b10f89205389a..bbde147692e858500eceb01af9635c1fa7ae1964 100644 (file)
@@ -146,10 +146,14 @@ Uart8250::read(MemReqPtr &req, uint8_t *data)
             break;
         case 0x2: // Intr Identification Register (IIR)
             DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
-            if (status)
-                *(uint8_t*)data = 0;
+
+            //Tx interrupts are cleared on IIR reads
+            status &= ~TX_INT;
+
+            if (status & RX_INT)
+                *(uint8_t*)data = IIR_RXID;
             else
-                *(uint8_t*)data = 1;
+                *(uint8_t*)data = IIR_NOPEND;
             break;
         case 0x3: // Line Control Register (LCR)
             *(uint8_t*)data = LCR;
index 06a798e26f744849515e4a3b560871b9e3522fc3..b4c660021b430277b3be903b5b2a1f5a5bdec75e 100644 (file)
 #include "dev/io_device.hh"
 #include "dev/uart.hh"
 
+
+/* UART8250 Interrupt ID Register
+ *  bit 0    Interrupt Pending 0 = true, 1 = false
+ *  bit 2:1  ID of highest priority interrupt
+ *  bit 7:3  zeroes
+ */
+#define IIR_NOPEND 0x1
+
+// Interrupt IDs
+#define IIR_MODEM 0x00 /* Modem Status (lowest priority) */
+#define IIR_TXID  0x02 /* Tx Data */
+#define IIR_RXID  0x04 /* Rx Data */
+#define IIR_LINE  0x06 /* Rx Line Status (highest priority)*/
+
 class SimConsole;
 class Platform;
 
index 21450e40055e6cb868fa4011de5c0af0c51ad5a6..fd444341ad314dbb5783eaacbea7277a7d099878 100644 (file)
@@ -96,7 +96,7 @@ LinuxSystem::LinuxSystem(Params *p)
         char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
 
         if (dp264_mv) {
-            *(uint32_t*)(dp264_mv+0x18) = htoa((uint32_t)127);
+            *(uint32_t*)(dp264_mv+0x18) = htog((uint32_t)127);
         } else
             panic("could not translate dp264_mv addr\n");
 
index 0957e288346da12fc22bab07b51493fa408026ac..defdd10a3c1055196e55ba8f24cf3519c97daf2f 100644 (file)
@@ -50,3 +50,6 @@ class PciDevice(DmaDevice):
     pci_func = Param.Int("PCI function code")
     configdata = Param.PciConfigData(Parent.any, "PCI Config data")
     configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
+
+class PciFake(PciDevice):
+    type = 'PciFake'
index c8fd94e2cfd1b9e8414a9b213753842cd436978c..5425f421fdcdf743882666695905ebf15cf19c5b 100644 (file)
@@ -11,8 +11,9 @@ class TsunamiCChip(FooPioDevice):
     type = 'TsunamiCChip'
     tsunami = Param.Tsunami(Parent.any, "Tsunami")
 
-class TsunamiFake(FooPioDevice):
-    type = 'TsunamiFake'
+class IsaFake(FooPioDevice):
+    type = 'IsaFake'
+    size = Param.Addr("Size of address range")
 
 class TsunamiIO(FooPioDevice):
     type = 'TsunamiIO'
index 47ffc4b016552e8668135e5c8bdfb18b3a31ffd5..3da92c44734d4463f922be9b7ff49e20a2533de1 100644 (file)
@@ -154,8 +154,8 @@ System::System(Params *p)
         if (!hwrpb)
             panic("could not translate hwrpb addr\n");
 
-        *(uint64_t*)(hwrpb+0x50) = htoa(params->system_type);
-        *(uint64_t*)(hwrpb+0x58) = htoa(params->system_rev);
+        *(uint64_t*)(hwrpb+0x50) = htog(params->system_type);
+        *(uint64_t*)(hwrpb+0x58) = htog(params->system_rev);
     } else
         panic("could not find hwrpb\n");
 
@@ -192,7 +192,7 @@ System::setAlphaAccess(Addr access)
         if (!m5AlphaAccess)
             panic("could not translate m5AlphaAccess addr\n");
 
-        *m5AlphaAccess = htoa(EV5::Phys2K0Seg(access));
+        *m5AlphaAccess = htog(EV5::Phys2K0Seg(access));
     } else
         panic("could not find m5AlphaAccess\n");
 }