]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
Remove some useless EDK_RELEASE_VERSION, EFI_SPECIFICATION_VERSION ,and review VALID_...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Snp.c
CommitLineData
a15a4195 1/** @file\r
4cda7726 2 Implementation of driver entry point and driver binding protocol.\r
3 \r
4Copyright (c) 2004 - 2008, Intel Corporation. <BR> \r
5All rights reserved. This program and the accompanying materials are licensed \r
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
a15a4195 25\r
26/**\r
4cda7726 27 Unsupport currently.\r
28 \r
29 @param Cdb command to be sent to UNDI.\r
a15a4195 30\r
31**/\r
32EFI_STATUS\r
4cda7726 33IssueHwUndiCommand (\r
34 UINT64 Cdb\r
a15a4195 35 )\r
36{\r
4cda7726 37 DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));\r
a15a4195 38\r
4cda7726 39 if (Cdb == 0) {\r
a15a4195 40 return EFI_INVALID_PARAMETER;\r
41\r
42 }\r
43 //\r
44 // %%TBD - For now, nothing is done.\r
45 //\r
46 return EFI_UNSUPPORTED;\r
47}\r
48\r
49\r
50/**\r
51 Compute 8-bit checksum of a buffer.\r
52\r
4cda7726 53 @param Buffer Pointer to buffer.\r
54 @param Length Length of buffer in bytes.\r
a15a4195 55\r
56 @return 8-bit checksum of all bytes in buffer.\r
57 @return If ptr is NULL or len is zero, zero is returned.\r
58\r
59**/\r
a15a4195 60UINT8\r
4cda7726 61Calc8BitCksum (\r
62 VOID *Buffer,\r
63 UINTN Length\r
a15a4195 64 )\r
65{\r
4cda7726 66 UINT8 *Ptr;\r
67 UINT8 Cksum;\r
a15a4195 68\r
4cda7726 69 Ptr = Buffer;\r
70 Cksum = 0;\r
a15a4195 71\r
4cda7726 72 if (Ptr == NULL || Length == 0) {\r
a15a4195 73 return 0;\r
74 }\r
75\r
4cda7726 76 while (Length-- != 0) {\r
77 Cksum = (UINT8) (Cksum + *Ptr++);\r
a15a4195 78 }\r
79\r
4cda7726 80 return Cksum;\r
a15a4195 81}\r
82\r
a15a4195 83/**\r
4cda7726 84 Test to see if this driver supports ControllerHandle. This service\r
85 is called by the EFI boot service ConnectController(). In\r
86 order to make drivers as small as possible, there are a few calling\r
87 restrictions for this service. ConnectController() must\r
88 follow these calling restrictions. If any other agent wishes to call\r
89 Supported() it must also follow these calling restrictions.\r
90\r
91 @param This Protocol instance pointer.\r
92 @param ControllerHandle Handle of device to test\r
93 @param RemainingDevicePath Optional parameter use to pick a specific child\r
94 device to start.\r
95\r
96 @retval EFI_SUCCESS This driver supports this device\r
97 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
98 @retval other This driver does not support this device\r
a15a4195 99\r
100**/\r
101EFI_STATUS\r
102EFIAPI\r
103SimpleNetworkDriverSupported (\r
104 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
105 IN EFI_HANDLE Controller,\r
106 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
107 )\r
108{\r
109 EFI_STATUS Status;\r
110 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;\r
4cda7726 111 PXE_UNDI *Pxe;\r
a15a4195 112\r
113 Status = gBS->OpenProtocol (\r
114 Controller,\r
115 &gEfiDevicePathProtocolGuid,\r
116 NULL,\r
117 This->DriverBindingHandle,\r
118 Controller,\r
119 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
120 );\r
121 if (EFI_ERROR (Status)) {\r
122 return Status;\r
123 }\r
124\r
125 Status = gBS->OpenProtocol (\r
126 Controller,\r
127 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
128 (VOID **) &NiiProtocol,\r
129 This->DriverBindingHandle,\r
130 Controller,\r
131 EFI_OPEN_PROTOCOL_BY_DRIVER\r
132 );\r
133\r
134 if (EFI_ERROR (Status)) {\r
135 if (Status == EFI_ALREADY_STARTED) {\r
0e549d5b 136 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
a15a4195 137 }\r
138 return Status;\r
139 }\r
140\r
0e549d5b 141 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
a15a4195 142\r
143 //\r
144 // check the version, we don't want to connect to the undi16\r
145 //\r
146 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {\r
147 Status = EFI_UNSUPPORTED;\r
148 goto Done;\r
149 }\r
150 //\r
151 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.\r
152 //\r
153 if (NiiProtocol->ID & 0x0F) {\r
154 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
155 Status = EFI_UNSUPPORTED;\r
156 goto Done;\r
157 }\r
158\r
4cda7726 159 Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);\r
a15a4195 160\r
161 //\r
162 // Verify !PXE revisions.\r
163 //\r
4cda7726 164 if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
a15a4195 165 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));\r
166 Status = EFI_UNSUPPORTED;\r
167 goto Done;\r
168 }\r
169\r
4cda7726 170 if (Pxe->hw.Rev < PXE_ROMID_REV) {\r
a15a4195 171 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));\r
172 Status = EFI_UNSUPPORTED;\r
173 goto Done;\r
174 }\r
175\r
4cda7726 176 if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
a15a4195 177\r
178 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));\r
179 Status = EFI_UNSUPPORTED;\r
180 goto Done;\r
181\r
4cda7726 182 } else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) {\r
a15a4195 183 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));\r
184 Status = EFI_UNSUPPORTED;\r
185 goto Done;\r
186 }\r
187 //\r
188 // Do S/W UNDI specific checks.\r
189 //\r
4cda7726 190 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
191 if (Pxe->sw.EntryPoint < Pxe->sw.Len) {\r
a15a4195 192 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));\r
193 Status = EFI_UNSUPPORTED;\r
194 goto Done;\r
195 }\r
196\r
4cda7726 197 if (Pxe->sw.BusCnt == 0) {\r
a15a4195 198 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));\r
199 Status = EFI_UNSUPPORTED;\r
200 goto Done;\r
201 }\r
202 }\r
203\r
204 Status = EFI_SUCCESS;\r
0e549d5b 205 DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));\r
a15a4195 206\r
207Done:\r
208 gBS->CloseProtocol (\r
209 Controller,\r
210 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
211 This->DriverBindingHandle,\r
212 Controller\r
213 );\r
214\r
215 return Status;\r
216}\r
217\r
a15a4195 218/**\r
4cda7726 219 Start this driver on ControllerHandle. This service is called by the\r
220 EFI boot service ConnectController(). In order to make\r
221 drivers as small as possible, there are a few calling restrictions for\r
222 this service. ConnectController() must follow these\r
223 calling restrictions. If any other agent wishes to call Start() it\r
224 must also follow these calling restrictions.\r
a15a4195 225\r
226 @param This Protocol instance pointer.\r
4cda7726 227 @param ControllerHandle Handle of device to bind driver to.\r
228 @param RemainingDevicePath Optional parameter use to pick a specific child\r
229 device to start.\r
a15a4195 230\r
4cda7726 231 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
232 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
233 @retval other This driver does not support this device\r
a15a4195 234\r
235**/\r
236EFI_STATUS\r
237EFIAPI\r
238SimpleNetworkDriverStart (\r
239 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
240 IN EFI_HANDLE Controller,\r
241 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
242 )\r
243{\r
244 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
245 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;\r
246 EFI_STATUS Status;\r
4cda7726 247 PXE_UNDI *Pxe;\r
248 SNP_DRIVER *Snp;\r
249 VOID *Address;\r
a15a4195 250 EFI_HANDLE Handle;\r
251 PXE_PCI_CONFIG_INFO ConfigInfo;\r
252 PCI_TYPE00 *ConfigHeader;\r
253 UINT32 *TempBar;\r
254 UINT8 BarIndex;\r
255 PXE_STATFLAGS InitStatFlags;\r
256\r
257 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
258\r
259 Status = gBS->OpenProtocol (\r
260 Controller,\r
261 &gEfiDevicePathProtocolGuid,\r
262 (VOID **) &NiiDevicePath,\r
263 This->DriverBindingHandle,\r
264 Controller,\r
265 EFI_OPEN_PROTOCOL_BY_DRIVER\r
266 );\r
267\r
268 if (EFI_ERROR (Status)) {\r
269 return Status;\r
270 }\r
271\r
272 Status = gBS->LocateDevicePath (\r
273 &gEfiPciIoProtocolGuid,\r
274 &NiiDevicePath,\r
275 &Handle\r
276 );\r
277\r
278 if (EFI_ERROR (Status)) {\r
279 return Status;\r
280 }\r
281\r
282 Status = gBS->OpenProtocol (\r
283 Handle,\r
284 &gEfiPciIoProtocolGuid,\r
4cda7726 285 (VOID **) &mPciIo,\r
a15a4195 286 This->DriverBindingHandle,\r
287 Controller,\r
288 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
289 );\r
290 if (EFI_ERROR (Status)) {\r
291 return Status;\r
292 }\r
293 //\r
294 // Get the NII interface.\r
295 //\r
296 Status = gBS->OpenProtocol (\r
297 Controller,\r
298 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
299 (VOID **) &Nii,\r
300 This->DriverBindingHandle,\r
301 Controller,\r
302 EFI_OPEN_PROTOCOL_BY_DRIVER\r
303 );\r
304 if (EFI_ERROR (Status)) {\r
305 gBS->CloseProtocol (\r
306 Controller,\r
307 &gEfiDevicePathProtocolGuid,\r
308 This->DriverBindingHandle,\r
309 Controller\r
310 );\r
311 return Status;\r
312 }\r
313\r
314 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));\r
315\r
4cda7726 316 Pxe = (PXE_UNDI *) (UINTN) (Nii->ID);\r
a15a4195 317\r
4cda7726 318 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
a15a4195 319 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
320 goto NiiError;\r
321 }\r
322\r
4cda7726 323 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
a15a4195 324 //\r
325 // We can get any packets.\r
326 //\r
4cda7726 327 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
a15a4195 328 //\r
329 // We need to be able to get broadcast packets for DHCP.\r
330 // If we do not have promiscuous support, we must at least have\r
331 // broadcast support or we cannot do DHCP!\r
332 //\r
333 } else {\r
334 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
335 goto NiiError;\r
336 }\r
337 //\r
338 // OK, we like this UNDI, and we know snp is not already there on this handle\r
339 // Allocate and initialize a new simple network protocol structure.\r
340 //\r
4cda7726 341 Status = mPciIo->AllocateBuffer (\r
342 mPciIo,\r
a15a4195 343 AllocateAnyPages,\r
344 EfiBootServicesData,\r
345 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 346 &Address,\r
a15a4195 347 0\r
348 );\r
349\r
350 if (Status != EFI_SUCCESS) {\r
351 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
352 goto NiiError;\r
353 }\r
354\r
4cda7726 355 Snp = (SNP_DRIVER *) (UINTN) Address;\r
a15a4195 356\r
4cda7726 357 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
a15a4195 358\r
4cda7726 359 Snp->PciIo = mPciIo;\r
360 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
a15a4195 361\r
4cda7726 362 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
a15a4195 363\r
4cda7726 364 Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
365 Snp->Snp.Start = SnpUndi32Start;\r
366 Snp->Snp.Stop = SnpUndi32Stop;\r
367 Snp->Snp.Initialize = SnpUndi32Initialize;\r
368 Snp->Snp.Reset = SnpUndi32Reset;\r
369 Snp->Snp.Shutdown = SnpUndi32Shutdown;\r
370 Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;\r
371 Snp->Snp.StationAddress = SnpUndi32StationAddress;\r
372 Snp->Snp.Statistics = SnpUndi32Statistics;\r
373 Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;\r
374 Snp->Snp.NvData = SnpUndi32NvData;\r
375 Snp->Snp.GetStatus = SnpUndi32GetStatus;\r
376 Snp->Snp.Transmit = SnpUndi32Transmit;\r
377 Snp->Snp.Receive = SnpUndi32Receive;\r
378 Snp->Snp.WaitForPacket = NULL;\r
a15a4195 379\r
4cda7726 380 Snp->Snp.Mode = &Snp->Mode;\r
a15a4195 381\r
4cda7726 382 Snp->TxRxBufferSize = 0;\r
383 Snp->TxRxBuffer = NULL;\r
a15a4195 384\r
4cda7726 385 Snp->IfNum = Nii->IfNum;\r
a15a4195 386\r
4cda7726 387 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
388 Snp->IsSwUndi = FALSE;\r
389 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
a15a4195 390 } else {\r
4cda7726 391 Snp->IsSwUndi = TRUE;\r
a15a4195 392\r
4cda7726 393 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
394 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;\r
a15a4195 395 } else {\r
4cda7726 396 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);\r
a15a4195 397 }\r
398 }\r
399 //\r
400 // Allocate a global CPB and DB buffer for this UNDI interface.\r
401 // we do this because:\r
402 //\r
403 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
404 // within 2GB limit, create them here and map them so that when undi calls\r
405 // v2p callback to check if the physical address is < 2gb, we will pass.\r
406 //\r
407 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
408 // simpler if we use the same cpb, db variables for both old and new undi\r
409 // interfaces from all the SNP interface calls (we don't map the buffers\r
410 // for the newer undi interfaces though)\r
411 // .\r
412 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
413 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
414 //\r
4cda7726 415 Status = mPciIo->AllocateBuffer (\r
416 mPciIo,\r
a15a4195 417 AllocateAnyPages,\r
418 EfiBootServicesData,\r
419 SNP_MEM_PAGES (4096),\r
4cda7726 420 &Address,\r
a15a4195 421 0\r
422 );\r
423\r
424 if (Status != EFI_SUCCESS) {\r
425 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
426 goto Error_DeleteSNP;\r
427 }\r
428\r
4cda7726 429 Snp->Cpb = (VOID *) (UINTN) Address;\r
430 Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
a15a4195 431\r
432 //\r
4cda7726 433 // PxeStart call is going to give the callback functions to UNDI, these callback\r
a15a4195 434 // functions use the BarIndex values from the snp structure, so these must be initialized\r
4cda7726 435 // with default values before doing a PxeStart. The correct values can be obtained after\r
a15a4195 436 // getting the config information from UNDI\r
437 //\r
4cda7726 438 Snp->MemoryBarIndex = 0;\r
439 Snp->IoBarIndex = 1;\r
a15a4195 440\r
441 //\r
442 // we need the undi init information many times in this snp code, just get it\r
443 // once here and store it in the snp driver structure. to get Init Info\r
444 // from UNDI we have to start undi first.\r
445 //\r
4cda7726 446 Status = PxeStart (Snp);\r
a15a4195 447\r
448 if (Status != EFI_SUCCESS) {\r
449 goto Error_DeleteSNP;\r
450 }\r
451\r
4cda7726 452 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
453 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 454\r
4cda7726 455 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
456 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 457\r
4cda7726 458 Snp->Cdb.DBsize = sizeof Snp->InitInfo;\r
459 Snp->Cdb.DBaddr = (UINT64)(UINTN) &Snp->InitInfo;\r
a15a4195 460\r
4cda7726 461 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
462 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 463\r
4cda7726 464 Snp->Cdb.IFnum = Snp->IfNum;\r
465 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 466\r
4cda7726 467 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 468\r
4cda7726 469 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 470\r
471 //\r
472 // Save the INIT Stat Code...\r
473 //\r
4cda7726 474 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 475\r
4cda7726 476 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
477 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
478 PxeStop (Snp);\r
a15a4195 479 goto Error_DeleteSNP;\r
480 }\r
481\r
4cda7726 482 Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;\r
483 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 484\r
4cda7726 485 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
486 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 487\r
4cda7726 488 Snp->Cdb.DBsize = sizeof ConfigInfo;\r
489 Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\r
a15a4195 490\r
4cda7726 491 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
492 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 493\r
4cda7726 494 Snp->Cdb.IFnum = Snp->IfNum;\r
495 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 496\r
4cda7726 497 DEBUG ((EFI_D_NET, "\nSnp->undi.get_config_info() "));\r
a15a4195 498\r
4cda7726 499 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 500\r
4cda7726 501 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
502 DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
503 PxeStop (Snp);\r
a15a4195 504 goto Error_DeleteSNP;\r
505 }\r
506 //\r
507 // Find the correct BAR to do IO.\r
508 //\r
509 //\r
510 // Enumerate through the PCI BARs for the device to determine which one is\r
511 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
512 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
513 //\r
514 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];\r
515 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];\r
516 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {\r
517 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {\r
518 //\r
519 // This is a 64-bit memory bar, skip this and the\r
520 // next bar as well.\r
521 //\r
522 TempBar++;\r
523 }\r
524\r
525 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {\r
4cda7726 526 Snp->IoBarIndex = BarIndex;\r
a15a4195 527 break;\r
528 }\r
529\r
530 TempBar++;\r
531 }\r
532\r
533 //\r
534 // Initialize simple network protocol mode structure\r
535 //\r
4cda7726 536 Snp->Mode.State = EfiSimpleNetworkStopped;\r
537 Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;\r
538 Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;\r
539 Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;\r
540 Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;\r
541 Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;\r
542 Snp->Mode.IfType = Snp->InitInfo.IFtype;\r
543 Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;\r
544 Snp->Mode.MCastFilterCount = 0;\r
a15a4195 545\r
546 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
547 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
4cda7726 548 Snp->Mode.MediaPresentSupported = TRUE;\r
a15a4195 549 break;\r
550\r
551 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
552 default:\r
4cda7726 553 Snp->Mode.MediaPresentSupported = FALSE;\r
a15a4195 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
4cda7726 590 if (Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {\r
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
4cda7726 612 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
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
633 //\r
634 // add SNP to the undi handle\r
635 //\r
636 Status = gBS->InstallProtocolInterface (\r
637 &Controller,\r
638 &gEfiSimpleNetworkProtocolGuid,\r
639 EFI_NATIVE_INTERFACE,\r
4cda7726 640 &(Snp->Snp)\r
a15a4195 641 );\r
642\r
643 if (!EFI_ERROR (Status)) {\r
644 return Status;\r
645 }\r
646\r
4cda7726 647 Status = mPciIo->FreeBuffer (\r
648 mPciIo,\r
a15a4195 649 SNP_MEM_PAGES (4096),\r
4cda7726 650 Snp->Cpb\r
a15a4195 651 );\r
652\r
653Error_DeleteSNP:\r
654\r
4cda7726 655 mPciIo->FreeBuffer (\r
656 mPciIo,\r
a15a4195 657 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 658 Snp\r
a15a4195 659 );\r
660NiiError:\r
661 gBS->CloseProtocol (\r
662 Controller,\r
663 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
664 This->DriverBindingHandle,\r
665 Controller\r
666 );\r
667\r
668 gBS->CloseProtocol (\r
669 Controller,\r
670 &gEfiDevicePathProtocolGuid,\r
671 This->DriverBindingHandle,\r
672 Controller\r
673 );\r
674\r
675 return Status;\r
676}\r
677\r
a15a4195 678/**\r
4cda7726 679 Stop this driver on ControllerHandle. This service is called by the\r
680 EFI boot service DisconnectController(). In order to\r
681 make drivers as small as possible, there are a few calling\r
682 restrictions for this service. DisconnectController()\r
683 must follow these calling restrictions. If any other agent wishes\r
684 to call Stop() it must also follow these calling restrictions.\r
685 \r
686 @param This Protocol instance pointer.\r
687 @param ControllerHandle Handle of device to stop driver on\r
688 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
689 children is zero stop the entire bus driver.\r
690 @param ChildHandleBuffer List of Child Handles to Stop.\r
691\r
692 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
693 @retval other This driver was not removed from this device\r
a15a4195 694\r
695**/\r
696EFI_STATUS\r
697EFIAPI\r
698SimpleNetworkDriverStop (\r
699 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
700 IN EFI_HANDLE Controller,\r
701 IN UINTN NumberOfChildren,\r
702 IN EFI_HANDLE *ChildHandleBuffer\r
703 )\r
704{\r
705 EFI_STATUS Status;\r
706 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
707 SNP_DRIVER *Snp;\r
708\r
709 //\r
710 // Get our context back.\r
711 //\r
712 Status = gBS->OpenProtocol (\r
713 Controller,\r
714 &gEfiSimpleNetworkProtocolGuid,\r
715 (VOID **) &SnpProtocol,\r
716 This->DriverBindingHandle,\r
717 Controller,\r
718 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
719 );\r
720\r
721 if (EFI_ERROR (Status)) {\r
722 return EFI_UNSUPPORTED;\r
723 }\r
724\r
725 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
726\r
727 Status = gBS->UninstallProtocolInterface (\r
728 Controller,\r
729 &gEfiSimpleNetworkProtocolGuid,\r
4cda7726 730 &Snp->Snp\r
a15a4195 731 );\r
732\r
733 if (EFI_ERROR (Status)) {\r
734 return Status;\r
735 }\r
736\r
737 Status = gBS->CloseProtocol (\r
738 Controller,\r
739 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
740 This->DriverBindingHandle,\r
741 Controller\r
742 );\r
743\r
744 Status = gBS->CloseProtocol (\r
745 Controller,\r
746 &gEfiDevicePathProtocolGuid,\r
747 This->DriverBindingHandle,\r
748 Controller\r
749 );\r
750\r
4cda7726 751 PxeShutdown (Snp);\r
752 PxeStop (Snp);\r
a15a4195 753\r
4cda7726 754 mPciIo->FreeBuffer (\r
755 mPciIo,\r
a15a4195 756 SNP_MEM_PAGES (4096),\r
4cda7726 757 Snp->Cpb\r
a15a4195 758 );\r
759\r
4cda7726 760 mPciIo->FreeBuffer (\r
761 mPciIo,\r
a15a4195 762 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
763 Snp\r
764 );\r
765\r
766 return Status;\r
767}\r
768\r
4cda7726 769//\r
770// Simple Network Protocol Driver Global Variables\r
771//\r
772EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {\r
773 SimpleNetworkDriverSupported,\r
774 SimpleNetworkDriverStart,\r
775 SimpleNetworkDriverStop,\r
776 0xa,\r
777 NULL,\r
778 NULL\r
779};\r
780\r
781\r
782/**\r
783 This routine maps the given CPU address to a Device address. It creates a\r
784 an entry in the map list with the virtual and physical addresses and the\r
785 un map cookie.\r
786\r
787 @param V2p pointer to return a map list node pointer.\r
788 @param Type the direction in which the data flows from the given\r
789 virtual address device->cpu or cpu->device or both\r
790 ways.\r
791 @param VirtualAddress virtual address (or CPU address) to be mapped.\r
792 @param BufferSize size of the buffer to be mapped.\r
793\r
794 @retval EFI_SUCEESS routine has completed the mapping.\r
795 @retval EFI_INVALID_PARAMETER invalid parameter.\r
796 @retval EFI_OUT_OF_RESOURCES out of resource.\r
797 @retval other error as indicated.\r
798\r
799**/\r
800EFI_STATUS\r
801AddV2P (\r
802 IN OUT V2P **V2p,\r
803 EFI_PCI_IO_PROTOCOL_OPERATION Type,\r
804 VOID *VirtualAddress,\r
805 UINTN BufferSize\r
806 )\r
807{\r
808 EFI_STATUS Status;\r
809\r
810 if ((V2p == NULL) || (VirtualAddress == NULL) || (BufferSize == 0)) {\r
811 return EFI_INVALID_PARAMETER;\r
812 }\r
813\r
814 *V2p = AllocatePool (sizeof (V2P ));\r
815 if (*V2p != NULL) {\r
816 return EFI_OUT_OF_RESOURCES;\r
817 }\r
818\r
819 Status = mPciIo->Map (\r
820 mPciIo,\r
821 Type,\r
822 VirtualAddress,\r
823 &BufferSize,\r
824 &(*V2p)->PhysicalAddress,\r
825 &(*V2p)->Unmap\r
826 );\r
827 if (Status != EFI_SUCCESS) {\r
828 FreePool (*V2p);\r
829 return Status;\r
830 }\r
831 (*V2p)->VirtualAddress = VirtualAddress;\r
832 (*V2p)->BufferSize = BufferSize;\r
833 (*V2p)->Next = mV2p;\r
834 mV2p = *V2p;\r
835\r
836 return EFI_SUCCESS;\r
837}\r
838\r
839\r
840/**\r
841 This routine searches the linked list of mapped address nodes (for undi3.0\r
842 interface) to find the node that corresponds to the given virtual address and\r
843 returns a pointer to that node.\r
844\r
845 @param V2p pointer to return a map list node pointer.\r
846 @param VirtualAddr virtual address (or CPU address) to be searched in\r
847 the map list\r
848\r
849 @retval EFI_SUCEESS if a match found!\r
850 @retval Other match not found\r
851\r
852**/\r
853EFI_STATUS\r
854FindV2p (\r
855 V2P **V2p,\r
856 VOID *VirtualAddr\r
857 )\r
858{\r
859 V2P *Ptr;\r
860\r
861 if (V2p == NULL || VirtualAddr == NULL) {\r
862 return EFI_INVALID_PARAMETER;\r
863 }\r
864\r
865 for (Ptr = mV2p; Ptr != NULL; Ptr = Ptr->Next) {\r
866 if (Ptr->VirtualAddress == VirtualAddr) {\r
867 *V2p = Ptr;\r
868 return EFI_SUCCESS;\r
869 }\r
870 }\r
871\r
872 return EFI_NOT_FOUND;\r
873}\r
874\r
875\r
876/**\r
877 This routine unmaps the given virtual address and frees the memory allocated\r
878 for the map list node corresponding to that address.\r
879\r
880 @param VirtualAddress virtual address (or CPU address) to be unmapped\r
881\r
882 @retval EFI_SUCEESS if successfully unmapped\r
883 @retval Other as indicated by the error\r
884\r
885**/\r
886EFI_STATUS\r
887DelV2p (\r
888 VOID *VirtualAddress\r
889 )\r
890{\r
891 V2P *Current;\r
892 V2P *Next;\r
893 EFI_STATUS Status;\r
894\r
895 if (VirtualAddress == NULL) {\r
896 return EFI_INVALID_PARAMETER;\r
897 }\r
898\r
899 if (mV2p == NULL) {\r
900 return EFI_NOT_FOUND;\r
901 }\r
902 //\r
903 // Is our node at the head of the list??\r
904 //\r
905 if ((Current = mV2p)->VirtualAddress == VirtualAddress) {\r
906 mV2p = mV2p->Next;\r
907\r
908 Status = mPciIo->Unmap (mPciIo, Current->Unmap);\r
909\r
910 FreePool (Current);\r
911\r
912 if (EFI_ERROR (Status)) {\r
913 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
914 }\r
915 return Status;\r
916 }\r
917\r
918 for (; Current->Next != NULL; Current = Next) {\r
919 if ((Next = Current->Next)->VirtualAddress == VirtualAddress) {\r
920 Current->Next = Next->Next;\r
921 Status = mPciIo->Unmap (mPciIo, Next->Unmap);\r
922 FreePool (Next);\r
923\r
924 if (EFI_ERROR (Status)) {\r
925 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
926 }\r
927 return Status;\r
928 }\r
929 }\r
930\r
931 return EFI_NOT_FOUND;\r
932}\r
a15a4195 933\r
934/**\r
4cda7726 935 The SNP driver entry point.\r
a15a4195 936\r
4cda7726 937 @param ImageHandle The driver image handle.\r
938 @param SystemTable The system table.\r
a15a4195 939\r
4cda7726 940 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
941 loaded it's ROM, and installed a notify event for\r
942 the Network Indentifier Interface Protocol\r
943 successfully.\r
944 @retval Other Return value from HandleProtocol for\r
945 DeviceIoProtocol or LoadedImageProtocol\r
a15a4195 946\r
947**/\r
948EFI_STATUS\r
949EFIAPI\r
950InitializeSnpNiiDriver (\r
951 IN EFI_HANDLE ImageHandle,\r
952 IN EFI_SYSTEM_TABLE *SystemTable\r
953 )\r
954{\r
955 return EfiLibInstallDriverBindingComponentName2 (\r
956 ImageHandle,\r
957 SystemTable,\r
958 &mSimpleNetworkDriverBinding,\r
959 NULL,\r
960 &gSimpleNetworkComponentName,\r
961 &gSimpleNetworkComponentName2\r
962 );\r
963}\r