--- a/usbdrv/peripheral/ldd/perildd/src/usbdma.cpp Tue Aug 31 17:01:47 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,983 +0,0 @@
-// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// e32\drivers\usbc\usbdma.cpp
-// LDD for USB Device driver stack:
-// Management of DMA-capable data buffers.
-//
-//
-
-/**
- @file usbdma.cpp
- @internalTechnology
-*/
-
-#include <usb/usbc.h>
-
-
-#if defined(_DEBUG)
-static const char KUsbPanicLdd[] = "USB LDD";
-#endif
-
-
-TDmaBuf::TDmaBuf(TUsbcEndpointInfo* aEndpointInfo, TInt aBandwidthPriority)
- : iBufBasePtr(NULL),
- iCurrentDrainingBuffer(NULL),
- iCurrentPacket(0),
- iCurrentPacketIndexArray(NULL),
- iCurrentPacketSizeArray(NULL)
- {
- iMaxPacketSize = aEndpointInfo->iSize;
- iEndpointType = aEndpointInfo->iType;
-
- switch (aEndpointInfo->iType)
- {
- case UsbShai::KUsbEpTypeControl:
- iBufSz = KUsbcDmaBufSzControl;
- iNumberofBuffers = KUsbcDmaBufNumControl;
- break;
- case UsbShai::KUsbEpTypeIsochronous:
- iBufSz = KUsbcDmaBufSzIsochronous;
- iNumberofBuffers = KUsbcDmaBufNumIsochronous;
- break;
- case UsbShai::KUsbEpTypeBulk:
- {
- if (aEndpointInfo->iDir == UsbShai::KUsbEpDirOut)
- {
- const TInt priorityOUT = aBandwidthPriority & 0x0f;
- iBufSz = KUsbcDmaBufSizesBulkOUT[priorityOUT];
- }
- else
- {
- const TInt priorityIN = (aBandwidthPriority >> 4) & 0x0f;
- iBufSz = KUsbcDmaBufSizesBulkIN[priorityIN];
- }
- iNumberofBuffers = KUsbcDmaBufNumBulk;
- }
- break;
- case UsbShai::KUsbEpTypeInterrupt:
- iBufSz = KUsbcDmaBufSzInterrupt;
- iNumberofBuffers = KUsbcDmaBufNumInterrupt;
- break;
- default:
- iBufSz = 0;
- iNumberofBuffers = 0;
- }
-
- if (aEndpointInfo->iDir == UsbShai::KUsbEpDirIn)
- {
- iNumberofBuffers = 1; // IN endpoints only have 1 buffer
- }
-
- for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
- {
- // Buffer logical addresses (pointers)
- iBuffers[i] = NULL;
- // Buffer physical addresses
- iBufferPhys[i] = 0;
- // Packet indexes base array
- iPacketIndex[i] = NULL;
- // Packet sizes base array
- iPacketSize[i] = NULL;
- }
- }
-
-
-TInt TDmaBuf::Construct(TUsbcEndpointInfo* aEndpointInfo)
- {
- if (aEndpointInfo->iDir != UsbShai::KUsbEpDirIn)
- {
- // IN endpoints don't need a packet array
-
- // At most 2 packets (clump of max packet size packets) + possible zlp
- TUsbcPacketArray* bufPtr = iPacketInfoStorage;
- // this divides up the packet indexing & packet size array over the number of buffers
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() array base=0x%08x", bufPtr));
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- iPacketIndex[i] = bufPtr;
- bufPtr += KUsbcDmaBufMaxPkts;
- iPacketSize[i] = bufPtr;
- bufPtr += KUsbcDmaBufMaxPkts;
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() packetIndex[%d]=0x%08x packetSize[%d]=0x%08x",
- i, iPacketIndex[i], i, iPacketSize[i]));
- }
- }
- else
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Construct() IN endpoint"));
- }
- Flush();
- return KErrNone;
- }
-
-
-TDmaBuf::~TDmaBuf()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::~TDmaBuf()"));
- }
-
-TInt TDmaBuf::BufferTotalSize() const
- {
- return iBufSz * iNumberofBuffers;
- }
-
-TInt TDmaBuf::BufferSize() const
- {
- return iBufSz;
- }
-
-TInt TDmaBuf::SetBufferAddr(TInt aBufInd, TUint8* aBufAddr)
- {
- __ASSERT_DEBUG((aBufInd < iNumberofBuffers),
- Kern::Fault(KUsbPanicLdd, __LINE__));
- iDrainable[aBufInd] = iCanBeFreed[aBufInd] = EFalse;
- iBuffers[aBufInd] = aBufAddr;
- iBufferPhys[aBufInd] = Epoc::LinearToPhysical((TLinAddr)aBufAddr);
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::SetBufferAddr() iBuffers[%d]=0x%08x", aBufInd, iBuffers[aBufInd]));
- return KErrNone;
- }
-
-TInt TDmaBuf::BufferNumber() const
- {
- return iNumberofBuffers;
- }
-
-void TDmaBuf::SetMaxPacketSize(TInt aSize)
- {
- iMaxPacketSize = aSize;
- }
-
-
-void TDmaBuf::Flush()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::Flush %x", this));
- iRxActive = EFalse;
- iTxActive = EFalse;
- iExtractOffset = 0;
- iTotalRxBytesAvail = 0;
- iTotalRxPacketsAvail = 0;
- iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
- iCurrentFillingBufferIndex = 0;
- iDrainQueueIndex = KUsbcInvalidDrainQueueIndex;
- for (TInt i = 0; i < KUsbcDmaBufNumMax; i++)
- {
- iDrainable[i] = EFalse;
- iCanBeFreed[i] = EFalse;
- iNumberofBytesRx[i] = 0;
- iNumberofPacketsRx[i] = 0;
- iError[i] = KErrGeneral;
- iDrainQueue[i] = KUsbcInvalidBufferIndex;
-#if defined(USBC_LDD_BUFFER_TRACE)
- iFillingOrderArray[i] = 0;
- iNumberofBytesRxRemain[i] = 0;
- iNumberofPacketsRxRemain[i] = 0;
-#endif
- }
- // Drain queue is 1 oversized
- iDrainQueue[KUsbcDmaBufNumMax] = KUsbcInvalidBufferIndex;
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- iFillingOrder = 0;
- iDrainingOrder = 0;
-#endif
- }
-
-
-void TDmaBuf::RxSetActive()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetActive %x", this));
- iRxActive = ETrue;
- }
-
-
-void TDmaBuf::RxSetInActive()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxSetInActive %x", this));
- iRxActive = EFalse;
- }
-
-
-TBool TDmaBuf::RxIsActive()
- {
- return iRxActive;
- }
-
-
-void TDmaBuf::TxSetActive()
- {
- iTxActive = ETrue;
- }
-
-
-void TDmaBuf::TxSetInActive()
- {
- iTxActive = EFalse;
- }
-
-
-TBool TDmaBuf::TxIsActive()
- {
- return iTxActive;
- }
-
-
-/**************************** Rx DMA Buffer Access *************************/
-
-void TDmaBuf::ModifyTotalRxBytesAvail(TInt aVal)
- {
- iTotalRxBytesAvail += aVal;
- }
-
-
-void TDmaBuf::ModifyTotalRxPacketsAvail(TInt aVal)
- {
- iTotalRxPacketsAvail += aVal;
- }
-
-
-TBool TDmaBuf::AdvancePacket()
- {
- ModifyTotalRxPacketsAvail(-1);
- TBool r = ETrue;
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
- Kern::Fault(KUsbPanicLdd, __LINE__));
- if (++iCurrentPacket >= iNumberofPacketsRx[iCurrentDrainingBufferIndex])
- {
- r = NextDrainableBuffer();
- }
- iExtractOffset = 0;
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
- (iCurrentPacket < KUsbcDmaBufMaxPkts),
- Kern::Fault(KUsbPanicLdd, __LINE__));
- return r;
- }
-
-
-TInt TDmaBuf::PeekNextPacketSize()
- {
- TUint pkt = iCurrentPacket;
- TInt index = iCurrentDrainingBufferIndex;
- TInt size = -1;
- if (pkt >= iNumberofPacketsRx[index])
- {
- index = PeekNextDrainableBuffer();
- pkt = 0;
- }
-
- if ((index != KUsbcInvalidBufferIndex) && iNumberofPacketsRx[index])
- {
- const TUsbcPacketArray* sizeArray = iPacketSize[index];
- size = (TInt)sizeArray[pkt];
- }
-
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
- (iCurrentPacket < KUsbcDmaBufMaxPkts),
- Kern::Fault(KUsbPanicLdd, __LINE__));
- return size;
- }
-
-
-inline TInt TDmaBuf::GetCurrentError()
- {
- // USB bus errors are v.rare. To avoid having an error code attached to every packet since
- // almost every errorcode will be KErrNone, we have a single error code per buffer
- // If the error code is != KErrNone then it refers to the LAST packet in the buffer
- TInt errorCode = KErrNone;
- //Check the index, it's not equal to negative (-1) value defined in
- //KUsbcInvalidBufferIndex.
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0),
- Kern::Fault(KUsbPanicLdd, __LINE__));
-
- if (iError[iCurrentDrainingBufferIndex] != KErrNone)
- {
- // See if we are at the last packet
- if ((iCurrentPacket + 1) == iNumberofPacketsRx[iCurrentDrainingBufferIndex])
- {
- errorCode = iError[iCurrentDrainingBufferIndex];
- }
- }
- return errorCode;
- }
-
-
-// used to decide whether a client read can complete straight away
-TBool TDmaBuf::IsReaderEmpty()
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::IsReaderEmpty iTotalRxPacketsAvail=%d",
- iTotalRxPacketsAvail));
- return (iTotalRxPacketsAvail == 0);
- }
-
-
-void TDmaBuf::ReadXferComplete(TInt aNoBytesRecv, TInt aNoPacketsRecv, TInt aErrorCode)
- {
- // Adjust pending packet
- if ((aNoBytesRecv == 0) && (aErrorCode != KErrNone))
- {
- // Make the buffer available for reuse
- iDrainable[iCurrentFillingBufferIndex] = EFalse;
- return;
- }
-
- ModifyTotalRxBytesAvail(aNoBytesRecv);
- ModifyTotalRxPacketsAvail(aNoPacketsRecv);
- iNumberofBytesRx[iCurrentFillingBufferIndex] = aNoBytesRecv;
- iNumberofPacketsRx[iCurrentFillingBufferIndex] = aNoPacketsRecv;
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofBytesRxRemain[iCurrentFillingBufferIndex] = aNoBytesRecv;
- iNumberofPacketsRxRemain[iCurrentFillingBufferIndex] = aNoPacketsRecv;
-#endif
-
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ReadXferComplete 2 # of bytes=%d # of packets=%d",
- iTotalRxBytesAvail, iTotalRxPacketsAvail));
- iDrainable[iCurrentFillingBufferIndex] = ETrue;
- iError[iCurrentFillingBufferIndex] = aErrorCode;
- AddToDrainQueue(iCurrentFillingBufferIndex);
- if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
- {
- NextDrainableBuffer();
- }
- }
-
-
-TInt TDmaBuf::RxGetNextXfer(TUint8*& aBufferAddr, TUsbcPacketArray*& aIndexArray,
- TUsbcPacketArray*& aSizeArray, TInt& aLength, TPhysAddr& aBufferPhys)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer 1"));
- if (RxIsActive())
- {
- __KTRACE_OPT(KUSB, Kern::Printf(" ---> RxIsActive, returning"));
- return KErrInUse;
- }
-
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer Current buffer=%d",
- iCurrentFillingBufferIndex));
- if (iDrainable[iCurrentFillingBufferIndex])
- {
- // If the controller refused the last read request, then the current buffer will still be marked
- // as !Drainable, because the controller never completed the read to the ldd. and therefore the buffer
- // can be reused.
- if (!NextFillableBuffer())
- {
- return KErrNoMemory;
- }
- }
-
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxGetNextXfer New buffer=%d",
- iCurrentFillingBufferIndex));
- aBufferAddr = iBuffers[iCurrentFillingBufferIndex];
- aBufferPhys = iBufferPhys[iCurrentFillingBufferIndex];
- aIndexArray = iPacketIndex[iCurrentFillingBufferIndex];
- aSizeArray = iPacketSize[iCurrentFillingBufferIndex];
- aLength = iBufSz;
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- iFillingOrderArray[iCurrentFillingBufferIndex] = ++iFillingOrder;
-#endif
-
- return KErrNone;
- }
-
-
-TInt TDmaBuf::RxCopyPacketToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 1"));
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- const TInt numPkts = NoRxPackets();
- const TInt numPktsAlt = NoRxPacketsAlt();
- const TInt numBytes = RxBytesAvailable();
- const TInt numBytesAlt = NoRxBytesAlt();
-
- if (numPkts != numPktsAlt)
- {
- Kern::Printf(
- "TDmaBuf::RxCopyPacketToClient: Error: #pkts mismatch global=%d actual=%d",
- numPkts, numPktsAlt);
- }
- if (numBytes != numBytesAlt)
- {
- Kern::Printf(
- "TDmaBuf::RxCopyPacketToClient: Error: #bytes mismatch global=%d actual=%d",
- numBytes, numBytesAlt);
- }
- if ((numPkts == 0) && (numBytes !=0))
- {
- Kern::Printf(
- "TDmaBuf::RxCopyPacketToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
- numPkts, numBytes);
- }
- if ((numPktsAlt == 0) && (numBytesAlt !=0))
- {
- Kern::Printf(
- "TDmaBuf::RxCopyPacketToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
- numPktsAlt, numBytesAlt);
- }
-#endif
-
- if (!NoRxPackets())
- return KErrNotFound;
-
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 2"));
- // the next condition should be true because we have some packets available
- // coverity[var_tested_neg]
- if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
- {
- // Marked as Coverity "Intentional" as the member variable
- // iCurrentDrainingBufferIndex is attentionaly negative, from previous
- // initialization to KUsbcInvalidBufferIndex (which equals -1).
- if (!NextDrainableBuffer())
- return KErrNotFound;
- }
-
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
- Kern::Fault(KUsbPanicLdd, __LINE__));
-
- if (!iDrainable[iCurrentDrainingBufferIndex])
- return KErrNotFound;
-
- // Calculate copy-from address & adjust for the fact that
- // some data may have already been read from the packet
- TUint8* logicalSrc = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
- TInt packetSz = iCurrentPacketSizeArray[iCurrentPacket];
- TInt thisPacketSz = packetSz - iExtractOffset;
- TInt errorCode;
- // try and sort out what a "packet" might mean.
- // in a multi-packet dma environment, we might see super-packets
- // i.e. we might just see one packet, maybe 4K or so long, made of lots of small packets
- // Since we don't know where the packet boundaries will be, we have to assume that
- // any 'packet' larger than the max packet size of the ep is, in fact, a conglomeration
- // of smaller packets. However, for the purposes of the packet count, this is still regarded
- // as a single packet and the packet count only decremented when it is consumed.
- // As before, if the user fails to read an entire packet out then the next packet is moved onto anyway
- // To be safe the user must always supply a buffer of at least max packet size bytes.
- if (thisPacketSz > iMaxPacketSize)
- {
- // Multiple packets left in buffer
- // calculate number of bytes to end of packet
- if (iEndpointType == UsbShai::KUsbEpTypeBulk)
- {
- thisPacketSz = iMaxPacketSize - (iExtractOffset & (iMaxPacketSize - 1));
- }
- else
- {
- thisPacketSz = iMaxPacketSize - (iExtractOffset % iMaxPacketSize);
- }
- errorCode = KErrNone;
- }
- else
- {
- errorCode = GetCurrentError(); // single packet left
- }
-
- iExtractOffset += thisPacketSz; // iExtractOffset is now at the end of the real or notional packet
-
- ModifyTotalRxBytesAvail(-thisPacketSz);
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= thisPacketSz;
-#endif
- // this can only be untrue if the "packet" is a conglomeration of smaller packets:
- if (iExtractOffset == packetSz)
- {
- // packet consumed, advance to next packet in buffer
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
-#endif
- AdvancePacket();
- }
-
- TPtrC8 des(logicalSrc, thisPacketSz);
- TInt r=Kern::ThreadBufWrite(aThread, aTcb, des, 0, 0, aThread);
- if (r == KErrNone)
- {
- r = errorCode;
- }
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyPacketToClient 3"));
-
- FreeDrainedBuffers();
-
- // Use this error code to complete client read request:
- return r;
- }
-
-
-TInt TDmaBuf::RxCopyDataToClient(DThread* aThread, TClientBuffer *aTcb, TInt aLength, TUint32& aDestOffset,
- TBool aRUS, TBool& aCompleteNow)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 1"));
- aCompleteNow = ETrue;
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- const TInt numPkts = NoRxPackets();
- const TInt numPktsAlt = NoRxPacketsAlt();
- const TInt numBytes = RxBytesAvailable();
- const TInt numBytesAlt = NoRxBytesAlt();
-
- if (numPkts != numPktsAlt)
- {
- Kern::Printf(
- "TDmaBuf::RxCopyDataToClient: Error: #pkts mismatch global=%d actual=%d",
- numPkts, numPktsAlt);
- }
- if (numBytes != numBytesAlt)
- {
- Kern::Printf(
- "TDmaBuf::RxCopyDataToClient: Error: #bytes mismatch global=%d actual=%d",
- numBytes, numBytesAlt);
- }
- if ((numPkts == 0) && (numBytes != 0))
- {
- Kern::Printf(
- "TDmaBuf::RxCopyDataToClient: Error: global bytes & pkts mismatch pkts=%d bytes=%d",
- numPkts, numBytes);
- }
- if ((numPktsAlt == 0) && (numBytesAlt != 0))
- {
- Kern::Printf(
- "TDmaBuf::RxCopyDataToClient: Error: actual bytes & pkts mismatch pkts=%d bytes=%d",
- numPktsAlt, numBytesAlt);
- }
-#endif
-
- if (!NoRxPackets())
- {
- return KErrNotFound;
- }
-
- // coverity[var_tested_neg]
- if (iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex)
- {
- // Marked as Coverity "Inentional" as the member variable
- // iCurrentDrainingBufferIndex is attentionaly negative, from previous
- // initialization to KUsbcInvalidBufferIndex (which equals -1).
-
- if (!NextDrainableBuffer())
- {
-#if defined(USBC_LDD_BUFFER_TRACE)
- Kern::Printf("TDmaBuf::RxCopyDataToClient: Error: No buffer draining=%d, packets=%d",
- iCurrentDrainingBufferIndex, iTotalRxPacketsAvail);
-#endif
- return KErrNotFound;
- }
- }
-#if defined(USBC_LDD_BUFFER_TRACE)
-
- __ASSERT_DEBUG((iCurrentDrainingBufferIndex >= 0 ),
- Kern::Fault(KUsbPanicLdd, __LINE__));
-
- if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
- {
- Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 10 draining=%d",
- iCurrentDrainingBufferIndex);
- }
-#endif
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::RxCopyDataToClient 2"));
-
- TUint8* blockStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
- TUint8* lastEndAddr = blockStartAddr; // going to track the contiguity of the memory
- TUint8* thisStartAddr = blockStartAddr;
- TInt toDo = Min(aLength - (TInt)aDestOffset, iTotalRxBytesAvail);
-#if defined(USBC_LDD_BUFFER_TRACE)
- TInt bufnum = iCurrentDrainingBufferIndex;
-#endif
- TInt errorCode = KErrNone;
- TBool isShortPacket = EFalse;
- const TInt maxPacketSizeMask = iMaxPacketSize - 1;
- do
- {
-#if defined(USBC_LDD_BUFFER_TRACE)
- if (bufnum != iCurrentDrainingBufferIndex)
- {
- bufnum = iCurrentDrainingBufferIndex;
- if (iDrainingOrder != iFillingOrderArray[iCurrentDrainingBufferIndex])
- {
- Kern::Printf("!!! Out of Order Draining TDmaBuf::RxCopyDataToClient 20 draining=%d",
- iCurrentDrainingBufferIndex);
- }
- }
-#endif
- if (errorCode == KErrNone)
- {
- errorCode = GetCurrentError();
- }
- thisStartAddr = iCurrentDrainingBuffer + iCurrentPacketIndexArray[iCurrentPacket] + iExtractOffset;
- const TInt thisPacketSize = iCurrentPacketSizeArray[iCurrentPacket];
- const TInt size = thisPacketSize - iExtractOffset;
- if (aRUS)
- {
- if (iEndpointType == UsbShai::KUsbEpTypeBulk)
- {
- isShortPacket = (size < iMaxPacketSize) || (size & maxPacketSizeMask);
- }
- else
- {
- // this 'if' block is arranged to avoid a division on packet sizes <= iMaxPacketSize
- isShortPacket = (size < iMaxPacketSize) ||
- ((size > iMaxPacketSize) && (size % iMaxPacketSize));
- }
- }
- TInt copySize = Min(size, toDo);
- iExtractOffset += copySize;
- toDo -= copySize;
- if (thisStartAddr != lastEndAddr)
- {
- TInt bytesToCopy = lastEndAddr - blockStartAddr;
- TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
- if(r != KErrNone)
- Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
- blockStartAddr = thisStartAddr;
- }
-
- ModifyTotalRxBytesAvail(-copySize);
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofBytesRxRemain[iCurrentDrainingBufferIndex] -= copySize;
-#endif
- lastEndAddr = thisStartAddr + copySize;
- if (iExtractOffset == thisPacketSize)
- {
- // More data to copy, so need to access new packet
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
-#endif
- if (!AdvancePacket())
- {
- break; // no more packets left
- }
- }
- } while (toDo > 0 && !isShortPacket);
-
- if (thisStartAddr != lastEndAddr)
- {
- TInt bytesToCopy = lastEndAddr - blockStartAddr;
- TInt r=CopyToUser(aThread, blockStartAddr, bytesToCopy, aTcb, aDestOffset);
- if(r != KErrNone)
- Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
- }
-
- // If we have transferred the requested amount of data it is still possible that
- // the next packet is a zlp which needs to be bumped over
-
- if (aRUS && (toDo == 0) && (iExtractOffset == 0) && (!isShortPacket) && (!IsReaderEmpty()) &&
- (PeekNextPacketSize() == 0))
- {
- // swallow a zlp
- isShortPacket = ETrue;
-#if defined(USBC_LDD_BUFFER_TRACE)
- iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex] -= 1;
-#endif
- AdvancePacket();
- }
- aCompleteNow = isShortPacket || (((TInt)aDestOffset) == aLength) || (errorCode != KErrNone);
-
- FreeDrainedBuffers();
-
- // Use this error code to complete client read request
- return errorCode;
- }
-
-
-inline TInt TDmaBuf::CopyToUser(DThread* aThread, const TUint8* aSourceAddr,
- TInt aLength, TClientBuffer *aTcb, TUint32& aDestOffset)
- {
- TPtrC8 des(aSourceAddr, aLength);
- TInt errorCode = Kern::ThreadBufWrite(aThread, aTcb, des, aDestOffset, KChunkShiftBy0, aThread);
- if (errorCode == KErrNone)
- {
- aDestOffset += aLength;
- }
- return errorCode;
- }
-
-
-inline TInt TDmaBuf::NoRxPackets() const
- {
- return iTotalRxPacketsAvail;
- }
-
-
-inline void TDmaBuf::IncrementBufferIndex(TInt& aIndex)
- {
- if (++aIndex == iNumberofBuffers)
- aIndex = 0;
- }
-
-
-TBool TDmaBuf::NextDrainableBuffer()
- {
- TBool r = EFalse;
- if (iCurrentDrainingBufferIndex != KUsbcInvalidBufferIndex)
- {
- iCanBeFreed[iCurrentDrainingBufferIndex] = ETrue;
- iNumberofPacketsRx[iCurrentDrainingBufferIndex] = 0; // Current buffer is empty
- iNumberofBytesRx[iCurrentDrainingBufferIndex] = 0; // Current buffer is empty
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- TUint& bytesRemain = iNumberofBytesRxRemain[iCurrentDrainingBufferIndex];
- TUint& pktsRemain = iNumberofPacketsRxRemain[iCurrentDrainingBufferIndex];
- if ((bytesRemain != 0) || (pktsRemain != 0))
- {
- Kern::Printf(
- "TDmaBuf::NextDrainableBuffer: Error: data discarded buffer=%d pkts=%d bytes=%d",
- iCurrentDrainingBufferIndex, pktsRemain, bytesRemain);
- bytesRemain = 0;
- pktsRemain = 0;
- }
-#endif
-
- iCurrentDrainingBufferIndex = KUsbcInvalidBufferIndex;
- iCurrentPacket = KUsbcInvalidPacketIndex;
- }
-
- if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
- {
- r = ETrue;
- const TInt index = iDrainQueue[0];
- iDrainQueueIndex--;
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- iDrainQueue[i] = iDrainQueue[i+1];
- }
-
-#if defined(USBC_LDD_BUFFER_TRACE)
- if (index != KUsbcInvalidBufferIndex)
- iDrainingOrder++;
-#endif
-
- iCurrentDrainingBufferIndex = index;
- iCurrentDrainingBuffer = iBuffers[index];
- iCurrentPacketIndexArray = iPacketIndex[index];
- iCurrentPacketSizeArray = iPacketSize[index];
- iCurrentPacket = 0;
- }
- return r;
- }
-
-
-TInt TDmaBuf::PeekNextDrainableBuffer()
- {
- TInt r = KUsbcInvalidBufferIndex;
- if (iDrainQueueIndex != KUsbcInvalidDrainQueueIndex)
- {
- r = iDrainQueue[0];
- }
- return r;
- }
-
-
-TBool TDmaBuf::NextFillableBuffer()
- {
- TBool r = EFalse;
- TInt index = iCurrentFillingBufferIndex;
- IncrementBufferIndex(index);
- // the sequence will restart at 0 if a buffer can't be found this time
- iCurrentFillingBufferIndex = 0;
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (!iDrainable[index])
- {
- iCurrentFillingBufferIndex = index;
- r = ETrue;
- break;
- }
- IncrementBufferIndex(index);
- }
- return r;
- }
-
-
-void TDmaBuf::FreeDrainedBuffers()
- {
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (iDrainable[i] && iCanBeFreed[i])
- {
- iDrainable[i] = iCanBeFreed[i] = EFalse;
- }
- }
- }
-
-
-TBool TDmaBuf::ShortPacketExists()
- {
- // Actually, a short packet or residue data
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::ShortPacketExists 1"));
- TInt index = iCurrentDrainingBufferIndex;
- TUsbcPacketArray* pktSizeArray = iCurrentPacketSizeArray;
-
- if (iMaxPacketSize > 0)
- {
- // No buffers available for draining
- if ((iCurrentDrainingBufferIndex == KUsbcInvalidBufferIndex) ||
- (iCurrentPacket == KUsbcInvalidPacketIndex))
- return EFalse;
-
- // Zlp waiting at tail
- if ((iTotalRxBytesAvail == 0) && (NoRxPackets() == 1))
- return ETrue;
-
- if (iEndpointType == UsbShai::KUsbEpTypeBulk)
- {
- const TInt mask = iMaxPacketSize - 1;
- if (iTotalRxBytesAvail & mask)
- return ETrue;
-
- // residue==0; this can be because
- // zlps exist, or short packets combine to n * max_packet_size
- // This means spadework
- const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
- if ((s == 0) || (s & mask))
- {
- return ETrue;
- }
-
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (index == KUsbcInvalidBufferIndex)
- break;
- if (iDrainable[index])
- {
- const TInt packetCount = iNumberofPacketsRx[index];
- const TInt lastPacketSize=pktSizeArray[packetCount - 1];
- if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize & mask))
- {
- return ETrue;
- }
- }
- index = iDrainQueue[i];
- pktSizeArray = iPacketSize[index];
- }
- }
- else
- {
- if (iTotalRxBytesAvail % iMaxPacketSize)
- return ETrue;
-
- // residue==0; this can be because
- // zlps exist, or short packets combine to n * max_packet_size
- // This means spadework
- const TInt s = iCurrentPacketSizeArray[iCurrentPacket] - iExtractOffset;
- if ((s == 0) || (s % iMaxPacketSize))
- {
- return ETrue;
- }
-
- for (TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (index == KUsbcInvalidBufferIndex)
- break;
- if (iDrainable[index])
- {
- const TInt packetCount = iNumberofPacketsRx[index];
- const TInt lastPacketSize = pktSizeArray[packetCount - 1];
- if ((lastPacketSize < iMaxPacketSize) || (lastPacketSize % iMaxPacketSize))
- {
- return ETrue;
- }
- }
- index = iDrainQueue[i];
- pktSizeArray = iPacketSize[index];
- }
- }
- }
-
- return EFalse;
- }
-
-
-void TDmaBuf::AddToDrainQueue(TInt aBufferIndex)
- {
- if (iDrainQueue[iDrainQueueIndex + 1] != KUsbcInvalidBufferIndex)
- {
-#if defined(USBC_LDD_BUFFER_TRACE)
- Kern::Printf("TDmaBuf::AddToDrainQueue: Error: invalid iDrainQueue[x]");
-#endif
- }
- iDrainQueue[++iDrainQueueIndex] = aBufferIndex;
- }
-
-
-#if defined(USBC_LDD_BUFFER_TRACE)
-TInt TDmaBuf::NoRxPacketsAlt() const
- {
- TInt pktCount = 0;
- for(TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (iDrainable[i])
- {
- pktCount += iNumberofPacketsRxRemain[i];
- }
- }
- return pktCount;
- }
-
-
-TInt TDmaBuf::NoRxBytesAlt() const
- {
- TInt byteCount = 0;
- for(TInt i = 0; i < iNumberofBuffers; i++)
- {
- if (iDrainable[i])
- {
- byteCount += iNumberofBytesRxRemain[i];
- }
- }
- return byteCount;
- }
-#endif
-
-
-// We only store 1 transaction, no other buffering is done
-TInt TDmaBuf::TxStoreData(DThread* aThread, TClientBuffer *aTcb, TInt aTxLength, TUint32 aBufferOffset)
- {
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 1"));
- if (!IsReaderEmpty())
- return KErrInUse;
-
- __KTRACE_OPT(KUSB, Kern::Printf("TDmaBuf::TxStoreData 2"));
-
- TInt remainTxLength = aTxLength;
- TUint32 bufferOffset = aBufferOffset;
- // Store each buffer separately
- for( TInt i=0;(i<iNumberofBuffers)&&(remainTxLength>0);i++)
- {
- TUint8* logicalDest = iBuffers[i];
- TInt xferSz = Min(remainTxLength, iBufSz);
- TPtr8 des(logicalDest, xferSz, xferSz);
- TInt r = Kern::ThreadBufRead(aThread, aTcb, des, bufferOffset, KChunkShiftBy0);
- if(r != KErrNone)
- {
- Kern::ThreadKill(aThread, EExitPanic, r, KUsbLDDKillCat);
- return r;
- }
- remainTxLength -= iBufSz;
- bufferOffset += iBufSz;
- }
-
- return KErrNone;
- }
-
-
-TInt TDmaBuf::TxGetNextXfer(TUint8*& aBufferAddr, TInt& aTxLength, TPhysAddr& aBufferPhys)
- {
- if (iTxActive)
- return KErrInUse;
-
- aBufferAddr = iBuffers[0]; // only 1 tx buffer
- aBufferPhys = iBufferPhys[0];
- aTxLength = BufferTotalSize();
-
- return KErrNone;
- }
-