usbdrv/peripheral/ldd/perildd/src/usbdma.cpp
branchRCL_3
changeset 15 f92a4f87e424
equal deleted inserted replaced
14:d3e8e7d462dd 15:f92a4f87e424
       
     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 <usb/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 UsbShai::KUsbEpTypeControl:
       
    46         iBufSz = KUsbcDmaBufSzControl;
       
    47         iNumberofBuffers = KUsbcDmaBufNumControl;
       
    48         break;
       
    49     case UsbShai::KUsbEpTypeIsochronous:
       
    50         iBufSz = KUsbcDmaBufSzIsochronous;
       
    51         iNumberofBuffers = KUsbcDmaBufNumIsochronous;
       
    52         break;
       
    53     case UsbShai::KUsbEpTypeBulk:
       
    54         {
       
    55         if (aEndpointInfo->iDir == UsbShai::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 UsbShai::KUsbEpTypeInterrupt:
       
    69         iBufSz = KUsbcDmaBufSzInterrupt;
       
    70         iNumberofBuffers = KUsbcDmaBufNumInterrupt;
       
    71         break;
       
    72     default:
       
    73         iBufSz = 0;
       
    74         iNumberofBuffers = 0;
       
    75         }
       
    76 
       
    77     if (aEndpointInfo->iDir == UsbShai::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 != UsbShai::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 == UsbShai::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 == UsbShai::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 == UsbShai::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