]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
Roll back the DEBUG mask change which cause SerialIo read_conf test item failure.
[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
f3816027 27 Send command to UNDI. It does nothing currently.\r
4cda7726 28 \r
29 @param Cdb command to be sent to UNDI.\r
f3816027 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
a15a4195 35**/\r
36EFI_STATUS\r
4cda7726 37IssueHwUndiCommand (\r
38 UINT64 Cdb\r
a15a4195 39 )\r
40{\r
4cda7726 41 DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));\r
a15a4195 42\r
4cda7726 43 if (Cdb == 0) {\r
a15a4195 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
4cda7726 57 @param Buffer Pointer to buffer.\r
58 @param Length Length of buffer in bytes.\r
a15a4195 59\r
f3816027 60 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len \r
61 is zero.\r
a15a4195 62\r
63**/\r
a15a4195 64UINT8\r
4cda7726 65Calc8BitCksum (\r
66 VOID *Buffer,\r
67 UINTN Length\r
a15a4195 68 )\r
69{\r
4cda7726 70 UINT8 *Ptr;\r
71 UINT8 Cksum;\r
a15a4195 72\r
4cda7726 73 Ptr = Buffer;\r
74 Cksum = 0;\r
a15a4195 75\r
4cda7726 76 if (Ptr == NULL || Length == 0) {\r
a15a4195 77 return 0;\r
78 }\r
79\r
4cda7726 80 while (Length-- != 0) {\r
81 Cksum = (UINT8) (Cksum + *Ptr++);\r
a15a4195 82 }\r
83\r
4cda7726 84 return Cksum;\r
a15a4195 85}\r
86\r
a15a4195 87/**\r
4cda7726 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
f3816027 96 @param ControllerHandle Handle of device to test.\r
4cda7726 97 @param RemainingDevicePath Optional parameter use to pick a specific child\r
98 device to start.\r
99\r
f3816027 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
a15a4195 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
4cda7726 115 PXE_UNDI *Pxe;\r
a15a4195 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
0e549d5b 140 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
a15a4195 141 }\r
142 return Status;\r
143 }\r
144\r
0e549d5b 145 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
a15a4195 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
9cff2f8d 158 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
a15a4195 159 Status = EFI_UNSUPPORTED;\r
160 goto Done;\r
161 }\r
162\r
4cda7726 163 Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);\r
a15a4195 164\r
165 //\r
166 // Verify !PXE revisions.\r
167 //\r
4cda7726 168 if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
9cff2f8d 169 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));\r
a15a4195 170 Status = EFI_UNSUPPORTED;\r
171 goto Done;\r
172 }\r
173\r
4cda7726 174 if (Pxe->hw.Rev < PXE_ROMID_REV) {\r
9cff2f8d 175 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));\r
a15a4195 176 Status = EFI_UNSUPPORTED;\r
177 goto Done;\r
178 }\r
179\r
4cda7726 180 if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
a15a4195 181\r
9cff2f8d 182 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));\r
a15a4195 183 Status = EFI_UNSUPPORTED;\r
184 goto Done;\r
185\r
4cda7726 186 } else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) {\r
9cff2f8d 187 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));\r
a15a4195 188 Status = EFI_UNSUPPORTED;\r
189 goto Done;\r
190 }\r
191 //\r
192 // Do S/W UNDI specific checks.\r
193 //\r
4cda7726 194 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
195 if (Pxe->sw.EntryPoint < Pxe->sw.Len) {\r
9cff2f8d 196 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));\r
a15a4195 197 Status = EFI_UNSUPPORTED;\r
198 goto Done;\r
199 }\r
200\r
4cda7726 201 if (Pxe->sw.BusCnt == 0) {\r
9cff2f8d 202 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));\r
a15a4195 203 Status = EFI_UNSUPPORTED;\r
204 goto Done;\r
205 }\r
206 }\r
207\r
208 Status = EFI_SUCCESS;\r
0e549d5b 209 DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));\r
a15a4195 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
a15a4195 222/**\r
4cda7726 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
a15a4195 229\r
230 @param This Protocol instance pointer.\r
4cda7726 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
a15a4195 234\r
4cda7726 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
a15a4195 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
4cda7726 251 PXE_UNDI *Pxe;\r
252 SNP_DRIVER *Snp;\r
253 VOID *Address;\r
a15a4195 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
9cff2f8d 261 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
a15a4195 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
4cda7726 289 (VOID **) &mPciIo,\r
a15a4195 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
4cda7726 320 Pxe = (PXE_UNDI *) (UINTN) (Nii->ID);\r
a15a4195 321\r
4cda7726 322 if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {\r
9cff2f8d 323 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
a15a4195 324 goto NiiError;\r
325 }\r
326\r
4cda7726 327 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
a15a4195 328 //\r
329 // We can get any packets.\r
330 //\r
4cda7726 331 } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
a15a4195 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
9cff2f8d 338 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
a15a4195 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
4cda7726 345 Status = mPciIo->AllocateBuffer (\r
346 mPciIo,\r
a15a4195 347 AllocateAnyPages,\r
348 EfiBootServicesData,\r
349 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 350 &Address,\r
a15a4195 351 0\r
352 );\r
353\r
354 if (Status != EFI_SUCCESS) {\r
9cff2f8d 355 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
a15a4195 356 goto NiiError;\r
357 }\r
358\r
4cda7726 359 Snp = (SNP_DRIVER *) (UINTN) Address;\r
a15a4195 360\r
4cda7726 361 ZeroMem (Snp, sizeof (SNP_DRIVER));\r
a15a4195 362\r
4cda7726 363 Snp->PciIo = mPciIo;\r
364 Snp->Signature = SNP_DRIVER_SIGNATURE;\r
a15a4195 365\r
4cda7726 366 EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);\r
a15a4195 367\r
4cda7726 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
a15a4195 383\r
4cda7726 384 Snp->Snp.Mode = &Snp->Mode;\r
a15a4195 385\r
4cda7726 386 Snp->TxRxBufferSize = 0;\r
387 Snp->TxRxBuffer = NULL;\r
a15a4195 388\r
4cda7726 389 Snp->IfNum = Nii->IfNum;\r
a15a4195 390\r
4cda7726 391 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
392 Snp->IsSwUndi = FALSE;\r
393 Snp->IssueUndi32Command = &IssueHwUndiCommand;\r
a15a4195 394 } else {\r
4cda7726 395 Snp->IsSwUndi = TRUE;\r
a15a4195 396\r
4cda7726 397 if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
398 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;\r
a15a4195 399 } else {\r
4cda7726 400 Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);\r
a15a4195 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
4cda7726 419 Status = mPciIo->AllocateBuffer (\r
420 mPciIo,\r
a15a4195 421 AllocateAnyPages,\r
422 EfiBootServicesData,\r
423 SNP_MEM_PAGES (4096),\r
4cda7726 424 &Address,\r
a15a4195 425 0\r
426 );\r
427\r
428 if (Status != EFI_SUCCESS) {\r
9cff2f8d 429 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
a15a4195 430 goto Error_DeleteSNP;\r
431 }\r
432\r
4cda7726 433 Snp->Cpb = (VOID *) (UINTN) Address;\r
434 Snp->Db = (VOID *) ((UINTN) Address + 2048);\r
a15a4195 435\r
436 //\r
4cda7726 437 // PxeStart call is going to give the callback functions to UNDI, these callback\r
a15a4195 438 // functions use the BarIndex values from the snp structure, so these must be initialized\r
4cda7726 439 // with default values before doing a PxeStart. The correct values can be obtained after\r
a15a4195 440 // getting the config information from UNDI\r
441 //\r
4cda7726 442 Snp->MemoryBarIndex = 0;\r
443 Snp->IoBarIndex = 1;\r
a15a4195 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
4cda7726 450 Status = PxeStart (Snp);\r
a15a4195 451\r
452 if (Status != EFI_SUCCESS) {\r
453 goto Error_DeleteSNP;\r
454 }\r
455\r
4cda7726 456 Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
457 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
a15a4195 458\r
4cda7726 459 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
460 Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
a15a4195 461\r
4cda7726 462 Snp->Cdb.DBsize = sizeof Snp->InitInfo;\r
463 Snp->Cdb.DBaddr = (UINT64)(UINTN) &Snp->InitInfo;\r
a15a4195 464\r
4cda7726 465 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
466 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
a15a4195 467\r
4cda7726 468 Snp->Cdb.IFnum = Snp->IfNum;\r
469 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a15a4195 470\r
9cff2f8d 471 DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));\r
a15a4195 472\r
4cda7726 473 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 474\r
475 //\r
476 // Save the INIT Stat Code...\r
477 //\r
4cda7726 478 InitStatFlags = Snp->Cdb.StatFlags;\r
a15a4195 479\r
4cda7726 480 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 481 DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 482 PxeStop (Snp);\r
a15a4195 483 goto Error_DeleteSNP;\r
484 }\r
485\r
4cda7726 486 Snp->Cdb.OpCode = PXE_OPCODE_GET_CONFIG_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
4cda7726 492 Snp->Cdb.DBsize = sizeof ConfigInfo;\r
493 Snp->Cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\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_config_info() "));\r
a15a4195 502\r
4cda7726 503 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
a15a4195 504\r
4cda7726 505 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
9cff2f8d 506 DEBUG ((EFI_D_NET, "\nSnp->undi.config_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));\r
4cda7726 507 PxeStop (Snp);\r
a15a4195 508 goto Error_DeleteSNP;\r
509 }\r
510 //\r
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
4cda7726 530 Snp->IoBarIndex = BarIndex;\r
a15a4195 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
4cda7726 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
a15a4195 549\r
550 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
551 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
4cda7726 552 Snp->Mode.MediaPresentSupported = TRUE;\r
a15a4195 553 break;\r
554\r
555 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
556 default:\r
4cda7726 557 Snp->Mode.MediaPresentSupported = FALSE;\r
a15a4195 558 }\r
559\r
4cda7726 560 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
561 Snp->Mode.MacAddressChangeable = TRUE;\r
a15a4195 562 } else {\r
4cda7726 563 Snp->Mode.MacAddressChangeable = FALSE;\r
a15a4195 564 }\r
565\r
4cda7726 566 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
567 Snp->Mode.MultipleTxSupported = TRUE;\r
a15a4195 568 } else {\r
4cda7726 569 Snp->Mode.MultipleTxSupported = FALSE;\r
a15a4195 570 }\r
571\r
4cda7726 572 Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
a15a4195 573\r
4cda7726 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
a15a4195 576\r
577 }\r
578\r
4cda7726 579 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
580 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
a15a4195 581\r
582 }\r
583\r
4cda7726 584 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
585 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
a15a4195 586\r
587 }\r
588\r
4cda7726 589 if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
590 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
a15a4195 591\r
592 }\r
593\r
4cda7726 594 if (Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {\r
595 Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
a15a4195 596\r
597 }\r
598\r
4cda7726 599 Snp->Mode.ReceiveFilterSetting = 0;\r
a15a4195 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
4cda7726 605 Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;\r
606 Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
a15a4195 607\r
4cda7726 608 if (EFI_ERROR (Status)) {\r
609 PxeStop (Snp);\r
a15a4195 610 goto Error_DeleteSNP;\r
611 }\r
612\r
4cda7726 613 Status = PxeGetStnAddr (Snp);\r
a15a4195 614\r
615 if (Status != EFI_SUCCESS) {\r
f3816027 616 DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));\r
4cda7726 617 PxeShutdown (Snp);\r
618 PxeStop (Snp);\r
a15a4195 619 goto Error_DeleteSNP;\r
620 }\r
621\r
4cda7726 622 Snp->Mode.MediaPresent = FALSE;\r
a15a4195 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
4cda7726 628 // The UNDI layer will be started when upper layers call Snp->start.\r
a15a4195 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
4cda7726 634 PxeShutdown (Snp);\r
635 PxeStop (Snp);\r
a15a4195 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
4cda7726 644 &(Snp->Snp)\r
a15a4195 645 );\r
646\r
647 if (!EFI_ERROR (Status)) {\r
648 return Status;\r
649 }\r
650\r
4cda7726 651 Status = mPciIo->FreeBuffer (\r
652 mPciIo,\r
a15a4195 653 SNP_MEM_PAGES (4096),\r
4cda7726 654 Snp->Cpb\r
a15a4195 655 );\r
656\r
657Error_DeleteSNP:\r
658\r
4cda7726 659 mPciIo->FreeBuffer (\r
660 mPciIo,\r
a15a4195 661 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
4cda7726 662 Snp\r
a15a4195 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
a15a4195 682/**\r
4cda7726 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
a15a4195 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
4cda7726 734 &Snp->Snp\r
a15a4195 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
4cda7726 755 PxeShutdown (Snp);\r
756 PxeStop (Snp);\r
a15a4195 757\r
4cda7726 758 mPciIo->FreeBuffer (\r
759 mPciIo,\r
a15a4195 760 SNP_MEM_PAGES (4096),\r
4cda7726 761 Snp->Cpb\r
a15a4195 762 );\r
763\r
4cda7726 764 mPciIo->FreeBuffer (\r
765 mPciIo,\r
a15a4195 766 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
767 Snp\r
768 );\r
769\r
770 return Status;\r
771}\r
772\r
4cda7726 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
f3816027 818 *V2p = AllocatePool (sizeof (V2P));\r
4cda7726 819 if (*V2p != NULL) {\r
820 return EFI_OUT_OF_RESOURCES;\r
821 }\r
822\r
823 Status = mPciIo->Map (\r
f3816027 824 mPciIo,\r
825 Type,\r
826 VirtualAddress,\r
827 &BufferSize,\r
828 &(*V2p)->PhysicalAddress,\r
829 &(*V2p)->Unmap\r
830 );\r
4cda7726 831 if (Status != EFI_SUCCESS) {\r
832 FreePool (*V2p);\r
833 return Status;\r
834 }\r
835 (*V2p)->VirtualAddress = VirtualAddress;\r
f3816027 836 (*V2p)->BufferSize = BufferSize;\r
837 (*V2p)->Next = mV2p;\r
838 mV2p = *V2p;\r
4cda7726 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
f3816027 853 @retval EFI_SUCEESS A match was found.\r
854 @retval Other A match cannot be found.\r
4cda7726 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
f3816027 881 Unmap the given virtual address and free the memory allocated for the map list\r
882 node corresponding to that address.\r
4cda7726 883\r
f3816027 884 @param VirtualAddress virtual address (or CPU address) to be unmapped.\r
4cda7726 885\r
f3816027 886 @retval EFI_SUCEESS Successfully unmapped.\r
887 @retval Other Other errors as indicated.\r
4cda7726 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
a15a4195 937\r
938/**\r
4cda7726 939 The SNP driver entry point.\r
a15a4195 940\r
4cda7726 941 @param ImageHandle The driver image handle.\r
942 @param SystemTable The system table.\r
a15a4195 943\r
4cda7726 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
a15a4195 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