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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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