dma_device.hh revision 3349
12817Sksewell@umich.edu/*
22817Sksewell@umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
32817Sksewell@umich.edu * All rights reserved.
42817Sksewell@umich.edu *
52817Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
62817Sksewell@umich.edu * modification, are permitted provided that the following conditions are
72817Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
82817Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
92817Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
102817Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
112817Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
122817Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
132817Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
142817Sksewell@umich.edu * this software without specific prior written permission.
152817Sksewell@umich.edu *
162817Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172817Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182817Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192817Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202817Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212817Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222817Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232817Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242817Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252817Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262817Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272817Sksewell@umich.edu *
282817Sksewell@umich.edu * Authors: Ali Saidi
292817Sksewell@umich.edu *          Nathan Binkert
302817Sksewell@umich.edu */
312817Sksewell@umich.edu
322817Sksewell@umich.edu#ifndef __DEV_IO_DEVICE_HH__
332834Sksewell@umich.edu#define __DEV_IO_DEVICE_HH__
342817Sksewell@umich.edu
352817Sksewell@umich.edu#include "mem/mem_object.hh"
362817Sksewell@umich.edu#include "mem/packet.hh"
372817Sksewell@umich.edu#include "mem/tport.hh"
382817Sksewell@umich.edu#include "sim/sim_object.hh"
392817Sksewell@umich.edu
402817Sksewell@umich.educlass Event;
412817Sksewell@umich.educlass Platform;
422817Sksewell@umich.educlass PioDevice;
432817Sksewell@umich.educlass DmaDevice;
442817Sksewell@umich.educlass System;
452817Sksewell@umich.edu
462817Sksewell@umich.edu/**
472817Sksewell@umich.edu * The PioPort class is a programmed i/o port that all devices that are
482817Sksewell@umich.edu * sensitive to an address range use. The port takes all the memory
492817Sksewell@umich.edu * access types and roles them into one read() and write() call that the device
502817Sksewell@umich.edu * must respond to. The device must also provide the addressRanges() function
512817Sksewell@umich.edu * with which it returns the address ranges it is interested in.
522817Sksewell@umich.edu */
532817Sksewell@umich.educlass PioPort : public SimpleTimingPort
542817Sksewell@umich.edu{
552817Sksewell@umich.edu  protected:
562817Sksewell@umich.edu    /** The device that this port serves. */
572817Sksewell@umich.edu    PioDevice *device;
582817Sksewell@umich.edu
592817Sksewell@umich.edu    virtual Tick recvAtomic(PacketPtr pkt);
602817Sksewell@umich.edu
612817Sksewell@umich.edu    virtual void getDeviceAddressRanges(AddrRangeList &resp,
622817Sksewell@umich.edu                                        AddrRangeList &snoop);
632817Sksewell@umich.edu
642817Sksewell@umich.edu  public:
652817Sksewell@umich.edu
662817Sksewell@umich.edu    PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
672817Sksewell@umich.edu};
682817Sksewell@umich.edu
692817Sksewell@umich.edu
702817Sksewell@umich.educlass DmaPort : public Port
712817Sksewell@umich.edu{
722817Sksewell@umich.edu  protected:
732817Sksewell@umich.edu    struct DmaReqState : public Packet::SenderState
742817Sksewell@umich.edu    {
752817Sksewell@umich.edu        /** Event to call on the device when this transaction (all packets)
762817Sksewell@umich.edu         * complete. */
772817Sksewell@umich.edu        Event *completionEvent;
782817Sksewell@umich.edu
792817Sksewell@umich.edu        /** Where we came from for some sanity checking. */
802817Sksewell@umich.edu        Port *outPort;
812817Sksewell@umich.edu
822817Sksewell@umich.edu        /** Total number of bytes that this transaction involves. */
832817Sksewell@umich.edu        Addr totBytes;
842817Sksewell@umich.edu
852817Sksewell@umich.edu        /** Number of bytes that have been acked for this transaction. */
862817Sksewell@umich.edu        Addr numBytes;
872817Sksewell@umich.edu
882817Sksewell@umich.edu        DmaReqState(Event *ce, Port *p, Addr tb)
892817Sksewell@umich.edu            : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0)
902817Sksewell@umich.edu        {}
912817Sksewell@umich.edu    };
922817Sksewell@umich.edu
932817Sksewell@umich.edu    DmaDevice *device;
942817Sksewell@umich.edu    std::list<PacketPtr> transmitList;
952817Sksewell@umich.edu
962817Sksewell@umich.edu    /** The system that device/port are in. This is used to select which mode
972817Sksewell@umich.edu     * we are currently operating in. */
982817Sksewell@umich.edu    System *sys;
992817Sksewell@umich.edu
1002817Sksewell@umich.edu    /** Number of outstanding packets the dma port has. */
1012817Sksewell@umich.edu    int pendingCount;
1022817Sksewell@umich.edu
1032817Sksewell@umich.edu    /** If a dmaAction is in progress. */
1042817Sksewell@umich.edu    int actionInProgress;
1052817Sksewell@umich.edu
1062817Sksewell@umich.edu    /** If we need to drain, keep the drain event around until we're done
1072817Sksewell@umich.edu     * here.*/
1082817Sksewell@umich.edu    Event *drainEvent;
1092817Sksewell@umich.edu
1102817Sksewell@umich.edu    virtual bool recvTiming(PacketPtr pkt);
1112817Sksewell@umich.edu    virtual Tick recvAtomic(PacketPtr pkt)
1122817Sksewell@umich.edu    { panic("dma port shouldn't be used for pio access."); }
1132817Sksewell@umich.edu    virtual void recvFunctional(PacketPtr pkt)
1142817Sksewell@umich.edu    { panic("dma port shouldn't be used for pio access."); }
1152817Sksewell@umich.edu
1162875Sksewell@umich.edu    virtual void recvStatusChange(Status status)
1172875Sksewell@umich.edu    { ; }
1182817Sksewell@umich.edu
1192817Sksewell@umich.edu    virtual void recvRetry() ;
1202817Sksewell@umich.edu
1212817Sksewell@umich.edu    virtual void getDeviceAddressRanges(AddrRangeList &resp,
1222817Sksewell@umich.edu                                        AddrRangeList &snoop)
1232817Sksewell@umich.edu    { resp.clear(); snoop.clear(); }
1242817Sksewell@umich.edu
1252817Sksewell@umich.edu    void sendDma(PacketPtr pkt, bool front = false);
1262817Sksewell@umich.edu
1272817Sksewell@umich.edu  public:
1282817Sksewell@umich.edu    DmaPort(DmaDevice *dev, System *s);
1292817Sksewell@umich.edu
1302817Sksewell@umich.edu    void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
1312817Sksewell@umich.edu                   uint8_t *data = NULL);
1322817Sksewell@umich.edu
1332817Sksewell@umich.edu    bool dmaPending() { return pendingCount > 0; }
1342817Sksewell@umich.edu
1352817Sksewell@umich.edu    unsigned int drain(Event *de);
1362817Sksewell@umich.edu};
1372817Sksewell@umich.edu
1382817Sksewell@umich.edu/**
1392817Sksewell@umich.edu * This device is the base class which all devices senstive to an address range
1402817Sksewell@umich.edu * inherit from. There are three pure virtual functions which all devices must
1412875Sksewell@umich.edu * implement addressRanges(), read(), and write(). The magic do choose which
1422875Sksewell@umich.edu * mode we are in, etc is handled by the PioPort so the device doesn't have to
1432817Sksewell@umich.edu * bother.
1442817Sksewell@umich.edu */
1452817Sksewell@umich.educlass PioDevice : public MemObject
1462817Sksewell@umich.edu{
1472817Sksewell@umich.edu  protected:
1482817Sksewell@umich.edu
1492817Sksewell@umich.edu    /** The platform we are in. This is used to decide what type of memory
1502817Sksewell@umich.edu     * transaction we should perform. */
1512817Sksewell@umich.edu    Platform *platform;
1522817Sksewell@umich.edu
1532817Sksewell@umich.edu    System *sys;
1542817Sksewell@umich.edu
1552817Sksewell@umich.edu    /** The pioPort that handles the requests for us and provides us requests
1562817Sksewell@umich.edu     * that it sees. */
1572817Sksewell@umich.edu    PioPort *pioPort;
1582817Sksewell@umich.edu
1592817Sksewell@umich.edu    virtual void addressRanges(AddrRangeList &range_list) = 0;
1602817Sksewell@umich.edu
1612817Sksewell@umich.edu    /** Pure virtual function that the device must implement. Called
1622817Sksewell@umich.edu     * when a read command is recieved by the port.
1632817Sksewell@umich.edu     * @param pkt Packet describing this request
1642817Sksewell@umich.edu     * @return number of ticks it took to complete
1652817Sksewell@umich.edu     */
1662875Sksewell@umich.edu    virtual Tick read(PacketPtr pkt) = 0;
1672817Sksewell@umich.edu
1682875Sksewell@umich.edu    /** Pure virtual function that the device must implement. Called when a
1692875Sksewell@umich.edu     * write command is recieved by the port.
1702817Sksewell@umich.edu     * @param pkt Packet describing this request
1712817Sksewell@umich.edu     * @return number of ticks it took to complete
1722817Sksewell@umich.edu     */
1732817Sksewell@umich.edu    virtual Tick write(PacketPtr pkt) = 0;
1742817Sksewell@umich.edu
1752875Sksewell@umich.edu  public:
1762817Sksewell@umich.edu    /** Params struct which is extended through each device based on
1772817Sksewell@umich.edu     * the parameters it needs. Since we are re-writing everything, we
1782817Sksewell@umich.edu     * might as well start from the bottom this time. */
1792817Sksewell@umich.edu    struct Params
1802817Sksewell@umich.edu    {
1812817Sksewell@umich.edu        std::string name;
1822875Sksewell@umich.edu        Platform *platform;
1832875Sksewell@umich.edu        System *system;
1842817Sksewell@umich.edu    };
1852817Sksewell@umich.edu
1862817Sksewell@umich.edu  protected:
1872817Sksewell@umich.edu    Params *_params;
1882817Sksewell@umich.edu
1892817Sksewell@umich.edu  public:
1902817Sksewell@umich.edu    const Params *params() const { return _params; }
1912817Sksewell@umich.edu
1922817Sksewell@umich.edu    PioDevice(Params *p)
1932817Sksewell@umich.edu              : MemObject(p->name),  platform(p->platform), sys(p->system),
1942817Sksewell@umich.edu              pioPort(NULL), _params(p)
1952817Sksewell@umich.edu              {}
1962817Sksewell@umich.edu
1972817Sksewell@umich.edu    virtual ~PioDevice();
1982817Sksewell@umich.edu
1992817Sksewell@umich.edu    virtual void init();
2002817Sksewell@umich.edu
2012817Sksewell@umich.edu    virtual unsigned int drain(Event *de);
2022817Sksewell@umich.edu
2032817Sksewell@umich.edu    virtual Port *getPort(const std::string &if_name, int idx = -1)
2042817Sksewell@umich.edu    {
2052817Sksewell@umich.edu        if (if_name == "pio") {
2062817Sksewell@umich.edu            if (pioPort != NULL)
2072817Sksewell@umich.edu                panic("pio port already connected to.");
2082817Sksewell@umich.edu            pioPort = new PioPort(this, sys);
2092817Sksewell@umich.edu            return pioPort;
2102817Sksewell@umich.edu        } else
2112817Sksewell@umich.edu            return NULL;
2122817Sksewell@umich.edu    }
2132817Sksewell@umich.edu    friend class PioPort;
2142817Sksewell@umich.edu
2152817Sksewell@umich.edu};
2162817Sksewell@umich.edu
2172817Sksewell@umich.educlass BasicPioDevice : public PioDevice
2182817Sksewell@umich.edu{
2192817Sksewell@umich.edu  public:
2202817Sksewell@umich.edu    struct Params :  public PioDevice::Params
2212817Sksewell@umich.edu    {
2222817Sksewell@umich.edu        Addr pio_addr;
2232817Sksewell@umich.edu        Tick pio_delay;
2242817Sksewell@umich.edu    };
2252817Sksewell@umich.edu
2262817Sksewell@umich.edu  protected:
2272817Sksewell@umich.edu    /** Address that the device listens to. */
2282817Sksewell@umich.edu    Addr pioAddr;
2292817Sksewell@umich.edu
2302817Sksewell@umich.edu    /** Size that the device's address range. */
2312817Sksewell@umich.edu    Addr pioSize;
2322817Sksewell@umich.edu
2332817Sksewell@umich.edu    /** Delay that the device experinces on an access. */
2342817Sksewell@umich.edu    Tick pioDelay;
2352817Sksewell@umich.edu
2362817Sksewell@umich.edu  public:
2372817Sksewell@umich.edu    BasicPioDevice(Params *p)
2382817Sksewell@umich.edu        : PioDevice(p), pioAddr(p->pio_addr), pioSize(0),
2392817Sksewell@umich.edu          pioDelay(p->pio_delay)
2402817Sksewell@umich.edu    {}
2412817Sksewell@umich.edu
2422817Sksewell@umich.edu    /** return the address ranges that this device responds to.
2432817Sksewell@umich.edu     * @param range_list range list to populate with ranges
2442817Sksewell@umich.edu     */
2452817Sksewell@umich.edu    void addressRanges(AddrRangeList &range_list);
2462817Sksewell@umich.edu
2472817Sksewell@umich.edu};
2482817Sksewell@umich.edu
2492817Sksewell@umich.educlass DmaDevice : public PioDevice
2502817Sksewell@umich.edu{
2512817Sksewell@umich.edu  protected:
2522817Sksewell@umich.edu    DmaPort *dmaPort;
2532817Sksewell@umich.edu
2542817Sksewell@umich.edu  public:
2552817Sksewell@umich.edu    DmaDevice(Params *p);
2562817Sksewell@umich.edu    virtual ~DmaDevice();
2572817Sksewell@umich.edu
2582817Sksewell@umich.edu    void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
2592817Sksewell@umich.edu    { dmaPort->dmaAction(Packet::WriteInvalidateReq, addr, size, event, data) ; }
2602817Sksewell@umich.edu
2612817Sksewell@umich.edu    void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
2622817Sksewell@umich.edu    { dmaPort->dmaAction(Packet::ReadReq, addr, size, event, data); }
2632817Sksewell@umich.edu
2642817Sksewell@umich.edu    bool dmaPending() { return dmaPort->dmaPending(); }
2652817Sksewell@umich.edu
2662817Sksewell@umich.edu    virtual unsigned int drain(Event *de);
2672817Sksewell@umich.edu
2682817Sksewell@umich.edu    virtual Port *getPort(const std::string &if_name, int idx = -1)
2692817Sksewell@umich.edu    {
2702817Sksewell@umich.edu        if (if_name == "pio") {
2712817Sksewell@umich.edu            if (pioPort != NULL)
2722817Sksewell@umich.edu                panic("pio port already connected to.");
2732817Sksewell@umich.edu            pioPort = new PioPort(this, sys);
2742817Sksewell@umich.edu            return pioPort;
2752817Sksewell@umich.edu        } else if (if_name == "dma") {
2762817Sksewell@umich.edu            if (dmaPort != NULL)
2772817Sksewell@umich.edu                panic("dma port already connected to.");
2782817Sksewell@umich.edu            dmaPort = new DmaPort(this, sys);
2792817Sksewell@umich.edu            return dmaPort;
2802817Sksewell@umich.edu        } else
2812817Sksewell@umich.edu            return NULL;
2822817Sksewell@umich.edu    }
2832817Sksewell@umich.edu
2842817Sksewell@umich.edu    friend class DmaPort;
2852817Sksewell@umich.edu};
2862986Sgblack@eecs.umich.edu
2872817Sksewell@umich.edu
2882817Sksewell@umich.edu#endif // __DEV_IO_DEVICE_HH__
2892817Sksewell@umich.edu