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