equal
deleted
inserted
replaced
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 { |