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