Home | History | Annotate | Download | only in Isp1761UsbDxe
      1 /** @file
      2 
      3   Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <Library/DebugLib.h>
     16 #include <Library/UefiBootServicesTableLib.h>
     17 #include <Library/UefiDriverEntryPoint.h>
     18 #include <Library/IoLib.h>
     19 #include <Library/MemoryAllocationLib.h>
     20 
     21 #include <IndustryStandard/Usb.h>
     22 
     23 #include <Protocol/UsbDevice.h>
     24 
     25 #include "Isp1761UsbDxe.h"
     26 
     27 /*
     28   Driver for using the NXP ISP1761 as a USB Peripheral controller.
     29   Doesn't use USB OTG - just sets it in Pure Peripheral mode.
     30 
     31   The ISP1582 datasheet has a little more info on the Peripheral controller
     32   registers than the ISP1761 datasheet
     33 
     34   We don't do string descriptors. They're optional.
     35   We currently assume the device has one configuration, one interface, one IN
     36   endpoint, and one OUT endpoint (plus the default control endpoint).
     37 
     38   In fact, this driver is the minimum required to implement fastboot.
     39 */
     40 
     41 // TODO Make sure the controller isn't sending empty packets when it shouldn't
     42 // (check behaviour in cases when Buffer Length isn't explcitly set)
     43 
     44 // ISP1582 Datasheet:
     45 // "Data transfers preceding the status stage must first be fully
     46 // completed before the STATUS bit can be set."
     47 // This variable stores whether some control data has been pended in the EP0TX
     48 // Tx buffer, so that when an EP0TX interrupt is received we can set the STATUS
     49 // bit to go to the Status stage of the control transfer.
     50 STATIC BOOLEAN mControlTxPending = FALSE;
     51 
     52 STATIC USB_DEVICE_DESCRIPTOR    *mDeviceDescriptor;
     53 
     54 // The config descriptor, interface descriptor, and endpoint descriptors in a
     55 // buffer (in that order)
     56 STATIC VOID                     *mDescriptors;
     57 // Convenience pointers to those descriptors inside the buffer:
     58 STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor;
     59 STATIC USB_CONFIG_DESCRIPTOR    *mConfigDescriptor;
     60 STATIC USB_ENDPOINT_DESCRIPTOR  *mEndpointDescriptors;
     61 
     62 STATIC USB_DEVICE_RX_CALLBACK   mDataReceivedCallback;
     63 STATIC USB_DEVICE_TX_CALLBACK   mDataSentCallback;
     64 
     65 // The time between interrupt polls, in units of 100 nanoseconds
     66 // 10 Microseconds
     67 #define ISP1761_INTERRUPT_POLL_PERIOD 10000
     68 
     69 STATIC
     70 VOID
     71 SelectEndpoint (
     72   IN UINT8 Endpoint
     73   )
     74 {
     75   // The DMA Endpoint Index must not point to the same as the
     76   // Endpoint Index Register.
     77   WRITE_REG32 (ISP1761_DMA_ENDPOINT_INDEX, ((Endpoint + 2) % ISP1761_NUM_ENDPOINTS));
     78   WRITE_REG32 (ISP1761_ENDPOINT_INDEX, Endpoint);
     79 }
     80 
     81 // Enable going to the Data stage of a control transfer
     82 STATIC
     83 VOID
     84 DataStageEnable (
     85   IN UINT8 Endpoint
     86   )
     87 {
     88   SelectEndpoint (Endpoint);
     89   WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_DSEN);
     90 }
     91 
     92 // Go to the Status stage of a successful control transfer
     93 STATIC
     94 VOID
     95 StatusAcknowledge (
     96   IN UINT8 Endpoint
     97 )
     98 {
     99   SelectEndpoint (Endpoint);
    100   WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_STATUS);
    101 }
    102 
    103 // Read the FIFO for the endpoint indexed by Endpoint, into the buffer pointed
    104 // at by Buffer, whose size is *Size bytes.
    105 //
    106 // If *Size is less than the number of bytes in the FIFO, return EFI_BUFFER_TOO_SMALL
    107 //
    108 // Update *Size with the number of bytes of data in the FIFO.
    109 STATIC
    110 EFI_STATUS
    111 ReadEndpointBuffer (
    112   IN      UINT8   Endpoint,
    113   IN OUT  UINTN  *Size,
    114   IN OUT  VOID   *Buffer
    115   )
    116 {
    117   UINT16  NumBytesAvailable;
    118   UINT32  Val32;
    119   UINTN   Index;
    120   UINTN   NumBytesRead;
    121 
    122   SelectEndpoint (Endpoint);
    123 
    124   NumBytesAvailable = READ_REG16 (ISP1761_BUFFER_LENGTH);
    125 
    126   if (NumBytesAvailable > *Size) {
    127     *Size = NumBytesAvailable;
    128     return EFI_BUFFER_TOO_SMALL;
    129   }
    130   *Size = NumBytesAvailable;
    131 
    132   /* -- NB! --
    133     The datasheet says the Data Port is 16 bits but it actually appears to
    134     be 32 bits.
    135    */
    136 
    137   // Read 32-bit chunks
    138   for (Index = 0; Index < NumBytesAvailable / 4; Index++) {
    139     ((UINT32 *) Buffer)[Index] = READ_REG32 (ISP1761_DATA_PORT);
    140   }
    141 
    142   // Read remaining bytes
    143 
    144   // Round NumBytesAvailable down to nearest power of 4
    145   NumBytesRead = NumBytesAvailable & (~0x3);
    146   if (NumBytesRead != NumBytesAvailable) {
    147     Val32 = READ_REG32 (ISP1761_DATA_PORT);
    148     // Copy each required byte of 32-bit word into buffer
    149     for (Index = 0; Index < NumBytesAvailable % 4; Index++) {
    150       ((UINT8 *) Buffer)[NumBytesRead + Index] = Val32 >> (Index * 8);
    151     }
    152   }
    153   return EFI_SUCCESS;
    154 }
    155 
    156 /*
    157   Write an endpoint buffer. Parameters:
    158   Endpoint        Endpoint index (see Endpoint Index Register in datasheet)
    159   MaxPacketSize   The MaxPacketSize this endpoint is configured for
    160   Size            The size of the Buffer
    161   Buffer          The data
    162 
    163   Assumes MaxPacketSize is a multiple of 4.
    164   (It seems that all valid values for MaxPacketSize _are_ multiples of 4)
    165 */
    166 STATIC
    167 EFI_STATUS
    168 WriteEndpointBuffer (
    169   IN       UINT8   Endpoint,
    170   IN       UINTN   MaxPacketSize,
    171   IN       UINTN   Size,
    172   IN CONST VOID   *Buffer
    173   )
    174 {
    175   UINTN    Index;
    176   UINT32  *DwordBuffer;
    177 
    178   DwordBuffer = (UINT32 *) Buffer;
    179   SelectEndpoint (Endpoint);
    180 
    181   /* -- NB! --
    182     The datasheet says the Data Port is 16 bits but it actually appears to
    183     be 32 bits.
    184    */
    185 
    186   // Write packets of size MaxPacketSize
    187   while (Size > MaxPacketSize) {
    188     for (Index = 0; Index < MaxPacketSize / 4; Index++) {
    189       WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[Index]);
    190     }
    191     Size -= MaxPacketSize;
    192     DwordBuffer += (MaxPacketSize / sizeof (UINT32));
    193   }
    194 
    195   // Write remaining data
    196 
    197   if (Size > 0) {
    198     WRITE_REG32 (ISP1761_BUFFER_LENGTH, Size);
    199 
    200     while (Size > 4) {
    201       WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]);
    202       Size -= 4;
    203       DwordBuffer++;
    204     }
    205 
    206     if (Size > 0) {
    207       WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]);
    208     }
    209   }
    210 
    211   return EFI_SUCCESS;
    212 }
    213 
    214 STATIC
    215 EFI_STATUS
    216 HandleGetDescriptor (
    217   IN USB_DEVICE_REQUEST  *Request
    218   )
    219 {
    220   EFI_STATUS  Status;
    221   UINT8       DescriptorType;
    222   UINTN       ResponseSize;
    223   VOID       *ResponseData;
    224 
    225   ResponseSize = 0;
    226   ResponseData = NULL;
    227   Status = EFI_SUCCESS;
    228 
    229   // Pretty confused if bmRequestType is anything but this:
    230   ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
    231 
    232   // Choose the response
    233   DescriptorType = Request->Value >> 8;
    234   switch (DescriptorType) {
    235   case USB_DESC_TYPE_DEVICE:
    236     DEBUG ((EFI_D_INFO, "USB: Got a request for device descriptor\n"));
    237     ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
    238     ResponseData = mDeviceDescriptor;
    239     break;
    240   case USB_DESC_TYPE_CONFIG:
    241     DEBUG ((EFI_D_INFO, "USB: Got a request for config descriptor\n"));
    242     ResponseSize = mConfigDescriptor->TotalLength;
    243     ResponseData = mDescriptors;
    244     break;
    245   case USB_DESC_TYPE_STRING:
    246     DEBUG ((EFI_D_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
    247     break;
    248   default:
    249     DEBUG ((EFI_D_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
    250     Status = EFI_NOT_FOUND;
    251     break;
    252   }
    253 
    254   // Send the response
    255   if (ResponseData) {
    256     ASSERT (ResponseSize != 0);
    257 
    258     if (Request->Length < ResponseSize) {
    259       // Truncate response
    260       ResponseSize = Request->Length;
    261     } else if (Request->Length > ResponseSize) {
    262       DEBUG ((EFI_D_INFO, "USB: Info: ResponseSize < wLength\n"));
    263     }
    264 
    265     DataStageEnable (ISP1761_EP0TX);
    266     Status = WriteEndpointBuffer (
    267               ISP1761_EP0TX,
    268               MAX_PACKET_SIZE_CONTROL,
    269               ResponseSize,
    270               ResponseData
    271               );
    272     if (!EFI_ERROR (Status)) {
    273       // Setting this value should cause us to go to the Status stage on the
    274       // next EP0TX interrupt
    275       mControlTxPending = TRUE;
    276     }
    277   }
    278 
    279   return EFI_SUCCESS;
    280 }
    281 
    282 STATIC
    283 EFI_STATUS
    284 HandleSetAddress (
    285   IN USB_DEVICE_REQUEST  *Request
    286   )
    287 {
    288   // Pretty confused if bmRequestType is anything but this:
    289   ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
    290   // USB Spec: "The USB device does not change its device address until after
    291   // the Status stage of this request is completed successfully."
    292   // ISP1582 datasheet: "The new device address is activated when the
    293   // device receives an acknowledgment from the host for the empty packet
    294   // token". (StatusAcknowledge causes an empty packet to be sent).
    295   // So, we write the Address register _before_ acking the SET_ADDRESS.
    296   DEBUG ((EFI_D_INFO, "USB: Setting address to %d\n", Request->Value));
    297   WRITE_REG32 (ISP1761_ADDRESS, Request->Value | ISP1761_ADDRESS_DEVEN);
    298   StatusAcknowledge (ISP1761_EP0TX);
    299 
    300   return EFI_SUCCESS;
    301 }
    302 
    303 // Move the device to the Configured state.
    304 // (This code only supports one configuration for a device, so the configuration
    305 //  index is ignored)
    306 STATIC
    307 EFI_STATUS
    308 HandleSetConfiguration (
    309   IN USB_DEVICE_REQUEST  *Request
    310   )
    311 {
    312   USB_ENDPOINT_DESCRIPTOR  *EPDesc;
    313   UINTN                     Index;
    314   UINT8                     EndpointIndex;
    315 
    316   ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
    317   DEBUG ((EFI_D_INFO, "USB: Setting configuration.\n"));
    318 
    319   // Configure endpoints
    320   for (Index = 0; Index < mInterfaceDescriptor->NumEndpoints; Index++) {
    321     EPDesc = &mEndpointDescriptors[Index];
    322 
    323     // To simplify for now, assume endpoints aren't "sparse", and are in order.
    324     ASSERT ((EPDesc->EndpointAddress & 0xF) == ((Index / 2) + 1));
    325 
    326     // Convert from USB endpoint index to ISP1761 endpoint Index
    327     // USB:     Endpoint number is bits [3:0], IN/OUT is bit [7]
    328     // ISP1761: Endpoint number is bits [4:1], IN/OUT is bit [0]
    329     EndpointIndex = ((EPDesc->EndpointAddress & 0xF) << 1) |
    330                     ((EPDesc->EndpointAddress & BIT7) >> 7);
    331     SelectEndpoint (EndpointIndex);
    332     // Set endpoint type (Bulk/Isochronous/Interrupt)
    333     WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, EPDesc->MaxPacketSize);
    334     // Hardware foible (bug?): Although the datasheet seems to suggest it should
    335     // automatically be set to MaxPacketSize, the Buffer Length register appears
    336     // to be reset to 0, which causes an empty packet to be sent in response to
    337     // the first IN token of the session. The NOEMPKT field of the Endpoint Type
    338     // register sounds like it might fix this problem, but it doesn't
    339     // (it's "applicable only in the DMA mode").
    340     WRITE_REG32 (ISP1761_BUFFER_LENGTH, EPDesc->MaxPacketSize);
    341     WRITE_REG32 (ISP1761_ENDPOINT_TYPE, (EPDesc->Attributes & 0x3) |
    342                                         ISP1761_ENDPOINT_TYPE_ENABLE);
    343   }
    344 
    345   StatusAcknowledge (ISP1761_EP0TX);
    346   return EFI_SUCCESS;
    347 }
    348 
    349 STATIC
    350 EFI_STATUS
    351 HandleDeviceRequest (
    352   IN USB_DEVICE_REQUEST  *Request
    353   )
    354 {
    355   EFI_STATUS  Status;
    356 
    357   Status = EFI_SUCCESS;
    358 
    359   switch (Request->Request) {
    360   case USB_DEV_GET_DESCRIPTOR:
    361     Status = HandleGetDescriptor (Request);
    362     break;
    363   case USB_DEV_SET_ADDRESS:
    364     Status = HandleSetAddress (Request);
    365     break;
    366   case USB_DEV_SET_CONFIGURATION:
    367     Status = HandleSetConfiguration (Request);
    368     break;
    369   default:
    370     DEBUG ((EFI_D_ERROR,
    371       "Didn't understand RequestType 0x%x Request 0x%x\n",
    372       Request->RequestType, Request->Request));
    373       Status = EFI_INVALID_PARAMETER;
    374     break;
    375   }
    376 
    377   return Status;
    378 }
    379 
    380 // Instead of actually registering interrupt handlers, we poll the controller's
    381 //  interrupt source register in this function.
    382 STATIC
    383 VOID
    384 CheckInterrupts (
    385   IN EFI_EVENT  Event,
    386   IN VOID      *Context
    387   )
    388 {
    389   UINT32      DcInterrupts;
    390   UINTN       NumBytes;
    391   UINTN       MoreBytes;
    392   UINT8       Packet[512];
    393   VOID       *DataPacket;
    394   UINT32      HandledInterrupts;
    395   UINT32      UnhandledInterrupts;
    396   EFI_STATUS  Status;
    397 
    398   // Set bits in HandledInterrupts to mark the interrupt source handled.
    399   HandledInterrupts = 0;
    400 
    401   WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC);
    402 
    403   DcInterrupts = READ_REG32 (ISP1761_DC_INTERRUPT);
    404   if (DcInterrupts & ISP1761_DC_INTERRUPT_SUSP) {
    405     DEBUG ((EFI_D_INFO, "USB: Suspend\n"));
    406     HandledInterrupts |= ISP1761_DC_INTERRUPT_SUSP;
    407   }
    408   if (DcInterrupts & ISP1761_DC_INTERRUPT_RESUME) {
    409     DEBUG ((EFI_D_INFO, "USB: Resume\n"));
    410     HandledInterrupts |= ISP1761_DC_INTERRUPT_RESUME;
    411   }
    412   if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0SETUP) {
    413     NumBytes = 512;
    414     ReadEndpointBuffer (0x20, &NumBytes, &Packet);
    415     ASSERT (NumBytes == 8);
    416     HandleDeviceRequest ((USB_DEVICE_REQUEST *) Packet);
    417     HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0SETUP;
    418   }
    419   if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0RX) {
    420     HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0RX;
    421   }
    422   if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0TX) {
    423     if (mControlTxPending) {
    424       // We previously put some data in the Control Endpoint's IN (Tx) FIFO.
    425       // We assume that that data has now been sent in response to the IN token
    426       // that triggered this interrupt. We can therefore go to the Status stage
    427       // of the control transfer.
    428       StatusAcknowledge (ISP1761_EP0TX);
    429       mControlTxPending = FALSE;
    430     }
    431     HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0TX;
    432   }
    433   if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1RX) {
    434     NumBytes = 512;
    435     DataPacket = AllocatePool (NumBytes);
    436     Status = ReadEndpointBuffer (ISP1761_EP1RX, &NumBytes, DataPacket);
    437     if (EFI_ERROR (Status) || NumBytes == 0) {
    438       if (EFI_ERROR (Status)) {
    439         DEBUG ((EFI_D_ERROR, "Couldn't read EP1RX data: %r\n", Status));
    440       }
    441       FreePool (DataPacket);
    442     } else {
    443       // Signal this event again so we poll again ASAP
    444       gBS->SignalEvent (Event);
    445       mDataReceivedCallback (NumBytes, DataPacket);
    446     }
    447     HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1RX;
    448   }
    449   if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1TX) {
    450     mDataSentCallback (1);
    451     HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1TX;
    452   }
    453   if (DcInterrupts & (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF)) {
    454     // Don't care about SOFs or pseudo-SOFs
    455     HandledInterrupts |= (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF);
    456   }
    457   if (ISP1761_DC_INTERRUPT_BRESET) {
    458     HandledInterrupts |= ISP1761_DC_INTERRUPT_BRESET;
    459   }
    460   if (ISP1761_DC_INTERRUPT_HS_STAT) {
    461     HandledInterrupts |= ISP1761_DC_INTERRUPT_HS_STAT;
    462   }
    463   if (ISP1761_DC_INTERRUPT_VBUS) {
    464     HandledInterrupts |= ISP1761_DC_INTERRUPT_VBUS;
    465   }
    466 
    467   UnhandledInterrupts = DcInterrupts & (~HandledInterrupts) & ISP1761_DC_INTERRUPT_MASK;
    468   if (UnhandledInterrupts) {
    469     DEBUG ((EFI_D_ERROR, "USB: Unhandled DC Interrupts: 0x%08x\n",
    470       UnhandledInterrupts));
    471   }
    472 
    473   // Check if we received any more data while we were handling the interrupt.
    474   SelectEndpoint (ISP1761_EP1RX);
    475   MoreBytes = READ_REG16 (ISP1761_BUFFER_LENGTH);
    476   if (MoreBytes) {
    477     HandledInterrupts &= ~ISP1761_DC_INTERRUPT_EP1RX;
    478   }
    479 
    480   WRITE_REG32 (ISP1761_DC_INTERRUPT, HandledInterrupts);
    481 }
    482 
    483 EFI_STATUS
    484 Isp1761PeriphSend (
    485   IN        UINT8  EndpointIndex,
    486   IN        UINTN  Size,
    487   IN  CONST VOID  *Buffer
    488   )
    489 {
    490   return WriteEndpointBuffer (
    491           (EndpointIndex << 1) | 0x1, //Convert to ISP1761 endpoint index, Tx
    492           MAX_PACKET_SIZE_BULK,
    493           Size,
    494           Buffer
    495           );
    496 }
    497 
    498 EFI_STATUS
    499 EFIAPI
    500 Isp1761PeriphStart (
    501   IN USB_DEVICE_DESCRIPTOR   *DeviceDescriptor,
    502   IN VOID                   **Descriptors,
    503   IN USB_DEVICE_RX_CALLBACK   RxCallback,
    504   IN USB_DEVICE_TX_CALLBACK   TxCallback
    505   )
    506 {
    507   UINT16                    OtgStatus;
    508   UINT8                    *Ptr;
    509   EFI_STATUS                Status;
    510   EFI_EVENT                 TimerEvent;
    511 
    512   ASSERT (DeviceDescriptor != NULL);
    513   ASSERT (Descriptors[0] != NULL);
    514   ASSERT (RxCallback != NULL);
    515   ASSERT (TxCallback != NULL);
    516 
    517   WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC);
    518 
    519   WRITE_REG32 (ISP1761_SW_RESET_REG, ISP1761_SW_RESET_ALL);
    520   while (READ_REG32 (ISP1761_SW_RESET_REG) & ISP1761_SW_RESET_ALL) {
    521     //busy wait
    522   }
    523   WRITE_REG32 (ISP1761_MODE, ISP1761_MODE_SFRESET);
    524   while (READ_REG32 (ISP1761_MODE) & ISP1761_MODE_SFRESET) {
    525     //busy wait
    526   }
    527   DEBUG ((EFI_D_INFO, "USB: Software reset done\n"));
    528 
    529   WRITE_REG32 (ISP1761_DC_INTERRUPT_ENABLE, 0x03FFFFFF);
    530   WRITE_REG32 (ISP1761_OTG_INTERRUPT_ENABLE_RISE, 0x07FF);
    531 
    532   WRITE_REG8 (ISP1761_ADDRESS, ISP1761_ADDRESS_DEVEN);
    533   WRITE_REG8 (ISP1761_MODE, ISP1761_MODE_WKUPCS | ISP1761_MODE_CLKAON);
    534 
    535   // Use port 1 as peripheral controller (magic - disagrees with datasheet)
    536   WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0xffff0000);
    537   WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0x000014d1);
    538 
    539   OtgStatus = READ_REG16 (ISP1761_OTG_STATUS);
    540   if ((OtgStatus & ISP1761_OTG_STATUS_B_SESS_END) != 0) {
    541     DEBUG ((EFI_D_ERROR, "USB: Vbus not powered.\n"));
    542   }
    543   if ((OtgStatus & ISP1761_OTG_STATUS_A_B_SESS_VLD) == 0) {
    544     DEBUG ((EFI_D_ERROR, "USB: Session not valid.\n"));
    545   }
    546 
    547   // Configure Control endpoints
    548   SelectEndpoint (0x20);
    549   WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);
    550   WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);
    551   SelectEndpoint (0x0);
    552   WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);
    553   WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);
    554   SelectEndpoint (0x1);
    555   WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL);
    556   WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE);
    557 
    558   // Interrupt on all ACK and NAK
    559   WRITE_REG32 (ISP1761_INTERRUPT_CONFIG, ISP1761_INTERRUPT_CONFIG_ACK_ONLY);
    560 
    561   mDeviceDescriptor = DeviceDescriptor;
    562   mDescriptors = Descriptors[0];
    563 
    564   // Right now we just support one configuration
    565   ASSERT (mDeviceDescriptor->NumConfigurations == 1);
    566   // ... and one interface
    567   mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
    568   ASSERT (mConfigDescriptor->NumInterfaces == 1);
    569 
    570   Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
    571   mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
    572   Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
    573 
    574   mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
    575 
    576   mDataReceivedCallback = RxCallback;
    577   mDataSentCallback = TxCallback;
    578 
    579   // Register a timer event so CheckInterupts gets called periodically
    580   Status = gBS->CreateEvent (
    581                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    582                   TPL_CALLBACK,
    583                   CheckInterrupts,
    584                   NULL,
    585                   &TimerEvent
    586                   );
    587   ASSERT_EFI_ERROR (Status);
    588   if (EFI_ERROR (Status)) {
    589     return Status;
    590   }
    591 
    592   Status = gBS->SetTimer (
    593                   TimerEvent,
    594                   TimerPeriodic,
    595                   ISP1761_INTERRUPT_POLL_PERIOD
    596                   );
    597   ASSERT_EFI_ERROR (Status);
    598 
    599   return Status;
    600 }
    601 
    602 USB_DEVICE_PROTOCOL mUsbDevice = {
    603   Isp1761PeriphStart,
    604   Isp1761PeriphSend
    605 };
    606 
    607 
    608 EFI_STATUS
    609 EFIAPI
    610 Isp1761PeriphEntryPoint (
    611   IN EFI_HANDLE                            ImageHandle,
    612   IN EFI_SYSTEM_TABLE                      *SystemTable
    613   )
    614 {
    615   UINT32      DeviceId;
    616   EFI_HANDLE  Handle;
    617 
    618   DeviceId = READ_REG32 (ISP1761_DEVICE_ID);
    619 
    620   if (DeviceId != ISP1761_DEVICE_ID_VAL) {
    621     DEBUG ((EFI_D_ERROR,
    622       "ERROR: Read incorrect device ID for ISP1761: 0x%08x, expected 0x%08x\n",
    623       DeviceId , ISP1761_DEVICE_ID_VAL
    624       ));
    625     return EFI_DEVICE_ERROR;
    626   }
    627 
    628   Handle = NULL;
    629   return gBS->InstallProtocolInterface (
    630     &Handle,
    631     &gUsbDeviceProtocolGuid,
    632     EFI_NATIVE_INTERFACE,
    633     &mUsbDevice
    634     );
    635 }
    636