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 
     15 #include "DebugCommunicationLibUsb3Internal.h"
     16 
     17 //
     18 // The global variable which can be used after memory is ready.
     19 //
     20 USB3_DEBUG_PORT_HANDLE     mDebugCommunicationLibUsb3DebugPortHandle;
     21 
     22 UINT16   mString0Desc[] = {
     23   //  String Descriptor Type + Length
     24   ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,
     25   0x0409
     26 };
     27 
     28 UINT16   mManufacturerStrDesc[] = {
     29   //  String Descriptor Type + Length
     30   ( USB_DESC_TYPE_STRING << 8 ) + MANU_DESC_LEN,
     31   'I', 'n', 't', 'e', 'l'
     32 };
     33 
     34 UINT16   mProductStrDesc[] = {
     35   //  String Descriptor Type + Length
     36   ( USB_DESC_TYPE_STRING << 8 ) +  PRODUCT_DESC_LEN,
     37   'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'
     38 };
     39 
     40 UINT16   mSerialNumberStrDesc[] = {
     41   //  String Descriptor Type + Length
     42   ( USB_DESC_TYPE_STRING << 8 ) +  SERIAL_DESC_LEN,
     43   '1'
     44 };
     45 
     46 /**
     47   Sets bits as per the enabled bit positions in the mask.
     48 
     49   @param[in, out] Register    UINTN register
     50   @param[in]      BitMask     32-bit mask
     51 **/
     52 VOID
     53 XhcSetR32Bit(
     54   IN OUT  UINTN  Register,
     55   IN      UINT32 BitMask
     56   )
     57 {
     58   UINT32    RegisterValue;
     59 
     60   RegisterValue = MmioRead32 (Register);
     61   RegisterValue |= (UINT32)(BitMask);
     62   MmioWrite32 (Register, RegisterValue);
     63 }
     64 
     65 /**
     66   Clears bits as per the enabled bit positions in the mask.
     67 
     68   @param[in, out] Register    UINTN register
     69   @param[in]      BitMask     32-bit mask
     70 **/
     71 VOID
     72 XhcClearR32Bit(
     73   IN OUT  UINTN  Register,
     74   IN      UINT32 BitMask
     75   )
     76 {
     77   UINT32    RegisterValue;
     78 
     79   RegisterValue = MmioRead32 (Register);
     80   RegisterValue &= ~BitMask;
     81   MmioWrite32 (Register, RegisterValue);
     82 }
     83 
     84 /**
     85   Write the data to the XHCI debug register.
     86 
     87   @param  Handle       Debug port handle.
     88   @param  Offset       The offset of the runtime register.
     89   @param  Data         The data to write.
     90 
     91 **/
     92 VOID
     93 XhcWriteDebugReg (
     94   IN USB3_DEBUG_PORT_HANDLE  *Handle,
     95   IN UINT32                   Offset,
     96   IN UINT32                   Data
     97   )
     98 {
     99   EFI_PHYSICAL_ADDRESS  DebugCapabilityBase;
    100 
    101   DebugCapabilityBase = Handle->DebugCapabilityBase;
    102   MmioWrite32 ((UINTN)(DebugCapabilityBase + Offset), Data);
    103 
    104   return;
    105 }
    106 
    107 /**
    108   Read XHCI debug register.
    109 
    110   @param  Handle       Debug port handle.
    111   @param  Offset       The offset of the runtime register.
    112 
    113   @return The register content read
    114 
    115 **/
    116 UINT32
    117 XhcReadDebugReg (
    118   IN  USB3_DEBUG_PORT_HANDLE *Handle,
    119   IN  UINT32                   Offset
    120   )
    121 {
    122   UINT32                  Data;
    123   EFI_PHYSICAL_ADDRESS    DebugCapabilityBase;
    124 
    125   DebugCapabilityBase = Handle->DebugCapabilityBase;
    126   Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));
    127 
    128   return Data;
    129 }
    130 
    131 /**
    132   Set one bit of the runtime register while keeping other bits.
    133 
    134   @param  Handle       Debug port handle.
    135   @param  Offset       The offset of the runtime register.
    136   @param  Bit          The bit mask of the register to set.
    137 
    138 **/
    139 VOID
    140 XhcSetDebugRegBit (
    141   IN USB3_DEBUG_PORT_HANDLE *Handle,
    142   IN UINT32                   Offset,
    143   IN UINT32                   Bit
    144   )
    145 {
    146   UINT32                  Data;
    147 
    148   Data  = XhcReadDebugReg (Handle, Offset);
    149   Data |= Bit;
    150   XhcWriteDebugReg (Handle, Offset, Data);
    151 }
    152 
    153 /**
    154   Program and eanble XHCI MMIO base address.
    155 
    156   @return XHCI MMIO base address.
    157 
    158 **/
    159 EFI_PHYSICAL_ADDRESS
    160 ProgramXhciBaseAddress (
    161   VOID
    162   )
    163 {
    164   UINT16                      PciCmd;
    165   UINT32                      Low;
    166   UINT32                      High;
    167   EFI_PHYSICAL_ADDRESS        XhciMmioBase;
    168 
    169   Low = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
    170   High = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4);
    171   XhciMmioBase = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
    172   XhciMmioBase &= XHCI_BASE_ADDRESS_64_BIT_MASK;
    173 
    174   if ((XhciMmioBase == 0) || (XhciMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
    175     XhciMmioBase = PcdGet64(PcdUsbXhciMemorySpaceBase);
    176     PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, XhciMmioBase & 0xFFFFFFFF);
    177     PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4, (RShiftU64 (XhciMmioBase, 32) & 0xFFFFFFFF));
    178   }
    179 
    180   PciCmd = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET);
    181   if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
    182     PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;
    183     PciWrite16(PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
    184   }
    185 
    186   return XhciMmioBase;
    187 }
    188 
    189 /**
    190   Update XHC MMIO base address when MMIO base address is changed.
    191 
    192   @param  Handle          Debug port handle.
    193   @param  XhciMmioBase    XHCI MMIO base address.
    194 
    195 **/
    196 VOID
    197 UpdateXhcResource (
    198   IN OUT USB3_DEBUG_PORT_HANDLE            *Handle,
    199   IN EFI_PHYSICAL_ADDRESS                   XhciMmioBase
    200   )
    201 {
    202   if ((Handle == NULL) || (Handle->XhciMmioBase == XhciMmioBase)) {
    203     return;
    204   }
    205 
    206   //
    207   // Need fix Handle data according to new XHCI MMIO base address.
    208   //
    209   Handle->XhciMmioBase        = XhciMmioBase;
    210   Handle->DebugCapabilityBase = XhciMmioBase + Handle->DebugCapabilityOffset;
    211   Handle->XhciOpRegister      = XhciMmioBase + MmioRead8 ((UINTN)XhciMmioBase);
    212 }
    213 
    214 /**
    215   Calculate the usb debug port bar address.
    216 
    217   @param  Handle             Debug port handle.
    218 
    219   @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.
    220   @retval RETURN_SUCCESS     Get bar and offset successfully.
    221 
    222 **/
    223 RETURN_STATUS
    224 EFIAPI
    225 CalculateUsbDebugPortMmioBase (
    226   USB3_DEBUG_PORT_HANDLE          *Handle
    227  )
    228 {
    229   UINT16                          VendorId;
    230   UINT16                          DeviceId;
    231   UINT8                           ProgInterface;
    232   UINT8                           SubClassCode;
    233   UINT8                           BaseCode;
    234   BOOLEAN                         Flag;
    235   UINT32                          Capability;
    236   EFI_PHYSICAL_ADDRESS            CapabilityPointer;
    237   UINT8                           CapLength;
    238 
    239   VendorId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_VENDOR_ID_OFFSET);
    240   DeviceId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_DEVICE_ID_OFFSET);
    241 
    242   if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {
    243     goto Done;
    244   }
    245 
    246   ProgInterface = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET);
    247   SubClassCode  = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);
    248   BaseCode      = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);
    249 
    250   if ((ProgInterface != PCI_IF_XHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {
    251     goto Done;
    252   }
    253 
    254   CapLength = MmioRead8 ((UINTN) Handle->XhciMmioBase);
    255 
    256   //
    257   // Get capability pointer from HCCPARAMS at offset 0x10
    258   //
    259   CapabilityPointer = Handle->XhciMmioBase + (MmioRead32 ((UINTN)(Handle->XhciMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
    260 
    261   //
    262   // Search XHCI debug capability
    263   //
    264   Flag = FALSE;
    265   Capability = MmioRead32 ((UINTN)CapabilityPointer);
    266   while (TRUE) {
    267     if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
    268       Flag = TRUE;
    269       break;
    270     }
    271     if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
    272       //
    273       // Reach the end of capability list, quit
    274       //
    275       break;
    276     }
    277     CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
    278     Capability = MmioRead32 ((UINTN)CapabilityPointer);
    279   }
    280 
    281   if (!Flag) {
    282     goto Done;
    283   }
    284 
    285   //
    286   // USB3 debug capability is supported.
    287   //
    288   Handle->DebugCapabilityBase   = CapabilityPointer;
    289   Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;
    290   Handle->XhciOpRegister        = Handle->XhciMmioBase + CapLength;
    291   Handle->Initialized = USB3DBG_DBG_CAB;
    292   return RETURN_SUCCESS;
    293 
    294 Done:
    295   Handle->Initialized = USB3DBG_NO_DBG_CAB;
    296   return RETURN_UNSUPPORTED;
    297 }
    298 
    299 /**
    300   Check if it needs to re-initialize usb debug port hardware.
    301 
    302   During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
    303   whether the usb debug port hardware configuration is changed. Such case can be triggered by
    304   Pci bus resource allocation and so on.
    305 
    306   @param  Handle           Debug port handle.
    307 
    308   @retval TRUE             The usb debug port hardware configuration is changed.
    309   @retval FALSE            The usb debug port hardware configuration is not changed.
    310 
    311 **/
    312 BOOLEAN
    313 EFIAPI
    314 NeedReinitializeHardware(
    315   IN USB3_DEBUG_PORT_HANDLE *Handle
    316   )
    317 {
    318   BOOLEAN                 Result;
    319   volatile UINT32         Dcctrl;
    320 
    321   Result = FALSE;
    322 
    323   //
    324   // If DCE bit, it means USB3 debug is not enabled.
    325   //
    326   Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
    327   if ((Dcctrl & BIT0) == 0) {
    328     Result = TRUE;
    329   }
    330 
    331   return Result;
    332 }
    333 
    334 /**
    335   Create XHCI event ring.
    336 
    337   @param  Handle              Debug port handle.
    338   @param  EventRing           The created event ring.
    339 
    340 **/
    341 EFI_STATUS
    342 CreateEventRing (
    343   IN  USB3_DEBUG_PORT_HANDLE     *Handle,
    344   OUT EVENT_RING                 *EventRing
    345   )
    346 {
    347   VOID                        *Buf;
    348   EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;
    349 
    350   ASSERT (EventRing != NULL);
    351 
    352   //
    353   // Allocate Event Ring
    354   //
    355   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
    356   ASSERT (Buf != NULL);
    357   ASSERT (((UINTN) Buf & 0x3F) == 0);
    358   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
    359 
    360   EventRing->EventRingSeg0    = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
    361   EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;
    362   EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
    363   EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
    364 
    365   //
    366   // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
    367   // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
    368   //
    369   EventRing->EventRingCCS = 1;
    370 
    371   //
    372   // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
    373   //
    374   Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
    375   ASSERT (Buf != NULL);
    376   ASSERT (((UINTN) Buf & 0x3F) == 0);
    377   ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
    378 
    379   ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
    380   EventRing->ERSTBase   = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;
    381 
    382   //
    383   // Fill Event Segment address
    384   //
    385   ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingSeg0);
    386   ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
    387   ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
    388 
    389   //
    390   // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
    391   //
    392   XhcWriteDebugReg (
    393     Handle,
    394     XHC_DC_DCERDP,
    395     XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
    396     );
    397 
    398   XhcWriteDebugReg (
    399     Handle,
    400     XHC_DC_DCERDP + 4,
    401     XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
    402     );
    403 
    404   //
    405   // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
    406   //
    407   XhcWriteDebugReg (
    408     Handle,
    409     XHC_DC_DCERSTBA,
    410     XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
    411     );
    412 
    413   XhcWriteDebugReg (
    414     Handle,
    415     XHC_DC_DCERSTBA + 4,
    416     XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
    417     );
    418 
    419   //
    420   // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
    421   //
    422   XhcWriteDebugReg (
    423     Handle,
    424     XHC_DC_DCERSTSZ,
    425     ERST_NUMBER
    426     );
    427   return EFI_SUCCESS;
    428 }
    429 
    430 /**
    431   Create XHCI transfer ring.
    432 
    433   @param  Handle            Debug port handle.
    434   @param  TrbNum            The number of TRB in the ring.
    435   @param  TransferRing      The created transfer ring.
    436 
    437 **/
    438 VOID
    439 CreateTransferRing (
    440   IN  USB3_DEBUG_PORT_HANDLE      *Handle,
    441   IN  UINT32                      TrbNum,
    442   OUT TRANSFER_RING               *TransferRing
    443   )
    444 {
    445   VOID                  *Buf;
    446   LINK_TRB              *EndTrb;
    447 
    448   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
    449   ASSERT (Buf != NULL);
    450   ASSERT (((UINTN) Buf & 0xF) == 0);
    451   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
    452 
    453   TransferRing->RingSeg0     = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
    454   TransferRing->TrbNumber    = TrbNum;
    455   TransferRing->RingEnqueue  = TransferRing->RingSeg0;
    456   TransferRing->RingDequeue  = TransferRing->RingSeg0;
    457   TransferRing->RingPCS      = 1;
    458   //
    459   // 4.9.2 Transfer Ring Management
    460   // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
    461   // point to the first TRB in the ring.
    462   //
    463   EndTrb        = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
    464   EndTrb->Type  = TRB_TYPE_LINK;
    465   EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
    466   EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
    467   //
    468   // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
    469   //
    470   EndTrb->TC    = 1;
    471   //
    472   // Set Cycle bit as other TRB PCS init value
    473   //
    474   EndTrb->CycleBit = 0;
    475 }
    476 
    477 /**
    478   Create debug capability context for XHC debug device.
    479 
    480   @param  Handle       Debug port handle.
    481 
    482   @retval EFI_SUCCESS  The bit successfully changed by host controller.
    483   @retval EFI_TIMEOUT  The time out occurred.
    484 
    485 **/
    486 EFI_STATUS
    487 CreateDebugCapabilityContext (
    488   IN  USB3_DEBUG_PORT_HANDLE   *Handle
    489   )
    490 {
    491   VOID                        *Buf;
    492   XHC_DC_CONTEXT              *DebugCapabilityContext;
    493   UINT8                       *String0Desc;
    494   UINT8                       *ManufacturerStrDesc;
    495   UINT8                       *ProductStrDesc;
    496   UINT8                       *SerialNumberStrDesc;
    497 
    498   //
    499   // Allocate debug device context
    500   //
    501   Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
    502   ASSERT (Buf != NULL);
    503   ASSERT (((UINTN) Buf & 0xF) == 0);
    504   ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
    505 
    506   DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;
    507   Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;
    508 
    509   //
    510   // Initialize DbcInfoContext.
    511   //
    512   DebugCapabilityContext->DbcInfoContext.String0Length         = STRING0_DESC_LEN;
    513   DebugCapabilityContext->DbcInfoContext.ManufacturerStrLength = MANU_DESC_LEN;
    514   DebugCapabilityContext->DbcInfoContext.ProductStrLength      = PRODUCT_DESC_LEN;
    515   DebugCapabilityContext->DbcInfoContext.SerialNumberStrLength = SERIAL_DESC_LEN;
    516 
    517   //
    518   // Initialize EpOutContext.
    519   //
    520   DebugCapabilityContext->EpOutContext.CErr             = 0x3;
    521   DebugCapabilityContext->EpOutContext.EPType           = ED_BULK_OUT;
    522   DebugCapabilityContext->EpOutContext.MaxPacketSize    = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
    523   DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;
    524 
    525   //
    526   // Initialize EpInContext.
    527   //
    528   DebugCapabilityContext->EpInContext.CErr             = 0x3;
    529   DebugCapabilityContext->EpInContext.EPType           = ED_BULK_IN;
    530   DebugCapabilityContext->EpInContext.MaxPacketSize    = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
    531   DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;
    532 
    533   //
    534   // Update string descriptor address
    535   //
    536   String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
    537   ASSERT (String0Desc != NULL);
    538   ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
    539   CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
    540   DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
    541 
    542   ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
    543   CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
    544   DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
    545 
    546   ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
    547   CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
    548   DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
    549 
    550   SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
    551   CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
    552   DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
    553 
    554   //
    555   // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
    556   //
    557   ZeroMem (&Handle->TransferRingIn, sizeof (TRANSFER_RING));
    558   CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingIn);
    559   DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingIn.RingSeg0) | BIT0;
    560   DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingIn.RingSeg0);
    561 
    562   //
    563   // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
    564   //
    565   ZeroMem (&Handle->TransferRingOut, sizeof (TRANSFER_RING));
    566   CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingOut);
    567   DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingOut.RingSeg0) | BIT0;
    568   DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingOut.RingSeg0);
    569 
    570   //
    571   // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
    572   //
    573   XhcWriteDebugReg (
    574     Handle,
    575     XHC_DC_DCCP,
    576     XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)
    577     );
    578   XhcWriteDebugReg (
    579     Handle,
    580     XHC_DC_DCCP + 4,
    581     XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)
    582     );
    583   return EFI_SUCCESS;
    584 }
    585 
    586 /**
    587   Check if debug device is running.
    588 
    589   @param  Handle       Debug port handle.
    590 
    591 **/
    592 VOID
    593 XhcDetectDebugCapabilityReady (
    594   IN USB3_DEBUG_PORT_HANDLE *Handle
    595   )
    596 {
    597   UINT64                          TimeOut;
    598   volatile UINT32                 Dcctrl;
    599 
    600   TimeOut = 1;
    601   if (Handle->Initialized == USB3DBG_DBG_CAB) {
    602     //
    603     // As detection is slow in seconds, wait for longer timeout for the first time.
    604     // If first initialization is failed, we will try to enable debug device in the
    605     // Poll function invoked by timer.
    606     //
    607     TimeOut = DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout), XHC_POLL_DELAY) + 1;
    608   }
    609 
    610   do {
    611     //
    612     // Check if debug device is in configured state
    613     //
    614     Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
    615     if ((Dcctrl & BIT0) != 0) {
    616       //
    617       // Set the flag to indicate debug device is in configured state
    618       //
    619       Handle->Ready = TRUE;
    620       break;
    621     }
    622     MicroSecondDelay (XHC_POLL_DELAY);
    623     TimeOut--;
    624   } while (TimeOut != 0);
    625 }
    626 
    627 /**
    628   Initialize usb debug port hardware.
    629 
    630   @param  Handle           Debug port handle.
    631 
    632   @retval TRUE             The usb debug port hardware configuration is changed.
    633   @retval FALSE            The usb debug port hardware configuration is not changed.
    634 
    635 **/
    636 RETURN_STATUS
    637 EFIAPI
    638 InitializeUsbDebugHardware (
    639   IN USB3_DEBUG_PORT_HANDLE *Handle
    640   )
    641 {
    642   RETURN_STATUS                   Status;
    643   UINT8                           *Buffer;
    644   UINTN                           Index;
    645   UINT8                           TotalUsb3Port;
    646   EFI_PHYSICAL_ADDRESS            XhciOpRegister;
    647 
    648   XhciOpRegister = Handle->XhciOpRegister;
    649   TotalUsb3Port = MmioRead32 (((UINTN) Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;
    650 
    651   if (Handle->Initialized == USB3DBG_NOT_ENABLED) {
    652     //
    653     // If XHCI supports debug capability, hardware resource has been allocated,
    654     // but it has not been enabled, try to enable again.
    655     //
    656     goto Enable;
    657   }
    658 
    659   //
    660   // Initialize for PEI phase when AllocatePages can work.
    661   // Allocate data buffer with max packet size for data read and data poll.
    662   // Allocate data buffer for data write.
    663   //
    664   Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);
    665   if (Buffer == NULL) {
    666     //
    667     // AllocatePages can not still work now, return fail and do not initialize now.
    668     //
    669     return RETURN_NOT_READY;
    670   }
    671 
    672   //
    673   // Reset port to get debug device discovered
    674   //
    675   for (Index = 0; Index < TotalUsb3Port; Index++) {
    676     XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT4);
    677     MicroSecondDelay (10 * 1000);
    678   }
    679 
    680   //
    681   // Construct the buffer for read, poll and write.
    682   //
    683   Handle->UrbIn.Data  = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer;
    684   Handle->Data        = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
    685   Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;
    686 
    687   //
    688   // Initialize event ring
    689   //
    690   ZeroMem (&Handle->EventRing, sizeof (EVENT_RING));
    691   Status = CreateEventRing (Handle, &Handle->EventRing);
    692   ASSERT_EFI_ERROR (Status);
    693 
    694   //
    695   // Init IN and OUT endpoint context
    696   //
    697   Status = CreateDebugCapabilityContext (Handle);
    698   ASSERT_EFI_ERROR (Status);
    699 
    700   //
    701   // Init DCDDI1 and DCDDI2
    702   //
    703   XhcWriteDebugReg (
    704    Handle,
    705    XHC_DC_DCDDI1,
    706    (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
    707    );
    708 
    709   XhcWriteDebugReg (
    710    Handle,
    711    XHC_DC_DCDDI2,
    712    (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
    713    );
    714 
    715 Enable:
    716   if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {
    717     //
    718     // If the first time detection is failed, turn port power off and on in order to
    719     // reset port status this time, then try to check if debug device is ready again.
    720     //
    721     for (Index = 0; Index < TotalUsb3Port; Index++) {
    722       XhcClearR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
    723       MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
    724       XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
    725       MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
    726       Handle->ChangePortPower = TRUE;
    727     }
    728   }
    729 
    730   //
    731   // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
    732   //
    733   XhcSetDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
    734 
    735   XhcDetectDebugCapabilityReady (Handle);
    736 
    737   Status = RETURN_SUCCESS;
    738   if (!Handle->Ready) {
    739     Handle->Initialized = USB3DBG_NOT_ENABLED;
    740     Status = RETURN_NOT_READY;
    741   } else {
    742     Handle->Initialized = USB3DBG_ENABLED;
    743   }
    744 
    745   return Status;
    746 }
    747 
    748 /**
    749   Read data from debug device and save the data in buffer.
    750 
    751   Reads NumberOfBytes data bytes from a debug device into the buffer
    752   specified by Buffer. The number of bytes actually read is returned.
    753   If the return value is less than NumberOfBytes, then the rest operation failed.
    754   If NumberOfBytes is zero, then return 0.
    755 
    756   @param  Handle           Debug port handle.
    757   @param  Buffer           Pointer to the data buffer to store the data read from the debug device.
    758   @param  NumberOfBytes    Number of bytes which will be read.
    759   @param  Timeout          Timeout value for reading from debug device. It unit is Microsecond.
    760 
    761   @retval 0                Read data failed, no data is to be read.
    762   @retval >0               Actual number of bytes read from debug device.
    763 
    764 **/
    765 UINTN
    766 EFIAPI
    767 DebugPortReadBuffer (
    768   IN   DEBUG_PORT_HANDLE        Handle,
    769   IN   UINT8                    *Buffer,
    770   IN   UINTN                    NumberOfBytes,
    771   IN   UINTN                    Timeout
    772   )
    773 {
    774   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
    775   RETURN_STATUS             Status;
    776   UINT8                     Index;
    777   UINT8                     *Data;
    778 
    779   if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
    780     return 0;
    781   }
    782 
    783   //
    784   // If Handle is NULL, it means memory is ready for use.
    785   // Use global variable to store handle value.
    786   //
    787   if (Handle == NULL) {
    788     UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;
    789   } else {
    790     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
    791   }
    792 
    793   if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {
    794     return 0;
    795   }
    796 
    797   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
    798     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
    799     if (RETURN_ERROR(Status)) {
    800       return 0;
    801     }
    802   }
    803 
    804   Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;
    805 
    806   //
    807   // Read data from buffer
    808   //
    809   if (UsbDebugPortHandle->DataCount < 1) {
    810     return 0;
    811   } else {
    812     *Buffer = Data[0];
    813 
    814     for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
    815       if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
    816         return 0;
    817       }
    818       Data[Index] = Data[Index + 1];
    819     }
    820     UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
    821     return 1;
    822   }
    823 }
    824 
    825 /**
    826   Write data from buffer to debug device.
    827 
    828   Writes NumberOfBytes data bytes from Buffer to the debug device.
    829   The number of bytes actually written to the debug device is returned.
    830   If the return value is less than NumberOfBytes, then the write operation failed.
    831   If NumberOfBytes is zero, then return 0.
    832 
    833   @param  Handle           Debug port handle.
    834   @param  Buffer           Pointer to the data buffer to be written.
    835   @param  NumberOfBytes    Number of bytes to written to the debug device.
    836 
    837   @retval 0                NumberOfBytes is 0.
    838   @retval >0               The number of bytes written to the debug device.
    839                            If this value is less than NumberOfBytes, then the read operation failed.
    840 
    841 **/
    842 UINTN
    843 EFIAPI
    844 DebugPortWriteBuffer (
    845   IN   DEBUG_PORT_HANDLE    Handle,
    846   IN   UINT8                *Buffer,
    847   IN   UINTN                NumberOfBytes
    848   )
    849 {
    850   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
    851   RETURN_STATUS             Status;
    852   UINTN                     Sent;
    853   UINTN                     Total;
    854   EFI_PHYSICAL_ADDRESS      XhciMmioBase;
    855   UINTN                     Index;
    856 
    857   if (NumberOfBytes == 0 || Buffer == NULL) {
    858     return 0;
    859   }
    860 
    861   Sent  = 0;
    862   Total = 0;
    863 
    864   //
    865   // If Handle is NULL, it means memory is ready for use.
    866   // Use global variable to store handle value.
    867   //
    868   if (Handle == NULL) {
    869     UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;
    870   } else {
    871     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
    872   }
    873 
    874   if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {
    875     return 0;
    876   }
    877 
    878   //
    879   // MMIO base address is possible to clear, set it if it is cleared. (XhciMemorySpaceClose in PchUsbCommon.c)
    880   //
    881   XhciMmioBase = ProgramXhciBaseAddress ();
    882 
    883   UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);
    884 
    885   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
    886     Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
    887     if (RETURN_ERROR(Status)) {
    888       return 0;
    889     }
    890   }
    891 
    892   //
    893   // When host is trying to send data, write will be blocked.
    894   // Poll to see if there is any data sent by host at first.
    895   //
    896   DebugPortPollBuffer (Handle);
    897 
    898   Index = 0;
    899   while ((Total < NumberOfBytes)) {
    900     if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {
    901       Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;
    902     } else {
    903       Sent = (UINT8)(NumberOfBytes - Total);
    904     }
    905     Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);
    906     Total += Sent;
    907   }
    908 
    909   return Total;
    910 }
    911 
    912 /**
    913   Polls a debug device to see if there is any data waiting to be read.
    914 
    915   Polls a debug device to see if there is any data waiting to be read.
    916   If there is data waiting to be read from the debug device, then TRUE is returned.
    917   If there is no data waiting to be read from the debug device, then FALSE is returned.
    918 
    919   @param  Handle           Debug port handle.
    920 
    921   @retval TRUE             Data is waiting to be read from the debug device.
    922   @retval FALSE            There is no data waiting to be read from the serial device.
    923 
    924 **/
    925 BOOLEAN
    926 EFIAPI
    927 DebugPortPollBuffer (
    928   IN DEBUG_PORT_HANDLE      Handle
    929   )
    930 {
    931   USB3_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
    932   UINTN                     Length;
    933   RETURN_STATUS             Status;
    934   EFI_PHYSICAL_ADDRESS      XhciMmioBase;
    935 
    936   //
    937   // If Handle is NULL, it means memory is ready for use.
    938   // Use global variable to store handle value.
    939   //
    940   if (Handle == NULL) {
    941     UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;
    942   } else {
    943     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
    944   }
    945 
    946   if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {
    947     return 0;
    948   }
    949 
    950   XhciMmioBase = ProgramXhciBaseAddress ();
    951   UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);
    952 
    953   if (NeedReinitializeHardware(UsbDebugPortHandle)) {
    954     Status = InitializeUsbDebugHardware(UsbDebugPortHandle);
    955     if (RETURN_ERROR(Status)) {
    956       return FALSE;
    957     }
    958   }
    959 
    960   //
    961   // If the data buffer is not empty, then return TRUE directly.
    962   // Otherwise initialize a usb read transaction and read data to internal data buffer.
    963   //
    964   if (UsbDebugPortHandle->DataCount != 0) {
    965     return TRUE;
    966   }
    967 
    968   //
    969   // Read data as much as we can
    970   //
    971   Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
    972   XhcDataTransfer (Handle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);
    973 
    974   if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
    975     return FALSE;
    976   }
    977 
    978   if (Length == 0) {
    979     return FALSE;
    980   }
    981 
    982   //
    983   // Store data into internal buffer for use later
    984   //
    985   UsbDebugPortHandle->DataCount = (UINT8) Length;
    986   return TRUE;
    987 }
    988 
    989 /**
    990   Initialize the debug port.
    991 
    992   If Function is not NULL, Debug Communication Library will call this function
    993   by passing in the Context to be the first parameter. If needed, Debug Communication
    994   Library will create one debug port handle to be the second argument passing in
    995   calling the Function, otherwise it will pass NULL to be the second argument of
    996   Function.
    997 
    998   If Function is NULL, and Context is not NULL, the Debug Communication Library could
    999     a) Return the same handle as passed in (as Context parameter).
   1000     b) Ignore the input Context parameter and create new handle to be returned.
   1001 
   1002   If parameter Function is NULL and Context is NULL, Debug Communication Library could
   1003   created a new handle if needed and return it, otherwise it will return NULL.
   1004 
   1005   @param[in] Context      Context needed by callback function; it was optional.
   1006   @param[in] Function     Continue function called by Debug Communication library;
   1007                           it was optional.
   1008 
   1009   @return  The debug port handle created by Debug Communication Library if Function
   1010            is not NULL.
   1011 
   1012 **/
   1013 DEBUG_PORT_HANDLE
   1014 EFIAPI
   1015 DebugPortInitialize (
   1016   IN VOID                 *Context,
   1017   IN DEBUG_PORT_CONTINUE  Function
   1018   )
   1019 {
   1020   RETURN_STATUS             Status;
   1021   USB3_DEBUG_PORT_HANDLE    Handle;
   1022   USB3_DEBUG_PORT_HANDLE    *UsbDebugPortHandle;
   1023 
   1024   //
   1025   // Validate the PCD PcdDebugPortHandleBufferSize value
   1026   //
   1027   ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));
   1028 
   1029   if (Function == NULL && Context != NULL) {
   1030     UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Context;
   1031   } else {
   1032     ZeroMem(&Handle, sizeof (USB3_DEBUG_PORT_HANDLE));
   1033     UsbDebugPortHandle = &Handle;
   1034   }
   1035 
   1036   if (Function == NULL && Context != NULL) {
   1037     return (DEBUG_PORT_HANDLE *) Context;
   1038   }
   1039 
   1040   //
   1041   // Read 64-bit MMIO base address
   1042   //
   1043   UsbDebugPortHandle->XhciMmioBase = ProgramXhciBaseAddress ();
   1044 
   1045   Status = CalculateUsbDebugPortMmioBase (UsbDebugPortHandle);
   1046   if (RETURN_ERROR (Status)) {
   1047     goto Exit;
   1048   }
   1049 
   1050   if (NeedReinitializeHardware(&Handle)) {
   1051     Status = InitializeUsbDebugHardware (&Handle);
   1052     if (RETURN_ERROR(Status)) {
   1053       goto Exit;
   1054     }
   1055   }
   1056 
   1057 Exit:
   1058 
   1059   if (Function != NULL) {
   1060     Function (Context, &Handle);
   1061   } else {
   1062     CopyMem(&mDebugCommunicationLibUsb3DebugPortHandle, &Handle, sizeof (USB3_DEBUG_PORT_HANDLE));
   1063   }
   1064 
   1065   return (DEBUG_PORT_HANDLE)(UINTN)&mDebugCommunicationLibUsb3DebugPortHandle;
   1066 }
   1067