kernel/eka/drivers/dma/dma2_pil.cpp
changeset 243 c7a0ce20c48c
parent 231 75252ea6123b
equal deleted inserted replaced
231:75252ea6123b 243:c7a0ce20c48c
  1930 		}
  1930 		}
  1931 	else
  1931 	else
  1932 		{
  1932 		{
  1933 		iQueued = ETrue;
  1933 		iQueued = ETrue;
  1934 		iChannel.iReqQ.Add(&iLink);
  1934 		iChannel.iReqQ.Add(&iLink);
  1935 		// iChannel.iNullPtr points to iChannel.iCurHdr for an empty queue
  1935 		iChannel.SetNullPtr(*this);
  1936 		*iChannel.iNullPtr = iFirstHdr;
       
  1937 		iChannel.iNullPtr = &(iLastHdr->iNext);
       
  1938 		if (iIsrCb)
  1936 		if (iIsrCb)
  1939 			{
  1937 			{
  1940 			// Since we've made sure that there is no other request in the
  1938 			// Since we've made sure that there is no other request in the
  1941 			// queue before this, the only thing of relevance is the channel
  1939 			// queue before this, the only thing of relevance is the channel
  1942 			// DFC which might yet have to complete for the previous request,
  1940 			// DFC which might yet have to complete for the previous request,
  1944 			// the client callback. This should be all right though as once
  1942 			// the client callback. This should be all right though as once
  1945 			// we've set the following flag no further Queue()'s will be
  1943 			// we've set the following flag no further Queue()'s will be
  1946 			// possible.
  1944 			// possible.
  1947 			__e32_atomic_store_rel32(&iChannel.iIsrCbRequest, ETrue);
  1945 			__e32_atomic_store_rel32(&iChannel.iIsrCbRequest, ETrue);
  1948 			}
  1946 			}
  1949 		iChannel.DoQueue(const_cast<const DDmaRequest&>(*this));
  1947 		iChannel.DoQueue(*this);
  1950 		r = KErrNone;
  1948 		r = KErrNone;
  1951 		__DMA_INVARIANT();
  1949 		__DMA_INVARIANT();
  1952 		iChannel.Signal();
  1950 		iChannel.Signal();
  1953 		}
  1951 		}
  1954 
  1952 
  2122 EXPORT_C TUint32 DDmaRequest::TotalNumSrcElementsTransferred()
  2120 EXPORT_C TUint32 DDmaRequest::TotalNumSrcElementsTransferred()
  2123 	{
  2121 	{
  2124 	__KTRACE_OPT(KDMA, Kern::Printf("DDmaRequest::TotalNumSrcElementsTransferred"));
  2122 	__KTRACE_OPT(KDMA, Kern::Printf("DDmaRequest::TotalNumSrcElementsTransferred"));
  2125 
  2123 
  2126 	// Not yet implemented.
  2124 	// Not yet implemented.
  2127 
       
  2128 	// So far largely bogus code (just to touch some symbols)...
       
  2129 	iTotalNumSrcElementsTransferred = 0;
       
  2130 	TDmac& c = *(iChannel.iController);
       
  2131 	if (c.iCapsHwDes)
       
  2132 		{
       
  2133 		for (const SDmaDesHdr* pH = iFirstHdr; pH != NULL; pH = pH->iNext)
       
  2134 			{
       
  2135 			iTotalNumSrcElementsTransferred += c.HwDesNumDstElementsTransferred(*pH);
       
  2136 			}
       
  2137 		}
       
  2138 	else
       
  2139 		{
       
  2140 		// Do something different for pseudo descriptors...
       
  2141 		}
       
  2142 	return iTotalNumSrcElementsTransferred;
  2125 	return iTotalNumSrcElementsTransferred;
  2143 	}
  2126 	}
  2144 
  2127 
  2145 
  2128 
  2146 EXPORT_C TUint32 DDmaRequest::TotalNumDstElementsTransferred()
  2129 EXPORT_C TUint32 DDmaRequest::TotalNumDstElementsTransferred()
  2431 		// There is a transfer in progress. It may complete before the DMAC
  2414 		// There is a transfer in progress. It may complete before the DMAC
  2432 		// has stopped, but the resulting ISR will not post a DFC.
  2415 		// has stopped, but the resulting ISR will not post a DFC.
  2433 		// ISR should not happen after this function returns.
  2416 		// ISR should not happen after this function returns.
  2434 		iController->StopTransfer(*this);
  2417 		iController->StopTransfer(*this);
  2435 
  2418 
  2436 		ResetStateMachine();
  2419 		DoCancelAll();
       
  2420 		ResetNullPtr();
  2437 
  2421 
  2438 		// Clean-up the request queue.
  2422 		// Clean-up the request queue.
  2439 		SDblQueLink* pL;
  2423 		SDblQueLink* pL;
  2440 		while ((pL = iReqQ.GetFirst()) != NULL)
  2424 		while ((pL = iReqQ.GetFirst()) != NULL)
  2441 			{
  2425 			{
  2705 			TBool complete;
  2689 			TBool complete;
  2706 			if (iDmacCaps->iAsymHwDescriptors)
  2690 			if (iDmacCaps->iAsymHwDescriptors)
  2707 				{
  2691 				{
  2708 				SDmaDesHdr* pCompletedSrcHdr = NULL;
  2692 				SDmaDesHdr* pCompletedSrcHdr = NULL;
  2709 				SDmaDesHdr* pCompletedDstHdr = NULL;
  2693 				SDmaDesHdr* pCompletedDstHdr = NULL;
  2710 				DoDfc(const_cast<const DDmaRequest&>(*pCurReq),
  2694 				DoDfc(*pCurReq, pCompletedSrcHdr, pCompletedDstHdr);
  2711 					  pCompletedSrcHdr, pCompletedDstHdr);
       
  2712 				// We don't support asymmetrical ISR notifications and request
  2695 				// We don't support asymmetrical ISR notifications and request
  2713 				// completions yet, hence we can do the following assert test
  2696 				// completions yet, hence we can do the following assert test
  2714 				// here; also 'complete' is determined equally by either the
  2697 				// here; also 'complete' is determined equally by either the
  2715 				// SRC or DST side.
  2698 				// SRC or DST side.
  2716 				__DMA_ASSERTD(!LOGICAL_XOR((pCompletedSrcHdr == pCurReq->iSrcLastHdr),
  2699 				__DMA_ASSERTD(!LOGICAL_XOR((pCompletedSrcHdr == pCurReq->iSrcLastHdr),
  2718 				complete = (pCompletedDstHdr == pCurReq->iDstLastHdr);
  2701 				complete = (pCompletedDstHdr == pCurReq->iDstLastHdr);
  2719 				}
  2702 				}
  2720 			else
  2703 			else
  2721 				{
  2704 				{
  2722 				SDmaDesHdr* pCompletedHdr = NULL;
  2705 				SDmaDesHdr* pCompletedHdr = NULL;
  2723 				DoDfc(const_cast<const DDmaRequest&>(*pCurReq), pCompletedHdr);
  2706 				DoDfc(*pCurReq, pCompletedHdr);
  2724 				complete = (pCompletedHdr == pCurReq->iLastHdr);
  2707 				complete = (pCompletedHdr == pCurReq->iLastHdr);
  2725 				}
  2708 				}
  2726 			// If just completed last fragment from current request, switch to
  2709 			// If just completed last fragment from current request, switch to
  2727 			// next request (if any).
  2710 			// next request (if any).
  2728 			if (complete)
  2711 			if (complete)
  2729 				{
  2712 				{
  2730 				pCompletedReq = pCurReq;
  2713 				pCompletedReq = pCurReq;
  2731 				pCurReq->iLink.Deque();
  2714 				pCurReq->iLink.Deque();
  2732 				iQueuedRequests--;
  2715 				iQueuedRequests--;
  2733 				if (iReqQ.IsEmpty())
  2716 				if (iReqQ.IsEmpty())
  2734 					iNullPtr = &iCurHdr;
  2717 					ResetNullPtr();
  2735 				pCompletedReq->OnDeque();
  2718 				pCompletedReq->OnDeque();
  2736 				}
  2719 				}
  2737 			}
  2720 			}
  2738 		else
  2721 		else
  2739 			{
  2722 			{
  2816 
  2799 
  2817 	__DMA_INVARIANT();
  2800 	__DMA_INVARIANT();
  2818 	}
  2801 	}
  2819 
  2802 
  2820 
  2803 
  2821 //
       
  2822 // Reset state machine only, request queue is unchanged */
       
  2823 //
       
  2824 void TDmaChannel::ResetStateMachine()
       
  2825 	{
       
  2826 	DoCancelAll();
       
  2827 	iCurHdr = NULL;
       
  2828 	iNullPtr = &iCurHdr;
       
  2829 	}
       
  2830 
       
  2831 
       
  2832 void TDmaChannel::DoQueue(const DDmaRequest& /*aReq*/)
  2804 void TDmaChannel::DoQueue(const DDmaRequest& /*aReq*/)
  2833 	{
  2805 	{
  2834 	// Must be overridden
  2806 	// Must be overridden
  2835 	__DMA_UNREACHABLE_DEFAULT();
  2807 	__DMA_UNREACHABLE_DEFAULT();
  2836 	}
  2808 	}
  2860 	{
  2832 	{
  2861 	// To make sure this version of the function isn't called for channels for
  2833 	// To make sure this version of the function isn't called for channels for
  2862 	// which it isn't appropriate (and which therefore don't override it) we
  2834 	// which it isn't appropriate (and which therefore don't override it) we
  2863 	// put this check in here.
  2835 	// put this check in here.
  2864 	__DMA_UNREACHABLE_DEFAULT();
  2836 	__DMA_UNREACHABLE_DEFAULT();
       
  2837 	}
       
  2838 
       
  2839 
       
  2840 void TDmaChannel::SetNullPtr(const DDmaRequest& aReq)
       
  2841 	{
       
  2842 	// iNullPtr points to iCurHdr for an empty queue
       
  2843 	*iNullPtr = aReq.iFirstHdr;
       
  2844 	iNullPtr = &(aReq.iLastHdr->iNext);
       
  2845 	}
       
  2846 
       
  2847 
       
  2848 void TDmaChannel::ResetNullPtr()
       
  2849 	{
       
  2850 	iCurHdr = NULL;
       
  2851 	iNullPtr = &iCurHdr;
  2865 	}
  2852 	}
  2866 
  2853 
  2867 
  2854 
  2868 /** PSL may override */
  2855 /** PSL may override */
  2869 void TDmaChannel::QueuedRequestCountChanged()
  2856 void TDmaChannel::QueuedRequestCountChanged()
  3036 
  3023 
  3037 
  3024 
  3038 //////////////////////////////////////////////////////////////////////////////
  3025 //////////////////////////////////////////////////////////////////////////////
  3039 // TDmaAsymSgChannel
  3026 // TDmaAsymSgChannel
  3040 
  3027 
       
  3028 TDmaAsymSgChannel::TDmaAsymSgChannel()
       
  3029 	: iSrcCurHdr(NULL),
       
  3030 	  iSrcNullPtr(&iSrcCurHdr),
       
  3031 	  iDstCurHdr(NULL),
       
  3032 	  iDstNullPtr(&iDstCurHdr)
       
  3033 	{
       
  3034 	__DMA_INVARIANT();
       
  3035 	}
       
  3036 
       
  3037 
       
  3038 void TDmaAsymSgChannel::SetNullPtr(const DDmaRequest& aReq)
       
  3039 	{
       
  3040 	// i{Src|Dst}NullPtr points to i{Src|Dst}CurHdr for an empty queue
       
  3041 	*iSrcNullPtr = aReq.iSrcFirstHdr;
       
  3042 	*iDstNullPtr = aReq.iDstFirstHdr;
       
  3043 	iSrcNullPtr = &(aReq.iSrcLastHdr->iNext);
       
  3044 	iDstNullPtr = &(aReq.iDstLastHdr->iNext);
       
  3045 	}
       
  3046 
       
  3047 
       
  3048 void TDmaAsymSgChannel::ResetNullPtr()
       
  3049 	{
       
  3050 	iSrcCurHdr = NULL;
       
  3051 	iSrcNullPtr = &iSrcCurHdr;
       
  3052 	iDstCurHdr = NULL;
       
  3053 	iDstNullPtr = &iDstCurHdr;
       
  3054 	}
       
  3055 
       
  3056 
  3041 void TDmaAsymSgChannel::DoQueue(const DDmaRequest& aReq)
  3057 void TDmaAsymSgChannel::DoQueue(const DDmaRequest& aReq)
  3042 	{
  3058 	{
  3043 	if (iState == ETransferring)
  3059 	if (iState == ETransferring)
  3044 		{
  3060 		{
  3045 		__DMA_ASSERTD(!aReq.iLink.Alone());
  3061 		__DMA_ASSERTD(!aReq.iLink.Alone());
  3080 	// Must be either both NULL or none of them.
  3096 	// Must be either both NULL or none of them.
  3081 	__DMA_ASSERTD(!LOGICAL_XOR(iSrcCurHdr, iDstCurHdr));
  3097 	__DMA_ASSERTD(!LOGICAL_XOR(iSrcCurHdr, iDstCurHdr));
  3082 	iState = (iSrcCurHdr != NULL) ? ETransferring : EIdle;
  3098 	iState = (iSrcCurHdr != NULL) ? ETransferring : EIdle;
  3083 	}
  3099 	}
  3084 
  3100 
       
  3101 
       
  3102 #ifdef _DEBUG
       
  3103 void TDmaAsymSgChannel::Invariant()
       
  3104 	{
       
  3105 	Wait();
       
  3106 
       
  3107 	__DMA_ASSERTD(iReqCount >= 0);
       
  3108 
       
  3109 	__DMA_ASSERTD(iSrcCurHdr == NULL || iController->IsValidHdr(iSrcCurHdr));
       
  3110 	__DMA_ASSERTD(iDstCurHdr == NULL || iController->IsValidHdr(iDstCurHdr));
       
  3111 
       
  3112 	// should always point to NULL pointer ending fragment queue
       
  3113 	__DMA_ASSERTD(*iSrcNullPtr == NULL);
       
  3114 	__DMA_ASSERTD(*iDstNullPtr == NULL);
       
  3115 
       
  3116 	__DMA_ASSERTD((0 <= iAvailDesCount) && (iAvailDesCount <= iMaxDesCount));
       
  3117 
       
  3118 	__DMA_ASSERTD((iSrcCurHdr && iDstCurHdr && !IsQueueEmpty()) ||
       
  3119 				  (!iSrcCurHdr && !iDstCurHdr && IsQueueEmpty()));
       
  3120 	if (iSrcCurHdr == NULL)
       
  3121 		{
       
  3122 		__DMA_ASSERTD(iSrcNullPtr == &iSrcCurHdr);
       
  3123 		}
       
  3124 	if (iDstCurHdr == NULL)
       
  3125 		{
       
  3126 		__DMA_ASSERTD(iDstNullPtr == &iDstCurHdr);
       
  3127 		}
       
  3128 
       
  3129 	Signal();
       
  3130 	}
       
  3131 #endif