Home | History | Annotate | Line # | Download | only in acpica
OsdHardware.c revision 1.2.38.1
      1  1.2.38.1   matt /*	$NetBSD: OsdHardware.c,v 1.2.38.1 2008/01/09 01:52:22 matt Exp $	*/
      2       1.1  kochi 
      3       1.1  kochi /*
      4       1.1  kochi  * Copyright 2001 Wasabi Systems, Inc.
      5       1.1  kochi  * All rights reserved.
      6       1.1  kochi  *
      7       1.1  kochi  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8       1.1  kochi  *
      9       1.1  kochi  * Redistribution and use in source and binary forms, with or without
     10       1.1  kochi  * modification, are permitted provided that the following conditions
     11       1.1  kochi  * are met:
     12       1.1  kochi  * 1. Redistributions of source code must retain the above copyright
     13       1.1  kochi  *    notice, this list of conditions and the following disclaimer.
     14       1.1  kochi  * 2. Redistributions in binary form must reproduce the above copyright
     15       1.1  kochi  *    notice, this list of conditions and the following disclaimer in the
     16       1.1  kochi  *    documentation and/or other materials provided with the distribution.
     17       1.1  kochi  * 3. All advertising materials mentioning features or use of this software
     18       1.1  kochi  *    must display the following acknowledgement:
     19       1.1  kochi  *	This product includes software developed for the NetBSD Project by
     20       1.1  kochi  *	Wasabi Systems, Inc.
     21       1.1  kochi  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22       1.1  kochi  *    or promote products derived from this software without specific prior
     23       1.1  kochi  *    written permission.
     24       1.1  kochi  *
     25       1.1  kochi  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26       1.1  kochi  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27       1.1  kochi  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28       1.1  kochi  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29       1.1  kochi  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30       1.1  kochi  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31       1.1  kochi  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32       1.1  kochi  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33       1.1  kochi  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34       1.1  kochi  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35       1.1  kochi  * POSSIBILITY OF SUCH DAMAGE.
     36       1.1  kochi  */
     37       1.1  kochi 
     38       1.1  kochi /*
     39       1.1  kochi  * OS Services Layer
     40       1.1  kochi  *
     41       1.1  kochi  * 6.7: Address Space Access: Port Input/Output
     42       1.1  kochi  * 6.8: Address Space Access: Memory and Memory Mapped I/O
     43       1.1  kochi  * 6.9: Address Space Access: PCI Configuration Space
     44       1.1  kochi  */
     45       1.1  kochi 
     46       1.1  kochi #include <sys/cdefs.h>
     47  1.2.38.1   matt __KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.2.38.1 2008/01/09 01:52:22 matt Exp $");
     48       1.1  kochi 
     49       1.1  kochi #include <sys/param.h>
     50       1.1  kochi #include <sys/device.h>
     51       1.1  kochi 
     52       1.1  kochi #include <dev/acpi/acpica.h>
     53       1.1  kochi #include <dev/acpi/acpivar.h>
     54       1.1  kochi 
     55       1.1  kochi #include <machine/acpi_machdep.h>
     56       1.1  kochi 
     57       1.1  kochi /*
     58       1.1  kochi  * ACPICA doesn't provide much in the way of letting us know which
     59       1.1  kochi  * hardware resources it wants to use.  We therefore have to resort
     60       1.1  kochi  * to calling machinde-dependent code to do the access for us.
     61       1.1  kochi  */
     62       1.1  kochi 
     63       1.1  kochi /*
     64       1.1  kochi  * AcpiOsReadPort:
     65       1.1  kochi  *
     66       1.1  kochi  *	Read a value from an input port.
     67       1.1  kochi  */
     68       1.1  kochi ACPI_STATUS
     69       1.1  kochi AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
     70       1.1  kochi {
     71       1.1  kochi 
     72       1.1  kochi 	switch (Width) {
     73       1.1  kochi 	case 8:
     74       1.1  kochi 		*Value = acpi_md_OsIn8(Address);
     75       1.1  kochi 		break;
     76       1.1  kochi 
     77       1.1  kochi 	case 16:
     78       1.1  kochi 		*Value = acpi_md_OsIn16(Address);
     79       1.1  kochi 		break;
     80       1.1  kochi 
     81       1.1  kochi 	case 32:
     82       1.1  kochi 		*Value = acpi_md_OsIn32(Address);
     83       1.1  kochi 		break;
     84       1.1  kochi 
     85       1.1  kochi 	default:
     86       1.1  kochi 		return AE_BAD_PARAMETER;
     87       1.1  kochi 	}
     88       1.1  kochi 
     89       1.1  kochi 	return AE_OK;
     90       1.1  kochi }
     91       1.1  kochi 
     92       1.1  kochi /*
     93       1.1  kochi  * AcpiOsWritePort:
     94       1.1  kochi  *
     95       1.1  kochi  *	Write a value to an output port.
     96       1.1  kochi  */
     97       1.1  kochi ACPI_STATUS
     98       1.1  kochi AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
     99       1.1  kochi {
    100       1.1  kochi 
    101       1.1  kochi 	switch (Width) {
    102       1.1  kochi 	case 8:
    103       1.1  kochi 		acpi_md_OsOut8(Address, Value);
    104       1.1  kochi 		break;
    105       1.1  kochi 
    106       1.1  kochi 	case 16:
    107       1.1  kochi 		acpi_md_OsOut16(Address, Value);
    108       1.1  kochi 		break;
    109       1.1  kochi 
    110       1.1  kochi 	case 32:
    111       1.1  kochi 		acpi_md_OsOut32(Address, Value);
    112       1.1  kochi 		break;
    113       1.1  kochi 
    114       1.1  kochi 	default:
    115       1.1  kochi 		return AE_BAD_PARAMETER;
    116       1.1  kochi 	}
    117       1.1  kochi 
    118       1.1  kochi 	return AE_OK;
    119       1.1  kochi }
    120       1.1  kochi 
    121       1.1  kochi /*
    122       1.1  kochi  * AcpiOsReadMemory:
    123       1.1  kochi  *
    124       1.1  kochi  *	Read a value from a memory location.
    125       1.1  kochi  */
    126       1.1  kochi ACPI_STATUS
    127       1.1  kochi AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width)
    128       1.1  kochi {
    129       1.1  kochi 	void *LogicalAddress;
    130       1.1  kochi 	ACPI_STATUS rv;
    131       1.1  kochi 
    132  1.2.38.1   matt 	LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
    133  1.2.38.1   matt 	if (LogicalAddress == NULL)
    134  1.2.38.1   matt 		return AE_NOT_EXIST;
    135       1.1  kochi 
    136       1.1  kochi 	switch (Width) {
    137       1.1  kochi 	case 8:
    138       1.1  kochi 		*Value = *(volatile uint8_t *) LogicalAddress;
    139       1.1  kochi 		break;
    140       1.1  kochi 
    141       1.1  kochi 	case 16:
    142       1.1  kochi 		*Value = *(volatile uint16_t *) LogicalAddress;
    143       1.1  kochi 		break;
    144       1.1  kochi 
    145       1.1  kochi 	case 32:
    146       1.1  kochi 		*Value = *(volatile uint32_t *) LogicalAddress;
    147       1.1  kochi 		break;
    148       1.1  kochi 
    149       1.1  kochi 	default:
    150       1.1  kochi 		rv = AE_BAD_PARAMETER;
    151       1.1  kochi 	}
    152       1.1  kochi 
    153       1.1  kochi 	AcpiOsUnmapMemory(LogicalAddress, Width / 8);
    154       1.1  kochi 
    155       1.1  kochi 	return rv;
    156       1.1  kochi }
    157       1.1  kochi 
    158       1.1  kochi /*
    159       1.1  kochi  * AcpiOsWriteMemory:
    160       1.1  kochi  *
    161       1.1  kochi  *	Write a value to a memory location.
    162       1.1  kochi  */
    163       1.1  kochi ACPI_STATUS
    164       1.1  kochi AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width)
    165       1.1  kochi {
    166       1.1  kochi 	void *LogicalAddress;
    167       1.1  kochi 	ACPI_STATUS rv;
    168       1.1  kochi 
    169  1.2.38.1   matt 	LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
    170  1.2.38.1   matt 	if (LogicalAddress == NULL)
    171  1.2.38.1   matt 		return AE_NOT_FOUND;
    172       1.1  kochi 
    173       1.1  kochi 	switch (Width) {
    174       1.1  kochi 	case 8:
    175       1.1  kochi 		*(volatile uint8_t *) LogicalAddress = Value;
    176       1.1  kochi 		break;
    177       1.1  kochi 
    178       1.1  kochi 	case 16:
    179       1.1  kochi 		*(volatile uint16_t *) LogicalAddress = Value;
    180       1.1  kochi 		break;
    181       1.1  kochi 
    182       1.1  kochi 	case 32:
    183       1.1  kochi 		*(volatile uint32_t *) LogicalAddress = Value;
    184       1.1  kochi 		break;
    185       1.1  kochi 
    186       1.1  kochi 	default:
    187       1.1  kochi 		rv = AE_BAD_PARAMETER;
    188       1.1  kochi 	}
    189       1.1  kochi 
    190       1.1  kochi 	AcpiOsUnmapMemory(LogicalAddress, Width / 8);
    191       1.1  kochi 
    192       1.1  kochi 	return rv;
    193       1.1  kochi }
    194       1.1  kochi 
    195       1.1  kochi /*
    196       1.1  kochi  * AcpiOsReadPciConfiguration:
    197       1.1  kochi  *
    198       1.1  kochi  *	Read a value from a PCI configuration register.
    199       1.1  kochi  */
    200       1.1  kochi ACPI_STATUS
    201       1.1  kochi AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, void *Value,
    202       1.1  kochi     UINT32 Width)
    203       1.1  kochi {
    204       1.1  kochi 	pcitag_t tag;
    205       1.1  kochi 	pcireg_t tmp;
    206       1.1  kochi 
    207       1.1  kochi 	/* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
    208       1.1  kochi 
    209  1.2.38.1   matt 	if (PciId->Bus >= 256 || PciId->Device >= 32 || PciId->Function >= 8)
    210  1.2.38.1   matt 		return AE_BAD_PARAMETER;
    211  1.2.38.1   matt 
    212       1.1  kochi 	tag = pci_make_tag(acpi_softc->sc_pc, PciId->Bus, PciId->Device,
    213       1.1  kochi 	    PciId->Function);
    214       1.1  kochi 	tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3);
    215       1.1  kochi 
    216       1.1  kochi 	switch (Width) {
    217       1.1  kochi 	case 8:
    218       1.1  kochi 		*(uint8_t *) Value = (tmp >> ((Register & 3) * 8)) & 0xff;
    219       1.1  kochi 		break;
    220       1.1  kochi 
    221       1.1  kochi 	case 16:
    222       1.1  kochi 		*(uint16_t *) Value = (tmp >> ((Register & 3) * 8)) & 0xffff;
    223       1.1  kochi 		break;
    224       1.1  kochi 
    225       1.1  kochi 	case 32:
    226       1.1  kochi 		*(uint32_t *) Value = tmp;
    227       1.1  kochi 		break;
    228       1.1  kochi 
    229       1.1  kochi 	default:
    230       1.1  kochi 		return AE_BAD_PARAMETER;
    231       1.1  kochi 	}
    232       1.1  kochi 
    233       1.1  kochi 	return AE_OK;
    234       1.1  kochi }
    235       1.1  kochi 
    236       1.1  kochi /*
    237       1.1  kochi  * AcpiOsWritePciConfiguration:
    238       1.1  kochi  *
    239       1.1  kochi  *	Write a value to a PCI configuration register.
    240       1.1  kochi  */
    241       1.1  kochi ACPI_STATUS
    242       1.1  kochi AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
    243       1.1  kochi     ACPI_INTEGER Value, UINT32 Width)
    244       1.1  kochi {
    245       1.1  kochi 	pcitag_t tag;
    246       1.1  kochi 	pcireg_t tmp;
    247       1.1  kochi 
    248       1.1  kochi 	/* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
    249       1.1  kochi 
    250       1.1  kochi 	tag = pci_make_tag(acpi_softc->sc_pc, PciId->Bus, PciId->Device,
    251       1.1  kochi 	    PciId->Function);
    252       1.1  kochi 
    253       1.1  kochi 	switch (Width) {
    254       1.1  kochi 	case 8:
    255       1.1  kochi 		tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3);
    256       1.1  kochi 		tmp &= ~(0xff << ((Register & 3) * 8));
    257       1.1  kochi 		tmp |= (Value << ((Register & 3) * 8));
    258       1.1  kochi 		break;
    259       1.1  kochi 
    260       1.1  kochi 	case 16:
    261       1.1  kochi 		tmp = pci_conf_read(acpi_softc->sc_pc, tag, Register & ~3);
    262       1.1  kochi 		tmp &= ~(0xffff << ((Register & 3) * 8));
    263       1.1  kochi 		tmp |= (Value << ((Register & 3) * 8));
    264       1.1  kochi 		break;
    265       1.1  kochi 
    266       1.1  kochi 	case 32:
    267       1.1  kochi 		tmp = Value;
    268       1.1  kochi 		break;
    269       1.1  kochi 
    270       1.1  kochi 	default:
    271       1.1  kochi 		return AE_BAD_PARAMETER;
    272       1.1  kochi 	}
    273       1.1  kochi 
    274       1.1  kochi 	pci_conf_write(acpi_softc->sc_pc, tag, Register & ~3, tmp);
    275       1.1  kochi 
    276       1.1  kochi 	return AE_OK;
    277       1.1  kochi }
    278       1.1  kochi 
    279       1.1  kochi /* get PCI bus# from root bridge recursively */
    280       1.1  kochi static int
    281       1.1  kochi get_bus_number(
    282       1.1  kochi     ACPI_HANDLE        rhandle,
    283       1.1  kochi     ACPI_HANDLE        chandle,
    284       1.1  kochi     ACPI_PCI_ID        **PciId)
    285       1.1  kochi {
    286       1.1  kochi 	ACPI_HANDLE handle;
    287       1.1  kochi 	ACPI_STATUS rv;
    288       1.1  kochi 	ACPI_OBJECT_TYPE type;
    289       1.1  kochi 	ACPI_PCI_ID *id;
    290       1.1  kochi 	ACPI_INTEGER v;
    291       1.1  kochi 	int bus;
    292       1.1  kochi 
    293       1.1  kochi 	id = *PciId;
    294       1.1  kochi 
    295       1.1  kochi 	rv = AcpiGetParent(chandle, &handle);
    296       1.1  kochi 	if (ACPI_FAILURE(rv))
    297       1.1  kochi 		return 0;
    298       1.1  kochi 
    299       1.1  kochi 	/*
    300       1.1  kochi 	 * When handle == rhandle, we have valid PciId->Bus
    301       1.1  kochi 	 * which was obtained from _BBN in evrgnini.c
    302       1.1  kochi 	 * so we don't have to reevaluate _BBN.
    303       1.1  kochi 	 */
    304       1.1  kochi 	if (handle != rhandle) {
    305       1.1  kochi 		bus = get_bus_number(rhandle, handle, PciId);
    306       1.1  kochi 
    307       1.1  kochi 		rv = AcpiGetType(handle, &type);
    308       1.1  kochi 		if (ACPI_FAILURE(rv) || type != ACPI_TYPE_DEVICE)
    309       1.1  kochi 			return bus;
    310       1.1  kochi 
    311       1.1  kochi 		rv = acpi_eval_integer(handle, METHOD_NAME__ADR, &v);
    312       1.1  kochi 
    313       1.1  kochi 		if (ACPI_FAILURE(rv))
    314       1.1  kochi 			return bus;
    315       1.1  kochi 
    316       1.1  kochi 		id->Bus = bus;
    317       1.1  kochi 		id->Device = ACPI_HIWORD((ACPI_INTEGER)v);
    318       1.1  kochi 		id->Function = ACPI_LOWORD((ACPI_INTEGER)v);
    319       1.1  kochi 
    320       1.1  kochi 		/* read HDR_TYPE register */
    321       1.1  kochi 		rv = AcpiOsReadPciConfiguration(id, 0x0e, &v, 8);
    322       1.1  kochi 		if (ACPI_SUCCESS(rv) &&
    323       1.1  kochi 			/* mask multifunction bit & check bridge type */
    324       1.1  kochi 			((v & 0x7f) == 1 || (v & 0x7f) == 2)) {
    325       1.1  kochi 			/* read SECONDARY_BUS register */
    326       1.1  kochi 			rv = AcpiOsReadPciConfiguration(id, 0x19, &v, 8);
    327       1.1  kochi 			if (ACPI_SUCCESS(rv))
    328       1.1  kochi 				id->Bus = v;
    329       1.1  kochi 		}
    330       1.1  kochi 	}
    331       1.1  kochi 
    332       1.1  kochi 	return id->Bus;
    333       1.1  kochi }
    334       1.1  kochi 
    335       1.1  kochi /*
    336       1.1  kochi  * AcpiOsDerivePciId:
    337       1.1  kochi  *
    338       1.1  kochi  * Derive correct PCI bus# by traversing bridges
    339       1.1  kochi  */
    340       1.1  kochi void
    341       1.1  kochi AcpiOsDerivePciId(
    342       1.1  kochi     ACPI_HANDLE        rhandle,
    343       1.1  kochi     ACPI_HANDLE        chandle,
    344       1.1  kochi     ACPI_PCI_ID        **PciId)
    345       1.1  kochi {
    346       1.1  kochi 	(*PciId)->Bus = get_bus_number(rhandle, chandle, PciId);
    347       1.1  kochi }
    348