xref: /dflybsd-src/sys/contrib/dev/acpica/source/components/hardware/hwvalid.c (revision 0d02842ff209a03716ed693bcf4f13cb680fe411)
1*0d02842fSSascha Wildner /******************************************************************************
2*0d02842fSSascha Wildner  *
3*0d02842fSSascha Wildner  * Module Name: hwvalid - I/O request validation
4*0d02842fSSascha Wildner  *
5*0d02842fSSascha Wildner  *****************************************************************************/
6*0d02842fSSascha Wildner 
7*0d02842fSSascha Wildner /*
8*0d02842fSSascha Wildner  * Copyright (C) 2000 - 2013, Intel Corp.
9*0d02842fSSascha Wildner  * All rights reserved.
10*0d02842fSSascha Wildner  *
11*0d02842fSSascha Wildner  * Redistribution and use in source and binary forms, with or without
12*0d02842fSSascha Wildner  * modification, are permitted provided that the following conditions
13*0d02842fSSascha Wildner  * are met:
14*0d02842fSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
15*0d02842fSSascha Wildner  *    notice, this list of conditions, and the following disclaimer,
16*0d02842fSSascha Wildner  *    without modification.
17*0d02842fSSascha Wildner  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*0d02842fSSascha Wildner  *    substantially similar to the "NO WARRANTY" disclaimer below
19*0d02842fSSascha Wildner  *    ("Disclaimer") and any redistribution must be conditioned upon
20*0d02842fSSascha Wildner  *    including a substantially similar Disclaimer requirement for further
21*0d02842fSSascha Wildner  *    binary redistribution.
22*0d02842fSSascha Wildner  * 3. Neither the names of the above-listed copyright holders nor the names
23*0d02842fSSascha Wildner  *    of any contributors may be used to endorse or promote products derived
24*0d02842fSSascha Wildner  *    from this software without specific prior written permission.
25*0d02842fSSascha Wildner  *
26*0d02842fSSascha Wildner  * Alternatively, this software may be distributed under the terms of the
27*0d02842fSSascha Wildner  * GNU General Public License ("GPL") version 2 as published by the Free
28*0d02842fSSascha Wildner  * Software Foundation.
29*0d02842fSSascha Wildner  *
30*0d02842fSSascha Wildner  * NO WARRANTY
31*0d02842fSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*0d02842fSSascha Wildner  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*0d02842fSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*0d02842fSSascha Wildner  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*0d02842fSSascha Wildner  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*0d02842fSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*0d02842fSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*0d02842fSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*0d02842fSSascha Wildner  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*0d02842fSSascha Wildner  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*0d02842fSSascha Wildner  * POSSIBILITY OF SUCH DAMAGES.
42*0d02842fSSascha Wildner  */
43*0d02842fSSascha Wildner 
44*0d02842fSSascha Wildner #define __HWVALID_C__
45*0d02842fSSascha Wildner 
46*0d02842fSSascha Wildner #include "acpi.h"
47*0d02842fSSascha Wildner #include "accommon.h"
48*0d02842fSSascha Wildner 
49*0d02842fSSascha Wildner #define _COMPONENT          ACPI_HARDWARE
50*0d02842fSSascha Wildner         ACPI_MODULE_NAME    ("hwvalid")
51*0d02842fSSascha Wildner 
52*0d02842fSSascha Wildner /* Local prototypes */
53*0d02842fSSascha Wildner 
54*0d02842fSSascha Wildner static ACPI_STATUS
55*0d02842fSSascha Wildner AcpiHwValidateIoRequest (
56*0d02842fSSascha Wildner     ACPI_IO_ADDRESS         Address,
57*0d02842fSSascha Wildner     UINT32                  BitWidth);
58*0d02842fSSascha Wildner 
59*0d02842fSSascha Wildner 
60*0d02842fSSascha Wildner /*
61*0d02842fSSascha Wildner  * Protected I/O ports. Some ports are always illegal, and some are
62*0d02842fSSascha Wildner  * conditionally illegal. This table must remain ordered by port address.
63*0d02842fSSascha Wildner  *
64*0d02842fSSascha Wildner  * The table is used to implement the Microsoft port access rules that
65*0d02842fSSascha Wildner  * first appeared in Windows XP. Some ports are always illegal, and some
66*0d02842fSSascha Wildner  * ports are only illegal if the BIOS calls _OSI with a WinXP string or
67*0d02842fSSascha Wildner  * later (meaning that the BIOS itelf is post-XP.)
68*0d02842fSSascha Wildner  *
69*0d02842fSSascha Wildner  * This provides ACPICA with the desired port protections and
70*0d02842fSSascha Wildner  * Microsoft compatibility.
71*0d02842fSSascha Wildner  *
72*0d02842fSSascha Wildner  * Description of port entries:
73*0d02842fSSascha Wildner  *  DMA:   DMA controller
74*0d02842fSSascha Wildner  *  PIC0:  Programmable Interrupt Controller (8259A)
75*0d02842fSSascha Wildner  *  PIT1:  System Timer 1
76*0d02842fSSascha Wildner  *  PIT2:  System Timer 2 failsafe
77*0d02842fSSascha Wildner  *  RTC:   Real-time clock
78*0d02842fSSascha Wildner  *  CMOS:  Extended CMOS
79*0d02842fSSascha Wildner  *  DMA1:  DMA 1 page registers
80*0d02842fSSascha Wildner  *  DMA1L: DMA 1 Ch 0 low page
81*0d02842fSSascha Wildner  *  DMA2:  DMA 2 page registers
82*0d02842fSSascha Wildner  *  DMA2L: DMA 2 low page refresh
83*0d02842fSSascha Wildner  *  ARBC:  Arbitration control
84*0d02842fSSascha Wildner  *  SETUP: Reserved system board setup
85*0d02842fSSascha Wildner  *  POS:   POS channel select
86*0d02842fSSascha Wildner  *  PIC1:  Cascaded PIC
87*0d02842fSSascha Wildner  *  IDMA:  ISA DMA
88*0d02842fSSascha Wildner  *  ELCR:  PIC edge/level registers
89*0d02842fSSascha Wildner  *  PCI:   PCI configuration space
90*0d02842fSSascha Wildner  */
91*0d02842fSSascha Wildner static const ACPI_PORT_INFO     AcpiProtectedPorts[] =
92*0d02842fSSascha Wildner {
93*0d02842fSSascha Wildner     {"DMA",     0x0000, 0x000F, ACPI_OSI_WIN_XP},
94*0d02842fSSascha Wildner     {"PIC0",    0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
95*0d02842fSSascha Wildner     {"PIT1",    0x0040, 0x0043, ACPI_OSI_WIN_XP},
96*0d02842fSSascha Wildner     {"PIT2",    0x0048, 0x004B, ACPI_OSI_WIN_XP},
97*0d02842fSSascha Wildner     {"RTC",     0x0070, 0x0071, ACPI_OSI_WIN_XP},
98*0d02842fSSascha Wildner     {"CMOS",    0x0074, 0x0076, ACPI_OSI_WIN_XP},
99*0d02842fSSascha Wildner     {"DMA1",    0x0081, 0x0083, ACPI_OSI_WIN_XP},
100*0d02842fSSascha Wildner     {"DMA1L",   0x0087, 0x0087, ACPI_OSI_WIN_XP},
101*0d02842fSSascha Wildner     {"DMA2",    0x0089, 0x008B, ACPI_OSI_WIN_XP},
102*0d02842fSSascha Wildner     {"DMA2L",   0x008F, 0x008F, ACPI_OSI_WIN_XP},
103*0d02842fSSascha Wildner     {"ARBC",    0x0090, 0x0091, ACPI_OSI_WIN_XP},
104*0d02842fSSascha Wildner     {"SETUP",   0x0093, 0x0094, ACPI_OSI_WIN_XP},
105*0d02842fSSascha Wildner     {"POS",     0x0096, 0x0097, ACPI_OSI_WIN_XP},
106*0d02842fSSascha Wildner     {"PIC1",    0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
107*0d02842fSSascha Wildner     {"IDMA",    0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
108*0d02842fSSascha Wildner     {"ELCR",    0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
109*0d02842fSSascha Wildner     {"PCI",     0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
110*0d02842fSSascha Wildner };
111*0d02842fSSascha Wildner 
112*0d02842fSSascha Wildner #define ACPI_PORT_INFO_ENTRIES  ACPI_ARRAY_LENGTH (AcpiProtectedPorts)
113*0d02842fSSascha Wildner 
114*0d02842fSSascha Wildner 
115*0d02842fSSascha Wildner /******************************************************************************
116*0d02842fSSascha Wildner  *
117*0d02842fSSascha Wildner  * FUNCTION:    AcpiHwValidateIoRequest
118*0d02842fSSascha Wildner  *
119*0d02842fSSascha Wildner  * PARAMETERS:  Address             Address of I/O port/register
120*0d02842fSSascha Wildner  *              BitWidth            Number of bits (8,16,32)
121*0d02842fSSascha Wildner  *
122*0d02842fSSascha Wildner  * RETURN:      Status
123*0d02842fSSascha Wildner  *
124*0d02842fSSascha Wildner  * DESCRIPTION: Validates an I/O request (address/length). Certain ports are
125*0d02842fSSascha Wildner  *              always illegal and some ports are only illegal depending on
126*0d02842fSSascha Wildner  *              the requests the BIOS AML code makes to the predefined
127*0d02842fSSascha Wildner  *              _OSI method.
128*0d02842fSSascha Wildner  *
129*0d02842fSSascha Wildner  ******************************************************************************/
130*0d02842fSSascha Wildner 
131*0d02842fSSascha Wildner static ACPI_STATUS
132*0d02842fSSascha Wildner AcpiHwValidateIoRequest (
133*0d02842fSSascha Wildner     ACPI_IO_ADDRESS         Address,
134*0d02842fSSascha Wildner     UINT32                  BitWidth)
135*0d02842fSSascha Wildner {
136*0d02842fSSascha Wildner     UINT32                  i;
137*0d02842fSSascha Wildner     UINT32                  ByteWidth;
138*0d02842fSSascha Wildner     ACPI_IO_ADDRESS         LastAddress;
139*0d02842fSSascha Wildner     const ACPI_PORT_INFO    *PortInfo;
140*0d02842fSSascha Wildner 
141*0d02842fSSascha Wildner 
142*0d02842fSSascha Wildner     ACPI_FUNCTION_TRACE (HwValidateIoRequest);
143*0d02842fSSascha Wildner 
144*0d02842fSSascha Wildner 
145*0d02842fSSascha Wildner     /* Supported widths are 8/16/32 */
146*0d02842fSSascha Wildner 
147*0d02842fSSascha Wildner     if ((BitWidth != 8) &&
148*0d02842fSSascha Wildner         (BitWidth != 16) &&
149*0d02842fSSascha Wildner         (BitWidth != 32))
150*0d02842fSSascha Wildner     {
151*0d02842fSSascha Wildner         ACPI_ERROR ((AE_INFO,
152*0d02842fSSascha Wildner             "Bad BitWidth parameter: %8.8X", BitWidth));
153*0d02842fSSascha Wildner         return (AE_BAD_PARAMETER);
154*0d02842fSSascha Wildner     }
155*0d02842fSSascha Wildner 
156*0d02842fSSascha Wildner     PortInfo = AcpiProtectedPorts;
157*0d02842fSSascha Wildner     ByteWidth = ACPI_DIV_8 (BitWidth);
158*0d02842fSSascha Wildner     LastAddress = Address + ByteWidth - 1;
159*0d02842fSSascha Wildner 
160*0d02842fSSascha Wildner     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
161*0d02842fSSascha Wildner         ACPI_CAST_PTR (void, Address), ACPI_CAST_PTR (void, LastAddress),
162*0d02842fSSascha Wildner         ByteWidth));
163*0d02842fSSascha Wildner 
164*0d02842fSSascha Wildner     /* Maximum 16-bit address in I/O space */
165*0d02842fSSascha Wildner 
166*0d02842fSSascha Wildner     if (LastAddress > ACPI_UINT16_MAX)
167*0d02842fSSascha Wildner     {
168*0d02842fSSascha Wildner         ACPI_ERROR ((AE_INFO,
169*0d02842fSSascha Wildner             "Illegal I/O port address/length above 64K: %p/0x%X",
170*0d02842fSSascha Wildner             ACPI_CAST_PTR (void, Address), ByteWidth));
171*0d02842fSSascha Wildner         return_ACPI_STATUS (AE_LIMIT);
172*0d02842fSSascha Wildner     }
173*0d02842fSSascha Wildner 
174*0d02842fSSascha Wildner     /* Exit if requested address is not within the protected port table */
175*0d02842fSSascha Wildner 
176*0d02842fSSascha Wildner     if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End)
177*0d02842fSSascha Wildner     {
178*0d02842fSSascha Wildner         return_ACPI_STATUS (AE_OK);
179*0d02842fSSascha Wildner     }
180*0d02842fSSascha Wildner 
181*0d02842fSSascha Wildner     /* Check request against the list of protected I/O ports */
182*0d02842fSSascha Wildner 
183*0d02842fSSascha Wildner     for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++)
184*0d02842fSSascha Wildner     {
185*0d02842fSSascha Wildner         /*
186*0d02842fSSascha Wildner          * Check if the requested address range will write to a reserved
187*0d02842fSSascha Wildner          * port. Four cases to consider:
188*0d02842fSSascha Wildner          *
189*0d02842fSSascha Wildner          * 1) Address range is contained completely in the port address range
190*0d02842fSSascha Wildner          * 2) Address range overlaps port range at the port range start
191*0d02842fSSascha Wildner          * 3) Address range overlaps port range at the port range end
192*0d02842fSSascha Wildner          * 4) Address range completely encompasses the port range
193*0d02842fSSascha Wildner          */
194*0d02842fSSascha Wildner         if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start))
195*0d02842fSSascha Wildner         {
196*0d02842fSSascha Wildner             /* Port illegality may depend on the _OSI calls made by the BIOS */
197*0d02842fSSascha Wildner 
198*0d02842fSSascha Wildner             if (AcpiGbl_OsiData >= PortInfo->OsiDependency)
199*0d02842fSSascha Wildner             {
200*0d02842fSSascha Wildner                 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
201*0d02842fSSascha Wildner                     "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
202*0d02842fSSascha Wildner                     ACPI_CAST_PTR (void, Address), ByteWidth, PortInfo->Name,
203*0d02842fSSascha Wildner                     PortInfo->Start, PortInfo->End));
204*0d02842fSSascha Wildner 
205*0d02842fSSascha Wildner                 return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS);
206*0d02842fSSascha Wildner             }
207*0d02842fSSascha Wildner         }
208*0d02842fSSascha Wildner 
209*0d02842fSSascha Wildner         /* Finished if address range ends before the end of this port */
210*0d02842fSSascha Wildner 
211*0d02842fSSascha Wildner         if (LastAddress <= PortInfo->End)
212*0d02842fSSascha Wildner         {
213*0d02842fSSascha Wildner             break;
214*0d02842fSSascha Wildner         }
215*0d02842fSSascha Wildner     }
216*0d02842fSSascha Wildner 
217*0d02842fSSascha Wildner     return_ACPI_STATUS (AE_OK);
218*0d02842fSSascha Wildner }
219*0d02842fSSascha Wildner 
220*0d02842fSSascha Wildner 
221*0d02842fSSascha Wildner /******************************************************************************
222*0d02842fSSascha Wildner  *
223*0d02842fSSascha Wildner  * FUNCTION:    AcpiHwReadPort
224*0d02842fSSascha Wildner  *
225*0d02842fSSascha Wildner  * PARAMETERS:  Address             Address of I/O port/register to read
226*0d02842fSSascha Wildner  *              Value               Where value is placed
227*0d02842fSSascha Wildner  *              Width               Number of bits
228*0d02842fSSascha Wildner  *
229*0d02842fSSascha Wildner  * RETURN:      Status and value read from port
230*0d02842fSSascha Wildner  *
231*0d02842fSSascha Wildner  * DESCRIPTION: Read data from an I/O port or register. This is a front-end
232*0d02842fSSascha Wildner  *              to AcpiOsReadPort that performs validation on both the port
233*0d02842fSSascha Wildner  *              address and the length.
234*0d02842fSSascha Wildner  *
235*0d02842fSSascha Wildner  *****************************************************************************/
236*0d02842fSSascha Wildner 
237*0d02842fSSascha Wildner ACPI_STATUS
238*0d02842fSSascha Wildner AcpiHwReadPort (
239*0d02842fSSascha Wildner     ACPI_IO_ADDRESS         Address,
240*0d02842fSSascha Wildner     UINT32                  *Value,
241*0d02842fSSascha Wildner     UINT32                  Width)
242*0d02842fSSascha Wildner {
243*0d02842fSSascha Wildner     ACPI_STATUS             Status;
244*0d02842fSSascha Wildner     UINT32                  OneByte;
245*0d02842fSSascha Wildner     UINT32                  i;
246*0d02842fSSascha Wildner 
247*0d02842fSSascha Wildner 
248*0d02842fSSascha Wildner     /* Truncate address to 16 bits if requested */
249*0d02842fSSascha Wildner 
250*0d02842fSSascha Wildner     if (AcpiGbl_TruncateIoAddresses)
251*0d02842fSSascha Wildner     {
252*0d02842fSSascha Wildner         Address &= ACPI_UINT16_MAX;
253*0d02842fSSascha Wildner     }
254*0d02842fSSascha Wildner 
255*0d02842fSSascha Wildner     /* Validate the entire request and perform the I/O */
256*0d02842fSSascha Wildner 
257*0d02842fSSascha Wildner     Status = AcpiHwValidateIoRequest (Address, Width);
258*0d02842fSSascha Wildner     if (ACPI_SUCCESS (Status))
259*0d02842fSSascha Wildner     {
260*0d02842fSSascha Wildner         Status = AcpiOsReadPort (Address, Value, Width);
261*0d02842fSSascha Wildner         return (Status);
262*0d02842fSSascha Wildner     }
263*0d02842fSSascha Wildner 
264*0d02842fSSascha Wildner     if (Status != AE_AML_ILLEGAL_ADDRESS)
265*0d02842fSSascha Wildner     {
266*0d02842fSSascha Wildner         return (Status);
267*0d02842fSSascha Wildner     }
268*0d02842fSSascha Wildner 
269*0d02842fSSascha Wildner     /*
270*0d02842fSSascha Wildner      * There has been a protection violation within the request. Fall
271*0d02842fSSascha Wildner      * back to byte granularity port I/O and ignore the failing bytes.
272*0d02842fSSascha Wildner      * This provides Windows compatibility.
273*0d02842fSSascha Wildner      */
274*0d02842fSSascha Wildner     for (i = 0, *Value = 0; i < Width; i += 8)
275*0d02842fSSascha Wildner     {
276*0d02842fSSascha Wildner         /* Validate and read one byte */
277*0d02842fSSascha Wildner 
278*0d02842fSSascha Wildner         if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
279*0d02842fSSascha Wildner         {
280*0d02842fSSascha Wildner             Status = AcpiOsReadPort (Address, &OneByte, 8);
281*0d02842fSSascha Wildner             if (ACPI_FAILURE (Status))
282*0d02842fSSascha Wildner             {
283*0d02842fSSascha Wildner                 return (Status);
284*0d02842fSSascha Wildner             }
285*0d02842fSSascha Wildner 
286*0d02842fSSascha Wildner             *Value |= (OneByte << i);
287*0d02842fSSascha Wildner         }
288*0d02842fSSascha Wildner 
289*0d02842fSSascha Wildner         Address++;
290*0d02842fSSascha Wildner     }
291*0d02842fSSascha Wildner 
292*0d02842fSSascha Wildner     return (AE_OK);
293*0d02842fSSascha Wildner }
294*0d02842fSSascha Wildner 
295*0d02842fSSascha Wildner 
296*0d02842fSSascha Wildner /******************************************************************************
297*0d02842fSSascha Wildner  *
298*0d02842fSSascha Wildner  * FUNCTION:    AcpiHwWritePort
299*0d02842fSSascha Wildner  *
300*0d02842fSSascha Wildner  * PARAMETERS:  Address             Address of I/O port/register to write
301*0d02842fSSascha Wildner  *              Value               Value to write
302*0d02842fSSascha Wildner  *              Width               Number of bits
303*0d02842fSSascha Wildner  *
304*0d02842fSSascha Wildner  * RETURN:      Status
305*0d02842fSSascha Wildner  *
306*0d02842fSSascha Wildner  * DESCRIPTION: Write data to an I/O port or register. This is a front-end
307*0d02842fSSascha Wildner  *              to AcpiOsWritePort that performs validation on both the port
308*0d02842fSSascha Wildner  *              address and the length.
309*0d02842fSSascha Wildner  *
310*0d02842fSSascha Wildner  *****************************************************************************/
311*0d02842fSSascha Wildner 
312*0d02842fSSascha Wildner ACPI_STATUS
313*0d02842fSSascha Wildner AcpiHwWritePort (
314*0d02842fSSascha Wildner     ACPI_IO_ADDRESS         Address,
315*0d02842fSSascha Wildner     UINT32                  Value,
316*0d02842fSSascha Wildner     UINT32                  Width)
317*0d02842fSSascha Wildner {
318*0d02842fSSascha Wildner     ACPI_STATUS             Status;
319*0d02842fSSascha Wildner     UINT32                  i;
320*0d02842fSSascha Wildner 
321*0d02842fSSascha Wildner 
322*0d02842fSSascha Wildner     /* Truncate address to 16 bits if requested */
323*0d02842fSSascha Wildner 
324*0d02842fSSascha Wildner     if (AcpiGbl_TruncateIoAddresses)
325*0d02842fSSascha Wildner     {
326*0d02842fSSascha Wildner         Address &= ACPI_UINT16_MAX;
327*0d02842fSSascha Wildner     }
328*0d02842fSSascha Wildner 
329*0d02842fSSascha Wildner     /* Validate the entire request and perform the I/O */
330*0d02842fSSascha Wildner 
331*0d02842fSSascha Wildner     Status = AcpiHwValidateIoRequest (Address, Width);
332*0d02842fSSascha Wildner     if (ACPI_SUCCESS (Status))
333*0d02842fSSascha Wildner     {
334*0d02842fSSascha Wildner         Status = AcpiOsWritePort (Address, Value, Width);
335*0d02842fSSascha Wildner         return (Status);
336*0d02842fSSascha Wildner     }
337*0d02842fSSascha Wildner 
338*0d02842fSSascha Wildner     if (Status != AE_AML_ILLEGAL_ADDRESS)
339*0d02842fSSascha Wildner     {
340*0d02842fSSascha Wildner         return (Status);
341*0d02842fSSascha Wildner     }
342*0d02842fSSascha Wildner 
343*0d02842fSSascha Wildner     /*
344*0d02842fSSascha Wildner      * There has been a protection violation within the request. Fall
345*0d02842fSSascha Wildner      * back to byte granularity port I/O and ignore the failing bytes.
346*0d02842fSSascha Wildner      * This provides Windows compatibility.
347*0d02842fSSascha Wildner      */
348*0d02842fSSascha Wildner     for (i = 0; i < Width; i += 8)
349*0d02842fSSascha Wildner     {
350*0d02842fSSascha Wildner         /* Validate and write one byte */
351*0d02842fSSascha Wildner 
352*0d02842fSSascha Wildner         if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
353*0d02842fSSascha Wildner         {
354*0d02842fSSascha Wildner             Status = AcpiOsWritePort (Address, (Value >> i) & 0xFF, 8);
355*0d02842fSSascha Wildner             if (ACPI_FAILURE (Status))
356*0d02842fSSascha Wildner             {
357*0d02842fSSascha Wildner                 return (Status);
358*0d02842fSSascha Wildner             }
359*0d02842fSSascha Wildner         }
360*0d02842fSSascha Wildner 
361*0d02842fSSascha Wildner         Address++;
362*0d02842fSSascha Wildner     }
363*0d02842fSSascha Wildner 
364*0d02842fSSascha Wildner     return (AE_OK);
365*0d02842fSSascha Wildner }
366