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