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