]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/SnpDxe/Snp.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / SnpDxe / Snp.c
CommitLineData
a15a4195 1/** @file\r
894d038a 2 Implementation of driver entry point and driver binding protocol.\r
e2851998 3\r
61bb6eeb 4Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
ca08f3d4 5Copyright (c) Microsoft Corporation.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
a15a4195 7\r
a15a4195 8**/\r
9\r
10#include "Snp.h"\r
11\r
0428a6cb 12/**\r
13 One notified function to stop UNDI device when gBS->ExitBootServices() called.\r
14\r
15 @param Event Pointer to this event\r
e3644786 16 @param Context Event handler private data\r
0428a6cb 17\r
18**/\r
19VOID\r
20EFIAPI\r
21SnpNotifyExitBootServices (\r
d1050b9d
MK
22 EFI_EVENT Event,\r
23 VOID *Context\r
0428a6cb 24 )\r
25{\r
d1050b9d 26 SNP_DRIVER *Snp;\r
0428a6cb 27\r
d1050b9d 28 Snp = (SNP_DRIVER *)Context;\r
0428a6cb 29\r
30 //\r
31 // Shutdown and stop UNDI driver\r
32 //\r
33 PxeShutdown (Snp);\r
34 PxeStop (Snp);\r
35}\r
a15a4195 36\r
37/**\r
f3816027 38 Send command to UNDI. It does nothing currently.\r
e2851998 39\r
4cda7726 40 @param Cdb command to be sent to UNDI.\r
e2851998 41\r
42 @retval EFI_INVALID_PARAMETER The command is 0.\r
43 @retval EFI_UNSUPPORTED Default return status because it's not\r
f3816027 44 supported currently.\r
e2851998 45\r
a15a4195 46**/\r
47EFI_STATUS\r
9c9f5859 48EFIAPI\r
4cda7726 49IssueHwUndiCommand (\r
d1050b9d 50 UINT64 Cdb\r
a15a4195 51 )\r
52{\r
c49ca4a2 53 DEBUG ((DEBUG_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));\r
a15a4195 54\r
4cda7726 55 if (Cdb == 0) {\r
a15a4195 56 return EFI_INVALID_PARAMETER;\r
a15a4195 57 }\r
d1050b9d 58\r
a15a4195 59 //\r
60 // %%TBD - For now, nothing is done.\r
61 //\r
62 return EFI_UNSUPPORTED;\r
63}\r
64\r
a15a4195 65/**\r
66 Compute 8-bit checksum of a buffer.\r
67\r
4cda7726 68 @param Buffer Pointer to buffer.\r
69 @param Length Length of buffer in bytes.\r
a15a4195 70\r
e2851998 71 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len\r
f3816027 72 is zero.\r
a15a4195 73\r
74**/\r
a15a4195 75UINT8\r
4cda7726 76Calc8BitCksum (\r
d1050b9d
MK
77 VOID *Buffer,\r
78 UINTN Length\r
a15a4195 79 )\r
80{\r
d1050b9d
MK
81 UINT8 *Ptr;\r
82 UINT8 Cksum;\r
a15a4195 83\r
4cda7726 84 Ptr = Buffer;\r
85 Cksum = 0;\r
a15a4195 86\r
d1050b9d 87 if ((Ptr == NULL) || (Length == 0)) {\r
a15a4195 88 return 0;\r
89 }\r
90\r
4cda7726 91 while (Length-- != 0) {\r
d1050b9d 92 Cksum = (UINT8)(Cksum + *Ptr++);\r
a15a4195 93 }\r
94\r
4cda7726 95 return Cksum;\r
a15a4195 96}\r
97\r
a15a4195 98/**\r
4cda7726 99 Test to see if this driver supports ControllerHandle. This service\r
100 is called by the EFI boot service ConnectController(). In\r
101 order to make drivers as small as possible, there are a few calling\r
102 restrictions for this service. ConnectController() must\r
103 follow these calling restrictions. If any other agent wishes to call\r
104 Supported() it must also follow these calling restrictions.\r
105\r
106 @param This Protocol instance pointer.\r
f3816027 107 @param ControllerHandle Handle of device to test.\r
4cda7726 108 @param RemainingDevicePath Optional parameter use to pick a specific child\r
109 device to start.\r
110\r
f3816027 111 @retval EFI_SUCCESS This driver supports this device.\r
112 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
113 @retval other This driver does not support this device.\r
a15a4195 114\r
115**/\r
116EFI_STATUS\r
117EFIAPI\r
118SimpleNetworkDriverSupported (\r
d1050b9d
MK
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
120 IN EFI_HANDLE Controller,\r
121 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
a15a4195 122 )\r
123{\r
d1050b9d
MK
124 EFI_STATUS Status;\r
125 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;\r
126 PXE_UNDI *Pxe;\r
a15a4195 127\r
128 Status = gBS->OpenProtocol (\r
129 Controller,\r
130 &gEfiDevicePathProtocolGuid,\r
131 NULL,\r
132 This->DriverBindingHandle,\r
133 Controller,\r
134 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
135 );\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139\r
140 Status = gBS->OpenProtocol (\r
141 Controller,\r
142 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
d1050b9d 143 (VOID **)&NiiProtocol,\r
a15a4195 144 This->DriverBindingHandle,\r
145 Controller,\r
146 EFI_OPEN_PROTOCOL_BY_DRIVER\r
147 );\r
148\r
149 if (EFI_ERROR (Status)) {\r
150 if (Status == EFI_ALREADY_STARTED) {\r
c49ca4a2 151 DEBUG ((DEBUG_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
a15a4195 152 }\r
d1050b9d 153\r
a15a4195 154 return Status;\r
155 }\r
156\r
c49ca4a2 157 DEBUG ((DEBUG_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
a15a4195 158\r
159 //\r
160 // check the version, we don't want to connect to the undi16\r
161 //\r
162 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {\r
163 Status = EFI_UNSUPPORTED;\r
164 goto Done;\r
165 }\r
d1050b9d 166\r
a15a4195 167 //\r
168 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.\r
169 //\r
e2851998 170 if ((NiiProtocol->Id & 0x0F) != 0) {\r
c49ca4a2 171 DEBUG ((DEBUG_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
a15a4195 172 Status = EFI_UNSUPPORTED;\r
173 goto Done;\r
174 }\r
175\r
d1050b9d 176 Pxe = (PXE_UNDI *)(UINTN)(NiiProtocol->Id);\r
a15a4195 177\r
178 //\r
179 // Verify !PXE revisions.\r
180 //\r
4cda7726 181 if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
c49ca4a2 182 DEBUG ((DEBUG_NET, "\n!PXE signature is not valid.\n"));\r
a15a4195 183 Status = EFI_UNSUPPORTED;\r
184 goto Done;\r
185 }\r
186\r
4cda7726 187 if (Pxe->hw.Rev < PXE_ROMID_REV) {\r
c49ca4a2 188 DEBUG ((DEBUG_NET, "\n!PXE.Rev is not supported.\n"));\r
a15a4195 189 Status = EFI_UNSUPPORTED;\r
190 goto Done;\r
191 }\r
192\r
4cda7726 193 if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
c49ca4a2 194 DEBUG ((DEBUG_NET, "\n!PXE.MajorVer is not supported.\n"));\r
a15a4195 195 Status = EFI_UNSUPPORTED;\r
196 goto Done;\r
d1050b9d 197 } else if ((Pxe->hw.MajorVer == PXE_ROMID_MAJORVER) && (Pxe->hw.MinorVer < PXE_ROMID_MINORVER)) {\r
c49ca4a2 198 DEBUG ((DEBUG_NET, "\n!PXE.MinorVer is not supported."));\r
a15a4195 199 Status = EFI_UNSUPPORTED;\r
200 goto Done;\r
201 }\r
d1050b9d 202\r
a15a4195 203 //\r
204 // Do S/W UNDI specific checks.\r
205 //\r
4cda7726 206 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
207 if (Pxe->sw.EntryPoint < Pxe->sw.Len) {\r
c49ca4a2 208 DEBUG ((DEBUG_NET, "\n!PXE S/W entry point is not valid."));\r
a15a4195 209 Status = EFI_UNSUPPORTED;\r
210 goto Done;\r
211 }\r
212\r
4cda7726 213 if (Pxe->sw.BusCnt == 0) {\r
c49ca4a2 214 DEBUG ((DEBUG_NET, "\n!PXE.BusCnt is zero."));\r
a15a4195 215 Status = EFI_UNSUPPORTED;\r
216 goto Done;\r
217 }\r
218 }\r
219\r
220 Status = EFI_SUCCESS;\r
c49ca4a2 221 DEBUG ((DEBUG_INFO, "Support(): supported on %p\n", Controller));\r
a15a4195 222\r
223Done:\r
224 gBS->CloseProtocol (\r
d1050b9d
MK
225 Controller,\r
226 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
227 This->DriverBindingHandle,\r
228 Controller\r
229 );\r
a15a4195 230\r
231 return Status;\r
232}\r
233\r
a15a4195 234/**\r
4cda7726 235 Start this driver on ControllerHandle. This service is called by the\r
236 EFI boot service ConnectController(). In order to make\r
237 drivers as small as possible, there are a few calling restrictions for\r
238 this service. ConnectController() must follow these\r
239 calling restrictions. If any other agent wishes to call Start() it\r
240 must also follow these calling restrictions.\r
a15a4195 241\r
242 @param This Protocol instance pointer.\r
4cda7726 243 @param ControllerHandle Handle of device to bind driver to.\r
244 @param RemainingDevicePath Optional parameter use to pick a specific child\r
245 device to start.\r
a15a4195 246\r
4cda7726 247 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
469462b1 248 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error\r
4cda7726 249 @retval other This driver does not support this device\r
a15a4195 250\r
251**/\r
252EFI_STATUS\r
253EFIAPI\r
254SimpleNetworkDriverStart (\r
d1050b9d
MK
255 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
256 IN EFI_HANDLE Controller,\r
257 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
a15a4195 258 )\r
259{\r
d1050b9d
MK
260 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
261 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;\r
262 EFI_STATUS Status;\r
263 PXE_UNDI *Pxe;\r
264 SNP_DRIVER *Snp;\r
265 VOID *Address;\r
266 EFI_HANDLE Handle;\r
267 UINT8 BarIndex;\r
268 PXE_STATFLAGS InitStatFlags;\r
269 EFI_PCI_IO_PROTOCOL *PciIo;\r
270 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
271 BOOLEAN FoundIoBar;\r
272 BOOLEAN FoundMemoryBar;\r
d1102dba 273\r
c49ca4a2 274 DEBUG ((DEBUG_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
a15a4195 275\r
276 Status = gBS->OpenProtocol (\r
277 Controller,\r
278 &gEfiDevicePathProtocolGuid,\r
d1050b9d 279 (VOID **)&NiiDevicePath,\r
a15a4195 280 This->DriverBindingHandle,\r
281 Controller,\r
282 EFI_OPEN_PROTOCOL_BY_DRIVER\r
283 );\r
284\r
285 if (EFI_ERROR (Status)) {\r
286 return Status;\r
287 }\r
288\r
289 Status = gBS->LocateDevicePath (\r
290 &gEfiPciIoProtocolGuid,\r
291 &NiiDevicePath,\r
292 &Handle\r
293 );\r
294\r
295 if (EFI_ERROR (Status)) {\r
296 return Status;\r
297 }\r
298\r
299 Status = gBS->OpenProtocol (\r
300 Handle,\r
301 &gEfiPciIoProtocolGuid,\r
d1050b9d 302 (VOID **)&PciIo,\r
a15a4195 303 This->DriverBindingHandle,\r
304 Controller,\r
305 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 return Status;\r
309 }\r
d1050b9d 310\r
a15a4195 311 //\r
312 // Get the NII interface.\r
313 //\r
314 Status = gBS->OpenProtocol (\r
315 Controller,\r
316 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
d1050b9d 317 (VOID **)&Nii,\r
a15a4195 318 This->DriverBindingHandle,\r
319 Controller,\r
320 EFI_OPEN_PROTOCOL_BY_DRIVER\r
321 );\r
322 if (EFI_ERROR (Status)) {\r
323 gBS->CloseProtocol (\r
d1050b9d
MK
324 Controller,\r
325 &gEfiDevicePathProtocolGuid,\r
326 This->DriverBindingHandle,\r
327 Controller\r
328 );\r
a15a4195 329 return Status;\r
330 }\r
331\r
c49ca4a2 332 DEBUG ((DEBUG_INFO, "Start(): UNDI3.1 found\n"));\r
a15a4195 333\r
d1050b9d 334 Pxe = (PXE_UNDI *)(UINTN)(Nii->Id);\r
a15a4195 335\r
4cda7726 336 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
c49ca4a2 337 DEBUG ((DEBUG_NET, "\n!PXE checksum is not correct.\n"));\r
a15a4195 338 goto NiiError;\r
339 }\r
340\r
4cda7726 341 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
a15a4195 342 //\r
343 // We can get any packets.\r
344 //\r
4cda7726 345 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
a15a4195 346 //\r
347 // We need to be able to get broadcast packets for DHCP.\r
348 // If we do not have promiscuous support, we must at least have\r
349 // broadcast support or we cannot do DHCP!\r
350 //\r
351 } else {\r
c49ca4a2 352 DEBUG ((DEBUG_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
a15a4195 353 goto NiiError;\r
354 }\r
d1050b9d 355\r
a15a4195 356 //\r
357 // OK, we like this UNDI, and we know snp is not already there on this handle\r
358 // Allocate and initialize a new simple network protocol structure.\r
359 //\r
c4a7d208
FS
360 Status = PciIo->AllocateBuffer (\r
361 PciIo,\r
362 AllocateAnyPages,\r
363 EfiBootServicesData,\r
364 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
365 &Address,\r
366 0\r
367 );\r
a15a4195 368\r
369 if (Status != EFI_SUCCESS) {\r
c49ca4a2 370 DEBUG ((DEBUG_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
a15a4195 371 goto NiiError;\r
372 }\r
373\r
d1050b9d 374 Snp = (SNP_DRIVER *)(UINTN)Address;\r
a15a4195 375\r
4cda7726 376 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
a15a4195 377\r
d1050b9d
MK
378 Snp->PciIo = PciIo;\r
379 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
a15a4195 380\r
4cda7726 381 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
a15a4195 382\r
4cda7726 383 Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
384 Snp->Snp.Start = SnpUndi32Start;\r
385 Snp->Snp.Stop = SnpUndi32Stop;\r
386 Snp->Snp.Initialize = SnpUndi32Initialize;\r
387 Snp->Snp.Reset = SnpUndi32Reset;\r
388 Snp->Snp.Shutdown = SnpUndi32Shutdown;\r
389 Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;\r
390 Snp->Snp.StationAddress = SnpUndi32StationAddress;\r
391 Snp->Snp.Statistics = SnpUndi32Statistics;\r
392 Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;\r
393 Snp->Snp.NvData = SnpUndi32NvData;\r
394 Snp->Snp.GetStatus = SnpUndi32GetStatus;\r
395 Snp->Snp.Transmit = SnpUndi32Transmit;\r
396 Snp->Snp.Receive = SnpUndi32Receive;\r
397 Snp->Snp.WaitForPacket = NULL;\r
a15a4195 398\r
d1050b9d 399 Snp->Snp.Mode = &Snp->Mode;\r
a15a4195 400\r
d1050b9d
MK
401 Snp->TxRxBufferSize = 0;\r
402 Snp->TxRxBuffer = NULL;\r
7b4b93a2
FS
403\r
404 Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);\r
405 if (Snp->RecycledTxBuf == NULL) {\r
406 Status = EFI_OUT_OF_RESOURCES;\r
407 goto Error_DeleteSNP;\r
408 }\r
d1050b9d
MK
409\r
410 Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT;\r
411 Snp->RecycledTxBufCount = 0;\r
d1102dba 412\r
61f2ab90 413 if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
f70f52f5 414 Snp->IfNum = Nii->IfNum;\r
61f2ab90 415 } else {\r
d1050b9d 416 Snp->IfNum = (UINT8)(Nii->IfNum & 0xFF);\r
61f2ab90 417 }\r
a15a4195 418\r
4cda7726 419 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
d1050b9d
MK
420 Snp->IsSwUndi = FALSE;\r
421 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
a15a4195 422 } else {\r
4cda7726 423 Snp->IsSwUndi = TRUE;\r
a15a4195 424\r
4cda7726 425 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
d1050b9d 426 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND)(UINTN)Pxe->sw.EntryPoint;\r
a15a4195 427 } else {\r
d1050b9d 428 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND)(UINTN)((UINT8)(UINTN)Pxe + Pxe->sw.EntryPoint);\r
a15a4195 429 }\r
430 }\r
d1050b9d 431\r
a15a4195 432 //\r
433 // Allocate a global CPB and DB buffer for this UNDI interface.\r
434 // we do this because:\r
435 //\r
436 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
437 // within 2GB limit, create them here and map them so that when undi calls\r
438 // v2p callback to check if the physical address is < 2gb, we will pass.\r
439 //\r
440 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
441 // simpler if we use the same cpb, db variables for both old and new undi\r
442 // interfaces from all the SNP interface calls (we don't map the buffers\r
443 // for the newer undi interfaces though)\r
444 // .\r
445 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
446 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
447 //\r
c4a7d208
FS
448 Status = PciIo->AllocateBuffer (\r
449 PciIo,\r
450 AllocateAnyPages,\r
451 EfiBootServicesData,\r
452 SNP_MEM_PAGES (4096),\r
453 &Address,\r
454 0\r
455 );\r
a15a4195 456\r
457 if (Status != EFI_SUCCESS) {\r
c49ca4a2 458 DEBUG ((DEBUG_NET, "\nCould not allocate CPB and DB structures.\n"));\r
a15a4195 459 goto Error_DeleteSNP;\r
460 }\r
461\r
d1050b9d
MK
462 Snp->Cpb = (VOID *)(UINTN)Address;\r
463 Snp->Db = (VOID *)((UINTN)Address + 2048);\r
a15a4195 464\r
465 //\r
3f103c08 466 // Find the correct BAR to do IO.\r
c4a7d208 467 //\r
3f103c08
FS
468 // Enumerate through the PCI BARs for the device to determine which one is\r
469 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
470 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
471 //\r
df4f154d
MK
472 Snp->MemoryBarIndex = PCI_MAX_BAR;\r
473 Snp->IoBarIndex = PCI_MAX_BAR;\r
f70f52f5
FS
474 FoundMemoryBar = FALSE;\r
475 FoundIoBar = FALSE;\r
c4a7d208
FS
476 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
477 Status = PciIo->GetBarAttributes (\r
478 PciIo,\r
479 BarIndex,\r
480 NULL,\r
d1050b9d 481 (VOID **)&BarDesc\r
c4a7d208
FS
482 );\r
483 if (Status == EFI_UNSUPPORTED) {\r
484 continue;\r
485 } else if (EFI_ERROR (Status)) {\r
486 goto Error_DeleteSNP;\r
487 }\r
488\r
f70f52f5 489 if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {\r
c4a7d208 490 Snp->MemoryBarIndex = BarIndex;\r
f70f52f5
FS
491 FoundMemoryBar = TRUE;\r
492 } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {\r
c4a7d208 493 Snp->IoBarIndex = BarIndex;\r
f70f52f5 494 FoundIoBar = TRUE;\r
c4a7d208
FS
495 }\r
496\r
497 FreePool (BarDesc);\r
f70f52f5
FS
498\r
499 if (FoundMemoryBar && FoundIoBar) {\r
500 break;\r
501 }\r
c4a7d208 502 }\r
a15a4195 503\r
4cda7726 504 Status = PxeStart (Snp);\r
a15a4195 505\r
506 if (Status != EFI_SUCCESS) {\r
507 goto Error_DeleteSNP;\r
508 }\r
509\r
d1050b9d
MK
510 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
511 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 512\r
d1050b9d
MK
513 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
514 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 515\r
d1050b9d
MK
516 Snp->Cdb.DBsize = (UINT16)sizeof (Snp->InitInfo);\r
517 Snp->Cdb.DBaddr = (UINT64)(UINTN)(&Snp->InitInfo);\r
a15a4195 518\r
d1050b9d
MK
519 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
520 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 521\r
d1050b9d
MK
522 Snp->Cdb.IFnum = Snp->IfNum;\r
523 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 524\r
c49ca4a2 525 DEBUG ((DEBUG_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 526\r
d1050b9d 527 (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);\r
a15a4195 528\r
529 //\r
530 // Save the INIT Stat Code...\r
531 //\r
4cda7726 532 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 533\r
4cda7726 534 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
c49ca4a2 535 DEBUG ((DEBUG_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 536 PxeStop (Snp);\r
a15a4195 537 goto Error_DeleteSNP;\r
538 }\r
539\r
a15a4195 540 //\r
541 // Initialize simple network protocol mode structure\r
542 //\r
4cda7726 543 Snp->Mode.State = EfiSimpleNetworkStopped;\r
544 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
545 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
546 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
547 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
548 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
549 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
550 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
551 Snp->Mode.MCastFilterCount = 0;\r
a15a4195 552\r
553 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
d1050b9d
MK
554 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
555 Snp->CableDetectSupported = TRUE;\r
556 break;\r
a15a4195 557\r
d1050b9d
MK
558 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
559 default:\r
560 Snp->CableDetectSupported = FALSE;\r
a15a4195 561 }\r
562\r
c777c357 563 switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
d1050b9d
MK
564 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:\r
565 Snp->MediaStatusSupported = TRUE;\r
566 break;\r
c777c357 567\r
d1050b9d
MK
568 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:\r
569 default:\r
570 Snp->MediaStatusSupported = FALSE;\r
c777c357 571 }\r
572\r
128946c9
FS
573 if (Snp->CableDetectSupported || Snp->MediaStatusSupported) {\r
574 Snp->Mode.MediaPresentSupported = TRUE;\r
575 }\r
576\r
4cda7726 577 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
578 Snp->Mode.MacAddressChangeable = TRUE;\r
a15a4195 579 } else {\r
4cda7726 580 Snp->Mode.MacAddressChangeable = FALSE;\r
a15a4195 581 }\r
582\r
4cda7726 583 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
584 Snp->Mode.MultipleTxSupported = TRUE;\r
a15a4195 585 } else {\r
4cda7726 586 Snp->Mode.MultipleTxSupported = FALSE;\r
a15a4195 587 }\r
588\r
4cda7726 589 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
a15a4195 590\r
4cda7726 591 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
592 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 593 }\r
594\r
4cda7726 595 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
596 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
a15a4195 597 }\r
598\r
4cda7726 599 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
600 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
a15a4195 601 }\r
602\r
4cda7726 603 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
604 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
a15a4195 605 }\r
606\r
e2851998 607 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
4cda7726 608 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 609 }\r
610\r
4cda7726 611 Snp->Mode.ReceiveFilterSetting = 0;\r
a15a4195 612\r
613 //\r
614 // need to get the station address to save in the mode structure. we need to\r
615 // initialize the UNDI first for this.\r
616 //\r
4cda7726 617 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
618 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
a15a4195 619\r
4cda7726 620 if (EFI_ERROR (Status)) {\r
621 PxeStop (Snp);\r
a15a4195 622 goto Error_DeleteSNP;\r
623 }\r
624\r
4cda7726 625 Status = PxeGetStnAddr (Snp);\r
a15a4195 626\r
627 if (Status != EFI_SUCCESS) {\r
c49ca4a2 628 DEBUG ((DEBUG_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
4cda7726 629 PxeShutdown (Snp);\r
630 PxeStop (Snp);\r
a15a4195 631 goto Error_DeleteSNP;\r
632 }\r
633\r
4cda7726 634 Snp->Mode.MediaPresent = FALSE;\r
a15a4195 635\r
636 //\r
637 // We should not leave UNDI started and initialized here. this DriverStart()\r
638 // routine must only find and attach the SNP interface to UNDI layer that it\r
639 // finds on the given handle!\r
4cda7726 640 // The UNDI layer will be started when upper layers call Snp->start.\r
a15a4195 641 // How ever, this DriverStart() must fill up the snp mode structure which\r
642 // contains the MAC address of the NIC. For this reason we started and\r
643 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
644 // UNDI interface!\r
645 //\r
4cda7726 646 PxeShutdown (Snp);\r
647 PxeStop (Snp);\r
a15a4195 648\r
6f3ac73c 649 if (PcdGetBool (PcdSnpCreateExitBootServicesEvent)) {\r
61bb6eeb
MR
650 //\r
651 // Create EXIT_BOOT_SERIVES Event\r
652 //\r
653 Status = gBS->CreateEventEx (\r
654 EVT_NOTIFY_SIGNAL,\r
ca08f3d4 655 TPL_CALLBACK,\r
61bb6eeb
MR
656 SnpNotifyExitBootServices,\r
657 Snp,\r
658 &gEfiEventExitBootServicesGuid,\r
659 &Snp->ExitBootServicesEvent\r
660 );\r
661 if (EFI_ERROR (Status)) {\r
662 goto Error_DeleteSNP;\r
663 }\r
0428a6cb 664 }\r
665\r
a15a4195 666 //\r
667 // add SNP to the undi handle\r
668 //\r
669 Status = gBS->InstallProtocolInterface (\r
670 &Controller,\r
671 &gEfiSimpleNetworkProtocolGuid,\r
672 EFI_NATIVE_INTERFACE,\r
4cda7726 673 &(Snp->Snp)\r
a15a4195 674 );\r
675\r
676 if (!EFI_ERROR (Status)) {\r
677 return Status;\r
678 }\r
679\r
c4a7d208
FS
680 PciIo->FreeBuffer (\r
681 PciIo,\r
682 SNP_MEM_PAGES (4096),\r
683 Snp->Cpb\r
684 );\r
a15a4195 685\r
686Error_DeleteSNP:\r
687\r
7b4b93a2
FS
688 if (Snp->RecycledTxBuf != NULL) {\r
689 FreePool (Snp->RecycledTxBuf);\r
690 }\r
691\r
c4a7d208
FS
692 PciIo->FreeBuffer (\r
693 PciIo,\r
694 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
695 Snp\r
696 );\r
a15a4195 697NiiError:\r
698 gBS->CloseProtocol (\r
d1050b9d
MK
699 Controller,\r
700 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
701 This->DriverBindingHandle,\r
702 Controller\r
703 );\r
a15a4195 704\r
705 gBS->CloseProtocol (\r
d1050b9d
MK
706 Controller,\r
707 &gEfiDevicePathProtocolGuid,\r
708 This->DriverBindingHandle,\r
709 Controller\r
710 );\r
a15a4195 711\r
469462b1 712 //\r
713 // If we got here that means we are in error state.\r
714 //\r
715 if (!EFI_ERROR (Status)) {\r
716 Status = EFI_DEVICE_ERROR;\r
717 }\r
718\r
a15a4195 719 return Status;\r
720}\r
721\r
a15a4195 722/**\r
4cda7726 723 Stop this driver on ControllerHandle. This service is called by the\r
724 EFI boot service DisconnectController(). In order to\r
725 make drivers as small as possible, there are a few calling\r
726 restrictions for this service. DisconnectController()\r
727 must follow these calling restrictions. If any other agent wishes\r
728 to call Stop() it must also follow these calling restrictions.\r
e2851998 729\r
4cda7726 730 @param This Protocol instance pointer.\r
731 @param ControllerHandle Handle of device to stop driver on\r
732 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
733 children is zero stop the entire bus driver.\r
734 @param ChildHandleBuffer List of Child Handles to Stop.\r
735\r
736 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
737 @retval other This driver was not removed from this device\r
a15a4195 738\r
739**/\r
740EFI_STATUS\r
741EFIAPI\r
742SimpleNetworkDriverStop (\r
d1050b9d
MK
743 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
744 IN EFI_HANDLE Controller,\r
745 IN UINTN NumberOfChildren,\r
746 IN EFI_HANDLE *ChildHandleBuffer\r
a15a4195 747 )\r
748{\r
d1050b9d
MK
749 EFI_STATUS Status;\r
750 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
751 SNP_DRIVER *Snp;\r
752 EFI_PCI_IO_PROTOCOL *PciIo;\r
a15a4195 753\r
754 //\r
755 // Get our context back.\r
756 //\r
757 Status = gBS->OpenProtocol (\r
758 Controller,\r
759 &gEfiSimpleNetworkProtocolGuid,\r
d1050b9d 760 (VOID **)&SnpProtocol,\r
a15a4195 761 This->DriverBindingHandle,\r
762 Controller,\r
763 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
764 );\r
765\r
766 if (EFI_ERROR (Status)) {\r
767 return EFI_UNSUPPORTED;\r
768 }\r
769\r
770 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
771\r
772 Status = gBS->UninstallProtocolInterface (\r
773 Controller,\r
774 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 775 &Snp->Snp\r
a15a4195 776 );\r
777\r
778 if (EFI_ERROR (Status)) {\r
779 return Status;\r
780 }\r
781\r
6f3ac73c 782 if (PcdGetBool (PcdSnpCreateExitBootServicesEvent)) {\r
61bb6eeb 783 //\r
bb3594e8 784 // Close EXIT_BOOT_SERVICES Event\r
61bb6eeb
MR
785 //\r
786 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
787 }\r
0428a6cb 788\r
a15a4195 789 Status = gBS->CloseProtocol (\r
790 Controller,\r
791 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
792 This->DriverBindingHandle,\r
793 Controller\r
794 );\r
795\r
796 Status = gBS->CloseProtocol (\r
797 Controller,\r
798 &gEfiDevicePathProtocolGuid,\r
799 This->DriverBindingHandle,\r
800 Controller\r
801 );\r
802\r
4cda7726 803 PxeShutdown (Snp);\r
804 PxeStop (Snp);\r
a15a4195 805\r
7b4b93a2
FS
806 FreePool (Snp->RecycledTxBuf);\r
807\r
c4a7d208
FS
808 PciIo = Snp->PciIo;\r
809 PciIo->FreeBuffer (\r
810 PciIo,\r
811 SNP_MEM_PAGES (4096),\r
812 Snp->Cpb\r
813 );\r
a15a4195 814\r
c4a7d208
FS
815 PciIo->FreeBuffer (\r
816 PciIo,\r
817 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
818 Snp\r
819 );\r
a15a4195 820\r
821 return Status;\r
822}\r
823\r
4cda7726 824//\r
825// Simple Network Protocol Driver Global Variables\r
826//\r
d1050b9d 827EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
4cda7726 828 SimpleNetworkDriverSupported,\r
829 SimpleNetworkDriverStart,\r
830 SimpleNetworkDriverStop,\r
831 0xa,\r
832 NULL,\r
833 NULL\r
834};\r
835\r
a15a4195 836/**\r
4cda7726 837 The SNP driver entry point.\r
a15a4195 838\r
4cda7726 839 @param ImageHandle The driver image handle.\r
840 @param SystemTable The system table.\r
a15a4195 841\r
bb3594e8 842 @retval EFI_SUCCESS Initialization routine has found UNDI hardware,\r
4cda7726 843 loaded it's ROM, and installed a notify event for\r
bb3594e8 844 the Network Identifier Interface Protocol\r
4cda7726 845 successfully.\r
846 @retval Other Return value from HandleProtocol for\r
847 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 848\r
849**/\r
850EFI_STATUS\r
851EFIAPI\r
852InitializeSnpNiiDriver (\r
d1050b9d
MK
853 IN EFI_HANDLE ImageHandle,\r
854 IN EFI_SYSTEM_TABLE *SystemTable\r
a15a4195 855 )\r
856{\r
857 return EfiLibInstallDriverBindingComponentName2 (\r
858 ImageHandle,\r
859 SystemTable,\r
216f7970 860 &gSimpleNetworkDriverBinding,\r
f3de0a60 861 ImageHandle,\r
a15a4195 862 &gSimpleNetworkComponentName,\r
863 &gSimpleNetworkComponentName2\r
864 );\r
865}\r