device.hh revision 5834
12SN/A/* 21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 292665Ssaidi@eecs.umich.edu * Andrew Schultz 302SN/A * Nathan Binkert 312SN/A */ 322SN/A 332SN/A/* @file 342SN/A * Interface for devices using PCI configuration 352SN/A */ 361354SN/A 371354SN/A#ifndef __DEV_PCIDEV_HH__ 382SN/A#define __DEV_PCIDEV_HH__ 392SN/A 405501Snate@binkert.org#include <cstring> 415546Snate@binkert.org 422SN/A#include "dev/io_device.hh" 432SN/A#include "dev/pcireg.h" 442SN/A#include "dev/platform.hh" 452SN/A#include "params/PciDevice.hh" 4656SN/A#include "sim/byteswap.hh" 472361SN/A 481354SN/A#define BAR_IO_MASK 0x3 4956SN/A#define BAR_MEM_MASK 0xF 505501Snate@binkert.org#define BAR_IO_SPACE_BIT 0x1 512SN/A#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) 525543Ssaidi@eecs.umich.edu#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); 532SN/A 541354SN/A 551354SN/A 562SN/A/** 572SN/A * PCI device, base implementation is only config space. 582SN/A */ 592SN/Aclass PciDev : public DmaDevice 605501Snate@binkert.org{ 615501Snate@binkert.org class PciConfigPort : public SimpleTimingPort 622SN/A { 63395SN/A protected: 642SN/A PciDev *device; 652SN/A 662SN/A virtual Tick recvAtomic(PacketPtr pkt); 672SN/A 685502Snate@binkert.org virtual void getDeviceAddressRanges(AddrRangeList &resp, 695502Snate@binkert.org bool &snoop); 705502Snate@binkert.org 715503Snate@binkert.org Platform *platform; 725503Snate@binkert.org 735502Snate@binkert.org int busId; 745502Snate@binkert.org int deviceId; 755502Snate@binkert.org int functionId; 765502Snate@binkert.org 775502Snate@binkert.org Addr configAddr; 785502Snate@binkert.org 795502Snate@binkert.org public: 805602Snate@binkert.org PciConfigPort(PciDev *dev, int busid, int devid, int funcid, 815602Snate@binkert.org Platform *p); 825501Snate@binkert.org }; 835543Ssaidi@eecs.umich.edu 845543Ssaidi@eecs.umich.edu public: 855501Snate@binkert.org typedef PciDeviceParams Params; 864016Sstever@eecs.umich.edu const Params * 874016Sstever@eecs.umich.edu params() const 884016Sstever@eecs.umich.edu { 894016Sstever@eecs.umich.edu return dynamic_cast<const Params *>(_params); 904016Sstever@eecs.umich.edu } 914016Sstever@eecs.umich.edu 924016Sstever@eecs.umich.edu protected: 934016Sstever@eecs.umich.edu /** The current config space. */ 944016Sstever@eecs.umich.edu PCIConfig config; 955501Snate@binkert.org 965605Snate@binkert.org /** The size of the BARs */ 975605Snate@binkert.org uint32_t BARSize[6]; 985605Snate@binkert.org 995605Snate@binkert.org /** The current address mapping of the BARs */ 1005501Snate@binkert.org Addr BARAddrs[6]; 1014016Sstever@eecs.umich.edu 1025577SSteve.Reinhardt@amd.com /** Whether the BARs are really hardwired legacy IO locations. */ 1035501Snate@binkert.org bool legacyIO[6]; 1045501Snate@binkert.org 1055501Snate@binkert.org /** 1065502Snate@binkert.org * Does the given address lie within the space mapped by the given 1075502Snate@binkert.org * base address register? 1085605Snate@binkert.org */ 1095502Snate@binkert.org bool 1105502Snate@binkert.org isBAR(Addr addr, int bar) const 1115605Snate@binkert.org { 1125605Snate@binkert.org assert(bar >= 0 && bar < 6); 1135605Snate@binkert.org return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 1145577SSteve.Reinhardt@amd.com } 1155502Snate@binkert.org 1165502Snate@binkert.org /** 1175502Snate@binkert.org * Which base address register (if any) maps the given address? 1185502Snate@binkert.org * @return The BAR number (0-5 inclusive), or -1 if none. 1192SN/A */ 1202SN/A int 1212SN/A getBAR(Addr addr) 1222SN/A { 1232SN/A for (int i = 0; i <= 5; ++i) 124237SN/A if (isBAR(addr, i)) 1252667Sstever@eecs.umich.edu return i; 1265605Snate@binkert.org 1275605Snate@binkert.org return -1; 1282SN/A } 1292SN/A 1302SN/A /** 1312SN/A * Which base address register (if any) maps the given address? 1322SN/A * @param addr The address to check. 1332SN/A * @retval bar The BAR number (0-5 inclusive), 1342SN/A * only valid if return value is true. 1355501Snate@binkert.org * @retval offs The offset from the base address, 1365543Ssaidi@eecs.umich.edu * only valid if return value is true. 1372SN/A * @return True iff address maps to a base address register's region. 1382SN/A */ 139396SN/A bool 140396SN/A getBAR(Addr addr, int &bar, Addr &offs) 141396SN/A { 142396SN/A int b = getBAR(addr); 143396SN/A if (b < 0) 1445501Snate@binkert.org return false; 1455543Ssaidi@eecs.umich.edu 1465501Snate@binkert.org offs = addr - BARAddrs[b]; 1473329Sstever@eecs.umich.edu bar = b; 1483329Sstever@eecs.umich.edu return true; 1493329Sstever@eecs.umich.edu } 1503329Sstever@eecs.umich.edu 1513329Sstever@eecs.umich.edu protected: 1523329Sstever@eecs.umich.edu Platform *plat; 1533329Sstever@eecs.umich.edu Tick pioDelay; 1543329Sstever@eecs.umich.edu Tick configDelay; 1555543Ssaidi@eecs.umich.edu PciConfigPort *configPort; 156396SN/A 1573329Sstever@eecs.umich.edu /** 1583329Sstever@eecs.umich.edu * Write to the PCI config space data that is stored locally. This may be 1593329Sstever@eecs.umich.edu * overridden by the device but at some point it will eventually call this 1603329Sstever@eecs.umich.edu * for normal operations that it does not need to override. 1615543Ssaidi@eecs.umich.edu * @param pkt packet containing the write the offset into config space 1623329Sstever@eecs.umich.edu */ 163396SN/A virtual Tick writeConfig(PacketPtr pkt); 164396SN/A 165396SN/A 1665543Ssaidi@eecs.umich.edu /** 167396SN/A * Read from the PCI config space data that is stored locally. This may be 168396SN/A * overridden by the device but at some point it will eventually call this 1695543Ssaidi@eecs.umich.edu * for normal operations that it does not need to override. 170396SN/A * @param pkt packet containing the write the offset into config space 171396SN/A */ 172396SN/A virtual Tick readConfig(PacketPtr pkt); 173396SN/A 1745543Ssaidi@eecs.umich.edu public: 175396SN/A Addr pciToDma(Addr pciAddr) const 176396SN/A { return plat->pciToDma(pciAddr); } 177396SN/A 1785543Ssaidi@eecs.umich.edu void 179396SN/A intrPost() 180396SN/A { plat->postPciInt(letoh(config.interruptLine)); } 181396SN/A 1825543Ssaidi@eecs.umich.edu void 183396SN/A intrClear() 1844075Sbinkertn@umich.edu { plat->clearPciInt(letoh(config.interruptLine)); } 1854075Sbinkertn@umich.edu 1864075Sbinkertn@umich.edu uint8_t 187396SN/A interruptLine() 188396SN/A { return letoh(config.interruptLine); } 1895543Ssaidi@eecs.umich.edu 1905501Snate@binkert.org /** return the address ranges that this device responds to. 1915501Snate@binkert.org * @params range_list range list to populate with ranges 1925543Ssaidi@eecs.umich.edu */ 193396SN/A void addressRanges(AddrRangeList &range_list); 194396SN/A 1952SN/A /** 1962SN/A * Constructor for PCI Dev. This function copies data from the 1972SN/A * config file object PCIConfigData and registers the device with 1982SN/A * a PciConfigAll object. 1995605Snate@binkert.org */ 2005605Snate@binkert.org PciDev(const Params *params); 201224SN/A 2024016Sstever@eecs.umich.edu virtual void init(); 2035501Snate@binkert.org 2045605Snate@binkert.org /** 2055501Snate@binkert.org * Serialize this object to the given output stream. 2065501Snate@binkert.org * @param os The stream to serialize to. 2075501Snate@binkert.org */ 2085501Snate@binkert.org virtual void serialize(std::ostream &os); 2094016Sstever@eecs.umich.edu 210224SN/A /** 211224SN/A * Reconstruct the state of this object from a checkpoint. 2125768Snate@binkert.org * @param cp The checkpoint use. 2135768Snate@binkert.org * @param section The section name of this object 214265SN/A */ 2155501Snate@binkert.org virtual void unserialize(Checkpoint *cp, const std::string §ion); 2165501Snate@binkert.org 2175501Snate@binkert.org 2185501Snate@binkert.org virtual unsigned int drain(Event *de); 2195501Snate@binkert.org 2205501Snate@binkert.org virtual Port *getPort(const std::string &if_name, int idx = -1) 2215501Snate@binkert.org { 2225501Snate@binkert.org if (if_name == "config") { 2235501Snate@binkert.org if (configPort != NULL) 2245501Snate@binkert.org panic("pciconfig port already connected to."); 2255501Snate@binkert.org configPort = new PciConfigPort(this, params()->pci_bus, 2265501Snate@binkert.org params()->pci_dev, params()->pci_func, 2275501Snate@binkert.org params()->platform); 2285501Snate@binkert.org return configPort; 2295501Snate@binkert.org } 2305501Snate@binkert.org return DmaDevice::getPort(if_name, idx); 2315501Snate@binkert.org } 2325501Snate@binkert.org 2335501Snate@binkert.org}; 2345501Snate@binkert.org#endif // __DEV_PCIDEV_HH__ 2355501Snate@binkert.org