]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/SnpDxe/Initialize.c
NetworkPkg: Apply uncrustify changes
[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 #include "Snp.h"
10
11 /**
12 Call UNDI to initialize the interface.
13
14 @param Snp Pointer to snp driver structure.
15 @param CableDetectFlag Do/don't detect the cable (depending on what
16 undi supports).
17
18 @retval EFI_SUCCESS UNDI is initialized successfully.
19 @retval EFI_DEVICE_ERROR UNDI could not be initialized.
20 @retval Other Other errors as indicated.
21
22 **/
23 EFI_STATUS
24 PxeInit (
25 SNP_DRIVER *Snp,
26 UINT16 CableDetectFlag
27 )
28 {
29 PXE_CPB_INITIALIZE *Cpb;
30 VOID *Addr;
31 EFI_STATUS Status;
32
33 Status = EFI_SUCCESS;
34
35 Cpb = Snp->Cpb;
36 if (Snp->TxRxBufferSize != 0) {
37 Status = Snp->PciIo->AllocateBuffer (
38 Snp->PciIo,
39 AllocateAnyPages,
40 EfiBootServicesData,
41 SNP_MEM_PAGES (Snp->TxRxBufferSize),
42 &Addr,
43 0
44 );
45
46 if (Status != EFI_SUCCESS) {
47 DEBUG (
48 (DEBUG_ERROR,
49 "\nSnp->PxeInit() AllocateBuffer %xh (%r)\n",
50 Status,
51 Status)
52 );
53
54 return Status;
55 }
56
57 ASSERT (Addr);
58
59 Snp->TxRxBuffer = Addr;
60 }
61
62 Cpb->MemoryAddr = (UINT64)(UINTN)Snp->TxRxBuffer;
63
64 Cpb->MemoryLength = Snp->TxRxBufferSize;
65
66 //
67 // let UNDI decide/detect these values
68 //
69 Cpb->LinkSpeed = 0;
70 Cpb->TxBufCnt = 0;
71 Cpb->TxBufSize = 0;
72 Cpb->RxBufCnt = 0;
73 Cpb->RxBufSize = 0;
74
75 Cpb->DuplexMode = PXE_DUPLEX_DEFAULT;
76
77 Cpb->LoopBackMode = LOOPBACK_NORMAL;
78
79 Snp->Cdb.OpCode = PXE_OPCODE_INITIALIZE;
80 Snp->Cdb.OpFlags = CableDetectFlag;
81
82 Snp->Cdb.CPBsize = (UINT16)sizeof (PXE_CPB_INITIALIZE);
83 Snp->Cdb.DBsize = (UINT16)sizeof (PXE_DB_INITIALIZE);
84
85 Snp->Cdb.CPBaddr = (UINT64)(UINTN)Snp->Cpb;
86 Snp->Cdb.DBaddr = (UINT64)(UINTN)Snp->Db;
87
88 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
89 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
90 Snp->Cdb.IFnum = Snp->IfNum;
91 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
92
93 DEBUG ((DEBUG_NET, "\nSnp->undi.initialize() "));
94
95 (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);
96
97 //
98 // There are two fields need to be checked here:
99 // First is the upper two bits (14 & 15) in the CDB.StatFlags field. Until these bits change to report
100 // PXE_STATFLAGS_COMMAND_COMPLETE or PXE_STATFLAGS_COMMAND_FAILED, the command has not been executed by the UNDI.
101 // Second is the CDB.StatCode field. After command execution completes, either successfully or not,
102 // the CDB.StatCode field contains the result of the command execution.
103 //
104 if ((((Snp->Cdb.StatFlags) & PXE_STATFLAGS_STATUS_MASK) == PXE_STATFLAGS_COMMAND_COMPLETE) &&
105 (Snp->Cdb.StatCode == PXE_STATCODE_SUCCESS))
106 {
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 (DEBUG_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 Resets a network adapter and allocates the transmit and receive buffers
148 required by the network interface; optionally, also requests allocation of
149 additional transmit and receive buffers.
150
151 This function allocates the transmit and receive buffers required by the network
152 interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned.
153 If the allocation succeeds and the network interface is successfully initialized,
154 then EFI_SUCCESS will be returned.
155
156 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
157
158 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
159 that the driver should allocate for the network interface.
160 Some network interfaces will not be able to use the
161 extra buffer, and the caller will not know if it is
162 actually being used.
163 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
164 that the driver should allocate for the network interface.
165 Some network interfaces will not be able to use the
166 extra buffer, and the caller will not know if it is
167 actually being used.
168
169 @retval EFI_SUCCESS The network interface was initialized.
170 @retval EFI_NOT_STARTED The network interface has not been started.
171 @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
172 receive buffers.
173 @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
174 EFI_SIMPLE_NETWORK_PROTOCOL structure.
175 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
176 @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
177
178 **/
179 EFI_STATUS
180 EFIAPI
181 SnpUndi32Initialize (
182 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
183 IN UINTN ExtraRxBufferSize OPTIONAL,
184 IN UINTN ExtraTxBufferSize OPTIONAL
185 )
186 {
187 EFI_STATUS EfiStatus;
188 SNP_DRIVER *Snp;
189 EFI_TPL OldTpl;
190
191 if (This == NULL) {
192 return EFI_INVALID_PARAMETER;
193 }
194
195 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
196
197 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
198
199 if (Snp == NULL) {
200 EfiStatus = EFI_INVALID_PARAMETER;
201 goto ON_EXIT;
202 }
203
204 switch (Snp->Mode.State) {
205 case EfiSimpleNetworkStarted:
206 break;
207
208 case EfiSimpleNetworkStopped:
209 EfiStatus = EFI_NOT_STARTED;
210 goto ON_EXIT;
211
212 default:
213 EfiStatus = EFI_DEVICE_ERROR;
214 goto ON_EXIT;
215 }
216
217 EfiStatus = gBS->CreateEvent (
218 EVT_NOTIFY_WAIT,
219 TPL_NOTIFY,
220 &SnpWaitForPacketNotify,
221 Snp,
222 &Snp->Snp.WaitForPacket
223 );
224
225 if (EFI_ERROR (EfiStatus)) {
226 Snp->Snp.WaitForPacket = NULL;
227 EfiStatus = EFI_DEVICE_ERROR;
228 goto ON_EXIT;
229 }
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 }