]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UndiRuntimeDxe/Init.c
Fixed tabbing issue
[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
96f6af14 290 UINT64 Supports;\r
40834173 291\r
292 Status = gBS->OpenProtocol (\r
293 Controller,\r
294 &gEfiPciIoProtocolGuid,\r
295 (VOID **) &PciIoFncs,\r
296 This->DriverBindingHandle,\r
297 Controller,\r
298 EFI_OPEN_PROTOCOL_BY_DRIVER\r
299 );\r
300\r
301 if (EFI_ERROR (Status)) {\r
302 return Status;\r
303 }\r
304\r
305 Status = gBS->OpenProtocol (\r
306 Controller,\r
307 &gEfiDevicePathProtocolGuid,\r
308 (VOID **) &UndiDevicePath,\r
309 This->DriverBindingHandle,\r
310 Controller,\r
311 EFI_OPEN_PROTOCOL_BY_DRIVER\r
312 );\r
313\r
314 if (EFI_ERROR (Status)) {\r
315 gBS->CloseProtocol (\r
316 Controller,\r
317 &gEfiPciIoProtocolGuid,\r
318 This->DriverBindingHandle,\r
319 Controller\r
320 );\r
321\r
322 return Status;\r
323 }\r
324\r
325 Status = gBS->AllocatePool (\r
326 EfiRuntimeServicesData,\r
327 sizeof (UNDI32_DEV),\r
328 (VOID **) &UNDI32Device\r
329 );\r
330\r
331 if (EFI_ERROR (Status)) {\r
332 goto UndiError;\r
333 }\r
334\r
335 ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));\r
336\r
337 //\r
338 // allocate and initialize both (old and new) the !pxe structures here,\r
339 // there should only be one copy of each of these structure for any number\r
340 // of NICs this undi supports. Also, these structures need to be on a\r
341 // paragraph boundary as per the spec. so, while allocating space for these,\r
342 // make sure that there is space for 2 !pxe structures (old and new) and a\r
343 // 32 bytes padding for alignment adjustment (in case)\r
344 //\r
345 TmpPxePointer = NULL;\r
346 if (pxe_31 == NULL) {\r
347 Status = gBS->AllocatePool (\r
348 EfiRuntimeServicesData,\r
349 (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),\r
350 (VOID **) &TmpPxePointer\r
351 );\r
352\r
353 if (EFI_ERROR (Status)) {\r
354 goto UndiErrorDeleteDevice;\r
355 }\r
356\r
357 ZeroMem (\r
358 TmpPxePointer,\r
359 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32\r
360 );\r
361 //\r
362 // check for paragraph alignment here, assuming that the pointer is\r
363 // already 8 byte aligned.\r
364 //\r
365 if (((UINTN) TmpPxePointer & 0x0F) != 0) {\r
366 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));\r
367 } else {\r
368 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;\r
369 }\r
370 //\r
371 // assuming that the sizeof pxe_31 is a 16 byte multiple\r
372 //\r
373 pxe = (PXE_SW_UNDI *) ((CHAR8 *) (pxe_31) + sizeof (PXE_SW_UNDI));\r
374\r
375 PxeStructInit (pxe, 0x30);\r
376 PxeStructInit (pxe_31, 0x31);\r
377 }\r
378\r
379 UNDI32Device->NIIProtocol.ID = (UINT64) (UINTN) (pxe);\r
380 UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31);\r
381\r
382 Status = PciIoFncs->Attributes (\r
383 PciIoFncs,\r
96f6af14
LG
384 EfiPciIoAttributeOperationSupported,\r
385 0,\r
386 &Supports\r
40834173 387 );\r
96f6af14
LG
388 if (!EFI_ERROR (Status)) {\r
389 Supports &= EFI_PCI_DEVICE_ENABLE;\r
390 Status = PciIoFncs->Attributes (\r
391 PciIoFncs,\r
392 EfiPciIoAttributeOperationEnable,\r
393 Supports,\r
394 NULL\r
395 );\r
396 }\r
40834173 397 //\r
398 // Read all the registers from device's PCI Configuration space\r
399 //\r
400 Status = PciIoFncs->Pci.Read (\r
401 PciIoFncs,\r
402 EfiPciIoWidthUint32,\r
403 0,\r
404 MAX_PCI_CONFIG_LEN,\r
405 &UNDI32Device->NicInfo.Config\r
406 );\r
407\r
408 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);\r
409\r
410 //\r
411 // make sure that this device is a PCI bus master\r
412 //\r
413\r
414 NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);\r
415 if (CfgHdr->Command != NewCommand) {\r
416 PciIoFncs->Pci.Write (\r
417 PciIoFncs,\r
418 EfiPciIoWidthUint16,\r
419 PCI_COMMAND,\r
420 1,\r
421 &NewCommand\r
422 );\r
423 CfgHdr->Command = NewCommand;\r
424 }\r
425\r
426 //\r
427 // make sure that the latency timer is at least 32\r
428 //\r
429 if (CfgHdr->LatencyTimer < 32) {\r
430 CfgHdr->LatencyTimer = 32;\r
431 PciIoFncs->Pci.Write (\r
432 PciIoFncs,\r
433 EfiPciIoWidthUint8,\r
434 PCI_LATENCY_TIMER,\r
435 1,\r
436 &CfgHdr->LatencyTimer\r
437 );\r
438 }\r
439 //\r
440 // the IfNum index for the current interface will be the total number\r
441 // of interfaces initialized so far\r
442 //\r
443 UNDI32Device->NIIProtocol.IfNum = pxe->IFcnt;\r
444 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt;\r
445\r
446 PxeUpdate (&UNDI32Device->NicInfo, pxe);\r
447 PxeUpdate (&UNDI32Device->NicInfo, pxe_31);\r
448\r
449 UNDI32Device->NicInfo.Io_Function = PciIoFncs;\r
450 UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = UNDI32Device;\r
451 UNDI32Device->Undi32BaseDevPath = UndiDevicePath;\r
452\r
453 Status = AppendMac2DevPath (\r
454 &UNDI32Device->Undi32DevPath,\r
455 UNDI32Device->Undi32BaseDevPath,\r
456 &UNDI32Device->NicInfo\r
457 );\r
458\r
459 if (Status != 0) {\r
460 goto UndiErrorDeletePxe;\r
461 }\r
462\r
463 UNDI32Device->Signature = UNDI_DEV_SIGNATURE;\r
464\r
465 UNDI32Device->NIIProtocol.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;\r
466 UNDI32Device->NIIProtocol.Type = EfiNetworkInterfaceUndi;\r
467 UNDI32Device->NIIProtocol.MajorVer = PXE_ROMID_MAJORVER;\r
468 UNDI32Device->NIIProtocol.MinorVer = PXE_ROMID_MINORVER;\r
469 UNDI32Device->NIIProtocol.ImageSize = 0;\r
470 UNDI32Device->NIIProtocol.ImageAddr = 0;\r
471 UNDI32Device->NIIProtocol.Ipv6Supported = FALSE;\r
472\r
473 UNDI32Device->NIIProtocol.StringId[0] = 'U';\r
474 UNDI32Device->NIIProtocol.StringId[1] = 'N';\r
475 UNDI32Device->NIIProtocol.StringId[2] = 'D';\r
476 UNDI32Device->NIIProtocol.StringId[3] = 'I';\r
477\r
478 UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;\r
479 UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;\r
480 UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;\r
481 UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;\r
482 UNDI32Device->NIIProtocol_31.ImageSize = 0;\r
483 UNDI32Device->NIIProtocol_31.ImageAddr = 0;\r
484 UNDI32Device->NIIProtocol_31.Ipv6Supported = FALSE;\r
485\r
486 UNDI32Device->NIIProtocol_31.StringId[0] = 'U';\r
487 UNDI32Device->NIIProtocol_31.StringId[1] = 'N';\r
488 UNDI32Device->NIIProtocol_31.StringId[2] = 'D';\r
489 UNDI32Device->NIIProtocol_31.StringId[3] = 'I';\r
490\r
491 UNDI32Device->DeviceHandle = NULL;\r
492\r
493 //\r
494 // install both the 3.0 and 3.1 NII protocols.\r
495 //\r
496 Status = gBS->InstallMultipleProtocolInterfaces (\r
497 &UNDI32Device->DeviceHandle,\r
498 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
499 &UNDI32Device->NIIProtocol_31,\r
500 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
501 &UNDI32Device->NIIProtocol,\r
502 &gEfiDevicePathProtocolGuid,\r
503 UNDI32Device->Undi32DevPath,\r
504 NULL\r
505 );\r
506\r
507 if (EFI_ERROR (Status)) {\r
508 goto UndiErrorDeleteDevicePath;\r
509 }\r
510\r
511 //\r
512 // if the table exists, free it and alloc again, or alloc it directly \r
513 //\r
514 if (UnidiDataPointer != NULL) {\r
515 Status = gBS->FreePool(UnidiDataPointer);\r
516 }\r
517 if (EFI_ERROR (Status)) {\r
518 goto UndiErrorDeleteDevicePath;\r
519 }\r
520\r
521 Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UnidiDataPointer);\r
522 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UnidiDataPointer);\r
523\r
524 if (EFI_ERROR (Status)) {\r
525 goto UndiErrorAllocDataPointer;\r
526 }\r
527 \r
528 //\r
529 // Open For Child Device\r
530 //\r
531 Status = gBS->OpenProtocol (\r
532 Controller,\r
533 &gEfiPciIoProtocolGuid,\r
534 (VOID **) &PciIoFncs,\r
535 This->DriverBindingHandle,\r
536 UNDI32Device->DeviceHandle,\r
537 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
538 );\r
539\r
540 return EFI_SUCCESS;\r
541UndiErrorAllocDataPointer:\r
542 gBS->UninstallMultipleProtocolInterfaces (\r
543 &UNDI32Device->DeviceHandle,\r
544 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
545 &UNDI32Device->NIIProtocol_31,\r
546 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
547 &UNDI32Device->NIIProtocol,\r
548 &gEfiDevicePathProtocolGuid,\r
549 UNDI32Device->Undi32DevPath,\r
550 NULL\r
551 );\r
552\r
553UndiErrorDeleteDevicePath:\r
554 UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = NULL;\r
555 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
556\r
557UndiErrorDeletePxe:\r
558 PxeUpdate (NULL, pxe);\r
559 PxeUpdate (NULL, pxe_31);\r
560 if (TmpPxePointer != NULL) {\r
561 gBS->FreePool (TmpPxePointer);\r
562\r
563 }\r
564\r
565UndiErrorDeleteDevice:\r
566 gBS->FreePool (UNDI32Device);\r
567\r
568UndiError:\r
569 gBS->CloseProtocol (\r
570 Controller,\r
571 &gEfiDevicePathProtocolGuid,\r
572 This->DriverBindingHandle,\r
573 Controller\r
574 );\r
575\r
576 gBS->CloseProtocol (\r
577 Controller,\r
578 &gEfiPciIoProtocolGuid,\r
579 This->DriverBindingHandle,\r
580 Controller\r
581 );\r
582\r
583 return Status;\r
584}\r
585\r
586EFI_STATUS\r
587EFIAPI\r
588UndiDriverStop (\r
589 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
590 IN EFI_HANDLE Controller,\r
591 IN UINTN NumberOfChildren,\r
592 IN EFI_HANDLE *ChildHandleBuffer\r
593 )\r
594/*++\r
595\r
596Routine Description:\r
597 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
598 closing the DevicePath and PciIo protocols on Controller.\r
599\r
600Arguments:\r
601 This - Protocol instance pointer.\r
602 Controller - Handle of device to stop driver on.\r
603 NumberOfChildren - How many children need to be stopped.\r
604 ChildHandleBuffer - Not used.\r
605\r
606Returns:\r
607 EFI_SUCCESS - This driver is removed Controller.\r
608 other - This driver was not removed from this device.\r
609\r
610--*/\r
611// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
612{\r
613 EFI_STATUS Status;\r
614 BOOLEAN AllChildrenStopped;\r
615 UINTN Index;\r
616 UNDI32_DEV *UNDI32Device;\r
617 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;\r
618 EFI_PCI_IO_PROTOCOL *PciIo;\r
619\r
620 //\r
621 // Complete all outstanding transactions to Controller.\r
622 // Don't allow any new transaction to Controller to be started.\r
623 //\r
624 if (NumberOfChildren == 0) {\r
625\r
626 //\r
627 // Close the bus driver\r
628 //\r
629 Status = gBS->CloseProtocol (\r
630 Controller,\r
631 &gEfiDevicePathProtocolGuid,\r
632 This->DriverBindingHandle,\r
633 Controller\r
634 );\r
635\r
636 Status = gBS->CloseProtocol (\r
637 Controller,\r
638 &gEfiPciIoProtocolGuid,\r
639 This->DriverBindingHandle,\r
640 Controller\r
641 );\r
642\r
643 return Status;\r
644 }\r
645\r
646 AllChildrenStopped = TRUE;\r
647\r
648 for (Index = 0; Index < NumberOfChildren; Index++) {\r
649\r
650 Status = gBS->OpenProtocol (\r
651 ChildHandleBuffer[Index],\r
652 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
653 (VOID **) &NIIProtocol,\r
654 This->DriverBindingHandle,\r
655 Controller,\r
656 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
657 );\r
658 if (!EFI_ERROR (Status)) {\r
659\r
660 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);\r
661\r
662 Status = gBS->CloseProtocol (\r
663 Controller,\r
664 &gEfiPciIoProtocolGuid,\r
665 This->DriverBindingHandle,\r
666 ChildHandleBuffer[Index]\r
667 );\r
668\r
669 Status = gBS->UninstallMultipleProtocolInterfaces (\r
670 ChildHandleBuffer[Index],\r
671 &gEfiDevicePathProtocolGuid,\r
672 UNDI32Device->Undi32DevPath,\r
673 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
674 &UNDI32Device->NIIProtocol_31,\r
675 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
676 &UNDI32Device->NIIProtocol,\r
677 NULL\r
678 );\r
679\r
680 if (EFI_ERROR (Status)) {\r
681 gBS->OpenProtocol (\r
682 Controller,\r
683 &gEfiPciIoProtocolGuid,\r
684 (VOID **) &PciIo,\r
685 This->DriverBindingHandle,\r
686 ChildHandleBuffer[Index],\r
687 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
688 );\r
689 } else {\r
690 gBS->FreePool (UNDI32Device->Undi32DevPath);\r
691 gBS->FreePool (UNDI32Device);\r
692 }\r
693 }\r
694\r
695 if (EFI_ERROR (Status)) {\r
696 AllChildrenStopped = FALSE;\r
697 }\r
698 }\r
699\r
700 if (!AllChildrenStopped) {\r
701 return EFI_DEVICE_ERROR;\r
702 }\r
703\r
704 return EFI_SUCCESS;\r
705\r
706}\r
707\r
708VOID\r
709TmpDelay (\r
710 IN UINT64 UnqId,\r
711 IN UINTN MicroSeconds\r
712 )\r
713/*++\r
714\r
715Routine Description:\r
716\r
717 Use the EFI boot services to produce a pause. This is also the routine which\r
718 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can\r
719 do it's own pause.\r
720\r
721Arguments:\r
722\r
723 UnqId - Runtime O/S routine might use this, this temp routine does not use it\r
724 \r
725 MicroSeconds - Determines the length of pause.\r
726\r
727Returns:\r
728\r
729 none\r
730\r
731--*/\r
732{\r
733 gBS->Stall ((UINT32) MicroSeconds);\r
734}\r
735\r
736VOID\r
737TmpMemIo (\r
738 IN UINT64 UnqId,\r
739 IN UINT8 ReadWrite,\r
740 IN UINT8 Len,\r
741 IN UINT64 Port,\r
742 IN UINT64 BuffAddr\r
743 )\r
744/*++\r
745\r
746Routine Description:\r
747\r
748 Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which\r
749 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.\r
750\r
751Arguments:\r
752\r
753 UnqId - Runtime O/S routine may use this field, this temp routine does not.\r
754 \r
755 ReadWrite - Determine if it is an I/O or Memory Read/Write Operation.\r
756 \r
757 Len - Determines the width of the data operation.\r
758 \r
759 Port - What port to Read/Write from.\r
760 \r
761 BuffAddr - Address to read to or write from.\r
762\r
763Returns:\r
764\r
765 none\r
766\r
767--*/\r
768{\r
769 EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
770 NIC_DATA_INSTANCE *AdapterInfo;\r
771\r
772 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
773 AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;\r
774 switch (Len) {\r
775 case 2:\r
776 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
777 break;\r
778\r
779 case 4:\r
780 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
781 break;\r
782\r
783 case 8:\r
784 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
785 break;\r
786 }\r
787\r
788 switch (ReadWrite) {\r
789 case PXE_IO_READ:\r
790 AdapterInfo->Io_Function->Io.Read (\r
791 AdapterInfo->Io_Function,\r
792 Width,\r
793 1,\r
794 Port,\r
795 1,\r
796 (VOID *) (UINTN) (BuffAddr)\r
797 );\r
798 break;\r
799\r
800 case PXE_IO_WRITE:\r
801 AdapterInfo->Io_Function->Io.Write (\r
802 AdapterInfo->Io_Function,\r
803 Width,\r
804 1,\r
805 Port,\r
806 1,\r
807 (VOID *) (UINTN) (BuffAddr)\r
808 );\r
809 break;\r
810\r
811 case PXE_MEM_READ:\r
812 AdapterInfo->Io_Function->Mem.Read (\r
813 AdapterInfo->Io_Function,\r
814 Width,\r
815 0,\r
816 Port,\r
817 1,\r
818 (VOID *) (UINTN) (BuffAddr)\r
819 );\r
820 break;\r
821\r
822 case PXE_MEM_WRITE:\r
823 AdapterInfo->Io_Function->Mem.Write (\r
824 AdapterInfo->Io_Function,\r
825 Width,\r
826 0,\r
827 Port,\r
828 1,\r
829 (VOID *) (UINTN) (BuffAddr)\r
830 );\r
831 break;\r
832 }\r
833\r
834 return ;\r
835}\r
836\r
837EFI_STATUS\r
838AppendMac2DevPath (\r
839 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,\r
840 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,\r
841 IN NIC_DATA_INSTANCE *AdapterInfo\r
842 )\r
843/*++\r
844\r
845Routine Description:\r
846\r
847 Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space\r
848 for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)\r
849 and an added MAC node.\r
850\r
851Arguments:\r
852\r
853 DevPtr - Pointer which will point to the newly created device path with the MAC node attached.\r
854 \r
855 BaseDevPtr - Pointer to the device path which the UNDI device driver is latching on to.\r
856 \r
857 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
858\r
859Returns:\r
860\r
861 EFI_SUCCESS - A MAC address was successfully appended to the Base Device Path.\r
862 \r
863 other - Not enough resources available to create new Device Path node.\r
864\r
865--*/\r
866{\r
867 EFI_MAC_ADDRESS MACAddress;\r
868 PCI_CONFIG_HEADER *CfgHdr;\r
869 INT32 Val;\r
870 INT32 Index;\r
871 INT32 Index2;\r
872 UINT8 AddrLen;\r
873 MAC_ADDR_DEVICE_PATH MacAddrNode;\r
874 EFI_DEVICE_PATH_PROTOCOL *EndNode;\r
875 UINT8 *DevicePtr;\r
876 UINT16 TotalPathLen;\r
877 UINT16 BasePathLen;\r
878 EFI_STATUS Status;\r
879\r
880 //\r
881 // set the environment ready (similar to UNDI_Start call) so that we can\r
882 // execute the other UNDI_ calls to get the mac address\r
883 // we are using undi 3.1 style\r
884 //\r
885 AdapterInfo->Delay = TmpDelay;\r
886 AdapterInfo->Virt2Phys = (VOID *) 0;\r
887 AdapterInfo->Block = (VOID *) 0;\r
888 AdapterInfo->Map_Mem = (VOID *) 0;\r
889 AdapterInfo->UnMap_Mem = (VOID *) 0;\r
890 AdapterInfo->Sync_Mem = (VOID *) 0;\r
891 AdapterInfo->Mem_Io = TmpMemIo;\r
892 //\r
893 // these tmp call-backs follow 3.1 undi style\r
894 // i.e. they have the unique_id parameter.\r
895 //\r
896 AdapterInfo->VersionFlag = 0x31;\r
897 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;\r
898\r
899 //\r
900 // undi init portion\r
901 //\r
902 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);\r
903 AdapterInfo->ioaddr = 0;\r
904 AdapterInfo->RevID = CfgHdr->RevID;\r
905\r
906 AddrLen = E100bGetEepromAddrLen (AdapterInfo);\r
907\r
908 for (Index = 0, Index2 = 0; Index < 3; Index++) {\r
909 Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);\r
910 MACAddress.Addr[Index2++] = (UINT8) Val;\r
911 MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);\r
912 }\r
913\r
914 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);\r
915 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {\r
916 // MACAddress.Addr[Index2] = 0;\r
917 //}\r
918 //\r
919 // stop undi\r
920 //\r
921 AdapterInfo->Delay = (VOID *) 0;\r
922 AdapterInfo->Mem_Io = (VOID *) 0;\r
923\r
924 //\r
925 // fill the mac address node first\r
926 //\r
927 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);\r
928 CopyMem (\r
929 (CHAR8 *) &MacAddrNode.MacAddress,\r
930 (CHAR8 *) &MACAddress,\r
931 sizeof (EFI_MAC_ADDRESS)\r
932 );\r
933\r
934 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;\r
935 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;\r
936 MacAddrNode.Header.Length[0] = sizeof (MacAddrNode);\r
937 MacAddrNode.Header.Length[1] = 0;\r
938\r
939 //\r
940 // find the size of the base dev path.\r
941 //\r
942 EndNode = BaseDevPtr;\r
943\r
944 while (!IsDevicePathEnd (EndNode)) {\r
945 EndNode = NextDevicePathNode (EndNode);\r
946 }\r
947\r
948 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));\r
949\r
950 //\r
951 // create space for full dev path\r
952 //\r
953 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
954\r
955 Status = gBS->AllocatePool (\r
956 EfiRuntimeServicesData,\r
957 TotalPathLen,\r
958 (VOID **) &DevicePtr\r
959 );\r
960\r
961 if (Status != EFI_SUCCESS) {\r
962 return Status;\r
963 }\r
964 //\r
965 // copy the base path, mac addr and end_dev_path nodes\r
966 //\r
967 *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;\r
968 CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);\r
969 DevicePtr += BasePathLen;\r
970 CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));\r
971 DevicePtr += sizeof (MacAddrNode);\r
972 CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
973\r
974 return EFI_SUCCESS;\r
975}\r
976\r
977EFI_STATUS\r
978InstallConfigTable (\r
979 IN VOID\r
980 )\r
981/*++\r
982\r
983Routine Description:\r
984\r
985 Install a GUID/Pointer pair into the system's configuration table.\r
986\r
987Arguments:\r
988\r
989 none\r
990\r
991Returns:\r
992\r
993 EFI_SUCCESS - Install a GUID/Pointer pair into the system's configuration table.\r
994 \r
995 other - Did not successfully install the GUID/Pointer pair into the configuration table.\r
996\r
997--*/\r
998// TODO: VOID - add argument and description to function comment\r
999{\r
1000 EFI_STATUS Status;\r
1001 EFI_CONFIGURATION_TABLE *CfgPtr;\r
1002 NII_TABLE *TmpData;\r
1003 UINT16 Index;\r
1004 NII_TABLE *UndiData;\r
1005\r
1006 if (pxe_31 == NULL) {\r
1007 return EFI_SUCCESS;\r
1008 }\r
1009\r
1010 if(UnidiDataPointer == NULL) { \r
1011 return EFI_SUCCESS;\r
1012 }\r
1013 \r
1014 UndiData = (NII_TABLE *)UnidiDataPointer; \r
1015 \r
1016 UndiData->NumEntries = pxe_31->IFcnt;\r
1017 UndiData->NextLink = NULL;\r
1018\r
1019 for (Index = 0; Index < pxe_31->IFcnt; Index++) {\r
1020 UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;\r
1021 UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;\r
1022 }\r
1023\r
1024 //\r
1025 // see if there is an entry in the config table already\r
1026 //\r
1027 CfgPtr = gST->ConfigurationTable;\r
1028\r
1029 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
1030 Status = CompareGuid (\r
1031 &CfgPtr->VendorGuid,\r
1032 &gEfiNetworkInterfaceIdentifierProtocolGuid_31\r
1033 );\r
1034 if (Status != EFI_SUCCESS) {\r
1035 break;\r
1036 }\r
1037\r
1038 CfgPtr++;\r
1039 }\r
1040\r
1041 if (Index < gST->NumberOfTableEntries) {\r
1042 TmpData = (NII_TABLE *) CfgPtr->VendorTable;\r
1043\r
1044 //\r
1045 // go to the last link\r
1046 //\r
1047 while (TmpData->NextLink != NULL) {\r
1048 TmpData = TmpData->NextLink;\r
1049 }\r
1050\r
1051 TmpData->NextLink = UndiData;\r
1052\r
1053 //\r
1054 // 1st one in chain\r
1055 //\r
1056 UndiData = (NII_TABLE *) CfgPtr->VendorTable;\r
1057 }\r
1058\r
1059 //\r
1060 // create an entry in the configuration table for our GUID\r
1061 //\r
1062 Status = gBS->InstallConfigurationTable (\r
1063 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
1064 UndiData\r
1065 );\r
1066 return Status;\r
1067}\r
1068\r
1069/**\r
1070 \r
1071 Install driver binding protocol of UNDI.\r
1072 \r
1073 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
1074 @param[in] SystemTable A pointer to the EFI System Table.\r
1075 \r
1076 @retval EFI_SUCCESS The entry point is executed successfully.\r
1077 @retval other Some error occurs when executing this entry point.\r
1078\r
1079**/\r
1080EFI_STATUS\r
1081EFIAPI\r
1082InitializeUndi(\r
1083 IN EFI_HANDLE ImageHandle,\r
1084 IN EFI_SYSTEM_TABLE *SystemTable\r
1085 )\r
1086{\r
1087 EFI_EVENT Event;\r
1088 EFI_STATUS Status;\r
1089\r
1090 Status = EfiLibInstallDriverBinding (\r
1091 ImageHandle,\r
1092 SystemTable,\r
1093 &gUndiDriverBinding,\r
1094 ImageHandle\r
1095 );\r
1096 ASSERT_EFI_ERROR (Status);\r
1097\r
1098 Status = gBS->CreateEvent (\r
1099 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
1100 TPL_NOTIFY,\r
1101 UndiNotifyExitBs,\r
1102 NULL,\r
1103 &Event\r
1104 );\r
1105 ASSERT_EFI_ERROR (Status);\r
1106\r
1107 Status = gBS->CreateEvent (\r
1108 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
1109 TPL_NOTIFY,\r
1110 UndiNotifyVirtual,\r
1111 NULL,\r
1112 &Event\r
1113 );\r
1114 ASSERT_EFI_ERROR (Status);\r
1115\r
1116 return Status;\r
1117}\r