kernel/eka/drivers/dma/dmapil.cpp
changeset 36 538db54a451d
parent 0 a41df078684a
child 80 597aaf25e343
child 90 947f0dc9f7a8
equal deleted inserted replaced
34:f497542af8e4 36:538db54a451d
   473 	__DMA_ASSERTD(iDesCount > 0);	// Not configured? call Fragment() first !
   473 	__DMA_ASSERTD(iDesCount > 0);	// Not configured? call Fragment() first !
   474 	__DMA_ASSERTD(!iQueued);
   474 	__DMA_ASSERTD(!iQueued);
   475 
   475 
   476 	// append request to queue and link new descriptor list to existing one.
   476 	// append request to queue and link new descriptor list to existing one.
   477 	iChannel.Wait();
   477 	iChannel.Wait();
       
   478 
       
   479 	TUint32 req_count = iChannel.iQueuedRequests++;
       
   480 	if (req_count == 0)
       
   481 		{
       
   482 		iChannel.Signal();
       
   483 		iChannel.QueuedRequestCountChanged();
       
   484 		iChannel.Wait();
       
   485 		}
       
   486 
   478 	if (!(iChannel.iIsrDfc & (TUint32)TDmaChannel::KCancelFlagMask))
   487 	if (!(iChannel.iIsrDfc & (TUint32)TDmaChannel::KCancelFlagMask))
   479 		{
   488 		{
   480 		iQueued = ETrue;
   489 		iQueued = ETrue;
   481 		iChannel.iReqQ.Add(&iLink);
   490 		iChannel.iReqQ.Add(&iLink);
   482 		*iChannel.iNullPtr = iFirstHdr;
   491 		*iChannel.iNullPtr = iFirstHdr;
   483 		iChannel.iNullPtr = &(iLastHdr->iNext);
   492 		iChannel.iNullPtr = &(iLastHdr->iNext);
   484 		iChannel.DoQueue(*this);
   493 		iChannel.DoQueue(*this);
   485 		}
   494 		iChannel.Signal();
   486 	iChannel.Signal();
   495 		}
       
   496 	else
       
   497 		{
       
   498 		// Someone is cancelling all requests...
       
   499 		req_count = --iChannel.iQueuedRequests;
       
   500 		iChannel.Signal();
       
   501 		if (req_count == 0)
       
   502 			{
       
   503 			iChannel.QueuedRequestCountChanged();
       
   504 			}
       
   505 		}
   487 
   506 
   488 	__DMA_INVARIANT();
   507 	__DMA_INVARIANT();
   489 	}
   508 	}
   490 
   509 
   491 EXPORT_C TInt DDmaRequest::ExpandDesList(TInt aCount)
   510 EXPORT_C TInt DDmaRequest::ExpandDesList(TInt aCount)
   584 	return DmaChannelMgr::StaticExtension(aCmd, aArg);
   603 	return DmaChannelMgr::StaticExtension(aCmd, aArg);
   585 	}
   604 	}
   586 
   605 
   587 
   606 
   588 TDmaChannel::TDmaChannel()
   607 TDmaChannel::TDmaChannel()
   589 	: iNullPtr(&iCurHdr),
   608 	: iController(NULL),
   590 	  iDfc(Dfc, NULL, 0)
   609 	  iPslId(0),
   591 	{
   610 	  iCurHdr(NULL),
   592 	// iController = NULL;
   611 	  iNullPtr(&iCurHdr),
   593 	// iPslId = 0;
   612 	  iDfc(Dfc, NULL, 0),
   594 	// iCurHdr = NULL;
   613 	  iMaxDesCount(0),
   595 	// iMaxDesCount = iAvailDesCount = 0;
   614 	  iAvailDesCount(0),
   596 	// iReqCount = 0;
   615 	  iIsrDfc(0),
       
   616 	  iReqQ(),
       
   617 	  iReqCount(0),
       
   618 	  iQueuedRequests(0),
       
   619 	  iCancelInfo(NULL)
       
   620 	{
   597 	__DMA_INVARIANT();
   621 	__DMA_INVARIANT();
   598 	}
   622 	}
   599 
   623 
   600 
   624 
   601 EXPORT_C TInt TDmaChannel::Open(const SCreateInfo& aInfo, TDmaChannel*& aChannel)
   625 EXPORT_C TInt TDmaChannel::Open(const SCreateInfo& aInfo, TDmaChannel*& aChannel)
   638 	__KTRACE_OPT(KDMA, Kern::Printf("TDmaChannel::Close %d", iPslId));
   662 	__KTRACE_OPT(KDMA, Kern::Printf("TDmaChannel::Close %d", iPslId));
   639 	__DMA_ASSERTD(IsOpened());
   663 	__DMA_ASSERTD(IsOpened());
   640 	__DMA_ASSERTD(IsQueueEmpty());
   664 	__DMA_ASSERTD(IsQueueEmpty());
   641 	__DMA_ASSERTD(iReqCount == 0);
   665 	__DMA_ASSERTD(iReqCount == 0);
   642 
   666 
       
   667 	__DMA_ASSERTD(iQueuedRequests == 0);
       
   668 
   643 	// descriptor leak? bug in request code
   669 	// descriptor leak? bug in request code
   644 	__DMA_ASSERTD(iAvailDesCount == iMaxDesCount);
   670 	__DMA_ASSERTD(iAvailDesCount == iMaxDesCount);
   645 
   671 
   646 	iController->ReleaseSetOfDes(iMaxDesCount);
   672 	iController->ReleaseSetOfDes(iMaxDesCount);
   647 	iAvailDesCount = iMaxDesCount = 0;
   673 	iAvailDesCount = iMaxDesCount = 0;
   663 
   689 
   664 	NThread* nt = NKern::CurrentThread();
   690 	NThread* nt = NKern::CurrentThread();
   665 	TBool wait = FALSE;
   691 	TBool wait = FALSE;
   666 	TDmaCancelInfo c;
   692 	TDmaCancelInfo c;
   667 	TDmaCancelInfo* waiters = 0;
   693 	TDmaCancelInfo* waiters = 0;
       
   694 
   668 	NKern::ThreadEnterCS();
   695 	NKern::ThreadEnterCS();
   669 	Wait();
   696 	Wait();
       
   697 	const TUint32 req_count_before = iQueuedRequests;
   670 	NThreadBase* dfcnt = iDfc.Thread();
   698 	NThreadBase* dfcnt = iDfc.Thread();
   671 	__e32_atomic_store_ord32(&iIsrDfc, (TUint32)KCancelFlagMask);
   699 	__e32_atomic_store_ord32(&iIsrDfc, (TUint32)KCancelFlagMask);
   672 	// ISRs after this point will not post a DFC, however a DFC may already be queued or running or both
   700 	// ISRs after this point will not post a DFC, however a DFC may already be queued or running or both
   673 	if (!IsQueueEmpty())
   701 	if (!IsQueueEmpty())
   674 		{
   702 		{
   681 
   709 
   682 		// Clean-up the request queue.
   710 		// Clean-up the request queue.
   683 		SDblQueLink* pL;
   711 		SDblQueLink* pL;
   684 		while ((pL = iReqQ.GetFirst()) != NULL)
   712 		while ((pL = iReqQ.GetFirst()) != NULL)
   685 			{
   713 			{
       
   714 			iQueuedRequests--;
   686 			DDmaRequest* pR = _LOFF(pL, DDmaRequest, iLink);
   715 			DDmaRequest* pR = _LOFF(pL, DDmaRequest, iLink);
   687 			pR->OnDeque();
   716 			pR->OnDeque();
   688 			}
   717 			}
   689 		}
   718 		}
   690 	if (!dfcnt || dfcnt==nt)
   719 	if (!dfcnt || dfcnt==nt)
   707 		else
   736 		else
   708 			iCancelInfo = &c;
   737 			iCancelInfo = &c;
   709 		wait = TRUE;
   738 		wait = TRUE;
   710 		iDfc.Enque();
   739 		iDfc.Enque();
   711 		}
   740 		}
       
   741 	const TUint32 req_count_after = iQueuedRequests;
   712 	Signal();
   742 	Signal();
   713 	if (waiters)
   743 	if (waiters)
   714 		waiters->Signal();
   744 		waiters->Signal();
   715 	if (wait)
   745 	if (wait)
   716 		NKern::FSWait(&c.iSem);
   746 		NKern::FSWait(&c.iSem);
   717  	NKern::ThreadLeaveCS();
   747  	NKern::ThreadLeaveCS();
       
   748 
       
   749 	// Only call PSL if there were requests queued when we entered AND there
       
   750 	// are now no requests left on the queue.
       
   751 	if ((req_count_before != 0) && (req_count_after == 0))
       
   752 		{
       
   753 		QueuedRequestCountChanged();
       
   754 		}
       
   755 
   718 	__DMA_INVARIANT();
   756 	__DMA_INVARIANT();
   719 	}
   757 	}
   720 
   758 
   721 
   759 
   722 /**
   760 /**
   738 	const TUint32 w = __e32_atomic_and_ord32(&iIsrDfc, (TUint32)KCancelFlagMask);
   776 	const TUint32 w = __e32_atomic_and_ord32(&iIsrDfc, (TUint32)KCancelFlagMask);
   739 	TUint32 count = w & KDfcCountMask;
   777 	TUint32 count = w & KDfcCountMask;
   740 	const TBool error = w & (TUint32)KErrorFlagMask;
   778 	const TBool error = w & (TUint32)KErrorFlagMask;
   741 	TBool stop = w & (TUint32)KCancelFlagMask;
   779 	TBool stop = w & (TUint32)KCancelFlagMask;
   742 	__DMA_ASSERTD(count>0 || stop);
   780 	__DMA_ASSERTD(count>0 || stop);
       
   781 	const TUint32 req_count_before = iQueuedRequests;
       
   782 	TUint32 req_count_after = 0;
   743 
   783 
   744 	while(count && !stop)
   784 	while(count && !stop)
   745 		{
   785 		{
   746 		--count;
   786 		--count;
   747 
   787 
   765 			// request (if any).
   805 			// request (if any).
   766 			if (pCompletedHdr == pCurReq->iLastHdr)
   806 			if (pCompletedHdr == pCurReq->iLastHdr)
   767 				{
   807 				{
   768 				pCompletedReq = pCurReq;
   808 				pCompletedReq = pCurReq;
   769 				pCurReq->iLink.Deque();
   809 				pCurReq->iLink.Deque();
       
   810 				iQueuedRequests--;
   770 				if (iReqQ.IsEmpty())
   811 				if (iReqQ.IsEmpty())
   771 					iNullPtr = &iCurHdr;
   812 					iNullPtr = &iCurHdr;
   772 				pCompletedReq->OnDeque();
   813 				pCompletedReq->OnDeque();
   773 				}
   814 				}
   774 			}
   815 			}
   812 		iDfc.Cancel();
   853 		iDfc.Cancel();
   813 
   854 
   814 		// reset the ISR count - new requests can now be processed
   855 		// reset the ISR count - new requests can now be processed
   815 		__e32_atomic_store_rel32(&iIsrDfc, 0);
   856 		__e32_atomic_store_rel32(&iIsrDfc, 0);
   816 
   857 
       
   858 		req_count_after = iQueuedRequests;
   817 		Signal();
   859 		Signal();
   818 
   860 
   819 		// release threads doing CancelAll()
   861 		// release threads doing CancelAll()
   820 		waiters->Signal();
   862 		waiters->Signal();
   821 		}
   863 		}
   830 		q.MoveFrom(&iReqQ);
   872 		q.MoveFrom(&iReqQ);
   831 
   873 
   832 		SDblQueLink* pL;
   874 		SDblQueLink* pL;
   833 		while ((pL = q.GetFirst()) != NULL)
   875 		while ((pL = q.GetFirst()) != NULL)
   834 			{
   876 			{
       
   877 			iQueuedRequests--;
   835 			DDmaRequest* pR = _LOFF(pL, DDmaRequest, iLink);
   878 			DDmaRequest* pR = _LOFF(pL, DDmaRequest, iLink);
   836 			__KTRACE_OPT(KDMA, Kern::Printf("Removing request from queue and notifying client"));
   879 			__KTRACE_OPT(KDMA, Kern::Printf("Removing request from queue and notifying client"));
   837 			pR->OnDeque();
   880 			pR->OnDeque();
   838 			DDmaRequest::TCallback cb = pR->iCb;
   881 			DDmaRequest::TCallback cb = pR->iCb;
   839 			TAny* arg = pR->iCbArg;
   882 			TAny* arg = pR->iCbArg;
   842 				Signal();
   885 				Signal();
   843 				(*cb)(DDmaRequest::EOk, arg);
   886 				(*cb)(DDmaRequest::EOk, arg);
   844 				Wait();
   887 				Wait();
   845 				}
   888 				}
   846 			}
   889 			}
       
   890 		req_count_after = iQueuedRequests;
   847 		Signal();
   891 		Signal();
   848 		}
   892 		}
   849 	else
   893 	else
       
   894 		{
       
   895 		req_count_after = iQueuedRequests;
   850 		Signal();
   896 		Signal();
       
   897 		}
       
   898 
       
   899 	// Only call PSL if there were requests queued when we entered AND there
       
   900 	// are now no requests left on the queue (after also having executed all
       
   901 	// client callbacks).
       
   902 	if ((req_count_before != 0) && (req_count_after == 0))
       
   903 		{
       
   904 		QueuedRequestCountChanged();
       
   905 		}
   851 
   906 
   852 	__DMA_INVARIANT();
   907 	__DMA_INVARIANT();
   853 	}
   908 	}
   854 
   909 
   855 
   910 
   867 	Default implementation does nothing. This is overridden by scatter-gather channels. */
   922 	Default implementation does nothing. This is overridden by scatter-gather channels. */
   868 
   923 
   869 void TDmaChannel::DoUnlink(SDmaDesHdr& /*aHdr*/)
   924 void TDmaChannel::DoUnlink(SDmaDesHdr& /*aHdr*/)
   870 	{
   925 	{
   871 	}
   926 	}
       
   927 
       
   928 
       
   929 /** PSL may override */
       
   930 void TDmaChannel::QueuedRequestCountChanged()
       
   931 	{
       
   932 #ifdef _DEBUG
       
   933 	Wait();
       
   934 	__KTRACE_OPT(KDMA,
       
   935 				 Kern::Printf("TDmaChannel::QueuedRequestCountChanged() %d",
       
   936 							  iQueuedRequests));
       
   937 	__DMA_ASSERTA(iQueuedRequests >= 0);
       
   938 	Signal();
       
   939 #endif
       
   940 	}
       
   941 
   872 
   942 
   873 #ifdef _DEBUG
   943 #ifdef _DEBUG
   874 
   944 
   875 void TDmaChannel::Invariant()
   945 void TDmaChannel::Invariant()
   876 	{
   946 	{