Home | History | Annotate | Download | only in Ax88772
      1 /** @file
      2   Implement the interface to the AX88772 Ethernet controller.
      3 
      4   This module implements the interface to the ASIX AX88772
      5   USB to Ethernet MAC with integrated 10/100 PHY.  Note that this implementation
      6   only supports the integrated PHY since no other test cases were available.
      7 
      8   Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
      9   This program and the accompanying materials
     10   are licensed and made available under the terms and conditions of the BSD License
     11   which accompanies this distribution.  The full text of the license may be found at
     12   http://opensource.org/licenses/bsd-license.php
     13 
     14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17 **/
     18 
     19 #include "Ax88772.h"
     20 
     21 
     22 /**
     23   Compute the CRC
     24 
     25   @param [in] pMacAddress      Address of a six byte buffer to containing the MAC address.
     26 
     27   @returns The CRC-32 value associated with this MAC address
     28 
     29 **/
     30 UINT32
     31 Ax88772Crc (
     32   IN UINT8 * pMacAddress
     33   )
     34 {
     35   UINT32 BitNumber;
     36   INT32 Carry;
     37   INT32 Crc;
     38   UINT32 Data;
     39   UINT8 * pEnd;
     40 
     41   DBG_ENTER ( );
     42 
     43   //
     44   //  Walk the MAC address
     45   //
     46   Crc = -1;
     47   pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];
     48   while ( pEnd > pMacAddress ) {
     49     Data = *pMacAddress++;
     50 
     51 
     52     //
     53     //  CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
     54     //
     55     //          1 0000 0100 1100 0001 0001 1101 1011 0111
     56     //
     57     for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {
     58       Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );
     59       Crc <<= 1;
     60       if ( 0 != Carry ) {
     61         Crc ^= 0x04c11db7;
     62       }
     63       Data >>= 1;
     64     }
     65   }
     66 
     67   //
     68   //  Return the CRC value
     69   //
     70   DBG_EXIT_HEX ( Crc );
     71   return (UINT32) Crc;
     72 }
     73 
     74 
     75 /**
     76   Get the MAC address
     77 
     78   This routine calls ::Ax88772UsbCommand to request the MAC
     79   address from the network adapter.
     80 
     81   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
     82   @param [out] pMacAddress      Address of a six byte buffer to receive the MAC address.
     83 
     84   @retval EFI_SUCCESS          The MAC address is available.
     85   @retval other                The MAC address is not valid.
     86 
     87 **/
     88 EFI_STATUS
     89 Ax88772MacAddressGet (
     90   IN NIC_DEVICE * pNicDevice,
     91   OUT UINT8 * pMacAddress
     92   )
     93 {
     94   USB_DEVICE_REQUEST SetupMsg;
     95   EFI_STATUS Status;
     96 
     97   DBG_ENTER ( );
     98 
     99   //
    100   //  Set the register address.
    101   //
    102   SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
    103                        | USB_REQ_TYPE_VENDOR
    104                        | USB_TARGET_DEVICE;
    105   SetupMsg.Request = CMD_MAC_ADDRESS_READ;
    106   SetupMsg.Value = 0;
    107   SetupMsg.Index = 0;
    108   SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
    109 
    110   //
    111   //  Read the PHY register
    112   //
    113   Status = Ax88772UsbCommand ( pNicDevice,
    114                                &SetupMsg,
    115                                pMacAddress );
    116 
    117   //
    118   // Return the operation status
    119   //
    120   DBG_EXIT_STATUS ( Status );
    121   return Status;
    122 }
    123 
    124 
    125 /**
    126   Set the MAC address
    127 
    128   This routine calls ::Ax88772UsbCommand to set the MAC address
    129   in the network adapter.
    130 
    131   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    132   @param [in] pMacAddress      Address of a six byte buffer to containing the new MAC address.
    133 
    134   @retval EFI_SUCCESS          The MAC address was set.
    135   @retval other                The MAC address was not set.
    136 
    137 **/
    138 EFI_STATUS
    139 Ax88772MacAddressSet (
    140   IN NIC_DEVICE * pNicDevice,
    141   IN UINT8 * pMacAddress
    142   )
    143 {
    144   USB_DEVICE_REQUEST SetupMsg;
    145   EFI_STATUS Status;
    146 
    147   DBG_ENTER ( );
    148 
    149   //
    150   //  Set the register address.
    151   //
    152   SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    153                        | USB_TARGET_DEVICE;
    154   SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;
    155   SetupMsg.Value = 0;
    156   SetupMsg.Index = 0;
    157   SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
    158 
    159   //
    160   //  Read the PHY register
    161   //
    162   Status = Ax88772UsbCommand ( pNicDevice,
    163                                &SetupMsg,
    164                                pMacAddress );
    165 
    166   //
    167   // Return the operation status
    168   //
    169   DBG_EXIT_STATUS ( Status );
    170   return Status;
    171 }
    172 
    173 
    174 /**
    175   Clear the multicast hash table
    176 
    177   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    178 
    179 **/
    180 VOID
    181 Ax88772MulticastClear (
    182   IN NIC_DEVICE * pNicDevice
    183   )
    184 {
    185   DBG_ENTER ( );
    186 
    187   //
    188   // Clear the multicast hash table
    189   //
    190   pNicDevice->MulticastHash[0] = 0;
    191   pNicDevice->MulticastHash[1] = 0;
    192 
    193   DBG_EXIT ( );
    194 }
    195 
    196 
    197 /**
    198   Enable a multicast address in the multicast hash table
    199 
    200   This routine calls ::Ax88772Crc to compute the hash bit for
    201   this MAC address.
    202 
    203   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    204   @param [in] pMacAddress      Address of a six byte buffer to containing the MAC address.
    205 
    206 **/
    207 VOID
    208 Ax88772MulticastSet (
    209   IN NIC_DEVICE * pNicDevice,
    210   IN UINT8 * pMacAddress
    211   )
    212 {
    213   UINT32 BitNumber;
    214   UINT32 Crc;
    215   UINT32 Mask;
    216 
    217   DBG_ENTER ( );
    218 
    219   //
    220   //  Compute the CRC on the destination address
    221   //
    222   Crc = Ax88772Crc ( pMacAddress );
    223 
    224   //
    225   //  Set the bit corresponding to the destination address
    226   //
    227   BitNumber = Crc >> 26;
    228   if ( 32 > BitNumber ) {
    229     Mask = 1 << BitNumber;
    230     pNicDevice->MulticastHash[0] |= Mask;
    231   }
    232   else {
    233     Mask = 1 << ( BitNumber - 32 );
    234     pNicDevice->MulticastHash[1] |= Mask;
    235   }
    236 
    237   //
    238   //  Display the multicast address
    239   //
    240   DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,
    241             "Enable multicast: 0x%02x-%02x-%02x-%02x-%02x-%02x, CRC: 0x%08x, Bit number: 0x%02x\r\n",
    242             pMacAddress[0],
    243             pMacAddress[1],
    244             pMacAddress[2],
    245             pMacAddress[3],
    246             pMacAddress[4],
    247             pMacAddress[5],
    248             Crc,
    249             BitNumber ));
    250 
    251   DBG_EXIT ( );
    252 }
    253 
    254 
    255 /**
    256   Start the link negotiation
    257 
    258   This routine calls ::Ax88772PhyWrite to start the PHY's link
    259   negotiation.
    260 
    261   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    262 
    263   @retval EFI_SUCCESS          The link negotiation was started.
    264   @retval other                Failed to start the link negotiation.
    265 
    266 **/
    267 EFI_STATUS
    268 Ax88772NegotiateLinkStart (
    269   IN NIC_DEVICE * pNicDevice
    270   )
    271 {
    272   UINT16 Control;
    273   EFI_STATUS Status;
    274 
    275   DBG_ENTER ( );
    276 
    277   //
    278   // Set the supported capabilities.
    279   //
    280   Status = Ax88772PhyWrite ( pNicDevice,
    281                              PHY_ANAR,
    282                              AN_CSMA_CD
    283                              | AN_TX_FDX | AN_TX_HDX
    284                              | AN_10_FDX | AN_10_HDX );
    285   if ( !EFI_ERROR ( Status )) {
    286     //
    287     // Set the link speed and duplex
    288     //
    289     Control = BMCR_AUTONEGOTIATION_ENABLE
    290             | BMCR_RESTART_AUTONEGOTIATION;
    291     if ( pNicDevice->b100Mbps ) {
    292       Control |= BMCR_100MBPS;
    293     }
    294     if ( pNicDevice->bFullDuplex ) {
    295       Control |= BMCR_FULL_DUPLEX;
    296     }
    297     Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );
    298   }
    299 
    300   //
    301   // Return the operation status
    302   //
    303   DBG_EXIT_STATUS ( Status );
    304   return Status;
    305 }
    306 
    307 
    308 /**
    309   Complete the negotiation of the PHY link
    310 
    311   This routine calls ::Ax88772PhyRead to determine if the
    312   link negotiation is complete.
    313 
    314   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    315   @param [in, out] pPollCount  Address of number of times this routine was polled
    316   @param [out] pbComplete      Address of boolean to receive complate status.
    317   @param [out] pbLinkUp        Address of boolean to receive link status, TRUE=up.
    318   @param [out] pbHiSpeed       Address of boolean to receive link speed, TRUE=100Mbps.
    319   @param [out] pbFullDuplex    Address of boolean to receive link duplex, TRUE=full.
    320 
    321   @retval EFI_SUCCESS          The MAC address is available.
    322   @retval other                The MAC address is not valid.
    323 
    324 **/
    325 EFI_STATUS
    326 Ax88772NegotiateLinkComplete (
    327   IN NIC_DEVICE * pNicDevice,
    328   IN OUT UINTN * pPollCount,
    329   OUT BOOLEAN * pbComplete,
    330   OUT BOOLEAN * pbLinkUp,
    331   OUT BOOLEAN * pbHiSpeed,
    332   OUT BOOLEAN * pbFullDuplex
    333   )
    334 {
    335   UINT16 Mask;
    336   UINT16 PhyData;
    337   EFI_STATUS  Status;
    338 
    339   DBG_ENTER ( );
    340 
    341   //
    342   //  Determine if the link is up.
    343   //
    344   *pbComplete = FALSE;
    345 
    346   //
    347   //  Get the link status
    348   //
    349   Status = Ax88772PhyRead ( pNicDevice,
    350                             PHY_BMSR,
    351                             &PhyData );
    352   if ( !EFI_ERROR ( Status )) {
    353     //
    354     //  Determine if the autonegotiation is complete.
    355     //
    356     *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));
    357     *pbComplete = *pbLinkUp;
    358     if ( 0 != *pbComplete ) {
    359       //
    360       //  Get the partners capabilities.
    361       //
    362       Status = Ax88772PhyRead ( pNicDevice,
    363                                 PHY_ANLPAR,
    364                                 &PhyData );
    365       if ( !EFI_ERROR ( Status )) {
    366         //
    367         //  Autonegotiation is complete
    368         //  Determine the link speed.
    369         //
    370         *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));
    371 
    372         //
    373         //  Determine the link duplex.
    374         //
    375         Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;
    376         *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));
    377       }
    378     }
    379   }
    380 
    381   //
    382   // Return the operation status
    383   //
    384   DBG_EXIT_STATUS ( Status );
    385   return Status;
    386 }
    387 
    388 
    389 /**
    390   Read a register from the PHY
    391 
    392   This routine calls ::Ax88772UsbCommand to read a PHY register.
    393 
    394   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    395   @param [in] RegisterAddress  Number of the register to read.
    396   @param [in, out] pPhyData    Address of a buffer to receive the PHY register value
    397 
    398   @retval EFI_SUCCESS          The PHY data is available.
    399   @retval other                The PHY data is not valid.
    400 
    401 **/
    402 EFI_STATUS
    403 Ax88772PhyRead (
    404   IN NIC_DEVICE * pNicDevice,
    405   IN UINT8 RegisterAddress,
    406   IN OUT UINT16 * pPhyData
    407   )
    408 {
    409   USB_DEVICE_REQUEST SetupMsg;
    410   EFI_STATUS Status;
    411 
    412   DBG_ENTER ( );
    413 
    414   //
    415   //  Request access to the PHY
    416   //
    417   SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    418                        | USB_TARGET_DEVICE;
    419   SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
    420   SetupMsg.Value = 0;
    421   SetupMsg.Index = 0;
    422   SetupMsg.Length = 0;
    423   Status = Ax88772UsbCommand ( pNicDevice,
    424                                &SetupMsg,
    425                                NULL );
    426   if ( !EFI_ERROR ( Status )) {
    427     //
    428     //  Read the PHY register address.
    429     //
    430     SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
    431                          | USB_REQ_TYPE_VENDOR
    432                          | USB_TARGET_DEVICE;
    433     SetupMsg.Request = CMD_PHY_REG_READ;
    434     SetupMsg.Value = pNicDevice->PhyId;
    435     SetupMsg.Index = RegisterAddress;
    436     SetupMsg.Length = sizeof ( *pPhyData );
    437     Status = Ax88772UsbCommand ( pNicDevice,
    438                                  &SetupMsg,
    439                                  pPhyData );
    440     if ( !EFI_ERROR ( Status )) {
    441       DEBUG (( DEBUG_PHY | DEBUG_INFO,
    442                 "PHY %d: 0x%02x --> 0x%04x\r\n",
    443                 pNicDevice->PhyId,
    444                 RegisterAddress,
    445                 *pPhyData ));
    446 
    447       //
    448       //  Release the PHY to the hardware
    449       //
    450       SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    451                            | USB_TARGET_DEVICE;
    452       SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
    453       SetupMsg.Value = 0;
    454       SetupMsg.Index = 0;
    455       SetupMsg.Length = 0;
    456       Status = Ax88772UsbCommand ( pNicDevice,
    457                                    &SetupMsg,
    458                                    NULL );
    459     }
    460   }
    461 
    462   //
    463   //  Return the operation status.
    464   //
    465   DBG_EXIT_STATUS ( Status );
    466   return Status;
    467 }
    468 
    469 
    470 /**
    471   Write to a PHY register
    472 
    473   This routine calls ::Ax88772UsbCommand to write a PHY register.
    474 
    475   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    476   @param [in] RegisterAddress  Number of the register to read.
    477   @param [in] PhyData          Address of a buffer to receive the PHY register value
    478 
    479   @retval EFI_SUCCESS          The PHY data was written.
    480   @retval other                Failed to wwrite the PHY register.
    481 
    482 **/
    483 EFI_STATUS
    484 Ax88772PhyWrite (
    485   IN NIC_DEVICE * pNicDevice,
    486   IN UINT8 RegisterAddress,
    487   IN UINT16 PhyData
    488   )
    489 {
    490   USB_DEVICE_REQUEST SetupMsg;
    491   EFI_STATUS Status;
    492 
    493   DBG_ENTER ( );
    494 
    495   //
    496   //  Request access to the PHY
    497   //
    498   SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    499                        | USB_TARGET_DEVICE;
    500   SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
    501   SetupMsg.Value = 0;
    502   SetupMsg.Index = 0;
    503   SetupMsg.Length = 0;
    504   Status = Ax88772UsbCommand ( pNicDevice,
    505                                &SetupMsg,
    506                                NULL );
    507   if ( !EFI_ERROR ( Status )) {
    508     //
    509     //  Write the PHY register
    510     //
    511     SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    512                          | USB_TARGET_DEVICE;
    513     SetupMsg.Request = CMD_PHY_REG_WRITE;
    514     SetupMsg.Value = pNicDevice->PhyId;
    515     SetupMsg.Index = RegisterAddress;
    516     SetupMsg.Length = sizeof ( PhyData );
    517     Status = Ax88772UsbCommand ( pNicDevice,
    518                                  &SetupMsg,
    519                                  &PhyData );
    520     if ( !EFI_ERROR ( Status )) {
    521       DEBUG (( DEBUG_PHY | DEBUG_INFO,
    522                 "PHY %d: 0x%02x <-- 0x%04x\r\n",
    523                 pNicDevice->PhyId,
    524                 RegisterAddress,
    525                 PhyData ));
    526 
    527       //
    528       //  Release the PHY to the hardware
    529       //
    530       SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    531                            | USB_TARGET_DEVICE;
    532       SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
    533       SetupMsg.Value = 0;
    534       SetupMsg.Index = 0;
    535       SetupMsg.Length = 0;
    536       Status = Ax88772UsbCommand ( pNicDevice,
    537                                    &SetupMsg,
    538                                    NULL );
    539     }
    540   }
    541 
    542   //
    543   //  Return the operation status.
    544   //
    545   DBG_EXIT_STATUS ( Status );
    546   return Status;
    547 }
    548 
    549 
    550 /**
    551   Reset the AX88772
    552 
    553   This routine uses ::Ax88772UsbCommand to reset the network
    554   adapter.  This routine also uses ::Ax88772PhyWrite to reset
    555   the PHY.
    556 
    557   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    558 
    559   @retval EFI_SUCCESS          The MAC address is available.
    560   @retval other                The MAC address is not valid.
    561 
    562 **/
    563 EFI_STATUS
    564 Ax88772Reset (
    565   IN NIC_DEVICE * pNicDevice
    566   )
    567 {
    568   USB_DEVICE_REQUEST SetupMsg;
    569   EFI_STATUS Status;
    570 
    571   DBG_ENTER ( );
    572 
    573   //
    574   //  Turn off the MAC
    575   //
    576   SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    577                        | USB_TARGET_DEVICE;
    578   SetupMsg.Request = CMD_RX_CONTROL_WRITE;
    579   SetupMsg.Value = 0;
    580   SetupMsg.Index = 0;
    581   SetupMsg.Length = 0;
    582   Status = Ax88772UsbCommand ( pNicDevice,
    583                                &SetupMsg,
    584                                NULL );
    585   if ( !EFI_ERROR ( Status )) {
    586     DEBUG (( DEBUG_PHY | DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST
    587               | DEBUG_RX_UNICAST | DEBUG_TX | DEBUG_INFO,
    588               "MAC reset\r\n" ));
    589 
    590     //
    591     //  The link is now idle
    592     //
    593     pNicDevice->bLinkIdle = TRUE;
    594 
    595     //
    596     //  Delay for a bit
    597     //
    598     gBS->Stall ( RESET_MSEC );
    599 
    600     //
    601     //  Select the internal PHY
    602     //
    603     SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    604                          | USB_TARGET_DEVICE;
    605     SetupMsg.Request = CMD_PHY_SELECT;
    606     SetupMsg.Value = SPHY_PSEL;
    607     SetupMsg.Index = 0;
    608     SetupMsg.Length = 0;
    609     Status = Ax88772UsbCommand ( pNicDevice,
    610                                  &SetupMsg,
    611                                  NULL );
    612     if ( !EFI_ERROR ( Status )) {
    613       //
    614       //  Delay for a bit
    615       //
    616       gBS->Stall ( PHY_RESET_MSEC );
    617 
    618       //
    619       //  Clear the internal PHY reset
    620       //
    621       SetupMsg.Request = CMD_RESET;
    622       SetupMsg.Value = SRR_IPRL | SRR_PRL;
    623       Status = Ax88772UsbCommand ( pNicDevice,
    624                                    &SetupMsg,
    625                                    NULL );
    626       if ( !EFI_ERROR ( Status )) {
    627         //
    628         //  Reset the PHY
    629         //
    630         Status = Ax88772PhyWrite ( pNicDevice,
    631                                    PHY_BMCR,
    632                                    BMCR_RESET );
    633         if ( !EFI_ERROR ( Status )) {
    634           //
    635           //  Set the gaps
    636           //
    637           SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
    638                                | USB_TARGET_DEVICE;
    639           SetupMsg.Request = CMD_GAPS_WRITE;
    640           SetupMsg.Value = 0x0c15;
    641           SetupMsg.Index = 0x0e;
    642           SetupMsg.Length = 0;
    643           Status = Ax88772UsbCommand ( pNicDevice,
    644                                        &SetupMsg,
    645                                        NULL );
    646         }
    647       }
    648     }
    649   }
    650 
    651   //
    652   //  Return the operation status.
    653   //
    654   DBG_EXIT_STATUS ( Status );
    655   return Status;
    656 }
    657 
    658 
    659 VOID
    660 FillPkt2Queue (
    661   IN NIC_DEVICE * pNicDevice,
    662   IN UINTN BufLength)
    663 {
    664 
    665   UINT16 * pLength;
    666   UINT16 * pLengthBar;
    667   UINT8* pData;
    668   UINT32 offset;
    669   RX_TX_PACKET * pRxPacket;
    670   UINTN LengthInBytes;
    671   EFI_STATUS Status;
    672 
    673   for ( offset = 0; offset < BufLength; ){
    674     pLength = (UINT16*) (pNicDevice->pBulkInBuff + offset);
    675     pLengthBar = (UINT16*) (pNicDevice->pBulkInBuff + offset +2);
    676 
    677     *pLength &= 0x7ff;
    678     *pLengthBar &= 0x7ff;
    679     *pLengthBar |= 0xf800;
    680 
    681     if ((*pLength ^ *pLengthBar ) != 0xFFFF) {
    682       DEBUG (( EFI_D_ERROR , "Pkt length error. BufLength = %d\n", BufLength));
    683       return;
    684     }
    685 
    686     pRxPacket = pNicDevice->pRxFree;
    687     LengthInBytes = sizeof ( *pRxPacket ) - sizeof ( pRxPacket->pNext );
    688     if ( NULL == pRxPacket ) {
    689       Status = gBS->AllocatePool ( EfiRuntimeServicesData,
    690                                    sizeof( RX_TX_PACKET ),
    691                                    (VOID **) &pRxPacket );
    692       if ( !EFI_ERROR ( Status )) {
    693         //
    694         //  Add this packet to the free packet list
    695         //
    696         pNicDevice->pRxFree = pRxPacket;
    697         pRxPacket->pNext = NULL;
    698       }
    699       else {
    700         //
    701         //  Use the discard packet buffer
    702         //
    703         //pRxPacket = &Packet;
    704       }
    705     }
    706 
    707 
    708     pData = pNicDevice->pBulkInBuff + offset + 4;
    709     pRxPacket->Length = *pLength;
    710     pRxPacket->LengthBar = *(UINT16*) (pNicDevice->pBulkInBuff + offset +2);
    711     CopyMem (&pRxPacket->Data[0], pData, *pLength);
    712     //DEBUG((DEBUG_INFO, "Packet [%d]\n", *pLength));
    713 
    714     pNicDevice->pRxFree = pRxPacket->pNext;
    715     pRxPacket->pNext = NULL;
    716 
    717     if ( NULL == pNicDevice->pRxTail ) {
    718       pNicDevice->pRxHead = pRxPacket;
    719     }
    720     else {
    721       pNicDevice->pRxTail->pNext = pRxPacket;
    722     }
    723     pNicDevice->pRxTail = pRxPacket;
    724     offset += (*pLength + 4);
    725 
    726   }
    727 }
    728 
    729 
    730 
    731 /**
    732   Receive a frame from the network.
    733 
    734   This routine polls the USB receive interface for a packet.  If a packet
    735   is available, this routine adds the receive packet to the list of
    736   pending receive packets.
    737 
    738   This routine calls ::Ax88772NegotiateLinkComplete to verify
    739   that the link is up.  This routine also calls ::SN_Reset to
    740   reset the network adapter when necessary.  Finally this
    741   routine attempts to receive one or more packets from the
    742   network adapter.
    743 
    744   @param [in] pNicDevice  Pointer to the NIC_DEVICE structure
    745   @param [in] bUpdateLink TRUE = Update link status
    746 
    747 **/
    748 VOID
    749 Ax88772Rx (
    750   IN NIC_DEVICE * pNicDevice,
    751   IN BOOLEAN bUpdateLink
    752   )
    753 {
    754   BOOLEAN bFullDuplex;
    755   BOOLEAN bLinkUp;
    756   BOOLEAN bRxPacket;
    757   BOOLEAN bSpeed100;
    758   UINTN LengthInBytes;
    759   RX_TX_PACKET Packet;
    760   RX_TX_PACKET * pRxPacket;
    761   EFI_USB_IO_PROTOCOL *pUsbIo;
    762   EFI_STATUS Status;
    763   EFI_TPL TplPrevious;
    764   UINT32 TransferStatus;
    765 
    766   //
    767   //  Synchronize with Ax88772Timer
    768   //
    769   VERIFY_TPL ( TPL_AX88772 );
    770   TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
    771   DEBUG (( DEBUG_TPL | DEBUG_INFO,
    772             "%d: TPL\r\n",
    773             TPL_AX88772 ));
    774 
    775   //
    776   //  Get the link status
    777   //
    778   if ( bUpdateLink ) {
    779     bLinkUp = pNicDevice->bLinkUp;
    780     bSpeed100 = pNicDevice->b100Mbps;
    781     bFullDuplex = pNicDevice->bFullDuplex;
    782     Status = Ax88772NegotiateLinkComplete ( pNicDevice,
    783                                             &pNicDevice->PollCount,
    784                                             &pNicDevice->bComplete,
    785                                             &pNicDevice->bLinkUp,
    786                                             &pNicDevice->b100Mbps,
    787                                             &pNicDevice->bFullDuplex );
    788 
    789     //
    790     // Determine if the autonegotiation is complete
    791     //
    792     if ( pNicDevice->bComplete ) {
    793       if ( pNicDevice->bLinkUp ) {
    794         if (( bSpeed100 && ( !pNicDevice->b100Mbps ))
    795           || (( !bSpeed100 ) && pNicDevice->b100Mbps )
    796           || ( bFullDuplex && ( !pNicDevice->bFullDuplex ))
    797           || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) {
    798           pNicDevice->PollCount = 0;
    799           DEBUG (( DEBUG_LINK | DEBUG_INFO,
    800                     "Reset to establish proper link setup: %d Mbps, %s duplex\r\n",
    801                     pNicDevice->b100Mbps ? 100 : 10,
    802                     pNicDevice->bFullDuplex ? L"Full" : L"Half" ));
    803           Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE );
    804         }
    805         if (( !bLinkUp ) && pNicDevice->bLinkUp ) {
    806           //
    807           // Display the autonegotiation status
    808           //
    809           DEBUG (( DEBUG_LINK | DEBUG_INFO,
    810                     "Link: Up, %d Mbps, %s duplex\r\n",
    811                     pNicDevice->b100Mbps ? 100 : 10,
    812                     pNicDevice->bFullDuplex ? L"Full" : L"Half" ));
    813         }
    814       }
    815     }
    816 
    817     //
    818     //  Update the link status
    819     //
    820     if ( bLinkUp && ( !pNicDevice->bLinkUp )) {
    821       DEBUG (( DEBUG_LINK | DEBUG_INFO, "Link: Down\r\n" ));
    822     }
    823   }
    824 
    825   //
    826   //  Loop until all the packets are emptied from the receiver
    827   //
    828   do {
    829     bRxPacket = FALSE;
    830 
    831     //
    832     //  Locate a packet for use
    833     //
    834     pRxPacket = pNicDevice->pRxFree;
    835     LengthInBytes = MAX_BULKIN_SIZE;
    836     if ( NULL == pRxPacket ) {
    837       Status = gBS->AllocatePool ( EfiRuntimeServicesData,
    838                                    sizeof ( *pRxPacket ),
    839                                    (VOID **) &pRxPacket );
    840       if ( !EFI_ERROR ( Status )) {
    841         //
    842         //  Add this packet to the free packet list
    843         //
    844         pNicDevice->pRxFree = pRxPacket;
    845         pRxPacket->pNext = NULL;
    846       }
    847       else {
    848         //
    849         //  Use the discard packet buffer
    850         //
    851         pRxPacket = &Packet;
    852       }
    853     }
    854 
    855     //
    856     //  Attempt to receive a packet
    857     //
    858     SetMem (&pNicDevice->pBulkInBuff[0], MAX_BULKIN_SIZE, 0);
    859     pUsbIo = pNicDevice->pUsbIo;
    860     Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
    861                                        USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
    862                                        &pNicDevice->pBulkInBuff[0],
    863                                        &LengthInBytes,
    864                                        2,
    865                                        &TransferStatus );
    866     if ( LengthInBytes > 0 ) {
    867       FillPkt2Queue(pNicDevice, LengthInBytes);
    868     }
    869     pRxPacket = pNicDevice->pRxHead;
    870     if (( !EFI_ERROR ( Status ))
    871       && ( 0 < pRxPacket->Length )
    872       && ( pRxPacket->Length <= sizeof ( pRxPacket->Data ))
    873       && ( LengthInBytes > 0)) {
    874 
    875       //
    876       //  Determine if the packet should be received
    877       //
    878       bRxPacket = TRUE;
    879       LengthInBytes = pRxPacket->Length;
    880       pNicDevice->bLinkIdle = FALSE;
    881       if ( pNicDevice->pRxFree == pRxPacket ) {
    882         //
    883         //  Display the received packet
    884         //
    885         if ( 0 != ( pRxPacket->Data[0] & 1 )) {
    886           if (( 0xff == pRxPacket->Data[0])
    887             && ( 0xff == pRxPacket->Data[1])
    888             && ( 0xff == pRxPacket->Data[2])
    889             && ( 0xff == pRxPacket->Data[3])
    890             && ( 0xff == pRxPacket->Data[4])
    891             && ( 0xff == pRxPacket->Data[5])) {
    892             DEBUG (( DEBUG_RX_BROADCAST | DEBUG_INFO,
    893                       "RX: %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x  %d bytes\r\n",
    894                       pRxPacket->Data[0],
    895                       pRxPacket->Data[1],
    896                       pRxPacket->Data[2],
    897                       pRxPacket->Data[3],
    898                       pRxPacket->Data[4],
    899                       pRxPacket->Data[5],
    900                       pRxPacket->Data[6],
    901                       pRxPacket->Data[7],
    902                       pRxPacket->Data[8],
    903                       pRxPacket->Data[9],
    904                       pRxPacket->Data[10],
    905                       pRxPacket->Data[11],
    906                       pRxPacket->Data[12],
    907                       pRxPacket->Data[13],
    908                       LengthInBytes ));
    909           }
    910           else {
    911             DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,
    912                       "RX: %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x  %d bytes\r\n",
    913                       pRxPacket->Data[0],
    914                       pRxPacket->Data[1],
    915                       pRxPacket->Data[2],
    916                       pRxPacket->Data[3],
    917                       pRxPacket->Data[4],
    918                       pRxPacket->Data[5],
    919                       pRxPacket->Data[6],
    920                       pRxPacket->Data[7],
    921                       pRxPacket->Data[8],
    922                       pRxPacket->Data[9],
    923                       pRxPacket->Data[10],
    924                       pRxPacket->Data[11],
    925                       pRxPacket->Data[12],
    926                       pRxPacket->Data[13],
    927                       LengthInBytes ));
    928           }
    929         }
    930         else {
    931           DEBUG (( DEBUG_RX_UNICAST | DEBUG_INFO,
    932                     "RX: %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x  %d bytes\r\n",
    933                     pRxPacket->Data[0],
    934                     pRxPacket->Data[1],
    935                     pRxPacket->Data[2],
    936                     pRxPacket->Data[3],
    937                     pRxPacket->Data[4],
    938                     pRxPacket->Data[5],
    939                     pRxPacket->Data[6],
    940                     pRxPacket->Data[7],
    941                     pRxPacket->Data[8],
    942                     pRxPacket->Data[9],
    943                     pRxPacket->Data[10],
    944                     pRxPacket->Data[11],
    945                     pRxPacket->Data[12],
    946                     pRxPacket->Data[13],
    947                     LengthInBytes ));
    948         }
    949 
    950       }
    951       else {
    952         //
    953         //  Error, not enough buffers for this packet, discard packet
    954         //
    955         DEBUG (( DEBUG_WARN | DEBUG_INFO,
    956                   "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x  %d bytes\r\n",
    957                   pRxPacket->Data[0],
    958                   pRxPacket->Data[1],
    959                   pRxPacket->Data[2],
    960                   pRxPacket->Data[3],
    961                   pRxPacket->Data[4],
    962                   pRxPacket->Data[5],
    963                   pRxPacket->Data[6],
    964                   pRxPacket->Data[7],
    965                   pRxPacket->Data[8],
    966                   pRxPacket->Data[9],
    967                   pRxPacket->Data[10],
    968                   pRxPacket->Data[11],
    969                   pRxPacket->Data[12],
    970                   pRxPacket->Data[13],
    971                   LengthInBytes ));
    972       }
    973     }
    974   }while ( bRxPacket );
    975 
    976   //
    977   //  Release the synchronization withhe Ax88772Timer
    978   //
    979   gBS->RestoreTPL ( TplPrevious );
    980   DEBUG (( DEBUG_TPL | DEBUG_INFO,
    981             "%d: TPL\r\n",
    982             TplPrevious ));
    983 }
    984 
    985 
    986 /**
    987   Enable or disable the receiver
    988 
    989   This routine calls ::Ax88772UsbCommand to update the
    990   receiver state.  This routine also calls ::Ax88772MacAddressSet
    991   to establish the MAC address for the network adapter.
    992 
    993   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
    994   @param [in] RxFilter         Simple network RX filter mask value
    995 
    996   @retval EFI_SUCCESS          The MAC address was set.
    997   @retval other                The MAC address was not set.
    998 
    999 **/
   1000 EFI_STATUS
   1001 Ax88772RxControl (
   1002   IN NIC_DEVICE * pNicDevice,
   1003   IN UINT32 RxFilter
   1004   )
   1005 {
   1006   UINT16 MediumStatus;
   1007   INT32 MulticastHash[2];
   1008   UINT16 RxControl;
   1009   USB_DEVICE_REQUEST SetupMsg;
   1010   EFI_STATUS Status;
   1011 
   1012   DBG_ENTER ( );
   1013 
   1014   //
   1015   //  Disable all multicast
   1016   //
   1017   MulticastHash[0] = 0;
   1018   MulticastHash[1] = 0;
   1019 
   1020   //
   1021   // Enable the receiver if something is to be received
   1022   //
   1023   Status = EFI_SUCCESS;
   1024   RxControl = RXC_SO | RXC_MFB_16384;
   1025   if ( 0 != RxFilter ) {
   1026     //
   1027     //  Enable the receiver
   1028     //
   1029     SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
   1030                          | USB_REQ_TYPE_VENDOR
   1031                          | USB_TARGET_DEVICE;
   1032     SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
   1033     SetupMsg.Value = 0;
   1034     SetupMsg.Index = 0;
   1035     SetupMsg.Length = sizeof ( MediumStatus );
   1036     Status = Ax88772UsbCommand ( pNicDevice,
   1037                                  &SetupMsg,
   1038                                  &MediumStatus );
   1039     if ( !EFI_ERROR ( Status )) {
   1040       if ( 0 == ( MediumStatus & MS_RE )) {
   1041         MediumStatus |= MS_RE | MS_ONE;
   1042         if ( pNicDevice->bFullDuplex ) {
   1043           MediumStatus |= MS_TFC | MS_RFC;
   1044         }
   1045         SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
   1046                              | USB_TARGET_DEVICE;
   1047         SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
   1048         SetupMsg.Value = MediumStatus;
   1049         SetupMsg.Index = 0;
   1050         SetupMsg.Length = 0;
   1051         Status = Ax88772UsbCommand ( pNicDevice,
   1052                                      &SetupMsg,
   1053                                      NULL );
   1054         if ( EFI_ERROR ( Status )) {
   1055           DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1056                     "ERROR - Failed to enable receiver, Status: %r\r\n",
   1057                     Status ));
   1058         }
   1059       }
   1060     }
   1061     else {
   1062       DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1063                 "ERROR - Failed to read receiver status, Status: %r\r\n",
   1064                 Status ));
   1065     }
   1066 
   1067     //
   1068     //  Enable multicast if requested
   1069     //
   1070     if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
   1071       RxControl |= RXC_AM;
   1072       MulticastHash[0] = pNicDevice->MulticastHash[0];
   1073       MulticastHash[1] = pNicDevice->MulticastHash[1];
   1074     }
   1075 
   1076     //
   1077     //  Enable all multicast if requested
   1078     //
   1079     if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
   1080       RxControl |= RXC_AMALL;
   1081       MulticastHash[0] = -1;
   1082       MulticastHash[1] = -1;
   1083     }
   1084 
   1085     //
   1086     //  Enable broadcast if requested
   1087     //
   1088     if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
   1089       RxControl |= RXC_AB;
   1090     }
   1091 
   1092     //
   1093     //  Enable promiscuous mode if requested
   1094     //
   1095     if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
   1096       RxControl |= RXC_PRO;
   1097       MulticastHash[0] = -1;
   1098       MulticastHash[1] = -1;
   1099     }
   1100   }
   1101 
   1102   //
   1103   //  Update the MAC address
   1104   //
   1105   if ( !EFI_ERROR ( Status )) {
   1106     Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]);
   1107   }
   1108 
   1109   //
   1110   //  Update the receiver control
   1111   //
   1112   if ( !EFI_ERROR ( Status )) {
   1113     SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
   1114                          | USB_TARGET_DEVICE;
   1115     SetupMsg.Request = CMD_RX_CONTROL_WRITE;
   1116     SetupMsg.Value = RxControl;
   1117     SetupMsg.Index = 0;
   1118     SetupMsg.Length = 0;
   1119     Status = Ax88772UsbCommand ( pNicDevice,
   1120                                  &SetupMsg,
   1121                                  NULL );
   1122     if ( !EFI_ERROR ( Status )) {
   1123       DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_INFO,
   1124                 "RxControl: 0x%04x\r\n",
   1125                 RxControl ));
   1126 
   1127       //
   1128       //  Update the multicast hash table
   1129       //
   1130       SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
   1131                            | USB_TARGET_DEVICE;
   1132       SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
   1133       SetupMsg.Value = 0;
   1134       SetupMsg.Index = 0;
   1135       SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
   1136       Status = Ax88772UsbCommand ( pNicDevice,
   1137                                    &SetupMsg,
   1138                                    &pNicDevice->MulticastHash );
   1139       if ( !EFI_ERROR ( Status )) {
   1140         DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,
   1141                   "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
   1142                   (UINT8) MulticastHash[0],
   1143                   (UINT8)( MulticastHash[0] >> 8 ),
   1144                   (UINT8)( MulticastHash[0] >> 16 ),
   1145                   (UINT8)( MulticastHash[0] >> 24 ),
   1146                   (UINT8) MulticastHash[1],
   1147                   (UINT8)( MulticastHash[1] >> 8 ),
   1148                   (UINT8)( MulticastHash[1] >> 16 ),
   1149                   (UINT8)( MulticastHash[1] >> 24 )));
   1150       }
   1151       else {
   1152         DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1153                   "ERROR - Failed to update multicast hash table, Status: %r\r\n",
   1154                   Status ));
   1155       }
   1156     }
   1157     else {
   1158       DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1159                 "ERROR - Failed to set receiver control, Status: %r\r\n",
   1160                 Status ));
   1161     }
   1162   }
   1163 
   1164   //
   1165   // Return the operation status
   1166   //
   1167   DBG_EXIT_STATUS ( Status );
   1168   return Status;
   1169 }
   1170 
   1171 
   1172 /**
   1173   Read an SROM location
   1174 
   1175   This routine calls ::Ax88772UsbCommand to read data from the
   1176   SROM.
   1177 
   1178   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
   1179   @param [in] Address          SROM address
   1180   @param [out] pData           Buffer to receive the data
   1181 
   1182   @retval EFI_SUCCESS          The read was successful
   1183   @retval other                The read failed
   1184 
   1185 **/
   1186 EFI_STATUS
   1187 Ax88772SromRead (
   1188   IN NIC_DEVICE * pNicDevice,
   1189   IN UINT32 Address,
   1190   OUT UINT16 * pData
   1191   )
   1192 {
   1193   USB_DEVICE_REQUEST SetupMsg;
   1194   EFI_STATUS Status;
   1195 
   1196   DBG_ENTER ( );
   1197 
   1198   //
   1199   //  Read a value from the SROM
   1200   //
   1201   SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
   1202                        | USB_REQ_TYPE_VENDOR
   1203                        | USB_TARGET_DEVICE;
   1204   SetupMsg.Request = CMD_SROM_READ;
   1205   SetupMsg.Value = (UINT16) Address;
   1206   SetupMsg.Index = 0;
   1207   SetupMsg.Length = sizeof ( *pData );
   1208   Status = Ax88772UsbCommand ( pNicDevice,
   1209                                &SetupMsg,
   1210                                pData );
   1211 
   1212   //
   1213   // Return the operation status
   1214   //
   1215   DBG_EXIT_STATUS ( Status );
   1216   return Status;
   1217 }
   1218 
   1219 
   1220 /**
   1221   This routine is called at a regular interval to poll for
   1222   receive packets.
   1223 
   1224   This routine polls the link state and gets any receive packets
   1225   by calling ::Ax88772Rx.
   1226 
   1227   @param [in] Event            Timer event
   1228   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
   1229 
   1230 **/
   1231 VOID
   1232 Ax88772Timer (
   1233   IN EFI_EVENT Event,
   1234   IN NIC_DEVICE * pNicDevice
   1235   )
   1236 {
   1237   //
   1238   //  Use explicit DEBUG messages since the output frequency is too
   1239   //  high for DEBUG_INFO to keep up and have spare cycles for the
   1240   //  shell
   1241   //
   1242   DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" ));
   1243 
   1244   //
   1245   //  Poll the link state and get any receive packets
   1246   //
   1247   Ax88772Rx ( pNicDevice, FALSE );
   1248 
   1249   DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" ));
   1250 }
   1251 
   1252 
   1253 /**
   1254   Send a command to the USB device.
   1255 
   1256   @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
   1257   @param [in] pRequest         Pointer to the request structure
   1258   @param [in, out] pBuffer     Data buffer address
   1259 
   1260   @retval EFI_SUCCESS          The USB transfer was successful
   1261   @retval other                The USB transfer failed
   1262 
   1263 **/
   1264 EFI_STATUS
   1265 Ax88772UsbCommand (
   1266   IN NIC_DEVICE * pNicDevice,
   1267   IN USB_DEVICE_REQUEST * pRequest,
   1268   IN OUT VOID * pBuffer
   1269   )
   1270 {
   1271   UINT32 CmdStatus;
   1272   EFI_USB_DATA_DIRECTION Direction;
   1273   EFI_USB_IO_PROTOCOL * pUsbIo;
   1274   EFI_STATUS Status;
   1275 
   1276   DBG_ENTER ( );
   1277 
   1278   //
   1279   // Determine the transfer direction
   1280   //
   1281   Direction = EfiUsbNoData;
   1282   if ( 0 != pRequest->Length ) {
   1283     Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
   1284               ? EfiUsbDataIn : EfiUsbDataOut;
   1285   }
   1286 
   1287   //
   1288   // Issue the command
   1289   //
   1290   pUsbIo = pNicDevice->pUsbIo;
   1291   Status = pUsbIo->UsbControlTransfer ( pUsbIo,
   1292                                         pRequest,
   1293                                         Direction,
   1294                                         USB_BUS_TIMEOUT,
   1295                                         pBuffer,
   1296                                         pRequest->Length,
   1297                                         &CmdStatus );
   1298 
   1299   //
   1300   // Determine the operation status
   1301   //
   1302   if ( !EFI_ERROR ( Status )) {
   1303     Status = CmdStatus;
   1304   }
   1305   else {
   1306     //
   1307     // Display any errors
   1308     //
   1309     DEBUG (( DEBUG_INFO,
   1310               "Ax88772UsbCommand - Status: %r\n",
   1311               Status ));
   1312 
   1313     //
   1314     // Only use status values associated with the Simple Network protocol
   1315     //
   1316     if ( EFI_TIMEOUT == Status ) {
   1317       Status = EFI_DEVICE_ERROR;
   1318     }
   1319   }
   1320 
   1321   //
   1322   // Return the operation status
   1323   //
   1324   DBG_EXIT_STATUS ( Status );
   1325   return Status;
   1326 }
   1327