OsdHardware.c revision 114246
167760Smsmith/*-
280071Smsmith * Copyright (c) 2000, 2001 Michael Smith
367760Smsmith * Copyright (c) 2000 BSDi
467760Smsmith * All rights reserved.
567760Smsmith *
667760Smsmith * Redistribution and use in source and binary forms, with or without
767760Smsmith * modification, are permitted provided that the following conditions
867760Smsmith * are met:
967760Smsmith * 1. Redistributions of source code must retain the above copyright
1067760Smsmith *    notice, this list of conditions and the following disclaimer.
1167760Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1267760Smsmith *    notice, this list of conditions and the following disclaimer in the
1367760Smsmith *    documentation and/or other materials provided with the distribution.
1467760Smsmith *
1567760Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1667760Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1767760Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1867760Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1967760Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2067760Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2167760Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2267760Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2367760Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2467760Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2567760Smsmith * SUCH DAMAGE.
2667760Smsmith *
2767760Smsmith *	$FreeBSD: head/sys/dev/acpica/Osd/OsdHardware.c 114246 2003-04-29 18:50:34Z njl $
2867760Smsmith */
2967760Smsmith
3067760Smsmith/*
3167760Smsmith * 6.7 : Hardware Abstraction
3267760Smsmith */
3367760Smsmith
3467760Smsmith#include "acpi.h"
3567760Smsmith
3667760Smsmith#include <machine/bus_pio.h>
3767760Smsmith#include <machine/bus.h>
3867760Smsmith#include <machine/pci_cfgreg.h>
39114246Snjl#include <dev/pci/pcireg.h>
4067760Smsmith
4167760Smsmith/*
4267760Smsmith * ACPICA's rather gung-ho approach to hardware resource ownership is a little
4367760Smsmith * troublesome insofar as there is no easy way for us to know in advance
4467760Smsmith * exactly which I/O resources it's going to want to use.
4567760Smsmith *
4667760Smsmith * In order to deal with this, we ignore resource ownership entirely, and simply
4767760Smsmith * use the native I/O space accessor functionality.  This is Evil, but it works.
4867760Smsmith *
4967760Smsmith * XXX use an intermediate #define for the tag/handle
5067760Smsmith */
5167760Smsmith
5284446Sdfr#ifdef __i386__
5367760Smsmith#define ACPI_BUS_SPACE_IO	I386_BUS_SPACE_IO
5467760Smsmith#define ACPI_BUS_HANDLE		0
5584446Sdfr#endif
5684446Sdfr#ifdef __ia64__
5784446Sdfr#define ACPI_BUS_SPACE_IO	IA64_BUS_SPACE_IO
5884446Sdfr#define ACPI_BUS_HANDLE		0
5984446Sdfr#endif
6067760Smsmith
6180071SmsmithACPI_STATUS
6280071SmsmithAcpiOsReadPort (
6380071Smsmith    ACPI_IO_ADDRESS	InPort,
6480071Smsmith    void		*Value,
6580071Smsmith    UINT32		Width)
6667760Smsmith{
6780071Smsmith    switch (Width) {
6880071Smsmith    case 8:
6980071Smsmith        *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
7080071Smsmith        break;
7180071Smsmith    case 16:
7280071Smsmith        *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
7380071Smsmith        break;
7480071Smsmith    case 32:
7580071Smsmith        *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort);
7680071Smsmith        break;
7780071Smsmith    default:
7880071Smsmith        /* debug trap goes here */
7992666Speter	break;
8080071Smsmith    }
8167760Smsmith
8280071Smsmith    return(AE_OK);
8367760Smsmith}
8467760Smsmith
8567760SmsmithACPI_STATUS
8680071SmsmithAcpiOsWritePort (
8780071Smsmith    ACPI_IO_ADDRESS	OutPort,
8887036Smsmith    ACPI_INTEGER	Value,
8980071Smsmith    UINT32		Width)
9067760Smsmith{
9180071Smsmith    switch (Width) {
9280071Smsmith    case 8:
9380071Smsmith        bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
9480071Smsmith        break;
9580071Smsmith    case 16:
9680071Smsmith        bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
9780071Smsmith        break;
9880071Smsmith    case 32:
9980071Smsmith        bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value);
10080071Smsmith        break;
10180071Smsmith    default:
10280071Smsmith        /* debug trap goes here */
10392666Speter	break;
10480071Smsmith    }
10567760Smsmith
10667760Smsmith    return(AE_OK);
10767760Smsmith}
10867760Smsmith
10967760SmsmithACPI_STATUS
11080071SmsmithAcpiOsReadPciConfiguration (
11180071Smsmith    ACPI_PCI_ID		*PciId,
11280071Smsmith    UINT32		Register,
11380071Smsmith    void		*Value,
11480071Smsmith    UINT32		Width)
11567760Smsmith{
11680071Smsmith    u_int32_t	byte_width = Width / 8;
11780071Smsmith    u_int32_t	val;
11867760Smsmith
11967760Smsmith    if (!pci_cfgregopen())
12080071Smsmith        return(AE_NOT_EXIST);
12167760Smsmith
12280071Smsmith    val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width);
12380071Smsmith    switch (Width) {
12480071Smsmith    case 8:
12580071Smsmith	*(u_int8_t *)Value = val & 0xff;
12680071Smsmith	break;
12780071Smsmith    case 16:
12880071Smsmith	*(u_int16_t *)Value = val & 0xffff;
12980071Smsmith	break;
13080071Smsmith    case 32:
13180071Smsmith	*(u_int32_t *)Value = val;
13280071Smsmith	break;
13380071Smsmith    default:
13480071Smsmith	/* debug trap goes here */
13592666Speter	break;
13680071Smsmith    }
13780071Smsmith
13880071Smsmith
13967760Smsmith    return(AE_OK);
14067760Smsmith}
14167760Smsmith
14280071Smsmith
14367760SmsmithACPI_STATUS
14480071SmsmithAcpiOsWritePciConfiguration (
14580071Smsmith    ACPI_PCI_ID		*PciId,
14680071Smsmith    UINT32		Register,
14787036Smsmith    ACPI_INTEGER	Value,
14880071Smsmith    UINT32		Width)
14967760Smsmith{
15080071Smsmith    u_int32_t	byte_width = Width / 8;
15167760Smsmith
15267760Smsmith    if (!pci_cfgregopen())
15380071Smsmith    	return(AE_NOT_EXIST);
15467760Smsmith
15580071Smsmith    pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width);
15680071Smsmith
15767760Smsmith    return(AE_OK);
15867760Smsmith}
159114246Snjl
160114246Snjl/* XXX should use acpivar.h but too many include dependencies */
161114246Snjlextern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int
162114246Snjl    *number);
163114246Snjl
164114246Snjl/*
165114246Snjl * Depth-first recursive case for finding the bus, given the slot/function.
166114246Snjl */
167114246Snjlstatic int
168114246Snjlacpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId)
169114246Snjl{
170114246Snjl    ACPI_HANDLE parent;
171114246Snjl    ACPI_OBJECT_TYPE type;
172114246Snjl    UINT32 adr;
173114246Snjl    int bus, slot, func, class, subclass, header;
174114246Snjl
175114246Snjl    /* Try to get the _BBN object of the root, otherwise assume it is 0 */
176114246Snjl    bus = 0;
177114246Snjl    if (root == curr) {
178114246Snjl        if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus)))
179114246Snjl            printf("acpi_bus_number: root bus has no _BBN, assuming 0\n");
180114246Snjl	return (bus);
181114246Snjl    }
182114246Snjl    if (ACPI_FAILURE(AcpiGetParent(curr, &parent)))
183114246Snjl        return (bus);
184114246Snjl
185114246Snjl    /* First, recurse up the tree until we find the host bus */
186114246Snjl    bus = acpi_bus_number(root, parent, PciId);
187114246Snjl
188114246Snjl    /* Validate parent bus device type */
189114246Snjl    if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) {
190114246Snjl        printf("acpi_bus_number: not a device, type %d\n", type);
191114246Snjl        return (bus);
192114246Snjl    }
193114246Snjl    /* Get the parent's slot and function */
194114246Snjl    if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) {
195114246Snjl        printf("acpi_bus_number: can't get _ADR\n");
196114246Snjl        return (bus);
197114246Snjl    }
198114246Snjl    slot = ACPI_HIWORD(adr);
199114246Snjl    func = ACPI_LOWORD(adr);
200114246Snjl
201114246Snjl    /* Is this a PCI-PCI or Cardbus-PCI bridge? */
202114246Snjl    class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1);
203114246Snjl    if (class != PCIC_BRIDGE)
204114246Snjl        return (bus);
205114246Snjl    subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1);
206114246Snjl    /* Find the header type, masking off the multifunction bit */
207114246Snjl    header = pci_cfgregread(bus, slot, func, PCIR_HEADERTYPE, 1) & 0x7f;
208114246Snjl    if (header == 1 && subclass == PCIS_BRIDGE_PCI)
209114246Snjl        bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1);
210114246Snjl    if (header == 2 && subclass == PCIS_BRIDGE_CARDBUS)
211114246Snjl        bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1);
212114246Snjl    return (bus);
213114246Snjl}
214114246Snjl
215114246Snjl/*
216114246Snjl * Find the bus number for a device
217114246Snjl *
218114246Snjl * rhandle: handle for the root bus
219114246Snjl * chandle: handle for the device
220114246Snjl * PciId: pointer to device slot and function, we fill out bus
221114246Snjl */
222114246Snjlvoid
223114246SnjlAcpiOsDerivePciId (
224114246Snjl    ACPI_HANDLE		rhandle,
225114246Snjl    ACPI_HANDLE		chandle,
226114246Snjl    ACPI_PCI_ID		**PciId)
227114246Snjl{
228114246Snjl    ACPI_HANDLE parent;
229114246Snjl    int bus;
230114246Snjl
231114246Snjl    if (pci_cfgregopen() == 0)
232114246Snjl        panic("AcpiOsDerivePciId unable to initialize pci bus");
233114246Snjl
234114246Snjl    /* Try to read _BBN for bus number if we're at the root */
235114246Snjl    bus = 0;
236114246Snjl    if (rhandle == chandle) {
237114246Snjl        if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus)))
238114246Snjl            printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n");
239114246Snjl    }
240114246Snjl    /*
241114246Snjl     * Get the parent handle and call the recursive case.  It is not
242114246Snjl     * clear why we seem to be getting a chandle that points to a child
243114246Snjl     * of the desired slot/function but passing in the parent handle
244114246Snjl     * here works.
245114246Snjl     */
246114246Snjl    if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent)))
247114246Snjl        bus = acpi_bus_number(rhandle, parent, *PciId);
248114246Snjl    (*PciId)->Bus = bus;
249114246Snjl    if (bootverbose) {
250114246Snjl        printf("AcpiOsDerivePciId: bus %d dev %d func %d\n",
251114246Snjl            (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function);
252114246Snjl    }
253114246Snjl}
254