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