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