OsdHardware.c revision 114246
1/*-
2 * Copyright (c) 2000, 2001 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *	$FreeBSD: head/sys/dev/acpica/Osd/OsdHardware.c 114246 2003-04-29 18:50:34Z njl $
28 */
29
30/*
31 * 6.7 : Hardware Abstraction
32 */
33
34#include "acpi.h"
35
36#include <machine/bus_pio.h>
37#include <machine/bus.h>
38#include <machine/pci_cfgreg.h>
39#include <dev/pci/pcireg.h>
40
41/*
42 * ACPICA's rather gung-ho approach to hardware resource ownership is a little
43 * troublesome insofar as there is no easy way for us to know in advance
44 * exactly which I/O resources it's going to want to use.
45 *
46 * In order to deal with this, we ignore resource ownership entirely, and simply
47 * use the native I/O space accessor functionality.  This is Evil, but it works.
48 *
49 * XXX use an intermediate #define for the tag/handle
50 */
51
52#ifdef __i386__
53#define ACPI_BUS_SPACE_IO	I386_BUS_SPACE_IO
54#define ACPI_BUS_HANDLE		0
55#endif
56#ifdef __ia64__
57#define ACPI_BUS_SPACE_IO	IA64_BUS_SPACE_IO
58#define ACPI_BUS_HANDLE		0
59#endif
60
61ACPI_STATUS
62AcpiOsReadPort (
63    ACPI_IO_ADDRESS	InPort,
64    void		*Value,
65    UINT32		Width)
66{
67    switch (Width) {
68    case 8:
69        *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
70        break;
71    case 16:
72        *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
73        break;
74    case 32:
75        *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
76        break;
77    default:
78        /* debug trap goes here */
79	break;
80    }
81
82    return(AE_OK);
83}
84
85ACPI_STATUS
86AcpiOsWritePort (
87    ACPI_IO_ADDRESS	OutPort,
88    ACPI_INTEGER	Value,
89    UINT32		Width)
90{
91    switch (Width) {
92    case 8:
93        bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
94        break;
95    case 16:
96        bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
97        break;
98    case 32:
99        bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
100        break;
101    default:
102        /* debug trap goes here */
103	break;
104    }
105
106    return(AE_OK);
107}
108
109ACPI_STATUS
110AcpiOsReadPciConfiguration (
111    ACPI_PCI_ID		*PciId,
112    UINT32		Register,
113    void		*Value,
114    UINT32		Width)
115{
116    u_int32_t	byte_width = Width / 8;
117    u_int32_t	val;
118
119    if (!pci_cfgregopen())
120        return(AE_NOT_EXIST);
121
122    val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width);
123    switch (Width) {
124    case 8:
125	*(u_int8_t *)Value = val & 0xff;
126	break;
127    case 16:
128	*(u_int16_t *)Value = val & 0xffff;
129	break;
130    case 32:
131	*(u_int32_t *)Value = val;
132	break;
133    default:
134	/* debug trap goes here */
135	break;
136    }
137
138
139    return(AE_OK);
140}
141
142
143ACPI_STATUS
144AcpiOsWritePciConfiguration (
145    ACPI_PCI_ID		*PciId,
146    UINT32		Register,
147    ACPI_INTEGER	Value,
148    UINT32		Width)
149{
150    u_int32_t	byte_width = Width / 8;
151
152    if (!pci_cfgregopen())
153    	return(AE_NOT_EXIST);
154
155    pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width);
156
157    return(AE_OK);
158}
159
160/* XXX should use acpivar.h but too many include dependencies */
161extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int
162    *number);
163
164/*
165 * Depth-first recursive case for finding the bus, given the slot/function.
166 */
167static int
168acpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId)
169{
170    ACPI_HANDLE parent;
171    ACPI_OBJECT_TYPE type;
172    UINT32 adr;
173    int bus, slot, func, class, subclass, header;
174
175    /* Try to get the _BBN object of the root, otherwise assume it is 0 */
176    bus = 0;
177    if (root == curr) {
178        if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus)))
179            printf("acpi_bus_number: root bus has no _BBN, assuming 0\n");
180	return (bus);
181    }
182    if (ACPI_FAILURE(AcpiGetParent(curr, &parent)))
183        return (bus);
184
185    /* First, recurse up the tree until we find the host bus */
186    bus = acpi_bus_number(root, parent, PciId);
187
188    /* Validate parent bus device type */
189    if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) {
190        printf("acpi_bus_number: not a device, type %d\n", type);
191        return (bus);
192    }
193    /* Get the parent's slot and function */
194    if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) {
195        printf("acpi_bus_number: can't get _ADR\n");
196        return (bus);
197    }
198    slot = ACPI_HIWORD(adr);
199    func = ACPI_LOWORD(adr);
200
201    /* Is this a PCI-PCI or Cardbus-PCI bridge? */
202    class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1);
203    if (class != PCIC_BRIDGE)
204        return (bus);
205    subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1);
206    /* Find the header type, masking off the multifunction bit */
207    header = pci_cfgregread(bus, slot, func, PCIR_HEADERTYPE, 1) & 0x7f;
208    if (header == 1 && subclass == PCIS_BRIDGE_PCI)
209        bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1);
210    if (header == 2 && subclass == PCIS_BRIDGE_CARDBUS)
211        bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1);
212    return (bus);
213}
214
215/*
216 * Find the bus number for a device
217 *
218 * rhandle: handle for the root bus
219 * chandle: handle for the device
220 * PciId: pointer to device slot and function, we fill out bus
221 */
222void
223AcpiOsDerivePciId (
224    ACPI_HANDLE		rhandle,
225    ACPI_HANDLE		chandle,
226    ACPI_PCI_ID		**PciId)
227{
228    ACPI_HANDLE parent;
229    int bus;
230
231    if (pci_cfgregopen() == 0)
232        panic("AcpiOsDerivePciId unable to initialize pci bus");
233
234    /* Try to read _BBN for bus number if we're at the root */
235    bus = 0;
236    if (rhandle == chandle) {
237        if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus)))
238            printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n");
239    }
240    /*
241     * Get the parent handle and call the recursive case.  It is not
242     * clear why we seem to be getting a chandle that points to a child
243     * of the desired slot/function but passing in the parent handle
244     * here works.
245     */
246    if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent)))
247        bus = acpi_bus_number(rhandle, parent, *PciId);
248    (*PciId)->Bus = bus;
249    if (bootverbose) {
250        printf("AcpiOsDerivePciId: bus %d dev %d func %d\n",
251            (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function);
252    }
253}
254