]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
ArmPkg/CpuDxe: Added support to not set a memory region with the same attribute
[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
469462b1 4Copyright (c) 2004 - 2013, 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
a15a4195 17//\r
18// Module global variables needed to support undi 3.0 interface\r
19//\r
4cda7726 20EFI_PCI_IO_PROTOCOL *mPciIo;\r
21V2P *mV2p = NULL; // undi3.0 map_list head\r
a15a4195 22// End Global variables\r
23//\r
24\r
0428a6cb 25/**\r
26 One notified function to stop UNDI device when gBS->ExitBootServices() called.\r
27\r
28 @param Event Pointer to this event\r
29 @param Context Event hanlder private data\r
30\r
31**/\r
32VOID\r
33EFIAPI\r
34SnpNotifyExitBootServices (\r
35 EFI_EVENT Event,\r
36 VOID *Context\r
37 )\r
38{\r
39 SNP_DRIVER *Snp;\r
40\r
41 Snp = (SNP_DRIVER *)Context;\r
42\r
43 //\r
44 // Shutdown and stop UNDI driver\r
45 //\r
46 PxeShutdown (Snp);\r
47 PxeStop (Snp);\r
48}\r
a15a4195 49\r
50/**\r
f3816027 51 Send command to UNDI. It does nothing currently.\r
e2851998 52\r
4cda7726 53 @param Cdb command to be sent to UNDI.\r
e2851998 54\r
55 @retval EFI_INVALID_PARAMETER The command is 0.\r
56 @retval EFI_UNSUPPORTED Default return status because it's not\r
f3816027 57 supported currently.\r
e2851998 58\r
a15a4195 59**/\r
60EFI_STATUS\r
9c9f5859 61EFIAPI\r
4cda7726 62IssueHwUndiCommand (\r
63 UINT64 Cdb\r
a15a4195 64 )\r
65{\r
4cda7726 66 DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));\r
a15a4195 67\r
4cda7726 68 if (Cdb == 0) {\r
a15a4195 69 return EFI_INVALID_PARAMETER;\r
70\r
71 }\r
72 //\r
73 // %%TBD - For now, nothing is done.\r
74 //\r
75 return EFI_UNSUPPORTED;\r
76}\r
77\r
78\r
79/**\r
80 Compute 8-bit checksum of a buffer.\r
81\r
4cda7726 82 @param Buffer Pointer to buffer.\r
83 @param Length Length of buffer in bytes.\r
a15a4195 84\r
e2851998 85 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len\r
f3816027 86 is zero.\r
a15a4195 87\r
88**/\r
a15a4195 89UINT8\r
4cda7726 90Calc8BitCksum (\r
91 VOID *Buffer,\r
92 UINTN Length\r
a15a4195 93 )\r
94{\r
4cda7726 95 UINT8 *Ptr;\r
96 UINT8 Cksum;\r
a15a4195 97\r
4cda7726 98 Ptr = Buffer;\r
99 Cksum = 0;\r
a15a4195 100\r
4cda7726 101 if (Ptr == NULL || Length == 0) {\r
a15a4195 102 return 0;\r
103 }\r
104\r
4cda7726 105 while (Length-- != 0) {\r
106 Cksum = (UINT8) (Cksum + *Ptr++);\r
a15a4195 107 }\r
108\r
4cda7726 109 return Cksum;\r
a15a4195 110}\r
111\r
a15a4195 112/**\r
4cda7726 113 Test to see if this driver supports ControllerHandle. This service\r
114 is called by the EFI boot service ConnectController(). In\r
115 order to make drivers as small as possible, there are a few calling\r
116 restrictions for this service. ConnectController() must\r
117 follow these calling restrictions. If any other agent wishes to call\r
118 Supported() it must also follow these calling restrictions.\r
119\r
120 @param This Protocol instance pointer.\r
f3816027 121 @param ControllerHandle Handle of device to test.\r
4cda7726 122 @param RemainingDevicePath Optional parameter use to pick a specific child\r
123 device to start.\r
124\r
f3816027 125 @retval EFI_SUCCESS This driver supports this device.\r
126 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
127 @retval other This driver does not support this device.\r
a15a4195 128\r
129**/\r
130EFI_STATUS\r
131EFIAPI\r
132SimpleNetworkDriverSupported (\r
133 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
134 IN EFI_HANDLE Controller,\r
135 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;\r
4cda7726 140 PXE_UNDI *Pxe;\r
a15a4195 141\r
142 Status = gBS->OpenProtocol (\r
143 Controller,\r
144 &gEfiDevicePathProtocolGuid,\r
145 NULL,\r
146 This->DriverBindingHandle,\r
147 Controller,\r
148 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
149 );\r
150 if (EFI_ERROR (Status)) {\r
151 return Status;\r
152 }\r
153\r
154 Status = gBS->OpenProtocol (\r
155 Controller,\r
156 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
157 (VOID **) &NiiProtocol,\r
158 This->DriverBindingHandle,\r
159 Controller,\r
160 EFI_OPEN_PROTOCOL_BY_DRIVER\r
161 );\r
162\r
163 if (EFI_ERROR (Status)) {\r
164 if (Status == EFI_ALREADY_STARTED) {\r
0e549d5b 165 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
a15a4195 166 }\r
167 return Status;\r
168 }\r
169\r
0e549d5b 170 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
a15a4195 171\r
172 //\r
173 // check the version, we don't want to connect to the undi16\r
174 //\r
175 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {\r
176 Status = EFI_UNSUPPORTED;\r
177 goto Done;\r
178 }\r
179 //\r
180 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.\r
181 //\r
e2851998 182 if ((NiiProtocol->Id & 0x0F) != 0) {\r
9cff2f8d 183 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
a15a4195 184 Status = EFI_UNSUPPORTED;\r
185 goto Done;\r
186 }\r
187\r
bdc82513 188 Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->Id);\r
a15a4195 189\r
190 //\r
191 // Verify !PXE revisions.\r
192 //\r
4cda7726 193 if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
9cff2f8d 194 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));\r
a15a4195 195 Status = EFI_UNSUPPORTED;\r
196 goto Done;\r
197 }\r
198\r
4cda7726 199 if (Pxe->hw.Rev < PXE_ROMID_REV) {\r
9cff2f8d 200 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));\r
a15a4195 201 Status = EFI_UNSUPPORTED;\r
202 goto Done;\r
203 }\r
204\r
4cda7726 205 if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
a15a4195 206\r
9cff2f8d 207 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));\r
a15a4195 208 Status = EFI_UNSUPPORTED;\r
209 goto Done;\r
210\r
4cda7726 211 } else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) {\r
9cff2f8d 212 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));\r
a15a4195 213 Status = EFI_UNSUPPORTED;\r
214 goto Done;\r
215 }\r
216 //\r
217 // Do S/W UNDI specific checks.\r
218 //\r
4cda7726 219 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
220 if (Pxe->sw.EntryPoint < Pxe->sw.Len) {\r
9cff2f8d 221 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));\r
a15a4195 222 Status = EFI_UNSUPPORTED;\r
223 goto Done;\r
224 }\r
225\r
4cda7726 226 if (Pxe->sw.BusCnt == 0) {\r
9cff2f8d 227 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));\r
a15a4195 228 Status = EFI_UNSUPPORTED;\r
229 goto Done;\r
230 }\r
231 }\r
232\r
233 Status = EFI_SUCCESS;\r
0e549d5b 234 DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));\r
a15a4195 235\r
236Done:\r
237 gBS->CloseProtocol (\r
238 Controller,\r
239 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
240 This->DriverBindingHandle,\r
241 Controller\r
242 );\r
243\r
244 return Status;\r
245}\r
246\r
a15a4195 247/**\r
4cda7726 248 Start this driver on ControllerHandle. This service is called by the\r
249 EFI boot service ConnectController(). In order to make\r
250 drivers as small as possible, there are a few calling restrictions for\r
251 this service. ConnectController() must follow these\r
252 calling restrictions. If any other agent wishes to call Start() it\r
253 must also follow these calling restrictions.\r
a15a4195 254\r
255 @param This Protocol instance pointer.\r
4cda7726 256 @param ControllerHandle Handle of device to bind driver to.\r
257 @param RemainingDevicePath Optional parameter use to pick a specific child\r
258 device to start.\r
a15a4195 259\r
4cda7726 260 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
469462b1 261 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error\r
4cda7726 262 @retval other This driver does not support this device\r
a15a4195 263\r
264**/\r
265EFI_STATUS\r
266EFIAPI\r
267SimpleNetworkDriverStart (\r
268 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
269 IN EFI_HANDLE Controller,\r
270 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
271 )\r
272{\r
273 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
274 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;\r
275 EFI_STATUS Status;\r
4cda7726 276 PXE_UNDI *Pxe;\r
277 SNP_DRIVER *Snp;\r
278 VOID *Address;\r
a15a4195 279 EFI_HANDLE Handle;\r
280 PXE_PCI_CONFIG_INFO ConfigInfo;\r
281 PCI_TYPE00 *ConfigHeader;\r
282 UINT32 *TempBar;\r
283 UINT8 BarIndex;\r
284 PXE_STATFLAGS InitStatFlags;\r
285\r
9cff2f8d 286 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
a15a4195 287\r
288 Status = gBS->OpenProtocol (\r
289 Controller,\r
290 &gEfiDevicePathProtocolGuid,\r
291 (VOID **) &NiiDevicePath,\r
292 This->DriverBindingHandle,\r
293 Controller,\r
294 EFI_OPEN_PROTOCOL_BY_DRIVER\r
295 );\r
296\r
297 if (EFI_ERROR (Status)) {\r
298 return Status;\r
299 }\r
300\r
301 Status = gBS->LocateDevicePath (\r
302 &gEfiPciIoProtocolGuid,\r
303 &NiiDevicePath,\r
304 &Handle\r
305 );\r
306\r
307 if (EFI_ERROR (Status)) {\r
308 return Status;\r
309 }\r
310\r
311 Status = gBS->OpenProtocol (\r
312 Handle,\r
313 &gEfiPciIoProtocolGuid,\r
4cda7726 314 (VOID **) &mPciIo,\r
a15a4195 315 This->DriverBindingHandle,\r
316 Controller,\r
317 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
318 );\r
319 if (EFI_ERROR (Status)) {\r
320 return Status;\r
321 }\r
322 //\r
323 // Get the NII interface.\r
324 //\r
325 Status = gBS->OpenProtocol (\r
326 Controller,\r
327 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
328 (VOID **) &Nii,\r
329 This->DriverBindingHandle,\r
330 Controller,\r
331 EFI_OPEN_PROTOCOL_BY_DRIVER\r
332 );\r
333 if (EFI_ERROR (Status)) {\r
334 gBS->CloseProtocol (\r
335 Controller,\r
336 &gEfiDevicePathProtocolGuid,\r
337 This->DriverBindingHandle,\r
338 Controller\r
339 );\r
340 return Status;\r
341 }\r
342\r
343 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));\r
344\r
bdc82513 345 Pxe = (PXE_UNDI *) (UINTN) (Nii->Id);\r
a15a4195 346\r
4cda7726 347 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
9cff2f8d 348 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
a15a4195 349 goto NiiError;\r
350 }\r
351\r
4cda7726 352 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
a15a4195 353 //\r
354 // We can get any packets.\r
355 //\r
4cda7726 356 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
a15a4195 357 //\r
358 // We need to be able to get broadcast packets for DHCP.\r
359 // If we do not have promiscuous support, we must at least have\r
360 // broadcast support or we cannot do DHCP!\r
361 //\r
362 } else {\r
9cff2f8d 363 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
a15a4195 364 goto NiiError;\r
365 }\r
366 //\r
367 // OK, we like this UNDI, and we know snp is not already there on this handle\r
368 // Allocate and initialize a new simple network protocol structure.\r
369 //\r
4cda7726 370 Status = mPciIo->AllocateBuffer (\r
371 mPciIo,\r
a15a4195 372 AllocateAnyPages,\r
373 EfiBootServicesData,\r
374 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 375 &Address,\r
a15a4195 376 0\r
377 );\r
378\r
379 if (Status != EFI_SUCCESS) {\r
9cff2f8d 380 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
a15a4195 381 goto NiiError;\r
382 }\r
383\r
4cda7726 384 Snp = (SNP_DRIVER *) (UINTN) Address;\r
a15a4195 385\r
4cda7726 386 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
a15a4195 387\r
4cda7726 388 Snp->PciIo = mPciIo;\r
389 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
a15a4195 390\r
4cda7726 391 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
a15a4195 392\r
4cda7726 393 Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
394 Snp->Snp.Start = SnpUndi32Start;\r
395 Snp->Snp.Stop = SnpUndi32Stop;\r
396 Snp->Snp.Initialize = SnpUndi32Initialize;\r
397 Snp->Snp.Reset = SnpUndi32Reset;\r
398 Snp->Snp.Shutdown = SnpUndi32Shutdown;\r
399 Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;\r
400 Snp->Snp.StationAddress = SnpUndi32StationAddress;\r
401 Snp->Snp.Statistics = SnpUndi32Statistics;\r
402 Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;\r
403 Snp->Snp.NvData = SnpUndi32NvData;\r
404 Snp->Snp.GetStatus = SnpUndi32GetStatus;\r
405 Snp->Snp.Transmit = SnpUndi32Transmit;\r
406 Snp->Snp.Receive = SnpUndi32Receive;\r
407 Snp->Snp.WaitForPacket = NULL;\r
a15a4195 408\r
4cda7726 409 Snp->Snp.Mode = &Snp->Mode;\r
a15a4195 410\r
4cda7726 411 Snp->TxRxBufferSize = 0;\r
412 Snp->TxRxBuffer = NULL;\r
a15a4195 413\r
4cda7726 414 Snp->IfNum = Nii->IfNum;\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
4cda7726 444 Status = mPciIo->AllocateBuffer (\r
445 mPciIo,\r
a15a4195 446 AllocateAnyPages,\r
447 EfiBootServicesData,\r
448 SNP_MEM_PAGES (4096),\r
4cda7726 449 &Address,\r
a15a4195 450 0\r
451 );\r
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
4cda7726 462 // PxeStart call is going to give the callback functions to UNDI, these callback\r
a15a4195 463 // functions use the BarIndex values from the snp structure, so these must be initialized\r
4cda7726 464 // with default values before doing a PxeStart. The correct values can be obtained after\r
a15a4195 465 // getting the config information from UNDI\r
466 //\r
4cda7726 467 Snp->MemoryBarIndex = 0;\r
468 Snp->IoBarIndex = 1;\r
a15a4195 469\r
470 //\r
471 // we need the undi init information many times in this snp code, just get it\r
472 // once here and store it in the snp driver structure. to get Init Info\r
473 // from UNDI we have to start undi first.\r
474 //\r
4cda7726 475 Status = PxeStart (Snp);\r
a15a4195 476\r
477 if (Status != EFI_SUCCESS) {\r
478 goto Error_DeleteSNP;\r
479 }\r
480\r
4cda7726 481 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
482 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 483\r
4cda7726 484 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
485 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 486\r
c9325700
ED
487 Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo);\r
488 Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);\r
a15a4195 489\r
4cda7726 490 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
491 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 492\r
4cda7726 493 Snp->Cdb.IFnum = Snp->IfNum;\r
494 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 495\r
9cff2f8d 496 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 497\r
4cda7726 498 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 499\r
500 //\r
501 // Save the INIT Stat Code...\r
502 //\r
4cda7726 503 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 504\r
4cda7726 505 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 506 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 507 PxeStop (Snp);\r
a15a4195 508 goto Error_DeleteSNP;\r
509 }\r
510\r
4cda7726 511 Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;\r
512 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 513\r
4cda7726 514 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
515 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 516\r
c9325700 517 Snp->Cdb.DBsize = (UINT16) sizeof (ConfigInfo);\r
4cda7726 518 Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\r
a15a4195 519\r
4cda7726 520 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
521 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 522\r
4cda7726 523 Snp->Cdb.IFnum = Snp->IfNum;\r
524 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 525\r
9cff2f8d 526 DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() "));\r
a15a4195 527\r
4cda7726 528 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 529\r
4cda7726 530 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 531 DEBUG ((EFI_D_NET, "\nSnp->undi.config_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
536 // Find the correct BAR to do IO.\r
537 //\r
538 //\r
539 // Enumerate through the PCI BARs for the device to determine which one is\r
540 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
541 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
542 //\r
543 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];\r
544 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];\r
545 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {\r
546 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {\r
547 //\r
548 // This is a 64-bit memory bar, skip this and the\r
549 // next bar as well.\r
550 //\r
551 TempBar++;\r
552 }\r
553\r
554 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {\r
4cda7726 555 Snp->IoBarIndex = BarIndex;\r
a15a4195 556 break;\r
557 }\r
558\r
559 TempBar++;\r
560 }\r
561\r
562 //\r
563 // Initialize simple network protocol mode structure\r
564 //\r
4cda7726 565 Snp->Mode.State = EfiSimpleNetworkStopped;\r
566 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
567 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
568 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
569 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
570 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
571 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
572 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
573 Snp->Mode.MCastFilterCount = 0;\r
a15a4195 574\r
575 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
576 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
4cda7726 577 Snp->Mode.MediaPresentSupported = TRUE;\r
a15a4195 578 break;\r
579\r
580 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
581 default:\r
4cda7726 582 Snp->Mode.MediaPresentSupported = FALSE;\r
a15a4195 583 }\r
584\r
c777c357 585 switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
586 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:\r
587 Snp->MediaStatusSupported = TRUE;\r
588 break;\r
589\r
590 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:\r
591 default:\r
592 Snp->MediaStatusSupported = FALSE;\r
593 }\r
594\r
4cda7726 595 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
596 Snp->Mode.MacAddressChangeable = TRUE;\r
a15a4195 597 } else {\r
4cda7726 598 Snp->Mode.MacAddressChangeable = FALSE;\r
a15a4195 599 }\r
600\r
4cda7726 601 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
602 Snp->Mode.MultipleTxSupported = TRUE;\r
a15a4195 603 } else {\r
4cda7726 604 Snp->Mode.MultipleTxSupported = FALSE;\r
a15a4195 605 }\r
606\r
4cda7726 607 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
a15a4195 608\r
4cda7726 609 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
610 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 611\r
612 }\r
613\r
4cda7726 614 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
615 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
a15a4195 616\r
617 }\r
618\r
4cda7726 619 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
620 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
a15a4195 621\r
622 }\r
623\r
4cda7726 624 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
625 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
a15a4195 626\r
627 }\r
628\r
e2851998 629 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
4cda7726 630 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 631\r
632 }\r
633\r
4cda7726 634 Snp->Mode.ReceiveFilterSetting = 0;\r
a15a4195 635\r
636 //\r
637 // need to get the station address to save in the mode structure. we need to\r
638 // initialize the UNDI first for this.\r
639 //\r
4cda7726 640 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
641 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
a15a4195 642\r
4cda7726 643 if (EFI_ERROR (Status)) {\r
644 PxeStop (Snp);\r
a15a4195 645 goto Error_DeleteSNP;\r
646 }\r
647\r
4cda7726 648 Status = PxeGetStnAddr (Snp);\r
a15a4195 649\r
650 if (Status != EFI_SUCCESS) {\r
f3816027 651 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
4cda7726 652 PxeShutdown (Snp);\r
653 PxeStop (Snp);\r
a15a4195 654 goto Error_DeleteSNP;\r
655 }\r
656\r
4cda7726 657 Snp->Mode.MediaPresent = FALSE;\r
a15a4195 658\r
659 //\r
660 // We should not leave UNDI started and initialized here. this DriverStart()\r
661 // routine must only find and attach the SNP interface to UNDI layer that it\r
662 // finds on the given handle!\r
4cda7726 663 // The UNDI layer will be started when upper layers call Snp->start.\r
a15a4195 664 // How ever, this DriverStart() must fill up the snp mode structure which\r
665 // contains the MAC address of the NIC. For this reason we started and\r
666 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
667 // UNDI interface!\r
668 //\r
4cda7726 669 PxeShutdown (Snp);\r
670 PxeStop (Snp);\r
a15a4195 671\r
0428a6cb 672 //\r
673 // Create EXIT_BOOT_SERIVES Event\r
674 //\r
675 Status = gBS->CreateEventEx (\r
676 EVT_NOTIFY_SIGNAL,\r
677 TPL_NOTIFY,\r
678 SnpNotifyExitBootServices,\r
679 Snp,\r
680 &gEfiEventExitBootServicesGuid,\r
681 &Snp->ExitBootServicesEvent\r
682 );\r
683 if (EFI_ERROR (Status)) {\r
684 goto Error_DeleteSNP;\r
685 }\r
686\r
a15a4195 687 //\r
688 // add SNP to the undi handle\r
689 //\r
690 Status = gBS->InstallProtocolInterface (\r
691 &Controller,\r
692 &gEfiSimpleNetworkProtocolGuid,\r
693 EFI_NATIVE_INTERFACE,\r
4cda7726 694 &(Snp->Snp)\r
a15a4195 695 );\r
696\r
697 if (!EFI_ERROR (Status)) {\r
698 return Status;\r
699 }\r
700\r
469462b1 701 mPciIo->FreeBuffer (\r
702 mPciIo,\r
703 SNP_MEM_PAGES (4096),\r
704 Snp->Cpb\r
705 );\r
a15a4195 706\r
707Error_DeleteSNP:\r
708\r
4cda7726 709 mPciIo->FreeBuffer (\r
710 mPciIo,\r
a15a4195 711 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 712 Snp\r
a15a4195 713 );\r
714NiiError:\r
715 gBS->CloseProtocol (\r
716 Controller,\r
717 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
718 This->DriverBindingHandle,\r
719 Controller\r
720 );\r
721\r
722 gBS->CloseProtocol (\r
723 Controller,\r
724 &gEfiDevicePathProtocolGuid,\r
725 This->DriverBindingHandle,\r
726 Controller\r
727 );\r
728\r
469462b1 729 //\r
730 // If we got here that means we are in error state.\r
731 //\r
732 if (!EFI_ERROR (Status)) {\r
733 Status = EFI_DEVICE_ERROR;\r
734 }\r
735\r
a15a4195 736 return Status;\r
737}\r
738\r
a15a4195 739/**\r
4cda7726 740 Stop this driver on ControllerHandle. This service is called by the\r
741 EFI boot service DisconnectController(). In order to\r
742 make drivers as small as possible, there are a few calling\r
743 restrictions for this service. DisconnectController()\r
744 must follow these calling restrictions. If any other agent wishes\r
745 to call Stop() it must also follow these calling restrictions.\r
e2851998 746\r
4cda7726 747 @param This Protocol instance pointer.\r
748 @param ControllerHandle Handle of device to stop driver on\r
749 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
750 children is zero stop the entire bus driver.\r
751 @param ChildHandleBuffer List of Child Handles to Stop.\r
752\r
753 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
754 @retval other This driver was not removed from this device\r
a15a4195 755\r
756**/\r
757EFI_STATUS\r
758EFIAPI\r
759SimpleNetworkDriverStop (\r
760 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
761 IN EFI_HANDLE Controller,\r
762 IN UINTN NumberOfChildren,\r
763 IN EFI_HANDLE *ChildHandleBuffer\r
764 )\r
765{\r
766 EFI_STATUS Status;\r
767 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
768 SNP_DRIVER *Snp;\r
769\r
770 //\r
771 // Get our context back.\r
772 //\r
773 Status = gBS->OpenProtocol (\r
774 Controller,\r
775 &gEfiSimpleNetworkProtocolGuid,\r
776 (VOID **) &SnpProtocol,\r
777 This->DriverBindingHandle,\r
778 Controller,\r
779 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
780 );\r
781\r
782 if (EFI_ERROR (Status)) {\r
783 return EFI_UNSUPPORTED;\r
784 }\r
785\r
786 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
787\r
788 Status = gBS->UninstallProtocolInterface (\r
789 Controller,\r
790 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 791 &Snp->Snp\r
a15a4195 792 );\r
793\r
794 if (EFI_ERROR (Status)) {\r
795 return Status;\r
796 }\r
797\r
0428a6cb 798 //\r
799 // Close EXIT_BOOT_SERIVES Event\r
800 //\r
801 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
802\r
a15a4195 803 Status = gBS->CloseProtocol (\r
804 Controller,\r
805 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
806 This->DriverBindingHandle,\r
807 Controller\r
808 );\r
809\r
810 Status = gBS->CloseProtocol (\r
811 Controller,\r
812 &gEfiDevicePathProtocolGuid,\r
813 This->DriverBindingHandle,\r
814 Controller\r
815 );\r
816\r
4cda7726 817 PxeShutdown (Snp);\r
818 PxeStop (Snp);\r
a15a4195 819\r
4cda7726 820 mPciIo->FreeBuffer (\r
821 mPciIo,\r
a15a4195 822 SNP_MEM_PAGES (4096),\r
4cda7726 823 Snp->Cpb\r
a15a4195 824 );\r
825\r
4cda7726 826 mPciIo->FreeBuffer (\r
827 mPciIo,\r
a15a4195 828 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
829 Snp\r
830 );\r
831\r
832 return Status;\r
833}\r
834\r
4cda7726 835//\r
836// Simple Network Protocol Driver Global Variables\r
837//\r
216f7970 838EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
4cda7726 839 SimpleNetworkDriverSupported,\r
840 SimpleNetworkDriverStart,\r
841 SimpleNetworkDriverStop,\r
842 0xa,\r
843 NULL,\r
844 NULL\r
845};\r
846\r
847\r
848/**\r
849 This routine maps the given CPU address to a Device address. It creates a\r
850 an entry in the map list with the virtual and physical addresses and the\r
851 un map cookie.\r
852\r
853 @param V2p pointer to return a map list node pointer.\r
854 @param Type the direction in which the data flows from the given\r
855 virtual address device->cpu or cpu->device or both\r
856 ways.\r
857 @param VirtualAddress virtual address (or CPU address) to be mapped.\r
858 @param BufferSize size of the buffer to be mapped.\r
859\r
860 @retval EFI_SUCEESS routine has completed the mapping.\r
861 @retval EFI_INVALID_PARAMETER invalid parameter.\r
862 @retval EFI_OUT_OF_RESOURCES out of resource.\r
863 @retval other error as indicated.\r
864\r
865**/\r
866EFI_STATUS\r
867AddV2P (\r
868 IN OUT V2P **V2p,\r
869 EFI_PCI_IO_PROTOCOL_OPERATION Type,\r
870 VOID *VirtualAddress,\r
871 UINTN BufferSize\r
872 )\r
873{\r
874 EFI_STATUS Status;\r
875\r
876 if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) {\r
877 return EFI_INVALID_PARAMETER;\r
878 }\r
879\r
f3816027 880 *V2p = AllocatePool (sizeof (V2P));\r
894d038a 881 if (*V2p == NULL) {\r
4cda7726 882 return EFI_OUT_OF_RESOURCES;\r
883 }\r
884\r
885 Status = mPciIo->Map (\r
f3816027 886 mPciIo,\r
887 Type,\r
888 VirtualAddress,\r
889 &BufferSize,\r
890 &(*V2p)->PhysicalAddress,\r
891 &(*V2p)->Unmap\r
892 );\r
4cda7726 893 if (Status != EFI_SUCCESS) {\r
894 FreePool (*V2p);\r
895 return Status;\r
896 }\r
897 (*V2p)->VirtualAddress = VirtualAddress;\r
f3816027 898 (*V2p)->BufferSize = BufferSize;\r
899 (*V2p)->Next = mV2p;\r
900 mV2p = *V2p;\r
4cda7726 901\r
902 return EFI_SUCCESS;\r
903}\r
904\r
905\r
906/**\r
907 This routine searches the linked list of mapped address nodes (for undi3.0\r
908 interface) to find the node that corresponds to the given virtual address and\r
909 returns a pointer to that node.\r
910\r
911 @param V2p pointer to return a map list node pointer.\r
912 @param VirtualAddr virtual address (or CPU address) to be searched in\r
913 the map list\r
914\r
f3816027 915 @retval EFI_SUCEESS A match was found.\r
916 @retval Other A match cannot be found.\r
4cda7726 917\r
918**/\r
919EFI_STATUS\r
920FindV2p (\r
921 V2P **V2p,\r
922 VOID *VirtualAddr\r
923 )\r
924{\r
925 V2P *Ptr;\r
926\r
927 if (V2p == NULL || VirtualAddr == NULL) {\r
928 return EFI_INVALID_PARAMETER;\r
929 }\r
930\r
931 for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) {\r
932 if (Ptr->VirtualAddress == VirtualAddr) {\r
933 *V2p = Ptr;\r
934 return EFI_SUCCESS;\r
935 }\r
936 }\r
937\r
938 return EFI_NOT_FOUND;\r
939}\r
940\r
941\r
942/**\r
f3816027 943 Unmap the given virtual address and free the memory allocated for the map list\r
944 node corresponding to that address.\r
4cda7726 945\r
f3816027 946 @param VirtualAddress virtual address (or CPU address) to be unmapped.\r
4cda7726 947\r
f3816027 948 @retval EFI_SUCEESS Successfully unmapped.\r
949 @retval Other Other errors as indicated.\r
4cda7726 950\r
951**/\r
952EFI_STATUS\r
953DelV2p (\r
954 VOID *VirtualAddress\r
955 )\r
956{\r
957 V2P *Current;\r
958 V2P *Next;\r
959 EFI_STATUS Status;\r
960\r
961 if (VirtualAddress == NULL) {\r
962 return EFI_INVALID_PARAMETER;\r
963 }\r
964\r
965 if (mV2p == NULL) {\r
966 return EFI_NOT_FOUND;\r
967 }\r
968 //\r
969 // Is our node at the head of the list??\r
970 //\r
971 if ((Current = mV2p)->VirtualAddress == VirtualAddress) {\r
972 mV2p = mV2p->Next;\r
973\r
974 Status = mPciIo->Unmap (mPciIo, Current->Unmap);\r
975\r
976 FreePool (Current);\r
977\r
978 if (EFI_ERROR (Status)) {\r
979 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
980 }\r
981 return Status;\r
982 }\r
983\r
984 for (; Current->Next != NULL; Current = Next) {\r
985 if ((Next = Current->Next)->VirtualAddress == VirtualAddress) {\r
986 Current->Next = Next->Next;\r
987 Status = mPciIo->Unmap (mPciIo, Next->Unmap);\r
988 FreePool (Next);\r
989\r
990 if (EFI_ERROR (Status)) {\r
991 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
992 }\r
993 return Status;\r
994 }\r
995 }\r
996\r
997 return EFI_NOT_FOUND;\r
998}\r
a15a4195 999\r
1000/**\r
4cda7726 1001 The SNP driver entry point.\r
a15a4195 1002\r
4cda7726 1003 @param ImageHandle The driver image handle.\r
1004 @param SystemTable The system table.\r
a15a4195 1005\r
4cda7726 1006 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
1007 loaded it's ROM, and installed a notify event for\r
1008 the Network Indentifier Interface Protocol\r
1009 successfully.\r
1010 @retval Other Return value from HandleProtocol for\r
1011 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 1012\r
1013**/\r
1014EFI_STATUS\r
1015EFIAPI\r
1016InitializeSnpNiiDriver (\r
1017 IN EFI_HANDLE ImageHandle,\r
1018 IN EFI_SYSTEM_TABLE *SystemTable\r
1019 )\r
1020{\r
1021 return EfiLibInstallDriverBindingComponentName2 (\r
1022 ImageHandle,\r
1023 SystemTable,\r
216f7970 1024 &gSimpleNetworkDriverBinding,\r
f3de0a60 1025 ImageHandle,\r
a15a4195 1026 &gSimpleNetworkComponentName,\r
1027 &gSimpleNetworkComponentName2\r
1028 );\r
1029}\r