summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/SioBusDxe/SioService.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/SioBusDxe/SioService.c')
-rw-r--r--OvmfPkg/SioBusDxe/SioService.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/OvmfPkg/SioBusDxe/SioService.c b/OvmfPkg/SioBusDxe/SioService.c
new file mode 100644
index 0000000000..6a97a4a2c0
--- /dev/null
+++ b/OvmfPkg/SioBusDxe/SioService.c
@@ -0,0 +1,405 @@
+/** @file
+ The SioBusDxe driver is used to create child devices on the ISA bus and
+ installs the Super I/O protocols on them.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ 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 "SioBusDxe.h"
+
+//
+// Super I/O Protocol interfaces
+//
+EFI_SIO_PROTOCOL mSioInterface = {
+ SioRegisterAccess,
+ SioGetResources,
+ SioSetResources,
+ SioPossibleResources,
+ SioModify
+};
+
+//
+// COM 1 UART Controller
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+SIO_RESOURCES_IO mCom1Resources = {
+ { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x3F8, 8 },
+ { ACPI_END_TAG_DESCRIPTOR, 0 }
+};
+
+//
+// COM 2 UART Controller
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+SIO_RESOURCES_IO mCom2Resources = {
+ { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x2F8, 8 },
+ { ACPI_END_TAG_DESCRIPTOR, 0 }
+};
+
+//
+// PS/2 Keyboard Controller
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+SIO_RESOURCES_IO mPs2KeyboardDeviceResources = {
+ { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x60, 5 },
+ { ACPI_END_TAG_DESCRIPTOR, 0 }
+};
+
+//
+// Table of SIO Controllers
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+SIO_DEVICE_INFO mDevicesInfo[] = {
+ {
+ EISA_PNP_ID (0x501),
+ 0,
+ { (ACPI_SMALL_RESOURCE_HEADER *) &mCom1Resources }
+ }, // COM 1 UART Controller
+ {
+ EISA_PNP_ID (0x501),
+ 1,
+ { (ACPI_SMALL_RESOURCE_HEADER *) &mCom2Resources }
+ }, // COM 2 UART Controller
+ {
+ EISA_PNP_ID(0x303),
+ 0,
+ { (ACPI_SMALL_RESOURCE_HEADER *) &mPs2KeyboardDeviceResources }
+ } // PS/2 Keyboard Controller
+};
+
+//
+// ACPI Device Path Node template
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+ACPI_HID_DEVICE_PATH mAcpiDeviceNodeTemplate = {
+ { // Header
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0x0, // HID
+ 0x0 // UID
+};
+
+
+/**
+ Provides a low level access to the registers for the Super I/O.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] Write Specifies the type of the register operation.
+ If this parameter is TRUE, Value is interpreted
+ as an input parameter and the operation is a
+ register write. If this parameter is FALSE,
+ Value is interpreted as an output parameter and
+ the operation is a register read.
+ @param[in] ExitCfgMode Exit Configuration Mode Indicator. If this
+ parameter is set to TRUE, the Super I/O driver
+ will turn off configuration mode of the Super
+ I/O prior to returning from this function. If
+ this parameter is set to FALSE, the Super I/O
+ driver will leave Super I/O in the
+ configuration mode. The Super I/O driver must
+ track the current state of the Super I/O and
+ enable the configuration mode of Super I/O if
+ necessary prior to register access.
+ @param[in] Register Register number.
+ @param[in,out] Value If Write is TRUE, Value is a pointer to the
+ buffer containing the byte of data to be
+ written to the Super I/O register. If Write is
+ FALSE, Value is a pointer to the destination
+ buffer for the byte of data to be read from the
+ Super I/O register.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER The Value is NULL.
+ @retval EFI_INVALID_PARAMETER Invalid Register number.
+
+**/
+EFI_STATUS
+EFIAPI
+SioRegisterAccess (
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN BOOLEAN ExitCfgMode,
+ IN UINT8 Register,
+ IN OUT UINT8 *Value
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Provides an interface to get a list of the current resources consumed by the
+ device in the ACPI Resource Descriptor format.
+
+ GetResources() returns a list of resources currently consumed by the device.
+ The ResourceList is a pointer to the buffer containing resource descriptors
+ for the device. The descriptors are in the format of Small or Large ACPI
+ resource descriptor as defined by ACPI specification (2.0 & 3.0). The buffer
+ of resource descriptors is terminated with the 'End tag' resource descriptor.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[out] ResourceList A pointer to an ACPI resource descriptor list
+ that defines the current resources used by the
+ device.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER ResourceList is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SioGetResources (
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceList
+ )
+{
+ SIO_DEV *SioDevice;
+
+ if (ResourceList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SioDevice = SIO_DEV_FROM_SIO (This);
+ if (SioDevice->DeviceIndex < ARRAY_SIZE (mDevicesInfo)) {
+ *ResourceList = mDevicesInfo[SioDevice->DeviceIndex].Resources;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets the resources for the device.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] ResourceList Pointer to the ACPI resource descriptor list.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER ResourceList is invalid.
+ @retval EFI_ACCESS_DENIED Some of the resources in ResourceList are in
+ use.
+
+**/
+EFI_STATUS
+EFIAPI
+SioSetResources (
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN ACPI_RESOURCE_HEADER_PTR ResourceList
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Provides a collection of resource descriptor lists. Each resource descriptor
+ list in the collection defines a combination of resources that can
+ potentially be used by the device.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[out] ResourceCollection Collection of the resource descriptor
+ lists.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER ResourceCollection is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SioPossibleResources (
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceCollection
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Provides an interface for a table based programming of the Super I/O
+ registers.
+
+ The Modify() function provides an interface for table based programming of
+ the Super I/O registers. This function can be used to perform programming of
+ multiple Super I/O registers with a single function call. For each table
+ entry, the Register is read, its content is bitwise ANDed with AndMask, and
+ then ORed with OrMask before being written back to the Register. The Super
+ I/O driver must track the current state of the Super I/O and enable the
+ configuration mode of Super I/O if necessary prior to table processing. Once
+ the table is processed, the Super I/O device has to be returned to the
+ original state.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] Command A pointer to an array of NumberOfCommands
+ EFI_SIO_REGISTER_MODIFY structures. Each
+ structure specifies a single Super I/O register
+ modify operation.
+ @param[in] NumberOfCommands Number of elements in the Command array.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Command is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SioModify (
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN CONST EFI_SIO_REGISTER_MODIFY *Command,
+ IN UINTN NumberOfCommands
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Create the child device with a given device index.
+
+ @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of ISA bus controller.
+ @param[in] PciIo The pointer to the PCI protocol.
+ @param[in] ParentDevicePath Device path of the ISA bus controller.
+ @param[in] DeviceIndex Index of the device supported by this driver.
+
+ @retval EFI_SUCCESS The child device has been created successfully.
+ @retval Others Error occured during the child device creation.
+
+**/
+EFI_STATUS
+SioCreateChildDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN UINT32 DeviceIndex
+ )
+{
+ EFI_STATUS Status;
+ SIO_DEV *SioDevice;
+
+ //
+ // Initialize the SIO_DEV structure
+ //
+ SioDevice = AllocateZeroPool (sizeof (SIO_DEV));
+ if (SioDevice == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SioDevice->Signature = SIO_DEV_SIGNATURE;
+ SioDevice->Handle = NULL;
+ SioDevice->PciIo = PciIo;
+
+ //
+ // Construct the child device path
+ //
+ mAcpiDeviceNodeTemplate.HID = mDevicesInfo[DeviceIndex].Hid;
+ mAcpiDeviceNodeTemplate.UID = mDevicesInfo[DeviceIndex].Uid;
+ SioDevice->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &mAcpiDeviceNodeTemplate
+ );
+ if (SioDevice->DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ CopyMem (&SioDevice->Sio, &mSioInterface, sizeof (EFI_SIO_PROTOCOL));
+ SioDevice->DeviceIndex = DeviceIndex;
+
+ //
+ // Create a child handle and install Device Path and Super I/O protocols
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SioDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SioDevice->DevicePath,
+ &gEfiSioProtocolGuid,
+ &SioDevice->Sio,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ SioDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ SioDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SioDevice->DevicePath,
+ &gEfiSioProtocolGuid,
+ &SioDevice->Sio,
+ NULL
+ );
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (SioDevice->DevicePath != NULL) {
+ FreePool (SioDevice->DevicePath);
+ }
+
+ FreePool (SioDevice);
+ }
+
+ return Status;
+}
+
+/**
+ Create all the ISA child devices on the ISA bus controller (PCI to ISA
+ bridge).
+
+ @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of ISA bus controller.
+ @param[in] PciIo The pointer to the PCI protocol.
+ @param[in] ParentDevicePath Device path of the ISA bus controller.
+
+ @retval The number of child device that is successfully created.
+
+**/
+UINT32
+SioCreateAllChildDevices (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath
+ )
+{
+ UINT32 Index;
+ UINT32 ChildDeviceNumber;
+ EFI_STATUS Status;
+
+ ChildDeviceNumber = 0;
+
+ for (Index = 0; Index < ARRAY_SIZE (mDevicesInfo); Index++) {
+ Status = SioCreateChildDevice (
+ This,
+ Controller,
+ PciIo,
+ ParentDevicePath,
+ Index
+ );
+ if (!EFI_ERROR (Status)) {
+ ChildDeviceNumber++;
+ }
+ }
+
+ return ChildDeviceNumber;
+}