]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Common.c
1 /** @file
2 Debug Port Library implementation based on usb3 debug port.
3
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "DebugCommunicationLibUsb3Internal.h"
10
11 UINT16 mString0Desc[] = {
12 // String Descriptor Type + Length
13 (USB_DESC_TYPE_STRING << 8) + STRING0_DESC_LEN,
14 0x0409
15 };
16
17 UINT16 mManufacturerStrDesc[] = {
18 // String Descriptor Type + Length
19 (USB_DESC_TYPE_STRING << 8) + MANU_DESC_LEN,
20 'I', 'n','t', 'e', 'l'
21 };
22
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'
27 };
28
29 UINT16 mSerialNumberStrDesc[] = {
30 // String Descriptor Type + Length
31 (USB_DESC_TYPE_STRING << 8) + SERIAL_DESC_LEN,
32 '1'
33 };
34
35 /**
36 Sets bits as per the enabled bit positions in the mask.
37
38 @param[in, out] Register UINTN register
39 @param[in] BitMask 32-bit mask
40 **/
41 VOID
42 XhcSetR32Bit (
43 IN OUT UINTN Register,
44 IN UINT32 BitMask
45 )
46 {
47 UINT32 RegisterValue;
48
49 RegisterValue = MmioRead32 (Register);
50 RegisterValue |= (UINT32)(BitMask);
51 MmioWrite32 (Register, RegisterValue);
52 }
53
54 /**
55 Clears bits as per the enabled bit positions in the mask.
56
57 @param[in, out] Register UINTN register
58 @param[in] BitMask 32-bit mask
59 **/
60 VOID
61 XhcClearR32Bit (
62 IN OUT UINTN Register,
63 IN UINT32 BitMask
64 )
65 {
66 UINT32 RegisterValue;
67
68 RegisterValue = MmioRead32 (Register);
69 RegisterValue &= ~BitMask;
70 MmioWrite32 (Register, RegisterValue);
71 }
72
73 /**
74 Write the data to the XHCI debug register.
75
76 @param Handle Debug port handle.
77 @param Offset The offset of the debug register.
78 @param Data The data to write.
79
80 **/
81 VOID
82 XhcWriteDebugReg (
83 IN USB3_DEBUG_PORT_HANDLE *Handle,
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
96 /**
97 Read XHCI debug register.
98
99 @param Handle Debug port handle.
100 @param Offset The offset of the runtime register.
101
102 @return The register content read
103
104 **/
105 UINT32
106 XhcReadDebugReg (
107 IN USB3_DEBUG_PORT_HANDLE *Handle,
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
120 /**
121 Set one bit of the debug register while keeping other bits.
122
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.
126
127 **/
128 VOID
129 XhcSetDebugRegBit (
130 IN USB3_DEBUG_PORT_HANDLE *Handle,
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
142 /**
143 Clear one bit of the debug register while keeping other bits.
144
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.
148
149 **/
150 VOID
151 XhcClearDebugRegBit (
152 IN USB3_DEBUG_PORT_HANDLE *Handle,
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
164 /**
165 Program and enable XHCI MMIO base address.
166
167 @return XHCI MMIO base address.
168
169 **/
170 EFI_PHYSICAL_ADDRESS
171 ProgramXhciBaseAddress (
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)) {
193 PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;
194 PciWrite16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);
195 }
196
197 return XhciMmioBase;
198 }
199
200 /**
201 Update XHC MMIO base address when MMIO base address is changed.
202
203 @param Handle Debug port handle.
204 @param XhciMmioBase XHCI MMIO base address.
205
206 **/
207 VOID
208 UpdateXhcResource (
209 IN OUT USB3_DEBUG_PORT_HANDLE *Handle,
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
225 /**
226 Calculate the usb debug port bar address.
227
228 @param Handle Debug port handle.
229
230 @retval RETURN_UNSUPPORTED The usb host controller does not support usb debug port capability.
231 @retval RETURN_SUCCESS Get bar and offset successfully.
232
233 **/
234 RETURN_STATUS
235 EFIAPI
236 CalculateUsbDebugPortMmioBase (
237 USB3_DEBUG_PORT_HANDLE *Handle
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
316 Done:
317 Handle->Initialized = USB3DBG_NO_DBG_CAB;
318 return RETURN_UNSUPPORTED;
319 }
320
321 /**
322 Check if it needs to re-initialize usb debug port hardware.
323
324 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
325 whether the usb debug port hardware configuration is changed. Such case can be triggered by
326 Pci bus resource allocation and so on.
327
328 @param Handle Debug port handle.
329
330 @retval TRUE The usb debug port hardware configuration is changed.
331 @retval FALSE The usb debug port hardware configuration is not changed.
332
333 **/
334 BOOLEAN
335 EFIAPI
336 NeedReinitializeHardware (
337 IN USB3_DEBUG_PORT_HANDLE *Handle
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
359 /**
360 Create XHCI event ring.
361
362 @param Handle Debug port handle.
363 @param EventRing The created event ring.
364
365 **/
366 EFI_STATUS
367 CreateEventRing (
368 IN USB3_DEBUG_PORT_HANDLE *Handle,
369 OUT EVENT_RING *EventRing
370 )
371 {
372 VOID *Buf;
373 EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;
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 //
417 XhcWriteDebugReg (
418 Handle,
419 XHC_DC_DCERDP,
420 XHC_LOW_32BIT ((UINT64)(UINTN)EventRing->EventRingDequeue)
421 );
422
423 XhcWriteDebugReg (
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 //
432 XhcWriteDebugReg (
433 Handle,
434 XHC_DC_DCERSTBA,
435 XHC_LOW_32BIT ((UINT64)(UINTN)ERSTBase)
436 );
437
438 XhcWriteDebugReg (
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 //
447 XhcWriteDebugReg (
448 Handle,
449 XHC_DC_DCERSTSZ,
450 ERST_NUMBER
451 );
452 return EFI_SUCCESS;
453 }
454
455 /**
456 Create XHCI transfer ring.
457
458 @param Handle Debug port handle.
459 @param TrbNum The number of TRB in the ring.
460 @param TransferRing The created transfer ring.
461
462 **/
463 VOID
464 CreateTransferRing (
465 IN USB3_DEBUG_PORT_HANDLE *Handle,
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
502 /**
503 Create debug capability context for XHC debug device.
504
505 @param Handle Debug port handle.
506
507 @retval EFI_SUCCESS The bit successfully changed by host controller.
508 @retval EFI_TIMEOUT The time out occurred.
509
510 **/
511 EFI_STATUS
512 CreateDebugCapabilityContext (
513 IN USB3_DEBUG_PORT_HANDLE *Handle
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 //
598 XhcWriteDebugReg (
599 Handle,
600 XHC_DC_DCCP,
601 XHC_LOW_32BIT ((UINT64)(UINTN)DebugCapabilityContext)
602 );
603 XhcWriteDebugReg (
604 Handle,
605 XHC_DC_DCCP + 4,
606 XHC_HIGH_32BIT ((UINT64)(UINTN)DebugCapabilityContext)
607 );
608 return EFI_SUCCESS;
609 }
610
611 /**
612 Check if debug device is running.
613
614 @param Handle Debug port handle.
615
616 **/
617 VOID
618 XhcDetectDebugCapabilityReady (
619 IN USB3_DEBUG_PORT_HANDLE *Handle
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
653 /**
654 Initialize usb debug port hardware.
655
656 @param Handle Debug port handle.
657
658 @retval TRUE The usb debug port hardware configuration is changed.
659 @retval FALSE The usb debug port hardware configuration is not changed.
660
661 **/
662 RETURN_STATUS
663 EFIAPI
664 InitializeUsbDebugHardware (
665 IN USB3_DEBUG_PORT_HANDLE *Handle
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 //
745 XhcWriteDebugReg (
746 Handle,
747 XHC_DC_DCDDI1,
748 (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
749 );
750
751 XhcWriteDebugReg (
752 Handle,
753 XHC_DC_DCDDI2,
754 (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
755 );
756
757 Enable:
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
777 XhcDetectDebugCapabilityReady (Handle);
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
790 /**
791 Discover and initialize usb debug port.
792
793 @param Handle Debug port handle.
794
795 **/
796 VOID
797 DiscoverInitializeUsbDebugPort (
798 IN USB3_DEBUG_PORT_HANDLE *Handle
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)) {
814 InitializeUsbDebugHardware (Handle);
815 }
816 }
817 }
818
819 /**
820 Set USB3 debug instance address.
821
822 @param[in] Instance Debug port instance.
823
824 **/
825 VOID
826 SetUsb3DebugPortInstance (
827 IN USB3_DEBUG_PORT_HANDLE *Instance
828 )
829 {
830 EFI_PHYSICAL_ADDRESS *AddrPtr;
831
832 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
833 ASSERT (AddrPtr != NULL);
834 *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;
835 }
836
837 /**
838 Return USB3 debug instance address.
839
840 **/
841 USB3_DEBUG_PORT_HANDLE *
842 GetUsb3DebugPortInstance (
843 VOID
844 )
845 {
846 EFI_PHYSICAL_ADDRESS *AddrPtr;
847 USB3_DEBUG_PORT_HANDLE *Instance;
848
849 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
850 ASSERT (AddrPtr != NULL);
851
852 Instance = (USB3_DEBUG_PORT_HANDLE *)(UINTN)*AddrPtr;
853
854 return Instance;
855 }
856
857 /**
858 Read data from debug device and save the data in buffer.
859
860 Reads NumberOfBytes data bytes from a debug device into the buffer
861 specified by Buffer. The number of bytes actually read is returned.
862 If the return value is less than NumberOfBytes, then the rest operation failed.
863 If NumberOfBytes is zero, then return 0.
864
865 @param Handle Debug port handle.
866 @param Buffer Pointer to the data buffer to store the data read from the debug device.
867 @param NumberOfBytes Number of bytes which will be read.
868 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.
869
870 @retval 0 Read data failed, no data is to be read.
871 @retval >0 Actual number of bytes read from debug device.
872
873 **/
874 UINTN
875 EFIAPI
876 DebugPortReadBuffer (
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
939 /**
940 Write data from buffer to debug device.
941
942 Writes NumberOfBytes data bytes from Buffer to the debug device.
943 The number of bytes actually written to the debug device is returned.
944 If the return value is less than NumberOfBytes, then the write operation failed.
945 If NumberOfBytes is zero, then return 0.
946
947 @param Handle Debug port handle.
948 @param Buffer Pointer to the data buffer to be written.
949 @param NumberOfBytes Number of bytes to written to the debug device.
950
951 @retval 0 NumberOfBytes is 0.
952 @retval >0 The number of bytes written to the debug device.
953 If this value is less than NumberOfBytes, then the write operation failed.
954
955 **/
956 UINTN
957 EFIAPI
958 DebugPortWriteBuffer (
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
1020 /**
1021 Polls a debug device to see if there is any data waiting to be read.
1022
1023 Polls a debug device to see if there is any data waiting to be read.
1024 If there is data waiting to be read from the debug device, then TRUE is returned.
1025 If there is no data waiting to be read from the debug device, then FALSE is returned.
1026
1027 @param Handle Debug port handle.
1028
1029 @retval TRUE Data is waiting to be read from the debug device.
1030 @retval FALSE There is no data waiting to be read from the debug device.
1031
1032 **/
1033 BOOLEAN
1034 EFIAPI
1035 DebugPortPollBuffer (
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
1096 /**
1097 Initialize the debug port.
1098
1099 If Function is not NULL, Debug Communication Library will call this function
1100 by passing in the Context to be the first parameter. If needed, Debug Communication
1101 Library will create one debug port handle to be the second argument passing in
1102 calling the Function, otherwise it will pass NULL to be the second argument of
1103 Function.
1104
1105 If Function is NULL, and Context is not NULL, the Debug Communication Library could
1106 a) Return the same handle as passed in (as Context parameter).
1107 b) Ignore the input Context parameter and create new handle to be returned.
1108
1109 If parameter Function is NULL and Context is NULL, Debug Communication Library could
1110 created a new handle if needed and return it, otherwise it will return NULL.
1111
1112 @param[in] Context Context needed by callback function; it was optional.
1113 @param[in] Function Continue function called by Debug Communication library;
1114 it was optional.
1115
1116 @return The debug port handle created by Debug Communication Library if Function
1117 is not NULL.
1118
1119 **/
1120 DEBUG_PORT_HANDLE
1121 EFIAPI
1122 DebugPortInitialize (
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)) {
1135 SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE *)Context);
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 }