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