]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
1. Use the PciIo->GetBarAttributes to find the logical bar index of the memory mapped...
[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
523f48e7 4Copyright (c) 2004 - 2014, 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
276 \r
9cff2f8d 277 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
a15a4195 278\r
279 Status = gBS->OpenProtocol (\r
280 Controller,\r
281 &gEfiDevicePathProtocolGuid,\r
282 (VOID **) &NiiDevicePath,\r
283 This->DriverBindingHandle,\r
284 Controller,\r
285 EFI_OPEN_PROTOCOL_BY_DRIVER\r
286 );\r
287\r
288 if (EFI_ERROR (Status)) {\r
289 return Status;\r
290 }\r
291\r
292 Status = gBS->LocateDevicePath (\r
293 &gEfiPciIoProtocolGuid,\r
294 &NiiDevicePath,\r
295 &Handle\r
296 );\r
297\r
298 if (EFI_ERROR (Status)) {\r
299 return Status;\r
300 }\r
301\r
302 Status = gBS->OpenProtocol (\r
303 Handle,\r
304 &gEfiPciIoProtocolGuid,\r
c4a7d208 305 (VOID **) &PciIo,\r
a15a4195 306 This->DriverBindingHandle,\r
307 Controller,\r
308 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
309 );\r
310 if (EFI_ERROR (Status)) {\r
311 return Status;\r
312 }\r
313 //\r
314 // Get the NII interface.\r
315 //\r
316 Status = gBS->OpenProtocol (\r
317 Controller,\r
318 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
319 (VOID **) &Nii,\r
320 This->DriverBindingHandle,\r
321 Controller,\r
322 EFI_OPEN_PROTOCOL_BY_DRIVER\r
323 );\r
324 if (EFI_ERROR (Status)) {\r
325 gBS->CloseProtocol (\r
326 Controller,\r
327 &gEfiDevicePathProtocolGuid,\r
328 This->DriverBindingHandle,\r
329 Controller\r
330 );\r
331 return Status;\r
332 }\r
333\r
334 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));\r
335\r
bdc82513 336 Pxe = (PXE_UNDI *) (UINTN) (Nii->Id);\r
a15a4195 337\r
4cda7726 338 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
9cff2f8d 339 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
a15a4195 340 goto NiiError;\r
341 }\r
342\r
4cda7726 343 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
a15a4195 344 //\r
345 // We can get any packets.\r
346 //\r
4cda7726 347 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
a15a4195 348 //\r
349 // We need to be able to get broadcast packets for DHCP.\r
350 // If we do not have promiscuous support, we must at least have\r
351 // broadcast support or we cannot do DHCP!\r
352 //\r
353 } else {\r
9cff2f8d 354 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
a15a4195 355 goto NiiError;\r
356 }\r
357 //\r
358 // OK, we like this UNDI, and we know snp is not already there on this handle\r
359 // Allocate and initialize a new simple network protocol structure.\r
360 //\r
c4a7d208
FS
361 Status = PciIo->AllocateBuffer (\r
362 PciIo,\r
363 AllocateAnyPages,\r
364 EfiBootServicesData,\r
365 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
366 &Address,\r
367 0\r
368 );\r
a15a4195 369\r
370 if (Status != EFI_SUCCESS) {\r
9cff2f8d 371 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
a15a4195 372 goto NiiError;\r
373 }\r
374\r
4cda7726 375 Snp = (SNP_DRIVER *) (UINTN) Address;\r
a15a4195 376\r
4cda7726 377 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
a15a4195 378\r
c4a7d208 379 Snp->PciIo = PciIo;\r
4cda7726 380 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
a15a4195 381\r
4cda7726 382 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
a15a4195 383\r
4cda7726 384 Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
385 Snp->Snp.Start = SnpUndi32Start;\r
386 Snp->Snp.Stop = SnpUndi32Stop;\r
387 Snp->Snp.Initialize = SnpUndi32Initialize;\r
388 Snp->Snp.Reset = SnpUndi32Reset;\r
389 Snp->Snp.Shutdown = SnpUndi32Shutdown;\r
390 Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;\r
391 Snp->Snp.StationAddress = SnpUndi32StationAddress;\r
392 Snp->Snp.Statistics = SnpUndi32Statistics;\r
393 Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;\r
394 Snp->Snp.NvData = SnpUndi32NvData;\r
395 Snp->Snp.GetStatus = SnpUndi32GetStatus;\r
396 Snp->Snp.Transmit = SnpUndi32Transmit;\r
397 Snp->Snp.Receive = SnpUndi32Receive;\r
398 Snp->Snp.WaitForPacket = NULL;\r
a15a4195 399\r
4cda7726 400 Snp->Snp.Mode = &Snp->Mode;\r
a15a4195 401\r
4cda7726 402 Snp->TxRxBufferSize = 0;\r
403 Snp->TxRxBuffer = NULL;\r
61f2ab90
QO
404 \r
405 if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
406 Snp->IfNum = Nii->IfNum;\r
a15a4195 407\r
61f2ab90
QO
408 } else {\r
409 Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);\r
410 }\r
a15a4195 411\r
4cda7726 412 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
413 Snp->IsSwUndi = FALSE;\r
414 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
a15a4195 415 } else {\r
4cda7726 416 Snp->IsSwUndi = TRUE;\r
a15a4195 417\r
4cda7726 418 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
419 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;\r
a15a4195 420 } else {\r
4cda7726 421 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);\r
a15a4195 422 }\r
423 }\r
424 //\r
425 // Allocate a global CPB and DB buffer for this UNDI interface.\r
426 // we do this because:\r
427 //\r
428 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
429 // within 2GB limit, create them here and map them so that when undi calls\r
430 // v2p callback to check if the physical address is < 2gb, we will pass.\r
431 //\r
432 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
433 // simpler if we use the same cpb, db variables for both old and new undi\r
434 // interfaces from all the SNP interface calls (we don't map the buffers\r
435 // for the newer undi interfaces though)\r
436 // .\r
437 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
438 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
439 //\r
c4a7d208
FS
440 Status = PciIo->AllocateBuffer (\r
441 PciIo,\r
442 AllocateAnyPages,\r
443 EfiBootServicesData,\r
444 SNP_MEM_PAGES (4096),\r
445 &Address,\r
446 0\r
447 );\r
a15a4195 448\r
449 if (Status != EFI_SUCCESS) {\r
9cff2f8d 450 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
a15a4195 451 goto Error_DeleteSNP;\r
452 }\r
453\r
4cda7726 454 Snp->Cpb = (VOID *) (UINTN) Address;\r
455 Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
a15a4195 456\r
457 //\r
c4a7d208
FS
458 // Find the correct memory and io bar.\r
459 //\r
460 Snp->MemoryBarIndex = PCI_MAX_BAR;\r
461 Snp->IoBarIndex = PCI_MAX_BAR;\r
462 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
463 Status = PciIo->GetBarAttributes (\r
464 PciIo,\r
465 BarIndex,\r
466 NULL,\r
467 (VOID**) &BarDesc\r
468 );\r
469 if (Status == EFI_UNSUPPORTED) {\r
470 continue;\r
471 } else if (EFI_ERROR (Status)) {\r
472 goto Error_DeleteSNP;\r
473 }\r
474\r
475 if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
476 Snp->MemoryBarIndex = BarIndex;\r
477 } else if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
478 Snp->IoBarIndex = BarIndex;\r
479 }\r
480\r
481 FreePool (BarDesc);\r
482 }\r
483 if ((Snp->MemoryBarIndex == PCI_MAX_BAR) || (Snp->IoBarIndex == PCI_MAX_BAR)) {\r
484 goto Error_DeleteSNP;\r
485 }\r
a15a4195 486\r
4cda7726 487 Status = PxeStart (Snp);\r
a15a4195 488\r
489 if (Status != EFI_SUCCESS) {\r
490 goto Error_DeleteSNP;\r
491 }\r
492\r
4cda7726 493 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
494 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 495\r
4cda7726 496 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
497 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 498\r
c9325700
ED
499 Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo);\r
500 Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);\r
a15a4195 501\r
4cda7726 502 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
503 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 504\r
4cda7726 505 Snp->Cdb.IFnum = Snp->IfNum;\r
506 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 507\r
9cff2f8d 508 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 509\r
4cda7726 510 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 511\r
512 //\r
513 // Save the INIT Stat Code...\r
514 //\r
4cda7726 515 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 516\r
4cda7726 517 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 518 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 519 PxeStop (Snp);\r
a15a4195 520 goto Error_DeleteSNP;\r
521 }\r
522\r
a15a4195 523 //\r
524 // Initialize simple network protocol mode structure\r
525 //\r
4cda7726 526 Snp->Mode.State = EfiSimpleNetworkStopped;\r
527 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
528 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
529 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
530 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
531 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
532 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
533 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
534 Snp->Mode.MCastFilterCount = 0;\r
a15a4195 535\r
536 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
537 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
4cda7726 538 Snp->Mode.MediaPresentSupported = TRUE;\r
a15a4195 539 break;\r
540\r
541 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
542 default:\r
4cda7726 543 Snp->Mode.MediaPresentSupported = FALSE;\r
a15a4195 544 }\r
545\r
c777c357 546 switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
547 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:\r
548 Snp->MediaStatusSupported = TRUE;\r
549 break;\r
550\r
551 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:\r
552 default:\r
553 Snp->MediaStatusSupported = FALSE;\r
554 }\r
555\r
4cda7726 556 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
557 Snp->Mode.MacAddressChangeable = TRUE;\r
a15a4195 558 } else {\r
4cda7726 559 Snp->Mode.MacAddressChangeable = FALSE;\r
a15a4195 560 }\r
561\r
4cda7726 562 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
563 Snp->Mode.MultipleTxSupported = TRUE;\r
a15a4195 564 } else {\r
4cda7726 565 Snp->Mode.MultipleTxSupported = FALSE;\r
a15a4195 566 }\r
567\r
4cda7726 568 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
a15a4195 569\r
4cda7726 570 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
571 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 572\r
573 }\r
574\r
4cda7726 575 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
576 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
a15a4195 577\r
578 }\r
579\r
4cda7726 580 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
581 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
a15a4195 582\r
583 }\r
584\r
4cda7726 585 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
586 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
a15a4195 587\r
588 }\r
589\r
e2851998 590 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
4cda7726 591 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 592\r
593 }\r
594\r
4cda7726 595 Snp->Mode.ReceiveFilterSetting = 0;\r
a15a4195 596\r
597 //\r
598 // need to get the station address to save in the mode structure. we need to\r
599 // initialize the UNDI first for this.\r
600 //\r
4cda7726 601 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
602 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
a15a4195 603\r
4cda7726 604 if (EFI_ERROR (Status)) {\r
605 PxeStop (Snp);\r
a15a4195 606 goto Error_DeleteSNP;\r
607 }\r
608\r
4cda7726 609 Status = PxeGetStnAddr (Snp);\r
a15a4195 610\r
611 if (Status != EFI_SUCCESS) {\r
f3816027 612 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
4cda7726 613 PxeShutdown (Snp);\r
614 PxeStop (Snp);\r
a15a4195 615 goto Error_DeleteSNP;\r
616 }\r
617\r
4cda7726 618 Snp->Mode.MediaPresent = FALSE;\r
a15a4195 619\r
620 //\r
621 // We should not leave UNDI started and initialized here. this DriverStart()\r
622 // routine must only find and attach the SNP interface to UNDI layer that it\r
623 // finds on the given handle!\r
4cda7726 624 // The UNDI layer will be started when upper layers call Snp->start.\r
a15a4195 625 // How ever, this DriverStart() must fill up the snp mode structure which\r
626 // contains the MAC address of the NIC. For this reason we started and\r
627 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
628 // UNDI interface!\r
629 //\r
4cda7726 630 PxeShutdown (Snp);\r
631 PxeStop (Snp);\r
a15a4195 632\r
0428a6cb 633 //\r
634 // Create EXIT_BOOT_SERIVES Event\r
635 //\r
636 Status = gBS->CreateEventEx (\r
637 EVT_NOTIFY_SIGNAL,\r
638 TPL_NOTIFY,\r
639 SnpNotifyExitBootServices,\r
640 Snp,\r
641 &gEfiEventExitBootServicesGuid,\r
642 &Snp->ExitBootServicesEvent\r
643 );\r
644 if (EFI_ERROR (Status)) {\r
645 goto Error_DeleteSNP;\r
646 }\r
647\r
a15a4195 648 //\r
649 // add SNP to the undi handle\r
650 //\r
651 Status = gBS->InstallProtocolInterface (\r
652 &Controller,\r
653 &gEfiSimpleNetworkProtocolGuid,\r
654 EFI_NATIVE_INTERFACE,\r
4cda7726 655 &(Snp->Snp)\r
a15a4195 656 );\r
657\r
658 if (!EFI_ERROR (Status)) {\r
659 return Status;\r
660 }\r
661\r
c4a7d208
FS
662 PciIo->FreeBuffer (\r
663 PciIo,\r
664 SNP_MEM_PAGES (4096),\r
665 Snp->Cpb\r
666 );\r
a15a4195 667\r
668Error_DeleteSNP:\r
669\r
c4a7d208
FS
670 PciIo->FreeBuffer (\r
671 PciIo,\r
672 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
673 Snp\r
674 );\r
a15a4195 675NiiError:\r
676 gBS->CloseProtocol (\r
677 Controller,\r
678 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
679 This->DriverBindingHandle,\r
680 Controller\r
681 );\r
682\r
683 gBS->CloseProtocol (\r
684 Controller,\r
685 &gEfiDevicePathProtocolGuid,\r
686 This->DriverBindingHandle,\r
687 Controller\r
688 );\r
689\r
469462b1 690 //\r
691 // If we got here that means we are in error state.\r
692 //\r
693 if (!EFI_ERROR (Status)) {\r
694 Status = EFI_DEVICE_ERROR;\r
695 }\r
696\r
a15a4195 697 return Status;\r
698}\r
699\r
a15a4195 700/**\r
4cda7726 701 Stop this driver on ControllerHandle. This service is called by the\r
702 EFI boot service DisconnectController(). In order to\r
703 make drivers as small as possible, there are a few calling\r
704 restrictions for this service. DisconnectController()\r
705 must follow these calling restrictions. If any other agent wishes\r
706 to call Stop() it must also follow these calling restrictions.\r
e2851998 707\r
4cda7726 708 @param This Protocol instance pointer.\r
709 @param ControllerHandle Handle of device to stop driver on\r
710 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
711 children is zero stop the entire bus driver.\r
712 @param ChildHandleBuffer List of Child Handles to Stop.\r
713\r
714 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
715 @retval other This driver was not removed from this device\r
a15a4195 716\r
717**/\r
718EFI_STATUS\r
719EFIAPI\r
720SimpleNetworkDriverStop (\r
721 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
722 IN EFI_HANDLE Controller,\r
723 IN UINTN NumberOfChildren,\r
724 IN EFI_HANDLE *ChildHandleBuffer\r
725 )\r
726{\r
727 EFI_STATUS Status;\r
728 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
729 SNP_DRIVER *Snp;\r
c4a7d208 730 EFI_PCI_IO_PROTOCOL *PciIo;\r
a15a4195 731\r
732 //\r
733 // Get our context back.\r
734 //\r
735 Status = gBS->OpenProtocol (\r
736 Controller,\r
737 &gEfiSimpleNetworkProtocolGuid,\r
738 (VOID **) &SnpProtocol,\r
739 This->DriverBindingHandle,\r
740 Controller,\r
741 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
742 );\r
743\r
744 if (EFI_ERROR (Status)) {\r
745 return EFI_UNSUPPORTED;\r
746 }\r
747\r
748 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
749\r
750 Status = gBS->UninstallProtocolInterface (\r
751 Controller,\r
752 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 753 &Snp->Snp\r
a15a4195 754 );\r
755\r
756 if (EFI_ERROR (Status)) {\r
757 return Status;\r
758 }\r
759\r
0428a6cb 760 //\r
761 // Close EXIT_BOOT_SERIVES Event\r
762 //\r
763 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
764\r
a15a4195 765 Status = gBS->CloseProtocol (\r
766 Controller,\r
767 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
768 This->DriverBindingHandle,\r
769 Controller\r
770 );\r
771\r
772 Status = gBS->CloseProtocol (\r
773 Controller,\r
774 &gEfiDevicePathProtocolGuid,\r
775 This->DriverBindingHandle,\r
776 Controller\r
777 );\r
778\r
4cda7726 779 PxeShutdown (Snp);\r
780 PxeStop (Snp);\r
a15a4195 781\r
c4a7d208
FS
782 PciIo = Snp->PciIo;\r
783 PciIo->FreeBuffer (\r
784 PciIo,\r
785 SNP_MEM_PAGES (4096),\r
786 Snp->Cpb\r
787 );\r
a15a4195 788\r
c4a7d208
FS
789 PciIo->FreeBuffer (\r
790 PciIo,\r
791 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
792 Snp\r
793 );\r
a15a4195 794\r
795 return Status;\r
796}\r
797\r
4cda7726 798//\r
799// Simple Network Protocol Driver Global Variables\r
800//\r
216f7970 801EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
4cda7726 802 SimpleNetworkDriverSupported,\r
803 SimpleNetworkDriverStart,\r
804 SimpleNetworkDriverStop,\r
805 0xa,\r
806 NULL,\r
807 NULL\r
808};\r
809\r
a15a4195 810/**\r
4cda7726 811 The SNP driver entry point.\r
a15a4195 812\r
4cda7726 813 @param ImageHandle The driver image handle.\r
814 @param SystemTable The system table.\r
a15a4195 815\r
4cda7726 816 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
817 loaded it's ROM, and installed a notify event for\r
818 the Network Indentifier Interface Protocol\r
819 successfully.\r
820 @retval Other Return value from HandleProtocol for\r
821 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 822\r
823**/\r
824EFI_STATUS\r
825EFIAPI\r
826InitializeSnpNiiDriver (\r
827 IN EFI_HANDLE ImageHandle,\r
828 IN EFI_SYSTEM_TABLE *SystemTable\r
829 )\r
830{\r
831 return EfiLibInstallDriverBindingComponentName2 (\r
832 ImageHandle,\r
833 SystemTable,\r
216f7970 834 &gSimpleNetworkDriverBinding,\r
f3de0a60 835 ImageHandle,\r
a15a4195 836 &gSimpleNetworkComponentName,\r
837 &gSimpleNetworkComponentName2\r
838 );\r
839}\r