TianoCore EDK2 master
Loading...
Searching...
No Matches
DebugCommunicationLibUsb3Common.c
Go to the documentation of this file.
1
10
11UINT16 mString0Desc[] = {
12 // String Descriptor Type + Length
13 (USB_DESC_TYPE_STRING << 8) + STRING0_DESC_LEN,
14 0x0409
15};
16
17UINT16 mManufacturerStrDesc[] = {
18 // String Descriptor Type + Length
19 (USB_DESC_TYPE_STRING << 8) + MANU_DESC_LEN,
20 'I', 'n','t', 'e', 'l'
21};
22
23UINT16 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'
27};
28
29UINT16 mSerialNumberStrDesc[] = {
30 // String Descriptor Type + Length
31 (USB_DESC_TYPE_STRING << 8) + SERIAL_DESC_LEN,
32 '1'
33};
34
41VOID
44 IN UINT32 BitMask
45 )
46{
47 UINT32 RegisterValue;
48
49 RegisterValue = MmioRead32 (Register);
50 RegisterValue |= (UINT32)(BitMask);
51 MmioWrite32 (Register, RegisterValue);
52}
53
60VOID
63 IN UINT32 BitMask
64 )
65{
66 UINT32 RegisterValue;
67
68 RegisterValue = MmioRead32 (Register);
69 RegisterValue &= ~BitMask;
70 MmioWrite32 (Register, RegisterValue);
71}
72
81VOID
84 IN UINT32 Offset,
85 IN UINT32 Data
86 )
87{
88 EFI_PHYSICAL_ADDRESS DebugCapabilityBase;
89
90 DebugCapabilityBase = Handle->DebugCapabilityBase;
91 MmioWrite32 ((UINTN)(DebugCapabilityBase + Offset), Data);
92
93 return;
94}
95
105UINT32
108 IN UINT32 Offset
109 )
110{
111 UINT32 Data;
112 EFI_PHYSICAL_ADDRESS DebugCapabilityBase;
113
114 DebugCapabilityBase = Handle->DebugCapabilityBase;
115 Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));
116
117 return Data;
118}
119
128VOID
131 IN UINT32 Offset,
132 IN UINT32 Bit
133 )
134{
135 UINT32 Data;
136
137 Data = XhcReadDebugReg (Handle, Offset);
138 Data |= Bit;
139 XhcWriteDebugReg (Handle, Offset, Data);
140}
141
150VOID
153 IN UINT32 Offset,
154 IN UINT32 Bit
155 )
156{
157 UINT32 Data;
158
159 Data = XhcReadDebugReg (Handle, Offset);
160 Data &= ~Bit;
161 XhcWriteDebugReg (Handle, Offset, Data);
162}
163
172 VOID
173 )
174{
175 UINT16 PciCmd;
176 UINT32 Low;
177 UINT32 High;
178 EFI_PHYSICAL_ADDRESS XhciMmioBase;
179
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;
184
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));
189 }
190
191 PciCmd = PciRead16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET);
192 if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
194 PciWrite16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
195 }
196
197 return XhciMmioBase;
198}
199
207VOID
210 IN EFI_PHYSICAL_ADDRESS XhciMmioBase
211 )
212{
213 if (Handle == NULL) {
214 return;
215 }
216
217 //
218 // Need fix Handle data according to new XHCI MMIO base address.
219 //
220 Handle->XhciMmioBase = XhciMmioBase;
221 Handle->DebugCapabilityBase = XhciMmioBase + Handle->DebugCapabilityOffset;
222 Handle->XhciOpRegister = XhciMmioBase + MmioRead8 ((UINTN)XhciMmioBase);
223}
224
234RETURN_STATUS
235EFIAPI
238 )
239{
240 UINT16 VendorId;
241 UINT16 DeviceId;
242 UINT8 ProgInterface;
243 UINT8 SubClassCode;
244 UINT8 BaseCode;
245 BOOLEAN Flag;
246 UINT32 Capability;
247 EFI_PHYSICAL_ADDRESS CapabilityPointer;
248 UINT8 CapLength;
249
250 if (Handle->Initialized != USB3DBG_UNINITIALIZED) {
251 if (Handle->Initialized == USB3DBG_NO_DBG_CAB) {
252 return RETURN_UNSUPPORTED;
253 } else {
254 return RETURN_SUCCESS;
255 }
256 }
257
258 VendorId = PciRead16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_VENDOR_ID_OFFSET);
259 DeviceId = PciRead16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_DEVICE_ID_OFFSET);
260
261 if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {
262 goto Done;
263 }
264
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);
268
269 if ((ProgInterface != PCI_IF_XHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {
270 goto Done;
271 }
272
273 CapLength = MmioRead8 ((UINTN)Handle->XhciMmioBase);
274
275 //
276 // Get capability pointer from HCCPARAMS at offset 0x10
277 //
278 CapabilityPointer = Handle->XhciMmioBase + (MmioRead32 ((UINTN)(Handle->XhciMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
279
280 //
281 // Search XHCI debug capability
282 //
283 Flag = FALSE;
284 Capability = MmioRead32 ((UINTN)CapabilityPointer);
285 while (TRUE) {
286 if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
287 Flag = TRUE;
288 break;
289 }
290
291 if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
292 //
293 // Reach the end of capability list, quit
294 //
295 break;
296 }
297
298 CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
299 Capability = MmioRead32 ((UINTN)CapabilityPointer);
300 }
301
302 if (!Flag) {
303 goto Done;
304 }
305
306 //
307 // USB3 debug capability is supported.
308 //
309 Handle->DebugCapabilityBase = CapabilityPointer;
310 Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;
311 Handle->XhciOpRegister = Handle->XhciMmioBase + CapLength;
312 Handle->DebugSupport = TRUE;
313 Handle->Initialized = USB3DBG_DBG_CAB;
314 return RETURN_SUCCESS;
315
316Done:
317 Handle->Initialized = USB3DBG_NO_DBG_CAB;
318 return RETURN_UNSUPPORTED;
319}
320
334BOOLEAN
335EFIAPI
338 )
339{
340 BOOLEAN Result;
341 volatile UINT32 Dcctrl;
342
343 Result = FALSE;
344
345 //
346 // If DCE bit, it means USB3 debug is not enabled.
347 //
348 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
349 if ((Dcctrl & BIT0) == 0) {
350 Result = TRUE;
351 } else if (!Handle->Ready) {
352 Handle->Ready = TRUE;
353 Handle->Initialized = USB3DBG_ENABLED;
354 }
355
356 return Result;
357}
358
369 OUT EVENT_RING *EventRing
370 )
371{
372 VOID *Buf;
374
375 ASSERT (EventRing != NULL);
376
377 //
378 // Allocate Event Ring
379 //
380 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
381 ASSERT (Buf != NULL);
382 ASSERT (((UINTN)Buf & 0x3F) == 0);
383 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
384
385 EventRing->EventRingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN)Buf;
386 EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;
387 EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN)EventRing->EventRingSeg0;
388 EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EventRing->EventRingSeg0;
389
390 //
391 // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
392 // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
393 //
394 EventRing->EventRingCCS = 1;
395
396 //
397 // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
398 //
399 Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
400 ASSERT (Buf != NULL);
401 ASSERT (((UINTN)Buf & 0x3F) == 0);
402 ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
403
404 ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *)Buf;
405 EventRing->ERSTBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ERSTBase;
406
407 //
408 // Fill Event Segment address
409 //
410 ERSTBase->PtrLo = XHC_LOW_32BIT (EventRing->EventRingSeg0);
411 ERSTBase->PtrHi = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
412 ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
413
414 //
415 // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
416 //
418 Handle,
419 XHC_DC_DCERDP,
420 XHC_LOW_32BIT ((UINT64)(UINTN)EventRing->EventRingDequeue)
421 );
422
424 Handle,
425 XHC_DC_DCERDP + 4,
426 XHC_HIGH_32BIT ((UINT64)(UINTN)EventRing->EventRingDequeue)
427 );
428
429 //
430 // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
431 //
433 Handle,
434 XHC_DC_DCERSTBA,
435 XHC_LOW_32BIT ((UINT64)(UINTN)ERSTBase)
436 );
437
439 Handle,
440 XHC_DC_DCERSTBA + 4,
441 XHC_HIGH_32BIT ((UINT64)(UINTN)ERSTBase)
442 );
443
444 //
445 // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
446 //
448 Handle,
449 XHC_DC_DCERSTSZ,
450 ERST_NUMBER
451 );
452 return EFI_SUCCESS;
453}
454
463VOID
466 IN UINT32 TrbNum,
467 OUT TRANSFER_RING *TransferRing
468 )
469{
470 VOID *Buf;
471 LINK_TRB *EndTrb;
472
473 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
474 ASSERT (Buf != NULL);
475 ASSERT (((UINTN)Buf & 0xF) == 0);
476 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
477
478 TransferRing->RingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN)Buf;
479 TransferRing->TrbNumber = TrbNum;
480 TransferRing->RingEnqueue = TransferRing->RingSeg0;
481 TransferRing->RingDequeue = TransferRing->RingSeg0;
482 TransferRing->RingPCS = 1;
483 //
484 // 4.9.2 Transfer Ring Management
485 // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
486 // point to the first TRB in the ring.
487 //
488 EndTrb = (LINK_TRB *)((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
489 EndTrb->Type = TRB_TYPE_LINK;
490 EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
491 EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
492 //
493 // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
494 //
495 EndTrb->TC = 1;
496 //
497 // Set Cycle bit as other TRB PCS init value
498 //
499 EndTrb->CycleBit = 0;
500}
501
514 )
515{
516 VOID *Buf;
517 XHC_DC_CONTEXT *DebugCapabilityContext;
518 UINT8 *String0Desc;
519 UINT8 *ManufacturerStrDesc;
520 UINT8 *ProductStrDesc;
521 UINT8 *SerialNumberStrDesc;
522
523 //
524 // Allocate debug device context
525 //
526 Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
527 ASSERT (Buf != NULL);
528 ASSERT (((UINTN)Buf & 0xF) == 0);
529 ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
530
531 DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN)Buf;
532 Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN)DebugCapabilityContext;
533
534 //
535 // Initialize DbcInfoContext.
536 //
537 DebugCapabilityContext->DbcInfoContext.String0Length = STRING0_DESC_LEN;
538 DebugCapabilityContext->DbcInfoContext.ManufacturerStrLength = MANU_DESC_LEN;
539 DebugCapabilityContext->DbcInfoContext.ProductStrLength = PRODUCT_DESC_LEN;
540 DebugCapabilityContext->DbcInfoContext.SerialNumberStrLength = SERIAL_DESC_LEN;
541
542 //
543 // Initialize EpOutContext.
544 //
545 DebugCapabilityContext->EpOutContext.CErr = 0x3;
546 DebugCapabilityContext->EpOutContext.EPType = ED_BULK_OUT;
547 DebugCapabilityContext->EpOutContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
548 DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;
549
550 //
551 // Initialize EpInContext.
552 //
553 DebugCapabilityContext->EpInContext.CErr = 0x3;
554 DebugCapabilityContext->EpInContext.EPType = ED_BULK_IN;
555 DebugCapabilityContext->EpInContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
556 DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;
557
558 //
559 // Update string descriptor address
560 //
561 String0Desc = (UINT8 *)AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
562 ASSERT (String0Desc != NULL);
563 ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
564 CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
565 DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
566
567 ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
568 CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
569 DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
570
571 ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
572 CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
573 DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
574
575 SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
576 CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
577 DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
578
579 //
580 // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
581 //
582 ZeroMem (&Handle->TransferRingIn, sizeof (TRANSFER_RING));
583 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingIn);
584 DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingIn.RingSeg0) | BIT0;
585 DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingIn.RingSeg0);
586
587 //
588 // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
589 //
590 ZeroMem (&Handle->TransferRingOut, sizeof (TRANSFER_RING));
591 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingOut);
592 DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingOut.RingSeg0) | BIT0;
593 DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingOut.RingSeg0);
594
595 //
596 // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
597 //
599 Handle,
600 XHC_DC_DCCP,
601 XHC_LOW_32BIT ((UINT64)(UINTN)DebugCapabilityContext)
602 );
604 Handle,
605 XHC_DC_DCCP + 4,
606 XHC_HIGH_32BIT ((UINT64)(UINTN)DebugCapabilityContext)
607 );
608 return EFI_SUCCESS;
609}
610
617VOID
620 )
621{
622 UINT64 TimeOut;
623 volatile UINT32 Dcctrl;
624
625 TimeOut = 1;
626 if (Handle->Initialized == USB3DBG_DBG_CAB) {
627 //
628 // As detection is slow in seconds, wait for longer timeout for the first time.
629 // If first initialization is failed, we will try to enable debug device in the
630 // Poll function invoked by timer.
631 //
632 TimeOut = DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout), XHC_POLL_DELAY) + 1;
633 }
634
635 do {
636 //
637 // Check if debug device is in configured state
638 //
639 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
640 if ((Dcctrl & BIT0) != 0) {
641 //
642 // Set the flag to indicate debug device is in configured state
643 //
644 Handle->Ready = TRUE;
645 break;
646 }
647
648 MicroSecondDelay (XHC_POLL_DELAY);
649 TimeOut--;
650 } while (TimeOut != 0);
651}
652
662RETURN_STATUS
663EFIAPI
666 )
667{
668 RETURN_STATUS Status;
669 UINT8 *Buffer;
670 UINTN Index;
671 UINT8 TotalUsb3Port;
672 EFI_PHYSICAL_ADDRESS XhciOpRegister;
673 UINT32 Dcddi1;
674
675 XhciOpRegister = Handle->XhciOpRegister;
676 TotalUsb3Port = MmioRead32 (((UINTN)Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;
677
678 if (Handle->Initialized == USB3DBG_NOT_ENABLED) {
679 Dcddi1 = XhcReadDebugReg (Handle, XHC_DC_DCDDI1);
680 if (Dcddi1 != (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)) {
681 //
682 // The debug capability has been reset by other code, return device error.
683 //
684 return EFI_DEVICE_ERROR;
685 }
686
687 //
688 // If XHCI supports debug capability, hardware resource has been allocated,
689 // but it has not been enabled, try to enable again.
690 //
691 goto Enable;
692 }
693
694 //
695 // Initialize for PEI phase when AllocatePages can work.
696 // Allocate data buffer with max packet size for data read and data poll.
697 // Allocate data buffer for data write.
698 //
699 Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);
700 if (Buffer == NULL) {
701 //
702 // AllocatePages can not still work now, return fail and do not initialize now.
703 //
704 return RETURN_NOT_READY;
705 }
706
707 //
708 // Reset port to get debug device discovered
709 //
710 for (Index = 0; Index < TotalUsb3Port; Index++) {
711 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT4);
712 MicroSecondDelay (10 * 1000);
713 }
714
715 //
716 // Clear DCE bit and LSE bit in DCCTRL
717 //
718 if ((XhcReadDebugReg (Handle, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {
719 XhcClearDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
720 }
721
722 //
723 // Construct the buffer for read, poll and write.
724 //
725 Handle->UrbIn.Data = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
726 Handle->Data = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
727 Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;
728
729 //
730 // Initialize event ring
731 //
732 ZeroMem (&Handle->EventRing, sizeof (EVENT_RING));
733 Status = CreateEventRing (Handle, &Handle->EventRing);
734 ASSERT_EFI_ERROR (Status);
735
736 //
737 // Init IN and OUT endpoint context
738 //
739 Status = CreateDebugCapabilityContext (Handle);
740 ASSERT_EFI_ERROR (Status);
741
742 //
743 // Init DCDDI1 and DCDDI2
744 //
746 Handle,
747 XHC_DC_DCDDI1,
748 (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
749 );
750
752 Handle,
753 XHC_DC_DCDDI2,
754 (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
755 );
756
757Enable:
758 if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {
759 //
760 // If the first time detection is failed, turn port power off and on in order to
761 // reset port status this time, then try to check if debug device is ready again.
762 //
763 for (Index = 0; Index < TotalUsb3Port; Index++) {
764 XhcClearR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
765 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
766 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
767 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
768 Handle->ChangePortPower = TRUE;
769 }
770 }
771
772 //
773 // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
774 //
775 XhcSetDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
776
778
779 Status = RETURN_SUCCESS;
780 if (!Handle->Ready) {
781 Handle->Initialized = USB3DBG_NOT_ENABLED;
782 Status = RETURN_NOT_READY;
783 } else {
784 Handle->Initialized = USB3DBG_ENABLED;
785 }
786
787 return Status;
788}
789
796VOID
799 )
800{
801 EFI_STATUS Status;
802 EFI_PHYSICAL_ADDRESS XhciMmioBase;
803
804 //
805 // Read 64-bit MMIO base address
806 //
807 XhciMmioBase = ProgramXhciBaseAddress ();
808 Handle->XhciMmioBase = XhciMmioBase;
809
810 Status = CalculateUsbDebugPortMmioBase (Handle);
811 if (!RETURN_ERROR (Status)) {
812 UpdateXhcResource (Handle, XhciMmioBase);
813 if (NeedReinitializeHardware (Handle)) {
815 }
816 }
817}
818
825VOID
827 IN USB3_DEBUG_PORT_HANDLE *Instance
828 )
829{
830 EFI_PHYSICAL_ADDRESS *AddrPtr;
831
833 ASSERT (AddrPtr != NULL);
834 *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;
835}
836
843 VOID
844 )
845{
846 EFI_PHYSICAL_ADDRESS *AddrPtr;
847 USB3_DEBUG_PORT_HANDLE *Instance;
848
850 ASSERT (AddrPtr != NULL);
851
852 Instance = (USB3_DEBUG_PORT_HANDLE *)(UINTN)*AddrPtr;
853
854 return Instance;
855}
856
874UINTN
875EFIAPI
877 IN DEBUG_PORT_HANDLE Handle,
878 IN UINT8 *Buffer,
879 IN UINTN NumberOfBytes,
880 IN UINTN Timeout
881 )
882{
883 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
884 UINT8 Index;
885 UINT8 *Data;
886
887 if ((NumberOfBytes != 1) || (Buffer == NULL) || (Timeout != 0)) {
888 return 0;
889 }
890
891 //
892 // If Handle is NULL, get own instance.
893 // If Handle is not NULL, use it and set the instance.
894 //
895 if (Handle != NULL) {
896 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
897 SetUsb3DebugPortInstance (UsbDebugPortHandle);
898 } else {
899 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
900 }
901
902 if (UsbDebugPortHandle == NULL) {
903 return 0;
904 }
905
906 if (UsbDebugPortHandle->InNotify) {
907 return 0;
908 }
909
910 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
911
912 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
913 return 0;
914 }
915
916 Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;
917
918 //
919 // Read data from buffer
920 //
921 if (UsbDebugPortHandle->DataCount < 1) {
922 return 0;
923 } else {
924 *Buffer = Data[0];
925
926 for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
927 if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
928 return 0;
929 }
930
931 Data[Index] = Data[Index + 1];
932 }
933
934 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
935 return 1;
936 }
937}
938
956UINTN
957EFIAPI
959 IN DEBUG_PORT_HANDLE Handle,
960 IN UINT8 *Buffer,
961 IN UINTN NumberOfBytes
962 )
963{
964 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
965 UINTN Sent;
966 UINTN Total;
967
968 if ((NumberOfBytes == 0) || (Buffer == NULL)) {
969 return 0;
970 }
971
972 Sent = 0;
973 Total = 0;
974
975 //
976 // If Handle is NULL, get own instance.
977 // If Handle is not NULL, use it and set the instance.
978 //
979 if (Handle != NULL) {
980 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
981 SetUsb3DebugPortInstance (UsbDebugPortHandle);
982 } else {
983 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
984 }
985
986 if (UsbDebugPortHandle == NULL) {
987 return 0;
988 }
989
990 if (UsbDebugPortHandle->InNotify) {
991 return 0;
992 }
993
994 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
995
996 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
997 return 0;
998 }
999
1000 //
1001 // When host is trying to send data, write will be blocked.
1002 // Poll to see if there is any data sent by host at first.
1003 //
1004 DebugPortPollBuffer (UsbDebugPortHandle);
1005
1006 while ((Total < NumberOfBytes)) {
1007 if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {
1008 Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;
1009 } else {
1010 Sent = (UINT8)(NumberOfBytes - Total);
1011 }
1012
1013 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);
1014 Total += Sent;
1015 }
1016
1017 return Total;
1018}
1019
1033BOOLEAN
1034EFIAPI
1036 IN DEBUG_PORT_HANDLE Handle
1037 )
1038{
1039 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
1040 UINTN Length;
1041
1042 //
1043 // If Handle is NULL, get own instance.
1044 // If Handle is not NULL, use it and set the instance.
1045 //
1046 if (Handle != NULL) {
1047 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;
1048 SetUsb3DebugPortInstance (UsbDebugPortHandle);
1049 } else {
1050 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1051 }
1052
1053 if (UsbDebugPortHandle == NULL) {
1054 return FALSE;
1055 }
1056
1057 if (UsbDebugPortHandle->InNotify) {
1058 return FALSE;
1059 }
1060
1061 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1062
1063 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
1064 return FALSE;
1065 }
1066
1067 //
1068 // If the data buffer is not empty, then return TRUE directly.
1069 // Otherwise initialize a usb read transaction and read data to internal data buffer.
1070 //
1071 if (UsbDebugPortHandle->DataCount != 0) {
1072 return TRUE;
1073 }
1074
1075 //
1076 // Read data as much as we can
1077 //
1078 Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
1079 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);
1080
1081 if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
1082 return FALSE;
1083 }
1084
1085 if (Length == 0) {
1086 return FALSE;
1087 }
1088
1089 //
1090 // Store data into internal buffer for use later
1091 //
1092 UsbDebugPortHandle->DataCount = (UINT8)Length;
1093 return TRUE;
1094}
1095
1120DEBUG_PORT_HANDLE
1121EFIAPI
1123 IN VOID *Context,
1124 IN DEBUG_PORT_CONTINUE Function
1125 )
1126{
1127 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
1128
1129 //
1130 // Validate the PCD PcdDebugPortHandleBufferSize value
1131 //
1132 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));
1133
1134 if ((Function == NULL) && (Context != NULL)) {
1136 return (DEBUG_PORT_HANDLE)Context;
1137 }
1138
1139 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1140 if (UsbDebugPortHandle == NULL) {
1141 return NULL;
1142 }
1143
1144 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1145
1146 if (Function != NULL) {
1147 Function (Context, (DEBUG_PORT_HANDLE)UsbDebugPortHandle);
1148 }
1149
1150 return (DEBUG_PORT_HANDLE)UsbDebugPortHandle;
1151}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID(EFIAPI * DEBUG_PORT_CONTINUE)(IN VOID *Context, IN DEBUG_PORT_HANDLE DebugPortHandle)
VOID CreateTransferRing(IN USB3_DEBUG_PORT_HANDLE *Handle, IN UINT32 TrbNum, OUT TRANSFER_RING *TransferRing)
RETURN_STATUS EFIAPI CalculateUsbDebugPortMmioBase(USB3_DEBUG_PORT_HANDLE *Handle)
VOID XhcSetDebugRegBit(IN USB3_DEBUG_PORT_HANDLE *Handle, IN UINT32 Offset, IN UINT32 Bit)
VOID XhcDetectDebugCapabilityReady(IN USB3_DEBUG_PORT_HANDLE *Handle)
VOID XhcClearR32Bit(IN OUT UINTN Register, IN UINT32 BitMask)
USB3_DEBUG_PORT_HANDLE * GetUsb3DebugPortInstance(VOID)
DEBUG_PORT_HANDLE EFIAPI DebugPortInitialize(IN VOID *Context, IN DEBUG_PORT_CONTINUE Function)
UINTN EFIAPI DebugPortReadBuffer(IN DEBUG_PORT_HANDLE Handle, IN UINT8 *Buffer, IN UINTN NumberOfBytes, IN UINTN Timeout)
EFI_STATUS CreateDebugCapabilityContext(IN USB3_DEBUG_PORT_HANDLE *Handle)
VOID SetUsb3DebugPortInstance(IN USB3_DEBUG_PORT_HANDLE *Instance)
VOID XhcSetR32Bit(IN OUT UINTN Register, IN UINT32 BitMask)
UINT32 XhcReadDebugReg(IN USB3_DEBUG_PORT_HANDLE *Handle, IN UINT32 Offset)
EFI_PHYSICAL_ADDRESS ProgramXhciBaseAddress(VOID)
BOOLEAN EFIAPI DebugPortPollBuffer(IN DEBUG_PORT_HANDLE Handle)
EFI_STATUS CreateEventRing(IN USB3_DEBUG_PORT_HANDLE *Handle, OUT EVENT_RING *EventRing)
VOID UpdateXhcResource(IN OUT USB3_DEBUG_PORT_HANDLE *Handle, IN EFI_PHYSICAL_ADDRESS XhciMmioBase)
VOID XhcClearDebugRegBit(IN USB3_DEBUG_PORT_HANDLE *Handle, IN UINT32 Offset, IN UINT32 Bit)
VOID XhcWriteDebugReg(IN USB3_DEBUG_PORT_HANDLE *Handle, IN UINT32 Offset, IN UINT32 Data)
RETURN_STATUS EFIAPI InitializeUsbDebugHardware(IN USB3_DEBUG_PORT_HANDLE *Handle)
VOID DiscoverInitializeUsbDebugPort(IN USB3_DEBUG_PORT_HANDLE *Handle)
UINTN EFIAPI DebugPortWriteBuffer(IN DEBUG_PORT_HANDLE Handle, IN UINT8 *Buffer, IN UINTN NumberOfBytes)
BOOLEAN EFIAPI NeedReinitializeHardware(IN USB3_DEBUG_PORT_HANDLE *Handle)
VOID * AllocateAlignBuffer(IN UINTN BufferSize)
EFI_PHYSICAL_ADDRESS * GetUsb3DebugPortInstanceAddrPtr(VOID)
EFI_STATUS EFIAPI XhcDataTransfer(IN USB3_DEBUG_PORT_HANDLE *Handle, IN EFI_USB_DATA_DIRECTION Direction, IN OUT VOID *Data, IN OUT UINTN *DataLength, IN UINTN Timeout)
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_NOT_READY
Definition: Base.h:1098
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
UINT32 EFIAPI PciRead32(IN UINTN Address)
Definition: PciLib.c:739
UINT8 EFIAPI PciRead8(IN UINTN Address)
Definition: PciLib.c:62
UINT32 EFIAPI PciWrite32(IN UINTN Address, IN UINT32 Value)
Definition: PciLib.c:765
UINT16 EFIAPI PciWrite16(IN UINTN Address, IN UINT16 Value)
Definition: PciLib.c:422
UINT16 EFIAPI PciRead16(IN UINTN Address)
Definition: PciLib.c:396
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define EFI_PCI_COMMAND_MEMORY_SPACE
0x0002
Definition: Pci22.h:592
#define EFI_PCI_COMMAND_BUS_MASTER
0x0004
Definition: Pci22.h:593
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112