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 #include "DebugCommunicationLibUsb3Internal.h" 15 16 /** 17 Synchronize the specified transfer ring to update the enqueue and dequeue pointer. 18 19 @param Handle Debug port handle. 20 @param TrsRing The transfer ring to sync. 21 22 @retval EFI_SUCCESS The transfer ring is synchronized successfully. 23 24 **/ 25 EFI_STATUS 26 EFIAPI 27 XhcSyncTrsRing ( 28 IN USB3_DEBUG_PORT_HANDLE *Handle, 29 IN TRANSFER_RING *TrsRing 30 ) 31 { 32 UINTN Index; 33 TRB_TEMPLATE *TrsTrb; 34 UINT32 CycleBit; 35 36 ASSERT (TrsRing != NULL); 37 38 // 39 // Calculate the latest RingEnqueue and RingPCS 40 // 41 TrsTrb = (TRB_TEMPLATE *)(UINTN) TrsRing->RingEnqueue; 42 43 ASSERT (TrsTrb != NULL); 44 45 for (Index = 0; Index < TrsRing->TrbNumber; Index++) { 46 if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) { 47 break; 48 } 49 TrsTrb++; 50 if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) { 51 ASSERT (((LINK_TRB*)TrsTrb)->TC != 0); 52 // 53 // set cycle bit in Link TRB as normal 54 // 55 ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0; 56 // 57 // Toggle PCS maintained by software 58 // 59 TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1; 60 TrsTrb = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F); 61 } 62 } 63 ASSERT (Index != TrsRing->TrbNumber); 64 65 if ((EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb != TrsRing->RingEnqueue) { 66 TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb; 67 } 68 69 // 70 // Clear the Trb context for enqueue, but reserve the PCS bit which indicates free Trb. 71 // 72 CycleBit = TrsTrb->CycleBit; 73 ZeroMem (TrsTrb, sizeof (TRB_TEMPLATE)); 74 TrsTrb->CycleBit = CycleBit; 75 76 return EFI_SUCCESS; 77 } 78 79 /** 80 Synchronize the specified event ring to update the enqueue and dequeue pointer. 81 82 @param Handle Debug port handle. 83 @param EvtRing The event ring to sync. 84 85 @retval EFI_SUCCESS The event ring is synchronized successfully. 86 87 **/ 88 EFI_STATUS 89 EFIAPI 90 XhcSyncEventRing ( 91 IN USB3_DEBUG_PORT_HANDLE *Handle, 92 IN EVENT_RING *EvtRing 93 ) 94 { 95 UINTN Index; 96 TRB_TEMPLATE *EvtTrb1; 97 98 ASSERT (EvtRing != NULL); 99 100 // 101 // Calculate the EventRingEnqueue and EventRingCCS. 102 // Note: only support single Segment 103 // 104 EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue; 105 106 for (Index = 0; Index < EvtRing->TrbNumber; Index++) { 107 if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) { 108 break; 109 } 110 111 EvtTrb1++; 112 113 if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { 114 EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingSeg0; 115 EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1; 116 } 117 } 118 119 if (Index < EvtRing->TrbNumber) { 120 EvtRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EvtTrb1; 121 } else { 122 ASSERT (FALSE); 123 } 124 125 return EFI_SUCCESS; 126 } 127 128 /** 129 Check if there is a new generated event. 130 131 @param Handle Debug port handle. 132 @param EvtRing The event ring to check. 133 @param NewEvtTrb The new event TRB found. 134 135 @retval EFI_SUCCESS Found a new event TRB at the event ring. 136 @retval EFI_NOT_READY The event ring has no new event. 137 138 **/ 139 EFI_STATUS 140 EFIAPI 141 XhcCheckNewEvent ( 142 IN USB3_DEBUG_PORT_HANDLE *Handle, 143 IN EVENT_RING *EvtRing, 144 OUT TRB_TEMPLATE **NewEvtTrb 145 ) 146 { 147 EFI_STATUS Status; 148 TRB_TEMPLATE *EvtTrb; 149 150 ASSERT (EvtRing != NULL); 151 152 EvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue; 153 *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue; 154 155 if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) { 156 return EFI_NOT_READY; 157 } 158 159 Status = EFI_SUCCESS; 160 161 EvtRing->EventRingDequeue += sizeof (TRB_TEMPLATE); 162 // 163 // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring. 164 // 165 if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { 166 EvtRing->EventRingDequeue = EvtRing->EventRingSeg0; 167 } 168 169 return Status; 170 } 171 172 /** 173 Check if the Trb is a transaction of the URB. 174 175 @param Ring The transfer ring to be checked. 176 @param Trb The TRB to be checked. 177 178 @retval TRUE It is a transaction of the URB. 179 @retval FALSE It is not any transaction of the URB. 180 181 **/ 182 BOOLEAN 183 IsTrbInTrsRing ( 184 IN TRANSFER_RING *Ring, 185 IN TRB_TEMPLATE *Trb 186 ) 187 { 188 TRB_TEMPLATE *CheckedTrb; 189 UINTN Index; 190 191 CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0; 192 193 ASSERT (Ring->TrbNumber == TR_RING_TRB_NUMBER); 194 195 for (Index = 0; Index < Ring->TrbNumber; Index++) { 196 if (Trb == CheckedTrb) { 197 return TRUE; 198 } 199 CheckedTrb++; 200 } 201 202 return FALSE; 203 } 204 205 /** 206 Check the URB's execution result and update the URB's 207 result accordingly. 208 209 @param Handle Debug port handle. 210 @param Urb The URB to check result. 211 212 **/ 213 VOID 214 XhcCheckUrbResult ( 215 IN USB3_DEBUG_PORT_HANDLE *Handle, 216 IN URB *Urb 217 ) 218 { 219 EVT_TRB_TRANSFER *EvtTrb; 220 TRB_TEMPLATE *TRBPtr; 221 UINTN Index; 222 EFI_STATUS Status; 223 URB *CheckedUrb; 224 UINT64 XhcDequeue; 225 UINT32 High; 226 UINT32 Low; 227 228 ASSERT ((Handle != NULL) && (Urb != NULL)); 229 230 if (Urb->Finished) { 231 goto EXIT; 232 } 233 234 EvtTrb = NULL; 235 236 // 237 // Traverse the event ring to find out all new events from the previous check. 238 // 239 XhcSyncEventRing (Handle, &Handle->EventRing); 240 241 for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) { 242 243 Status = XhcCheckNewEvent (Handle, &Handle->EventRing, ((TRB_TEMPLATE **)&EvtTrb)); 244 if (Status == EFI_NOT_READY) { 245 // 246 // All new events are handled, return directly. 247 // 248 goto EXIT; 249 } 250 251 if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) { 252 continue; 253 } 254 255 TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32)); 256 257 if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Urb->Ring), TRBPtr)) { 258 CheckedUrb = Urb; 259 } else if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Handle->UrbIn.Ring), TRBPtr)) { 260 // 261 // If it is read event and it should be generated by poll, and current operation is write, we need save data into internal buffer. 262 // Internal buffer is used by next read. 263 // 264 Handle->DataCount = (UINT8) (Handle->UrbIn.DataLen - EvtTrb->Length); 265 CopyMem ((VOID *)(UINTN)Handle->Data, (VOID *)(UINTN)Handle->UrbIn.Data, Handle->DataCount); 266 // 267 // Fill this TRB complete with CycleBit, otherwise next read will fail with old TRB. 268 // 269 TRBPtr->CycleBit = (TRBPtr->CycleBit & BIT0) ? 0 : 1; 270 continue; 271 } else { 272 continue; 273 } 274 275 if ((EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) || 276 (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS)) { 277 // 278 // The length of data which were transferred. 279 // 280 CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length); 281 } else { 282 CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT; 283 } 284 // 285 // This Urb has been processed 286 // 287 CheckedUrb->Finished = TRUE; 288 } 289 290 EXIT: 291 // 292 // Advance event ring to last available entry 293 // 294 // Some 3rd party XHCI external cards don't support single 64-bytes width register access, 295 // So divide it to two 32-bytes width register access. 296 // 297 Low = XhcReadDebugReg (Handle, XHC_DC_DCERDP); 298 High = XhcReadDebugReg (Handle, XHC_DC_DCERDP + 4); 299 XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low); 300 301 if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Handle->EventRing.EventRingDequeue & (~0x0F))) { 302 // 303 // Some 3rd party XHCI external cards don't support single 64-bytes width register access, 304 // So divide it to two 32-bytes width register access. 305 // 306 XhcWriteDebugReg (Handle, XHC_DC_DCERDP, XHC_LOW_32BIT (Handle->EventRing.EventRingDequeue)); 307 XhcWriteDebugReg (Handle, XHC_DC_DCERDP + 4, XHC_HIGH_32BIT (Handle->EventRing.EventRingDequeue)); 308 } 309 } 310 311 /** 312 Ring the door bell to notify XHCI there is a transaction to be executed. 313 314 @param Handle Debug port handle. 315 @param Urb The pointer to URB. 316 317 @retval EFI_SUCCESS Successfully ring the door bell. 318 319 **/ 320 EFI_STATUS 321 EFIAPI 322 XhcRingDoorBell ( 323 IN USB3_DEBUG_PORT_HANDLE *Handle, 324 IN URB *Urb 325 ) 326 { 327 UINT32 Dcdb; 328 329 // 330 // 7.6.8.2 DCDB Register 331 // 332 Dcdb = (Urb->Direction == EfiUsbDataIn) ? 0x100 : 0x0; 333 334 XhcWriteDebugReg ( 335 Handle, 336 XHC_DC_DCDB, 337 Dcdb 338 ); 339 340 return EFI_SUCCESS; 341 } 342 343 /** 344 Execute the transfer by polling the URB. This is a synchronous operation. 345 346 @param Handle Debug port handle. 347 @param Urb The URB to execute. 348 @param Timeout The time to wait before abort, in microsecond. 349 350 **/ 351 VOID 352 XhcExecTransfer ( 353 IN USB3_DEBUG_PORT_HANDLE *Handle, 354 IN URB *Urb, 355 IN UINTN Timeout 356 ) 357 { 358 TRANSFER_RING *Ring; 359 TRB_TEMPLATE *Trb; 360 UINTN Loop; 361 UINTN Index; 362 363 Loop = Timeout / XHC_DEBUG_PORT_1_MILLISECOND; 364 if (Timeout == 0) { 365 Loop = 0xFFFFFFFF; 366 } 367 XhcRingDoorBell (Handle, Urb); 368 // 369 // Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay. 370 // 371 for (Index = 0; Index < Loop; Index++) { 372 XhcCheckUrbResult (Handle, Urb); 373 if (Urb->Finished) { 374 break; 375 } 376 MicroSecondDelay (XHC_DEBUG_PORT_1_MILLISECOND); 377 } 378 if (Index == Loop) { 379 // 380 // If time out occurs. 381 // 382 Urb->Result |= EFI_USB_ERR_TIMEOUT; 383 } 384 // 385 // If URB transfer is error, restore transfer ring to original value before URB transfer 386 // This will make the current transfer TRB is always at the latest unused one in transfer ring. 387 // 388 Ring = (TRANSFER_RING *)(UINTN) Urb->Ring; 389 if ((Urb->Result != EFI_USB_NOERROR) && (Urb->Direction == EfiUsbDataIn)) { 390 // 391 // Adjust Enqueue pointer 392 // 393 Ring->RingEnqueue = Urb->Trb; 394 // 395 // Clear CCS flag for next use 396 // 397 Trb = (TRB_TEMPLATE *)(UINTN) Urb->Trb; 398 Trb->CycleBit = ((~Ring->RingPCS) & BIT0); 399 } else { 400 // 401 // Update transfer ring for next transfer. 402 // 403 XhcSyncTrsRing (Handle, Ring); 404 } 405 } 406 407 /** 408 Create a transfer TRB. 409 410 @param Handle Debug port handle. 411 @param Urb The urb used to construct the transfer TRB. 412 413 @return Created TRB or NULL 414 415 **/ 416 EFI_STATUS 417 XhcCreateTransferTrb ( 418 IN USB3_DEBUG_PORT_HANDLE *Handle, 419 IN URB *Urb 420 ) 421 { 422 TRANSFER_RING *EPRing; 423 TRB *Trb; 424 425 if (Urb->Direction == EfiUsbDataIn) { 426 EPRing = &Handle->TransferRingIn; 427 } else { 428 EPRing = &Handle->TransferRingOut; 429 } 430 431 Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing; 432 XhcSyncTrsRing (Handle, EPRing); 433 434 Urb->Trb = EPRing->RingEnqueue; 435 Trb = (TRB *)(UINTN)EPRing->RingEnqueue; 436 Trb->TrbNormal.TRBPtrLo = XHC_LOW_32BIT (Urb->Data); 437 Trb->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT (Urb->Data); 438 Trb->TrbNormal.Length = Urb->DataLen; 439 Trb->TrbNormal.TDSize = 0; 440 Trb->TrbNormal.IntTarget = 0; 441 Trb->TrbNormal.ISP = 1; 442 Trb->TrbNormal.IOC = 1; 443 Trb->TrbNormal.Type = TRB_TYPE_NORMAL; 444 445 // 446 // Update the cycle bit to indicate this TRB has been consumed. 447 // 448 Trb->TrbNormal.CycleBit = EPRing->RingPCS & BIT0; 449 450 return EFI_SUCCESS; 451 } 452 453 /** 454 Create a new URB for a new transaction. 455 456 @param Handle Debug port handle. 457 @param Direction The direction of data flow. 458 @param Data The user data to transfer 459 @param DataLen The length of data buffer 460 461 @return Created URB or NULL 462 463 **/ 464 URB* 465 XhcCreateUrb ( 466 IN USB3_DEBUG_PORT_HANDLE *Handle, 467 IN EFI_USB_DATA_DIRECTION Direction, 468 IN VOID *Data, 469 IN UINTN DataLen 470 ) 471 { 472 EFI_STATUS Status; 473 URB *Urb; 474 EFI_PHYSICAL_ADDRESS UrbData; 475 476 if (Direction == EfiUsbDataIn) { 477 Urb = &Handle->UrbIn; 478 } else { 479 Urb = &Handle->UrbOut; 480 } 481 482 UrbData = Urb->Data; 483 484 ZeroMem (Urb, sizeof (URB)); 485 Urb->Direction = Direction; 486 487 // 488 // Allocate memory to move data from CAR or SMRAM to normal memory 489 // to make XHCI DMA successfully 490 // re-use the pre-allocate buffer in PEI to avoid DXE memory service or gBS are not ready 491 // 492 Urb->Data = UrbData; 493 494 if (Direction == EfiUsbDataIn) { 495 // 496 // Do not break URB data in buffer as it may contain the data which were just put in via DMA by XHC 497 // 498 Urb->DataLen = (UINT32) DataLen; 499 } else { 500 // 501 // Put data into URB data out buffer which will create TRBs 502 // 503 ZeroMem ((VOID*)(UINTN) Urb->Data, DataLen); 504 CopyMem ((VOID*)(UINTN) Urb->Data, Data, DataLen); 505 Urb->DataLen = (UINT32) DataLen; 506 } 507 508 Status = XhcCreateTransferTrb (Handle, Urb); 509 ASSERT_EFI_ERROR (Status); 510 511 return Urb; 512 } 513 514 /** 515 Submits bulk transfer to a bulk endpoint of a USB device. 516 517 @param Handle Debug port handle. 518 @param Direction The direction of data transfer. 519 @param Data Array of pointers to the buffers of data to transmit 520 from or receive into. 521 @param DataLength The lenght of the data buffer. 522 @param Timeout Indicates the maximum time, in microsecond, which 523 the transfer is allowed to complete. 524 525 @retval EFI_SUCCESS The transfer was completed successfully. 526 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. 527 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 528 @retval EFI_TIMEOUT The transfer failed due to timeout. 529 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. 530 531 **/ 532 EFI_STATUS 533 EFIAPI 534 XhcDataTransfer ( 535 IN USB3_DEBUG_PORT_HANDLE *Handle, 536 IN EFI_USB_DATA_DIRECTION Direction, 537 IN OUT VOID *Data, 538 IN OUT UINTN *DataLength, 539 IN UINTN Timeout 540 ) 541 { 542 URB *Urb; 543 EFI_STATUS Status; 544 545 // 546 // Validate the parameters 547 // 548 if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL)) { 549 return EFI_INVALID_PARAMETER; 550 } 551 552 // 553 // Create a new URB, insert it into the asynchronous 554 // schedule list, then poll the execution status. 555 // 556 Urb = XhcCreateUrb (Handle, Direction, Data, *DataLength); 557 ASSERT (Urb != NULL); 558 559 XhcExecTransfer (Handle, Urb, Timeout); 560 561 *DataLength = Urb->Completed; 562 563 Status = EFI_TIMEOUT; 564 if (Urb->Result == EFI_USB_NOERROR) { 565 Status = EFI_SUCCESS; 566 } 567 568 if (Direction == EfiUsbDataIn) { 569 // 570 // Move data from internal buffer to outside buffer (outside buffer may be in SMRAM...) 571 // SMRAM does not allow to do DMA, so we create an internal buffer. 572 // 573 CopyMem (Data, (VOID *)(UINTN)Urb->Data, *DataLength); 574 } 575 576 return Status; 577 } 578 579