Home | History | Annotate | Download | only in Dxe
      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 
    896