]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
4e49a7437f8b088a1cfc363dc23cda3d780e5130
[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 eanble 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 if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
291 //
292 // Reach the end of capability list, quit
293 //
294 break;
295 }
296 CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
297 Capability = MmioRead32 ((UINTN)CapabilityPointer);
298 }
299
300 if (!Flag) {
301 goto Done;
302 }
303
304 //
305 // USB3 debug capability is supported.
306 //
307 Handle->DebugCapabilityBase = CapabilityPointer;
308 Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;
309 Handle->XhciOpRegister = Handle->XhciMmioBase + CapLength;
310 Handle->DebugSupport = TRUE;
311 Handle->Initialized = USB3DBG_DBG_CAB;
312 return RETURN_SUCCESS;
313
314 Done:
315 Handle->Initialized = USB3DBG_NO_DBG_CAB;
316 return RETURN_UNSUPPORTED;
317 }
318
319 /**
320 Check if it needs to re-initialize usb debug port hardware.
321
322 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check
323 whether the usb debug port hardware configuration is changed. Such case can be triggered by
324 Pci bus resource allocation and so on.
325
326 @param Handle Debug port handle.
327
328 @retval TRUE The usb debug port hardware configuration is changed.
329 @retval FALSE The usb debug port hardware configuration is not changed.
330
331 **/
332 BOOLEAN
333 EFIAPI
334 NeedReinitializeHardware(
335 IN USB3_DEBUG_PORT_HANDLE *Handle
336 )
337 {
338 BOOLEAN Result;
339 volatile UINT32 Dcctrl;
340
341 Result = FALSE;
342
343 //
344 // If DCE bit, it means USB3 debug is not enabled.
345 //
346 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
347 if ((Dcctrl & BIT0) == 0) {
348 Result = TRUE;
349 } else if (!Handle->Ready) {
350 Handle->Ready = TRUE;
351 Handle->Initialized = USB3DBG_ENABLED;
352 }
353
354 return Result;
355 }
356
357 /**
358 Create XHCI event ring.
359
360 @param Handle Debug port handle.
361 @param EventRing The created event ring.
362
363 **/
364 EFI_STATUS
365 CreateEventRing (
366 IN USB3_DEBUG_PORT_HANDLE *Handle,
367 OUT EVENT_RING *EventRing
368 )
369 {
370 VOID *Buf;
371 EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;
372
373 ASSERT (EventRing != NULL);
374
375 //
376 // Allocate Event Ring
377 //
378 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
379 ASSERT (Buf != NULL);
380 ASSERT (((UINTN) Buf & 0x3F) == 0);
381 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
382
383 EventRing->EventRingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
384 EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;
385 EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
386 EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
387
388 //
389 // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
390 // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
391 //
392 EventRing->EventRingCCS = 1;
393
394 //
395 // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
396 //
397 Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
398 ASSERT (Buf != NULL);
399 ASSERT (((UINTN) Buf & 0x3F) == 0);
400 ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
401
402 ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
403 EventRing->ERSTBase = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;
404
405 //
406 // Fill Event Segment address
407 //
408 ERSTBase->PtrLo = XHC_LOW_32BIT (EventRing->EventRingSeg0);
409 ERSTBase->PtrHi = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
410 ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
411
412 //
413 // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
414 //
415 XhcWriteDebugReg (
416 Handle,
417 XHC_DC_DCERDP,
418 XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
419 );
420
421 XhcWriteDebugReg (
422 Handle,
423 XHC_DC_DCERDP + 4,
424 XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
425 );
426
427 //
428 // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
429 //
430 XhcWriteDebugReg (
431 Handle,
432 XHC_DC_DCERSTBA,
433 XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
434 );
435
436 XhcWriteDebugReg (
437 Handle,
438 XHC_DC_DCERSTBA + 4,
439 XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
440 );
441
442 //
443 // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
444 //
445 XhcWriteDebugReg (
446 Handle,
447 XHC_DC_DCERSTSZ,
448 ERST_NUMBER
449 );
450 return EFI_SUCCESS;
451 }
452
453 /**
454 Create XHCI transfer ring.
455
456 @param Handle Debug port handle.
457 @param TrbNum The number of TRB in the ring.
458 @param TransferRing The created transfer ring.
459
460 **/
461 VOID
462 CreateTransferRing (
463 IN USB3_DEBUG_PORT_HANDLE *Handle,
464 IN UINT32 TrbNum,
465 OUT TRANSFER_RING *TransferRing
466 )
467 {
468 VOID *Buf;
469 LINK_TRB *EndTrb;
470
471 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
472 ASSERT (Buf != NULL);
473 ASSERT (((UINTN) Buf & 0xF) == 0);
474 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
475
476 TransferRing->RingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
477 TransferRing->TrbNumber = TrbNum;
478 TransferRing->RingEnqueue = TransferRing->RingSeg0;
479 TransferRing->RingDequeue = TransferRing->RingSeg0;
480 TransferRing->RingPCS = 1;
481 //
482 // 4.9.2 Transfer Ring Management
483 // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
484 // point to the first TRB in the ring.
485 //
486 EndTrb = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
487 EndTrb->Type = TRB_TYPE_LINK;
488 EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
489 EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
490 //
491 // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
492 //
493 EndTrb->TC = 1;
494 //
495 // Set Cycle bit as other TRB PCS init value
496 //
497 EndTrb->CycleBit = 0;
498 }
499
500 /**
501 Create debug capability context for XHC debug device.
502
503 @param Handle Debug port handle.
504
505 @retval EFI_SUCCESS The bit successfully changed by host controller.
506 @retval EFI_TIMEOUT The time out occurred.
507
508 **/
509 EFI_STATUS
510 CreateDebugCapabilityContext (
511 IN USB3_DEBUG_PORT_HANDLE *Handle
512 )
513 {
514 VOID *Buf;
515 XHC_DC_CONTEXT *DebugCapabilityContext;
516 UINT8 *String0Desc;
517 UINT8 *ManufacturerStrDesc;
518 UINT8 *ProductStrDesc;
519 UINT8 *SerialNumberStrDesc;
520
521 //
522 // Allocate debug device context
523 //
524 Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
525 ASSERT (Buf != NULL);
526 ASSERT (((UINTN) Buf & 0xF) == 0);
527 ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
528
529 DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;
530 Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;
531
532 //
533 // Initialize DbcInfoContext.
534 //
535 DebugCapabilityContext->DbcInfoContext.String0Length = STRING0_DESC_LEN;
536 DebugCapabilityContext->DbcInfoContext.ManufacturerStrLength = MANU_DESC_LEN;
537 DebugCapabilityContext->DbcInfoContext.ProductStrLength = PRODUCT_DESC_LEN;
538 DebugCapabilityContext->DbcInfoContext.SerialNumberStrLength = SERIAL_DESC_LEN;
539
540 //
541 // Initialize EpOutContext.
542 //
543 DebugCapabilityContext->EpOutContext.CErr = 0x3;
544 DebugCapabilityContext->EpOutContext.EPType = ED_BULK_OUT;
545 DebugCapabilityContext->EpOutContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
546 DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;
547
548 //
549 // Initialize EpInContext.
550 //
551 DebugCapabilityContext->EpInContext.CErr = 0x3;
552 DebugCapabilityContext->EpInContext.EPType = ED_BULK_IN;
553 DebugCapabilityContext->EpInContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
554 DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;
555
556 //
557 // Update string descriptor address
558 //
559 String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
560 ASSERT (String0Desc != NULL);
561 ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
562 CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
563 DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
564
565 ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
566 CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
567 DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
568
569 ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
570 CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
571 DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
572
573 SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
574 CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
575 DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
576
577 //
578 // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
579 //
580 ZeroMem (&Handle->TransferRingIn, sizeof (TRANSFER_RING));
581 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingIn);
582 DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingIn.RingSeg0) | BIT0;
583 DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingIn.RingSeg0);
584
585 //
586 // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
587 //
588 ZeroMem (&Handle->TransferRingOut, sizeof (TRANSFER_RING));
589 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingOut);
590 DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingOut.RingSeg0) | BIT0;
591 DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingOut.RingSeg0);
592
593 //
594 // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
595 //
596 XhcWriteDebugReg (
597 Handle,
598 XHC_DC_DCCP,
599 XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)
600 );
601 XhcWriteDebugReg (
602 Handle,
603 XHC_DC_DCCP + 4,
604 XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)
605 );
606 return EFI_SUCCESS;
607 }
608
609 /**
610 Check if debug device is running.
611
612 @param Handle Debug port handle.
613
614 **/
615 VOID
616 XhcDetectDebugCapabilityReady (
617 IN USB3_DEBUG_PORT_HANDLE *Handle
618 )
619 {
620 UINT64 TimeOut;
621 volatile UINT32 Dcctrl;
622
623 TimeOut = 1;
624 if (Handle->Initialized == USB3DBG_DBG_CAB) {
625 //
626 // As detection is slow in seconds, wait for longer timeout for the first time.
627 // If first initialization is failed, we will try to enable debug device in the
628 // Poll function invoked by timer.
629 //
630 TimeOut = DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout), XHC_POLL_DELAY) + 1;
631 }
632
633 do {
634 //
635 // Check if debug device is in configured state
636 //
637 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);
638 if ((Dcctrl & BIT0) != 0) {
639 //
640 // Set the flag to indicate debug device is in configured state
641 //
642 Handle->Ready = TRUE;
643 break;
644 }
645 MicroSecondDelay (XHC_POLL_DELAY);
646 TimeOut--;
647 } while (TimeOut != 0);
648 }
649
650 /**
651 Initialize usb debug port hardware.
652
653 @param Handle Debug port handle.
654
655 @retval TRUE The usb debug port hardware configuration is changed.
656 @retval FALSE The usb debug port hardware configuration is not changed.
657
658 **/
659 RETURN_STATUS
660 EFIAPI
661 InitializeUsbDebugHardware (
662 IN USB3_DEBUG_PORT_HANDLE *Handle
663 )
664 {
665 RETURN_STATUS Status;
666 UINT8 *Buffer;
667 UINTN Index;
668 UINT8 TotalUsb3Port;
669 EFI_PHYSICAL_ADDRESS XhciOpRegister;
670 UINT32 Dcddi1;
671
672 XhciOpRegister = Handle->XhciOpRegister;
673 TotalUsb3Port = MmioRead32 (((UINTN) Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;
674
675 if (Handle->Initialized == USB3DBG_NOT_ENABLED) {
676 Dcddi1 = XhcReadDebugReg (Handle,XHC_DC_DCDDI1);
677 if (Dcddi1 != (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)) {
678 //
679 // The debug capability has been reset by other code, return device error.
680 //
681 return EFI_DEVICE_ERROR;
682 }
683 //
684 // If XHCI supports debug capability, hardware resource has been allocated,
685 // but it has not been enabled, try to enable again.
686 //
687 goto Enable;
688 }
689
690 //
691 // Initialize for PEI phase when AllocatePages can work.
692 // Allocate data buffer with max packet size for data read and data poll.
693 // Allocate data buffer for data write.
694 //
695 Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);
696 if (Buffer == NULL) {
697 //
698 // AllocatePages can not still work now, return fail and do not initialize now.
699 //
700 return RETURN_NOT_READY;
701 }
702
703 //
704 // Reset port to get debug device discovered
705 //
706 for (Index = 0; Index < TotalUsb3Port; Index++) {
707 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT4);
708 MicroSecondDelay (10 * 1000);
709 }
710
711 //
712 // Clear DCE bit and LSE bit in DCCTRL
713 //
714 if ((XhcReadDebugReg (Handle, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {
715 XhcClearDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
716 }
717
718 //
719 // Construct the buffer for read, poll and write.
720 //
721 Handle->UrbIn.Data = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer;
722 Handle->Data = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
723 Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;
724
725 //
726 // Initialize event ring
727 //
728 ZeroMem (&Handle->EventRing, sizeof (EVENT_RING));
729 Status = CreateEventRing (Handle, &Handle->EventRing);
730 ASSERT_EFI_ERROR (Status);
731
732 //
733 // Init IN and OUT endpoint context
734 //
735 Status = CreateDebugCapabilityContext (Handle);
736 ASSERT_EFI_ERROR (Status);
737
738 //
739 // Init DCDDI1 and DCDDI2
740 //
741 XhcWriteDebugReg (
742 Handle,
743 XHC_DC_DCDDI1,
744 (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
745 );
746
747 XhcWriteDebugReg (
748 Handle,
749 XHC_DC_DCDDI2,
750 (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
751 );
752
753 Enable:
754 if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {
755 //
756 // If the first time detection is failed, turn port power off and on in order to
757 // reset port status this time, then try to check if debug device is ready again.
758 //
759 for (Index = 0; Index < TotalUsb3Port; Index++) {
760 XhcClearR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
761 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
762 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);
763 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);
764 Handle->ChangePortPower = TRUE;
765 }
766 }
767
768 //
769 // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization
770 //
771 XhcSetDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);
772
773 XhcDetectDebugCapabilityReady (Handle);
774
775 Status = RETURN_SUCCESS;
776 if (!Handle->Ready) {
777 Handle->Initialized = USB3DBG_NOT_ENABLED;
778 Status = RETURN_NOT_READY;
779 } else {
780 Handle->Initialized = USB3DBG_ENABLED;
781 }
782
783 return Status;
784 }
785
786 /**
787 Discover and initialize usb debug port.
788
789 @param Handle Debug port handle.
790
791 **/
792 VOID
793 DiscoverInitializeUsbDebugPort (
794 IN USB3_DEBUG_PORT_HANDLE *Handle
795 )
796 {
797 EFI_STATUS Status;
798 EFI_PHYSICAL_ADDRESS XhciMmioBase;
799
800 //
801 // Read 64-bit MMIO base address
802 //
803 XhciMmioBase = ProgramXhciBaseAddress ();
804 Handle->XhciMmioBase = XhciMmioBase;
805
806 Status = CalculateUsbDebugPortMmioBase (Handle);
807 if (!RETURN_ERROR (Status)) {
808 UpdateXhcResource (Handle, XhciMmioBase);
809 if (NeedReinitializeHardware (Handle)) {
810 InitializeUsbDebugHardware (Handle);
811 }
812 }
813 }
814
815 /**
816 Set USB3 debug instance address.
817
818 @param[in] Instance Debug port instance.
819
820 **/
821 VOID
822 SetUsb3DebugPortInstance (
823 IN USB3_DEBUG_PORT_HANDLE *Instance
824 )
825 {
826 EFI_PHYSICAL_ADDRESS *AddrPtr;
827
828 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
829 ASSERT (AddrPtr != NULL);
830 *AddrPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) Instance;
831 }
832
833 /**
834 Return USB3 debug instance address.
835
836 **/
837 USB3_DEBUG_PORT_HANDLE *
838 GetUsb3DebugPortInstance (
839 VOID
840 )
841 {
842 EFI_PHYSICAL_ADDRESS *AddrPtr;
843 USB3_DEBUG_PORT_HANDLE *Instance;
844
845 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();
846 ASSERT (AddrPtr != NULL);
847
848 Instance = (USB3_DEBUG_PORT_HANDLE *) (UINTN) *AddrPtr;
849
850 return Instance;
851 }
852
853 /**
854 Read data from debug device and save the data in buffer.
855
856 Reads NumberOfBytes data bytes from a debug device into the buffer
857 specified by Buffer. The number of bytes actually read is returned.
858 If the return value is less than NumberOfBytes, then the rest operation failed.
859 If NumberOfBytes is zero, then return 0.
860
861 @param Handle Debug port handle.
862 @param Buffer Pointer to the data buffer to store the data read from the debug device.
863 @param NumberOfBytes Number of bytes which will be read.
864 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.
865
866 @retval 0 Read data failed, no data is to be read.
867 @retval >0 Actual number of bytes read from debug device.
868
869 **/
870 UINTN
871 EFIAPI
872 DebugPortReadBuffer (
873 IN DEBUG_PORT_HANDLE Handle,
874 IN UINT8 *Buffer,
875 IN UINTN NumberOfBytes,
876 IN UINTN Timeout
877 )
878 {
879 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
880 UINT8 Index;
881 UINT8 *Data;
882
883 if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {
884 return 0;
885 }
886
887 //
888 // If Handle is NULL, get own instance.
889 // If Handle is not NULL, use it and set the instance.
890 //
891 if (Handle != NULL) {
892 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
893 SetUsb3DebugPortInstance (UsbDebugPortHandle);
894 } else {
895 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
896 }
897 if (UsbDebugPortHandle == NULL) {
898 return 0;
899 }
900
901 if (UsbDebugPortHandle->InNotify) {
902 return 0;
903 }
904
905 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
906
907 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
908 return 0;
909 }
910
911 Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;
912
913 //
914 // Read data from buffer
915 //
916 if (UsbDebugPortHandle->DataCount < 1) {
917 return 0;
918 } else {
919 *Buffer = Data[0];
920
921 for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {
922 if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
923 return 0;
924 }
925 Data[Index] = Data[Index + 1];
926 }
927 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);
928 return 1;
929 }
930 }
931
932 /**
933 Write data from buffer to debug device.
934
935 Writes NumberOfBytes data bytes from Buffer to the debug device.
936 The number of bytes actually written to the debug device is returned.
937 If the return value is less than NumberOfBytes, then the write operation failed.
938 If NumberOfBytes is zero, then return 0.
939
940 @param Handle Debug port handle.
941 @param Buffer Pointer to the data buffer to be written.
942 @param NumberOfBytes Number of bytes to written to the debug device.
943
944 @retval 0 NumberOfBytes is 0.
945 @retval >0 The number of bytes written to the debug device.
946 If this value is less than NumberOfBytes, then the write operation failed.
947
948 **/
949 UINTN
950 EFIAPI
951 DebugPortWriteBuffer (
952 IN DEBUG_PORT_HANDLE Handle,
953 IN UINT8 *Buffer,
954 IN UINTN NumberOfBytes
955 )
956 {
957 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
958 UINTN Sent;
959 UINTN Total;
960
961 if (NumberOfBytes == 0 || Buffer == NULL) {
962 return 0;
963 }
964
965 Sent = 0;
966 Total = 0;
967
968 //
969 // If Handle is NULL, get own instance.
970 // If Handle is not NULL, use it and set the instance.
971 //
972 if (Handle != NULL) {
973 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
974 SetUsb3DebugPortInstance (UsbDebugPortHandle);
975 } else {
976 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
977 }
978 if (UsbDebugPortHandle == NULL) {
979 return 0;
980 }
981
982 if (UsbDebugPortHandle->InNotify) {
983 return 0;
984 }
985
986 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
987
988 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
989 return 0;
990 }
991
992 //
993 // When host is trying to send data, write will be blocked.
994 // Poll to see if there is any data sent by host at first.
995 //
996 DebugPortPollBuffer (UsbDebugPortHandle);
997
998 while ((Total < NumberOfBytes)) {
999 if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {
1000 Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;
1001 } else {
1002 Sent = (UINT8)(NumberOfBytes - Total);
1003 }
1004 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);
1005 Total += Sent;
1006 }
1007
1008 return Total;
1009 }
1010
1011 /**
1012 Polls a debug device to see if there is any data waiting to be read.
1013
1014 Polls a debug device to see if there is any data waiting to be read.
1015 If there is data waiting to be read from the debug device, then TRUE is returned.
1016 If there is no data waiting to be read from the debug device, then FALSE is returned.
1017
1018 @param Handle Debug port handle.
1019
1020 @retval TRUE Data is waiting to be read from the debug device.
1021 @retval FALSE There is no data waiting to be read from the debug device.
1022
1023 **/
1024 BOOLEAN
1025 EFIAPI
1026 DebugPortPollBuffer (
1027 IN DEBUG_PORT_HANDLE Handle
1028 )
1029 {
1030 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
1031 UINTN Length;
1032
1033 //
1034 // If Handle is NULL, get own instance.
1035 // If Handle is not NULL, use it and set the instance.
1036 //
1037 if (Handle != NULL) {
1038 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *) Handle;
1039 SetUsb3DebugPortInstance (UsbDebugPortHandle);
1040 } else {
1041 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1042 }
1043 if (UsbDebugPortHandle == NULL) {
1044 return FALSE;
1045 }
1046
1047 if (UsbDebugPortHandle->InNotify) {
1048 return FALSE;
1049 }
1050
1051 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1052
1053 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {
1054 return FALSE;
1055 }
1056
1057 //
1058 // If the data buffer is not empty, then return TRUE directly.
1059 // Otherwise initialize a usb read transaction and read data to internal data buffer.
1060 //
1061 if (UsbDebugPortHandle->DataCount != 0) {
1062 return TRUE;
1063 }
1064
1065 //
1066 // Read data as much as we can
1067 //
1068 Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;
1069 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);
1070
1071 if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {
1072 return FALSE;
1073 }
1074
1075 if (Length == 0) {
1076 return FALSE;
1077 }
1078
1079 //
1080 // Store data into internal buffer for use later
1081 //
1082 UsbDebugPortHandle->DataCount = (UINT8) Length;
1083 return TRUE;
1084 }
1085
1086 /**
1087 Initialize the debug port.
1088
1089 If Function is not NULL, Debug Communication Library will call this function
1090 by passing in the Context to be the first parameter. If needed, Debug Communication
1091 Library will create one debug port handle to be the second argument passing in
1092 calling the Function, otherwise it will pass NULL to be the second argument of
1093 Function.
1094
1095 If Function is NULL, and Context is not NULL, the Debug Communication Library could
1096 a) Return the same handle as passed in (as Context parameter).
1097 b) Ignore the input Context parameter and create new handle to be returned.
1098
1099 If parameter Function is NULL and Context is NULL, Debug Communication Library could
1100 created a new handle if needed and return it, otherwise it will return NULL.
1101
1102 @param[in] Context Context needed by callback function; it was optional.
1103 @param[in] Function Continue function called by Debug Communication library;
1104 it was optional.
1105
1106 @return The debug port handle created by Debug Communication Library if Function
1107 is not NULL.
1108
1109 **/
1110 DEBUG_PORT_HANDLE
1111 EFIAPI
1112 DebugPortInitialize (
1113 IN VOID *Context,
1114 IN DEBUG_PORT_CONTINUE Function
1115 )
1116 {
1117 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;
1118
1119 //
1120 // Validate the PCD PcdDebugPortHandleBufferSize value
1121 //
1122 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));
1123
1124 if (Function == NULL && Context != NULL) {
1125 SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE *) Context);
1126 return (DEBUG_PORT_HANDLE) Context;
1127 }
1128 UsbDebugPortHandle = GetUsb3DebugPortInstance ();
1129 if (UsbDebugPortHandle == NULL) {
1130 return NULL;
1131 }
1132
1133 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);
1134
1135 if (Function != NULL) {
1136 Function (Context, (DEBUG_PORT_HANDLE) UsbDebugPortHandle);
1137 }
1138
1139 return (DEBUG_PORT_HANDLE) UsbDebugPortHandle;
1140 }