kernel/eka/drivers/usbc/usbdma.cpp
changeset 0 a41df078684a
child 33 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2000-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 // e32\drivers\usbc\usbdma.cpp
       
    15 // LDD for USB Device driver stack:
       
    16 // Management of DMA-capable data buffers.
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file usbdma.cpp
       
    22  @internalTechnology
       
    23 */
       
    24 
       
    25 #include <drivers/usbc.h>
       
    26 
       
    27 
       
    28 #if defined(_DEBUG)
       
    29 static const char KUsbPanicLdd[] = "USB LDD";
       
    30 #endif
       
    31 
       
    32 
       
    33 TDmaBuf::TDmaBuf(TUsbcEndpointInfo* aEndpointInfo, TInt aBandwidthPriority)
       
    34 	: iBufBasePtr(NULL),
       
    35 	  iCurrentDrainingBuffer(NULL),
       
    36 	  iCurrentPacket(0),
       
    37 	  iCurrentPacketIndexArray(NULL),
       
    38 	  iCurrentPacketSizeArray(NULL)
       
    39 	{
       
    40 	iMaxPacketSize = aEndpointInfo->iSize;
       
    41 	iEndpointType = aEndpointInfo->iType;
       
    42 
       
    43 	switch (aEndpointInfo->iType)
       
    44 		{
       
    45 	case KUsbEpTypeControl:
       
    46 		iBufSz = KUsbcDmaBufSzControl;
       
    47 		iNumberofBuffers = KUsbcDmaBufNumControl;
       
    48 		break;
       
    49 	case KUsbEpTypeIsochronous:
       
    50 		iBufSz = KUsbcDmaBufSzIsochronous;
       
    51 		iNumberofBuffers = KUsbcDmaBufNumIsochronous;
       
    52 		break;
       
    53 	case KUsbEpTypeBulk:
       
    54 		{
       
    55 		if (aEndpointInfo->iDir == KUsbEpDirOut)
       
    56 			{
       
    57 			const TInt priorityOUT = aBandwidthPriority & 0x0f;
       
    58 			iBufSz = KUsbcDmaBufSizesBulkOUT[priorityOUT];
       
    59 			}
       
    60 		else
       
    61 			{
       
    62 			const TInt priorityIN = (aBandwidthPriority >> 4) & 0x0f;
       
    63 			iBufSz = KUsbcDmaBufSizesBulkIN[priorityIN];
       
    64 			}
       
    65 		iNumberofBuffers = KUsbcDmaBufNumBulk;
       
    66 		}
       
    67 		break;
       
    68 	case KUsbEpTypeInterrupt:
       
    69 		iBufSz = KUsbcDmaBufSzInterrupt;
       
    70 		iNumberofBuffers = KUsbcDmaBufNumInterrupt;
       
    71 		break;
       
    72 	default:
       
    73 		iBufSz = 0;
       
    74 		iNumberofBuffers = 0;
       
    75 		}
       
    76 
       
    77 	if (aEndpointInfo->iDir == KUsbEpDirIn)
       
    78 		{
       
    79 		iNumberofBuffers = 1;								// IN endpoints only have 1 buffer
       
    80 		}
       
    81 
       
    82 	for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
       
    83 		{
       
    84 		// Buffer logical addresses (pointers)
       
    85 		iBuffers[i] = NULL;
       
    86 		// Buffer physical addresses
       
    87 		iBufferPhys[i] = 0;
       
    88 		// Packet indexes base array
       
    89 		iPacketIndex[i] = NULL;
       
    90 		// Packet sizes base array
       
    91 		iPacketSize[i] = NULL;
       
    92 		}
       
    93 	}
       
    94 
       
    95 
       
    96 TInt TDmaBuf::Construct(TUsbcEndpointInfo* aEndpointInfo)
       
    97 	{
       
    98 	if (aEndpointInfo->iDir != KUsbEpDirIn)
       
    99 		{
       
   100 		// IN endpoints don't need a packet array
       
   101 
       
   102 		// At most 2 packets (clump of max packet size packets) + possible zlp
       
   103 		TUsbcPacketArray* bufPtr = iPacketInfoStorage;
       
   104 		// this divides up the packet indexing & packet size array over the number of buffers
       
   105 		__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() array base=0x%08x", bufPtr));
       
   106 		for (TInt i = 0; i < iNumberofBuffers; i++)
       
   107 			{
       
   108 			iPacketIndex[i] = bufPtr;
       
   109 			bufPtr += KUsbcDmaBufMaxPkts;
       
   110 			iPacketSize[i] = bufPtr;
       
   111 			bufPtr += KUsbcDmaBufMaxPkts;
       
   112 			__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() packetIndex[%d]=0x%08x packetSize[%d]=0x%08x",
       
   113 											i, iPacketIndex[i], i, iPacketSize[i]));
       
   114 			}
       
   115 		}
       
   116 	else
       
   117 		{
       
   118 		__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() IN endpoint"));
       
   119 		}
       
   120 	Flush();
       
   121 	return KErrNone;
       
   122 	}
       
   123 
       
   124 
       
   125 TDmaBuf::~TDmaBuf()
       
   126 	{
       
   127 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::~TDmaBuf()"));
       
   128 	}
       
   129 
       
   130 
       
   131 TUint8* TDmaBuf::SetBufferBase(TUint8* aBase)
       
   132 	{
       
   133 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::SetBufferBase base=0x%08x size=0x%08x", aBase, iBufSz));
       
   134 	TUint8* bufPtr = aBase;
       
   135 	iBufBasePtr = aBase;
       
   136 	for (TInt i = 0; i < iNumberofBuffers; i++)
       
   137 		{
       
   138 		iDrainable[i] = iCanBeFreed[i] = EFalse;
       
   139 		iBuffers[i] = bufPtr;
       
   140 		iBufferPhys[i] = Epoc::LinearToPhysical((TLinAddr)bufPtr);
       
   141 		bufPtr += iBufSz;
       
   142 		__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::SetBufferBase() iBuffers[%d]=0x%08x", i, iBuffers[i]));
       
   143 		}
       
   144 	return bufPtr;
       
   145 	}
       
   146 
       
   147 
       
   148 TInt TDmaBuf::BufferTotalSize() const
       
   149 	{
       
   150 	return iBufSz * iNumberofBuffers;
       
   151 	}
       
   152 
       
   153 
       
   154 TUint8* TDmaBuf::BufferBase() const
       
   155 	{
       
   156 	return iBufBasePtr;
       
   157 	}
       
   158 
       
   159 
       
   160 void TDmaBuf::SetMaxPacketSize(TInt aSize)
       
   161 	{
       
   162 	iMaxPacketSize = aSize;
       
   163 	}
       
   164 
       
   165 
       
   166 void TDmaBuf::Flush()
       
   167 	{
       
   168 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Flush %x", this));
       
   169 	iRxActive = EFalse;
       
   170 	iTxActive = EFalse;
       
   171 	iExtractOffset = 0;
       
   172 	iTotalRxBytesAvail = 0;
       
   173 	iTotalRxPacketsAvail = 0;
       
   174 	iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
       
   175 	iCurrentFillingBufferIndex = 0;
       
   176 	iDrainQueueIndex = KUsbcInvalidDrainQueueIndex;
       
   177 	for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
       
   178 		{
       
   179 		iDrainable[i] = EFalse;
       
   180 		iCanBeFreed[i] = EFalse;
       
   181 		iNumberofBytesRx[i] = 0;
       
   182 		iNumberofPacketsRx[i] = 0;
       
   183 		iError[i] = KErrGeneral;
       
   184 		iDrainQueue[i] = KUsbcInvalidBufferIndex;
       
   185 #if defined(USBC_LDD_BUFFER_TRACE)
       
   186 		iFillingOrderArray[i] = 0;
       
   187 		iNumberofBytesRxRemain[i] = 0;
       
   188 		iNumberofPacketsRxRemain[i] = 0;
       
   189 #endif
       
   190 		}
       
   191 	// Drain queue is 1 oversized
       
   192 	iDrainQueue[KUsbcDmaBufNumMax] = KUsbcInvalidBufferIndex;
       
   193 
       
   194 #if defined(USBC_LDD_BUFFER_TRACE)
       
   195 	iFillingOrder = 0;
       
   196 	iDrainingOrder = 0;
       
   197 #endif
       
   198 	}
       
   199 
       
   200 
       
   201 void TDmaBuf::RxSetActive()
       
   202 	{
       
   203 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetActive %x", this));
       
   204 	iRxActive = ETrue;
       
   205 	}
       
   206 
       
   207 
       
   208 void TDmaBuf::RxSetInActive()
       
   209 	{
       
   210 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetInActive %x", this));
       
   211 	iRxActive = EFalse;
       
   212 	}
       
   213 
       
   214 
       
   215 TBool TDmaBuf::RxIsActive()
       
   216 	{
       
   217 	return iRxActive;
       
   218 	}
       
   219 
       
   220 
       
   221 void TDmaBuf::TxSetActive()
       
   222 	{
       
   223 	iTxActive = ETrue;
       
   224 	}
       
   225 
       
   226 
       
   227 void TDmaBuf::TxSetInActive()
       
   228 	{
       
   229 	iTxActive = EFalse;
       
   230 	}
       
   231 
       
   232 
       
   233 TBool TDmaBuf::TxIsActive()
       
   234 	{
       
   235 	return iTxActive;
       
   236 	}
       
   237 
       
   238 
       
   239 /**************************** Rx DMA Buffer Access *************************/
       
   240 
       
   241 void TDmaBuf::ModifyTotalRxBytesAvail(TInt aVal)
       
   242 	{
       
   243 	iTotalRxBytesAvail += aVal;
       
   244 	}
       
   245 
       
   246 
       
   247 void TDmaBuf::ModifyTotalRxPacketsAvail(TInt aVal)
       
   248 	{
       
   249 	iTotalRxPacketsAvail += aVal;
       
   250 	}
       
   251 
       
   252 
       
   253 TBool TDmaBuf::AdvancePacket()
       
   254 	{
       
   255 	ModifyTotalRxPacketsAvail(-1);
       
   256 	TBool r = ETrue;
       
   257 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
       
   258 					   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   259 	if (++iCurrentPacket >= iNumberofPacketsRx[iCurrentDrainingBufferIndex])
       
   260 		{
       
   261 		r = NextDrainableBuffer();
       
   262 		}
       
   263 	iExtractOffset = 0;
       
   264 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
       
   265 				   (iCurrentPacket < KUsbcDmaBufMaxPkts),
       
   266 				   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   267 	return r;
       
   268 	}
       
   269 
       
   270 
       
   271 TInt TDmaBuf::PeekNextPacketSize()
       
   272 	{
       
   273 	TUint pkt = iCurrentPacket;
       
   274 	TInt index = iCurrentDrainingBufferIndex;
       
   275 	TInt size = -1;
       
   276 	if (pkt >= iNumberofPacketsRx[index])
       
   277 		{
       
   278 		index = PeekNextDrainableBuffer();
       
   279 		pkt = 0;
       
   280 		}
       
   281 
       
   282 	if ((index != KUsbcInvalidBufferIndex) && iNumberofPacketsRx[index])
       
   283 		{
       
   284 		const TUsbcPacketArray* sizeArray = iPacketSize[index];
       
   285 		size = (TInt)sizeArray[pkt];
       
   286 		}
       
   287 
       
   288 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
       
   289 				   (iCurrentPacket < KUsbcDmaBufMaxPkts),
       
   290 				   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   291 	return size;
       
   292 	}
       
   293 
       
   294 
       
   295 inline TInt TDmaBuf::GetCurrentError()
       
   296 	{
       
   297 	// USB bus errors are v.rare. To avoid having an error code attached to every packet since
       
   298 	// almost every errorcode will be KErrNone, we have a single error code per buffer
       
   299 	// If the error code is != KErrNone then it refers to the LAST packet in the buffer
       
   300 	TInt errorCode = KErrNone;
       
   301 	//Check the index, it's not equal to negative (-1) value defined in 
       
   302 	//KUsbcInvalidBufferIndex.
       
   303 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
       
   304 					   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   305 	
       
   306 	if (iError[iCurrentDrainingBufferIndex] != KErrNone)
       
   307 		{
       
   308 		// See if we are at the last packet
       
   309 		if ((iCurrentPacket + 1) == iNumberofPacketsRx[iCurrentDrainingBufferIndex])
       
   310 			{
       
   311 			errorCode = iError[iCurrentDrainingBufferIndex];
       
   312 			}
       
   313 		}
       
   314 	return errorCode;
       
   315 	}
       
   316 
       
   317 
       
   318 // used to decide whether a client read can complete straight away
       
   319 TBool TDmaBuf::IsReaderEmpty()
       
   320 	{
       
   321 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::IsReaderEmpty iTotalRxPacketsAvail=%d",
       
   322 									iTotalRxPacketsAvail));
       
   323 	return (iTotalRxPacketsAvail == 0);
       
   324 	}
       
   325 
       
   326 
       
   327 void TDmaBuf::ReadXferComplete(TInt aNoBytesRecv, TInt aNoPacketsRecv, TInt aErrorCode)
       
   328 	{
       
   329 	// Adjust pending packet
       
   330 	if ((aNoBytesRecv == 0) && (aErrorCode != KErrNone))
       
   331 		{
       
   332 		// Make the buffer available for reuse
       
   333 		iDrainable[iCurrentFillingBufferIndex] = EFalse;
       
   334 		return;
       
   335 		}
       
   336 
       
   337 	ModifyTotalRxBytesAvail(aNoBytesRecv);
       
   338 	ModifyTotalRxPacketsAvail(aNoPacketsRecv);
       
   339 	iNumberofBytesRx[iCurrentFillingBufferIndex] = aNoBytesRecv;
       
   340 	iNumberofPacketsRx[iCurrentFillingBufferIndex] = aNoPacketsRecv;
       
   341 
       
   342 #if defined(USBC_LDD_BUFFER_TRACE)
       
   343 	iNumberofBytesRxRemain[iCurrentFillingBufferIndex] = aNoBytesRecv;
       
   344 	iNumberofPacketsRxRemain[iCurrentFillingBufferIndex] = aNoPacketsRecv;
       
   345 #endif
       
   346 
       
   347 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ReadXferComplete 2 # of bytes=%d # of packets=%d",
       
   348 									iTotalRxBytesAvail, iTotalRxPacketsAvail));
       
   349 	iDrainable[iCurrentFillingBufferIndex] = ETrue;
       
   350 	iError[iCurrentFillingBufferIndex] = aErrorCode;
       
   351 	AddToDrainQueue(iCurrentFillingBufferIndex);
       
   352 	if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
       
   353 		{
       
   354 		NextDrainableBuffer();
       
   355 		}
       
   356 	}
       
   357 
       
   358 
       
   359 TInt TDmaBuf::RxGetNextXfer(TUint8*& aBufferAddr, TUsbcPacketArray*& aIndexArray,
       
   360 							TUsbcPacketArray*& aSizeArray, TInt& aLength, TPhysAddr& aBufferPhys)
       
   361 	{
       
   362 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer 1"));
       
   363 	if (RxIsActive())
       
   364 		{
       
   365 		__KTRACE_OPT(KUSB, Kern::Printf(" ---> RxIsActive, returning"));
       
   366 		return KErrInUse;
       
   367 		}
       
   368 
       
   369 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer Current buffer=%d",
       
   370 									iCurrentFillingBufferIndex));
       
   371 	if (iDrainable[iCurrentFillingBufferIndex])
       
   372 		{
       
   373 		// If the controller refused the last read request, then the current buffer will still be marked
       
   374 		// as !Drainable, because the controller never completed the read to the ldd. and therefore the buffer
       
   375 		// can be reused.
       
   376 		if (!NextFillableBuffer())
       
   377 			{
       
   378 			return KErrNoMemory;
       
   379 			}
       
   380 		}
       
   381 
       
   382 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer New buffer=%d",
       
   383 									iCurrentFillingBufferIndex));
       
   384 	aBufferAddr = iBuffers[iCurrentFillingBufferIndex];
       
   385 	aBufferPhys = iBufferPhys[iCurrentFillingBufferIndex];
       
   386 	aIndexArray = iPacketIndex[iCurrentFillingBufferIndex];
       
   387 	aSizeArray = iPacketSize[iCurrentFillingBufferIndex];
       
   388 	aLength = iBufSz;
       
   389 
       
   390 #if defined(USBC_LDD_BUFFER_TRACE)
       
   391 	iFillingOrderArray[iCurrentFillingBufferIndex] = ++iFillingOrder;
       
   392 #endif
       
   393 
       
   394 	return KErrNone;
       
   395 	}
       
   396 
       
   397 
       
   398 TInt TDmaBuf::RxCopyPacketToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength)
       
   399 	{
       
   400 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 1"));
       
   401 
       
   402 #if defined(USBC_LDD_BUFFER_TRACE)
       
   403 	const TInt numPkts = NoRxPackets();
       
   404 	const TInt numPktsAlt = NoRxPacketsAlt();
       
   405 	const TInt numBytes = RxBytesAvailable();
       
   406 	const TInt numBytesAlt = NoRxBytesAlt();
       
   407 
       
   408 	if (numPkts != numPktsAlt)
       
   409 		{
       
   410 		Kern::Printf(
       
   411 			"TDmaBuf::RxCopyPacketToClient: Error: #pkts mismatch global=%d actual=%d",
       
   412 			numPkts, numPktsAlt);
       
   413 		}
       
   414 	if (numBytes != numBytesAlt)
       
   415 		{
       
   416 		Kern::Printf(
       
   417 			"TDmaBuf::RxCopyPacketToClient: Error: #bytes mismatch global=%d actual=%d",
       
   418 			numBytes, numBytesAlt);
       
   419 		}
       
   420 	if ((numPkts == 0) && (numBytes !=0))
       
   421 		{
       
   422 		Kern::Printf(
       
   423 			"TDmaBuf::RxCopyPacketToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
       
   424 			numPkts, numBytes);
       
   425 		}
       
   426 	if ((numPktsAlt == 0) && (numBytesAlt !=0))
       
   427 		{
       
   428 		Kern::Printf(
       
   429 			"TDmaBuf::RxCopyPacketToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
       
   430 			numPktsAlt, numBytesAlt);
       
   431 		}
       
   432 #endif
       
   433 
       
   434 	if (!NoRxPackets())
       
   435 		return KErrNotFound;
       
   436 
       
   437 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 2"));
       
   438 	// the next condition should be true because we have some packets available
       
   439 	// coverity[var_tested_neg]
       
   440 	if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
       
   441 		{
       
   442 		// Marked as Coverity "Intentional" as the member variable
       
   443 		// iCurrentDrainingBufferIndex is attentionaly negative, from previous 
       
   444 		// initialization to KUsbcInvalidBufferIndex (which equals -1).
       
   445 		if (!NextDrainableBuffer())
       
   446 			return KErrNotFound;
       
   447 		}
       
   448 
       
   449 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
       
   450 						   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   451 	
       
   452 	if (!iDrainable[iCurrentDrainingBufferIndex])
       
   453 		return KErrNotFound;
       
   454 
       
   455 	// Calculate copy-from address & adjust for the fact that
       
   456 	// some data may have already been read from the packet
       
   457 	TUint8* logicalSrc = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
       
   458 	TInt packetSz = iCurrentPacketSizeArray[iCurrentPacket];
       
   459 	TInt thisPacketSz = packetSz - iExtractOffset;
       
   460 	TInt errorCode;
       
   461 	// try and sort out what a "packet" might mean.
       
   462 	// in a multi-packet dma environment, we might see super-packets
       
   463 	// i.e. we might just see one packet, maybe 4K or so long, made of lots of small packets
       
   464 	// Since we don't know where the packet boundaries will be, we have to assume that
       
   465 	// any 'packet' larger than the max packet size of the ep is, in fact, a conglomeration
       
   466 	// of smaller packets. However, for the purposes of the packet count, this is still regarded
       
   467 	// as a single packet and the packet count only decremented when it is consumed.
       
   468 	// As before, if the user fails to read an entire packet out then the next packet is moved onto anyway
       
   469 	// To be safe the user must always supply a buffer of at least max packet size bytes.
       
   470 	if (thisPacketSz > iMaxPacketSize)
       
   471 		{
       
   472 		// Multiple packets left in buffer
       
   473 		// calculate number of bytes to end of packet
       
   474 		if (iEndpointType == KUsbEpTypeBulk)
       
   475 			{
       
   476 			thisPacketSz = iMaxPacketSize - (iExtractOffset & (iMaxPacketSize - 1));
       
   477 			}
       
   478 		else
       
   479 			{
       
   480 			thisPacketSz = iMaxPacketSize - (iExtractOffset % iMaxPacketSize);
       
   481 			}
       
   482 		errorCode = KErrNone;
       
   483 		}
       
   484 	else
       
   485 		{
       
   486 		errorCode = GetCurrentError();						// single packet left
       
   487 		}
       
   488 
       
   489 	iExtractOffset += thisPacketSz;			// iExtractOffset is now at the end of the real or notional packet
       
   490 
       
   491 	ModifyTotalRxBytesAvail(-thisPacketSz);
       
   492 #if defined(USBC_LDD_BUFFER_TRACE)
       
   493 	iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= thisPacketSz;
       
   494 #endif
       
   495 	// this can only be untrue if the "packet" is a conglomeration of smaller packets:
       
   496 	if (iExtractOffset == packetSz)
       
   497 		{
       
   498 		// packet consumed, advance to next packet in buffer
       
   499 #if defined(USBC_LDD_BUFFER_TRACE)
       
   500 		iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
       
   501 #endif
       
   502 		AdvancePacket();
       
   503 		}
       
   504 
       
   505 	TPtrC8 des(logicalSrc, thisPacketSz);
       
   506 	TInt r=Kern::ThreadBufWrite(aThread, aTcb, des, 0, 0, aThread);
       
   507 	if (r == KErrNone)
       
   508 		{
       
   509 		r = errorCode;
       
   510 		}
       
   511 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 3"));
       
   512 
       
   513 	FreeDrainedBuffers();
       
   514 
       
   515 	// Use this error code to complete client read request:
       
   516 	return r;
       
   517 	}
       
   518 
       
   519 
       
   520 TInt TDmaBuf::RxCopyDataToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength, TUint32& aDestOffset,
       
   521 								 TBool aRUS, TBool& aCompleteNow)
       
   522 	{
       
   523 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 1"));
       
   524 	aCompleteNow = ETrue;
       
   525 
       
   526 #if defined(USBC_LDD_BUFFER_TRACE)
       
   527 	const TInt numPkts = NoRxPackets();
       
   528 	const TInt numPktsAlt = NoRxPacketsAlt();
       
   529 	const TInt numBytes = RxBytesAvailable();
       
   530 	const TInt numBytesAlt = NoRxBytesAlt();
       
   531 
       
   532 	if (numPkts != numPktsAlt)
       
   533 		{
       
   534 		Kern::Printf(
       
   535 			"TDmaBuf::RxCopyDataToClient: Error: #pkts mismatch global=%d actual=%d",
       
   536 			numPkts, numPktsAlt);
       
   537 		}
       
   538 	if (numBytes != numBytesAlt)
       
   539 		{
       
   540 		Kern::Printf(
       
   541 			"TDmaBuf::RxCopyDataToClient: Error: #bytes mismatch global=%d actual=%d",
       
   542 			numBytes, numBytesAlt);
       
   543 		}
       
   544 	if ((numPkts == 0) && (numBytes != 0))
       
   545 		{
       
   546 		Kern::Printf(
       
   547 			"TDmaBuf::RxCopyDataToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
       
   548 			numPkts, numBytes);
       
   549 		}
       
   550 	if ((numPktsAlt == 0) && (numBytesAlt != 0))
       
   551 		{
       
   552 		Kern::Printf(
       
   553 			"TDmaBuf::RxCopyDataToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
       
   554 			numPktsAlt, numBytesAlt);
       
   555 		}
       
   556 #endif
       
   557 
       
   558 	if (!NoRxPackets())
       
   559 		{
       
   560 		return KErrNotFound;
       
   561 		}
       
   562 
       
   563 	// coverity[var_tested_neg]
       
   564 	if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
       
   565 		{
       
   566 		// Marked as Coverity "Inentional" as the member variable
       
   567 		// iCurrentDrainingBufferIndex is attentionaly negative, from previous 
       
   568 		// initialization to KUsbcInvalidBufferIndex (which equals -1).
       
   569 
       
   570 		if (!NextDrainableBuffer())
       
   571 			{
       
   572 #if defined(USBC_LDD_BUFFER_TRACE)
       
   573 			Kern::Printf("TDmaBuf::RxCopyDataToClient: Error:  No buffer draining=%d, packets=%d",
       
   574 						 iCurrentDrainingBufferIndex, iTotalRxPacketsAvail);
       
   575 #endif
       
   576 			return KErrNotFound;
       
   577 			}
       
   578 		}
       
   579 #if defined(USBC_LDD_BUFFER_TRACE)
       
   580 
       
   581 	__ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
       
   582 							   Kern::Fault(KUsbPanicLdd, __LINE__));
       
   583 		
       
   584 	if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
       
   585 		{
       
   586 		Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 10 draining=%d",
       
   587 					 iCurrentDrainingBufferIndex);
       
   588 		}
       
   589 #endif
       
   590 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 2"));
       
   591 
       
   592 	TUint8* blockStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
       
   593 	TUint8* lastEndAddr = blockStartAddr;					// going to track the contiguity of the memory
       
   594 	TUint8* thisStartAddr = blockStartAddr;
       
   595 	TInt toDo = Min(aLength - (TInt)aDestOffset, iTotalRxBytesAvail);
       
   596 #if defined(USBC_LDD_BUFFER_TRACE)
       
   597 	TInt bufnum = iCurrentDrainingBufferIndex;
       
   598 #endif
       
   599 	TInt errorCode = KErrNone;
       
   600 	TBool isShortPacket = EFalse;
       
   601 	const TInt maxPacketSizeMask = iMaxPacketSize - 1;
       
   602 	do
       
   603 		{
       
   604 #if defined(USBC_LDD_BUFFER_TRACE)
       
   605 		if (bufnum != iCurrentDrainingBufferIndex)
       
   606 			{
       
   607 			bufnum = iCurrentDrainingBufferIndex;
       
   608 			if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
       
   609 				{
       
   610 				Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 20 draining=%d",
       
   611 							 iCurrentDrainingBufferIndex);
       
   612 				}
       
   613 			}
       
   614 #endif
       
   615 		if (errorCode == KErrNone)
       
   616 			{
       
   617 			errorCode = GetCurrentError();
       
   618 			}
       
   619 		thisStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
       
   620 		const TInt thisPacketSize = iCurrentPacketSizeArray[iCurrentPacket];
       
   621 		const TInt size = thisPacketSize - iExtractOffset;
       
   622 		if (aRUS)
       
   623 			{
       
   624 			if (iEndpointType == KUsbEpTypeBulk)
       
   625 				{
       
   626 				isShortPacket = (size < iMaxPacketSize) || (size & maxPacketSizeMask);
       
   627 				}
       
   628 			else
       
   629 				{
       
   630 				// this 'if' block is arranged to avoid a division on packet sizes <= iMaxPacketSize
       
   631 				isShortPacket = (size < iMaxPacketSize) ||
       
   632 					((size > iMaxPacketSize) && (size % iMaxPacketSize));
       
   633 				}
       
   634 			}
       
   635 		TInt copySize = Min(size, toDo);
       
   636 		iExtractOffset += copySize;
       
   637 		toDo -= copySize;
       
   638 		if (thisStartAddr != lastEndAddr)
       
   639 			{
       
   640 			TInt bytesToCopy = lastEndAddr - blockStartAddr;
       
   641 			TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
       
   642 			if(r != KErrNone)
       
   643 				Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
       
   644 			blockStartAddr = thisStartAddr;
       
   645 			}
       
   646 
       
   647 		ModifyTotalRxBytesAvail(-copySize);
       
   648 #if defined(USBC_LDD_BUFFER_TRACE)
       
   649 		iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= copySize;
       
   650 #endif
       
   651 		lastEndAddr = thisStartAddr + copySize;
       
   652 		if (iExtractOffset == thisPacketSize)
       
   653 			{
       
   654 			// More data to copy, so need to access new packet
       
   655 #if defined(USBC_LDD_BUFFER_TRACE)
       
   656 			iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
       
   657 #endif
       
   658 			if (!AdvancePacket())
       
   659 				{
       
   660 				break;										// no more packets left
       
   661 				}
       
   662 			}
       
   663 		} while (toDo > 0 && !isShortPacket);
       
   664 
       
   665 	if (thisStartAddr != lastEndAddr)
       
   666 		{
       
   667 		TInt bytesToCopy = lastEndAddr - blockStartAddr;
       
   668 		TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
       
   669 		if(r != KErrNone)
       
   670 			Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
       
   671 		}
       
   672 
       
   673 	// If we have transferred the requested amount of data it is still possible that
       
   674 	// the next packet is a zlp which needs to be bumped over
       
   675 
       
   676 	if (aRUS && (toDo == 0) && (iExtractOffset == 0) && (!isShortPacket) && (!IsReaderEmpty()) &&
       
   677 		(PeekNextPacketSize() == 0))
       
   678 		{
       
   679 		// swallow a zlp
       
   680 		isShortPacket = ETrue;
       
   681 #if defined(USBC_LDD_BUFFER_TRACE)
       
   682 		iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
       
   683 #endif
       
   684 		AdvancePacket();
       
   685 		}
       
   686 	aCompleteNow = isShortPacket || (((TInt)aDestOffset) == aLength) || (errorCode != KErrNone);
       
   687 
       
   688 	FreeDrainedBuffers();
       
   689 
       
   690 	// Use this error code to complete client read request
       
   691 	return errorCode;
       
   692 	}
       
   693 
       
   694 
       
   695 inline TInt TDmaBuf::CopyToUser(DThread* aThread, const TUint8* aSourceAddr,
       
   696 								TInt aLength, TClientBuffer *aTcb, TUint32& aDestOffset)
       
   697 	{
       
   698 	TPtrC8 des(aSourceAddr, aLength);
       
   699 	TInt errorCode = Kern::ThreadBufWrite(aThread, aTcb, des, aDestOffset, KChunkShiftBy0, aThread);
       
   700 	if (errorCode == KErrNone)
       
   701 		{
       
   702 		aDestOffset += aLength;
       
   703 		}
       
   704 	return errorCode;
       
   705 	}
       
   706 
       
   707 
       
   708 inline TInt TDmaBuf::NoRxPackets() const
       
   709 	{
       
   710 	return iTotalRxPacketsAvail;
       
   711 	}
       
   712 
       
   713 
       
   714 inline void TDmaBuf::IncrementBufferIndex(TInt& aIndex)
       
   715 	{
       
   716 	if (++aIndex == iNumberofBuffers)
       
   717 		aIndex = 0;
       
   718 	}
       
   719 
       
   720 
       
   721 TBool TDmaBuf::NextDrainableBuffer()
       
   722 	{
       
   723 	TBool r = EFalse;
       
   724 	if (iCurrentDrainingBufferIndex != KUsbcInvalidBufferIndex)
       
   725 		{
       
   726 		iCanBeFreed[iCurrentDrainingBufferIndex] = ETrue;
       
   727 		iNumberofPacketsRx[iCurrentDrainingBufferIndex] = 0; // Current buffer is empty
       
   728 		iNumberofBytesRx[iCurrentDrainingBufferIndex] = 0;	// Current buffer is empty
       
   729 
       
   730 #if defined(USBC_LDD_BUFFER_TRACE)
       
   731 		TUint& bytesRemain = iNumberofBytesRxRemain[iCurrentDrainingBufferIndex];
       
   732 		TUint& pktsRemain = iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex];
       
   733 		if ((bytesRemain != 0) || (pktsRemain != 0))
       
   734 			{
       
   735 			Kern::Printf(
       
   736 				"TDmaBuf::NextDrainableBuffer: Error: data discarded buffer=%d pkts=%d bytes=%d",
       
   737 				iCurrentDrainingBufferIndex, pktsRemain, bytesRemain);
       
   738 			bytesRemain = 0;
       
   739 			pktsRemain = 0;
       
   740 			}
       
   741 #endif
       
   742 
       
   743 		iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
       
   744 		iCurrentPacket = KUsbcInvalidPacketIndex;
       
   745 		}
       
   746 
       
   747 	if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
       
   748 		{
       
   749 		r = ETrue;
       
   750 		const TInt index = iDrainQueue[0];
       
   751 		iDrainQueueIndex--;
       
   752 		for (TInt i = 0; i < iNumberofBuffers; i++)
       
   753 			{
       
   754 			iDrainQueue[i] = iDrainQueue[i+1];
       
   755 			}
       
   756 
       
   757 #if defined(USBC_LDD_BUFFER_TRACE)
       
   758 		if (index != KUsbcInvalidBufferIndex)
       
   759 			iDrainingOrder++;
       
   760 #endif
       
   761 
       
   762 		iCurrentDrainingBufferIndex = index;
       
   763 		iCurrentDrainingBuffer = iBuffers[index];
       
   764 		iCurrentPacketIndexArray = iPacketIndex[index];
       
   765 		iCurrentPacketSizeArray = iPacketSize[index];
       
   766 		iCurrentPacket = 0;
       
   767 		}
       
   768 	return r;
       
   769 	}
       
   770 
       
   771 
       
   772 TInt TDmaBuf::PeekNextDrainableBuffer()
       
   773 	{
       
   774 	TInt r = KUsbcInvalidBufferIndex;
       
   775 	if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
       
   776 		{
       
   777 		r = iDrainQueue[0];
       
   778 		}
       
   779 	return r;
       
   780 	}
       
   781 
       
   782 
       
   783 TBool TDmaBuf::NextFillableBuffer()
       
   784 	{
       
   785 	TBool r = EFalse;
       
   786 	TInt index = iCurrentFillingBufferIndex;
       
   787 	IncrementBufferIndex(index);
       
   788 	// the sequence will restart at 0 if a buffer can't be found this time
       
   789 	iCurrentFillingBufferIndex = 0;
       
   790 	for (TInt i = 0; i < iNumberofBuffers; i++)
       
   791 		{
       
   792 		if (!iDrainable[index])
       
   793 			{
       
   794 			iCurrentFillingBufferIndex = index;
       
   795 			r = ETrue;
       
   796 			break;
       
   797 			}
       
   798 		IncrementBufferIndex(index);
       
   799 		}
       
   800 	return r;
       
   801 	}
       
   802 
       
   803 
       
   804 void TDmaBuf::FreeDrainedBuffers()
       
   805 	{
       
   806 	for (TInt i = 0; i < iNumberofBuffers; i++)
       
   807 		{
       
   808 		if (iDrainable[i] && iCanBeFreed[i])
       
   809 			{
       
   810 			iDrainable[i] = iCanBeFreed[i] = EFalse;
       
   811 			}
       
   812 		}
       
   813 	}
       
   814 
       
   815 
       
   816 TBool TDmaBuf::ShortPacketExists()
       
   817 	{
       
   818 	// Actually, a short packet or residue data
       
   819 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ShortPacketExists 1"));
       
   820 	TInt index = iCurrentDrainingBufferIndex;
       
   821 	TUsbcPacketArray* pktSizeArray = iCurrentPacketSizeArray;
       
   822 
       
   823 	if (iMaxPacketSize > 0)
       
   824 		{
       
   825 		// No buffers available for draining
       
   826 		if ((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
       
   827 			(iCurrentPacket == KUsbcInvalidPacketIndex))
       
   828 			return EFalse;
       
   829 
       
   830 		// Zlp waiting at tail
       
   831 		if ((iTotalRxBytesAvail == 0) && (NoRxPackets() == 1))
       
   832 			return ETrue;
       
   833 
       
   834 		if (iEndpointType == KUsbEpTypeBulk)
       
   835 			{
       
   836 			const TInt mask = iMaxPacketSize - 1;
       
   837 			if (iTotalRxBytesAvail & mask)
       
   838 				return ETrue;
       
   839 
       
   840 			// residue==0; this can be because
       
   841 			// zlps exist, or short packets combine to n * max_packet_size
       
   842 			// This means spadework
       
   843 			const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
       
   844 			if ((s == 0) || (s & mask))
       
   845 				{
       
   846 				return ETrue;
       
   847 				}
       
   848 
       
   849 			for (TInt i = 0; i < iNumberofBuffers; i++)
       
   850 				{
       
   851 				if (index == KUsbcInvalidBufferIndex)
       
   852 					break;
       
   853 				if (iDrainable[index])
       
   854 					{
       
   855 					const TInt packetCount = iNumberofPacketsRx[index];
       
   856 					const TInt lastPacketSize=pktSizeArray[packetCount - 1];
       
   857 					if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize & mask))
       
   858 						{
       
   859 						return ETrue;
       
   860 						}
       
   861 					}
       
   862 				index = iDrainQueue[i];
       
   863 				pktSizeArray = iPacketSize[index];
       
   864 				}
       
   865 			}
       
   866 		else
       
   867 			{
       
   868 			if (iTotalRxBytesAvail % iMaxPacketSize)
       
   869 				return ETrue;
       
   870 
       
   871 			// residue==0; this can be because
       
   872 			// zlps exist, or short packets combine to n * max_packet_size
       
   873 			// This means spadework
       
   874 			const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
       
   875 			if ((s == 0) || (s % iMaxPacketSize))
       
   876 				{
       
   877 				return ETrue;
       
   878 				}
       
   879 
       
   880 			for (TInt i = 0; i < iNumberofBuffers; i++)
       
   881 				{
       
   882 				if (index == KUsbcInvalidBufferIndex)
       
   883 					break;
       
   884 				if (iDrainable[index])
       
   885 					{
       
   886 					const TInt packetCount = iNumberofPacketsRx[index];
       
   887 					const TInt lastPacketSize = pktSizeArray[packetCount - 1];
       
   888 					if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize % iMaxPacketSize))
       
   889 						{
       
   890 						return ETrue;
       
   891 						}
       
   892 					}
       
   893 				index = iDrainQueue[i];
       
   894 				pktSizeArray = iPacketSize[index];
       
   895 				}
       
   896 			}
       
   897 		}
       
   898 
       
   899 	return EFalse;
       
   900 	}
       
   901 
       
   902 
       
   903 void TDmaBuf::AddToDrainQueue(TInt aBufferIndex)
       
   904 	{
       
   905 	if (iDrainQueue[iDrainQueueIndex + 1] != KUsbcInvalidBufferIndex)
       
   906 		{
       
   907 #if defined(USBC_LDD_BUFFER_TRACE)
       
   908 		Kern::Printf("TDmaBuf::AddToDrainQueue: Error: invalid iDrainQueue[x]");
       
   909 #endif
       
   910 		}
       
   911 	iDrainQueue[++iDrainQueueIndex] = aBufferIndex;
       
   912 	}
       
   913 
       
   914 
       
   915 #if defined(USBC_LDD_BUFFER_TRACE)
       
   916 TInt TDmaBuf::NoRxPacketsAlt() const
       
   917 	{
       
   918 	TInt pktCount = 0;
       
   919 	for(TInt i = 0; i < iNumberofBuffers; i++)
       
   920 		{
       
   921 		if (iDrainable[i])
       
   922 			{
       
   923 			pktCount += iNumberofPacketsRxRemain[i];
       
   924 			}
       
   925 		}
       
   926 	return pktCount;
       
   927 	}
       
   928 
       
   929 
       
   930 TInt TDmaBuf::NoRxBytesAlt() const
       
   931 	{
       
   932 	TInt byteCount = 0;
       
   933 	for(TInt i = 0; i < iNumberofBuffers; i++)
       
   934 		{
       
   935 		if (iDrainable[i])
       
   936 			{
       
   937 			byteCount += iNumberofBytesRxRemain[i];
       
   938 			}
       
   939 		}
       
   940 	return byteCount;
       
   941 	}
       
   942 #endif
       
   943 
       
   944 
       
   945 // We only store 1 transaction, no other buffering is done
       
   946 TInt TDmaBuf::TxStoreData(DThread* aThread, TClientBuffer *aTcb, TInt aTxLength, TUint32 aBufferOffset)
       
   947 	{
       
   948 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 1"));
       
   949 	if (!IsReaderEmpty())
       
   950 		return KErrInUse;
       
   951 
       
   952 	__KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 2"));
       
   953 	TUint8* logicalDest = iBufBasePtr;
       
   954 	TInt xferSz = Min(aTxLength, BufferTotalSize());
       
   955 	TPtr8 des(logicalDest, xferSz, xferSz);
       
   956 	TInt r = Kern::ThreadBufRead(aThread, aTcb, des, aBufferOffset,KChunkShiftBy0);
       
   957 	if(r != KErrNone)
       
   958 		Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
       
   959 	return r;
       
   960 	}
       
   961 
       
   962 
       
   963 TInt TDmaBuf::TxGetNextXfer(TUint8*& aBufferAddr, TInt& aTxLength, TPhysAddr& aBufferPhys)
       
   964 	{
       
   965 	if (iTxActive)
       
   966 		return KErrInUse;
       
   967 
       
   968 	aBufferAddr = iBuffers[0];								// only 1 tx buffer
       
   969 	aBufferPhys = iBufferPhys[0];
       
   970 	aTxLength = BufferTotalSize();
       
   971 
       
   972 	return KErrNone;
       
   973 	}
       
   974