Home | History | Annotate | Download | only in Pei
      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 "OhcPeim.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     return NULL;
     41   }
     42   Td->CurrBufferPointer = NULL;
     43   Td->NextTD = NULL;
     44   Td->BufferEndPointer = NULL;
     45   Td->NextTDPointer = NULL;
     46 
     47   return Td;
     48 }
     49 
     50 
     51 /**
     52 
     53   Free a TD
     54 
     55   @Param  Ohc                   UHC private data
     56   @Param  Td                    Pointer to a TD to free
     57 
     58   @retval  EFI_SUCCESS          TD freed
     59 
     60 **/
     61 EFI_STATUS
     62 OhciFreeTD (
     63   IN USB_OHCI_HC_DEV      *Ohc,
     64   IN TD_DESCRIPTOR        *Td
     65   )
     66 {
     67   if (Td == NULL) {
     68     return EFI_SUCCESS;
     69   }
     70   UsbHcFreeMem(Ohc->MemPool, Td, sizeof(TD_DESCRIPTOR));
     71 
     72   return EFI_SUCCESS;
     73 }
     74 
     75 
     76 /**
     77 
     78   Create a ED
     79 
     80   @Param   Ohc                  Device private data
     81 
     82   @retval  ED                   descriptor pointer
     83 
     84 **/
     85 ED_DESCRIPTOR *
     86 OhciCreateED (
     87   USB_OHCI_HC_DEV          *Ohc
     88   )
     89 {
     90   ED_DESCRIPTOR   *Ed;
     91   Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR));
     92   if (Ed == NULL) {
     93     return NULL;
     94   }
     95   Ed->Word0.Skip = 1;
     96   Ed->TdTailPointer = NULL;
     97   Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL);
     98   Ed->NextED = NULL;
     99 
    100   return Ed;
    101 }
    102 
    103 /**
    104 
    105   Free a ED
    106 
    107   @Param  Ohc                   UHC private data
    108   @Param  Ed                    Pointer to a ED to free
    109 
    110   @retval  EFI_SUCCESS          ED freed
    111 
    112 **/
    113 
    114 EFI_STATUS
    115 OhciFreeED (
    116   IN USB_OHCI_HC_DEV      *Ohc,
    117   IN ED_DESCRIPTOR        *Ed
    118   )
    119 {
    120   if (Ed == NULL) {
    121     return EFI_SUCCESS;
    122   }
    123   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
    124 
    125   return EFI_SUCCESS;
    126 }
    127 
    128 /**
    129 
    130   Free  ED
    131 
    132   @Param  Ohc                    Device private data
    133   @Param  Ed                     Pointer to a ED to free
    134 
    135   @retval  EFI_SUCCESS           ED freed
    136 
    137 **/
    138 EFI_STATUS
    139 OhciFreeAllTDFromED (
    140   IN USB_OHCI_HC_DEV      *Ohc,
    141   IN ED_DESCRIPTOR        *Ed
    142   )
    143 {
    144   TD_DESCRIPTOR           *HeadTd;
    145   TD_DESCRIPTOR           *TailTd;
    146   TD_DESCRIPTOR           *Td;
    147   TD_DESCRIPTOR           *TempTd;
    148 
    149   if (Ed == NULL) {
    150     return EFI_SUCCESS;
    151   }
    152 
    153   HeadTd = TD_PTR (Ed->Word2.TdHeadPointer);
    154   TailTd = Ed->TdTailPointer;
    155 
    156   Td = HeadTd;
    157   while (Td != TailTd) {
    158     TempTd = Td;
    159     Td = Td->NextTDPointer;
    160     OhciFreeTD (Ohc, TempTd);
    161   }
    162 
    163   return EFI_SUCCESS;
    164 }
    165 
    166 /**
    167 
    168   Attach an ED
    169 
    170   @Param  Ed                    Ed to be attached
    171   @Param  NewEd                 Ed to attach
    172 
    173   @retval EFI_SUCCESS           NewEd attached to Ed
    174   @retval EFI_INVALID_PARAMETER Ed is NULL
    175 
    176 **/
    177 EFI_STATUS
    178 OhciAttachED (
    179   IN ED_DESCRIPTOR        *Ed,
    180   IN ED_DESCRIPTOR        *NewEd
    181   )
    182 {
    183   ED_DESCRIPTOR           *Temp;
    184 
    185   if (Ed == NULL) {
    186     return EFI_INVALID_PARAMETER;
    187   }
    188 
    189   if (Ed->NextED == NULL){
    190     Ed->NextED = NewEd;
    191   } else {
    192     Temp = Ed->NextED;
    193     Ed->NextED = NewEd;
    194     NewEd->NextED = Temp;
    195   }
    196 
    197   return EFI_SUCCESS;
    198 }
    199 /**
    200 
    201   Attach an ED to an ED list
    202 
    203   @Param  OHC                   UHC private data
    204   @Param  ListType              Type of the ED list
    205   @Param  Ed                    ED to attach
    206   @Param  EdList                ED list to be attached
    207 
    208   @retval  EFI_SUCCESS          ED attached to ED list
    209 
    210 **/
    211 EFI_STATUS
    212 OhciAttachEDToList (
    213   IN USB_OHCI_HC_DEV       *Ohc,
    214   IN DESCRIPTOR_LIST_TYPE  ListType,
    215   IN ED_DESCRIPTOR         *Ed,
    216   IN ED_DESCRIPTOR         *EdList
    217   )
    218 {
    219   ED_DESCRIPTOR            *HeadEd;
    220 
    221   switch(ListType) {
    222     case CONTROL_LIST:
    223       HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_CONTROL_HEAD);
    224       if (HeadEd == NULL) {
    225         OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, Ed);
    226       } else {
    227         OhciAttachED (HeadEd, Ed);
    228       }
    229     break;
    230 
    231     case BULK_LIST:
    232       HeadEd = (ED_DESCRIPTOR *) OhciGetMemoryPointer (Ohc, HC_BULK_HEAD);
    233       if (HeadEd == NULL) {
    234         OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, Ed);
    235       } else {
    236         OhciAttachED (HeadEd, Ed);
    237       }
    238     break;
    239 
    240     case INTERRUPT_LIST:
    241       OhciAttachED (EdList, Ed);
    242       break;
    243 
    244     default:
    245       ASSERT (FALSE);
    246   }
    247 
    248   return EFI_SUCCESS;
    249 }
    250 /**
    251 
    252   Link Td2 to the end of Td1
    253 
    254   @Param Td1                    TD to be linked
    255   @Param Td2                    TD to link
    256 
    257   @retval EFI_SUCCESS           TD successfully linked
    258   @retval EFI_INVALID_PARAMETER Td1 is NULL
    259 
    260 **/
    261 EFI_STATUS
    262 OhciLinkTD (
    263   IN TD_DESCRIPTOR        *Td1,
    264   IN TD_DESCRIPTOR        *Td2
    265   )
    266 {
    267   TD_DESCRIPTOR           *TempTd;
    268 
    269   if (Td1 == NULL) {
    270     return EFI_INVALID_PARAMETER;
    271   }
    272 
    273   if (Td1 == Td2) {
    274     return EFI_SUCCESS;
    275   }
    276 
    277   TempTd = Td1;
    278   while (TempTd->NextTD != NULL) {
    279     TempTd = TempTd->NextTD;
    280   }
    281 
    282   TempTd->NextTD = Td2;
    283   TempTd->NextTDPointer = Td2;
    284 
    285   return EFI_SUCCESS;
    286 }
    287 
    288 
    289 /**
    290 
    291   Attach TD list to ED
    292 
    293   @Param  Ed                    ED which TD list attach on
    294   @Param  HeadTd                Head of the TD list to attach
    295 
    296   @retval  EFI_SUCCESS          TD list attached on the ED
    297 
    298 **/
    299 EFI_STATUS
    300 OhciAttachTDListToED (
    301   IN ED_DESCRIPTOR        *Ed,
    302   IN TD_DESCRIPTOR        *HeadTd
    303   )
    304 {
    305   TD_DESCRIPTOR           *TempTd;
    306 
    307   TempTd = TD_PTR (Ed->Word2.TdHeadPointer);
    308 
    309   if (TempTd != NULL) {
    310     while (TempTd->NextTD != NULL) {
    311       TempTd = TempTd->NextTD;
    312     }
    313     TempTd->NextTD = HeadTd;
    314     TempTd->NextTDPointer = HeadTd;
    315   } else {
    316     Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) HeadTd);
    317   }
    318 
    319   return EFI_SUCCESS;
    320 }
    321 
    322 
    323 /**
    324 
    325   Set value to ED specific field
    326 
    327   @Param  Ed                    ED to be set
    328   @Param  Field                 Field to be set
    329   @Param  Value                 Value to set
    330 
    331   @retval  EFI_SUCCESS          Value set
    332 
    333 **/
    334 EFI_STATUS
    335 OhciSetEDField (
    336   IN ED_DESCRIPTOR        *Ed,
    337   IN UINT32               Field,
    338   IN UINT32               Value
    339   )
    340 {
    341   if (Field & ED_FUNC_ADD) {
    342     Ed->Word0.FunctionAddress = Value;
    343   }
    344   if (Field & ED_ENDPT_NUM) {
    345     Ed->Word0.EndPointNum = Value;
    346   }
    347   if (Field & ED_DIR) {
    348     Ed->Word0.Direction = Value;
    349   }
    350   if (Field & ED_SPEED) {
    351     Ed->Word0.Speed = Value;
    352   }
    353   if (Field & ED_SKIP) {
    354     Ed->Word0.Skip = Value;
    355   }
    356   if (Field & ED_FORMAT) {
    357     Ed->Word0.Format = Value;
    358   }
    359   if (Field & ED_MAX_PACKET) {
    360     Ed->Word0.MaxPacketSize = Value;
    361   }
    362   if (Field & ED_PDATA) {
    363     Ed->Word0.FreeSpace = Value;
    364   }
    365   if (Field & ED_ZERO) {
    366     Ed->Word2.Zero = Value;
    367   }
    368   if (Field & ED_TDTAIL_PTR) {
    369     Ed->TdTailPointer = (VOID *) Value;
    370   }
    371 
    372   if (Field & ED_HALTED) {
    373     Ed->Word2.Halted = Value;
    374   }
    375   if (Field & ED_DTTOGGLE) {
    376     Ed->Word2.ToggleCarry = Value;
    377   }
    378   if (Field & ED_TDHEAD_PTR) {
    379     Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 (Value);
    380   }
    381 
    382   if (Field & ED_NEXT_EDPTR) {
    383     Ed->NextED = (VOID *) Value;
    384   }
    385 
    386   return EFI_SUCCESS;
    387 }
    388 
    389 /**
    390 
    391   Get value from an ED's specific field
    392 
    393   @Param  Ed                    ED pointer
    394   @Param  Field                 Field to get value from
    395 
    396   @retval                       Value of the field
    397 
    398 **/
    399 UINT32
    400 OhciGetEDField (
    401   IN ED_DESCRIPTOR        *Ed,
    402   IN UINT32               Field
    403   )
    404 {
    405   switch (Field) {
    406     case ED_FUNC_ADD:
    407       return Ed->Word0.FunctionAddress;
    408       break;
    409     case ED_ENDPT_NUM:
    410       return Ed->Word0.EndPointNum;
    411       break;
    412     case ED_DIR:
    413       return Ed->Word0.Direction;
    414       break;
    415     case ED_SPEED:
    416       return Ed->Word0.Speed;
    417       break;
    418     case ED_SKIP:
    419       return Ed->Word0.Skip;
    420       break;
    421     case ED_FORMAT:
    422       return Ed->Word0.Format;
    423       break;
    424     case ED_MAX_PACKET:
    425       return Ed->Word0.MaxPacketSize;
    426       break;
    427 
    428     case ED_TDTAIL_PTR:
    429       return (UINT32) Ed->TdTailPointer;
    430       break;
    431 
    432     case ED_HALTED:
    433       return Ed->Word2.Halted;
    434       break;
    435 
    436     case ED_DTTOGGLE:
    437       return Ed->Word2.ToggleCarry;
    438       break;
    439 
    440     case ED_TDHEAD_PTR:
    441       return Ed->Word2.TdHeadPointer << 4;
    442       break;
    443 
    444     case ED_NEXT_EDPTR:
    445       return (UINT32) Ed->NextED;
    446       break;
    447 
    448     default:
    449       ASSERT (FALSE);
    450   }
    451 
    452   return 0;
    453 }
    454 
    455 
    456 /**
    457 
    458   Set value to TD specific field
    459 
    460   @Param  Td                    TD to be set
    461   @Param  Field                 Field to be set
    462   @Param  Value                 Value to set
    463 
    464   @retval  EFI_SUCCESS          Value set
    465 
    466 **/
    467 EFI_STATUS
    468 OhciSetTDField (
    469   IN TD_DESCRIPTOR        *Td,
    470   IN UINT32               Field,
    471   IN UINT32               Value
    472   )
    473 {
    474   if (Field & TD_PDATA) {
    475     Td->Word0.Reserved = Value;
    476   }
    477   if (Field & TD_BUFFER_ROUND) {
    478     Td->Word0.BufferRounding = Value;
    479   }
    480   if (Field & TD_DIR_PID) {
    481     Td->Word0.DirPID = Value;
    482   }
    483   if (Field & TD_DELAY_INT) {
    484     Td->Word0.DelayInterrupt = Value;
    485   }
    486   if (Field & TD_DT_TOGGLE) {
    487     Td->Word0.DataToggle = Value | 0x2;
    488   }
    489   if (Field & TD_ERROR_CNT) {
    490     Td->Word0.ErrorCount = Value;
    491   }
    492   if (Field & TD_COND_CODE) {
    493     Td->Word0.ConditionCode = Value;
    494   }
    495 
    496   if (Field & TD_CURR_BUFFER_PTR) {
    497     Td->CurrBufferPointer = (VOID *) Value;
    498   }
    499 
    500 
    501   if (Field & TD_NEXT_PTR) {
    502     Td->NextTD = (VOID *) Value;
    503   }
    504 
    505   if (Field & TD_BUFFER_END_PTR) {
    506     Td->BufferEndPointer = (VOID *) Value;
    507   }
    508 
    509   return EFI_SUCCESS;
    510 }
    511 
    512 
    513 /**
    514 
    515   Get value from ED specific field
    516 
    517   @Param  Td                    TD pointer
    518   @Param  Field                 Field to get value from
    519 
    520   @retval                       Value of the field
    521 
    522 **/
    523 
    524 UINT32
    525 OhciGetTDField (
    526   IN TD_DESCRIPTOR      *Td,
    527   IN UINT32             Field
    528   )
    529 {
    530   switch (Field){
    531     case TD_BUFFER_ROUND:
    532       return Td->Word0.BufferRounding;
    533       break;
    534     case TD_DIR_PID:
    535       return Td->Word0.DirPID;
    536       break;
    537     case TD_DELAY_INT:
    538       return Td->Word0.DelayInterrupt;
    539       break;
    540     case TD_DT_TOGGLE:
    541       return Td->Word0.DataToggle;
    542       break;
    543     case TD_ERROR_CNT:
    544       return Td->Word0.ErrorCount;
    545       break;
    546     case TD_COND_CODE:
    547       return Td->Word0.ConditionCode;
    548       break;
    549     case TD_CURR_BUFFER_PTR:
    550       return (UINT32) Td->CurrBufferPointer;
    551       break;
    552 
    553     case TD_NEXT_PTR:
    554       return (UINT32) Td->NextTD;
    555       break;
    556 
    557     case TD_BUFFER_END_PTR:
    558       return (UINT32) Td->BufferEndPointer;
    559       break;
    560 
    561     default:
    562       ASSERT (FALSE);
    563   }
    564 
    565   return 0;
    566 }
    567