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 &section);
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