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