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