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