diff -r e880629062dd -r e4a7b1cbe40c kernel/eka/include/drivers/dma_v2.h --- a/kernel/eka/include/drivers/dma_v2.h Wed May 05 05:11:16 2010 +0100 +++ b/kernel/eka/include/drivers/dma_v2.h Mon May 10 11:40:53 2010 +0100 @@ -1197,14 +1197,53 @@ empty request queue, or immediately after the request count has become zero because of request cancellation or completion. - Depending on the current value of iQueuedRequests, the PSL may power - down or power up the channel. Note that iQueuedRequests gets accessed - and changed by different threads, so the PSL needs to take the usual - precautions when evaluating the variable's value. + Depending on the current and previous observed values of + iQueuedRequests, the PSL may power down or power up the channel. + + Note that iQueuedRequests gets accessed and changed by different + threads, so the PSL needs to take the usual precautions when evaluating + the variable's value. Also, due to the multithreaded framework + architecture, there is no guarantee that the function calls always + arrive at the PSL level in the strict chronological order of + iQueuedRequests being incremented/decremented in the PIL, i.e. it might + happen that the PSL finds iQueuedRequests to have the same value in two + or more consecutive calls (that's why the previous observed value needs + to be locally available and taken into account). It is however promised + that before any actual transfer commences the PSL will find the request + count to be greater than zero and that after the last request has + finished it will be found to be zero. None of the internal DMA framework mutexes is being held by the PIL when calling this function. + Here is an example implementation for a derived channel class: + + @code + + class TFooDmaChannel : public TDmaSgChannel + { + DMutex* iDmaMutex; + TInt iPrevQueuedRequests; + virtual void QueuedRequestCountChanged(); + }; + + void TFooDmaChannel::QueuedRequestCountChanged() + { + Kern::MutexWait(*iDmaMutex); + if ((iQueuedRequests > 0) && (iPrevQueuedRequests == 0)) + { + IncreasePowerCount(); // Base port specific + } + else if ((iQueuedRequests == 0) && (iPrevQueuedRequests > 0)) + { + DecreasePowerCount(); // Base port specific + } + iPrevQueuedRequests = iQueuedRequests; + Kern::MutexSignal(*iDmaMutex); + } + + @endcode + @see iQueuedRequests */ virtual void QueuedRequestCountChanged();