dma_device.hh revision 11169
1545SN/A/* 211010Sandreas.sandberg@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited 38948SN/A * All rights reserved. 48948SN/A * 58948SN/A * The license below extends only to copyright in the software and shall 68948SN/A * not be construed as granting a license to any other intellectual 78948SN/A * property including but not limited to intellectual property relating 88948SN/A * to a hardware implementation of the functionality of the software 98948SN/A * licensed hereunder. You may use the software subject to the license 108948SN/A * terms below provided that you ensure that this notice is replicated 118948SN/A * unmodified and in its entirety in all distributions of the software, 128948SN/A * modified or unmodified, in source code or in binary form. 138948SN/A * 141762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 15545SN/A * All rights reserved. 16545SN/A * 17545SN/A * Redistribution and use in source and binary forms, with or without 18545SN/A * modification, are permitted provided that the following conditions are 19545SN/A * met: redistributions of source code must retain the above copyright 20545SN/A * notice, this list of conditions and the following disclaimer; 21545SN/A * redistributions in binary form must reproduce the above copyright 22545SN/A * notice, this list of conditions and the following disclaimer in the 23545SN/A * documentation and/or other materials provided with the distribution; 24545SN/A * neither the name of the copyright holders nor the names of its 25545SN/A * contributors may be used to endorse or promote products derived from 26545SN/A * this software without specific prior written permission. 27545SN/A * 28545SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29545SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30545SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31545SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32545SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33545SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34545SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35545SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36545SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37545SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38545SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Ali Saidi 412665SN/A * Nathan Binkert 4211010Sandreas.sandberg@arm.com * Andreas Sandberg 43545SN/A */ 44545SN/A 459016Sandreas.hansson@arm.com#ifndef __DEV_DMA_DEVICE_HH__ 469016Sandreas.hansson@arm.com#define __DEV_DMA_DEVICE_HH__ 47545SN/A 489166Sandreas.hansson@arm.com#include <deque> 4911010Sandreas.sandberg@arm.com#include <memory> 509166Sandreas.hansson@arm.com 5111010Sandreas.sandberg@arm.com#include "base/circlebuf.hh" 529016Sandreas.hansson@arm.com#include "dev/io_device.hh" 534762SN/A#include "params/DmaDevice.hh" 549342SAndreas.Sandberg@arm.com#include "sim/drain.hh" 559814Sandreas.hansson@arm.com#include "sim/system.hh" 562565SN/A 5710912Sandreas.sandberg@arm.comclass DmaPort : public MasterPort, public Drainable 582384SN/A{ 599307Sandreas.hansson@arm.com private: 602784SN/A 619307Sandreas.hansson@arm.com /** 629307Sandreas.hansson@arm.com * Take the first packet of the transmit list and attempt to send 639307Sandreas.hansson@arm.com * it as a timing request. If it is successful, schedule the 649307Sandreas.hansson@arm.com * sending of the next packet, otherwise remember that we are 659307Sandreas.hansson@arm.com * waiting for a retry. 669307Sandreas.hansson@arm.com */ 679307Sandreas.hansson@arm.com void trySendTimingReq(); 682784SN/A 699307Sandreas.hansson@arm.com /** 709307Sandreas.hansson@arm.com * For timing, attempt to send the first item on the transmit 719307Sandreas.hansson@arm.com * list, and if it is successful and there are more packets 729307Sandreas.hansson@arm.com * waiting, then schedule the sending of the next packet. For 739307Sandreas.hansson@arm.com * atomic, simply send and process everything on the transmit 749307Sandreas.hansson@arm.com * list. 759307Sandreas.hansson@arm.com */ 769307Sandreas.hansson@arm.com void sendDma(); 774435SN/A 789166Sandreas.hansson@arm.com /** 799166Sandreas.hansson@arm.com * Handle a response packet by updating the corresponding DMA 809166Sandreas.hansson@arm.com * request state to reflect the bytes received, and also update 819166Sandreas.hansson@arm.com * the pending request counter. If the DMA request that this 829166Sandreas.hansson@arm.com * packet is part of is complete, then signal the completion event 839166Sandreas.hansson@arm.com * if present, potentially with a delay added to it. 849166Sandreas.hansson@arm.com * 859166Sandreas.hansson@arm.com * @param pkt Response packet to handler 869166Sandreas.hansson@arm.com * @param delay Additional delay for scheduling the completion event 879166Sandreas.hansson@arm.com */ 889166Sandreas.hansson@arm.com void handleResp(PacketPtr pkt, Tick delay = 0); 898948SN/A 909307Sandreas.hansson@arm.com struct DmaReqState : public Packet::SenderState 919307Sandreas.hansson@arm.com { 929307Sandreas.hansson@arm.com /** Event to call on the device when this transaction (all packets) 939307Sandreas.hansson@arm.com * complete. */ 949307Sandreas.hansson@arm.com Event *completionEvent; 959307Sandreas.hansson@arm.com 969307Sandreas.hansson@arm.com /** Total number of bytes that this transaction involves. */ 979307Sandreas.hansson@arm.com const Addr totBytes; 989307Sandreas.hansson@arm.com 999307Sandreas.hansson@arm.com /** Number of bytes that have been acked for this transaction. */ 1009307Sandreas.hansson@arm.com Addr numBytes; 1019307Sandreas.hansson@arm.com 1029307Sandreas.hansson@arm.com /** Amount to delay completion of dma by */ 1039307Sandreas.hansson@arm.com const Tick delay; 1049307Sandreas.hansson@arm.com 1059307Sandreas.hansson@arm.com DmaReqState(Event *ce, Addr tb, Tick _delay) 1069307Sandreas.hansson@arm.com : completionEvent(ce), totBytes(tb), numBytes(0), delay(_delay) 1079307Sandreas.hansson@arm.com {} 1089307Sandreas.hansson@arm.com }; 1099307Sandreas.hansson@arm.com 11011010Sandreas.sandberg@arm.com public: 1119307Sandreas.hansson@arm.com /** The device that owns this port. */ 11211010Sandreas.sandberg@arm.com MemObject *const device; 1139307Sandreas.hansson@arm.com 11411010Sandreas.sandberg@arm.com /** The system that device/port are in. This is used to select which mode 11511010Sandreas.sandberg@arm.com * we are currently operating in. */ 11611010Sandreas.sandberg@arm.com System *const sys; 11711010Sandreas.sandberg@arm.com 11811010Sandreas.sandberg@arm.com /** Id for all requests */ 11911010Sandreas.sandberg@arm.com const MasterID masterId; 12011010Sandreas.sandberg@arm.com 12111010Sandreas.sandberg@arm.com protected: 1229307Sandreas.hansson@arm.com /** Use a deque as we never do any insertion or removal in the middle */ 1239307Sandreas.hansson@arm.com std::deque<PacketPtr> transmitList; 1249307Sandreas.hansson@arm.com 1259307Sandreas.hansson@arm.com /** Event used to schedule a future sending from the transmit list. */ 1269307Sandreas.hansson@arm.com EventWrapper<DmaPort, &DmaPort::sendDma> sendEvent; 1279307Sandreas.hansson@arm.com 1289307Sandreas.hansson@arm.com /** Number of outstanding packets the dma port has. */ 1299307Sandreas.hansson@arm.com uint32_t pendingCount; 1309307Sandreas.hansson@arm.com 1319307Sandreas.hansson@arm.com /** If the port is currently waiting for a retry before it can 1329307Sandreas.hansson@arm.com * send whatever it is that it's sending. */ 1339307Sandreas.hansson@arm.com bool inRetry; 1349307Sandreas.hansson@arm.com 1359307Sandreas.hansson@arm.com protected: 1369307Sandreas.hansson@arm.com 13711169Sandreas.hansson@arm.com bool recvTimingResp(PacketPtr pkt) override; 13811169Sandreas.hansson@arm.com void recvReqRetry() override; 1392384SN/A 1409166Sandreas.hansson@arm.com void queueDma(PacketPtr pkt); 1414435SN/A 1429165Sandreas.hansson@arm.com public: 1432489SN/A 1449165Sandreas.hansson@arm.com DmaPort(MemObject *dev, System *s); 1452565SN/A 14610621SCurtis.Dunham@arm.com RequestPtr dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, 14710621SCurtis.Dunham@arm.com uint8_t *data, Tick delay, Request::Flags flag = 0); 1482565SN/A 1499166Sandreas.hansson@arm.com bool dmaPending() const { return pendingCount > 0; } 1502384SN/A 15111168Sandreas.hansson@arm.com DrainState drain() override; 1522384SN/A}; 1532384SN/A 154545SN/Aclass DmaDevice : public PioDevice 155545SN/A{ 1564435SN/A protected: 1578851SN/A DmaPort dmaPort; 158545SN/A 159545SN/A public: 1604762SN/A typedef DmaDeviceParams Params; 1614762SN/A DmaDevice(const Params *p); 1629166Sandreas.hansson@arm.com virtual ~DmaDevice() { } 1634762SN/A 1648851SN/A void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, 1658851SN/A Tick delay = 0) 1664022SN/A { 1678851SN/A dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); 1684022SN/A } 1692565SN/A 1708851SN/A void dmaRead(Addr addr, int size, Event *event, uint8_t *data, 1718851SN/A Tick delay = 0) 1724263SN/A { 1738851SN/A dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); 1744263SN/A } 1752565SN/A 1769307Sandreas.hansson@arm.com bool dmaPending() const { return dmaPort.dmaPending(); } 1778851SN/A 17811169Sandreas.hansson@arm.com void init() override; 1792565SN/A 1809814Sandreas.hansson@arm.com unsigned int cacheBlockSize() const { return sys->cacheLineSize(); } 1814263SN/A 18211169Sandreas.hansson@arm.com BaseMasterPort &getMasterPort(const std::string &if_name, 18311169Sandreas.hansson@arm.com PortID idx = InvalidPortID) override; 1842489SN/A 185545SN/A}; 186545SN/A 18711010Sandreas.sandberg@arm.com/** 18811010Sandreas.sandberg@arm.com * Buffered DMA engine helper class 18911010Sandreas.sandberg@arm.com * 19011010Sandreas.sandberg@arm.com * This class implements a simple DMA engine that feeds a FIFO 19111010Sandreas.sandberg@arm.com * buffer. The size of the buffer, the maximum number of pending 19211010Sandreas.sandberg@arm.com * requests and the maximum request size are all set when the engine 19311010Sandreas.sandberg@arm.com * is instantiated. 19411010Sandreas.sandberg@arm.com * 19511010Sandreas.sandberg@arm.com * An <i>asynchronous</i> transfer of a <i>block</i> of data 19611010Sandreas.sandberg@arm.com * (designated by a start address and a size) is started by calling 19711010Sandreas.sandberg@arm.com * the startFill() method. The DMA engine will aggressively try to 19811010Sandreas.sandberg@arm.com * keep the internal FIFO full. As soon as there is room in the FIFO 19911010Sandreas.sandberg@arm.com * for more data <i>and</i> there are free request slots, a new fill 20011010Sandreas.sandberg@arm.com * will be started. 20111010Sandreas.sandberg@arm.com * 20211010Sandreas.sandberg@arm.com * Data in the FIFO can be read back using the get() and tryGet() 20311010Sandreas.sandberg@arm.com * methods. Both request a block of data from the FIFO. However, get() 20411010Sandreas.sandberg@arm.com * panics if the block cannot be satisfied, while tryGet() simply 20511010Sandreas.sandberg@arm.com * returns false. The latter call makes it possible to implement 20611010Sandreas.sandberg@arm.com * custom buffer underrun handling. 20711010Sandreas.sandberg@arm.com * 20811010Sandreas.sandberg@arm.com * A simple use case would be something like this: 20911010Sandreas.sandberg@arm.com * \code{.cpp} 21011010Sandreas.sandberg@arm.com * // Create a DMA engine with a 1KiB buffer. Issue up to 8 concurrent 21111010Sandreas.sandberg@arm.com * // uncacheable 64 byte (maximum) requests. 21211010Sandreas.sandberg@arm.com * DmaReadFifo *dma = new DmaReadFifo(port, 1024, 64, 8, 21311010Sandreas.sandberg@arm.com * Request::UNCACHEABLE); 21411010Sandreas.sandberg@arm.com * 21511010Sandreas.sandberg@arm.com * // Start copying 4KiB data from 0xFF000000 21611010Sandreas.sandberg@arm.com * dma->startFill(0xFF000000, 0x1000); 21711010Sandreas.sandberg@arm.com * 21811010Sandreas.sandberg@arm.com * // Some time later when there is data in the FIFO. 21911010Sandreas.sandberg@arm.com * uint8_t data[8]; 22011010Sandreas.sandberg@arm.com * dma->get(data, sizeof(data)) 22111010Sandreas.sandberg@arm.com * \endcode 22211010Sandreas.sandberg@arm.com * 22311010Sandreas.sandberg@arm.com * 22411010Sandreas.sandberg@arm.com * The DMA engine allows new blocks to be requested as soon as the 22511010Sandreas.sandberg@arm.com * last request for a block has been sent (i.e., there is no need to 22611010Sandreas.sandberg@arm.com * wait for pending requests to complete). This can be queried with 22711010Sandreas.sandberg@arm.com * the atEndOfBlock() method and more advanced implementations may 22811010Sandreas.sandberg@arm.com * override the onEndOfBlock() callback. 22911010Sandreas.sandberg@arm.com */ 23011010Sandreas.sandberg@arm.comclass DmaReadFifo : public Drainable, public Serializable 23111010Sandreas.sandberg@arm.com{ 23211010Sandreas.sandberg@arm.com public: 23311010Sandreas.sandberg@arm.com DmaReadFifo(DmaPort &port, size_t size, 23411010Sandreas.sandberg@arm.com unsigned max_req_size, 23511010Sandreas.sandberg@arm.com unsigned max_pending, 23611010Sandreas.sandberg@arm.com Request::Flags flags = 0); 23711010Sandreas.sandberg@arm.com 23811010Sandreas.sandberg@arm.com ~DmaReadFifo(); 23911010Sandreas.sandberg@arm.com 24011010Sandreas.sandberg@arm.com public: // Serializable 24111168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 24211168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 24311010Sandreas.sandberg@arm.com 24411010Sandreas.sandberg@arm.com public: // Drainable 24511168Sandreas.hansson@arm.com DrainState drain() override; 24611010Sandreas.sandberg@arm.com 24711010Sandreas.sandberg@arm.com public: // FIFO access 24811010Sandreas.sandberg@arm.com /** 24911010Sandreas.sandberg@arm.com * @{ 25011010Sandreas.sandberg@arm.com * @name FIFO access 25111010Sandreas.sandberg@arm.com */ 25211010Sandreas.sandberg@arm.com /** 25311010Sandreas.sandberg@arm.com * Try to read data from the FIFO. 25411010Sandreas.sandberg@arm.com * 25511010Sandreas.sandberg@arm.com * This method reads len bytes of data from the FIFO and stores 25611010Sandreas.sandberg@arm.com * them in the memory location pointed to by dst. The method 25711010Sandreas.sandberg@arm.com * fails, and no data is written to the buffer, if the FIFO 25811010Sandreas.sandberg@arm.com * doesn't contain enough data to satisfy the request. 25911010Sandreas.sandberg@arm.com * 26011010Sandreas.sandberg@arm.com * @param dst Pointer to a destination buffer 26111010Sandreas.sandberg@arm.com * @param len Amount of data to read. 26211010Sandreas.sandberg@arm.com * @return true on success, false otherwise. 26311010Sandreas.sandberg@arm.com */ 26411010Sandreas.sandberg@arm.com bool tryGet(uint8_t *dst, size_t len); 26511010Sandreas.sandberg@arm.com 26611010Sandreas.sandberg@arm.com template<typename T> 26711010Sandreas.sandberg@arm.com bool tryGet(T &value) { 26811010Sandreas.sandberg@arm.com return tryGet(static_cast<T *>(&value), sizeof(T)); 26911010Sandreas.sandberg@arm.com }; 27011010Sandreas.sandberg@arm.com 27111010Sandreas.sandberg@arm.com /** 27211010Sandreas.sandberg@arm.com * Read data from the FIFO and panic on failure. 27311010Sandreas.sandberg@arm.com * 27411010Sandreas.sandberg@arm.com * @see tryGet() 27511010Sandreas.sandberg@arm.com * 27611010Sandreas.sandberg@arm.com * @param dst Pointer to a destination buffer 27711010Sandreas.sandberg@arm.com * @param len Amount of data to read. 27811010Sandreas.sandberg@arm.com */ 27911010Sandreas.sandberg@arm.com void get(uint8_t *dst, size_t len); 28011010Sandreas.sandberg@arm.com 28111010Sandreas.sandberg@arm.com template<typename T> 28211010Sandreas.sandberg@arm.com T get() { 28311010Sandreas.sandberg@arm.com T value; 28411010Sandreas.sandberg@arm.com get(static_cast<uint8_t *>(&value), sizeof(T)); 28511010Sandreas.sandberg@arm.com return value; 28611010Sandreas.sandberg@arm.com }; 28711010Sandreas.sandberg@arm.com 28811010Sandreas.sandberg@arm.com /** Get the amount of data stored in the FIFO */ 28911010Sandreas.sandberg@arm.com size_t size() const { return buffer.size(); } 29011010Sandreas.sandberg@arm.com /** Flush the FIFO */ 29111010Sandreas.sandberg@arm.com void flush() { buffer.flush(); } 29211010Sandreas.sandberg@arm.com 29311010Sandreas.sandberg@arm.com /** @} */ 29411010Sandreas.sandberg@arm.com public: // FIFO fill control 29511010Sandreas.sandberg@arm.com /** 29611010Sandreas.sandberg@arm.com * @{ 29711010Sandreas.sandberg@arm.com * @name FIFO fill control 29811010Sandreas.sandberg@arm.com */ 29911010Sandreas.sandberg@arm.com /** 30011010Sandreas.sandberg@arm.com * Start filling the FIFO. 30111010Sandreas.sandberg@arm.com * 30211010Sandreas.sandberg@arm.com * @warn It's considered an error to call start on an active DMA 30311010Sandreas.sandberg@arm.com * engine unless the last request from the active block has been 30411010Sandreas.sandberg@arm.com * sent (i.e., atEndOfBlock() is true). 30511010Sandreas.sandberg@arm.com * 30611010Sandreas.sandberg@arm.com * @param start Physical address to copy from. 30711010Sandreas.sandberg@arm.com * @param size Size of the block to copy. 30811010Sandreas.sandberg@arm.com */ 30911010Sandreas.sandberg@arm.com void startFill(Addr start, size_t size); 31011010Sandreas.sandberg@arm.com 31111010Sandreas.sandberg@arm.com /** 31211010Sandreas.sandberg@arm.com * Stop the DMA engine. 31311010Sandreas.sandberg@arm.com * 31411010Sandreas.sandberg@arm.com * Stop filling the FIFO and ignore incoming responses for pending 31511010Sandreas.sandberg@arm.com * requests. The onEndOfBlock() callback will not be called after 31611010Sandreas.sandberg@arm.com * this method has been invoked. However, once the last response 31711010Sandreas.sandberg@arm.com * has been received, the onIdle() callback will still be called. 31811010Sandreas.sandberg@arm.com */ 31911010Sandreas.sandberg@arm.com void stopFill(); 32011010Sandreas.sandberg@arm.com 32111010Sandreas.sandberg@arm.com /** 32211010Sandreas.sandberg@arm.com * Has the DMA engine sent out the last request for the active 32311010Sandreas.sandberg@arm.com * block? 32411010Sandreas.sandberg@arm.com */ 32511010Sandreas.sandberg@arm.com bool atEndOfBlock() const { 32611010Sandreas.sandberg@arm.com return nextAddr == endAddr; 32711010Sandreas.sandberg@arm.com } 32811010Sandreas.sandberg@arm.com 32911010Sandreas.sandberg@arm.com /** 33011010Sandreas.sandberg@arm.com * Is the DMA engine active (i.e., are there still in-flight 33111010Sandreas.sandberg@arm.com * accesses)? 33211010Sandreas.sandberg@arm.com */ 33311010Sandreas.sandberg@arm.com bool isActive() const { 33411010Sandreas.sandberg@arm.com return !(pendingRequests.empty() && atEndOfBlock()); 33511010Sandreas.sandberg@arm.com } 33611010Sandreas.sandberg@arm.com 33711010Sandreas.sandberg@arm.com /** @} */ 33811010Sandreas.sandberg@arm.com protected: // Callbacks 33911010Sandreas.sandberg@arm.com /** 34011010Sandreas.sandberg@arm.com * @{ 34111010Sandreas.sandberg@arm.com * @name Callbacks 34211010Sandreas.sandberg@arm.com */ 34311010Sandreas.sandberg@arm.com /** 34411010Sandreas.sandberg@arm.com * End of block callback 34511010Sandreas.sandberg@arm.com * 34611010Sandreas.sandberg@arm.com * This callback is called <i>once</i> after the last access in a 34711010Sandreas.sandberg@arm.com * block has been sent. It is legal for a derived class to call 34811010Sandreas.sandberg@arm.com * startFill() from this method to initiate a transfer. 34911010Sandreas.sandberg@arm.com */ 35011010Sandreas.sandberg@arm.com virtual void onEndOfBlock() {}; 35111010Sandreas.sandberg@arm.com 35211010Sandreas.sandberg@arm.com /** 35311010Sandreas.sandberg@arm.com * Last response received callback 35411010Sandreas.sandberg@arm.com * 35511010Sandreas.sandberg@arm.com * This callback is called when the DMA engine becomes idle (i.e., 35611010Sandreas.sandberg@arm.com * there are no pending requests). 35711010Sandreas.sandberg@arm.com * 35811010Sandreas.sandberg@arm.com * It is possible for a DMA engine to reach the end of block and 35911010Sandreas.sandberg@arm.com * become idle at the same tick. In such a case, the 36011010Sandreas.sandberg@arm.com * onEndOfBlock() callback will be called first. This callback 36111010Sandreas.sandberg@arm.com * will <i>NOT</i> be called if that callback initiates a new DMA transfer. 36211010Sandreas.sandberg@arm.com */ 36311010Sandreas.sandberg@arm.com virtual void onIdle() {}; 36411010Sandreas.sandberg@arm.com 36511010Sandreas.sandberg@arm.com /** @} */ 36611010Sandreas.sandberg@arm.com private: // Configuration 36711010Sandreas.sandberg@arm.com /** Maximum request size in bytes */ 36811010Sandreas.sandberg@arm.com const Addr maxReqSize; 36911010Sandreas.sandberg@arm.com /** Maximum FIFO size in bytes */ 37011010Sandreas.sandberg@arm.com const size_t fifoSize; 37111010Sandreas.sandberg@arm.com /** Request flags */ 37211010Sandreas.sandberg@arm.com const Request::Flags reqFlags; 37311010Sandreas.sandberg@arm.com 37411010Sandreas.sandberg@arm.com DmaPort &port; 37511010Sandreas.sandberg@arm.com 37611010Sandreas.sandberg@arm.com private: 37711010Sandreas.sandberg@arm.com class DmaDoneEvent : public Event 37811010Sandreas.sandberg@arm.com { 37911010Sandreas.sandberg@arm.com public: 38011010Sandreas.sandberg@arm.com DmaDoneEvent(DmaReadFifo *_parent, size_t max_size); 38111010Sandreas.sandberg@arm.com 38211010Sandreas.sandberg@arm.com void kill(); 38311010Sandreas.sandberg@arm.com void cancel(); 38411010Sandreas.sandberg@arm.com bool canceled() const { return _canceled; } 38511010Sandreas.sandberg@arm.com void reset(size_t size); 38611010Sandreas.sandberg@arm.com void process(); 38711010Sandreas.sandberg@arm.com 38811010Sandreas.sandberg@arm.com bool done() const { return _done; } 38911010Sandreas.sandberg@arm.com size_t requestSize() const { return _requestSize; } 39011010Sandreas.sandberg@arm.com const uint8_t *data() const { return _data.data(); } 39111010Sandreas.sandberg@arm.com uint8_t *data() { return _data.data(); } 39211010Sandreas.sandberg@arm.com 39311010Sandreas.sandberg@arm.com private: 39411010Sandreas.sandberg@arm.com DmaReadFifo *parent; 39511010Sandreas.sandberg@arm.com bool _done; 39611010Sandreas.sandberg@arm.com bool _canceled; 39711010Sandreas.sandberg@arm.com size_t _requestSize; 39811010Sandreas.sandberg@arm.com std::vector<uint8_t> _data; 39911010Sandreas.sandberg@arm.com }; 40011010Sandreas.sandberg@arm.com 40111010Sandreas.sandberg@arm.com typedef std::unique_ptr<DmaDoneEvent> DmaDoneEventUPtr; 40211010Sandreas.sandberg@arm.com 40311010Sandreas.sandberg@arm.com /** 40411010Sandreas.sandberg@arm.com * DMA request done, handle incoming data and issue new 40511010Sandreas.sandberg@arm.com * request. 40611010Sandreas.sandberg@arm.com */ 40711010Sandreas.sandberg@arm.com void dmaDone(); 40811010Sandreas.sandberg@arm.com 40911010Sandreas.sandberg@arm.com /** Handle pending requests that have been flagged as done. */ 41011010Sandreas.sandberg@arm.com void handlePending(); 41111010Sandreas.sandberg@arm.com 41211010Sandreas.sandberg@arm.com /** Try to issue new DMA requests */ 41311010Sandreas.sandberg@arm.com void resumeFill(); 41411010Sandreas.sandberg@arm.com 41511010Sandreas.sandberg@arm.com private: // Internal state 41611010Sandreas.sandberg@arm.com Fifo<uint8_t> buffer; 41711010Sandreas.sandberg@arm.com 41811010Sandreas.sandberg@arm.com Addr nextAddr; 41911010Sandreas.sandberg@arm.com Addr endAddr; 42011010Sandreas.sandberg@arm.com 42111010Sandreas.sandberg@arm.com std::deque<DmaDoneEventUPtr> pendingRequests; 42211010Sandreas.sandberg@arm.com std::deque<DmaDoneEventUPtr> freeRequests; 42311010Sandreas.sandberg@arm.com}; 42411010Sandreas.sandberg@arm.com 4259016Sandreas.hansson@arm.com#endif // __DEV_DMA_DEVICE_HH__ 426