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