device.hh revision 2846
1955SN/A/* 2955SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 294762Snate@binkert.org * Andrew Schultz 30955SN/A * Nathan Binkert 315522Snate@binkert.org */ 326143Snate@binkert.org 334762Snate@binkert.org/* @file 345522Snate@binkert.org * Interface for devices using PCI configuration 35955SN/A */ 365522Snate@binkert.org 3711974Sgabeblack@google.com#ifndef __DEV_PCIDEV_HH__ 38955SN/A#define __DEV_PCIDEV_HH__ 395522Snate@binkert.org 404202Sbinkertn@umich.edu#include "dev/io_device.hh" 415742Snate@binkert.org#include "dev/pcireg.h" 42955SN/A#include "dev/platform.hh" 434381Sbinkertn@umich.edu 444381Sbinkertn@umich.edu#define BAR_IO_MASK 0x3 458334Snate@binkert.org#define BAR_MEM_MASK 0xF 46955SN/A#define BAR_IO_SPACE_BIT 0x1 47955SN/A#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) 484202Sbinkertn@umich.edu#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); 49955SN/A 504382Sbinkertn@umich.edu 514382Sbinkertn@umich.edu/** 524382Sbinkertn@umich.edu * This class encapulates the first 64 bytes of a singles PCI 536654Snate@binkert.org * devices config space that in configured by the configuration file. 545517Snate@binkert.org */ 558614Sgblack@eecs.umich.educlass PciConfigData : public SimObject 567674Snate@binkert.org{ 576143Snate@binkert.org public: 586143Snate@binkert.org /** 596143Snate@binkert.org * Constructor to initialize the devices config space to 0. 608233Snate@binkert.org */ 618233Snate@binkert.org PciConfigData(const std::string &name) 628233Snate@binkert.org : SimObject(name) 638233Snate@binkert.org { 648233Snate@binkert.org memset(config.data, 0, sizeof(config.data)); 658334Snate@binkert.org memset(BARAddrs, 0, sizeof(BARAddrs)); 668334Snate@binkert.org memset(BARSize, 0, sizeof(BARSize)); 6710453SAndrew.Bardsley@arm.com } 6810453SAndrew.Bardsley@arm.com 698233Snate@binkert.org /** The first 64 bytes */ 708233Snate@binkert.org PCIConfig config; 718233Snate@binkert.org 728233Snate@binkert.org /** The size of the BARs */ 738233Snate@binkert.org uint32_t BARSize[6]; 748233Snate@binkert.org 7511983Sgabeblack@google.com /** The addresses of the BARs */ 7611983Sgabeblack@google.com Addr BARAddrs[6]; 7711983Sgabeblack@google.com}; 7811983Sgabeblack@google.com 7911983Sgabeblack@google.com 8011983Sgabeblack@google.com/** 8111983Sgabeblack@google.com * PCI device, base implemnation is only config space. 8211983Sgabeblack@google.com */ 8311983Sgabeblack@google.comclass PciDev : public DmaDevice 8411983Sgabeblack@google.com{ 8511983Sgabeblack@google.com class PciConfigPort : public PioPort 866143Snate@binkert.org { 878233Snate@binkert.org protected: 888233Snate@binkert.org PciDev *device; 898233Snate@binkert.org 906143Snate@binkert.org virtual bool recvTiming(Packet *pkt); 916143Snate@binkert.org 926143Snate@binkert.org virtual Tick recvAtomic(Packet *pkt); 9311308Santhony.gutierrez@amd.com 948233Snate@binkert.org virtual void recvFunctional(Packet *pkt) ; 958233Snate@binkert.org 968233Snate@binkert.org virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); 9711983Sgabeblack@google.com 9811983Sgabeblack@google.com int busId; 994762Snate@binkert.org int deviceId; 1006143Snate@binkert.org int functionId; 1018233Snate@binkert.org 1028233Snate@binkert.org Addr configAddr; 1038233Snate@binkert.org 1048233Snate@binkert.org public: 1058233Snate@binkert.org PciConfigPort(PciDev *dev, int busid, int devid, int funcid, 1066143Snate@binkert.org Platform *p); 1078233Snate@binkert.org 1088233Snate@binkert.org friend class PioPort::SendEvent; 1098233Snate@binkert.org }; 1108233Snate@binkert.org 1116143Snate@binkert.org public: 1126143Snate@binkert.org struct Params : public PioDevice::Params 1136143Snate@binkert.org { 1146143Snate@binkert.org /** 1156143Snate@binkert.org * A pointer to the object that contains the first 64 bytes of 1166143Snate@binkert.org * config space 1176143Snate@binkert.org */ 1186143Snate@binkert.org PciConfigData *configData; 1196143Snate@binkert.org 1207065Snate@binkert.org /** The bus number we are on */ 1216143Snate@binkert.org uint32_t busNum; 1228233Snate@binkert.org 1238233Snate@binkert.org /** The device number we have */ 1248233Snate@binkert.org uint32_t deviceNum; 1258233Snate@binkert.org 1268233Snate@binkert.org /** The function number */ 1278233Snate@binkert.org uint32_t functionNum; 1288233Snate@binkert.org 1298233Snate@binkert.org /** The latency for pio accesses. */ 1308233Snate@binkert.org Tick pio_delay; 1318233Snate@binkert.org 1328233Snate@binkert.org /** The latency for a config access. */ 1338233Snate@binkert.org Tick config_delay; 1348233Snate@binkert.org }; 1358233Snate@binkert.org 1368233Snate@binkert.org public: 1378233Snate@binkert.org const Params *params() const { return (const Params *)_params; } 1388233Snate@binkert.org 1398233Snate@binkert.org protected: 1408233Snate@binkert.org /** The current config space. Unlike the PciConfigData this is 1418233Snate@binkert.org * updated during simulation while continues to reflect what was 1428233Snate@binkert.org * in the config file. 1438233Snate@binkert.org */ 1448233Snate@binkert.org PCIConfig config; 1458233Snate@binkert.org 1468233Snate@binkert.org /** The size of the BARs */ 1478233Snate@binkert.org uint32_t BARSize[6]; 1488233Snate@binkert.org 1498233Snate@binkert.org /** The current address mapping of the BARs */ 1508233Snate@binkert.org Addr BARAddrs[6]; 1518233Snate@binkert.org 1528233Snate@binkert.org bool 1536143Snate@binkert.org isBAR(Addr addr, int bar) const 1546143Snate@binkert.org { 1556143Snate@binkert.org assert(bar >= 0 && bar < 6); 1566143Snate@binkert.org return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar]; 1576143Snate@binkert.org } 1586143Snate@binkert.org 1599982Satgutier@umich.edu int 16010196SCurtis.Dunham@arm.com getBAR(Addr addr) 16110196SCurtis.Dunham@arm.com { 16210196SCurtis.Dunham@arm.com for (int i = 0; i <= 5; ++i) 16310196SCurtis.Dunham@arm.com if (isBAR(addr, i)) 16410196SCurtis.Dunham@arm.com return i; 16510196SCurtis.Dunham@arm.com 16610196SCurtis.Dunham@arm.com return -1; 16710196SCurtis.Dunham@arm.com } 1686143Snate@binkert.org 16911983Sgabeblack@google.com bool 17011983Sgabeblack@google.com getBAR(Addr paddr, Addr &daddr, int &bar) 17111983Sgabeblack@google.com { 17211983Sgabeblack@google.com int b = getBAR(paddr); 17311983Sgabeblack@google.com if (b < 0) 17411983Sgabeblack@google.com return false; 17511983Sgabeblack@google.com 17611983Sgabeblack@google.com daddr = paddr - BARAddrs[b]; 17711983Sgabeblack@google.com bar = b; 1786143Snate@binkert.org return true; 17911988Sandreas.sandberg@arm.com } 1808233Snate@binkert.org 1818233Snate@binkert.org protected: 1826143Snate@binkert.org Platform *plat; 1838945Ssteve.reinhardt@amd.com PciConfigData *configData; 1846143Snate@binkert.org Tick pioDelay; 18511983Sgabeblack@google.com Tick configDelay; 18611983Sgabeblack@google.com PciConfigPort *configPort; 1876143Snate@binkert.org 1886143Snate@binkert.org /** 1895522Snate@binkert.org * Write to the PCI config space data that is stored locally. This may be 1906143Snate@binkert.org * overridden by the device but at some point it will eventually call this 1916143Snate@binkert.org * for normal operations that it does not need to override. 1926143Snate@binkert.org * @param pkt packet containing the write the offset into config space 1939982Satgutier@umich.edu */ 1948233Snate@binkert.org virtual Tick writeConfig(Packet *pkt); 1958233Snate@binkert.org 1968233Snate@binkert.org 1976143Snate@binkert.org /** 1986143Snate@binkert.org * Read from the PCI config space data that is stored locally. This may be 1996143Snate@binkert.org * overridden by the device but at some point it will eventually call this 2006143Snate@binkert.org * for normal operations that it does not need to override. 2015522Snate@binkert.org * @param pkt packet containing the write the offset into config space 2025522Snate@binkert.org */ 2035522Snate@binkert.org virtual Tick readConfig(Packet *pkt); 2045522Snate@binkert.org 2055604Snate@binkert.org public: 2065604Snate@binkert.org Addr pciToDma(Addr pciAddr) const 2076143Snate@binkert.org { return plat->pciToDma(pciAddr); } 2086143Snate@binkert.org 2094762Snate@binkert.org void 2104762Snate@binkert.org intrPost() 2116143Snate@binkert.org { plat->postPciInt(letoh(configData->config.interruptLine)); } 2126727Ssteve.reinhardt@amd.com 2136727Ssteve.reinhardt@amd.com void 2146727Ssteve.reinhardt@amd.com intrClear() 2154762Snate@binkert.org { plat->clearPciInt(letoh(configData->config.interruptLine)); } 2166143Snate@binkert.org 2176143Snate@binkert.org uint8_t 2186143Snate@binkert.org interruptLine() 2196143Snate@binkert.org { return letoh(configData->config.interruptLine); } 2206727Ssteve.reinhardt@amd.com 2216143Snate@binkert.org /** return the address ranges that this device responds to. 2227674Snate@binkert.org * @params range_list range list to populate with ranges 2237674Snate@binkert.org */ 2245604Snate@binkert.org void addressRanges(AddrRangeList &range_list); 2256143Snate@binkert.org 2266143Snate@binkert.org /** Do a PCI Configspace memory access. */ 2276143Snate@binkert.org Tick recvConfig(Packet *pkt) 2284762Snate@binkert.org { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); } 2296143Snate@binkert.org 2304762Snate@binkert.org /** 2314762Snate@binkert.org * Constructor for PCI Dev. This function copies data from the 2324762Snate@binkert.org * config file object PCIConfigData and registers the device with 2336143Snate@binkert.org * a PciConfigAll object. 2346143Snate@binkert.org */ 2354762Snate@binkert.org PciDev(Params *params); 2368233Snate@binkert.org 2378233Snate@binkert.org virtual void init(); 2388233Snate@binkert.org 2398233Snate@binkert.org /** 2406143Snate@binkert.org * Serialize this object to the given output stream. 2416143Snate@binkert.org * @param os The stream to serialize to. 2424762Snate@binkert.org */ 2436143Snate@binkert.org virtual void serialize(std::ostream &os); 2444762Snate@binkert.org 2459396Sandreas.hansson@arm.com /** 2469396Sandreas.hansson@arm.com * Reconstruct the state of this object from a checkpoint. 2479396Sandreas.hansson@arm.com * @param cp The checkpoint use. 2489396Sandreas.hansson@arm.com * @param section The section name of this object 2499396Sandreas.hansson@arm.com */ 2509396Sandreas.hansson@arm.com virtual void unserialize(Checkpoint *cp, const std::string §ion); 2519396Sandreas.hansson@arm.com 2529396Sandreas.hansson@arm.com virtual Port *getPort(const std::string &if_name, int idx = -1) 2539396Sandreas.hansson@arm.com { 2549396Sandreas.hansson@arm.com if (if_name == "config") { 2559396Sandreas.hansson@arm.com if (configPort != NULL) 2569396Sandreas.hansson@arm.com panic("pciconfig port already connected to."); 2579396Sandreas.hansson@arm.com configPort = new PciConfigPort(this, params()->busNum, 2589930Sandreas.hansson@arm.com params()->deviceNum, params()->functionNum, 2599930Sandreas.hansson@arm.com params()->platform); 2609396Sandreas.hansson@arm.com return configPort; 2618235Snate@binkert.org } 2628235Snate@binkert.org return DmaDevice::getPort(if_name, idx); 2636143Snate@binkert.org } 2648235Snate@binkert.org 2659003SAli.Saidi@ARM.com}; 2668235Snate@binkert.org#endif // __DEV_PCIDEV_HH__ 2678235Snate@binkert.org