io_device.hh revision 9015:7f4d25789dc4
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 *          Nathan Binkert
42 */
43
44#ifndef __DEV_IO_DEVICE_HH__
45#define __DEV_IO_DEVICE_HH__
46
47#include "base/fast_alloc.hh"
48#include "mem/mem_object.hh"
49#include "mem/packet.hh"
50#include "mem/tport.hh"
51#include "params/BasicPioDevice.hh"
52#include "params/DmaDevice.hh"
53#include "params/PioDevice.hh"
54#include "sim/sim_object.hh"
55
56class Event;
57class PioDevice;
58class DmaDevice;
59class System;
60
61/**
62 * The PioPort class is a programmed i/o port that all devices that are
63 * sensitive to an address range use. The port takes all the memory
64 * access types and roles them into one read() and write() call that the device
65 * must respond to. The device must also provide getAddrRanges() function
66 * with which it returns the address ranges it is interested in.
67 */
68class PioPort : public SimpleTimingPort
69{
70  protected:
71    /** The device that this port serves. */
72    PioDevice *device;
73
74    virtual Tick recvAtomic(PacketPtr pkt);
75
76    virtual AddrRangeList getAddrRanges();
77
78  public:
79
80    PioPort(PioDevice *dev);
81};
82
83
84class DmaPort : public MasterPort
85{
86  protected:
87    struct DmaReqState : public Packet::SenderState, public FastAlloc
88    {
89        /** Event to call on the device when this transaction (all packets)
90         * complete. */
91        Event *completionEvent;
92
93        /** Where we came from for some sanity checking. */
94        Port *outPort;
95
96        /** Total number of bytes that this transaction involves. */
97        Addr totBytes;
98
99        /** Number of bytes that have been acked for this transaction. */
100        Addr numBytes;
101
102        /** Amount to delay completion of dma by */
103        Tick delay;
104
105
106        DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay)
107            : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0),
108              delay(_delay)
109        {}
110    };
111
112    MemObject *device;
113    std::list<PacketPtr> transmitList;
114
115    /** The system that device/port are in. This is used to select which mode
116     * we are currently operating in. */
117    System *sys;
118
119    /** Id for all requests */
120    MasterID masterId;
121
122    /** Number of outstanding packets the dma port has. */
123    int pendingCount;
124
125    /** If a dmaAction is in progress. */
126    int actionInProgress;
127
128    /** If we need to drain, keep the drain event around until we're done
129     * here.*/
130    Event *drainEvent;
131
132    /** time to wait between sending another packet, increases as NACKs are
133     * recived, decreases as responses are recived. */
134    Tick backoffTime;
135
136    /** Minimum time that device should back off for after failed sendTiming */
137    Tick minBackoffDelay;
138
139    /** Maximum time that device should back off for after failed sendTiming */
140    Tick maxBackoffDelay;
141
142    /** If the port is currently waiting for a retry before it can send whatever
143     * it is that it's sending. */
144    bool inRetry;
145
146    virtual bool recvTimingResp(PacketPtr pkt);
147
148    virtual void recvRetry() ;
149
150    void queueDma(PacketPtr pkt, bool front = false);
151    void sendDma();
152
153    /** event to give us a kick every time we backoff time is reached. */
154    EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent;
155
156  public:
157    DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff);
158
159    void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
160                   uint8_t *data, Tick delay, Request::Flags flag = 0);
161
162    bool dmaPending() { return pendingCount > 0; }
163
164    unsigned cacheBlockSize() const { return peerBlockSize(); }
165    unsigned int drain(Event *de);
166};
167
168/**
169 * This device is the base class which all devices senstive to an address range
170 * inherit from. There are three pure virtual functions which all devices must
171 * implement getAddrRanges(), read(), and write(). The magic do choose which
172 * mode we are in, etc is handled by the PioPort so the device doesn't have to
173 * bother.
174 */
175class PioDevice : public MemObject
176{
177  protected:
178    System *sys;
179
180    /** The pioPort that handles the requests for us and provides us requests
181     * that it sees. */
182    PioPort pioPort;
183
184    /**
185     * Every PIO device is obliged to provide an implementation that
186     * returns the address ranges the device responds to.
187     *
188     * @return a list of non-overlapping address ranges
189     */
190    virtual AddrRangeList getAddrRanges() = 0;
191
192    /** Pure virtual function that the device must implement. Called
193     * when a read command is recieved by the port.
194     * @param pkt Packet describing this request
195     * @return number of ticks it took to complete
196     */
197    virtual Tick read(PacketPtr pkt) = 0;
198
199    /** Pure virtual function that the device must implement. Called when a
200     * write command is recieved by the port.
201     * @param pkt Packet describing this request
202     * @return number of ticks it took to complete
203     */
204    virtual Tick write(PacketPtr pkt) = 0;
205
206  public:
207    typedef PioDeviceParams Params;
208    PioDevice(const Params *p);
209    virtual ~PioDevice();
210
211    const Params *
212    params() const
213    {
214        return dynamic_cast<const Params *>(_params);
215    }
216
217    virtual void init();
218
219    virtual unsigned int drain(Event *de);
220
221    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
222
223    friend class PioPort;
224
225};
226
227class BasicPioDevice : public PioDevice
228{
229  protected:
230    /** Address that the device listens to. */
231    Addr pioAddr;
232
233    /** Size that the device's address range. */
234    Addr pioSize;
235
236    /** Delay that the device experinces on an access. */
237    Tick pioDelay;
238
239  public:
240    typedef BasicPioDeviceParams Params;
241    BasicPioDevice(const Params *p);
242
243    const Params *
244    params() const
245    {
246        return dynamic_cast<const Params *>(_params);
247    }
248
249    /**
250     * Determine the address ranges that this device responds to.
251     *
252     * @return a list of non-overlapping address ranges
253     */
254    virtual AddrRangeList getAddrRanges();
255
256};
257
258class DmaDevice : public PioDevice
259{
260   protected:
261    DmaPort dmaPort;
262
263  public:
264    typedef DmaDeviceParams Params;
265    DmaDevice(const Params *p);
266    virtual ~DmaDevice();
267
268    const Params *
269    params() const
270    {
271        return dynamic_cast<const Params *>(_params);
272    }
273
274    void dmaWrite(Addr addr, int size, Event *event, uint8_t *data,
275                  Tick delay = 0)
276    {
277        dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay);
278    }
279
280    void dmaRead(Addr addr, int size, Event *event, uint8_t *data,
281                 Tick delay = 0)
282    {
283        dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay);
284    }
285
286    bool dmaPending() { return dmaPort.dmaPending(); }
287
288    virtual void init();
289
290    virtual unsigned int drain(Event *de);
291
292    unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); }
293
294    virtual MasterPort &getMasterPort(const std::string &if_name,
295                                      int idx = -1);
296
297    friend class DmaPort;
298};
299
300
301#endif // __DEV_IO_DEVICE_HH__
302