From: niruiyu Date: Thu, 19 Aug 2010 02:40:27 +0000 (+0000) Subject: Check in the IsaIoDxe device driver that consumes EFI_SIO_PROTOCOL to produce EFI_ISA... X-Git-Tag: edk2-stable201903~15591 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=558be4559ac1fba1a81b483c90d00680a18640ff;ds=sidebyside Check in the IsaIoDxe device driver that consumes EFI_SIO_PROTOCOL to produce EFI_ISA_IO_PROTOCOL. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10808 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c new file mode 100644 index 0000000000..e4e77a916b --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.c @@ -0,0 +1,182 @@ +/** @file + UEFI Component Name(2) protocol implementation for Isa driver. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "IsaDriver.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName = { + IsaIoComponentNameGetDriverName, + IsaIoComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaIoComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaIoComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIsaIoDriverNameTable[] = { + { + "eng;en", + L"ISA IO Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mIsaIoDriverNameTable, + DriverName, + (BOOLEAN)(This == &gIsaIoComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h new file mode 100644 index 0000000000..7c52119002 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/ComponentName.h @@ -0,0 +1,148 @@ +/** @file + Header file for implementation of UEFI Component Name(2) protocol. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_H_ + +extern EFI_COMPONENT_NAME_PROTOCOL gIsaIoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gIsaIoComponentName2; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +IsaIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c new file mode 100644 index 0000000000..a9252f0486 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.c @@ -0,0 +1,339 @@ +/** @file + IsaIo UEFI driver. + + Produce an instance of the ISA I/O Protocol for every SIO controller. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "IsaDriver.h" + +// +// IsaIo Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gIsaIoDriver = { + IsaIoDriverSupported, + IsaIoDriverStart, + IsaIoDriverStop, + 0xa, + NULL, + NULL +}; + +/** + The main entry point for the IsaIo driver. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. +**/ +EFI_STATUS +EFIAPI +InitializeIsaIo ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gIsaIoDriver, + ImageHandle, + &gIsaIoComponentName, + &gIsaIoComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Tests to see if a controller can be managed by the IsaIo driver. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaIoDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIO_PROTOCOL *Sio; + EFI_HANDLE PciHandle; + + // + // Try to open EFI DEVICE PATH protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + // + // Get the PciIo protocol from its parent controller. + // + Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle); + if (!EFI_ERROR (Status)) { + if ((DevicePathType (DevicePath) != ACPI_DEVICE_PATH) || + ((DevicePathSubType (DevicePath) != ACPI_DP) && (DevicePathSubType (DevicePath) != ACPI_EXTENDED_DP))) { + Status = EFI_UNSUPPORTED; + } + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Try to open the Super IO protocol on the controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSioProtocolGuid, + (VOID **) &Sio, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiSioProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +/** + Start this driver on ControllerHandle. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE PciHandle; + EFI_SIO_PROTOCOL *Sio; + ACPI_RESOURCE_HEADER_PTR Resources; + EFI_DEVICE_PATH_PROTOCOL *AcpiNode; + ISA_IO_DEVICE *IsaIoDevice; + + PciIo = NULL; + Sio = NULL; + + // + // Open Device Path Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the PciIo protocol from its parent controller. + // + AcpiNode = DevicePath; + Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &AcpiNode, &PciHandle); + if (!EFI_ERROR (Status)) { + // + // AcpiNode should point to the ACPI node now. + // + ASSERT ((DevicePathType (AcpiNode) == ACPI_DEVICE_PATH) && + ((DevicePathSubType (AcpiNode) == ACPI_DP) || (DevicePathSubType (AcpiNode) == ACPI_EXTENDED_DP)) + ); + + Status = gBS->HandleProtocol (PciHandle, &gEfiPciIoProtocolGuid, &PciIo); + ASSERT_EFI_ERROR (Status); + + // + // Open Super IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSioProtocolGuid, + (VOID **) &Sio, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + } + + if (EFI_ERROR (Status)) { + // + // Fail due to LocateDevicePath(...) or OpenProtocol(Sio, BY_DRIVER) + // + return Status; + } + + Status = Sio->GetResources (Sio, &Resources); + ASSERT_EFI_ERROR (Status); + + IsaIoDevice = AllocatePool (sizeof (ISA_IO_DEVICE)); + ASSERT (IsaIoDevice != NULL); + + IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE; + IsaIoDevice->PciIo = PciIo; + + // + // Initialize the ISA I/O instance structure + // + InitializeIsaIoInstance (IsaIoDevice, DevicePath, Resources); + + // + // Install the ISA I/O protocol on the Controller handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + EFI_ISA_IO_PROTOCOL *IsaIo; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiIsaIoProtocolGuid, + &IsaIoDevice->IsaIo, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->CloseProtocol ( + Controller, + &gEfiSioProtocolGuid, + This->DriverBindingHandle, + Controller + ); + FreePool (IsaIoDevice->IsaIo.ResourceList); + FreePool (IsaIoDevice); + } + + return Status; +} \ No newline at end of file diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h new file mode 100644 index 0000000000..64f710bcec --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaDriver.h @@ -0,0 +1,263 @@ +/** @file + The header file for ISA driver + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ISA_DRIVER_H_ +#define _ISA_DRIVER_H_ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ComponentName.h" + +// +// 8237 DMA registers +// +#define R_8237_DMA_BASE_CA_CH0 0x00 +#define R_8237_DMA_BASE_CA_CH1 0x02 +#define R_8237_DMA_BASE_CA_CH2 0x04 +#define R_8237_DMA_BASE_CA_CH3 0xd6 +#define R_8237_DMA_BASE_CA_CH5 0xc4 +#define R_8237_DMA_BASE_CA_CH6 0xc8 +#define R_8237_DMA_BASE_CA_CH7 0xcc + +#define R_8237_DMA_BASE_CC_CH0 0x01 +#define R_8237_DMA_BASE_CC_CH1 0x03 +#define R_8237_DMA_BASE_CC_CH2 0x05 +#define R_8237_DMA_BASE_CC_CH3 0xd7 +#define R_8237_DMA_BASE_CC_CH5 0xc6 +#define R_8237_DMA_BASE_CC_CH6 0xca +#define R_8237_DMA_BASE_CC_CH7 0xce + +#define R_8237_DMA_MEM_LP_CH0 0x87 +#define R_8237_DMA_MEM_LP_CH1 0x83 +#define R_8237_DMA_MEM_LP_CH2 0x81 +#define R_8237_DMA_MEM_LP_CH3 0x82 +#define R_8237_DMA_MEM_LP_CH5 0x8B +#define R_8237_DMA_MEM_LP_CH6 0x89 +#define R_8237_DMA_MEM_LP_CH7 0x8A + + +#define R_8237_DMA_COMMAND_CH0_3 0x08 +#define R_8237_DMA_COMMAND_CH4_7 0xd0 +#define B_8237_DMA_COMMAND_GAP 0x10 +#define B_8237_DMA_COMMAND_CGE 0x04 + + +#define R_8237_DMA_STA_CH0_3 0xd8 +#define R_8237_DMA_STA_CH4_7 0xd0 + +#define R_8237_DMA_WRSMSK_CH0_3 0x0a +#define R_8237_DMA_WRSMSK_CH4_7 0xd4 +#define B_8237_DMA_WRSMSK_CMS 0x04 + + +#define R_8237_DMA_CHMODE_CH0_3 0x0b +#define R_8237_DMA_CHMODE_CH4_7 0xd6 +#define V_8237_DMA_CHMODE_DEMAND 0x00 +#define V_8237_DMA_CHMODE_SINGLE 0x40 +#define V_8237_DMA_CHMODE_CASCADE 0xc0 +#define B_8237_DMA_CHMODE_DECREMENT 0x20 +#define B_8237_DMA_CHMODE_INCREMENT 0x00 +#define B_8237_DMA_CHMODE_AE 0x10 +#define V_8237_DMA_CHMODE_VERIFY 0 +#define V_8237_DMA_CHMODE_IO2MEM 0x04 +#define V_8237_DMA_CHMODE_MEM2IO 0x08 + +#define R_8237_DMA_CBPR_CH0_3 0x0c +#define R_8237_DMA_CBPR_CH4_7 0xd8 + +#define R_8237_DMA_MCR_CH0_3 0x0d +#define R_8237_DMA_MCR_CH4_7 0xda + +#define R_8237_DMA_CLMSK_CH0_3 0x0e +#define R_8237_DMA_CLMSK_CH4_7 0xdc + +#define R_8237_DMA_WRMSK_CH0_3 0x0f +#define R_8237_DMA_WRMSK_CH4_7 0xde + +typedef enum { + IsaAccessTypeUnknown, + IsaAccessTypeIo, + IsaAccessTypeMem, + IsaAccessTypeMaxType +} ISA_ACCESS_TYPE; + +typedef struct { + UINT8 Address; + UINT8 Page; + UINT8 Count; +} EFI_ISA_DMA_REGISTERS; + +// +// ISA I/O Device Structure +// +#define ISA_IO_DEVICE_SIGNATURE SIGNATURE_32 ('i', 's', 'a', 'i') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_ISA_IO_PROTOCOL IsaIo; + EFI_PCI_IO_PROTOCOL *PciIo; +} ISA_IO_DEVICE; + +#define ISA_IO_DEVICE_FROM_ISA_IO_THIS(a) CR (a, ISA_IO_DEVICE, IsaIo, ISA_IO_DEVICE_SIGNATURE) + +// +// Mapping structure for performing ISA DMA to a buffer above 16 MB +// +typedef struct { + EFI_ISA_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} ISA_MAP_INFO; + +// +// EFI Driver Binding Protocol Interface Functions +// + +/** + Tests to see if a controller can be managed by the ISA Driver. + + How the Start() function of a driver is implemented can affect how the Supported() function is implemented. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] Controller The handle of the controller to test. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + + @retval EFI_SUCCESS The device is supported by this driver. + @retval EFI_ALREADY_STARTED The device is already being managed by this driver. + @retval EFI_ACCESS_DENIED The device is already being managed by a different driver + or an application that requires exclusive access. + @retval EFI_UNSUPPORTED The device is is not supported by this driver. + +**/ +EFI_STATUS +EFIAPI +IsaIoDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Start this driver on ControllerHandle. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, but the following calling + restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. + This parameter is ignored by device drivers, and is optional for bus drivers. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error. + Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stop this driver on ControllerHandle. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +IsaIoDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer OPTIONAL + ); + +// +// Function Prototypes +// + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The isa device to be initialized. + @param[in] DevicePath The device path of the isa device. + @param[in] Resources The ACPI resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN ACPI_RESOURCE_HEADER_PTR Resources + ); + +#endif + diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c new file mode 100644 index 0000000000..9058d7849e --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.c @@ -0,0 +1,1796 @@ +/** @file + The implementation for EFI_ISA_IO_PROTOCOL. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "IsaIo.h" + +// +// Module Variables +// +EFI_ISA_IO_PROTOCOL mIsaIoInterface = { + { + IsaIoMemRead, + IsaIoMemWrite + }, + { + IsaIoIoRead, + IsaIoIoWrite + }, + IsaIoCopyMem, + IsaIoMap, + IsaIoUnmap, + IsaIoAllocateBuffer, + IsaIoFreeBuffer, + IsaIoFlush, + NULL, + 0, + NULL +}; + +EFI_ISA_DMA_REGISTERS mDmaRegisters[8] = { + { + 0x00, + 0x87, + 0x01 + }, + { + 0x02, + 0x83, + 0x03 + }, + { + 0x04, + 0x81, + 0x05 + }, + { + 0x06, + 0x82, + 0x07 + }, + { + 0x00, + 0x00, + 0x00 + }, // Channel 4 is invalid + { + 0xC4, + 0x8B, + 0xC6 + }, + { + 0xC8, + 0x89, + 0xCA + }, + { + 0xCC, + 0x8A, + 0xCE + }, +}; + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ) +{ + EFI_ISA_ACPI_RESOURCE *Item; + EFI_STATUS Status; + + if (Width < EfiIsaIoWidthUint8 || + Width >= EfiIsaIoWidthMaximum || + Width == EfiIsaIoWidthReserved || + Width == EfiIsaIoWidthFifoReserved || + Width == EfiIsaIoWidthFillReserved + ) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiIsaIoWidthFifoUintX then convert to EfiIsaIoWidthUintX + // If Width is EfiIsaIoWidthFillUintX then convert to EfiIsaIoWidthUintX + // + if (Width >= EfiIsaIoWidthFifoUint8 && Width < EfiIsaIoWidthFifoReserved) { + Count = 1; + } + + Width = (EFI_ISA_IO_PROTOCOL_WIDTH) (Width & 0x03); + + Status = EFI_UNSUPPORTED; + Item = IsaIoDevice->IsaIo.ResourceList->ResourceItem; + while (Item->Type != EfiIsaAcpiResourceEndOfList) { + if ((Type == IsaAccessTypeMem && Item->Type == EfiIsaAcpiResourceMemory) || + (Type == IsaAccessTypeIo && Item->Type == EfiIsaAcpiResourceIo)) { + if (Offset >= Item->StartRange && (Offset + Count * (UINT32)(1 << Width)) - 1 <= Item->EndRange) { + return EFI_SUCCESS; + } + + if (Offset >= Item->StartRange && Offset <= Item->EndRange) { + Status = EFI_INVALID_PARAMETER; + } + } + + Item++; + } + + return Status; +} + +/** + Convert the IO Information in ACPI descriptor to IO ISA Attribute. + + @param[in] Information The IO Information in ACPI descriptor + + @return UINT32 The IO ISA Attribute +**/ +UINT32 +IsaIoAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + switch (Information & EFI_ACPI_IO_DECODE_MASK) { + case EFI_ACPI_IO_DECODE_16_BIT: + Attribute |= EFI_ISA_ACPI_IO_DECODE_16_BITS; + break; + + case EFI_ACPI_IO_DECODE_10_BIT: + Attribute |= EFI_ISA_ACPI_IO_DECODE_10_BITS; + break; + } + + return Attribute; +} + +/** + Convert the IRQ Information in ACPI descriptor to IRQ ISA Attribute. + + @param[in] Information The IRQ Information in ACPI descriptor + + @return UINT32 The IRQ ISA Attribute +**/ +UINT32 +IsaIrqAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + if ((Information & EFI_ACPI_IRQ_POLARITY_MASK) == EFI_ACPI_IRQ_HIGH_TRUE) { + if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE; + } else { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; + } + } else { + if ((Information & EFI_ACPI_IRQ_MODE) == EFI_ACPI_IRQ_LEVEL_TRIGGERED) { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE; + } else { + Attribute = EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE; + } + } + return Attribute; +} + +/** + Convert the Memory Information in ACPI descriptor to Memory ISA Attribute. + + @param[in] Information The Memory Information in ACPI descriptor + + @return UINT32 The Memory ISA Attribute +**/ +UINT32 +IsaMemoryAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = 0; + + switch (Information & EFI_ACPI_MEMORY_WRITE_STATUS_MASK) { + case EFI_ACPI_MEMORY_WRITABLE: + Attribute |= EFI_ISA_ACPI_MEMORY_WRITEABLE; + break; + } + + return Attribute; +} + +/** + Convert the DMA Information in ACPI descriptor to DMA ISA Attribute. + + @param[in] Information The DMA Information in ACPI descriptor + + @return UINT32 The DMA ISA Attribute +**/ +UINT32 +IsaDmaAttribute ( + IN UINT8 Information + ) +{ + UINT32 Attribute; + + Attribute = EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE; + + switch (Information & EFI_ACPI_DMA_SPEED_TYPE_MASK) { + case EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE; + break; + case EFI_ACPI_DMA_SPEED_TYPE_A: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A; + break; + case EFI_ACPI_DMA_SPEED_TYPE_B: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B; + break; + case EFI_ACPI_DMA_SPEED_TYPE_F: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C; + break; + } + + switch (Information & EFI_ACPI_DMA_TRANSFER_TYPE_MASK) { + case EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8; + break; + case EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT: + Attribute |= EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16; + break; + } + + return Attribute; +} + +/** + Convert the ACPI resource descriptor to ISA resource descriptor. + + @param[in] AcpiResource Pointer to the ACPI resource descriptor + @param[out] IsaResource The optional pointer to the buffer to + store the converted ISA resource descriptor + + @return UINTN Number of ISA resource descriptor needed +**/ +UINTN +AcpiResourceToIsaResource ( + IN ACPI_RESOURCE_HEADER_PTR AcpiResource, + OUT EFI_ISA_ACPI_RESOURCE *IsaResource OPTIONAL + ) +{ + UINT32 Index; + UINTN Count; + UINT32 LastIndex; + EFI_ACPI_IO_PORT_DESCRIPTOR *Io; + EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo; + EFI_ACPI_IRQ_DESCRIPTOR *Irq; + EFI_ACPI_DMA_DESCRIPTOR *Dma; + EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *Memory; + EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *FixedMemory; + + Count = 0; + LastIndex = 0; + + switch (AcpiResource.SmallHeader->Byte) { + case ACPI_DMA_DESCRIPTOR: + Dma = (EFI_ACPI_DMA_DESCRIPTOR *) AcpiResource.SmallHeader; + for (Index = 0; Index < sizeof (Dma->ChannelMask) * 8; Index++) { + if (Dma->ChannelMask & (1 << Index)) { + if ((Count > 0) && (LastIndex + 1 == Index)) { + if (IsaResource != NULL) { + IsaResource[Count - 1].EndRange ++; + } + } else { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceDma; + IsaResource[Count].Attribute = IsaDmaAttribute (Dma->Information); + IsaResource[Count].StartRange = Index; + IsaResource[Count].EndRange = Index; + } + Count ++; + } + + LastIndex = Index; + } + } + break; + + case ACPI_IO_PORT_DESCRIPTOR: + Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceIo; + IsaResource[Count].Attribute = IsaIoAttribute (Io->Information); + IsaResource[Count].StartRange = Io->BaseAddressMin; + IsaResource[Count].EndRange = Io->BaseAddressMin + Io->Length - 1; + } + Count ++; + break; + + case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: + FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) AcpiResource.SmallHeader; + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceIo; + IsaResource[Count].Attribute = EFI_ISA_ACPI_IO_DECODE_10_BITS; + IsaResource[Count].StartRange = FixedIo->BaseAddress; + IsaResource[Count].EndRange = FixedIo->BaseAddress + FixedIo->Length - 1; + } + Count ++; + break; + + case ACPI_IRQ_DESCRIPTOR: + case ACPI_IRQ_NOFLAG_DESCRIPTOR: + Irq = (EFI_ACPI_IRQ_DESCRIPTOR *) AcpiResource.SmallHeader; + for (Index = 0; Index < sizeof (Irq->Mask) * 8; Index++) { + if (Irq->Mask & (1 << Index)) { + if ((Count > 0) && (LastIndex + 1 == Index)) { + if (IsaResource != NULL) { + IsaResource[Count - 1].EndRange ++; + } + } else { + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceInterrupt; + if (AcpiResource.SmallHeader->Byte == ACPI_IRQ_DESCRIPTOR) { + IsaResource[Count].Attribute = IsaIrqAttribute (Irq->Information); + } else { + IsaResource[Count].Attribute = EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE; + } + IsaResource[Count].StartRange = Index; + IsaResource[Count].EndRange = Index; + } + Count++; + } + + LastIndex = Index; + } + } + break; + + case ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR: + Memory = (EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceMemory; + IsaResource[Count].Attribute = IsaMemoryAttribute (Memory->Information); + IsaResource[Count].StartRange = Memory->BaseAddressMin; + IsaResource[Count].EndRange = Memory->BaseAddressMin + Memory->Length - 1; + } + Count ++; + break; + + case ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR: + FixedMemory = (EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR *) AcpiResource.LargeHeader; + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceMemory; + IsaResource[Count].Attribute = IsaMemoryAttribute (FixedMemory->Information); + IsaResource[Count].StartRange = FixedMemory->BaseAddress; + IsaResource[Count].EndRange = FixedMemory->BaseAddress + FixedMemory->Length - 1; + } + Count ++; + break; + + case ACPI_END_TAG_DESCRIPTOR: + if (IsaResource != NULL) { + IsaResource[Count].Type = EfiIsaAcpiResourceEndOfList; + IsaResource[Count].Attribute = 0; + IsaResource[Count].StartRange = 0; + IsaResource[Count].EndRange = 0; + } + Count ++; + break; + } + + return Count; +} + +/** + Initializes an ISA I/O Instance + + @param[in] IsaIoDevice The isa device to be initialized. + @param[in] DevicePath The device path of the isa device. + @param[in] Resources The ACPI resource list. + +**/ +VOID +InitializeIsaIoInstance ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN ACPI_RESOURCE_HEADER_PTR Resources + ) +{ + UINTN Index; + ACPI_HID_DEVICE_PATH *AcpiNode; + ACPI_RESOURCE_HEADER_PTR ResourcePtr; + + // + // Use the ISA IO Protocol structure template to initialize the ISA IO instance + // + CopyMem ( + &IsaIoDevice->IsaIo, + &mIsaIoInterface, + sizeof (EFI_ISA_IO_PROTOCOL) + ); + + // + // Count the resources including the ACPI End Tag + // + ResourcePtr = Resources; + Index = 0; + while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { + + Index += AcpiResourceToIsaResource (ResourcePtr, NULL); + + if (ResourcePtr.SmallHeader->Bits.Type == 0) { + ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader + + ResourcePtr.SmallHeader->Bits.Length + + sizeof (*ResourcePtr.SmallHeader)); + } else { + ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader + + ResourcePtr.LargeHeader->Length + + sizeof (*ResourcePtr.LargeHeader)); + } + + } + // + // Get the Isa Resource count for ACPI End Tag + // + Index += AcpiResourceToIsaResource (ResourcePtr, NULL); + + // + // Initialize the ResourceList + // + IsaIoDevice->IsaIo.ResourceList = AllocatePool (sizeof (EFI_ISA_ACPI_RESOURCE_LIST) + Index * sizeof (EFI_ISA_ACPI_RESOURCE)); + ASSERT (IsaIoDevice->IsaIo.ResourceList != NULL); + IsaIoDevice->IsaIo.ResourceList->ResourceItem = (EFI_ISA_ACPI_RESOURCE *) (IsaIoDevice->IsaIo.ResourceList + 1); + + AcpiNode = (ACPI_HID_DEVICE_PATH *) ((UINT8 *) DevicePath + GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH - sizeof (ACPI_HID_DEVICE_PATH)); + IsaIoDevice->IsaIo.ResourceList->Device.HID = AcpiNode->HID; + IsaIoDevice->IsaIo.ResourceList->Device.UID = AcpiNode->UID; + + ResourcePtr = Resources; + Index = 0; + while (ResourcePtr.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) { + + Index += AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); + + if (ResourcePtr.SmallHeader->Bits.Type == 0) { + ResourcePtr.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.SmallHeader + + ResourcePtr.SmallHeader->Bits.Length + + sizeof (*ResourcePtr.SmallHeader)); + } else { + ResourcePtr.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) ResourcePtr.LargeHeader + + ResourcePtr.LargeHeader->Length + + sizeof (*ResourcePtr.LargeHeader)); + } + } + + // + // Convert the ACPI End Tag + // + AcpiResourceToIsaResource (ResourcePtr, &IsaIoDevice->IsaIo.ResourceList->ResourceItem[Index]); +} + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeIo, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Io.Write ( + IsaIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + // + // Wait for 50 microseconds to take affect. + // + gBS->Stall (50); + + return EFI_SUCCESS; +} + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ) +{ + EFI_STATUS Status; + + Status = WritePort (This, AddrOffset, (UINT8) (BaseAddress & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, AddrOffset, (UINT8) ((BaseAddress >> 8) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, PageOffset, (UINT8) ((BaseAddress >> 16) & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) (Count & 0xff)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, CountOffset, (UINT8) ((Count >> 8) & 0xff)); + return Status; +} + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + ISA_MAP_INFO *IsaMapInfo; + + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + + // + // See if the Map() operation associated with this Unmap() required a mapping + // buffer.If a mapping buffer was not required, then this function simply + // returns EFI_SUCCESS. + // + if (Mapping != NULL) { + // + // Get the MAP_INFO structure from Mapping + // + IsaMapInfo = (ISA_MAP_INFO *) Mapping; + + // + // If this is a write operation from the Agent's point of view, + // then copy the contents of the mapped buffer into the real buffer + // so the processor can read the contents of the real buffer. + // + if (IsaMapInfo->Operation == EfiIsaIoOperationBusMasterWrite) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->HostAddress, + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // Free the mapped buffer and the MAP_INFO structure. + // + gBS->FreePages (IsaMapInfo->MappedHostAddress, IsaMapInfo->NumberOfPages); + FreePool (IsaMapInfo); + } + + return EFI_SUCCESS; +} + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + Status = IsaIoDevice->PciIo->Flush (IsaIoDevice->PciIo); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify the Isa Io Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Read ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + Offset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->Mem.Write ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ) +{ + EFI_STATUS Status; + ISA_IO_DEVICE *IsaIoDevice; + + // + // Check if ISA memory is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_ISA_MEMORY) == 0) { + return EFI_UNSUPPORTED; + } + + IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (This); + + // + // Verify Isa IO Access for destination and source + // + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + DestOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoVerifyAccess ( + IsaIoDevice, + IsaAccessTypeMem, + Width, + Count, + SrcOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IsaIoDevice->PciIo->CopyMem ( + IsaIoDevice->PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) Width, + EFI_PCI_IO_PASS_THROUGH_BAR, + DestOffset, + EFI_PCI_IO_PASS_THROUGH_BAR, + SrcOffset, + Count + ); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + +/** + Maps a memory region for DMA, note this implementation + only supports slave read/write operation to save code size. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapOnlySupportSlaveReadWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid. + // Light IsaIo only supports two operations. + // + if (!(Operation == EfiIsaIoOperationSlaveRead || + Operation == EfiIsaIoOperationSlaveWrite)) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 4) { + // + // The Light IsaIo doesn't support channelNumber larger than 4. + // + return EFI_INVALID_PARAMETER; + } + + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress + *NumberOfBytes) > BASE_16MB) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = BASE_16MB - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationSlaveRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Operation == EfiIsaIoOperationSlaveRead) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + // + // We only support EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE in simplified IsaIo + // + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA. This implementation implement the + the full mapping support. + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED - The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR - The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. +**/ +EFI_STATUS +IsaIoMapFullSupport ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + BOOLEAN Master; + BOOLEAN Read; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + ISA_MAP_INFO *IsaMapInfo; + UINT8 DmaMode; + UINTN MaxNumberOfBytes; + UINT32 BaseAddress; + UINT16 Count; + UINT8 DmaMask; + UINT8 DmaClear; + UINT8 DmaChannelMode; + + if ((NULL == This) || + (NULL == HostAddress) || + (NULL == NumberOfBytes) || + (NULL == DeviceAddress) || + (NULL == Mapping) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure the Operation parameter is valid + // + if (Operation < 0 || Operation >= EfiIsaIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber >= 8) { + return EFI_INVALID_PARAMETER; + } + + // + // See if this is a Slave DMA Operation + // + Master = TRUE; + Read = FALSE; + if (Operation == EfiIsaIoOperationSlaveRead) { + Operation = EfiIsaIoOperationBusMasterRead; + Master = FALSE; + Read = TRUE; + } + + if (Operation == EfiIsaIoOperationSlaveWrite) { + Operation = EfiIsaIoOperationBusMasterWrite; + Master = FALSE; + Read = FALSE; + } + + if (!Master) { + // + // Make sure that ChannelNumber is a valid channel number + // Channel 4 is used to cascade, so it is illegal. + // + if (ChannelNumber == 4 || ChannelNumber > 7) { + return EFI_INVALID_PARAMETER; + } + // + // This implementation only support COMPATIBLE DMA Transfers + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((ChannelAttributes & + (EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B | + EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C)) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (ChannelNumber < 4) { + // + // If this is Channel 0..3, then the width must be 8 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) == 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) != 0) + ) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // If this is Channel 4..7, then the width must be 16 bit + // + if (((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8) != 0) || + ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16) == 0)) { + return EFI_INVALID_PARAMETER; + } + } + // + // Either Demand Mode or Single Mode must be selected, but not both + // + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + return EFI_INVALID_PARAMETER; + } + } else { + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) == 0) { + return EFI_INVALID_PARAMETER; + } + } + } + // + // Map the HostAddress to a DeviceAddress. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress; + if ((PhysicalAddress +*NumberOfBytes) > BASE_16MB) { + // + // Common Buffer operations can not be remapped. If the common buffer + // is above 16MB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiIsaIoOperationBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + // + // Allocate an ISA_MAP_INFO structure to remember the mapping when Unmap() + // is called later. + // + IsaMapInfo = AllocatePool (sizeof (ISA_MAP_INFO)); + if (IsaMapInfo == NULL) { + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = IsaMapInfo; + + // + // Initialize the MAP_INFO structure + // + IsaMapInfo->Operation = Operation; + IsaMapInfo->NumberOfBytes = *NumberOfBytes; + IsaMapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + IsaMapInfo->HostAddress = PhysicalAddress; + IsaMapInfo->MappedHostAddress = BASE_16MB - 1; + + // + // Allocate a buffer below 16MB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + IsaMapInfo->NumberOfPages, + &IsaMapInfo->MappedHostAddress + ); + if (EFI_ERROR (Status)) { + FreePool (IsaMapInfo); + *NumberOfBytes = 0; + *Mapping = NULL; + return Status; + } + // + // If this is a read operation from the DMA agents's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the DMA agent can read the contents of the real buffer. + // + if (Operation == EfiIsaIoOperationBusMasterRead) { + CopyMem ( + (VOID *) (UINTN) IsaMapInfo->MappedHostAddress, + (VOID *) (UINTN) IsaMapInfo->HostAddress, + IsaMapInfo->NumberOfBytes + ); + } + // + // The DeviceAddress is the address of the maped buffer below 16 MB + // + *DeviceAddress = IsaMapInfo->MappedHostAddress; + } else { + // + // The transfer is below 16 MB, so the DeviceAddress is simply the + // HostAddress + // + *DeviceAddress = PhysicalAddress; + } + // + // If this is a Bus Master operation then return + // + if (Master) { + return EFI_SUCCESS; + } + // + // Figure out what to program into the DMA Channel Mode Register + // + DmaMode = (UINT8) (B_8237_DMA_CHMODE_INCREMENT | (ChannelNumber & 0x03)); + if (Read) { + DmaMode |= V_8237_DMA_CHMODE_MEM2IO; + } else { + DmaMode |= V_8237_DMA_CHMODE_IO2MEM; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE) != 0) { + DmaMode |= B_8237_DMA_CHMODE_AE; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_DEMAND; + } + + if ((ChannelAttributes & EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE) != 0) { + DmaMode |= V_8237_DMA_CHMODE_SINGLE; + } + // + // A Slave DMA transfer can not cross a 64K boundary. + // Compute *NumberOfBytes based on this restriction. + // + MaxNumberOfBytes = 0x10000 - ((UINT32) (*DeviceAddress) & 0xffff); + if (*NumberOfBytes > MaxNumberOfBytes) { + *NumberOfBytes = MaxNumberOfBytes; + } + // + // Compute the values to program into the BaseAddress and Count registers + // of the Slave DMA controller + // + if (ChannelNumber < 4) { + BaseAddress = (UINT32) (*DeviceAddress); + Count = (UINT16) (*NumberOfBytes - 1); + } else { + BaseAddress = (UINT32) (((UINT32) (*DeviceAddress) & 0xff0000) | (((UINT32) (*DeviceAddress) & 0xffff) >> 1)); + Count = (UINT16) ((*NumberOfBytes - 1) >> 1); + } + // + // Program the DMA Write Single Mask Register for ChannelNumber + // Clear the DMA Byte Pointer Register + // + if (ChannelNumber < 4) { + DmaMask = R_8237_DMA_WRSMSK_CH0_3; + DmaClear = R_8237_DMA_CBPR_CH0_3; + DmaChannelMode = R_8237_DMA_CHMODE_CH0_3; + } else { + DmaMask = R_8237_DMA_WRSMSK_CH4_7; + DmaClear = R_8237_DMA_CBPR_CH4_7; + DmaChannelMode = R_8237_DMA_CHMODE_CH4_7; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaClear, + (UINT8) (B_8237_DMA_WRSMSK_CMS | (ChannelNumber & 0x03)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort (This, DmaChannelMode, DmaMode); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteDmaPort ( + This, + mDmaRegisters[ChannelNumber].Address, + mDmaRegisters[ChannelNumber].Page, + mDmaRegisters[ChannelNumber].Count, + BaseAddress, + Count + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WritePort ( + This, + DmaMask, + (UINT8) (ChannelNumber & 0x03) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + // + // Check if DMA is supported. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) { + return EFI_UNSUPPORTED; + } + // + // Set Feature Flag PcdIsaBusSupportBusMaster to FALSE to disable support for + // ISA Bus Master. + // + // So we just return EFI_UNSUPPORTED for these functions. + // + if ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0) { + return IsaIoMapOnlySupportSlaveReadWrite ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + } else { + return IsaIoMapFullSupport ( + This, + Operation, + ChannelNumber, + ChannelAttributes, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } +} + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Type < AllocateAnyPages || Type >= MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { + return EFI_INVALID_PARAMETER; + } + + if ((Attributes & ~(EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED)) != 0) { + return EFI_UNSUPPORTED; + } + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (BASE_16MB - 1); + if (Type == AllocateAddress) { + if ((UINTN) (*HostAddress) >= BASE_16MB) { + return EFI_UNSUPPORTED; + } else { + PhysicalAddress = (UINTN) (*HostAddress); + } + } + + if (Type == AllocateAnyPages) { + Type = AllocateMaxAddress; + } + + Status = gBS->AllocatePages (Type, MemoryType, Pages, &PhysicalAddress); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + return Status; + } + + *HostAddress = (VOID *) (UINTN) PhysicalAddress; + return Status; +} + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + EFI_STATUS Status; + + // + // Set Feature Flag PcdIsaBusOnlySupportSlaveDma to FALSE to disable support for + // ISA Bus Master. + // Or unset Feature Flag PcdIsaBusSupportDma to disable support for ISA DMA. + // + if (((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_SUPPORT_DMA) == 0) || + ((PcdGet8 (PcdIsaBusSupportedFeatures) & PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA) != 0)) { + return EFI_UNSUPPORTED; + } + + Status = gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, + Pages + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_LPC | EFI_IOB_EC_CONTROLLER_ERROR + ); + } + + return Status; +} + diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h new file mode 100644 index 0000000000..cc4a1f8b80 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIo.h @@ -0,0 +1,331 @@ +/** @file + The header file for EFI_ISA_IO protocol implementation. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ISA_IO_H_ +#define _ISA_IO_H_ + +#include "IsaDriver.h" + +// +// Bits definition of PcdIsaBusSupportedFeatures +// +#define PCD_ISA_BUS_SUPPORT_DMA BIT0 +#define PCD_ISA_BUS_ONLY_SUPPORT_SLAVE_DMA BIT1 +#define PCD_ISA_BUS_SUPPORT_ISA_MEMORY BIT2 + +// +// ISA I/O Support Function Prototypes +// + +/** + Verifies access to an ISA device + + @param[in] IsaIoDevice The ISA device to be verified. + @param[in] Type The Access type. The input must be either IsaAccessTypeMem or IsaAccessTypeIo. + @param[in] Width The width of the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Offset The offset in ISA memory space to start the memory operation. + + @retval EFI_SUCCESS Verify success. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The device ont support the access type. +**/ +EFI_STATUS +IsaIoVerifyAccess ( + IN ISA_IO_DEVICE *IsaIoDevice, + IN ISA_ACCESS_TYPE Type, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT32 Offset + ); + +/** + Performs an ISA I/O Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Performs an ISA I/O Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O operation. + @param[in] Offset The offset in ISA I/O space to start the I/O operation. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was writen to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoIoWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Maps a memory region for DMA + + @param This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param Operation Indicates the type of DMA (slave or bus master), and if + the DMA operation is going to read or write to system memory. + @param ChannelNumber The slave channel number to use for this DMA operation. + If Operation and ChannelAttributes shows that this device + performs bus mastering DMA, then this field is ignored. + The legal range for this field is 0..7. + @param ChannelAttributes The attributes of the DMA channel to use for this DMA operation + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input the number of bytes to map. On output the number + of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use + to access the hosts HostAddress. + @param Mapping A resulting value to pass to EFI_ISA_IO.Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a common buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoMap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Unmaps a memory region for DMA + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO.Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +EFIAPI +IsaIoUnmap ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Flushes any posted write data to the system memory. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. +**/ +EFI_STATUS +EFIAPI +IsaIoFlush ( + IN EFI_ISA_IO_PROTOCOL *This + ); + +/** + Writes I/O operation base address and count number to a 8 bit I/O Port. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] AddrOffset The address' offset. + @param[in] PageOffset The page's offest. + @param[in] CountOffset The count's offset. + @param[in] BaseAddress The base address. + @param[in] Count The number of I/O operations to perform. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by these Offsets and Count is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WriteDmaPort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 AddrOffset, + IN UINT32 PageOffset, + IN UINT32 CountOffset, + IN UINT32 BaseAddress, + IN UINT16 Count + ); + +/** + Writes an 8-bit I/O Port + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Offset The offset in ISA IO space to start the IO operation. + @param[in] Value The data to write port. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Parameter is invalid. + @retval EFI_UNSUPPORTED The address range specified by Offset is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +WritePort ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINT32 Offset, + IN UINT8 Value + ); + +/** + Performs an ISA Memory Read Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[out] Buffer The destination buffer to store the results + + @retval EFI_SUCCESS The data was read from the device successfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemRead ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + OUT VOID *Buffer + ); + + +/** + Performs an ISA Memory Write Cycle + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory operation. + @param[in] Offset The offset in ISA memory space to start the memory operation. + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer to write data from + + @retval EFI_SUCCESS The data was written to the device sucessfully. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoMemWrite ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Copy one region of ISA memory space to another region of ISA memory space on the ISA controller. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the memory copy operation. + @param[in] DestOffset The offset of the destination + @param[in] SrcOffset The offset of the source + @param[in] Count The number of memory copy operations to perform + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +EFI_STATUS +EFIAPI +IsaIoCopyMem ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommonBuffer mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER Type is invalid or MemoryType is invalid or HostAddress is NULL + @retval EFI_UNSUPPORTED Attributes is unsupported or the memory range specified + by HostAddress, Pages, and Type is not available for common buffer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. +**/ +EFI_STATUS +EFIAPI +IsaIoAllocateBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with EFI_ISA_IO.AllocateBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free. + @param[in] HostAddress The base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_ISA_IO.AllocateBufer(). +**/ +EFI_STATUS +EFIAPI +IsaIoFreeBuffer ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +#endif + diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf new file mode 100644 index 0000000000..4caf3387e2 --- /dev/null +++ b/IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf @@ -0,0 +1,67 @@ +## @file +# Component description file for IsaIoDxe module. +# +# Produces an instance of the ISA I/O Protocol for every SIO controller. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = IsaIoDxe + FILE_GUID = 61AD3083-DCAD-4850-A50C-73B23B3B14F9 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeIsaIo + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# DRIVER_BINDING = gIsaIoDriver +# COMPONENT_NAME = gIsaIoComponentName; +# COMPONENT_NAME2 = gIsaIoComponentName2; +# + +[Sources] + ComponentName.h + ComponentName.c + IsaIo.h + IsaIo.c + IsaDriver.h + IsaDriver.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + ReportStatusCodeLib + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + UefiDriverEntryPoint + DebugLib + +[Protocols] + gEfiIsaIoProtocolGuid # PROTOCOL BY_START + gEfiSioProtocolGuid # PROTOCOL TO_START + gEfiPciIoProtocolGuid # PROTOCOL TO_START + gEfiDevicePathProtocolGuid # PROTOCOL TO_START + gEfiGenericMemTestProtocolGuid # PROTOCOL TO_START + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSupportedFeatures + + diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc index 8cb6430500..677de6d361 100644 --- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc +++ b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc @@ -128,6 +128,7 @@ IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf