diff options
Diffstat (limited to 'src/dev')
-rw-r--r-- | src/dev/ide_disk.hh | 2 | ||||
-rw-r--r-- | src/dev/io_device.cc | 25 | ||||
-rw-r--r-- | src/dev/io_device.hh | 49 | ||||
-rw-r--r-- | src/dev/pcidev.cc | 134 | ||||
-rw-r--r-- | src/dev/pcidev.hh | 46 | ||||
-rw-r--r-- | src/dev/pcireg.h | 13 |
6 files changed, 102 insertions, 167 deletions
diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh index fb0614d4d..0bc0b73ab 100644 --- a/src/dev/ide_disk.hh +++ b/src/dev/ide_disk.hh @@ -43,6 +43,8 @@ #include "dev/io_device.hh" #include "sim/eventq.hh" +class ChunkGenerator; + #define DMA_BACKOFF_PERIOD 200 #define MAX_DMA_SIZE (131072) // 128K diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index b51a93190..408d8de3e 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -29,6 +29,7 @@ * Nathan Binkert */ +#include "base/chunk_generator.hh" #include "base/trace.hh" #include "dev/io_device.hh" #include "sim/builder.hh" @@ -36,20 +37,14 @@ PioPort::PioPort(PioDevice *dev, System *s, std::string pname) - : SimpleTimingPort(dev->name() + pname), device(dev), sys(s) + : SimpleTimingPort(dev->name() + pname), device(dev) { } Tick PioPort::recvAtomic(Packet *pkt) { - return device->recvAtomic(pkt); -} - -void -PioPort::recvFunctional(Packet *pkt) -{ - device->recvAtomic(pkt); + return pkt->isRead() ? device->read(pkt) : device->write(pkt); } void @@ -60,20 +55,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) } -bool -PioPort::recvTiming(Packet *pkt) -{ - if (pkt->result == Packet::Nacked) { - resendNacked(pkt); - } else { - Tick latency = device->recvAtomic(pkt); - // turn packet around to go back to requester - pkt->makeTimingResponse(); - sendTiming(pkt, latency); - } - return true; -} - PioDevice::~PioDevice() { if (pioPort) diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 710b22b2c..df4f494cb 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -32,13 +32,12 @@ #ifndef __DEV_IO_DEVICE_HH__ #define __DEV_IO_DEVICE_HH__ -#include "base/chunk_generator.hh" #include "mem/mem_object.hh" #include "mem/packet_impl.hh" -#include "sim/eventq.hh" #include "sim/sim_object.hh" #include "mem/tport.hh" +class Event; class Platform; class PioDevice; class DmaDevice; @@ -49,35 +48,22 @@ class System; * sensitive to an address range use. The port takes all the memory * access types and roles them into one read() and write() call that the device * must respond to. The device must also provide the addressRanges() function - * with which it returns the address ranges it is interested in. */ - + * with which it returns the address ranges it is interested in. + */ class PioPort : public SimpleTimingPort { protected: /** The device that this port serves. */ PioDevice *device; - /** The system that device/port are in. This is used to select which mode - * we are currently operating in. */ - System *sys; - - /** The current status of the peer(bus) that we are connected to. */ - Status peerStatus; - - virtual bool recvTiming(Packet *pkt); - virtual Tick recvAtomic(Packet *pkt); - virtual void recvFunctional(Packet *pkt) ; - - virtual void recvStatusChange(Status status) - { peerStatus = status; } - - virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop); public: - PioPort(PioDevice *dev, System *s, std::string pname = "-pioport"); + PioPort(PioDevice *dev, System *s, std::string pname = "-pioport"); }; @@ -132,7 +118,8 @@ class DmaPort : public Port virtual void recvRetry() ; - virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) { resp.clear(); snoop.clear(); } void sendDma(Packet *pkt, bool front = false); @@ -155,7 +142,6 @@ class DmaPort : public Port * mode we are in, etc is handled by the PioPort so the device doesn't have to * bother. */ - class PioDevice : public MemObject { protected: @@ -172,13 +158,8 @@ class PioDevice : public MemObject virtual void addressRanges(AddrRangeList &range_list) = 0; - /** As far as the devices are concerned they only accept atomic transactions - * which are converted to either a write or a read. */ - Tick recvAtomic(Packet *pkt) - { return pkt->isRead() ? this->read(pkt) : this->write(pkt); } - - /** Pure virtual function that the device must implement. Called when a read - * command is recieved by the port. + /** Pure virtual function that the device must implement. Called + * when a read command is recieved by the port. * @param pkt Packet describing this request * @return number of ticks it took to complete */ @@ -192,10 +173,9 @@ class PioDevice : public MemObject virtual Tick write(Packet *pkt) = 0; public: - /** Params struct which is extended through each device based on the - * parameters it needs. Since we are re-writing everything, we might as well - * start from the bottom this time. */ - + /** Params struct which is extended through each device based on + * the parameters it needs. Since we are re-writing everything, we + * might as well start from the bottom this time. */ struct Params { std::string name; @@ -255,7 +235,8 @@ class BasicPioDevice : public PioDevice public: BasicPioDevice(Params *p) - : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), pioDelay(p->pio_delay) + : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), + pioDelay(p->pio_delay) {} /** return the address ranges that this device responds to. diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index e81e0d1ee..8ea22cb24 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -39,6 +39,7 @@ #include <vector> #include "base/inifile.hh" +#include "base/intmath.hh" // for isPowerOf2( #include "base/misc.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" @@ -56,8 +57,8 @@ using namespace std; PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, int funcid, Platform *p) - : PioPort(dev,p->system,"-pciconf"), device(dev), platform(p), - busId(busid), deviceId(devid), functionId(funcid) + : SimpleTimingPort(dev->name() + "-pciconf"), device(dev), platform(p), + busId(busid), deviceId(devid), functionId(funcid) { configAddr = platform->calcConfigAddr(busId, deviceId, functionId); } @@ -67,45 +68,20 @@ Tick PciDev::PciConfigPort::recvAtomic(Packet *pkt) { assert(pkt->result == Packet::Unknown); - assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr + - PCI_CONFIG_SIZE); - return device->recvConfig(pkt); + assert(pkt->getAddr() >= configAddr && + pkt->getAddr() < configAddr + PCI_CONFIG_SIZE); + return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt); } void -PciDev::PciConfigPort::recvFunctional(Packet *pkt) -{ - assert(pkt->result == Packet::Unknown); - assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr + - PCI_CONFIG_SIZE); - device->recvConfig(pkt); -} - -void -PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) +PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) { snoop.clear(); resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1)); } -bool -PciDev::PciConfigPort::recvTiming(Packet *pkt) -{ - if (pkt->result == Packet::Nacked) { - resendNacked(pkt); - } else { - assert(pkt->result == Packet::Unknown); - assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr + - PCI_CONFIG_SIZE); - Tick latency = device->recvConfig(pkt); - // turn packet around to go back to requester - pkt->makeTimingResponse(); - sendTiming(pkt, latency); - } - return true; -} - PciDev::PciDev(Params *p) : DmaDevice(p), plat(p->platform), configData(p->configData), pioDelay(p->pio_delay), configDelay(p->config_delay), @@ -115,10 +91,11 @@ PciDev::PciDev(Params *p) if (configData) { memcpy(config.data, configData->config.data, sizeof(config.data)); memcpy(BARSize, configData->BARSize, sizeof(BARSize)); - memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs)); } else panic("NULL pointer to configuration data"); + memset(BARAddrs, 0, sizeof(BARAddrs)); + plat->registerPciDevice(0, p->deviceNum, p->functionNum, letoh(configData->config.interruptLine)); } @@ -157,21 +134,21 @@ PciDev::readConfig(Packet *pkt) case sizeof(uint8_t): pkt->set<uint8_t>(config.data[offset]); DPRINTF(PCIDEV, - "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n", + "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint8_t>()); break; case sizeof(uint16_t): pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]); DPRINTF(PCIDEV, - "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n", + "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint16_t>()); break; case sizeof(uint32_t): pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]); DPRINTF(PCIDEV, - "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n", + "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint32_t>()); break; @@ -221,7 +198,7 @@ PciDev::writeConfig(Packet *pkt) panic("writing to a read only register"); } DPRINTF(PCIDEV, - "write device: %#x function: %#x register: %#x 1 bytes: data: %#x\n", + "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint8_t>()); break; @@ -238,7 +215,7 @@ PciDev::writeConfig(Packet *pkt) panic("writing to a read only register"); } DPRINTF(PCIDEV, - "write device: %#x function: %#x register: %#x 2 bytes: data: %#x\n", + "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint16_t>()); break; @@ -250,40 +227,33 @@ PciDev::writeConfig(Packet *pkt) 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 (letoh(pkt->get<uint32_t>()) == 0xffffffff) { - // This is I/O Space, bottom two bits are read only - - config.baseAddr[barnum] = letoh( - (~(BARSize[barnum] - 1) & ~bar_mask) | - (letoh(config.baseAddr[barnum]) & bar_mask)); - } else { - config.baseAddr[barnum] = letoh( - (letoh(pkt->get<uint32_t>()) & ~bar_mask) | - (letoh(config.baseAddr[barnum]) & bar_mask)); - - if (letoh(config.baseAddr[barnum]) & ~bar_mask) { - base_addr = (letoh(pkt->get<uint32_t>()) & ~bar_mask) + space_base; - base_size = BARSize[barnum]; - BARAddrs[barnum] = base_addr; - - pioPort->sendStatusChange(Port::RangeChange); + { + int barnum = BAR_NUMBER(offset); + + // convert BAR values to host endianness + uint32_t he_old_bar = letoh(config.baseAddr[barnum]); + uint32_t he_new_bar = letoh(pkt->get<uint32_t>()); + + uint32_t bar_mask = + BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; + + // Writing 0xffffffff to a BAR tells the card to set the + // value of the bar to a bitmask indicating the size of + // memory it needs + if (he_new_bar == 0xffffffff) { + he_new_bar = ~(BARSize[barnum] - 1); + } else { + // does it mean something special to write 0 to a BAR? + he_new_bar &= ~bar_mask; + if (he_new_bar) { + Addr space_base = BAR_IO_SPACE(he_old_bar) ? + TSUNAMI_PCI0_IO : TSUNAMI_PCI0_MEMORY; + BARAddrs[barnum] = he_new_bar + space_base; + pioPort->sendStatusChange(Port::RangeChange); + } } + config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | + (he_old_bar & bar_mask)); } break; @@ -305,7 +275,7 @@ PciDev::writeConfig(Packet *pkt) DPRINTF(PCIDEV, "Writing to a read only register"); } DPRINTF(PCIDEV, - "write device: %#x function: %#x register: %#x 4 bytes: data: %#x\n", + "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", params()->deviceNum, params()->functionNum, offset, (uint32_t)pkt->get<uint32_t>()); break; @@ -427,12 +397,12 @@ CREATE_SIM_OBJECT(PciConfigData) 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.baseAddr[0] = htole(BAR0); + data->config.baseAddr[1] = htole(BAR1); + data->config.baseAddr[2] = htole(BAR2); + data->config.baseAddr[3] = htole(BAR3); + data->config.baseAddr[4] = htole(BAR4); + data->config.baseAddr[5] = htole(BAR5); data->config.cardbusCIS = htole(CardbusCIS); data->config.subsystemVendorID = htole(SubsystemVendorID); data->config.subsystemID = htole(SubsystemVendorID); @@ -449,6 +419,14 @@ CREATE_SIM_OBJECT(PciConfigData) data->BARSize[4] = BAR4Size; data->BARSize[5] = BAR5Size; + for (int i = 0; i < 6; ++i) { + uint32_t barsize = data->BARSize[i]; + if (barsize != 0 && !isPowerOf2(barsize)) { + fatal("%s: BAR %d size %d is not a power of 2\n", + getInstanceName(), i, data->BARSize[i]); + } + } + return data; } diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index 847fb07d0..22dd6296e 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -62,7 +62,6 @@ class PciConfigData : public SimObject : SimObject(name) { memset(config.data, 0, sizeof(config.data)); - memset(BARAddrs, 0, sizeof(BARAddrs)); memset(BARSize, 0, sizeof(BARSize)); } @@ -71,29 +70,23 @@ class PciConfigData : public SimObject /** The size of the BARs */ uint32_t BARSize[6]; - - /** The addresses of the BARs */ - Addr BARAddrs[6]; }; /** - * PCI device, base implemnation is only config space. + * PCI device, base implementation is only config space. */ class PciDev : public DmaDevice { - class PciConfigPort : public PioPort + class PciConfigPort : public SimpleTimingPort { protected: PciDev *device; - virtual bool recvTiming(Packet *pkt); - virtual Tick recvAtomic(Packet *pkt); - virtual void recvFunctional(Packet *pkt) ; - - virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop); Platform *platform; @@ -105,9 +98,7 @@ class PciDev : public DmaDevice public: PciConfigPort(PciDev *dev, int busid, int devid, int funcid, - Platform *p); - - friend class PioPort::SendEvent; + Platform *p); }; public: @@ -151,6 +142,10 @@ class PciDev : public DmaDevice /** The current address mapping of the BARs */ Addr BARAddrs[6]; + /** + * Does the given address lie within the space mapped by the given + * base address register? + */ bool isBAR(Addr addr, int bar) const { @@ -158,6 +153,10 @@ class PciDev : public DmaDevice return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; } + /** + * Which base address register (if any) maps the given address? + * @return The BAR number (0-5 inclusive), or -1 if none. + */ int getBAR(Addr addr) { @@ -168,14 +167,23 @@ class PciDev : public DmaDevice return -1; } + /** + * Which base address register (if any) maps the given address? + * @param addr The address to check. + * @retval bar The BAR number (0-5 inclusive), + * only valid if return value is true. + * @retval offs The offset from the base address, + * only valid if return value is true. + * @return True iff address maps to a base address register's region. + */ bool - getBAR(Addr paddr, Addr &daddr, int &bar) + getBAR(Addr addr, int &bar, Addr &offs) { - int b = getBAR(paddr); + int b = getBAR(addr); if (b < 0) return false; - daddr = paddr - BARAddrs[b]; + offs = addr - BARAddrs[b]; bar = b; return true; } @@ -225,10 +233,6 @@ class PciDev : public DmaDevice */ void addressRanges(AddrRangeList &range_list); - /** Do a PCI Configspace memory access. */ - Tick recvConfig(Packet *pkt) - { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); } - /** * Constructor for PCI Dev. This function copies data from the * config file object PCIConfigData and registers the device with diff --git a/src/dev/pcireg.h b/src/dev/pcireg.h index a48abd4fa..df57acdb0 100644 --- a/src/dev/pcireg.h +++ b/src/dev/pcireg.h @@ -54,18 +54,7 @@ union PCIConfig { uint8_t latencyTimer; uint8_t headerType; uint8_t bist; - union { - uint32_t baseAddr[6]; - - struct { - uint32_t baseAddr0; - uint32_t baseAddr1; - uint32_t baseAddr2; - uint32_t baseAddr3; - uint32_t baseAddr4; - uint32_t baseAddr5; - }; - }; + uint32_t baseAddr[6]; uint32_t cardbusCIS; uint16_t subsystemVendorID; uint16_t subsystemID; |