2 Debug Port Library implementation based on usb3 debug port.
4 Copyright (c) 2014 - 2018, 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.
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.
15 #include "DebugCommunicationLibUsb3Internal.h"
17 UINT16 mString0Desc
[] = {
18 // String Descriptor Type + Length
19 ( USB_DESC_TYPE_STRING
<< 8 ) + STRING0_DESC_LEN
,
23 UINT16 mManufacturerStrDesc
[] = {
24 // String Descriptor Type + Length
25 ( USB_DESC_TYPE_STRING
<< 8 ) + MANU_DESC_LEN
,
26 'I', 'n', 't', 'e', 'l'
29 UINT16 mProductStrDesc
[] = {
30 // String Descriptor Type + Length
31 ( USB_DESC_TYPE_STRING
<< 8 ) + PRODUCT_DESC_LEN
,
32 'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'
35 UINT16 mSerialNumberStrDesc
[] = {
36 // String Descriptor Type + Length
37 ( USB_DESC_TYPE_STRING
<< 8 ) + SERIAL_DESC_LEN
,
42 Sets bits as per the enabled bit positions in the mask.
44 @param[in, out] Register UINTN register
45 @param[in] BitMask 32-bit mask
49 IN OUT UINTN Register
,
55 RegisterValue
= MmioRead32 (Register
);
56 RegisterValue
|= (UINT32
)(BitMask
);
57 MmioWrite32 (Register
, RegisterValue
);
61 Clears bits as per the enabled bit positions in the mask.
63 @param[in, out] Register UINTN register
64 @param[in] BitMask 32-bit mask
68 IN OUT UINTN Register
,
74 RegisterValue
= MmioRead32 (Register
);
75 RegisterValue
&= ~BitMask
;
76 MmioWrite32 (Register
, RegisterValue
);
80 Write the data to the XHCI debug register.
82 @param Handle Debug port handle.
83 @param Offset The offset of the debug register.
84 @param Data The data to write.
89 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
94 EFI_PHYSICAL_ADDRESS DebugCapabilityBase
;
96 DebugCapabilityBase
= Handle
->DebugCapabilityBase
;
97 MmioWrite32 ((UINTN
)(DebugCapabilityBase
+ Offset
), Data
);
103 Read XHCI debug register.
105 @param Handle Debug port handle.
106 @param Offset The offset of the runtime register.
108 @return The register content read
113 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
118 EFI_PHYSICAL_ADDRESS DebugCapabilityBase
;
120 DebugCapabilityBase
= Handle
->DebugCapabilityBase
;
121 Data
= MmioRead32 ((UINTN
)(DebugCapabilityBase
+ Offset
));
127 Set one bit of the debug register while keeping other bits.
129 @param Handle Debug port handle.
130 @param Offset The offset of the debug register.
131 @param Bit The bit mask of the register to set.
136 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
143 Data
= XhcReadDebugReg (Handle
, Offset
);
145 XhcWriteDebugReg (Handle
, Offset
, Data
);
149 Clear one bit of the debug register while keeping other bits.
151 @param Handle Debug port handle.
152 @param Offset The offset of the debug register.
153 @param Bit The bit mask of the register to clear.
157 XhcClearDebugRegBit (
158 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
165 Data
= XhcReadDebugReg (Handle
, Offset
);
167 XhcWriteDebugReg (Handle
, Offset
, Data
);
171 Program and eanble XHCI MMIO base address.
173 @return XHCI MMIO base address.
177 ProgramXhciBaseAddress (
184 EFI_PHYSICAL_ADDRESS XhciMmioBase
;
186 Low
= PciRead32 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
);
187 High
= PciRead32 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ 4);
188 XhciMmioBase
= (EFI_PHYSICAL_ADDRESS
) (LShiftU64 ((UINT64
) High
, 32) | Low
);
189 XhciMmioBase
&= XHCI_BASE_ADDRESS_64_BIT_MASK
;
191 if ((XhciMmioBase
== 0) || (XhciMmioBase
== XHCI_BASE_ADDRESS_64_BIT_MASK
)) {
192 XhciMmioBase
= PcdGet64(PcdUsbXhciMemorySpaceBase
);
193 PciWrite32(PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
, XhciMmioBase
& 0xFFFFFFFF);
194 PciWrite32(PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ 4, (RShiftU64 (XhciMmioBase
, 32) & 0xFFFFFFFF));
197 PciCmd
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_COMMAND_OFFSET
);
198 if (((PciCmd
& EFI_PCI_COMMAND_MEMORY_SPACE
) == 0) || ((PciCmd
& EFI_PCI_COMMAND_BUS_MASTER
) == 0)) {
199 PciCmd
|= EFI_PCI_COMMAND_MEMORY_SPACE
| EFI_PCI_COMMAND_BUS_MASTER
;
200 PciWrite16(PcdGet32(PcdUsbXhciPciAddress
) + PCI_COMMAND_OFFSET
, PciCmd
);
207 Update XHC MMIO base address when MMIO base address is changed.
209 @param Handle Debug port handle.
210 @param XhciMmioBase XHCI MMIO base address.
215 IN OUT USB3_DEBUG_PORT_HANDLE
*Handle
,
216 IN EFI_PHYSICAL_ADDRESS XhciMmioBase
219 if (Handle
== NULL
) {
224 // Need fix Handle data according to new XHCI MMIO base address.
226 Handle
->XhciMmioBase
= XhciMmioBase
;
227 Handle
->DebugCapabilityBase
= XhciMmioBase
+ Handle
->DebugCapabilityOffset
;
228 Handle
->XhciOpRegister
= XhciMmioBase
+ MmioRead8 ((UINTN
)XhciMmioBase
);
232 Calculate the usb debug port bar address.
234 @param Handle Debug port handle.
236 @retval RETURN_UNSUPPORTED The usb host controller does not support usb debug port capability.
237 @retval RETURN_SUCCESS Get bar and offset successfully.
242 CalculateUsbDebugPortMmioBase (
243 USB3_DEBUG_PORT_HANDLE
*Handle
253 EFI_PHYSICAL_ADDRESS CapabilityPointer
;
256 if (Handle
->Initialized
!= USB3DBG_UNINITIALIZED
) {
257 if (Handle
->Initialized
== USB3DBG_NO_DBG_CAB
) {
258 return RETURN_UNSUPPORTED
;
260 return RETURN_SUCCESS
;
264 VendorId
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_VENDOR_ID_OFFSET
);
265 DeviceId
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_DEVICE_ID_OFFSET
);
267 if ((VendorId
== 0xFFFF) || (DeviceId
== 0xFFFF)) {
271 ProgInterface
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
);
272 SubClassCode
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 1);
273 BaseCode
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 2);
275 if ((ProgInterface
!= PCI_IF_XHCI
) || (SubClassCode
!= PCI_CLASS_SERIAL_USB
) || (BaseCode
!= PCI_CLASS_SERIAL
)) {
279 CapLength
= MmioRead8 ((UINTN
) Handle
->XhciMmioBase
);
282 // Get capability pointer from HCCPARAMS at offset 0x10
284 CapabilityPointer
= Handle
->XhciMmioBase
+ (MmioRead32 ((UINTN
)(Handle
->XhciMmioBase
+ XHC_HCCPARAMS_OFFSET
)) >> 16) * 4;
287 // Search XHCI debug capability
290 Capability
= MmioRead32 ((UINTN
)CapabilityPointer
);
292 if ((Capability
& XHC_CAPABILITY_ID_MASK
) == PCI_CAPABILITY_ID_DEBUG_PORT
) {
296 if ((((Capability
& XHC_NEXT_CAPABILITY_MASK
) >> 8) & XHC_CAPABILITY_ID_MASK
) == 0) {
298 // Reach the end of capability list, quit
302 CapabilityPointer
+= ((Capability
& XHC_NEXT_CAPABILITY_MASK
) >> 8) * 4;
303 Capability
= MmioRead32 ((UINTN
)CapabilityPointer
);
311 // USB3 debug capability is supported.
313 Handle
->DebugCapabilityBase
= CapabilityPointer
;
314 Handle
->DebugCapabilityOffset
= CapabilityPointer
- Handle
->XhciMmioBase
;
315 Handle
->XhciOpRegister
= Handle
->XhciMmioBase
+ CapLength
;
316 Handle
->DebugSupport
= TRUE
;
317 Handle
->Initialized
= USB3DBG_DBG_CAB
;
318 return RETURN_SUCCESS
;
321 Handle
->Initialized
= USB3DBG_NO_DBG_CAB
;
322 return RETURN_UNSUPPORTED
;
326 Check if it needs to re-initialize usb debug port hardware.
328 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
329 whether the usb debug port hardware configuration is changed. Such case can be triggered by
330 Pci bus resource allocation and so on.
332 @param Handle Debug port handle.
334 @retval TRUE The usb debug port hardware configuration is changed.
335 @retval FALSE The usb debug port hardware configuration is not changed.
340 NeedReinitializeHardware(
341 IN USB3_DEBUG_PORT_HANDLE
*Handle
345 volatile UINT32 Dcctrl
;
350 // If DCE bit, it means USB3 debug is not enabled.
352 Dcctrl
= XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
);
353 if ((Dcctrl
& BIT0
) == 0) {
355 } else if (!Handle
->Ready
) {
356 Handle
->Ready
= TRUE
;
357 Handle
->Initialized
= USB3DBG_ENABLED
;
364 Create XHCI event ring.
366 @param Handle Debug port handle.
367 @param EventRing The created event ring.
372 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
373 OUT EVENT_RING
*EventRing
377 EVENT_RING_SEG_TABLE_ENTRY
*ERSTBase
;
379 ASSERT (EventRing
!= NULL
);
382 // Allocate Event Ring
384 Buf
= AllocateAlignBuffer (sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
);
385 ASSERT (Buf
!= NULL
);
386 ASSERT (((UINTN
) Buf
& 0x3F) == 0);
387 ZeroMem (Buf
, sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
);
389 EventRing
->EventRingSeg0
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buf
;
390 EventRing
->TrbNumber
= EVENT_RING_TRB_NUMBER
;
391 EventRing
->EventRingDequeue
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) EventRing
->EventRingSeg0
;
392 EventRing
->EventRingEnqueue
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) EventRing
->EventRingSeg0
;
395 // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
396 // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
398 EventRing
->EventRingCCS
= 1;
401 // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
403 Buf
= AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
);
404 ASSERT (Buf
!= NULL
);
405 ASSERT (((UINTN
) Buf
& 0x3F) == 0);
406 ZeroMem (Buf
, sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
);
408 ERSTBase
= (EVENT_RING_SEG_TABLE_ENTRY
*) Buf
;
409 EventRing
->ERSTBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) ERSTBase
;
412 // Fill Event Segment address
414 ERSTBase
->PtrLo
= XHC_LOW_32BIT (EventRing
->EventRingSeg0
);
415 ERSTBase
->PtrHi
= XHC_HIGH_32BIT (EventRing
->EventRingSeg0
);
416 ERSTBase
->RingTrbSize
= EVENT_RING_TRB_NUMBER
;
419 // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
424 XHC_LOW_32BIT((UINT64
)(UINTN
)EventRing
->EventRingDequeue
)
430 XHC_HIGH_32BIT((UINT64
)(UINTN
)EventRing
->EventRingDequeue
)
434 // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
439 XHC_LOW_32BIT((UINT64
)(UINTN
)ERSTBase
)
445 XHC_HIGH_32BIT((UINT64
)(UINTN
)ERSTBase
)
449 // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
460 Create XHCI transfer ring.
462 @param Handle Debug port handle.
463 @param TrbNum The number of TRB in the ring.
464 @param TransferRing The created transfer ring.
469 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
471 OUT TRANSFER_RING
*TransferRing
477 Buf
= AllocateAlignBuffer (sizeof (TRB_TEMPLATE
) * TrbNum
);
478 ASSERT (Buf
!= NULL
);
479 ASSERT (((UINTN
) Buf
& 0xF) == 0);
480 ZeroMem (Buf
, sizeof (TRB_TEMPLATE
) * TrbNum
);
482 TransferRing
->RingSeg0
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buf
;
483 TransferRing
->TrbNumber
= TrbNum
;
484 TransferRing
->RingEnqueue
= TransferRing
->RingSeg0
;
485 TransferRing
->RingDequeue
= TransferRing
->RingSeg0
;
486 TransferRing
->RingPCS
= 1;
488 // 4.9.2 Transfer Ring Management
489 // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
490 // point to the first TRB in the ring.
492 EndTrb
= (LINK_TRB
*) ((UINTN
)Buf
+ sizeof (TRB_TEMPLATE
) * (TrbNum
- 1));
493 EndTrb
->Type
= TRB_TYPE_LINK
;
494 EndTrb
->PtrLo
= XHC_LOW_32BIT (Buf
);
495 EndTrb
->PtrHi
= XHC_HIGH_32BIT (Buf
);
497 // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
501 // Set Cycle bit as other TRB PCS init value
503 EndTrb
->CycleBit
= 0;
507 Create debug capability context for XHC debug device.
509 @param Handle Debug port handle.
511 @retval EFI_SUCCESS The bit successfully changed by host controller.
512 @retval EFI_TIMEOUT The time out occurred.
516 CreateDebugCapabilityContext (
517 IN USB3_DEBUG_PORT_HANDLE
*Handle
521 XHC_DC_CONTEXT
*DebugCapabilityContext
;
523 UINT8
*ManufacturerStrDesc
;
524 UINT8
*ProductStrDesc
;
525 UINT8
*SerialNumberStrDesc
;
528 // Allocate debug device context
530 Buf
= AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT
));
531 ASSERT (Buf
!= NULL
);
532 ASSERT (((UINTN
) Buf
& 0xF) == 0);
533 ZeroMem (Buf
, sizeof (XHC_DC_CONTEXT
));
535 DebugCapabilityContext
= (XHC_DC_CONTEXT
*)(UINTN
) Buf
;
536 Handle
->DebugCapabilityContext
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) DebugCapabilityContext
;
539 // Initialize DbcInfoContext.
541 DebugCapabilityContext
->DbcInfoContext
.String0Length
= STRING0_DESC_LEN
;
542 DebugCapabilityContext
->DbcInfoContext
.ManufacturerStrLength
= MANU_DESC_LEN
;
543 DebugCapabilityContext
->DbcInfoContext
.ProductStrLength
= PRODUCT_DESC_LEN
;
544 DebugCapabilityContext
->DbcInfoContext
.SerialNumberStrLength
= SERIAL_DESC_LEN
;
547 // Initialize EpOutContext.
549 DebugCapabilityContext
->EpOutContext
.CErr
= 0x3;
550 DebugCapabilityContext
->EpOutContext
.EPType
= ED_BULK_OUT
;
551 DebugCapabilityContext
->EpOutContext
.MaxPacketSize
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
552 DebugCapabilityContext
->EpOutContext
.AverageTRBLength
= 0x1000;
555 // Initialize EpInContext.
557 DebugCapabilityContext
->EpInContext
.CErr
= 0x3;
558 DebugCapabilityContext
->EpInContext
.EPType
= ED_BULK_IN
;
559 DebugCapabilityContext
->EpInContext
.MaxPacketSize
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
560 DebugCapabilityContext
->EpInContext
.AverageTRBLength
= 0x1000;
563 // Update string descriptor address
565 String0Desc
= (UINT8
*) AllocateAlignBuffer (STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
);
566 ASSERT (String0Desc
!= NULL
);
567 ZeroMem (String0Desc
, STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
);
568 CopyMem (String0Desc
, mString0Desc
, STRING0_DESC_LEN
);
569 DebugCapabilityContext
->DbcInfoContext
.String0DescAddress
= (UINT64
)(UINTN
)String0Desc
;
571 ManufacturerStrDesc
= String0Desc
+ STRING0_DESC_LEN
;
572 CopyMem (ManufacturerStrDesc
, mManufacturerStrDesc
, MANU_DESC_LEN
);
573 DebugCapabilityContext
->DbcInfoContext
.ManufacturerStrDescAddress
= (UINT64
)(UINTN
)ManufacturerStrDesc
;
575 ProductStrDesc
= ManufacturerStrDesc
+ MANU_DESC_LEN
;
576 CopyMem (ProductStrDesc
, mProductStrDesc
, PRODUCT_DESC_LEN
);
577 DebugCapabilityContext
->DbcInfoContext
.ProductStrDescAddress
= (UINT64
)(UINTN
)ProductStrDesc
;
579 SerialNumberStrDesc
= ProductStrDesc
+ PRODUCT_DESC_LEN
;
580 CopyMem (SerialNumberStrDesc
, mSerialNumberStrDesc
, SERIAL_DESC_LEN
);
581 DebugCapabilityContext
->DbcInfoContext
.SerialNumberStrDescAddress
= (UINT64
)(UINTN
)SerialNumberStrDesc
;
584 // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
586 ZeroMem (&Handle
->TransferRingIn
, sizeof (TRANSFER_RING
));
587 CreateTransferRing (Handle
, TR_RING_TRB_NUMBER
, &Handle
->TransferRingIn
);
588 DebugCapabilityContext
->EpInContext
.PtrLo
= XHC_LOW_32BIT (Handle
->TransferRingIn
.RingSeg0
) | BIT0
;
589 DebugCapabilityContext
->EpInContext
.PtrHi
= XHC_HIGH_32BIT (Handle
->TransferRingIn
.RingSeg0
);
592 // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
594 ZeroMem (&Handle
->TransferRingOut
, sizeof (TRANSFER_RING
));
595 CreateTransferRing (Handle
, TR_RING_TRB_NUMBER
, &Handle
->TransferRingOut
);
596 DebugCapabilityContext
->EpOutContext
.PtrLo
= XHC_LOW_32BIT (Handle
->TransferRingOut
.RingSeg0
) | BIT0
;
597 DebugCapabilityContext
->EpOutContext
.PtrHi
= XHC_HIGH_32BIT (Handle
->TransferRingOut
.RingSeg0
);
600 // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
605 XHC_LOW_32BIT((UINT64
)(UINTN
)DebugCapabilityContext
)
610 XHC_HIGH_32BIT((UINT64
)(UINTN
)DebugCapabilityContext
)
616 Check if debug device is running.
618 @param Handle Debug port handle.
622 XhcDetectDebugCapabilityReady (
623 IN USB3_DEBUG_PORT_HANDLE
*Handle
627 volatile UINT32 Dcctrl
;
630 if (Handle
->Initialized
== USB3DBG_DBG_CAB
) {
632 // As detection is slow in seconds, wait for longer timeout for the first time.
633 // If first initialization is failed, we will try to enable debug device in the
634 // Poll function invoked by timer.
636 TimeOut
= DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout
), XHC_POLL_DELAY
) + 1;
641 // Check if debug device is in configured state
643 Dcctrl
= XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
);
644 if ((Dcctrl
& BIT0
) != 0) {
646 // Set the flag to indicate debug device is in configured state
648 Handle
->Ready
= TRUE
;
651 MicroSecondDelay (XHC_POLL_DELAY
);
653 } while (TimeOut
!= 0);
657 Initialize usb debug port hardware.
659 @param Handle Debug port handle.
661 @retval TRUE The usb debug port hardware configuration is changed.
662 @retval FALSE The usb debug port hardware configuration is not changed.
667 InitializeUsbDebugHardware (
668 IN USB3_DEBUG_PORT_HANDLE
*Handle
671 RETURN_STATUS Status
;
675 EFI_PHYSICAL_ADDRESS XhciOpRegister
;
677 XhciOpRegister
= Handle
->XhciOpRegister
;
678 TotalUsb3Port
= MmioRead32 (((UINTN
) Handle
->XhciMmioBase
+ XHC_HCSPARAMS1_OFFSET
)) >> 24;
680 if (Handle
->Initialized
== USB3DBG_NOT_ENABLED
) {
682 // If XHCI supports debug capability, hardware resource has been allocated,
683 // but it has not been enabled, try to enable again.
689 // Initialize for PEI phase when AllocatePages can work.
690 // Allocate data buffer with max packet size for data read and data poll.
691 // Allocate data buffer for data write.
693 Buffer
= AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
);
694 if (Buffer
== NULL
) {
696 // AllocatePages can not still work now, return fail and do not initialize now.
698 return RETURN_NOT_READY
;
702 // Reset port to get debug device discovered
704 for (Index
= 0; Index
< TotalUsb3Port
; Index
++) {
705 XhcSetR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT4
);
706 MicroSecondDelay (10 * 1000);
710 // Clear DCE bit and LSE bit in DCCTRL
712 if ((XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
) & (BIT1
|BIT31
)) == (BIT1
|BIT31
)) {
713 XhcClearDebugRegBit (Handle
, XHC_DC_DCCTRL
, BIT1
|BIT31
);
717 // Construct the buffer for read, poll and write.
719 Handle
->UrbIn
.Data
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buffer
;
720 Handle
->Data
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buffer
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
721 Handle
->UrbOut
.Data
= Handle
->UrbIn
.Data
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2;
724 // Initialize event ring
726 ZeroMem (&Handle
->EventRing
, sizeof (EVENT_RING
));
727 Status
= CreateEventRing (Handle
, &Handle
->EventRing
);
728 ASSERT_EFI_ERROR (Status
);
731 // Init IN and OUT endpoint context
733 Status
= CreateDebugCapabilityContext (Handle
);
734 ASSERT_EFI_ERROR (Status
);
737 // Init DCDDI1 and DCDDI2
742 (UINT32
)((XHCI_DEBUG_DEVICE_VENDOR_ID
<< 16) | XHCI_DEBUG_DEVICE_PROTOCOL
)
748 (UINT32
)((XHCI_DEBUG_DEVICE_REVISION
<< 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID
)
752 if ((Handle
->Initialized
== USB3DBG_NOT_ENABLED
) && (!Handle
->ChangePortPower
)) {
754 // If the first time detection is failed, turn port power off and on in order to
755 // reset port status this time, then try to check if debug device is ready again.
757 for (Index
= 0; Index
< TotalUsb3Port
; Index
++) {
758 XhcClearR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT9
);
759 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY
);
760 XhcSetR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT9
);
761 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY
);
762 Handle
->ChangePortPower
= TRUE
;
767 // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
769 XhcSetDebugRegBit (Handle
, XHC_DC_DCCTRL
, BIT1
|BIT31
);
771 XhcDetectDebugCapabilityReady (Handle
);
773 Status
= RETURN_SUCCESS
;
774 if (!Handle
->Ready
) {
775 Handle
->Initialized
= USB3DBG_NOT_ENABLED
;
776 Status
= RETURN_NOT_READY
;
778 Handle
->Initialized
= USB3DBG_ENABLED
;
785 Discover and initialize usb debug port.
787 @param Handle Debug port handle.
791 DiscoverInitializeUsbDebugPort (
792 IN USB3_DEBUG_PORT_HANDLE
*Handle
796 EFI_PHYSICAL_ADDRESS XhciMmioBase
;
799 // Read 64-bit MMIO base address
801 XhciMmioBase
= ProgramXhciBaseAddress ();
802 Handle
->XhciMmioBase
= XhciMmioBase
;
804 Status
= CalculateUsbDebugPortMmioBase (Handle
);
805 if (!RETURN_ERROR (Status
)) {
806 UpdateXhcResource (Handle
, XhciMmioBase
);
807 if (NeedReinitializeHardware (Handle
)) {
808 InitializeUsbDebugHardware (Handle
);
814 Set USB3 debug instance address.
816 @param[in] Instance Debug port instance.
820 SetUsb3DebugPortInstance (
821 IN USB3_DEBUG_PORT_HANDLE
*Instance
824 EFI_PHYSICAL_ADDRESS
*AddrPtr
;
826 AddrPtr
= GetUsb3DebugPortInstanceAddrPtr ();
827 ASSERT (AddrPtr
!= NULL
);
828 *AddrPtr
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Instance
;
832 Return USB3 debug instance address.
835 USB3_DEBUG_PORT_HANDLE
*
836 GetUsb3DebugPortInstance (
840 EFI_PHYSICAL_ADDRESS
*AddrPtr
;
841 USB3_DEBUG_PORT_HANDLE
*Instance
;
843 AddrPtr
= GetUsb3DebugPortInstanceAddrPtr ();
844 ASSERT (AddrPtr
!= NULL
);
846 Instance
= (USB3_DEBUG_PORT_HANDLE
*) (UINTN
) *AddrPtr
;
852 Read data from debug device and save the data in buffer.
854 Reads NumberOfBytes data bytes from a debug device into the buffer
855 specified by Buffer. The number of bytes actually read is returned.
856 If the return value is less than NumberOfBytes, then the rest operation failed.
857 If NumberOfBytes is zero, then return 0.
859 @param Handle Debug port handle.
860 @param Buffer Pointer to the data buffer to store the data read from the debug device.
861 @param NumberOfBytes Number of bytes which will be read.
862 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.
864 @retval 0 Read data failed, no data is to be read.
865 @retval >0 Actual number of bytes read from debug device.
870 DebugPortReadBuffer (
871 IN DEBUG_PORT_HANDLE Handle
,
873 IN UINTN NumberOfBytes
,
877 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
881 if (NumberOfBytes
!= 1 || Buffer
== NULL
|| Timeout
!= 0) {
886 // If Handle is NULL, get own instance.
887 // If Handle is not NULL, use it and set the instance.
889 if (Handle
!= NULL
) {
890 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
891 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
893 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
895 if (UsbDebugPortHandle
== NULL
) {
899 if (UsbDebugPortHandle
->InNotify
) {
903 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
905 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
909 Data
= (UINT8
*)(UINTN
)UsbDebugPortHandle
->Data
;
912 // Read data from buffer
914 if (UsbDebugPortHandle
->DataCount
< 1) {
919 for (Index
= 0; Index
< UsbDebugPortHandle
->DataCount
- 1; Index
++) {
920 if ((Index
+ 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
) {
923 Data
[Index
] = Data
[Index
+ 1];
925 UsbDebugPortHandle
->DataCount
= (UINT8
)(UsbDebugPortHandle
->DataCount
- 1);
931 Write data from buffer to debug device.
933 Writes NumberOfBytes data bytes from Buffer to the debug device.
934 The number of bytes actually written to the debug device is returned.
935 If the return value is less than NumberOfBytes, then the write operation failed.
936 If NumberOfBytes is zero, then return 0.
938 @param Handle Debug port handle.
939 @param Buffer Pointer to the data buffer to be written.
940 @param NumberOfBytes Number of bytes to written to the debug device.
942 @retval 0 NumberOfBytes is 0.
943 @retval >0 The number of bytes written to the debug device.
944 If this value is less than NumberOfBytes, then the write operation failed.
949 DebugPortWriteBuffer (
950 IN DEBUG_PORT_HANDLE Handle
,
952 IN UINTN NumberOfBytes
955 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
959 if (NumberOfBytes
== 0 || Buffer
== NULL
) {
967 // If Handle is NULL, get own instance.
968 // If Handle is not NULL, use it and set the instance.
970 if (Handle
!= NULL
) {
971 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
972 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
974 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
976 if (UsbDebugPortHandle
== NULL
) {
980 if (UsbDebugPortHandle
->InNotify
) {
984 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
986 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
991 // When host is trying to send data, write will be blocked.
992 // Poll to see if there is any data sent by host at first.
994 DebugPortPollBuffer (UsbDebugPortHandle
);
996 while ((Total
< NumberOfBytes
)) {
997 if (NumberOfBytes
- Total
> USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
) {
998 Sent
= USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
;
1000 Sent
= (UINT8
)(NumberOfBytes
- Total
);
1002 XhcDataTransfer (UsbDebugPortHandle
, EfiUsbDataOut
, Buffer
+ Total
, &Sent
, DATA_TRANSFER_WRITE_TIMEOUT
);
1010 Polls a debug device to see if there is any data waiting to be read.
1012 Polls a debug device to see if there is any data waiting to be read.
1013 If there is data waiting to be read from the debug device, then TRUE is returned.
1014 If there is no data waiting to be read from the debug device, then FALSE is returned.
1016 @param Handle Debug port handle.
1018 @retval TRUE Data is waiting to be read from the debug device.
1019 @retval FALSE There is no data waiting to be read from the debug device.
1024 DebugPortPollBuffer (
1025 IN DEBUG_PORT_HANDLE Handle
1028 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1032 // If Handle is NULL, get own instance.
1033 // If Handle is not NULL, use it and set the instance.
1035 if (Handle
!= NULL
) {
1036 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
1037 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
1039 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
1041 if (UsbDebugPortHandle
== NULL
) {
1045 if (UsbDebugPortHandle
->InNotify
) {
1049 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
1051 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
1056 // If the data buffer is not empty, then return TRUE directly.
1057 // Otherwise initialize a usb read transaction and read data to internal data buffer.
1059 if (UsbDebugPortHandle
->DataCount
!= 0) {
1064 // Read data as much as we can
1066 Length
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
1067 XhcDataTransfer (UsbDebugPortHandle
, EfiUsbDataIn
, (VOID
*)(UINTN
)UsbDebugPortHandle
->Data
, &Length
, DATA_TRANSFER_POLL_TIMEOUT
);
1069 if (Length
> XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
) {
1078 // Store data into internal buffer for use later
1080 UsbDebugPortHandle
->DataCount
= (UINT8
) Length
;
1085 Initialize the debug port.
1087 If Function is not NULL, Debug Communication Library will call this function
1088 by passing in the Context to be the first parameter. If needed, Debug Communication
1089 Library will create one debug port handle to be the second argument passing in
1090 calling the Function, otherwise it will pass NULL to be the second argument of
1093 If Function is NULL, and Context is not NULL, the Debug Communication Library could
1094 a) Return the same handle as passed in (as Context parameter).
1095 b) Ignore the input Context parameter and create new handle to be returned.
1097 If parameter Function is NULL and Context is NULL, Debug Communication Library could
1098 created a new handle if needed and return it, otherwise it will return NULL.
1100 @param[in] Context Context needed by callback function; it was optional.
1101 @param[in] Function Continue function called by Debug Communication library;
1104 @return The debug port handle created by Debug Communication Library if Function
1110 DebugPortInitialize (
1112 IN DEBUG_PORT_CONTINUE Function
1115 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1118 // Validate the PCD PcdDebugPortHandleBufferSize value
1120 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize
) == sizeof (USB3_DEBUG_PORT_HANDLE
));
1122 if (Function
== NULL
&& Context
!= NULL
) {
1123 SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE
*) Context
);
1124 return (DEBUG_PORT_HANDLE
) Context
;
1126 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
1127 if (UsbDebugPortHandle
== NULL
) {
1131 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
1133 if (Function
!= NULL
) {
1134 Function (Context
, (DEBUG_PORT_HANDLE
) UsbDebugPortHandle
);
1137 return (DEBUG_PORT_HANDLE
) UsbDebugPortHandle
;