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