diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 85380c75c..1b19ec368 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -1,4 +1,30 @@ -/* $Id$ */ +/* + * Copyright (c) 2003 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 * PCI Configspace implementation @@ -25,7 +51,7 @@ PCIConfigAll::PCIConfigAll(const string &name, Tsunami *t, Addr addr, Addr mask, MemoryController *mmu) : MmapDevice(name, addr, mask, mmu), tsunami(t) { - //Put back pointer in tsunami + // Put back pointer in tsunami tsunami->pciconfig = this; // Make all the pointers to devices null @@ -75,7 +101,8 @@ PCIConfigAll::read(MemReqPtr &req, uint8_t *data) } } - DPRINTFN("Tsunami PCI Configspace ERROR: read daddr=%#x size=%d\n", daddr, req->size); + DPRINTFN("Tsunami PCI Configspace ERROR: read daddr=%#x size=%d\n", + daddr, req->size); return No_Fault; } @@ -83,7 +110,6 @@ PCIConfigAll::read(MemReqPtr &req, uint8_t *data) Fault PCIConfigAll::write(MemReqPtr &req, const uint8_t *data) { - Addr daddr = (req->paddr & addr_mask); int device = (daddr >> 11) & 0x1F; @@ -96,7 +122,6 @@ PCIConfigAll::write(MemReqPtr &req, const uint8_t *data) uint32_t word_value; }; - if (devices[device][func] == NULL) panic("Attempting to write to config space on non-existant device\n"); else { @@ -114,15 +139,15 @@ PCIConfigAll::write(MemReqPtr &req, const uint8_t *data) panic("invalid access size(?) for PCI configspace!\n"); } } + DPRINTF(PCIConfigAll, "write - va=%#x size=%d data=%#x\n", req->vaddr, req->size, word_value); - devices[device][func]->WriteConfig(reg, req->size, word_value); + devices[device][func]->WriteConfig(reg, req->size, word_value); return No_Fault; } - void PCIConfigAll::serialize(std::ostream &os) { @@ -135,6 +160,8 @@ PCIConfigAll::unserialize(Checkpoint *cp, const std::string §ion) //code should be written } +#ifndef DOXYGEN_SHOULD_SKIP_THIS + BEGIN_DECLARE_SIM_OBJECT_PARAMS(PCIConfigAll) SimObjectParam tsunami; @@ -159,3 +186,5 @@ CREATE_SIM_OBJECT(PCIConfigAll) } REGISTER_SIM_OBJECT("PCIConfigAll", PCIConfigAll) + +#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh index e84c6adb3..070643fd9 100644 --- a/dev/pciconfigall.hh +++ b/dev/pciconfigall.hh @@ -26,7 +26,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* @file +/* + * @todo + * Should derive Tsunami from common platform class so PCI will work with + * multiple platforms + * + * @file * PCI Config space implementation. */ @@ -58,6 +63,7 @@ class PCIConfigAll : public MmapDevice /** * Pointer to the Tsunmi Object so we can communicate * to other Tsunami devices in need be. + * @todo Make this more generic for multiple platforms */ Tsunami *tsunami; diff --git a/dev/pcidev.cc b/dev/pcidev.cc index fcd011123..13663b32c 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -50,47 +50,57 @@ using namespace std; -PciDev::PciDev(const string &name, PCIConfigAll *cf, uint32_t bus, - uint32_t dev, uint32_t func) - : MMapDevice(name), ConfigSpace(cf), Bus(bus), Device(dev), Function(func), MMU(mmu) +PciDev::PciDev(const string &name, MemoryController *mmu, PCIConfigAll *cf, + PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func) + : MmapDevice(name), MMU(mmu), ConfigSpace(cf), ConfigData(cd), + Bus(bus), Device(dev), Function(func) { - memset(config.data, 0, sizeof(config.data)); - memset(BARAddrs, 0, sizeof(Addr) * 6); + // copy the config data from the PciConfigData object + if (cd) { + memcpy(config.data, cd->config.data, sizeof(config.data)); + memcpy(BARSize, cd->BARSize, sizeof(BARSize)); + memcpy(BARAddrs, cd->BARAddrs, sizeof(BARAddrs)); + } else + panic("NULL pointer to configuration data"); // Setup pointer in config space to point to this entry - if(cf->devices[dev][func] != NULL) + if (cf->devices[dev][func] != NULL) panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func); else cf->devices[dev][func] = this; } - void PciDev::ReadConfig(int offset, int size, uint8_t *data) { switch(size) { - case sizeof(uint32_t): - memcpy((uint32_t*)data, config.data + offset, sizeof(uint32_t)); - DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x data: %#x\n", + case sizeof(uint32_t): + memcpy((uint32_t*)data, config.data + offset, sizeof(uint32_t)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", Device, Function, offset, *(uint32_t*)(config.data + offset)); - break; - case sizeof(uint16_t): - memcpy((uint16_t*)data, config.data + offset, sizeof(uint16_t)); - DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x data: %#x\n", + break; + + case sizeof(uint16_t): + memcpy((uint16_t*)data, config.data + offset, sizeof(uint16_t)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", Device, Function, offset, *(uint16_t*)(config.data + offset)); - break; - case sizeof(uint8_t): - memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t)); - printf("data: %#x\n", *(uint8_t*)(config.data + offset)); - DPRINTF(PCIDEV, "read device: %#x function: %#x register: %#x data: %#x\n", + break; + + case sizeof(uint8_t): + memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t)); + printf("data: %#x\n", *(uint8_t*)(config.data + offset)); + DPRINTF(PCIDEV, + "read device: %#x function: %#x register: %#x data: %#x\n", Device, Function, offset, *(uint8_t*)(config.data + offset)); - break; - default: - panic("Invalid Read Size"); + break; + + default: + panic("Invalid Read Size"); } } - void PciDev::WriteConfig(int offset, int size, uint32_t data) { @@ -103,8 +113,9 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) }; word_value = data; - DPRINTF(PCIDEV, "write device: %#x function: %#x register: %#x size: %#x data: %#x\n", - Device, Function, offset, size, word_value); + DPRINTF(PCIDEV, + "write device: %#x function: %#x reg: %#x size: %#x data: %#x\n", + Device, Function, offset, size, word_value); barnum = (offset - PCI0_BASE_ADDR0) >> 2; @@ -145,63 +156,63 @@ PciDev::WriteConfig(int offset, int size, uint32_t data) case PCI0_BASE_ADDR3: case PCI0_BASE_ADDR4: case PCI0_BASE_ADDR5: - // 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) { - // This is I/O Space, bottom two bits are read only - if(config.data[offset] & 0x1) { + // 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) { + // This is I/O Space, bottom two bits are read only + if (config.data[offset] & 0x1) { *(uint32_t *)&config.data[offset] = ~(BARSize[barnum] - 1) | (config.data[offset] & 0x3); - } else { - // This is memory space, bottom four bits are read only + } else { + // This is memory space, bottom four bits are read only *(uint32_t *)&config.data[offset] = ~(BARSize[barnum] - 1) | (config.data[offset] & 0xF); - } - - - } else { - // This is I/O Space, bottom two bits are read only - if(config.data[offset] & 0x1) { + } + } else { + // This is I/O Space, bottom two bits are read only + if(config.data[offset] & 0x1) { *(uint32_t *)&config.data[offset] = (word_value & ~0x3) | - (config.data[offset] & 0x3); + (config.data[offset] & 0x3); if (word_value) { // It's never been set - if (BARAddr[barnum] == 0) + if (BARAddrs[barnum] == 0) AddMapping(word_value, BARSize[barnum]-1, MMU); else - UpdateMapping(BARAddr[barnum], BARSize[barnum]-1, + ChangeMapping(BARAddrs[barnum], BARSize[barnum]-1, word_value, BARSize[barnum]-1, MMU); - BARAddr[barnum] = word_value; + BARAddrs[barnum] = word_value; } - } else { - // This is memory space, bottom four bits are read only + } else { + // This is memory space, bottom four bits are read only *(uint32_t *)&config.data[offset] = (word_value & ~0xF) | - (config.data[offset] & 0xF); - } - } + (config.data[offset] & 0xF); + } + } break; - case PCI0_ROM_BASE_ADDR: - if (word_value == 0xfffffffe) - *(uint32_t *)&config.data[offset] = 0xffffffff; - else - *(uint32_t *)&config.data[offset] = word_value; - 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] = half_value; - break; + case PCI0_ROM_BASE_ADDR: + if (word_value == 0xfffffffe) + *(uint32_t *)&config.data[offset] = 0xffffffff; + else + *(uint32_t *)&config.data[offset] = word_value; + 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] = half_value; + break; default: panic("writing to a read only register"); } break; } - } void @@ -216,8 +227,9 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(config.data, 64); } +#ifndef DOXYGEN_SHOULD_SKIP_THIS -BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciDev) +BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) Param VendorID; Param DeviceID; @@ -252,18 +264,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciDev) Param BAR4Size; Param BAR5Size; - SimObjectParam mmu; - SimObjectParam cf; - Param addr; - Param mask; - Param bus; - Param device; - Param func; +END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) - -END_DECLARE_SIM_OBJECT_PARAMS(PciDev) - -BEGIN_INIT_SIM_OBJECT_PARAMS(PciDev) +BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData) INIT_PARAM(VendorID, "Vendor ID"), INIT_PARAM(DeviceID, "Device ID"), @@ -296,56 +299,52 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(PciDev) INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00), INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00), INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00), - INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00), + INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00) - INIT_PARAM(cf, "Pointer to Configspace device"), - INIT_PARAM(bus, "PCI Bus Number"), - INIT_PARAM(device, "PCI Device number"), - INIT_PARAM(func, "PCI Function Number") +END_INIT_SIM_OBJECT_PARAMS(PciConfigData) - -END_INIT_SIM_OBJECT_PARAMS(PciDev) - -CREATE_SIM_OBJECT(PciDev) +CREATE_SIM_OBJECT(PciConfigData) { - PciDev *dev = new PciDev(getInstanceName(), cf, bus, device, func); + PciConfigData *data = new PciConfigData(getInstanceName()); - dev->config.hdr.vendor = VendorID; - dev->config.hdr.device = DeviceID; - dev->config.hdr.command = Command; - dev->config.hdr.status = Status; - dev->config.hdr.revision = Revision; - dev->config.hdr.progIF = ProgIF; - dev->config.hdr.subClassCode = SubClassCode; - dev->config.hdr.classCode = ClassCode; - dev->config.hdr.cacheLineSize = CacheLineSize; - dev->config.hdr.latencyTimer = LatencyTimer; - dev->config.hdr.headerType = HeaderType; - dev->config.hdr.bist = BIST; + data->config.hdr.vendor = VendorID; + data->config.hdr.device = DeviceID; + data->config.hdr.command = Command; + data->config.hdr.status = Status; + data->config.hdr.revision = Revision; + data->config.hdr.progIF = ProgIF; + data->config.hdr.subClassCode = SubClassCode; + data->config.hdr.classCode = ClassCode; + data->config.hdr.cacheLineSize = CacheLineSize; + data->config.hdr.latencyTimer = LatencyTimer; + data->config.hdr.headerType = HeaderType; + data->config.hdr.bist = BIST; - dev->config.hdr.pci0.baseAddr0 = BAR0; - dev->config.hdr.pci0.baseAddr1 = BAR1; - dev->config.hdr.pci0.baseAddr2 = BAR2; - dev->config.hdr.pci0.baseAddr3 = BAR3; - dev->config.hdr.pci0.baseAddr4 = BAR4; - dev->config.hdr.pci0.baseAddr5 = BAR5; - dev->config.hdr.pci0.cardbusCIS = CardbusCIS; - dev->config.hdr.pci0.subsystemVendorID = SubsystemVendorID; - dev->config.hdr.pci0.subsystemID = SubsystemVendorID; - dev->config.hdr.pci0.expansionROM = ExpansionROM; - dev->config.hdr.pci0.interruptLine = InterruptLine; - dev->config.hdr.pci0.interruptPin = InterruptPin; - dev->config.hdr.pci0.minimumGrant = MinimumGrant; - dev->config.hdr.pci0.maximumLatency = MaximumLatency; + data->config.hdr.pci0.baseAddr0 = BAR0; + data->config.hdr.pci0.baseAddr1 = BAR1; + data->config.hdr.pci0.baseAddr2 = BAR2; + data->config.hdr.pci0.baseAddr3 = BAR3; + data->config.hdr.pci0.baseAddr4 = BAR4; + data->config.hdr.pci0.baseAddr5 = BAR5; + data->config.hdr.pci0.cardbusCIS = CardbusCIS; + data->config.hdr.pci0.subsystemVendorID = SubsystemVendorID; + data->config.hdr.pci0.subsystemID = SubsystemVendorID; + data->config.hdr.pci0.expansionROM = ExpansionROM; + data->config.hdr.pci0.interruptLine = InterruptLine; + data->config.hdr.pci0.interruptPin = InterruptPin; + data->config.hdr.pci0.minimumGrant = MinimumGrant; + data->config.hdr.pci0.maximumLatency = MaximumLatency; - dev->BARSize[0] = BAR0Size; - dev->BARSize[1] = BAR1Size; - dev->BARSize[2] = BAR2Size; - dev->BARSize[3] = BAR3Size; - dev->BARSize[4] = BAR4Size; - dev->BARSize[5] = BAR5Size; + data->BARSize[0] = BAR0Size; + data->BARSize[1] = BAR1Size; + data->BARSize[2] = BAR2Size; + data->BARSize[3] = BAR3Size; + data->BARSize[4] = BAR4Size; + data->BARSize[5] = BAR5Size; - return dev; + return data; } -REGISTER_SIM_OBJECT("PciDev", PciDev) +REGISTER_SIM_OBJECT("PciConfigData", PciConfigData) + +#endif // DOXYGEN_SHOULD_SKIP_THIS diff --git a/dev/pcidev.hh b/dev/pcidev.hh index ae8368b71..8cb68945a 100644 --- a/dev/pcidev.hh +++ b/dev/pcidev.hh @@ -33,10 +33,28 @@ #ifndef __PCI_DEV_HH__ #define __PCI_DEV_HH__ -#include "mem/functional_mem/mmap_device.hh" #include "dev/pcireg.h" +#include "sim/sim_object.hh" +#include "mem/functional_mem/mmap_device.hh" class PCIConfigAll; +class MemoryController; + +class PciConfigData : public SimObject +{ + public: + PciConfigData(const std::string &name) + : SimObject(name) + { + memset(config.data, 0, sizeof(config.data)); + memset(BARAddrs, 0, sizeof(BARAddrs)); + memset(BARSize, 0, sizeof(BARSize)); + } + + PCIConfig config; + uint32_t BARSize[6]; + Addr BARAddrs[6]; +}; /** * PCI device, base implemnation is only config space. @@ -47,23 +65,32 @@ class PCIConfigAll; */ class PciDev : public MmapDevice { - private: + protected: + MemoryController *MMU; + PCIConfigAll *ConfigSpace; + PciConfigData *ConfigData; uint32_t Bus; uint32_t Device; uint32_t Function; - public: - PciDev(const std::string &name, PCIConfigAll *cf, uint32_t bus, - uint32_t dev, uint32_t func); - PCIConfigAll *ConfigSpace; PCIConfig config; uint32_t BARSize[6]; Addr BARAddrs[6]; + public: + PciDev(const std::string &name, MemoryController *mmu, PCIConfigAll *cf, + PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func); + + virtual Fault read(MemReqPtr &req, uint8_t *data) { + return No_Fault; + } + virtual Fault write(MemReqPtr &req, const uint8_t *data) { + return No_Fault; + } + virtual void WriteConfig(int offset, int size, uint32_t data); virtual void ReadConfig(int offset, int size, uint8_t *data); - virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); }; diff --git a/dev/tsunami.cc b/dev/tsunami.cc index c6823ffa4..5fe1d0f23 100644 --- a/dev/tsunami.cc +++ b/dev/tsunami.cc @@ -43,9 +43,9 @@ using namespace std; -Tsunami::Tsunami(const string &name, AdaptecController *s, EtherDev *e, - SimConsole *con, IntrControl *ic, int intr_freq) - : SimObject(name), intrctrl(ic), cons(con), scsi(s), ethernet(e), +Tsunami::Tsunami(const string &name, EtherDev *e, SimConsole *con, + IntrControl *ic, int intr_freq) + : SimObject(name), intrctrl(ic), cons(con), ethernet(e), interrupt_frequency(intr_freq) { for (int i = 0; i < Tsunami::Max_CPUs; i++) @@ -66,7 +66,6 @@ Tsunami::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami) - SimObjectParam scsi; SimObjectParam ethernet; SimObjectParam cons; SimObjectParam intrctrl; @@ -76,7 +75,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tsunami) BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami) - INIT_PARAM(scsi, "scsi controller"), INIT_PARAM(ethernet, "ethernet controller"), INIT_PARAM(cons, "system console"), INIT_PARAM(intrctrl, "interrupt controller"), @@ -84,12 +82,10 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami) END_INIT_SIM_OBJECT_PARAMS(Tsunami) - CREATE_SIM_OBJECT(Tsunami) { - return new Tsunami(getInstanceName(), scsi, ethernet, - cons, intrctrl, interrupt_frequency); + return new Tsunami(getInstanceName(), ethernet, cons, intrctrl, + interrupt_frequency); } REGISTER_SIM_OBJECT("Tsunami", Tsunami) - diff --git a/dev/tsunami.hh b/dev/tsunami.hh index f45bb2059..f10a18fea 100644 --- a/dev/tsunami.hh +++ b/dev/tsunami.hh @@ -45,7 +45,7 @@ class TlaserClock; class EtherDev; class TsunamiCChip; class TsunamiPChip; -class TsunamiPCIConfig; +class PCIConfigAll; /** * Top level class for Tsunami Chipset emulation. @@ -83,11 +83,11 @@ class Tsunami : public SimObject */ TsunamiPChip *pchip; - /** Pointer to the Tsunami PCI Config Space - * The config space in tsunami all needs to return + /** Pointer to the PCI Config Space + * The config space in Tsunami all needs to return * -1 if a device is not there. */ - TsunamiPCIConfig *pciconfig; + PCIConfigAll *pciconfig; int intr_sum_type[Tsunami::Max_CPUs]; int ipi_pending[Tsunami::Max_CPUs]; @@ -99,9 +99,8 @@ class Tsunami : public SimObject * Constructor for the Tsunami Class. * @param */ - Tsunami(const std::string &name, AdaptecController *scsi, - EtherDev *ethernet, - SimConsole *, IntrControl *intctrl, int intrFreq); + Tsunami(const std::string &name, EtherDev *ethernet, SimConsole *con, + IntrControl *intctrl, int intrFreq); virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion);