]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UndiRuntimeDxe/Init.c
Boolean values and variable type BOOLEAN should not use explicit comparisons to TRUE...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UndiRuntimeDxe / Init.c
CommitLineData
ffa5008a 1/** @file\r
2 Initialization functions for EFI UNDI32 driver.\r
40834173 3\r
7c24ae36 4Copyright (c) 2006 - 2008, Intel Corporation\r
68246fa8 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies 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
40834173 12\r
ffa5008a 13**/\r
40834173 14\r
15#include "Undi32.h"\r
40834173 16//\r
17// Global Variables\r
18//\r
40834173 19\r
41057d77 20PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry\r
21UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
68246fa8 22NII_TABLE *UndiDataPointer = NULL;\r
40834173 23\r
40834173 24\r
ffa5008a 25/**\r
40834173 26 When address mapping changes to virtual this should make the appropriate\r
27 address conversions.\r
28\r
40834173 29 (Standard Event handler)\r
30\r
ffa5008a 31 @return None\r
40834173 32\r
ffa5008a 33**/\r
40834173 34// TODO: Context - add argument and description to function comment\r
ffa5008a 35VOID\r
36EFIAPI\r
37UndiNotifyVirtual (\r
38 EFI_EVENT Event,\r
39 VOID *Context\r
40 )\r
40834173 41{\r
42 UINT16 Index;\r
43 VOID *Pxe31Pointer;\r
44\r
45 if (pxe_31 != NULL) {\r
46 Pxe31Pointer = (VOID *) pxe_31;\r
47\r
48 EfiConvertPointer (\r
ffa5008a 49 EFI_OPTIONAL_PTR,\r
40834173 50 (VOID **) &Pxe31Pointer\r
51 );\r
52\r
53 //\r
54 // UNDI32DeviceList is an array of pointers\r
55 //\r
56 for (Index = 0; Index < pxe_31->IFcnt; Index++) {\r
57 UNDI32DeviceList[Index]->NIIProtocol_31.ID = (UINT64) (UINTN) Pxe31Pointer;\r
58 EfiConvertPointer (\r
ffa5008a 59 EFI_OPTIONAL_PTR,\r
40834173 60 (VOID **) &(UNDI32DeviceList[Index])\r
61 );\r
62 }\r
63\r
64 EfiConvertPointer (\r
ffa5008a 65 EFI_OPTIONAL_PTR,\r
40834173 66 (VOID **) &(pxe_31->EntryPoint)\r
67 );\r
68 pxe_31 = Pxe31Pointer;\r
69 }\r
70\r
71 for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {\r
72 EfiConvertPointer (\r
ffa5008a 73 EFI_OPTIONAL_PTR,\r
40834173 74 (VOID **) &api_table[Index].api_ptr\r
75 );\r
76 }\r
77}\r
78\r
40834173 79\r
ffa5008a 80/**\r
68246fa8 81 When EFI is shuting down the boot services, we need to install a\r
40834173 82 configuration table for UNDI to work at runtime!\r
83\r
40834173 84 (Standard Event handler)\r
85\r
ffa5008a 86 @return None\r
40834173 87\r
ffa5008a 88**/\r
40834173 89// TODO: Context - add argument and description to function comment\r
ffa5008a 90VOID\r
91EFIAPI\r
92UndiNotifyExitBs (\r
93 EFI_EVENT Event,\r
94 VOID *Context\r
95 )\r
40834173 96{\r
97 InstallConfigTable ();\r
98}\r
99//\r
100// UNDI Class Driver Global Variables\r
101//\r
102EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {\r
103 UndiDriverSupported,\r
104 UndiDriverStart,\r
105 UndiDriverStop,\r
106 0xa,\r
107 NULL,\r
108 NULL\r
109};\r
110\r
111\r
40834173 112\r
ffa5008a 113/**\r
40834173 114 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
115 than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,\r
116 and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||\r
117 ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||\r
118 ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.\r
119\r
ffa5008a 120 @param This Protocol instance pointer.\r
121 @param Controller Handle of device to test.\r
122 @param RemainingDevicePath Not used.\r
68246fa8 123\r
ffa5008a 124 @retval EFI_SUCCESS This driver supports this device.\r
125 @retval other This driver does not support this device.\r
40834173 126\r
ffa5008a 127**/\r
128EFI_STATUS\r
129EFIAPI\r
130UndiDriverSupported (\r
131 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
132 IN EFI_HANDLE Controller,\r
133 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
134 )\r
40834173 135{\r
136 EFI_STATUS Status;\r
137 EFI_PCI_IO_PROTOCOL *PciIo;\r
138 PCI_TYPE00 Pci;\r
139\r
140 Status = gBS->OpenProtocol (\r
141 Controller,\r
142 &gEfiDevicePathProtocolGuid,\r
143 NULL,\r
144 This->DriverBindingHandle,\r
145 Controller,\r
146 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
147 );\r
148 if (EFI_ERROR (Status)) {\r
149 return Status;\r
150 }\r
151\r
152 Status = gBS->OpenProtocol (\r
153 Controller,\r
154 &gEfiPciIoProtocolGuid,\r
155 (VOID **) &PciIo,\r
156 This->DriverBindingHandle,\r
157 Controller,\r
158 EFI_OPEN_PROTOCOL_BY_DRIVER\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 return Status;\r
162 }\r
163\r
164 Status = PciIo->Pci.Read (\r
165 PciIo,\r
166 EfiPciIoWidthUint8,\r
167 0,\r
168 sizeof (PCI_CONFIG_HEADER),\r
169 &Pci\r
170 );\r
171\r
172 if (!EFI_ERROR (Status)) {\r
173 Status = EFI_UNSUPPORTED;\r
174\r
175 if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {\r
176 switch (Pci.Hdr.DeviceId) {\r
177 case D100_DEVICE_ID:\r
178 case D102_DEVICE_ID:\r
179 case ICH3_DEVICE_ID_1:\r
180 case ICH3_DEVICE_ID_2:\r
181 case ICH3_DEVICE_ID_3:\r
182 case ICH3_DEVICE_ID_4:\r
183 case ICH3_DEVICE_ID_5:\r
184 case ICH3_DEVICE_ID_6:\r
185 case ICH3_DEVICE_ID_7:\r
186 case ICH3_DEVICE_ID_8:\r
187 case 0x1039:\r
188 case 0x103A:\r
189 case 0x103B:\r
190 case 0x103C:\r
191 case 0x103D:\r
192 case 0x103E:\r
193 case 0x1050:\r
194 case 0x1051:\r
195 case 0x1052:\r
196 case 0x1053:\r
197 case 0x1054:\r
198 case 0x1055:\r
199 case 0x1056:\r
200 case 0x1057:\r
201 case 0x1059:\r
202 case 0x1064:\r
203 Status = EFI_SUCCESS;\r
204 }\r
205 }\r
206 }\r
207\r
208 gBS->CloseProtocol (\r
209 Controller,\r
210 &gEfiPciIoProtocolGuid,\r
211 This->DriverBindingHandle,\r
212 Controller\r
213 );\r
214\r
215 return Status;\r
216}\r
217\r
40834173 218\r
ffa5008a 219/**\r
40834173 220 Start this driver on Controller by opening PciIo and DevicePath protocol.\r
221 Initialize PXE structures, create a copy of the Controller Device Path with the\r
222 NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol\r
223 on the newly created Device Path.\r
224\r
ffa5008a 225 @param This Protocol instance pointer.\r
226 @param Controller Handle of device to work with.\r
227 @param RemainingDevicePath Not used, always produce all possible children.\r
68246fa8 228\r
ffa5008a 229 @retval EFI_SUCCESS This driver is added to Controller.\r
230 @retval other This driver does not support this device.\r
40834173 231\r
ffa5008a 232**/\r
233EFI_STATUS\r
234EFIAPI\r
235UndiDriverStart (\r
236 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
237 IN EFI_HANDLE Controller,\r
238 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
239 )\r
40834173 240{\r
241 EFI_STATUS Status;\r
242 EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;\r
243 PCI_CONFIG_HEADER *CfgHdr;\r
244 UNDI32_DEV *UNDI32Device;\r
245 UINT16 NewCommand;\r
246 UINT8 *TmpPxePointer;\r
247 EFI_PCI_IO_PROTOCOL *PciIoFncs;\r
68246fa8 248 UINTN Len;\r
96f6af14 249 UINT64 Supports;\r
6a6d955c 250 BOOLEAN PciAttributesSaved;\r
40834173 251\r
252 Status = gBS->OpenProtocol (\r
253 Controller,\r
254 &gEfiPciIoProtocolGuid,\r
255 (VOID **) &PciIoFncs,\r
256 This->DriverBindingHandle,\r
257 Controller,\r
258 EFI_OPEN_PROTOCOL_BY_DRIVER\r
259 );\r
260\r
261 if (EFI_ERROR (Status)) {\r
262 return Status;\r
263 }\r
264\r
265 Status = gBS->OpenProtocol (\r
266 Controller,\r
267 &gEfiDevicePathProtocolGuid,\r
268 (VOID **) &UndiDevicePath,\r
269 This->DriverBindingHandle,\r
270 Controller,\r
271 EFI_OPEN_PROTOCOL_BY_DRIVER\r
272 );\r
273\r
274 if (EFI_ERROR (Status)) {\r
275 gBS->CloseProtocol (\r
276 Controller,\r
277 &gEfiPciIoProtocolGuid,\r
278 This->DriverBindingHandle,\r
279 Controller\r
280 );\r
281\r
282 return Status;\r
283 }\r
284\r
6a6d955c 285 PciAttributesSaved = FALSE;\r
286\r
40834173 287 Status = gBS->AllocatePool (\r
288 EfiRuntimeServicesData,\r
289 sizeof (UNDI32_DEV),\r
290 (VOID **) &UNDI32Device\r
291 );\r
292\r
293 if (EFI_ERROR (Status)) {\r
294 goto UndiError;\r
295 }\r
296\r
297 ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));\r
298\r
68246fa8 299 //\r
300 // Get original PCI attributes\r
301 //\r
302 Status = PciIoFncs->Attributes (\r
303 PciIoFncs,\r
304 EfiPciIoAttributeOperationGet,\r
305 0,\r
306 &UNDI32Device->NicInfo.OriginalPciAttributes\r
307 );\r
308\r
309 if (EFI_ERROR (Status)) {\r
6a6d955c 310 goto UndiErrorDeleteDevice;\r
68246fa8 311 }\r
6a6d955c 312 PciAttributesSaved = TRUE;\r
68246fa8 313\r
40834173 314 //\r
315 // allocate and initialize both (old and new) the !pxe structures here,\r
316 // there should only be one copy of each of these structure for any number\r
317 // of NICs this undi supports. Also, these structures need to be on a\r
318 // paragraph boundary as per the spec. so, while allocating space for these,\r
319 // make sure that there is space for 2 !pxe structures (old and new) and a\r
320 // 32 bytes padding for alignment adjustment (in case)\r
321 //\r
322 TmpPxePointer = NULL;\r
323 if (pxe_31 == NULL) {\r
324 Status = gBS->AllocatePool (\r
325 EfiRuntimeServicesData,\r
326 (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),\r
327 (VOID **) &TmpPxePointer\r
328 );\r
329\r
330 if (EFI_ERROR (Status)) {\r
331 goto UndiErrorDeleteDevice;\r
332 }\r
333\r
334 ZeroMem (\r
335 TmpPxePointer,\r
336 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32\r
337 );\r
338 //\r
339 // check for paragraph alignment here, assuming that the pointer is\r
340 // already 8 byte aligned.\r
341 //\r
342 if (((UINTN) TmpPxePointer & 0x0F) != 0) {\r
343 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));\r
344 } else {\r
345 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;\r
346 }\r
40834173 347\r
41057d77 348 PxeStructInit (pxe_31);\r
40834173 349 }\r
350\r
40834173 351 UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31);\r
352\r
353 Status = PciIoFncs->Attributes (\r
354 PciIoFncs,\r
96f6af14
LG
355 EfiPciIoAttributeOperationSupported,\r
356 0,\r
357 &Supports\r
40834173 358 );\r
96f6af14
LG
359 if (!EFI_ERROR (Status)) {\r
360 Supports &= EFI_PCI_DEVICE_ENABLE;\r
361 Status = PciIoFncs->Attributes (\r
362 PciIoFncs,\r
363 EfiPciIoAttributeOperationEnable,\r
364 Supports,\r
365 NULL\r
366 );\r
367 }\r
40834173 368 //\r
369 // Read all the registers from device's PCI Configuration space\r
370 //\r
371 Status = PciIoFncs->Pci.Read (\r
372 PciIoFncs,\r
373 EfiPciIoWidthUint32,\r
374 0,\r
375 MAX_PCI_CONFIG_LEN,\r
376 &UNDI32Device->NicInfo.Config\r
377 );\r
378\r
379 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);\r
380\r
381 //\r
382 // make sure that this device is a PCI bus master\r
383 //\r
384\r
385 NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);\r
386 if (CfgHdr->Command != NewCommand) {\r
387 PciIoFncs->Pci.Write (\r
388 PciIoFncs,\r
389 EfiPciIoWidthUint16,\r
390 PCI_COMMAND,\r
391 1,\r
392 &NewCommand\r
393 );\r
394 CfgHdr->Command = NewCommand;\r
395 }\r
396\r
397 //\r
398 // make sure that the latency timer is at least 32\r
399 //\r
400 if (CfgHdr->LatencyTimer < 32) {\r
401 CfgHdr->LatencyTimer = 32;\r
402 PciIoFncs->Pci.Write (\r
403 PciIoFncs,\r
404 EfiPciIoWidthUint8,\r
405 PCI_LATENCY_TIMER,\r
406 1,\r
407 &CfgHdr->LatencyTimer\r
408 );\r
409 }\r
410 //\r
411 // the IfNum index for the current interface will be the total number\r
412 // of interfaces initialized so far\r
413 //\r
40834173 414 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt;\r
415\r
40834173 416 PxeUpdate (&UNDI32Device->NicInfo, pxe_31);\r
417\r
41057d77 418 UNDI32Device->NicInfo.Io_Function = PciIoFncs;\r
419 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;\r
420 UNDI32Device->Undi32BaseDevPath = UndiDevicePath;\r
40834173 421\r
422 Status = AppendMac2DevPath (\r
423 &UNDI32Device->Undi32DevPath,\r
424 UNDI32Device->Undi32BaseDevPath,\r
425 &UNDI32Device->NicInfo\r
426 );\r
427\r
428 if (Status != 0) {\r
429 goto UndiErrorDeletePxe;\r
430 }\r
431\r
432 UNDI32Device->Signature = UNDI_DEV_SIGNATURE;\r
433\r
40834173 434 UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;\r
435 UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;\r
436 UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;\r
437 UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;\r
438 UNDI32Device->NIIProtocol_31.ImageSize = 0;\r
439 UNDI32Device->NIIProtocol_31.ImageAddr = 0;\r
440 UNDI32Device->NIIProtocol_31.Ipv6Supported = FALSE;\r
441\r
442 UNDI32Device->NIIProtocol_31.StringId[0] = 'U';\r
443 UNDI32Device->NIIProtocol_31.StringId[1] = 'N';\r
444 UNDI32Device->NIIProtocol_31.StringId[2] = 'D';\r
445 UNDI32Device->NIIProtocol_31.StringId[3] = 'I';\r
446\r
447 UNDI32Device->DeviceHandle = NULL;\r
448\r
449 //\r
450 // install both the 3.0 and 3.1 NII protocols.\r
451 //\r
452 Status = gBS->InstallMultipleProtocolInterfaces (\r
453 &UNDI32Device->DeviceHandle,\r
454 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
455 &UNDI32Device->NIIProtocol_31,\r
40834173 456 &gEfiDevicePathProtocolGuid,\r
457 UNDI32Device->Undi32DevPath,\r
458 NULL\r
459 );\r
460\r
461 if (EFI_ERROR (Status)) {\r
462 goto UndiErrorDeleteDevicePath;\r
463 }\r
464\r
465 //\r
68246fa8 466 // if the table exists, free it and alloc again, or alloc it directly\r
40834173 467 //\r
68246fa8 468 if (UndiDataPointer != NULL) {\r
ffa5008a 469 Status = gBS->FreePool(UndiDataPointer);\r
40834173 470 }\r
471 if (EFI_ERROR (Status)) {\r
472 goto UndiErrorDeleteDevicePath;\r
473 }\r
474\r
68246fa8 475 Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UndiDataPointer);\r
476 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);\r
40834173 477\r
478 if (EFI_ERROR (Status)) {\r
479 goto UndiErrorAllocDataPointer;\r
480 }\r
68246fa8 481\r
40834173 482 //\r
483 // Open For Child Device\r
484 //\r
485 Status = gBS->OpenProtocol (\r
486 Controller,\r
487 &gEfiPciIoProtocolGuid,\r
488 (VOID **) &PciIoFncs,\r
489 This->DriverBindingHandle,\r
490 UNDI32Device->DeviceHandle,\r
491 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
492 );\r
493\r
494 return EFI_SUCCESS;\r
495UndiErrorAllocDataPointer:\r
496 gBS->UninstallMultipleProtocolInterfaces (\r
497 &UNDI32Device->DeviceHandle,\r
498 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
499 &UNDI32Device->NIIProtocol_31,\r
40834173 500 &gEfiDevicePathProtocolGuid,\r
501 UNDI32Device->Undi32DevPath,\r
502 NULL\r
503 );\r
504\r
505UndiErrorDeleteDevicePath:\r
41057d77 506 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;\r
40834173 507 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
508\r
509UndiErrorDeletePxe:\r
40834173 510 PxeUpdate (NULL, pxe_31);\r
511 if (TmpPxePointer != NULL) {\r
512 gBS->FreePool (TmpPxePointer);\r
513\r
514 }\r
515\r
516UndiErrorDeleteDevice:\r
7c24ae36 517 if (PciAttributesSaved) {\r
6a6d955c 518 //\r
519 // Restore original PCI attributes\r
520 //\r
521 PciIoFncs->Attributes (\r
522 PciIoFncs,\r
523 EfiPciIoAttributeOperationSet,\r
524 UNDI32Device->NicInfo.OriginalPciAttributes,\r
525 NULL\r
526 );\r
527 }\r
68246fa8 528\r
40834173 529 gBS->FreePool (UNDI32Device);\r
530\r
531UndiError:\r
532 gBS->CloseProtocol (\r
533 Controller,\r
534 &gEfiDevicePathProtocolGuid,\r
535 This->DriverBindingHandle,\r
536 Controller\r
537 );\r
538\r
539 gBS->CloseProtocol (\r
540 Controller,\r
541 &gEfiPciIoProtocolGuid,\r
542 This->DriverBindingHandle,\r
543 Controller\r
544 );\r
545\r
546 return Status;\r
547}\r
548\r
ffa5008a 549\r
550/**\r
551 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
552 closing the DevicePath and PciIo protocols on Controller.\r
553\r
554 @param This Protocol instance pointer.\r
555 @param Controller Handle of device to stop driver on.\r
556 @param NumberOfChildren How many children need to be stopped.\r
557 @param ChildHandleBuffer Not used.\r
558\r
559 @retval EFI_SUCCESS This driver is removed Controller.\r
560 @retval other This driver was not removed from this device.\r
561\r
562**/\r
563// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
40834173 564EFI_STATUS\r
565EFIAPI\r
566UndiDriverStop (\r
567 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
568 IN EFI_HANDLE Controller,\r
569 IN UINTN NumberOfChildren,\r
570 IN EFI_HANDLE *ChildHandleBuffer\r
571 )\r
40834173 572{\r
573 EFI_STATUS Status;\r
574 BOOLEAN AllChildrenStopped;\r
575 UINTN Index;\r
576 UNDI32_DEV *UNDI32Device;\r
577 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;\r
578 EFI_PCI_IO_PROTOCOL *PciIo;\r
579\r
580 //\r
581 // Complete all outstanding transactions to Controller.\r
582 // Don't allow any new transaction to Controller to be started.\r
583 //\r
584 if (NumberOfChildren == 0) {\r
585\r
586 //\r
587 // Close the bus driver\r
588 //\r
589 Status = gBS->CloseProtocol (\r
590 Controller,\r
591 &gEfiDevicePathProtocolGuid,\r
592 This->DriverBindingHandle,\r
593 Controller\r
594 );\r
595\r
596 Status = gBS->CloseProtocol (\r
597 Controller,\r
598 &gEfiPciIoProtocolGuid,\r
599 This->DriverBindingHandle,\r
600 Controller\r
601 );\r
602\r
603 return Status;\r
604 }\r
605\r
606 AllChildrenStopped = TRUE;\r
607\r
608 for (Index = 0; Index < NumberOfChildren; Index++) {\r
609\r
610 Status = gBS->OpenProtocol (\r
611 ChildHandleBuffer[Index],\r
41057d77 612 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
40834173 613 (VOID **) &NIIProtocol,\r
614 This->DriverBindingHandle,\r
615 Controller,\r
616 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
617 );\r
618 if (!EFI_ERROR (Status)) {\r
619\r
620 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);\r
621\r
68246fa8 622 //\r
623 // Restore original PCI attributes\r
624 //\r
625 Status = UNDI32Device->NicInfo.Io_Function->Attributes (\r
626 UNDI32Device->NicInfo.Io_Function,\r
627 EfiPciIoAttributeOperationSet,\r
628 UNDI32Device->NicInfo.OriginalPciAttributes,\r
629 NULL\r
630 );\r
631 ASSERT_EFI_ERROR (Status);\r
632\r
40834173 633 Status = gBS->CloseProtocol (\r
634 Controller,\r
635 &gEfiPciIoProtocolGuid,\r
636 This->DriverBindingHandle,\r
637 ChildHandleBuffer[Index]\r
638 );\r
639\r
640 Status = gBS->UninstallMultipleProtocolInterfaces (\r
641 ChildHandleBuffer[Index],\r
642 &gEfiDevicePathProtocolGuid,\r
643 UNDI32Device->Undi32DevPath,\r
644 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
645 &UNDI32Device->NIIProtocol_31,\r
40834173 646 NULL\r
647 );\r
648\r
649 if (EFI_ERROR (Status)) {\r
650 gBS->OpenProtocol (\r
651 Controller,\r
652 &gEfiPciIoProtocolGuid,\r
653 (VOID **) &PciIo,\r
654 This->DriverBindingHandle,\r
655 ChildHandleBuffer[Index],\r
656 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
657 );\r
658 } else {\r
659 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
660 gBS->FreePool (UNDI32Device);\r
661 }\r
662 }\r
663\r
664 if (EFI_ERROR (Status)) {\r
665 AllChildrenStopped = FALSE;\r
666 }\r
667 }\r
668\r
669 if (!AllChildrenStopped) {\r
670 return EFI_DEVICE_ERROR;\r
671 }\r
672\r
673 return EFI_SUCCESS;\r
674\r
675}\r
676\r
40834173 677\r
ffa5008a 678/**\r
40834173 679 Use the EFI boot services to produce a pause. This is also the routine which\r
680 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can\r
681 do it's own pause.\r
682\r
ffa5008a 683 @param UnqId Runtime O/S routine might use this, this temp\r
684 routine does not use it\r
685 @param MicroSeconds Determines the length of pause.\r
40834173 686\r
ffa5008a 687 @return none\r
40834173 688\r
ffa5008a 689**/\r
690VOID\r
691TmpDelay (\r
692 IN UINT64 UnqId,\r
693 IN UINTN MicroSeconds\r
694 )\r
40834173 695{\r
696 gBS->Stall ((UINT32) MicroSeconds);\r
697}\r
698\r
ffa5008a 699\r
700/**\r
701 Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which\r
702 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.\r
703\r
704 @param UnqId Runtime O/S routine may use this field, this temp\r
705 routine does not.\r
706 @param ReadWrite Determine if it is an I/O or Memory Read/Write\r
707 Operation.\r
708 @param Len Determines the width of the data operation.\r
709 @param Port What port to Read/Write from.\r
710 @param BuffAddr Address to read to or write from.\r
711\r
712 @return none\r
713\r
714**/\r
40834173 715VOID\r
716TmpMemIo (\r
717 IN UINT64 UnqId,\r
718 IN UINT8 ReadWrite,\r
719 IN UINT8 Len,\r
720 IN UINT64 Port,\r
721 IN UINT64 BuffAddr\r
722 )\r
40834173 723{\r
724 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
725 NIC_DATA_INSTANCE *AdapterInfo;\r
726\r
727 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
728 AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;\r
729 switch (Len) {\r
730 case 2:\r
731 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
732 break;\r
733\r
734 case 4:\r
735 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
736 break;\r
737\r
738 case 8:\r
739 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
740 break;\r
741 }\r
742\r
743 switch (ReadWrite) {\r
744 case PXE_IO_READ:\r
745 AdapterInfo->Io_Function->Io.Read (\r
746 AdapterInfo->Io_Function,\r
747 Width,\r
748 1,\r
749 Port,\r
750 1,\r
751 (VOID *) (UINTN) (BuffAddr)\r
752 );\r
753 break;\r
754\r
755 case PXE_IO_WRITE:\r
756 AdapterInfo->Io_Function->Io.Write (\r
757 AdapterInfo->Io_Function,\r
758 Width,\r
759 1,\r
760 Port,\r
761 1,\r
762 (VOID *) (UINTN) (BuffAddr)\r
763 );\r
764 break;\r
765\r
766 case PXE_MEM_READ:\r
767 AdapterInfo->Io_Function->Mem.Read (\r
768 AdapterInfo->Io_Function,\r
769 Width,\r
770 0,\r
771 Port,\r
772 1,\r
773 (VOID *) (UINTN) (BuffAddr)\r
774 );\r
775 break;\r
776\r
777 case PXE_MEM_WRITE:\r
778 AdapterInfo->Io_Function->Mem.Write (\r
779 AdapterInfo->Io_Function,\r
780 Width,\r
781 0,\r
782 Port,\r
783 1,\r
784 (VOID *) (UINTN) (BuffAddr)\r
785 );\r
786 break;\r
787 }\r
788\r
789 return ;\r
790}\r
791\r
40834173 792\r
ffa5008a 793/**\r
40834173 794 Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space\r
795 for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)\r
796 and an added MAC node.\r
797\r
ffa5008a 798 @param DevPtr Pointer which will point to the newly created device\r
799 path with the MAC node attached.\r
800 @param BaseDevPtr Pointer to the device path which the UNDI device\r
801 driver is latching on to.\r
802 @param AdapterInfo Pointer to the NIC data structure information which\r
803 the UNDI driver is layering on..\r
40834173 804\r
ffa5008a 805 @retval EFI_SUCCESS A MAC address was successfully appended to the Base\r
806 Device Path.\r
807 @retval other Not enough resources available to create new Device\r
808 Path node.\r
40834173 809\r
ffa5008a 810**/\r
811EFI_STATUS\r
812AppendMac2DevPath (\r
813 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,\r
814 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,\r
815 IN NIC_DATA_INSTANCE *AdapterInfo\r
816 )\r
40834173 817{\r
818 EFI_MAC_ADDRESS MACAddress;\r
819 PCI_CONFIG_HEADER *CfgHdr;\r
820 INT32 Val;\r
821 INT32 Index;\r
822 INT32 Index2;\r
823 UINT8 AddrLen;\r
824 MAC_ADDR_DEVICE_PATH MacAddrNode;\r
825 EFI_DEVICE_PATH_PROTOCOL *EndNode;\r
826 UINT8 *DevicePtr;\r
827 UINT16 TotalPathLen;\r
828 UINT16 BasePathLen;\r
829 EFI_STATUS Status;\r
830\r
831 //\r
832 // set the environment ready (similar to UNDI_Start call) so that we can\r
833 // execute the other UNDI_ calls to get the mac address\r
834 // we are using undi 3.1 style\r
835 //\r
836 AdapterInfo->Delay = TmpDelay;\r
837 AdapterInfo->Virt2Phys = (VOID *) 0;\r
838 AdapterInfo->Block = (VOID *) 0;\r
839 AdapterInfo->Map_Mem = (VOID *) 0;\r
840 AdapterInfo->UnMap_Mem = (VOID *) 0;\r
841 AdapterInfo->Sync_Mem = (VOID *) 0;\r
842 AdapterInfo->Mem_Io = TmpMemIo;\r
843 //\r
844 // these tmp call-backs follow 3.1 undi style\r
845 // i.e. they have the unique_id parameter.\r
846 //\r
847 AdapterInfo->VersionFlag = 0x31;\r
848 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;\r
849\r
850 //\r
851 // undi init portion\r
852 //\r
853 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);\r
854 AdapterInfo->ioaddr = 0;\r
855 AdapterInfo->RevID = CfgHdr->RevID;\r
856\r
857 AddrLen = E100bGetEepromAddrLen (AdapterInfo);\r
858\r
859 for (Index = 0, Index2 = 0; Index < 3; Index++) {\r
860 Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);\r
861 MACAddress.Addr[Index2++] = (UINT8) Val;\r
862 MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);\r
863 }\r
864\r
865 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);\r
866 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {\r
867 // MACAddress.Addr[Index2] = 0;\r
868 //}\r
869 //\r
870 // stop undi\r
871 //\r
872 AdapterInfo->Delay = (VOID *) 0;\r
873 AdapterInfo->Mem_Io = (VOID *) 0;\r
874\r
875 //\r
876 // fill the mac address node first\r
877 //\r
878 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);\r
879 CopyMem (\r
880 (CHAR8 *) &MacAddrNode.MacAddress,\r
881 (CHAR8 *) &MACAddress,\r
882 sizeof (EFI_MAC_ADDRESS)\r
883 );\r
884\r
885 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;\r
886 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;\r
887 MacAddrNode.Header.Length[0] = sizeof (MacAddrNode);\r
888 MacAddrNode.Header.Length[1] = 0;\r
889\r
890 //\r
891 // find the size of the base dev path.\r
892 //\r
893 EndNode = BaseDevPtr;\r
894\r
895 while (!IsDevicePathEnd (EndNode)) {\r
896 EndNode = NextDevicePathNode (EndNode);\r
897 }\r
898\r
899 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));\r
900\r
901 //\r
902 // create space for full dev path\r
903 //\r
904 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
905\r
906 Status = gBS->AllocatePool (\r
907 EfiRuntimeServicesData,\r
908 TotalPathLen,\r
909 (VOID **) &DevicePtr\r
910 );\r
911\r
912 if (Status != EFI_SUCCESS) {\r
913 return Status;\r
914 }\r
915 //\r
916 // copy the base path, mac addr and end_dev_path nodes\r
917 //\r
918 *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;\r
919 CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);\r
920 DevicePtr += BasePathLen;\r
921 CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));\r
922 DevicePtr += sizeof (MacAddrNode);\r
923 CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
924\r
925 return EFI_SUCCESS;\r
926}\r
927\r
40834173 928\r
ffa5008a 929/**\r
40834173 930 Install a GUID/Pointer pair into the system's configuration table.\r
931\r
40834173 932 none\r
933\r
ffa5008a 934 @retval EFI_SUCCESS Install a GUID/Pointer pair into the system's\r
935 configuration table.\r
936 @retval other Did not successfully install the GUID/Pointer pair\r
937 into the configuration table.\r
40834173 938\r
ffa5008a 939**/\r
40834173 940// TODO: VOID - add argument and description to function comment\r
ffa5008a 941EFI_STATUS\r
942InstallConfigTable (\r
943 IN VOID\r
944 )\r
40834173 945{\r
946 EFI_STATUS Status;\r
947 EFI_CONFIGURATION_TABLE *CfgPtr;\r
948 NII_TABLE *TmpData;\r
949 UINT16 Index;\r
950 NII_TABLE *UndiData;\r
951\r
952 if (pxe_31 == NULL) {\r
953 return EFI_SUCCESS;\r
954 }\r
955\r
68246fa8 956 if(UndiDataPointer == NULL) {\r
ffa5008a 957 return EFI_SUCCESS;\r
40834173 958 }\r
68246fa8 959\r
960 UndiData = (NII_TABLE *)UndiDataPointer;\r
961\r
40834173 962 UndiData->NumEntries = pxe_31->IFcnt;\r
963 UndiData->NextLink = NULL;\r
964\r
965 for (Index = 0; Index < pxe_31->IFcnt; Index++) {\r
966 UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;\r
967 UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;\r
968 }\r
969\r
970 //\r
971 // see if there is an entry in the config table already\r
972 //\r
973 CfgPtr = gST->ConfigurationTable;\r
974\r
975 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
976 Status = CompareGuid (\r
977 &CfgPtr->VendorGuid,\r
978 &gEfiNetworkInterfaceIdentifierProtocolGuid_31\r
979 );\r
980 if (Status != EFI_SUCCESS) {\r
981 break;\r
982 }\r
983\r
984 CfgPtr++;\r
985 }\r
986\r
987 if (Index < gST->NumberOfTableEntries) {\r
988 TmpData = (NII_TABLE *) CfgPtr->VendorTable;\r
989\r
990 //\r
991 // go to the last link\r
992 //\r
993 while (TmpData->NextLink != NULL) {\r
994 TmpData = TmpData->NextLink;\r
995 }\r
996\r
997 TmpData->NextLink = UndiData;\r
998\r
999 //\r
1000 // 1st one in chain\r
1001 //\r
1002 UndiData = (NII_TABLE *) CfgPtr->VendorTable;\r
1003 }\r
1004\r
1005 //\r
1006 // create an entry in the configuration table for our GUID\r
1007 //\r
1008 Status = gBS->InstallConfigurationTable (\r
1009 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
1010 UndiData\r
1011 );\r
1012 return Status;\r
1013}\r
1014\r
1015/**\r
68246fa8 1016\r
40834173 1017**/\r
1018EFI_STATUS\r
1019EFIAPI\r
1020InitializeUndi(\r
1021 IN EFI_HANDLE ImageHandle,\r
1022 IN EFI_SYSTEM_TABLE *SystemTable\r
1023 )\r
1024{\r
1025 EFI_EVENT Event;\r
1026 EFI_STATUS Status;\r
1027\r
1028 Status = EfiLibInstallDriverBinding (\r
1029 ImageHandle,\r
1030 SystemTable,\r
1031 &gUndiDriverBinding,\r
1032 ImageHandle\r
1033 );\r
1034 ASSERT_EFI_ERROR (Status);\r
1035\r
1036 Status = gBS->CreateEvent (\r
1037 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
1038 TPL_NOTIFY,\r
1039 UndiNotifyExitBs,\r
1040 NULL,\r
1041 &Event\r
1042 );\r
1043 ASSERT_EFI_ERROR (Status);\r
1044\r
1045 Status = gBS->CreateEvent (\r
1046 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
1047 TPL_NOTIFY,\r
1048 UndiNotifyVirtual,\r
1049 NULL,\r
1050 &Event\r
1051 );\r
1052 ASSERT_EFI_ERROR (Status);\r
1053\r
1054 return Status;\r
1055}\r