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