Home | History | Annotate | Download | only in UsbBusPei
      1 /** @file
      2 The module is used to implement Usb Io PPI interfaces.
      3 
      4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions
      8 of the BSD License which accompanies this distribution.  The
      9 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 #include "UsbPeim.h"
     18 #include "PeiUsbLib.h"
     19 
     20 /**
     21   Submits control transfer to a target USB device.
     22 
     23   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
     24   @param  This                   The pointer of PEI_USB_IO_PPI.
     25   @param  Request                USB device request to send.
     26   @param  Direction              Specifies the data direction for the data stage.
     27   @param  Timeout                Indicates the maximum timeout, in millisecond. If Timeout
     28                                  is 0, then the caller must wait for the function to be
     29                                  completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
     30   @param  Data                   Data buffer to be transmitted or received from USB device.
     31   @param  DataLength             The size (in bytes) of the data buffer.
     32 
     33   @retval EFI_SUCCESS            Transfer was completed successfully.
     34   @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
     35   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
     36   @retval EFI_TIMEOUT            Transfer failed due to timeout.
     37   @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
     38 
     39 **/
     40 EFI_STATUS
     41 EFIAPI
     42 PeiUsbControlTransfer (
     43   IN     EFI_PEI_SERVICES          **PeiServices,
     44   IN     PEI_USB_IO_PPI            *This,
     45   IN     EFI_USB_DEVICE_REQUEST    *Request,
     46   IN     EFI_USB_DATA_DIRECTION    Direction,
     47   IN     UINT32                    Timeout,
     48   IN OUT VOID                      *Data,      OPTIONAL
     49   IN     UINTN                     DataLength  OPTIONAL
     50   )
     51 {
     52   EFI_STATUS                  Status;
     53   PEI_USB_DEVICE              *PeiUsbDev;
     54   UINT32                      TransferResult;
     55   EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
     56   UINT8                       EndpointIndex;
     57 
     58   PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
     59 
     60   EndpointDescriptor = NULL;
     61   EndpointIndex = 0;
     62 
     63   if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&
     64       (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
     65       (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {
     66     //
     67     // Request->Index is the Endpoint Address, use it to get the Endpoint Index.
     68     //
     69     while (EndpointIndex < MAX_ENDPOINT) {
     70       Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
     71       if (EFI_ERROR (Status)) {
     72         return EFI_INVALID_PARAMETER;
     73       }
     74 
     75       if (EndpointDescriptor->EndpointAddress == Request->Index) {
     76         break;
     77       }
     78 
     79       EndpointIndex++;
     80     }
     81 
     82     if (EndpointIndex == MAX_ENDPOINT) {
     83       return EFI_INVALID_PARAMETER;
     84     }
     85   }
     86 
     87   if (PeiUsbDev->Usb2HcPpi != NULL) {
     88     Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
     89                         PeiServices,
     90                         PeiUsbDev->Usb2HcPpi,
     91                         PeiUsbDev->DeviceAddress,
     92                         PeiUsbDev->DeviceSpeed,
     93                         PeiUsbDev->MaxPacketSize0,
     94                         Request,
     95                         Direction,
     96                         Data,
     97                         &DataLength,
     98                         Timeout,
     99                         &(PeiUsbDev->Translator),
    100                         &TransferResult
    101                         );
    102   } else {
    103     Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
    104                         PeiServices,
    105                         PeiUsbDev->UsbHcPpi,
    106                         PeiUsbDev->DeviceAddress,
    107                         PeiUsbDev->DeviceSpeed,
    108                         (UINT8) PeiUsbDev->MaxPacketSize0,
    109                         Request,
    110                         Direction,
    111                         Data,
    112                         &DataLength,
    113                         Timeout,
    114                         &TransferResult
    115                         );
    116   }
    117 
    118   //
    119   // Reset the endpoint toggle when endpoint stall is cleared
    120   //
    121   if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&
    122       (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
    123       (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {
    124     if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
    125       PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
    126     }
    127   }
    128 
    129   DEBUG ((EFI_D_INFO, "PeiUsbControlTransfer: %r\n", Status));
    130   return Status;
    131 }
    132 
    133 /**
    134   Submits bulk transfer to a bulk endpoint of a USB device.
    135 
    136   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
    137   @param  This                  The pointer of PEI_USB_IO_PPI.
    138   @param  DeviceEndpoint        Endpoint number and its direction in bit 7.
    139   @param  Data                  A pointer to the buffer of data to transmit
    140                                 from or receive into.
    141   @param  DataLength            The lenght of the data buffer.
    142   @param  Timeout               Indicates the maximum time, in millisecond, which the
    143                                 transfer is allowed to complete. If Timeout is 0, then
    144                                 the caller must wait for the function to be completed
    145                                 until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
    146 
    147   @retval EFI_SUCCESS           The transfer was completed successfully.
    148   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
    149   @retval EFI_INVALID_PARAMETER Parameters are invalid.
    150   @retval EFI_TIMEOUT           The transfer failed due to timeout.
    151   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
    152 
    153 **/
    154 EFI_STATUS
    155 EFIAPI
    156 PeiUsbBulkTransfer (
    157   IN     EFI_PEI_SERVICES    **PeiServices,
    158   IN     PEI_USB_IO_PPI      *This,
    159   IN     UINT8               DeviceEndpoint,
    160   IN OUT VOID                *Data,
    161   IN OUT UINTN               *DataLength,
    162   IN     UINTN               Timeout
    163   )
    164 {
    165   EFI_STATUS                  Status;
    166   PEI_USB_DEVICE              *PeiUsbDev;
    167   UINT32                      TransferResult;
    168   UINTN                       MaxPacketLength;
    169   UINT8                       DataToggle;
    170   UINT8                       OldToggle;
    171   EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
    172   UINT8                       EndpointIndex;
    173   VOID                        *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
    174 
    175   PeiUsbDev     = PEI_USB_DEVICE_FROM_THIS (This);
    176 
    177   EndpointDescriptor = NULL;
    178   EndpointIndex = 0;
    179   Data2[0] = Data;
    180   Data2[1] = NULL;
    181 
    182   while (EndpointIndex < MAX_ENDPOINT) {
    183     Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
    184     if (EFI_ERROR (Status)) {
    185       return EFI_INVALID_PARAMETER;
    186     }
    187 
    188     if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
    189       break;
    190     }
    191 
    192     EndpointIndex++;
    193   }
    194 
    195   if (EndpointIndex == MAX_ENDPOINT) {
    196     return EFI_INVALID_PARAMETER;
    197   }
    198 
    199   MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
    200   if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
    201     DataToggle = 1;
    202   } else {
    203     DataToggle = 0;
    204   }
    205 
    206   OldToggle = DataToggle;
    207 
    208   if (PeiUsbDev->Usb2HcPpi != NULL) {
    209     Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
    210                         PeiServices,
    211                         PeiUsbDev->Usb2HcPpi,
    212                         PeiUsbDev->DeviceAddress,
    213                         DeviceEndpoint,
    214                         PeiUsbDev->DeviceSpeed,
    215                         MaxPacketLength,
    216                         Data2,
    217                         DataLength,
    218                         &DataToggle,
    219                         Timeout,
    220                         &(PeiUsbDev->Translator),
    221                         &TransferResult
    222                         );
    223   } else {
    224     Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
    225                         PeiServices,
    226                         PeiUsbDev->UsbHcPpi,
    227                         PeiUsbDev->DeviceAddress,
    228                         DeviceEndpoint,
    229                         (UINT8) MaxPacketLength,
    230                         Data,
    231                         DataLength,
    232                         &DataToggle,
    233                         Timeout,
    234                         &TransferResult
    235                         );
    236   }
    237 
    238   if (OldToggle != DataToggle) {
    239     PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
    240   }
    241 
    242   DEBUG ((EFI_D_INFO, "PeiUsbBulkTransfer: %r\n", Status));
    243   return Status;
    244 }
    245 
    246 /**
    247   Get the usb interface descriptor.
    248 
    249   @param  PeiServices          General-purpose services that are available to every PEIM.
    250   @param  This                 Indicates the PEI_USB_IO_PPI instance.
    251   @param  InterfaceDescriptor  Request interface descriptor.
    252 
    253 
    254   @retval EFI_SUCCESS          Usb interface descriptor is obtained successfully.
    255 
    256 **/
    257 EFI_STATUS
    258 EFIAPI
    259 PeiUsbGetInterfaceDescriptor (
    260   IN  EFI_PEI_SERVICES               **PeiServices,
    261   IN  PEI_USB_IO_PPI                 *This,
    262   OUT EFI_USB_INTERFACE_DESCRIPTOR   **InterfaceDescriptor
    263   )
    264 {
    265   PEI_USB_DEVICE  *PeiUsbDev;
    266   PeiUsbDev             = PEI_USB_DEVICE_FROM_THIS (This);
    267   *InterfaceDescriptor  = PeiUsbDev->InterfaceDesc;
    268   return EFI_SUCCESS;
    269 }
    270 
    271 /**
    272   Get the usb endpoint descriptor.
    273 
    274   @param  PeiServices          General-purpose services that are available to every PEIM.
    275   @param  This                 Indicates the PEI_USB_IO_PPI instance.
    276   @param  EndpointIndex        The valid index of the specified endpoint.
    277   @param  EndpointDescriptor   Request endpoint descriptor.
    278 
    279   @retval EFI_SUCCESS       Usb endpoint descriptor is obtained successfully.
    280   @retval EFI_NOT_FOUND     Usb endpoint descriptor is NOT found.
    281 
    282 **/
    283 EFI_STATUS
    284 EFIAPI
    285 PeiUsbGetEndpointDescriptor (
    286   IN  EFI_PEI_SERVICES               **PeiServices,
    287   IN  PEI_USB_IO_PPI                 *This,
    288   IN  UINT8                          EndpointIndex,
    289   OUT EFI_USB_ENDPOINT_DESCRIPTOR    **EndpointDescriptor
    290   )
    291 {
    292   PEI_USB_DEVICE  *PeiUsbDev;
    293 
    294   PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
    295 
    296   ASSERT (EndpointDescriptor != NULL);
    297 
    298   //
    299   // The valid range of EndpointIndex is 0..15
    300   // If EndpointIndex is lesser than 15 but larger than the number of interfaces,
    301   // a EFI_NOT_FOUND should be returned
    302   //
    303   ASSERT (EndpointIndex <= 15);
    304 
    305   if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
    306     return EFI_NOT_FOUND;
    307   }
    308 
    309   *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
    310 
    311   return EFI_SUCCESS;
    312 }
    313 
    314 /**
    315   Reset the port and re-configure the usb device.
    316 
    317   @param  PeiServices    General-purpose services that are available to every PEIM.
    318   @param  This           Indicates the PEI_USB_IO_PPI instance.
    319 
    320   @retval EFI_SUCCESS    Usb device is reset and configured successfully.
    321   @retval Others         Other failure occurs.
    322 
    323 **/
    324 EFI_STATUS
    325 EFIAPI
    326 PeiUsbPortReset (
    327   IN EFI_PEI_SERVICES               **PeiServices,
    328   IN PEI_USB_IO_PPI                 *This
    329   )
    330 {
    331   PEI_USB_DEVICE  *PeiUsbDev;
    332   EFI_STATUS      Status;
    333   UINT8           Address;
    334 
    335   PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
    336 
    337   ResetRootPort (
    338     PeiServices,
    339     PeiUsbDev->UsbHcPpi,
    340     PeiUsbDev->Usb2HcPpi,
    341     PeiUsbDev->DeviceAddress,
    342     0
    343     );
    344 
    345   //
    346   // Set address
    347   //
    348   Address                   = PeiUsbDev->DeviceAddress;
    349   PeiUsbDev->DeviceAddress  = 0;
    350 
    351   Status = PeiUsbSetDeviceAddress (
    352             PeiServices,
    353             This,
    354             Address
    355             );
    356 
    357   if (EFI_ERROR (Status)) {
    358     return Status;
    359   }
    360 
    361   PeiUsbDev->DeviceAddress = Address;
    362 
    363   //
    364   // Set default configuration
    365   //
    366   Status = PeiUsbSetConfiguration (
    367             PeiServices,
    368             This
    369             );
    370 
    371   return Status;
    372 }
    373