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