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
PxeInit(SNP_DRIVER * Snp,UINT16 CableDetectFlag)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
SnpUndi32Initialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)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