^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Module Name: hwvalid - I/O request validation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2000 - 2020, Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <acpi/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "accommon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define _COMPONENT ACPI_HARDWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) ACPI_MODULE_NAME("hwvalid")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Local prototypes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Protected I/O ports. Some ports are always illegal, and some are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * conditionally illegal. This table must remain ordered by port address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * The table is used to implement the Microsoft port access rules that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * first appeared in Windows XP. Some ports are always illegal, and some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * ports are only illegal if the BIOS calls _OSI with a win_XP string or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * later (meaning that the BIOS itelf is post-XP.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * This provides ACPICA with the desired port protections and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Microsoft compatibility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Description of port entries:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * DMA: DMA controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * PIC0: Programmable Interrupt Controller (8259A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * PIT1: System Timer 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * PIT2: System Timer 2 failsafe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * RTC: Real-time clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * CMOS: Extended CMOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * DMA1: DMA 1 page registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * DMA1L: DMA 1 Ch 0 low page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * DMA2: DMA 2 page registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * DMA2L: DMA 2 low page refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * ARBC: Arbitration control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * SETUP: Reserved system board setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * POS: POS channel select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * PIC1: Cascaded PIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * IDMA: ISA DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * ELCR: PIC edge/level registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * PCI: PCI configuration space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static const struct acpi_port_info acpi_protected_ports[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * FUNCTION: acpi_hw_validate_io_request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * PARAMETERS: Address Address of I/O port/register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * bit_width Number of bits (8,16,32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * DESCRIPTION: Validates an I/O request (address/length). Certain ports are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * always illegal and some ports are only illegal depending on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * the requests the BIOS AML code makes to the predefined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * _OSI method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 byte_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) acpi_io_address last_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const struct acpi_port_info *port_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ACPI_FUNCTION_TRACE(hw_validate_io_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* Supported widths are 8/16/32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) "Bad BitWidth parameter: %8.8X", bit_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return_ACPI_STATUS(AE_BAD_PARAMETER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) port_info = acpi_protected_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) byte_width = ACPI_DIV_8(bit_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) last_address = address + byte_width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ACPI_DEBUG_PRINT((ACPI_DB_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ACPI_FORMAT_UINT64(address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ACPI_FORMAT_UINT64(last_address), byte_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Maximum 16-bit address in I/O space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (last_address > ACPI_UINT16_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ACPI_FORMAT_UINT64(address), byte_width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return_ACPI_STATUS(AE_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* Exit if requested address is not within the protected port table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Check request against the list of protected I/O ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Check if the requested address range will write to a reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * port. There are four cases to consider:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * 1) Address range is contained completely in the port address range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * 2) Address range overlaps port range at the port range start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * 3) Address range overlaps port range at the port range end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * 4) Address range completely encompasses the port range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if ((address <= port_info->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) && (last_address >= port_info->start)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Port illegality may depend on the _OSI calls made by the BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (acpi_gbl_osi_data >= port_info->osi_dependency) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ACPI_FORMAT_UINT64(address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) byte_width, port_info->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) port_info->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) port_info->end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* Finished if address range ends before the end of this port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (last_address <= port_info->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * FUNCTION: acpi_hw_read_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * PARAMETERS: Address Address of I/O port/register to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * Value Where value (data) is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * Width Number of bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * RETURN: Status and value read from port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * DESCRIPTION: Read data from an I/O port or register. This is a front-end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * to acpi_os_read_port that performs validation on both the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * address and the length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u32 one_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* Truncate address to 16 bits if requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (acpi_gbl_truncate_io_addresses) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) address &= ACPI_UINT16_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* Validate the entire request and perform the I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) status = acpi_hw_validate_io_request(address, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (ACPI_SUCCESS(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) status = acpi_os_read_port(address, value, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (status != AE_AML_ILLEGAL_ADDRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * There has been a protection violation within the request. Fall
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * back to byte granularity port I/O and ignore the failing bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * This provides compatibility with other ACPI implementations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (i = 0, *value = 0; i < width; i += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* Validate and read one byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) status = acpi_os_read_port(address, &one_byte, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *value |= (one_byte << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) address++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return (AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * FUNCTION: acpi_hw_write_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * PARAMETERS: Address Address of I/O port/register to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * Value Value to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Width Number of bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * DESCRIPTION: Write data to an I/O port or register. This is a front-end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * to acpi_os_write_port that performs validation on both the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * address and the length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Truncate address to 16 bits if requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (acpi_gbl_truncate_io_addresses) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) address &= ACPI_UINT16_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Validate the entire request and perform the I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) status = acpi_hw_validate_io_request(address, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (ACPI_SUCCESS(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) status = acpi_os_write_port(address, value, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (status != AE_AML_ILLEGAL_ADDRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * There has been a protection violation within the request. Fall
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * back to byte granularity port I/O and ignore the failing bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * This provides compatibility with other ACPI implementations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) for (i = 0; i < width; i += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* Validate and write one byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) acpi_os_write_port(address, (value >> i) & 0xFF, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) address++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return (AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * FUNCTION: acpi_hw_validate_io_block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * PARAMETERS: Address Address of I/O port/register blobk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * bit_width Number of bits (8,16,32) in each register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * count Number of registers in the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * DESCRIPTION: Validates a block of I/O ports/registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) while (count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) status = acpi_hw_validate_io_request((acpi_io_address)address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) bit_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (ACPI_FAILURE(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return_ACPI_STATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) address += ACPI_DIV_8(bit_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }