kerneltest/e32test/dma/dmasim.cpp
changeset 0 a41df078684a
child 87 2f92ad2dc5db
child 90 947f0dc9f7a8
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    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.
       
    17 // 
       
    18 //
       
    19 
       
    20 #include <drivers/dma.h>
       
    21 #include <kernel/kern_priv.h>
       
    22 
       
    23 
       
    24 const char KDmaPanicCat[] = "DMASIM";
       
    25 
       
    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;
       
    29 
       
    30 typedef void (*TPseudoIsr)();
       
    31 
       
    32 const TInt KChannelCount = 4;								// # of channels per controller
       
    33 const TInt KDesCount = 256;									// # of descriptors allocated per controller
       
    34 
       
    35 //////////////////////////////////////////////////////////////////////////////
       
    36 // SOFTWARE DMA CONTROLLER SIMULATION
       
    37 //////////////////////////////////////////////////////////////////////////////
       
    38 
       
    39 class DmacSb
       
    40 /** Single-buffer DMA controller software simulation */
       
    41 	{
       
    42 public:
       
    43 	enum { ECsRun = 0x80000000 };
       
    44 public:
       
    45 	static void DoTransfer();
       
    46 private:
       
    47 	static void BurstTransfer();
       
    48 private:
       
    49 	static TInt CurrentChannel;
       
    50 public:
       
    51 	// pseudo registers
       
    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];
       
    62 	};
       
    63 
       
    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;
       
    73 
       
    74 void DmacSb::DoTransfer()
       
    75 	{
       
    76 	if (ControlStatus[CurrentChannel] & ECsRun)
       
    77 		{
       
    78 		if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
       
    79 			{
       
    80 			ControlStatus[CurrentChannel] &= ~ECsRun;
       
    81 			ErrorInt |= 1 << CurrentChannel;
       
    82 			Isr();
       
    83 			}
       
    84 		else
       
    85 			{
       
    86 			//__KTRACE_OPT(KDMA, Kern::Printf("DmacSb::DoTransfer channel %d", CurrentChannel));
       
    87 			if (Count[CurrentChannel] == 0)
       
    88 				{
       
    89 				//__KTRACE_OPT(KDMA, Kern::Printf("DmacSb::DoTransfer transfer complete"));
       
    90 				ControlStatus[CurrentChannel] &= ~ECsRun;
       
    91 				CompletionInt |= 1 << CurrentChannel;
       
    92 				Isr();
       
    93 				}
       
    94 			else
       
    95 				BurstTransfer();
       
    96 			}
       
    97 		}
       
    98 
       
    99 	CurrentChannel++;
       
   100 	if (CurrentChannel >= KChannelCount)
       
   101 		CurrentChannel = 0;
       
   102 	}
       
   103 
       
   104 void DmacSb::BurstTransfer()
       
   105 	{
       
   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;
       
   112 	}
       
   113 
       
   114 //////////////////////////////////////////////////////////////////////////////
       
   115 
       
   116 class DmacDb
       
   117 /** Double-buffer DMA controller software simulation */
       
   118 	{
       
   119 public:
       
   120 	enum { ECsRun = 0x80000000, ECsPrg = 0x40000000 };
       
   121 public:
       
   122 	static void Enable(TInt aIdx);
       
   123 	static void DoTransfer();
       
   124 private:
       
   125 	static TInt CurrentChannel;
       
   126 private:
       
   127 	// internal pseudo-registers
       
   128 	static TUint8* ActSrcAddr[KChannelCount];
       
   129 	static TUint8* ActDestAddr[KChannelCount];
       
   130 	static TInt ActCount[KChannelCount];
       
   131 public:
       
   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];
       
   144 	};
       
   145 
       
   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;
       
   159 
       
   160 void DmacDb::Enable(TInt aIdx)
       
   161 	{
       
   162 	if (ControlStatus[aIdx] & ECsRun)
       
   163 		ControlStatus[aIdx] |= ECsPrg;
       
   164 	else
       
   165 		{
       
   166 		ActSrcAddr[aIdx] = PrgSrcAddr[aIdx];
       
   167 		ActDestAddr[aIdx] = PrgDestAddr[aIdx];
       
   168 		ActCount[aIdx] = PrgCount[aIdx];
       
   169 		ControlStatus[aIdx] |= ECsRun;
       
   170 		}
       
   171 	}
       
   172 
       
   173 void DmacDb::DoTransfer()
       
   174 	{
       
   175 	if (ControlStatus[CurrentChannel] & ECsRun)
       
   176 		{
       
   177 		if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
       
   178 			{
       
   179 			ControlStatus[CurrentChannel] &= ~ECsRun;
       
   180 			ErrorInt |= 1 << CurrentChannel;
       
   181 			Isr();
       
   182 			}
       
   183 		else
       
   184 			{
       
   185 			if (ActCount[CurrentChannel] == 0)
       
   186 				{
       
   187 				if (ControlStatus[CurrentChannel] & ECsPrg)
       
   188 					{
       
   189 					ActSrcAddr[CurrentChannel] = PrgSrcAddr[CurrentChannel];
       
   190 					ActDestAddr[CurrentChannel] = PrgDestAddr[CurrentChannel];
       
   191 					ActCount[CurrentChannel] = PrgCount[CurrentChannel];
       
   192 					ControlStatus[CurrentChannel] &= ~ECsPrg;
       
   193 					}
       
   194 				else
       
   195 					ControlStatus[CurrentChannel] &= ~ECsRun;
       
   196 				if (InterruptsToMiss[CurrentChannel] > 0)
       
   197 					InterruptsToMiss[CurrentChannel]--;
       
   198 				else
       
   199 					{
       
   200 					CompletionInt |= 1 << CurrentChannel;
       
   201 					Isr();
       
   202 					}
       
   203 				}
       
   204 			else
       
   205 				{
       
   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;
       
   211 				}
       
   212 			}
       
   213 		}
       
   214 
       
   215 	CurrentChannel++;
       
   216 	if (CurrentChannel >= KChannelCount)
       
   217 		CurrentChannel = 0;
       
   218 	}
       
   219 
       
   220 
       
   221 //////////////////////////////////////////////////////////////////////////////
       
   222 
       
   223 class DmacSg
       
   224 /** Scatter/gather DMA controller software simulation */
       
   225 	{
       
   226 public:
       
   227 	enum { EChannelBitRun = 0x80000000 };
       
   228 	enum { EDesBitInt = 1 };
       
   229 	struct SDes
       
   230 		{
       
   231 		TUint8* iSrcAddr;
       
   232 		TUint8* iDestAddr;
       
   233 		TInt iCount;
       
   234 		TUint iControl;
       
   235 		SDes* iNext;
       
   236 		};
       
   237 public:
       
   238 	static void DoTransfer();
       
   239 	static void Enable(TInt aIdx);
       
   240 private:
       
   241 	static TInt CurrentChannel;
       
   242 	static TBool IsDescriptorLoaded[KChannelCount];
       
   243 public:
       
   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];
       
   258 	};
       
   259 
       
   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];
       
   273 
       
   274 
       
   275 void DmacSg::DoTransfer()
       
   276 	{
       
   277 	if (ChannelControl[CurrentChannel] & EChannelBitRun)
       
   278 		{
       
   279 		if (FailCount[CurrentChannel] > 0 && --FailCount[CurrentChannel] == 0)
       
   280 			{
       
   281 			ChannelControl[CurrentChannel] &= ~EChannelBitRun;
       
   282 			ErrorInt |= 1 << CurrentChannel;
       
   283 			Isr();
       
   284 			}
       
   285 		else
       
   286 			{
       
   287 			if (IsDescriptorLoaded[CurrentChannel])
       
   288 				{
       
   289 				if (Count[CurrentChannel] == 0)
       
   290 					{
       
   291 					IsDescriptorLoaded[CurrentChannel] = EFalse;
       
   292 					if (Control[CurrentChannel] & EDesBitInt)
       
   293 						{
       
   294 						if (InterruptsToMiss[CurrentChannel] > 0)
       
   295 							InterruptsToMiss[CurrentChannel]--;
       
   296 						else
       
   297 							{
       
   298 							CompletionInt |= 1 << CurrentChannel;
       
   299 							Isr();
       
   300 							}
       
   301 						}
       
   302 					}
       
   303 				else
       
   304 					{
       
   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;
       
   310 					}
       
   311 				}
       
   312 			// Need to test again as new descriptor must be loaded if
       
   313 			// completion has just occured.
       
   314 			if (! IsDescriptorLoaded[CurrentChannel])
       
   315 				{
       
   316 				if (NextDes[CurrentChannel] != NULL)
       
   317 					{
       
   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;
       
   324 					}
       
   325 				else
       
   326 					ChannelControl[CurrentChannel] &= ~EChannelBitRun;
       
   327 				}
       
   328 			}
       
   329 		}
       
   330 
       
   331 	CurrentChannel++;
       
   332 	if (CurrentChannel >= KChannelCount)
       
   333 		CurrentChannel = 0;
       
   334 	}
       
   335 
       
   336 
       
   337 void DmacSg::Enable(TInt aIdx)
       
   338 	{
       
   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;
       
   346 	}
       
   347 
       
   348 //////////////////////////////////////////////////////////////////////////////
       
   349 
       
   350 class DmacSim
       
   351 /** 
       
   352  Harness calling the various DMA controller simulators periodically.
       
   353  */
       
   354 	{
       
   355 public:
       
   356 	static void StartEmulation();
       
   357 	static void StopEmulation();
       
   358 private:
       
   359 	enum { KPeriod = 1 }; // in ms
       
   360 	static void TickCB(TAny* aThis);
       
   361 	static NTimer Timer;
       
   362 	};
       
   363 
       
   364 NTimer DmacSim::Timer;
       
   365 
       
   366 void DmacSim::StartEmulation()
       
   367 	{
       
   368 	new (&Timer) NTimer(&TickCB, 0);
       
   369 	__DMA_ASSERTA(Timer.OneShot(KPeriod, EFalse) == KErrNone);
       
   370 	}
       
   371 
       
   372 void DmacSim::StopEmulation()
       
   373 	{
       
   374 	Timer.Cancel();
       
   375 	}
       
   376 
       
   377 void DmacSim::TickCB(TAny*)
       
   378 	{
       
   379 	DmacSb::DoTransfer();
       
   380 	DmacDb::DoTransfer();
       
   381 	DmacSg::DoTransfer();
       
   382 	__DMA_ASSERTA(Timer.Again(KPeriod) == KErrNone);
       
   383 	}
       
   384 
       
   385 //////////////////////////////////////////////////////////////////////////////
       
   386 // PSL FOR DMA SIMULATION
       
   387 //////////////////////////////////////////////////////////////////////////////
       
   388 
       
   389 class DSimSbController : public TDmac
       
   390 	{
       
   391 public:
       
   392 	DSimSbController();
       
   393 private:
       
   394 	static void Isr();
       
   395 	// from 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);
       
   402 public:
       
   403 	static const SCreateInfo KInfo;
       
   404 	TDmaSbChannel iChannels[KChannelCount];
       
   405 	};
       
   406 
       
   407 DSimSbController SbController;
       
   408 
       
   409 const TDmac::SCreateInfo DSimSbController::KInfo =
       
   410 	{
       
   411 	KChannelCount,
       
   412 	KDesCount,
       
   413 	0,
       
   414 	sizeof(SDmaPseudoDes),
       
   415 	0,
       
   416 	};
       
   417 
       
   418 DSimSbController::DSimSbController()
       
   419 	: TDmac(KInfo)
       
   420 	{
       
   421 	DmacSb::Isr = Isr;
       
   422 	}
       
   423 
       
   424 
       
   425 void DSimSbController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
       
   426 	{
       
   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;
       
   433 	}
       
   434 
       
   435 
       
   436 void DSimSbController::StopTransfer(const TDmaChannel& aChannel)
       
   437 	{
       
   438 	__e32_atomic_and_ord32(&DmacSb::ControlStatus[aChannel.PslId()], (TUint32)~DmacSb::ECsRun);
       
   439 	}
       
   440 
       
   441 
       
   442 TInt DSimSbController::FailNext(const TDmaChannel& aChannel)
       
   443 	{
       
   444 	DmacSb::FailCount[aChannel.PslId()] = 1;
       
   445 	return KErrNone;
       
   446 	}
       
   447 
       
   448 
       
   449 TBool DSimSbController::IsIdle(const TDmaChannel& aChannel)
       
   450 	{
       
   451 	return (DmacSb::ControlStatus[aChannel.PslId()] & DmacSb::ECsRun) == 0;
       
   452 	}
       
   453 
       
   454 
       
   455 TInt DSimSbController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   456 	{
       
   457 	return KMaxTransferSize;
       
   458 	}
       
   459 
       
   460 
       
   461 TUint DSimSbController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   462 	{
       
   463 	return KMemAlignMask;
       
   464 	}
       
   465 
       
   466 
       
   467 void DSimSbController::Isr()
       
   468 	{
       
   469 	for (TInt i = 0; i < KChannelCount; i++)
       
   470 		{
       
   471 		TUint32 mask = (1 << i);
       
   472 		if (DmacSb::CompletionInt & mask)
       
   473 			{
       
   474 			DmacSb::CompletionInt &= ~mask;
       
   475 			HandleIsr(SbController.iChannels[i], ETrue);
       
   476 			}
       
   477 		if (DmacSb::ErrorInt & mask)
       
   478 			{
       
   479 			DmacSb::ErrorInt &= ~mask;
       
   480 			HandleIsr(SbController.iChannels[i], EFalse);
       
   481 			}
       
   482 		}
       
   483 	}
       
   484 
       
   485 //////////////////////////////////////////////////////////////////////////////
       
   486 
       
   487 class DSimDbController : public TDmac
       
   488 	{
       
   489 public:
       
   490 	DSimDbController();
       
   491 private:
       
   492 	static void Isr();
       
   493 	// from 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);
       
   501 public:
       
   502 	static const SCreateInfo KInfo;
       
   503 	TDmaDbChannel iChannels[KChannelCount];
       
   504 	};
       
   505 
       
   506 DSimDbController DbController;
       
   507 
       
   508 const TDmac::SCreateInfo DSimDbController::KInfo =
       
   509 	{
       
   510 	KChannelCount,
       
   511 	KDesCount,
       
   512 	0,
       
   513 	sizeof(SDmaPseudoDes),
       
   514 	0,
       
   515 	};
       
   516 
       
   517 
       
   518 DSimDbController::DSimDbController()
       
   519 	: TDmac(KInfo)
       
   520 	{
       
   521 	DmacDb::Isr = Isr;
       
   522 	}
       
   523 
       
   524 
       
   525 void DSimDbController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
       
   526 	{
       
   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;
       
   532 	DmacDb::Enable(i);
       
   533 	}
       
   534 
       
   535 
       
   536 void DSimDbController::StopTransfer(const TDmaChannel& aChannel)
       
   537 	{
       
   538 	__e32_atomic_and_ord32(&DmacDb::ControlStatus[aChannel.PslId()], (TUint32)~(DmacDb::ECsRun|DmacDb::ECsPrg));
       
   539 	}
       
   540 
       
   541 
       
   542 TInt DSimDbController::FailNext(const TDmaChannel& aChannel)
       
   543 	{
       
   544 	DmacDb::FailCount[aChannel.PslId()] = 1;
       
   545 	return KErrNone;
       
   546 	}
       
   547 
       
   548 
       
   549 TInt DSimDbController::MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount)
       
   550 	{
       
   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)
       
   555 		{
       
   556 		DmacDb::InterruptsToMiss[aChannel.PslId()] = aInterruptCount;
       
   557 		return KErrNone;
       
   558 		}
       
   559 	else
       
   560 		return KErrNotSupported;
       
   561 	}
       
   562 
       
   563 
       
   564 TBool DSimDbController::IsIdle(const TDmaChannel& aChannel)
       
   565 	{
       
   566 	return (DmacDb::ControlStatus[aChannel.PslId()] & DmacDb::ECsRun) == 0;
       
   567 	}
       
   568 
       
   569 
       
   570 TInt DSimDbController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   571 	{
       
   572 	return KMaxTransferSize;
       
   573 	}
       
   574 
       
   575 
       
   576 TUint DSimDbController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   577 	{
       
   578 	return KMemAlignMask;
       
   579 	}
       
   580 
       
   581 
       
   582 void DSimDbController::Isr()
       
   583 	{
       
   584 	for (TInt i = 0; i < KChannelCount; i++)
       
   585 		{
       
   586 		TUint32 mask = (1 << i);
       
   587 		if (DmacDb::CompletionInt & mask)
       
   588 			{
       
   589 			DmacDb::CompletionInt &= ~mask;
       
   590 			HandleIsr(DbController.iChannels[i], ETrue);
       
   591 			}
       
   592 		if (DmacDb::ErrorInt & mask)
       
   593 			{
       
   594 			DmacDb::ErrorInt &= ~mask;
       
   595 			HandleIsr(DbController.iChannels[i], EFalse);
       
   596 			}
       
   597 		}
       
   598 	}
       
   599 
       
   600 //////////////////////////////////////////////////////////////////////////////
       
   601 
       
   602 class DSimSgController : public TDmac
       
   603 	{
       
   604 public:
       
   605 	DSimSgController();
       
   606 private:
       
   607 	static void Isr();
       
   608 	// from 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);
       
   622 private:
       
   623 	inline DmacSg::SDes* HdrToHwDes(const SDmaDesHdr& aHdr);
       
   624 public:
       
   625 	static const SCreateInfo KInfo;
       
   626 	TDmaSgChannel iChannels[KChannelCount];
       
   627 	};
       
   628 
       
   629 DSimSgController SgController;
       
   630 
       
   631 const TDmac::SCreateInfo DSimSgController::KInfo =
       
   632 	{
       
   633 	KChannelCount,
       
   634 	KDesCount,
       
   635 	KCapsBitHwDes,
       
   636 	sizeof(DmacSg::SDes),
       
   637 #ifdef __WINS__
       
   638 	0,
       
   639 #else
       
   640 	EMapAttrSupRw|EMapAttrFullyBlocking,
       
   641 #endif
       
   642 	};
       
   643 
       
   644 
       
   645 inline DmacSg::SDes* DSimSgController::HdrToHwDes(const SDmaDesHdr& aHdr)
       
   646 	{
       
   647 	return static_cast<DmacSg::SDes*>(TDmac::HdrToHwDes(aHdr));
       
   648 	}
       
   649 
       
   650 
       
   651 DSimSgController::DSimSgController()
       
   652 	: TDmac(KInfo)
       
   653 	{
       
   654 	DmacSg::Isr = Isr;
       
   655 	}
       
   656 
       
   657 
       
   658 void DSimSgController::Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr)
       
   659 	{
       
   660 	TUint32 i = aChannel.PslId();
       
   661 	DmacSg::NextDes[i] = HdrToHwDes(aHdr);
       
   662 	DmacSg::Enable(i);
       
   663 	}
       
   664 
       
   665 
       
   666 void DSimSgController::StopTransfer(const TDmaChannel& aChannel)
       
   667 	{
       
   668 	__e32_atomic_and_ord32(&DmacSg::ChannelControl[aChannel.PslId()], (TUint32)~DmacSg::EChannelBitRun);
       
   669 	}
       
   670 
       
   671 
       
   672 void DSimSgController::InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
       
   673 								 TUint /*aFlags*/, TUint32 /*aPslInfo*/, TUint32 /*aCookie*/)
       
   674 	{
       
   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;
       
   680 	des.iNext = NULL;
       
   681 	}
       
   682 
       
   683 
       
   684 void DSimSgController::ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr)
       
   685 	{
       
   686 	DmacSg::SDes& des = *HdrToHwDes(aHdr);
       
   687 	des.iControl &= ~DmacSg::EDesBitInt;
       
   688 	des.iNext = HdrToHwDes(aNextHdr);
       
   689 	}
       
   690 
       
   691 
       
   692 void DSimSgController::AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
       
   693 								   const SDmaDesHdr& aNewHdr)
       
   694 	{
       
   695 	TUint32 i = aChannel.PslId();
       
   696 	DmacSg::SDes* pNewDes = HdrToHwDes(aNewHdr);
       
   697 	TInt prevLevel = NKern::DisableAllInterrupts();
       
   698 
       
   699 	if ((DmacSg::ChannelControl[i] & DmacSg::EChannelBitRun) == 0)
       
   700 		{
       
   701 		DmacSg::NextDes[i] = pNewDes;
       
   702 		DmacSg::Enable(i);
       
   703 		}
       
   704 	else if (DmacSg::NextDes[i] == NULL)
       
   705 		DmacSg::NextDes[i] = pNewDes;
       
   706 	else
       
   707 		HdrToHwDes(aLastHdr)->iNext = pNewDes;
       
   708 
       
   709 	NKern::RestoreInterrupts(prevLevel);
       
   710 	}
       
   711 
       
   712 
       
   713 void DSimSgController::UnlinkHwDes(const TDmaChannel& /*aChannel*/, SDmaDesHdr& aHdr)
       
   714 	{
       
   715   	DmacSg::SDes* pD = HdrToHwDes(aHdr);
       
   716 	pD->iNext = NULL;
       
   717 	pD->iControl |= DmacSg::EDesBitInt;
       
   718 	}
       
   719 
       
   720 
       
   721 TInt DSimSgController::FailNext(const TDmaChannel& aChannel)
       
   722 	{
       
   723 	__DMA_ASSERTD((DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0);
       
   724 	DmacSg::FailCount[aChannel.PslId()] = 1;
       
   725 	return KErrNone;
       
   726 	}
       
   727 
       
   728 
       
   729 TInt DSimSgController::MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount)
       
   730 	{
       
   731 	__DMA_ASSERTD((DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0);
       
   732 	__DMA_ASSERTD(aInterruptCount >= 0);
       
   733 	DmacSg::InterruptsToMiss[aChannel.PslId()] = aInterruptCount;
       
   734 	return KErrNone;
       
   735 	}
       
   736 
       
   737 
       
   738 TBool DSimSgController::IsIdle(const TDmaChannel& aChannel)
       
   739 	{
       
   740 	return (DmacSg::ChannelControl[aChannel.PslId()] & DmacSg::EChannelBitRun) == 0;
       
   741 	}
       
   742 
       
   743 
       
   744 TInt DSimSgController::MaxTransferSize(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   745 	{
       
   746 	return KMaxTransferSize;
       
   747 	}
       
   748 
       
   749 
       
   750 TUint DSimSgController::MemAlignMask(TDmaChannel& /*aChannel*/, TUint /*aFlags*/, TUint32 /*aPslInfo*/)
       
   751 	{
       
   752 	return KMemAlignMask;
       
   753 	}
       
   754 
       
   755 
       
   756 void DSimSgController::Isr()
       
   757 	{
       
   758 	for (TInt i = 0; i < KChannelCount; i++)
       
   759 		{
       
   760 		TUint32 mask = (1 << i);
       
   761 		if (DmacSg::CompletionInt & mask)
       
   762 			{
       
   763 			DmacSg::CompletionInt &= ~mask;
       
   764 			HandleIsr(SgController.iChannels[i], ETrue);
       
   765 			}
       
   766 		if (DmacSg::ErrorInt & mask)
       
   767 			{
       
   768 			DmacSg::ErrorInt &= ~mask;
       
   769 			HandleIsr(SgController.iChannels[i], EFalse);
       
   770 			}
       
   771 		}
       
   772 	}
       
   773 
       
   774 
       
   775 //////////////////////////////////////////////////////////////////////////////
       
   776 // Channel opening/closing
       
   777 
       
   778 enum TController { ESb=0, EDb=1, ESg=2 };
       
   779 
       
   780 const TUint32 KControllerMask = 0x30;
       
   781 const TUint32 KControllerShift = 4;
       
   782 const TUint32 KChannelIdxMask = 3;
       
   783 
       
   784 #define MKCHN(type, idx) (((type)<<KControllerShift)|idx)
       
   785 
       
   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) };
       
   789 
       
   790 static TDmaTestInfo TestInfo =
       
   791 	{
       
   792 	KMaxTransferSize,
       
   793 	KMemAlignMask,
       
   794 	0,
       
   795 	KChannelCount,
       
   796 	TestSbChannels,
       
   797 	KChannelCount,
       
   798 	TestDbChannels,
       
   799 	KChannelCount,
       
   800 	TestSgChannels,
       
   801 	};
       
   802 
       
   803 EXPORT_C const TDmaTestInfo& DmaTestInfo()
       
   804 	{
       
   805 	return TestInfo;
       
   806 	}
       
   807 
       
   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;
       
   811 
       
   812 
       
   813 TDmaChannel* DmaChannelMgr::Open(TUint32 aOpenId)
       
   814 	{
       
   815 	TInt dmac = (aOpenId & KControllerMask) >> KControllerShift;
       
   816 	__DMA_ASSERTD(dmac < 3);
       
   817 	TInt i = aOpenId & KChannelIdxMask;
       
   818 	TDmaChannel* pC = NULL;
       
   819 	TDmac* controller = NULL;
       
   820 	switch (dmac)
       
   821 		{
       
   822 	case ESb:
       
   823 		pC = SbController.iChannels + i;
       
   824 		controller = &SbController;
       
   825 		break;
       
   826 	case EDb:
       
   827 		pC = DbController.iChannels + i;
       
   828 		controller = &DbController;
       
   829 		break;
       
   830 	case ESg:
       
   831 		pC = SgController.iChannels + i;
       
   832 		controller = &SgController;
       
   833 		break;
       
   834 	default:
       
   835 		__DMA_CANT_HAPPEN();
       
   836 		}
       
   837 
       
   838 	if (++OpenChannelCount == 1)
       
   839 		{
       
   840 		__KTRACE_OPT(KDMA, Kern::Printf("Enabling DMA simulation"));
       
   841 		DmacSim::StartEmulation();
       
   842 		}
       
   843 	if (pC->IsOpened())
       
   844 		return NULL;
       
   845 	pC->iController = controller;
       
   846 	pC->iPslId = i;
       
   847 	return pC;
       
   848 	}
       
   849 
       
   850 
       
   851 void DmaChannelMgr::Close(TDmaChannel* /*aChannel*/)
       
   852 	{
       
   853 	if (--OpenChannelCount == 0)
       
   854 		{
       
   855 		DmacSim::StopEmulation();
       
   856 		__KTRACE_OPT(KDMA, Kern::Printf("Stopping DMA simulation"));
       
   857 		}
       
   858 	}
       
   859 
       
   860 TInt DmaChannelMgr::StaticExtension(TInt /*aCmd*/, TAny* /*aArg*/)
       
   861 	{
       
   862 	return KErrNotSupported;
       
   863 	}
       
   864 
       
   865 //////////////////////////////////////////////////////////////////////////////
       
   866 
       
   867 //
       
   868 // On hardware, this code is inside a kernel extension.
       
   869 //
       
   870 
       
   871 DECLARE_STANDARD_EXTENSION()
       
   872 	{
       
   873 	__KTRACE_OPT(KDMA, Kern::Printf("Starting DMA simulator..."));
       
   874 	TInt r;
       
   875 	r = SbController.Create(DSimSbController::KInfo);
       
   876 	if (r != KErrNone)
       
   877 		return r;
       
   878 	r = DbController.Create(DSimDbController::KInfo);
       
   879 	if (r != KErrNone)
       
   880 		return r;
       
   881 	r = SgController.Create(DSimSgController::KInfo);
       
   882 	if (r != KErrNone)
       
   883 		return r;
       
   884 
       
   885 	return KErrNone;
       
   886 	}
       
   887 
       
   888 //
       
   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.
       
   891 //
       
   892 
       
   893 class DDummyLdd : public DLogicalDevice
       
   894 	{
       
   895 public:
       
   896 	// from DLogicalDevice
       
   897 	TInt Install();
       
   898 	void GetCaps(TDes8& aDes) const;
       
   899 	TInt Create(DLogicalChannelBase*& aChannel);
       
   900 	};
       
   901 
       
   902 TInt DDummyLdd::Create(DLogicalChannelBase*& aChannel)
       
   903     {
       
   904 	aChannel=NULL;
       
   905 	return KErrNone;
       
   906     }
       
   907 
       
   908 TInt DDummyLdd::Install()
       
   909     {
       
   910 	_LIT(KLddName, "DmaSim");
       
   911     TInt r = SetName(&KLddName);
       
   912 	if (r == KErrNone)
       
   913 		r = InitExtension();
       
   914 	return r;
       
   915     }
       
   916 
       
   917 void DDummyLdd::GetCaps(TDes8& /*aDes*/) const
       
   918     {
       
   919     }
       
   920 
       
   921 EXPORT_C DLogicalDevice* CreateLogicalDevice()
       
   922 	{
       
   923     return new DDummyLdd;
       
   924 	}
       
   925 
       
   926 
       
   927 //---