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