2 Debug Port Library implementation based on usb3 debug port.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "DebugCommunicationLibUsb3Internal.h"
11 UINT16 mString0Desc
[] = {
12 // String Descriptor Type + Length
13 ( USB_DESC_TYPE_STRING
<< 8 ) + STRING0_DESC_LEN
,
17 UINT16 mManufacturerStrDesc
[] = {
18 // String Descriptor Type + Length
19 ( USB_DESC_TYPE_STRING
<< 8 ) + MANU_DESC_LEN
,
20 'I', 'n', 't', 'e', 'l'
23 UINT16 mProductStrDesc
[] = {
24 // String Descriptor Type + Length
25 ( USB_DESC_TYPE_STRING
<< 8 ) + PRODUCT_DESC_LEN
,
26 'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'
29 UINT16 mSerialNumberStrDesc
[] = {
30 // String Descriptor Type + Length
31 ( USB_DESC_TYPE_STRING
<< 8 ) + SERIAL_DESC_LEN
,
36 Sets bits as per the enabled bit positions in the mask.
38 @param[in, out] Register UINTN register
39 @param[in] BitMask 32-bit mask
43 IN OUT UINTN Register
,
49 RegisterValue
= MmioRead32 (Register
);
50 RegisterValue
|= (UINT32
)(BitMask
);
51 MmioWrite32 (Register
, RegisterValue
);
55 Clears bits as per the enabled bit positions in the mask.
57 @param[in, out] Register UINTN register
58 @param[in] BitMask 32-bit mask
62 IN OUT UINTN Register
,
68 RegisterValue
= MmioRead32 (Register
);
69 RegisterValue
&= ~BitMask
;
70 MmioWrite32 (Register
, RegisterValue
);
74 Write the data to the XHCI debug register.
76 @param Handle Debug port handle.
77 @param Offset The offset of the debug register.
78 @param Data The data to write.
83 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
88 EFI_PHYSICAL_ADDRESS DebugCapabilityBase
;
90 DebugCapabilityBase
= Handle
->DebugCapabilityBase
;
91 MmioWrite32 ((UINTN
)(DebugCapabilityBase
+ Offset
), Data
);
97 Read XHCI debug register.
99 @param Handle Debug port handle.
100 @param Offset The offset of the runtime register.
102 @return The register content read
107 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
112 EFI_PHYSICAL_ADDRESS DebugCapabilityBase
;
114 DebugCapabilityBase
= Handle
->DebugCapabilityBase
;
115 Data
= MmioRead32 ((UINTN
)(DebugCapabilityBase
+ Offset
));
121 Set one bit of the debug register while keeping other bits.
123 @param Handle Debug port handle.
124 @param Offset The offset of the debug register.
125 @param Bit The bit mask of the register to set.
130 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
137 Data
= XhcReadDebugReg (Handle
, Offset
);
139 XhcWriteDebugReg (Handle
, Offset
, Data
);
143 Clear one bit of the debug register while keeping other bits.
145 @param Handle Debug port handle.
146 @param Offset The offset of the debug register.
147 @param Bit The bit mask of the register to clear.
151 XhcClearDebugRegBit (
152 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
159 Data
= XhcReadDebugReg (Handle
, Offset
);
161 XhcWriteDebugReg (Handle
, Offset
, Data
);
165 Program and enable XHCI MMIO base address.
167 @return XHCI MMIO base address.
171 ProgramXhciBaseAddress (
178 EFI_PHYSICAL_ADDRESS XhciMmioBase
;
180 Low
= PciRead32 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
);
181 High
= PciRead32 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ 4);
182 XhciMmioBase
= (EFI_PHYSICAL_ADDRESS
) (LShiftU64 ((UINT64
) High
, 32) | Low
);
183 XhciMmioBase
&= XHCI_BASE_ADDRESS_64_BIT_MASK
;
185 if ((XhciMmioBase
== 0) || (XhciMmioBase
== XHCI_BASE_ADDRESS_64_BIT_MASK
)) {
186 XhciMmioBase
= PcdGet64(PcdUsbXhciMemorySpaceBase
);
187 PciWrite32(PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
, XhciMmioBase
& 0xFFFFFFFF);
188 PciWrite32(PcdGet32(PcdUsbXhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ 4, (RShiftU64 (XhciMmioBase
, 32) & 0xFFFFFFFF));
191 PciCmd
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_COMMAND_OFFSET
);
192 if (((PciCmd
& EFI_PCI_COMMAND_MEMORY_SPACE
) == 0) || ((PciCmd
& EFI_PCI_COMMAND_BUS_MASTER
) == 0)) {
193 PciCmd
|= EFI_PCI_COMMAND_MEMORY_SPACE
| EFI_PCI_COMMAND_BUS_MASTER
;
194 PciWrite16(PcdGet32(PcdUsbXhciPciAddress
) + PCI_COMMAND_OFFSET
, PciCmd
);
201 Update XHC MMIO base address when MMIO base address is changed.
203 @param Handle Debug port handle.
204 @param XhciMmioBase XHCI MMIO base address.
209 IN OUT USB3_DEBUG_PORT_HANDLE
*Handle
,
210 IN EFI_PHYSICAL_ADDRESS XhciMmioBase
213 if (Handle
== NULL
) {
218 // Need fix Handle data according to new XHCI MMIO base address.
220 Handle
->XhciMmioBase
= XhciMmioBase
;
221 Handle
->DebugCapabilityBase
= XhciMmioBase
+ Handle
->DebugCapabilityOffset
;
222 Handle
->XhciOpRegister
= XhciMmioBase
+ MmioRead8 ((UINTN
)XhciMmioBase
);
226 Calculate the usb debug port bar address.
228 @param Handle Debug port handle.
230 @retval RETURN_UNSUPPORTED The usb host controller does not support usb debug port capability.
231 @retval RETURN_SUCCESS Get bar and offset successfully.
236 CalculateUsbDebugPortMmioBase (
237 USB3_DEBUG_PORT_HANDLE
*Handle
247 EFI_PHYSICAL_ADDRESS CapabilityPointer
;
250 if (Handle
->Initialized
!= USB3DBG_UNINITIALIZED
) {
251 if (Handle
->Initialized
== USB3DBG_NO_DBG_CAB
) {
252 return RETURN_UNSUPPORTED
;
254 return RETURN_SUCCESS
;
258 VendorId
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_VENDOR_ID_OFFSET
);
259 DeviceId
= PciRead16 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_DEVICE_ID_OFFSET
);
261 if ((VendorId
== 0xFFFF) || (DeviceId
== 0xFFFF)) {
265 ProgInterface
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
);
266 SubClassCode
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 1);
267 BaseCode
= PciRead8 (PcdGet32(PcdUsbXhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 2);
269 if ((ProgInterface
!= PCI_IF_XHCI
) || (SubClassCode
!= PCI_CLASS_SERIAL_USB
) || (BaseCode
!= PCI_CLASS_SERIAL
)) {
273 CapLength
= MmioRead8 ((UINTN
) Handle
->XhciMmioBase
);
276 // Get capability pointer from HCCPARAMS at offset 0x10
278 CapabilityPointer
= Handle
->XhciMmioBase
+ (MmioRead32 ((UINTN
)(Handle
->XhciMmioBase
+ XHC_HCCPARAMS_OFFSET
)) >> 16) * 4;
281 // Search XHCI debug capability
284 Capability
= MmioRead32 ((UINTN
)CapabilityPointer
);
286 if ((Capability
& XHC_CAPABILITY_ID_MASK
) == PCI_CAPABILITY_ID_DEBUG_PORT
) {
290 if ((((Capability
& XHC_NEXT_CAPABILITY_MASK
) >> 8) & XHC_CAPABILITY_ID_MASK
) == 0) {
292 // Reach the end of capability list, quit
296 CapabilityPointer
+= ((Capability
& XHC_NEXT_CAPABILITY_MASK
) >> 8) * 4;
297 Capability
= MmioRead32 ((UINTN
)CapabilityPointer
);
305 // USB3 debug capability is supported.
307 Handle
->DebugCapabilityBase
= CapabilityPointer
;
308 Handle
->DebugCapabilityOffset
= CapabilityPointer
- Handle
->XhciMmioBase
;
309 Handle
->XhciOpRegister
= Handle
->XhciMmioBase
+ CapLength
;
310 Handle
->DebugSupport
= TRUE
;
311 Handle
->Initialized
= USB3DBG_DBG_CAB
;
312 return RETURN_SUCCESS
;
315 Handle
->Initialized
= USB3DBG_NO_DBG_CAB
;
316 return RETURN_UNSUPPORTED
;
320 Check if it needs to re-initialize usb debug port hardware.
322 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
323 whether the usb debug port hardware configuration is changed. Such case can be triggered by
324 Pci bus resource allocation and so on.
326 @param Handle Debug port handle.
328 @retval TRUE The usb debug port hardware configuration is changed.
329 @retval FALSE The usb debug port hardware configuration is not changed.
334 NeedReinitializeHardware(
335 IN USB3_DEBUG_PORT_HANDLE
*Handle
339 volatile UINT32 Dcctrl
;
344 // If DCE bit, it means USB3 debug is not enabled.
346 Dcctrl
= XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
);
347 if ((Dcctrl
& BIT0
) == 0) {
349 } else if (!Handle
->Ready
) {
350 Handle
->Ready
= TRUE
;
351 Handle
->Initialized
= USB3DBG_ENABLED
;
358 Create XHCI event ring.
360 @param Handle Debug port handle.
361 @param EventRing The created event ring.
366 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
367 OUT EVENT_RING
*EventRing
371 EVENT_RING_SEG_TABLE_ENTRY
*ERSTBase
;
373 ASSERT (EventRing
!= NULL
);
376 // Allocate Event Ring
378 Buf
= AllocateAlignBuffer (sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
);
379 ASSERT (Buf
!= NULL
);
380 ASSERT (((UINTN
) Buf
& 0x3F) == 0);
381 ZeroMem (Buf
, sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
);
383 EventRing
->EventRingSeg0
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buf
;
384 EventRing
->TrbNumber
= EVENT_RING_TRB_NUMBER
;
385 EventRing
->EventRingDequeue
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) EventRing
->EventRingSeg0
;
386 EventRing
->EventRingEnqueue
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) EventRing
->EventRingSeg0
;
389 // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
390 // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
392 EventRing
->EventRingCCS
= 1;
395 // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
397 Buf
= AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
);
398 ASSERT (Buf
!= NULL
);
399 ASSERT (((UINTN
) Buf
& 0x3F) == 0);
400 ZeroMem (Buf
, sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
);
402 ERSTBase
= (EVENT_RING_SEG_TABLE_ENTRY
*) Buf
;
403 EventRing
->ERSTBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) ERSTBase
;
406 // Fill Event Segment address
408 ERSTBase
->PtrLo
= XHC_LOW_32BIT (EventRing
->EventRingSeg0
);
409 ERSTBase
->PtrHi
= XHC_HIGH_32BIT (EventRing
->EventRingSeg0
);
410 ERSTBase
->RingTrbSize
= EVENT_RING_TRB_NUMBER
;
413 // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
418 XHC_LOW_32BIT((UINT64
)(UINTN
)EventRing
->EventRingDequeue
)
424 XHC_HIGH_32BIT((UINT64
)(UINTN
)EventRing
->EventRingDequeue
)
428 // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
433 XHC_LOW_32BIT((UINT64
)(UINTN
)ERSTBase
)
439 XHC_HIGH_32BIT((UINT64
)(UINTN
)ERSTBase
)
443 // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
454 Create XHCI transfer ring.
456 @param Handle Debug port handle.
457 @param TrbNum The number of TRB in the ring.
458 @param TransferRing The created transfer ring.
463 IN USB3_DEBUG_PORT_HANDLE
*Handle
,
465 OUT TRANSFER_RING
*TransferRing
471 Buf
= AllocateAlignBuffer (sizeof (TRB_TEMPLATE
) * TrbNum
);
472 ASSERT (Buf
!= NULL
);
473 ASSERT (((UINTN
) Buf
& 0xF) == 0);
474 ZeroMem (Buf
, sizeof (TRB_TEMPLATE
) * TrbNum
);
476 TransferRing
->RingSeg0
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buf
;
477 TransferRing
->TrbNumber
= TrbNum
;
478 TransferRing
->RingEnqueue
= TransferRing
->RingSeg0
;
479 TransferRing
->RingDequeue
= TransferRing
->RingSeg0
;
480 TransferRing
->RingPCS
= 1;
482 // 4.9.2 Transfer Ring Management
483 // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
484 // point to the first TRB in the ring.
486 EndTrb
= (LINK_TRB
*) ((UINTN
)Buf
+ sizeof (TRB_TEMPLATE
) * (TrbNum
- 1));
487 EndTrb
->Type
= TRB_TYPE_LINK
;
488 EndTrb
->PtrLo
= XHC_LOW_32BIT (Buf
);
489 EndTrb
->PtrHi
= XHC_HIGH_32BIT (Buf
);
491 // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
495 // Set Cycle bit as other TRB PCS init value
497 EndTrb
->CycleBit
= 0;
501 Create debug capability context for XHC debug device.
503 @param Handle Debug port handle.
505 @retval EFI_SUCCESS The bit successfully changed by host controller.
506 @retval EFI_TIMEOUT The time out occurred.
510 CreateDebugCapabilityContext (
511 IN USB3_DEBUG_PORT_HANDLE
*Handle
515 XHC_DC_CONTEXT
*DebugCapabilityContext
;
517 UINT8
*ManufacturerStrDesc
;
518 UINT8
*ProductStrDesc
;
519 UINT8
*SerialNumberStrDesc
;
522 // Allocate debug device context
524 Buf
= AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT
));
525 ASSERT (Buf
!= NULL
);
526 ASSERT (((UINTN
) Buf
& 0xF) == 0);
527 ZeroMem (Buf
, sizeof (XHC_DC_CONTEXT
));
529 DebugCapabilityContext
= (XHC_DC_CONTEXT
*)(UINTN
) Buf
;
530 Handle
->DebugCapabilityContext
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) DebugCapabilityContext
;
533 // Initialize DbcInfoContext.
535 DebugCapabilityContext
->DbcInfoContext
.String0Length
= STRING0_DESC_LEN
;
536 DebugCapabilityContext
->DbcInfoContext
.ManufacturerStrLength
= MANU_DESC_LEN
;
537 DebugCapabilityContext
->DbcInfoContext
.ProductStrLength
= PRODUCT_DESC_LEN
;
538 DebugCapabilityContext
->DbcInfoContext
.SerialNumberStrLength
= SERIAL_DESC_LEN
;
541 // Initialize EpOutContext.
543 DebugCapabilityContext
->EpOutContext
.CErr
= 0x3;
544 DebugCapabilityContext
->EpOutContext
.EPType
= ED_BULK_OUT
;
545 DebugCapabilityContext
->EpOutContext
.MaxPacketSize
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
546 DebugCapabilityContext
->EpOutContext
.AverageTRBLength
= 0x1000;
549 // Initialize EpInContext.
551 DebugCapabilityContext
->EpInContext
.CErr
= 0x3;
552 DebugCapabilityContext
->EpInContext
.EPType
= ED_BULK_IN
;
553 DebugCapabilityContext
->EpInContext
.MaxPacketSize
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
554 DebugCapabilityContext
->EpInContext
.AverageTRBLength
= 0x1000;
557 // Update string descriptor address
559 String0Desc
= (UINT8
*) AllocateAlignBuffer (STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
);
560 ASSERT (String0Desc
!= NULL
);
561 ZeroMem (String0Desc
, STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
);
562 CopyMem (String0Desc
, mString0Desc
, STRING0_DESC_LEN
);
563 DebugCapabilityContext
->DbcInfoContext
.String0DescAddress
= (UINT64
)(UINTN
)String0Desc
;
565 ManufacturerStrDesc
= String0Desc
+ STRING0_DESC_LEN
;
566 CopyMem (ManufacturerStrDesc
, mManufacturerStrDesc
, MANU_DESC_LEN
);
567 DebugCapabilityContext
->DbcInfoContext
.ManufacturerStrDescAddress
= (UINT64
)(UINTN
)ManufacturerStrDesc
;
569 ProductStrDesc
= ManufacturerStrDesc
+ MANU_DESC_LEN
;
570 CopyMem (ProductStrDesc
, mProductStrDesc
, PRODUCT_DESC_LEN
);
571 DebugCapabilityContext
->DbcInfoContext
.ProductStrDescAddress
= (UINT64
)(UINTN
)ProductStrDesc
;
573 SerialNumberStrDesc
= ProductStrDesc
+ PRODUCT_DESC_LEN
;
574 CopyMem (SerialNumberStrDesc
, mSerialNumberStrDesc
, SERIAL_DESC_LEN
);
575 DebugCapabilityContext
->DbcInfoContext
.SerialNumberStrDescAddress
= (UINT64
)(UINTN
)SerialNumberStrDesc
;
578 // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
580 ZeroMem (&Handle
->TransferRingIn
, sizeof (TRANSFER_RING
));
581 CreateTransferRing (Handle
, TR_RING_TRB_NUMBER
, &Handle
->TransferRingIn
);
582 DebugCapabilityContext
->EpInContext
.PtrLo
= XHC_LOW_32BIT (Handle
->TransferRingIn
.RingSeg0
) | BIT0
;
583 DebugCapabilityContext
->EpInContext
.PtrHi
= XHC_HIGH_32BIT (Handle
->TransferRingIn
.RingSeg0
);
586 // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
588 ZeroMem (&Handle
->TransferRingOut
, sizeof (TRANSFER_RING
));
589 CreateTransferRing (Handle
, TR_RING_TRB_NUMBER
, &Handle
->TransferRingOut
);
590 DebugCapabilityContext
->EpOutContext
.PtrLo
= XHC_LOW_32BIT (Handle
->TransferRingOut
.RingSeg0
) | BIT0
;
591 DebugCapabilityContext
->EpOutContext
.PtrHi
= XHC_HIGH_32BIT (Handle
->TransferRingOut
.RingSeg0
);
594 // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
599 XHC_LOW_32BIT((UINT64
)(UINTN
)DebugCapabilityContext
)
604 XHC_HIGH_32BIT((UINT64
)(UINTN
)DebugCapabilityContext
)
610 Check if debug device is running.
612 @param Handle Debug port handle.
616 XhcDetectDebugCapabilityReady (
617 IN USB3_DEBUG_PORT_HANDLE
*Handle
621 volatile UINT32 Dcctrl
;
624 if (Handle
->Initialized
== USB3DBG_DBG_CAB
) {
626 // As detection is slow in seconds, wait for longer timeout for the first time.
627 // If first initialization is failed, we will try to enable debug device in the
628 // Poll function invoked by timer.
630 TimeOut
= DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout
), XHC_POLL_DELAY
) + 1;
635 // Check if debug device is in configured state
637 Dcctrl
= XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
);
638 if ((Dcctrl
& BIT0
) != 0) {
640 // Set the flag to indicate debug device is in configured state
642 Handle
->Ready
= TRUE
;
645 MicroSecondDelay (XHC_POLL_DELAY
);
647 } while (TimeOut
!= 0);
651 Initialize usb debug port hardware.
653 @param Handle Debug port handle.
655 @retval TRUE The usb debug port hardware configuration is changed.
656 @retval FALSE The usb debug port hardware configuration is not changed.
661 InitializeUsbDebugHardware (
662 IN USB3_DEBUG_PORT_HANDLE
*Handle
665 RETURN_STATUS Status
;
669 EFI_PHYSICAL_ADDRESS XhciOpRegister
;
672 XhciOpRegister
= Handle
->XhciOpRegister
;
673 TotalUsb3Port
= MmioRead32 (((UINTN
) Handle
->XhciMmioBase
+ XHC_HCSPARAMS1_OFFSET
)) >> 24;
675 if (Handle
->Initialized
== USB3DBG_NOT_ENABLED
) {
676 Dcddi1
= XhcReadDebugReg (Handle
,XHC_DC_DCDDI1
);
677 if (Dcddi1
!= (UINT32
)((XHCI_DEBUG_DEVICE_VENDOR_ID
<< 16) | XHCI_DEBUG_DEVICE_PROTOCOL
)) {
679 // The debug capability has been reset by other code, return device error.
681 return EFI_DEVICE_ERROR
;
684 // If XHCI supports debug capability, hardware resource has been allocated,
685 // but it has not been enabled, try to enable again.
691 // Initialize for PEI phase when AllocatePages can work.
692 // Allocate data buffer with max packet size for data read and data poll.
693 // Allocate data buffer for data write.
695 Buffer
= AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
);
696 if (Buffer
== NULL
) {
698 // AllocatePages can not still work now, return fail and do not initialize now.
700 return RETURN_NOT_READY
;
704 // Reset port to get debug device discovered
706 for (Index
= 0; Index
< TotalUsb3Port
; Index
++) {
707 XhcSetR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT4
);
708 MicroSecondDelay (10 * 1000);
712 // Clear DCE bit and LSE bit in DCCTRL
714 if ((XhcReadDebugReg (Handle
, XHC_DC_DCCTRL
) & (BIT1
|BIT31
)) == (BIT1
|BIT31
)) {
715 XhcClearDebugRegBit (Handle
, XHC_DC_DCCTRL
, BIT1
|BIT31
);
719 // Construct the buffer for read, poll and write.
721 Handle
->UrbIn
.Data
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buffer
;
722 Handle
->Data
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Buffer
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
723 Handle
->UrbOut
.Data
= Handle
->UrbIn
.Data
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2;
726 // Initialize event ring
728 ZeroMem (&Handle
->EventRing
, sizeof (EVENT_RING
));
729 Status
= CreateEventRing (Handle
, &Handle
->EventRing
);
730 ASSERT_EFI_ERROR (Status
);
733 // Init IN and OUT endpoint context
735 Status
= CreateDebugCapabilityContext (Handle
);
736 ASSERT_EFI_ERROR (Status
);
739 // Init DCDDI1 and DCDDI2
744 (UINT32
)((XHCI_DEBUG_DEVICE_VENDOR_ID
<< 16) | XHCI_DEBUG_DEVICE_PROTOCOL
)
750 (UINT32
)((XHCI_DEBUG_DEVICE_REVISION
<< 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID
)
754 if ((Handle
->Initialized
== USB3DBG_NOT_ENABLED
) && (!Handle
->ChangePortPower
)) {
756 // If the first time detection is failed, turn port power off and on in order to
757 // reset port status this time, then try to check if debug device is ready again.
759 for (Index
= 0; Index
< TotalUsb3Port
; Index
++) {
760 XhcClearR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT9
);
761 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY
);
762 XhcSetR32Bit ((UINTN
)XhciOpRegister
+ XHC_PORTSC_OFFSET
+ Index
* 0x10, BIT9
);
763 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY
);
764 Handle
->ChangePortPower
= TRUE
;
769 // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
771 XhcSetDebugRegBit (Handle
, XHC_DC_DCCTRL
, BIT1
|BIT31
);
773 XhcDetectDebugCapabilityReady (Handle
);
775 Status
= RETURN_SUCCESS
;
776 if (!Handle
->Ready
) {
777 Handle
->Initialized
= USB3DBG_NOT_ENABLED
;
778 Status
= RETURN_NOT_READY
;
780 Handle
->Initialized
= USB3DBG_ENABLED
;
787 Discover and initialize usb debug port.
789 @param Handle Debug port handle.
793 DiscoverInitializeUsbDebugPort (
794 IN USB3_DEBUG_PORT_HANDLE
*Handle
798 EFI_PHYSICAL_ADDRESS XhciMmioBase
;
801 // Read 64-bit MMIO base address
803 XhciMmioBase
= ProgramXhciBaseAddress ();
804 Handle
->XhciMmioBase
= XhciMmioBase
;
806 Status
= CalculateUsbDebugPortMmioBase (Handle
);
807 if (!RETURN_ERROR (Status
)) {
808 UpdateXhcResource (Handle
, XhciMmioBase
);
809 if (NeedReinitializeHardware (Handle
)) {
810 InitializeUsbDebugHardware (Handle
);
816 Set USB3 debug instance address.
818 @param[in] Instance Debug port instance.
822 SetUsb3DebugPortInstance (
823 IN USB3_DEBUG_PORT_HANDLE
*Instance
826 EFI_PHYSICAL_ADDRESS
*AddrPtr
;
828 AddrPtr
= GetUsb3DebugPortInstanceAddrPtr ();
829 ASSERT (AddrPtr
!= NULL
);
830 *AddrPtr
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Instance
;
834 Return USB3 debug instance address.
837 USB3_DEBUG_PORT_HANDLE
*
838 GetUsb3DebugPortInstance (
842 EFI_PHYSICAL_ADDRESS
*AddrPtr
;
843 USB3_DEBUG_PORT_HANDLE
*Instance
;
845 AddrPtr
= GetUsb3DebugPortInstanceAddrPtr ();
846 ASSERT (AddrPtr
!= NULL
);
848 Instance
= (USB3_DEBUG_PORT_HANDLE
*) (UINTN
) *AddrPtr
;
854 Read data from debug device and save the data in buffer.
856 Reads NumberOfBytes data bytes from a debug device into the buffer
857 specified by Buffer. The number of bytes actually read is returned.
858 If the return value is less than NumberOfBytes, then the rest operation failed.
859 If NumberOfBytes is zero, then return 0.
861 @param Handle Debug port handle.
862 @param Buffer Pointer to the data buffer to store the data read from the debug device.
863 @param NumberOfBytes Number of bytes which will be read.
864 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.
866 @retval 0 Read data failed, no data is to be read.
867 @retval >0 Actual number of bytes read from debug device.
872 DebugPortReadBuffer (
873 IN DEBUG_PORT_HANDLE Handle
,
875 IN UINTN NumberOfBytes
,
879 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
883 if (NumberOfBytes
!= 1 || Buffer
== NULL
|| Timeout
!= 0) {
888 // If Handle is NULL, get own instance.
889 // If Handle is not NULL, use it and set the instance.
891 if (Handle
!= NULL
) {
892 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
893 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
895 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
897 if (UsbDebugPortHandle
== NULL
) {
901 if (UsbDebugPortHandle
->InNotify
) {
905 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
907 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
911 Data
= (UINT8
*)(UINTN
)UsbDebugPortHandle
->Data
;
914 // Read data from buffer
916 if (UsbDebugPortHandle
->DataCount
< 1) {
921 for (Index
= 0; Index
< UsbDebugPortHandle
->DataCount
- 1; Index
++) {
922 if ((Index
+ 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
) {
925 Data
[Index
] = Data
[Index
+ 1];
927 UsbDebugPortHandle
->DataCount
= (UINT8
)(UsbDebugPortHandle
->DataCount
- 1);
933 Write data from buffer to debug device.
935 Writes NumberOfBytes data bytes from Buffer to the debug device.
936 The number of bytes actually written to the debug device is returned.
937 If the return value is less than NumberOfBytes, then the write operation failed.
938 If NumberOfBytes is zero, then return 0.
940 @param Handle Debug port handle.
941 @param Buffer Pointer to the data buffer to be written.
942 @param NumberOfBytes Number of bytes to written to the debug device.
944 @retval 0 NumberOfBytes is 0.
945 @retval >0 The number of bytes written to the debug device.
946 If this value is less than NumberOfBytes, then the write operation failed.
951 DebugPortWriteBuffer (
952 IN DEBUG_PORT_HANDLE Handle
,
954 IN UINTN NumberOfBytes
957 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
961 if (NumberOfBytes
== 0 || Buffer
== NULL
) {
969 // If Handle is NULL, get own instance.
970 // If Handle is not NULL, use it and set the instance.
972 if (Handle
!= NULL
) {
973 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
974 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
976 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
978 if (UsbDebugPortHandle
== NULL
) {
982 if (UsbDebugPortHandle
->InNotify
) {
986 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
988 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
993 // When host is trying to send data, write will be blocked.
994 // Poll to see if there is any data sent by host at first.
996 DebugPortPollBuffer (UsbDebugPortHandle
);
998 while ((Total
< NumberOfBytes
)) {
999 if (NumberOfBytes
- Total
> USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
) {
1000 Sent
= USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
;
1002 Sent
= (UINT8
)(NumberOfBytes
- Total
);
1004 XhcDataTransfer (UsbDebugPortHandle
, EfiUsbDataOut
, Buffer
+ Total
, &Sent
, DATA_TRANSFER_WRITE_TIMEOUT
);
1012 Polls a debug device to see if there is any data waiting to be read.
1014 Polls a debug device to see if there is any data waiting to be read.
1015 If there is data waiting to be read from the debug device, then TRUE is returned.
1016 If there is no data waiting to be read from the debug device, then FALSE is returned.
1018 @param Handle Debug port handle.
1020 @retval TRUE Data is waiting to be read from the debug device.
1021 @retval FALSE There is no data waiting to be read from the debug device.
1026 DebugPortPollBuffer (
1027 IN DEBUG_PORT_HANDLE Handle
1030 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1034 // If Handle is NULL, get own instance.
1035 // If Handle is not NULL, use it and set the instance.
1037 if (Handle
!= NULL
) {
1038 UsbDebugPortHandle
= (USB3_DEBUG_PORT_HANDLE
*) Handle
;
1039 SetUsb3DebugPortInstance (UsbDebugPortHandle
);
1041 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
1043 if (UsbDebugPortHandle
== NULL
) {
1047 if (UsbDebugPortHandle
->InNotify
) {
1051 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
1053 if (UsbDebugPortHandle
->Initialized
!= USB3DBG_ENABLED
) {
1058 // If the data buffer is not empty, then return TRUE directly.
1059 // Otherwise initialize a usb read transaction and read data to internal data buffer.
1061 if (UsbDebugPortHandle
->DataCount
!= 0) {
1066 // Read data as much as we can
1068 Length
= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
;
1069 XhcDataTransfer (UsbDebugPortHandle
, EfiUsbDataIn
, (VOID
*)(UINTN
)UsbDebugPortHandle
->Data
, &Length
, DATA_TRANSFER_POLL_TIMEOUT
);
1071 if (Length
> XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
) {
1080 // Store data into internal buffer for use later
1082 UsbDebugPortHandle
->DataCount
= (UINT8
) Length
;
1087 Initialize the debug port.
1089 If Function is not NULL, Debug Communication Library will call this function
1090 by passing in the Context to be the first parameter. If needed, Debug Communication
1091 Library will create one debug port handle to be the second argument passing in
1092 calling the Function, otherwise it will pass NULL to be the second argument of
1095 If Function is NULL, and Context is not NULL, the Debug Communication Library could
1096 a) Return the same handle as passed in (as Context parameter).
1097 b) Ignore the input Context parameter and create new handle to be returned.
1099 If parameter Function is NULL and Context is NULL, Debug Communication Library could
1100 created a new handle if needed and return it, otherwise it will return NULL.
1102 @param[in] Context Context needed by callback function; it was optional.
1103 @param[in] Function Continue function called by Debug Communication library;
1106 @return The debug port handle created by Debug Communication Library if Function
1112 DebugPortInitialize (
1114 IN DEBUG_PORT_CONTINUE Function
1117 USB3_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1120 // Validate the PCD PcdDebugPortHandleBufferSize value
1122 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize
) == sizeof (USB3_DEBUG_PORT_HANDLE
));
1124 if (Function
== NULL
&& Context
!= NULL
) {
1125 SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE
*) Context
);
1126 return (DEBUG_PORT_HANDLE
) Context
;
1128 UsbDebugPortHandle
= GetUsb3DebugPortInstance ();
1129 if (UsbDebugPortHandle
== NULL
) {
1133 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle
);
1135 if (Function
!= NULL
) {
1136 Function (Context
, (DEBUG_PORT_HANDLE
) UsbDebugPortHandle
);
1139 return (DEBUG_PORT_HANDLE
) UsbDebugPortHandle
;