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