Home | History | Annotate | Download | only in SnpDxe
      1 /** @file
      2  		Implementation of initializing a network adapter.
      3 
      4 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials are licensed
      6 and made available under the terms and conditions of the BSD License which
      7 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 
     16 #include "Snp.h"
     17 
     18 /**
     19   Call UNDI to initialize the interface.
     20 
     21   @param  Snp                   Pointer to snp driver structure.
     22   @param  CableDetectFlag       Do/don't detect the cable (depending on what
     23                                 undi supports).
     24 
     25   @retval EFI_SUCCESS           UNDI is initialized successfully.
     26   @retval EFI_DEVICE_ERROR      UNDI could not be initialized.
     27   @retval Other                 Other errors as indicated.
     28 
     29 **/
     30 EFI_STATUS
     31 PxeInit (
     32   SNP_DRIVER *Snp,
     33   UINT16     CableDetectFlag
     34   )
     35 {
     36   PXE_CPB_INITIALIZE  *Cpb;
     37   VOID                *Addr;
     38   EFI_STATUS          Status;
     39 
     40   Cpb = Snp->Cpb;
     41   if (Snp->TxRxBufferSize != 0) {
     42     Status = Snp->PciIo->AllocateBuffer (
     43                            Snp->PciIo,
     44                            AllocateAnyPages,
     45                            EfiBootServicesData,
     46                            SNP_MEM_PAGES (Snp->TxRxBufferSize),
     47                            &Addr,
     48                            0
     49                            );
     50 
     51     if (Status != EFI_SUCCESS) {
     52       DEBUG (
     53         (EFI_D_ERROR,
     54         "\nSnp->PxeInit()  AllocateBuffer  %xh (%r)\n",
     55         Status,
     56         Status)
     57         );
     58 
     59       return Status;
     60     }
     61 
     62     ASSERT (Addr);
     63 
     64     Snp->TxRxBuffer = Addr;
     65   }
     66 
     67   Cpb->MemoryAddr   = (UINT64)(UINTN) Snp->TxRxBuffer;
     68 
     69   Cpb->MemoryLength = Snp->TxRxBufferSize;
     70 
     71   //
     72   // let UNDI decide/detect these values
     73   //
     74   Cpb->LinkSpeed      = 0;
     75   Cpb->TxBufCnt       = 0;
     76   Cpb->TxBufSize      = 0;
     77   Cpb->RxBufCnt       = 0;
     78   Cpb->RxBufSize      = 0;
     79 
     80   Cpb->DuplexMode         = PXE_DUPLEX_DEFAULT;
     81 
     82   Cpb->LoopBackMode       = LOOPBACK_NORMAL;
     83 
     84   Snp->Cdb.OpCode     = PXE_OPCODE_INITIALIZE;
     85   Snp->Cdb.OpFlags    = CableDetectFlag;
     86 
     87   Snp->Cdb.CPBsize    = (UINT16) sizeof (PXE_CPB_INITIALIZE);
     88   Snp->Cdb.DBsize     = (UINT16) sizeof (PXE_DB_INITIALIZE);
     89 
     90   Snp->Cdb.CPBaddr    = (UINT64)(UINTN) Snp->Cpb;
     91   Snp->Cdb.DBaddr     = (UINT64)(UINTN) Snp->Db;
     92 
     93   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;
     94   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;
     95   Snp->Cdb.IFnum      = Snp->IfNum;
     96   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;
     97 
     98   DEBUG ((EFI_D_NET, "\nSnp->undi.initialize()  "));
     99 
    100   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
    101 
    102   if (Snp->Cdb.StatCode == PXE_STATCODE_SUCCESS) {
    103     Snp->Mode.State = EfiSimpleNetworkInitialized;
    104 
    105     Status          = EFI_SUCCESS;
    106   } else {
    107     DEBUG (
    108       (EFI_D_WARN,
    109       "\nSnp->undi.initialize()  %xh:%xh\n",
    110       Snp->Cdb.StatFlags,
    111       Snp->Cdb.StatCode)
    112       );
    113 
    114     if (Snp->TxRxBuffer != NULL) {
    115       Snp->PciIo->FreeBuffer (
    116                     Snp->PciIo,
    117                     SNP_MEM_PAGES (Snp->TxRxBufferSize),
    118                     (VOID *) Snp->TxRxBuffer
    119                     );
    120     }
    121 
    122     Snp->TxRxBuffer = NULL;
    123 
    124     Status          = EFI_DEVICE_ERROR;
    125   }
    126 
    127   return Status;
    128 }
    129 
    130 
    131 /**
    132   Resets a network adapter and allocates the transmit and receive buffers
    133   required by the network interface; optionally, also requests allocation of
    134   additional transmit and receive buffers.
    135 
    136   This function allocates the transmit and receive buffers required by the network
    137   interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned.
    138   If the allocation succeeds and the network interface is successfully initialized,
    139   then EFI_SUCCESS will be returned.
    140 
    141   @param This               A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
    142 
    143   @param ExtraRxBufferSize  The size, in bytes, of the extra receive buffer space
    144                             that the driver should allocate for the network interface.
    145                             Some network interfaces will not be able to use the
    146                             extra buffer, and the caller will not know if it is
    147                             actually being used.
    148   @param ExtraTxBufferSize  The size, in bytes, of the extra transmit buffer space
    149                             that the driver should allocate for the network interface.
    150                             Some network interfaces will not be able to use the
    151                             extra buffer, and the caller will not know if it is
    152                             actually being used.
    153 
    154   @retval EFI_SUCCESS           The network interface was initialized.
    155   @retval EFI_NOT_STARTED       The network interface has not been started.
    156   @retval EFI_OUT_OF_RESOURCES  There was not enough memory for the transmit and
    157                                 receive buffers.
    158   @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
    159                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
    160   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
    161   @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
    162 
    163 **/
    164 EFI_STATUS
    165 EFIAPI
    166 SnpUndi32Initialize (
    167   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    168   IN UINTN                       ExtraRxBufferSize OPTIONAL,
    169   IN UINTN                       ExtraTxBufferSize OPTIONAL
    170   )
    171 {
    172   EFI_STATUS  EfiStatus;
    173   SNP_DRIVER  *Snp;
    174   EFI_TPL     OldTpl;
    175 
    176   if (This == NULL) {
    177     return EFI_INVALID_PARAMETER;
    178   }
    179 
    180   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
    181 
    182   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    183 
    184   if (Snp == NULL) {
    185     EfiStatus = EFI_INVALID_PARAMETER;
    186     goto ON_EXIT;
    187   }
    188 
    189   switch (Snp->Mode.State) {
    190   case EfiSimpleNetworkStarted:
    191     break;
    192 
    193   case EfiSimpleNetworkStopped:
    194     EfiStatus = EFI_NOT_STARTED;
    195     goto ON_EXIT;
    196 
    197   default:
    198     EfiStatus = EFI_DEVICE_ERROR;
    199     goto ON_EXIT;
    200   }
    201 
    202   EfiStatus = gBS->CreateEvent (
    203                     EVT_NOTIFY_WAIT,
    204                     TPL_NOTIFY,
    205                     &SnpWaitForPacketNotify,
    206                     Snp,
    207                     &Snp->Snp.WaitForPacket
    208                     );
    209 
    210   if (EFI_ERROR (EfiStatus)) {
    211     Snp->Snp.WaitForPacket = NULL;
    212     EfiStatus = EFI_DEVICE_ERROR;
    213     goto ON_EXIT;
    214   }
    215   //
    216   //
    217   //
    218   Snp->Mode.MCastFilterCount      = 0;
    219   Snp->Mode.ReceiveFilterSetting  = 0;
    220   ZeroMem (Snp->Mode.MCastFilter, sizeof Snp->Mode.MCastFilter);
    221   CopyMem (
    222     &Snp->Mode.CurrentAddress,
    223     &Snp->Mode.PermanentAddress,
    224     sizeof (EFI_MAC_ADDRESS)
    225     );
    226 
    227   //
    228   // Compute tx/rx buffer sizes based on UNDI init info and parameters.
    229   //
    230   Snp->TxRxBufferSize = (UINT32) (Snp->InitInfo.MemoryRequired + ExtraRxBufferSize + ExtraTxBufferSize);
    231 
    232   if (Snp->Mode.MediaPresentSupported) {
    233     if (PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {
    234       Snp->Mode.MediaPresent = TRUE;
    235       goto ON_EXIT;
    236     }
    237   }
    238 
    239   Snp->Mode.MediaPresent  = FALSE;
    240 
    241   EfiStatus               = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
    242 
    243   if (EFI_ERROR (EfiStatus)) {
    244     gBS->CloseEvent (Snp->Snp.WaitForPacket);
    245   }
    246 
    247 ON_EXIT:
    248   gBS->RestoreTPL (OldTpl);
    249 
    250   return EfiStatus;
    251 }
    252