1 /** @file
2   Usb3 Debug Port initialization
3 
4   Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <Base.h>
10 
11 #include <PiPei.h>
12 #include <Library/SerialPortLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/PciLib.h>
15 #include <Library/PcdLib.h>
16 #include <Library/TimerLib.h>
17 #include <Library/HobLib.h>
18 #include <Library/Usb3DebugPortParamLib.h>
19 #include "Usb3DebugPortLibInternal.h"
20 
21 UINT16   mString0Desc[] = {
22   //  String Descriptor Type + Length
23   ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,
24   0x0409
25 };
26 
27 UINT16   mManufacturerStrDesc[] = {
28   //  String Descriptor Type + Length
29   ( USB_DESC_TYPE_STRING << 8 ) + MANU_DESC_LEN,
30   'I', 'n', 't', 'e', 'l'
31 };
32 
33 //USB 3.0 Debug Cable
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 XHC_DC_CONTEXT   DebugCapabilityContextTemplate = {
47   {
48     0,
49     0,
50     0,
51     0,
52     STRING0_DESC_LEN,
53     MANU_DESC_LEN,
54     PRODUCT_DESC_LEN,
55     SERIAL_DESC_LEN,
56     0,
57     0,
58     0,
59     0
60   },
61   {
62     0,  // EPState
63     0,  // RsvdZ1
64     0,  // Mult
65     0,  // MaxPStreams
66     0,  // LSA
67     0,  // Interval
68     0,  // RsvdZ2
69     0,  // RsvdZ3
70     3,  // CERR
71     ED_BULK_OUT,  // EPType
72     0,  // RsvdZ4
73     0,  // HID
74     0,  // MaxBurstSize
75     1024, // MaxPacketSize
76     0,    // PtrLo
77     0,    // PtrHi
78     0x1000, // AverageTRBLength
79     0,     // MaxESITPayload
80     0,
81     0,
82     0,
83     0,
84     0,
85     0,
86     0,
87     0,
88     0,
89     0,
90     0
91   },
92   {
93     0,
94     0,
95     0,
96     0,
97     0,
98     0,
99     0,
100     0,
101     3,    //CERR
102     ED_BULK_IN,
103     0,
104     0,
105     0,
106     1024, //MaxPacketSize
107     0,
108     0,
109     0x1000,
110     0,
111     0,
112     0,
113     0,
114     0,
115     0,
116     0,
117     0,
118     0,
119     0,
120     0,
121     0
122   }
123 };
124 
125 /**
126   Return command register value in XHCI controller.
127 
128 **/
129 UINT16
GetXhciPciCommand(VOID)130 GetXhciPciCommand (
131   VOID
132   )
133 {
134   UINT8                                  Bus;
135   UINT8                                  Device;
136   UINT8                                  Function;
137   UINT16                                 Command;
138   USB3_DEBUG_PORT_CONTROLLER             UsbDebugPort;
139 
140   UsbDebugPort.Controller = GetUsb3DebugPortController();
141 
142   Bus = UsbDebugPort.PciAddress.Bus;
143   Device = UsbDebugPort.PciAddress.Device;
144   Function = UsbDebugPort.PciAddress.Function;
145   Command = PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
146   return Command;
147 }
148 
149 /**
150   Discover the USB3 debug device.
151 
152   @param[in] Instance           Pointer to USB3 debug port object instance.
153 
154   @retval RETURN_SUCCESS        The USB3 debug device was found.
155   @retval RETURN_DEVICE_ERROR   The USB3 debug device was not found.
156 
157 **/
158 RETURN_STATUS
DiscoverUsb3DebugPort(IN USB3_DEBUG_PORT_INSTANCE * Instance)159 DiscoverUsb3DebugPort(
160   IN USB3_DEBUG_PORT_INSTANCE   *Instance
161   )
162 {
163   UINT8                           Bus;
164   UINT8                           Device;
165   UINT8                           Function;
166   UINT16                          Command;
167   EFI_PHYSICAL_ADDRESS            UsbBase;
168   USB3_DEBUG_PORT_CONTROLLER      UsbDebugPort;
169   EFI_PHYSICAL_ADDRESS            CapabilityPointer;
170   UINT32                          Capability;
171   BOOLEAN                         Flag;
172   UINT8                           CapLength;
173 
174   UsbDebugPort.Controller = GetUsb3DebugPortController();
175   Bus = UsbDebugPort.PciAddress.Bus;
176   Device = UsbDebugPort.PciAddress.Device;
177   Function = UsbDebugPort.PciAddress.Function;
178   if ((PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2)) != PCI_CLASS_SERIAL) ||
179       (PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1)) != PCI_CLASS_SERIAL_USB) ||
180       (PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET)) != 0x30)) {
181     //
182     // The device is not XHCI controller
183     //
184     return RETURN_NOT_FOUND;
185   }
186 
187   //
188   // USBBASE is at 10-13h, i.e. the first BAR, clear the low bits which is not part of base address
189   //
190   UsbBase = GetXhciBaseAddress ();
191 
192   //
193   // Set XHCI MMIO base address if necessary
194   //
195   if ((UsbBase == 0) || (UsbBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
196     UsbBase  = PcdGet32 (PcdXhciDefaultBaseAddress);
197     PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)UsbBase);
198     PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0x0);
199     UsbBase = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET)) & XHCI_BASE_ADDRESS_32_BIT_MASK;
200     if (UsbBase == 0 || UsbBase == XHCI_BASE_ADDRESS_32_BIT_MASK) {
201       return RETURN_DEVICE_ERROR;
202     }
203   }
204 
205   //
206   //  Set MSE and BME bit - enable the address space
207   //
208   Command = PciRead16 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
209   if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
210     PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
211     PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
212   }
213 
214   CapLength = MmioRead8 ((UINTN) UsbBase);
215 
216   //
217   // Get capability pointer from HCCPARAMS at offset 0x10
218   //
219   CapabilityPointer = UsbBase + (MmioRead32 ((UINTN)(UsbBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
220 
221   //
222   // Search XHCI debug capability
223   //
224   Flag = FALSE;
225   Capability = MmioRead32 ((UINTN)CapabilityPointer);
226   while (TRUE) {
227     if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
228       Flag = TRUE;
229       break;
230     }
231     if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
232       //
233       // Reach the end of capability list, quit
234       //
235       break;
236     }
237     CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
238     Capability = MmioRead32 ((UINTN)CapabilityPointer);
239   }
240 
241   Instance->Signature             = USB3_DEBUG_PORT_INSTANCE_SIGNATURE;
242 
243   if (Flag) {
244     Instance->DebugSupport          = TRUE;
245     Instance->DebugCapabilityBase   = CapabilityPointer;
246     Instance->DebugCapabilityOffset = CapabilityPointer - UsbBase;
247 
248     Instance->XhciOpRegister        = UsbBase + CapLength;
249     Instance->XhcMmioBase           = UsbBase;
250 
251     Instance->PciBusNumber          = Bus;
252     Instance->PciDeviceNumber       = Device;
253     Instance->PciFunctionNumber     = Function;
254   }
255 
256   //
257   // Restore Command Register
258   //
259   PciWrite16(PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
260 
261   return RETURN_SUCCESS;
262 }
263 
264 /**
265   Create XHCI event ring.
266 
267   @param  Xhc                 The XHCI Instance.
268   @param  EventRing           The created event ring.
269 
270 **/
271 EFI_STATUS
CreateEventRing(IN USB3_DEBUG_PORT_INSTANCE * Xhc,OUT EVENT_RING * EventRing)272 CreateEventRing (
273   IN  USB3_DEBUG_PORT_INSTANCE   *Xhc,
274   OUT EVENT_RING                 *EventRing
275   )
276 {
277   VOID                        *Buf;
278   EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;
279 
280   ASSERT (EventRing != NULL);
281 
282   //
283   // Allocate Event Ring
284   //
285   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
286   ASSERT (Buf != NULL);
287   ASSERT (((UINTN) Buf & 0x3F) == 0);
288   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
289 
290   EventRing->EventRingSeg0    = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
291   EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;
292   EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
293   EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
294 
295   //
296   // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
297   // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
298   //
299   EventRing->EventRingCCS = 1;
300 
301   //
302   // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
303   //
304   Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
305   ASSERT (Buf != NULL);
306   ASSERT (((UINTN) Buf & 0x3F) == 0);
307   ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
308 
309   ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
310   EventRing->ERSTBase   = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;
311 
312   //
313   // Fill Event Segment address
314   //
315   ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingSeg0);
316   ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
317   ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
318 
319   //
320   // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
321   //
322   XhcWriteDebugReg (
323     Xhc,
324     XHC_DC_DCERDP,
325     XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
326     );
327 
328   XhcWriteDebugReg (
329     Xhc,
330     XHC_DC_DCERDP + 4,
331     XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
332     );
333 
334   //
335   // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
336   //
337   XhcWriteDebugReg (
338     Xhc,
339     XHC_DC_DCERSTBA,
340     XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
341     );
342 
343   XhcWriteDebugReg (
344     Xhc,
345     XHC_DC_DCERSTBA + 4,
346     XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
347     );
348 
349   //
350   // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
351   //
352   XhcWriteDebugReg (
353     Xhc,
354     XHC_DC_DCERSTSZ,
355     ERST_NUMBER
356     );
357   return EFI_SUCCESS;
358 }
359 
360 /**
361   Create XHCI transfer ring.
362 
363   @param  Xhc               The XHCI Instance.
364   @param  TrbNum            The number of TRB in the ring.
365   @param  TransferRing      The created transfer ring.
366 
367 **/
368 VOID
CreateTransferRing(IN USB3_DEBUG_PORT_INSTANCE * Xhc,IN UINT32 TrbNum,OUT TRANSFER_RING * TransferRing)369 CreateTransferRing (
370   IN  USB3_DEBUG_PORT_INSTANCE    *Xhc,
371   IN  UINT32                      TrbNum,
372   OUT TRANSFER_RING               *TransferRing
373   )
374 {
375   VOID                  *Buf;
376   LINK_TRB              *EndTrb;
377 
378   Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
379   ASSERT (Buf != NULL);
380   ASSERT (((UINTN) Buf & 0xF) == 0);
381   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
382 
383   TransferRing->RingSeg0     = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
384   TransferRing->TrbNumber    = TrbNum;
385   TransferRing->RingEnqueue  = TransferRing->RingSeg0;
386   TransferRing->RingDequeue  = TransferRing->RingSeg0;
387   TransferRing->RingPCS      = 1;
388   //
389   // 4.9.2 Transfer Ring Management
390   // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
391   // point to the first TRB in the ring.
392   //
393   EndTrb        = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
394   EndTrb->Type  = TRB_TYPE_LINK;
395   EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
396   EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
397   //
398   // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
399   //
400   EndTrb->TC    = 1;
401   //
402   // Set Cycle bit as other TRB PCS init value
403   //
404   EndTrb->CycleBit = 0;
405 }
406 
407 /**
408   Create debug capability context for XHC debug device.
409 
410   @param  Xhc          The XHCI Instance.
411 
412   @retval EFI_SUCCESS  The bit successfully changed by host controller.
413   @retval EFI_TIMEOUT  The time out occurred.
414 
415 **/
416 EFI_STATUS
CreateDebugCapabilityContext(IN USB3_DEBUG_PORT_INSTANCE * Xhc)417 CreateDebugCapabilityContext (
418   IN  USB3_DEBUG_PORT_INSTANCE   *Xhc
419   )
420 {
421   VOID                        *Buf;
422   XHC_DC_CONTEXT              *DebugCapabilityContext;
423   UINT8                       *String0Desc;
424   UINT8                       *ManufacturerStrDesc;
425   UINT8                       *ProductStrDesc;
426   UINT8                       *SerialNumberStrDesc;
427 
428   //
429   // Allocate debug device context
430   //
431   Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
432   ASSERT (Buf != NULL);
433   ASSERT (((UINTN) Buf & 0xF) == 0);
434   ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
435 
436   DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;
437   Xhc->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;
438 
439   CopyMem (DebugCapabilityContext, &DebugCapabilityContextTemplate, sizeof (XHC_DC_CONTEXT));
440 
441   //
442   // Update string descriptor address
443   //
444   String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
445   ASSERT (String0Desc != NULL);
446   ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
447   CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
448   DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
449 
450   ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
451   CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
452   DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
453 
454   ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
455   CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
456   DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
457 
458   SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
459   CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
460   DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
461 
462   //
463   // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
464   //
465   ZeroMem (&Xhc->TransferRingIn, sizeof (TRANSFER_RING));
466   CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, &Xhc->TransferRingIn);
467 
468   //
469   // Can not set BIT0, otherwise there is no transfer ring detected.
470   //
471   DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Xhc->TransferRingIn.RingSeg0) | BIT0;
472   DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Xhc->TransferRingIn.RingSeg0);
473 
474   //
475   // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
476   //
477   ZeroMem (&Xhc->TransferRingOut, sizeof (TRANSFER_RING));
478   CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, &Xhc->TransferRingOut);
479 
480   //
481   // Can not set BIT0, otherwise there is no transfer ring detected.
482   //
483   DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Xhc->TransferRingOut.RingSeg0) | BIT0;
484   DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Xhc->TransferRingOut.RingSeg0);
485 
486   //
487   // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
488   //
489   XhcWriteDebugReg (
490     Xhc,
491     XHC_DC_DCCP,
492     XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)
493     );
494   XhcWriteDebugReg (
495     Xhc,
496     XHC_DC_DCCP + 4,
497     XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)
498     );
499   return EFI_SUCCESS;
500 }
501 
502 /**
503   Initialize the USB3 debug Device hardware.
504 
505   @param[in] Instance       Pointer to USB3 debug port object instance.
506 
507   @retval RETURN_SUCCESS    The USB3 debug device was initialized successfully.
508   @retval !RETURN_SUCCESS   Error.
509 
510 **/
511 RETURN_STATUS
InitializeUsb3DebugPort(IN USB3_DEBUG_PORT_INSTANCE * Instance)512 InitializeUsb3DebugPort (
513   IN USB3_DEBUG_PORT_INSTANCE   *Instance
514   )
515 {
516   RETURN_STATUS                   Status;
517   UINT64                          XhciOpRegister;
518   volatile UINT32                 Dcctrl;
519   UINT8                           Bus;
520   UINT8                           Device;
521   UINT8                           Function;
522   UINT16                          Command;
523   EFI_BOOT_MODE                   BootMode;
524   UINT64                          TimeOut;
525   CHAR8                           *TestString;
526   UINTN                           Length;
527   UINT32                          TransferResult;
528 
529   Bus      = Instance->PciBusNumber;
530   Device   = Instance->PciDeviceNumber;
531   Function = Instance->PciFunctionNumber;
532 
533   Command = GetXhciPciCommand ();
534 
535   //
536   // Save and set Command Register
537   //
538   if (((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((Command & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
539     PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
540     PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
541   }
542 
543   //
544   // Clear DCE bit and LSE bit in DCCTRL
545   //
546   if ((XhcReadDebugReg (Instance, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {
547     XhcClearDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
548   }
549 
550   XhciOpRegister = Instance->XhciOpRegister;
551 
552   //
553   // Get current Boot Mode
554   //
555   BootMode = GetBootModeHob ();
556 
557   if (BootMode != BOOT_ON_S3_RESUME) {
558     if (!XhcIsBitSet((UINTN)(XhciOpRegister + XHC_USBSTS_OFFSET), XHC_USBSTS_HALT)) {
559       XhcClrR32Bit((UINTN) XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
560       while (!XhcIsBitSet((UINTN)(XhciOpRegister + XHC_USBSTS_OFFSET), XHC_USBSTS_HALT)) {
561         MicroSecondDelay (10);
562       }
563     }
564 
565     //
566     // Reset host controller
567     //
568     XhcSetR32Bit((UINTN)XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
569 
570     //
571     // Ensure that the host controller is reset (RESET bit must be cleared after reset)
572     //
573     while (XhcIsBitSet((UINTN)XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RESET)) {
574       MicroSecondDelay (10);
575     }
576   }
577 
578   //
579   // Initialize event ring
580   //
581   ZeroMem (&Instance->EventRing, sizeof (EVENT_RING));
582   Status = CreateEventRing (Instance, &Instance->EventRing);
583   ASSERT_EFI_ERROR (Status);
584 
585   //
586   // Init IN and OUT endpoint context
587   //
588   Status = CreateDebugCapabilityContext (Instance);
589   ASSERT_EFI_ERROR (Status);
590 
591   //
592   // Init data buffer used to transfer
593   //
594   Instance->Urb.Data = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAlignBuffer (XHC_DEBUG_PORT_DATA_LENGTH);
595 
596   //
597   // Init DCDDI1 and DCDDI2
598   //
599   XhcWriteDebugReg (
600    Instance,
601    XHC_DC_DCDDI1,
602    (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
603    );
604 
605   XhcWriteDebugReg (
606    Instance,
607    XHC_DC_DCDDI2,
608    (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
609    );
610 
611   //
612   // Set DCE bit and LSE bit to "1" in DCCTRL
613   //
614   XhcSetDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
615 
616   TimeOut = DivU64x32 (PcdGet64 (PcdXhciHostWaitTimeout), XHC_POLL_DELAY) + 1;
617   while (TimeOut != 0) {
618     //
619     // Check if debug device is in configured state
620     //
621     Dcctrl = XhcReadDebugReg (Instance, XHC_DC_DCCTRL);
622     if ((Dcctrl & BIT0) != 0) {
623       //
624       // Set the flag to indicate debug device is ready
625       //
626       Instance->Ready = TRUE;
627       break;
628     }
629     MicroSecondDelay (XHC_POLL_DELAY);
630     TimeOut--;
631   }
632 
633   if (!Instance->Ready) {
634     XhcClearDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
635   } else {
636     TestString = "Usb 3.0 Debug Message Start\n";
637     Length = AsciiStrLen (TestString);
638     XhcDataTransfer (
639       Instance,
640       EfiUsbDataOut,
641       TestString,
642       &Length,
643       0,
644       &TransferResult
645       );
646   }
647 
648   //
649   // Restore Command Register
650   //
651   PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
652 
653   return EFI_SUCCESS;
654 }
655 
656 /**
657   Update XHC hardware address when MMIO base is changed.
658 
659   @param  Instance          The XHCI Instance.
660   @param  XhcMmioBase       XHCI MMIO base address.
661 
662 **/
663 VOID
FixUsb3InstanceResource(IN OUT USB3_DEBUG_PORT_INSTANCE * Instance,IN EFI_PHYSICAL_ADDRESS XhcMmioBase)664 FixUsb3InstanceResource (
665   IN OUT USB3_DEBUG_PORT_INSTANCE           *Instance,
666   IN EFI_PHYSICAL_ADDRESS                   XhcMmioBase
667   )
668 {
669   if ((Instance == NULL) || (Instance->XhcMmioBase == XhcMmioBase)) {
670     return;
671   }
672 
673   //
674   // Need fix Instance data according to PCI resource
675   //
676   Instance->XhcMmioBase         = XhcMmioBase;
677   Instance->DebugCapabilityBase = XhcMmioBase + Instance->DebugCapabilityOffset;
678   Instance->XhciOpRegister      = XhcMmioBase + MmioRead8 ((UINTN)XhcMmioBase);
679 }
680 
681 /**
682   Save USB3 instance address.
683 
684   @param[in] Instance   The XHCI Instance.
685 
686 **/
687 VOID
SaveUsb3InstanceAddress(IN USB3_DEBUG_PORT_INSTANCE * Instance)688 SaveUsb3InstanceAddress (
689   IN USB3_DEBUG_PORT_INSTANCE   *Instance
690   )
691 {
692   UINT16                        Command;
693   USB3_DEBUG_PORT_CONTROLLER    UsbDebugPort;
694   UINT8                         Bus;
695   UINT8                         Device;
696   UINT8                         Function;
697 
698   Command = GetXhciPciCommand ();
699   UsbDebugPort.Controller = GetUsb3DebugPortController();
700   Bus      = UsbDebugPort.PciAddress.Bus;
701   Device   = UsbDebugPort.PciAddress.Device;
702   Function = UsbDebugPort.PciAddress.Function;
703 
704   //
705   // Set Command Register
706   //
707   if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
708     PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
709     PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
710   }
711 
712   //
713   // After debug device is finished to enumerate, use DCDDI2 register to store instance address
714   //
715   XhcWriteDebugReg (
716    Instance,
717    XHC_DC_DCDDI2,
718    (UINT32)(UINTN)Instance
719    );
720 
721   //
722   // Restore Command Register
723   //
724   PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
725 }
726 
727