2 This file contains URB request, each request is warpped in a
3 URB (Usb Request Block).
5 Copyright (c) 2013-2015 Intel Corporation.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
20 @Param Ohc UHC private data
22 @retval TD structure pointer
27 IN USB_OHCI_HC_DEV
*Ohc
32 Td
= UsbHcAllocateMem(Ohc
->MemPool
, sizeof(TD_DESCRIPTOR
));
34 DEBUG ((EFI_D_INFO
, "STV allocate TD fail !\r\n"));
37 Td
->CurrBufferPointer
= 0;
39 Td
->BufferEndPointer
= 0;
40 Td
->NextTDPointer
= 0;
50 @Param Ohc UHC private data
51 @Param Td Pointer to a TD to free
53 @retval EFI_SUCCESS TD freed
58 IN USB_OHCI_HC_DEV
*Ohc
,
65 UsbHcFreeMem(Ohc
->MemPool
, Td
, sizeof(TD_DESCRIPTOR
));
75 @Param Ohc Device private data
77 @retval ED descriptor pointer
86 Ed
= UsbHcAllocateMem(Ohc
->MemPool
, sizeof (ED_DESCRIPTOR
));
88 DEBUG ((EFI_D_INFO
, "STV allocate ED fail !\r\n"));
92 Ed
->TdTailPointer
= 0;
93 Ed
->Word2
.TdHeadPointer
= 0;
103 @Param Ohc UHC private data
104 @Param Ed Pointer to a ED to free
106 @retval EFI_SUCCESS ED freed
112 IN USB_OHCI_HC_DEV
*Ohc
,
119 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
128 @Param Ohc Device private data
129 @Param Ed Pointer to a ED to free
131 @retval EFI_SUCCESS ED freed
135 OhciFreeAllTDFromED (
136 IN USB_OHCI_HC_DEV
*Ohc
,
140 TD_DESCRIPTOR
*HeadTd
;
141 TD_DESCRIPTOR
*TailTd
;
143 TD_DESCRIPTOR
*TempTd
;
149 HeadTd
= TD_PTR (Ed
->Word2
.TdHeadPointer
);
150 TailTd
= (TD_DESCRIPTOR
*)(UINTN
)(Ed
->TdTailPointer
);
153 while (Td
!= TailTd
) {
155 Td
= (TD_DESCRIPTOR
*)(UINTN
)(Td
->NextTDPointer
);
156 OhciFreeTD (Ohc
, TempTd
);
164 Find a working ED match the requirement
166 @Param EdHead Head of the ED list
167 @Param DeviceAddress Device address to search
168 @Param EndPointNum End point num to search
169 @Param EdDir ED Direction to search
171 @retval ED descriptor searched
177 IN ED_DESCRIPTOR
*EdHead
,
178 IN UINT8 DeviceAddress
,
179 IN UINT8 EndPointNum
,
185 for (Ed
= EdHead
; Ed
!= NULL
; Ed
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
)) {
186 if (Ed
->Word2
.Halted
== 0 && Ed
->Word0
.Skip
== 0 &&
187 Ed
->Word0
.FunctionAddress
== DeviceAddress
&& Ed
->Word0
.EndPointNum
== EndPointNum
&&
188 Ed
->Word0
.Direction
== EdDir
) {
199 Initialize interrupt list.
201 @Param Ohc Device private data
203 @retval EFI_SUCCESS Initialization done
207 OhciInitializeInterruptList (
211 static UINT32 Leaf
[32] = {0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17,
212 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31};
213 UINT32
*HccaInterruptTable
;
217 ED_DESCRIPTOR
*NewEd
;
219 HccaInterruptTable
= Ohc
->HccaMemoryBlock
->HccaInterruptTable
;
221 for (Index
= 0; Index
< 32; Index
++) {
222 NewEd
= OhciCreateED (Ohc
);
224 return EFI_OUT_OF_RESOURCES
;
226 HccaInterruptTable
[Index
] = (UINT32
)(UINTN
)NewEd
;
229 for (Index
= 0; Index
< 32; Index
++) {
230 Ohc
->IntervalList
[0][Index
] = (ED_DESCRIPTOR
*)(UINTN
)HccaInterruptTable
[Leaf
[Index
]];
234 for (Level
= 1; Level
<= 5; Level
++) {
237 for (Index
= 0; Index
< Count
; Index
++) {
238 Ohc
->IntervalList
[Level
][Index
] = OhciCreateED (Ohc
);
239 if (HccaInterruptTable
[Index
] == 0) {
240 return EFI_OUT_OF_RESOURCES
;
242 Ohc
->IntervalList
[Level
- 1][Index
* 2 ]->NextED
= (UINT32
)(UINTN
)Ohc
->IntervalList
[Level
][Index
];
243 Ohc
->IntervalList
[Level
- 1][Index
* 2 + 1]->NextED
= (UINT32
)(UINTN
)Ohc
->IntervalList
[Level
][Index
];
254 @Param Ed Ed to be attached
255 @Param NewEd Ed to attach
257 @retval EFI_SUCCESS NewEd attached to Ed
258 @retval EFI_INVALID_PARAMETER Ed is NULL
263 IN ED_DESCRIPTOR
*Ed
,
264 IN ED_DESCRIPTOR
*NewEd
270 return EFI_INVALID_PARAMETER
;
273 if (Ed
->NextED
== 0){
274 Ed
->NextED
= (UINT32
)(UINTN
)NewEd
;
276 Temp
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
277 Ed
->NextED
= (UINT32
)(UINTN
)NewEd
;
278 NewEd
->NextED
= (UINT32
)(UINTN
)Temp
;
287 Count ED number on a ED chain
289 @Param Ed Head of the ED chain
291 @retval ED number on the chain
305 Ed
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
314 Find the minimal burn ED list on a specific depth level
316 @Param Ohc Device private data
317 @Param Depth Depth level
319 @retval ED list found
324 OhciFindMinInterruptEDList (
325 IN USB_OHCI_HC_DEV
*Ohc
,
331 ED_DESCRIPTOR
*TempEd
;
332 ED_DESCRIPTOR
*HeadEd
;
339 MinEdNum
= 0xFFFFFFFF;
341 for (Index
= 0; Index
< (UINTN
)(32 >> Depth
); Index
++) {
342 HeadEd
= Ohc
->IntervalList
[Depth
][Index
];
343 EdNum
= CountEdNum (HeadEd
);
344 if (EdNum
< MinEdNum
) {
350 ASSERT (TempEd
!= NULL
);
358 Attach an ED to an ED list
360 @Param OHC UHC private data
361 @Param ListType Type of the ED list
362 @Param Ed ED to attach
363 @Param EdList ED list to be attached
365 @retval EFI_SUCCESS ED attached to ED list
370 IN USB_OHCI_HC_DEV
*Ohc
,
371 IN DESCRIPTOR_LIST_TYPE ListType
,
372 IN ED_DESCRIPTOR
*Ed
,
373 IN ED_DESCRIPTOR
*EdList
376 ED_DESCRIPTOR
*HeadEd
;
381 HeadEd
= (ED_DESCRIPTOR
*) OhciGetMemoryPointer (Ohc
, HC_CONTROL_HEAD
);
382 if (HeadEd
== NULL
) {
383 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, Ed
);
386 OhciAttachED (HeadEd
, Ed
);
391 HeadEd
= (ED_DESCRIPTOR
*) OhciGetMemoryPointer (Ohc
, HC_BULK_HEAD
);
392 if (HeadEd
== NULL
) {
393 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, Ed
);
396 OhciAttachED (HeadEd
, Ed
);
401 OhciAttachED (EdList
, Ed
);
413 Remove interrupt EDs that match requirement
415 @Param Ohc UHC private data
416 @Param IntEd The address of Interrupt endpoint
418 @retval EFI_SUCCESS EDs match requirement removed
423 OhciFreeInterruptEdByEd (
424 IN USB_OHCI_HC_DEV
*Ohc
,
425 IN ED_DESCRIPTOR
*IntEd
429 ED_DESCRIPTOR
*TempEd
;
435 for (Index
= 0; Index
< 32; Index
++) {
436 Ed
= (ED_DESCRIPTOR
*)(UINTN
)Ohc
->HccaMemoryBlock
->HccaInterruptTable
[Index
];
440 while (Ed
->NextED
!= 0) {
441 if (Ed
->NextED
== (UINT32
)(UINTN
)IntEd
) {
442 TempEd
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
443 Ed
->NextED
= TempEd
->NextED
;
444 OhciFreeED (Ohc
, TempEd
);
446 Ed
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
455 Remove interrupt EDs that match requirement
457 @Param Ohc UHC private data
458 @Param FunctionAddress Requirement on function address
459 @Param EndPointNum Requirement on end point number
461 @retval EFI_SUCCESS EDs match requirement removed
465 OhciFreeInterruptEdByAddr (
466 IN USB_OHCI_HC_DEV
*Ohc
,
467 IN UINT8 FunctionAddress
,
472 ED_DESCRIPTOR
*TempEd
;
475 for (Index
= 0; Index
< 32; Index
++) {
476 Ed
= (ED_DESCRIPTOR
*)(UINTN
)Ohc
->HccaMemoryBlock
->HccaInterruptTable
[Index
];
481 while (Ed
->NextED
!= 0) {
482 TempEd
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
483 if (TempEd
->Word0
.FunctionAddress
== FunctionAddress
&&
484 TempEd
->Word0
.EndPointNum
== EndPointNum
) {
485 Ed
->NextED
= TempEd
->NextED
;
486 OhciFreeED (Ohc
, TempEd
);
488 Ed
= (ED_DESCRIPTOR
*)(UINTN
)(Ed
->NextED
);
499 Link Td2 to the end of Td1
501 @Param Td1 TD to be linked
502 @Param Td2 TD to link
504 @retval EFI_SUCCESS TD successfully linked
505 @retval EFI_INVALID_PARAMETER Td1 is NULL
510 IN TD_DESCRIPTOR
*Td1
,
511 IN TD_DESCRIPTOR
*Td2
514 TD_DESCRIPTOR
*TempTd
;
517 return EFI_INVALID_PARAMETER
;
525 while (TempTd
->NextTD
!= 0) {
526 TempTd
= (TD_DESCRIPTOR
*)(UINTN
)(TempTd
->NextTD
);
529 TempTd
->NextTD
= (UINT32
)(UINTN
)Td2
;
530 TempTd
->NextTDPointer
= (UINT32
)(UINTN
)Td2
;
540 @Param Ed ED which TD list attach on
541 @Param HeadTd Head of the TD list to attach
543 @retval EFI_SUCCESS TD list attached on the ED
547 OhciAttachTDListToED (
548 IN ED_DESCRIPTOR
*Ed
,
549 IN TD_DESCRIPTOR
*HeadTd
552 TD_DESCRIPTOR
*TempTd
;
554 TempTd
= TD_PTR (Ed
->Word2
.TdHeadPointer
);
556 if (TempTd
!= NULL
) {
557 while (TempTd
->NextTD
!= 0) {
558 TempTd
= (TD_DESCRIPTOR
*)(UINTN
)(TempTd
->NextTD
);
560 TempTd
->NextTD
= (UINT32
)(UINTN
)HeadTd
;
561 TempTd
->NextTDPointer
= (UINT32
)(UINTN
)HeadTd
;
563 Ed
->Word2
.TdHeadPointer
= RIGHT_SHIFT_4 ((UINT32
)(UINTN
)HeadTd
);
572 Set value to ED specific field
574 @Param Ed ED to be set
575 @Param Field Field to be set
576 @Param Value Value to set
578 @retval EFI_SUCCESS Value set
583 IN ED_DESCRIPTOR
*Ed
,
588 if (Field
& ED_FUNC_ADD
) {
589 Ed
->Word0
.FunctionAddress
= Value
;
591 if (Field
& ED_ENDPT_NUM
) {
592 Ed
->Word0
.EndPointNum
= Value
;
594 if (Field
& ED_DIR
) {
595 Ed
->Word0
.Direction
= Value
;
597 if (Field
& ED_SPEED
) {
598 Ed
->Word0
.Speed
= Value
;
600 if (Field
& ED_SKIP
) {
601 Ed
->Word0
.Skip
= Value
;
603 if (Field
& ED_FORMAT
) {
604 Ed
->Word0
.Format
= Value
;
606 if (Field
& ED_MAX_PACKET
) {
607 Ed
->Word0
.MaxPacketSize
= Value
;
609 if (Field
& ED_PDATA
) {
610 Ed
->Word0
.FreeSpace
= Value
;
612 if (Field
& ED_ZERO
) {
613 Ed
->Word2
.Zero
= Value
;
615 if (Field
& ED_TDTAIL_PTR
) {
616 Ed
->TdTailPointer
= Value
;
619 if (Field
& ED_HALTED
) {
620 Ed
->Word2
.Halted
= Value
;
622 if (Field
& ED_DTTOGGLE
) {
623 Ed
->Word2
.ToggleCarry
= Value
;
625 if (Field
& ED_TDHEAD_PTR
) {
626 Ed
->Word2
.TdHeadPointer
= RIGHT_SHIFT_4 (Value
);
629 if (Field
& ED_NEXT_EDPTR
) {
638 Get value from an ED's specific field
641 @Param Field Field to get value from
643 @retval Value of the field
648 IN ED_DESCRIPTOR
*Ed
,
654 return Ed
->Word0
.FunctionAddress
;
657 return Ed
->Word0
.EndPointNum
;
660 return Ed
->Word0
.Direction
;
663 return Ed
->Word0
.Speed
;
666 return Ed
->Word0
.Skip
;
669 return Ed
->Word0
.Format
;
672 return Ed
->Word0
.MaxPacketSize
;
676 return Ed
->TdTailPointer
;
680 return Ed
->Word2
.Halted
;
684 return Ed
->Word2
.ToggleCarry
;
688 return Ed
->Word2
.TdHeadPointer
<< 4;
705 Set value to TD specific field
707 @Param Td TD to be set
708 @Param Field Field to be set
709 @Param Value Value to set
711 @retval EFI_SUCCESS Value set
716 IN TD_DESCRIPTOR
*Td
,
721 if (Field
& TD_PDATA
) {
722 Td
->Word0
.Reserved
= Value
;
724 if (Field
& TD_BUFFER_ROUND
) {
725 Td
->Word0
.BufferRounding
= Value
;
727 if (Field
& TD_DIR_PID
) {
728 Td
->Word0
.DirPID
= Value
;
730 if (Field
& TD_DELAY_INT
) {
731 Td
->Word0
.DelayInterrupt
= Value
;
733 if (Field
& TD_DT_TOGGLE
) {
734 Td
->Word0
.DataToggle
= Value
| 0x2;
736 if (Field
& TD_ERROR_CNT
) {
737 Td
->Word0
.ErrorCount
= Value
;
739 if (Field
& TD_COND_CODE
) {
740 Td
->Word0
.ConditionCode
= Value
;
743 if (Field
& TD_CURR_BUFFER_PTR
) {
744 Td
->CurrBufferPointer
= Value
;
748 if (Field
& TD_NEXT_PTR
) {
752 if (Field
& TD_BUFFER_END_PTR
) {
753 Td
->BufferEndPointer
= Value
;
762 Get value from ED specific field
765 @Param Field Field to get value from
767 @retval Value of the field
773 IN TD_DESCRIPTOR
*Td
,
778 case TD_BUFFER_ROUND
:
779 return Td
->Word0
.BufferRounding
;
782 return Td
->Word0
.DirPID
;
785 return Td
->Word0
.DelayInterrupt
;
788 return Td
->Word0
.DataToggle
;
791 return Td
->Word0
.ErrorCount
;
794 return Td
->Word0
.ConditionCode
;
796 case TD_CURR_BUFFER_PTR
:
797 return Td
->CurrBufferPointer
;
804 case TD_BUFFER_END_PTR
:
805 return Td
->BufferEndPointer
;
817 Free the Ed,Td,buffer that were created during transferring
819 @Param Ohc Device private data
823 OhciFreeDynamicIntMemory(
824 IN USB_OHCI_HC_DEV
*Ohc
827 INTERRUPT_CONTEXT_ENTRY
*Entry
;
829 while (Ohc
->InterruptContextList
!= NULL
) {
830 Entry
= Ohc
->InterruptContextList
;
831 Ohc
->InterruptContextList
= Ohc
->InterruptContextList
->NextEntry
;
832 OhciFreeInterruptEdByEd (Ohc
, Entry
->Ed
);
833 OhciFreeInterruptContextEntry (Ohc
, Entry
);
839 Free the Ed that were initilized during driver was starting,
840 those memory were used as interrupt ED head
842 @Param Ohc Device private data
847 OhciFreeFixedIntMemory (
848 IN USB_OHCI_HC_DEV
*Ohc
851 static UINT32 Leaf
[] = {32,16,8,4,2,1};
855 for (Level
= 0; Level
< 6; Level
++) {
856 for (Index
= 0; Index
< Leaf
[Level
]; Index
++) {
857 if (Ohc
->IntervalList
[Level
][Index
] != NULL
) {
858 UsbHcFreeMem(Ohc
->MemPool
, Ohc
->IntervalList
[Level
][Index
], sizeof(ED_DESCRIPTOR
));
865 Release all OHCI used memory when OHCI going to quit
867 @Param Ohc Device private data
869 @retval EFI_SUCCESS Memory released
874 OhciFreeIntTransferMemory (
875 IN USB_OHCI_HC_DEV
*Ohc
879 // Free the Ed,Td,buffer that were created during transferring
881 OhciFreeDynamicIntMemory (Ohc
);
883 // Free the Ed that were initilized during driver was starting
885 OhciFreeFixedIntMemory (Ohc
);