Import UndiRuntimeDxe.
[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
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 // allocate and initialize both (old and new) the !pxe structures here,
338 // there should only be one copy of each of these structure for any number
339 // of NICs this undi supports. Also, these structures need to be on a
340 // paragraph boundary as per the spec. so, while allocating space for these,
341 // make sure that there is space for 2 !pxe structures (old and new) and a
342 // 32 bytes padding for alignment adjustment (in case)
343 //
344 TmpPxePointer = NULL;
345 if (pxe_31 == NULL) {
346 Status = gBS->AllocatePool (
347 EfiRuntimeServicesData,
348 (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),
349 (VOID **) &TmpPxePointer
350 );
351
352 if (EFI_ERROR (Status)) {
353 goto UndiErrorDeleteDevice;
354 }
355
356 ZeroMem (
357 TmpPxePointer,
358 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32
359 );
360 //
361 // check for paragraph alignment here, assuming that the pointer is
362 // already 8 byte aligned.
363 //
364 if (((UINTN) TmpPxePointer & 0x0F) != 0) {
365 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));
366 } else {
367 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;
368 }
369 //
370 // assuming that the sizeof pxe_31 is a 16 byte multiple
371 //
372 pxe = (PXE_SW_UNDI *) ((CHAR8 *) (pxe_31) + sizeof (PXE_SW_UNDI));
373
374 PxeStructInit (pxe, 0x30);
375 PxeStructInit (pxe_31, 0x31);
376 }
377
378 UNDI32Device->NIIProtocol.ID = (UINT64) (UINTN) (pxe);
379 UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31);
380
381 Status = PciIoFncs->Attributes (
382 PciIoFncs,
383 EfiPciIoAttributeOperationEnable,
384 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER,
385 NULL
386 );
387 //
388 // Read all the registers from device's PCI Configuration space
389 //
390 Status = PciIoFncs->Pci.Read (
391 PciIoFncs,
392 EfiPciIoWidthUint32,
393 0,
394 MAX_PCI_CONFIG_LEN,
395 &UNDI32Device->NicInfo.Config
396 );
397
398 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);
399
400 //
401 // make sure that this device is a PCI bus master
402 //
403
404 NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
405 if (CfgHdr->Command != NewCommand) {
406 PciIoFncs->Pci.Write (
407 PciIoFncs,
408 EfiPciIoWidthUint16,
409 PCI_COMMAND,
410 1,
411 &NewCommand
412 );
413 CfgHdr->Command = NewCommand;
414 }
415
416 //
417 // make sure that the latency timer is at least 32
418 //
419 if (CfgHdr->LatencyTimer < 32) {
420 CfgHdr->LatencyTimer = 32;
421 PciIoFncs->Pci.Write (
422 PciIoFncs,
423 EfiPciIoWidthUint8,
424 PCI_LATENCY_TIMER,
425 1,
426 &CfgHdr->LatencyTimer
427 );
428 }
429 //
430 // the IfNum index for the current interface will be the total number
431 // of interfaces initialized so far
432 //
433 UNDI32Device->NIIProtocol.IfNum = pxe->IFcnt;
434 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt;
435
436 PxeUpdate (&UNDI32Device->NicInfo, pxe);
437 PxeUpdate (&UNDI32Device->NicInfo, pxe_31);
438
439 UNDI32Device->NicInfo.Io_Function = PciIoFncs;
440 UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = UNDI32Device;
441 UNDI32Device->Undi32BaseDevPath = UndiDevicePath;
442
443 Status = AppendMac2DevPath (
444 &UNDI32Device->Undi32DevPath,
445 UNDI32Device->Undi32BaseDevPath,
446 &UNDI32Device->NicInfo
447 );
448
449 if (Status != 0) {
450 goto UndiErrorDeletePxe;
451 }
452
453 UNDI32Device->Signature = UNDI_DEV_SIGNATURE;
454
455 UNDI32Device->NIIProtocol.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
456 UNDI32Device->NIIProtocol.Type = EfiNetworkInterfaceUndi;
457 UNDI32Device->NIIProtocol.MajorVer = PXE_ROMID_MAJORVER;
458 UNDI32Device->NIIProtocol.MinorVer = PXE_ROMID_MINORVER;
459 UNDI32Device->NIIProtocol.ImageSize = 0;
460 UNDI32Device->NIIProtocol.ImageAddr = 0;
461 UNDI32Device->NIIProtocol.Ipv6Supported = FALSE;
462
463 UNDI32Device->NIIProtocol.StringId[0] = 'U';
464 UNDI32Device->NIIProtocol.StringId[1] = 'N';
465 UNDI32Device->NIIProtocol.StringId[2] = 'D';
466 UNDI32Device->NIIProtocol.StringId[3] = 'I';
467
468 UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;
469 UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;
470 UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;
471 UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;
472 UNDI32Device->NIIProtocol_31.ImageSize = 0;
473 UNDI32Device->NIIProtocol_31.ImageAddr = 0;
474 UNDI32Device->NIIProtocol_31.Ipv6Supported = FALSE;
475
476 UNDI32Device->NIIProtocol_31.StringId[0] = 'U';
477 UNDI32Device->NIIProtocol_31.StringId[1] = 'N';
478 UNDI32Device->NIIProtocol_31.StringId[2] = 'D';
479 UNDI32Device->NIIProtocol_31.StringId[3] = 'I';
480
481 UNDI32Device->DeviceHandle = NULL;
482
483 //
484 // install both the 3.0 and 3.1 NII protocols.
485 //
486 Status = gBS->InstallMultipleProtocolInterfaces (
487 &UNDI32Device->DeviceHandle,
488 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
489 &UNDI32Device->NIIProtocol_31,
490 &gEfiNetworkInterfaceIdentifierProtocolGuid,
491 &UNDI32Device->NIIProtocol,
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 (UnidiDataPointer != NULL) {
505 Status = gBS->FreePool(UnidiDataPointer);
506 }
507 if (EFI_ERROR (Status)) {
508 goto UndiErrorDeleteDevicePath;
509 }
510
511 Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UnidiDataPointer);
512 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UnidiDataPointer);
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 &gEfiNetworkInterfaceIdentifierProtocolGuid,
537 &UNDI32Device->NIIProtocol,
538 &gEfiDevicePathProtocolGuid,
539 UNDI32Device->Undi32DevPath,
540 NULL
541 );
542
543 UndiErrorDeleteDevicePath:
544 UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = NULL;
545 gBS->FreePool (UNDI32Device->Undi32DevPath);
546
547 UndiErrorDeletePxe:
548 PxeUpdate (NULL, pxe);
549 PxeUpdate (NULL, pxe_31);
550 if (TmpPxePointer != NULL) {
551 gBS->FreePool (TmpPxePointer);
552
553 }
554
555 UndiErrorDeleteDevice:
556 gBS->FreePool (UNDI32Device);
557
558 UndiError:
559 gBS->CloseProtocol (
560 Controller,
561 &gEfiDevicePathProtocolGuid,
562 This->DriverBindingHandle,
563 Controller
564 );
565
566 gBS->CloseProtocol (
567 Controller,
568 &gEfiPciIoProtocolGuid,
569 This->DriverBindingHandle,
570 Controller
571 );
572
573 return Status;
574 }
575
576 EFI_STATUS
577 EFIAPI
578 UndiDriverStop (
579 IN EFI_DRIVER_BINDING_PROTOCOL *This,
580 IN EFI_HANDLE Controller,
581 IN UINTN NumberOfChildren,
582 IN EFI_HANDLE *ChildHandleBuffer
583 )
584 /*++
585
586 Routine Description:
587 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
588 closing the DevicePath and PciIo protocols on Controller.
589
590 Arguments:
591 This - Protocol instance pointer.
592 Controller - Handle of device to stop driver on.
593 NumberOfChildren - How many children need to be stopped.
594 ChildHandleBuffer - Not used.
595
596 Returns:
597 EFI_SUCCESS - This driver is removed Controller.
598 other - This driver was not removed from this device.
599
600 --*/
601 // TODO: EFI_DEVICE_ERROR - add return value to function comment
602 {
603 EFI_STATUS Status;
604 BOOLEAN AllChildrenStopped;
605 UINTN Index;
606 UNDI32_DEV *UNDI32Device;
607 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;
608 EFI_PCI_IO_PROTOCOL *PciIo;
609
610 //
611 // Complete all outstanding transactions to Controller.
612 // Don't allow any new transaction to Controller to be started.
613 //
614 if (NumberOfChildren == 0) {
615
616 //
617 // Close the bus driver
618 //
619 Status = gBS->CloseProtocol (
620 Controller,
621 &gEfiDevicePathProtocolGuid,
622 This->DriverBindingHandle,
623 Controller
624 );
625
626 Status = gBS->CloseProtocol (
627 Controller,
628 &gEfiPciIoProtocolGuid,
629 This->DriverBindingHandle,
630 Controller
631 );
632
633 return Status;
634 }
635
636 AllChildrenStopped = TRUE;
637
638 for (Index = 0; Index < NumberOfChildren; Index++) {
639
640 Status = gBS->OpenProtocol (
641 ChildHandleBuffer[Index],
642 &gEfiNetworkInterfaceIdentifierProtocolGuid,
643 (VOID **) &NIIProtocol,
644 This->DriverBindingHandle,
645 Controller,
646 EFI_OPEN_PROTOCOL_GET_PROTOCOL
647 );
648 if (!EFI_ERROR (Status)) {
649
650 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);
651
652 Status = gBS->CloseProtocol (
653 Controller,
654 &gEfiPciIoProtocolGuid,
655 This->DriverBindingHandle,
656 ChildHandleBuffer[Index]
657 );
658
659 Status = gBS->UninstallMultipleProtocolInterfaces (
660 ChildHandleBuffer[Index],
661 &gEfiDevicePathProtocolGuid,
662 UNDI32Device->Undi32DevPath,
663 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
664 &UNDI32Device->NIIProtocol_31,
665 &gEfiNetworkInterfaceIdentifierProtocolGuid,
666 &UNDI32Device->NIIProtocol,
667 NULL
668 );
669
670 if (EFI_ERROR (Status)) {
671 gBS->OpenProtocol (
672 Controller,
673 &gEfiPciIoProtocolGuid,
674 (VOID **) &PciIo,
675 This->DriverBindingHandle,
676 ChildHandleBuffer[Index],
677 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
678 );
679 } else {
680 gBS->FreePool (UNDI32Device->Undi32DevPath);
681 gBS->FreePool (UNDI32Device);
682 }
683 }
684
685 if (EFI_ERROR (Status)) {
686 AllChildrenStopped = FALSE;
687 }
688 }
689
690 if (!AllChildrenStopped) {
691 return EFI_DEVICE_ERROR;
692 }
693
694 return EFI_SUCCESS;
695
696 }
697
698 VOID
699 TmpDelay (
700 IN UINT64 UnqId,
701 IN UINTN MicroSeconds
702 )
703 /*++
704
705 Routine Description:
706
707 Use the EFI boot services to produce a pause. This is also the routine which
708 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can
709 do it's own pause.
710
711 Arguments:
712
713 UnqId - Runtime O/S routine might use this, this temp routine does not use it
714
715 MicroSeconds - Determines the length of pause.
716
717 Returns:
718
719 none
720
721 --*/
722 {
723 gBS->Stall ((UINT32) MicroSeconds);
724 }
725
726 VOID
727 TmpMemIo (
728 IN UINT64 UnqId,
729 IN UINT8 ReadWrite,
730 IN UINT8 Len,
731 IN UINT64 Port,
732 IN UINT64 BuffAddr
733 )
734 /*++
735
736 Routine Description:
737
738 Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which
739 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.
740
741 Arguments:
742
743 UnqId - Runtime O/S routine may use this field, this temp routine does not.
744
745 ReadWrite - Determine if it is an I/O or Memory Read/Write Operation.
746
747 Len - Determines the width of the data operation.
748
749 Port - What port to Read/Write from.
750
751 BuffAddr - Address to read to or write from.
752
753 Returns:
754
755 none
756
757 --*/
758 {
759 EFI_PCI_IO_PROTOCOL_WIDTH Width;
760 NIC_DATA_INSTANCE *AdapterInfo;
761
762 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
763 AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;
764 switch (Len) {
765 case 2:
766 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;
767 break;
768
769 case 4:
770 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
771 break;
772
773 case 8:
774 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
775 break;
776 }
777
778 switch (ReadWrite) {
779 case PXE_IO_READ:
780 AdapterInfo->Io_Function->Io.Read (
781 AdapterInfo->Io_Function,
782 Width,
783 1,
784 Port,
785 1,
786 (VOID *) (UINTN) (BuffAddr)
787 );
788 break;
789
790 case PXE_IO_WRITE:
791 AdapterInfo->Io_Function->Io.Write (
792 AdapterInfo->Io_Function,
793 Width,
794 1,
795 Port,
796 1,
797 (VOID *) (UINTN) (BuffAddr)
798 );
799 break;
800
801 case PXE_MEM_READ:
802 AdapterInfo->Io_Function->Mem.Read (
803 AdapterInfo->Io_Function,
804 Width,
805 0,
806 Port,
807 1,
808 (VOID *) (UINTN) (BuffAddr)
809 );
810 break;
811
812 case PXE_MEM_WRITE:
813 AdapterInfo->Io_Function->Mem.Write (
814 AdapterInfo->Io_Function,
815 Width,
816 0,
817 Port,
818 1,
819 (VOID *) (UINTN) (BuffAddr)
820 );
821 break;
822 }
823
824 return ;
825 }
826
827 EFI_STATUS
828 AppendMac2DevPath (
829 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,
830 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,
831 IN NIC_DATA_INSTANCE *AdapterInfo
832 )
833 /*++
834
835 Routine Description:
836
837 Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space
838 for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)
839 and an added MAC node.
840
841 Arguments:
842
843 DevPtr - Pointer which will point to the newly created device path with the MAC node attached.
844
845 BaseDevPtr - Pointer to the device path which the UNDI device driver is latching on to.
846
847 AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
848
849 Returns:
850
851 EFI_SUCCESS - A MAC address was successfully appended to the Base Device Path.
852
853 other - Not enough resources available to create new Device Path node.
854
855 --*/
856 {
857 EFI_MAC_ADDRESS MACAddress;
858 PCI_CONFIG_HEADER *CfgHdr;
859 INT32 Val;
860 INT32 Index;
861 INT32 Index2;
862 UINT8 AddrLen;
863 MAC_ADDR_DEVICE_PATH MacAddrNode;
864 EFI_DEVICE_PATH_PROTOCOL *EndNode;
865 UINT8 *DevicePtr;
866 UINT16 TotalPathLen;
867 UINT16 BasePathLen;
868 EFI_STATUS Status;
869
870 //
871 // set the environment ready (similar to UNDI_Start call) so that we can
872 // execute the other UNDI_ calls to get the mac address
873 // we are using undi 3.1 style
874 //
875 AdapterInfo->Delay = TmpDelay;
876 AdapterInfo->Virt2Phys = (VOID *) 0;
877 AdapterInfo->Block = (VOID *) 0;
878 AdapterInfo->Map_Mem = (VOID *) 0;
879 AdapterInfo->UnMap_Mem = (VOID *) 0;
880 AdapterInfo->Sync_Mem = (VOID *) 0;
881 AdapterInfo->Mem_Io = TmpMemIo;
882 //
883 // these tmp call-backs follow 3.1 undi style
884 // i.e. they have the unique_id parameter.
885 //
886 AdapterInfo->VersionFlag = 0x31;
887 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;
888
889 //
890 // undi init portion
891 //
892 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
893 AdapterInfo->ioaddr = 0;
894 AdapterInfo->RevID = CfgHdr->RevID;
895
896 AddrLen = E100bGetEepromAddrLen (AdapterInfo);
897
898 for (Index = 0, Index2 = 0; Index < 3; Index++) {
899 Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);
900 MACAddress.Addr[Index2++] = (UINT8) Val;
901 MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);
902 }
903
904 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);
905 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {
906 // MACAddress.Addr[Index2] = 0;
907 //}
908 //
909 // stop undi
910 //
911 AdapterInfo->Delay = (VOID *) 0;
912 AdapterInfo->Mem_Io = (VOID *) 0;
913
914 //
915 // fill the mac address node first
916 //
917 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);
918 CopyMem (
919 (CHAR8 *) &MacAddrNode.MacAddress,
920 (CHAR8 *) &MACAddress,
921 sizeof (EFI_MAC_ADDRESS)
922 );
923
924 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;
925 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;
926 MacAddrNode.Header.Length[0] = sizeof (MacAddrNode);
927 MacAddrNode.Header.Length[1] = 0;
928
929 //
930 // find the size of the base dev path.
931 //
932 EndNode = BaseDevPtr;
933
934 while (!IsDevicePathEnd (EndNode)) {
935 EndNode = NextDevicePathNode (EndNode);
936 }
937
938 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));
939
940 //
941 // create space for full dev path
942 //
943 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
944
945 Status = gBS->AllocatePool (
946 EfiRuntimeServicesData,
947 TotalPathLen,
948 (VOID **) &DevicePtr
949 );
950
951 if (Status != EFI_SUCCESS) {
952 return Status;
953 }
954 //
955 // copy the base path, mac addr and end_dev_path nodes
956 //
957 *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;
958 CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);
959 DevicePtr += BasePathLen;
960 CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));
961 DevicePtr += sizeof (MacAddrNode);
962 CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));
963
964 return EFI_SUCCESS;
965 }
966
967 EFI_STATUS
968 InstallConfigTable (
969 IN VOID
970 )
971 /*++
972
973 Routine Description:
974
975 Install a GUID/Pointer pair into the system's configuration table.
976
977 Arguments:
978
979 none
980
981 Returns:
982
983 EFI_SUCCESS - Install a GUID/Pointer pair into the system's configuration table.
984
985 other - Did not successfully install the GUID/Pointer pair into the configuration table.
986
987 --*/
988 // TODO: VOID - add argument and description to function comment
989 {
990 EFI_STATUS Status;
991 EFI_CONFIGURATION_TABLE *CfgPtr;
992 NII_TABLE *TmpData;
993 UINT16 Index;
994 NII_TABLE *UndiData;
995
996 if (pxe_31 == NULL) {
997 return EFI_SUCCESS;
998 }
999
1000 if(UnidiDataPointer == NULL) {
1001 return EFI_SUCCESS;
1002 }
1003
1004 UndiData = (NII_TABLE *)UnidiDataPointer;
1005
1006 UndiData->NumEntries = pxe_31->IFcnt;
1007 UndiData->NextLink = NULL;
1008
1009 for (Index = 0; Index < pxe_31->IFcnt; Index++) {
1010 UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;
1011 UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;
1012 }
1013
1014 //
1015 // see if there is an entry in the config table already
1016 //
1017 CfgPtr = gST->ConfigurationTable;
1018
1019 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
1020 Status = CompareGuid (
1021 &CfgPtr->VendorGuid,
1022 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
1023 );
1024 if (Status != EFI_SUCCESS) {
1025 break;
1026 }
1027
1028 CfgPtr++;
1029 }
1030
1031 if (Index < gST->NumberOfTableEntries) {
1032 TmpData = (NII_TABLE *) CfgPtr->VendorTable;
1033
1034 //
1035 // go to the last link
1036 //
1037 while (TmpData->NextLink != NULL) {
1038 TmpData = TmpData->NextLink;
1039 }
1040
1041 TmpData->NextLink = UndiData;
1042
1043 //
1044 // 1st one in chain
1045 //
1046 UndiData = (NII_TABLE *) CfgPtr->VendorTable;
1047 }
1048
1049 //
1050 // create an entry in the configuration table for our GUID
1051 //
1052 Status = gBS->InstallConfigurationTable (
1053 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
1054 UndiData
1055 );
1056 return Status;
1057 }
1058
1059 /**
1060
1061 Install driver binding protocol of UNDI.
1062
1063 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1064 @param[in] SystemTable A pointer to the EFI System Table.
1065
1066 @retval EFI_SUCCESS The entry point is executed successfully.
1067 @retval other Some error occurs when executing this entry point.
1068
1069 **/
1070 EFI_STATUS
1071 EFIAPI
1072 InitializeUndi(
1073 IN EFI_HANDLE ImageHandle,
1074 IN EFI_SYSTEM_TABLE *SystemTable
1075 )
1076 {
1077 EFI_EVENT Event;
1078 EFI_STATUS Status;
1079
1080 Status = EfiLibInstallDriverBinding (
1081 ImageHandle,
1082 SystemTable,
1083 &gUndiDriverBinding,
1084 ImageHandle
1085 );
1086 ASSERT_EFI_ERROR (Status);
1087
1088 Status = gBS->CreateEvent (
1089 EVT_SIGNAL_EXIT_BOOT_SERVICES,
1090 TPL_NOTIFY,
1091 UndiNotifyExitBs,
1092 NULL,
1093 &Event
1094 );
1095 ASSERT_EFI_ERROR (Status);
1096
1097 Status = gBS->CreateEvent (
1098 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
1099 TPL_NOTIFY,
1100 UndiNotifyVirtual,
1101 NULL,
1102 &Event
1103 );
1104 ASSERT_EFI_ERROR (Status);
1105
1106 return Status;
1107 }