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.
25 InitialPeriodicFrameList (
26 IN USB2_HC_DEV
*HcDev
,
33 Initialize Periodic Schedule Frame List
38 Length - Frame List Length
49 EFI_PHYSICAL_ADDRESS FrameBuffer
;
51 UINTN BufferSizeInPages
;
52 UINTN BufferSizeInBytes
;
54 FRAME_LIST_ENTRY
*FrameEntryPtr
;
57 // The Frame List is a common buffer that will be
58 // accessed by both the cpu and the usb bus master
60 // The Frame List ocupies 4K bytes,
61 // and must be aligned on 4-Kbyte boundaries.
63 if (EHCI_MAX_FRAME_LIST_LENGTH
!= Length
&& IsFrameListProgrammable (HcDev
)) {
64 Status
= SetFrameListLen (HcDev
, Length
);
65 if (EFI_ERROR (Status
)) {
66 Status
= EFI_INVALID_PARAMETER
;
71 BufferSizeInBytes
= EFI_PAGE_SIZE
;
72 BufferSizeInPages
= EFI_SIZE_TO_PAGES (BufferSizeInBytes
);
73 Status
= HcDev
->PciIo
->AllocateBuffer (
81 if (EFI_ERROR (Status
)) {
82 DEBUG ((gEHCErrorLevel
, "PciIo->AllocateBuffer Failed\n"));
83 Status
= EFI_OUT_OF_RESOURCES
;
87 Status
= HcDev
->PciIo
->Map (
89 EfiPciIoOperationBusMasterCommonBuffer
,
95 if (EFI_ERROR (Status
) || (BufferSizeInBytes
!= EFI_PAGE_SIZE
)) {
96 DEBUG ((gEHCErrorLevel
, "PciIo->MapBuffer Failed\n"));
97 Status
= EFI_OUT_OF_RESOURCES
;
102 // Put high 32bit into CtrlDataStructSeg reg
103 // when 64bit addressing range capability
105 if (HcDev
->Is64BitCapable
!= 0) {
106 HcDev
->High32BitAddr
= (UINT32
) GET_32B_TO_63B (FrameBuffer
);
108 Status
= SetCtrlDataStructSeg (HcDev
);
109 if (EFI_ERROR (Status
)) {
110 DEBUG ((gEHCErrorLevel
, "SetCtrlDataStructSeg Failed\n"));
111 Status
= EFI_DEVICE_ERROR
;
117 // Tell the Host Controller where the Frame List lies,
118 // by set the Frame List Base Address Register.
120 Status
= SetFrameListBaseAddr (HcDev
, (UINT32
) FrameBuffer
);
121 if (EFI_ERROR (Status
)) {
122 Status
= EFI_DEVICE_ERROR
;
126 HcDev
->PeriodicFrameListLength
= Length
;
127 HcDev
->PeriodicFrameListBuffer
= (VOID
*) ((UINTN
) FrameBuffer
);
128 HcDev
->PeriodicFrameListMap
= Map
;
131 // Init Frame List Array fields
133 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
134 for (FrameIndex
= 0; FrameIndex
< HcDev
->PeriodicFrameListLength
; FrameIndex
++) {
135 FrameEntryPtr
->LinkPointer
= 0;
136 FrameEntryPtr
->Rsvd
= 0;
137 FrameEntryPtr
->SelectType
= 0;
138 FrameEntryPtr
->LinkTerminate
= TRUE
;
145 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, Map
);
147 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, BufferSizeInPages
, CommonBuffer
);
153 DeinitialPeriodicFrameList (
154 IN USB2_HC_DEV
*HcDev
160 Deinitialize Periodic Schedule Frame List
172 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, HcDev
->PeriodicFrameListMap
);
173 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE
), HcDev
->PeriodicFrameListBuffer
);
179 IN USB2_HC_DEV
*HcDev
,
180 IN EFI_EVENT_NOTIFY NotifyFunction
186 Create Async Request Polling Timer
191 NotifyFunction - Timer Notify Function
196 EFI_DEVICE_ERROR Fail
200 return gBS
->CreateEvent (
201 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
205 &HcDev
->AsyncRequestEvent
210 DestoryPollingTimer (
211 IN USB2_HC_DEV
*HcDev
217 Destory Async Request Polling Timer
226 EFI_DEVICE_ERROR Fail
230 return gBS
->CloseEvent (HcDev
->AsyncRequestEvent
);
235 IN USB2_HC_DEV
*HcDev
241 Start Async Request Polling Timer
250 EFI_DEVICE_ERROR Fail
254 return gBS
->SetTimer (
255 HcDev
->AsyncRequestEvent
,
257 EHCI_ASYNC_REQUEST_POLLING_TIME
263 IN USB2_HC_DEV
*HcDev
269 Stop Async Request Polling Timer
278 EFI_DEVICE_ERROR Fail
282 return gBS
->SetTimer (
283 HcDev
->AsyncRequestEvent
,
285 EHCI_ASYNC_REQUEST_POLLING_TIME
291 IN USB2_HC_DEV
*HcDev
,
294 IN UINT8 DeviceSpeed
,
295 IN UINTN MaxPacketLen
,
296 OUT EHCI_QH_ENTITY
**QhPtrPtr
302 Create Qh Structure and Pre-Initialize
307 DeviceAddr - Address of Device
308 Endpoint - Endpoint Number
309 DeviceSpeed - Device Speed
310 MaxPacketLen - Max Length of one Packet
311 QhPtrPtr - A pointer of pointer to Qh for return
316 EFI_OUT_OF_RESOURCES Cannot allocate resources
329 // Allocate memory for Qh structure
331 Status
= EhciAllocatePool (
334 sizeof (EHCI_QH_ENTITY
)
336 if (EFI_ERROR (Status
)) {
337 Status
= EFI_OUT_OF_RESOURCES
;
343 ZeroMem (*QhPtrPtr
, sizeof (EHCI_QH_ENTITY
));
348 (*QhPtrPtr
)->Next
= NULL
;
349 (*QhPtrPtr
)->Prev
= NULL
;
350 (*QhPtrPtr
)->FirstQtdPtr
= NULL
;
351 (*QhPtrPtr
)->AltQtdPtr
= NULL
;
352 (*QhPtrPtr
)->LastQtdPtr
= NULL
;
357 QhHwPtr
= &((*QhPtrPtr
)->Qh
);
358 QhHwPtr
->QhHorizontalPointer
= 0;
359 QhHwPtr
->SelectType
= 0;
360 QhHwPtr
->MaxPacketLen
= (UINT32
) MaxPacketLen
;
361 QhHwPtr
->EndpointSpeed
= (DeviceSpeed
& 0x3);
362 QhHwPtr
->EndpointNum
= (Endpoint
& 0x0f);
363 QhHwPtr
->DeviceAddr
= (DeviceAddr
& 0x7f);
364 QhHwPtr
->Multiplier
= HIGH_BANDWIDTH_PIPE_MULTIPLIER
;
378 IN USB2_HC_DEV
*HcDev
,
379 IN EHCI_QH_ENTITY
*QhPtr
390 QhPtr - A pointer to Qh
395 EFI_DEVICE_ERROR Fail
402 EhciFreePool (HcDev
, (UINT8
*) QhPtr
, sizeof (EHCI_QH_ENTITY
));
408 IN USB2_HC_DEV
*HcDev
,
410 IN UINT8 DeviceSpeed
,
411 IN UINTN MaxPacketLen
,
412 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
413 OUT EHCI_QH_ENTITY
**QhPtrPtr
419 Create Qh for Control Transfer
424 DeviceAddr - Address of Device
425 DeviceSpeed - Device Speed
426 MaxPacketLen - Max Length of one Packet
427 Translator - Translator Transaction for SplitX
428 QhPtrPtr - A pointer of pointer to Qh for return
433 EFI_OUT_OF_RESOURCES Cannot allocate resources
440 // Create and init Control Qh
450 if (EFI_ERROR (Status
)) {
451 Status
= EFI_OUT_OF_RESOURCES
;
457 (*QhPtrPtr
)->Next
= (*QhPtrPtr
);
458 (*QhPtrPtr
)->Prev
= (*QhPtrPtr
);
459 (*QhPtrPtr
)->TransferType
= CONTROL_TRANSFER
;
464 // Control Transfer use DataToggleControl
466 (*QhPtrPtr
)->Qh
.DataToggleControl
= TRUE
;
467 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&((*QhPtrPtr
)->Qh
)) >> 5);
468 (*QhPtrPtr
)->Qh
.SelectType
= QH_SELECT_TYPE
;
469 (*QhPtrPtr
)->Qh
.QhTerminate
= FALSE
;
470 (*QhPtrPtr
)->Qh
.ControlEndpointFlag
= TRUE
;
471 (*QhPtrPtr
)->Qh
.NakCountReload
= NAK_COUNT_RELOAD
;
472 if (NULL
!= Translator
) {
473 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
474 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
475 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
484 IN USB2_HC_DEV
*HcDev
,
486 IN UINT8 EndPointAddr
,
487 IN UINT8 DeviceSpeed
,
489 IN UINTN MaxPacketLen
,
490 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
491 OUT EHCI_QH_ENTITY
**QhPtrPtr
497 Create Qh for Bulk Transfer
502 DeviceAddr - Address of Device
503 EndPointAddr - Address of Endpoint
504 DeviceSpeed - Device Speed
505 MaxPacketLen - Max Length of one Packet
506 Translator - Translator Transaction for SplitX
507 QhPtrPtr - A pointer of pointer to Qh for return
512 EFI_OUT_OF_RESOURCES Cannot allocate resources
519 // Create and init Bulk Qh
529 if (EFI_ERROR (Status
)) {
530 Status
= EFI_OUT_OF_RESOURCES
;
537 (*QhPtrPtr
)->Next
= (*QhPtrPtr
);
538 (*QhPtrPtr
)->Prev
= (*QhPtrPtr
);
539 (*QhPtrPtr
)->TransferType
= BULK_TRANSFER
;
544 // BulkTransfer don't use DataToggleControl
546 (*QhPtrPtr
)->Qh
.DataToggleControl
= FALSE
;
547 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= (UINT32
) (GET_0B_TO_31B (&((*QhPtrPtr
)->Qh
)) >> 5);
548 (*QhPtrPtr
)->Qh
.SelectType
= QH_SELECT_TYPE
;
549 (*QhPtrPtr
)->Qh
.QhTerminate
= FALSE
;
550 (*QhPtrPtr
)->Qh
.NakCountReload
= NAK_COUNT_RELOAD
;
551 (*QhPtrPtr
)->Qh
.DataToggle
= DataToggle
;
552 if (NULL
!= Translator
) {
553 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
554 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
555 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
564 IN USB2_HC_DEV
*HcDev
,
566 IN UINT8 EndPointAddr
,
567 IN UINT8 DeviceSpeed
,
569 IN UINTN MaxPacketLen
,
571 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
572 OUT EHCI_QH_ENTITY
**QhPtrPtr
578 Create Qh for Control Transfer
583 DeviceAddr - Address of Device
584 EndPointAddr - Address of Endpoint
585 DeviceSpeed - Device Speed
586 MaxPacketLen - Max Length of one Packet
587 Interval - value of interval
588 Translator - Translator Transaction for SplitX
589 QhPtrPtr - A pointer of pointer to Qh for return
594 EFI_OUT_OF_RESOURCES Cannot allocate resources
601 // Create and init InterruptQh
611 if (EFI_ERROR (Status
)) {
612 Status
= EFI_OUT_OF_RESOURCES
;
620 (*QhPtrPtr
)->TransferType
= SYNC_INTERRUPT_TRANSFER
;
622 (*QhPtrPtr
)->TransferType
= ASYNC_INTERRUPT_TRANSFER
;
624 (*QhPtrPtr
)->Interval
= GetApproxiOfInterval (Interval
);
629 // InterruptTranfer don't use DataToggleControl
631 (*QhPtrPtr
)->Qh
.DataToggleControl
= FALSE
;
632 (*QhPtrPtr
)->Qh
.QhHorizontalPointer
= 0;
633 (*QhPtrPtr
)->Qh
.QhTerminate
= TRUE
;
634 (*QhPtrPtr
)->Qh
.NakCountReload
= 0;
635 (*QhPtrPtr
)->Qh
.InerruptScheduleMask
= MICRO_FRAME_0_CHANNEL
;
636 (*QhPtrPtr
)->Qh
.SplitComletionMask
= (MICRO_FRAME_2_CHANNEL
| MICRO_FRAME_3_CHANNEL
| MICRO_FRAME_4_CHANNEL
);
637 (*QhPtrPtr
)->Qh
.DataToggle
= DataToggle
;
638 if (NULL
!= Translator
) {
639 (*QhPtrPtr
)->Qh
.PortNum
= Translator
->TranslatorPortNumber
;
640 (*QhPtrPtr
)->Qh
.HubAddr
= Translator
->TranslatorHubAddress
;
641 (*QhPtrPtr
)->Qh
.Status
|= QTD_STATUS_DO_START_SPLIT
;
650 IN USB2_HC_DEV
*HcDev
,
656 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
662 Create Qtd Structure and Pre-Initialize it
667 DataPtr - A pointer to user data buffer to transfer
668 DataLen - Length of user data to transfer
669 PktId - Packet Identification of this Qtd
670 Toggle - Data Toggle of this Qtd
671 QtdStatus - Default value of status of this Qtd
672 QtdPtrPtr - A pointer of pointer to Qtd for return
677 EFI_OUT_OF_RESOURCES Cannot allocate resources
682 EHCI_QTD_HW
*QtdHwPtr
;
688 // Create memory for Qtd structure
690 Status
= EhciAllocatePool (
692 (UINT8
**) QtdPtrPtr
,
693 sizeof (EHCI_QTD_ENTITY
)
695 if (EFI_ERROR (Status
)) {
696 Status
= EFI_OUT_OF_RESOURCES
;
700 // Init fields in Qtd
703 ZeroMem (*QtdPtrPtr
, sizeof (EHCI_QTD_ENTITY
));
708 (*QtdPtrPtr
)->TotalBytes
= (UINT32
) DataLen
;
709 (*QtdPtrPtr
)->StaticTotalBytes
= (UINT32
) DataLen
;
710 (*QtdPtrPtr
)->Prev
= NULL
;
711 (*QtdPtrPtr
)->Next
= NULL
;
716 QtdHwPtr
= &((*QtdPtrPtr
)->Qtd
);
717 QtdHwPtr
->NextQtdPointer
= 0;
718 QtdHwPtr
->NextQtdTerminate
= TRUE
;
719 QtdHwPtr
->AltNextQtdPointer
= 0;
720 QtdHwPtr
->AltNextQtdTerminate
= TRUE
;
721 QtdHwPtr
->DataToggle
= Toggle
;
722 QtdHwPtr
->TotalBytes
= (UINT32
) DataLen
;
723 QtdHwPtr
->CurrentPage
= 0;
724 QtdHwPtr
->ErrorCount
= QTD_ERROR_COUNTER
;
725 QtdHwPtr
->Status
= QtdStatus
;
734 // Set PacketID [Setup/Data/Status]
737 case SETUP_PACKET_ID
:
738 QtdHwPtr
->PidCode
= SETUP_PACKET_PID_CODE
;
741 case INPUT_PACKET_ID
:
742 QtdHwPtr
->PidCode
= INPUT_PACKET_PID_CODE
;
745 case OUTPUT_PACKET_ID
:
746 QtdHwPtr
->PidCode
= OUTPUT_PACKET_PID_CODE
;
750 Status
= EFI_INVALID_PARAMETER
;
755 // Set Data Buffer Pointers
757 if (NULL
!= DataPtr
) {
758 SetQtdBufferPointer (
763 (*QtdPtrPtr
)->StaticCurrentOffset
= QtdHwPtr
->CurrentOffset
;
772 IN USB2_HC_DEV
*HcDev
,
774 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
780 Create Qtd Structure for Setup
785 DevReqPtr - A pointer to Device Request Data
786 QtdPtrPtr - A pointer of pointer to Qtd for return
791 EFI_OUT_OF_RESOURCES Cannot allocate resources
798 sizeof (EFI_USB_DEVICE_REQUEST
),
808 IN USB2_HC_DEV
*HcDev
,
813 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
819 Create Qtd Structure for data
824 DataPtr - A pointer to user data buffer to transfer
825 DataLen - Length of user data to transfer
826 PktId - Packet Identification of this Qtd
827 Toggle - Data Toggle of this Qtd
828 QtdPtrPtr - A pointer of pointer to Qtd for return
833 EFI_OUT_OF_RESOURCES Cannot allocate resources
850 IN USB2_HC_DEV
*HcDev
,
852 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
858 Create Qtd Structure for Alternative
863 PktId - Packet Identification of this Qtd
864 QtdPtrPtr - A pointer of pointer to Qtd for return
869 EFI_OUT_OF_RESOURCES Cannot allocate resources
886 IN USB2_HC_DEV
*HcDev
,
888 OUT EHCI_QTD_ENTITY
**QtdPtrPtr
894 Create Qtd Structure for status
899 PktId - Packet Identification of this Qtd
900 QtdPtrPtr - A pointer of pointer to Qtd for return
905 EFI_OUT_OF_RESOURCES Cannot allocate resources
922 IN USB2_HC_DEV
*HcDev
,
924 IN UINT8
*RequestCursor
,
925 IN UINT8
*DataCursor
,
927 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
928 OUT EHCI_QTD_ENTITY
**ControlQtdsHead
934 Create Qtds list for Control Transfer
939 DataPktId - Packet Identification of Data Qtds
940 RequestCursor - A pointer to request structure buffer to transfer
941 DataCursor - A pointer to user data buffer to transfer
942 DataLen - Length of user data to transfer
943 ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return
948 EFI_OUT_OF_RESOURCES Cannot allocate resources
953 EHCI_QTD_ENTITY
*QtdPtr
;
954 EHCI_QTD_ENTITY
*PreQtdPtr
;
955 EHCI_QTD_ENTITY
*SetupQtdPtr
;
956 EHCI_QTD_ENTITY
*FirstDataQtdPtr
;
957 EHCI_QTD_ENTITY
*LastDataQtdPtr
;
958 EHCI_QTD_ENTITY
*StatusQtdPtr
;
969 FirstDataQtdPtr
= NULL
;
970 LastDataQtdPtr
= NULL
;
975 // Setup Stage of Control Transfer
977 Status
= CreateSetupQtd (
982 if (EFI_ERROR (Status
)) {
983 Status
= EFI_OUT_OF_RESOURCES
;
988 // Data Stage of Control Transfer
994 // Create Qtd structure and link together
996 while (DataCount
> 0) {
998 // PktSize is the data load size that each Qtd.
1000 CapacityOfQtd
= GetCapacityOfQtd (DataCursor
);
1001 SizePerQtd
= DataCount
;
1002 if (DataCount
> CapacityOfQtd
) {
1003 SizePerQtd
= CapacityOfQtd
;
1006 Status
= CreateDataQtd (
1014 if (EFI_ERROR (Status
)) {
1015 Status
= EFI_OUT_OF_RESOURCES
;
1016 if (NULL
== FirstDataQtdPtr
) {
1017 goto destory_setup_qtd
;
1023 if (NULL
== FirstDataQtdPtr
) {
1024 FirstDataQtdPtr
= QtdPtr
;
1026 LinkQtdToQtd (PreQtdPtr
, QtdPtr
);
1030 // Reverse Data Toggle or not determined by parity of transactions of one qtd
1032 Xnum
= Translator
? GetNumberOfTransaction (SizePerQtd
, EHCI_BLOCK_SIZE_WITH_TT
) : GetNumberOfTransaction (SizePerQtd
, EHCI_BLOCK_SIZE
);
1033 if (Xnum
% 2 != 0) {
1038 DataCursor
+= SizePerQtd
;
1039 DataCount
-= SizePerQtd
;
1042 LastDataQtdPtr
= QtdPtr
;
1045 // Status Stage of Control Transfer
1047 if (OUTPUT_PACKET_ID
== DataPktId
) {
1048 StatusPktId
= INPUT_PACKET_ID
;
1050 StatusPktId
= OUTPUT_PACKET_ID
;
1053 Status
= CreateStatusQtd (
1058 if (EFI_ERROR (Status
)) {
1059 Status
= EFI_OUT_OF_RESOURCES
;
1064 // Link setup Qtd -> data Qtds -> status Qtd
1066 if (FirstDataQtdPtr
!= NULL
) {
1067 LinkQtdToQtd (SetupQtdPtr
, FirstDataQtdPtr
);
1068 LinkQtdToQtd (LastDataQtdPtr
, StatusQtdPtr
);
1070 LinkQtdToQtd (SetupQtdPtr
, StatusQtdPtr
);
1073 *ControlQtdsHead
= SetupQtdPtr
;
1078 DestoryQtds (HcDev
, FirstDataQtdPtr
);
1080 DestoryQtds (HcDev
, SetupQtdPtr
);
1086 CreateBulkOrInterruptQtds (
1087 IN USB2_HC_DEV
*HcDev
,
1089 IN UINT8
*DataCursor
,
1091 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1092 OUT EHCI_QTD_ENTITY
**QtdsHead
1096 Routine Description:
1098 Create Qtds list for Bulk or Interrupt Transfer
1103 PktId - Packet Identification of Qtds
1104 DataCursor - A pointer to user data buffer to transfer
1105 DataLen - Length of user data to transfer
1106 DataToggle - Data Toggle to start
1107 Translator - Translator Transaction for SplitX
1108 QtdsHead - A pointer of pointer to first Qtd for control tranfer for return
1113 EFI_OUT_OF_RESOURCES Cannot allocate resources
1118 EHCI_QTD_ENTITY
*QtdPtr
;
1119 EHCI_QTD_ENTITY
*PreQtdPtr
;
1120 EHCI_QTD_ENTITY
*FirstQtdPtr
;
1121 EHCI_QTD_ENTITY
*AltQtdPtr
;
1123 UINTN CapacityOfQtd
;
1126 Status
= EFI_SUCCESS
;
1133 DataCount
= DataLen
;
1134 while (DataCount
> 0) {
1136 CapacityOfQtd
= GetCapacityOfQtd (DataCursor
);
1137 SizePerQtd
= DataCount
;
1138 if (DataCount
> CapacityOfQtd
) {
1139 SizePerQtd
= CapacityOfQtd
;
1142 Status
= CreateDataQtd (
1150 if (EFI_ERROR (Status
)) {
1151 Status
= EFI_OUT_OF_RESOURCES
;
1152 if (NULL
== FirstQtdPtr
) {
1159 if (NULL
== FirstQtdPtr
) {
1160 FirstQtdPtr
= QtdPtr
;
1162 LinkQtdToQtd (PreQtdPtr
, QtdPtr
);
1166 DataCursor
+= SizePerQtd
;
1167 DataCount
-= SizePerQtd
;
1171 // Set Alternate Qtd
1173 if (INPUT_PACKET_ID
== PktId
&& 1 < GetNumberOfQtd (FirstQtdPtr
)) {
1174 Status
= CreateAltQtd (
1179 if (EFI_ERROR (Status
)) {
1180 Status
= EFI_OUT_OF_RESOURCES
;
1184 LinkQtdsToAltQtd (FirstQtdPtr
, AltQtdPtr
);
1187 *QtdsHead
= FirstQtdPtr
;
1191 DestoryQtds (HcDev
, FirstQtdPtr
);
1198 IN USB2_HC_DEV
*HcDev
,
1199 IN EHCI_QTD_ENTITY
*FirstQtdPtr
1203 Routine Description:
1205 Destory all Qtds in the list
1210 FirstQtdPtr - A pointer to first Qtd in the list
1218 EHCI_QTD_ENTITY
*PrevQtd
;
1219 EHCI_QTD_ENTITY
*NextQtd
;
1225 PrevQtd
= FirstQtdPtr
;
1228 // Delete all the Qtds.
1231 NextQtd
= PrevQtd
->Next
;
1232 EhciFreePool (HcDev
, (UINT8
*) PrevQtd
, sizeof (EHCI_QTD_ENTITY
));
1234 } while (NULL
!= PrevQtd
);
1242 IN EHCI_QTD_ENTITY
*FirstQtdPtr
1246 Routine Description:
1248 Number of Qtds in the list
1252 FirstQtdPtr - A pointer to first Qtd in the list
1256 Number of Qtds in the list
1261 EHCI_QTD_ENTITY
*QtdPtr
;
1263 QtdPtr
= FirstQtdPtr
;
1267 while (NULL
!= QtdPtr
) {
1269 QtdPtr
= QtdPtr
->Next
;
1276 GetNumberOfTransaction (
1277 IN UINTN SizeOfData
,
1278 IN UINTN SizeOfTransaction
1282 Routine Description:
1284 Number of Transactions in one Qtd
1288 SizeOfData - Size of one Qtd
1289 SizeOfTransaction - Size of one Transaction
1293 Number of Transactions in this Qtd
1298 return ((SizeOfData
& (SizeOfTransaction
- 1)) ? SizeOfData
/ SizeOfTransaction
+ 1 : SizeOfData
/ SizeOfTransaction
);
1304 IN UINT8
*BufferCursor
1308 Routine Description:
1310 Get Size of First Qtd
1314 BufferCursor - BufferCursor of the Qtd
1323 return (EHCI_MAX_QTD_CAPACITY
- (EHCI_BLOCK_SIZE
* GetNumberOfTransaction (EFI_PAGE_MASK
& GET_0B_TO_31B (BufferCursor
), EHCI_BLOCK_SIZE
)));
1328 GetApproxiOfInterval (
1333 Routine Description:
1335 Get the approximate value in the 2 index sequence
1339 Interval - the value of interval
1343 approximate value of interval in the 2 index sequence
1350 Orignate
= Interval
;
1353 while (Orignate
!= 1 && Orignate
!= 0) {
1354 Orignate
= Orignate
>> 1;
1355 Approxi
= Approxi
<< 1;
1358 if (Interval
& (Approxi
>> 1)) {
1359 Approxi
= Approxi
<< 1;
1366 GetQtdAlternateNextPointer (
1367 IN EHCI_QTD_HW
*HwQtdPtr
1371 Routine Description:
1373 Get Qtd alternate next pointer field
1377 HwQtdPtr - A pointer to hardware Qtd structure
1381 A pointer to hardware alternate Qtd
1389 if (!HwQtdPtr
->AltNextQtdTerminate
) {
1390 Value
= (EHCI_QTD_HW
*) GET_0B_TO_31B (HwQtdPtr
->AltNextQtdPointer
<< 5);
1398 IN EHCI_QTD_HW
*HwQtdPtr
1402 Routine Description:
1404 Get Qtd next pointer field
1408 HwQtdPtr - A pointer to hardware Qtd structure
1412 A pointer to next hardware Qtd structure
1420 if (!HwQtdPtr
->NextQtdTerminate
) {
1421 Value
= (EHCI_QTD_HW
*) GET_0B_TO_31B (HwQtdPtr
->NextQtdPointer
<< 5);
1428 IN EHCI_QTD_ENTITY
* PreQtdPtr
,
1429 IN EHCI_QTD_ENTITY
* QtdPtr
1433 Routine Description:
1439 PreQtdPtr - A pointer to pre Qtd
1440 QtdPtr - A pointer to next Qtd
1448 EHCI_QTD_HW
*QtdHwPtr
;
1456 PreQtdPtr
->Next
= QtdPtr
;
1457 QtdPtr
->Prev
= PreQtdPtr
;
1462 QtdHwPtr
= &(QtdPtr
->Qtd
);
1463 PreQtdPtr
->Qtd
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B(QtdHwPtr
) >> 5);
1464 PreQtdPtr
->Qtd
.NextQtdTerminate
= FALSE
;
1470 VOID
LinkQtdsToAltQtd (
1471 IN EHCI_QTD_ENTITY
* FirstQtdPtr
,
1472 IN EHCI_QTD_ENTITY
* AltQtdPtr
1476 Routine Description:
1478 Link AlterQtds together
1482 FirstQtdPtr - A pointer to first Qtd in the list
1483 AltQtdPtr - A pointer to alternative Qtd
1491 EHCI_QTD_ENTITY
*QtdPtr
;
1492 EHCI_QTD_HW
*AltQtdHwPtr
;
1494 ASSERT(FirstQtdPtr
);
1497 AltQtdHwPtr
= &(AltQtdPtr
->Qtd
);
1498 QtdPtr
= FirstQtdPtr
;
1500 while (NULL
!= QtdPtr
) {
1504 QtdPtr
->AltNext
= AltQtdPtr
;
1508 QtdPtr
->Qtd
.AltNextQtdPointer
= (UINT32
) (GET_0B_TO_31B(AltQtdHwPtr
) >> 5);
1509 QtdPtr
->Qtd
.AltNextQtdTerminate
= FALSE
;
1510 QtdPtr
= QtdPtr
->Next
;
1518 IN EHCI_QH_ENTITY
*QhPtr
,
1519 IN EHCI_QTD_ENTITY
*QtdPtr
1523 Routine Description:
1525 Link Qtds list to Qh
1529 QhPtr - A pointer to Qh
1530 QtdPtr - A pointer to first Qtd in the list
1538 EHCI_QTD_ENTITY
*Cursor
;
1539 EHCI_QTD_HW
*QtdHwPtr
;
1544 QhPtr
->FirstQtdPtr
= QtdPtr
;
1545 if (NULL
!= QtdPtr
->AltNext
) {
1546 QhPtr
->AltQtdPtr
= QtdPtr
->AltNext
;
1550 while (NULL
!= Cursor
) {
1551 Cursor
->SelfQh
= QhPtr
;
1552 if (NULL
== Cursor
->Next
) {
1553 QhPtr
->LastQtdPtr
= Cursor
;
1556 Cursor
= Cursor
->Next
;
1559 QtdHwPtr
= &(QtdPtr
->Qtd
);
1560 QhPtr
->Qh
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B (QtdHwPtr
) >> 5);
1561 QhPtr
->Qh
.NextQtdTerminate
= FALSE
;
1568 IN USB2_HC_DEV
*HcDev
,
1569 IN EHCI_QH_ENTITY
*QhPtr
1573 Routine Description:
1575 Link Qh to Async Schedule List
1580 QhPtr - A pointer to Qh
1585 EFI_DEVICE_ERROR Fail
1594 QhPtr
->Qh
.HeadReclamationFlag
= TRUE
;
1596 Status
= SetAsyncListAddr (HcDev
, QhPtr
);
1597 if (EFI_ERROR (Status
)) {
1598 Status
= EFI_DEVICE_ERROR
;
1602 if (!IsAsyncScheduleEnabled (HcDev
)) {
1604 Status
= EnableAsynchronousSchedule (HcDev
);
1605 if (EFI_ERROR (Status
)) {
1606 Status
= EFI_DEVICE_ERROR
;
1610 Status
= WaitForAsyncScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
1611 if (EFI_ERROR (Status
)) {
1612 DEBUG ((gEHCDebugLevel
, "WaitForAsyncScheduleEnable TimeOut"));
1613 Status
= EFI_TIMEOUT
;
1617 if (IsEhcHalted (HcDev
)) {
1618 Status
= StartScheduleExecution (HcDev
);
1619 if (EFI_ERROR (Status
)) {
1620 Status
= EFI_DEVICE_ERROR
;
1631 UnlinkQhFromAsyncList (
1632 IN USB2_HC_DEV
*HcDev
,
1633 IN EHCI_QH_ENTITY
*QhPtr
1637 Routine Description:
1639 Unlink Qh from Async Schedule List
1644 QhPtr - A pointer to Qh
1649 EFI_DEVICE_ERROR Fail
1655 Status
= EFI_SUCCESS
;
1660 if (QhPtr
== QhPtr
->Next
) {
1662 Status
= DisableAsynchronousSchedule (HcDev
);
1663 if (EFI_ERROR (Status
)) {
1664 Status
= EFI_DEVICE_ERROR
;
1668 Status
= WaitForAsyncScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
1669 if (EFI_ERROR (Status
)) {
1670 DEBUG ((gEHCErrorLevel
, "WaitForAsyncScheduleDisable TimeOut\n"));
1671 Status
= EFI_TIMEOUT
;
1682 LinkQhToPeriodicList (
1683 IN USB2_HC_DEV
*HcDev
,
1684 IN EHCI_QH_ENTITY
*QhPtr
1688 Routine Description:
1690 Link Qh to Periodic Schedule List
1695 QhPtr - A pointer to Qh
1703 FRAME_LIST_ENTRY
*FrameEntryPtr
;
1704 EHCI_QH_ENTITY
*FindQhPtr
;
1705 EHCI_QH_HW
*FindQhHwPtr
;
1714 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
1716 QhPtr
->Qh
.HeadReclamationFlag
= FALSE
;
1718 if (QhPtr
->TransferType
== ASYNC_INTERRUPT_TRANSFER
) {
1721 // AsyncInterruptTransfer Qh
1725 // Link to Frame[0] List
1727 if (!FrameEntryPtr
->LinkTerminate
) {
1729 // Not Null FrameList
1731 FindQhHwPtr
= (EHCI_QH_HW
*) GET_0B_TO_31B (FrameEntryPtr
->LinkPointer
<< 5);
1732 FindQhPtr
= (EHCI_QH_ENTITY
*) GET_QH_ENTITY_ADDR (FindQhHwPtr
);
1734 // FindQh is Left/Right to Qh
1736 while ((NULL
!= FindQhPtr
->Next
) && (FindQhPtr
->Interval
> QhPtr
->Interval
)) {
1737 FindQhPtr
= FindQhPtr
->Next
;
1740 if (FindQhPtr
->Interval
== QhPtr
->Interval
) {
1742 // Link Qh after FindQh
1744 if (NULL
!= FindQhPtr
->Next
) {
1745 FindQhPtr
->Next
->Prev
= QhPtr
;
1746 QhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(FindQhPtr
->Next
->Qh
) >> 5);
1747 QhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1748 QhPtr
->Qh
.QhTerminate
= FALSE
;
1751 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1752 FindQhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1753 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
1755 QhPtr
->Prev
= FindQhPtr
;
1756 QhPtr
->Next
= FindQhPtr
->Next
;
1757 FindQhPtr
->Next
= QhPtr
;
1758 } else if (FindQhPtr
->Interval
< QhPtr
->Interval
) {
1760 // Link Qh before FindQh
1762 if (NULL
== FindQhPtr
->Prev
) {
1764 // Qh is the First one in Frame[0] List
1766 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1767 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1768 FrameEntryPtr
->LinkTerminate
= FALSE
;
1771 // Qh is not the First one in Frame[0] List
1773 FindQhPtr
->Prev
->Next
= QhPtr
;
1774 FindQhPtr
->Prev
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1775 FindQhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
1776 FindQhPtr
->Prev
->Qh
.QhTerminate
= FALSE
;
1779 QhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(FindQhPtr
->Qh
) >> 5);
1780 QhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1781 QhPtr
->Qh
.QhTerminate
= FALSE
;
1783 QhPtr
->Next
= FindQhPtr
;
1784 QhPtr
->Prev
= FindQhPtr
->Prev
;
1785 FindQhPtr
->Prev
= QhPtr
;
1788 // Link Qh after FindQh, Qh is the Last one
1790 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1791 FindQhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
1792 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
1794 QhPtr
->Prev
= FindQhPtr
;
1796 FindQhPtr
->Next
= QhPtr
;
1802 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1803 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1804 FrameEntryPtr
->LinkTerminate
= FALSE
;
1809 if (NULL
== QhPtr
->Prev
) {
1811 // Qh is the First one in Frame[0] List
1813 FrameIndex
+= QhPtr
->Interval
;
1814 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1815 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) (FrameEntryPtr
+ QhPtr
->Interval
);
1816 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1817 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1818 FrameEntryPtr
->LinkTerminate
= FALSE
;
1819 FrameIndex
+= QhPtr
->Interval
;
1821 } else if (QhPtr
->Interval
< QhPtr
->Prev
->Interval
) {
1823 // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
1825 FrameIndex
+= QhPtr
->Interval
;
1826 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1827 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) (FrameEntryPtr
+ QhPtr
->Interval
);
1828 if ((FrameIndex
% QhPtr
->Prev
->Interval
) != 0) {
1829 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1830 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1831 FrameEntryPtr
->LinkTerminate
= FALSE
;
1834 FrameIndex
+= QhPtr
->Interval
;
1840 // SyncInterruptTransfer Qh
1843 if (!FrameEntryPtr
->LinkTerminate
) {
1845 // Not Null FrameList
1847 FindQhHwPtr
= (EHCI_QH_HW
*) GET_0B_TO_31B (FrameEntryPtr
->LinkPointer
<< 5);
1848 FindQhPtr
= (EHCI_QH_ENTITY
*) GET_QH_ENTITY_ADDR (FindQhHwPtr
);
1850 // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
1852 while (NULL
!= FindQhPtr
->Next
) {
1853 FindQhPtr
= FindQhPtr
->Next
;
1856 FindQhPtr
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1857 FindQhPtr
->Qh
.SelectType
= QH_SELECT_TYPE
;
1858 FindQhPtr
->Qh
.QhTerminate
= FALSE
;
1860 FindQhPtr
->Next
= QhPtr
;
1861 QhPtr
->Prev
= FindQhPtr
;
1866 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Qh
) >> 5);
1867 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1868 FrameEntryPtr
->LinkTerminate
= FALSE
;
1876 UnlinkQhFromPeriodicList (
1877 IN USB2_HC_DEV
*HcDev
,
1878 IN EHCI_QH_ENTITY
*QhPtr
,
1883 Routine Description:
1885 Unlink Qh from Periodic Schedule List
1890 QhPtr - A pointer to Qh
1891 Interval - Interval of this periodic transfer
1899 FRAME_LIST_ENTRY
*FrameEntryPtr
;
1908 FrameEntryPtr
= (FRAME_LIST_ENTRY
*) HcDev
->PeriodicFrameListBuffer
;
1910 if (QhPtr
->TransferType
== ASYNC_INTERRUPT_TRANSFER
) {
1913 // AsyncInterruptTransfer Qh
1916 if (NULL
== QhPtr
->Prev
) {
1918 // Qh is the First one on Frame[0] List
1920 if (NULL
== QhPtr
->Next
) {
1922 // Only one on Frame[0] List
1924 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1925 FrameEntryPtr
->LinkPointer
= 0;
1926 FrameEntryPtr
->SelectType
= 0;
1927 FrameEntryPtr
->LinkTerminate
= TRUE
;
1928 FrameEntryPtr
+= Interval
;
1929 FrameIndex
+= Interval
;
1932 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1933 FrameEntryPtr
->LinkPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Next
->Qh
) >> 5);
1934 FrameEntryPtr
->SelectType
= QH_SELECT_TYPE
;
1935 FrameEntryPtr
->LinkTerminate
= FALSE
;
1936 FrameEntryPtr
+= Interval
;
1937 FrameIndex
+= Interval
;
1943 // Not First one on Frame[0] List
1945 if (NULL
== QhPtr
->Next
) {
1947 // Qh is the Last one on Frame[0] List
1949 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= 0;
1950 QhPtr
->Prev
->Qh
.SelectType
= 0;
1951 QhPtr
->Prev
->Qh
.QhTerminate
= TRUE
;
1953 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= (UINT32
) GET_0B_TO_31B (&(QhPtr
->Next
->Qh
) >> 5);
1954 QhPtr
->Prev
->Qh
.SelectType
= QH_SELECT_TYPE
;
1955 QhPtr
->Prev
->Qh
.QhTerminate
= FALSE
;
1958 if (Interval
== QhPtr
->Prev
->Interval
) {
1960 // Interval is the same as Prev
1961 // Not involed Frame[X]
1967 while (FrameIndex
< HcDev
->PeriodicFrameListLength
) {
1968 if ((FrameIndex
% QhPtr
->Prev
->Interval
) != 0) {
1969 FrameEntryPtr
->LinkPointer
= QhPtr
->Prev
->Qh
.QhHorizontalPointer
;
1970 FrameEntryPtr
->SelectType
= QhPtr
->Prev
->Qh
.SelectType
;
1971 FrameEntryPtr
->LinkTerminate
= QhPtr
->Prev
->Qh
.QhTerminate
;
1973 FrameEntryPtr
+= Interval
;
1974 FrameIndex
+= Interval
;
1979 if (NULL
!= QhPtr
->Next
) {
1980 QhPtr
->Next
->Prev
= QhPtr
->Prev
;
1983 if (NULL
!= QhPtr
->Prev
) {
1984 QhPtr
->Prev
->Next
= QhPtr
->Next
;
1988 // SyncInterruptTransfer Qh
1990 if (NULL
== QhPtr
->Prev
) {
1992 // Qh is the only one Qh on Frame[0] List
1994 FrameEntryPtr
->LinkPointer
= 0;
1995 FrameEntryPtr
->SelectType
= 0;
1996 FrameEntryPtr
->LinkTerminate
= TRUE
;
1998 QhPtr
->Prev
->Qh
.QhHorizontalPointer
= 0;
1999 QhPtr
->Prev
->Qh
.SelectType
= 0;
2000 QhPtr
->Prev
->Qh
.QhTerminate
= TRUE
;
2003 if (NULL
!= QhPtr
->Prev
) {
2004 QhPtr
->Prev
->Next
= NULL
;
2012 LinkToAsyncReqeust (
2013 IN USB2_HC_DEV
*HcDev
,
2014 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
2018 Routine Description:
2020 Llink AsyncRequest Entry to Async Request List
2025 AsyncRequestPtr - A pointer to Async Request Entry
2033 EHCI_ASYNC_REQUEST
*CurrentPtr
;
2035 CurrentPtr
= HcDev
->AsyncRequestList
;
2036 HcDev
->AsyncRequestList
= AsyncRequestPtr
;
2037 AsyncRequestPtr
->Prev
= NULL
;
2038 AsyncRequestPtr
->Next
= CurrentPtr
;
2040 if (NULL
!= CurrentPtr
) {
2041 CurrentPtr
->Prev
= AsyncRequestPtr
;
2048 UnlinkFromAsyncReqeust (
2049 IN USB2_HC_DEV
*HcDev
,
2050 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
2054 Routine Description:
2056 Unlink AsyncRequest Entry from Async Request List
2061 AsyncRequestPtr - A pointer to Async Request Entry
2069 if (NULL
== AsyncRequestPtr
->Prev
) {
2070 HcDev
->AsyncRequestList
= AsyncRequestPtr
->Next
;
2071 if (NULL
!= AsyncRequestPtr
->Next
) {
2072 AsyncRequestPtr
->Next
->Prev
= NULL
;
2075 AsyncRequestPtr
->Prev
->Next
= AsyncRequestPtr
->Next
;
2076 if (NULL
!= AsyncRequestPtr
->Next
) {
2077 AsyncRequestPtr
->Next
->Prev
= AsyncRequestPtr
->Prev
;
2085 SetQtdBufferPointer (
2086 IN EHCI_QTD_HW
*QtdHwPtr
,
2092 Routine Description:
2094 Set data buffer pointers in Qtd
2098 QtdHwPtr - A pointer to Qtd hardware structure
2099 DataPtr - A pointer to user data buffer
2100 DataLen - Length of the user data buffer
2110 RemainLen
= DataLen
;
2114 // Allow buffer address range across 4G.
2115 // But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow
2116 // seperate buffer array.
2120 // Set BufferPointer0, ExtBufferPointer0 and Offset
2122 QtdHwPtr
->BufferPointer0
= (UINT32
) (GET_0B_TO_31B (DataPtr
) >> 12);
2123 QtdHwPtr
->CurrentOffset
= (UINT32
) (GET_0B_TO_31B (DataPtr
) & EFI_PAGE_MASK
);
2124 QtdHwPtr
->ExtBufferPointer0
= (UINT32
) GET_32B_TO_63B (DataPtr
);
2127 // Set BufferPointer1 and ExtBufferPointer1
2129 RemainLen
= RemainLen
> (EFI_PAGE_SIZE
- QtdHwPtr
->CurrentOffset
) ? (RemainLen
- (EFI_PAGE_SIZE
- QtdHwPtr
->CurrentOffset
)) : 0;
2130 if (RemainLen
== 0) {
2134 QtdHwPtr
->BufferPointer1
= QtdHwPtr
->BufferPointer0
+ 1;
2135 QtdHwPtr
->ExtBufferPointer1
= (QtdHwPtr
->BufferPointer1
== 0) ? (QtdHwPtr
->ExtBufferPointer0
+ 1) : QtdHwPtr
->ExtBufferPointer0
;
2138 // Set BufferPointer2 and ExtBufferPointer2
2140 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2141 if (RemainLen
== 0) {
2145 QtdHwPtr
->BufferPointer2
= QtdHwPtr
->BufferPointer1
+ 1;
2146 QtdHwPtr
->ExtBufferPointer2
= (QtdHwPtr
->BufferPointer2
== 0) ? (QtdHwPtr
->ExtBufferPointer1
+ 1) : QtdHwPtr
->ExtBufferPointer1
;
2149 // Set BufferPointer3 and ExtBufferPointer3
2151 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2152 if (RemainLen
== 0) {
2156 QtdHwPtr
->BufferPointer3
= QtdHwPtr
->BufferPointer2
+ 1;
2157 QtdHwPtr
->ExtBufferPointer3
= (QtdHwPtr
->BufferPointer2
== 0) ? (QtdHwPtr
->ExtBufferPointer2
+ 1) : QtdHwPtr
->ExtBufferPointer2
;
2160 // Set BufferPointer4 and ExtBufferPointer4
2162 RemainLen
= RemainLen
> EFI_PAGE_SIZE
? (RemainLen
- EFI_PAGE_SIZE
) : 0;
2163 if (RemainLen
== 0) {
2167 QtdHwPtr
->BufferPointer4
= QtdHwPtr
->BufferPointer3
+ 1;
2168 QtdHwPtr
->ExtBufferPointer4
= (QtdHwPtr
->BufferPointer3
== 0) ? (QtdHwPtr
->ExtBufferPointer3
+ 1) : QtdHwPtr
->ExtBufferPointer3
;
2176 IN EHCI_QTD_HW
*HwQtdPtr
2180 Routine Description:
2182 Whether Qtd status is active or not
2186 HwQtdPtr - A pointer to hardware Qtd structure
2198 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2199 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_ACTIVE
);
2206 IN EHCI_QTD_HW
*HwQtdPtr
2210 Routine Description:
2212 Whether Qtd status is halted or not
2216 HwQtdPtr - A pointer to hardware Qtd structure
2228 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2229 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_HALTED
);
2235 IsQtdStatusBufferError (
2236 IN EHCI_QTD_HW
*HwQtdPtr
2240 Routine Description:
2242 Whether Qtd status is buffer error or not
2246 HwQtdPtr - A pointer to hardware Qtd structure
2251 FALSE No buffer error
2258 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2259 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_BUFFER_ERR
);
2265 IsQtdStatusBabbleError (
2266 IN EHCI_QTD_HW
*HwQtdPtr
2270 Routine Description:
2272 Whether Qtd status is babble error or not
2276 HwQtdPtr - A pointer to hardware Qtd structure
2281 FALSE No babble error
2288 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2289 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_BABBLE_ERR
);
2295 IsQtdStatusTransactionError (
2296 IN EHCI_QTD_HW
*HwQtdPtr
2300 Routine Description:
2302 Whether Qtd status is transaction error or not
2306 HwQtdPtr - A pointer to hardware Qtd structure
2310 TRUE Transaction error
2311 FALSE No transaction error
2318 QtdStatus
= (UINT8
) (HwQtdPtr
->Status
);
2319 Value
= (BOOLEAN
) (QtdStatus
& QTD_STATUS_TRANSACTION_ERR
);
2326 IN UINT8 EndPointAddress
2330 Routine Description:
2332 Whether is a DataIn direction transfer
2336 EndPointAddress - address of the endpoint
2347 if (EndPointAddress
& 0x80) {
2358 IN USB2_HC_DEV
*HcDev
,
2359 IN EFI_USB_DATA_DIRECTION TransferDirection
,
2361 IN OUT UINTN
*DataLength
,
2363 OUT UINT8
**DataCursor
,
2368 Routine Description:
2370 Map address of user data buffer
2375 TransferDirection - direction of transfer
2376 Data - A pointer to user data buffer
2377 DataLength - length of user data
2378 PktId - Packte Identificaion
2379 DataCursor - mapped address to return
2380 DataMap - identificaion of this mapping to return
2385 EFI_DEVICE_ERROR Fail
2390 EFI_PHYSICAL_ADDRESS TempPhysicalAddr
;
2392 Status
= EFI_SUCCESS
;
2394 switch (TransferDirection
) {
2398 *PktId
= INPUT_PACKET_ID
;
2400 // BusMasterWrite means cpu read
2402 Status
= HcDev
->PciIo
->Map (
2404 EfiPciIoOperationBusMasterWrite
,
2410 if (EFI_ERROR (Status
)) {
2411 DEBUG ((gEHCDebugLevel
, "MapDataBuffer Failed\n"));
2412 Status
= EFI_DEVICE_ERROR
;
2416 *DataCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2421 *PktId
= OUTPUT_PACKET_ID
;
2423 // BusMasterRead means cpu write
2425 Status
= HcDev
->PciIo
->Map (
2427 EfiPciIoOperationBusMasterRead
,
2433 if (EFI_ERROR (Status
)) {
2434 Status
= EFI_DEVICE_ERROR
;
2438 *DataCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2443 *PktId
= OUTPUT_PACKET_ID
;
2452 Status
= EFI_INVALID_PARAMETER
;
2461 IN USB2_HC_DEV
*HcDev
,
2462 IN OUT VOID
*Request
,
2463 OUT UINT8
**RequestCursor
,
2464 OUT VOID
**RequestMap
2468 Routine Description:
2470 Map address of request structure buffer
2475 Request - A pointer to request structure
2476 RequestCursor - Mapped address of request structure to return
2477 RequestMap - Identificaion of this mapping to return
2482 EFI_DEVICE_ERROR Fail
2488 EFI_PHYSICAL_ADDRESS TempPhysicalAddr
;
2490 RequestLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
2491 Status
= HcDev
->PciIo
->Map (
2493 EfiPciIoOperationBusMasterRead
,
2495 (UINTN
*) &RequestLen
,
2499 if (EFI_ERROR (Status
)) {
2500 Status
= EFI_DEVICE_ERROR
;
2504 *RequestCursor
= (UINT8
*) ((UINTN
) TempPhysicalAddr
);
2511 DeleteAsyncRequestTransfer (
2512 IN USB2_HC_DEV
*HcDev
,
2513 IN UINT8 DeviceAddress
,
2514 IN UINT8 EndPointAddress
,
2515 OUT UINT8
*DataToggle
2519 Routine Description:
2521 Delete all asynchronous request transfer
2526 DeviceAddress - address of usb device
2527 EndPointAddress - address of endpoint
2528 DataToggle - stored data toggle
2533 EFI_DEVICE_ERROR Fail
2538 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2539 EHCI_ASYNC_REQUEST
*MatchPtr
;
2540 EHCI_QH_HW
*QhHwPtr
;
2543 if (NULL
== HcDev
->AsyncRequestList
) {
2544 Status
= EFI_INVALID_PARAMETER
;
2550 EndPointNum
= EndPointAddress
& 0x0f;
2551 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
2554 // Find QH of AsyncRequest by DeviceAddress and EndPointNum
2558 QhHwPtr
= &(AsyncRequestPtr
->QhPtr
->Qh
);
2559 if (QhHwPtr
->DeviceAddr
== DeviceAddress
&& QhHwPtr
->EndpointNum
== EndPointNum
) {
2560 MatchPtr
= AsyncRequestPtr
;
2564 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
2566 } while (NULL
!= AsyncRequestPtr
);
2568 if (NULL
== MatchPtr
) {
2569 Status
= EFI_INVALID_PARAMETER
;
2573 Status
= DisablePeriodicSchedule (HcDev
);
2574 if (EFI_ERROR (Status
)) {
2575 Status
= EFI_DEVICE_ERROR
;
2579 Status
= WaitForPeriodicScheduleDisable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2580 if (EFI_ERROR (Status
)) {
2581 DEBUG ((gEHCErrorLevel
, "WaitForPeriodicScheduleDisable TimeOut\n"));
2582 Status
= EFI_TIMEOUT
;
2586 *DataToggle
= (UINT8
) MatchPtr
->QhPtr
->Qh
.DataToggle
;
2587 UnlinkQhFromPeriodicList (HcDev
, MatchPtr
->QhPtr
, MatchPtr
->QhPtr
->Interval
);
2588 UnlinkFromAsyncReqeust (HcDev
, MatchPtr
);
2590 if (NULL
== HcDev
->AsyncRequestList
) {
2592 Status
= StopPollingTimer (HcDev
);
2593 if (EFI_ERROR (Status
)) {
2594 Status
= EFI_DEVICE_ERROR
;
2600 Status
= EnablePeriodicSchedule (HcDev
);
2601 if (EFI_ERROR (Status
)) {
2602 Status
= EFI_DEVICE_ERROR
;
2606 Status
= WaitForPeriodicScheduleEnable (HcDev
, EHCI_GENERIC_TIMEOUT
);
2607 if (EFI_ERROR (Status
)) {
2608 DEBUG ((gEHCErrorLevel
, "WaitForPeriodicScheduleEnable TimeOut\n"));
2609 Status
= EFI_TIMEOUT
;
2613 if (IsEhcHalted (HcDev
)) {
2614 Status
= StartScheduleExecution (HcDev
);
2615 if (EFI_ERROR (Status
)) {
2616 Status
= EFI_DEVICE_ERROR
;
2623 DestoryQtds (HcDev
, MatchPtr
->QhPtr
->FirstQtdPtr
);
2624 DestoryQh (HcDev
, MatchPtr
->QhPtr
);
2625 EhciFreePool (HcDev
, (UINT8
*) MatchPtr
, sizeof (EHCI_ASYNC_REQUEST
));
2632 CleanUpAllAsyncRequestTransfer (
2633 IN USB2_HC_DEV
*HcDev
2637 Routine Description:
2639 Clean up all asynchronous request transfer
2651 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2652 EHCI_ASYNC_REQUEST
*FreePtr
;
2654 AsyncRequestPtr
= NULL
;
2657 StopPollingTimer (HcDev
);
2659 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
2660 while (NULL
!= AsyncRequestPtr
) {
2662 FreePtr
= AsyncRequestPtr
;
2663 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
2664 UnlinkFromAsyncReqeust (HcDev
, FreePtr
);
2665 UnlinkQhFromPeriodicList (HcDev
, FreePtr
->QhPtr
, FreePtr
->QhPtr
->Interval
);
2666 DestoryQtds (HcDev
, FreePtr
->QhPtr
->FirstQtdPtr
);
2667 DestoryQh (HcDev
, FreePtr
->QhPtr
);
2668 EhciFreePool (HcDev
, (UINT8
*) FreePtr
, sizeof (EHCI_ASYNC_REQUEST
));
2677 IN EHCI_QH_ENTITY
*QhPtr
2681 Routine Description:
2683 Zero out the fields in Qh structure
2687 QhPtr - A pointer to Qh structure
2695 QhPtr
->Qh
.CurrentQtdPointer
= 0;
2696 QhPtr
->Qh
.AltNextQtdPointer
= 0;
2697 QhPtr
->Qh
.NakCount
= 0;
2698 QhPtr
->Qh
.AltNextQtdTerminate
= 0;
2699 QhPtr
->Qh
.TotalBytes
= 0;
2700 QhPtr
->Qh
.InterruptOnComplete
= 0;
2701 QhPtr
->Qh
.CurrentPage
= 0;
2702 QhPtr
->Qh
.ErrorCount
= 0;
2703 QhPtr
->Qh
.PidCode
= 0;
2704 QhPtr
->Qh
.Status
= 0;
2705 QhPtr
->Qh
.BufferPointer0
= 0;
2706 QhPtr
->Qh
.CurrentOffset
= 0;
2707 QhPtr
->Qh
.BufferPointer1
= 0;
2708 QhPtr
->Qh
.CompleteSplitMask
= 0;
2709 QhPtr
->Qh
.BufferPointer2
= 0;
2710 QhPtr
->Qh
.SplitBytes
= 0;
2711 QhPtr
->Qh
.FrameTag
= 0;
2712 QhPtr
->Qh
.BufferPointer3
= 0;
2713 QhPtr
->Qh
.BufferPointer4
= 0;
2714 QhPtr
->Qh
.ExtBufferPointer0
= 0;
2715 QhPtr
->Qh
.ExtBufferPointer1
= 0;
2716 QhPtr
->Qh
.ExtBufferPointer2
= 0;
2717 QhPtr
->Qh
.ExtBufferPointer3
= 0;
2718 QhPtr
->Qh
.ExtBufferPointer4
= 0;
2722 UpdateAsyncRequestTransfer (
2723 IN EHCI_ASYNC_REQUEST
*AsyncRequestPtr
,
2724 IN UINT32 TransferResult
,
2729 Routine Description:
2731 Update asynchronous request transfer
2735 AsyncRequestPtr - A pointer to async request
2736 TransferResult - transfer result
2737 ErrQtdPos - postion of error Qtd
2745 EHCI_QTD_ENTITY
*QtdPtr
;
2749 if (EFI_USB_NOERROR
== TransferResult
) {
2752 // Update Qh for next trigger
2755 QtdPtr
= AsyncRequestPtr
->QhPtr
->FirstQtdPtr
;
2758 // Update fields in Qh
2762 // Get DataToggle from Overlay in Qh
2764 // ZeroOut Overlay in Qh except DataToggle, HostController will update this field
2766 ZeroOutQhOverlay (AsyncRequestPtr
->QhPtr
);
2767 AsyncRequestPtr
->QhPtr
->Qh
.NextQtdPointer
= (UINT32
) (GET_0B_TO_31B (&(QtdPtr
->Qtd
)) >> 5);
2768 AsyncRequestPtr
->QhPtr
->Qh
.NextQtdTerminate
= FALSE
;
2771 // Update fields in Qtd
2773 while (NULL
!= QtdPtr
) {
2774 QtdPtr
->Qtd
.TotalBytes
= QtdPtr
->StaticTotalBytes
;
2775 QtdPtr
->Qtd
.CurrentOffset
= QtdPtr
->StaticCurrentOffset
;
2776 QtdPtr
->Qtd
.CurrentPage
= 0;
2777 QtdPtr
->Qtd
.ErrorCount
= QTD_ERROR_COUNTER
;
2778 QtdPtr
->Qtd
.Status
= QTD_STATUS_ACTIVE
;
2780 QtdPtr
->TotalBytes
= QtdPtr
->StaticTotalBytes
;
2781 QtdPtr
= QtdPtr
->Next
;
2789 CheckQtdsTransferResult (
2790 IN BOOLEAN IsControl
,
2791 IN EHCI_QH_ENTITY
*QhPtr
,
2793 OUT UINTN
*ErrQtdPos
,
2794 OUT UINTN
*ActualLen
2798 Routine Description:
2800 Check transfer result of Qtds
2804 IsControl - Is control transfer or not
2805 QhPtr - A pointer to Qh
2806 Result - Transfer result
2807 ErrQtdPos - Error TD Position
2808 ActualLen - Actual Transfer Size
2817 UINTN ActualLenPerQtd
;
2818 EHCI_QTD_ENTITY
*QtdPtr
;
2819 EHCI_QTD_HW
*QtdHwPtr
;
2828 QtdPtr
= QhPtr
->FirstQtdPtr
;
2829 QtdHwPtr
= &(QtdPtr
->Qtd
);
2831 while (NULL
!= QtdHwPtr
) {
2833 if (IsQtdStatusActive (QtdHwPtr
)) {
2834 *Result
|= EFI_USB_ERR_NOTEXECUTE
;
2837 if (IsQtdStatusHalted (QtdHwPtr
)) {
2838 *Result
|= EFI_USB_ERR_STALL
;
2841 if (IsQtdStatusBufferError (QtdHwPtr
)) {
2842 *Result
|= EFI_USB_ERR_BUFFER
;
2845 if (IsQtdStatusBabbleError (QtdHwPtr
)) {
2846 *Result
|= EFI_USB_ERR_BABBLE
;
2849 if (IsQtdStatusTransactionError (QtdHwPtr
)) {
2850 *Result
|= EFI_USB_ERR_TIMEOUT
;
2853 ActualLenPerQtd
= QtdPtr
->TotalBytes
- QtdHwPtr
->TotalBytes
;
2854 QtdPtr
->TotalBytes
= QtdHwPtr
->TotalBytes
;
2856 // Accumulate actual transferred data length in each DataQtd.
2858 if (SETUP_PACKET_PID_CODE
!= QtdHwPtr
->PidCode
) {
2859 *ActualLen
+= ActualLenPerQtd
;
2867 if ((!IsControl
) && (QtdPtr
->TotalBytes
> 0)) {
2869 // Did something, but isn't full workload
2875 QtdPtr
= QtdPtr
->Next
;
2876 QtdHwPtr
= &(QtdPtr
->Qtd
);
2885 IN USB2_HC_DEV
*HcDev
,
2886 IN BOOLEAN IsControl
,
2887 IN EHCI_QH_ENTITY
*QhPtr
,
2888 IN OUT UINTN
*ActualLen
,
2889 OUT UINT8
*DataToggle
,
2891 OUT UINT32
*TransferResult
2895 Routine Description:
2897 Execute Bulk or SyncInterrupt Transfer
2902 IsControl - Is control transfer or not
2903 QhPtr - A pointer to Qh
2904 ActualLen - Actual transfered Len
2905 DataToggle - Data Toggle
2906 TimeOut - TimeOut threshold
2907 TransferResult - Transfer result
2912 EFI_DEVICE_ERROR Fail
2922 Status
= EFI_SUCCESS
;
2924 *TransferResult
= EFI_USB_NOERROR
;
2925 RequireLen
= *ActualLen
;
2929 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2932 *TransferResult
= 0;
2933 Finished
= CheckQtdsTransferResult (
2944 // Qtd is inactive, which means bulk or interrupt transfer's end.
2946 if (!(*TransferResult
& EFI_USB_ERR_NOTEXECUTE
)) {
2950 gBS
->Stall (EHCI_SYNC_REQUEST_POLLING_TIME
);
2954 if (EFI_USB_NOERROR
!= *TransferResult
) {
2956 Status
= EFI_TIMEOUT
;
2958 Status
= EFI_DEVICE_ERROR
;
2963 // Special for Bulk and Interrupt Transfer
2965 *DataToggle
= (UINT8
) QhPtr
->Qh
.DataToggle
;
2971 AsyncRequestMoniter (
2976 Routine Description:
2978 Interrupt transfer periodic check handler
2981 Event - Interrupt event
2982 Context - Pointer to USB2_HC_DEV
2987 EFI_DEVICE_ERROR Fail
2993 EHCI_ASYNC_REQUEST
*AsyncRequestPtr
;
2994 EHCI_QTD_HW
*QtdHwPtr
;
2997 UINT32 TransferResult
;
2998 UINT8
*ReceiveBuffer
;
2999 UINT8
*ProcessBuffer
;
3001 Status
= EFI_SUCCESS
;
3003 ReceiveBuffer
= NULL
;
3004 ProcessBuffer
= NULL
;
3005 HcDev
= (USB2_HC_DEV
*) Context
;
3006 AsyncRequestPtr
= HcDev
->AsyncRequestList
;
3008 while (NULL
!= AsyncRequestPtr
) {
3014 CheckQtdsTransferResult (
3016 AsyncRequestPtr
->QhPtr
,
3022 if ((TransferResult
& EFI_USB_ERR_NAK
) || (TransferResult
& EFI_USB_ERR_NOTEXECUTE
)) {
3023 AsyncRequestPtr
= AsyncRequestPtr
->Next
;
3027 // Allocate memory for EHC private data structure
3029 ProcessBuffer
= AllocateZeroPool (ActualLen
);
3030 if (NULL
== ProcessBuffer
) {
3031 Status
= EFI_OUT_OF_RESOURCES
;
3035 QtdHwPtr
= &(AsyncRequestPtr
->QhPtr
->FirstQtdPtr
->Qtd
);
3036 ReceiveBuffer
= (UINT8
*) GET_0B_TO_31B ((QtdHwPtr
->BufferPointer0
<< 12) | AsyncRequestPtr
->QhPtr
->FirstQtdPtr
->StaticCurrentOffset
);
3043 UpdateAsyncRequestTransfer (AsyncRequestPtr
, TransferResult
, ErrQtdPos
);
3045 if (EFI_USB_NOERROR
== TransferResult
) {
3047 if (AsyncRequestPtr
->CallBackFunc
!= NULL
) {
3048 (AsyncRequestPtr
->CallBackFunc
) (ProcessBuffer
, ActualLen
, AsyncRequestPtr
->Context
, TransferResult
);
3054 // leave error recovery to its related device driver. A common case of
3055 // the error recovery is to re-submit the interrupt transfer.
3056 // When an interrupt transfer is re-submitted, its position in the linked
3057 // list is changed. It is inserted to the head of the linked list, while
3058 // this function scans the whole list from head to tail. Thus, the
3059 // re-submitted interrupt transfer's callback function will not be called
3060 // again in this round.
3062 if (AsyncRequestPtr
->CallBackFunc
!= NULL
) {
3063 (AsyncRequestPtr
->CallBackFunc
) (NULL
, 0, AsyncRequestPtr
->Context
, TransferResult
);
3068 if (NULL
!= ProcessBuffer
) {
3069 gBS
->FreePool (ProcessBuffer
);
3072 AsyncRequestPtr
= AsyncRequestPtr
->Next
;