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