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