device.hh revision 2846
1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Andrew Schultz 30 * Nathan Binkert 31 */ 32 33/* @file 34 * Interface for devices using PCI configuration 35 */ 36 37#ifndef __DEV_PCIDEV_HH__ 38#define __DEV_PCIDEV_HH__ 39 40#include "dev/io_device.hh" 41#include "dev/pcireg.h" 42#include "dev/platform.hh" 43 44#define BAR_IO_MASK 0x3 45#define BAR_MEM_MASK 0xF 46#define BAR_IO_SPACE_BIT 0x1 47#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) 48#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); 49 50 51/** 52 * This class encapulates the first 64 bytes of a singles PCI 53 * devices config space that in configured by the configuration file. 54 */ 55class PciConfigData : public SimObject 56{ 57 public: 58 /** 59 * Constructor to initialize the devices config space to 0. 60 */ 61 PciConfigData(const std::string &name) 62 : SimObject(name) 63 { 64 memset(config.data, 0, sizeof(config.data)); 65 memset(BARAddrs, 0, sizeof(BARAddrs)); 66 memset(BARSize, 0, sizeof(BARSize)); 67 } 68 69 /** The first 64 bytes */ 70 PCIConfig config; 71 72 /** The size of the BARs */ 73 uint32_t BARSize[6]; 74 75 /** The addresses of the BARs */ 76 Addr BARAddrs[6]; 77}; 78 79 80/** 81 * PCI device, base implemnation is only config space. 82 */ 83class PciDev : public DmaDevice 84{ 85 class PciConfigPort : public PioPort 86 { 87 protected: 88 PciDev *device; 89 90 virtual bool recvTiming(Packet *pkt); 91 92 virtual Tick recvAtomic(Packet *pkt); 93 94 virtual void recvFunctional(Packet *pkt) ; 95 96 virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); 97 98 int busId; 99 int deviceId; 100 int functionId; 101 102 Addr configAddr; 103 104 public: 105 PciConfigPort(PciDev *dev, int busid, int devid, int funcid, 106 Platform *p); 107 108 friend class PioPort::SendEvent; 109 }; 110 111 public: 112 struct Params : public PioDevice::Params 113 { 114 /** 115 * A pointer to the object that contains the first 64 bytes of 116 * config space 117 */ 118 PciConfigData *configData; 119 120 /** The bus number we are on */ 121 uint32_t busNum; 122 123 /** The device number we have */ 124 uint32_t deviceNum; 125 126 /** The function number */ 127 uint32_t functionNum; 128 129 /** The latency for pio accesses. */ 130 Tick pio_delay; 131 132 /** The latency for a config access. */ 133 Tick config_delay; 134 }; 135 136 public: 137 const Params *params() const { return (const Params *)_params; } 138 139 protected: 140 /** The current config space. Unlike the PciConfigData this is 141 * updated during simulation while continues to reflect what was 142 * in the config file. 143 */ 144 PCIConfig config; 145 146 /** The size of the BARs */ 147 uint32_t BARSize[6]; 148 149 /** The current address mapping of the BARs */ 150 Addr BARAddrs[6]; 151 152 bool 153 isBAR(Addr addr, int bar) const 154 { 155 assert(bar >= 0 && bar < 6); 156 return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 157 } 158 159 int 160 getBAR(Addr addr) 161 { 162 for (int i = 0; i <= 5; ++i) 163 if (isBAR(addr, i)) 164 return i; 165 166 return -1; 167 } 168 169 bool 170 getBAR(Addr paddr, Addr &daddr, int &bar) 171 { 172 int b = getBAR(paddr); 173 if (b < 0) 174 return false; 175 176 daddr = paddr - BARAddrs[b]; 177 bar = b; 178 return true; 179 } 180 181 protected: 182 Platform *plat; 183 PciConfigData *configData; 184 Tick pioDelay; 185 Tick configDelay; 186 PciConfigPort *configPort; 187 188 /** 189 * Write to the PCI config space data that is stored locally. This may be 190 * overridden by the device but at some point it will eventually call this 191 * for normal operations that it does not need to override. 192 * @param pkt packet containing the write the offset into config space 193 */ 194 virtual Tick writeConfig(Packet *pkt); 195 196 197 /** 198 * Read from the PCI config space data that is stored locally. This may be 199 * overridden by the device but at some point it will eventually call this 200 * for normal operations that it does not need to override. 201 * @param pkt packet containing the write the offset into config space 202 */ 203 virtual Tick readConfig(Packet *pkt); 204 205 public: 206 Addr pciToDma(Addr pciAddr) const 207 { return plat->pciToDma(pciAddr); } 208 209 void 210 intrPost() 211 { plat->postPciInt(letoh(configData->config.interruptLine)); } 212 213 void 214 intrClear() 215 { plat->clearPciInt(letoh(configData->config.interruptLine)); } 216 217 uint8_t 218 interruptLine() 219 { return letoh(configData->config.interruptLine); } 220 221 /** return the address ranges that this device responds to. 222 * @params range_list range list to populate with ranges 223 */ 224 void addressRanges(AddrRangeList &range_list); 225 226 /** Do a PCI Configspace memory access. */ 227 Tick recvConfig(Packet *pkt) 228 { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); } 229 230 /** 231 * Constructor for PCI Dev. This function copies data from the 232 * config file object PCIConfigData and registers the device with 233 * a PciConfigAll object. 234 */ 235 PciDev(Params *params); 236 237 virtual void init(); 238 239 /** 240 * Serialize this object to the given output stream. 241 * @param os The stream to serialize to. 242 */ 243 virtual void serialize(std::ostream &os); 244 245 /** 246 * Reconstruct the state of this object from a checkpoint. 247 * @param cp The checkpoint use. 248 * @param section The section name of this object 249 */ 250 virtual void unserialize(Checkpoint *cp, const std::string §ion); 251 252 virtual Port *getPort(const std::string &if_name, int idx = -1) 253 { 254 if (if_name == "config") { 255 if (configPort != NULL) 256 panic("pciconfig port already connected to."); 257 configPort = new PciConfigPort(this, params()->busNum, 258 params()->deviceNum, params()->functionNum, 259 params()->platform); 260 return configPort; 261 } 262 return DmaDevice::getPort(if_name, idx); 263 } 264 265}; 266#endif // __DEV_PCIDEV_HH__ 267