Update contrib.
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\dma\dmasim.cpp
15 // DMA framework Platform Specific Layer (PSL) for software-emulated
16 // DMA controller used for testing the DMA framework PIL.
20 #include <drivers/dma.h>
21 #include <kernel/kern_priv.h>
24 const char KDmaPanicCat[] = "DMASIM";
26 const TInt KMaxTransferSize = 0x1FFF;
27 const TInt KMemAlignMask = 3; // memory addresses passed to DMAC must be multiple of 4
28 const TInt KBurstSize = 0x800;
30 typedef void (*TPseudoIsr)();
32 const TInt KChannelCount = 4; // # of channels per controller
33 const TInt KDesCount = 256; // # of descriptors allocated per controller
35 //////////////////////////////////////////////////////////////////////////////
36 // SOFTWARE DMA CONTROLLER SIMULATION
37 //////////////////////////////////////////////////////////////////////////////
40 /** Single-buffer DMA controller software simulation */
43 enum { ECsRun = 0x80000000 };
45 static void DoTransfer();
47 static void BurstTransfer();
49 static TInt CurrentChannel;
52 static TUint8* SrcAddr[KChannelCount];
53 static TUint8* DestAddr[KChannelCount];
54 static TInt Count[KChannelCount];
55 static TUint32 ControlStatus[KChannelCount];
56 static TUint32 CompletionInt;
57 static TUint32 ErrorInt;
58 // hook for pseudo ISR
59 static TPseudoIsr Isr;
60 // transfer failure simulation
61 static TInt FailCount[KChannelCount];
64 TUint8* DmacSb::SrcAddr[KChannelCount];
65 TUint8* DmacSb::DestAddr[KChannelCount];
66 TInt DmacSb::Count[KChannelCount];
67 TUint32 DmacSb::ControlStatus[KChannelCount];
68 TUint32 DmacSb::CompletionInt;
69 TUint32 DmacSb::ErrorInt;
70 TPseudoIsr DmacSb::Isr;
71 TInt DmacSb::FailCount[KChannelCount];
72 TInt DmacSb::CurrentChannel;
74 void DmacSb::DoTransfer()
76 if (ControlStatus[CurrentChannel] & ECsRun)
78 if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
80 ControlStatus[CurrentChannel] &= ~ECsRun;
81 ErrorInt |= 1 << CurrentChannel;
86 //__KTRACE_OPT(KDMA, Kern::Printf("DmacSb::DoTransfer channel %d", CurrentChannel));
87 if (Count[CurrentChannel] == 0)
89 //__KTRACE_OPT(KDMA, Kern::Printf("DmacSb::DoTransfer transfer complete"));
90 ControlStatus[CurrentChannel] &= ~ECsRun;
91 CompletionInt |= 1 << CurrentChannel;
100 if (CurrentChannel >= KChannelCount)
104 void DmacSb::BurstTransfer()
106 //__KTRACE_OPT(KDMA, Kern::Printf("DmacSb::BurstTransfer"));
107 TInt s = Min(Count[CurrentChannel], KBurstSize);
108 memcpy(DestAddr[CurrentChannel], SrcAddr[CurrentChannel], s);
109 Count[CurrentChannel] -= s;
110 SrcAddr[CurrentChannel] += s;
111 DestAddr[CurrentChannel] += s;
114 //////////////////////////////////////////////////////////////////////////////
117 /** Double-buffer DMA controller software simulation */
120 enum { ECsRun = 0x80000000, ECsPrg = 0x40000000 };
122 static void Enable(TInt aIdx);
123 static void DoTransfer();
125 static TInt CurrentChannel;
127 // internal pseudo-registers
128 static TUint8* ActSrcAddr[KChannelCount];
129 static TUint8* ActDestAddr[KChannelCount];
130 static TInt ActCount[KChannelCount];
132 // externally accessible pseudo-registers
133 static TUint32 ControlStatus[KChannelCount];
134 static TUint8* PrgSrcAddr[KChannelCount];
135 static TUint8* PrgDestAddr[KChannelCount];
136 static TInt PrgCount[KChannelCount];
137 static TUint32 CompletionInt;
138 static TUint32 ErrorInt;
139 // hook for pseudo ISR
140 static TPseudoIsr Isr;
141 // transfer failure simulation
142 static TInt FailCount[KChannelCount];
143 static TInt InterruptsToMiss[KChannelCount];
146 TUint8* DmacDb::PrgSrcAddr[KChannelCount];
147 TUint8* DmacDb::PrgDestAddr[KChannelCount];
148 TInt DmacDb::PrgCount[KChannelCount];
149 TUint8* DmacDb::ActSrcAddr[KChannelCount];
150 TUint8* DmacDb::ActDestAddr[KChannelCount];
151 TInt DmacDb::ActCount[KChannelCount];
152 TUint32 DmacDb::ControlStatus[KChannelCount];
153 TUint32 DmacDb::CompletionInt;
154 TUint32 DmacDb::ErrorInt;
155 TPseudoIsr DmacDb::Isr;
156 TInt DmacDb::FailCount[KChannelCount];
157 TInt DmacDb::InterruptsToMiss[KChannelCount];
158 TInt DmacDb::CurrentChannel;
160 void DmacDb::Enable(TInt aIdx)
162 if (ControlStatus[aIdx] & ECsRun)
163 ControlStatus[aIdx] |= ECsPrg;
166 ActSrcAddr[aIdx] = PrgSrcAddr[aIdx];
167 ActDestAddr[aIdx] = PrgDestAddr[aIdx];
168 ActCount[aIdx] = PrgCount[aIdx];
169 ControlStatus[aIdx] |= ECsRun;
173 void DmacDb::DoTransfer()
175 if (ControlStatus[CurrentChannel] & ECsRun)
177 if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
179 ControlStatus[CurrentChannel] &= ~ECsRun;
180 ErrorInt |= 1 << CurrentChannel;
185 if (ActCount[CurrentChannel] == 0)
187 if (ControlStatus[CurrentChannel] & ECsPrg)
189 ActSrcAddr[CurrentChannel] = PrgSrcAddr[CurrentChannel];
190 ActDestAddr[CurrentChannel] = PrgDestAddr[CurrentChannel];
191 ActCount[CurrentChannel] = PrgCount[CurrentChannel];
192 ControlStatus[CurrentChannel] &= ~ECsPrg;
195 ControlStatus[CurrentChannel] &= ~ECsRun;
196 if (InterruptsToMiss[CurrentChannel] > 0)
197 InterruptsToMiss[CurrentChannel]--;
200 CompletionInt |= 1 << CurrentChannel;
206 TInt s = Min(ActCount[CurrentChannel], KBurstSize);
207 memcpy(ActDestAddr[CurrentChannel], ActSrcAddr[CurrentChannel], s);
208 ActCount[CurrentChannel] -= s;
209 ActSrcAddr[CurrentChannel] += s;
210 ActDestAddr[CurrentChannel] += s;
216 if (CurrentChannel >= KChannelCount)
221 //////////////////////////////////////////////////////////////////////////////
224 /** Scatter/gather DMA controller software simulation */
227 enum { EChannelBitRun = 0x80000000 };
228 enum { EDesBitInt = 1 };
238 static void DoTransfer();
239 static void Enable(TInt aIdx);
241 static TInt CurrentChannel;
242 static TBool IsDescriptorLoaded[KChannelCount];
244 // externally accessible pseudo-registers
245 static TUint32 ChannelControl[KChannelCount];
246 static TUint8* SrcAddr[KChannelCount];
247 static TUint8* DestAddr[KChannelCount];
248 static TInt Count[KChannelCount];
249 static TUint Control[KChannelCount];
250 static SDes* NextDes[KChannelCount];
251 static TUint32 CompletionInt;
252 static TUint32 ErrorInt;
253 // hook for pseudo ISR
254 static TPseudoIsr Isr;
255 // transfer failure simulation
256 static TInt FailCount[KChannelCount];
257 static TInt InterruptsToMiss[KChannelCount];
260 TUint32 DmacSg::ChannelControl[KChannelCount];
261 TUint8* DmacSg::SrcAddr[KChannelCount];
262 TUint8* DmacSg::DestAddr[KChannelCount];
263 TInt DmacSg::Count[KChannelCount];
264 TUint DmacSg::Control[KChannelCount];
265 DmacSg::SDes* DmacSg::NextDes[KChannelCount];
266 TUint32 DmacSg::CompletionInt;
267 TUint32 DmacSg::ErrorInt;
268 TPseudoIsr DmacSg::Isr;
269 TInt DmacSg::FailCount[KChannelCount];
270 TInt DmacSg::InterruptsToMiss[KChannelCount];
271 TInt DmacSg::CurrentChannel;
272 TBool DmacSg::IsDescriptorLoaded[KChannelCount];
275 void DmacSg::DoTransfer()
277 if (ChannelControl[CurrentChannel] & EChannelBitRun)
279 if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
281 ChannelControl[CurrentChannel] &= ~EChannelBitRun;
282 ErrorInt |= 1 << CurrentChannel;
287 if (IsDescriptorLoaded[CurrentChannel])
289 if (Count[CurrentChannel] == 0)
291 IsDescriptorLoaded[CurrentChannel] = EFalse;
292 if (Control[CurrentChannel] & EDesBitInt)
294 if (InterruptsToMiss[CurrentChannel] > 0)
295 InterruptsToMiss[CurrentChannel]--;
298 CompletionInt |= 1 << CurrentChannel;
305 TInt s = Min(Count[CurrentChannel], KBurstSize);
306 memcpy(DestAddr[CurrentChannel], SrcAddr[CurrentChannel], s);
307 Count[CurrentChannel] -= s;
308 SrcAddr[CurrentChannel] += s;
309 DestAddr[CurrentChannel] += s;
312 // Need to test again as new descriptor must be loaded if
313 // completion has just occured.
314 if (! IsDescriptorLoaded[CurrentChannel])
316 if (NextDes[CurrentChannel] != NULL)
318 SrcAddr[CurrentChannel] = NextDes[CurrentChannel]->iSrcAddr;
319 DestAddr[CurrentChannel] = NextDes[CurrentChannel]->iDestAddr;
320 Count[CurrentChannel] = NextDes[CurrentChannel]->iCount;
321 Control[CurrentChannel] = NextDes[CurrentChannel]->iControl;
322 NextDes[CurrentChannel] = NextDes[CurrentChannel]->iNext;
323 IsDescriptorLoaded[CurrentChannel] = ETrue;
326 ChannelControl[CurrentChannel] &= ~EChannelBitRun;
332 if (CurrentChannel >= KChannelCount)
337 void DmacSg::Enable(TInt aIdx)
339 SrcAddr[aIdx] = NextDes[aIdx]->iSrcAddr;
340 DestAddr[aIdx] = NextDes[aIdx]->iDestAddr;
341 Count[aIdx] = NextDes[aIdx]->iCount;
342 Control[aIdx] = NextDes[aIdx]->iControl;
343 NextDes[aIdx] = NextDes[aIdx]->iNext;
344 IsDescriptorLoaded[aIdx] = ETrue;
345 ChannelControl[aIdx] |= EChannelBitRun;
348 //////////////////////////////////////////////////////////////////////////////
352 Harness calling the various DMA controller simulators periodically.
356 static void StartEmulation();
357 static void StopEmulation();
359 enum { KPeriod = 1 }; // in ms
360 static void TickCB(TAny* aThis);
364 NTimer DmacSim::Timer;
366 void DmacSim::StartEmulation()
368 new (&Timer) NTimer(&TickCB, 0);
369 __DMA_ASSERTA(Timer.OneShot(KPeriod, EFalse) == KErrNone);
372 void DmacSim::StopEmulation()
377 void DmacSim::TickCB(TAny*)
379 DmacSb::DoTransfer();
380 DmacDb::DoTransfer();
381 DmacSg::DoTransfer();
382 __DMA_ASSERTA(Timer.Again(KPeriod) == KErrNone);
385 //////////////////////////////////////////////////////////////////////////////
386 // PSL FOR DMA SIMULATION
387 //////////////////////////////////////////////////////////////////////////////
389 class DSimSbController : public TDmac
396 virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr);
397 virtual void StopTransfer(const TDmaChannel& aChannel);
398 virtual TInt FailNext(const TDmaChannel& aChannel);
399 virtual TBool IsIdle(const TDmaChannel& aChannel);
400 virtual TInt MaxTransferSize(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
401 virtual TUint MemAlignMask(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
403 static const SCreateInfo KInfo;
404 TDmaSbChannel iChannels[KChannelCount];
407 DSimSbController SbController;
409 const TDmac::SCreateInfo DSimSbController::KInfo =
414 sizeof(SDmaPseudoDes),
418 DSimSbController::DSimSbController()
425 void DSimSbController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
427 TUint32 i = aChannel.PslId();
428 const SDmaPseudoDes& des = HdrToDes(aHdr);
429 DmacSb::SrcAddr[i] = (TUint8*) des.iSrc;
430 DmacSb::DestAddr[i] = (TUint8*) des.iDest;
431 DmacSb::Count[i] = des.iCount;
432 DmacSb::ControlStatus[i] |= DmacSb::ECsRun;
436 void DSimSbController::StopTransfer(const TDmaChannel& aChannel)
438 __e32_atomic_and_ord32(&DmacSb::ControlStatus[aChannel.PslId()], (TUint32)~DmacSb::ECsRun);
442 TInt DSimSbController::FailNext(const TDmaChannel& aChannel)
444 DmacSb::FailCount[aChannel.PslId()] = 1;
449 TBool DSimSbController::IsIdle(const TDmaChannel& aChannel)
451 return (DmacSb::ControlStatus[aChannel.PslId()] & DmacSb::ECsRun) == 0;
455 TInt DSimSbController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
457 return KMaxTransferSize;
461 TUint DSimSbController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
463 return KMemAlignMask;
467 void DSimSbController::Isr()
469 for (TInt i = 0; i < KChannelCount; i++)
471 TUint32 mask = (1 << i);
472 if (DmacSb::CompletionInt & mask)
474 DmacSb::CompletionInt &= ~mask;
475 HandleIsr(SbController.iChannels[i], ETrue);
477 if (DmacSb::ErrorInt & mask)
479 DmacSb::ErrorInt &= ~mask;
480 HandleIsr(SbController.iChannels[i], EFalse);
485 //////////////////////////////////////////////////////////////////////////////
487 class DSimDbController : public TDmac
494 virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr);
495 virtual void StopTransfer(const TDmaChannel& aChannel);
496 virtual TInt FailNext(const TDmaChannel& aChannel);
497 virtual TInt MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount);
498 virtual TBool IsIdle(const TDmaChannel& aChannel);
499 virtual TInt MaxTransferSize(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
500 virtual TUint MemAlignMask(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
502 static const SCreateInfo KInfo;
503 TDmaDbChannel iChannels[KChannelCount];
506 DSimDbController DbController;
508 const TDmac::SCreateInfo DSimDbController::KInfo =
513 sizeof(SDmaPseudoDes),
518 DSimDbController::DSimDbController()
525 void DSimDbController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
527 TUint32 i = aChannel.PslId();
528 const SDmaPseudoDes& des = HdrToDes(aHdr);
529 DmacDb::PrgSrcAddr[i] = (TUint8*) des.iSrc;
530 DmacDb::PrgDestAddr[i] = (TUint8*) des.iDest;
531 DmacDb::PrgCount[i] = des.iCount;
536 void DSimDbController::StopTransfer(const TDmaChannel& aChannel)
538 __e32_atomic_and_ord32(&DmacDb::ControlStatus[aChannel.PslId()], (TUint32)~(DmacDb::ECsRun|DmacDb::ECsPrg));
542 TInt DSimDbController::FailNext(const TDmaChannel& aChannel)
544 DmacDb::FailCount[aChannel.PslId()] = 1;
549 TInt DSimDbController::MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount)
551 __DMA_ASSERTD((DmacDb::ControlStatus[aChannel.PslId()] & DmacDb::ECsRun) == 0);
552 __DMA_ASSERTD(aInterruptCount >= 0);
553 // At most one interrupt can be missed with double-buffer controller
554 if (aInterruptCount == 1)
556 DmacDb::InterruptsToMiss[aChannel.PslId()] = aInterruptCount;
560 return KErrNotSupported;
564 TBool DSimDbController::IsIdle(const TDmaChannel& aChannel)
566 return (DmacDb::ControlStatus[aChannel.PslId()] & DmacDb::ECsRun) == 0;
570 TInt DSimDbController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
572 return KMaxTransferSize;
576 TUint DSimDbController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
578 return KMemAlignMask;
582 void DSimDbController::Isr()
584 for (TInt i = 0; i < KChannelCount; i++)
586 TUint32 mask = (1 << i);
587 if (DmacDb::CompletionInt & mask)
589 DmacDb::CompletionInt &= ~mask;
590 HandleIsr(DbController.iChannels[i], ETrue);
592 if (DmacDb::ErrorInt & mask)
594 DmacDb::ErrorInt &= ~mask;
595 HandleIsr(DbController.iChannels[i], EFalse);
600 //////////////////////////////////////////////////////////////////////////////
602 class DSimSgController : public TDmac
609 virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr);
610 virtual void StopTransfer(const TDmaChannel& aChannel);
611 virtual TBool IsIdle(const TDmaChannel& aChannel);
612 virtual TInt MaxTransferSize(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
613 virtual TUint MemAlignMask(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo);
614 virtual void InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
615 TUint aFlags, TUint32 aPslInfo, TUint32 aCookie);
616 virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr);
617 virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
618 const SDmaDesHdr& aNewHdr);
619 virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr);
620 virtual TInt FailNext(const TDmaChannel& aChannel);
621 virtual TInt MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount);
623 inline DmacSg::SDes* HdrToHwDes(const SDmaDesHdr& aHdr);
625 static const SCreateInfo KInfo;
626 TDmaSgChannel iChannels[KChannelCount];
629 DSimSgController SgController;
631 const TDmac::SCreateInfo DSimSgController::KInfo =
636 sizeof(DmacSg::SDes),
640 EMapAttrSupRw|EMapAttrFullyBlocking,
645 inline DmacSg::SDes* DSimSgController::HdrToHwDes(const SDmaDesHdr& aHdr)
647 return static_cast<DmacSg::SDes*>(TDmac::HdrToHwDes(aHdr));
651 DSimSgController::DSimSgController()
658 void DSimSgController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
660 TUint32 i = aChannel.PslId();
661 DmacSg::NextDes[i] = HdrToHwDes(aHdr);
666 void DSimSgController::StopTransfer(const TDmaChannel& aChannel)
668 __e32_atomic_and_ord32(&DmacSg::ChannelControl[aChannel.PslId()], (TUint32)~DmacSg::EChannelBitRun);
672 void DSimSgController::InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
673 TUint /*aFlags*/, TUint32 /*aPslInfo*/, TUint32 /*aCookie*/)
675 DmacSg::SDes& des = *HdrToHwDes(aHdr);
676 des.iSrcAddr = reinterpret_cast<TUint8*>(aSrc);
677 des.iDestAddr = reinterpret_cast<TUint8*>(aDest);
678 des.iCount = static_cast<TInt16>(aCount);
679 des.iControl |= DmacSg::EDesBitInt;
684 void DSimSgController::ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr)
686 DmacSg::SDes& des = *HdrToHwDes(aHdr);
687 des.iControl &= ~DmacSg::EDesBitInt;
688 des.iNext = HdrToHwDes(aNextHdr);
692 void DSimSgController::AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
693 const SDmaDesHdr& aNewHdr)
695 TUint32 i = aChannel.PslId();
696 DmacSg::SDes* pNewDes = HdrToHwDes(aNewHdr);
697 TInt prevLevel = NKern::DisableAllInterrupts();
699 if ((DmacSg::ChannelControl[i] & DmacSg::EChannelBitRun) == 0)
701 DmacSg::NextDes[i] = pNewDes;
704 else if (DmacSg::NextDes[i] == NULL)
705 DmacSg::NextDes[i] = pNewDes;
707 HdrToHwDes(aLastHdr)->iNext = pNewDes;
709 NKern::RestoreInterrupts(prevLevel);
713 void DSimSgController::UnlinkHwDes(const TDmaChannel& /*aChannel*/, SDmaDesHdr& aHdr)
715 DmacSg::SDes* pD = HdrToHwDes(aHdr);
717 pD->iControl |= DmacSg::EDesBitInt;
721 TInt DSimSgController::FailNext(const TDmaChannel& aChannel)
723 __DMA_ASSERTD((DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0);
724 DmacSg::FailCount[aChannel.PslId()] = 1;
729 TInt DSimSgController::MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount)
731 __DMA_ASSERTD((DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0);
732 __DMA_ASSERTD(aInterruptCount >= 0);
733 DmacSg::InterruptsToMiss[aChannel.PslId()] = aInterruptCount;
738 TBool DSimSgController::IsIdle(const TDmaChannel& aChannel)
740 return (DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0;
744 TInt DSimSgController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
746 return KMaxTransferSize;
750 TUint DSimSgController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
752 return KMemAlignMask;
756 void DSimSgController::Isr()
758 for (TInt i = 0; i < KChannelCount; i++)
760 TUint32 mask = (1 << i);
761 if (DmacSg::CompletionInt & mask)
763 DmacSg::CompletionInt &= ~mask;
764 HandleIsr(SgController.iChannels[i], ETrue);
766 if (DmacSg::ErrorInt & mask)
768 DmacSg::ErrorInt &= ~mask;
769 HandleIsr(SgController.iChannels[i], EFalse);
775 //////////////////////////////////////////////////////////////////////////////
776 // Channel opening/closing
778 enum TController { ESb=0, EDb=1, ESg=2 };
780 const TUint32 KControllerMask = 0x30;
781 const TUint32 KControllerShift = 4;
782 const TUint32 KChannelIdxMask = 3;
784 #define MKCHN(type, idx) (((type)<<KControllerShift)|idx)
786 static TUint32 TestSbChannels[] = { MKCHN(ESb,0), MKCHN(ESb,1), MKCHN(ESb,2), MKCHN(ESb,3) };
787 static TUint32 TestDbChannels[] = { MKCHN(EDb,0), MKCHN(EDb,1), MKCHN(EDb,2), MKCHN(EDb,3) };
788 static TUint32 TestSgChannels[] = { MKCHN(ESg,0), MKCHN(ESg,1), MKCHN(ESg,2), MKCHN(ESg,3) };
790 static TDmaTestInfo TestInfo =
803 EXPORT_C const TDmaTestInfo& DmaTestInfo()
808 // Keep track of opened channels so Tick callback used to fake DMA
809 // transfers is enabled only when necessary.
810 static TInt OpenChannelCount = 0;
813 TDmaChannel* DmaChannelMgr::Open(TUint32 aOpenId)
815 TInt dmac = (aOpenId & KControllerMask) >> KControllerShift;
816 __DMA_ASSERTD(dmac < 3);
817 TInt i = aOpenId & KChannelIdxMask;
818 TDmaChannel* pC = NULL;
819 TDmac* controller = NULL;
823 pC = SbController.iChannels + i;
824 controller = &SbController;
827 pC = DbController.iChannels + i;
828 controller = &DbController;
831 pC = SgController.iChannels + i;
832 controller = &SgController;
838 if (++OpenChannelCount == 1)
840 __KTRACE_OPT(KDMA, Kern::Printf("Enabling DMA simulation"));
841 DmacSim::StartEmulation();
845 pC->iController = controller;
851 void DmaChannelMgr::Close(TDmaChannel* /*aChannel*/)
853 if (--OpenChannelCount == 0)
855 DmacSim::StopEmulation();
856 __KTRACE_OPT(KDMA, Kern::Printf("Stopping DMA simulation"));
860 TInt DmaChannelMgr::StaticExtension(TInt /*aCmd*/, TAny* /*aArg*/)
862 return KErrNotSupported;
865 //////////////////////////////////////////////////////////////////////////////
868 // On hardware, this code is inside a kernel extension.
871 DECLARE_STANDARD_EXTENSION()
873 __KTRACE_OPT(KDMA, Kern::Printf("Starting DMA simulator..."));
875 r = SbController.Create(DSimSbController::KInfo);
878 r = DbController.Create(DSimDbController::KInfo);
881 r = SgController.Create(DSimSgController::KInfo);
889 // On WINS, this code is inside a LDD (see mmp file) so we need some
890 // bootstrapping code to call the kernel extension entry point.
893 class DDummyLdd : public DLogicalDevice
896 // from DLogicalDevice
898 void GetCaps(TDes8& aDes) const;
899 TInt Create(DLogicalChannelBase*& aChannel);
902 TInt DDummyLdd::Create(DLogicalChannelBase*& aChannel)
908 TInt DDummyLdd::Install()
910 _LIT(KLddName, "DmaSim");
911 TInt r = SetName(&KLddName);
917 void DDummyLdd::GetCaps(TDes8& /*aDes*/) const
921 EXPORT_C DLogicalDevice* CreateLogicalDevice()
923 return new DDummyLdd;