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