]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
SourceLevelDebugPkg DebugCommUsb3: Refine some formats/comments
[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
f0c56276 88 @param Offset The offset of the debug 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
f0c56276
SZ
95 IN UINT32 Offset,\r
96 IN UINT32 Data\r
2cb6eabe
EL
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
f0c56276 119 IN UINT32 Offset\r
2cb6eabe
EL
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
f0c56276 132 Set one bit of the debug register while keeping other bits.\r
2cb6eabe
EL
133\r
134 @param Handle Debug port handle.\r
f0c56276 135 @param Offset The offset of the debug register.\r
2cb6eabe
EL
136 @param Bit The bit mask of the register to set.\r
137\r
138**/\r
139VOID\r
140XhcSetDebugRegBit (\r
f0c56276 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
f0c56276 219 @retval RETURN_UNSUPPORTED The usb host controller does not support 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
2cb6eabe
EL
855\r
856 if (NumberOfBytes == 0 || Buffer == NULL) {\r
857 return 0;\r
858 }\r
859\r
860 Sent = 0;\r
861 Total = 0;\r
862\r
1f279e7a
SZ
863 //\r
864 // If Handle is NULL, it means memory is ready for use.\r
865 // Use global variable to store handle value.\r
866 //\r
867 if (Handle == NULL) {\r
868 UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
869 } else {\r
870 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
2cb6eabe 871 }\r
1f279e7a
SZ
872 \r
873 if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
de8373fa
SZ
874 return 0;\r
875 }\r
2cb6eabe 876\r
1f279e7a
SZ
877 //\r
878 // MMIO base address is possible to clear, set it if it is cleared. (XhciMemorySpaceClose in PchUsbCommon.c)\r
879 //\r
880 XhciMmioBase = ProgramXhciBaseAddress ();\r
881\r
882 UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
883\r
884 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
885 Status = InitializeUsbDebugHardware (UsbDebugPortHandle);\r
886 if (RETURN_ERROR(Status)) {\r
887 return 0;\r
888 }\r
2cb6eabe
EL
889 }\r
890\r
891 //\r
892 // When host is trying to send data, write will be blocked.\r
893 // Poll to see if there is any data sent by host at first.\r
894 //\r
1f279e7a 895 DebugPortPollBuffer (Handle);\r
2cb6eabe 896\r
2cb6eabe 897 while ((Total < NumberOfBytes)) {\r
5d6507a1
EL
898 if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {\r
899 Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;\r
2cb6eabe
EL
900 } else {\r
901 Sent = (UINT8)(NumberOfBytes - Total);\r
902 }\r
1f279e7a 903 Status = XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);\r
2cb6eabe
EL
904 Total += Sent;\r
905 }\r
906 \r
907 return Total;\r
908}\r
909\r
910/**\r
911 Polls a debug device to see if there is any data waiting to be read.\r
912\r
913 Polls a debug device to see if there is any data waiting to be read.\r
914 If there is data waiting to be read from the debug device, then TRUE is returned.\r
915 If there is no data waiting to be read from the debug device, then FALSE is returned.\r
916\r
917 @param Handle Debug port handle.\r
918\r
919 @retval TRUE Data is waiting to be read from the debug device.\r
f4043414 920 @retval FALSE There is no data waiting to be read from the debug device.\r
2cb6eabe
EL
921\r
922**/\r
923BOOLEAN\r
924EFIAPI\r
925DebugPortPollBuffer (\r
926 IN DEBUG_PORT_HANDLE Handle\r
927 )\r
928{\r
929 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
930 UINTN Length;\r
1f279e7a
SZ
931 RETURN_STATUS Status;\r
932 EFI_PHYSICAL_ADDRESS XhciMmioBase;\r
2cb6eabe 933\r
1f279e7a
SZ
934 //\r
935 // If Handle is NULL, it means memory is ready for use.\r
936 // Use global variable to store handle value.\r
937 //\r
938 if (Handle == NULL) {\r
939 UsbDebugPortHandle = &mDebugCommunicationLibUsb3DebugPortHandle;\r
940 } else {\r
941 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
2cb6eabe
EL
942 }\r
943\r
1f279e7a
SZ
944 if (UsbDebugPortHandle->Initialized == USB3DBG_NO_DBG_CAB) {\r
945 return 0;\r
2cb6eabe
EL
946 }\r
947\r
1f279e7a
SZ
948 XhciMmioBase = ProgramXhciBaseAddress ();\r
949 UpdateXhcResource (UsbDebugPortHandle, XhciMmioBase);\r
950 \r
951 if (NeedReinitializeHardware(UsbDebugPortHandle)) {\r
952 Status = InitializeUsbDebugHardware(UsbDebugPortHandle);\r
953 if (RETURN_ERROR(Status)) {\r
954 return FALSE;\r
955 }\r
2cb6eabe 956 }\r
1f279e7a 957 \r
2cb6eabe
EL
958 //\r
959 // If the data buffer is not empty, then return TRUE directly.\r
960 // Otherwise initialize a usb read transaction and read data to internal data buffer.\r
961 //\r
962 if (UsbDebugPortHandle->DataCount != 0) {\r
963 return TRUE;\r
964 }\r
965\r
966 //\r
5d6507a1 967 // Read data as much as we can\r
2cb6eabe 968 //\r
5d6507a1 969 Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
1f279e7a 970 XhcDataTransfer (Handle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);\r
2cb6eabe 971\r
5d6507a1 972 if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
2cb6eabe
EL
973 return FALSE;\r
974 }\r
975\r
976 if (Length == 0) {\r
977 return FALSE;\r
978 }\r
979\r
980 //\r
981 // Store data into internal buffer for use later\r
982 //\r
2cb6eabe
EL
983 UsbDebugPortHandle->DataCount = (UINT8) Length;\r
984 return TRUE;\r
985}\r
986\r
987/**\r
988 Initialize the debug port.\r
989\r
74cdb367 990 If Function is not NULL, Debug Communication Library will call this function\r
2cb6eabe
EL
991 by passing in the Context to be the first parameter. If needed, Debug Communication\r
992 Library will create one debug port handle to be the second argument passing in\r
993 calling the Function, otherwise it will pass NULL to be the second argument of\r
994 Function.\r
995\r
996 If Function is NULL, and Context is not NULL, the Debug Communication Library could\r
997 a) Return the same handle as passed in (as Context parameter).\r
74cdb367 998 b) Ignore the input Context parameter and create new handle to be returned.\r
2cb6eabe
EL
999\r
1000 If parameter Function is NULL and Context is NULL, Debug Communication Library could\r
1001 created a new handle if needed and return it, otherwise it will return NULL.\r
1002\r
1003 @param[in] Context Context needed by callback function; it was optional.\r
1004 @param[in] Function Continue function called by Debug Communication library;\r
1005 it was optional.\r
1006\r
1007 @return The debug port handle created by Debug Communication Library if Function\r
1008 is not NULL.\r
1009\r
1010**/\r
1011DEBUG_PORT_HANDLE\r
1012EFIAPI\r
1013DebugPortInitialize (\r
1014 IN VOID *Context,\r
1015 IN DEBUG_PORT_CONTINUE Function\r
1016 )\r
1017{\r
1f279e7a
SZ
1018 RETURN_STATUS Status;\r
1019 USB3_DEBUG_PORT_HANDLE Handle;\r
2cb6eabe 1020 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
2cb6eabe 1021\r
1f279e7a
SZ
1022 //\r
1023 // Validate the PCD PcdDebugPortHandleBufferSize value \r
1024 //\r
1025 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));\r
1026\r
1027 if (Function == NULL && Context != NULL) {\r
1028 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Context;\r
1029 } else {\r
1030 ZeroMem(&Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
1031 UsbDebugPortHandle = &Handle;\r
2cb6eabe
EL
1032 }\r
1033\r
1f279e7a
SZ
1034 if (Function == NULL && Context != NULL) {\r
1035 return (DEBUG_PORT_HANDLE *) Context;\r
1036 }\r
1037 \r
1038 //\r
1039 // Read 64-bit MMIO base address\r
1040 //\r
1041 UsbDebugPortHandle->XhciMmioBase = ProgramXhciBaseAddress ();\r
1042\r
1043 Status = CalculateUsbDebugPortMmioBase (UsbDebugPortHandle);\r
1044 if (RETURN_ERROR (Status)) {\r
1045 goto Exit;\r
1046 }\r
1047\r
1048 if (NeedReinitializeHardware(&Handle)) {\r
1049 Status = InitializeUsbDebugHardware (&Handle);\r
1050 if (RETURN_ERROR(Status)) {\r
1051 goto Exit;\r
1052 }\r
1053 }\r
1054\r
1055Exit:\r
1056\r
2cb6eabe 1057 if (Function != NULL) {\r
1f279e7a
SZ
1058 Function (Context, &Handle);\r
1059 } else {\r
1060 CopyMem(&mDebugCommunicationLibUsb3DebugPortHandle, &Handle, sizeof (USB3_DEBUG_PORT_HANDLE));\r
2cb6eabe
EL
1061 }\r
1062\r
1f279e7a 1063 return (DEBUG_PORT_HANDLE)(UINTN)&mDebugCommunicationLibUsb3DebugPortHandle;\r
2cb6eabe 1064}\r