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