+++ /dev/null
-/** @file\r
- Initialization functions for EFI UNDI32 driver.\r
-\r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Undi32.h"\r
-//\r
-// Global Variables\r
-//\r
-\r
-PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry\r
-UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
-UNDI_CONFIG_TABLE *UndiDataPointer = NULL;\r
-\r
-//\r
-// UNDI Class Driver Global Variables\r
-//\r
-EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {\r
- UndiDriverSupported,\r
- UndiDriverStart,\r
- UndiDriverStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-\r
-/**\r
- When address mapping changes to virtual this should make the appropriate\r
- address conversions.\r
-\r
- (Standard Event handler)\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-UndiNotifyVirtual (\r
- EFI_EVENT Event,\r
- VOID *Context\r
- )\r
-{\r
- UINT16 Index;\r
- VOID *Pxe31Pointer;\r
-\r
- if (pxe_31 != NULL) {\r
- Pxe31Pointer = (VOID *) pxe_31;\r
-\r
- EfiConvertPointer (\r
- EFI_OPTIONAL_PTR,\r
- (VOID **) &Pxe31Pointer\r
- );\r
-\r
- //\r
- // UNDI32DeviceList is an array of pointers\r
- //\r
- for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {\r
- UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer;\r
- EfiConvertPointer (\r
- EFI_OPTIONAL_PTR,\r
- (VOID **) &(UNDI32DeviceList[Index])\r
- );\r
- }\r
-\r
- EfiConvertPointer (\r
- EFI_OPTIONAL_PTR,\r
- (VOID **) &(pxe_31->EntryPoint)\r
- );\r
- pxe_31 = Pxe31Pointer;\r
- }\r
-\r
- for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {\r
- EfiConvertPointer (\r
- EFI_OPTIONAL_PTR,\r
- (VOID **) &api_table[Index].api_ptr\r
- );\r
- }\r
-}\r
-\r
-\r
-/**\r
- When EFI is shuting down the boot services, we need to install a\r
- configuration table for UNDI to work at runtime!\r
-\r
- (Standard Event handler)\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-UndiNotifyReadyToBoot (\r
- EFI_EVENT Event,\r
- VOID *Context\r
- )\r
-{\r
- InstallConfigTable ();\r
-}\r
-\r
-\r
-/**\r
- Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
- than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,\r
- and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||\r
- ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||\r
- ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to test.\r
- @param RemainingDevicePath Not used.\r
-\r
- @retval EFI_SUCCESS This driver supports this device.\r
- @retval other This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UndiDriverSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- 0,\r
- sizeof (PCI_CONFIG_HEADER),\r
- &Pci\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
-\r
- if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {\r
- switch (Pci.Hdr.DeviceId) {\r
- case D100_DEVICE_ID:\r
- case D102_DEVICE_ID:\r
- case ICH3_DEVICE_ID_1:\r
- case ICH3_DEVICE_ID_2:\r
- case ICH3_DEVICE_ID_3:\r
- case ICH3_DEVICE_ID_4:\r
- case ICH3_DEVICE_ID_5:\r
- case ICH3_DEVICE_ID_6:\r
- case ICH3_DEVICE_ID_7:\r
- case ICH3_DEVICE_ID_8:\r
- case 0x1039:\r
- case 0x103A:\r
- case 0x103B:\r
- case 0x103C:\r
- case 0x103D:\r
- case 0x103E:\r
- case 0x1050:\r
- case 0x1051:\r
- case 0x1052:\r
- case 0x1053:\r
- case 0x1054:\r
- case 0x1055:\r
- case 0x1056:\r
- case 0x1057:\r
- case 0x1059:\r
- case 0x1064:\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Start this driver on Controller by opening PciIo and DevicePath protocol.\r
- Initialize PXE structures, create a copy of the Controller Device Path with the\r
- NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol\r
- on the newly created Device Path.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to work with.\r
- @param RemainingDevicePath Not used, always produce all possible children.\r
-\r
- @retval EFI_SUCCESS This driver is added to Controller.\r
- @retval other This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UndiDriverStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;\r
- PCI_CONFIG_HEADER *CfgHdr;\r
- UNDI32_DEV *UNDI32Device;\r
- UINT16 NewCommand;\r
- UINT8 *TmpPxePointer;\r
- EFI_PCI_IO_PROTOCOL *PciIoFncs;\r
- UINTN Len;\r
- UINT64 Supports;\r
- BOOLEAN PciAttributesSaved;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIoFncs,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &UndiDevicePath,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
- }\r
-\r
- PciAttributesSaved = FALSE;\r
-\r
- Status = gBS->AllocatePool (\r
- EfiRuntimeServicesData,\r
- sizeof (UNDI32_DEV),\r
- (VOID **) &UNDI32Device\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto UndiError;\r
- }\r
-\r
- ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));\r
-\r
- //\r
- // Get original PCI attributes\r
- //\r
- Status = PciIoFncs->Attributes (\r
- PciIoFncs,\r
- EfiPciIoAttributeOperationGet,\r
- 0,\r
- &UNDI32Device->NicInfo.OriginalPciAttributes\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto UndiErrorDeleteDevice;\r
- }\r
- PciAttributesSaved = TRUE;\r
-\r
- //\r
- // allocate and initialize both (old and new) the !pxe structures here,\r
- // there should only be one copy of each of these structure for any number\r
- // of NICs this undi supports. Also, these structures need to be on a\r
- // paragraph boundary as per the spec. so, while allocating space for these,\r
- // make sure that there is space for 2 !pxe structures (old and new) and a\r
- // 32 bytes padding for alignment adjustment (in case)\r
- //\r
- TmpPxePointer = NULL;\r
- if (pxe_31 == NULL) {\r
- Status = gBS->AllocatePool (\r
- EfiRuntimeServicesData,\r
- (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),\r
- (VOID **) &TmpPxePointer\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto UndiErrorDeleteDevice;\r
- }\r
-\r
- ZeroMem (\r
- TmpPxePointer,\r
- sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32\r
- );\r
- //\r
- // check for paragraph alignment here, assuming that the pointer is\r
- // already 8 byte aligned.\r
- //\r
- if (((UINTN) TmpPxePointer & 0x0F) != 0) {\r
- pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));\r
- } else {\r
- pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;\r
- }\r
-\r
- PxeStructInit (pxe_31);\r
- }\r
-\r
- UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31);\r
-\r
- Status = PciIoFncs->Attributes (\r
- PciIoFncs,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
- Status = PciIoFncs->Attributes (\r
- PciIoFncs,\r
- EfiPciIoAttributeOperationEnable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
- //\r
- // Read all the registers from device's PCI Configuration space\r
- //\r
- Status = PciIoFncs->Pci.Read (\r
- PciIoFncs,\r
- EfiPciIoWidthUint32,\r
- 0,\r
- MAX_PCI_CONFIG_LEN,\r
- &UNDI32Device->NicInfo.Config\r
- );\r
-\r
- CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);\r
-\r
- //\r
- // make sure that this device is a PCI bus master\r
- //\r
-\r
- NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);\r
- if (CfgHdr->Command != NewCommand) {\r
- PciIoFncs->Pci.Write (\r
- PciIoFncs,\r
- EfiPciIoWidthUint16,\r
- PCI_COMMAND,\r
- 1,\r
- &NewCommand\r
- );\r
- CfgHdr->Command = NewCommand;\r
- }\r
-\r
- //\r
- // make sure that the latency timer is at least 32\r
- //\r
- if (CfgHdr->LatencyTimer < 32) {\r
- CfgHdr->LatencyTimer = 32;\r
- PciIoFncs->Pci.Write (\r
- PciIoFncs,\r
- EfiPciIoWidthUint8,\r
- PCI_LATENCY_TIMER,\r
- 1,\r
- &CfgHdr->LatencyTimer\r
- );\r
- }\r
- //\r
- // the IfNum index for the current interface will be the total number\r
- // of interfaces initialized so far\r
- //\r
- UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt | pxe_31->IFcntExt << 8;\r
-\r
- PxeUpdate (&UNDI32Device->NicInfo, pxe_31);\r
-\r
- UNDI32Device->NicInfo.Io_Function = PciIoFncs;\r
- UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;\r
- UNDI32Device->Undi32BaseDevPath = UndiDevicePath;\r
-\r
- Status = AppendMac2DevPath (\r
- &UNDI32Device->Undi32DevPath,\r
- UNDI32Device->Undi32BaseDevPath,\r
- &UNDI32Device->NicInfo\r
- );\r
-\r
- if (Status != 0) {\r
- goto UndiErrorDeletePxe;\r
- }\r
-\r
- UNDI32Device->Signature = UNDI_DEV_SIGNATURE;\r
-\r
- UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;\r
- UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;\r
- UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;\r
- UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;\r
- UNDI32Device->NIIProtocol_31.ImageSize = 0;\r
- UNDI32Device->NIIProtocol_31.ImageAddr = 0;\r
- UNDI32Device->NIIProtocol_31.Ipv6Supported = TRUE;\r
-\r
- UNDI32Device->NIIProtocol_31.StringId[0] = 'U';\r
- UNDI32Device->NIIProtocol_31.StringId[1] = 'N';\r
- UNDI32Device->NIIProtocol_31.StringId[2] = 'D';\r
- UNDI32Device->NIIProtocol_31.StringId[3] = 'I';\r
-\r
- UNDI32Device->DeviceHandle = NULL;\r
-\r
- UNDI32Device->Aip.GetInformation = UndiAipGetInfo;\r
- UNDI32Device->Aip.SetInformation = UndiAipSetInfo;\r
- UNDI32Device->Aip.GetSupportedTypes = UndiAipGetSupportedTypes;\r
-\r
- //\r
- // install both the 3.0 and 3.1 NII protocols.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &UNDI32Device->DeviceHandle,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- &UNDI32Device->NIIProtocol_31,\r
- &gEfiDevicePathProtocolGuid,\r
- UNDI32Device->Undi32DevPath,\r
- &gEfiAdapterInformationProtocolGuid,\r
- &UNDI32Device->Aip,\r
- NULL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto UndiErrorDeleteDevicePath;\r
- }\r
-\r
- //\r
- // if the table exists, free it and alloc again, or alloc it directly\r
- //\r
- if (UndiDataPointer != NULL) {\r
- Status = gBS->FreePool(UndiDataPointer);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto UndiErrorDeleteDevicePath;\r
- }\r
-\r
- Len = ((pxe_31->IFcnt|pxe_31->IFcntExt << 8)* sizeof (UndiDataPointer->NII_entry)) + sizeof (UndiDataPointer);\r
- Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto UndiErrorAllocDataPointer;\r
- }\r
-\r
- //\r
- // Open For Child Device\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIoFncs,\r
- This->DriverBindingHandle,\r
- UNDI32Device->DeviceHandle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
-\r
- return EFI_SUCCESS;\r
-UndiErrorAllocDataPointer:\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- &UNDI32Device->DeviceHandle,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- &UNDI32Device->NIIProtocol_31,\r
- &gEfiDevicePathProtocolGuid,\r
- UNDI32Device->Undi32DevPath,\r
- &gEfiAdapterInformationProtocolGuid,\r
- &UNDI32Device->Aip,\r
- NULL\r
- );\r
-\r
-UndiErrorDeleteDevicePath:\r
- UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;\r
- gBS->FreePool (UNDI32Device->Undi32DevPath);\r
-\r
-UndiErrorDeletePxe:\r
- PxeUpdate (NULL, pxe_31);\r
- if (TmpPxePointer != NULL) {\r
- gBS->FreePool (TmpPxePointer);\r
-\r
- }\r
-\r
-UndiErrorDeleteDevice:\r
- if (PciAttributesSaved) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- PciIoFncs->Attributes (\r
- PciIoFncs,\r
- EfiPciIoAttributeOperationSet,\r
- UNDI32Device->NicInfo.OriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
-\r
- gBS->FreePool (UNDI32Device);\r
-\r
-UndiError:\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
- closing the DevicePath and PciIo protocols on Controller.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to stop driver on.\r
- @param NumberOfChildren How many children need to be stopped.\r
- @param ChildHandleBuffer Not used.\r
-\r
- @retval EFI_SUCCESS This driver is removed Controller.\r
- @retval other This driver was not removed from this device.\r
-\r
-**/\r
-// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-EFI_STATUS\r
-EFIAPI\r
-UndiDriverStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN AllChildrenStopped;\r
- UINTN Index;\r
- UNDI32_DEV *UNDI32Device;\r
- EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;\r
-\r
- //\r
- // Complete all outstanding transactions to Controller.\r
- // Don't allow any new transaction to Controller to be started.\r
- //\r
- if (NumberOfChildren == 0) {\r
-\r
- //\r
- // Close the bus driver\r
- //\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
- }\r
-\r
- AllChildrenStopped = TRUE;\r
-\r
- for (Index = 0; Index < NumberOfChildren; Index++) {\r
-\r
- Status = gBS->OpenProtocol (\r
- ChildHandleBuffer[Index],\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- (VOID **) &NIIProtocol,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-\r
- UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);\r
-\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ChildHandleBuffer[Index]\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- ChildHandleBuffer[Index],\r
- &gEfiDevicePathProtocolGuid,\r
- UNDI32Device->Undi32DevPath,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- &UNDI32Device->NIIProtocol_31,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- Status = UNDI32Device->NicInfo.Io_Function->Attributes (\r
- UNDI32Device->NicInfo.Io_Function,\r
- EfiPciIoAttributeOperationSet,\r
- UNDI32Device->NicInfo.OriginalPciAttributes,\r
- NULL\r
- );\r
-\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- gBS->FreePool (UNDI32Device->Undi32DevPath);\r
- gBS->FreePool (UNDI32Device);\r
-\r
- }\r
- }\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- AllChildrenStopped = FALSE;\r
- }\r
- }\r
-\r
- if (!AllChildrenStopped) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-/**\r
- Use the EFI boot services to produce a pause. This is also the routine which\r
- gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can\r
- do it's own pause.\r
-\r
- @param UnqId Runtime O/S routine might use this, this temp\r
- routine does not use it\r
- @param MicroSeconds Determines the length of pause.\r
-\r
- @return none\r
-\r
-**/\r
-VOID\r
-TmpDelay (\r
- IN UINT64 UnqId,\r
- IN UINTN MicroSeconds\r
- )\r
-{\r
- gBS->Stall ((UINT32) MicroSeconds);\r
-}\r
-\r
-\r
-/**\r
- Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which\r
- gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.\r
-\r
- @param UnqId Runtime O/S routine may use this field, this temp\r
- routine does not.\r
- @param ReadWrite Determine if it is an I/O or Memory Read/Write\r
- Operation.\r
- @param Len Determines the width of the data operation.\r
- @param Port What port to Read/Write from.\r
- @param BuffAddr Address to read to or write from.\r
-\r
- @return none\r
-\r
-**/\r
-VOID\r
-TmpMemIo (\r
- IN UINT64 UnqId,\r
- IN UINT8 ReadWrite,\r
- IN UINT8 Len,\r
- IN UINT64 Port,\r
- IN UINT64 BuffAddr\r
- )\r
-{\r
- EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
- NIC_DATA_INSTANCE *AdapterInfo;\r
-\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;\r
- AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;\r
- switch (Len) {\r
- case 2:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;\r
- break;\r
-\r
- case 4:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;\r
- break;\r
-\r
- case 8:\r
- Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;\r
- break;\r
- }\r
-\r
- switch (ReadWrite) {\r
- case PXE_IO_READ:\r
- AdapterInfo->Io_Function->Io.Read (\r
- AdapterInfo->Io_Function,\r
- Width,\r
- 1,\r
- Port,\r
- 1,\r
- (VOID *) (UINTN) (BuffAddr)\r
- );\r
- break;\r
-\r
- case PXE_IO_WRITE:\r
- AdapterInfo->Io_Function->Io.Write (\r
- AdapterInfo->Io_Function,\r
- Width,\r
- 1,\r
- Port,\r
- 1,\r
- (VOID *) (UINTN) (BuffAddr)\r
- );\r
- break;\r
-\r
- case PXE_MEM_READ:\r
- AdapterInfo->Io_Function->Mem.Read (\r
- AdapterInfo->Io_Function,\r
- Width,\r
- 0,\r
- Port,\r
- 1,\r
- (VOID *) (UINTN) (BuffAddr)\r
- );\r
- break;\r
-\r
- case PXE_MEM_WRITE:\r
- AdapterInfo->Io_Function->Mem.Write (\r
- AdapterInfo->Io_Function,\r
- Width,\r
- 0,\r
- Port,\r
- 1,\r
- (VOID *) (UINTN) (BuffAddr)\r
- );\r
- break;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space\r
- for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)\r
- and an added MAC node.\r
-\r
- @param DevPtr Pointer which will point to the newly created device\r
- path with the MAC node attached.\r
- @param BaseDevPtr Pointer to the device path which the UNDI device\r
- driver is latching on to.\r
- @param AdapterInfo Pointer to the NIC data structure information which\r
- the UNDI driver is layering on..\r
-\r
- @retval EFI_SUCCESS A MAC address was successfully appended to the Base\r
- Device Path.\r
- @retval other Not enough resources available to create new Device\r
- Path node.\r
-\r
-**/\r
-EFI_STATUS\r
-AppendMac2DevPath (\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,\r
- IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,\r
- IN NIC_DATA_INSTANCE *AdapterInfo\r
- )\r
-{\r
- EFI_MAC_ADDRESS MACAddress;\r
- PCI_CONFIG_HEADER *CfgHdr;\r
- INT32 Val;\r
- INT32 Index;\r
- INT32 Index2;\r
- UINT8 AddrLen;\r
- MAC_ADDR_DEVICE_PATH MacAddrNode;\r
- EFI_DEVICE_PATH_PROTOCOL *EndNode;\r
- UINT8 *DevicePtr;\r
- UINT16 TotalPathLen;\r
- UINT16 BasePathLen;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // set the environment ready (similar to UNDI_Start call) so that we can\r
- // execute the other UNDI_ calls to get the mac address\r
- // we are using undi 3.1 style\r
- //\r
- AdapterInfo->Delay = TmpDelay;\r
- AdapterInfo->Virt2Phys = (VOID *) 0;\r
- AdapterInfo->Block = (VOID *) 0;\r
- AdapterInfo->Map_Mem = (VOID *) 0;\r
- AdapterInfo->UnMap_Mem = (VOID *) 0;\r
- AdapterInfo->Sync_Mem = (VOID *) 0;\r
- AdapterInfo->Mem_Io = TmpMemIo;\r
- //\r
- // these tmp call-backs follow 3.1 undi style\r
- // i.e. they have the unique_id parameter.\r
- //\r
- AdapterInfo->VersionFlag = 0x31;\r
- AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;\r
-\r
- //\r
- // undi init portion\r
- //\r
- CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);\r
- AdapterInfo->ioaddr = 0;\r
- AdapterInfo->RevID = CfgHdr->RevID;\r
-\r
- AddrLen = E100bGetEepromAddrLen (AdapterInfo);\r
-\r
- for (Index = 0, Index2 = 0; Index < 3; Index++) {\r
- Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);\r
- MACAddress.Addr[Index2++] = (UINT8) Val;\r
- MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);\r
- }\r
-\r
- SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);\r
- //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {\r
- // MACAddress.Addr[Index2] = 0;\r
- //}\r
- //\r
- // stop undi\r
- //\r
- AdapterInfo->Delay = (VOID *) 0;\r
- AdapterInfo->Mem_Io = (VOID *) 0;\r
-\r
- //\r
- // fill the mac address node first\r
- //\r
- ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);\r
- CopyMem (\r
- (CHAR8 *) &MacAddrNode.MacAddress,\r
- (CHAR8 *) &MACAddress,\r
- sizeof (EFI_MAC_ADDRESS)\r
- );\r
-\r
- MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;\r
- MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;\r
- MacAddrNode.Header.Length[0] = (UINT8) sizeof (MacAddrNode);\r
- MacAddrNode.Header.Length[1] = 0;\r
-\r
- //\r
- // find the size of the base dev path.\r
- //\r
- EndNode = BaseDevPtr;\r
-\r
- while (!IsDevicePathEnd (EndNode)) {\r
- EndNode = NextDevicePathNode (EndNode);\r
- }\r
-\r
- BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));\r
-\r
- //\r
- // create space for full dev path\r
- //\r
- TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-\r
- Status = gBS->AllocatePool (\r
- EfiRuntimeServicesData,\r
- TotalPathLen,\r
- (VOID **) &DevicePtr\r
- );\r
-\r
- if (Status != EFI_SUCCESS) {\r
- return Status;\r
- }\r
- //\r
- // copy the base path, mac addr and end_dev_path nodes\r
- //\r
- *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;\r
- CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);\r
- DevicePtr += BasePathLen;\r
- CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));\r
- DevicePtr += sizeof (MacAddrNode);\r
- CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Install a GUID/Pointer pair into the system's configuration table.\r
-\r
- none\r
-\r
- @retval EFI_SUCCESS Install a GUID/Pointer pair into the system's\r
- configuration table.\r
- @retval other Did not successfully install the GUID/Pointer pair\r
- into the configuration table.\r
-\r
-**/\r
-// TODO: VOID - add argument and description to function comment\r
-EFI_STATUS\r
-InstallConfigTable (\r
- IN VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_CONFIGURATION_TABLE *CfgPtr;\r
- UNDI_CONFIG_TABLE *TmpData;\r
- UINT16 Index;\r
- UNDI_CONFIG_TABLE *UndiData;\r
-\r
- if (pxe_31 == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if(UndiDataPointer == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- UndiData = (UNDI_CONFIG_TABLE *)UndiDataPointer;\r
-\r
- UndiData->NumberOfInterfaces = (pxe_31->IFcnt | pxe_31->IFcntExt << 8);\r
- UndiData->nextlink = NULL;\r
-\r
- for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {\r
- UndiData->NII_entry[Index].NII_InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;\r
- UndiData->NII_entry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;\r
- }\r
-\r
- //\r
- // see if there is an entry in the config table already\r
- //\r
- CfgPtr = gST->ConfigurationTable;\r
-\r
- for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
- Status = CompareGuid (\r
- &CfgPtr->VendorGuid,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- break;\r
- }\r
-\r
- CfgPtr++;\r
- }\r
-\r
- if (Index < gST->NumberOfTableEntries) {\r
- TmpData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;\r
-\r
- //\r
- // go to the last link\r
- //\r
- while (TmpData->nextlink != NULL) {\r
- TmpData = TmpData->nextlink;\r
- }\r
-\r
- TmpData->nextlink = UndiData;\r
-\r
- //\r
- // 1st one in chain\r
- //\r
- UndiData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;\r
- }\r
-\r
- //\r
- // create an entry in the configuration table for our GUID\r
- //\r
- Status = gBS->InstallConfigurationTable (\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- UndiData\r
- );\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeUndi(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_EVENT Event;\r
- EFI_STATUS Status;\r
-\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gUndiDriverBinding,\r
- ImageHandle,\r
- &gUndiComponentName,\r
- &gUndiComponentName2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- UndiNotifyReadyToBoot,\r
- NULL,\r
- &gEfiEventReadyToBootGuid,\r
- &Event\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- UndiNotifyVirtual,\r
- NULL,\r
- &gEfiEventVirtualAddressChangeGuid,\r
- &Event\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r