]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
Revert "DebugUsb3: Support IOMMU"
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Common.c
CommitLineData
2cb6eabe
EL
1/** @file\r
2 Debug Port Library implementation based on usb3 debug port.\r
3\r
f4043414 4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
2cb6eabe
EL
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "DebugCommunicationLibUsb3Internal.h"\r
16\r
1f279e7a
SZ
17//\r
18// The global variable which can be used after memory is ready.\r
19//\r
20USB3_DEBUG_PORT_HANDLE mDebugCommunicationLibUsb3DebugPortHandle;\r
21\r
2cb6eabe
EL
22UINT16 mString0Desc[] = {\r
23 // String Descriptor Type + Length\r
24 ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,\r
25 0x0409\r
26};\r
27\r
28UINT16 mManufacturerStrDesc[] = {\r
29 // String Descriptor Type + Length\r
30 ( USB_DESC_TYPE_STRING << 8 ) + MANU_DESC_LEN,\r
31 'I', 'n', 't', 'e', 'l'\r
32};\r
33\r
34UINT16 mProductStrDesc[] = {\r
35 // String Descriptor Type + Length\r
36 ( USB_DESC_TYPE_STRING << 8 ) + PRODUCT_DESC_LEN,\r
37 'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'\r
38};\r
39\r
40UINT16 mSerialNumberStrDesc[] = {\r
41 // String Descriptor Type + Length\r
42 ( USB_DESC_TYPE_STRING << 8 ) + SERIAL_DESC_LEN,\r
43 '1'\r
44};\r
45\r
46/**\r
47 Sets bits as per the enabled bit positions in the mask.\r
48\r
49 @param[in, out] Register UINTN register\r
50 @param[in] BitMask 32-bit mask\r
51**/\r
52VOID\r
53XhcSetR32Bit(\r
54 IN OUT UINTN Register, \r
55 IN UINT32 BitMask\r
56 )\r
57{\r
58 UINT32 RegisterValue;\r
59\r
60 RegisterValue = MmioRead32 (Register);\r
61 RegisterValue |= (UINT32)(BitMask);\r
62 MmioWrite32 (Register, RegisterValue);\r
63}\r
64\r
65/**\r
66 Clears bits as per the enabled bit positions in the mask.\r
67\r
68 @param[in, out] Register UINTN register\r
69 @param[in] BitMask 32-bit mask\r
70**/\r
71VOID\r
72XhcClearR32Bit(\r
73 IN OUT UINTN Register, \r
74 IN UINT32 BitMask\r
75 )\r
76{\r
77 UINT32 RegisterValue;\r
78\r
79 RegisterValue = MmioRead32 (Register);\r
80 RegisterValue &= ~BitMask;\r
81 MmioWrite32 (Register, RegisterValue);\r
82}\r
83\r
84/**\r
85 Write the data to the XHCI debug register.\r
86\r
87 @param Handle Debug port handle.\r
1f279e7a 88 @param Offset The offset of the runtime register.\r
2cb6eabe
EL
89 @param Data The data to write.\r
90\r
91**/\r
92VOID\r
93XhcWriteDebugReg (\r
94 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
95 IN UINT32 Offset,\r
96 IN UINT32 Data\r
97 )\r
98{\r
99 EFI_PHYSICAL_ADDRESS DebugCapabilityBase;\r
100 \r
101 DebugCapabilityBase = Handle->DebugCapabilityBase;\r
102 MmioWrite32 ((UINTN)(DebugCapabilityBase + Offset), Data);\r
103 \r
104 return;\r
105}\r
106\r
107/**\r
108 Read XHCI debug register.\r
109\r
110 @param Handle Debug port handle.\r
111 @param Offset The offset of the runtime register.\r
112\r
113 @return The register content read\r
114\r
115**/\r
116UINT32\r
117XhcReadDebugReg (\r
118 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
119 IN UINT32 Offset\r
120 )\r
121{\r
122 UINT32 Data;\r
123 EFI_PHYSICAL_ADDRESS DebugCapabilityBase;\r
124 \r
125 DebugCapabilityBase = Handle->DebugCapabilityBase;\r
126 Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));\r
127\r
128 return Data;\r
129}\r
130\r
131/**\r
1f279e7a 132 Set one bit of the runtime register while keeping other bits.\r
2cb6eabe
EL
133\r
134 @param Handle Debug port handle.\r
1f279e7a 135 @param Offset The offset of the runtime register.\r
2cb6eabe
EL
136 @param Bit The bit mask of the register to set.\r
137\r
138**/\r
139VOID\r
140XhcSetDebugRegBit (\r
1f279e7a 141 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
2cb6eabe
EL
142 IN UINT32 Offset,\r
143 IN UINT32 Bit\r
144 )\r
145{\r
146 UINT32 Data;\r
147\r
148 Data = XhcReadDebugReg (Handle, Offset);\r
149 Data |= Bit;\r
150 XhcWriteDebugReg (Handle, Offset, Data);\r
151}\r
152\r
153/**\r
154 Program and eanble XHCI MMIO base address.\r
155\r
156 @return XHCI MMIO base address.\r
157\r
158**/\r
159EFI_PHYSICAL_ADDRESS\r
160ProgramXhciBaseAddress (\r
161 VOID\r
162 )\r
163{\r
164 UINT16 PciCmd;\r
165 UINT32 Low;\r
166 UINT32 High;\r
167 EFI_PHYSICAL_ADDRESS XhciMmioBase;\r
168 \r
169 Low = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
170 High = PciRead32 (PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4);\r
171 XhciMmioBase = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);\r
172 XhciMmioBase &= XHCI_BASE_ADDRESS_64_BIT_MASK;\r
173\r
174 if ((XhciMmioBase == 0) || (XhciMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {\r
175 XhciMmioBase = PcdGet64(PcdUsbXhciMemorySpaceBase);\r
176 PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, XhciMmioBase & 0xFFFFFFFF);\r
177 PciWrite32(PcdGet32(PcdUsbXhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + 4, (RShiftU64 (XhciMmioBase, 32) & 0xFFFFFFFF));\r
178 }\r
179\r
180 PciCmd = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET);\r
181 if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
182 PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
183 PciWrite16(PcdGet32(PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
184 }\r
185\r
186 return XhciMmioBase;\r
187}\r
188\r
2cb6eabe
EL
189/**\r
190 Update XHC MMIO base address when MMIO base address is changed.\r
191\r
192 @param Handle Debug port handle.\r
193 @param XhciMmioBase XHCI MMIO base address.\r
194\r
195**/\r
196VOID\r
197UpdateXhcResource (\r
198 IN OUT USB3_DEBUG_PORT_HANDLE *Handle,\r
199 IN EFI_PHYSICAL_ADDRESS XhciMmioBase\r
200 )\r
201{\r
1f279e7a 202 if ((Handle == NULL) || (Handle->XhciMmioBase == XhciMmioBase)) {\r
2cb6eabe
EL
203 return;\r
204 }\r
205\r
206 //\r
207 // Need fix Handle data according to new XHCI MMIO base address.\r
208 //\r
209 Handle->XhciMmioBase = XhciMmioBase;\r
210 Handle->DebugCapabilityBase = XhciMmioBase + Handle->DebugCapabilityOffset;\r
211 Handle->XhciOpRegister = XhciMmioBase + MmioRead8 ((UINTN)XhciMmioBase);\r
212}\r
213\r
214/**\r
215 Calculate the usb debug port bar address.\r
216\r
217 @param Handle Debug port handle.\r
218\r
1f279e7a 219 @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.\r
2cb6eabe
EL
220 @retval RETURN_SUCCESS Get bar and offset successfully.\r
221\r
222**/\r
223RETURN_STATUS\r
224EFIAPI\r
225CalculateUsbDebugPortMmioBase (\r
226 USB3_DEBUG_PORT_HANDLE *Handle\r
227 )\r
228{\r
229 UINT16 VendorId;\r
230 UINT16 DeviceId;\r
231 UINT8 ProgInterface;\r
232 UINT8 SubClassCode;\r
233 UINT8 BaseCode;\r
234 BOOLEAN Flag;\r
235 UINT32 Capability;\r
236 EFI_PHYSICAL_ADDRESS CapabilityPointer;\r
237 UINT8 CapLength;\r
238\r
239 VendorId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_VENDOR_ID_OFFSET);\r
240 DeviceId = PciRead16 (PcdGet32(PcdUsbXhciPciAddress) + PCI_DEVICE_ID_OFFSET);\r
241 \r
242 if ((VendorId == 0xFFFF) || (DeviceId == 0xFFFF)) {\r
243 goto Done;\r
244 }\r
245\r
246 ProgInterface = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET);\r
247 SubClassCode = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 1);\r
248 BaseCode = PciRead8 (PcdGet32(PcdUsbXhciPciAddress) + PCI_CLASSCODE_OFFSET + 2);\r
249 \r
250 if ((ProgInterface != PCI_IF_XHCI) || (SubClassCode != PCI_CLASS_SERIAL_USB) || (BaseCode != PCI_CLASS_SERIAL)) {\r
251 goto Done;\r
252 }\r
253\r
254 CapLength = MmioRead8 ((UINTN) Handle->XhciMmioBase);\r
255\r
256 //\r
257 // Get capability pointer from HCCPARAMS at offset 0x10\r
258 //\r
259 CapabilityPointer = Handle->XhciMmioBase + (MmioRead32 ((UINTN)(Handle->XhciMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;\r
260 \r
261 //\r
262 // Search XHCI debug capability\r
263 //\r
264 Flag = FALSE;\r
265 Capability = MmioRead32 ((UINTN)CapabilityPointer);\r
266 while (TRUE) {\r
267 if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {\r
268 Flag = TRUE;\r
269 break;\r
270 }\r
271 if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {\r
272 //\r
273 // Reach the end of capability list, quit\r
274 //\r
275 break;\r
276 }\r
277 CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;\r
278 Capability = MmioRead32 ((UINTN)CapabilityPointer);\r
279 }\r
280\r
281 if (!Flag) {\r
282 goto Done;\r
283 }\r
284\r
285 //\r
286 // USB3 debug capability is supported.\r
287 //\r
288 Handle->DebugCapabilityBase = CapabilityPointer;\r
289 Handle->DebugCapabilityOffset = CapabilityPointer - Handle->XhciMmioBase;\r
290 Handle->XhciOpRegister = Handle->XhciMmioBase + CapLength;\r
291 Handle->Initialized = USB3DBG_DBG_CAB;\r
292 return RETURN_SUCCESS;\r
293\r
294Done:\r
295 Handle->Initialized = USB3DBG_NO_DBG_CAB;\r
296 return RETURN_UNSUPPORTED;\r
297}\r
298\r
299/**\r
300 Check if it needs to re-initialize usb debug port hardware.\r
301\r
302 During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check\r
74cdb367 303 whether the usb debug port hardware configuration is changed. Such case can be triggered by\r
2cb6eabe
EL
304 Pci bus resource allocation and so on.\r
305\r
306 @param Handle Debug port handle.\r
307\r
308 @retval TRUE The usb debug port hardware configuration is changed.\r
309 @retval FALSE The usb debug port hardware configuration is not changed.\r
310\r
311**/\r
312BOOLEAN\r
313EFIAPI\r
314NeedReinitializeHardware(\r
315 IN USB3_DEBUG_PORT_HANDLE *Handle\r
316 )\r
317{\r
318 BOOLEAN Result;\r
319 volatile UINT32 Dcctrl;\r
320\r
321 Result = FALSE;\r
322\r
323 //\r
324 // If DCE bit, it means USB3 debug is not enabled.\r
325 //\r
326 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);\r
327 if ((Dcctrl & BIT0) == 0) {\r
328 Result = TRUE;\r
329 }\r
330\r
331 return Result;\r
332}\r
333\r
334/**\r
335 Create XHCI event ring.\r
336\r
337 @param Handle Debug port handle.\r
338 @param EventRing The created event ring.\r
339\r
340**/\r
341EFI_STATUS\r
342CreateEventRing (\r
343 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
344 OUT EVENT_RING *EventRing\r
345 )\r
346{\r
347 VOID *Buf;\r
348 EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;\r
349\r
350 ASSERT (EventRing != NULL);\r
351 \r
352 //\r
353 // Allocate Event Ring\r
354 //\r
355 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
356 ASSERT (Buf != NULL);\r
357 ASSERT (((UINTN) Buf & 0x3F) == 0);\r
358 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
359\r
360 EventRing->EventRingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;\r
361 EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;\r
362 EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;\r
363 EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;\r
364 \r
365 //\r
366 // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'\r
367 // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.\r
368 //\r
369 EventRing->EventRingCCS = 1;\r
370\r
371 //\r
372 // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table\r
373 //\r
374 Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
375 ASSERT (Buf != NULL);\r
376 ASSERT (((UINTN) Buf & 0x3F) == 0);\r
377 ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
378\r
379 ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;\r
380 EventRing->ERSTBase = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;\r
381\r
382 //\r
383 // Fill Event Segment address\r
384 //\r
385 ERSTBase->PtrLo = XHC_LOW_32BIT (EventRing->EventRingSeg0);\r
386 ERSTBase->PtrHi = XHC_HIGH_32BIT (EventRing->EventRingSeg0);\r
387 ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;\r
388\r
389 //\r
390 // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)\r
391 //\r
392 XhcWriteDebugReg (\r
393 Handle,\r
394 XHC_DC_DCERDP,\r
395 XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
396 );\r
397\r
398 XhcWriteDebugReg (\r
399 Handle,\r
400 XHC_DC_DCERDP + 4,\r
401 XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
402 );\r
403\r
404 //\r
405 // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)\r
406 //\r
407 XhcWriteDebugReg (\r
408 Handle,\r
409 XHC_DC_DCERSTBA,\r
410 XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)\r
411 );\r
412\r
413 XhcWriteDebugReg (\r
414 Handle,\r
415 XHC_DC_DCERSTBA + 4,\r
416 XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)\r
417 );\r
418\r
419 //\r
420 // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)\r
421 //\r
422 XhcWriteDebugReg (\r
423 Handle,\r
424 XHC_DC_DCERSTSZ,\r
425 ERST_NUMBER\r
426 );\r
427 return EFI_SUCCESS;\r
428}\r
429\r
430/**\r
431 Create XHCI transfer ring.\r
432\r
433 @param Handle Debug port handle.\r
434 @param TrbNum The number of TRB in the ring.\r
435 @param TransferRing The created transfer ring.\r
436\r
437**/\r
438VOID\r
439CreateTransferRing (\r
440 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
441 IN UINT32 TrbNum,\r
442 OUT TRANSFER_RING *TransferRing\r
443 )\r
444{\r
445 VOID *Buf;\r
446 LINK_TRB *EndTrb;\r
447 \r
448 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);\r
449 ASSERT (Buf != NULL);\r
450 ASSERT (((UINTN) Buf & 0xF) == 0);\r
451 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
452\r
453 TransferRing->RingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;\r
454 TransferRing->TrbNumber = TrbNum;\r
455 TransferRing->RingEnqueue = TransferRing->RingSeg0;\r
456 TransferRing->RingDequeue = TransferRing->RingSeg0;\r
457 TransferRing->RingPCS = 1;\r
458 //\r
459 // 4.9.2 Transfer Ring Management\r
460 // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to\r
461 // point to the first TRB in the ring.\r
462 //\r
463 EndTrb = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));\r
464 EndTrb->Type = TRB_TYPE_LINK;\r
465 EndTrb->PtrLo = XHC_LOW_32BIT (Buf);\r
466 EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);\r
467 //\r
468 // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.\r
469 //\r
470 EndTrb->TC = 1;\r
471 //\r
472 // Set Cycle bit as other TRB PCS init value\r
473 //\r
474 EndTrb->CycleBit = 0;\r
475}\r
476\r
477/**\r
478 Create debug capability context for XHC debug device.\r
479\r
480 @param Handle Debug port handle.\r
481\r
482 @retval EFI_SUCCESS The bit successfully changed by host controller.\r
483 @retval EFI_TIMEOUT The time out occurred.\r
484\r
485**/\r
486EFI_STATUS\r
487CreateDebugCapabilityContext (\r
488 IN USB3_DEBUG_PORT_HANDLE *Handle\r
489 )\r
490{\r
491 VOID *Buf;\r
492 XHC_DC_CONTEXT *DebugCapabilityContext;\r
493 UINT8 *String0Desc;\r
494 UINT8 *ManufacturerStrDesc;\r
495 UINT8 *ProductStrDesc;\r
496 UINT8 *SerialNumberStrDesc;\r
497 \r
498 //\r
499 // Allocate debug device context\r
500 //\r
501 Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));\r
502 ASSERT (Buf != NULL);\r
503 ASSERT (((UINTN) Buf & 0xF) == 0);\r
504 ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));\r
505 \r
506 DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;\r
507 Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;\r
508 \r
509 //\r
510 // Initialize DbcInfoContext.\r
511 //\r
512 DebugCapabilityContext->DbcInfoContext.String0Length = STRING0_DESC_LEN;\r
513 DebugCapabilityContext->DbcInfoContext.ManufacturerStrLength = MANU_DESC_LEN;\r
514 DebugCapabilityContext->DbcInfoContext.ProductStrLength = PRODUCT_DESC_LEN;\r
515 DebugCapabilityContext->DbcInfoContext.SerialNumberStrLength = SERIAL_DESC_LEN;\r
516\r
517 //\r
518 // Initialize EpOutContext.\r
519 //\r
520 DebugCapabilityContext->EpOutContext.CErr = 0x3;\r
521 DebugCapabilityContext->EpOutContext.EPType = ED_BULK_OUT;\r
5d6507a1 522 DebugCapabilityContext->EpOutContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
2cb6eabe
EL
523 DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;\r
524 \r
525 //\r
526 // Initialize EpInContext.\r
527 //\r
528 DebugCapabilityContext->EpInContext.CErr = 0x3;\r
529 DebugCapabilityContext->EpInContext.EPType = ED_BULK_IN;\r
5d6507a1 530 DebugCapabilityContext->EpInContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
2cb6eabe
EL
531 DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;\r
532 \r
533 //\r
534 // Update string descriptor address\r
535 //\r
536 String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);\r
537 ASSERT (String0Desc != NULL);\r
538 ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);\r
539 CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);\r
540 DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;\r
541 \r
542 ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;\r
543 CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);\r
544 DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;\r
545 \r
546 ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;\r
547 CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);\r
548 DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;\r
549 \r
550 SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;\r
551 CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);\r
552 DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;\r
553 \r
554 //\r
555 // Allocate and initialize the Transfer Ring for the Input Endpoint Context.\r
556 //\r
557 ZeroMem (&Handle->TransferRingIn, sizeof (TRANSFER_RING));\r
558 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingIn);\r
559 DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingIn.RingSeg0) | BIT0;\r
560 DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingIn.RingSeg0);\r
561\r
562 //\r
563 // Allocate and initialize the Transfer Ring for the Output Endpoint Context.\r
564 //\r
565 ZeroMem (&Handle->TransferRingOut, sizeof (TRANSFER_RING));\r
566 CreateTransferRing (Handle, TR_RING_TRB_NUMBER, &Handle->TransferRingOut);\r
567 DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Handle->TransferRingOut.RingSeg0) | BIT0;\r
568 DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Handle->TransferRingOut.RingSeg0);\r
569\r
570 //\r
571 // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)\r
572 //\r
573 XhcWriteDebugReg (\r
574 Handle,\r
575 XHC_DC_DCCP,\r
576 XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)\r
577 );\r
578 XhcWriteDebugReg (\r
579 Handle,\r
580 XHC_DC_DCCP + 4,\r
581 XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)\r
582 );\r
583 return EFI_SUCCESS;\r
584}\r
585\r
586/**\r
587 Check if debug device is running.\r
588\r
589 @param Handle Debug port handle.\r
590\r
591**/\r
592VOID\r
593XhcDetectDebugCapabilityReady (\r
594 IN USB3_DEBUG_PORT_HANDLE *Handle\r
595 )\r
596{\r
597 UINT64 TimeOut;\r
598 volatile UINT32 Dcctrl;\r
599\r
600 TimeOut = 1;\r
601 if (Handle->Initialized == USB3DBG_DBG_CAB) {\r
602 //\r
603 // As detection is slow in seconds, wait for longer timeout for the first time.\r
604 // If first initialization is failed, we will try to enable debug device in the\r
605 // Poll function invoked by timer.\r
606 //\r
607 TimeOut = DivU64x32 (PcdGet64 (PcdUsbXhciDebugDetectTimeout), XHC_POLL_DELAY) + 1;\r
608 }\r
609\r
610 do {\r
611 //\r
612 // Check if debug device is in configured state\r
613 //\r
614 Dcctrl = XhcReadDebugReg (Handle, XHC_DC_DCCTRL);\r
615 if ((Dcctrl & BIT0) != 0) {\r
616 //\r
617 // Set the flag to indicate debug device is in configured state\r
618 //\r
619 Handle->Ready = TRUE;\r
620 break;\r
621 }\r
622 MicroSecondDelay (XHC_POLL_DELAY);\r
623 TimeOut--;\r
624 } while (TimeOut != 0);\r
625}\r
626\r
627/**\r
628 Initialize usb debug port hardware.\r
629\r
630 @param Handle Debug port handle.\r
631\r
632 @retval TRUE The usb debug port hardware configuration is changed.\r
633 @retval FALSE The usb debug port hardware configuration is not changed.\r
634\r
635**/\r
636RETURN_STATUS\r
637EFIAPI\r
638InitializeUsbDebugHardware (\r
639 IN USB3_DEBUG_PORT_HANDLE *Handle\r
640 )\r
641{\r
642 RETURN_STATUS Status;\r
643 UINT8 *Buffer;\r
644 UINTN Index;\r
645 UINT8 TotalUsb3Port;\r
646 EFI_PHYSICAL_ADDRESS XhciOpRegister;\r
647\r
648 XhciOpRegister = Handle->XhciOpRegister;\r
649 TotalUsb3Port = MmioRead32 (((UINTN) Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;\r
650\r
651 if (Handle->Initialized == USB3DBG_NOT_ENABLED) {\r
652 //\r
653 // If XHCI supports debug capability, hardware resource has been allocated, \r
654 // but it has not been enabled, try to enable again.\r
655 //\r
656 goto Enable;\r
657 }\r
658\r
659 //\r
5d6507a1
EL
660 // Initialize for PEI phase when AllocatePages can work.\r
661 // Allocate data buffer with max packet size for data read and data poll.\r
662 // Allocate data buffer for data write.\r
2cb6eabe 663 //\r
5d6507a1 664 Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);\r
2cb6eabe
EL
665 if (Buffer == NULL) {\r
666 //\r
667 // AllocatePages can not still work now, return fail and do not initialize now.\r
668 //\r
669 return RETURN_NOT_READY;\r
670 }\r
671\r
672 //\r
673 // Reset port to get debug device discovered\r
674 // \r
675 for (Index = 0; Index < TotalUsb3Port; Index++) {\r
676 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT4);\r
677 MicroSecondDelay (10 * 1000);\r
678 }\r
679\r
680 //\r
5d6507a1 681 // Construct the buffer for read, poll and write.\r
2cb6eabe
EL
682 //\r
683 Handle->UrbIn.Data = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer;\r
5d6507a1
EL
684 Handle->Data = (EFI_PHYSICAL_ADDRESS)(UINTN) Buffer + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
685 Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;\r
2cb6eabe
EL
686 \r
687 //\r
688 // Initialize event ring\r
689 //\r
690 ZeroMem (&Handle->EventRing, sizeof (EVENT_RING));\r
691 Status = CreateEventRing (Handle, &Handle->EventRing);\r
692 ASSERT_EFI_ERROR (Status);\r
693 \r
694 //\r
695 // Init IN and OUT endpoint context\r
696 //\r
697 Status = CreateDebugCapabilityContext (Handle);\r
698 ASSERT_EFI_ERROR (Status);\r
699 \r
700 //\r
701 // Init DCDDI1 and DCDDI2\r
702 //\r
703 XhcWriteDebugReg (\r
704 Handle,\r
705 XHC_DC_DCDDI1,\r
706 (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)\r
707 ); \r
708\r
709 XhcWriteDebugReg (\r
710 Handle,\r
711 XHC_DC_DCDDI2,\r
712 (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)\r
713 );\r
714\r
715Enable:\r
716 if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {\r
717 //\r
718 // If the first time detection is failed, turn port power off and on in order to \r
719 // reset port status this time, then try to check if debug device is ready again.\r
720 //\r
721 for (Index = 0; Index < TotalUsb3Port; Index++) {\r
722 XhcClearR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);\r
723 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);\r
724 XhcSetR32Bit ((UINTN)XhciOpRegister + XHC_PORTSC_OFFSET + Index * 0x10, BIT9);\r
725 MicroSecondDelay (XHC_DEBUG_PORT_ON_OFF_DELAY);\r
726 Handle->ChangePortPower = TRUE;\r
727 }\r
728 }\r
729\r
730 //\r
731 // Set DCE bit and LSE bit to "1" in DCCTRL in first initialization\r
732 //\r
733 XhcSetDebugRegBit (Handle, XHC_DC_DCCTRL, BIT1|BIT31);\r
734 \r
735 XhcDetectDebugCapabilityReady (Handle);\r
736 \r
737 Status = RETURN_SUCCESS;\r
738 if (!Handle->Ready) {\r
739 Handle->Initialized = USB3DBG_NOT_ENABLED;\r
740 Status = RETURN_NOT_READY;\r
741 } else {\r
742 Handle->Initialized = USB3DBG_ENABLED;\r
743 }\r
744\r
745 return Status;\r
746}\r
747\r
748/**\r
749 Read data from debug device and save the data in buffer.\r
750\r
751 Reads NumberOfBytes data bytes from a debug device into the buffer\r
752 specified by Buffer. The number of bytes actually read is returned.\r
753 If the return value is less than NumberOfBytes, then the rest operation failed.\r
754 If NumberOfBytes is zero, then return 0.\r
755\r
756 @param Handle Debug port handle.\r
757 @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
758 @param NumberOfBytes Number of bytes which will be read.\r
f4043414 759 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.\r
2cb6eabe
EL
760\r
761 @retval 0 Read data failed, no data is to be read.\r
762 @retval >0 Actual number of bytes read from debug device.\r
763\r
764**/\r
765UINTN\r
766EFIAPI\r
767DebugPortReadBuffer (\r
768 IN DEBUG_PORT_HANDLE Handle,\r
769 IN UINT8 *Buffer,\r
770 IN UINTN NumberOfBytes,\r
771 IN UINTN Timeout\r
772 )\r
773{\r
774 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1f279e7a 775 RETURN_STATUS Status;\r
2cb6eabe 776 UINT8 Index;\r
5d6507a1 777 UINT8 *Data;\r
2cb6eabe 778\r
08021523 779 if (NumberOfBytes != 1 || Buffer == NULL || Timeout != 0) {\r
2cb6eabe
EL
780 return 0;\r
781 }\r
782\r
1f279e7a
SZ
783 //\r
784 // If Handle is NULL, it means memory is ready for use.\r
785 // Use global variable to store handle value.\r
786 //\r
787 if (Handle == NULL) {\r
788 UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
789 } else {\r
790 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
2cb6eabe 791 }\r
1f279e7a
SZ
792 \r
793 if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
2cb6eabe
EL
794 return 0;\r
795 }\r
1f279e7a
SZ
796 \r
797 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
798 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
799 if (RETURN_ERROR(Status)) {\r
800 return 0;\r
801 }\r
2cb6eabe
EL
802 }\r
803\r
5d6507a1
EL
804 Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;\r
805\r
2cb6eabe 806 //\r
08021523 807 // Read data from buffer\r
2cb6eabe 808 //\r
08021523
JF
809 if (UsbDebugPortHandle->DataCount < 1) {\r
810 return 0;\r
811 } else {\r
812 *Buffer = Data[0];\r
2cb6eabe 813\r
08021523
JF
814 for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {\r
815 if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
2cb6eabe
EL
816 return 0;\r
817 }\r
08021523 818 Data[Index] = Data[Index + 1];\r
2cb6eabe 819 }\r
08021523
JF
820 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);\r
821 return 1;\r
2cb6eabe 822 }\r
2cb6eabe
EL
823}\r
824\r
825/**\r
826 Write data from buffer to debug device.\r
827\r
828 Writes NumberOfBytes data bytes from Buffer to the debug device.\r
829 The number of bytes actually written to the debug device is returned.\r
830 If the return value is less than NumberOfBytes, then the write operation failed.\r
831 If NumberOfBytes is zero, then return 0.\r
832\r
833 @param Handle Debug port handle.\r
834 @param Buffer Pointer to the data buffer to be written.\r
835 @param NumberOfBytes Number of bytes to written to the debug device.\r
836\r
837 @retval 0 NumberOfBytes is 0.\r
838 @retval >0 The number of bytes written to the debug device.\r
f4043414 839 If this value is less than NumberOfBytes, then the write operation failed.\r
2cb6eabe
EL
840\r
841**/\r
842UINTN\r
843EFIAPI\r
844DebugPortWriteBuffer (\r
845 IN DEBUG_PORT_HANDLE Handle,\r
846 IN UINT8 *Buffer,\r
847 IN UINTN NumberOfBytes\r
848 )\r
849{\r
850 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1f279e7a 851 RETURN_STATUS Status;\r
2cb6eabe
EL
852 UINTN Sent;\r
853 UINTN Total;\r
1f279e7a 854 EFI_PHYSICAL_ADDRESS XhciMmioBase;\r
373b1d0e 855 UINTN Index;\r
2cb6eabe
EL
856\r
857 if (NumberOfBytes == 0 || Buffer == NULL) {\r
858 return 0;\r
859 }\r
860\r
861 Sent = 0;\r
862 Total = 0;\r
863\r
1f279e7a
SZ
864 //\r
865 // If Handle is NULL, it means memory is ready for use.\r
866 // Use global variable to store handle value.\r
867 //\r
868 if (Handle == NULL) {\r
869 UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
870 } else {\r
871 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
2cb6eabe 872 }\r
1f279e7a
SZ
873 \r
874 if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
de8373fa
SZ
875 return 0;\r
876 }\r
2cb6eabe 877\r
1f279e7a
SZ
878 //\r
879 // MMIO base address is possible to clear, set it if it is cleared. (XhciMemorySpaceClose in PchUsbCommon.c)\r
880 //\r
881 XhciMmioBase = ProgramXhciBaseAddress ();\r
882\r
883 UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
884\r
885 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
886 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
887 if (RETURN_ERROR(Status)) {\r
888 return 0;\r
889 }\r
2cb6eabe
EL
890 }\r
891\r
892 //\r
893 // When host is trying to send data, write will be blocked.\r
894 // Poll to see if there is any data sent by host at first.\r
895 //\r
1f279e7a 896 DebugPortPollBuffer (Handle);\r
2cb6eabe 897\r
373b1d0e 898 Index = 0;\r
2cb6eabe 899 while ((Total < NumberOfBytes)) {\r
5d6507a1
EL
900 if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {\r
901 Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;\r
2cb6eabe
EL
902 } else {\r
903 Sent = (UINT8)(NumberOfBytes - Total);\r
904 }\r
1f279e7a 905 Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);\r
2cb6eabe
EL
906 Total += Sent;\r
907 }\r
908 \r
909 return Total;\r
910}\r
911\r
912/**\r
913 Polls a debug device to see if there is any data waiting to be read.\r
914\r
915 Polls a debug device to see if there is any data waiting to be read.\r
916 If there is data waiting to be read from the debug device, then TRUE is returned.\r
917 If there is no data waiting to be read from the debug device, then FALSE is returned.\r
918\r
919 @param Handle Debug port handle.\r
920\r
921 @retval TRUE Data is waiting to be read from the debug device.\r
f4043414 922 @retval FALSE There is no data waiting to be read from the debug device.\r
2cb6eabe
EL
923\r
924**/\r
925BOOLEAN\r
926EFIAPI\r
927DebugPortPollBuffer (\r
928 IN DEBUG_PORT_HANDLE Handle\r
929 )\r
930{\r
931 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
932 UINTN Length;\r
1f279e7a
SZ
933 RETURN_STATUS Status;\r
934 EFI_PHYSICAL_ADDRESS XhciMmioBase;\r
2cb6eabe 935\r
1f279e7a
SZ
936 //\r
937 // If Handle is NULL, it means memory is ready for use.\r
938 // Use global variable to store handle value.\r
939 //\r
940 if (Handle == NULL) {\r
941 UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
942 } else {\r
943 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
2cb6eabe
EL
944 }\r
945\r
1f279e7a
SZ
946 if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
947 return 0;\r
2cb6eabe
EL
948 }\r
949\r
1f279e7a
SZ
950 XhciMmioBase = ProgramXhciBaseAddress ();\r
951 UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
952 \r
953 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
954 Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
955 if (RETURN_ERROR(Status)) {\r
956 return FALSE;\r
957 }\r
2cb6eabe 958 }\r
1f279e7a 959 \r
2cb6eabe
EL
960 //\r
961 // If the data buffer is not empty, then return TRUE directly.\r
962 // Otherwise initialize a usb read transaction and read data to internal data buffer.\r
963 //\r
964 if (UsbDebugPortHandle->DataCount != 0) {\r
965 return TRUE;\r
966 }\r
967\r
968 //\r
5d6507a1 969 // Read data as much as we can\r
2cb6eabe 970 //\r
5d6507a1 971 Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
1f279e7a 972 XhcDataTransfer (Handle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);\r
2cb6eabe 973\r
5d6507a1 974 if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
2cb6eabe
EL
975 return FALSE;\r
976 }\r
977\r
978 if (Length == 0) {\r
979 return FALSE;\r
980 }\r
981\r
982 //\r
983 // Store data into internal buffer for use later\r
984 //\r
2cb6eabe
EL
985 UsbDebugPortHandle->DataCount = (UINT8) Length;\r
986 return TRUE;\r
987}\r
988\r
989/**\r
990 Initialize the debug port.\r
991\r
74cdb367 992 If Function is not NULL, Debug Communication Library will call this function\r
2cb6eabe
EL
993 by passing in the Context to be the first parameter. If needed, Debug Communication\r
994 Library will create one debug port handle to be the second argument passing in\r
995 calling the Function, otherwise it will pass NULL to be the second argument of\r
996 Function.\r
997\r
998 If Function is NULL, and Context is not NULL, the Debug Communication Library could\r
999 a) Return the same handle as passed in (as Context parameter).\r
74cdb367 1000 b) Ignore the input Context parameter and create new handle to be returned.\r
2cb6eabe
EL
1001\r
1002 If parameter Function is NULL and Context is NULL, Debug Communication Library could\r
1003 created a new handle if needed and return it, otherwise it will return NULL.\r
1004\r
1005 @param[in] Context Context needed by callback function; it was optional.\r
1006 @param[in] Function Continue function called by Debug Communication library;\r
1007 it was optional.\r
1008\r
1009 @return The debug port handle created by Debug Communication Library if Function\r
1010 is not NULL.\r
1011\r
1012**/\r
1013DEBUG_PORT_HANDLE\r
1014EFIAPI\r
1015DebugPortInitialize (\r
1016 IN VOID *Context,\r
1017 IN DEBUG_PORT_CONTINUE Function\r
1018 )\r
1019{\r
1f279e7a
SZ
1020 RETURN_STATUS Status;\r
1021 USB3_DEBUG_PORT_HANDLE Handle;\r
2cb6eabe 1022 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
2cb6eabe 1023\r
1f279e7a
SZ
1024 //\r
1025 // Validate the PCD PcdDebugPortHandleBufferSize value \r
1026 //\r
1027 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));\r
1028\r
1029 if (Function == NULL && Context != NULL) {\r
1030 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Context;\r
1031 } else {\r
1032 ZeroMem(&Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
1033 UsbDebugPortHandle = &Handle;\r
2cb6eabe
EL
1034 }\r
1035\r
1f279e7a
SZ
1036 if (Function == NULL && Context != NULL) {\r
1037 return (DEBUG_PORT_HANDLE *) Context;\r
1038 }\r
1039 \r
1040 //\r
1041 // Read 64-bit MMIO base address\r
1042 //\r
1043 UsbDebugPortHandle->XhciMmioBase = ProgramXhciBaseAddress ();\r
1044\r
1045 Status = CalculateUsbDebugPortMmioBase (UsbDebugPortHandle);\r
1046 if (RETURN_ERROR (Status)) {\r
1047 goto Exit;\r
1048 }\r
1049\r
1050 if (NeedReinitializeHardware(&Handle)) {\r
1051 Status = InitializeUsbDebugHardware (&Handle);\r
1052 if (RETURN_ERROR(Status)) {\r
1053 goto Exit;\r
1054 }\r
1055 }\r
1056\r
1057Exit:\r
1058\r
2cb6eabe 1059 if (Function != NULL) {\r
1f279e7a
SZ
1060 Function (Context, &Handle);\r
1061 } else {\r
1062 CopyMem(&mDebugCommunicationLibUsb3DebugPortHandle, &Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
2cb6eabe
EL
1063 }\r
1064\r
1f279e7a 1065 return (DEBUG_PORT_HANDLE)(UINTN)&mDebugCommunicationLibUsb3DebugPortHandle;\r
2cb6eabe 1066}\r