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