Home | History | Annotate | Download | only in DebugCommunicationLibUsb3
      1 /** @file
      2   Debug Port Library implementation based on usb3 debug port.
      3 
      4   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 #include "DebugCommunicationLibUsb3Internal.h"
     15 
     16 /**
     17   Synchronize the specified transfer ring to update the enqueue and dequeue pointer.
     18 
     19   @param  Handle      Debug port handle.
     20   @param  TrsRing     The transfer ring to sync.
     21 
     22   @retval EFI_SUCCESS The transfer ring is synchronized successfully.
     23 
     24 **/
     25 EFI_STATUS
     26 EFIAPI
     27 XhcSyncTrsRing (
     28   IN USB3_DEBUG_PORT_HANDLE    *Handle,
     29   IN TRANSFER_RING             *TrsRing
     30   )
     31 {
     32   UINTN               Index;
     33   TRB_TEMPLATE        *TrsTrb;
     34   UINT32              CycleBit;
     35 
     36   ASSERT (TrsRing != NULL);
     37 
     38   //
     39   // Calculate the latest RingEnqueue and RingPCS
     40   //
     41   TrsTrb = (TRB_TEMPLATE *)(UINTN) TrsRing->RingEnqueue;
     42 
     43   ASSERT (TrsTrb != NULL);
     44 
     45   for (Index = 0; Index < TrsRing->TrbNumber; Index++) {
     46     if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) {
     47       break;
     48     }
     49     TrsTrb++;
     50     if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) {
     51       ASSERT (((LINK_TRB*)TrsTrb)->TC != 0);
     52       //
     53       // set cycle bit in Link TRB as normal
     54       //
     55       ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;
     56       //
     57       // Toggle PCS maintained by software
     58       //
     59       TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;
     60       TrsTrb           = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);
     61     }
     62   }
     63   ASSERT (Index != TrsRing->TrbNumber);
     64 
     65   if ((EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb != TrsRing->RingEnqueue) {
     66     TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb;
     67   }
     68 
     69   //
     70   // Clear the Trb context for enqueue, but reserve the PCS bit which indicates free Trb.
     71   //
     72   CycleBit = TrsTrb->CycleBit;
     73   ZeroMem (TrsTrb, sizeof (TRB_TEMPLATE));
     74   TrsTrb->CycleBit = CycleBit;
     75 
     76   return EFI_SUCCESS;
     77 }
     78 
     79 /**
     80   Synchronize the specified event ring to update the enqueue and dequeue pointer.
     81 
     82   @param  Handle      Debug port handle.
     83   @param  EvtRing     The event ring to sync.
     84 
     85   @retval EFI_SUCCESS The event ring is synchronized successfully.
     86 
     87 **/
     88 EFI_STATUS
     89 EFIAPI
     90 XhcSyncEventRing (
     91   IN USB3_DEBUG_PORT_HANDLE  *Handle,
     92   IN EVENT_RING                *EvtRing
     93   )
     94 {
     95   UINTN               Index;
     96   TRB_TEMPLATE        *EvtTrb1;
     97 
     98   ASSERT (EvtRing != NULL);
     99 
    100   //
    101   // Calculate the EventRingEnqueue and EventRingCCS.
    102   // Note: only support single Segment
    103   //
    104   EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
    105 
    106   for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
    107     if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {
    108       break;
    109     }
    110 
    111     EvtTrb1++;
    112 
    113     if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
    114       EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingSeg0;
    115       EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;
    116     }
    117   }
    118 
    119   if (Index < EvtRing->TrbNumber) {
    120     EvtRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EvtTrb1;
    121   } else {
    122     ASSERT (FALSE);
    123   }
    124 
    125   return EFI_SUCCESS;
    126 }
    127 
    128 /**
    129   Check if there is a new generated event.
    130 
    131   @param  Handle        Debug port handle.
    132   @param  EvtRing       The event ring to check.
    133   @param  NewEvtTrb     The new event TRB found.
    134 
    135   @retval EFI_SUCCESS   Found a new event TRB at the event ring.
    136   @retval EFI_NOT_READY The event ring has no new event.
    137 
    138 **/
    139 EFI_STATUS
    140 EFIAPI
    141 XhcCheckNewEvent (
    142   IN  USB3_DEBUG_PORT_HANDLE   *Handle,
    143   IN  EVENT_RING               *EvtRing,
    144   OUT TRB_TEMPLATE             **NewEvtTrb
    145   )
    146 {
    147   EFI_STATUS          Status;
    148   TRB_TEMPLATE        *EvtTrb;
    149 
    150   ASSERT (EvtRing != NULL);
    151 
    152   EvtTrb     = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
    153   *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
    154 
    155   if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {
    156     return EFI_NOT_READY;
    157   }
    158 
    159   Status = EFI_SUCCESS;
    160 
    161   EvtRing->EventRingDequeue += sizeof (TRB_TEMPLATE);
    162   //
    163   // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
    164   //
    165   if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
    166     EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;
    167   }
    168 
    169   return Status;
    170 }
    171 
    172 /**
    173   Check if the Trb is a transaction of the URB.
    174 
    175   @param Ring   The transfer ring to be checked.
    176   @param Trb    The TRB to be checked.
    177 
    178   @retval TRUE  It is a transaction of the URB.
    179   @retval FALSE It is not any transaction of the URB.
    180 
    181 **/
    182 BOOLEAN
    183 IsTrbInTrsRing (
    184   IN  TRANSFER_RING       *Ring,
    185   IN  TRB_TEMPLATE        *Trb
    186   )
    187 {
    188   TRB_TEMPLATE  *CheckedTrb;
    189   UINTN         Index;
    190 
    191   CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0;
    192 
    193   ASSERT (Ring->TrbNumber == TR_RING_TRB_NUMBER);
    194 
    195   for (Index = 0; Index < Ring->TrbNumber; Index++) {
    196     if (Trb == CheckedTrb) {
    197       return TRUE;
    198     }
    199     CheckedTrb++;
    200   }
    201 
    202   return FALSE;
    203 }
    204 
    205 /**
    206   Check the URB's execution result and update the URB's
    207   result accordingly.
    208 
    209   @param  Handle          Debug port handle.
    210   @param  Urb             The URB to check result.
    211 
    212 **/
    213 VOID
    214 XhcCheckUrbResult (
    215   IN  USB3_DEBUG_PORT_HANDLE *Handle,
    216   IN  URB                      *Urb
    217   )
    218 {
    219   EVT_TRB_TRANSFER        *EvtTrb;
    220   TRB_TEMPLATE            *TRBPtr;
    221   UINTN                   Index;
    222   EFI_STATUS              Status;
    223   URB                     *CheckedUrb;
    224   UINT64                  XhcDequeue;
    225   UINT32                  High;
    226   UINT32                  Low;
    227 
    228   ASSERT ((Handle != NULL) && (Urb != NULL));
    229 
    230   if (Urb->Finished) {
    231     goto EXIT;
    232   }
    233 
    234   EvtTrb = NULL;
    235 
    236   //
    237   // Traverse the event ring to find out all new events from the previous check.
    238   //
    239   XhcSyncEventRing (Handle, &Handle->EventRing);
    240 
    241   for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) {
    242 
    243     Status = XhcCheckNewEvent (Handle, &Handle->EventRing, ((TRB_TEMPLATE **)&EvtTrb));
    244     if (Status == EFI_NOT_READY) {
    245       //
    246       // All new events are handled, return directly.
    247       //
    248       goto EXIT;
    249     }
    250 
    251     if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {
    252       continue;
    253     }
    254 
    255     TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
    256 
    257     if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Urb->Ring), TRBPtr)) {
    258       CheckedUrb = Urb;
    259     } else if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Handle->UrbIn.Ring), TRBPtr)) {
    260       //
    261       // If it is read event and it should be generated by poll, and current operation is write, we need save data into internal buffer.
    262       // Internal buffer is used by next read.
    263       //
    264       Handle->DataCount = (UINT8) (Handle->UrbIn.DataLen - EvtTrb->Length);
    265       CopyMem ((VOID *)(UINTN)Handle->Data, (VOID *)(UINTN)Handle->UrbIn.Data, Handle->DataCount);
    266       //
    267       // Fill this TRB complete with CycleBit, otherwise next read will fail with old TRB.
    268       //
    269       TRBPtr->CycleBit = (TRBPtr->CycleBit & BIT0) ? 0 : 1;
    270       continue;
    271     } else {
    272       continue;
    273     }
    274 
    275     if ((EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) ||
    276         (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS)) {
    277       //
    278       // The length of data which were transferred.
    279       //
    280       CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length);
    281     } else {
    282       CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;
    283     }
    284     //
    285     // This Urb has been processed
    286     //
    287     CheckedUrb->Finished = TRUE;
    288   }
    289 
    290 EXIT:
    291   //
    292   // Advance event ring to last available entry
    293   //
    294   // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
    295   // So divide it to two 32-bytes width register access.
    296   //
    297   Low  = XhcReadDebugReg (Handle, XHC_DC_DCERDP);
    298   High = XhcReadDebugReg (Handle, XHC_DC_DCERDP + 4);
    299   XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
    300 
    301   if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Handle->EventRing.EventRingDequeue & (~0x0F))) {
    302     //
    303     // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
    304     // So divide it to two 32-bytes width register access.
    305     //
    306     XhcWriteDebugReg (Handle, XHC_DC_DCERDP, XHC_LOW_32BIT (Handle->EventRing.EventRingDequeue));
    307     XhcWriteDebugReg (Handle, XHC_DC_DCERDP + 4, XHC_HIGH_32BIT (Handle->EventRing.EventRingDequeue));
    308   }
    309 }
    310 
    311 /**
    312   Ring the door bell to notify XHCI there is a transaction to be executed.
    313 
    314   @param  Handle        Debug port handle.
    315   @param  Urb           The pointer to URB.
    316 
    317   @retval EFI_SUCCESS   Successfully ring the door bell.
    318 
    319 **/
    320 EFI_STATUS
    321 EFIAPI
    322 XhcRingDoorBell (
    323   IN USB3_DEBUG_PORT_HANDLE    *Handle,
    324   IN URB                       *Urb
    325   )
    326 {
    327   UINT32      Dcdb;
    328 
    329   //
    330   // 7.6.8.2 DCDB Register
    331   //
    332   Dcdb = (Urb->Direction == EfiUsbDataIn) ? 0x100 : 0x0;
    333 
    334   XhcWriteDebugReg (
    335     Handle,
    336     XHC_DC_DCDB,
    337     Dcdb
    338     );
    339 
    340   return EFI_SUCCESS;
    341 }
    342 
    343 /**
    344   Execute the transfer by polling the URB. This is a synchronous operation.
    345 
    346   @param  Handle            Debug port handle.
    347   @param  Urb               The URB to execute.
    348   @param  Timeout           The time to wait before abort, in microsecond.
    349 
    350 **/
    351 VOID
    352 XhcExecTransfer (
    353   IN  USB3_DEBUG_PORT_HANDLE   *Handle,
    354   IN  URB                      *Urb,
    355   IN  UINTN                    Timeout
    356   )
    357 {
    358   TRANSFER_RING           *Ring;
    359   TRB_TEMPLATE            *Trb;
    360   UINTN                   Loop;
    361   UINTN                   Index;
    362 
    363   Loop = Timeout / XHC_DEBUG_PORT_1_MILLISECOND;
    364   if (Timeout == 0) {
    365     Loop = 0xFFFFFFFF;
    366   }
    367   XhcRingDoorBell (Handle, Urb);
    368   //
    369   // Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay.
    370   //
    371   for (Index = 0; Index < Loop; Index++) {
    372     XhcCheckUrbResult (Handle, Urb);
    373     if (Urb->Finished) {
    374       break;
    375     }
    376     MicroSecondDelay (XHC_DEBUG_PORT_1_MILLISECOND);
    377   }
    378   if (Index == Loop) {
    379     //
    380     // If time out occurs.
    381     //
    382     Urb->Result |= EFI_USB_ERR_TIMEOUT;
    383   }
    384   //
    385   // If URB transfer is error, restore transfer ring to original value before URB transfer
    386   // This will make the current transfer TRB is always at the latest unused one in transfer ring.
    387   //
    388   Ring = (TRANSFER_RING *)(UINTN) Urb->Ring;
    389   if ((Urb->Result != EFI_USB_NOERROR) && (Urb->Direction == EfiUsbDataIn)) {
    390     //
    391     // Adjust Enqueue pointer
    392     //
    393     Ring->RingEnqueue = Urb->Trb;
    394     //
    395     // Clear CCS flag for next use
    396     //
    397     Trb = (TRB_TEMPLATE *)(UINTN) Urb->Trb;
    398     Trb->CycleBit = ((~Ring->RingPCS) & BIT0);
    399   } else {
    400     //
    401     // Update transfer ring for next transfer.
    402     //
    403     XhcSyncTrsRing (Handle, Ring);
    404   }
    405 }
    406 
    407 /**
    408   Create a transfer TRB.
    409 
    410   @param  Handle  Debug port handle.
    411   @param  Urb     The urb used to construct the transfer TRB.
    412 
    413   @return Created TRB or NULL
    414 
    415 **/
    416 EFI_STATUS
    417 XhcCreateTransferTrb (
    418   IN USB3_DEBUG_PORT_HANDLE   *Handle,
    419   IN URB                        *Urb
    420   )
    421 {
    422   TRANSFER_RING                 *EPRing;
    423   TRB                           *Trb;
    424 
    425   if (Urb->Direction == EfiUsbDataIn) {
    426     EPRing = &Handle->TransferRingIn;
    427   } else {
    428     EPRing = &Handle->TransferRingOut;
    429   }
    430 
    431   Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing;
    432   XhcSyncTrsRing (Handle, EPRing);
    433 
    434   Urb->Trb = EPRing->RingEnqueue;
    435   Trb = (TRB *)(UINTN)EPRing->RingEnqueue;
    436   Trb->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT (Urb->Data);
    437   Trb->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT (Urb->Data);
    438   Trb->TrbNormal.Length    = Urb->DataLen;
    439   Trb->TrbNormal.TDSize    = 0;
    440   Trb->TrbNormal.IntTarget = 0;
    441   Trb->TrbNormal.ISP       = 1;
    442   Trb->TrbNormal.IOC       = 1;
    443   Trb->TrbNormal.Type      = TRB_TYPE_NORMAL;
    444 
    445   //
    446   // Update the cycle bit to indicate this TRB has been consumed.
    447   //
    448   Trb->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;
    449 
    450   return EFI_SUCCESS;
    451 }
    452 
    453 /**
    454   Create a new URB for a new transaction.
    455 
    456   @param  Handle     Debug port handle.
    457   @param  Direction  The direction of data flow.
    458   @param  Data       The user data to transfer
    459   @param  DataLen    The length of data buffer
    460 
    461   @return Created URB or NULL
    462 
    463 **/
    464 URB*
    465 XhcCreateUrb (
    466   IN USB3_DEBUG_PORT_HANDLE             *Handle,
    467   IN EFI_USB_DATA_DIRECTION             Direction,
    468   IN VOID                               *Data,
    469   IN UINTN                              DataLen
    470   )
    471 {
    472   EFI_STATUS                    Status;
    473   URB                           *Urb;
    474   EFI_PHYSICAL_ADDRESS          UrbData;
    475 
    476   if (Direction == EfiUsbDataIn) {
    477     Urb = &Handle->UrbIn;
    478   } else {
    479     Urb = &Handle->UrbOut;
    480   }
    481 
    482   UrbData  = Urb->Data;
    483 
    484   ZeroMem (Urb, sizeof (URB));
    485   Urb->Direction = Direction;
    486 
    487   //
    488   // Allocate memory to move data from CAR or SMRAM to normal memory
    489   // to make XHCI DMA successfully
    490   // re-use the pre-allocate buffer in PEI to avoid DXE memory service or gBS are not ready
    491   //
    492   Urb->Data  = UrbData;
    493 
    494   if (Direction == EfiUsbDataIn) {
    495     //
    496     // Do not break URB data in buffer as it may contain the data which were just put in via DMA by XHC
    497     //
    498     Urb->DataLen  = (UINT32) DataLen;
    499   } else {
    500     //
    501     // Put data into URB data out buffer which will create TRBs
    502     //
    503     ZeroMem ((VOID*)(UINTN) Urb->Data, DataLen);
    504     CopyMem ((VOID*)(UINTN) Urb->Data, Data, DataLen);
    505     Urb->DataLen  = (UINT32) DataLen;
    506   }
    507 
    508   Status = XhcCreateTransferTrb (Handle, Urb);
    509   ASSERT_EFI_ERROR (Status);
    510 
    511   return Urb;
    512 }
    513 
    514 /**
    515   Submits bulk transfer to a bulk endpoint of a USB device.
    516 
    517   @param  Handle                Debug port handle.
    518   @param  Direction             The direction of data transfer.
    519   @param  Data                  Array of pointers to the buffers of data to transmit
    520                                 from or receive into.
    521   @param  DataLength            The lenght of the data buffer.
    522   @param  Timeout               Indicates the maximum time, in microsecond, which
    523                                 the transfer is allowed to complete.
    524 
    525   @retval EFI_SUCCESS           The transfer was completed successfully.
    526   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
    527   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    528   @retval EFI_TIMEOUT           The transfer failed due to timeout.
    529   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
    530 
    531 **/
    532 EFI_STATUS
    533 EFIAPI
    534 XhcDataTransfer (
    535   IN     USB3_DEBUG_PORT_HANDLE              *Handle,
    536   IN     EFI_USB_DATA_DIRECTION              Direction,
    537   IN OUT VOID                                *Data,
    538   IN OUT UINTN                               *DataLength,
    539   IN     UINTN                               Timeout
    540   )
    541 {
    542   URB                     *Urb;
    543   EFI_STATUS              Status;
    544 
    545   //
    546   // Validate the parameters
    547   //
    548   if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL)) {
    549     return EFI_INVALID_PARAMETER;
    550   }
    551 
    552   //
    553   // Create a new URB, insert it into the asynchronous
    554   // schedule list, then poll the execution status.
    555   //
    556   Urb = XhcCreateUrb (Handle, Direction, Data, *DataLength);
    557   ASSERT (Urb != NULL);
    558 
    559   XhcExecTransfer (Handle, Urb, Timeout);
    560 
    561   *DataLength     = Urb->Completed;
    562 
    563   Status = EFI_TIMEOUT;
    564   if (Urb->Result == EFI_USB_NOERROR) {
    565     Status = EFI_SUCCESS;
    566   }
    567 
    568   if (Direction == EfiUsbDataIn) {
    569     //
    570     // Move data from internal buffer to outside buffer (outside buffer may be in SMRAM...)
    571     // SMRAM does not allow to do DMA, so we create an internal buffer.
    572     //
    573     CopyMem (Data, (VOID *)(UINTN)Urb->Data, *DataLength);
    574   }
    575 
    576   return Status;
    577 }
    578 
    579