3 This file contains URB request, each request is warpped in a
4 URB (Usb Request Block).
6 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) Microsoft Corporation.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
16 Create a single QTD to hold the data.
18 @param Ehc The EHCI device.
19 @param Data The cpu memory address of current data not associated with a QTD.
20 @param DataPhy The pci bus address of current data not associated with a QTD.
21 @param DataLen The length of the data.
22 @param PktId Packet ID to use in the QTD.
23 @param Toggle Data toggle to use in the QTD.
24 @param MaxPacket Maximu packet length of the endpoint.
26 @return Created QTD or NULL if failed to create one.
48 Qtd
= UsbHcAllocateMem (Ehc
->MemPool
, sizeof (EHC_QTD
));
54 Qtd
->Signature
= EHC_QTD_SIG
;
58 InitializeListHead (&Qtd
->QtdList
);
61 QtdHw
->NextQtd
= QTD_LINK (NULL
, TRUE
);
62 QtdHw
->AltNext
= QTD_LINK (NULL
, TRUE
);
63 QtdHw
->Status
= QTD_STAT_ACTIVE
;
65 QtdHw
->ErrCnt
= QTD_MAX_ERR
;
67 QtdHw
->TotalBytes
= 0;
68 QtdHw
->DataToggle
= Toggle
;
71 // Fill in the buffer points
76 for (Index
= 0; Index
<= QTD_MAX_BUFFER
; Index
++) {
78 // Set the buffer point (Check page 41 EHCI Spec 1.0). No need to
79 // compute the offset and clear Reserved fields. This is already
80 // done in the data point.
82 QtdHw
->Page
[Index
] = EHC_LOW_32BIT (DataPhy
);
83 QtdHw
->PageHigh
[Index
] = EHC_HIGH_32BIT (DataPhy
);
85 ThisBufLen
= QTD_BUF_LEN
- (EHC_LOW_32BIT (DataPhy
) & QTD_BUF_MASK
);
87 if (Len
+ ThisBufLen
>= DataLen
) {
94 DataPhy
+= ThisBufLen
;
98 // Need to fix the last pointer if the Qtd can't hold all the
99 // user's data to make sure that the length is in the unit of
100 // max packets. If it can hold all the data, there is no such
104 Len
= Len
- Len
% MaxPacket
;
107 QtdHw
->TotalBytes
= (UINT32
) Len
;
117 Initialize the queue head for interrupt transfer,
118 that is, initialize the following three fields:
119 1. SplitXState in the Status field
123 @param Ep The queue head's related endpoint.
124 @param QhHw The queue head to initialize.
134 // Because UEFI interface can't utilitize an endpoint with
135 // poll rate faster than 1ms, only need to set one bit in
136 // the queue head. simple. But it may be changed later. If
137 // sub-1ms interrupt is supported, need to update the S-Mask
140 if (Ep
->DevSpeed
== EFI_USB_SPEED_HIGH
) {
141 QhHw
->SMask
= QH_MICROFRAME_0
;
146 // For low/full speed device, the transfer must go through
147 // the split transaction. Need to update three fields
148 // 1. SplitXState in the status
149 // 2. Microframe S-Mask
150 // 3. Microframe C-Mask
151 // UEFI USB doesn't exercise admission control. It simplely
152 // schedule the high speed transactions in microframe 0, and
153 // full/low speed transactions at microframe 1. This also
154 // avoid the use of FSTN.
156 QhHw
->SMask
= QH_MICROFRAME_1
;
157 QhHw
->CMask
= QH_MICROFRAME_3
| QH_MICROFRAME_4
| QH_MICROFRAME_5
;
163 Allocate and initialize a EHCI queue head.
165 @param Ehci The EHCI device.
166 @param Ep The endpoint to create queue head for.
168 @return Created queue head or NULL if failed to create one.
173 IN USB2_HC_DEV
*Ehci
,
180 Qh
= UsbHcAllocateMem (Ehci
->MemPool
, sizeof (EHC_QH
));
186 Qh
->Signature
= EHC_QH_SIG
;
188 Qh
->Interval
= Ep
->PollRate
;
190 InitializeListHead (&Qh
->Qtds
);
193 QhHw
->HorizonLink
= QH_LINK (NULL
, 0, TRUE
);
194 QhHw
->DeviceAddr
= Ep
->DevAddr
;
196 QhHw
->EpNum
= Ep
->EpAddr
;
197 QhHw
->EpSpeed
= Ep
->DevSpeed
;
199 QhHw
->ReclaimHead
= 0;
200 QhHw
->MaxPacketLen
= (UINT32
) Ep
->MaxPacket
;
202 QhHw
->NakReload
= QH_NAK_RELOAD
;
203 QhHw
->HubAddr
= Ep
->HubAddr
;
204 QhHw
->PortNum
= Ep
->HubPort
;
205 QhHw
->Multiplier
= 1;
206 QhHw
->DataToggle
= Ep
->Toggle
;
208 if (Ep
->DevSpeed
!= EFI_USB_SPEED_HIGH
) {
209 QhHw
->Status
|= QTD_STAT_DO_SS
;
213 case EHC_CTRL_TRANSFER
:
215 // Special initialization for the control transfer:
216 // 1. Control transfer initialize data toggle from each QTD
217 // 2. Set the Control Endpoint Flag (C) for low/full speed endpoint.
221 if (Ep
->DevSpeed
!= EFI_USB_SPEED_HIGH
) {
226 case EHC_INT_TRANSFER_ASYNC
:
227 case EHC_INT_TRANSFER_SYNC
:
229 // Special initialization for the interrupt transfer
230 // to set the S-Mask and C-Mask
233 EhcInitIntQh (Ep
, QhHw
);
236 case EHC_BULK_TRANSFER
:
237 if ((Ep
->DevSpeed
== EFI_USB_SPEED_HIGH
) && (Ep
->Direction
== EfiUsbDataOut
)) {
238 QhHw
->Status
|= QTD_STAT_DO_PING
;
249 Convert the poll interval from application to that
250 be used by EHCI interface data structure. Only need
251 to get the max 2^n that is less than interval. UEFI
252 can't support high speed endpoint with a interval less
253 than 8 microframe because interval is specified in
254 the unit of ms (millisecond).
256 @param Interval The interval to convert.
258 @return The converted interval.
273 // Find the index (1 based) of the highest non-zero bit
277 while (Interval
!= 0) {
282 return (UINTN
)1 << (BitCount
- 1);
289 @param Ehc The EHCI device.
290 @param Qtds The list head of the QTD.
303 BASE_LIST_FOR_EACH_SAFE (Entry
, Next
, Qtds
) {
304 Qtd
= EFI_LIST_CONTAINER (Entry
, EHC_QTD
, QtdList
);
306 RemoveEntryList (&Qtd
->QtdList
);
307 UsbHcFreeMem (Ehc
->MemPool
, Qtd
, sizeof (EHC_QTD
));
313 Free an allocated URB. It is possible for it to be partially inited.
315 @param Ehc The EHCI device.
316 @param Urb The URB to free.
325 EFI_PCI_IO_PROTOCOL
*PciIo
;
329 if (Urb
->RequestPhy
!= NULL
) {
330 PciIo
->Unmap (PciIo
, Urb
->RequestMap
);
333 if (Urb
->DataMap
!= NULL
) {
334 PciIo
->Unmap (PciIo
, Urb
->DataMap
);
337 if (Urb
->Qh
!= NULL
) {
339 // Ensure that this queue head has been unlinked from the
340 // schedule data structures. Free all the associated QTDs
342 EhcFreeQtds (Ehc
, &Urb
->Qh
->Qtds
);
343 UsbHcFreeMem (Ehc
->MemPool
, Urb
->Qh
, sizeof (EHC_QH
));
351 Create a list of QTDs for the URB.
353 @param Ehc The EHCI device.
354 @param Urb The URB to create QTDs for.
356 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for QTD.
357 @retval EFI_SUCCESS The QTDs are allocated for the URB.
376 EFI_PHYSICAL_ADDRESS PhyAddr
;
378 ASSERT ((Urb
!= NULL
) && (Urb
->Qh
!= NULL
));
381 // EHCI follows the alternet next QTD pointer if it meets
382 // a short read and the AlterNext pointer is valid. UEFI
383 // EHCI driver should terminate the transfer except the
390 AlterNext
= QTD_LINK (NULL
, TRUE
);
392 PhyAddr
= UsbHcGetPciAddressForHostMem (Ehc
->MemPool
, Ehc
->ShortReadStop
, sizeof (EHC_QTD
));
393 if (Ep
->Direction
== EfiUsbDataIn
) {
394 AlterNext
= QTD_LINK (PhyAddr
, FALSE
);
398 // Build the Setup and status packets for control transfer
400 if (Urb
->Ep
.Type
== EHC_CTRL_TRANSFER
) {
401 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
402 Qtd
= EhcCreateQtd (Ehc
, (UINT8
*)Urb
->Request
, (UINT8
*)Urb
->RequestPhy
, Len
, QTD_PID_SETUP
, 0, Ep
->MaxPacket
);
405 return EFI_OUT_OF_RESOURCES
;
408 InsertTailList (&Qh
->Qtds
, &Qtd
->QtdList
);
411 // Create the status packet now. Set the AlterNext to it. So, when
412 // EHCI meets a short control read, it can resume at the status stage.
413 // Use the opposite direction of the data stage, or IN if there is
416 if (Ep
->Direction
== EfiUsbDataIn
) {
417 Pid
= QTD_PID_OUTPUT
;
422 StatusQtd
= EhcCreateQtd (Ehc
, NULL
, NULL
, 0, Pid
, 1, Ep
->MaxPacket
);
424 if (StatusQtd
== NULL
) {
428 if (Ep
->Direction
== EfiUsbDataIn
) {
429 PhyAddr
= UsbHcGetPciAddressForHostMem (Ehc
->MemPool
, StatusQtd
, sizeof (EHC_QTD
));
430 AlterNext
= QTD_LINK (PhyAddr
, FALSE
);
437 // Build the data packets for all the transfers
439 if (Ep
->Direction
== EfiUsbDataIn
) {
442 Pid
= QTD_PID_OUTPUT
;
448 while (Len
< Urb
->DataLen
) {
451 (UINT8
*) Urb
->Data
+ Len
,
452 (UINT8
*) Urb
->DataPhy
+ Len
,
463 Qtd
->QtdHw
.AltNext
= AlterNext
;
464 InsertTailList (&Qh
->Qtds
, &Qtd
->QtdList
);
467 // Switch the Toggle bit if odd number of packets are included in the QTD.
469 if (((Qtd
->DataLen
+ Ep
->MaxPacket
- 1) / Ep
->MaxPacket
) % 2) {
470 Toggle
= (UINT8
) (1 - Toggle
);
477 // Insert the status packet for control transfer
479 if (Ep
->Type
== EHC_CTRL_TRANSFER
) {
480 InsertTailList (&Qh
->Qtds
, &StatusQtd
->QtdList
);
484 // OK, all the QTDs needed are created. Now, fix the NextQtd point
486 BASE_LIST_FOR_EACH (Entry
, &Qh
->Qtds
) {
487 Qtd
= EFI_LIST_CONTAINER (Entry
, EHC_QTD
, QtdList
);
490 // break if it is the last entry on the list
492 if (Entry
->ForwardLink
== &Qh
->Qtds
) {
496 NextQtd
= EFI_LIST_CONTAINER (Entry
->ForwardLink
, EHC_QTD
, QtdList
);
497 PhyAddr
= UsbHcGetPciAddressForHostMem (Ehc
->MemPool
, NextQtd
, sizeof (EHC_QTD
));
498 Qtd
->QtdHw
.NextQtd
= QTD_LINK (PhyAddr
, FALSE
);
502 // Link the QTDs to the queue head
504 NextQtd
= EFI_LIST_CONTAINER (Qh
->Qtds
.ForwardLink
, EHC_QTD
, QtdList
);
505 PhyAddr
= UsbHcGetPciAddressForHostMem (Ehc
->MemPool
, NextQtd
, sizeof (EHC_QTD
));
506 Qh
->QhHw
.NextQtd
= QTD_LINK (PhyAddr
, FALSE
);
510 EhcFreeQtds (Ehc
, &Qh
->Qtds
);
511 return EFI_OUT_OF_RESOURCES
;
516 Create a new URB and its associated QTD.
518 @param Ehc The EHCI device.
519 @param DevAddr The device address.
520 @param EpAddr Endpoint addrress & its direction.
521 @param DevSpeed The device speed.
522 @param Toggle Initial data toggle to use.
523 @param MaxPacket The max packet length of the endpoint.
524 @param Hub The transaction translator to use.
525 @param Type The transaction type.
526 @param Request The standard USB request for control transfer.
527 @param Data The user data to transfer.
528 @param DataLen The length of data buffer.
529 @param Callback The function to call when data is transferred.
530 @param Context The context to the callback.
531 @param Interval The interval for interrupt transfer.
533 @return Created URB or NULL.
544 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Hub
,
546 IN EFI_USB_DEVICE_REQUEST
*Request
,
549 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
555 EFI_PHYSICAL_ADDRESS PhyAddr
;
556 EFI_PCI_IO_PROTOCOL_OPERATION MapOp
;
557 EFI_PCI_IO_PROTOCOL
*PciIo
;
563 Urb
= AllocateZeroPool (sizeof (URB
));
569 Urb
->Signature
= EHC_URB_SIG
;
570 InitializeListHead (&Urb
->UrbList
);
573 Ep
->DevAddr
= DevAddr
;
574 Ep
->EpAddr
= (UINT8
) (EpAddr
& 0x0F);
575 Ep
->Direction
= (((EpAddr
& 0x80) != 0) ? EfiUsbDataIn
: EfiUsbDataOut
);
576 Ep
->DevSpeed
= DevSpeed
;
577 Ep
->MaxPacket
= MaxPacket
;
582 if (DevSpeed
!= EFI_USB_SPEED_HIGH
) {
583 ASSERT (Hub
!= NULL
);
585 Ep
->HubAddr
= Hub
->TranslatorHubAddress
;
586 Ep
->HubPort
= Hub
->TranslatorPortNumber
;
591 Ep
->PollRate
= EhcConvertPollRate (Interval
);
593 Urb
->Request
= Request
;
595 Urb
->DataLen
= DataLen
;
596 Urb
->Callback
= Callback
;
597 Urb
->Context
= Context
;
600 Urb
->Qh
= EhcCreateQh (Ehc
, &Urb
->Ep
);
602 if (Urb
->Qh
== NULL
) {
607 // Map the request and user data
609 if (Request
!= NULL
) {
610 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
611 MapOp
= EfiPciIoOperationBusMasterRead
;
612 Status
= PciIo
->Map (PciIo
, MapOp
, Request
, &Len
, &PhyAddr
, &Map
);
614 if (EFI_ERROR (Status
) || (Len
!= sizeof (EFI_USB_DEVICE_REQUEST
))) {
618 Urb
->RequestPhy
= (VOID
*) ((UINTN
) PhyAddr
);
619 Urb
->RequestMap
= Map
;
625 if (Ep
->Direction
== EfiUsbDataIn
) {
626 MapOp
= EfiPciIoOperationBusMasterWrite
;
628 MapOp
= EfiPciIoOperationBusMasterRead
;
631 Status
= PciIo
->Map (PciIo
, MapOp
, Data
, &Len
, &PhyAddr
, &Map
);
633 if (EFI_ERROR (Status
) || (Len
!= DataLen
)) {
637 Urb
->DataPhy
= (VOID
*) ((UINTN
) PhyAddr
);
641 Status
= EhcCreateQtds (Ehc
, Urb
);
643 if (EFI_ERROR (Status
)) {
650 EhcFreeUrb (Ehc
, Urb
);