]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Snp.c
CommitLineData
a15a4195 1/** @file\r
894d038a 2 Implementation of driver entry point and driver binding protocol.\r
e2851998 3\r
d1102dba 4Copyright (c) 2004 - 2018, 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
0428a6cb 650 //\r
651 // Create EXIT_BOOT_SERIVES Event\r
652 //\r
653 Status = gBS->CreateEventEx (\r
654 EVT_NOTIFY_SIGNAL,\r
655 TPL_NOTIFY,\r
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
664\r
a15a4195 665 //\r
666 // add SNP to the undi handle\r
667 //\r
668 Status = gBS->InstallProtocolInterface (\r
669 &Controller,\r
670 &gEfiSimpleNetworkProtocolGuid,\r
671 EFI_NATIVE_INTERFACE,\r
4cda7726 672 &(Snp->Snp)\r
a15a4195 673 );\r
674\r
675 if (!EFI_ERROR (Status)) {\r
676 return Status;\r
677 }\r
678\r
c4a7d208
FS
679 PciIo->FreeBuffer (\r
680 PciIo,\r
681 SNP_MEM_PAGES (4096),\r
682 Snp->Cpb\r
683 );\r
a15a4195 684\r
685Error_DeleteSNP:\r
686\r
7b4b93a2
FS
687 if (Snp->RecycledTxBuf != NULL) {\r
688 FreePool (Snp->RecycledTxBuf);\r
689 }\r
690\r
c4a7d208
FS
691 PciIo->FreeBuffer (\r
692 PciIo,\r
693 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
694 Snp\r
695 );\r
a15a4195 696NiiError:\r
697 gBS->CloseProtocol (\r
698 Controller,\r
699 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
700 This->DriverBindingHandle,\r
701 Controller\r
702 );\r
703\r
704 gBS->CloseProtocol (\r
705 Controller,\r
706 &gEfiDevicePathProtocolGuid,\r
707 This->DriverBindingHandle,\r
708 Controller\r
709 );\r
710\r
469462b1 711 //\r
712 // If we got here that means we are in error state.\r
713 //\r
714 if (!EFI_ERROR (Status)) {\r
715 Status = EFI_DEVICE_ERROR;\r
716 }\r
717\r
a15a4195 718 return Status;\r
719}\r
720\r
a15a4195 721/**\r
4cda7726 722 Stop this driver on ControllerHandle. This service is called by the\r
723 EFI boot service DisconnectController(). In order to\r
724 make drivers as small as possible, there are a few calling\r
725 restrictions for this service. DisconnectController()\r
726 must follow these calling restrictions. If any other agent wishes\r
727 to call Stop() it must also follow these calling restrictions.\r
e2851998 728\r
4cda7726 729 @param This Protocol instance pointer.\r
730 @param ControllerHandle Handle of device to stop driver on\r
731 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
732 children is zero stop the entire bus driver.\r
733 @param ChildHandleBuffer List of Child Handles to Stop.\r
734\r
735 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
736 @retval other This driver was not removed from this device\r
a15a4195 737\r
738**/\r
739EFI_STATUS\r
740EFIAPI\r
741SimpleNetworkDriverStop (\r
742 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
743 IN EFI_HANDLE Controller,\r
744 IN UINTN NumberOfChildren,\r
745 IN EFI_HANDLE *ChildHandleBuffer\r
746 )\r
747{\r
748 EFI_STATUS Status;\r
749 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
750 SNP_DRIVER *Snp;\r
c4a7d208 751 EFI_PCI_IO_PROTOCOL *PciIo;\r
a15a4195 752\r
753 //\r
754 // Get our context back.\r
755 //\r
756 Status = gBS->OpenProtocol (\r
757 Controller,\r
758 &gEfiSimpleNetworkProtocolGuid,\r
759 (VOID **) &SnpProtocol,\r
760 This->DriverBindingHandle,\r
761 Controller,\r
762 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
763 );\r
764\r
765 if (EFI_ERROR (Status)) {\r
766 return EFI_UNSUPPORTED;\r
767 }\r
768\r
769 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
770\r
771 Status = gBS->UninstallProtocolInterface (\r
772 Controller,\r
773 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 774 &Snp->Snp\r
a15a4195 775 );\r
776\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
779 }\r
780\r
0428a6cb 781 //\r
782 // Close EXIT_BOOT_SERIVES Event\r
783 //\r
784 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
785\r
a15a4195 786 Status = gBS->CloseProtocol (\r
787 Controller,\r
788 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
789 This->DriverBindingHandle,\r
790 Controller\r
791 );\r
792\r
793 Status = gBS->CloseProtocol (\r
794 Controller,\r
795 &gEfiDevicePathProtocolGuid,\r
796 This->DriverBindingHandle,\r
797 Controller\r
798 );\r
799\r
4cda7726 800 PxeShutdown (Snp);\r
801 PxeStop (Snp);\r
a15a4195 802\r
7b4b93a2
FS
803 FreePool (Snp->RecycledTxBuf);\r
804\r
c4a7d208
FS
805 PciIo = Snp->PciIo;\r
806 PciIo->FreeBuffer (\r
807 PciIo,\r
808 SNP_MEM_PAGES (4096),\r
809 Snp->Cpb\r
810 );\r
a15a4195 811\r
c4a7d208
FS
812 PciIo->FreeBuffer (\r
813 PciIo,\r
814 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
815 Snp\r
816 );\r
a15a4195 817\r
818 return Status;\r
819}\r
820\r
4cda7726 821//\r
822// Simple Network Protocol Driver Global Variables\r
823//\r
216f7970 824EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
4cda7726 825 SimpleNetworkDriverSupported,\r
826 SimpleNetworkDriverStart,\r
827 SimpleNetworkDriverStop,\r
828 0xa,\r
829 NULL,\r
830 NULL\r
831};\r
832\r
a15a4195 833/**\r
4cda7726 834 The SNP driver entry point.\r
a15a4195 835\r
4cda7726 836 @param ImageHandle The driver image handle.\r
837 @param SystemTable The system table.\r
a15a4195 838\r
4cda7726 839 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
840 loaded it's ROM, and installed a notify event for\r
841 the Network Indentifier Interface Protocol\r
842 successfully.\r
843 @retval Other Return value from HandleProtocol for\r
844 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 845\r
846**/\r
847EFI_STATUS\r
848EFIAPI\r
849InitializeSnpNiiDriver (\r
850 IN EFI_HANDLE ImageHandle,\r
851 IN EFI_SYSTEM_TABLE *SystemTable\r
852 )\r
853{\r
854 return EfiLibInstallDriverBindingComponentName2 (\r
855 ImageHandle,\r
856 SystemTable,\r
216f7970 857 &gSimpleNetworkDriverBinding,\r
f3de0a60 858 ImageHandle,\r
a15a4195 859 &gSimpleNetworkComponentName,\r
860 &gSimpleNetworkComponentName2\r
861 );\r
862}\r