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