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