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 *
OhciCreateTD(IN USB_OHCI_HC_DEV * Ohc)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
OhciFreeTD(IN USB_OHCI_HC_DEV * Ohc,IN TD_DESCRIPTOR * Td)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 *
OhciCreateED(USB_OHCI_HC_DEV * Ohc)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
OhciFreeED(IN USB_OHCI_HC_DEV * Ohc,IN ED_DESCRIPTOR * Ed)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
OhciFreeAllTDFromED(IN USB_OHCI_HC_DEV * Ohc,IN ED_DESCRIPTOR * Ed)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 *
OhciFindWorkingEd(IN ED_DESCRIPTOR * EdHead,IN UINT8 DeviceAddress,IN UINT8 EndPointNum,IN UINT8 EdDir)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
OhciInitializeInterruptList(USB_OHCI_HC_DEV * Ohc)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
OhciAttachED(IN ED_DESCRIPTOR * Ed,IN ED_DESCRIPTOR * NewEd)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
CountEdNum(IN ED_DESCRIPTOR * Ed)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 *
OhciFindMinInterruptEDList(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Depth)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 *
OhciAttachEDToList(IN USB_OHCI_HC_DEV * Ohc,IN DESCRIPTOR_LIST_TYPE ListType,IN ED_DESCRIPTOR * Ed,IN ED_DESCRIPTOR * EdList)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
OhciFreeInterruptEdByEd(IN USB_OHCI_HC_DEV * Ohc,IN ED_DESCRIPTOR * IntEd)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
OhciFreeInterruptEdByAddr(IN USB_OHCI_HC_DEV * Ohc,IN UINT8 FunctionAddress,IN UINT8 EndPointNum)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
OhciLinkTD(IN TD_DESCRIPTOR * Td1,IN TD_DESCRIPTOR * Td2)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
OhciAttachTDListToED(IN ED_DESCRIPTOR * Ed,IN TD_DESCRIPTOR * HeadTd)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
OhciSetEDField(IN ED_DESCRIPTOR * Ed,IN UINT32 Field,IN UINT32 Value)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
OhciGetEDField(IN ED_DESCRIPTOR * Ed,IN UINT32 Field)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
OhciSetTDField(IN TD_DESCRIPTOR * Td,IN UINT32 Field,IN UINT32 Value)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
OhciGetTDField(IN TD_DESCRIPTOR * Td,IN UINT32 Field)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
OhciFreeDynamicIntMemory(IN USB_OHCI_HC_DEV * Ohc)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
OhciFreeFixedIntMemory(IN USB_OHCI_HC_DEV * Ohc)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
OhciFreeIntTransferMemory(IN USB_OHCI_HC_DEV * Ohc)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 
896