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