device.hh revision 3083
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 implementation 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, 97 AddrRangeList &snoop); 98 99 Platform *platform; 100 101 int busId; 102 int deviceId; 103 int functionId; 104 105 Addr configAddr; 106 107 public: 108 PciConfigPort(PciDev *dev, int busid, int devid, int funcid, 109 Platform *p); 110 111 friend class PioPort::SendEvent; 112 }; 113 114 public: 115 struct Params : public PioDevice::Params 116 { 117 /** 118 * A pointer to the object that contains the first 64 bytes of 119 * config space 120 */ 121 PciConfigData *configData; 122 123 /** The bus number we are on */ 124 uint32_t busNum; 125 126 /** The device number we have */ 127 uint32_t deviceNum; 128 129 /** The function number */ 130 uint32_t functionNum; 131 132 /** The latency for pio accesses. */ 133 Tick pio_delay; 134 135 /** The latency for a config access. */ 136 Tick config_delay; 137 }; 138 139 public: 140 const Params *params() const { return (const Params *)_params; } 141 142 protected: 143 /** The current config space. Unlike the PciConfigData this is 144 * updated during simulation while continues to reflect what was 145 * in the config file. 146 */ 147 PCIConfig config; 148 149 /** The size of the BARs */ 150 uint32_t BARSize[6]; 151 152 /** The current address mapping of the BARs */ 153 Addr BARAddrs[6]; 154 155 /** 156 * Does the given address lie within the space mapped by the given 157 * base address register? 158 */ 159 bool 160 isBAR(Addr addr, int bar) const 161 { 162 assert(bar >= 0 && bar < 6); 163 return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 164 } 165 166 /** 167 * Which base address register (if any) maps the given address? 168 * @return The BAR number (0-5 inclusive), or -1 if none. 169 */ 170 int 171 getBAR(Addr addr) 172 { 173 for (int i = 0; i <= 5; ++i) 174 if (isBAR(addr, i)) 175 return i; 176 177 return -1; 178 } 179 180 /** 181 * Which base address register (if any) maps the given address? 182 * @param addr The address to check. 183 * @retval bar The BAR number (0-5 inclusive), 184 * only valid if return value is true. 185 * @retval offs The offset from the base address, 186 * only valid if return value is true. 187 * @return True iff address maps to a base address register's region. 188 */ 189 bool 190 getBAR(Addr addr, int &bar, Addr &offs) 191 { 192 int b = getBAR(addr); 193 if (b < 0) 194 return false; 195 196 offs = addr - BARAddrs[b]; 197 bar = b; 198 return true; 199 } 200 201 protected: 202 Platform *plat; 203 PciConfigData *configData; 204 Tick pioDelay; 205 Tick configDelay; 206 PciConfigPort *configPort; 207 208 /** 209 * Write to the PCI config space data that is stored locally. This may be 210 * overridden by the device but at some point it will eventually call this 211 * for normal operations that it does not need to override. 212 * @param pkt packet containing the write the offset into config space 213 */ 214 virtual Tick writeConfig(Packet *pkt); 215 216 217 /** 218 * Read from the PCI config space data that is stored locally. This may be 219 * overridden by the device but at some point it will eventually call this 220 * for normal operations that it does not need to override. 221 * @param pkt packet containing the write the offset into config space 222 */ 223 virtual Tick readConfig(Packet *pkt); 224 225 public: 226 Addr pciToDma(Addr pciAddr) const 227 { return plat->pciToDma(pciAddr); } 228 229 void 230 intrPost() 231 { plat->postPciInt(letoh(configData->config.interruptLine)); } 232 233 void 234 intrClear() 235 { plat->clearPciInt(letoh(configData->config.interruptLine)); } 236 237 uint8_t 238 interruptLine() 239 { return letoh(configData->config.interruptLine); } 240 241 /** return the address ranges that this device responds to. 242 * @params range_list range list to populate with ranges 243 */ 244 void addressRanges(AddrRangeList &range_list); 245 246 /** Do a PCI Configspace memory access. */ 247 Tick recvConfig(Packet *pkt) 248 { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); } 249 250 /** 251 * Constructor for PCI Dev. This function copies data from the 252 * config file object PCIConfigData and registers the device with 253 * a PciConfigAll object. 254 */ 255 PciDev(Params *params); 256 257 virtual void init(); 258 259 /** 260 * Serialize this object to the given output stream. 261 * @param os The stream to serialize to. 262 */ 263 virtual void serialize(std::ostream &os); 264 265 /** 266 * Reconstruct the state of this object from a checkpoint. 267 * @param cp The checkpoint use. 268 * @param section The section name of this object 269 */ 270 virtual void unserialize(Checkpoint *cp, const std::string §ion); 271 272 273 virtual unsigned int drain(Event *de); 274 275 virtual Port *getPort(const std::string &if_name, int idx = -1) 276 { 277 if (if_name == "config") { 278 if (configPort != NULL) 279 panic("pciconfig port already connected to."); 280 configPort = new PciConfigPort(this, params()->busNum, 281 params()->deviceNum, params()->functionNum, 282 params()->platform); 283 return configPort; 284 } 285 return DmaDevice::getPort(if_name, idx); 286 } 287 288}; 289#endif // __DEV_PCIDEV_HH__ 290