device.hh revision 2846
16019SN/A/*
26019SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
310346Smitch.hayenga@arm.com * All rights reserved.
47134Sgblack@eecs.umich.edu *
57134Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67134Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77134Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87134Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97134Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107134Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117134Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127134Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137134Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147134Sgblack@eecs.umich.edu * this software without specific prior written permission.
156019SN/A *
166019SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019SN/A *
286019SN/A * Authors: Ali Saidi
296019SN/A *          Andrew Schultz
306019SN/A *          Nathan Binkert
316019SN/A */
326019SN/A
336019SN/A/* @file
346019SN/A * Interface for devices using PCI configuration
356019SN/A */
366019SN/A
376019SN/A#ifndef __DEV_PCIDEV_HH__
386019SN/A#define __DEV_PCIDEV_HH__
396019SN/A
406019SN/A#include "dev/io_device.hh"
416019SN/A#include "dev/pcireg.h"
426308SN/A#include "dev/platform.hh"
436308SN/A
446309SN/A#define BAR_IO_MASK 0x3
456309SN/A#define BAR_MEM_MASK 0xF
466309SN/A#define BAR_IO_SPACE_BIT 0x1
476309SN/A#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
486309SN/A#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
497134Sgblack@eecs.umich.edu
508588Sgblack@eecs.umich.edu
516309SN/A/**
526309SN/A * This class encapulates the first 64 bytes of a singles PCI
537296Sgblack@eecs.umich.edu * devices config space that in configured by the configuration file.
548139SMatt.Horsnell@arm.com */
556309SN/Aclass PciConfigData : public SimObject
566309SN/A{
576309SN/A  public:
5810346Smitch.hayenga@arm.com    /**
5910346Smitch.hayenga@arm.com     * Constructor to initialize the devices config space to 0.
6010346Smitch.hayenga@arm.com     */
6110346Smitch.hayenga@arm.com    PciConfigData(const std::string &name)
6210346Smitch.hayenga@arm.com        : SimObject(name)
6310346Smitch.hayenga@arm.com    {
6410346Smitch.hayenga@arm.com        memset(config.data, 0, sizeof(config.data));
6510346Smitch.hayenga@arm.com        memset(BARAddrs, 0, sizeof(BARAddrs));
6610346Smitch.hayenga@arm.com        memset(BARSize, 0, sizeof(BARSize));
6710346Smitch.hayenga@arm.com    }
6810346Smitch.hayenga@arm.com
6910346Smitch.hayenga@arm.com    /** The first 64 bytes */
708588Sgblack@eecs.umich.edu    PCIConfig config;
717174Sgblack@eecs.umich.edu
727639Sgblack@eecs.umich.edu    /** The size of the BARs */
737639Sgblack@eecs.umich.edu    uint32_t BARSize[6];
747644Sali.saidi@arm.com
758139SMatt.Horsnell@arm.com    /** The addresses of the BARs */
767639Sgblack@eecs.umich.edu    Addr BARAddrs[6];
777639Sgblack@eecs.umich.edu};
787639Sgblack@eecs.umich.edu
798588Sgblack@eecs.umich.edu
807639Sgblack@eecs.umich.edu/**
817639Sgblack@eecs.umich.edu * PCI device, base implemnation is only config space.
827639Sgblack@eecs.umich.edu */
837644Sali.saidi@arm.comclass PciDev : public DmaDevice
848139SMatt.Horsnell@arm.com{
857639Sgblack@eecs.umich.edu    class PciConfigPort : public PioPort
867639Sgblack@eecs.umich.edu    {
877639Sgblack@eecs.umich.edu      protected:
887639Sgblack@eecs.umich.edu        PciDev *device;
897639Sgblack@eecs.umich.edu
908588Sgblack@eecs.umich.edu        virtual bool recvTiming(Packet *pkt);
917639Sgblack@eecs.umich.edu
927639Sgblack@eecs.umich.edu        virtual Tick recvAtomic(Packet *pkt);
937639Sgblack@eecs.umich.edu
947644Sali.saidi@arm.com        virtual void recvFunctional(Packet *pkt) ;
958139SMatt.Horsnell@arm.com
967639Sgblack@eecs.umich.edu        virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
977639Sgblack@eecs.umich.edu
987639Sgblack@eecs.umich.edu        int busId;
997639Sgblack@eecs.umich.edu        int deviceId;
1007174Sgblack@eecs.umich.edu        int functionId;
1018148SAli.Saidi@ARM.com
1028303SAli.Saidi@ARM.com        Addr configAddr;
1037400SAli.Saidi@ARM.com
1048303SAli.Saidi@ARM.com      public:
1058303SAli.Saidi@ARM.com        PciConfigPort(PciDev *dev, int busid, int devid, int funcid,
10610037SARM gem5 Developers                Platform *p);
10710037SARM gem5 Developers
1088303SAli.Saidi@ARM.com      friend class PioPort::SendEvent;
1098303SAli.Saidi@ARM.com    };
1108303SAli.Saidi@ARM.com
1118303SAli.Saidi@ARM.com  public:
1128303SAli.Saidi@ARM.com    struct Params : public PioDevice::Params
1138303SAli.Saidi@ARM.com    {
1148205SAli.Saidi@ARM.com        /**
1157858SMatt.Horsnell@arm.com         * A pointer to the object that contains the first 64 bytes of
1168285SPrakash.Ramrakhyani@arm.com         * config space
1176754SN/A         */
1188148SAli.Saidi@ARM.com        PciConfigData *configData;
1196754SN/A
1206754SN/A        /** The bus number we are on */
1218148SAli.Saidi@ARM.com        uint32_t busNum;
1228588Sgblack@eecs.umich.edu
1236754SN/A        /** The device number we have */
1248139SMatt.Horsnell@arm.com        uint32_t deviceNum;
1257422Sgblack@eecs.umich.edu
1268148SAli.Saidi@ARM.com        /** The function number */
1278148SAli.Saidi@ARM.com        uint32_t functionNum;
1286754SN/A
1298588Sgblack@eecs.umich.edu        /** The latency for pio accesses. */
1306309SN/A        Tick pio_delay;
1316309SN/A
1327296Sgblack@eecs.umich.edu        /** The latency for a config access. */
1337303Sgblack@eecs.umich.edu        Tick config_delay;
1348139SMatt.Horsnell@arm.com    };
1356309SN/A
1366309SN/A  public:
1376309SN/A    const Params *params() const { return (const Params *)_params; }
1388588Sgblack@eecs.umich.edu
1397174Sgblack@eecs.umich.edu  protected:
1407174Sgblack@eecs.umich.edu    /** The current config space. Unlike the PciConfigData this is
1417296Sgblack@eecs.umich.edu     * updated during simulation while continues to reflect what was
1427303Sgblack@eecs.umich.edu     * in the config file.
1437644Sali.saidi@arm.com     */
1448139SMatt.Horsnell@arm.com    PCIConfig config;
1457174Sgblack@eecs.umich.edu
1467174Sgblack@eecs.umich.edu    /** The size of the BARs */
1477174Sgblack@eecs.umich.edu    uint32_t BARSize[6];
1488588Sgblack@eecs.umich.edu
1497639Sgblack@eecs.umich.edu    /** The current address mapping of the BARs */
1507639Sgblack@eecs.umich.edu    Addr BARAddrs[6];
1517639Sgblack@eecs.umich.edu
1527639Sgblack@eecs.umich.edu    bool
1537644Sali.saidi@arm.com    isBAR(Addr addr, int bar) const
1548139SMatt.Horsnell@arm.com    {
1557639Sgblack@eecs.umich.edu        assert(bar >= 0 && bar < 6);
1567639Sgblack@eecs.umich.edu        return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar];
1577639Sgblack@eecs.umich.edu    }
1587639Sgblack@eecs.umich.edu
1597639Sgblack@eecs.umich.edu    int
1608588Sgblack@eecs.umich.edu    getBAR(Addr addr)
1617639Sgblack@eecs.umich.edu    {
1627639Sgblack@eecs.umich.edu        for (int i = 0; i <= 5; ++i)
1637639Sgblack@eecs.umich.edu            if (isBAR(addr, i))
1647639Sgblack@eecs.umich.edu                return i;
1657644Sali.saidi@arm.com
1668139SMatt.Horsnell@arm.com        return -1;
1677639Sgblack@eecs.umich.edu    }
1687639Sgblack@eecs.umich.edu
1697639Sgblack@eecs.umich.edu    bool
1707639Sgblack@eecs.umich.edu    getBAR(Addr paddr, Addr &daddr, int &bar)
1717639Sgblack@eecs.umich.edu    {
1727174Sgblack@eecs.umich.edu        int b = getBAR(paddr);
1737174Sgblack@eecs.umich.edu        if (b < 0)
17410346Smitch.hayenga@arm.com            return false;
17510346Smitch.hayenga@arm.com
1767639Sgblack@eecs.umich.edu        daddr = paddr - BARAddrs[b];
1777639Sgblack@eecs.umich.edu        bar = b;
1787174Sgblack@eecs.umich.edu        return true;
1797174Sgblack@eecs.umich.edu    }
1807174Sgblack@eecs.umich.edu
1817174Sgblack@eecs.umich.edu  protected:
1827174Sgblack@eecs.umich.edu    Platform *plat;
1837174Sgblack@eecs.umich.edu    PciConfigData *configData;
1847174Sgblack@eecs.umich.edu    Tick pioDelay;
1857174Sgblack@eecs.umich.edu    Tick configDelay;
1867174Sgblack@eecs.umich.edu    PciConfigPort *configPort;
1877174Sgblack@eecs.umich.edu
1887174Sgblack@eecs.umich.edu    /**
18910346Smitch.hayenga@arm.com     * Write to the PCI config space data that is stored locally. This may be
19010346Smitch.hayenga@arm.com     * overridden by the device but at some point it will eventually call this
19110346Smitch.hayenga@arm.com     * for normal operations that it does not need to override.
19210346Smitch.hayenga@arm.com     * @param pkt packet containing the write the offset into config space
19310346Smitch.hayenga@arm.com     */
19410346Smitch.hayenga@arm.com    virtual Tick writeConfig(Packet *pkt);
1956309SN/A
1966308SN/A
1977639Sgblack@eecs.umich.edu    /**
1987639Sgblack@eecs.umich.edu     * Read from the PCI config space data that is stored locally. This may be
1997639Sgblack@eecs.umich.edu     * overridden by the device but at some point it will eventually call this
20010037SARM gem5 Developers     * for normal operations that it does not need to override.
2017639Sgblack@eecs.umich.edu     * @param pkt packet containing the write the offset into config space
2027639Sgblack@eecs.umich.edu     */
2037639Sgblack@eecs.umich.edu    virtual Tick readConfig(Packet *pkt);
2047639Sgblack@eecs.umich.edu
2057639Sgblack@eecs.umich.edu  public:
2067639Sgblack@eecs.umich.edu    Addr pciToDma(Addr pciAddr) const
2077639Sgblack@eecs.umich.edu    { return plat->pciToDma(pciAddr); }
2087639Sgblack@eecs.umich.edu
2097639Sgblack@eecs.umich.edu    void
2107639Sgblack@eecs.umich.edu    intrPost()
2117639Sgblack@eecs.umich.edu    { plat->postPciInt(letoh(configData->config.interruptLine)); }
2127639Sgblack@eecs.umich.edu
2137639Sgblack@eecs.umich.edu    void
2147639Sgblack@eecs.umich.edu    intrClear()
2157639Sgblack@eecs.umich.edu    { plat->clearPciInt(letoh(configData->config.interruptLine)); }
2167639Sgblack@eecs.umich.edu
2177639Sgblack@eecs.umich.edu    uint8_t
2187639Sgblack@eecs.umich.edu    interruptLine()
2197639Sgblack@eecs.umich.edu    { return letoh(configData->config.interruptLine); }
2207639Sgblack@eecs.umich.edu
2217639Sgblack@eecs.umich.edu    /** return the address ranges that this device responds to.
2227639Sgblack@eecs.umich.edu     * @params range_list range list to populate with ranges
2237639Sgblack@eecs.umich.edu     */
2247639Sgblack@eecs.umich.edu    void addressRanges(AddrRangeList &range_list);
2257639Sgblack@eecs.umich.edu
2267639Sgblack@eecs.umich.edu    /** Do a PCI Configspace memory access. */
2277639Sgblack@eecs.umich.edu    Tick recvConfig(Packet *pkt)
2287639Sgblack@eecs.umich.edu    { return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); }
2297639Sgblack@eecs.umich.edu
2307639Sgblack@eecs.umich.edu    /**
2317639Sgblack@eecs.umich.edu     * Constructor for PCI Dev. This function copies data from the
2327639Sgblack@eecs.umich.edu     * config file object PCIConfigData and registers the device with
2337639Sgblack@eecs.umich.edu     * a PciConfigAll object.
2347639Sgblack@eecs.umich.edu     */
2357639Sgblack@eecs.umich.edu    PciDev(Params *params);
2368588Sgblack@eecs.umich.edu
2377639Sgblack@eecs.umich.edu    virtual void init();
2387639Sgblack@eecs.umich.edu
2397639Sgblack@eecs.umich.edu    /**
2407639Sgblack@eecs.umich.edu     * Serialize this object to the given output stream.
2417639Sgblack@eecs.umich.edu     * @param os The stream to serialize to.
2427639Sgblack@eecs.umich.edu     */
2438588Sgblack@eecs.umich.edu    virtual void serialize(std::ostream &os);
2447639Sgblack@eecs.umich.edu
2457639Sgblack@eecs.umich.edu    /**
2467639Sgblack@eecs.umich.edu     * Reconstruct the state of this object from a checkpoint.
2477639Sgblack@eecs.umich.edu     * @param cp The checkpoint use.
2487639Sgblack@eecs.umich.edu     * @param section The section name of this object
2497639Sgblack@eecs.umich.edu     */
2507639Sgblack@eecs.umich.edu    virtual void unserialize(Checkpoint *cp, const std::string &section);
2517639Sgblack@eecs.umich.edu
2527639Sgblack@eecs.umich.edu    virtual Port *getPort(const std::string &if_name, int idx = -1)
2537639Sgblack@eecs.umich.edu    {
2547639Sgblack@eecs.umich.edu        if (if_name == "config") {
2557644Sali.saidi@arm.com            if (configPort != NULL)
2567639Sgblack@eecs.umich.edu                panic("pciconfig port already connected to.");
2577639Sgblack@eecs.umich.edu            configPort = new PciConfigPort(this, params()->busNum,
2587639Sgblack@eecs.umich.edu                    params()->deviceNum, params()->functionNum,
2597639Sgblack@eecs.umich.edu                    params()->platform);
2607639Sgblack@eecs.umich.edu            return configPort;
2617639Sgblack@eecs.umich.edu        }
2627639Sgblack@eecs.umich.edu        return DmaDevice::getPort(if_name, idx);
2637639Sgblack@eecs.umich.edu    }
2647644Sali.saidi@arm.com
2657639Sgblack@eecs.umich.edu};
2667639Sgblack@eecs.umich.edu#endif // __DEV_PCIDEV_HH__
2677639Sgblack@eecs.umich.edu