17f0719039085cc40114abce84cf29fe57da226f4Bob Moore
27f0719039085cc40114abce84cf29fe57da226f4Bob Moore/******************************************************************************
37f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
47f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Module Name: hwvalid - I/O request validation
57f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
67f0719039085cc40114abce84cf29fe57da226f4Bob Moore *****************************************************************************/
77f0719039085cc40114abce84cf29fe57da226f4Bob Moore
87f0719039085cc40114abce84cf29fe57da226f4Bob Moore/*
977848130e53b06c22fe37a7b6acbb82bb3e9bfbaBob Moore * Copyright (C) 2000 - 2012, Intel Corp.
107f0719039085cc40114abce84cf29fe57da226f4Bob Moore * All rights reserved.
117f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
127f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Redistribution and use in source and binary forms, with or without
137f0719039085cc40114abce84cf29fe57da226f4Bob Moore * modification, are permitted provided that the following conditions
147f0719039085cc40114abce84cf29fe57da226f4Bob Moore * are met:
157f0719039085cc40114abce84cf29fe57da226f4Bob Moore * 1. Redistributions of source code must retain the above copyright
167f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    notice, this list of conditions, and the following disclaimer,
177f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    without modification.
187f0719039085cc40114abce84cf29fe57da226f4Bob Moore * 2. Redistributions in binary form must reproduce at minimum a disclaimer
197f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    substantially similar to the "NO WARRANTY" disclaimer below
207f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    ("Disclaimer") and any redistribution must be conditioned upon
217f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    including a substantially similar Disclaimer requirement for further
227f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    binary redistribution.
237f0719039085cc40114abce84cf29fe57da226f4Bob Moore * 3. Neither the names of the above-listed copyright holders nor the names
247f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    of any contributors may be used to endorse or promote products derived
257f0719039085cc40114abce84cf29fe57da226f4Bob Moore *    from this software without specific prior written permission.
267f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
277f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Alternatively, this software may be distributed under the terms of the
287f0719039085cc40114abce84cf29fe57da226f4Bob Moore * GNU General Public License ("GPL") version 2 as published by the Free
297f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Software Foundation.
307f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
317f0719039085cc40114abce84cf29fe57da226f4Bob Moore * NO WARRANTY
327f0719039085cc40114abce84cf29fe57da226f4Bob Moore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
337f0719039085cc40114abce84cf29fe57da226f4Bob Moore * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
347f0719039085cc40114abce84cf29fe57da226f4Bob Moore * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
357f0719039085cc40114abce84cf29fe57da226f4Bob Moore * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
367f0719039085cc40114abce84cf29fe57da226f4Bob Moore * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
377f0719039085cc40114abce84cf29fe57da226f4Bob Moore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
387f0719039085cc40114abce84cf29fe57da226f4Bob Moore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
397f0719039085cc40114abce84cf29fe57da226f4Bob Moore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
407f0719039085cc40114abce84cf29fe57da226f4Bob Moore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
417f0719039085cc40114abce84cf29fe57da226f4Bob Moore * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
427f0719039085cc40114abce84cf29fe57da226f4Bob Moore * POSSIBILITY OF SUCH DAMAGES.
437f0719039085cc40114abce84cf29fe57da226f4Bob Moore */
447f0719039085cc40114abce84cf29fe57da226f4Bob Moore
457f0719039085cc40114abce84cf29fe57da226f4Bob Moore#include <acpi/acpi.h>
467f0719039085cc40114abce84cf29fe57da226f4Bob Moore#include "accommon.h"
477f0719039085cc40114abce84cf29fe57da226f4Bob Moore
487f0719039085cc40114abce84cf29fe57da226f4Bob Moore#define _COMPONENT          ACPI_HARDWARE
497f0719039085cc40114abce84cf29fe57da226f4Bob MooreACPI_MODULE_NAME("hwvalid")
507f0719039085cc40114abce84cf29fe57da226f4Bob Moore
517f0719039085cc40114abce84cf29fe57da226f4Bob Moore/* Local prototypes */
527f0719039085cc40114abce84cf29fe57da226f4Bob Moorestatic acpi_status
537f0719039085cc40114abce84cf29fe57da226f4Bob Mooreacpi_hw_validate_io_request(acpi_io_address address, u32 bit_width);
547f0719039085cc40114abce84cf29fe57da226f4Bob Moore
557f0719039085cc40114abce84cf29fe57da226f4Bob Moore/*
567f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Protected I/O ports. Some ports are always illegal, and some are
577f0719039085cc40114abce84cf29fe57da226f4Bob Moore * conditionally illegal. This table must remain ordered by port address.
587f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
597f0719039085cc40114abce84cf29fe57da226f4Bob Moore * The table is used to implement the Microsoft port access rules that
607f0719039085cc40114abce84cf29fe57da226f4Bob Moore * first appeared in Windows XP. Some ports are always illegal, and some
617f0719039085cc40114abce84cf29fe57da226f4Bob Moore * ports are only illegal if the BIOS calls _OSI with a win_xP string or
627f0719039085cc40114abce84cf29fe57da226f4Bob Moore * later (meaning that the BIOS itelf is post-XP.)
637f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
647f0719039085cc40114abce84cf29fe57da226f4Bob Moore * This provides ACPICA with the desired port protections and
657f0719039085cc40114abce84cf29fe57da226f4Bob Moore * Microsoft compatibility.
66ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *
67ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore * Description of port entries:
68ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  DMA:   DMA controller
69ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  PIC0:  Programmable Interrupt Controller (8259_a)
70ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  PIT1:  System Timer 1
71ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  PIT2:  System Timer 2 failsafe
72ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  RTC:   Real-time clock
73ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  CMOS:  Extended CMOS
74ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  DMA1:  DMA 1 page registers
75ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  DMA1L: DMA 1 Ch 0 low page
76ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  DMA2:  DMA 2 page registers
77ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  DMA2L: DMA 2 low page refresh
78ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  ARBC:  Arbitration control
79ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  SETUP: Reserved system board setup
80ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  POS:   POS channel select
81ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  PIC1:  Cascaded PIC
82ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  IDMA:  ISA DMA
83ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  ELCR:  PIC edge/level registers
84ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore *  PCI:   PCI configuration space
857f0719039085cc40114abce84cf29fe57da226f4Bob Moore */
867f0719039085cc40114abce84cf29fe57da226f4Bob Moorestatic const struct acpi_port_info acpi_protected_ports[] = {
87ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP},
887f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
897f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP},
907f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
917f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
927f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
93a38d75fa2e48d4960b656eac39bc8a6b584a83c0Len Brown	{"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
94ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
95ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
96ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
97ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP},
98ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP},
997f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP},
1007f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
101ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bdBob Moore	{"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
1027f0719039085cc40114abce84cf29fe57da226f4Bob Moore	{"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
103f28ad2c3daf0691081d91488df4d9d101e1a2b5dBob Moore	{"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
1047f0719039085cc40114abce84cf29fe57da226f4Bob Moore};
1057f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1067f0719039085cc40114abce84cf29fe57da226f4Bob Moore#define ACPI_PORT_INFO_ENTRIES  ACPI_ARRAY_LENGTH (acpi_protected_ports)
1077f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1087f0719039085cc40114abce84cf29fe57da226f4Bob Moore/******************************************************************************
1097f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
1107f0719039085cc40114abce84cf29fe57da226f4Bob Moore * FUNCTION:    acpi_hw_validate_io_request
1117f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
1127f0719039085cc40114abce84cf29fe57da226f4Bob Moore * PARAMETERS:  Address             Address of I/O port/register
1137f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              bit_width           Number of bits (8,16,32)
1147f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
1157f0719039085cc40114abce84cf29fe57da226f4Bob Moore * RETURN:      Status
1167f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
1177f0719039085cc40114abce84cf29fe57da226f4Bob Moore * DESCRIPTION: Validates an I/O request (address/length). Certain ports are
1187f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              always illegal and some ports are only illegal depending on
1197f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              the requests the BIOS AML code makes to the predefined
1207f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              _OSI method.
1217f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
1227f0719039085cc40114abce84cf29fe57da226f4Bob Moore ******************************************************************************/
1237f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1247f0719039085cc40114abce84cf29fe57da226f4Bob Moorestatic acpi_status
1257f0719039085cc40114abce84cf29fe57da226f4Bob Mooreacpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
1267f0719039085cc40114abce84cf29fe57da226f4Bob Moore{
1277f0719039085cc40114abce84cf29fe57da226f4Bob Moore	u32 i;
1287f0719039085cc40114abce84cf29fe57da226f4Bob Moore	u32 byte_width;
1297f0719039085cc40114abce84cf29fe57da226f4Bob Moore	acpi_io_address last_address;
1307f0719039085cc40114abce84cf29fe57da226f4Bob Moore	const struct acpi_port_info *port_info;
1317f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1327f0719039085cc40114abce84cf29fe57da226f4Bob Moore	ACPI_FUNCTION_TRACE(hw_validate_io_request);
1337f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1347f0719039085cc40114abce84cf29fe57da226f4Bob Moore	/* Supported widths are 8/16/32 */
1357f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1367f0719039085cc40114abce84cf29fe57da226f4Bob Moore	if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) {
1378519bc9f1e6db43a9b95b70ef0c7b61cb36d58e4Bob Moore		ACPI_ERROR((AE_INFO,
1388519bc9f1e6db43a9b95b70ef0c7b61cb36d58e4Bob Moore			    "Bad BitWidth parameter: %8.8X", bit_width));
1397f0719039085cc40114abce84cf29fe57da226f4Bob Moore		return AE_BAD_PARAMETER;
1407f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
1417f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1427f0719039085cc40114abce84cf29fe57da226f4Bob Moore	port_info = acpi_protected_ports;
1437f0719039085cc40114abce84cf29fe57da226f4Bob Moore	byte_width = ACPI_DIV_8(bit_width);
1447f0719039085cc40114abce84cf29fe57da226f4Bob Moore	last_address = address + byte_width - 1;
1457f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1467f0719039085cc40114abce84cf29fe57da226f4Bob Moore	ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
1477f0719039085cc40114abce84cf29fe57da226f4Bob Moore			  ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void,
1487f0719039085cc40114abce84cf29fe57da226f4Bob Moore								      last_address),
1497f0719039085cc40114abce84cf29fe57da226f4Bob Moore			  byte_width));
1507f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1517f0719039085cc40114abce84cf29fe57da226f4Bob Moore	/* Maximum 16-bit address in I/O space */
1527f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1537f0719039085cc40114abce84cf29fe57da226f4Bob Moore	if (last_address > ACPI_UINT16_MAX) {
1547f0719039085cc40114abce84cf29fe57da226f4Bob Moore		ACPI_ERROR((AE_INFO,
155f6a22b0bc417042e83117f52ab1a03696af185abBob Moore			    "Illegal I/O port address/length above 64K: %p/0x%X",
1567f0719039085cc40114abce84cf29fe57da226f4Bob Moore			    ACPI_CAST_PTR(void, address), byte_width));
157a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		return_ACPI_STATUS(AE_LIMIT);
1587f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
1597f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1607f0719039085cc40114abce84cf29fe57da226f4Bob Moore	/* Exit if requested address is not within the protected port table */
1617f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1627f0719039085cc40114abce84cf29fe57da226f4Bob Moore	if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) {
1637f0719039085cc40114abce84cf29fe57da226f4Bob Moore		return_ACPI_STATUS(AE_OK);
1647f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
1657f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1667f0719039085cc40114abce84cf29fe57da226f4Bob Moore	/* Check request against the list of protected I/O ports */
1677f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1687f0719039085cc40114abce84cf29fe57da226f4Bob Moore	for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) {
1697f0719039085cc40114abce84cf29fe57da226f4Bob Moore		/*
1707f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * Check if the requested address range will write to a reserved
1717f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * port. Four cases to consider:
1727f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 *
1737f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * 1) Address range is contained completely in the port address range
1747f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * 2) Address range overlaps port range at the port range start
1757f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * 3) Address range overlaps port range at the port range end
1767f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 * 4) Address range completely encompasses the port range
1777f0719039085cc40114abce84cf29fe57da226f4Bob Moore		 */
1787f0719039085cc40114abce84cf29fe57da226f4Bob Moore		if ((address <= port_info->end)
1797f0719039085cc40114abce84cf29fe57da226f4Bob Moore		    && (last_address >= port_info->start)) {
1807f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1817f0719039085cc40114abce84cf29fe57da226f4Bob Moore			/* Port illegality may depend on the _OSI calls made by the BIOS */
1827f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1837f0719039085cc40114abce84cf29fe57da226f4Bob Moore			if (acpi_gbl_osi_data >= port_info->osi_dependency) {
184a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming				ACPI_DEBUG_PRINT((ACPI_DB_IO,
185a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming						  "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
186a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming						  ACPI_CAST_PTR(void, address),
187a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming						  byte_width, port_info->name,
188a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming						  port_info->start,
189a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming						  port_info->end));
1907f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1917f0719039085cc40114abce84cf29fe57da226f4Bob Moore				return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
1927f0719039085cc40114abce84cf29fe57da226f4Bob Moore			}
1937f0719039085cc40114abce84cf29fe57da226f4Bob Moore		}
1947f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1957f0719039085cc40114abce84cf29fe57da226f4Bob Moore		/* Finished if address range ends before the end of this port */
1967f0719039085cc40114abce84cf29fe57da226f4Bob Moore
1977f0719039085cc40114abce84cf29fe57da226f4Bob Moore		if (last_address <= port_info->end) {
1987f0719039085cc40114abce84cf29fe57da226f4Bob Moore			break;
1997f0719039085cc40114abce84cf29fe57da226f4Bob Moore		}
2007f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
2017f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2027f0719039085cc40114abce84cf29fe57da226f4Bob Moore	return_ACPI_STATUS(AE_OK);
2037f0719039085cc40114abce84cf29fe57da226f4Bob Moore}
2047f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2057f0719039085cc40114abce84cf29fe57da226f4Bob Moore/******************************************************************************
2067f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2077f0719039085cc40114abce84cf29fe57da226f4Bob Moore * FUNCTION:    acpi_hw_read_port
2087f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2097f0719039085cc40114abce84cf29fe57da226f4Bob Moore * PARAMETERS:  Address             Address of I/O port/register to read
2107f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              Value               Where value is placed
2117f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              Width               Number of bits
2127f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
213a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming * RETURN:      Status and value read from port
2147f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2157f0719039085cc40114abce84cf29fe57da226f4Bob Moore * DESCRIPTION: Read data from an I/O port or register. This is a front-end
2167f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              to acpi_os_read_port that performs validation on both the port
2177f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              address and the length.
2187f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2197f0719039085cc40114abce84cf29fe57da226f4Bob Moore *****************************************************************************/
2207f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2217f0719039085cc40114abce84cf29fe57da226f4Bob Mooreacpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
2227f0719039085cc40114abce84cf29fe57da226f4Bob Moore{
2237f0719039085cc40114abce84cf29fe57da226f4Bob Moore	acpi_status status;
224a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	u32 one_byte;
225a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	u32 i;
226a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
227b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	/* Truncate address to 16 bits if requested */
228b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett
229b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	if (acpi_gbl_truncate_io_addresses) {
230b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett		address &= ACPI_UINT16_MAX;
231b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	}
232b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett
233a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	/* Validate the entire request and perform the I/O */
2347f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2357f0719039085cc40114abce84cf29fe57da226f4Bob Moore	status = acpi_hw_validate_io_request(address, width);
236a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	if (ACPI_SUCCESS(status)) {
237a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		status = acpi_os_read_port(address, value, width);
2387f0719039085cc40114abce84cf29fe57da226f4Bob Moore		return status;
2397f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
2407f0719039085cc40114abce84cf29fe57da226f4Bob Moore
241a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	if (status != AE_AML_ILLEGAL_ADDRESS) {
242a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		return status;
243a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	}
244a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
245a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	/*
246a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * There has been a protection violation within the request. Fall
247a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * back to byte granularity port I/O and ignore the failing bytes.
248a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * This provides Windows compatibility.
249a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 */
250a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	for (i = 0, *value = 0; i < width; i += 8) {
251a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
252a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		/* Validate and read one byte */
253a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
254a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
255a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			status = acpi_os_read_port(address, &one_byte, 8);
256a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			if (ACPI_FAILURE(status)) {
257a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming				return status;
258a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			}
259a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
260a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			*value |= (one_byte << i);
261a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		}
262a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
263a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		address++;
264a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	}
265a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
266a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	return AE_OK;
2677f0719039085cc40114abce84cf29fe57da226f4Bob Moore}
2687f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2697f0719039085cc40114abce84cf29fe57da226f4Bob Moore/******************************************************************************
2707f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2717f0719039085cc40114abce84cf29fe57da226f4Bob Moore * FUNCTION:    acpi_hw_write_port
2727f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2737f0719039085cc40114abce84cf29fe57da226f4Bob Moore * PARAMETERS:  Address             Address of I/O port/register to write
2747f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              Value               Value to write
2757f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              Width               Number of bits
2767f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
277a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming * RETURN:      Status
2787f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2797f0719039085cc40114abce84cf29fe57da226f4Bob Moore * DESCRIPTION: Write data to an I/O port or register. This is a front-end
2807f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              to acpi_os_write_port that performs validation on both the port
2817f0719039085cc40114abce84cf29fe57da226f4Bob Moore *              address and the length.
2827f0719039085cc40114abce84cf29fe57da226f4Bob Moore *
2837f0719039085cc40114abce84cf29fe57da226f4Bob Moore *****************************************************************************/
2847f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2857f0719039085cc40114abce84cf29fe57da226f4Bob Mooreacpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
2867f0719039085cc40114abce84cf29fe57da226f4Bob Moore{
2877f0719039085cc40114abce84cf29fe57da226f4Bob Moore	acpi_status status;
288a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	u32 i;
289a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
290b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	/* Truncate address to 16 bits if requested */
291b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett
292b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	if (acpi_gbl_truncate_io_addresses) {
293b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett		address &= ACPI_UINT16_MAX;
294b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett	}
295b681f7d9ab4d697a214fa4428795790c3a937a89Matthew Garrett
296a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	/* Validate the entire request and perform the I/O */
2977f0719039085cc40114abce84cf29fe57da226f4Bob Moore
2987f0719039085cc40114abce84cf29fe57da226f4Bob Moore	status = acpi_hw_validate_io_request(address, width);
299a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	if (ACPI_SUCCESS(status)) {
300a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		status = acpi_os_write_port(address, value, width);
3017f0719039085cc40114abce84cf29fe57da226f4Bob Moore		return status;
3027f0719039085cc40114abce84cf29fe57da226f4Bob Moore	}
3037f0719039085cc40114abce84cf29fe57da226f4Bob Moore
304a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	if (status != AE_AML_ILLEGAL_ADDRESS) {
305a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		return status;
306a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	}
307a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
308a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	/*
309a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * There has been a protection violation within the request. Fall
310a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * back to byte granularity port I/O and ignore the failing bytes.
311a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 * This provides Windows compatibility.
312a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	 */
313a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	for (i = 0; i < width; i += 8) {
314a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
315a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		/* Validate and write one byte */
316a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
317a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
318a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			status =
319a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			    acpi_os_write_port(address, (value >> i) & 0xFF, 8);
320a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			if (ACPI_FAILURE(status)) {
321a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming				return status;
322a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming			}
323a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		}
324a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
325a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming		address++;
326a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	}
327a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming
328a65131e942e25c707a652fa4ec2cfcd8b63fec11Lin Ming	return AE_OK;
3297f0719039085cc40114abce84cf29fe57da226f4Bob Moore}
330