2 Debug Port Library implementation based on usb debug port.
4 Copyright (c) 2010 - 2014, 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.
16 #include <IndustryStandard/Pci.h>
17 #include <IndustryStandard/Usb.h>
18 #include <Library/IoLib.h>
19 #include <Library/PciLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/TimerLib.h>
22 #include <Library/DebugCommunicationLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/BaseLib.h>
25 #include <Library/DebugLib.h>
27 #define SETUP_PID 0x2D
28 #define INPUT_PID 0x69
29 #define OUTPUT_PID 0xE1
30 #define ERROR_PID 0x55
31 #define DATA0_PID 0xC3
32 #define DATA1_PID 0x4B
33 #define DATA2_PID 0x87
34 #define MDATA_PID 0x0F
37 #define STALL_PID 0x1E
40 #define PCI_CAPABILITY_ID_DEBUG_PORT 0x0A
41 #define USB_DEBUG_PORT_MAX_PACKET_SIZE 0x08
43 #define USB_DEBUG_PORT_IN_USE BIT10
44 #define USB_DEBUG_PORT_ENABLE BIT28
45 #define USB_DEBUG_PORT_OWNER BIT30
47 #define USB_PORT_LINE_STATUS_LS 0x400
48 #define USB_PORT_LINE_STATUS_MASK 0xC00
51 // Usb debug device descriptor, which is defined at
52 // USB2 Debug Device Specification.
54 typedef struct _USB_DEBUG_PORT_DESCRIPTOR
{
57 UINT8 DebugInEndpoint
;
58 UINT8 DebugOutEndpoint
;
59 }USB_DEBUG_PORT_DESCRIPTOR
;
61 USB_DEVICE_REQUEST mDebugCommunicationLibUsbGetDebugDescriptor
= {
63 USB_REQ_GET_DESCRIPTOR
,
66 sizeof(USB_DEBUG_PORT_DESCRIPTOR
)
69 USB_DEVICE_REQUEST mDebugCommunicationLibUsbSetDebugFeature
= {
77 USB_DEVICE_REQUEST mDebugCommunicationLibUsbSetDebugAddress
= {
86 // Usb debug port register file, which is defined at
87 // EHCI Specification.
89 typedef struct _USB_DEBUG_PORT_REGISTER
{
100 }USB_DEBUG_PORT_REGISTER
;
103 // The state machine of usb debug port
105 #define USBDBG_NO_DEV 0 // No device present at debug port
106 #define USBDBG_NO_DBG_CAB 1 // The device attached is not usb debug cable
107 #define USBDBG_DBG_CAB 2 // The device attached is usb debug cable
108 #define USBDBG_INIT_DONE 4 // The usb debug cable device is initialized
109 #define USBDBG_RESET 8 // The system is reset
113 // The internal data structure of DEBUG_PORT_HANDLE, which stores some
114 // important datum which are used across various phases.
116 typedef struct _USB_DEBUG_PORT_HANDLE
{
118 // The usb debug port memory BAR number in EHCI configuration space.
120 UINT8 DebugPortBarNumber
;
123 // The offset of usb debug port registers in EHCI memory range.
125 UINT16 DebugPortOffset
;
127 // The usb debug port memory BAR address.
129 UINT32 UsbDebugPortMemoryBase
;
131 // The EHCI memory BAR address.
133 UINT32 EhciMemoryBase
;
135 // The Bulk In endpoint toggle bit.
139 // The Bulk Out endpoint toggle bit.
143 // The available data length in the following data buffer.
147 // The data buffer. Maximum length is 8 bytes.
153 UINT64 TimerFrequency
;
155 BOOLEAN TimerCountDown
;
156 } USB_DEBUG_PORT_HANDLE
;
160 // The global variable which can be used after memory is ready.
162 USB_DEBUG_PORT_HANDLE mDebugCommunicationLibUsbDebugPortHandle
;
165 Check if the timer is timeout.
167 @param[in] UsbDebugPortHandle Pointer to USB Debug port handle
168 @param[in] Timer The start timer from the begin.
169 @param[in] TimeoutTicker Ticker number need time out.
171 @return TRUE Timer time out occurs.
172 @retval FALSE Timer does not time out.
177 IN USB_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
,
179 IN UINT64 TimeoutTicker
185 CurrentTimer
= GetPerformanceCounter ();
187 if (UsbDebugPortHandle
->TimerCountDown
) {
189 // The timer counter counts down. Check for roll over condition.
191 if (CurrentTimer
< Timer
) {
192 Delta
= Timer
- CurrentTimer
;
195 // Handle one roll-over.
197 Delta
= UsbDebugPortHandle
->TimerCycle
- (CurrentTimer
- Timer
);
201 // The timer counter counts up. Check for roll over condition.
203 if (CurrentTimer
> Timer
) {
204 Delta
= CurrentTimer
- Timer
;
207 // Handle one roll-over.
209 Delta
= UsbDebugPortHandle
->TimerCycle
- (Timer
- CurrentTimer
);
213 return (BOOLEAN
) (Delta
>= TimeoutTicker
);
217 Calculate the usb debug port bar address.
219 @param DebugPortOffset Get usb debug port offset in the usb debug port memory space.
220 @param DebugPortBarNumbar Get the bar number at which usb debug port is located.
222 @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.
223 @retval RETURN_SUCCESS Get bar and offset successfully.
228 CalculateUsbDebugPortBar (
229 OUT UINT16
*DebugPortOffset
,
230 OUT UINT8
*DebugPortBarNumbar
242 VendorId
= PciRead16 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_VENDOR_ID_OFFSET
);
243 DeviceId
= PciRead16 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_DEVICE_ID_OFFSET
);
245 if ((VendorId
== 0xFFFF) || (DeviceId
== 0xFFFF)) {
246 return RETURN_UNSUPPORTED
;
249 ProgInterface
= PciRead8 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_CLASSCODE_OFFSET
);
250 SubClassCode
= PciRead8 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 1);
251 BaseCode
= PciRead8 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_CLASSCODE_OFFSET
+ 2);
253 if ((ProgInterface
!= PCI_IF_EHCI
) || (SubClassCode
!= PCI_CLASS_SERIAL_USB
) || (BaseCode
!= PCI_CLASS_SERIAL
)) {
254 return RETURN_UNSUPPORTED
;
258 // Enable Ehci Host Controller MMIO Space.
260 PciStatus
= PciRead16 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_PRIMARY_STATUS_OFFSET
);
262 if ((PciStatus
& EFI_PCI_STATUS_CAPABILITY
) == 0) {
264 // The Pci Device Doesn't Support Capability Pointer.
266 return RETURN_UNSUPPORTED
;
270 // Get Pointer To Capability List
272 CapabilityPtr
= PciRead8(PcdGet32(PcdUsbEhciPciAddress
) + PCI_CAPBILITY_POINTER_OFFSET
);
275 // Find Capability ID 0xA, Which Is For Debug Port
277 while (CapabilityPtr
!= 0) {
278 CapabilityId
= PciRead8(PcdGet32(PcdUsbEhciPciAddress
) + CapabilityPtr
);
279 if (CapabilityId
== PCI_CAPABILITY_ID_DEBUG_PORT
) {
282 CapabilityPtr
= PciRead8(PcdGet32(PcdUsbEhciPciAddress
) + CapabilityPtr
+ 1);
286 // No Debug Port Capability Found
288 if (CapabilityPtr
== 0) {
289 return RETURN_UNSUPPORTED
;
293 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
295 *DebugPortOffset
= (UINT16
)(PciRead16(PcdGet32(PcdUsbEhciPciAddress
) + CapabilityPtr
+ 2) & 0x1FFF);
296 *DebugPortBarNumbar
= (UINT8
)((PciRead16(PcdGet32(PcdUsbEhciPciAddress
) + CapabilityPtr
+ 2) >> 13) - 1);
298 return RETURN_SUCCESS
;
302 Do a usb IN transaction by usb debug port.
304 @param DebugPortRegister Pointer to the base address of usb debug port register interface.
305 @param Buffer Pointer to the buffer receiving data.
306 @param Length Number of bytes of the received data.
307 @param Token The token PID for each USB transaction.
308 @param Addr The usb device address for usb transaction.
309 @param Ep The endpoint for usb transaction.
310 @param DataToggle The toggle bit used at usb transaction.
312 @retval RETURN_SUCCESS The IN transaction is executed successfully.
313 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
314 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
320 IN USB_DEBUG_PORT_REGISTER
*DebugPortRegister
,
321 IN OUT UINT8
*Buffer
,
331 if (Length
== NULL
) {
332 return RETURN_INVALID_PARAMETER
;
336 DebugPortRegister
->TokenPid
= Token
;
337 if (DataToggle
!= 0) {
338 DebugPortRegister
->SendPid
= DATA1_PID
;
340 DebugPortRegister
->SendPid
= DATA0_PID
;
343 DebugPortRegister
->UsbAddress
= (UINT8
)(Addr
& 0x7F);
344 DebugPortRegister
->UsbEndPoint
= (UINT8
)(Ep
& 0xF);
347 // Clearing W/R bit to indicate it's a READ operation
349 MmioAnd32((UINTN
)&DebugPortRegister
->ControlStatus
, (UINT32
)~BIT4
);
352 // Setting GO bit as well as clearing DONE bit
354 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, (UINT32
)BIT5
);
357 // Wait for completing the request
359 while ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
) & (UINT32
)BIT16
) == 0) {
360 if ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
) & (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
))
361 != (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
)) {
362 return RETURN_DEVICE_ERROR
;
367 // Clearing DONE bit by writing 1
369 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, BIT16
);
372 // Check if the request is executed successfully or not.
374 if ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
)) & BIT6
) {
375 return RETURN_DEVICE_ERROR
;
379 // Make sure the received data are not beyond the allowable maximum length - 8 byte
381 if (((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE
) {
382 return RETURN_DEVICE_ERROR
;
385 *Length
= (UINT8
)(MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
) & 0xF);
387 return RETURN_DEVICE_ERROR
;
390 for (Index
= 0; Index
< *Length
; Index
++) {
391 Buffer
[Index
] = DebugPortRegister
->DataBuffer
[Index
];
393 return RETURN_SUCCESS
;
397 Do a usb SETUP/OUT transaction by usb debug port.
399 @param DebugPortRegister Pointer to the base address of usb debug port register interface.
400 @param Buffer Pointer to the buffer receiving data.
401 @param Length Number of bytes of the received data.
402 @param Token The token PID for each USB transaction.
403 @param Addr The usb device address for usb transaction.
404 @param Ep The endpoint for usb transaction.
405 @param DataToggle The toggle bit used at usb transaction.
407 @retval RETURN_SUCCESS The IN transaction is executed successfully.
408 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
409 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
415 IN USB_DEBUG_PORT_REGISTER
*DebugPortRegister
,
427 return RETURN_INVALID_PARAMETER
;
430 DebugPortRegister
->TokenPid
= Token
;
431 if (DataToggle
!= 0) {
432 DebugPortRegister
->SendPid
= DATA1_PID
;
434 DebugPortRegister
->SendPid
= DATA0_PID
;
436 DebugPortRegister
->UsbAddress
= (UINT8
)(Addr
& 0x7F);
437 DebugPortRegister
->UsbEndPoint
= (UINT8
)(Ep
& 0xF);
440 // Fill in the data length and corresponding data.
442 MmioAnd32((UINTN
)&DebugPortRegister
->ControlStatus
, (UINT32
)~0xF);
443 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, Length
& 0xF);
444 for (Index
= 0; Index
< Length
; Index
++) {
445 DebugPortRegister
->DataBuffer
[Index
] = Buffer
[Index
];
449 // Setting W/R bit to indicate it's a WRITE operation
451 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, BIT4
);
453 // Setting GO bit as well as clearing DONE bit
455 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, BIT5
);
458 // Wait for completing the request
460 while ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
) & BIT16
) == 0) {
461 if ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
) & (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
))
462 != (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
)) {
463 return RETURN_DEVICE_ERROR
;
468 // Clearing DONE bit by writing 1
470 MmioOr32((UINTN
)&DebugPortRegister
->ControlStatus
, BIT16
);
473 // Check if the request is executed successfully or not.
475 if ((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
)) & BIT6
) {
476 return RETURN_DEVICE_ERROR
;
480 // Make sure the sent data are not beyond the allowable maximum length - 8 byte
482 if (((MmioRead32((UINTN
)&DebugPortRegister
->ControlStatus
)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE
) {
483 return RETURN_DEVICE_ERROR
;
486 return RETURN_SUCCESS
;
490 Do a usb control transfer by usb debug port.
492 @param DebugPortRegister Pointer to the base address of usb debug port register interface.
493 @param SetupPacket The token PID for each USB transaction.
494 @param Addr The usb device address for usb transaction.
495 @param Ep The endpoint for usb transaction.
496 @param Data Pointer to the buffer receiving data.
497 @param DataLength Number of bytes of the received data.
499 @retval RETURN_SUCCESS The IN transaction is executed successfully.
500 @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.
501 @retval RETURN_DEVICE_ERROR The IN transaction comes across error.
506 UsbDebugPortControlTransfer (
507 IN USB_DEBUG_PORT_REGISTER
*DebugPortRegister
,
508 IN USB_DEVICE_REQUEST
*SetupPacket
,
512 IN OUT UINT8
*DataLength
515 RETURN_STATUS Status
;
517 UINT8 ReturnStatus
[8];
522 Status
= UsbDebugPortOut(DebugPortRegister
, (UINT8
*)SetupPacket
, (UINT8
)sizeof(USB_DEVICE_REQUEST
), SETUP_PID
, Addr
, Ep
, 0);
523 if (RETURN_ERROR(Status
)) {
530 if (DataLength
!= 0) {
531 if ((SetupPacket
->RequestType
& BIT7
) != 0) {
533 // Get Data From Device
535 Status
= UsbDebugPortIn(DebugPortRegister
, Data
, DataLength
, INPUT_PID
, Addr
, Ep
, 1);
536 if (RETURN_ERROR(Status
)) {
541 // Send Data To Device
543 Status
= UsbDebugPortOut(DebugPortRegister
, Data
, *DataLength
, OUTPUT_PID
, Addr
, Ep
, 1);
544 if (RETURN_ERROR(Status
)) {
553 if ((SetupPacket
->RequestType
& BIT7
) != 0) {
555 // For READ operation, Data Toggle in Status Phase Should be 1.
557 Status
= UsbDebugPortOut(DebugPortRegister
, NULL
, 0, OUTPUT_PID
, Addr
, Ep
, 1);
560 // For WRITE operation, Data Toggle in Status Phase Should be 1.
562 Status
= UsbDebugPortIn(DebugPortRegister
, ReturnStatus
, &Temp
, INPUT_PID
, Addr
, Ep
, 1);
569 Check if it needs to re-initialize usb debug port hardware.
571 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
572 whether the usb debug port hardware configuration is changed. Such case can be triggerred by
573 Pci bus resource allocation and so on.
575 @param Handle Debug port handle.
577 @retval TRUE The usb debug port hardware configuration is changed.
578 @retval FALSE The usb debug port hardware configuration is not changed.
583 NeedReinitializeHardware(
584 IN USB_DEBUG_PORT_HANDLE
*Handle
588 UINT32 UsbDebugPortMemoryBase
;
589 UINT32 EhciMemoryBase
;
591 USB_DEBUG_PORT_REGISTER
*UsbDebugPortRegister
;
595 EhciMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
);
596 if (EhciMemoryBase
!= Handle
->EhciMemoryBase
) {
597 Handle
->EhciMemoryBase
= EhciMemoryBase
;
601 UsbDebugPortMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ Handle
->DebugPortBarNumber
* 4);
602 if (UsbDebugPortMemoryBase
!= Handle
->UsbDebugPortMemoryBase
) {
603 Handle
->UsbDebugPortMemoryBase
= UsbDebugPortMemoryBase
;
608 // Enable Ehci Memory Space Access
610 PciCmd
= PciRead16 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_COMMAND_OFFSET
);
611 if (((PciCmd
& EFI_PCI_COMMAND_MEMORY_SPACE
) == 0) || ((PciCmd
& EFI_PCI_COMMAND_BUS_MASTER
) == 0)) {
612 PciCmd
|= EFI_PCI_COMMAND_MEMORY_SPACE
| EFI_PCI_COMMAND_BUS_MASTER
;
613 PciWrite16(PcdGet32(PcdUsbEhciPciAddress
) + PCI_COMMAND_OFFSET
, PciCmd
);
618 // If the owner and in_use bit is not set, it means system is doing cold/warm boot or EHCI host controller is reset by system software.
620 UsbDebugPortRegister
= (USB_DEBUG_PORT_REGISTER
*)(UINTN
)(Handle
->UsbDebugPortMemoryBase
+ Handle
->DebugPortOffset
);
621 if ((MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
) & (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_ENABLE
| USB_DEBUG_PORT_IN_USE
))
622 != (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_ENABLE
| USB_DEBUG_PORT_IN_USE
)) {
626 if (Handle
->Initialized
== USBDBG_RESET
) {
628 } else if (Handle
->Initialized
!= USBDBG_INIT_DONE
) {
635 Initialize usb debug port hardware.
637 1. reset ehci host controller.
638 2. set right port to debug port.
639 3. find a usb debug device is attached by getting debug device descriptor.
640 4. set address for the usb debug device.
641 5. configure the usb debug device to debug mode.
643 @param Handle Debug port handle.
645 @retval TRUE The usb debug port hardware configuration is changed.
646 @retval FALSE The usb debug port hardware configuration is not changed.
651 InitializeUsbDebugHardware (
652 IN USB_DEBUG_PORT_HANDLE
*Handle
655 RETURN_STATUS Status
;
656 USB_DEBUG_PORT_REGISTER
*UsbDebugPortRegister
;
657 USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor
;
663 UINT8 DebugPortNumber
;
666 UsbDebugPortRegister
= (USB_DEBUG_PORT_REGISTER
*)(UINTN
)(Handle
->UsbDebugPortMemoryBase
+ Handle
->DebugPortOffset
);
667 PciCmd
= PciRead16 (PcdGet32(PcdUsbEhciPciAddress
) + PCI_COMMAND_OFFSET
);
668 UsbHCSParam
= (UINT32
*)(UINTN
)(Handle
->EhciMemoryBase
+ 0x04);
669 UsbCmd
= (UINT32
*)(UINTN
)(Handle
->EhciMemoryBase
+ 0x20);
670 UsbStatus
= (UINT32
*)(UINTN
)(Handle
->EhciMemoryBase
+ 0x24);
673 // Check if the debug port is enabled and owned by myself.
675 if (((MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
) & (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
))
676 != (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
)) || (Handle
->Initialized
== USBDBG_RESET
)) {
679 "UsbDbg: Need to reset the host controller. ControlStatus = %08x\n",
680 MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
)
683 // If the host controller is halted, then reset and restart it.
685 if ((MmioRead32((UINTN
)UsbStatus
) & BIT12
) != 0) {
686 DEBUG ((EFI_D_INFO
, "UsbDbg: Reset the host controller.\n"));
688 // reset the host controller.
690 MmioOr32((UINTN
)UsbCmd
, BIT1
);
692 // ensure that the host controller is reset.
694 while ((MmioRead32((UINTN
)UsbCmd
) & BIT1
) != 0);
696 MmioOr32((UINTN
)UsbCmd
, BIT0
);
697 // ensure that the host controller is started (HALTED bit must be cleared)
698 while ((MmioRead32((UINTN
)UsbStatus
) & BIT12
) != 0);
702 // First get the ownership of port 0.
704 MmioOr32((UINTN
)&UsbDebugPortRegister
->ControlStatus
, USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
);
706 MicroSecondDelay (200000);
709 // Find out which port is used as debug port.
711 DebugPortNumber
= (UINT8
)((MmioRead32((UINTN
)UsbHCSParam
) & 0x00F00000) >> 20);
713 // Should find a device is connected at debug port
715 PortStatus
= (UINT32
*)(UINTN
)(Handle
->EhciMemoryBase
+ 0x64 + (DebugPortNumber
- 1) * 4);
716 if (!(MmioRead32((UINTN
)PortStatus
) & BIT0
)) {
717 Handle
->Initialized
= USBDBG_NO_DEV
;
718 return RETURN_NOT_FOUND
;
721 if (Handle
->Initialized
!= USBDBG_INIT_DONE
||
722 (MmioRead32 ((UINTN
) &UsbDebugPortRegister
->ControlStatus
) & USB_DEBUG_PORT_ENABLE
) == 0) {
723 DEBUG ((EFI_D_INFO
, "UsbDbg: Reset the debug port.\n"));
725 // Reset the debug port
727 MmioOr32((UINTN
)PortStatus
, BIT8
);
728 MicroSecondDelay (500000);
729 MmioAnd32((UINTN
)PortStatus
, (UINT32
)~BIT8
);
730 while (MmioRead32((UINTN
)PortStatus
) & BIT8
);
733 // The port enabled bit should be set by HW.
735 if ((MmioRead32((UINTN
)PortStatus
) & BIT2
) == 0) {
736 Handle
->Initialized
= USBDBG_NO_DBG_CAB
;
737 return RETURN_DEVICE_ERROR
;
741 // Enable Usb Debug Port Capability
743 MmioOr32((UINTN
)&UsbDebugPortRegister
->ControlStatus
, USB_DEBUG_PORT_ENABLE
);
746 // initialize the data toggle used by bulk in/out endpoint.
748 Handle
->BulkInToggle
= 0;
749 Handle
->BulkOutToggle
= 0;
752 // set usb debug device address as 0x7F.
754 Status
= UsbDebugPortControlTransfer (UsbDebugPortRegister
, &mDebugCommunicationLibUsbSetDebugAddress
, 0x0, 0x0, NULL
, NULL
);
755 if (RETURN_ERROR(Status
)) {
757 // The device can not work well.
759 Handle
->Initialized
= USBDBG_NO_DBG_CAB
;
764 // Start to communicate with Usb Debug Device to see if the attached device is usb debug device or not.
766 Length
= (UINT8
)sizeof (USB_DEBUG_PORT_DESCRIPTOR
);
769 // Get debug descriptor.
771 Status
= UsbDebugPortControlTransfer (UsbDebugPortRegister
, &mDebugCommunicationLibUsbGetDebugDescriptor
, 0x7F, 0x0, (UINT8
*)&UsbDebugPortDescriptor
, &Length
);
772 if (RETURN_ERROR(Status
)) {
774 // The device is not a usb debug device.
776 Handle
->Initialized
= USBDBG_NO_DBG_CAB
;
780 if (Length
!= sizeof(USB_DEBUG_PORT_DESCRIPTOR
)) {
781 Handle
->Initialized
= USBDBG_NO_DBG_CAB
;
782 return RETURN_DEVICE_ERROR
;
786 // enable the usb debug feature.
788 Status
= UsbDebugPortControlTransfer (UsbDebugPortRegister
, &mDebugCommunicationLibUsbSetDebugFeature
, 0x7F, 0x0, NULL
, NULL
);
789 if (RETURN_ERROR(Status
)) {
791 // The device can not work well.
793 Handle
->Initialized
= USBDBG_NO_DBG_CAB
;
797 Handle
->Initialized
= USBDBG_DBG_CAB
;
801 // Set initialized flag
803 Handle
->Initialized
= USBDBG_INIT_DONE
;
805 return RETURN_SUCCESS
;
809 Read data from debug device and save the datas in buffer.
811 Reads NumberOfBytes data bytes from a debug device into the buffer
812 specified by Buffer. The number of bytes actually read is returned.
813 If the return value is less than NumberOfBytes, then the rest operation failed.
814 If NumberOfBytes is zero, then return 0.
816 @param Handle Debug port handle.
817 @param Buffer Pointer to the data buffer to store the data read from the debug device.
818 @param NumberOfBytes Number of bytes which will be read.
819 @param Timeout Timeout value for reading from debug device. It unit is Microsecond.
821 @retval 0 Read data failed, no data is to be read.
822 @retval >0 Actual number of bytes read from debug device.
827 DebugPortReadBuffer (
828 IN DEBUG_PORT_HANDLE Handle
,
830 IN UINTN NumberOfBytes
,
834 USB_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
835 USB_DEBUG_PORT_REGISTER
*UsbDebugPortRegister
;
836 RETURN_STATUS Status
;
843 UINT64 TimeoutTicker
;
846 if (NumberOfBytes
== 0 || Buffer
== NULL
) {
855 // If Handle is NULL, it means memory is ready for use.
856 // Use global variable to store handle value.
858 if (Handle
== NULL
) {
859 UsbDebugPortHandle
= &mDebugCommunicationLibUsbDebugPortHandle
;
861 UsbDebugPortHandle
= (USB_DEBUG_PORT_HANDLE
*)Handle
;
864 if (NeedReinitializeHardware(UsbDebugPortHandle
)) {
865 Status
= InitializeUsbDebugHardware (UsbDebugPortHandle
);
866 if (RETURN_ERROR(Status
)) {
871 UsbDebugPortRegister
= (USB_DEBUG_PORT_REGISTER
*)(UINTN
)(UsbDebugPortHandle
->UsbDebugPortMemoryBase
+ UsbDebugPortHandle
->DebugPortOffset
);
874 // First read data from buffer, then read debug port hw to get received data.
876 if (UsbDebugPortHandle
->DataCount
> 0) {
877 if (NumberOfBytes
<= UsbDebugPortHandle
->DataCount
) {
878 Total
= NumberOfBytes
;
880 Total
= UsbDebugPortHandle
->DataCount
;
883 for (Index
= 0; Index
< Total
; Index
++) {
884 Buffer
[Index
] = UsbDebugPortHandle
->Data
[Index
];
887 for (Index
= 0; Index
< UsbDebugPortHandle
->DataCount
- Total
; Index
++) {
888 if (Total
+ Index
>= 8) {
891 UsbDebugPortHandle
->Data
[Index
] = UsbDebugPortHandle
->Data
[Total
+ Index
];
893 UsbDebugPortHandle
->DataCount
= (UINT8
)(UsbDebugPortHandle
->DataCount
- (UINT8
)Total
);
897 // If Timeout is equal to 0, then it means it should always wait until all datum required are received.
903 Begin
= GetPerformanceCounter ();
904 TimeoutTicker
= DivU64x32 (
906 UsbDebugPortHandle
->TimerFrequency
,
911 TimerRound
= DivU64x64Remainder (
913 DivU64x32 (UsbDebugPortHandle
->TimerCycle
, 2),
919 // Read remaining data by executing one or more usb debug transfer transactions at usb debug port hw.
921 while (Total
< NumberOfBytes
) {
923 if (TimerRound
== 0) {
924 if (IsTimerTimeout (UsbDebugPortHandle
, Begin
, TimeoutTicker
)) {
926 // If time out occurs.
931 if (IsTimerTimeout (UsbDebugPortHandle
, Begin
, DivU64x32 (UsbDebugPortHandle
->TimerCycle
, 2))) {
936 Remaining
= NumberOfBytes
- Total
;
937 if (Remaining
>= USB_DEBUG_PORT_MAX_PACKET_SIZE
) {
938 Status
= UsbDebugPortIn(UsbDebugPortRegister
, Buffer
+ Total
, &Received
, INPUT_PID
, 0x7f, 0x82, UsbDebugPortHandle
->BulkInToggle
);
940 if (RETURN_ERROR(Status
)) {
944 Status
= UsbDebugPortIn(UsbDebugPortRegister
, &UsbDebugPortHandle
->Data
[0], &Received
, INPUT_PID
, 0x7f, 0x82, UsbDebugPortHandle
->BulkInToggle
);
946 if (RETURN_ERROR(Status
)) {
950 UsbDebugPortHandle
->DataCount
= Received
;
952 if (Remaining
<= Received
) {
953 Length
= (UINT8
)Remaining
;
955 Length
= (UINT8
)Received
;
959 // Copy required data from the data buffer to user buffer.
961 for (Index
= 0; Index
< Length
; Index
++) {
962 (Buffer
+ Total
)[Index
] = UsbDebugPortHandle
->Data
[Index
];
963 UsbDebugPortHandle
->DataCount
--;
967 // reorder the data buffer to make available data arranged from the beginning of the data buffer.
969 for (Index
= 0; Index
< Received
- Length
; Index
++) {
970 if (Length
+ Index
>= 8) {
973 UsbDebugPortHandle
->Data
[Index
] = UsbDebugPortHandle
->Data
[Length
+ Index
];
976 // fixup the real received length in Buffer.
980 UsbDebugPortHandle
->BulkInToggle
^= 1;
988 Write data from buffer to debug device.
990 Writes NumberOfBytes data bytes from Buffer to the debug device.
991 The number of bytes actually written to the debug device is returned.
992 If the return value is less than NumberOfBytes, then the write operation failed.
993 If NumberOfBytes is zero, then return 0.
995 @param Handle Debug port handle.
996 @param Buffer Pointer to the data buffer to be written.
997 @param NumberOfBytes Number of bytes to written to the debug device.
999 @retval 0 NumberOfBytes is 0.
1000 @retval >0 The number of bytes written to the debug device.
1001 If this value is less than NumberOfBytes, then the read operation failed.
1006 DebugPortWriteBuffer (
1007 IN DEBUG_PORT_HANDLE Handle
,
1009 IN UINTN NumberOfBytes
1012 USB_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1013 USB_DEBUG_PORT_REGISTER
*UsbDebugPortRegister
;
1014 RETURN_STATUS Status
;
1019 if (NumberOfBytes
== 0 || Buffer
== NULL
) {
1027 // If Handle is NULL, it means memory is ready for use.
1028 // Use global variable to store handle value.
1030 if (Handle
== NULL
) {
1031 UsbDebugPortHandle
= &mDebugCommunicationLibUsbDebugPortHandle
;
1033 UsbDebugPortHandle
= (USB_DEBUG_PORT_HANDLE
*)Handle
;
1036 if (NeedReinitializeHardware(UsbDebugPortHandle
)) {
1037 Status
= InitializeUsbDebugHardware (UsbDebugPortHandle
);
1038 if (RETURN_ERROR(Status
)) {
1043 UsbDebugPortRegister
= (USB_DEBUG_PORT_REGISTER
*)(UINTN
)(UsbDebugPortHandle
->UsbDebugPortMemoryBase
+ UsbDebugPortHandle
->DebugPortOffset
);
1045 while ((Total
< NumberOfBytes
)) {
1046 if (NumberOfBytes
- Total
> USB_DEBUG_PORT_MAX_PACKET_SIZE
) {
1047 Sent
= USB_DEBUG_PORT_MAX_PACKET_SIZE
;
1049 Sent
= (UINT8
)(NumberOfBytes
- Total
);
1052 Status
= UsbDebugPortOut(UsbDebugPortRegister
, Buffer
+ Total
, Sent
, OUTPUT_PID
, 0x7F, 0x01, UsbDebugPortHandle
->BulkOutToggle
);
1054 if (RETURN_ERROR(Status
)) {
1058 ReceivedPid
= (MmioRead8((UINTN
)&UsbDebugPortRegister
->ReceivedPid
));
1060 // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.
1061 // should send the packet again.
1063 if (ReceivedPid
== NAK_PID
) {
1066 UsbDebugPortHandle
->BulkOutToggle
^= 1;
1074 Polls a debug device to see if there is any data waiting to be read.
1076 Polls a debug device to see if there is any data waiting to be read.
1077 If there is data waiting to be read from the debug device, then TRUE is returned.
1078 If there is no data waiting to be read from the debug device, then FALSE is returned.
1080 @param Handle Debug port handle.
1082 @retval TRUE Data is waiting to be read from the debug device.
1083 @retval FALSE There is no data waiting to be read from the serial device.
1088 DebugPortPollBuffer (
1089 IN DEBUG_PORT_HANDLE Handle
1092 USB_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1093 USB_DEBUG_PORT_REGISTER
*UsbDebugPortRegister
;
1096 RETURN_STATUS Status
;
1099 // If Handle is NULL, it means memory is ready for use.
1100 // Use global variable to store handle value.
1102 if (Handle
== NULL
) {
1103 UsbDebugPortHandle
= &mDebugCommunicationLibUsbDebugPortHandle
;
1105 UsbDebugPortHandle
= (USB_DEBUG_PORT_HANDLE
*)Handle
;
1108 if (NeedReinitializeHardware(UsbDebugPortHandle
)) {
1109 Status
= InitializeUsbDebugHardware(UsbDebugPortHandle
);
1110 if (RETURN_ERROR(Status
)) {
1116 // If the data buffer is not empty, then return TRUE directly.
1117 // else initialize a usb read transaction and read data to the data buffer.
1119 if (UsbDebugPortHandle
->DataCount
!= 0) {
1123 UsbDebugPortRegister
= (USB_DEBUG_PORT_REGISTER
*)(UINTN
)(UsbDebugPortHandle
->UsbDebugPortMemoryBase
+ UsbDebugPortHandle
->DebugPortOffset
);
1125 UsbDebugPortRegister
->TokenPid
= INPUT_PID
;
1126 if (UsbDebugPortHandle
->BulkInToggle
== 0) {
1127 UsbDebugPortRegister
->SendPid
= DATA0_PID
;
1129 UsbDebugPortRegister
->SendPid
= DATA1_PID
;
1131 UsbDebugPortRegister
->UsbAddress
= 0x7F;
1132 UsbDebugPortRegister
->UsbEndPoint
= 0x82 & 0x0F;
1135 // Clearing W/R bit to indicate it's a READ operation
1137 MmioAnd32((UINTN
)&UsbDebugPortRegister
->ControlStatus
, (UINT32
)~BIT4
);
1139 // Setting GO bit as well as clearing DONE bit
1141 MmioOr32((UINTN
)&UsbDebugPortRegister
->ControlStatus
, (UINT32
)BIT5
);
1144 // Wait for completing the request
1146 while ((MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
) & (UINT32
)BIT16
) == 0) {
1147 if ((MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
) & (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
))
1148 != (USB_DEBUG_PORT_OWNER
| USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_ENABLE
)) {
1153 if ((MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
)) & BIT6
) {
1157 Length
= (UINT8
)(MmioRead32((UINTN
)&UsbDebugPortRegister
->ControlStatus
) & 0xF);
1163 UsbDebugPortHandle
->BulkInToggle
^= 1;
1169 for (Index
= 0; Index
< Length
; Index
++) {
1170 UsbDebugPortHandle
->Data
[Index
] = UsbDebugPortRegister
->DataBuffer
[Index
];
1172 UsbDebugPortHandle
->DataCount
= Length
;
1178 Initialize the debug port.
1180 If Function is not NULL, Debug Communication Libary will call this function
1181 by passing in the Context to be the first parameter. If needed, Debug Communication
1182 Library will create one debug port handle to be the second argument passing in
1183 calling the Function, otherwise it will pass NULL to be the second argument of
1186 If Function is NULL, and Context is not NULL, the Debug Communication Library could
1187 a) Return the same handle as passed in (as Context parameter).
1188 b) Ignore the input Context parameter and create new hanlde to be returned.
1190 If parameter Function is NULL and Context is NULL, Debug Communication Library could
1191 created a new handle if needed and return it, otherwise it will return NULL.
1193 @param[in] Context Context needed by callback function; it was optional.
1194 @param[in] Function Continue function called by Debug Communication library;
1197 @return The debug port handle created by Debug Communication Library if Function
1203 DebugPortInitialize (
1205 IN DEBUG_PORT_CONTINUE Function
1208 RETURN_STATUS Status
;
1209 USB_DEBUG_PORT_HANDLE Handle
;
1210 USB_DEBUG_PORT_HANDLE
*UsbDebugPortHandle
;
1211 UINT64 TimerStartValue
;
1212 UINT64 TimerEndValue
;
1215 // Validate the PCD PcdDebugPortHandleBufferSize value
1217 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize
) == sizeof (USB_DEBUG_PORT_HANDLE
));
1219 if (Function
== NULL
&& Context
!= NULL
) {
1220 UsbDebugPortHandle
= (USB_DEBUG_PORT_HANDLE
*)Context
;
1222 ZeroMem(&Handle
, sizeof (USB_DEBUG_PORT_HANDLE
));
1223 UsbDebugPortHandle
= &Handle
;
1226 UsbDebugPortHandle
->TimerFrequency
= GetPerformanceCounterProperties (
1230 DEBUG ((EFI_D_INFO
, "USB Debug Port: TimerFrequency = 0x%lx\n", UsbDebugPortHandle
->TimerFrequency
));
1231 DEBUG ((EFI_D_INFO
, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue
));
1232 DEBUG ((EFI_D_INFO
, "USB Debug Port: TimerEndValue = 0x%lx\n", TimerEndValue
));
1234 if (TimerEndValue
< TimerStartValue
) {
1235 UsbDebugPortHandle
->TimerCountDown
= TRUE
;
1236 UsbDebugPortHandle
->TimerCycle
= TimerStartValue
- TimerEndValue
;
1238 UsbDebugPortHandle
->TimerCountDown
= FALSE
;
1239 UsbDebugPortHandle
->TimerCycle
= TimerEndValue
- TimerStartValue
;
1242 if (Function
== NULL
&& Context
!= NULL
) {
1243 return (DEBUG_PORT_HANDLE
*) Context
;
1246 Status
= CalculateUsbDebugPortBar(&Handle
.DebugPortOffset
, &Handle
.DebugPortBarNumber
);
1247 if (RETURN_ERROR (Status
)) {
1248 DEBUG ((EFI_D_ERROR
, "UsbDbg: the pci device pointed by PcdUsbEhciPciAddress is not EHCI host controller or does not support debug port capability!\n"));
1252 Handle
.EhciMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
);
1254 if (Handle
.EhciMemoryBase
== 0) {
1256 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
1258 PciWrite32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
, PcdGet32(PcdUsbEhciMemorySpaceBase
));
1259 Handle
.EhciMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
);
1262 Handle
.UsbDebugPortMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ Handle
.DebugPortBarNumber
* 4);
1264 if (Handle
.UsbDebugPortMemoryBase
== 0) {
1266 // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
1268 PciWrite32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ Handle
.DebugPortBarNumber
* 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase
));
1269 Handle
.UsbDebugPortMemoryBase
= 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress
) + PCI_BASE_ADDRESSREG_OFFSET
+ Handle
.DebugPortBarNumber
* 4);
1272 Handle
.Initialized
= USBDBG_RESET
;
1274 if (NeedReinitializeHardware(&Handle
)) {
1275 DEBUG ((EFI_D_ERROR
, "UsbDbg: Start EHCI debug port initialization!\n"));
1276 Status
= InitializeUsbDebugHardware (&Handle
);
1277 if (RETURN_ERROR(Status
)) {
1278 DEBUG ((EFI_D_ERROR
, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));
1285 if (Function
!= NULL
) {
1286 Function (Context
, &Handle
);
1288 CopyMem(&mDebugCommunicationLibUsbDebugPortHandle
, &Handle
, sizeof (USB_DEBUG_PORT_HANDLE
));
1291 return (DEBUG_PORT_HANDLE
)(UINTN
)&mDebugCommunicationLibUsbDebugPortHandle
;