1 /** @file 2 3 This file contains URB request, each request is warpped in a 4 URB (Usb Request Block). 5 6 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR> 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include "Ehci.h" 18 19 20 /** 21 Create a single QTD to hold the data. 22 23 @param Ehc The EHCI device. 24 @param Data The cpu memory address of current data not associated with a QTD. 25 @param DataPhy The pci bus address of current data not associated with a QTD. 26 @param DataLen The length of the data. 27 @param PktId Packet ID to use in the QTD. 28 @param Toggle Data toggle to use in the QTD. 29 @param MaxPacket Maximu packet length of the endpoint. 30 31 @return Created QTD or NULL if failed to create one. 32 33 **/ 34 EHC_QTD * 35 EhcCreateQtd ( 36 IN USB2_HC_DEV *Ehc, 37 IN UINT8 *Data, 38 IN UINT8 *DataPhy, 39 IN UINTN DataLen, 40 IN UINT8 PktId, 41 IN UINT8 Toggle, 42 IN UINTN MaxPacket 43 ) 44 { 45 EHC_QTD *Qtd; 46 QTD_HW *QtdHw; 47 UINTN Index; 48 UINTN Len; 49 UINTN ThisBufLen; 50 51 ASSERT (Ehc != NULL); 52 53 Qtd = UsbHcAllocateMem (Ehc->MemPool, sizeof (EHC_QTD)); 54 55 if (Qtd == NULL) { 56 return NULL; 57 } 58 59 Qtd->Signature = EHC_QTD_SIG; 60 Qtd->Data = Data; 61 Qtd->DataLen = 0; 62 63 InitializeListHead (&Qtd->QtdList); 64 65 QtdHw = &Qtd->QtdHw; 66 QtdHw->NextQtd = QTD_LINK (NULL, TRUE); 67 QtdHw->AltNext = QTD_LINK (NULL, TRUE); 68 QtdHw->Status = QTD_STAT_ACTIVE; 69 QtdHw->Pid = PktId; 70 QtdHw->ErrCnt = QTD_MAX_ERR; 71 QtdHw->Ioc = 0; 72 QtdHw->TotalBytes = 0; 73 QtdHw->DataToggle = Toggle; 74 75 // 76 // Fill in the buffer points 77 // 78 if (Data != NULL) { 79 Len = 0; 80 81 for (Index = 0; Index <= QTD_MAX_BUFFER; Index++) { 82 // 83 // Set the buffer point (Check page 41 EHCI Spec 1.0). No need to 84 // compute the offset and clear Reserved fields. This is already 85 // done in the data point. 86 // 87 QtdHw->Page[Index] = EHC_LOW_32BIT (DataPhy); 88 QtdHw->PageHigh[Index] = EHC_HIGH_32BIT (DataPhy); 89 90 ThisBufLen = QTD_BUF_LEN - (EHC_LOW_32BIT (DataPhy) & QTD_BUF_MASK); 91 92 if (Len + ThisBufLen >= DataLen) { 93 Len = DataLen; 94 break; 95 } 96 97 Len += ThisBufLen; 98 Data += ThisBufLen; 99 DataPhy += ThisBufLen; 100 } 101 102 // 103 // Need to fix the last pointer if the Qtd can't hold all the 104 // user's data to make sure that the length is in the unit of 105 // max packets. If it can hold all the data, there is no such 106 // need. 107 // 108 if (Len < DataLen) { 109 Len = Len - Len % MaxPacket; 110 } 111 112 QtdHw->TotalBytes = (UINT32) Len; 113 Qtd->DataLen = Len; 114 } 115 116 return Qtd; 117 } 118 119 120 121 /** 122 Initialize the queue head for interrupt transfer, 123 that is, initialize the following three fields: 124 1. SplitXState in the Status field 125 2. Microframe S-mask 126 3. Microframe C-mask 127 128 @param Ep The queue head's related endpoint. 129 @param QhHw The queue head to initialize. 130 131 **/ 132 VOID 133 EhcInitIntQh ( 134 IN USB_ENDPOINT *Ep, 135 IN QH_HW *QhHw 136 ) 137 { 138 // 139 // Because UEFI interface can't utilitize an endpoint with 140 // poll rate faster than 1ms, only need to set one bit in 141 // the queue head. simple. But it may be changed later. If 142 // sub-1ms interrupt is supported, need to update the S-Mask 143 // here 144 // 145 if (Ep->DevSpeed == EFI_USB_SPEED_HIGH) { 146 QhHw->SMask = QH_MICROFRAME_0; 147 return ; 148 } 149 150 // 151 // For low/full speed device, the transfer must go through 152 // the split transaction. Need to update three fields 153 // 1. SplitXState in the status 154 // 2. Microframe S-Mask 155 // 3. Microframe C-Mask 156 // UEFI USB doesn't exercise admission control. It simplely 157 // schedule the high speed transactions in microframe 0, and 158 // full/low speed transactions at microframe 1. This also 159 // avoid the use of FSTN. 160 // 161 QhHw->SMask = QH_MICROFRAME_1; 162 QhHw->CMask = QH_MICROFRAME_3 | QH_MICROFRAME_4 | QH_MICROFRAME_5; 163 } 164 165 166 167 /** 168 Allocate and initialize a EHCI queue head. 169 170 @param Ehci The EHCI device. 171 @param Ep The endpoint to create queue head for. 172 173 @return Created queue head or NULL if failed to create one. 174 175 **/ 176 EHC_QH * 177 EhcCreateQh ( 178 IN USB2_HC_DEV *Ehci, 179 IN USB_ENDPOINT *Ep 180 ) 181 { 182 EHC_QH *Qh; 183 QH_HW *QhHw; 184 185 Qh = UsbHcAllocateMem (Ehci->MemPool, sizeof (EHC_QH)); 186 187 if (Qh == NULL) { 188 return NULL; 189 } 190 191 Qh->Signature = EHC_QH_SIG; 192 Qh->NextQh = NULL; 193 Qh->Interval = Ep->PollRate; 194 195 InitializeListHead (&Qh->Qtds); 196 197 QhHw = &Qh->QhHw; 198 QhHw->HorizonLink = QH_LINK (NULL, 0, TRUE); 199 QhHw->DeviceAddr = Ep->DevAddr; 200 QhHw->Inactive = 0; 201 QhHw->EpNum = Ep->EpAddr; 202 QhHw->EpSpeed = Ep->DevSpeed; 203 QhHw->DtCtrl = 0; 204 QhHw->ReclaimHead = 0; 205 QhHw->MaxPacketLen = (UINT32) Ep->MaxPacket; 206 QhHw->CtrlEp = 0; 207 QhHw->NakReload = QH_NAK_RELOAD; 208 QhHw->HubAddr = Ep->HubAddr; 209 QhHw->PortNum = Ep->HubPort; 210 QhHw->Multiplier = 1; 211 QhHw->DataToggle = Ep->Toggle; 212 213 if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) { 214 QhHw->Status |= QTD_STAT_DO_SS; 215 } 216 217 switch (Ep->Type) { 218 case EHC_CTRL_TRANSFER: 219 // 220 // Special initialization for the control transfer: 221 // 1. Control transfer initialize data toggle from each QTD 222 // 2. Set the Control Endpoint Flag (C) for low/full speed endpoint. 223 // 224 QhHw->DtCtrl = 1; 225 226 if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) { 227 QhHw->CtrlEp = 1; 228 } 229 break; 230 231 case EHC_INT_TRANSFER_ASYNC: 232 case EHC_INT_TRANSFER_SYNC: 233 // 234 // Special initialization for the interrupt transfer 235 // to set the S-Mask and C-Mask 236 // 237 QhHw->NakReload = 0; 238 EhcInitIntQh (Ep, QhHw); 239 break; 240 241 case EHC_BULK_TRANSFER: 242 if ((Ep->DevSpeed == EFI_USB_SPEED_HIGH) && (Ep->Direction == EfiUsbDataOut)) { 243 QhHw->Status |= QTD_STAT_DO_PING; 244 } 245 246 break; 247 } 248 249 return Qh; 250 } 251 252 253 /** 254 Convert the poll interval from application to that 255 be used by EHCI interface data structure. Only need 256 to get the max 2^n that is less than interval. UEFI 257 can't support high speed endpoint with a interval less 258 than 8 microframe because interval is specified in 259 the unit of ms (millisecond). 260 261 @param Interval The interval to convert. 262 263 @return The converted interval. 264 265 **/ 266 UINTN 267 EhcConvertPollRate ( 268 IN UINTN Interval 269 ) 270 { 271 UINTN BitCount; 272 273 if (Interval == 0) { 274 return 1; 275 } 276 277 // 278 // Find the index (1 based) of the highest non-zero bit 279 // 280 BitCount = 0; 281 282 while (Interval != 0) { 283 Interval >>= 1; 284 BitCount++; 285 } 286 287 return (UINTN)1 << (BitCount - 1); 288 } 289 290 291 /** 292 Free a list of QTDs. 293 294 @param Ehc The EHCI device. 295 @param Qtds The list head of the QTD. 296 297 **/ 298 VOID 299 EhcFreeQtds ( 300 IN USB2_HC_DEV *Ehc, 301 IN LIST_ENTRY *Qtds 302 ) 303 { 304 LIST_ENTRY *Entry; 305 LIST_ENTRY *Next; 306 EHC_QTD *Qtd; 307 308 EFI_LIST_FOR_EACH_SAFE (Entry, Next, Qtds) { 309 Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList); 310 311 RemoveEntryList (&Qtd->QtdList); 312 UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (EHC_QTD)); 313 } 314 } 315 316 317 /** 318 Free an allocated URB. It is possible for it to be partially inited. 319 320 @param Ehc The EHCI device. 321 @param Urb The URB to free. 322 323 **/ 324 VOID 325 EhcFreeUrb ( 326 IN USB2_HC_DEV *Ehc, 327 IN URB *Urb 328 ) 329 { 330 EFI_PCI_IO_PROTOCOL *PciIo; 331 332 PciIo = Ehc->PciIo; 333 334 if (Urb->RequestPhy != NULL) { 335 PciIo->Unmap (PciIo, Urb->RequestMap); 336 } 337 338 if (Urb->DataMap != NULL) { 339 PciIo->Unmap (PciIo, Urb->DataMap); 340 } 341 342 if (Urb->Qh != NULL) { 343 // 344 // Ensure that this queue head has been unlinked from the 345 // schedule data structures. Free all the associated QTDs 346 // 347 EhcFreeQtds (Ehc, &Urb->Qh->Qtds); 348 UsbHcFreeMem (Ehc->MemPool, Urb->Qh, sizeof (EHC_QH)); 349 } 350 351 gBS->FreePool (Urb); 352 } 353 354 355 /** 356 Create a list of QTDs for the URB. 357 358 @param Ehc The EHCI device. 359 @param Urb The URB to create QTDs for. 360 361 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for QTD. 362 @retval EFI_SUCCESS The QTDs are allocated for the URB. 363 364 **/ 365 EFI_STATUS 366 EhcCreateQtds ( 367 IN USB2_HC_DEV *Ehc, 368 IN URB *Urb 369 ) 370 { 371 USB_ENDPOINT *Ep; 372 EHC_QH *Qh; 373 EHC_QTD *Qtd; 374 EHC_QTD *StatusQtd; 375 EHC_QTD *NextQtd; 376 LIST_ENTRY *Entry; 377 UINT32 AlterNext; 378 UINT8 Toggle; 379 UINTN Len; 380 UINT8 Pid; 381 EFI_PHYSICAL_ADDRESS PhyAddr; 382 383 ASSERT ((Urb != NULL) && (Urb->Qh != NULL)); 384 385 // 386 // EHCI follows the alternet next QTD pointer if it meets 387 // a short read and the AlterNext pointer is valid. UEFI 388 // EHCI driver should terminate the transfer except the 389 // control transfer. 390 // 391 Toggle = 0; 392 Qh = Urb->Qh; 393 Ep = &Urb->Ep; 394 StatusQtd = NULL; 395 AlterNext = QTD_LINK (NULL, TRUE); 396 397 PhyAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD)); 398 if (Ep->Direction == EfiUsbDataIn) { 399 AlterNext = QTD_LINK (PhyAddr, FALSE); 400 } 401 402 // 403 // Build the Setup and status packets for control transfer 404 // 405 if (Urb->Ep.Type == EHC_CTRL_TRANSFER) { 406 Len = sizeof (EFI_USB_DEVICE_REQUEST); 407 Qtd = EhcCreateQtd (Ehc, (UINT8 *)Urb->Request, (UINT8 *)Urb->RequestPhy, Len, QTD_PID_SETUP, 0, Ep->MaxPacket); 408 409 if (Qtd == NULL) { 410 return EFI_OUT_OF_RESOURCES; 411 } 412 413 InsertTailList (&Qh->Qtds, &Qtd->QtdList); 414 415 // 416 // Create the status packet now. Set the AlterNext to it. So, when 417 // EHCI meets a short control read, it can resume at the status stage. 418 // Use the opposite direction of the data stage, or IN if there is 419 // no data stage. 420 // 421 if (Ep->Direction == EfiUsbDataIn) { 422 Pid = QTD_PID_OUTPUT; 423 } else { 424 Pid = QTD_PID_INPUT; 425 } 426 427 StatusQtd = EhcCreateQtd (Ehc, NULL, NULL, 0, Pid, 1, Ep->MaxPacket); 428 429 if (StatusQtd == NULL) { 430 goto ON_ERROR; 431 } 432 433 if (Ep->Direction == EfiUsbDataIn) { 434 PhyAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, StatusQtd, sizeof (EHC_QTD)); 435 AlterNext = QTD_LINK (PhyAddr, FALSE); 436 } 437 438 Toggle = 1; 439 } 440 441 // 442 // Build the data packets for all the transfers 443 // 444 if (Ep->Direction == EfiUsbDataIn) { 445 Pid = QTD_PID_INPUT; 446 } else { 447 Pid = QTD_PID_OUTPUT; 448 } 449 450 Qtd = NULL; 451 Len = 0; 452 453 while (Len < Urb->DataLen) { 454 Qtd = EhcCreateQtd ( 455 Ehc, 456 (UINT8 *) Urb->Data + Len, 457 (UINT8 *) Urb->DataPhy + Len, 458 Urb->DataLen - Len, 459 Pid, 460 Toggle, 461 Ep->MaxPacket 462 ); 463 464 if (Qtd == NULL) { 465 goto ON_ERROR; 466 } 467 468 Qtd->QtdHw.AltNext = AlterNext; 469 InsertTailList (&Qh->Qtds, &Qtd->QtdList); 470 471 // 472 // Switch the Toggle bit if odd number of packets are included in the QTD. 473 // 474 if (((Qtd->DataLen + Ep->MaxPacket - 1) / Ep->MaxPacket) % 2) { 475 Toggle = (UINT8) (1 - Toggle); 476 } 477 478 Len += Qtd->DataLen; 479 } 480 481 // 482 // Insert the status packet for control transfer 483 // 484 if (Ep->Type == EHC_CTRL_TRANSFER) { 485 InsertTailList (&Qh->Qtds, &StatusQtd->QtdList); 486 } 487 488 // 489 // OK, all the QTDs needed are created. Now, fix the NextQtd point 490 // 491 EFI_LIST_FOR_EACH (Entry, &Qh->Qtds) { 492 Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList); 493 494 // 495 // break if it is the last entry on the list 496 // 497 if (Entry->ForwardLink == &Qh->Qtds) { 498 break; 499 } 500 501 NextQtd = EFI_LIST_CONTAINER (Entry->ForwardLink, EHC_QTD, QtdList); 502 PhyAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, NextQtd, sizeof (EHC_QTD)); 503 Qtd->QtdHw.NextQtd = QTD_LINK (PhyAddr, FALSE); 504 } 505 506 // 507 // Link the QTDs to the queue head 508 // 509 NextQtd = EFI_LIST_CONTAINER (Qh->Qtds.ForwardLink, EHC_QTD, QtdList); 510 PhyAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, NextQtd, sizeof (EHC_QTD)); 511 Qh->QhHw.NextQtd = QTD_LINK (PhyAddr, FALSE); 512 return EFI_SUCCESS; 513 514 ON_ERROR: 515 EhcFreeQtds (Ehc, &Qh->Qtds); 516 return EFI_OUT_OF_RESOURCES; 517 } 518 519 520 /** 521 Create a new URB and its associated QTD. 522 523 @param Ehc The EHCI device. 524 @param DevAddr The device address. 525 @param EpAddr Endpoint addrress & its direction. 526 @param DevSpeed The device speed. 527 @param Toggle Initial data toggle to use. 528 @param MaxPacket The max packet length of the endpoint. 529 @param Hub The transaction translator to use. 530 @param Type The transaction type. 531 @param Request The standard USB request for control transfer. 532 @param Data The user data to transfer. 533 @param DataLen The length of data buffer. 534 @param Callback The function to call when data is transferred. 535 @param Context The context to the callback. 536 @param Interval The interval for interrupt transfer. 537 538 @return Created URB or NULL. 539 540 **/ 541 URB * 542 EhcCreateUrb ( 543 IN USB2_HC_DEV *Ehc, 544 IN UINT8 DevAddr, 545 IN UINT8 EpAddr, 546 IN UINT8 DevSpeed, 547 IN UINT8 Toggle, 548 IN UINTN MaxPacket, 549 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, 550 IN UINTN Type, 551 IN EFI_USB_DEVICE_REQUEST *Request, 552 IN VOID *Data, 553 IN UINTN DataLen, 554 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, 555 IN VOID *Context, 556 IN UINTN Interval 557 ) 558 { 559 USB_ENDPOINT *Ep; 560 EFI_PHYSICAL_ADDRESS PhyAddr; 561 EFI_PCI_IO_PROTOCOL_OPERATION MapOp; 562 EFI_PCI_IO_PROTOCOL *PciIo; 563 EFI_STATUS Status; 564 UINTN Len; 565 URB *Urb; 566 VOID *Map; 567 568 Urb = AllocateZeroPool (sizeof (URB)); 569 570 if (Urb == NULL) { 571 return NULL; 572 } 573 574 Urb->Signature = EHC_URB_SIG; 575 InitializeListHead (&Urb->UrbList); 576 577 Ep = &Urb->Ep; 578 Ep->DevAddr = DevAddr; 579 Ep->EpAddr = (UINT8) (EpAddr & 0x0F); 580 Ep->Direction = (((EpAddr & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut); 581 Ep->DevSpeed = DevSpeed; 582 Ep->MaxPacket = MaxPacket; 583 584 Ep->HubAddr = 0; 585 Ep->HubPort = 0; 586 587 if (DevSpeed != EFI_USB_SPEED_HIGH) { 588 ASSERT (Hub != NULL); 589 590 Ep->HubAddr = Hub->TranslatorHubAddress; 591 Ep->HubPort = Hub->TranslatorPortNumber; 592 } 593 594 Ep->Toggle = Toggle; 595 Ep->Type = Type; 596 Ep->PollRate = EhcConvertPollRate (Interval); 597 598 Urb->Request = Request; 599 Urb->Data = Data; 600 Urb->DataLen = DataLen; 601 Urb->Callback = Callback; 602 Urb->Context = Context; 603 604 PciIo = Ehc->PciIo; 605 Urb->Qh = EhcCreateQh (Ehc, &Urb->Ep); 606 607 if (Urb->Qh == NULL) { 608 goto ON_ERROR; 609 } 610 611 // 612 // Map the request and user data 613 // 614 if (Request != NULL) { 615 Len = sizeof (EFI_USB_DEVICE_REQUEST); 616 MapOp = EfiPciIoOperationBusMasterRead; 617 Status = PciIo->Map (PciIo, MapOp, Request, &Len, &PhyAddr, &Map); 618 619 if (EFI_ERROR (Status) || (Len != sizeof (EFI_USB_DEVICE_REQUEST))) { 620 goto ON_ERROR; 621 } 622 623 Urb->RequestPhy = (VOID *) ((UINTN) PhyAddr); 624 Urb->RequestMap = Map; 625 } 626 627 if (Data != NULL) { 628 Len = DataLen; 629 630 if (Ep->Direction == EfiUsbDataIn) { 631 MapOp = EfiPciIoOperationBusMasterWrite; 632 } else { 633 MapOp = EfiPciIoOperationBusMasterRead; 634 } 635 636 Status = PciIo->Map (PciIo, MapOp, Data, &Len, &PhyAddr, &Map); 637 638 if (EFI_ERROR (Status) || (Len != DataLen)) { 639 goto ON_ERROR; 640 } 641 642 Urb->DataPhy = (VOID *) ((UINTN) PhyAddr); 643 Urb->DataMap = Map; 644 } 645 646 Status = EhcCreateQtds (Ehc, Urb); 647 648 if (EFI_ERROR (Status)) { 649 goto ON_ERROR; 650 } 651 652 return Urb; 653 654 ON_ERROR: 655 EhcFreeUrb (Ehc, Urb); 656 return NULL; 657 } 658