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