Home | History | Annotate | Download | only in Ax88772
      1 /** @file
      2   Provides the Simple Network functions.
      3 
      4   Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
      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 "Ax88772.h"
     16 
     17 /**
     18   This function updates the filtering on the receiver.
     19 
     20   This support routine calls ::Ax88772MacAddressSet to update
     21   the MAC address.  This routine then rebuilds the multicast
     22   hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.
     23   Finally this routine enables the receiver by calling
     24   ::Ax88772RxControl.
     25 
     26   @param [in] pSimpleNetwork    Simple network mode pointer
     27 
     28   @retval EFI_SUCCESS           This operation was successful.
     29   @retval EFI_NOT_STARTED       The network interface was not started.
     30   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
     31                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
     32   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
     33   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
     34 
     35 **/
     36 EFI_STATUS
     37 ReceiveFilterUpdate (
     38   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
     39   )
     40 {
     41   EFI_SIMPLE_NETWORK_MODE * pMode;
     42   NIC_DEVICE * pNicDevice;
     43   EFI_STATUS Status;
     44   UINT32 Index;
     45 
     46   DBG_ENTER ( );
     47 
     48   //
     49   // Set the MAC address
     50   //
     51   pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
     52   pMode = pSimpleNetwork->Mode;
     53   Status = Ax88772MacAddressSet ( pNicDevice,
     54                                   &pMode->CurrentAddress.Addr[0]);
     55   if ( !EFI_ERROR ( Status )) {
     56     //
     57     // Clear the multicast hash table
     58     //
     59     Ax88772MulticastClear ( pNicDevice );
     60 
     61     //
     62     // Load the multicast hash table
     63     //
     64     if ( 0 != ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
     65       for ( Index = 0;
     66             ( !EFI_ERROR ( Status )) && ( Index < pMode->MCastFilterCount );
     67             Index++ ) {
     68         //
     69         // Enable the next multicast address
     70         //
     71         Ax88772MulticastSet ( pNicDevice,
     72                               &pMode->MCastFilter[ Index ].Addr[0]);
     73       }
     74     }
     75 
     76     //
     77     // Enable the receiver
     78     //
     79     if ( !EFI_ERROR ( Status )) {
     80       Status = Ax88772RxControl ( pNicDevice, pMode->ReceiveFilterSetting );
     81     }
     82   }
     83 
     84   //
     85   // Return the operation status
     86   //
     87   DBG_EXIT_STATUS ( Status );
     88   return Status;
     89 }
     90 
     91 
     92 /**
     93   This function updates the SNP driver status.
     94 
     95   This function gets the current interrupt and recycled transmit
     96   buffer status from the network interface.  The interrupt status
     97   and the media status are returned as a bit mask in InterruptStatus.
     98   If InterruptStatus is NULL, the interrupt status will not be read.
     99   Upon successful return of the media status, the MediaPresent field
    100   of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change
    101   of media status.  If TxBuf is not NULL, a recycled transmit buffer
    102   address will be retrived.  If a recycled transmit buffer address
    103   is returned in TxBuf, then the buffer has been successfully
    104   transmitted, and the status for that buffer is cleared.
    105 
    106   This function calls ::Ax88772Rx to update the media status and
    107   queue any receive packets.
    108 
    109   @param [in] pSimpleNetwork    Protocol instance pointer
    110   @param [in] pInterruptStatus  A pointer to the bit mask of the current active interrupts.
    111                                 If this is NULL, the interrupt status will not be read from
    112                                 the device.  If this is not NULL, the interrupt status will
    113                                 be read from teh device.  When the interrupt status is read,
    114                                 it will also be cleared.  Clearing the transmit interrupt
    115                                 does not empty the recycled transmit buffer array.
    116   @param [out] ppTxBuf          Recycled transmit buffer address.  The network interface will
    117                                 not transmit if its internal recycled transmit buffer array is
    118                                 full.  Reading the transmit buffer does not clear the transmit
    119                                 interrupt.  If this is NULL, then the transmit buffer status
    120                                 will not be read.  If there are not transmit buffers to recycle
    121                                 and TxBuf is not NULL, *TxBuf will be set to NULL.
    122 
    123   @retval EFI_SUCCESS           This operation was successful.
    124   @retval EFI_NOT_STARTED       The network interface was not started.
    125   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    126                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    127   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    128 
    129 **/
    130 EFI_STATUS
    131 EFIAPI
    132 SN_GetStatus (
    133   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    134   OUT UINT32 * pInterruptStatus,
    135   OUT VOID ** ppTxBuf
    136   )
    137 {
    138   BOOLEAN bLinkIdle;
    139   EFI_SIMPLE_NETWORK_MODE * pMode;
    140   NIC_DEVICE * pNicDevice;
    141   EFI_STATUS Status;
    142   EFI_TPL TplPrevious;
    143 
    144   DBG_ENTER ( );
    145 
    146   //
    147   // Verify the parameters
    148   //
    149   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    150     //
    151     // Return the transmit buffer
    152     //
    153     pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
    154     if (( NULL != ppTxBuf ) && ( NULL != pNicDevice->pTxBuffer )) {
    155       *ppTxBuf = pNicDevice->pTxBuffer;
    156       pNicDevice->pTxBuffer = NULL;
    157     }
    158 
    159     //
    160     // Determine if interface is running
    161     //
    162     pMode = pSimpleNetwork->Mode;
    163     if ( EfiSimpleNetworkStopped != pMode->State ) {
    164       //
    165       //  Synchronize with Ax88772Timer
    166       //
    167       VERIFY_TPL ( TPL_AX88772 );
    168       TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
    169 
    170       //
    171       // Update the link status
    172       //
    173       bLinkIdle = pNicDevice->bLinkIdle;
    174       pNicDevice->bLinkIdle = TRUE;
    175       Ax88772Rx ( pNicDevice, bLinkIdle );
    176       pMode->MediaPresent = pNicDevice->bLinkUp;
    177 
    178       //
    179       //  Release the synchronization with Ax88772Timer
    180       //
    181       gBS->RestoreTPL ( TplPrevious );
    182 
    183       //
    184       // Return the interrupt status
    185       //
    186       if ( NULL != pInterruptStatus ) {
    187         *pInterruptStatus = 0;
    188       }
    189       Status = EFI_SUCCESS;
    190     }
    191     else {
    192       Status = EFI_NOT_STARTED;
    193     }
    194   }
    195   else {
    196     Status = EFI_INVALID_PARAMETER;
    197   }
    198 
    199   //
    200   // Return the operation status
    201   //
    202   DBG_EXIT_STATUS ( Status );
    203   return Status;
    204 }
    205 
    206 
    207 /**
    208   Resets the network adapter and allocates the transmit and receive buffers
    209   required by the network interface; optionally, also requests allocation of
    210   additional transmit and receive buffers.  This routine must be called before
    211   any other routine in the Simple Network protocol is called.
    212 
    213   @param [in] pSimpleNetwork    Protocol instance pointer
    214   @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation
    215   @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation
    216 
    217   @retval EFI_SUCCESS           This operation was successful.
    218   @retval EFI_NOT_STARTED       The network interface was not started.
    219   @retval EFI_OUT_OF_RESORUCES  There was not enough memory for the transmit and receive buffers
    220   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    221                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    222   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    223   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    224 
    225 **/
    226 EFI_STATUS
    227 EFIAPI
    228 SN_Initialize (
    229   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    230   IN UINTN ExtraRxBufferSize,
    231   IN UINTN ExtraTxBufferSize
    232   )
    233 {
    234   EFI_SIMPLE_NETWORK_MODE * pMode;
    235   EFI_STATUS Status;
    236 
    237   DBG_ENTER ( );
    238 
    239   //
    240   // Verify the parameters
    241   //
    242   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    243     //
    244     // Determine if the interface is already started
    245     //
    246     pMode = pSimpleNetwork->Mode;
    247     if ( EfiSimpleNetworkStarted == pMode->State ) {
    248       if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) {
    249         //
    250         // Start the adapter
    251         //
    252         Status = SN_Reset ( pSimpleNetwork, FALSE );
    253         if ( !EFI_ERROR ( Status )) {
    254           //
    255           // Update the network state
    256           //
    257           pMode->State = EfiSimpleNetworkInitialized;
    258         }
    259       }
    260       else {
    261         Status = EFI_UNSUPPORTED;
    262       }
    263     }
    264     else {
    265       Status = EFI_NOT_STARTED;
    266     }
    267   }
    268   else {
    269     Status = EFI_INVALID_PARAMETER;
    270   }
    271 
    272   //
    273   // Return the operation status
    274   //
    275   DBG_EXIT_STATUS ( Status );
    276   return Status;
    277 }
    278 
    279 
    280 /**
    281   This function converts a multicast IP address to a multicast HW MAC address
    282   for all packet transactions.
    283 
    284   @param [in] pSimpleNetwork    Protocol instance pointer
    285   @param [in] bIPv6             Set to TRUE if the multicast IP address is IPv6 [RFC2460].
    286                                 Set to FALSE if the multicast IP address is IPv4 [RFC 791].
    287   @param [in] pIP               The multicast IP address that is to be converted to a
    288                                 multicast HW MAC address.
    289   @param [in] pMAC              The multicast HW MAC address that is to be generated from IP.
    290 
    291   @retval EFI_SUCCESS           This operation was successful.
    292   @retval EFI_NOT_STARTED       The network interface was not started.
    293   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    294                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    295   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    296   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    297 
    298 **/
    299 EFI_STATUS
    300 EFIAPI
    301 SN_MCastIPtoMAC (
    302   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    303   IN BOOLEAN bIPv6,
    304   IN EFI_IP_ADDRESS * pIP,
    305   IN EFI_MAC_ADDRESS * pMAC
    306   )
    307 {
    308   EFI_STATUS Status;
    309 
    310   DBG_ENTER ( );
    311 
    312   //
    313   // This is not currently supported
    314   //
    315   Status = EFI_UNSUPPORTED;
    316 
    317   //
    318   // Return the operation status
    319   //
    320   DBG_EXIT_STATUS ( Status );
    321   return Status;
    322 }
    323 
    324 
    325 /**
    326   This function performs read and write operations on the NVRAM device
    327   attached to a network interface.
    328 
    329   @param [in] pSimpleNetwork    Protocol instance pointer
    330   @param [in] ReadWrite         TRUE for read operations, FALSE for write operations.
    331   @param [in] Offset            Byte offset in the NVRAM device at which to start the
    332                                 read or write operation.  This must be a multiple of
    333                                 NvRamAccessSize and less than NvRamSize.
    334   @param [in] BufferSize        The number of bytes to read or write from the NVRAM device.
    335                                 This must also be a multiple of NvramAccessSize.
    336   @param [in, out] pBuffer      A pointer to the data buffer.
    337 
    338   @retval EFI_SUCCESS           This operation was successful.
    339   @retval EFI_NOT_STARTED       The network interface was not started.
    340   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    341                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    342   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    343   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    344 
    345 **/
    346 EFI_STATUS
    347 EFIAPI
    348 SN_NvData (
    349   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    350   IN BOOLEAN ReadWrite,
    351   IN UINTN Offset,
    352   IN UINTN BufferSize,
    353   IN OUT VOID * pBuffer
    354   )
    355 {
    356   EFI_STATUS Status;
    357 
    358   DBG_ENTER ( );
    359 
    360   //
    361   // This is not currently supported
    362   //
    363   Status = EFI_UNSUPPORTED;
    364 
    365   //
    366   // Return the operation status
    367   //
    368   DBG_EXIT_STATUS ( Status );
    369   return Status;
    370 }
    371 
    372 
    373 /**
    374   Attempt to receive a packet from the network adapter.
    375 
    376   This function retrieves one packet from the receive queue of the network
    377   interface.  If there are no packets on the receive queue, then EFI_NOT_READY
    378   will be returned.  If there is a packet on the receive queue, and the size
    379   of the packet is smaller than BufferSize, then the contents of the packet
    380   will be placed in Buffer, and BufferSize will be udpated with the actual
    381   size of the packet.  In addition, if SrcAddr, DestAddr, and Protocol are
    382   not NULL, then these values will be extracted from the media header and
    383   returned.  If BufferSize is smaller than the received packet, then the
    384   size of the receive packet will be placed in BufferSize and
    385   EFI_BUFFER_TOO_SMALL will be returned.
    386 
    387   This routine calls ::Ax88772Rx to update the media status and
    388   empty the network adapter of receive packets.
    389 
    390   @param [in] pSimpleNetwork    Protocol instance pointer
    391   @param [out] pHeaderSize      The size, in bytes, of the media header to be filled in by
    392                                 the Transmit() function.  If HeaderSize is non-zero, then
    393                                 it must be equal to SimpleNetwork->Mode->MediaHeaderSize
    394                                 and DestAddr and Protocol parameters must not be NULL.
    395   @param [out] pBufferSize      The size, in bytes, of the entire packet (media header and
    396                                 data) to be transmitted through the network interface.
    397   @param [out] pBuffer          A pointer to the packet (media header followed by data) to
    398                                 to be transmitted.  This parameter can not be NULL.  If
    399                                 HeaderSize is zero, then the media header is Buffer must
    400                                 already be filled in by the caller.  If HeaderSize is nonzero,
    401                                 then the media header will be filled in by the Transmit()
    402                                 function.
    403   @param [out] pSrcAddr         The source HW MAC address.  If HeaderSize is zero, then
    404                                 this parameter is ignored.  If HeaderSize is nonzero and
    405                                 SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
    406                                 is used for the source HW MAC address.
    407   @param [out] pDestAddr        The destination HW MAC address.  If HeaderSize is zero, then
    408                                 this parameter is ignored.
    409   @param [out] pProtocol        The type of header to build.  If HeaderSize is zero, then
    410                                 this parameter is ignored.
    411 
    412   @retval EFI_SUCCESS           This operation was successful.
    413   @retval EFI_NOT_STARTED       The network interface was not started.
    414   @retval EFI_NOT_READY         No packets have been received on the network interface.
    415   @retval EFI_BUFFER_TOO_SMALL  The packet is larger than BufferSize bytes.
    416   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    417                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    418   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    419 
    420 **/
    421 EFI_STATUS
    422 EFIAPI
    423 SN_Receive (
    424   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    425   OUT UINTN                      * pHeaderSize,
    426   OUT UINTN                      * pBufferSize,
    427   OUT VOID                       * pBuffer,
    428   OUT EFI_MAC_ADDRESS            * pSrcAddr,
    429   OUT EFI_MAC_ADDRESS            * pDestAddr,
    430   OUT UINT16                     * pProtocol
    431   )
    432 {
    433   ETHERNET_HEADER * pHeader;
    434   EFI_SIMPLE_NETWORK_MODE * pMode;
    435   NIC_DEVICE * pNicDevice;
    436   RX_TX_PACKET * pRxPacket;
    437   EFI_STATUS Status;
    438   EFI_TPL TplPrevious;
    439   UINT16 Type;
    440 
    441   DBG_ENTER ( );
    442 
    443   //
    444   // Verify the parameters
    445   //
    446   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    447     //
    448     // The interface must be running
    449     //
    450     pMode = pSimpleNetwork->Mode;
    451     if ( EfiSimpleNetworkInitialized == pMode->State ) {
    452       //
    453       //  Synchronize with Ax88772Timer
    454       //
    455       VERIFY_TPL ( TPL_AX88772 );
    456       TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
    457 
    458       //
    459       // Update the link status
    460       //
    461       pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
    462       Ax88772Rx ( pNicDevice, FALSE );
    463       pMode->MediaPresent = pNicDevice->bLinkUp;
    464       if ( pMode->MediaPresent ) {
    465         //
    466         //  Attempt to receive a packet
    467         //
    468         pRxPacket = pNicDevice->pRxHead;
    469         if ( NULL != pRxPacket ) {
    470           pNicDevice->pRxHead = pRxPacket->pNext;
    471           if ( NULL == pNicDevice->pRxHead ) {
    472             pNicDevice->pRxTail = NULL;
    473           }
    474 
    475           //
    476           // Copy the received packet into the receive buffer
    477           //
    478           *pBufferSize = pRxPacket->Length;
    479           CopyMem ( pBuffer, &pRxPacket->Data[0], pRxPacket->Length );
    480           pHeader = (ETHERNET_HEADER *) &pRxPacket->Data[0];
    481           if ( NULL != pHeaderSize ) {
    482             *pHeaderSize = sizeof ( *pHeader );
    483           }
    484           if ( NULL != pDestAddr ) {
    485             CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER );
    486           }
    487           if ( NULL != pSrcAddr ) {
    488             CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER );
    489           }
    490           if ( NULL != pProtocol ) {
    491             Type = pHeader->type;
    492             Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
    493             *pProtocol = Type;
    494           }
    495           Status = EFI_SUCCESS;
    496         }
    497         else {
    498           //
    499           //  No receive packets available
    500           //
    501           Status = EFI_NOT_READY;
    502         }
    503       }
    504       else {
    505         //
    506         //  Link no up
    507         //
    508         Status = EFI_NOT_READY;
    509       }
    510 
    511       //
    512       //  Release the synchronization with Ax88772Timer
    513       //
    514       gBS->RestoreTPL ( TplPrevious );
    515     }
    516     else {
    517       Status = EFI_NOT_STARTED;
    518     }
    519   }
    520   else {
    521     Status = EFI_INVALID_PARAMETER;
    522   }
    523 
    524   //
    525   // Return the operation status
    526   //
    527   DBG_EXIT_STATUS ( Status );
    528   return Status;
    529 }
    530 
    531 
    532 /**
    533   This function is used to enable and disable the hardware and software receive
    534   filters for the underlying network device.
    535 
    536   The receive filter change is broken down into three steps:
    537 
    538     1.  The filter mask bits that are set (ON) in the Enable parameter
    539         are added to the current receive filter settings.
    540 
    541     2.  The filter mask bits that are set (ON) in the Disable parameter
    542         are subtracted from the updated receive filter settins.
    543 
    544     3.  If the resulting filter settigns is not supported by the hardware
    545         a more liberal setting is selected.
    546 
    547   If the same bits are set in the Enable and Disable parameters, then the bits
    548   in the Disable parameter takes precedence.
    549 
    550   If the ResetMCastFilter parameter is TRUE, then the multicast address list
    551   filter is disabled (irregardless of what other multicast bits are set in
    552   the enable and Disable parameters).  The SNP->Mode->MCastFilterCount field
    553   is set to zero.  The SNP->Mode->MCastFilter contents are undefined.
    554 
    555   After enableing or disabling receive filter settings, software should
    556   verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,
    557   SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.
    558 
    559   Note: Some network drivers and/or devices will automatically promote
    560   receive filter settings if the requested setting can not be honored.
    561   For example, if a request for four multicast addresses is made and
    562   the underlying hardware only supports two multicast addresses the
    563   driver might set the promiscuous or promiscuous multicast receive filters
    564   instead.  The receiving software is responsible for discarding any extra
    565   packets that get through the hardware receive filters.
    566 
    567   If ResetMCastFilter is TRUE, then the multicast receive filter list
    568   on the network interface will be reset to the default multicast receive
    569   filter list.  If ResetMCastFilter is FALSE, and this network interface
    570   allows the multicast receive filter list to be modified, then the
    571   MCastFilterCnt and MCastFilter are used to update the current multicast
    572   receive filter list.  The modified receive filter list settings can be
    573   found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.
    574 
    575   This routine calls ::ReceiveFilterUpdate to update the receive
    576   state in the network adapter.
    577 
    578   @param [in] pSimpleNetwork    Protocol instance pointer
    579   @param [in] Enable            A bit mask of receive filters to enable on the network interface.
    580   @param [in] Disable           A bit mask of receive filters to disable on the network interface.
    581                                 For backward compatibility with EFI 1.1 platforms, the
    582                                 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set
    583                                 when the ResetMCastFilter parameter is TRUE.
    584   @param [in] bResetMCastFilter Set to TRUE to reset the contents of the multicast receive
    585                                 filters on the network interface to their default values.
    586   @param [in] MCastFilterCnt    Number of multicast HW MAC address in the new MCastFilter list.
    587                                 This value must be less than or equal to the MaxMCastFilterCnt
    588                                 field of EFI_SIMPLE_NETWORK_MODE.  This field is optional if
    589                                 ResetMCastFilter is TRUE.
    590   @param [in] pMCastFilter      A pointer to a list of new multicast receive filter HW MAC
    591                                 addresses.  This list will replace any existing multicast
    592                                 HW MAC address list.  This field is optional if ResetMCastFilter
    593                                 is TRUE.
    594 
    595   @retval EFI_SUCCESS           This operation was successful.
    596   @retval EFI_NOT_STARTED       The network interface was not started.
    597   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    598                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    599   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    600   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    601 
    602 **/
    603 EFI_STATUS
    604 EFIAPI
    605 SN_ReceiveFilters (
    606   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    607   IN UINT32 Enable,
    608   IN UINT32 Disable,
    609   IN BOOLEAN bResetMCastFilter,
    610   IN UINTN MCastFilterCnt,
    611   IN EFI_MAC_ADDRESS * pMCastFilter
    612   )
    613 {
    614   EFI_SIMPLE_NETWORK_MODE * pMode;
    615   EFI_MAC_ADDRESS * pMulticastAddress;
    616   EFI_MAC_ADDRESS * pTableEnd;
    617   EFI_STATUS Status;
    618 
    619   DBG_ENTER ( );
    620 
    621   //
    622   // Verify the parameters
    623   //
    624   Status = EFI_INVALID_PARAMETER;
    625   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    626     pMode = pSimpleNetwork->Mode;
    627 
    628     //
    629     //  Update the multicast list if necessary
    630     //
    631     if ( !bResetMCastFilter ) {
    632       if ( 0 != MCastFilterCnt ) {
    633         if (( MAX_MCAST_FILTER_CNT >= MCastFilterCnt )
    634           && ( NULL != pMCastFilter )) {
    635           //
    636           // Verify the multicast addresses
    637           //
    638           pMulticastAddress = pMCastFilter;
    639           pTableEnd = pMulticastAddress + MCastFilterCnt;
    640           while ( pTableEnd > pMulticastAddress ) {
    641             //
    642             // The first digit of the multicast address must have the LSB set
    643             //
    644             if ( 0 == ( pMulticastAddress->Addr[0] & 1 )) {
    645               //
    646               // Invalid multicast address
    647               //
    648               break;
    649             }
    650             pMulticastAddress += 1;
    651           }
    652           if ( pTableEnd == pMulticastAddress ) {
    653             //
    654             // Update the multicast filter list.
    655             //
    656             CopyMem (&pMode->MCastFilter[0],
    657                      pMCastFilter,
    658                      MCastFilterCnt * sizeof ( *pMCastFilter ));
    659             Status = EFI_SUCCESS;
    660           }
    661         }
    662       }
    663       else {
    664         Status = EFI_SUCCESS;
    665       }
    666     }
    667     else {
    668       //
    669       // No multicast address list is specified
    670       //
    671       MCastFilterCnt = 0;
    672       Status = EFI_SUCCESS;
    673     }
    674     if ( !EFI_ERROR ( Status )) {
    675       //
    676       // The parameters are valid!
    677       //
    678       pMode->ReceiveFilterSetting |= Enable;
    679       pMode->ReceiveFilterSetting &= ~Disable;
    680       pMode->MCastFilterCount = (UINT32)MCastFilterCnt;
    681 
    682       //
    683       // Update the receive filters in the adapter
    684       //
    685       Status = ReceiveFilterUpdate ( pSimpleNetwork );
    686     }
    687   }
    688 
    689   //
    690   // Return the operation status
    691   //
    692   DBG_EXIT_STATUS ( Status );
    693   return Status;
    694 }
    695 
    696 
    697 /**
    698   Reset the network adapter.
    699 
    700   Resets a network adapter and reinitializes it with the parameters that
    701   were provided in the previous call to Initialize ().  The transmit and
    702   receive queues are cleared.  Receive filters, the station address, the
    703   statistics, and the multicast-IP-to-HW MAC addresses are not reset by
    704   this call.
    705 
    706   This routine calls ::Ax88772Reset to perform the adapter specific
    707   reset operation.  This routine also starts the link negotiation
    708   by calling ::Ax88772NegotiateLinkStart.
    709 
    710   @param [in] pSimpleNetwork    Protocol instance pointer
    711   @param [in] bExtendedVerification  Indicates that the driver may perform a more
    712                                 exhaustive verification operation of the device
    713                                 during reset.
    714 
    715   @retval EFI_SUCCESS           This operation was successful.
    716   @retval EFI_NOT_STARTED       The network interface was not started.
    717   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    718                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    719   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    720   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    721 
    722 **/
    723 EFI_STATUS
    724 EFIAPI
    725 SN_Reset (
    726   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
    727   IN BOOLEAN bExtendedVerification
    728   )
    729 {
    730   EFI_SIMPLE_NETWORK_MODE * pMode;
    731   NIC_DEVICE * pNicDevice;
    732   RX_TX_PACKET * pRxPacket;
    733   EFI_STATUS Status;
    734   EFI_TPL TplPrevious;
    735 
    736   DBG_ENTER ( );
    737 
    738   //
    739   //  Verify the parameters
    740   //
    741   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    742     //
    743     //  Synchronize with Ax88772Timer
    744     //
    745     VERIFY_TPL ( TPL_AX88772 );
    746     TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
    747 
    748     //
    749     //  Update the device state
    750     //
    751     pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
    752     pNicDevice->bComplete = FALSE;
    753     pNicDevice->bLinkUp = FALSE;
    754 
    755     pMode = pSimpleNetwork->Mode;
    756     pMode->MediaPresent = FALSE;
    757 
    758     //
    759     //  Discard any received packets
    760     //
    761     while ( NULL != pNicDevice->pRxHead ) {
    762       //
    763       //  Remove the packet from the received packet list
    764       //
    765       pRxPacket = pNicDevice->pRxHead;
    766       pNicDevice->pRxHead = pRxPacket->pNext;
    767 
    768       //
    769       //  Queue the packet to the free list
    770       //
    771       pRxPacket->pNext = pNicDevice->pRxFree;
    772       pNicDevice->pRxFree = pRxPacket;
    773     }
    774     pNicDevice->pRxTail = NULL;
    775 
    776     //
    777     //  Reset the device
    778     //
    779     Status = Ax88772Reset ( pNicDevice );
    780     if ( !EFI_ERROR ( Status )) {
    781       //
    782       //  Update the receive filters in the adapter
    783       //
    784       Status = ReceiveFilterUpdate ( pSimpleNetwork );
    785 
    786       //
    787       //  Try to get a connection to the network
    788       //
    789       if ( !EFI_ERROR ( Status )) {
    790         //
    791         //  Start the autonegotiation
    792         //
    793         Status = Ax88772NegotiateLinkStart ( pNicDevice );
    794       }
    795     }
    796 
    797     //
    798     //  Release the synchronization with Ax88772Timer
    799     //
    800     gBS->RestoreTPL ( TplPrevious );
    801   }
    802   else {
    803     Status = EFI_INVALID_PARAMETER;
    804   }
    805 
    806   //
    807   // Return the operation status
    808   //
    809   DBG_EXIT_STATUS ( Status );
    810   return Status;
    811 }
    812 
    813 
    814 /**
    815   Initialize the simple network protocol.
    816 
    817   This routine calls ::Ax88772MacAddressGet to obtain the
    818   MAC address.
    819 
    820   @param [in] pNicDevice       NIC_DEVICE_INSTANCE pointer
    821 
    822   @retval EFI_SUCCESS     Setup was successful
    823 
    824 **/
    825 EFI_STATUS
    826 SN_Setup (
    827   IN NIC_DEVICE * pNicDevice
    828   )
    829 {
    830   EFI_SIMPLE_NETWORK_MODE * pMode;
    831   EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork;
    832   EFI_STATUS Status;
    833 
    834   DBG_ENTER ( );
    835 
    836   //
    837   // Initialize the simple network protocol
    838   //
    839   pSimpleNetwork = &pNicDevice->SimpleNetwork;
    840   pSimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
    841   pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start;
    842   pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop;
    843   pSimpleNetwork->Initialize = (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize;
    844   pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset;
    845   pSimpleNetwork->Shutdown = (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown;
    846   pSimpleNetwork->ReceiveFilters = (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters;
    847   pSimpleNetwork->StationAddress = (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress;
    848   pSimpleNetwork->Statistics = (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics;
    849   pSimpleNetwork->MCastIpToMac = (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC;
    850   pSimpleNetwork->NvData = (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData;
    851   pSimpleNetwork->GetStatus = (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus;
    852   pSimpleNetwork->Transmit = (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit;
    853   pSimpleNetwork->Receive = (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive;
    854   pSimpleNetwork->WaitForPacket = NULL;
    855   pMode = &pNicDevice->SimpleNetworkData;
    856   pSimpleNetwork->Mode = pMode;
    857 
    858   pMode->State = EfiSimpleNetworkStopped;
    859   pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
    860   pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
    861   pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
    862   pMode->NvRamSize = 0;
    863   pMode->NvRamAccessSize = 0;
    864   pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
    865                            | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
    866                            | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
    867                            | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
    868                            | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
    869   pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
    870                               | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
    871   pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
    872   pMode->MCastFilterCount = 0;
    873   SetMem ( &pMode->BroadcastAddress,
    874            PXE_HWADDR_LEN_ETHER,
    875            0xff );
    876   pMode->IfType = EfiNetworkInterfaceUndi;
    877   pMode->MacAddressChangeable = TRUE;
    878   pMode->MultipleTxSupported = TRUE;
    879   pMode->MediaPresentSupported = TRUE;
    880   pMode->MediaPresent = FALSE;
    881 
    882   //
    883   //  Read the MAC address
    884   //
    885   pNicDevice->PhyId = PHY_ID_INTERNAL;
    886   pNicDevice->b100Mbps = TRUE;
    887   pNicDevice->bFullDuplex = TRUE;
    888 
    889   Status = gBS->AllocatePool ( EfiRuntimeServicesData,
    890                                MAX_BULKIN_SIZE,
    891                                (VOID **) &pNicDevice->pBulkInBuff);
    892   if ( EFI_ERROR(Status)) {
    893     DEBUG (( EFI_D_ERROR, "Memory are not enough\n"));
    894     return Status;
    895   }
    896 
    897   Status = Ax88772MacAddressGet (
    898                 pNicDevice,
    899                 &pMode->PermanentAddress.Addr[0]);
    900   if ( !EFI_ERROR ( Status )) {
    901     //
    902     //  Display the MAC address
    903     //
    904     DEBUG (( DEBUG_MAC_ADDRESS | DEBUG_INFO,
    905               "MAC: %02x-%02x-%02x-%02x-%02x-%02x\n",
    906               pMode->PermanentAddress.Addr[0],
    907               pMode->PermanentAddress.Addr[1],
    908               pMode->PermanentAddress.Addr[2],
    909               pMode->PermanentAddress.Addr[3],
    910               pMode->PermanentAddress.Addr[4],
    911               pMode->PermanentAddress.Addr[5]));
    912 
    913     //
    914     //  Use the hardware address as the current address
    915     //
    916     CopyMem ( &pMode->CurrentAddress,
    917               &pMode->PermanentAddress,
    918               PXE_HWADDR_LEN_ETHER );
    919   }
    920 
    921   //
    922   //  Return the setup status
    923   //
    924   DBG_EXIT_STATUS ( Status );
    925   return Status;
    926 }
    927 
    928 
    929 /**
    930   This routine starts the network interface.
    931 
    932   @param [in] pSimpleNetwork    Protocol instance pointer
    933 
    934   @retval EFI_SUCCESS           This operation was successful.
    935   @retval EFI_ALREADY_STARTED   The network interface was already started.
    936   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
    937                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    938   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    939   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    940 
    941 **/
    942 EFI_STATUS
    943 EFIAPI
    944 SN_Start (
    945   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
    946   )
    947 {
    948   NIC_DEVICE * pNicDevice;
    949   EFI_SIMPLE_NETWORK_MODE * pMode;
    950   EFI_STATUS Status;
    951 
    952   DBG_ENTER ( );
    953 
    954   //
    955   // Verify the parameters
    956   //
    957   Status = EFI_INVALID_PARAMETER;
    958   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
    959     pMode = pSimpleNetwork->Mode;
    960     if ( EfiSimpleNetworkStopped == pMode->State ) {
    961       //
    962       // Initialize the mode structure
    963       // NVRAM access is not supported
    964       //
    965       ZeroMem ( pMode, sizeof ( *pMode ));
    966 
    967       pMode->State = EfiSimpleNetworkStarted;
    968       pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
    969       pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
    970       pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
    971       pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
    972                                | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
    973                                | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
    974                                | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
    975                                | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
    976       pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
    977       pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
    978       pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
    979       Status = Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddress.Addr[0]);
    980       CopyMem ( &pMode->CurrentAddress,
    981                 &pMode->PermanentAddress,
    982                 sizeof ( pMode->CurrentAddress ));
    983       pMode->BroadcastAddress.Addr[0] = 0xff;
    984       pMode->BroadcastAddress.Addr[1] = 0xff;
    985       pMode->BroadcastAddress.Addr[2] = 0xff;
    986       pMode->BroadcastAddress.Addr[3] = 0xff;
    987       pMode->BroadcastAddress.Addr[4] = 0xff;
    988       pMode->BroadcastAddress.Addr[5] = 0xff;
    989       pMode->IfType = 1;
    990       pMode->MacAddressChangeable = TRUE;
    991       pMode->MultipleTxSupported = TRUE;
    992       pMode->MediaPresentSupported = TRUE;
    993       pMode->MediaPresent = FALSE;
    994     }
    995     else {
    996       Status = EFI_ALREADY_STARTED;
    997     }
    998   }
    999 
   1000   //
   1001   // Return the operation status
   1002   //
   1003   DBG_EXIT_STATUS ( Status );
   1004   return Status;
   1005 }
   1006 
   1007 
   1008 /**
   1009   Set the MAC address.
   1010 
   1011   This function modifies or resets the current station address of a
   1012   network interface.  If Reset is TRUE, then the current station address
   1013   is set ot the network interface's permanent address.  If Reset if FALSE
   1014   then the current station address is changed to the address specified by
   1015   pNew.
   1016 
   1017   This routine calls ::Ax88772MacAddressSet to update the MAC address
   1018   in the network adapter.
   1019 
   1020   @param [in] pSimpleNetwork    Protocol instance pointer
   1021   @param [in] bReset            Flag used to reset the station address to the
   1022                                 network interface's permanent address.
   1023   @param [in] pNew              New station address to be used for the network
   1024                                 interface.
   1025 
   1026   @retval EFI_SUCCESS           This operation was successful.
   1027   @retval EFI_NOT_STARTED       The network interface was not started.
   1028   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
   1029                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
   1030   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
   1031   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
   1032 
   1033 **/
   1034 EFI_STATUS
   1035 EFIAPI
   1036 SN_StationAddress (
   1037   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
   1038   IN BOOLEAN bReset,
   1039   IN EFI_MAC_ADDRESS * pNew
   1040   )
   1041 {
   1042   NIC_DEVICE * pNicDevice;
   1043   EFI_SIMPLE_NETWORK_MODE * pMode;
   1044   EFI_STATUS Status;
   1045 
   1046   DBG_ENTER ( );
   1047 
   1048   //
   1049   // Verify the parameters
   1050   //
   1051   if (( NULL != pSimpleNetwork )
   1052     && ( NULL != pSimpleNetwork->Mode )
   1053     && (( !bReset ) || ( bReset && ( NULL != pNew )))) {
   1054     //
   1055     // Verify that the adapter is already started
   1056     //
   1057     pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
   1058     pMode = pSimpleNetwork->Mode;
   1059     if ( EfiSimpleNetworkStarted == pMode->State ) {
   1060       //
   1061       // Determine the adapter MAC address
   1062       //
   1063       if ( bReset ) {
   1064         //
   1065         // Use the permanent address
   1066         //
   1067         CopyMem ( &pMode->CurrentAddress,
   1068                   &pMode->PermanentAddress,
   1069                   sizeof ( pMode->CurrentAddress ));
   1070       }
   1071       else {
   1072         //
   1073         // Use the specified address
   1074         //
   1075         CopyMem ( &pMode->CurrentAddress,
   1076                   pNew,
   1077                   sizeof ( pMode->CurrentAddress ));
   1078       }
   1079 
   1080       //
   1081       // Update the address on the adapter
   1082       //
   1083       Status = Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress.Addr[0]);
   1084     }
   1085     else {
   1086       Status = EFI_NOT_STARTED;
   1087     }
   1088   }
   1089   else {
   1090     Status = EFI_INVALID_PARAMETER;
   1091   }
   1092 
   1093   //
   1094   // Return the operation status
   1095   //
   1096   DBG_EXIT_STATUS ( Status );
   1097   return Status;
   1098 }
   1099 
   1100 
   1101 /**
   1102   This function resets or collects the statistics on a network interface.
   1103   If the size of the statistics table specified by StatisticsSize is not
   1104   big enough for all of the statistics that are collected by the network
   1105   interface, then a partial buffer of statistics is returned in
   1106   StatisticsTable.
   1107 
   1108   @param [in] pSimpleNetwork    Protocol instance pointer
   1109   @param [in] bReset            Set to TRUE to reset the statistics for the network interface.
   1110   @param [in, out] pStatisticsSize  On input the size, in bytes, of StatisticsTable.  On output
   1111                                 the size, in bytes, of the resulting table of statistics.
   1112   @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
   1113                                 conains the statistics.
   1114 
   1115   @retval EFI_SUCCESS           This operation was successful.
   1116   @retval EFI_NOT_STARTED       The network interface was not started.
   1117   @retval EFI_BUFFER_TOO_SMALL  The pStatisticsTable is NULL or the buffer is too small.
   1118   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
   1119                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
   1120   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
   1121   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
   1122 
   1123 **/
   1124 EFI_STATUS
   1125 EFIAPI
   1126 SN_Statistics (
   1127   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
   1128   IN BOOLEAN bReset,
   1129   IN OUT UINTN * pStatisticsSize,
   1130   OUT EFI_NETWORK_STATISTICS * pStatisticsTable
   1131   )
   1132 {
   1133   EFI_STATUS Status;
   1134 
   1135   DBG_ENTER ( );
   1136 
   1137   //
   1138   // This is not currently supported
   1139   //
   1140   Status = EFI_UNSUPPORTED;
   1141 
   1142   //
   1143   // Return the operation status
   1144   //
   1145   DBG_EXIT_STATUS ( Status );
   1146   return Status;
   1147 }
   1148 
   1149 
   1150 /**
   1151   This function stops a network interface.  This call is only valid
   1152   if the network interface is in the started state.
   1153 
   1154   @param [in] pSimpleNetwork    Protocol instance pointer
   1155 
   1156   @retval EFI_SUCCESS           This operation was successful.
   1157   @retval EFI_NOT_STARTED       The network interface was not started.
   1158   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
   1159                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
   1160   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
   1161   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
   1162 
   1163 **/
   1164 EFI_STATUS
   1165 EFIAPI
   1166 SN_Stop (
   1167   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
   1168   )
   1169 {
   1170   EFI_SIMPLE_NETWORK_MODE * pMode;
   1171   EFI_STATUS Status;
   1172 
   1173   DBG_ENTER ( );
   1174 
   1175   //
   1176   // Verify the parameters
   1177   //
   1178   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
   1179     //
   1180     // Determine if the interface is started
   1181     //
   1182     pMode = pSimpleNetwork->Mode;
   1183     if ( EfiSimpleNetworkStopped != pMode->State ) {
   1184       if ( EfiSimpleNetworkStarted == pMode->State ) {
   1185         //
   1186         //  Release the resources acquired in SN_Start
   1187         //
   1188 
   1189         //
   1190         //  Mark the adapter as stopped
   1191         //
   1192         pMode->State = EfiSimpleNetworkStopped;
   1193         Status = EFI_SUCCESS;
   1194       }
   1195       else {
   1196         Status = EFI_UNSUPPORTED;
   1197       }
   1198     }
   1199     else {
   1200       Status = EFI_NOT_STARTED;
   1201     }
   1202   }
   1203   else {
   1204     Status = EFI_INVALID_PARAMETER;
   1205   }
   1206 
   1207   //
   1208   // Return the operation status
   1209   //
   1210   DBG_EXIT_STATUS ( Status );
   1211   return Status;
   1212 }
   1213 
   1214 
   1215 /**
   1216   This function releases the memory buffers assigned in the Initialize() call.
   1217   Pending transmits and receives are lost, and interrupts are cleared and disabled.
   1218   After this call, only Initialize() and Stop() calls may be used.
   1219 
   1220   @param [in] pSimpleNetwork    Protocol instance pointer
   1221 
   1222   @retval EFI_SUCCESS           This operation was successful.
   1223   @retval EFI_NOT_STARTED       The network interface was not started.
   1224   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
   1225                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
   1226   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
   1227   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
   1228 
   1229 **/
   1230 EFI_STATUS
   1231 EFIAPI
   1232 SN_Shutdown (
   1233   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
   1234   )
   1235 {
   1236   EFI_SIMPLE_NETWORK_MODE * pMode;
   1237   UINT32 RxFilter;
   1238   EFI_STATUS Status;
   1239 
   1240   DBG_ENTER ( );
   1241 
   1242   //
   1243   // Verify the parameters
   1244   //
   1245   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
   1246     //
   1247     // Determine if the interface is already started
   1248     //
   1249     pMode = pSimpleNetwork->Mode;
   1250     if ( EfiSimpleNetworkInitialized == pMode->State ) {
   1251       //
   1252       // Stop the adapter
   1253       //
   1254       RxFilter = pMode->ReceiveFilterSetting;
   1255       pMode->ReceiveFilterSetting = 0;
   1256       Status = SN_Reset ( pSimpleNetwork, FALSE );
   1257       pMode->ReceiveFilterSetting = RxFilter;
   1258       if ( !EFI_ERROR ( Status )) {
   1259         //
   1260         // Release the resources acquired by SN_Initialize
   1261         //
   1262 
   1263         //
   1264         // Update the network state
   1265         //
   1266         pMode->State = EfiSimpleNetworkStarted;
   1267       }
   1268     }
   1269     else {
   1270       Status = EFI_NOT_STARTED;
   1271     }
   1272   }
   1273   else {
   1274     Status = EFI_INVALID_PARAMETER;
   1275   }
   1276 
   1277   //
   1278   // Return the operation status
   1279   //
   1280   DBG_EXIT_STATUS ( Status );
   1281   return Status;
   1282 }
   1283 
   1284 
   1285 /**
   1286   Send a packet over the network.
   1287 
   1288   This function places the packet specified by Header and Buffer on
   1289   the transmit queue.  This function performs a non-blocking transmit
   1290   operation.  When the transmit is complete, the buffer is returned
   1291   via the GetStatus() call.
   1292 
   1293   This routine calls ::Ax88772Rx to empty the network adapter of
   1294   receive packets.  The routine then passes the transmit packet
   1295   to the network adapter.
   1296 
   1297   @param [in] pSimpleNetwork    Protocol instance pointer
   1298   @param [in] HeaderSize        The size, in bytes, of the media header to be filled in by
   1299                                 the Transmit() function.  If HeaderSize is non-zero, then
   1300                                 it must be equal to SimpleNetwork->Mode->MediaHeaderSize
   1301                                 and DestAddr and Protocol parameters must not be NULL.
   1302   @param [in] BufferSize        The size, in bytes, of the entire packet (media header and
   1303                                 data) to be transmitted through the network interface.
   1304   @param [in] pBuffer           A pointer to the packet (media header followed by data) to
   1305                                 to be transmitted.  This parameter can not be NULL.  If
   1306                                 HeaderSize is zero, then the media header is Buffer must
   1307                                 already be filled in by the caller.  If HeaderSize is nonzero,
   1308                                 then the media header will be filled in by the Transmit()
   1309                                 function.
   1310   @param [in] pSrcAddr          The source HW MAC address.  If HeaderSize is zero, then
   1311                                 this parameter is ignored.  If HeaderSize is nonzero and
   1312                                 SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
   1313                                 is used for the source HW MAC address.
   1314   @param [in] pDestAddr         The destination HW MAC address.  If HeaderSize is zero, then
   1315                                 this parameter is ignored.
   1316   @param [in] pProtocol         The type of header to build.  If HeaderSize is zero, then
   1317                                 this parameter is ignored.
   1318 
   1319   @retval EFI_SUCCESS           This operation was successful.
   1320   @retval EFI_NOT_STARTED       The network interface was not started.
   1321   @retval EFI_NOT_READY         The network interface is too busy to accept this transmit request.
   1322   @retval EFI_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
   1323   @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
   1324                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
   1325   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
   1326 
   1327 **/
   1328 EFI_STATUS
   1329 EFIAPI
   1330 SN_Transmit (
   1331   IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
   1332   IN UINTN HeaderSize,
   1333   IN UINTN BufferSize,
   1334   IN VOID * pBuffer,
   1335   IN EFI_MAC_ADDRESS * pSrcAddr,
   1336   IN EFI_MAC_ADDRESS * pDestAddr,
   1337   IN UINT16 * pProtocol
   1338   )
   1339 {
   1340   RX_TX_PACKET Packet;
   1341   ETHERNET_HEADER * pHeader;
   1342   EFI_SIMPLE_NETWORK_MODE * pMode;
   1343   NIC_DEVICE * pNicDevice;
   1344   EFI_USB_IO_PROTOCOL * pUsbIo;
   1345   EFI_STATUS Status;
   1346   EFI_TPL TplPrevious;
   1347   UINTN TransferLength;
   1348   UINT32 TransferStatus;
   1349   UINT16 Type;
   1350 
   1351   DBG_ENTER ( );
   1352 
   1353   //
   1354   // Verify the parameters
   1355   //
   1356   if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
   1357     //
   1358     // The interface must be running
   1359     //
   1360     pMode = pSimpleNetwork->Mode;
   1361     if ( EfiSimpleNetworkInitialized == pMode->State ) {
   1362       //
   1363       //  Synchronize with Ax88772Timer
   1364       //
   1365       VERIFY_TPL ( TPL_AX88772 );
   1366       TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
   1367 
   1368       //
   1369       // Update the link status
   1370       //
   1371       pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
   1372 
   1373       //
   1374       //No need to call receive to receive packet
   1375       //
   1376       //Ax88772Rx ( pNicDevice, FALSE );
   1377       pMode->MediaPresent = pNicDevice->bLinkUp;
   1378 
   1379       //
   1380       //  Release the synchronization with Ax88772Timer
   1381       //
   1382       gBS->RestoreTPL ( TplPrevious );
   1383       if ( pMode->MediaPresent ) {
   1384         //
   1385         //  Copy the packet into the USB buffer
   1386         //
   1387         CopyMem ( &Packet.Data[0], pBuffer, BufferSize );
   1388         Packet.Length = (UINT16) BufferSize;
   1389 
   1390         //
   1391         //  Transmit the packet
   1392         //
   1393         pHeader = (ETHERNET_HEADER *) &Packet.Data[0];
   1394         if ( 0 != HeaderSize ) {
   1395           if ( NULL != pDestAddr ) {
   1396             CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER );
   1397           }
   1398           if ( NULL != pSrcAddr ) {
   1399             CopyMem ( &pHeader->src_addr, pSrcAddr, PXE_HWADDR_LEN_ETHER );
   1400           }
   1401           else {
   1402             CopyMem ( &pHeader->src_addr, &pMode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER );
   1403           }
   1404           if ( NULL != pProtocol ) {
   1405             Type = *pProtocol;
   1406           }
   1407           else {
   1408             Type = Packet.Length;
   1409           }
   1410           Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
   1411           pHeader->type = Type;
   1412         }
   1413         if ( Packet.Length < MIN_ETHERNET_PKT_SIZE ) {
   1414           Packet.Length = MIN_ETHERNET_PKT_SIZE;
   1415           ZeroMem ( &Packet.Data[ BufferSize ],
   1416                     Packet.Length - BufferSize );
   1417         }
   1418         DEBUG (( DEBUG_TX | DEBUG_INFO,
   1419                   "TX: %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x-%02x-%02x-%02x-%02x  %02x-%02x  %d bytes\r\n",
   1420                   Packet.Data[0],
   1421                   Packet.Data[1],
   1422                   Packet.Data[2],
   1423                   Packet.Data[3],
   1424                   Packet.Data[4],
   1425                   Packet.Data[5],
   1426                   Packet.Data[6],
   1427                   Packet.Data[7],
   1428                   Packet.Data[8],
   1429                   Packet.Data[9],
   1430                   Packet.Data[10],
   1431                   Packet.Data[11],
   1432                   Packet.Data[12],
   1433                   Packet.Data[13],
   1434                   Packet.Length ));
   1435         Packet.LengthBar = ~Packet.Length;
   1436         TransferLength = sizeof ( Packet.Length )
   1437                        + sizeof ( Packet.LengthBar )
   1438                        + Packet.Length;
   1439 
   1440         //
   1441         //  Work around USB bus driver bug where a timeout set by receive
   1442         //  succeeds but the timeout expires immediately after, causing the
   1443         //  transmit operation to timeout.
   1444         //
   1445         pUsbIo = pNicDevice->pUsbIo;
   1446         Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
   1447                                            BULK_OUT_ENDPOINT,
   1448                                            &Packet.Length,
   1449                                            &TransferLength,
   1450                                            0xfffffffe,
   1451                                            &TransferStatus );
   1452         if ( !EFI_ERROR ( Status )) {
   1453           Status = TransferStatus;
   1454         }
   1455         if (( !EFI_ERROR ( Status ))
   1456           && ( TransferLength != (UINTN)( Packet.Length + 4 ))) {
   1457           Status = EFI_WARN_WRITE_FAILURE;
   1458         }
   1459         if ( EFI_SUCCESS == Status ) {
   1460           pNicDevice->pTxBuffer = pBuffer;
   1461         }
   1462         else {
   1463           DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1464                     "Ax88772 USB transmit error, TransferLength: %d, Status: %r\r\n",
   1465                     sizeof ( Packet.Length ) + Packet.Length,
   1466                     Status ));
   1467           //
   1468           //  Reset the controller to fix the error
   1469           //
   1470           if ( EFI_DEVICE_ERROR == Status ) {
   1471             SN_Reset ( pSimpleNetwork, FALSE );
   1472           }
   1473         }
   1474       }
   1475       else {
   1476         //
   1477         // No packets available.
   1478         //
   1479         Status = EFI_NOT_READY;
   1480       }
   1481     }
   1482     else {
   1483       Status = EFI_NOT_STARTED;
   1484     }
   1485   }
   1486   else {
   1487     DEBUG (( DEBUG_ERROR | DEBUG_INFO,
   1488               "Ax88772 invalid transmit parameter\r\n"
   1489               "  0x%08x: HeaderSize\r\n"
   1490               "  0x%08x: BufferSize\r\n"
   1491               "  0x%08x: Buffer\r\n"
   1492               "  0x%08x: SrcAddr\r\n"
   1493               "  0x%08x: DestAddr\r\n"
   1494               "  0x%04x:     Protocol\r\n",
   1495               HeaderSize,
   1496               BufferSize,
   1497               pBuffer,
   1498               pSrcAddr,
   1499               pDestAddr,
   1500               pProtocol ));
   1501     Status = EFI_INVALID_PARAMETER;
   1502   }
   1503 
   1504   //
   1505   // Return the operation status
   1506   //
   1507   DBG_EXIT_STATUS ( Status );
   1508   return Status;
   1509 }
   1510