device.hh revision 1992
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 29/* @file 30 * Interface for devices using PCI configuration 31 */ 32 33#ifndef __DEV_PCIDEV_HH__ 34#define __DEV_PCIDEV_HH__ 35 36#include "dev/io_device.hh" 37#include "dev/pcireg.h" 38#include "dev/platform.hh" 39 40#define BAR_IO_MASK 0x3 41#define BAR_MEM_MASK 0xF 42#define BAR_IO_SPACE_BIT 0x1 43#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) 44#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); 45 46class PciConfigAll; 47class MemoryController; 48 49 50/** 51 * This class encapulates the first 64 bytes of a singles PCI 52 * devices config space that in configured by the configuration file. 53 */ 54class PciConfigData : public SimObject 55{ 56 public: 57 /** 58 * Constructor to initialize the devices config space to 0. 59 */ 60 PciConfigData(const std::string &name) 61 : SimObject(name) 62 { 63 memset(config.data, 0, sizeof(config.data)); 64 memset(BARAddrs, 0, sizeof(BARAddrs)); 65 memset(BARSize, 0, sizeof(BARSize)); 66 } 67 68 /** The first 64 bytes */ 69 PCIConfig config; 70 71 /** The size of the BARs */ 72 uint32_t BARSize[6]; 73 74 /** The addresses of the BARs */ 75 Addr BARAddrs[6]; 76}; 77 78/** 79 * PCI device, base implemnation is only config space. 80 * Each device is connected to a PCIConfigSpace device 81 * which returns -1 for everything but the pcidevs that 82 * register with it. This object registers with the PCIConfig space 83 * object. 84 */ 85class PciDev : public DmaDevice 86{ 87 public: 88 struct Params 89 { 90 std::string name; 91 Platform *plat; 92 MemoryController *mmu; 93 94 /** 95 * A pointer to the configspace all object that calls us when 96 * a read comes to this particular device/function. 97 */ 98 PciConfigAll *configSpace; 99 100 /** 101 * A pointer to the object that contains the first 64 bytes of 102 * config space 103 */ 104 PciConfigData *configData; 105 106 /** The bus number we are on */ 107 uint32_t busNum; 108 109 /** The device number we have */ 110 uint32_t deviceNum; 111 112 /** The function number */ 113 uint32_t functionNum; 114 }; 115 116 protected: 117 Params *_params; 118 119 public: 120 const Params *params() const { return _params; } 121 122 protected: 123 /** The current config space. Unlike the PciConfigData this is 124 * updated during simulation while continues to reflect what was 125 * in the config file. 126 */ 127 PCIConfig config; 128 129 /** The size of the BARs */ 130 uint32_t BARSize[6]; 131 132 /** The current address mapping of the BARs */ 133 Addr BARAddrs[6]; 134 135 bool 136 isBAR(Addr addr, int bar) const 137 { 138 assert(bar >= 0 && bar < 6); 139 return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 140 } 141 142 int 143 getBAR(Addr addr) 144 { 145 for (int i = 0; i <= 5; ++i) 146 if (isBAR(addr, i)) 147 return i; 148 149 return -1; 150 } 151 152 bool 153 getBAR(Addr paddr, Addr &daddr, int &bar) 154 { 155 int b = getBAR(paddr); 156 if (b < 0) 157 return false; 158 159 daddr = paddr - BARAddrs[b]; 160 bar = b; 161 return true; 162 } 163 164 protected: 165 Platform *plat; 166 PciConfigData *configData; 167 168 public: 169 Addr pciToDma(Addr pciAddr) const 170 { return plat->pciToDma(pciAddr); } 171 172 void 173 intrPost() 174 { plat->postPciInt(configData->config.interruptLine); } 175 176 void 177 intrClear() 178 { plat->clearPciInt(configData->config.interruptLine); } 179 180 uint8_t 181 interruptLine() 182 { return configData->config.interruptLine; } 183 184 public: 185 /** 186 * Constructor for PCI Dev. This function copies data from the 187 * config file object PCIConfigData and registers the device with 188 * a PciConfigAll object. 189 */ 190 PciDev(Params *params); 191 192 virtual Fault read(MemReqPtr &req, uint8_t *data); 193 virtual Fault write(MemReqPtr &req, const uint8_t *data); 194 195 public: 196 /** 197 * Implement the read/write as BAR accesses 198 */ 199 Fault readBar(MemReqPtr &req, uint8_t *data); 200 Fault writeBar(MemReqPtr &req, const uint8_t *data); 201 202 public: 203 /** 204 * Read from a specific BAR 205 */ 206 virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data); 207 virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data); 208 virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data); 209 virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data); 210 virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data); 211 virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data); 212 213 public: 214 /** 215 * Write to a specific BAR 216 */ 217 virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data); 218 virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data); 219 virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data); 220 virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data); 221 virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data); 222 virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data); 223 224 public: 225 /** 226 * Write to the PCI config space data that is stored locally. This may be 227 * overridden by the device but at some point it will eventually call this 228 * for normal operations that it does not need to override. 229 * @param offset the offset into config space 230 * @param size the size of the write 231 * @param data the data to write 232 */ 233 virtual void writeConfig(int offset, int size, const uint8_t* data); 234 235 236 /** 237 * Read from the PCI config space data that is stored locally. This may be 238 * overridden by the device but at some point it will eventually call this 239 * for normal operations that it does not need to override. 240 * @param offset the offset into config space 241 * @param size the size of the read 242 * @param data pointer to the location where the read value should be stored 243 */ 244 virtual void readConfig(int offset, int size, uint8_t *data); 245 246 /** 247 * Serialize this object to the given output stream. 248 * @param os The stream to serialize to. 249 */ 250 virtual void serialize(std::ostream &os); 251 252 /** 253 * Reconstruct the state of this object from a checkpoint. 254 * @param cp The checkpoint use. 255 * @param section The section name of this object 256 */ 257 virtual void unserialize(Checkpoint *cp, const std::string §ion); 258}; 259 260inline Fault 261PciDev::readBar(MemReqPtr &req, uint8_t *data) 262{ 263 if (isBAR(req->paddr, 0)) 264 return readBar0(req, req->paddr - BARAddrs[0], data); 265 if (isBAR(req->paddr, 1)) 266 return readBar1(req, req->paddr - BARAddrs[1], data); 267 if (isBAR(req->paddr, 2)) 268 return readBar2(req, req->paddr - BARAddrs[2], data); 269 if (isBAR(req->paddr, 3)) 270 return readBar3(req, req->paddr - BARAddrs[3], data); 271 if (isBAR(req->paddr, 4)) 272 return readBar4(req, req->paddr - BARAddrs[4], data); 273 if (isBAR(req->paddr, 5)) 274 return readBar5(req, req->paddr - BARAddrs[5], data); 275 return Machine_Check_Fault; 276} 277 278inline Fault 279PciDev::writeBar(MemReqPtr &req, const uint8_t *data) 280{ 281 if (isBAR(req->paddr, 0)) 282 return writeBar0(req, req->paddr - BARAddrs[0], data); 283 if (isBAR(req->paddr, 1)) 284 return writeBar1(req, req->paddr - BARAddrs[1], data); 285 if (isBAR(req->paddr, 2)) 286 return writeBar2(req, req->paddr - BARAddrs[2], data); 287 if (isBAR(req->paddr, 3)) 288 return writeBar3(req, req->paddr - BARAddrs[3], data); 289 if (isBAR(req->paddr, 4)) 290 return writeBar4(req, req->paddr - BARAddrs[4], data); 291 if (isBAR(req->paddr, 5)) 292 return writeBar5(req, req->paddr - BARAddrs[5], data); 293 return Machine_Check_Fault; 294} 295 296#endif // __DEV_PCIDEV_HH__ 297