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