3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 IN USB2_HC_DEV
*HcDev
,
34 Set DoorBell and wait it to complete
51 Status
= ReadEhcOperationalReg (
56 if (EFI_ERROR (Status
)) {
57 Status
= EFI_DEVICE_ERROR
;
62 Status
= WriteEhcOperationalReg (
67 if (EFI_ERROR (Status
)) {
68 Status
= EFI_DEVICE_ERROR
;
72 // Timeout is in US unit
74 Delay
= (Timeout
/ 50) + 1;
76 Status
= ReadEhcOperationalReg (
81 if (EFI_ERROR (Status
)) {
82 Status
= EFI_DEVICE_ERROR
;
86 if ((Data
& USBSTS_IAA
) == USBSTS_IAA
) {
90 gBS
->Stall (EHCI_GENERIC_RECOVERY_TIME
);
94 Data
= Data
& 0xFFFFFFC0;
96 Status
= WriteEhcOperationalReg (
112 IN USB2_HC_DEV
*HcDev
118 Create the NULL QH to make it as the Async QH header
130 EHCI_QH_ENTITY
*NULLQhPtr
;
132 // Allocate memory for Qh structure
134 Status
= EhciAllocatePool (
136 (UINT8
**) &NULLQhPtr
,
137 sizeof (EHCI_QH_ENTITY
)
139 if (EFI_ERROR (Status
)) {
143 NULLQhPtr
->Qh
.Status
= QTD_STATUS_HALTED
;
144 NULLQhPtr
->Qh
.HeadReclamationFlag
= 1;
145 NULLQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&(NULLQhPtr
->Qh
) >> 5));
146 NULLQhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
147 NULLQhPtr
->Qh
.NextQtdTerminate
= 1;
149 NULLQhPtr
->Next
= NULLQhPtr
;
150 NULLQhPtr
->Prev
= NULLQhPtr
;
152 HcDev
->NULLQH
= NULLQhPtr
;
161 IN USB2_HC_DEV
*HcDev
165 if (HcDev
->NULLQH
!= NULL
) {
166 EhciFreePool (HcDev
, (UINT8
*)HcDev
->NULLQH
, sizeof (EHCI_QH_ENTITY
));
167 HcDev
->NULLQH
= NULL
;
174 InitialPeriodicFrameList (
175 IN USB2_HC_DEV
*HcDev
,
182 Initialize Periodic Schedule Frame List
187 Length - Frame List Length
192 EFI_DEVICE_ERROR Fail
198 EFI_PHYSICAL_ADDRESS FrameBuffer
;
200 UINTN BufferSizeInPages
;
201 UINTN BufferSizeInBytes
;
203 FRAME_LIST_ENTRY
*FrameEntryPtr
;
206 // The Frame List is a common buffer that will be
207 // accessed by both the cpu and the usb bus master
209 // The Frame List ocupies 4K bytes,
210 // and must be aligned on 4-Kbyte boundaries.
212 if (EHCI_MAX_FRAME_LIST_LENGTH
!= Length
&& IsFrameListProgrammable (HcDev
)) {
213 Status
= SetFrameListLen (HcDev
, Length
);
214 if (EFI_ERROR (Status
)) {
215 Status
= EFI_INVALID_PARAMETER
;
220 BufferSizeInBytes
= EFI_PAGE_SIZE
;
221 BufferSizeInPages
= EFI_SIZE_TO_PAGES (BufferSizeInBytes
);
222 Status
= HcDev
->PciIo
->AllocateBuffer (
230 if (EFI_ERROR (Status
)) {
231 DEBUG ((gEHCErrorLevel
, "EHCI: PciIo->AllocateBuffer Failed\n"));
232 Status
= EFI_OUT_OF_RESOURCES
;
236 Status
= HcDev
->PciIo
->Map (
238 EfiPciIoOperationBusMasterCommonBuffer
,
244 if (EFI_ERROR (Status
) || (BufferSizeInBytes
!= EFI_PAGE_SIZE
)) {
245 DEBUG ((gEHCErrorLevel
, "EHCI: PciIo->MapBuffer Failed\n"));
246 Status
= EFI_OUT_OF_RESOURCES
;
251 // Put high 32bit into CtrlDataStructSeg reg
252 // when 64bit addressing range capability
254 if (HcDev
->Is64BitCapable
!= 0) {
255 HcDev
->High32BitAddr
= (UINT32
) GET_32B_TO_63B (FrameBuffer
);
257 Status
= SetCtrlDataStructSeg (HcDev
);
258 if (EFI_ERROR (Status
)) {
259 DEBUG ((gEHCErrorLevel
, "EHCI: SetCtrlDataStructSeg Failed\n"));
260 Status
= EFI_DEVICE_ERROR
;
266 // Tell the Host Controller where the Frame List lies,
267 // by set the Frame List Base Address Register.
269 Status
= SetFrameListBaseAddr (HcDev
, (UINT32
) FrameBuffer
);
270 if (EFI_ERROR (Status
)) {
271 Status
= EFI_DEVICE_ERROR
;
275 HcDev
->PeriodicFrameListLength
= Length
;
276 HcDev
->PeriodicFrameListBuffer
= (VOID
*) ((UINTN
) FrameBuffer
);
277 HcDev
->PeriodicFrameListMap
= Map
;
280 // Init Frame List Array fields
282 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
283 for (FrameIndex
= 0; FrameIndex
< HcDev
->PeriodicFrameListLength
; FrameIndex
++) {
284 FrameEntryPtr
->LinkPointer
= 0;
285 FrameEntryPtr
->Rsvd
= 0;
286 FrameEntryPtr
->SelectType
= 0;
287 FrameEntryPtr
->LinkTerminate
= TRUE
;
294 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Map
);
296 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, BufferSizeInPages
, CommonBuffer
);
302 DeinitialPeriodicFrameList (
303 IN USB2_HC_DEV
*HcDev
309 Deinitialize Periodic Schedule Frame List
321 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, HcDev
->PeriodicFrameListMap
);
322 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE
), HcDev
->PeriodicFrameListBuffer
);
328 IN USB2_HC_DEV
*HcDev
,
329 IN EFI_EVENT_NOTIFY NotifyFunction
335 Create Async Request Polling Timer
340 NotifyFunction - Timer Notify Function
345 EFI_DEVICE_ERROR Fail
349 return gBS
->CreateEvent (
350 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
354 &HcDev
->AsyncRequestEvent
359 DestoryPollingTimer (
360 IN USB2_HC_DEV
*HcDev
366 Destory Async Request Polling Timer
375 EFI_DEVICE_ERROR Fail
379 return gBS
->CloseEvent (HcDev
->AsyncRequestEvent
);
384 IN USB2_HC_DEV
*HcDev
390 Start Async Request Polling Timer
399 EFI_DEVICE_ERROR Fail
403 return gBS
->SetTimer (
404 HcDev
->AsyncRequestEvent
,
406 EHCI_ASYNC_REQUEST_POLLING_TIME
412 IN USB2_HC_DEV
*HcDev
418 Stop Async Request Polling Timer
427 EFI_DEVICE_ERROR Fail
431 return gBS
->SetTimer (
432 HcDev
->AsyncRequestEvent
,
434 EHCI_ASYNC_REQUEST_POLLING_TIME
440 IN USB2_HC_DEV
*HcDev
,
443 IN UINT8 DeviceSpeed
,
444 IN UINTN MaxPacketLen
,
445 OUT EHCI_QH_ENTITY
**QhPtrPtr
451 Create Qh Structure and Pre-Initialize
456 DeviceAddr - Address of Device
457 Endpoint - Endpoint Number
458 DeviceSpeed - Device Speed
459 MaxPacketLen - Max Length of one Packet
460 QhPtrPtr - A pointer of pointer to Qh for return
465 EFI_OUT_OF_RESOURCES Cannot allocate resources
478 // Allocate memory for Qh structure
480 Status
= EhciAllocatePool (
483 sizeof (EHCI_QH_ENTITY
)
485 if (EFI_ERROR (Status
)) {
486 Status
= EFI_OUT_OF_RESOURCES
;
493 (*QhPtrPtr
)->Next
= NULL
;
494 (*QhPtrPtr
)->Prev
= NULL
;
495 (*QhPtrPtr
)->FirstQtdPtr
= NULL
;
496 (*QhPtrPtr
)->AltQtdPtr
= NULL
;
497 (*QhPtrPtr
)->LastQtdPtr
= NULL
;
502 QhHwPtr
= &((*QhPtrPtr
)->Qh
);
503 QhHwPtr
->QhHorizontalPointer
= 0;
504 QhHwPtr
->SelectType
= 0;
505 QhHwPtr
->MaxPacketLen
= (UINT32
) MaxPacketLen
;
506 QhHwPtr
->EndpointSpeed
= (DeviceSpeed
& 0x3);
507 QhHwPtr
->EndpointNum
= (Endpoint
& 0x0F);
508 QhHwPtr
->DeviceAddr
= (DeviceAddr
& 0x7F);
509 QhHwPtr
->Multiplier
= HIGH_BANDWIDTH_PIPE_MULTIPLIER
;
523 IN USB2_HC_DEV
*HcDev
,
524 IN EHCI_QH_ENTITY
*QhPtr
535 QhPtr - A pointer to Qh
540 EFI_DEVICE_ERROR Fail
547 EhciFreePool (HcDev
, (UINT8
*) QhPtr
, sizeof (EHCI_QH_ENTITY
));
553 IN USB2_HC_DEV
*HcDev
,
555 IN UINT8 DeviceSpeed
,
556 IN UINTN MaxPacketLen
,
557 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
558 OUT EHCI_QH_ENTITY
**QhPtrPtr
564 Create Qh for Control Transfer
569 DeviceAddr - Address of Device
570 DeviceSpeed - Device Speed
571 MaxPacketLen - Max Length of one Packet
572 Translator - Translator Transaction for SplitX
573 QhPtrPtr - A pointer of pointer to Qh for return
578 EFI_OUT_OF_RESOURCES Cannot allocate resources
585 // Create and init Control Qh
595 if (EFI_ERROR (Status
)) {
596 Status
= EFI_OUT_OF_RESOURCES
;
602 (*QhPtrPtr
)->Next
= (*QhPtrPtr
);
603 (*QhPtrPtr
)->Prev
= (*QhPtrPtr
);
604 (*QhPtrPtr
)->TransferType
= CONTROL_TRANSFER
;
609 // Control Transfer use DataToggleControl
611 (*QhPtrPtr
)->Qh
.DataToggleControl
= TRUE
;
612 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&((*QhPtrPtr
)->Qh
)) >> 5);
613 (*QhPtrPtr
)->Qh
.SelectType
= QH_SELECT_TYPE
;
614 (*QhPtrPtr
)->Qh
.QhTerminate
= FALSE
;
615 if (EFI_USB_SPEED_HIGH
!= DeviceSpeed
) {
616 (*QhPtrPtr
)->Qh
.ControlEndpointFlag
= TRUE
;
618 (*QhPtrPtr
)->Qh
.NakCountReload
= NAK_COUNT_RELOAD
;
619 if (NULL
!= Translator
) {
620 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
621 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
622 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
631 IN USB2_HC_DEV
*HcDev
,
633 IN UINT8 EndPointAddr
,
634 IN UINT8 DeviceSpeed
,
636 IN UINTN MaxPacketLen
,
637 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
638 OUT EHCI_QH_ENTITY
**QhPtrPtr
644 Create Qh for Bulk Transfer
649 DeviceAddr - Address of Device
650 EndPointAddr - Address of Endpoint
651 DeviceSpeed - Device Speed
652 MaxPacketLen - Max Length of one Packet
653 Translator - Translator Transaction for SplitX
654 QhPtrPtr - A pointer of pointer to Qh for return
659 EFI_OUT_OF_RESOURCES Cannot allocate resources
666 // Create and init Bulk Qh
676 if (EFI_ERROR (Status
)) {
677 Status
= EFI_OUT_OF_RESOURCES
;
684 (*QhPtrPtr
)->Next
= (*QhPtrPtr
);
685 (*QhPtrPtr
)->Prev
= (*QhPtrPtr
);
686 (*QhPtrPtr
)->TransferType
= BULK_TRANSFER
;
691 // BulkTransfer don't use DataToggleControl
693 (*QhPtrPtr
)->Qh
.DataToggleControl
= FALSE
;
694 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&((*QhPtrPtr
)->Qh
)) >> 5);
695 (*QhPtrPtr
)->Qh
.SelectType
= QH_SELECT_TYPE
;
696 (*QhPtrPtr
)->Qh
.QhTerminate
= FALSE
;
697 (*QhPtrPtr
)->Qh
.NakCountReload
= NAK_COUNT_RELOAD
;
698 (*QhPtrPtr
)->Qh
.DataToggle
= DataToggle
;
699 if (NULL
!= Translator
) {
700 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
701 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
702 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
711 IN USB2_HC_DEV
*HcDev
,
713 IN UINT8 EndPointAddr
,
714 IN UINT8 DeviceSpeed
,
716 IN UINTN MaxPacketLen
,
718 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
719 OUT EHCI_QH_ENTITY
**QhPtrPtr
725 Create Qh for Control Transfer
730 DeviceAddr - Address of Device
731 EndPointAddr - Address of Endpoint
732 DeviceSpeed - Device Speed
733 MaxPacketLen - Max Length of one Packet
734 Interval - value of interval
735 Translator - Translator Transaction for SplitX
736 QhPtrPtr - A pointer of pointer to Qh for return
741 EFI_OUT_OF_RESOURCES Cannot allocate resources
748 // Create and init InterruptQh
758 if (EFI_ERROR (Status
)) {
759 Status
= EFI_OUT_OF_RESOURCES
;
767 (*QhPtrPtr
)->TransferType
= SYNC_INTERRUPT_TRANSFER
;
769 (*QhPtrPtr
)->TransferType
= ASYNC_INTERRUPT_TRANSFER
;
771 (*QhPtrPtr
)->Interval
= GetApproxiOfInterval (Interval
);
776 // InterruptTranfer don't use DataToggleControl
778 (*QhPtrPtr
)->Qh
.DataToggleControl
= FALSE
;
779 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= 0;
780 (*QhPtrPtr
)->Qh
.QhTerminate
= TRUE
;
781 (*QhPtrPtr
)->Qh
.NakCountReload
= 0;
782 (*QhPtrPtr
)->Qh
.InerruptScheduleMask
= MICRO_FRAME_0_CHANNEL
;
783 (*QhPtrPtr
)->Qh
.SplitComletionMask
= (MICRO_FRAME_2_CHANNEL
| MICRO_FRAME_3_CHANNEL
| MICRO_FRAME_4_CHANNEL
);
784 (*QhPtrPtr
)->Qh
.DataToggle
= DataToggle
;
785 if (NULL
!= Translator
) {
786 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
787 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
788 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
797 IN USB2_HC_DEV
*HcDev
,
803 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
809 Create Qtd Structure and Pre-Initialize it
814 DataPtr - A pointer to user data buffer to transfer
815 DataLen - Length of user data to transfer
816 PktId - Packet Identification of this Qtd
817 Toggle - Data Toggle of this Qtd
818 QtdStatus - Default value of status of this Qtd
819 QtdPtrPtr - A pointer of pointer to Qtd for return
824 EFI_OUT_OF_RESOURCES Cannot allocate resources
829 EHCI_QTD_HW
*QtdHwPtr
;
835 // Create memory for Qtd structure
837 Status
= EhciAllocatePool (
839 (UINT8
**) QtdPtrPtr
,
840 sizeof (EHCI_QTD_ENTITY
)
842 if (EFI_ERROR (Status
)) {
843 Status
= EFI_OUT_OF_RESOURCES
;
850 (*QtdPtrPtr
)->TotalBytes
= (UINT32
) DataLen
;
851 (*QtdPtrPtr
)->StaticTotalBytes
= (UINT32
) DataLen
;
852 (*QtdPtrPtr
)->Prev
= NULL
;
853 (*QtdPtrPtr
)->Next
= NULL
;
858 QtdHwPtr
= &((*QtdPtrPtr
)->Qtd
);
859 QtdHwPtr
->NextQtdPointer
= 0;
860 QtdHwPtr
->NextQtdTerminate
= TRUE
;
861 QtdHwPtr
->AltNextQtdPointer
= 0;
862 QtdHwPtr
->AltNextQtdTerminate
= TRUE
;
863 QtdHwPtr
->DataToggle
= Toggle
;
864 QtdHwPtr
->TotalBytes
= (UINT32
) DataLen
;
865 QtdHwPtr
->CurrentPage
= 0;
866 QtdHwPtr
->ErrorCount
= QTD_ERROR_COUNTER
;
867 QtdHwPtr
->Status
= QtdStatus
;
876 // Set PacketID [Setup/Data/Status]
879 case SETUP_PACKET_ID
:
880 QtdHwPtr
->PidCode
= SETUP_PACKET_PID_CODE
;
883 case INPUT_PACKET_ID
:
884 QtdHwPtr
->PidCode
= INPUT_PACKET_PID_CODE
;
887 case OUTPUT_PACKET_ID
:
888 QtdHwPtr
->PidCode
= OUTPUT_PACKET_PID_CODE
;
892 Status
= EFI_INVALID_PARAMETER
;
897 // Set Data Buffer Pointers
899 if (NULL
!= DataPtr
) {
900 SetQtdBufferPointer (
905 (*QtdPtrPtr
)->StaticCurrentOffset
= QtdHwPtr
->CurrentOffset
;
914 IN USB2_HC_DEV
*HcDev
,
916 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
922 Create Qtd Structure for Setup
927 DevReqPtr - A pointer to Device Request Data
928 QtdPtrPtr - A pointer of pointer to Qtd for return
933 EFI_OUT_OF_RESOURCES Cannot allocate resources
940 sizeof (EFI_USB_DEVICE_REQUEST
),
950 IN USB2_HC_DEV
*HcDev
,
955 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
961 Create Qtd Structure for data
966 DataPtr - A pointer to user data buffer to transfer
967 DataLen - Length of user data to transfer
968 PktId - Packet Identification of this Qtd
969 Toggle - Data Toggle of this Qtd
970 QtdPtrPtr - A pointer of pointer to Qtd for return
975 EFI_OUT_OF_RESOURCES Cannot allocate resources
992 IN USB2_HC_DEV
*HcDev
,
994 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
1000 Create Qtd Structure for Alternative
1005 PktId - Packet Identification of this Qtd
1006 QtdPtrPtr - A pointer of pointer to Qtd for return
1011 EFI_OUT_OF_RESOURCES Cannot allocate resources
1028 IN USB2_HC_DEV
*HcDev
,
1030 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
1034 Routine Description:
1036 Create Qtd Structure for status
1041 PktId - Packet Identification of this Qtd
1042 QtdPtrPtr - A pointer of pointer to Qtd for return
1047 EFI_OUT_OF_RESOURCES Cannot allocate resources
1064 IN USB2_HC_DEV
*HcDev
,
1066 IN UINT8
*RequestCursor
,
1067 IN UINT8
*DataCursor
,
1069 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1070 OUT EHCI_QTD_ENTITY
**ControlQtdsHead
1074 Routine Description:
1076 Create Qtds list for Control Transfer
1081 DataPktId - Packet Identification of Data Qtds
1082 RequestCursor - A pointer to request structure buffer to transfer
1083 DataCursor - A pointer to user data buffer to transfer
1084 DataLen - Length of user data to transfer
1085 ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return
1090 EFI_OUT_OF_RESOURCES Cannot allocate resources
1095 EHCI_QTD_ENTITY
*QtdPtr
;
1096 EHCI_QTD_ENTITY
*PreQtdPtr
;
1097 EHCI_QTD_ENTITY
*SetupQtdPtr
;
1098 EHCI_QTD_ENTITY
*FirstDataQtdPtr
;
1099 EHCI_QTD_ENTITY
*LastDataQtdPtr
;
1100 EHCI_QTD_ENTITY
*StatusQtdPtr
;
1103 UINTN CapacityOfQtd
;
1110 FirstDataQtdPtr
= NULL
;
1111 LastDataQtdPtr
= NULL
;
1112 StatusQtdPtr
= NULL
;
1116 // Setup Stage of Control Transfer
1118 Status
= CreateSetupQtd (
1123 if (EFI_ERROR (Status
)) {
1124 Status
= EFI_OUT_OF_RESOURCES
;
1129 // Data Stage of Control Transfer
1132 DataCount
= DataLen
;
1135 // Create Qtd structure and link together
1137 while (DataCount
> 0) {
1139 // PktSize is the data load size that each Qtd.
1141 CapacityOfQtd
= GetCapacityOfQtd (DataCursor
);
1142 SizePerQtd
= DataCount
;
1143 if (DataCount
> CapacityOfQtd
) {
1144 SizePerQtd
= CapacityOfQtd
;
1147 Status
= CreateDataQtd (
1155 if (EFI_ERROR (Status
)) {
1156 Status
= EFI_OUT_OF_RESOURCES
;
1157 if (NULL
== FirstDataQtdPtr
) {
1158 goto destory_setup_qtd
;
1164 if (NULL
== FirstDataQtdPtr
) {
1165 FirstDataQtdPtr
= QtdPtr
;
1167 LinkQtdToQtd (PreQtdPtr
, QtdPtr
);
1173 DataCursor
+= SizePerQtd
;
1174 DataCount
-= SizePerQtd
;
1177 LastDataQtdPtr
= QtdPtr
;
1180 // Status Stage of Control Transfer
1182 if (OUTPUT_PACKET_ID
== DataPktId
) {
1183 StatusPktId
= INPUT_PACKET_ID
;
1185 StatusPktId
= OUTPUT_PACKET_ID
;
1188 Status
= CreateStatusQtd (
1193 if (EFI_ERROR (Status
)) {
1194 Status
= EFI_OUT_OF_RESOURCES
;
1199 // Link setup Qtd -> data Qtds -> status Qtd
1201 if (FirstDataQtdPtr
!= NULL
) {
1202 LinkQtdToQtd (SetupQtdPtr
, FirstDataQtdPtr
);
1203 LinkQtdToQtd (LastDataQtdPtr
, StatusQtdPtr
);
1205 LinkQtdToQtd (SetupQtdPtr
, StatusQtdPtr
);
1208 *ControlQtdsHead
= SetupQtdPtr
;
1213 DestoryQtds (HcDev
, FirstDataQtdPtr
);
1215 DestoryQtds (HcDev
, SetupQtdPtr
);
1221 CreateBulkOrInterruptQtds (
1222 IN USB2_HC_DEV
*HcDev
,
1224 IN UINT8
*DataCursor
,
1226 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1227 OUT EHCI_QTD_ENTITY
**QtdsHead
1231 Routine Description:
1233 Create Qtds list for Bulk or Interrupt Transfer
1238 PktId - Packet Identification of Qtds
1239 DataCursor - A pointer to user data buffer to transfer
1240 DataLen - Length of user data to transfer
1241 DataToggle - Data Toggle to start
1242 Translator - Translator Transaction for SplitX
1243 QtdsHead - A pointer of pointer to first Qtd for control tranfer for return
1248 EFI_OUT_OF_RESOURCES Cannot allocate resources
1253 EHCI_QTD_ENTITY
*QtdPtr
;
1254 EHCI_QTD_ENTITY
*PreQtdPtr
;
1255 EHCI_QTD_ENTITY
*FirstQtdPtr
;
1256 EHCI_QTD_ENTITY
*AltQtdPtr
;
1258 UINTN CapacityOfQtd
;
1261 Status
= EFI_SUCCESS
;
1268 DataCount
= DataLen
;
1269 while (DataCount
> 0) {
1271 CapacityOfQtd
= GetCapacityOfQtd (DataCursor
);
1272 SizePerQtd
= DataCount
;
1273 if (DataCount
> CapacityOfQtd
) {
1274 SizePerQtd
= CapacityOfQtd
;
1277 Status
= CreateDataQtd (
1285 if (EFI_ERROR (Status
)) {
1286 Status
= EFI_OUT_OF_RESOURCES
;
1287 if (NULL
== FirstQtdPtr
) {
1294 if (NULL
== FirstQtdPtr
) {
1295 FirstQtdPtr
= QtdPtr
;
1297 LinkQtdToQtd (PreQtdPtr
, QtdPtr
);
1301 DataCursor
+= SizePerQtd
;
1302 DataCount
-= SizePerQtd
;
1306 // Set Alternate Qtd
1308 if (INPUT_PACKET_ID
== PktId
&& 0 < GetNumberOfQtd (FirstQtdPtr
)) {
1309 Status
= CreateAltQtd (
1314 if (EFI_ERROR (Status
)) {
1315 Status
= EFI_OUT_OF_RESOURCES
;
1319 LinkQtdsToAltQtd (FirstQtdPtr
, AltQtdPtr
);
1322 *QtdsHead
= FirstQtdPtr
;
1326 DestoryQtds (HcDev
, FirstQtdPtr
);
1333 IN USB2_HC_DEV
*HcDev
,
1334 IN EHCI_QTD_ENTITY
*FirstQtdPtr
1338 Routine Description:
1340 Destory all Qtds in the list
1345 FirstQtdPtr - A pointer to first Qtd in the list
1353 EHCI_QTD_ENTITY
*PrevQtd
;
1354 EHCI_QTD_ENTITY
*NextQtd
;
1360 PrevQtd
= FirstQtdPtr
;
1363 // Delete all the Qtds.
1366 NextQtd
= PrevQtd
->Next
;
1367 EhciFreePool (HcDev
, (UINT8
*) PrevQtd
, sizeof (EHCI_QTD_ENTITY
));
1369 } while (NULL
!= PrevQtd
);
1377 IN EHCI_QTD_ENTITY
*FirstQtdPtr
1381 Routine Description:
1383 Number of Qtds in the list
1387 FirstQtdPtr - A pointer to first Qtd in the list
1391 Number of Qtds in the list
1396 EHCI_QTD_ENTITY
*QtdPtr
;
1398 QtdPtr
= FirstQtdPtr
;
1400 while (NULL
!= QtdPtr
) {
1402 QtdPtr
= QtdPtr
->Next
;
1410 IN UINT8
*BufferCursor
1414 Routine Description:
1416 Get Size of First Qtd
1420 BufferCursor - BufferCursor of the Qtd
1429 if (EFI_PAGE_MASK
& GET_0B_TO_31B (BufferCursor
)) {
1430 return EFI_PAGE_SIZE
* 4;
1432 return EFI_PAGE_SIZE
* 5;
1438 GetApproxiOfInterval (
1443 Routine Description:
1445 Get the approximate value in the 2 index sequence
1449 Interval - the value of interval
1453 approximate value of interval in the 2 index sequence
1460 Orignate
= Interval
;
1463 while (Orignate
!= 1 && Orignate
!= 0) {
1464 Orignate
= Orignate
>> 1;
1465 Approxi
= Approxi
<< 1;
1468 if (Interval
& (Approxi
>> 1)) {
1469 Approxi
= Approxi
<< 1;
1476 GetQtdAlternateNextPointer (
1477 IN EHCI_QTD_HW
*HwQtdPtr
1481 Routine Description:
1483 Get Qtd alternate next pointer field
1487 HwQtdPtr - A pointer to hardware Qtd structure
1491 A pointer to hardware alternate Qtd
1499 if (!HwQtdPtr
->AltNextQtdTerminate
) {
1500 Value
= (EHCI_QTD_HW
*) GET_0B_TO_31B (HwQtdPtr
->AltNextQtdPointer
<< 5);
1508 IN EHCI_QTD_HW
*HwQtdPtr
1512 Routine Description:
1514 Get Qtd next pointer field
1518 HwQtdPtr - A pointer to hardware Qtd structure
1522 A pointer to next hardware Qtd structure
1530 if (!HwQtdPtr
->NextQtdTerminate
) {
1531 Value
= (EHCI_QTD_HW
*) GET_0B_TO_31B (HwQtdPtr
->NextQtdPointer
<< 5);
1539 IN EHCI_QTD_ENTITY
* PreQtdPtr
,
1540 IN EHCI_QTD_ENTITY
* QtdPtr
1544 Routine Description:
1550 PreQtdPtr - A pointer to pre Qtd
1551 QtdPtr - A pointer to next Qtd
1559 EHCI_QTD_HW
*QtdHwPtr
;
1567 PreQtdPtr
->Next
= QtdPtr
;
1568 QtdPtr
->Prev
= PreQtdPtr
;
1573 QtdHwPtr
= &(QtdPtr
->Qtd
);
1574 PreQtdPtr
->Qtd
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B(QtdHwPtr
) >> 5);
1575 PreQtdPtr
->Qtd
.NextQtdTerminate
= FALSE
;
1583 IN EHCI_QTD_ENTITY
* FirstQtdPtr
,
1584 IN EHCI_QTD_ENTITY
* AltQtdPtr
1588 Routine Description:
1590 Link AlterQtds together
1594 FirstQtdPtr - A pointer to first Qtd in the list
1595 AltQtdPtr - A pointer to alternative Qtd
1603 EHCI_QTD_ENTITY
*QtdPtr
;
1604 EHCI_QTD_HW
*AltQtdHwPtr
;
1606 ASSERT(FirstQtdPtr
);
1609 AltQtdHwPtr
= &(AltQtdPtr
->Qtd
);
1610 QtdPtr
= FirstQtdPtr
;
1612 while (NULL
!= QtdPtr
) {
1616 QtdPtr
->AltNext
= AltQtdPtr
;
1620 QtdPtr
->Qtd
.AltNextQtdPointer
= (UINT32
) (GET_0B_TO_31B(AltQtdHwPtr
) >> 5);
1621 QtdPtr
->Qtd
.AltNextQtdTerminate
= FALSE
;
1622 QtdPtr
= QtdPtr
->Next
;
1630 IN EHCI_QH_ENTITY
*QhPtr
,
1631 IN EHCI_QTD_ENTITY
*QtdPtr
1635 Routine Description:
1637 Link Qtds list to Qh
1641 QhPtr - A pointer to Qh
1642 QtdPtr - A pointer to first Qtd in the list
1650 EHCI_QTD_ENTITY
*Cursor
;
1651 EHCI_QTD_HW
*QtdHwPtr
;
1656 QhPtr
->FirstQtdPtr
= QtdPtr
;
1657 if (NULL
!= QtdPtr
->AltNext
) {
1658 QhPtr
->AltQtdPtr
= QtdPtr
->AltNext
;
1662 while (NULL
!= Cursor
) {
1663 Cursor
->SelfQh
= QhPtr
;
1664 if (NULL
== Cursor
->Next
) {
1665 QhPtr
->LastQtdPtr
= Cursor
;
1668 Cursor
= Cursor
->Next
;
1671 QtdHwPtr
= &(QtdPtr
->Qtd
);
1672 QhPtr
->Qh
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B (QtdHwPtr
) >> 5);
1673 QhPtr
->Qh
.NextQtdTerminate
= FALSE
;
1675 QhPtr
->Qh
.AltNextQtdPointer
= 0;
1676 QhPtr
->Qh
.AltNextQtdTerminate
= TRUE
;
1679 if ((QtdPtr
->Qtd
.PidCode
== OUTPUT_PACKET_PID_CODE
) &&
1680 (QhPtr
->TransferType
== BULK_TRANSFER
)) {
1684 QhPtr
->Qh
.Status
|= QTD_STATUS_DO_PING
;
1692 IN USB2_HC_DEV
*HcDev
,
1693 IN EHCI_QH_ENTITY
*QhPtr
1697 Routine Description:
1699 Link Qh to Async Schedule List
1704 QhPtr - A pointer to Qh
1709 EFI_DEVICE_ERROR Fail
1720 // NULL QH created before
1723 HcDev
->NULLQH
->Next
= QhPtr
;
1724 HcDev
->NULLQH
->Prev
= QhPtr
;
1726 QhPtr
->Next
= HcDev
->NULLQH
;
1727 QhPtr
->Prev
= HcDev
->NULLQH
;
1730 HcDev
->NULLQH
->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5));
1731 QhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&(HcDev
->NULLQH
->Qh
) >> 5));
1734 Status
= SetAsyncListAddr (HcDev
, HcDev
->NULLQH
);
1735 if (EFI_ERROR (Status
)) {
1736 Status
= EFI_DEVICE_ERROR
;
1740 if (!IsAsyncScheduleEnabled (HcDev
)) {
1742 Status
= EnableAsynchronousSchedule (HcDev
);
1743 if (EFI_ERROR (Status
)) {
1744 Status
= EFI_DEVICE_ERROR
;
1748 Status
= WaitForAsyncScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
1749 if (EFI_ERROR (Status
)) {
1750 DEBUG ((gEHCDebugLevel
, "EHCI: WaitForAsyncScheduleEnable TimeOut"));
1751 Status
= EFI_TIMEOUT
;
1755 if (IsEhcHalted (HcDev
)) {
1756 Status
= StartScheduleExecution (HcDev
);
1757 if (EFI_ERROR (Status
)) {
1758 Status
= EFI_DEVICE_ERROR
;
1769 UnlinkQhFromAsyncList (
1770 IN USB2_HC_DEV
*HcDev
,
1771 IN EHCI_QH_ENTITY
*QhPtr
1775 Routine Description:
1777 Unlink Qh from Async Schedule List
1782 QhPtr - A pointer to Qh
1787 EFI_DEVICE_ERROR Fail
1793 Status
= EFI_SUCCESS
;
1799 HcDev
->NULLQH
->Next
= HcDev
->NULLQH
;
1800 HcDev
->NULLQH
->Prev
= HcDev
->NULLQH
;
1803 QhPtr
->Next
= QhPtr
;
1804 QhPtr
->Prev
= QhPtr
;
1806 HcDev
->NULLQH
->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&(HcDev
->NULLQH
->Qh
) >> 5));
1809 SetAndWaitDoorBell (HcDev
, 2 * EHCI_GENERIC_TIMEOUT
);
1811 QhPtr
->Qh
.QhTerminate
= 1;
1812 QhPtr
->Qh
.QhHorizontalPointer
= 0;
1815 Status
= DisableAsynchronousSchedule (HcDev
);
1816 if (EFI_ERROR (Status
)) {
1817 Status
= EFI_DEVICE_ERROR
;
1821 Status
= WaitForAsyncScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
1822 if (EFI_ERROR (Status
)) {
1823 DEBUG ((gEHCErrorLevel
, "EHCI: WaitForAsyncScheduleDisable TimeOut\n"));
1824 Status
= EFI_TIMEOUT
;
1834 LinkQhToPeriodicList (
1835 IN USB2_HC_DEV
*HcDev
,
1836 IN EHCI_QH_ENTITY
*QhPtr
1840 Routine Description:
1842 Link Qh to Periodic Schedule List
1847 QhPtr - A pointer to Qh
1855 FRAME_LIST_ENTRY
*FrameEntryPtr
;
1856 EHCI_QH_ENTITY
*FindQhPtr
;
1857 EHCI_QH_HW
*FindQhHwPtr
;
1866 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
1868 QhPtr
->Qh
.HeadReclamationFlag
= FALSE
;
1870 if (QhPtr
->TransferType
== ASYNC_INTERRUPT_TRANSFER
) {
1873 // AsyncInterruptTransfer Qh
1877 // Link to Frame[0] List
1879 if (!FrameEntryPtr
->LinkTerminate
) {
1881 // Not Null FrameList
1883 FindQhHwPtr
= (EHCI_QH_HW
*) GET_0B_TO_31B (FrameEntryPtr
->LinkPointer
<< 5);
1884 FindQhPtr
= (EHCI_QH_ENTITY
*) GET_QH_ENTITY_ADDR (FindQhHwPtr
);
1886 // FindQh is Left/Right to Qh
1888 while ((NULL
!= FindQhPtr
->Next
) && (FindQhPtr
->Interval
> QhPtr
->Interval
)) {
1889 FindQhPtr
= FindQhPtr
->Next
;
1892 if (FindQhPtr
->Interval
== QhPtr
->Interval
) {
1894 // Link Qh after FindQh
1896 if (NULL
!= FindQhPtr
->Next
) {
1897 FindQhPtr
->Next
->Prev
= QhPtr
;
1898 QhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(FindQhPtr
->Next
->Qh
) >> 5);
1899 QhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1900 QhPtr
->Qh
.QhTerminate
= FALSE
;
1903 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1904 FindQhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1905 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
1907 QhPtr
->Prev
= FindQhPtr
;
1908 QhPtr
->Next
= FindQhPtr
->Next
;
1909 FindQhPtr
->Next
= QhPtr
;
1910 } else if (FindQhPtr
->Interval
< QhPtr
->Interval
) {
1912 // Link Qh before FindQh
1914 if (NULL
== FindQhPtr
->Prev
) {
1916 // Qh is the First one in Frame[0] List
1918 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1919 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1920 FrameEntryPtr
->LinkTerminate
= FALSE
;
1923 // Qh is not the First one in Frame[0] List
1925 FindQhPtr
->Prev
->Next
= QhPtr
;
1926 FindQhPtr
->Prev
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1927 FindQhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
1928 FindQhPtr
->Prev
->Qh
.QhTerminate
= FALSE
;
1931 QhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(FindQhPtr
->Qh
) >> 5);
1932 QhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1933 QhPtr
->Qh
.QhTerminate
= FALSE
;
1935 QhPtr
->Next
= FindQhPtr
;
1936 QhPtr
->Prev
= FindQhPtr
->Prev
;
1937 FindQhPtr
->Prev
= QhPtr
;
1940 // Link Qh after FindQh, Qh is the Last one
1942 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1943 FindQhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
1944 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
1946 QhPtr
->Prev
= FindQhPtr
;
1948 FindQhPtr
->Next
= QhPtr
;
1954 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1955 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1956 FrameEntryPtr
->LinkTerminate
= FALSE
;
1961 if (NULL
== QhPtr
->Prev
) {
1963 // Qh is the First one in Frame[0] List
1965 FrameIndex
+= QhPtr
->Interval
;
1966 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1967 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) (FrameEntryPtr
+ QhPtr
->Interval
);
1968 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1969 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1970 FrameEntryPtr
->LinkTerminate
= FALSE
;
1971 FrameIndex
+= QhPtr
->Interval
;
1973 } else if (QhPtr
->Interval
< QhPtr
->Prev
->Interval
) {
1975 // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
1977 FrameIndex
+= QhPtr
->Interval
;
1978 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1979 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) (FrameEntryPtr
+ QhPtr
->Interval
);
1980 if ((FrameIndex
% QhPtr
->Prev
->Interval
) != 0) {
1981 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1982 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1983 FrameEntryPtr
->LinkTerminate
= FALSE
;
1986 FrameIndex
+= QhPtr
->Interval
;
1992 // SyncInterruptTransfer Qh
1995 if (!FrameEntryPtr
->LinkTerminate
) {
1997 // Not Null FrameList
1999 FindQhHwPtr
= (EHCI_QH_HW
*) GET_0B_TO_31B (FrameEntryPtr
->LinkPointer
<< 5);
2000 FindQhPtr
= (EHCI_QH_ENTITY
*) GET_QH_ENTITY_ADDR (FindQhHwPtr
);
2002 // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
2004 while (NULL
!= FindQhPtr
->Next
) {
2005 FindQhPtr
= FindQhPtr
->Next
;
2008 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
2009 FindQhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
2010 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
2012 FindQhPtr
->Next
= QhPtr
;
2013 QhPtr
->Prev
= FindQhPtr
;
2018 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
2019 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
2020 FrameEntryPtr
->LinkTerminate
= FALSE
;
2028 UnlinkQhFromPeriodicList (
2029 IN USB2_HC_DEV
*HcDev
,
2030 IN EHCI_QH_ENTITY
*QhPtr
,
2035 Routine Description:
2037 Unlink Qh from Periodic Schedule List
2042 QhPtr - A pointer to Qh
2043 Interval - Interval of this periodic transfer
2051 FRAME_LIST_ENTRY
*FrameEntryPtr
;
2060 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
2062 if (QhPtr
->TransferType
== ASYNC_INTERRUPT_TRANSFER
) {
2065 // AsyncInterruptTransfer Qh
2068 if (NULL
== QhPtr
->Prev
) {
2070 // Qh is the First one on Frame[0] List
2072 if (NULL
== QhPtr
->Next
) {
2074 // Only one on Frame[0] List
2076 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
2077 FrameEntryPtr
->LinkPointer
= 0;
2078 FrameEntryPtr
->SelectType
= 0;
2079 FrameEntryPtr
->LinkTerminate
= TRUE
;
2080 FrameEntryPtr
+= Interval
;
2081 FrameIndex
+= Interval
;
2084 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
2085 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Next
->Qh
) >> 5);
2086 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
2087 FrameEntryPtr
->LinkTerminate
= FALSE
;
2088 FrameEntryPtr
+= Interval
;
2089 FrameIndex
+= Interval
;
2095 // Not First one on Frame[0] List
2097 if (NULL
== QhPtr
->Next
) {
2099 // Qh is the Last one on Frame[0] List
2101 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= 0;
2102 QhPtr
->Prev
->Qh
.SelectType
= 0;
2103 QhPtr
->Prev
->Qh
.QhTerminate
= TRUE
;
2105 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Next
->Qh
) >> 5);
2106 QhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
2107 QhPtr
->Prev
->Qh
.QhTerminate
= FALSE
;
2110 if (Interval
== QhPtr
->Prev
->Interval
) {
2112 // Interval is the same as Prev
2113 // Not involed Frame[X]
2119 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
2120 if ((FrameIndex
% QhPtr
->Prev
->Interval
) != 0) {
2121 FrameEntryPtr
->LinkPointer
= QhPtr
->Prev
->Qh
.QhHorizontalPointer
;
2122 FrameEntryPtr
->SelectType
= QhPtr
->Prev
->Qh
.SelectType
;
2123 FrameEntryPtr
->LinkTerminate
= QhPtr
->Prev
->Qh
.QhTerminate
;
2125 FrameEntryPtr
+= Interval
;
2126 FrameIndex
+= Interval
;
2131 if (NULL
!= QhPtr
->Next
) {
2132 QhPtr
->Next
->Prev
= QhPtr
->Prev
;
2135 if (NULL
!= QhPtr
->Prev
) {
2136 QhPtr
->Prev
->Next
= QhPtr
->Next
;
2140 // SyncInterruptTransfer Qh
2142 if (NULL
== QhPtr
->Prev
) {
2144 // Qh is the only one Qh on Frame[0] List
2146 FrameEntryPtr
->LinkPointer
= 0;
2147 FrameEntryPtr
->SelectType
= 0;
2148 FrameEntryPtr
->LinkTerminate
= TRUE
;
2150 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= 0;
2151 QhPtr
->Prev
->Qh
.SelectType
= 0;
2152 QhPtr
->Prev
->Qh
.QhTerminate
= TRUE
;
2155 if (NULL
!= QhPtr
->Prev
) {
2156 QhPtr
->Prev
->Next
= NULL
;
2164 LinkToAsyncReqeust (
2165 IN USB2_HC_DEV
*HcDev
,
2166 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
2170 Routine Description:
2172 Llink AsyncRequest Entry to Async Request List
2177 AsyncRequestPtr - A pointer to Async Request Entry
2185 EHCI_ASYNC_REQUEST
*CurrentPtr
;
2187 CurrentPtr
= HcDev
->AsyncRequestList
;
2188 HcDev
->AsyncRequestList
= AsyncRequestPtr
;
2189 AsyncRequestPtr
->Prev
= NULL
;
2190 AsyncRequestPtr
->Next
= CurrentPtr
;
2192 if (NULL
!= CurrentPtr
) {
2193 CurrentPtr
->Prev
= AsyncRequestPtr
;
2200 UnlinkFromAsyncReqeust (
2201 IN USB2_HC_DEV
*HcDev
,
2202 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
2206 Routine Description:
2208 Unlink AsyncRequest Entry from Async Request List
2213 AsyncRequestPtr - A pointer to Async Request Entry
2221 if (NULL
== AsyncRequestPtr
->Prev
) {
2222 HcDev
->AsyncRequestList
= AsyncRequestPtr
->Next
;
2223 if (NULL
!= AsyncRequestPtr
->Next
) {
2224 AsyncRequestPtr
->Next
->Prev
= NULL
;
2227 AsyncRequestPtr
->Prev
->Next
= AsyncRequestPtr
->Next
;
2228 if (NULL
!= AsyncRequestPtr
->Next
) {
2229 AsyncRequestPtr
->Next
->Prev
= AsyncRequestPtr
->Prev
;
2237 SetQtdBufferPointer (
2238 IN EHCI_QTD_HW
*QtdHwPtr
,
2244 Routine Description:
2246 Set data buffer pointers in Qtd
2250 QtdHwPtr - A pointer to Qtd hardware structure
2251 DataPtr - A pointer to user data buffer
2252 DataLen - Length of the user data buffer
2263 ASSERT (DataLen
<= 5 * EFI_PAGE_SIZE
);
2265 RemainLen
= DataLen
;
2267 // Allow buffer address range across 4G.
2268 // But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow
2269 // seperate buffer array.
2272 // Set BufferPointer0, ExtBufferPointer0 and Offset
2274 QtdHwPtr
->BufferPointer0
= (UINT32
) (GET_0B_TO_31B (DataPtr
) >> EFI_PAGE_SHIFT
);
2275 QtdHwPtr
->CurrentOffset
= (UINT32
) (GET_0B_TO_31B (DataPtr
) & EFI_PAGE_MASK
);
2278 // Set BufferPointer1 and ExtBufferPointer1
2280 RemainLen
= RemainLen
> (EFI_PAGE_SIZE
- QtdHwPtr
->CurrentOffset
) ? (RemainLen
- (EFI_PAGE_SIZE
- QtdHwPtr
->CurrentOffset
)) : 0;
2281 if (RemainLen
== 0) {
2285 QtdHwPtr
->BufferPointer1
= QtdHwPtr
->BufferPointer0
+ 1;
2288 // Set BufferPointer2 and ExtBufferPointer2
2290 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2291 if (RemainLen
== 0) {
2295 QtdHwPtr
->BufferPointer2
= QtdHwPtr
->BufferPointer1
+ 1;
2298 // Set BufferPointer3 and ExtBufferPointer3
2300 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2301 if (RemainLen
== 0) {
2305 QtdHwPtr
->BufferPointer3
= QtdHwPtr
->BufferPointer2
+ 1;
2308 // Set BufferPointer4 and ExtBufferPointer4
2310 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2311 if (RemainLen
== 0) {
2315 QtdHwPtr
->BufferPointer4
= QtdHwPtr
->BufferPointer3
+ 1;
2323 IN EHCI_QTD_HW
*HwQtdPtr
2327 Routine Description:
2329 Whether Qtd status is active or not
2333 HwQtdPtr - A pointer to hardware Qtd structure
2345 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2346 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_ACTIVE
);
2347 //DEBUG ((gEHCErrorLevel, "EHCI: IsQtdStatusActive 0x%X, Address = %x\r\n",HwQtdPtr->Status, HwQtdPtr));
2354 IN EHCI_QTD_HW
*HwQtdPtr
2358 Routine Description:
2360 Whether Qtd status is halted or not
2364 HwQtdPtr - A pointer to hardware Qtd structure
2376 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2377 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_HALTED
);
2383 IsQtdStatusBufferError (
2384 IN EHCI_QTD_HW
*HwQtdPtr
2388 Routine Description:
2390 Whether Qtd status is buffer error or not
2394 HwQtdPtr - A pointer to hardware Qtd structure
2399 FALSE No buffer error
2406 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2407 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_BUFFER_ERR
);
2413 IsQtdStatusBabbleError (
2414 IN EHCI_QTD_HW
*HwQtdPtr
2418 Routine Description:
2420 Whether Qtd status is babble error or not
2424 HwQtdPtr - A pointer to hardware Qtd structure
2429 FALSE No babble error
2436 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2437 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_BABBLE_ERR
);
2443 IsQtdStatusTransactionError (
2444 IN EHCI_QTD_HW
*HwQtdPtr
2448 Routine Description:
2450 Whether Qtd status is transaction error or not
2454 HwQtdPtr - A pointer to hardware Qtd structure
2458 TRUE Transaction error
2459 FALSE No transaction error
2466 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2467 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_TRANSACTION_ERR
);
2474 IN UINT8 EndPointAddress
2478 Routine Description:
2480 Whether is a DataIn direction transfer
2484 EndPointAddress - address of the endpoint
2495 if (EndPointAddress
& 0x80) {
2506 IN USB2_HC_DEV
*HcDev
,
2507 IN EFI_USB_DATA_DIRECTION TransferDirection
,
2509 IN OUT UINTN
*DataLength
,
2511 OUT UINT8
**DataCursor
,
2516 Routine Description:
2518 Map address of user data buffer
2523 TransferDirection - direction of transfer
2524 Data - A pointer to user data buffer
2525 DataLength - length of user data
2526 PktId - Packte Identificaion
2527 DataCursor - mapped address to return
2528 DataMap - identificaion of this mapping to return
2533 EFI_DEVICE_ERROR Fail
2538 EFI_PHYSICAL_ADDRESS TempPhysicalAddr
;
2540 Status
= EFI_SUCCESS
;
2542 switch (TransferDirection
) {
2546 *PktId
= INPUT_PACKET_ID
;
2548 // BusMasterWrite means cpu read
2550 Status
= HcDev
->PciIo
->Map (
2552 EfiPciIoOperationBusMasterWrite
,
2558 if (EFI_ERROR (Status
)) {
2559 DEBUG ((gEHCDebugLevel
, "EHCI: MapDataBuffer Failed\n"));
2560 Status
= EFI_DEVICE_ERROR
;
2564 *DataCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2569 *PktId
= OUTPUT_PACKET_ID
;
2571 // BusMasterRead means cpu write
2573 Status
= HcDev
->PciIo
->Map (
2575 EfiPciIoOperationBusMasterRead
,
2581 if (EFI_ERROR (Status
)) {
2582 Status
= EFI_DEVICE_ERROR
;
2586 *DataCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2591 *PktId
= OUTPUT_PACKET_ID
;
2600 Status
= EFI_INVALID_PARAMETER
;
2609 IN USB2_HC_DEV
*HcDev
,
2610 IN OUT VOID
*Request
,
2611 OUT UINT8
**RequestCursor
,
2612 OUT VOID
**RequestMap
2616 Routine Description:
2618 Map address of request structure buffer
2623 Request - A pointer to request structure
2624 RequestCursor - Mapped address of request structure to return
2625 RequestMap - Identificaion of this mapping to return
2630 EFI_DEVICE_ERROR Fail
2636 EFI_PHYSICAL_ADDRESS TempPhysicalAddr
;
2638 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
2639 Status
= HcDev
->PciIo
->Map (
2641 EfiPciIoOperationBusMasterRead
,
2643 (UINTN
*) &RequestLen
,
2647 if (EFI_ERROR (Status
)) {
2648 Status
= EFI_DEVICE_ERROR
;
2652 *RequestCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2659 DeleteAsyncRequestTransfer (
2660 IN USB2_HC_DEV
*HcDev
,
2661 IN UINT8 DeviceAddress
,
2662 IN UINT8 EndPointAddress
,
2663 OUT UINT8
*DataToggle
2667 Routine Description:
2669 Delete all asynchronous request transfer
2674 DeviceAddress - address of usb device
2675 EndPointAddress - address of endpoint
2676 DataToggle - stored data toggle
2681 EFI_DEVICE_ERROR Fail
2686 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2687 EHCI_ASYNC_REQUEST
*MatchPtr
;
2688 EHCI_QH_HW
*QhHwPtr
;
2691 if (NULL
== HcDev
->AsyncRequestList
) {
2692 Status
= EFI_INVALID_PARAMETER
;
2698 EndPointNum
= (UINT8
) (EndPointAddress
& 0x0f);
2699 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
2702 // Find QH of AsyncRequest by DeviceAddress and EndPointNum
2706 QhHwPtr
= &(AsyncRequestPtr
->QhPtr
->Qh
);
2707 if (QhHwPtr
->DeviceAddr
== DeviceAddress
&& QhHwPtr
->EndpointNum
== EndPointNum
) {
2708 MatchPtr
= AsyncRequestPtr
;
2712 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
2714 } while (NULL
!= AsyncRequestPtr
);
2716 if (NULL
== MatchPtr
) {
2717 Status
= EFI_INVALID_PARAMETER
;
2721 Status
= DisablePeriodicSchedule (HcDev
);
2722 if (EFI_ERROR (Status
)) {
2723 Status
= EFI_DEVICE_ERROR
;
2727 Status
= WaitForPeriodicScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2728 if (EFI_ERROR (Status
)) {
2729 DEBUG ((gEHCErrorLevel
, "EHCI: WaitForPeriodicScheduleDisable TimeOut\n"));
2730 Status
= EFI_TIMEOUT
;
2734 *DataToggle
= (UINT8
) MatchPtr
->QhPtr
->Qh
.DataToggle
;
2735 UnlinkQhFromPeriodicList (HcDev
, MatchPtr
->QhPtr
, MatchPtr
->QhPtr
->Interval
);
2736 UnlinkFromAsyncReqeust (HcDev
, MatchPtr
);
2738 if (NULL
== HcDev
->AsyncRequestList
) {
2740 Status
= StopPollingTimer (HcDev
);
2741 if (EFI_ERROR (Status
)) {
2742 Status
= EFI_DEVICE_ERROR
;
2748 Status
= EnablePeriodicSchedule (HcDev
);
2749 if (EFI_ERROR (Status
)) {
2750 Status
= EFI_DEVICE_ERROR
;
2754 Status
= WaitForPeriodicScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2755 if (EFI_ERROR (Status
)) {
2756 DEBUG ((gEHCErrorLevel
, "EHCI: WaitForPeriodicScheduleEnable TimeOut\n"));
2757 Status
= EFI_TIMEOUT
;
2761 if (IsEhcHalted (HcDev
)) {
2762 Status
= StartScheduleExecution (HcDev
);
2763 if (EFI_ERROR (Status
)) {
2764 Status
= EFI_DEVICE_ERROR
;
2771 DestoryQtds (HcDev
, MatchPtr
->QhPtr
->FirstQtdPtr
);
2772 DestoryQh (HcDev
, MatchPtr
->QhPtr
);
2773 EhciFreePool (HcDev
, (UINT8
*) MatchPtr
, sizeof (EHCI_ASYNC_REQUEST
));
2780 CleanUpAllAsyncRequestTransfer (
2781 IN USB2_HC_DEV
*HcDev
2785 Routine Description:
2787 Clean up all asynchronous request transfer
2799 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2800 EHCI_ASYNC_REQUEST
*FreePtr
;
2802 AsyncRequestPtr
= NULL
;
2805 StopPollingTimer (HcDev
);
2807 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
2808 while (NULL
!= AsyncRequestPtr
) {
2810 FreePtr
= AsyncRequestPtr
;
2811 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
2812 UnlinkFromAsyncReqeust (HcDev
, FreePtr
);
2813 UnlinkQhFromPeriodicList (HcDev
, FreePtr
->QhPtr
, FreePtr
->QhPtr
->Interval
);
2814 DestoryQtds (HcDev
, FreePtr
->QhPtr
->FirstQtdPtr
);
2815 DestoryQh (HcDev
, FreePtr
->QhPtr
);
2816 EhciFreePool (HcDev
, (UINT8
*) FreePtr
, sizeof (EHCI_ASYNC_REQUEST
));
2825 IN EHCI_QH_ENTITY
*QhPtr
2829 Routine Description:
2831 Zero out the fields in Qh structure
2835 QhPtr - A pointer to Qh structure
2843 QhPtr
->Qh
.CurrentQtdPointer
= 0;
2844 QhPtr
->Qh
.AltNextQtdPointer
= 0;
2845 QhPtr
->Qh
.NakCount
= 0;
2846 QhPtr
->Qh
.AltNextQtdTerminate
= 0;
2847 QhPtr
->Qh
.TotalBytes
= 0;
2848 QhPtr
->Qh
.InterruptOnComplete
= 0;
2849 QhPtr
->Qh
.CurrentPage
= 0;
2850 QhPtr
->Qh
.ErrorCount
= 0;
2851 QhPtr
->Qh
.PidCode
= 0;
2852 QhPtr
->Qh
.Status
= 0;
2853 QhPtr
->Qh
.BufferPointer0
= 0;
2854 QhPtr
->Qh
.CurrentOffset
= 0;
2855 QhPtr
->Qh
.BufferPointer1
= 0;
2856 QhPtr
->Qh
.CompleteSplitMask
= 0;
2857 QhPtr
->Qh
.BufferPointer2
= 0;
2858 QhPtr
->Qh
.SplitBytes
= 0;
2859 QhPtr
->Qh
.FrameTag
= 0;
2860 QhPtr
->Qh
.BufferPointer3
= 0;
2861 QhPtr
->Qh
.BufferPointer4
= 0;
2865 UpdateAsyncRequestTransfer (
2866 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
,
2867 IN UINT32 TransferResult
,
2872 Routine Description:
2874 Update asynchronous request transfer
2878 AsyncRequestPtr - A pointer to async request
2879 TransferResult - transfer result
2880 ErrQtdPos - postion of error Qtd
2888 EHCI_QTD_ENTITY
*QtdPtr
;
2892 if (EFI_USB_NOERROR
== TransferResult
) {
2895 // Update Qh for next trigger
2898 QtdPtr
= AsyncRequestPtr
->QhPtr
->FirstQtdPtr
;
2901 // Update fields in Qh
2905 // Get DataToggle from Overlay in Qh
2907 // ZeroOut Overlay in Qh except DataToggle, HostController will update this field
2909 ZeroOutQhOverlay (AsyncRequestPtr
->QhPtr
);
2910 AsyncRequestPtr
->QhPtr
->Qh
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B (&(QtdPtr
->Qtd
)) >> 5);
2911 AsyncRequestPtr
->QhPtr
->Qh
.NextQtdTerminate
= FALSE
;
2914 // Update fields in Qtd
2916 while (NULL
!= QtdPtr
) {
2917 QtdPtr
->Qtd
.TotalBytes
= QtdPtr
->StaticTotalBytes
;
2918 QtdPtr
->Qtd
.CurrentOffset
= QtdPtr
->StaticCurrentOffset
;
2919 QtdPtr
->Qtd
.CurrentPage
= 0;
2920 QtdPtr
->Qtd
.ErrorCount
= QTD_ERROR_COUNTER
;
2921 QtdPtr
->Qtd
.Status
= QTD_STATUS_ACTIVE
;
2923 QtdPtr
->TotalBytes
= QtdPtr
->StaticTotalBytes
;
2924 QtdPtr
= QtdPtr
->Next
;
2932 CheckQtdsTransferResult (
2933 IN BOOLEAN IsControl
,
2934 IN EHCI_QH_ENTITY
*QhPtr
,
2936 OUT UINTN
*ErrQtdPos
,
2937 OUT UINTN
*ActualLen
2941 Routine Description:
2943 Check transfer result of Qtds
2947 IsControl - Is control transfer or not
2948 QhPtr - A pointer to Qh
2949 Result - Transfer result
2950 ErrQtdPos - Error TD Position
2951 ActualLen - Actual Transfer Size
2960 UINTN ActualLenPerQtd
;
2961 EHCI_QTD_ENTITY
*QtdPtr
;
2962 EHCI_QTD_HW
*QtdHwPtr
;
2971 QtdPtr
= QhPtr
->FirstQtdPtr
;
2972 QtdHwPtr
= &(QtdPtr
->Qtd
);
2974 while (NULL
!= QtdHwPtr
) {
2975 if (IsQtdStatusActive (QtdHwPtr
)) {
2976 *Result
|= EFI_USB_ERR_NOTEXECUTE
;
2979 if (IsQtdStatusHalted (QtdHwPtr
)) {
2981 DEBUG ((gEHCErrorLevel
, "EHCI: QTD_STATUS_HALTED 0x%X\n", QtdHwPtr
->Status
));
2982 *Result
|= EFI_USB_ERR_STALL
;
2985 if (IsQtdStatusBufferError (QtdHwPtr
)) {
2986 DEBUG ((gEHCErrorLevel
, "EHCI: QTD_STATUS_BUFFER_ERR 0x%X\n", QtdHwPtr
->Status
));
2987 *Result
|= EFI_USB_ERR_BUFFER
;
2990 if (IsQtdStatusBabbleError (QtdHwPtr
)) {
2991 DEBUG ((gEHCErrorLevel
, "EHCI: StatusBufferError 0x%X\n", QtdHwPtr
->Status
));
2992 *Result
|= EFI_USB_ERR_BABBLE
;
2995 if (IsQtdStatusTransactionError (QtdHwPtr
)) {
2998 //Exclude Special Case
3000 if (((QtdHwPtr
->Status
& QTD_STATUS_HALTED
) == QTD_STATUS_HALTED
) ||
3001 ((QtdHwPtr
->Status
& QTD_STATUS_ACTIVE
) == QTD_STATUS_ACTIVE
) ||
3002 ((QtdHwPtr
->ErrorCount
!= QTD_ERROR_COUNTER
))) {
3003 *Result
|= EFI_USB_ERR_TIMEOUT
;
3004 DEBUG ((gEHCErrorLevel
, "EHCI: QTD_STATUS_TRANSACTION_ERR: 0x%X\n", QtdHwPtr
->Status
));
3008 ActualLenPerQtd
= QtdPtr
->TotalBytes
- QtdHwPtr
->TotalBytes
;
3009 QtdPtr
->TotalBytes
= QtdHwPtr
->TotalBytes
;
3011 // Accumulate actual transferred data length in each DataQtd.
3013 if (SETUP_PACKET_PID_CODE
!= QtdHwPtr
->PidCode
) {
3014 *ActualLen
+= ActualLenPerQtd
;
3022 if ((INPUT_PACKET_PID_CODE
== QtdHwPtr
->PidCode
)&& (QtdPtr
->TotalBytes
> 0)) {
3024 // Short Packet: IN, Short
3026 DEBUG ((gEHCDebugLevel
, "EHCI: Short Packet Status: 0x%x\n", QtdHwPtr
->Status
));
3030 if (QtdPtr
->Next
!= NULL
) {
3032 QtdPtr
= QtdPtr
->Next
;
3033 QtdHwPtr
= &(QtdPtr
->Qtd
);
3045 IN USB2_HC_DEV
*HcDev
,
3046 IN BOOLEAN IsControl
,
3047 IN EHCI_QH_ENTITY
*QhPtr
,
3048 IN OUT UINTN
*ActualLen
,
3049 OUT UINT8
*DataToggle
,
3051 OUT UINT32
*TransferResult
3055 Routine Description:
3057 Execute Bulk or SyncInterrupt Transfer
3062 IsControl - Is control transfer or not
3063 QhPtr - A pointer to Qh
3064 ActualLen - Actual transfered Len
3065 DataToggle - Data Toggle
3066 TimeOut - TimeOut threshold
3067 TransferResult - Transfer result
3072 EFI_DEVICE_ERROR Fail
3081 Status
= EFI_SUCCESS
;
3083 *TransferResult
= EFI_USB_NOERROR
;
3087 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50);
3090 *TransferResult
= 0;
3091 Finished
= CheckQtdsTransferResult (
3102 // Qtd is inactive, which means bulk or interrupt transfer's end.
3104 if (!(*TransferResult
& EFI_USB_ERR_NOTEXECUTE
)) {
3108 gBS
->Stall (EHCI_SYNC_REQUEST_POLLING_TIME
);
3112 if (EFI_USB_NOERROR
!= *TransferResult
) {
3114 DEBUG((gEHCErrorLevel
, "EHCI: QTDS TimeOut\n"));
3115 Status
= EFI_TIMEOUT
;
3117 Status
= EFI_DEVICE_ERROR
;
3122 // Special for Bulk and Interrupt Transfer
3124 *DataToggle
= (UINT8
) QhPtr
->Qh
.DataToggle
;
3130 AsyncRequestMoniter (
3135 Routine Description:
3137 Interrupt transfer periodic check handler
3140 Event - Interrupt event
3141 Context - Pointer to USB2_HC_DEV
3146 EFI_DEVICE_ERROR Fail
3152 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
3153 EHCI_ASYNC_REQUEST
*NextPtr
;
3154 EHCI_QTD_HW
*QtdHwPtr
;
3157 UINT32 TransferResult
;
3158 UINT8
*ReceiveBuffer
;
3159 UINT8
*ProcessBuffer
;
3161 Status
= EFI_SUCCESS
;
3163 ReceiveBuffer
= NULL
;
3164 ProcessBuffer
= NULL
;
3165 HcDev
= (USB2_HC_DEV
*) Context
;
3166 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
3168 while (NULL
!= AsyncRequestPtr
) {
3174 CheckQtdsTransferResult (
3176 AsyncRequestPtr
->QhPtr
,
3182 if ((TransferResult
& EFI_USB_ERR_NAK
) || (TransferResult
& EFI_USB_ERR_NOTEXECUTE
)) {
3183 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
3187 // Allocate memory for EHC private data structure
3189 ProcessBuffer
= AllocateZeroPool (ActualLen
);
3190 if (NULL
== ProcessBuffer
) {
3191 Status
= EFI_OUT_OF_RESOURCES
;
3195 QtdHwPtr
= &(AsyncRequestPtr
->QhPtr
->FirstQtdPtr
->Qtd
);
3196 ReceiveBuffer
= (UINT8
*) GET_0B_TO_31B ((QtdHwPtr
->BufferPointer0
<< EFI_PAGE_SHIFT
) | AsyncRequestPtr
->QhPtr
->FirstQtdPtr
->StaticCurrentOffset
);
3203 UpdateAsyncRequestTransfer (AsyncRequestPtr
, TransferResult
, ErrQtdPos
);
3205 NextPtr
= AsyncRequestPtr
->Next
;
3207 if (EFI_USB_NOERROR
== TransferResult
) {
3209 if (AsyncRequestPtr
->CallBackFunc
!= NULL
) {
3210 (AsyncRequestPtr
->CallBackFunc
) (ProcessBuffer
, ActualLen
, AsyncRequestPtr
->Context
, TransferResult
);
3216 // leave error recovery to its related device driver. A common case of
3217 // the error recovery is to re-submit the interrupt transfer.
3218 // When an interrupt transfer is re-submitted, its position in the linked
3219 // list is changed. It is inserted to the head of the linked list, while
3220 // this function scans the whole list from head to tail. Thus, the
3221 // re-submitted interrupt transfer's callback function will not be called
3222 // again in this round.
3224 if (AsyncRequestPtr
->CallBackFunc
!= NULL
) {
3225 (AsyncRequestPtr
->CallBackFunc
) (NULL
, 0, AsyncRequestPtr
->Context
, TransferResult
);
3230 if (NULL
!= ProcessBuffer
) {
3231 gBS
->FreePool (ProcessBuffer
);
3234 AsyncRequestPtr
= NextPtr
;