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