Merge from vendor branch LESS:
[dragonfly.git] / sys / dev / acpica5 / Osd / OsdHardware.c
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: src/sys/dev/acpica/Osd/OsdHardware.c,v 1.11 2003/08/28 21:22:25 jhb Exp $
28  * $DragonFly: src/sys/dev/acpica5/Osd/OsdHardware.c,v 1.1 2004/02/21 06:48:09 dillon Exp $
29  */
30
31 /*
32  * 6.7 : Hardware Abstraction
33  */
34
35 #include "acpi.h"
36
37 #include <machine/bus_pio.h>
38 #include <machine/bus.h>
39 #include <machine/pci_cfgreg.h>
40 #include <bus/pci/pcireg.h>
41
42 /*
43  * ACPICA's rather gung-ho approach to hardware resource ownership is a little
44  * troublesome insofar as there is no easy way for us to know in advance 
45  * exactly which I/O resources it's going to want to use.
46  * 
47  * In order to deal with this, we ignore resource ownership entirely, and simply
48  * use the native I/O space accessor functionality.  This is Evil, but it works.
49  *
50  * XXX use an intermediate #define for the tag/handle
51  */
52
53 #ifdef __i386__
54 #define ACPI_BUS_SPACE_IO       I386_BUS_SPACE_IO
55 #define ACPI_BUS_HANDLE         0
56 #endif
57 #ifdef __ia64__
58 #define ACPI_BUS_SPACE_IO       IA64_BUS_SPACE_IO
59 #define ACPI_BUS_HANDLE         0
60 #endif
61 #ifdef __amd64__
62 #define ACPI_BUS_SPACE_IO       AMD64_BUS_SPACE_IO
63 #define ACPI_BUS_HANDLE         0
64 #endif
65
66 ACPI_STATUS
67 AcpiOsReadPort (
68     ACPI_IO_ADDRESS     InPort,
69     UINT32              *Value,
70     UINT32              Width)
71 {
72     switch (Width) {
73     case 8:
74         *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
75         break;
76     case 16:
77         *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
78         break;
79     case 32:
80         *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
81         break;
82     default:
83         /* debug trap goes here */
84         break;
85     }
86
87     return(AE_OK);
88 }
89
90 ACPI_STATUS
91 AcpiOsWritePort (
92     ACPI_IO_ADDRESS     OutPort,
93     UINT32              Value,
94     UINT32              Width)
95 {
96     switch (Width) {
97     case 8:
98         bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
99         break;
100     case 16:
101         bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
102         break;
103     case 32:
104         bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
105         break;
106     default:
107         /* debug trap goes here */
108         break;
109     }
110
111     return(AE_OK);
112 }
113
114 ACPI_STATUS
115 AcpiOsReadPciConfiguration (
116     ACPI_PCI_ID         *PciId,
117     UINT32              Register,
118     void                *Value,
119     UINT32              Width)
120 {
121     u_int32_t   byte_width = Width / 8;
122     u_int32_t   val;
123
124     if (!pci_cfgregopen())
125         return(AE_NOT_EXIST);
126
127     val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width);
128     switch (Width) {
129     case 8:
130         *(u_int8_t *)Value = val & 0xff;
131         break;
132     case 16:
133         *(u_int16_t *)Value = val & 0xffff;
134         break;
135     case 32:
136         *(u_int32_t *)Value = val;
137         break;
138     default:
139         /* debug trap goes here */
140         break;
141     }
142     
143
144     return(AE_OK);
145 }
146
147
148 ACPI_STATUS
149 AcpiOsWritePciConfiguration (
150     ACPI_PCI_ID         *PciId,
151     UINT32              Register,
152     ACPI_INTEGER        Value,
153     UINT32              Width)
154 {
155     u_int32_t   byte_width = Width / 8;
156
157     if (!pci_cfgregopen())
158         return(AE_NOT_EXIST);
159
160     pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width);
161
162     return(AE_OK);
163 }
164
165 /* XXX should use acpivar.h but too many include dependencies */
166 extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int
167     *number);
168
169 /*
170  * Depth-first recursive case for finding the bus, given the slot/function.
171  */
172 static int
173 acpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId)
174 {
175     ACPI_HANDLE parent;
176     ACPI_OBJECT_TYPE type;
177     UINT32 adr;
178     int bus, slot, func, class, subclass, header;
179
180     /* Try to get the _BBN object of the root, otherwise assume it is 0 */
181     bus = 0;
182     if (root == curr) {
183         if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus)) &&
184           bootverbose)
185             printf("acpi_bus_number: root bus has no _BBN, assuming 0\n");
186         return (bus);
187     }
188     if (ACPI_FAILURE(AcpiGetParent(curr, &parent)))
189         return (bus);
190     
191     /* First, recurse up the tree until we find the host bus */
192     bus = acpi_bus_number(root, parent, PciId);
193
194     /* Validate parent bus device type */
195     if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) {
196         printf("acpi_bus_number: not a device, type %d\n", type);
197         return (bus);
198     }
199     /* Get the parent's slot and function */
200     if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) {
201         printf("acpi_bus_number: can't get _ADR\n");
202         return (bus);
203     }
204     slot = ACPI_HIWORD(adr);
205     func = ACPI_LOWORD(adr);
206
207     /* Is this a PCI-PCI or Cardbus-PCI bridge? */
208     class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1);
209     if (class != PCIC_BRIDGE)
210         return (bus);
211     subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1);
212     /* Find the header type, masking off the multifunction bit */
213     header = pci_cfgregread(bus, slot, func, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE;
214     if (header == PCIM_HDRTYPE_BRIDGE && subclass == PCIS_BRIDGE_PCI)
215         bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1);
216     if (header == PCIM_HDRTYPE_CARDBUS && subclass == PCIS_BRIDGE_CARDBUS)
217         bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1);
218     return (bus);
219 }
220
221 /*
222  * Find the bus number for a device
223  *
224  * rhandle: handle for the root bus
225  * chandle: handle for the device
226  * PciId: pointer to device slot and function, we fill out bus
227  */
228 void
229 AcpiOsDerivePciId (
230     ACPI_HANDLE         rhandle,
231     ACPI_HANDLE         chandle,
232     ACPI_PCI_ID         **PciId)
233 {
234     ACPI_HANDLE parent;
235     int bus;
236
237     if (pci_cfgregopen() == 0)
238         panic("AcpiOsDerivePciId unable to initialize pci bus");
239
240     /* Try to read _BBN for bus number if we're at the root */
241     bus = 0;
242     if (rhandle == chandle) {
243         if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus)) &&
244           bootverbose)
245             printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n");
246     }
247     /*
248      * Get the parent handle and call the recursive case.  It is not
249      * clear why we seem to be getting a chandle that points to a child
250      * of the desired slot/function but passing in the parent handle
251      * here works.
252      */
253     if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent)))
254         bus = acpi_bus_number(rhandle, parent, *PciId);
255     (*PciId)->Bus = bus;
256     if (bootverbose) {
257         printf("AcpiOsDerivePciId: bus %d dev %d func %d\n",
258             (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function);
259     }
260 }