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