]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/OhciUrb.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Usb / Ohci / Dxe / OhciUrb.c
1 /** @file
2 This file contains URB request, each request is warpped in a
3 URB (Usb Request Block).
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11
12
13 #include "Ohci.h"
14
15
16 /**
17
18 Create a TD
19
20 @Param Ohc UHC private data
21
22 @retval TD structure pointer
23
24 **/
25 TD_DESCRIPTOR *
26 OhciCreateTD (
27 IN USB_OHCI_HC_DEV *Ohc
28 )
29 {
30 TD_DESCRIPTOR *Td;
31
32 Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR));
33 if (Td == NULL) {
34 DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n"));
35 return NULL;
36 }
37 Td->CurrBufferPointer = 0;
38 Td->NextTD = 0;
39 Td->BufferEndPointer = 0;
40 Td->NextTDPointer = 0;
41
42 return Td;
43 }
44
45
46 /**
47
48 Free a TD
49
50 @Param Ohc UHC private data
51 @Param Td Pointer to a TD to free
52
53 @retval EFI_SUCCESS TD freed
54
55 **/
56 EFI_STATUS
57 OhciFreeTD (
58 IN USB_OHCI_HC_DEV *Ohc,
59 IN TD_DESCRIPTOR *Td
60 )
61 {
62 if (Td == NULL) {
63 return EFI_SUCCESS;
64 }
65 UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
66
67 return EFI_SUCCESS;
68 }
69
70
71 /**
72
73 Create a ED
74
75 @Param Ohc Device private data
76
77 @retval ED descriptor pointer
78
79 **/
80 ED_DESCRIPTOR *
81 OhciCreateED (
82 USB_OHCI_HC_DEV *Ohc
83 )
84 {
85 ED_DESCRIPTOR *Ed;
86 Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
87 if (Ed == NULL) {
88 DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n"));
89 return NULL;
90 }
91 Ed->Word0.Skip = 1;
92 Ed->TdTailPointer = 0;
93 Ed->Word2.TdHeadPointer = 0;
94 Ed->NextED = 0;
95
96 return Ed;
97 }
98
99 /**
100
101 Free a ED
102
103 @Param Ohc UHC private data
104 @Param Ed Pointer to a ED to free
105
106 @retval EFI_SUCCESS ED freed
107
108 **/
109
110 EFI_STATUS
111 OhciFreeED (
112 IN USB_OHCI_HC_DEV *Ohc,
113 IN ED_DESCRIPTOR *Ed
114 )
115 {
116 if (Ed == NULL) {
117 return EFI_SUCCESS;
118 }
119 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
120
121 return EFI_SUCCESS;
122 }
123
124 /**
125
126 Free ED
127
128 @Param Ohc Device private data
129 @Param Ed Pointer to a ED to free
130
131 @retval EFI_SUCCESS ED freed
132
133 **/
134 EFI_STATUS
135 OhciFreeAllTDFromED (
136 IN USB_OHCI_HC_DEV *Ohc,
137 IN ED_DESCRIPTOR *Ed
138 )
139 {
140 TD_DESCRIPTOR *HeadTd;
141 TD_DESCRIPTOR *TailTd;
142 TD_DESCRIPTOR *Td;
143 TD_DESCRIPTOR *TempTd;
144
145 if (Ed == NULL) {
146 return EFI_SUCCESS;
147 }
148
149 HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
150 TailTd = (TD_DESCRIPTOR *)(UINTN)(Ed->TdTailPointer);
151
152 Td = HeadTd;
153 while (Td != TailTd) {
154 TempTd = Td;
155 Td = (TD_DESCRIPTOR *)(UINTN)(Td->NextTDPointer);
156 OhciFreeTD (Ohc, TempTd);
157 }
158
159 return EFI_SUCCESS;
160 }
161
162 /**
163
164 Find a working ED match the requirement
165
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
170
171 @retval ED descriptor searched
172
173 **/
174
175 ED_DESCRIPTOR *
176 OhciFindWorkingEd (
177 IN ED_DESCRIPTOR *EdHead,
178 IN UINT8 DeviceAddress,
179 IN UINT8 EndPointNum,
180 IN UINT8 EdDir
181 )
182 {
183 ED_DESCRIPTOR *Ed;
184
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) {
189 break;
190 }
191 }
192
193 return Ed;
194 }
195
196
197 /**
198
199 Initialize interrupt list.
200
201 @Param Ohc Device private data
202
203 @retval EFI_SUCCESS Initialization done
204
205 **/
206 EFI_STATUS
207 OhciInitializeInterruptList (
208 USB_OHCI_HC_DEV *Ohc
209 )
210 {
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;
214 UINTN Index;
215 UINTN Level;
216 UINTN Count;
217 ED_DESCRIPTOR *NewEd;
218
219 HccaInterruptTable = Ohc->HccaMemoryBlock->HccaInterruptTable;
220
221 for (Index = 0; Index < 32; Index++) {
222 NewEd = OhciCreateED (Ohc);
223 if (NewEd == NULL) {
224 return EFI_OUT_OF_RESOURCES;
225 }
226 HccaInterruptTable[Index] = (UINT32)(UINTN)NewEd;
227 }
228
229 for (Index = 0; Index < 32; Index++) {
230 Ohc->IntervalList[0][Index] = (ED_DESCRIPTOR *)(UINTN)HccaInterruptTable[Leaf[Index]];
231 }
232
233 Count = 32;
234 for (Level = 1; Level <= 5; Level++) {
235 Count = Count >> 1;
236
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;
241 }
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];
244 }
245 }
246
247 return EFI_SUCCESS;
248 }
249
250 /**
251
252 Attach an ED
253
254 @Param Ed Ed to be attached
255 @Param NewEd Ed to attach
256
257 @retval EFI_SUCCESS NewEd attached to Ed
258 @retval EFI_INVALID_PARAMETER Ed is NULL
259
260 **/
261 EFI_STATUS
262 OhciAttachED (
263 IN ED_DESCRIPTOR *Ed,
264 IN ED_DESCRIPTOR *NewEd
265 )
266 {
267 ED_DESCRIPTOR *Temp;
268
269 if (Ed == NULL) {
270 return EFI_INVALID_PARAMETER;
271 }
272
273 if (Ed->NextED == 0){
274 Ed->NextED = (UINT32)(UINTN)NewEd;
275 } else {
276 Temp = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
277 Ed->NextED = (UINT32)(UINTN)NewEd;
278 NewEd->NextED = (UINT32)(UINTN)Temp;
279 }
280
281 return EFI_SUCCESS;
282 }
283
284
285 /**
286
287 Count ED number on a ED chain
288
289 @Param Ed Head of the ED chain
290
291 @retval ED number on the chain
292
293 **/
294
295 UINTN
296 CountEdNum (
297 IN ED_DESCRIPTOR *Ed
298 )
299 {
300 UINTN Count;
301
302 Count = 0;
303
304 while (Ed) {
305 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
306 Count++;
307 }
308
309 return Count;
310 }
311
312 /**
313
314 Find the minimal burn ED list on a specific depth level
315
316 @Param Ohc Device private data
317 @Param Depth Depth level
318
319 @retval ED list found
320
321 **/
322
323 ED_DESCRIPTOR *
324 OhciFindMinInterruptEDList (
325 IN USB_OHCI_HC_DEV *Ohc,
326 IN UINT32 Depth
327 )
328 {
329 UINTN EdNum;
330 UINTN MinEdNum;
331 ED_DESCRIPTOR *TempEd;
332 ED_DESCRIPTOR *HeadEd;
333 UINTN Index;
334
335 if (Depth > 5) {
336 return NULL;
337 }
338
339 MinEdNum = 0xFFFFFFFF;
340 TempEd = NULL;
341 for (Index = 0; Index < (UINTN)(32 >> Depth); Index++) {
342 HeadEd = Ohc->IntervalList[Depth][Index];
343 EdNum = CountEdNum (HeadEd);
344 if (EdNum < MinEdNum) {
345 MinEdNum = EdNum;
346 TempEd = HeadEd;
347 }
348 }
349
350 ASSERT (TempEd != NULL);
351
352 return TempEd;
353 }
354
355
356 /**
357
358 Attach an ED to an ED list
359
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
364
365 @retval EFI_SUCCESS ED attached to ED list
366
367 **/
368 ED_DESCRIPTOR *
369 OhciAttachEDToList (
370 IN USB_OHCI_HC_DEV *Ohc,
371 IN DESCRIPTOR_LIST_TYPE ListType,
372 IN ED_DESCRIPTOR *Ed,
373 IN ED_DESCRIPTOR *EdList
374 )
375 {
376 ED_DESCRIPTOR *HeadEd;
377
378 HeadEd = NULL;
379 switch(ListType) {
380 case CONTROL_LIST:
381 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
382 if (HeadEd == NULL) {
383 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
384 HeadEd = Ed;
385 } else {
386 OhciAttachED (HeadEd, Ed);
387 }
388 break;
389
390 case BULK_LIST:
391 HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
392 if (HeadEd == NULL) {
393 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
394 HeadEd = Ed;
395 } else {
396 OhciAttachED (HeadEd, Ed);
397 }
398 break;
399
400 case INTERRUPT_LIST:
401 OhciAttachED (EdList, Ed);
402 break;
403
404 default:
405 ASSERT (FALSE);
406 }
407
408 return HeadEd;
409 }
410
411 /**
412
413 Remove interrupt EDs that match requirement
414
415 @Param Ohc UHC private data
416 @Param IntEd The address of Interrupt endpoint
417
418 @retval EFI_SUCCESS EDs match requirement removed
419
420 **/
421
422 EFI_STATUS
423 OhciFreeInterruptEdByEd (
424 IN USB_OHCI_HC_DEV *Ohc,
425 IN ED_DESCRIPTOR *IntEd
426 )
427 {
428 ED_DESCRIPTOR *Ed;
429 ED_DESCRIPTOR *TempEd;
430 UINTN Index;
431
432 if (IntEd == NULL)
433 return EFI_SUCCESS;
434
435 for (Index = 0; Index < 32; Index++) {
436 Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
437 if (Ed == NULL) {
438 continue;
439 }
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);
445 } else {
446 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
447 }
448 }
449 }
450 return EFI_SUCCESS;
451 }
452
453 /**
454
455 Remove interrupt EDs that match requirement
456
457 @Param Ohc UHC private data
458 @Param FunctionAddress Requirement on function address
459 @Param EndPointNum Requirement on end point number
460
461 @retval EFI_SUCCESS EDs match requirement removed
462
463 **/
464 EFI_STATUS
465 OhciFreeInterruptEdByAddr (
466 IN USB_OHCI_HC_DEV *Ohc,
467 IN UINT8 FunctionAddress,
468 IN UINT8 EndPointNum
469 )
470 {
471 ED_DESCRIPTOR *Ed;
472 ED_DESCRIPTOR *TempEd;
473 UINTN Index;
474
475 for (Index = 0; Index < 32; Index++) {
476 Ed = (ED_DESCRIPTOR *)(UINTN)Ohc->HccaMemoryBlock->HccaInterruptTable[Index];
477 if (Ed == NULL) {
478 continue;
479 }
480
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);
487 } else {
488 Ed = (ED_DESCRIPTOR *)(UINTN)(Ed->NextED);
489 }
490 }
491 }
492
493 return EFI_SUCCESS;
494 }
495
496
497 /**
498
499 Link Td2 to the end of Td1
500
501 @Param Td1 TD to be linked
502 @Param Td2 TD to link
503
504 @retval EFI_SUCCESS TD successfully linked
505 @retval EFI_INVALID_PARAMETER Td1 is NULL
506
507 **/
508 EFI_STATUS
509 OhciLinkTD (
510 IN TD_DESCRIPTOR *Td1,
511 IN TD_DESCRIPTOR *Td2
512 )
513 {
514 TD_DESCRIPTOR *TempTd;
515
516 if (Td1 == NULL) {
517 return EFI_INVALID_PARAMETER;
518 }
519
520 if (Td1 == Td2) {
521 return EFI_SUCCESS;
522 }
523
524 TempTd = Td1;
525 while (TempTd->NextTD != 0) {
526 TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
527 }
528
529 TempTd->NextTD = (UINT32)(UINTN)Td2;
530 TempTd->NextTDPointer = (UINT32)(UINTN)Td2;
531
532 return EFI_SUCCESS;
533 }
534
535
536 /**
537
538 Attach TD list to ED
539
540 @Param Ed ED which TD list attach on
541 @Param HeadTd Head of the TD list to attach
542
543 @retval EFI_SUCCESS TD list attached on the ED
544
545 **/
546 EFI_STATUS
547 OhciAttachTDListToED (
548 IN ED_DESCRIPTOR *Ed,
549 IN TD_DESCRIPTOR *HeadTd
550 )
551 {
552 TD_DESCRIPTOR *TempTd;
553
554 TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
555
556 if (TempTd != NULL) {
557 while (TempTd->NextTD != 0) {
558 TempTd = (TD_DESCRIPTOR *)(UINTN)(TempTd->NextTD);
559 }
560 TempTd->NextTD = (UINT32)(UINTN)HeadTd;
561 TempTd->NextTDPointer = (UINT32)(UINTN)HeadTd;
562 } else {
563 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32)(UINTN)HeadTd);
564 }
565
566 return EFI_SUCCESS;
567 }
568
569
570 /**
571
572 Set value to ED specific field
573
574 @Param Ed ED to be set
575 @Param Field Field to be set
576 @Param Value Value to set
577
578 @retval EFI_SUCCESS Value set
579
580 **/
581 EFI_STATUS
582 OhciSetEDField (
583 IN ED_DESCRIPTOR *Ed,
584 IN UINT32 Field,
585 IN UINT32 Value
586 )
587 {
588 if (Field & ED_FUNC_ADD) {
589 Ed->Word0.FunctionAddress = Value;
590 }
591 if (Field & ED_ENDPT_NUM) {
592 Ed->Word0.EndPointNum = Value;
593 }
594 if (Field & ED_DIR) {
595 Ed->Word0.Direction = Value;
596 }
597 if (Field & ED_SPEED) {
598 Ed->Word0.Speed = Value;
599 }
600 if (Field & ED_SKIP) {
601 Ed->Word0.Skip = Value;
602 }
603 if (Field & ED_FORMAT) {
604 Ed->Word0.Format = Value;
605 }
606 if (Field & ED_MAX_PACKET) {
607 Ed->Word0.MaxPacketSize = Value;
608 }
609 if (Field & ED_PDATA) {
610 Ed->Word0.FreeSpace = Value;
611 }
612 if (Field & ED_ZERO) {
613 Ed->Word2.Zero = Value;
614 }
615 if (Field & ED_TDTAIL_PTR) {
616 Ed->TdTailPointer = Value;
617 }
618
619 if (Field & ED_HALTED) {
620 Ed->Word2.Halted = Value;
621 }
622 if (Field & ED_DTTOGGLE) {
623 Ed->Word2.ToggleCarry = Value;
624 }
625 if (Field & ED_TDHEAD_PTR) {
626 Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
627 }
628
629 if (Field & ED_NEXT_EDPTR) {
630 Ed->NextED = Value;
631 }
632
633 return EFI_SUCCESS;
634 }
635
636 /**
637
638 Get value from an ED's specific field
639
640 @Param Ed ED pointer
641 @Param Field Field to get value from
642
643 @retval Value of the field
644
645 **/
646 UINT32
647 OhciGetEDField (
648 IN ED_DESCRIPTOR *Ed,
649 IN UINT32 Field
650 )
651 {
652 switch (Field) {
653 case ED_FUNC_ADD:
654 return Ed->Word0.FunctionAddress;
655 break;
656 case ED_ENDPT_NUM:
657 return Ed->Word0.EndPointNum;
658 break;
659 case ED_DIR:
660 return Ed->Word0.Direction;
661 break;
662 case ED_SPEED:
663 return Ed->Word0.Speed;
664 break;
665 case ED_SKIP:
666 return Ed->Word0.Skip;
667 break;
668 case ED_FORMAT:
669 return Ed->Word0.Format;
670 break;
671 case ED_MAX_PACKET:
672 return Ed->Word0.MaxPacketSize;
673 break;
674
675 case ED_TDTAIL_PTR:
676 return Ed->TdTailPointer;
677 break;
678
679 case ED_HALTED:
680 return Ed->Word2.Halted;
681 break;
682
683 case ED_DTTOGGLE:
684 return Ed->Word2.ToggleCarry;
685 break;
686
687 case ED_TDHEAD_PTR:
688 return Ed->Word2.TdHeadPointer << 4;
689 break;
690
691 case ED_NEXT_EDPTR:
692 return Ed->NextED;
693 break;
694
695 default:
696 ASSERT (FALSE);
697 }
698
699 return 0;
700 }
701
702
703 /**
704
705 Set value to TD specific field
706
707 @Param Td TD to be set
708 @Param Field Field to be set
709 @Param Value Value to set
710
711 @retval EFI_SUCCESS Value set
712
713 **/
714 EFI_STATUS
715 OhciSetTDField (
716 IN TD_DESCRIPTOR *Td,
717 IN UINT32 Field,
718 IN UINT32 Value
719 )
720 {
721 if (Field & TD_PDATA) {
722 Td->Word0.Reserved = Value;
723 }
724 if (Field & TD_BUFFER_ROUND) {
725 Td->Word0.BufferRounding = Value;
726 }
727 if (Field & TD_DIR_PID) {
728 Td->Word0.DirPID = Value;
729 }
730 if (Field & TD_DELAY_INT) {
731 Td->Word0.DelayInterrupt = Value;
732 }
733 if (Field & TD_DT_TOGGLE) {
734 Td->Word0.DataToggle = Value | 0x2;
735 }
736 if (Field & TD_ERROR_CNT) {
737 Td->Word0.ErrorCount = Value;
738 }
739 if (Field & TD_COND_CODE) {
740 Td->Word0.ConditionCode = Value;
741 }
742
743 if (Field & TD_CURR_BUFFER_PTR) {
744 Td->CurrBufferPointer = Value;
745 }
746
747
748 if (Field & TD_NEXT_PTR) {
749 Td->NextTD = Value;
750 }
751
752 if (Field & TD_BUFFER_END_PTR) {
753 Td->BufferEndPointer = Value;
754 }
755
756 return EFI_SUCCESS;
757 }
758
759
760 /**
761
762 Get value from ED specific field
763
764 @Param Td TD pointer
765 @Param Field Field to get value from
766
767 @retval Value of the field
768
769 **/
770
771 UINT32
772 OhciGetTDField (
773 IN TD_DESCRIPTOR *Td,
774 IN UINT32 Field
775 )
776 {
777 switch (Field){
778 case TD_BUFFER_ROUND:
779 return Td->Word0.BufferRounding;
780 break;
781 case TD_DIR_PID:
782 return Td->Word0.DirPID;
783 break;
784 case TD_DELAY_INT:
785 return Td->Word0.DelayInterrupt;
786 break;
787 case TD_DT_TOGGLE:
788 return Td->Word0.DataToggle;
789 break;
790 case TD_ERROR_CNT:
791 return Td->Word0.ErrorCount;
792 break;
793 case TD_COND_CODE:
794 return Td->Word0.ConditionCode;
795 break;
796 case TD_CURR_BUFFER_PTR:
797 return Td->CurrBufferPointer;
798 break;
799
800 case TD_NEXT_PTR:
801 return Td->NextTD;
802 break;
803
804 case TD_BUFFER_END_PTR:
805 return Td->BufferEndPointer;
806 break;
807
808 default:
809 ASSERT (FALSE);
810 }
811
812 return 0;
813 }
814
815 /**
816
817 Free the Ed,Td,buffer that were created during transferring
818
819 @Param Ohc Device private data
820 **/
821
822 VOID
823 OhciFreeDynamicIntMemory(
824 IN USB_OHCI_HC_DEV *Ohc
825 )
826 {
827 INTERRUPT_CONTEXT_ENTRY *Entry;
828 if (Ohc != NULL) {
829 while (Ohc->InterruptContextList != NULL) {
830 Entry = Ohc->InterruptContextList;
831 Ohc->InterruptContextList = Ohc->InterruptContextList->NextEntry;
832 OhciFreeInterruptEdByEd (Ohc, Entry->Ed);
833 OhciFreeInterruptContextEntry (Ohc, Entry);
834 }
835 }
836 }
837 /**
838
839 Free the Ed that were initilized during driver was starting,
840 those memory were used as interrupt ED head
841
842 @Param Ohc Device private data
843
844
845 **/
846 VOID
847 OhciFreeFixedIntMemory (
848 IN USB_OHCI_HC_DEV *Ohc
849 )
850 {
851 static UINT32 Leaf[] = {32,16,8,4,2,1};
852 UINTN Index;
853 UINTN Level;
854
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));
859 }
860 }
861 }
862 }
863 /**
864
865 Release all OHCI used memory when OHCI going to quit
866
867 @Param Ohc Device private data
868
869 @retval EFI_SUCCESS Memory released
870
871 **/
872
873 EFI_STATUS
874 OhciFreeIntTransferMemory (
875 IN USB_OHCI_HC_DEV *Ohc
876 )
877 {
878 //
879 // Free the Ed,Td,buffer that were created during transferring
880 //
881 OhciFreeDynamicIntMemory (Ohc);
882 //
883 // Free the Ed that were initilized during driver was starting
884 //
885 OhciFreeFixedIntMemory (Ohc);
886 return EFI_SUCCESS;
887 }
888
889