device.hh revision 3918
11689SN/A/* 22329SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 291689SN/A * Andrew Schultz 301689SN/A * Nathan Binkert 311060SN/A */ 321060SN/A 331858SN/A/* @file 341717SN/A * Interface for devices using PCI configuration 351060SN/A */ 362292SN/A 372292SN/A#ifndef __DEV_PCIDEV_HH__ 381061SN/A#define __DEV_PCIDEV_HH__ 392292SN/A 402292SN/A#include <cstring> 412292SN/A 422292SN/A#include "dev/io_device.hh" 432292SN/A#include "dev/pcireg.h" 442292SN/A#include "dev/platform.hh" 452292SN/A#include "sim/byteswap.hh" 461060SN/A 472292SN/A#define BAR_IO_MASK 0x3 482292SN/A#define BAR_MEM_MASK 0xF 492292SN/A#define BAR_IO_SPACE_BIT 0x1 502292SN/A#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) 512292SN/A#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); 522292SN/A 532292SN/A 542292SN/A/** 552292SN/A * This class encapulates the first 64 bytes of a singles PCI 562292SN/A * devices config space that in configured by the configuration file. 572292SN/A */ 582301SN/Aclass PciConfigData : public SimObject 592292SN/A{ 602292SN/A public: 612292SN/A /** 622292SN/A * Constructor to initialize the devices config space to 0. 632292SN/A */ 642292SN/A PciConfigData(const std::string &name) 652292SN/A : SimObject(name) 662292SN/A { 672292SN/A std::memset(config.data, 0, sizeof(config.data)); 682292SN/A std::memset(BARSize, 0, sizeof(BARSize)); 692292SN/A } 702292SN/A 712292SN/A /** The first 64 bytes */ 722292SN/A PCIConfig config; 732292SN/A 742292SN/A /** The size of the BARs */ 752292SN/A uint32_t BARSize[6]; 761060SN/A}; 771060SN/A 781061SN/A 791060SN/A/** 802292SN/A * PCI device, base implementation is only config space. 811062SN/A */ 821062SN/Aclass PciDev : public DmaDevice 832301SN/A{ 841062SN/A class PciConfigPort : public SimpleTimingPort 851062SN/A { 861062SN/A protected: 872301SN/A PciDev *device; 881062SN/A 891062SN/A virtual Tick recvAtomic(PacketPtr pkt); 901062SN/A 912301SN/A virtual void getDeviceAddressRanges(AddrRangeList &resp, 921062SN/A AddrRangeList &snoop); 931062SN/A 942301SN/A Platform *platform; 952301SN/A 962301SN/A int busId; 972301SN/A int deviceId; 982292SN/A int functionId; 992301SN/A 1002292SN/A Addr configAddr; 1012292SN/A 1021062SN/A public: 1032301SN/A PciConfigPort(PciDev *dev, int busid, int devid, int funcid, 1041062SN/A Platform *p); 1051062SN/A }; 1061062SN/A 1072301SN/A public: 1081062SN/A struct Params : public PioDevice::Params 1091062SN/A { 1101062SN/A /** 1112301SN/A * A pointer to the object that contains the first 64 bytes of 1121062SN/A * config space 1131062SN/A */ 1141062SN/A PciConfigData *configData; 1152301SN/A 1162292SN/A /** The bus number we are on */ 1171062SN/A uint32_t busNum; 1181062SN/A 1192301SN/A /** The device number we have */ 1202292SN/A uint32_t deviceNum; 1211062SN/A 1222292SN/A /** The function number */ 1232301SN/A uint32_t functionNum; 1242292SN/A 1252292SN/A /** The latency for pio accesses. */ 1261062SN/A Tick pio_delay; 1272301SN/A 1281062SN/A /** The latency for a config access. */ 1291062SN/A Tick config_delay; 1301062SN/A }; 1312301SN/A 1321062SN/A public: 1331062SN/A const Params *params() const { return (const Params *)_params; } 1341062SN/A 1352301SN/A protected: 1361062SN/A /** The current config space. Unlike the PciConfigData this is 1371062SN/A * updated during simulation while continues to reflect what was 1381062SN/A * in the config file. 1392301SN/A */ 1401062SN/A PCIConfig config; 1411062SN/A 1421062SN/A /** The size of the BARs */ 1432301SN/A uint32_t BARSize[6]; 1441062SN/A 1451062SN/A /** The current address mapping of the BARs */ 1462301SN/A Addr BARAddrs[6]; 1472301SN/A 1482301SN/A /** 1492301SN/A * Does the given address lie within the space mapped by the given 1502301SN/A * base address register? 1512301SN/A */ 1522301SN/A bool 1532301SN/A isBAR(Addr addr, int bar) const 1542301SN/A { 1552301SN/A assert(bar >= 0 && bar < 6); 1562307SN/A return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 1572307SN/A } 1582307SN/A 1592307SN/A /** 1602307SN/A * Which base address register (if any) maps the given address? 1611062SN/A * @return The BAR number (0-5 inclusive), or -1 if none. 1621062SN/A */ 1631062SN/A int 1641062SN/A getBAR(Addr addr) 1652733Sktlim@umich.edu { 1661060SN/A for (int i = 0; i <= 5; ++i) 1672292SN/A if (isBAR(addr, i)) 1681060SN/A return i; 1691060SN/A 1701060SN/A return -1; 1711061SN/A } 1721060SN/A 1732292SN/A /** 1741060SN/A * Which base address register (if any) maps the given address? 1752292SN/A * @param addr The address to check. 1761060SN/A * @retval bar The BAR number (0-5 inclusive), 1771060SN/A * only valid if return value is true. 1781060SN/A * @retval offs The offset from the base address, 1791060SN/A * only valid if return value is true. 1801060SN/A * @return True iff address maps to a base address register's region. 1811060SN/A */ 1821060SN/A bool 1831060SN/A getBAR(Addr addr, int &bar, Addr &offs) 1841060SN/A { 1851060SN/A int b = getBAR(addr); 1861060SN/A if (b < 0) 1871060SN/A return false; 1881061SN/A 1891060SN/A offs = addr - BARAddrs[b]; 1902292SN/A bar = b; 1911060SN/A return true; 1922292SN/A } 1931060SN/A 1941060SN/A protected: 1951060SN/A Platform *plat; 1961060SN/A PciConfigData *configData; 1971060SN/A Tick pioDelay; 1981060SN/A Tick configDelay; 1991061SN/A PciConfigPort *configPort; 2001060SN/A 2012292SN/A /** 2021060SN/A * Write to the PCI config space data that is stored locally. This may be 2032292SN/A * overridden by the device but at some point it will eventually call this 2041060SN/A * for normal operations that it does not need to override. 2051060SN/A * @param pkt packet containing the write the offset into config space 2061060SN/A */ 2071060SN/A virtual Tick writeConfig(PacketPtr pkt); 2081060SN/A 2091060SN/A 2101061SN/A /** 2111060SN/A * Read from the PCI config space data that is stored locally. This may be 2122292SN/A * overridden by the device but at some point it will eventually call this 2131060SN/A * for normal operations that it does not need to override. 2142329SN/A * @param pkt packet containing the write the offset into config space 2152292SN/A */ 2162292SN/A virtual Tick readConfig(PacketPtr pkt); 2172292SN/A 2182292SN/A public: 2192292SN/A Addr pciToDma(Addr pciAddr) const 2202292SN/A { return plat->pciToDma(pciAddr); } 2211060SN/A 2221060SN/A void 2232292SN/A intrPost() 2242292SN/A { plat->postPciInt(letoh(configData->config.interruptLine)); } 2252292SN/A 2262292SN/A void 2272292SN/A intrClear() 2282292SN/A { plat->clearPciInt(letoh(configData->config.interruptLine)); } 2292292SN/A 2302292SN/A uint8_t 2312292SN/A interruptLine() 2321061SN/A { return letoh(configData->config.interruptLine); } 2331060SN/A 2342292SN/A /** return the address ranges that this device responds to. 2351060SN/A * @params range_list range list to populate with ranges 2362292SN/A */ 2371060SN/A void addressRanges(AddrRangeList &range_list); 2382292SN/A 2392292SN/A /** 2401060SN/A * Constructor for PCI Dev. This function copies data from the 2411060SN/A * config file object PCIConfigData and registers the device with 2421060SN/A * a PciConfigAll object. 2431061SN/A */ 2441060SN/A PciDev(Params *params); 2452292SN/A 2461060SN/A virtual void init(); 2472292SN/A 2482292SN/A /** 2492292SN/A * Serialize this object to the given output stream. 2501060SN/A * @param os The stream to serialize to. 2512292SN/A */ 2522292SN/A virtual void serialize(std::ostream &os); 2532292SN/A 2542292SN/A /** 2552292SN/A * Reconstruct the state of this object from a checkpoint. 2562292SN/A * @param cp The checkpoint use. 2571060SN/A * @param section The section name of this object 2581060SN/A */ 2591061SN/A virtual void unserialize(Checkpoint *cp, const std::string §ion); 2602292SN/A 2612307SN/A 2621060SN/A virtual unsigned int drain(Event *de); 2632348SN/A 2642316SN/A virtual Port *getPort(const std::string &if_name, int idx = -1) 2652316SN/A { 2661060SN/A if (if_name == "config") { 2672316SN/A if (configPort != NULL) 2682316SN/A panic("pciconfig port already connected to."); 2692316SN/A configPort = new PciConfigPort(this, params()->busNum, 2702316SN/A params()->deviceNum, params()->functionNum, 2712348SN/A params()->platform); 2722307SN/A return configPort; 2732307SN/A } 2742307SN/A return DmaDevice::getPort(if_name, idx); 2752307SN/A } 2762307SN/A 2772307SN/A}; 2782307SN/A#endif // __DEV_PCIDEV_HH__ 2792307SN/A