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