]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Common.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
c1e126b1 11UINT16 mString0Desc[] = {\r
2cb6eabe 12 // String Descriptor Type + Length\r
c1e126b1 13 (USB_DESC_TYPE_STRING << 8) + STRING0_DESC_LEN,\r
2cb6eabe
EL
14 0x0409\r
15};\r
16\r
c1e126b1 17UINT16 mManufacturerStrDesc[] = {\r
2cb6eabe 18 // String Descriptor Type + Length\r
c1e126b1
MK
19 (USB_DESC_TYPE_STRING << 8) + MANU_DESC_LEN,\r
20 'I', 'n','t', 'e', 'l'\r
2cb6eabe
EL
21};\r
22\r
c1e126b1 23UINT16 mProductStrDesc[] = {\r
2cb6eabe 24 // String Descriptor Type + Length\r
c1e126b1
MK
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
2cb6eabe
EL
27};\r
28\r
c1e126b1 29UINT16 mSerialNumberStrDesc[] = {\r
2cb6eabe 30 // String Descriptor Type + Length\r
c1e126b1 31 (USB_DESC_TYPE_STRING << 8) + SERIAL_DESC_LEN,\r
2cb6eabe
EL
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
c1e126b1
MK
42XhcSetR32Bit (\r
43 IN OUT UINTN Register,\r
44 IN UINT32 BitMask\r
2cb6eabe
EL
45 )\r
46{\r
c1e126b1 47 UINT32 RegisterValue;\r
2cb6eabe 48\r
c1e126b1 49 RegisterValue = MmioRead32 (Register);\r
2cb6eabe
EL
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
c1e126b1
MK
61XhcClearR32Bit (\r
62 IN OUT UINTN Register,\r
63 IN UINT32 BitMask\r
2cb6eabe
EL
64 )\r
65{\r
c1e126b1 66 UINT32 RegisterValue;\r
2cb6eabe 67\r
c1e126b1 68 RegisterValue = MmioRead32 (Register);\r
2cb6eabe
EL
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
c1e126b1
MK
107 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
108 IN UINT32 Offset\r
2cb6eabe
EL
109 )\r
110{\r
c1e126b1
MK
111 UINT32 Data;\r
112 EFI_PHYSICAL_ADDRESS DebugCapabilityBase;\r
77695f4d 113\r
2cb6eabe 114 DebugCapabilityBase = Handle->DebugCapabilityBase;\r
c1e126b1 115 Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));\r
2cb6eabe
EL
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
c1e126b1
MK
130 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
131 IN UINT32 Offset,\r
132 IN UINT32 Bit\r
2cb6eabe
EL
133 )\r
134{\r
c1e126b1 135 UINT32 Data;\r
2cb6eabe
EL
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
c1e126b1
MK
152 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
153 IN UINT32 Offset,\r
154 IN UINT32 Bit\r
75787f65
SZ
155 )\r
156{\r
c1e126b1 157 UINT32 Data;\r
75787f65
SZ
158\r
159 Data = XhcReadDebugReg (Handle, Offset);\r
c1e126b1 160 Data &= ~Bit;\r
75787f65
SZ
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
c1e126b1
MK
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
2cb6eabe
EL
183 XhciMmioBase &= XHCI_BASE_ADDRESS_64_BIT_MASK;\r
184\r
185 if ((XhciMmioBase == 0) || (XhciMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {\r
c1e126b1
MK
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
2cb6eabe
EL
189 }\r
190\r
c1e126b1 191 PciCmd = PciRead16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET);\r
2cb6eabe
EL
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
c1e126b1 194 PciWrite16 (PcdGet32 (PcdUsbXhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
2cb6eabe
EL
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
c1e126b1
MK
209 IN OUT USB3_DEBUG_PORT_HANDLE *Handle,\r
210 IN EFI_PHYSICAL_ADDRESS XhciMmioBase\r
2cb6eabe
EL
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
c1e126b1
MK
237 USB3_DEBUG_PORT_HANDLE *Handle\r
238 )\r
2cb6eabe 239{\r
c1e126b1
MK
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
2cb6eabe 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
c1e126b1
MK
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
c1e126b1
MK
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
c1e126b1 273 CapLength = MmioRead8 ((UINTN)Handle->XhciMmioBase);\r
2cb6eabe
EL
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
c1e126b1 283 Flag = FALSE;\r
2cb6eabe
EL
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
c1e126b1 290\r
2cb6eabe
EL
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
c1e126b1 297\r
2cb6eabe 298 CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;\r
c1e126b1 299 Capability = MmioRead32 ((UINTN)CapabilityPointer);\r
2cb6eabe
EL
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
c1e126b1
MK
312 Handle->DebugSupport = TRUE;\r
313 Handle->Initialized = USB3DBG_DBG_CAB;\r
2cb6eabe
EL
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
74cdb367 325 whether the usb debug port hardware configuration is changed. Such case can be triggered by\r
2cb6eabe
EL
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
c1e126b1
MK
336NeedReinitializeHardware (\r
337 IN USB3_DEBUG_PORT_HANDLE *Handle\r
2cb6eabe
EL
338 )\r
339{\r
c1e126b1
MK
340 BOOLEAN Result;\r
341 volatile UINT32 Dcctrl;\r
2cb6eabe
EL
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
75787f65 351 } else if (!Handle->Ready) {\r
c1e126b1 352 Handle->Ready = TRUE;\r
75787f65 353 Handle->Initialized = USB3DBG_ENABLED;\r
2cb6eabe
EL
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
c1e126b1
MK
368 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
369 OUT EVENT_RING *EventRing\r
2cb6eabe
EL
370 )\r
371{\r
372 VOID *Buf;\r
373 EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;\r
374\r
375 ASSERT (EventRing != NULL);\r
77695f4d 376\r
2cb6eabe
EL
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
c1e126b1 382 ASSERT (((UINTN)Buf & 0x3F) == 0);\r
2cb6eabe
EL
383 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
384\r
c1e126b1 385 EventRing->EventRingSeg0 = (EFI_PHYSICAL_ADDRESS)(UINTN)Buf;\r
2cb6eabe 386 EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;\r
c1e126b1
MK
387 EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN)EventRing->EventRingSeg0;\r
388 EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EventRing->EventRingSeg0;\r
77695f4d 389\r
2cb6eabe
EL
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
c1e126b1 401 ASSERT (((UINTN)Buf & 0x3F) == 0);\r
2cb6eabe
EL
402 ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
403\r
c1e126b1
MK
404 ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *)Buf;\r
405 EventRing->ERSTBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ERSTBase;\r
2cb6eabe
EL
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
c1e126b1 420 XHC_LOW_32BIT ((UINT64)(UINTN)EventRing->EventRingDequeue)\r
2cb6eabe
EL
421 );\r
422\r
423 XhcWriteDebugReg (\r
424 Handle,\r
425 XHC_DC_DCERDP + 4,\r
c1e126b1 426 XHC_HIGH_32BIT ((UINT64)(UINTN)EventRing->EventRingDequeue)\r
2cb6eabe
EL
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
c1e126b1 435 XHC_LOW_32BIT ((UINT64)(UINTN)ERSTBase)\r
2cb6eabe
EL
436 );\r
437\r
438 XhcWriteDebugReg (\r
439 Handle,\r
440 XHC_DC_DCERSTBA + 4,\r
c1e126b1 441 XHC_HIGH_32BIT ((UINT64)(UINTN)ERSTBase)\r
2cb6eabe
EL
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
c1e126b1
MK
465 IN USB3_DEBUG_PORT_HANDLE *Handle,\r
466 IN UINT32 TrbNum,\r
467 OUT TRANSFER_RING *TransferRing\r
2cb6eabe
EL
468 )\r
469{\r
c1e126b1
MK
470 VOID *Buf;\r
471 LINK_TRB *EndTrb;\r
77695f4d 472\r
2cb6eabe
EL
473 Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);\r
474 ASSERT (Buf != NULL);\r
c1e126b1 475 ASSERT (((UINTN)Buf & 0xF) == 0);\r
2cb6eabe
EL
476 ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
477\r
c1e126b1
MK
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
2cb6eabe
EL
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
c1e126b1 488 EndTrb = (LINK_TRB *)((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));\r
2cb6eabe
EL
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
c1e126b1 495 EndTrb->TC = 1;\r
2cb6eabe
EL
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
c1e126b1 513 IN USB3_DEBUG_PORT_HANDLE *Handle\r
2cb6eabe
EL
514 )\r
515{\r
c1e126b1
MK
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
77695f4d 522\r
2cb6eabe
EL
523 //\r
524 // Allocate debug device context\r
525 //\r
526 Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));\r
527 ASSERT (Buf != NULL);\r
c1e126b1 528 ASSERT (((UINTN)Buf & 0xF) == 0);\r
2cb6eabe 529 ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));\r
77695f4d 530\r
c1e126b1
MK
531 DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN)Buf;\r
532 Handle->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN)DebugCapabilityContext;\r
77695f4d 533\r
2cb6eabe
EL
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
5d6507a1 547 DebugCapabilityContext->EpOutContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
2cb6eabe 548 DebugCapabilityContext->EpOutContext.AverageTRBLength = 0x1000;\r
77695f4d 549\r
2cb6eabe
EL
550 //\r
551 // Initialize EpInContext.\r
552 //\r
553 DebugCapabilityContext->EpInContext.CErr = 0x3;\r
554 DebugCapabilityContext->EpInContext.EPType = ED_BULK_IN;\r
5d6507a1 555 DebugCapabilityContext->EpInContext.MaxPacketSize = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
2cb6eabe 556 DebugCapabilityContext->EpInContext.AverageTRBLength = 0x1000;\r
77695f4d 557\r
2cb6eabe
EL
558 //\r
559 // Update string descriptor address\r
560 //\r
c1e126b1 561 String0Desc = (UINT8 *)AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);\r
2cb6eabe
EL
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
77695f4d 566\r
2cb6eabe
EL
567 ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;\r
568 CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);\r
569 DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;\r
77695f4d 570\r
2cb6eabe
EL
571 ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;\r
572 CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);\r
573 DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;\r
77695f4d 574\r
2cb6eabe
EL
575 SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;\r
576 CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);\r
577 DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;\r
77695f4d 578\r
2cb6eabe
EL
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
c1e126b1 601 XHC_LOW_32BIT ((UINT64)(UINTN)DebugCapabilityContext)\r
2cb6eabe
EL
602 );\r
603 XhcWriteDebugReg (\r
604 Handle,\r
605 XHC_DC_DCCP + 4,\r
c1e126b1 606 XHC_HIGH_32BIT ((UINT64)(UINTN)DebugCapabilityContext)\r
2cb6eabe
EL
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
c1e126b1 619 IN USB3_DEBUG_PORT_HANDLE *Handle\r
2cb6eabe
EL
620 )\r
621{\r
c1e126b1
MK
622 UINT64 TimeOut;\r
623 volatile UINT32 Dcctrl;\r
2cb6eabe
EL
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
c1e126b1 647\r
2cb6eabe
EL
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
c1e126b1 665 IN USB3_DEBUG_PORT_HANDLE *Handle\r
2cb6eabe
EL
666 )\r
667{\r
c1e126b1
MK
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
2cb6eabe
EL
674\r
675 XhciOpRegister = Handle->XhciOpRegister;\r
c1e126b1 676 TotalUsb3Port = MmioRead32 (((UINTN)Handle->XhciMmioBase + XHC_HCSPARAMS1_OFFSET)) >> 24;\r
2cb6eabe
EL
677\r
678 if (Handle->Initialized == USB3DBG_NOT_ENABLED) {\r
c1e126b1 679 Dcddi1 = XhcReadDebugReg (Handle, XHC_DC_DCDDI1);\r
df67a480
SZ
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
c1e126b1 686\r
2cb6eabe 687 //\r
77695f4d 688 // If XHCI supports debug capability, hardware resource has been allocated,\r
2cb6eabe
EL
689 // but it has not been enabled, try to enable again.\r
690 //\r
691 goto Enable;\r
692 }\r
693\r
694 //\r
5d6507a1
EL
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
2cb6eabe 698 //\r
5d6507a1 699 Buffer = AllocateAlignBuffer (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE);\r
2cb6eabe
EL
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
77695f4d 709 //\r
2cb6eabe
EL
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
75787f65
SZ
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
2cb6eabe 722 //\r
5d6507a1 723 // Construct the buffer for read, poll and write.\r
2cb6eabe 724 //\r
c1e126b1
MK
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
5d6507a1 727 Handle->UrbOut.Data = Handle->UrbIn.Data + XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2;\r
77695f4d 728\r
2cb6eabe
EL
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
77695f4d 735\r
2cb6eabe
EL
736 //\r
737 // Init IN and OUT endpoint context\r
738 //\r
739 Status = CreateDebugCapabilityContext (Handle);\r
740 ASSERT_EFI_ERROR (Status);\r
77695f4d 741\r
2cb6eabe
EL
742 //\r
743 // Init DCDDI1 and DCDDI2\r
744 //\r
745 XhcWriteDebugReg (\r
c1e126b1
MK
746 Handle,\r
747 XHC_DC_DCDDI1,\r
748 (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)\r
749 );\r
2cb6eabe
EL
750\r
751 XhcWriteDebugReg (\r
c1e126b1
MK
752 Handle,\r
753 XHC_DC_DCDDI2,\r
754 (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)\r
755 );\r
2cb6eabe
EL
756\r
757Enable:\r
758 if ((Handle->Initialized == USB3DBG_NOT_ENABLED) && (!Handle->ChangePortPower)) {\r
759 //\r
77695f4d 760 // If the first time detection is failed, turn port power off and on in order to\r
2cb6eabe
EL
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
77695f4d 776\r
2cb6eabe 777 XhcDetectDebugCapabilityReady (Handle);\r
77695f4d 778\r
2cb6eabe
EL
779 Status = RETURN_SUCCESS;\r
780 if (!Handle->Ready) {\r
781 Handle->Initialized = USB3DBG_NOT_ENABLED;\r
c1e126b1 782 Status = RETURN_NOT_READY;\r
2cb6eabe
EL
783 } else {\r
784 Handle->Initialized = USB3DBG_ENABLED;\r
785 }\r
786\r
787 return Status;\r
788}\r
789\r
75787f65
SZ
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
c1e126b1 798 IN USB3_DEBUG_PORT_HANDLE *Handle\r
75787f65
SZ
799 )\r
800{\r
c1e126b1
MK
801 EFI_STATUS Status;\r
802 EFI_PHYSICAL_ADDRESS XhciMmioBase;\r
75787f65
SZ
803\r
804 //\r
805 // Read 64-bit MMIO base address\r
806 //\r
c1e126b1 807 XhciMmioBase = ProgramXhciBaseAddress ();\r
75787f65
SZ
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
77695f4d 824**/\r
75787f65
SZ
825VOID\r
826SetUsb3DebugPortInstance (\r
c1e126b1 827 IN USB3_DEBUG_PORT_HANDLE *Instance\r
75787f65
SZ
828 )\r
829{\r
c1e126b1 830 EFI_PHYSICAL_ADDRESS *AddrPtr;\r
75787f65
SZ
831\r
832 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();\r
833 ASSERT (AddrPtr != NULL);\r
c1e126b1 834 *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;\r
75787f65
SZ
835}\r
836\r
837/**\r
838 Return USB3 debug instance address.\r
839\r
77695f4d 840**/\r
75787f65
SZ
841USB3_DEBUG_PORT_HANDLE *\r
842GetUsb3DebugPortInstance (\r
843 VOID\r
844 )\r
845{\r
c1e126b1
MK
846 EFI_PHYSICAL_ADDRESS *AddrPtr;\r
847 USB3_DEBUG_PORT_HANDLE *Instance;\r
75787f65
SZ
848\r
849 AddrPtr = GetUsb3DebugPortInstanceAddrPtr ();\r
850 ASSERT (AddrPtr != NULL);\r
851\r
c1e126b1 852 Instance = (USB3_DEBUG_PORT_HANDLE *)(UINTN)*AddrPtr;\r
75787f65
SZ
853\r
854 return Instance;\r
855}\r
856\r
2cb6eabe
EL
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
f4043414 868 @param Timeout Timeout value for reading from debug device. Its unit is Microsecond.\r
2cb6eabe
EL
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
c1e126b1
MK
877 IN DEBUG_PORT_HANDLE Handle,\r
878 IN UINT8 *Buffer,\r
879 IN UINTN NumberOfBytes,\r
880 IN UINTN Timeout\r
2cb6eabe
EL
881 )\r
882{\r
c1e126b1
MK
883 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
884 UINT8 Index;\r
885 UINT8 *Data;\r
2cb6eabe 886\r
c1e126b1 887 if ((NumberOfBytes != 1) || (Buffer == NULL) || (Timeout != 0)) {\r
2cb6eabe
EL
888 return 0;\r
889 }\r
890\r
1f279e7a 891 //\r
75787f65
SZ
892 // If Handle is NULL, get own instance.\r
893 // If Handle is not NULL, use it and set the instance.\r
1f279e7a 894 //\r
75787f65 895 if (Handle != NULL) {\r
c1e126b1 896 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
75787f65 897 SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
1f279e7a 898 } else {\r
75787f65 899 UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
2cb6eabe 900 }\r
c1e126b1 901\r
75787f65 902 if (UsbDebugPortHandle == NULL) {\r
2cb6eabe
EL
903 return 0;\r
904 }\r
75787f65
SZ
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
2cb6eabe
EL
914 }\r
915\r
5d6507a1
EL
916 Data = (UINT8 *)(UINTN)UsbDebugPortHandle->Data;\r
917\r
2cb6eabe 918 //\r
08021523 919 // Read data from buffer\r
2cb6eabe 920 //\r
08021523
JF
921 if (UsbDebugPortHandle->DataCount < 1) {\r
922 return 0;\r
923 } else {\r
924 *Buffer = Data[0];\r
2cb6eabe 925\r
08021523
JF
926 for (Index = 0; Index < UsbDebugPortHandle->DataCount - 1; Index++) {\r
927 if ((Index + 1) >= XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
2cb6eabe
EL
928 return 0;\r
929 }\r
c1e126b1 930\r
08021523 931 Data[Index] = Data[Index + 1];\r
2cb6eabe 932 }\r
c1e126b1 933\r
08021523
JF
934 UsbDebugPortHandle->DataCount = (UINT8)(UsbDebugPortHandle->DataCount - 1);\r
935 return 1;\r
2cb6eabe 936 }\r
2cb6eabe
EL
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
f4043414 953 If this value is less than NumberOfBytes, then the write operation failed.\r
2cb6eabe
EL
954\r
955**/\r
956UINTN\r
957EFIAPI\r
958DebugPortWriteBuffer (\r
c1e126b1
MK
959 IN DEBUG_PORT_HANDLE Handle,\r
960 IN UINT8 *Buffer,\r
961 IN UINTN NumberOfBytes\r
2cb6eabe
EL
962 )\r
963{\r
c1e126b1
MK
964 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
965 UINTN Sent;\r
966 UINTN Total;\r
2cb6eabe 967\r
c1e126b1 968 if ((NumberOfBytes == 0) || (Buffer == NULL)) {\r
2cb6eabe
EL
969 return 0;\r
970 }\r
971\r
972 Sent = 0;\r
973 Total = 0;\r
974\r
1f279e7a 975 //\r
75787f65
SZ
976 // If Handle is NULL, get own instance.\r
977 // If Handle is not NULL, use it and set the instance.\r
1f279e7a 978 //\r
75787f65 979 if (Handle != NULL) {\r
c1e126b1 980 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
75787f65 981 SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
1f279e7a 982 } else {\r
75787f65 983 UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
2cb6eabe 984 }\r
c1e126b1 985\r
75787f65 986 if (UsbDebugPortHandle == NULL) {\r
de8373fa
SZ
987 return 0;\r
988 }\r
2cb6eabe 989\r
75787f65
SZ
990 if (UsbDebugPortHandle->InNotify) {\r
991 return 0;\r
992 }\r
1f279e7a 993\r
75787f65 994 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
1f279e7a 995\r
75787f65
SZ
996 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {\r
997 return 0;\r
2cb6eabe
EL
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
75787f65 1004 DebugPortPollBuffer (UsbDebugPortHandle);\r
2cb6eabe 1005\r
2cb6eabe 1006 while ((Total < NumberOfBytes)) {\r
5d6507a1
EL
1007 if (NumberOfBytes - Total > USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE) {\r
1008 Sent = USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE;\r
2cb6eabe
EL
1009 } else {\r
1010 Sent = (UINT8)(NumberOfBytes - Total);\r
1011 }\r
c1e126b1 1012\r
75787f65 1013 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataOut, Buffer + Total, &Sent, DATA_TRANSFER_WRITE_TIMEOUT);\r
2cb6eabe
EL
1014 Total += Sent;\r
1015 }\r
77695f4d 1016\r
2cb6eabe
EL
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
f4043414 1030 @retval FALSE There is no data waiting to be read from the debug device.\r
2cb6eabe
EL
1031\r
1032**/\r
1033BOOLEAN\r
1034EFIAPI\r
1035DebugPortPollBuffer (\r
c1e126b1 1036 IN DEBUG_PORT_HANDLE Handle\r
2cb6eabe
EL
1037 )\r
1038{\r
c1e126b1
MK
1039 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
1040 UINTN Length;\r
2cb6eabe 1041\r
1f279e7a 1042 //\r
75787f65
SZ
1043 // If Handle is NULL, get own instance.\r
1044 // If Handle is not NULL, use it and set the instance.\r
1f279e7a 1045 //\r
75787f65 1046 if (Handle != NULL) {\r
c1e126b1 1047 UsbDebugPortHandle = (USB3_DEBUG_PORT_HANDLE *)Handle;\r
75787f65 1048 SetUsb3DebugPortInstance (UsbDebugPortHandle);\r
1f279e7a 1049 } else {\r
75787f65
SZ
1050 UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
1051 }\r
c1e126b1 1052\r
75787f65
SZ
1053 if (UsbDebugPortHandle == NULL) {\r
1054 return FALSE;\r
2cb6eabe
EL
1055 }\r
1056\r
75787f65
SZ
1057 if (UsbDebugPortHandle->InNotify) {\r
1058 return FALSE;\r
2cb6eabe
EL
1059 }\r
1060\r
75787f65
SZ
1061 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
1062\r
1063 if (UsbDebugPortHandle->Initialized != USB3DBG_ENABLED) {\r
1064 return FALSE;\r
2cb6eabe 1065 }\r
75787f65 1066\r
2cb6eabe
EL
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
5d6507a1 1076 // Read data as much as we can\r
2cb6eabe 1077 //\r
5d6507a1 1078 Length = XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE;\r
75787f65 1079 XhcDataTransfer (UsbDebugPortHandle, EfiUsbDataIn, (VOID *)(UINTN)UsbDebugPortHandle->Data, &Length, DATA_TRANSFER_POLL_TIMEOUT);\r
2cb6eabe 1080\r
5d6507a1 1081 if (Length > XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE) {\r
2cb6eabe
EL
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
c1e126b1 1092 UsbDebugPortHandle->DataCount = (UINT8)Length;\r
2cb6eabe
EL
1093 return TRUE;\r
1094}\r
1095\r
1096/**\r
1097 Initialize the debug port.\r
1098\r
74cdb367 1099 If Function is not NULL, Debug Communication Library will call this function\r
2cb6eabe
EL
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
74cdb367 1107 b) Ignore the input Context parameter and create new handle to be returned.\r
2cb6eabe
EL
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
c1e126b1 1127 USB3_DEBUG_PORT_HANDLE *UsbDebugPortHandle;\r
2cb6eabe 1128\r
1f279e7a 1129 //\r
77695f4d 1130 // Validate the PCD PcdDebugPortHandleBufferSize value\r
1f279e7a
SZ
1131 //\r
1132 ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB3_DEBUG_PORT_HANDLE));\r
1133\r
c1e126b1
MK
1134 if ((Function == NULL) && (Context != NULL)) {\r
1135 SetUsb3DebugPortInstance ((USB3_DEBUG_PORT_HANDLE *)Context);\r
1136 return (DEBUG_PORT_HANDLE)Context;\r
2cb6eabe 1137 }\r
c1e126b1 1138\r
75787f65
SZ
1139 UsbDebugPortHandle = GetUsb3DebugPortInstance ();\r
1140 if (UsbDebugPortHandle == NULL) {\r
1141 return NULL;\r
1f279e7a 1142 }\r
1f279e7a 1143\r
75787f65 1144 DiscoverInitializeUsbDebugPort (UsbDebugPortHandle);\r
1f279e7a 1145\r
2cb6eabe 1146 if (Function != NULL) {\r
c1e126b1 1147 Function (Context, (DEBUG_PORT_HANDLE)UsbDebugPortHandle);\r
2cb6eabe
EL
1148 }\r
1149\r
c1e126b1 1150 return (DEBUG_PORT_HANDLE)UsbDebugPortHandle;\r
2cb6eabe 1151}\r