]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
The current Makefile only checks the primary python file, such as build.py and does...
[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
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
e3644786 29 @param Context Event handler private data\r
0428a6cb 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
61f2ab90
QO
413 \r
414 if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
415 Snp->IfNum = Nii->IfNum;\r
a15a4195 416\r
61f2ab90
QO
417 } else {\r
418 Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);\r
419 }\r
a15a4195 420\r
4cda7726 421 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
422 Snp->IsSwUndi = FALSE;\r
423 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
a15a4195 424 } else {\r
4cda7726 425 Snp->IsSwUndi = TRUE;\r
a15a4195 426\r
4cda7726 427 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
428 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;\r
a15a4195 429 } else {\r
4cda7726 430 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);\r
a15a4195 431 }\r
432 }\r
433 //\r
434 // Allocate a global CPB and DB buffer for this UNDI interface.\r
435 // we do this because:\r
436 //\r
437 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
438 // within 2GB limit, create them here and map them so that when undi calls\r
439 // v2p callback to check if the physical address is < 2gb, we will pass.\r
440 //\r
441 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
442 // simpler if we use the same cpb, db variables for both old and new undi\r
443 // interfaces from all the SNP interface calls (we don't map the buffers\r
444 // for the newer undi interfaces though)\r
445 // .\r
446 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
447 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
448 //\r
4cda7726 449 Status = mPciIo->AllocateBuffer (\r
450 mPciIo,\r
a15a4195 451 AllocateAnyPages,\r
452 EfiBootServicesData,\r
453 SNP_MEM_PAGES (4096),\r
4cda7726 454 &Address,\r
a15a4195 455 0\r
456 );\r
457\r
458 if (Status != EFI_SUCCESS) {\r
9cff2f8d 459 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
a15a4195 460 goto Error_DeleteSNP;\r
461 }\r
462\r
4cda7726 463 Snp->Cpb = (VOID *) (UINTN) Address;\r
464 Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
a15a4195 465\r
466 //\r
4cda7726 467 // PxeStart call is going to give the callback functions to UNDI, these callback\r
a15a4195 468 // functions use the BarIndex values from the snp structure, so these must be initialized\r
4cda7726 469 // with default values before doing a PxeStart. The correct values can be obtained after\r
a15a4195 470 // getting the config information from UNDI\r
471 //\r
4cda7726 472 Snp->MemoryBarIndex = 0;\r
473 Snp->IoBarIndex = 1;\r
a15a4195 474\r
475 //\r
476 // we need the undi init information many times in this snp code, just get it\r
477 // once here and store it in the snp driver structure. to get Init Info\r
478 // from UNDI we have to start undi first.\r
479 //\r
4cda7726 480 Status = PxeStart (Snp);\r
a15a4195 481\r
482 if (Status != EFI_SUCCESS) {\r
483 goto Error_DeleteSNP;\r
484 }\r
485\r
4cda7726 486 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
487 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 488\r
4cda7726 489 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
490 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 491\r
c9325700
ED
492 Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo);\r
493 Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);\r
a15a4195 494\r
4cda7726 495 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
496 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 497\r
4cda7726 498 Snp->Cdb.IFnum = Snp->IfNum;\r
499 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 500\r
9cff2f8d 501 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 502\r
4cda7726 503 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 504\r
505 //\r
506 // Save the INIT Stat Code...\r
507 //\r
4cda7726 508 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 509\r
4cda7726 510 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 511 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 512 PxeStop (Snp);\r
a15a4195 513 goto Error_DeleteSNP;\r
514 }\r
515\r
4cda7726 516 Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;\r
517 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 518\r
4cda7726 519 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
520 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 521\r
c9325700 522 Snp->Cdb.DBsize = (UINT16) sizeof (ConfigInfo);\r
4cda7726 523 Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\r
a15a4195 524\r
4cda7726 525 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
526 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 527\r
4cda7726 528 Snp->Cdb.IFnum = Snp->IfNum;\r
529 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 530\r
9cff2f8d 531 DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() "));\r
a15a4195 532\r
4cda7726 533 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 534\r
4cda7726 535 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 536 DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 537 PxeStop (Snp);\r
a15a4195 538 goto Error_DeleteSNP;\r
539 }\r
540 //\r
541 // Find the correct BAR to do IO.\r
542 //\r
543 //\r
544 // Enumerate through the PCI BARs for the device to determine which one is\r
545 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
546 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
547 //\r
523f48e7
ED
548 ConfigHeader = (PCI_TYPE00 *) ConfigInfo.Config.Byte;\r
549 TempBar = (UINT32 *) ConfigHeader->Device.Bar;\r
a15a4195 550 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {\r
551 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {\r
552 //\r
553 // This is a 64-bit memory bar, skip this and the\r
554 // next bar as well.\r
555 //\r
556 TempBar++;\r
557 }\r
558\r
559 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {\r
4cda7726 560 Snp->IoBarIndex = BarIndex;\r
a15a4195 561 break;\r
562 }\r
563\r
564 TempBar++;\r
565 }\r
566\r
567 //\r
568 // Initialize simple network protocol mode structure\r
569 //\r
4cda7726 570 Snp->Mode.State = EfiSimpleNetworkStopped;\r
571 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
572 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
573 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
574 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
575 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
576 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
577 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
578 Snp->Mode.MCastFilterCount = 0;\r
a15a4195 579\r
580 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
581 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
4cda7726 582 Snp->Mode.MediaPresentSupported = TRUE;\r
a15a4195 583 break;\r
584\r
585 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
586 default:\r
4cda7726 587 Snp->Mode.MediaPresentSupported = FALSE;\r
a15a4195 588 }\r
589\r
c777c357 590 switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {\r
591 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:\r
592 Snp->MediaStatusSupported = TRUE;\r
593 break;\r
594\r
595 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:\r
596 default:\r
597 Snp->MediaStatusSupported = FALSE;\r
598 }\r
599\r
4cda7726 600 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
601 Snp->Mode.MacAddressChangeable = TRUE;\r
a15a4195 602 } else {\r
4cda7726 603 Snp->Mode.MacAddressChangeable = FALSE;\r
a15a4195 604 }\r
605\r
4cda7726 606 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
607 Snp->Mode.MultipleTxSupported = TRUE;\r
a15a4195 608 } else {\r
4cda7726 609 Snp->Mode.MultipleTxSupported = FALSE;\r
a15a4195 610 }\r
611\r
4cda7726 612 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
a15a4195 613\r
4cda7726 614 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
615 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 616\r
617 }\r
618\r
4cda7726 619 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
620 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
a15a4195 621\r
622 }\r
623\r
4cda7726 624 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
625 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
a15a4195 626\r
627 }\r
628\r
4cda7726 629 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
630 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
a15a4195 631\r
632 }\r
633\r
e2851998 634 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
4cda7726 635 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 636\r
637 }\r
638\r
4cda7726 639 Snp->Mode.ReceiveFilterSetting = 0;\r
a15a4195 640\r
641 //\r
642 // need to get the station address to save in the mode structure. we need to\r
643 // initialize the UNDI first for this.\r
644 //\r
4cda7726 645 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
646 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
a15a4195 647\r
4cda7726 648 if (EFI_ERROR (Status)) {\r
649 PxeStop (Snp);\r
a15a4195 650 goto Error_DeleteSNP;\r
651 }\r
652\r
4cda7726 653 Status = PxeGetStnAddr (Snp);\r
a15a4195 654\r
655 if (Status != EFI_SUCCESS) {\r
f3816027 656 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
4cda7726 657 PxeShutdown (Snp);\r
658 PxeStop (Snp);\r
a15a4195 659 goto Error_DeleteSNP;\r
660 }\r
661\r
4cda7726 662 Snp->Mode.MediaPresent = FALSE;\r
a15a4195 663\r
664 //\r
665 // We should not leave UNDI started and initialized here. this DriverStart()\r
666 // routine must only find and attach the SNP interface to UNDI layer that it\r
667 // finds on the given handle!\r
4cda7726 668 // The UNDI layer will be started when upper layers call Snp->start.\r
a15a4195 669 // How ever, this DriverStart() must fill up the snp mode structure which\r
670 // contains the MAC address of the NIC. For this reason we started and\r
671 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
672 // UNDI interface!\r
673 //\r
4cda7726 674 PxeShutdown (Snp);\r
675 PxeStop (Snp);\r
a15a4195 676\r
0428a6cb 677 //\r
678 // Create EXIT_BOOT_SERIVES Event\r
679 //\r
680 Status = gBS->CreateEventEx (\r
681 EVT_NOTIFY_SIGNAL,\r
682 TPL_NOTIFY,\r
683 SnpNotifyExitBootServices,\r
684 Snp,\r
685 &gEfiEventExitBootServicesGuid,\r
686 &Snp->ExitBootServicesEvent\r
687 );\r
688 if (EFI_ERROR (Status)) {\r
689 goto Error_DeleteSNP;\r
690 }\r
691\r
a15a4195 692 //\r
693 // add SNP to the undi handle\r
694 //\r
695 Status = gBS->InstallProtocolInterface (\r
696 &Controller,\r
697 &gEfiSimpleNetworkProtocolGuid,\r
698 EFI_NATIVE_INTERFACE,\r
4cda7726 699 &(Snp->Snp)\r
a15a4195 700 );\r
701\r
702 if (!EFI_ERROR (Status)) {\r
703 return Status;\r
704 }\r
705\r
469462b1 706 mPciIo->FreeBuffer (\r
707 mPciIo,\r
708 SNP_MEM_PAGES (4096),\r
709 Snp->Cpb\r
710 );\r
a15a4195 711\r
712Error_DeleteSNP:\r
713\r
4cda7726 714 mPciIo->FreeBuffer (\r
715 mPciIo,\r
a15a4195 716 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 717 Snp\r
a15a4195 718 );\r
719NiiError:\r
720 gBS->CloseProtocol (\r
721 Controller,\r
722 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
723 This->DriverBindingHandle,\r
724 Controller\r
725 );\r
726\r
727 gBS->CloseProtocol (\r
728 Controller,\r
729 &gEfiDevicePathProtocolGuid,\r
730 This->DriverBindingHandle,\r
731 Controller\r
732 );\r
733\r
469462b1 734 //\r
735 // If we got here that means we are in error state.\r
736 //\r
737 if (!EFI_ERROR (Status)) {\r
738 Status = EFI_DEVICE_ERROR;\r
739 }\r
740\r
a15a4195 741 return Status;\r
742}\r
743\r
a15a4195 744/**\r
4cda7726 745 Stop this driver on ControllerHandle. This service is called by the\r
746 EFI boot service DisconnectController(). In order to\r
747 make drivers as small as possible, there are a few calling\r
748 restrictions for this service. DisconnectController()\r
749 must follow these calling restrictions. If any other agent wishes\r
750 to call Stop() it must also follow these calling restrictions.\r
e2851998 751\r
4cda7726 752 @param This Protocol instance pointer.\r
753 @param ControllerHandle Handle of device to stop driver on\r
754 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
755 children is zero stop the entire bus driver.\r
756 @param ChildHandleBuffer List of Child Handles to Stop.\r
757\r
758 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
759 @retval other This driver was not removed from this device\r
a15a4195 760\r
761**/\r
762EFI_STATUS\r
763EFIAPI\r
764SimpleNetworkDriverStop (\r
765 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
766 IN EFI_HANDLE Controller,\r
767 IN UINTN NumberOfChildren,\r
768 IN EFI_HANDLE *ChildHandleBuffer\r
769 )\r
770{\r
771 EFI_STATUS Status;\r
772 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
773 SNP_DRIVER *Snp;\r
774\r
775 //\r
776 // Get our context back.\r
777 //\r
778 Status = gBS->OpenProtocol (\r
779 Controller,\r
780 &gEfiSimpleNetworkProtocolGuid,\r
781 (VOID **) &SnpProtocol,\r
782 This->DriverBindingHandle,\r
783 Controller,\r
784 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
785 );\r
786\r
787 if (EFI_ERROR (Status)) {\r
788 return EFI_UNSUPPORTED;\r
789 }\r
790\r
791 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
792\r
793 Status = gBS->UninstallProtocolInterface (\r
794 Controller,\r
795 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 796 &Snp->Snp\r
a15a4195 797 );\r
798\r
799 if (EFI_ERROR (Status)) {\r
800 return Status;\r
801 }\r
802\r
0428a6cb 803 //\r
804 // Close EXIT_BOOT_SERIVES Event\r
805 //\r
806 gBS->CloseEvent (Snp->ExitBootServicesEvent);\r
807\r
a15a4195 808 Status = gBS->CloseProtocol (\r
809 Controller,\r
810 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
811 This->DriverBindingHandle,\r
812 Controller\r
813 );\r
814\r
815 Status = gBS->CloseProtocol (\r
816 Controller,\r
817 &gEfiDevicePathProtocolGuid,\r
818 This->DriverBindingHandle,\r
819 Controller\r
820 );\r
821\r
4cda7726 822 PxeShutdown (Snp);\r
823 PxeStop (Snp);\r
a15a4195 824\r
4cda7726 825 mPciIo->FreeBuffer (\r
826 mPciIo,\r
a15a4195 827 SNP_MEM_PAGES (4096),\r
4cda7726 828 Snp->Cpb\r
a15a4195 829 );\r
830\r
4cda7726 831 mPciIo->FreeBuffer (\r
832 mPciIo,\r
a15a4195 833 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
834 Snp\r
835 );\r
836\r
837 return Status;\r
838}\r
839\r
4cda7726 840//\r
841// Simple Network Protocol Driver Global Variables\r
842//\r
216f7970 843EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {\r
4cda7726 844 SimpleNetworkDriverSupported,\r
845 SimpleNetworkDriverStart,\r
846 SimpleNetworkDriverStop,\r
847 0xa,\r
848 NULL,\r
849 NULL\r
850};\r
851\r
852\r
853/**\r
854 This routine maps the given CPU address to a Device address. It creates a\r
855 an entry in the map list with the virtual and physical addresses and the\r
856 un map cookie.\r
857\r
858 @param V2p pointer to return a map list node pointer.\r
859 @param Type the direction in which the data flows from the given\r
860 virtual address device->cpu or cpu->device or both\r
861 ways.\r
862 @param VirtualAddress virtual address (or CPU address) to be mapped.\r
863 @param BufferSize size of the buffer to be mapped.\r
864\r
865 @retval EFI_SUCEESS routine has completed the mapping.\r
866 @retval EFI_INVALID_PARAMETER invalid parameter.\r
867 @retval EFI_OUT_OF_RESOURCES out of resource.\r
868 @retval other error as indicated.\r
869\r
870**/\r
871EFI_STATUS\r
872AddV2P (\r
873 IN OUT V2P **V2p,\r
874 EFI_PCI_IO_PROTOCOL_OPERATION Type,\r
875 VOID *VirtualAddress,\r
876 UINTN BufferSize\r
877 )\r
878{\r
879 EFI_STATUS Status;\r
880\r
881 if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) {\r
882 return EFI_INVALID_PARAMETER;\r
883 }\r
884\r
f3816027 885 *V2p = AllocatePool (sizeof (V2P));\r
894d038a 886 if (*V2p == NULL) {\r
4cda7726 887 return EFI_OUT_OF_RESOURCES;\r
888 }\r
889\r
890 Status = mPciIo->Map (\r
f3816027 891 mPciIo,\r
892 Type,\r
893 VirtualAddress,\r
894 &BufferSize,\r
895 &(*V2p)->PhysicalAddress,\r
896 &(*V2p)->Unmap\r
897 );\r
4cda7726 898 if (Status != EFI_SUCCESS) {\r
899 FreePool (*V2p);\r
900 return Status;\r
901 }\r
902 (*V2p)->VirtualAddress = VirtualAddress;\r
f3816027 903 (*V2p)->BufferSize = BufferSize;\r
904 (*V2p)->Next = mV2p;\r
905 mV2p = *V2p;\r
4cda7726 906\r
907 return EFI_SUCCESS;\r
908}\r
909\r
910\r
911/**\r
912 This routine searches the linked list of mapped address nodes (for undi3.0\r
913 interface) to find the node that corresponds to the given virtual address and\r
914 returns a pointer to that node.\r
915\r
916 @param V2p pointer to return a map list node pointer.\r
917 @param VirtualAddr virtual address (or CPU address) to be searched in\r
918 the map list\r
919\r
f3816027 920 @retval EFI_SUCEESS A match was found.\r
921 @retval Other A match cannot be found.\r
4cda7726 922\r
923**/\r
924EFI_STATUS\r
925FindV2p (\r
926 V2P **V2p,\r
927 VOID *VirtualAddr\r
928 )\r
929{\r
930 V2P *Ptr;\r
931\r
932 if (V2p == NULL || VirtualAddr == NULL) {\r
933 return EFI_INVALID_PARAMETER;\r
934 }\r
935\r
936 for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) {\r
937 if (Ptr->VirtualAddress == VirtualAddr) {\r
938 *V2p = Ptr;\r
939 return EFI_SUCCESS;\r
940 }\r
941 }\r
942\r
943 return EFI_NOT_FOUND;\r
944}\r
945\r
946\r
947/**\r
f3816027 948 Unmap the given virtual address and free the memory allocated for the map list\r
949 node corresponding to that address.\r
4cda7726 950\r
f3816027 951 @param VirtualAddress virtual address (or CPU address) to be unmapped.\r
4cda7726 952\r
f3816027 953 @retval EFI_SUCEESS Successfully unmapped.\r
954 @retval Other Other errors as indicated.\r
4cda7726 955\r
956**/\r
957EFI_STATUS\r
958DelV2p (\r
959 VOID *VirtualAddress\r
960 )\r
961{\r
962 V2P *Current;\r
963 V2P *Next;\r
964 EFI_STATUS Status;\r
965\r
966 if (VirtualAddress == NULL) {\r
967 return EFI_INVALID_PARAMETER;\r
968 }\r
969\r
970 if (mV2p == NULL) {\r
971 return EFI_NOT_FOUND;\r
972 }\r
973 //\r
974 // Is our node at the head of the list??\r
975 //\r
976 if ((Current = mV2p)->VirtualAddress == VirtualAddress) {\r
977 mV2p = mV2p->Next;\r
978\r
979 Status = mPciIo->Unmap (mPciIo, Current->Unmap);\r
980\r
981 FreePool (Current);\r
982\r
983 if (EFI_ERROR (Status)) {\r
984 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
985 }\r
986 return Status;\r
987 }\r
988\r
989 for (; Current->Next != NULL; Current = Next) {\r
990 if ((Next = Current->Next)->VirtualAddress == VirtualAddress) {\r
991 Current->Next = Next->Next;\r
992 Status = mPciIo->Unmap (mPciIo, Next->Unmap);\r
993 FreePool (Next);\r
994\r
995 if (EFI_ERROR (Status)) {\r
996 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
997 }\r
998 return Status;\r
999 }\r
1000 }\r
1001\r
1002 return EFI_NOT_FOUND;\r
1003}\r
a15a4195 1004\r
1005/**\r
4cda7726 1006 The SNP driver entry point.\r
a15a4195 1007\r
4cda7726 1008 @param ImageHandle The driver image handle.\r
1009 @param SystemTable The system table.\r
a15a4195 1010\r
4cda7726 1011 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
1012 loaded it's ROM, and installed a notify event for\r
1013 the Network Indentifier Interface Protocol\r
1014 successfully.\r
1015 @retval Other Return value from HandleProtocol for\r
1016 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 1017\r
1018**/\r
1019EFI_STATUS\r
1020EFIAPI\r
1021InitializeSnpNiiDriver (\r
1022 IN EFI_HANDLE ImageHandle,\r
1023 IN EFI_SYSTEM_TABLE *SystemTable\r
1024 )\r
1025{\r
1026 return EfiLibInstallDriverBindingComponentName2 (\r
1027 ImageHandle,\r
1028 SystemTable,\r
216f7970 1029 &gSimpleNetworkDriverBinding,\r
f3de0a60 1030 ImageHandle,\r
a15a4195 1031 &gSimpleNetworkComponentName,\r
1032 &gSimpleNetworkComponentName2\r
1033 );\r
1034}\r