Home | History | Annotate | Download | only in DwUsb3Dxe
      1 /** @file
      2 
      3   Copyright (c) 2017, Linaro Limited. All rights reserved.
      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 <IndustryStandard/Usb.h>
     16 #include <Library/ArmLib.h>
     17 #include <Library/BaseLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/CacheMaintenanceLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/IoLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/TimerLib.h>
     24 #include <Library/UefiBootServicesTableLib.h>
     25 #include <Library/UefiDriverEntryPoint.h>
     26 #include <Library/UefiRuntimeServicesTableLib.h>
     27 #include <Library/UncachedMemoryAllocationLib.h>
     28 #include <Protocol/DwUsb.h>
     29 #include <Protocol/UsbDevice.h>
     30 
     31 #include "DwUsb3Dxe.h"
     32 
     33 #define FIFO_DIR_TX                  0
     34 #define FIFO_DIR_RX                  1
     35 
     36 #define TX_FIFO_ADDR                 0
     37 #define RX_FIFO_ADDR                 0
     38 
     39 #define RAM_WIDTH                    8
     40 #define RAM_TX0_DEPTH                2048
     41 #define RAM_TX1_DEPTH                4096
     42 #define RAM_RX_DEPTH                 8192
     43 
     44 #define USB_TYPE_LENGTH              16
     45 #define USB_BLOCK_HIGH_SPEED_SIZE    512
     46 #define DATA_SIZE                    131072
     47 #define CMD_SIZE                     512
     48 #define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
     49 
     50 // The time between interrupt polls, in units of 100 nanoseconds
     51 // 10 Microseconds
     52 #define DW_INTERRUPT_POLL_PERIOD     100
     53 
     54 #define DWUSB3_EVENT_BUF_SIZE        256
     55 
     56 // Maxpacket size for EP0, defined by USB3 spec
     57 #define USB3_MAX_EP0_SIZE            512
     58 
     59 // Maxpacket size for any EP, defined by USB3 spec
     60 #define USB3_MAX_PACKET_SIZE         1024
     61 #define USB2_HS_MAX_PACKET_SIZE      512
     62 #define USB2_FS_MAX_PACKET_SIZE      64
     63 
     64 #define USB3_STATE_UNCONNECTED       0
     65 #define USB3_STATE_DEFAULT           1
     66 #define USB3_STATE_ADDRESSED         2
     67 #define USB3_STATE_CONFIGURED        3
     68 
     69 #define GET_EVENTBUF_COUNT()       (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0))))
     70 #define UPDATE_EVENTBUF_COUNT(x)   (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x)))
     71 #define CLEAR_EVENTBUF()           do {                                                \
     72                                      MmioOr32 (GEVNTSIZ (0), GEVNTSIZ_EVNTINTMASK);    \
     73                                      MmioOr32 (GEVNTCOUNT (0), 0);                     \
     74                                    } while (0)
     75 
     76 #define SET_DEVADDR(x)             (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x)))
     77 
     78 EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
     79 
     80 STATIC DW_USB_PROTOCOL          *DwUsb;
     81 
     82 STATIC usb3_pcd_t               gPcd;
     83 STATIC UINT32                   *gEventBuf, *gEventPtr;
     84 STATIC struct usb_device_descriptor   gDwUsb3DevDesc;
     85 STATIC VOID                     *gRxBuf;
     86 
     87 STATIC usb_setup_pkt_t                *gEndPoint0SetupPacket;
     88 #define USB3_STATUS_BUF_SIZE    512
     89 STATIC UINT8                          *gEndPoint0StatusBuf;
     90 STATIC USB_DEVICE_RX_CALLBACK         mDataReceivedCallback;
     91 STATIC UINTN                          mDataBufferSize;
     92 /*
     93 	UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE];
     94 */
     95 
     96 struct usb_interface_descriptor intf = {
     97   sizeof (struct usb_interface_descriptor),
     98   UDESC_INTERFACE,
     99   0,
    100   0,
    101   2,
    102   USB_CLASS_VENDOR_SPEC,
    103   0x42,
    104   0x03,
    105   0
    106 };
    107 
    108 const struct usb_ss_ep_comp_descriptor ep_comp = {
    109   sizeof (struct usb_ss_ep_comp_descriptor),
    110   UDESC_SS_USB_COMPANION,
    111   0,
    112   0,
    113   0
    114 };
    115 
    116 const struct usb_endpoint_descriptor hs_bulk_in = {
    117   sizeof (struct usb_endpoint_descriptor),
    118   UDESC_ENDPOINT,
    119   UE_DIR_IN | USB3_BULK_IN_EP,
    120   USB_ENDPOINT_XFER_BULK,
    121   0x200,
    122   0
    123 };
    124 
    125 const struct usb_endpoint_descriptor
    126 hs_bulk_out = {
    127 	sizeof(struct usb_endpoint_descriptor), /* bLength */
    128 	UDESC_ENDPOINT, /* bDescriptorType */
    129 
    130 	UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */
    131 	USB_ENDPOINT_XFER_BULK, /* bmAttributes */
    132 	0x200, /* wMaxPacketSize: 512 of high-speed */
    133 	1, /* bInterval */
    134 };
    135 
    136 const struct usb_endpoint_descriptor ss_bulk_in = {
    137 	sizeof(struct usb_endpoint_descriptor), /* bLength */
    138 	UDESC_ENDPOINT, /* bDescriptorType */
    139 
    140 	UE_DIR_IN | USB3_BULK_IN_EP, /* bEndpointAddress */
    141 	USB_ENDPOINT_XFER_BULK, /* bmAttributes */
    142 	0x400, /* wMaxPacketSize: 1024 of super-speed */
    143 	0, /* bInterval */
    144 };
    145 
    146 const struct usb_endpoint_descriptor ss_bulk_out = {
    147 	sizeof(struct usb_endpoint_descriptor), /* bLength */
    148 	UDESC_ENDPOINT, /* bDescriptorType */
    149 
    150 	UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */
    151 	USB_ENDPOINT_XFER_BULK, /* bmAttributes */
    152 	0x400, /* wMaxPacketSize: 1024 of super-speed */
    153 	0, /* bInterval */
    154 };
    155 
    156 /** The BOS Descriptor */
    157 
    158 const struct usb_dev_cap_20_ext_desc cap1 = {
    159 	sizeof(struct usb_dev_cap_20_ext_desc),	/* bLength */
    160 	UDESC_DEVICE_CAPABILITY,		/* bDescriptorType */
    161 	USB_DEVICE_CAPABILITY_20_EXTENSION,	/* bDevCapabilityType */
    162 	0x2,				/* bmAttributes */
    163 };
    164 
    165 const struct usb_dev_cap_ss_usb
    166 cap2 = {
    167 	sizeof(struct usb_dev_cap_ss_usb),	/* bLength */
    168 	UDESC_DEVICE_CAPABILITY,		/* bDescriptorType */
    169 	USB_DEVICE_CAPABILITY_SS_USB,		/* bDevCapabilityType */
    170 	0x0,					/* bmAttributes */
    171 	(USB_DC_SS_USB_SPEED_SUPPORT_SS |
    172 	    USB_DC_SS_USB_SPEED_SUPPORT_HIGH),   /* wSpeedsSupported */
    173 	0x2,					/* bFunctionalitySupport */
    174 	/* @todo set these to correct value */
    175 	0xa,					/* bU1DevExitLat */
    176 	0x100,				/* wU2DevExitLat */
    177 };
    178 
    179 const struct usb_dev_cap_container_id
    180 cap3 = {
    181 	sizeof(struct usb_dev_cap_container_id),/* bLength */
    182 	UDESC_DEVICE_CAPABILITY,		/* bDescriptorType */
    183 	USB_DEVICE_CAPABILITY_CONTAINER_ID,	/* bDevCapabilityType */
    184 	0,					/* bReserved */
    185 	/* @todo Create UUID */
    186 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */
    187 };
    188 
    189 const struct wusb_bos_desc
    190 bos = {
    191 	sizeof(struct wusb_bos_desc),		/* bLength */
    192 	UDESC_BOS,				/* bDescriptorType */
    193 	(sizeof(struct wusb_bos_desc)	/* wTotalLength */
    194 	    + sizeof(cap1) + sizeof(cap2) + sizeof(cap3)),
    195 	3,					/* bNumDeviceCaps */
    196 };
    197 
    198 STATIC struct usb_enum_port_param usb_port_activity_config = {
    199   .idVendor           = USB_ENUM_ADB_PORT_VID,
    200   .idProduct          = USB_ENUM_ADB_PORT_PID,
    201   .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS,
    202   .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL
    203 };
    204 
    205 STATIC
    206 UINT32
    207 DwUsb3GetEventBufEvent (
    208   IN UINTN               Size
    209   )
    210 {
    211   UINT32                 Event;
    212 
    213   Event = *gEventPtr++;
    214   if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) {
    215     gEventPtr = gEventBuf;
    216   }
    217   return Event;
    218 }
    219 
    220 STATIC
    221 VOID
    222 DwUsb3SetFifoSize (
    223   IN UINT32              Addr,
    224   IN UINT32              Depth,
    225   IN UINT32              Dir,
    226   IN UINT32              FifoNum
    227   )
    228 {
    229   UINT32                 Reg;
    230 
    231   if (Dir == FIFO_DIR_TX) {
    232     Reg = GTXFIFOSIZ (FifoNum);
    233   } else if (Dir == FIFO_DIR_RX) {
    234     Reg = GRXFIFOSIZ (FifoNum);
    235   } else {
    236     ASSERT (0);
    237   }
    238   MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr));
    239 }
    240 
    241 STATIC
    242 UINT32
    243 Handshake (
    244   IN UINT32              Reg,
    245   IN UINT32              Mask,
    246   IN UINT32              Done
    247   )
    248 {
    249   UINT32                 Timeout = 100000;
    250 
    251   do {
    252     if ((MmioRead32 (Reg) & Mask) == Done) {
    253       return 1;
    254     }
    255     MicroSecondDelay (1);
    256   } while (Timeout-- > 0);
    257   return 0;
    258 }
    259 
    260 STATIC
    261 VOID
    262 DwUsb3FillDesc (
    263   IN usb3_dma_desc_t     *desc,
    264   IN UINT64              dma_addr,
    265   IN UINT32              dma_len,
    266   IN UINT32              stream,
    267   IN UINT32              type,
    268   IN UINT32              ctrlbits,
    269   IN UINT32              own
    270   )
    271 {
    272   desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF);
    273   desc->bpth = (UINT32)(dma_addr >> 32);
    274   desc->status = DSCSTS_XFERCNT (dma_len);
    275   if (type) {
    276     desc->control = DSCCTL_TRBCTL (type);
    277   }
    278   desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits;
    279   ArmDataSynchronizationBarrier ();
    280   /* must execute this operation at last */
    281   if (own) {
    282     desc->control |= DSCCTL_HWO;
    283   }
    284   ArmDataSynchronizationBarrier ();
    285 }
    286 
    287 STATIC
    288 VOID
    289 DwUsb3DepStartNewCfg (
    290   IN UINT32              EpIdx,
    291   IN UINT32              RsrcIdx
    292   )
    293 {
    294   /* start the command */
    295   MmioWrite32 (
    296     DEPCMD (EpIdx),
    297     DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | DEPCMD_CMDACT
    298     );
    299   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    300 }
    301 
    302 STATIC
    303 VOID
    304 DwUsb3DepCfg (
    305   IN UINT32              EpIdx,
    306   IN UINT32              DepCfg0,
    307   IN UINT32              DepCfg1,
    308   IN UINT32              DepCfg2
    309   )
    310 {
    311   MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2);
    312   MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1);
    313   MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0);
    314   MmioWrite32 (DEPCMD (EpIdx), DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT);
    315   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    316 }
    317 
    318 STATIC
    319 VOID
    320 DwUsb3DepXferCfg (
    321   IN UINT32              EpIdx,
    322   IN UINT32              DepStrmCfg
    323   )
    324 {
    325   MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg);
    326   MmioWrite32 (DEPCMD (EpIdx), DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT);
    327   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    328 }
    329 
    330 STATIC
    331 UINT8
    332 DwUsb3DepStartXfer (
    333   IN UINT32              EpIdx,
    334   IN UINT64              DmaAddr,
    335   IN UINT32              StreamOrUf
    336   )
    337 {
    338   UINT32                 Data;
    339 
    340   MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr);
    341   MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32));
    342   MmioWrite32 (
    343     DEPCMD (EpIdx),
    344     DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | DEPCMD_CMDACT
    345     );
    346   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    347   Data = MmioRead32 (DEPCMD (EpIdx));
    348   return GET_DEPCMD_XFER_RSRC_IDX(Data);
    349 }
    350 
    351 STATIC
    352 VOID
    353 DwUsb3DepStopXfer (
    354   IN UINT32               EpIdx,
    355   IN UINT32               Tri
    356   )
    357 {
    358   MmioWrite32 (DEPCMDPAR2 (EpIdx), 0);
    359   MmioWrite32 (DEPCMDPAR1 (EpIdx), 0);
    360   MmioWrite32 (DEPCMDPAR0 (EpIdx), 0);
    361   MmioWrite32 (
    362     DEPCMD (EpIdx),
    363     DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | DEPCMD_CMDACT
    364     );
    365   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    366 }
    367 
    368 VOID
    369 DwUsb3DepUpdateXfer (
    370   IN UINT32               EpIdx,
    371   IN UINT32               Tri
    372   )
    373 {
    374   MmioWrite32 (
    375     DEPCMD (EpIdx),
    376     DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | DEPCMD_CMDACT
    377     );
    378   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    379 }
    380 
    381 STATIC
    382 VOID
    383 DwUsb3DepClearStall (
    384   IN UINTN            EpIdx
    385   )
    386 {
    387   MmioWrite32 (DEPCMD (EpIdx), DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT);
    388   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    389 }
    390 
    391 
    392 STATIC
    393 VOID
    394 DwUsb3DepSetStall (
    395   IN UINTN            EpIdx
    396   )
    397 {
    398   MmioWrite32 (DEPCMD (EpIdx), DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT);
    399   Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0);
    400 }
    401 
    402 STATIC
    403 VOID
    404 DwUsb3EnableEp (
    405   IN UINT32                EpIdx,
    406   IN usb3_pcd_ep_t         *ep
    407   )
    408 {
    409   UINT32                   Dalepena;
    410 
    411   Dalepena = MmioRead32 (DALEPENA);
    412   /* If the EP is already enabled, skip to set it again. */
    413   if (Dalepena & (1 << EpIdx)) {
    414     return;
    415   }
    416   Dalepena |= 1 << EpIdx;
    417   MmioWrite32 (DALEPENA, Dalepena);
    418 }
    419 
    420 STATIC
    421 VOID
    422 DwUsb3Ep0Activate (
    423   IN OUT usb3_pcd_t         *pcd
    424   )
    425 {
    426   /* issue DEPCFG command to EP0 OUT */
    427   DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0);
    428   DwUsb3DepCfg (
    429     EP_OUT_IDX (0),
    430     EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512),
    431     EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY,
    432     0
    433     );
    434   /* issue DEPSTRMCFG command to EP0 OUT */
    435   DwUsb3DepXferCfg (EP_OUT_IDX (0), 1);  // one stream
    436   /* issue DEPCFG command to EP0 IN */
    437   DwUsb3DepCfg (
    438     EP_IN_IDX (0),
    439     EPCFG0_EPTYPE (EPTYPE_CONTROL)  | EPCFG0_MPS (512) | EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num),
    440     EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN,
    441     0
    442     );
    443   /* issue DEPSTRMCFG command to EP0 IN */
    444   DwUsb3DepXferCfg (EP_IN_IDX (0), 1);  // one stream
    445   pcd->ep0.active = 1;
    446 }
    447 
    448 STATIC
    449 VOID
    450 DwUsb3EpActivate (
    451   IN OUT usb3_pcd_t         *pcd,
    452   IN OUT usb3_pcd_ep_t      *ep
    453   )
    454 {
    455   UINT32                    EpIdx, DepCfg0, DepCfg1;
    456   if (ep->is_in) {
    457     EpIdx = EP_IN_IDX (ep->num);
    458   } else {
    459     EpIdx = EP_OUT_IDX (ep->num);
    460   }
    461 
    462   /* Start a new configurate when enable the first EP. */
    463   if (!pcd->eps_enabled) {
    464     pcd->eps_enabled = 1;
    465     /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first.
    466      * It resets the core's Tx FIFO mapping table.
    467      */
    468     DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL);
    469     DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
    470     DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN;
    471 
    472     switch (pcd->speed) {
    473     case USB_SPEED_SUPER:
    474       DepCfg0 |= EPCFG0_MPS (512);
    475       break;
    476     case USB_SPEED_HIGH:
    477     case USB_SPEED_FULL:
    478       DepCfg0 |= EPCFG0_MPS (64);
    479       break;
    480     case USB_SPEED_LOW:
    481       DepCfg0 |= EPCFG0_MPS (8);
    482       break;
    483     default:
    484       ASSERT (0);
    485       break;
    486     }
    487     DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0);
    488     DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2);
    489   }
    490   /* issue DEPCFG command to EP */
    491   DepCfg0 = EPCFG0_EPTYPE (ep->type);
    492   DepCfg0 |= EPCFG0_MPS (ep->maxpacket);
    493   if (ep->is_in) {
    494     DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num);
    495   }
    496   DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst);
    497   DepCfg1 = EPCFG1_EP_NUM (ep->num);
    498   if (ep->is_in) {
    499     DepCfg1 |= EPCFG1_EP_DIR_IN;
    500   } else {
    501     DepCfg1 |= EPCFG1_XFER_CMPL;
    502   }
    503   DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0);
    504   /* issue DEPSTRMCFG command to EP */
    505   DwUsb3DepXferCfg (EpIdx, 1);
    506   DwUsb3EnableEp (EpIdx, ep);
    507   ep->active = 1;
    508 }
    509 
    510 STATIC
    511 VOID
    512 DwUsb3Ep0OutStart (
    513   IN usb3_pcd_t          *pcd
    514   )
    515 {
    516   usb3_dma_desc_t        *desc;
    517 
    518   /* Get the SETUP packet DMA Descriptor (TRB) */
    519   desc = pcd->ep0_setup_desc;
    520 
    521   /* DMA Descriptor setup */
    522   DwUsb3FillDesc (
    523     desc,
    524     (UINT64)gEndPoint0SetupPacket,
    525     pcd->ep0.maxpacket,
    526     0,
    527     TRBCTL_SETUP,
    528     DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
    529     1
    530     );
    531 
    532   /* issue DEPSTRTXFER command to EP0 OUT */
    533   pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0);
    534 }
    535 
    536 STATIC
    537 VOID
    538 DwUsb3Init (
    539   VOID
    540   )
    541 {
    542   UINT32                 Data, Addr;
    543   usb3_pcd_t             *pcd = &gPcd;
    544 
    545   /* soft reset the usb core */
    546   do {
    547     MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST);
    548 
    549     do {
    550       MicroSecondDelay (1000);
    551       Data = MmioRead32 (DCTL);
    552     } while (Data & DCTL_CSFTRST);
    553     // wait for at least 3 PHY clocks
    554     MicroSecondDelay (1000);
    555   } while (0);
    556 
    557   pcd->link_state = 0;
    558 
    559   /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */
    560   MmioAndThenOr32 (GUSB2PHYCFG (0), ~GUSB2PHYCFG_USBTRDTIM_MASK, GUSB2PHYCFG_USBTRDTIM (9));
    561 
    562   /* set TX FIFO size */
    563   Addr = TX_FIFO_ADDR;
    564   DwUsb3SetFifoSize (Addr, RAM_TX0_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 0);
    565   Addr += RAM_TX0_DEPTH / RAM_WIDTH;
    566   DwUsb3SetFifoSize (Addr, RAM_TX1_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 1);
    567   /* set RX FIFO size */
    568   DwUsb3SetFifoSize (RX_FIFO_ADDR, RAM_RX_DEPTH / RAM_WIDTH, FIFO_DIR_RX, 0);
    569 
    570   /* set LFPS filter delay1trans */
    571   MmioAndThenOr32 (
    572     GUSB3PIPECTL (0),
    573     ~PIPECTL_DELAYP1TRANS,
    574     PIPECTL_LFPS_FILTER | PIPECTL_TX_DEMPH (1)
    575     );
    576 
    577   /* set GCTL */
    578   Data = GCTL_U2EXIT_LFPS | GCTL_PRTCAPDIR_DEVICE | GCTL_U2RSTECN |
    579          GCTL_PWRDNSCALE(2);
    580   MmioWrite32 (GCTL, Data);
    581 
    582   /* init event buf */
    583   MmioWrite32 (GEVNTADRL(0), (UINT32)(UINTN)gEventBuf);
    584   MmioWrite32 (GEVNTADRH(0), (UINTN)gEventBuf >> 32);
    585   MmioWrite32 (GEVNTSIZ(0), DWUSB3_EVENT_BUF_SIZE << 2);
    586   MmioWrite32 (GEVNTCOUNT(0), 0);
    587 
    588   /* set max speed to super speed */
    589   MmioAndThenOr32 (
    590     DCFG,
    591     ~DCFG_DEVSPD_MASK,
    592     DCFG_DEVSPD (DEVSPD_SS_PHY_125MHZ_OR_250MHZ)
    593     );
    594 
    595   /* set nump */
    596   MmioAndThenOr32 (DCFG, ~DCFG_NUMP_MASK, DCFG_NUMP (16));
    597 
    598   /* init address */
    599   SET_DEVADDR (0);
    600 
    601   /* disable phy suspend */
    602   MmioAnd32 (GUSB3PIPECTL (0), ~PIPECTL_SUSPEND_EN);
    603   MmioAnd32 (GUSB2PHYCFG (0), ~GUSB2PHYCFG_SUSPHY);
    604 
    605   /* clear any pending interrupts */
    606 #if 0
    607   CLEAR_EVENTBUF ();
    608 #else
    609   Data = MmioRead32 (GEVNTCOUNT (0));
    610   MmioWrite32 (GEVNTCOUNT (0), Data);
    611 #endif
    612   /* enable device interrupts */
    613   MmioWrite32 (DEVTEN, DEVTEN_CONNECTDONEEN | DEVTEN_USBRSTEN);
    614   /* activate EP0 */
    615   DwUsb3Ep0Activate (pcd);
    616   /* start EP0 to receive SETUP packets */
    617   DwUsb3Ep0OutStart (pcd);
    618 
    619   /* enable EP0 OUT/IN in DALEPENA */
    620   MmioWrite32 (DALEPENA, (1 << EP_OUT_IDX (0)) | (1 << EP_IN_IDX (0)));
    621 
    622   /* set RUN/STOP bit */
    623   MmioOr32 (DCTL, DCTL_RUN_STOP);
    624 }
    625 
    626 #define ALIGN(x, a)     (((x) + ((a) - 1)) & ~((a) - 1))
    627 
    628 STATIC
    629 VOID
    630 DriverInit (
    631   VOID
    632   )
    633 {
    634   usb3_pcd_t          *pcd = &gPcd;
    635   usb3_pcd_ep_t       *ep;
    636 
    637   pcd->speed = USB_SPEED_UNKNOWN;
    638 
    639   // init EP0
    640   ep = &pcd->ep0;
    641   ep->pcd = pcd;
    642   ep->stopped = 1;
    643   ep->is_in = 0;
    644   ep->active = 0;
    645   ep->phys = 0;
    646   ep->num = 0;
    647   ep->tx_fifo_num = 0;
    648   ep->type = EPTYPE_CONTROL;
    649   ep->maxburst = 0;
    650   ep->maxpacket = USB3_MAX_EP0_SIZE;
    651   ep->send_zlp = 0;
    652   ep->req.length = 0;
    653   ep->req.actual = 0;
    654   pcd->ep0_req.length = 0;
    655   pcd->ep0_req.actual = 0;
    656 
    657   // init EP1 OUT
    658   ep = &pcd->out_ep;
    659   ep->pcd = pcd;
    660   ep->stopped = 1;
    661   ep->is_in = 0;
    662   ep->active = 0;
    663   ep->phys = USB3_BULK_OUT_EP << 1;
    664   ep->num = 1;
    665   ep->tx_fifo_num = 0;
    666   // bulk ep is activated
    667   ep->type = EPTYPE_BULK;
    668   ep->maxburst = 0;
    669   ep->maxpacket = USB3_MAX_PACKET_SIZE;
    670   ep->send_zlp = 0;
    671   ep->req.length = 0;
    672   ep->req.actual = 0;
    673 
    674   // init EP1 IN
    675   ep = &pcd->in_ep;
    676   ep->stopped = 1;
    677   ep->is_in = 1;
    678   ep->active = 0;
    679   ep->phys = (USB3_BULK_IN_EP << 1) | 1;
    680   ep->num = 1;
    681   ep->tx_fifo_num = USB3_BULK_IN_EP;
    682   // bulk ep is activated
    683   ep->type = EPTYPE_BULK;
    684   ep->maxburst = 0;
    685   ep->maxpacket = USB3_MAX_PACKET_SIZE;
    686   ep->send_zlp = 0;
    687   ep->req.length = 0;
    688   ep->req.actual = 0;
    689 
    690   pcd->ep0state = EP0_IDLE;
    691   pcd->ep0.maxpacket = USB3_MAX_EP0_SIZE;
    692   pcd->ep0.type = EPTYPE_CONTROL;
    693 
    694 #if 0
    695   pcd->ep0_setup_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->ep0_setup, 16);
    696   pcd->ep0_in_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->ep0_in, 16);
    697   pcd->ep0_out_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->ep0_out, 16);
    698   pcd->in_ep.ep_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->in_ep.epx_desc, 16);
    699   pcd->out_ep.ep_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->out_ep.epx_desc, 16);
    700 #else
    701   pcd->ep0_setup_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
    702   pcd->ep0_in_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
    703   pcd->ep0_out_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
    704   pcd->in_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
    705   pcd->out_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
    706 #endif
    707 }
    708 
    709 STATIC
    710 VOID
    711 DwUsb3HandleUsbResetInterrupt (
    712   IN usb3_pcd_t       *pcd
    713   )
    714 {
    715   usb3_pcd_ep_t        *ep;
    716 
    717   // clear stall on each EP
    718   ep = &pcd->in_ep;
    719   if (ep->xfer_started) {
    720     if (ep->is_in) {
    721       DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in);
    722     } else {
    723       DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out);
    724     }
    725   }
    726   if (ep->stopped) {
    727     if (ep->is_in) {
    728       DwUsb3DepClearStall (EP_IN_IDX (ep->num));
    729     } else {
    730       DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
    731     }
    732   }
    733 
    734   ep = &pcd->out_ep;
    735   if (ep->xfer_started) {
    736     if (ep->is_in) {
    737       DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in);
    738     } else {
    739       DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out);
    740     }
    741   }
    742   if (ep->stopped) {
    743     if (ep->is_in) {
    744       DwUsb3DepClearStall (EP_IN_IDX (ep->num));
    745     } else {
    746       DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
    747     }
    748   }
    749 
    750   // set device address to 0
    751   SET_DEVADDR (0);
    752 
    753   pcd->ltm_enable = 0;
    754   DEBUG ((DEBUG_INFO, "usb reset\n"));
    755 }
    756 
    757 STATIC
    758 UINT32
    759 DwUsb3GetDeviceSpeed (
    760   IN usb3_pcd_t         *pcd
    761   )
    762 {
    763   UINT32                Data, Speed;
    764 
    765   Data = MmioRead32 (DSTS);
    766   switch (DSTS_GET_DEVSPD (Data)) {
    767   case DEVSPD_HS_PHY_30MHZ_OR_60MHZ:
    768     Speed = USB_SPEED_HIGH;
    769     break;
    770   case DEVSPD_FS_PHY_30MHZ_OR_60MHZ:
    771   case DEVSPD_FS_PHY_48MHZ:
    772     Speed = USB_SPEED_FULL;
    773     break;
    774   case DEVSPD_LS_PHY_6MHZ:
    775     Speed = USB_SPEED_LOW;
    776     break;
    777   case DEVSPD_SS_PHY_125MHZ_OR_250MHZ:
    778     Speed = USB_SPEED_SUPER;
    779     break;
    780   default:
    781     DEBUG ((DEBUG_ERROR, "DwUsb3GetDeviceSpeed: invalid DSTS:0x%x\n", Data));
    782     Speed = USB_SPEED_UNKNOWN;
    783     break;
    784   }
    785   return Speed;
    786 }
    787 
    788 STATIC
    789 VOID
    790 DwUsb3PcdSetSpeed (
    791   IN usb3_pcd_t         *pcd,
    792   IN UINTN              speed
    793   )
    794 {
    795   // set the MPS of EP0 based on the connection speed
    796   switch (speed) {
    797   case USB_SPEED_SUPER:
    798     pcd->ep0.maxpacket = 512;
    799     pcd->in_ep.maxpacket = USB3_MAX_PACKET_SIZE;
    800     pcd->out_ep.maxpacket = USB3_MAX_PACKET_SIZE;
    801     break;
    802   case USB_SPEED_HIGH:
    803     pcd->ep0.maxpacket = 64;
    804     pcd->in_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE;
    805     pcd->out_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE;
    806     break;
    807   case USB_SPEED_FULL:
    808     pcd->ep0.maxpacket = 64;
    809     pcd->in_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE;
    810     pcd->out_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE;
    811     break;
    812   default:
    813     DEBUG ((DEBUG_ERROR, "invalid speed: %d\n", speed));
    814     break;
    815   }
    816 }
    817 
    818 STATIC
    819 VOID
    820 DwUsb3HandleConnectDoneInterrupt (
    821   IN usb3_pcd_t         *pcd
    822   )
    823 {
    824   usb3_pcd_ep_t         *ep0 = &pcd->ep0;
    825   UINT32                DiepCfg0, DoepCfg0, DiepCfg1, DoepCfg1;
    826   UINT32                Speed;
    827 
    828   ep0->stopped = 0;
    829   Speed = (UINT32)DwUsb3GetDeviceSpeed (pcd);
    830   pcd->speed = (UINT8)Speed;
    831 
    832   DwUsb3PcdSetSpeed (pcd, Speed);
    833   // set the MPS of EP0 based on the connection speed
    834   DiepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
    835   DiepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN;
    836   DoepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY);
    837   DoepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY;
    838 
    839   switch (Speed) {
    840   case USB_SPEED_SUPER:
    841     DiepCfg0 |= EPCFG0_MPS (512);
    842     DoepCfg0 |= EPCFG0_MPS (512);
    843     break;
    844   case USB_SPEED_HIGH:
    845   case USB_SPEED_FULL:
    846     DiepCfg0 |= EPCFG0_MPS (64);
    847     DoepCfg0 |= EPCFG0_MPS (64);
    848     break;
    849   case USB_SPEED_LOW:
    850     DiepCfg0 |= EPCFG0_MPS (8);
    851     DoepCfg0 |= EPCFG0_MPS (8);
    852     break;
    853   default:
    854     DEBUG ((DEBUG_ERROR, "DwUsb3HandleConnectDoneInterrupt: invalid speed %d\n", Speed));
    855     break;
    856   }
    857   DiepCfg0 |= EPCFG0_TXFNUM (ep0->tx_fifo_num);
    858   // issue DEPCFG command to EP0 OUT
    859   DwUsb3DepCfg (EP_OUT_IDX (0), DoepCfg0, DoepCfg1, 0);
    860   // issue DEPCFG command to EP0 IN
    861   DwUsb3DepCfg (EP_IN_IDX (0), DiepCfg0, DiepCfg1, 0);
    862   pcd->state = USB3_STATE_DEFAULT;
    863 }
    864 
    865 STATIC
    866 VOID
    867 DwUsb3HandleDeviceInterrupt (
    868   IN usb3_pcd_t       *pcd,
    869   IN UINT32           Event
    870   )
    871 {
    872   switch (Event & GEVNT_DEVT_MASK) {
    873   case GEVNT_DEVT_USBRESET:
    874     DwUsb3HandleUsbResetInterrupt (pcd);
    875     break;
    876   case GEVNT_DEVT_CONNDONE:
    877     DwUsb3HandleConnectDoneInterrupt (pcd);
    878     break;
    879   default:
    880     DEBUG ((DEBUG_ERROR, "DwUsb3HandleDeviceInterrupt: invalid event\n"));
    881     break;
    882   }
    883 }
    884 
    885 STATIC
    886 usb3_pcd_ep_t *
    887 DwUsb3GetOutEndPoint (
    888   IN usb3_pcd_t       *pcd,
    889   IN UINT32           EndPointNum
    890   )
    891 {
    892   if (EndPointNum == 0) {
    893     return &pcd->ep0;
    894   }
    895   return &pcd->out_ep;
    896 }
    897 
    898 STATIC
    899 usb3_pcd_ep_t *
    900 DwUsb3GetInEndPoint (
    901   IN usb3_pcd_t       *pcd,
    902   IN UINT32           EndPointNum
    903   )
    904 {
    905   if (EndPointNum == 0) {
    906     return &pcd->ep0;
    907   }
    908   return &pcd->in_ep;
    909 }
    910 
    911 STATIC
    912 VOID
    913 EndPoint0DoStall (
    914   IN usb3_pcd_t       *pcd
    915   )
    916 {
    917   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
    918 
    919   // stall EP0 IN & OUT simultanelusly
    920   ep0->is_in = 1;
    921   DwUsb3DepSetStall (EP_IN_IDX (0));
    922   ep0->is_in = 0;
    923   DwUsb3DepSetStall (EP_OUT_IDX (0));
    924   // prepare for the next setup transfer
    925   ep0->stopped = 1;
    926   pcd->ep0state = EP0_IDLE;
    927   DwUsb3Ep0OutStart (pcd);
    928 }
    929 
    930 STATIC
    931 VOID
    932 EndPoint0ContinueTransfer (
    933   IN usb3_pcd_t       *pcd,
    934   IN usb3_pcd_req_t   *req
    935   )
    936 {
    937   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
    938   usb3_dma_desc_t     *desc;
    939   UINT64              desc_dma;
    940   UINT8               tri;
    941 
    942   // send a 0-byte length packet after the end of transfer
    943   if (ep0->is_in) {
    944     desc = pcd->ep0_in_desc;
    945     desc_dma = (UINT64)pcd->ep0_in_desc;
    946     // DMA descriptor setup
    947     DwUsb3FillDesc (
    948       desc,
    949       (UINT64)req->bufdma,
    950       0,
    951       0,
    952       TRBCTL_NORMAL,
    953       DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
    954       1
    955       );
    956     tri = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0);
    957     ep0->tri_in = tri;
    958   }
    959 }
    960 
    961 STATIC
    962 VOID
    963 EndPoint0CompleteRequest (
    964   IN usb3_pcd_t       *pcd,
    965   IN usb3_pcd_req_t   *req,
    966   IN usb3_dma_desc_t  *desc
    967   )
    968 {
    969   usb3_pcd_ep_t      *ep = &pcd->ep0;
    970 
    971   if (req == NULL) {
    972     return;
    973   }
    974 
    975   if ((pcd->ep0state == EP0_OUT_DATA_PHASE) ||
    976       (pcd->ep0state == EP0_IN_DATA_PHASE)) {
    977     if (ep->is_in) {
    978       if (GET_DSCSTS_XFERCNT (desc->status) == 0) {
    979         pcd->ep0.is_in = 0;
    980         pcd->ep0state = EP0_OUT_WAIT_NRDY;
    981       }
    982     } else {
    983       pcd->ep0.is_in = 1;
    984       pcd->ep0state = EP0_IN_WAIT_NRDY;
    985     }
    986   }
    987 }
    988 
    989 STATIC
    990 VOID
    991 DwUsb3OsGetTrb (
    992   IN usb3_pcd_t       *pcd,
    993   IN usb3_pcd_ep_t    *ep,
    994   IN usb3_pcd_req_t   *req
    995   )
    996 {
    997   // If EP0, fill request with EP0 IN/OUT data TRB
    998   if (ep == &pcd->ep0) {
    999     if (ep->is_in) {
   1000       req->trb = pcd->ep0_in_desc;
   1001       req->trbdma = (UINT64)pcd->ep0_in_desc;
   1002     } else {
   1003       req->trb = pcd->ep0_out_desc;
   1004       req->trbdma = (UINT64)pcd->ep0_out_desc;
   1005     }
   1006   } else {
   1007     // fill request with TRB from the non-EP0 allocation
   1008     req->trb = ep->ep_desc;
   1009     req->trbdma = (UINT64)ep->ep_desc;
   1010   }
   1011 }
   1012 
   1013 STATIC
   1014 VOID
   1015 DwUsb3EndPoint0StartTransfer (
   1016   IN usb3_pcd_t       *pcd,
   1017   IN usb3_pcd_req_t   *req
   1018   )
   1019 {
   1020   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
   1021   usb3_dma_desc_t     *desc;
   1022   UINT64              desc_dma;
   1023   UINT32              desc_type, len;
   1024 
   1025   // get the DMA descriptor (TRB) for this request
   1026   DwUsb3OsGetTrb (pcd, ep0, req);
   1027   desc = req->trb;
   1028   desc_dma = req->trbdma;
   1029 
   1030   if (ep0->is_in) {
   1031     // start DMA on EP0 IN
   1032     // DMA Descriptor (TRB) setup
   1033     len = req->length;
   1034     if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
   1035       if (ep0->three_stage) {
   1036         desc_type = TRBCTL_STATUS_3;
   1037       } else {
   1038         desc_type = TRBCTL_STATUS_2;
   1039       }
   1040     } else {
   1041       desc_type = TRBCTL_CTLDATA_1ST;
   1042     }
   1043     DwUsb3FillDesc (
   1044       desc,
   1045       (UINT64)req->bufdma,
   1046       len,
   1047       0,
   1048       desc_type,
   1049       DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
   1050       1
   1051       );
   1052     // issue DEPSTRTXFER command to EP0 IN
   1053     ep0->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0);
   1054   } else {
   1055     // start DMA on EP0 OUT
   1056     // DMA Descriptor (TRB) setup
   1057     len = ALIGN (req->length, ep0->maxpacket);
   1058     if (pcd->ep0state == EP0_OUT_STATUS_PHASE) {
   1059       if (ep0->three_stage) {
   1060         desc_type = TRBCTL_STATUS_3;
   1061       } else {
   1062         desc_type = TRBCTL_STATUS_2;
   1063       }
   1064     } else {
   1065       desc_type = TRBCTL_CTLDATA_1ST;
   1066     }
   1067     DwUsb3FillDesc (
   1068       desc,
   1069       (UINT64)req->bufdma,
   1070       len,
   1071       0,
   1072       desc_type,
   1073       DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
   1074       1
   1075       );
   1076     // issue DEPSTRTXFER command to EP0 OUT
   1077     ep0->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), desc_dma, 0);
   1078   }
   1079 }
   1080 
   1081 STATIC
   1082 INTN
   1083 DwUsb3EndPointXStartTransfer (
   1084   IN usb3_pcd_t       *pcd,
   1085   IN usb3_pcd_ep_t    *ep
   1086   )
   1087 {
   1088   usb3_pcd_req_t      *req = &ep->req;
   1089   usb3_dma_desc_t     *desc;
   1090   UINT64              desc_dma;
   1091   UINT32              len;
   1092 
   1093   // get the TRB for this request
   1094   DwUsb3OsGetTrb (pcd, ep, req);
   1095   desc = req->trb;
   1096   desc_dma = req->trbdma;
   1097 
   1098   if (ep->is_in) {
   1099     // For IN, TRB length is just xfer length
   1100     len = req->length;
   1101     if (ep->xfer_started && !(desc->control & DSCCTL_HWO)) {
   1102       DEBUG ((DEBUG_INFO, "[%a] last tx succ, but not in 10s!\n", __func__));
   1103       ep->xfer_started = 0;
   1104     }
   1105   } else {
   1106     // For OUT, TRB length must be multiple of maxpacket
   1107     // must be power of 2, use cheap AND
   1108     len = (req->length + ep->maxpacket - 1) & ~(ep->maxpacket - 1);
   1109     req->length = len;
   1110   }
   1111   // DMA descriptor setup
   1112   DwUsb3FillDesc (
   1113     desc,
   1114     (UINT64)req->bufdma,
   1115     len,
   1116     0,
   1117     TRBCTL_NORMAL,
   1118     DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
   1119     1
   1120     );
   1121   if (ep->is_in) {
   1122     // start DMA on EPn IN
   1123     if (ep->xfer_started) {
   1124       // issue DEPUPDTXFER command to EP
   1125       DwUsb3DepUpdateXfer (EP_IN_IDX (ep->num), ep->tri_in);
   1126     } else {
   1127       ep->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (ep->num), desc_dma, 0);
   1128       ep->xfer_started = 1;
   1129     }
   1130   } else {
   1131     // start DMA on EPn OUT
   1132     if (ep->xfer_started) {
   1133       // issue DEPUPDTXFER command to EP
   1134       DwUsb3DepUpdateXfer (EP_OUT_IDX (ep->num), ep->tri_out);
   1135     } else {
   1136       ep->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (ep->num), desc_dma, 0);
   1137       ep->xfer_started = 1;
   1138     }
   1139   }
   1140   if (ep->is_in) {
   1141     UINT32       count = 0;
   1142     // wait until send complete
   1143     while ((desc->control & DSCCTL_HWO) && (count < 1000000)) {
   1144       MicroSecondDelay (10);
   1145       count++;
   1146     }
   1147     if (count >= 1000000) {
   1148       DEBUG ((DEBUG_INFO, "[%a]: ep%d transfer timeout!\n", __func__, ep->num));
   1149       DEBUG ((DEBUG_INFO, "please disconnect then connect USB cable again to recovery!\n"));
   1150       return -1;
   1151     }
   1152     ep->xfer_started = 0;
   1153   }
   1154   return 0;
   1155 }
   1156 
   1157 #if 0
   1158 STATIC
   1159 VOID
   1160 DwUsb3EndPointXStopTransfer (
   1161   IN usb3_pcd_t       *pcd,
   1162   IN usb3_pcd_ep_t    *ep
   1163   )
   1164 {
   1165   if (ep->is_in) {
   1166     DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in);
   1167   } else {
   1168     DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out);
   1169   }
   1170 }
   1171 #endif
   1172 
   1173 STATIC
   1174 VOID
   1175 SetupInStatusPhase (
   1176   IN usb3_pcd_t       *pcd,
   1177   IN VOID             *buf
   1178   )
   1179 {
   1180   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
   1181 
   1182   if (pcd->ep0state == EP0_STALL)
   1183     return;
   1184 
   1185   ep0->is_in = 1;
   1186   pcd->ep0state = EP0_IN_STATUS_PHASE;
   1187   pcd->ep0_req.bufdma = buf;
   1188   pcd->ep0_req.length = 0;
   1189   pcd->ep0_req.actual = 0;
   1190   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   1191 }
   1192 
   1193 STATIC
   1194 VOID
   1195 SetupOutStatusPhase (
   1196   IN usb3_pcd_t       *pcd,
   1197   IN VOID             *buf
   1198   )
   1199 {
   1200   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
   1201 
   1202   if (pcd->ep0state == EP0_STALL)
   1203     return;
   1204 
   1205   ep0->is_in = 0;
   1206   pcd->ep0state = EP0_OUT_STATUS_PHASE;
   1207   pcd->ep0_req.bufdma = buf;
   1208   pcd->ep0_req.length = 0;
   1209   pcd->ep0_req.actual = 0;
   1210   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   1211 }
   1212 
   1213 STATIC
   1214 VOID
   1215 DwUsb3HandleEndPoint0 (
   1216   IN usb3_pcd_t       *pcd,
   1217   IN usb3_pcd_req_t   *req,
   1218   IN UINT32           event
   1219   )
   1220 {
   1221   usb3_pcd_ep_t       *ep0 = &pcd->ep0;
   1222   usb3_dma_desc_t     *desc;
   1223   UINT32              byte_count, len;
   1224 
   1225   switch (pcd->ep0state) {
   1226   case EP0_IN_DATA_PHASE:
   1227     if (req == NULL) {
   1228       req = &pcd->ep0_req;
   1229     }
   1230     desc = pcd->ep0_in_desc;
   1231 
   1232     if (desc->control & DSCCTL_HWO) {
   1233       goto out;
   1234     }
   1235 
   1236     if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) {
   1237       // start of a new control transfer
   1238       desc->status = 0;
   1239     }
   1240     byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status);
   1241     req->actual += byte_count;
   1242     req->bufdma += byte_count;
   1243 
   1244     if (req->actual < req->length) {
   1245       // IN CONTINUE, stall EP0
   1246       EndPoint0DoStall (pcd);
   1247     } else if (ep0->send_zlp) {
   1248       // CONTINUE TRANSFER IN ZLP
   1249       EndPoint0ContinueTransfer (pcd, req);
   1250       ep0->send_zlp = 0;
   1251     } else {
   1252       // COMPLETE IN TRANSFER
   1253       EndPoint0CompleteRequest (pcd, req, desc);
   1254     }
   1255     break;
   1256   case EP0_OUT_DATA_PHASE:
   1257     if (req == NULL) {
   1258       req = &pcd->ep0_req;
   1259     }
   1260     desc = pcd->ep0_out_desc;
   1261 
   1262     if (desc->control & DSCCTL_HWO) {
   1263       goto out;
   1264     }
   1265 
   1266     if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) {
   1267       // start of a new control transfer
   1268       desc->status = 0;
   1269     }
   1270     len = (req->length + ep0->maxpacket - 1) & ~(ep0->maxpacket - 1);
   1271     byte_count = len - GET_DSCSTS_XFERCNT (desc->status);
   1272     req->actual += byte_count;
   1273     req->bufdma += byte_count;
   1274 
   1275     if (req->actual < req->length) {
   1276       // IN CONTINUE, stall EP0
   1277       EndPoint0DoStall (pcd);
   1278     } else if (ep0->send_zlp) {
   1279       // CONTINUE TRANSFER IN ZLP
   1280       EndPoint0ContinueTransfer (pcd, req);
   1281       ep0->send_zlp = 0;
   1282     } else {
   1283       // COMPLETE IN TRANSFER
   1284       EndPoint0CompleteRequest (pcd, req, desc);
   1285     }
   1286     break;
   1287 #if 0
   1288   case EP0_IN_WAIT_NRDY:
   1289   case EP0_OUT_WAIT_NRDY:
   1290     if (ep0->is_in) {
   1291       SetupInStatusPhase (pcd, gEndPoint0SetupPacket);
   1292     } else {
   1293       SetupOutStatusPhase (pcd, gEndPoint0SetupPacket);
   1294     }
   1295     break;
   1296   case EP0_IN_STATUS_PHASE:
   1297   case EP0_OUT_STATUS_PHASE:
   1298     if (ep0->is_in) {
   1299       desc = pcd->ep0_in_desc;
   1300     } else {
   1301       desc = pcd->ep0_out_desc;
   1302     }
   1303 //ASSERT (0);
   1304     EndPoint0CompleteRequest (pcd, req, desc);
   1305     // skip test mode
   1306     pcd->ep0state = EP0_IDLE;
   1307     ep0->stopped = 1;
   1308     ep0->is_in = 0;  // OUT for next SETUP
   1309     // prepare for more SETUP packets
   1310     DwUsb3Ep0OutStart (pcd);
   1311     break;
   1312 #else
   1313   case EP0_IN_WAIT_NRDY:
   1314     if (ep0->is_in) {
   1315       SetupInStatusPhase (pcd, gEndPoint0SetupPacket);
   1316     } else {
   1317       ASSERT (0);
   1318     }
   1319     break;
   1320   case EP0_OUT_WAIT_NRDY:
   1321     if (!ep0->is_in) {
   1322       SetupOutStatusPhase (pcd, gEndPoint0SetupPacket);
   1323     } else {
   1324       ASSERT (0);
   1325     }
   1326     break;
   1327   case EP0_IN_STATUS_PHASE:
   1328     if (ep0->is_in) {
   1329       desc = pcd->ep0_in_desc;
   1330     } else {
   1331       ASSERT (0);
   1332     }
   1333     EndPoint0CompleteRequest (pcd, req, desc);
   1334     pcd->ep0state = EP0_IDLE;
   1335     ep0->stopped = 1;
   1336     ep0->is_in = 0;  // OUT for next SETUP
   1337     // prepare for more SETUP packets
   1338     DwUsb3Ep0OutStart (pcd);
   1339     break;
   1340   case EP0_OUT_STATUS_PHASE:
   1341     if (!ep0->is_in) {
   1342       desc = pcd->ep0_out_desc;
   1343     } else {
   1344       ASSERT (0);
   1345     }
   1346     EndPoint0CompleteRequest (pcd, req, desc);
   1347     pcd->ep0state = EP0_IDLE;
   1348     ep0->stopped = 1;
   1349     ep0->is_in = 0;  // OUT for next SETUP
   1350     // prepare for more SETUP packets
   1351     DwUsb3Ep0OutStart (pcd);
   1352     break;
   1353 #endif
   1354   case EP0_STALL:
   1355     break;
   1356   case EP0_IDLE:
   1357     break;
   1358   default:
   1359     DEBUG ((DEBUG_ERROR, "%a: invalid state %d\n", __func__, pcd->ep0state));
   1360     break;
   1361   }
   1362 out:
   1363   return;
   1364 }
   1365 
   1366 STATIC
   1367 usb3_pcd_ep_t *
   1368 Addr2EndPoint (
   1369   IN usb3_pcd_t       *pcd,
   1370   IN UINT16           index
   1371   )
   1372 {
   1373   UINT32              ep_num;
   1374 
   1375   ep_num = UE_GET_ADDR (index);
   1376   if (ep_num == 0) {
   1377     return &pcd->ep0;
   1378   } else {
   1379     if (UE_GET_DIR (index) == UE_DIR_IN) {
   1380       return &pcd->in_ep;
   1381     }
   1382     return &pcd->out_ep;
   1383   }
   1384 }
   1385 
   1386 STATIC
   1387 VOID
   1388 DwUsb3DoGetStatus (
   1389   IN usb3_pcd_t       *pcd
   1390   )
   1391 {
   1392   usb_device_request_t   *ctrl = &gEndPoint0SetupPacket->req;
   1393   UINT8                  *status = gEndPoint0StatusBuf;
   1394   usb3_pcd_ep_t          *ep;
   1395 
   1396   if (ctrl->wLength != 2) {
   1397     EndPoint0DoStall (pcd);
   1398     return;
   1399   }
   1400 
   1401   switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
   1402   case UT_DEVICE:
   1403     *status = 0;   // bus powered
   1404     if (pcd->speed == USB_SPEED_SUPER) {
   1405       if (pcd->state == USB3_STATE_CONFIGURED) {
   1406         if (MmioRead32 (DCTL) & DCTL_INIT_U1_EN) {
   1407           *status |= 1 << 2;
   1408         }
   1409         if (MmioRead32 (DCTL) & DCTL_INIT_U2_EN) {
   1410           *status |= 1 << 3;
   1411         }
   1412         *status |= (UINT8)(pcd->ltm_enable << 4);
   1413       }
   1414     }
   1415     *(status + 1) = 0;
   1416     break;
   1417   case UT_INTERFACE:
   1418     *status = 0;
   1419     *(status + 1) = 0;
   1420     break;
   1421   case UT_ENDPOINT:
   1422     ep = Addr2EndPoint (pcd, ctrl->wIndex);
   1423     *status = ep->stopped;
   1424     *(status + 1) = 0;
   1425     break;
   1426   default:
   1427     EndPoint0DoStall (pcd);
   1428     return;
   1429   }
   1430   pcd->ep0_req.bufdma = (UINT64 *)status;
   1431   pcd->ep0_req.length = 2;
   1432   pcd->ep0_req.actual = 0;
   1433   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   1434 }
   1435 
   1436 STATIC
   1437 VOID
   1438 DoClearHalt (
   1439   IN usb3_pcd_t       *pcd,
   1440   IN usb3_pcd_ep_t    *ep
   1441   )
   1442 {
   1443   if (ep->is_in) {
   1444     DwUsb3DepClearStall (EP_IN_IDX (ep->num));
   1445   } else {
   1446     DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
   1447   }
   1448   if (ep->stopped) {
   1449     ep->stopped = 0;
   1450   }
   1451 }
   1452 
   1453 STATIC
   1454 VOID
   1455 Usb3PcdEpEnable (
   1456   IN usb3_pcd_t        *pcd,
   1457   IN usb3_pcd_ep_t     *ep
   1458   )
   1459 {
   1460   // activate the EP
   1461   ep->stopped = 0;
   1462   ep->xfer_started = 0;
   1463   ep->ep_desc->control = 0;
   1464   ep->ep_desc->status = 0;
   1465   // set initial data pid.
   1466   if (ep->type == EPTYPE_BULK) {
   1467     ep->data_pid_start = 0;
   1468   }
   1469   DwUsb3EpActivate (pcd, ep);
   1470 }
   1471 
   1472 STATIC
   1473 VOID
   1474 DwUsb3DoClearFeature (
   1475   IN usb3_pcd_t       *pcd
   1476   )
   1477 {
   1478   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1479   usb3_pcd_ep_t  *ep;
   1480 
   1481   switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
   1482   case UT_DEVICE:
   1483     switch (ctrl->wValue) {
   1484     case UF_U1_ENABLE:
   1485       if ((pcd->speed != USB_SPEED_SUPER) ||
   1486           (pcd->state != USB3_STATE_CONFIGURED)) {
   1487         EndPoint0DoStall (pcd);
   1488         return;
   1489       }
   1490       MmioAnd32 (DCTL, ~DCTL_INIT_U1_EN);
   1491       break;
   1492     case UF_U2_ENABLE:
   1493       if ((pcd->speed != USB_SPEED_SUPER) ||
   1494           (pcd->state != USB3_STATE_CONFIGURED)) {
   1495         EndPoint0DoStall (pcd);
   1496         return;
   1497       }
   1498       MmioAnd32 (DCTL, ~DCTL_INIT_U2_EN);
   1499       break;
   1500     case UF_LTM_ENABLE:
   1501       if ((pcd->speed != USB_SPEED_SUPER) ||
   1502           (pcd->state != USB3_STATE_CONFIGURED) ||
   1503           (ctrl->wIndex != 0)) {
   1504         EndPoint0DoStall (pcd);
   1505         return;
   1506       }
   1507       pcd->ltm_enable = 0;
   1508       break;
   1509     default:
   1510       EndPoint0DoStall (pcd);
   1511       return;
   1512     }
   1513     break;
   1514   case UT_INTERFACE:
   1515     // if FUNCTION_SUSPEND
   1516     if (ctrl->wValue) {
   1517       EndPoint0DoStall (pcd);
   1518       return;
   1519     }
   1520     break;
   1521   case UT_ENDPOINT:
   1522     ep = Addr2EndPoint (pcd, ctrl->wIndex);
   1523     if (ctrl->wValue != UF_ENDPOINT_HALT) {
   1524       EndPoint0DoStall (pcd);
   1525       return;
   1526     }
   1527     DoClearHalt (pcd, ep);
   1528     break;
   1529   default:
   1530     DEBUG ((DEBUG_ERROR, "invalid bmRequestType :%d\n", UT_GET_RECIPIENT (ctrl->bmRequestType)));
   1531     break;
   1532   }
   1533   pcd->ep0.is_in = 1;
   1534   pcd->ep0state = EP0_IN_WAIT_NRDY;
   1535 }
   1536 
   1537 STATIC
   1538 VOID
   1539 DwUsb3DoSetFeature (
   1540   IN usb3_pcd_t       *pcd
   1541   )
   1542 {
   1543   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1544   usb3_pcd_ep_t  *ep;
   1545 
   1546   switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) {
   1547   case UT_DEVICE:
   1548     switch (ctrl->wValue) {
   1549     case UF_DEVICE_REMOTE_WAKEUP:
   1550       break;
   1551     case UF_TEST_MODE:
   1552       pcd->test_mode_nr = ctrl->wIndex >> 8;
   1553       pcd->test_mode = 1;
   1554       break;
   1555     case UF_U1_ENABLE:
   1556       if ((pcd->speed != USB_SPEED_SUPER) ||
   1557           (pcd->state != USB3_STATE_CONFIGURED)) {
   1558         EndPoint0DoStall (pcd);
   1559         return;
   1560       }
   1561       MmioOr32 (DCTL, DCTL_INIT_U1_EN);
   1562       break;
   1563     case UF_U2_ENABLE:
   1564       if ((pcd->speed != USB_SPEED_SUPER) ||
   1565           (pcd->state != USB3_STATE_CONFIGURED)) {
   1566         EndPoint0DoStall (pcd);
   1567         return;
   1568       }
   1569       MmioOr32 (DCTL, DCTL_INIT_U2_EN);
   1570       break;
   1571     case UF_LTM_ENABLE:
   1572       if ((pcd->speed != USB_SPEED_SUPER) ||
   1573           (pcd->state != USB3_STATE_CONFIGURED) ||
   1574           (ctrl->wIndex != 0)) {
   1575         EndPoint0DoStall (pcd);
   1576         return;
   1577       }
   1578       pcd->ltm_enable = 1;
   1579       break;
   1580     default:
   1581       EndPoint0DoStall (pcd);
   1582       return;
   1583     }
   1584     break;
   1585   case UT_INTERFACE:
   1586     // if FUNCTION_SUSPEND
   1587     if (ctrl->wValue) {
   1588       EndPoint0DoStall (pcd);
   1589       return;
   1590     }
   1591     break;
   1592   case UT_ENDPOINT:
   1593     ep = Addr2EndPoint (pcd, ctrl->wIndex);
   1594     if (ctrl->wValue != UF_ENDPOINT_HALT) {
   1595       EndPoint0DoStall (pcd);
   1596       return;
   1597     }
   1598     ep->stopped = 1;
   1599     if (ep->is_in) {
   1600       DwUsb3DepClearStall (EP_IN_IDX (ep->num));
   1601     } else {
   1602       DwUsb3DepClearStall (EP_OUT_IDX (ep->num));
   1603     }
   1604     break;
   1605   default:
   1606     DEBUG ((DEBUG_ERROR, "invalid bmRequestType %d\n", UT_GET_RECIPIENT (ctrl->bmRequestType)));
   1607     break;
   1608   }
   1609   pcd->ep0.is_in = 1;
   1610   pcd->ep0state = EP0_IN_WAIT_NRDY;
   1611 }
   1612 
   1613 STATIC
   1614 VOID
   1615 DwUsb3DoSetAddress (
   1616   IN usb3_pcd_t          *pcd
   1617   )
   1618 {
   1619   usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req;
   1620 
   1621   if (ctrl->bmRequestType == UT_DEVICE) {
   1622     SET_DEVADDR (ctrl->wValue);
   1623     pcd->ep0.is_in = 1;
   1624     pcd->ep0state = EP0_IN_WAIT_NRDY;
   1625     if (ctrl->wValue) {
   1626       pcd->state = USB3_STATE_ADDRESSED;
   1627     } else {
   1628       pcd->state = USB3_STATE_DEFAULT;
   1629     }
   1630   }
   1631 }
   1632 
   1633 #if 0
   1634 STATIC
   1635 UINTN
   1636 UsbStatus (
   1637   IN UINTN                        online,
   1638   IN UINTN                        speed
   1639   )
   1640 {
   1641   if (online) {
   1642 }
   1643 
   1644 VOID
   1645 DwUsb3SetConfig (
   1646   IN usb3_pcd_t           *pcd
   1647   )
   1648 {
   1649   usb_device_request_t   *ctrl = &gEndPoint0SetupPacket->req;
   1650   UINT16         wvalue = ctrl->wValue;
   1651   usb3_pcd_ep_t     *ep;
   1652 
   1653 DEBUG ((DEBUG_ERROR, "#%a, %d, wvalue:0x%x\n", __func__, __LINE__, wvalue));
   1654   if (ctrl->bmRequestType != (UT_WRITE | UT_STANDARD | UT_DEVICE)) {
   1655     EndPoint0DoStall (pcd);
   1656     return;
   1657   }
   1658 
   1659   if (!wvalue || (wvalue == CONFIG_VALUE)) {
   1660     UINT32         speed;
   1661     pcd->new_config = (UINT8)wvalue;
   1662     // set new configuration
   1663     if (wvalue) {
   1664       // activate bulk in endpoint
   1665       ep = &pcd->in_ep;
   1666       Usb3PcdEpEnable (pcd, ep);
   1667       // activate bulk out endpoint
   1668       ep = &pcd->out_ep;
   1669       Usb3PcdEpEnable (pcd, ep);
   1670       // prepare for next bulk transfer
   1671       speed = DwUsb3GetDeviceSpeed (pcd);
   1672       (VOID)speed;
   1673 
   1674 #if 0
   1675       if (g_usb_ops->status) {
   1676         g_usb_ops->status (ctrl->wValue ? 1 : 0,
   1677                            speed == USB_SPEED_SUPER ? USB_SS : speed == USB_SPEED_HIGH ? USB_HS : USB_FS);
   1678       }
   1679       usb_status ();
   1680 #endif
   1681       pcd->state = USB3_STATE_CONFIGURED;
   1682     } else {
   1683       pcd->state = USB3_STATE_ADDRESSED;
   1684     }
   1685 DEBUG ((DEBUG_ERROR, "#%a, %d, state:%d\n", __func__, __LINE__, pcd->state));
   1686     pcd->ep0.is_in = 1;
   1687     pcd->ep0state = EP0_IN_WAIT_NRDY;
   1688   } else {
   1689     EndPoint0DoStall (pcd);
   1690   }
   1691 }
   1692 #endif
   1693 
   1694 STATIC
   1695 VOID
   1696 DwUsb3DoGetConfig (
   1697   IN usb3_pcd_t       *pcd
   1698   )
   1699 {
   1700   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1701   UINT8  *status = gEndPoint0StatusBuf;
   1702 
   1703   if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) {
   1704     EndPoint0DoStall (pcd);
   1705     return;
   1706   }
   1707   // Notify host the current config value
   1708   *status = pcd->new_config;
   1709   pcd->ep0_req.bufdma = (UINT64 *)status;
   1710   pcd->ep0_req.length = 1;
   1711   pcd->ep0_req.actual = 0;
   1712   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   1713 }
   1714 
   1715 STATIC
   1716 VOID
   1717 DwUsb3DoSetConfig (
   1718   IN usb3_pcd_t       *pcd
   1719   )
   1720 {
   1721   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1722   UINT16  wvalue = ctrl->wValue;
   1723   usb3_pcd_ep_t  *ep;
   1724 
   1725   if (ctrl->bmRequestType != (UT_WRITE | UT_STANDARD | UT_DEVICE)) {
   1726     EndPoint0DoStall (pcd);
   1727     return;
   1728   }
   1729 
   1730   if (!wvalue || (wvalue == CONFIG_VALUE)) {
   1731     //UINT32 speed;
   1732 
   1733     pcd->new_config = (UINT8)wvalue;
   1734     // set new configuration
   1735     if (wvalue) {
   1736       // activate bulk in endpoint
   1737       ep = &pcd->in_ep;
   1738       Usb3PcdEpEnable (pcd, ep);
   1739       // activate bulk out endpoint
   1740       ep = &pcd->out_ep;
   1741       Usb3PcdEpEnable (pcd, ep);
   1742 #if 0
   1743       // prepare for next bulk transfer
   1744       speed = DwUsb3GetDeviceSpeed (pcd);
   1745       (VOID)speed;
   1746       g_usb_ops->status
   1747 #endif
   1748       pcd->state = USB3_STATE_CONFIGURED;
   1749       {
   1750         // prepare for EP1 OUT
   1751         usb3_pcd_ep_t                 *ep = &pcd->out_ep;
   1752         usb3_pcd_req_t                *req = &ep->req;
   1753 
   1754         // AndroidFast App will free the rx buffer.
   1755         gRxBuf = AllocatePool (DATA_SIZE);
   1756         ASSERT (gRxBuf != NULL);
   1757         WriteBackDataCacheRange (gRxBuf, DATA_SIZE);
   1758         req->bufdma = (UINT64 *)gRxBuf;
   1759         if (mDataBufferSize == 0) {
   1760           req->length = CMD_SIZE;
   1761         } else if (mDataBufferSize > DATA_SIZE) {
   1762           req->length = DATA_SIZE;
   1763           mDataBufferSize = mDataBufferSize - DATA_SIZE;
   1764         } else if (mDataBufferSize > CMD_SIZE) {
   1765           req->length = CMD_SIZE;
   1766           mDataBufferSize = mDataBufferSize - CMD_SIZE;
   1767         } else {
   1768           req->length = mDataBufferSize;
   1769           mDataBufferSize = 0;
   1770         }
   1771         DwUsb3EndPointXStartTransfer (pcd, ep);
   1772       }
   1773     } else {
   1774       pcd->state = USB3_STATE_ADDRESSED;
   1775     }
   1776     pcd->ep0.is_in = 1;
   1777     pcd->ep0state = EP0_IN_WAIT_NRDY;
   1778   } else {
   1779     EndPoint0DoStall (pcd);
   1780   }
   1781 }
   1782 
   1783 STATIC
   1784 VOID
   1785 DwUsb3DoGetDescriptor (
   1786   IN usb3_pcd_t       *pcd
   1787   )
   1788 {
   1789   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1790   UINT8                 dt = ctrl->wValue >> 8;
   1791   UINT8                 index = (UINT8)ctrl->wValue;
   1792   UINT16                len = ctrl->wLength;
   1793   UINT8                 *buf = gEndPoint0StatusBuf;
   1794   UINT16                value = 0;
   1795   EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;
   1796 
   1797   if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) {
   1798     EndPoint0DoStall (pcd);
   1799     return;
   1800   }
   1801 
   1802   switch (dt) {
   1803   case UDESC_DEVICE:
   1804     {
   1805       struct usb_device_descriptor  *dev = &gDwUsb3DevDesc;
   1806       dev->bLength = sizeof (struct usb_device_descriptor);
   1807       dev->bDescriptorType = UDESC_DEVICE;
   1808       dev->bDeviceClass = 0;
   1809       dev->bDeviceSubClass = 0;
   1810       dev->bDeviceProtocol = 0;
   1811       if (pcd->speed == USB_SPEED_SUPER) {
   1812         dev->bcdUSB = 0x300;
   1813         // 2^9 = 512
   1814         dev->bMaxPacketSize0 = 9;
   1815       } else {
   1816         dev->bcdUSB = 0x0200;
   1817         dev->bMaxPacketSize0 = 0x40;
   1818       }
   1819       dev->idVendor = usb_port_activity_config.idVendor;
   1820       dev->idProduct = usb_port_activity_config.idProduct;
   1821       dev->bcdDevice = 0x0100;
   1822       dev->iManufacturer = STRING_MANUFACTURER;
   1823       dev->iProduct = STRING_PRODUCT;
   1824       dev->iSerialNumber = STRING_SERIAL;
   1825       dev->bNumConfigurations = 1;
   1826       value = sizeof (struct usb_device_descriptor);
   1827       CopyMem ((void *)buf, (void *)dev, value);
   1828     }
   1829     break;
   1830   case UDESC_DEVICE_QUALIFIER:
   1831     {
   1832       struct usb_qualifier_descriptor   *qual = (struct usb_qualifier_descriptor *)buf;
   1833       struct usb_device_descriptor *dev = &gDwUsb3DevDesc;
   1834 
   1835       qual->bLength = sizeof (*qual);
   1836       qual->bDescriptorType = UDESC_DEVICE_QUALIFIER;
   1837       qual->bcdUSB = dev->bcdUSB;
   1838       qual->bDeviceClass = dev->bDeviceClass;
   1839       qual->bDeviceSubClass = dev->bDeviceSubClass;
   1840       qual->bDeviceProtocol = dev->bDeviceProtocol;
   1841       qual->bMaxPacketSize0 = dev->bMaxPacketSize0;
   1842       qual->bNumConfigurations = 1;
   1843       qual->bRESERVED = 0;
   1844       value = sizeof (struct usb_qualifier_descriptor);
   1845     }
   1846     break;
   1847 
   1848   case UDESC_CONFIG:
   1849     {
   1850       struct usb_config_descriptor    *config = (struct usb_config_descriptor *)buf;
   1851 
   1852       config->bLength = sizeof (*config);
   1853       config->bDescriptorType = UDESC_CONFIG;
   1854       config->bNumInterfaces = 1;
   1855       config->bConfigurationValue = 1;
   1856       config->iConfiguration = 0;
   1857       config->bmAttributes = USB_CONFIG_ATT_ONE;
   1858 
   1859       if (pcd->speed == USB_SPEED_SUPER) {
   1860         config->bMaxPower = 0x50;
   1861       } else {
   1862         config->bMaxPower = 0x80;
   1863       }
   1864       buf += sizeof (*config);
   1865 
   1866       intf.bInterfaceSubClass = usb_port_activity_config.bInterfaceSubClass;
   1867       intf.bInterfaceProtocol = usb_port_activity_config.bInterfaceProtocol;
   1868       CopyMem ((void *)buf, (void *)&intf, sizeof (intf));
   1869       buf += sizeof (intf);
   1870 
   1871       switch (pcd->speed) {
   1872       case USB_SPEED_SUPER:
   1873         CopyMem (buf, &ss_bulk_in, sizeof (ss_bulk_in));
   1874         buf += sizeof (ss_bulk_in);
   1875         CopyMem (buf, &ep_comp, sizeof (ep_comp));
   1876         buf += sizeof (ep_comp);
   1877         CopyMem (buf, &ss_bulk_out, sizeof (ss_bulk_out));
   1878         buf += sizeof (ss_bulk_out);
   1879         CopyMem (buf, &ep_comp, sizeof (ep_comp));
   1880 
   1881         config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (ss_bulk_in) +
   1882                                sizeof (ep_comp) + sizeof (ss_bulk_out) + sizeof (ep_comp);
   1883         break;
   1884 
   1885       default: // HS/FS
   1886         {
   1887           struct usb_endpoint_descriptor  *endp = (struct usb_endpoint_descriptor *)buf;
   1888 
   1889           CopyMem (buf, &hs_bulk_in, sizeof (hs_bulk_in));
   1890           (endp++)->wMaxPacketSize = pcd->in_ep.maxpacket;
   1891           buf += sizeof (hs_bulk_in);
   1892           CopyMem (buf, &hs_bulk_out, sizeof (hs_bulk_out));
   1893           endp->wMaxPacketSize = pcd->out_ep.maxpacket;
   1894           config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (hs_bulk_in) +
   1895                                  sizeof (hs_bulk_out);
   1896           break;
   1897         }
   1898       }
   1899       value = config->wTotalLength;
   1900     }
   1901     break;
   1902 
   1903   case UDESC_STRING:
   1904     {
   1905       switch (index) {
   1906       case STRING_LANGUAGE:
   1907         Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
   1908         ASSERT (Descriptor != NULL);
   1909         Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
   1910         Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
   1911         DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
   1912         value = Descriptor->Length;
   1913         break;
   1914       case STRING_MANUFACTURER:
   1915         Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
   1916         ASSERT (Descriptor != NULL);
   1917         Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
   1918         Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
   1919         DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
   1920         value = Descriptor->Length;
   1921         break;
   1922       case STRING_PRODUCT:
   1923         Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
   1924         ASSERT (Descriptor != NULL);
   1925         Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
   1926         Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
   1927         DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
   1928         value = Descriptor->Length;
   1929         break;
   1930       case STRING_SERIAL:
   1931         Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf;
   1932         ASSERT (Descriptor != NULL);
   1933         Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
   1934         Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
   1935         DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
   1936         value = Descriptor->Length;
   1937         break;
   1938       default:
   1939         EndPoint0DoStall (pcd);
   1940         break;
   1941       }
   1942     }
   1943     break;
   1944 
   1945   case UDESC_BOS:
   1946     if (pcd->speed != USB_SPEED_SUPER) {
   1947       EndPoint0DoStall (pcd);
   1948       return;
   1949     }
   1950     value = bos.wTotalLength;
   1951     CopyMem (buf, &bos, sizeof (bos));
   1952     buf += sizeof (bos);
   1953     CopyMem (buf, &cap1, sizeof (cap1));
   1954     buf += sizeof (cap1);
   1955     CopyMem (buf, &cap2, sizeof (cap2));
   1956     buf += sizeof (cap2);
   1957     CopyMem (buf, &cap3, sizeof (cap3));
   1958     break;
   1959   default:
   1960     EndPoint0DoStall (pcd);
   1961     return;
   1962   }
   1963   pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf;
   1964   pcd->ep0_req.length = value < len ? value : len;
   1965   pcd->ep0_req.actual = 0;
   1966   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   1967 }
   1968 
   1969 STATIC
   1970 VOID
   1971 DwUsb3DoSetup (
   1972   IN usb3_pcd_t       *pcd
   1973   )
   1974 {
   1975   usb_device_request_t  *ctrl = &gEndPoint0SetupPacket->req;
   1976   usb3_pcd_ep_t         *ep0 = &pcd->ep0;
   1977   UINT16                wLength;
   1978 
   1979   wLength = ctrl->wLength;
   1980   ep0->stopped = 0;
   1981   ep0->three_stage = 1;
   1982   if (ctrl->bmRequestType & UE_DIR_IN) {
   1983     ep0->is_in = 1;
   1984     pcd->ep0state = EP0_IN_DATA_PHASE;
   1985   } else {
   1986     ep0->is_in = 0;
   1987     pcd->ep0state = EP0_OUT_DATA_PHASE;
   1988   }
   1989 
   1990   if (wLength == 0) {
   1991     ep0->is_in = 1;
   1992     pcd->ep0state = EP0_IN_WAIT_NRDY;
   1993     ep0->three_stage = 0;
   1994   }
   1995   if (UT_GET_TYPE (ctrl->bmRequestType) != UT_STANDARD) {
   1996     EndPoint0DoStall (pcd);
   1997     return;
   1998   }
   1999 
   2000   switch (ctrl->bRequest) {
   2001   case UR_GET_STATUS:
   2002     DwUsb3DoGetStatus (pcd);
   2003     break;
   2004   case UR_CLEAR_FEATURE:
   2005     DwUsb3DoClearFeature (pcd);
   2006     break;
   2007   case UR_SET_FEATURE:
   2008     DwUsb3DoSetFeature (pcd);
   2009     break;
   2010   case UR_SET_ADDRESS:
   2011     DwUsb3DoSetAddress (pcd);
   2012     break;
   2013   case UR_SET_CONFIG:
   2014     DwUsb3DoSetConfig (pcd);
   2015     MmioOr32 (DCTL, DCTL_ACCEPT_U1_EN);
   2016     MmioOr32 (DCTL, DCTL_ACCEPT_U2_EN);
   2017     DEBUG ((DEBUG_INFO, "enum done"));
   2018     pcd->ltm_enable = 0;
   2019     break;
   2020   case UR_GET_CONFIG:
   2021     DwUsb3DoGetConfig (pcd);
   2022     break;
   2023   case UR_GET_DESCRIPTOR:
   2024     DwUsb3DoGetDescriptor (pcd);
   2025     break;
   2026   case UR_SET_SEL:
   2027     // for now this is a no-op
   2028     pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf;
   2029     pcd->ep0_req.length = USB3_STATUS_BUF_SIZE;
   2030     pcd->ep0_req.actual = 0;
   2031     ep0->send_zlp = 0;
   2032     DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
   2033     break;
   2034   default:
   2035     EndPoint0DoStall (pcd);
   2036     break;
   2037   }
   2038 }
   2039 
   2040 STATIC
   2041 VOID
   2042 DwUsb3OsHandleEndPoint0 (
   2043   IN usb3_pcd_t       *pcd,
   2044   IN UINT32           event
   2045   )
   2046 {
   2047   if (pcd->ep0state == EP0_IDLE) {
   2048     DwUsb3DoSetup (pcd);
   2049   } else {
   2050     DwUsb3HandleEndPoint0 (pcd, NULL, event);
   2051   }
   2052 }
   2053 
   2054 STATIC
   2055 VOID
   2056 DwUsb3RequestDone (
   2057   IN usb3_pcd_t       *pcd,
   2058   IN usb3_pcd_ep_t    *ep,
   2059   IN usb3_pcd_req_t   *req,
   2060   IN UINTN            status
   2061   )
   2062 {
   2063   if (ep != &pcd->ep0) {
   2064     req->trb = NULL;
   2065   }
   2066   if (req->complete) {
   2067     req->complete (req->actual, status);
   2068   } else {
   2069     if (!ep->is_in) {
   2070       ASSERT (req->actual <= req->length);
   2071       InvalidateDataCacheRange (gRxBuf, req->actual);
   2072       mDataReceivedCallback (req->actual, gRxBuf);
   2073     }
   2074   }
   2075   req->actual = 0;
   2076 }
   2077 
   2078 STATIC
   2079 VOID
   2080 DwUsb3EndPointcompleteRequest (
   2081   IN usb3_pcd_t       *pcd,
   2082   IN usb3_pcd_ep_t    *ep,
   2083   IN UINT32           event
   2084   )
   2085 {
   2086   usb3_pcd_req_t           *req = &ep->req;
   2087   usb3_dma_desc_t          *desc = req->trb;
   2088   UINT32 byte_count;
   2089 
   2090   ep->send_zlp = 0;
   2091   if (!desc) {
   2092     return;
   2093   }
   2094 
   2095   if (desc->control & DSCCTL_HWO) {
   2096     return;
   2097   }
   2098 
   2099   if (ep->is_in) {
   2100     // IN ep
   2101     if (GET_DSCSTS_XFERCNT (desc->status) == 0) {
   2102       req->actual += req->length;
   2103     }
   2104     // reset IN tri
   2105     ep->tri_in = 0;
   2106     // complete the IN request
   2107     // flush for dma?
   2108     DwUsb3RequestDone (pcd, ep, req, 0);
   2109   } else {
   2110     // OUT ep
   2111     byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status);
   2112     req->actual += byte_count;
   2113     //req->bufdma += byte_count;
   2114     // reset OUT tri
   2115     ep->tri_out = 0;
   2116     // OUT transfer complete or not
   2117     // complete the OUT request
   2118     // FIXME flush dma?
   2119     DwUsb3RequestDone (pcd, ep, req, 0);
   2120     {
   2121       // prepare for EP1 OUT
   2122       usb3_pcd_ep_t                 *ep = &pcd->out_ep;
   2123       usb3_pcd_req_t                *req = &ep->req;
   2124 
   2125       ZeroMem (req, sizeof (usb3_pcd_req_t));
   2126       gRxBuf = AllocatePool (DATA_SIZE);
   2127       ASSERT (gRxBuf != NULL);
   2128       WriteBackDataCacheRange (gRxBuf, DATA_SIZE);
   2129       req->bufdma = (UINT64 *)gRxBuf;
   2130       if (mDataBufferSize == 0) {
   2131         req->length = CMD_SIZE;
   2132       } else if (mDataBufferSize > DATA_SIZE) {
   2133         req->length = DATA_SIZE;
   2134         mDataBufferSize = mDataBufferSize - DATA_SIZE;
   2135       } else if (mDataBufferSize > CMD_SIZE) {
   2136         req->length = CMD_SIZE;
   2137         mDataBufferSize = mDataBufferSize - CMD_SIZE;
   2138       } else {
   2139         req->length = mDataBufferSize;
   2140         mDataBufferSize = 0;
   2141       }
   2142       DwUsb3EndPointXStartTransfer (pcd, ep);
   2143     }
   2144   }
   2145 }
   2146 
   2147 STATIC
   2148 VOID
   2149 DwUsb3HandleEndPointInterrupt (
   2150   IN usb3_pcd_t       *pcd,
   2151   IN UINTN            PhySep,
   2152   IN UINT32           event
   2153   )
   2154 {
   2155   usb3_pcd_ep_t       *ep;
   2156   UINT32              epnum, is_in;
   2157 
   2158   // Physical Out EPs are even, physical In EPs are odd
   2159   is_in = (UINT32)PhySep & 1;
   2160   epnum = ((UINT32)PhySep >> 1) & 0xF;
   2161 
   2162   // Get the EP pointer
   2163   if (is_in) {
   2164     ep = DwUsb3GetInEndPoint (pcd, epnum);
   2165   } else {
   2166     ep = DwUsb3GetOutEndPoint (pcd, epnum);
   2167   }
   2168 
   2169   switch (event & GEVNT_DEPEVT_INTTYPE_MASK) {
   2170   case GEVNT_DEPEVT_INTTYPE_XFER_CMPL:
   2171     ep->xfer_started = 0;
   2172     // complete the transfer
   2173     if (epnum == 0) {
   2174       DwUsb3OsHandleEndPoint0 (pcd, event);
   2175     } else {
   2176       DwUsb3EndPointcompleteRequest (pcd, ep, event);
   2177     }
   2178     break;
   2179   case GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG:
   2180     break;
   2181   case GEVNT_DEPEVT_INTTYPE_XFER_NRDY:
   2182     if (epnum == 0) {
   2183       switch (pcd->ep0state) {
   2184 #if 1
   2185       case EP0_IN_WAIT_NRDY:
   2186         if (is_in) {
   2187           DwUsb3OsHandleEndPoint0 (pcd, event);
   2188         } else {
   2189         }
   2190         break;
   2191       case EP0_OUT_WAIT_NRDY:
   2192         if (!is_in) {
   2193           DwUsb3OsHandleEndPoint0 (pcd, event);
   2194         } else {
   2195         }
   2196         break;
   2197 #else
   2198       case EP0_IN_WAIT_NRDY:
   2199       case EP0_OUT_WAIT_NRDY:
   2200         DwUsb3OsHandleEndPoint0 (pcd, event);
   2201         break;
   2202 #endif
   2203       default:
   2204         break;
   2205       }
   2206     } else {
   2207     }
   2208     break;
   2209   default:
   2210     DEBUG ((DEBUG_ERROR, "invalid event %d\n", event & GEVNT_DEPEVT_INTTYPE_MASK));
   2211     break;
   2212   }
   2213 }
   2214 
   2215 STATIC
   2216 UINTN
   2217 DwUsb3HandleEvent (
   2218   VOID
   2219   )
   2220 {
   2221   usb3_pcd_t          *pcd = &gPcd;
   2222   UINT32              Count, Index, Event, Intr;
   2223   UINT32              PhySep;
   2224 
   2225   Count = GET_EVENTBUF_COUNT ();
   2226   // reset event buffer when it's full
   2227   if ((GEVNTCOUNT_EVNTCOUNT (Count) == GEVNTCOUNT_EVNTCOUNT_MASK) ||
   2228       (Count >= DWUSB3_EVENT_BUF_SIZE * sizeof (UINT32))) {
   2229     UPDATE_EVENTBUF_COUNT (Count);
   2230     Count = 0;
   2231   }
   2232 
   2233   for (Index = 0; Index < Count; Index += sizeof (UINT32)) {
   2234     Event = DwUsb3GetEventBufEvent (DWUSB3_EVENT_BUF_SIZE << 2);
   2235     UPDATE_EVENTBUF_COUNT (sizeof (UINT32));
   2236     if (Event == 0) {
   2237       // ignore null events
   2238       continue;
   2239     }
   2240     if (Event & GEVNT_NON_EP) {
   2241       Intr = Event & GEVNT_INTTYPE_MASK;
   2242       if (Intr == GEVNT_INTTYPE (EVENT_DEV_INT)) {
   2243         DwUsb3HandleDeviceInterrupt (pcd, Event);
   2244       }
   2245     } else {
   2246       PhySep = (Event & GEVNT_DEPEVT_EPNUM_MASK) >> GEVNT_DEPEVT_EPNUM_SHIFT;
   2247       DwUsb3HandleEndPointInterrupt (pcd, PhySep, Event);
   2248     }
   2249   }
   2250   return 0;
   2251 }
   2252 
   2253 STATIC
   2254 VOID
   2255 DwUsb3Poll (
   2256   IN EFI_EVENT        Event,
   2257   IN VOID            *Context
   2258   )
   2259 {
   2260   if (DwUsb3HandleEvent ()) {
   2261     DEBUG ((DEBUG_ERROR, "error: exit from usb_poll\n"));
   2262     return;
   2263   }
   2264 }
   2265 
   2266 EFI_STATUS
   2267 EFIAPI
   2268 DwUsb3Start (
   2269   IN USB_DEVICE_DESCRIPTOR   *DeviceDescriptor,
   2270   IN VOID                   **Descriptors,
   2271   IN USB_DEVICE_RX_CALLBACK   RxCallback,
   2272   IN USB_DEVICE_TX_CALLBACK   TxCallback
   2273   )
   2274 {
   2275   EFI_STATUS             Status;
   2276   EFI_EVENT              TimerEvent;
   2277 
   2278   //gEventBuf = UncachedAllocateAlignedZeroPool (DWUSB3_EVENT_BUF_SIZE << 2, 256);
   2279   gEventBuf = UncachedAllocatePages (EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2));
   2280   if (gEventBuf == NULL) {
   2281     return EFI_OUT_OF_RESOURCES;
   2282   }
   2283   ZeroMem (gEventBuf, EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2));
   2284   gEventPtr = gEventBuf;
   2285   DriverInit ();
   2286   DwUsb3Init ();
   2287   Status = gBS->CreateEvent (
   2288                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   2289                   TPL_CALLBACK,
   2290                   DwUsb3Poll,
   2291                   NULL,
   2292                   &TimerEvent
   2293                   );
   2294   ASSERT_EFI_ERROR (Status);
   2295   if (EFI_ERROR (Status)) {
   2296     return Status;
   2297   }
   2298 
   2299   Status = gBS->SetTimer (
   2300                   TimerEvent,
   2301                   TimerPeriodic,
   2302                   DW_INTERRUPT_POLL_PERIOD
   2303                   );
   2304   ASSERT_EFI_ERROR (Status);
   2305   mDataReceivedCallback = RxCallback;
   2306   return Status;
   2307 }
   2308 
   2309 EFI_STATUS
   2310 DwUsb3Send (
   2311   IN        UINT8  EndpointIndex,
   2312   IN        UINTN  Size,
   2313   IN  CONST VOID  *Buffer
   2314   )
   2315 {
   2316   usb3_pcd_t                    *pcd = &gPcd;
   2317   usb3_pcd_ep_t                 *ep = &pcd->in_ep;
   2318   usb3_pcd_req_t                *req = &ep->req;
   2319 
   2320   WriteBackDataCacheRange ((VOID *)Buffer, Size);
   2321   req->bufdma = (UINT64 *)Buffer;
   2322   req->length = Size;
   2323   DwUsb3EndPointXStartTransfer (pcd, ep);
   2324   return EFI_SUCCESS;
   2325 }
   2326 
   2327 EFI_STATUS
   2328 DwUsb3Request (
   2329   IN UINTN   BufferSize
   2330   )
   2331 {
   2332   if (BufferSize) {
   2333     mDataBufferSize = BufferSize;
   2334   }
   2335   return EFI_SUCCESS;
   2336 }
   2337 
   2338 USB_DEVICE_PROTOCOL mUsbDevice = {
   2339   DwUsb3Start,
   2340   DwUsb3Send,
   2341   DwUsb3Request
   2342 };
   2343 
   2344 EFI_STATUS
   2345 EFIAPI
   2346 DwUsb3EntryPoint (
   2347   IN EFI_HANDLE                            ImageHandle,
   2348   IN EFI_SYSTEM_TABLE                      *SystemTable
   2349   )
   2350 {
   2351   EFI_STATUS      Status;
   2352 
   2353   gEndPoint0SetupPacket = UncachedAllocatePages (EFI_SIZE_TO_PAGES (sizeof (usb_setup_pkt_t) * 5));
   2354   if (gEndPoint0SetupPacket == NULL) {
   2355     return EFI_OUT_OF_RESOURCES;
   2356   }
   2357   gEndPoint0StatusBuf = UncachedAllocatePages (EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)));
   2358   if (gEndPoint0StatusBuf == NULL) {
   2359     return EFI_OUT_OF_RESOURCES;
   2360   }
   2361 #if 0
   2362   gRxBuf = UncachedAllocatePages (1);
   2363   if (gRxBuf == NULL) {
   2364     return EFI_OUT_OF_RESOURCES;
   2365   }
   2366 #endif
   2367   Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
   2368   if (EFI_ERROR (Status)) {
   2369     return Status;
   2370   }
   2371   Status = DwUsb->PhyInit(USB_DEVICE_MODE);
   2372   if (EFI_ERROR (Status)) {
   2373     return Status;
   2374   }
   2375 
   2376   return gBS->InstallProtocolInterface (
   2377 		  &ImageHandle,
   2378 		  &gUsbDeviceProtocolGuid,
   2379 		  EFI_NATIVE_INTERFACE,
   2380 		  &mUsbDevice
   2381 		  );
   2382 }
   2383