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