1 /* $NetBSD: OsdHardware.c,v 1.4 2007/12/12 23:33:22 jmcneill Exp $ */
4 * Copyright 2001 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
41 * 6.7: Address Space Access: Port Input/Output
42 * 6.8: Address Space Access: Memory and Memory Mapped I/O
43 * 6.9: Address Space Access: PCI Configuration Space
46 #include <sys/cdefs.h>
47 __KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.4 2007/12/12 23:33:22 jmcneill Exp $");
49 #include <sys/param.h>
50 #include <sys/device.h>
52 #include <dev/acpi/acpica.h>
53 #include <dev/acpi/acpivar.h>
55 #include <machine/acpi_machdep.h>
58 * ACPICA doesn't provide much in the way of letting us know which
59 * hardware resources it wants to use. We therefore have to resort
60 * to calling machinde-dependent code to do the access for us.
66 * Read a value from an input port.
69 AcpiOsReadPort(ACPI_IO_ADDRESS Address
, UINT32
*Value
, UINT32 Width
)
74 *Value
= acpi_md_OsIn8(Address
);
78 *Value
= acpi_md_OsIn16(Address
);
82 *Value
= acpi_md_OsIn32(Address
);
86 return AE_BAD_PARAMETER
;
95 * Write a value to an output port.
98 AcpiOsWritePort(ACPI_IO_ADDRESS Address
, UINT32 Value
, UINT32 Width
)
103 acpi_md_OsOut8(Address
, Value
);
107 acpi_md_OsOut16(Address
, Value
);
111 acpi_md_OsOut32(Address
, Value
);
115 return AE_BAD_PARAMETER
;
124 * Read a value from a memory location.
127 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address
, UINT32
*Value
, UINT32 Width
)
129 void *LogicalAddress
;
130 ACPI_STATUS rv
= AE_OK
;
132 LogicalAddress
= AcpiOsMapMemory(Address
, Width
/ 8);
133 if (LogicalAddress
== NULL
)
138 *Value
= *(volatile uint8_t *) LogicalAddress
;
142 *Value
= *(volatile uint16_t *) LogicalAddress
;
146 *Value
= *(volatile uint32_t *) LogicalAddress
;
150 rv
= AE_BAD_PARAMETER
;
153 AcpiOsUnmapMemory(LogicalAddress
, Width
/ 8);
161 * Write a value to a memory location.
164 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address
, UINT32 Value
, UINT32 Width
)
166 void *LogicalAddress
;
167 ACPI_STATUS rv
= AE_OK
;
169 LogicalAddress
= AcpiOsMapMemory(Address
, Width
/ 8);
170 if (LogicalAddress
== NULL
)
175 *(volatile uint8_t *) LogicalAddress
= Value
;
179 *(volatile uint16_t *) LogicalAddress
= Value
;
183 *(volatile uint32_t *) LogicalAddress
= Value
;
187 rv
= AE_BAD_PARAMETER
;
190 AcpiOsUnmapMemory(LogicalAddress
, Width
/ 8);
196 * AcpiOsReadPciConfiguration:
198 * Read a value from a PCI configuration register.
201 AcpiOsReadPciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Register
, void *Value
,
207 /* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
209 if (PciId
->Bus
>= 256 || PciId
->Device
>= 32 || PciId
->Function
>= 8)
210 return AE_BAD_PARAMETER
;
212 tag
= pci_make_tag(acpi_softc
->sc_pc
, PciId
->Bus
, PciId
->Device
,
214 tmp
= pci_conf_read(acpi_softc
->sc_pc
, tag
, Register
& ~3);
218 *(uint8_t *) Value
= (tmp
>> ((Register
& 3) * 8)) & 0xff;
222 *(uint16_t *) Value
= (tmp
>> ((Register
& 3) * 8)) & 0xffff;
226 *(uint32_t *) Value
= tmp
;
230 return AE_BAD_PARAMETER
;
237 * AcpiOsWritePciConfiguration:
239 * Write a value to a PCI configuration register.
242 AcpiOsWritePciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Register
,
243 ACPI_INTEGER Value
, UINT32 Width
)
248 /* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
250 tag
= pci_make_tag(acpi_softc
->sc_pc
, PciId
->Bus
, PciId
->Device
,
255 tmp
= pci_conf_read(acpi_softc
->sc_pc
, tag
, Register
& ~3);
256 tmp
&= ~(0xff << ((Register
& 3) * 8));
257 tmp
|= (Value
<< ((Register
& 3) * 8));
261 tmp
= pci_conf_read(acpi_softc
->sc_pc
, tag
, Register
& ~3);
262 tmp
&= ~(0xffff << ((Register
& 3) * 8));
263 tmp
|= (Value
<< ((Register
& 3) * 8));
271 return AE_BAD_PARAMETER
;
274 pci_conf_write(acpi_softc
->sc_pc
, tag
, Register
& ~3, tmp
);
279 /* get PCI bus# from root bridge recursively */
288 ACPI_OBJECT_TYPE type
;
295 rv
= AcpiGetParent(chandle
, &handle
);
296 if (ACPI_FAILURE(rv
))
300 * When handle == rhandle, we have valid PciId->Bus
301 * which was obtained from _BBN in evrgnini.c
302 * so we don't have to reevaluate _BBN.
304 if (handle
!= rhandle
) {
305 bus
= get_bus_number(rhandle
, handle
, PciId
);
307 rv
= AcpiGetType(handle
, &type
);
308 if (ACPI_FAILURE(rv
) || type
!= ACPI_TYPE_DEVICE
)
311 rv
= acpi_eval_integer(handle
, METHOD_NAME__ADR
, &v
);
313 if (ACPI_FAILURE(rv
))
317 id
->Device
= ACPI_HIWORD((ACPI_INTEGER
)v
);
318 id
->Function
= ACPI_LOWORD((ACPI_INTEGER
)v
);
320 /* read HDR_TYPE register */
321 rv
= AcpiOsReadPciConfiguration(id
, 0x0e, &v
, 8);
322 if (ACPI_SUCCESS(rv
) &&
323 /* mask multifunction bit & check bridge type */
324 ((v
& 0x7f) == 1 || (v
& 0x7f) == 2)) {
325 /* read SECONDARY_BUS register */
326 rv
= AcpiOsReadPciConfiguration(id
, 0x19, &v
, 8);
327 if (ACPI_SUCCESS(rv
))
338 * Derive correct PCI bus# by traversing bridges
346 (*PciId
)->Bus
= get_bus_number(rhandle
, chandle
, PciId
);