dev: Add a DmaCallback class to DmaDevice
This patch introduces the DmaCallback helper class, which registers a callback to fire after a sequence of (potentially non-contiguous) DMA transfers on a DmaPort completes.
This commit is contained in:
parent
f17a5faf44
commit
6e4c51fa99
1 changed files with 85 additions and 0 deletions
|
@ -184,6 +184,91 @@ class DmaDevice : public PioDevice
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* DMA callback class.
|
||||
*
|
||||
* Allows one to register for a callback event after a sequence of (potentially
|
||||
* non-contiguous) DMA transfers on a DmaPort completes. Derived classes must
|
||||
* implement the process() method and use getChunkEvent() to allocate a
|
||||
* callback event for each participating DMA.
|
||||
*/
|
||||
class DmaCallback : public Drainable
|
||||
{
|
||||
public:
|
||||
virtual const std::string name() const { return "DmaCallback"; }
|
||||
|
||||
/**
|
||||
* DmaPort ensures that all oustanding DMA accesses have completed before
|
||||
* it finishes draining. However, DmaChunkEvents scheduled with a delay
|
||||
* might still be sitting on the event queue. Therefore, draining is not
|
||||
* complete until count is 0, which ensures that all outstanding
|
||||
* DmaChunkEvents associated with this DmaCallback have fired.
|
||||
*/
|
||||
DrainState drain() override
|
||||
{
|
||||
return count ? DrainState::Draining : DrainState::Drained;
|
||||
}
|
||||
|
||||
protected:
|
||||
int count;
|
||||
|
||||
DmaCallback()
|
||||
: count(0)
|
||||
{ }
|
||||
|
||||
virtual ~DmaCallback() { }
|
||||
|
||||
/**
|
||||
* Callback function invoked on completion of all chunks.
|
||||
*/
|
||||
virtual void process() = 0;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called by DMA engine completion event on each chunk completion.
|
||||
* Since the object may delete itself here, callers should not use
|
||||
* the object pointer after calling this function.
|
||||
*/
|
||||
void chunkComplete()
|
||||
{
|
||||
if (--count == 0) {
|
||||
process();
|
||||
// Need to notify DrainManager that this object is finished
|
||||
// draining, even though it is immediately deleted.
|
||||
signalDrainDone();
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event invoked by DmaDevice on completion of each chunk.
|
||||
*/
|
||||
class DmaChunkEvent : public Event
|
||||
{
|
||||
private:
|
||||
DmaCallback *callback;
|
||||
|
||||
public:
|
||||
DmaChunkEvent(DmaCallback *cb)
|
||||
: Event(Default_Pri, AutoDelete), callback(cb)
|
||||
{ }
|
||||
|
||||
void process() { callback->chunkComplete(); }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Request a chunk event. Chunks events should be provided to each DMA
|
||||
* request that wishes to participate in this DmaCallback.
|
||||
*/
|
||||
Event *getChunkEvent()
|
||||
{
|
||||
++count;
|
||||
return new DmaChunkEvent(this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Buffered DMA engine helper class
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue