Home | History | Annotate | Line # | Download | only in acpi
acpi_pci.c revision 1.7
      1 /* $NetBSD: acpi_pci.c,v 1.7 2010/04/22 15:14:24 jruoho Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Christoph Egger and Gregoire Sutre.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 
     31 /*
     32  * ACPI PCI Bus
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.7 2010/04/22 15:14:24 jruoho Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/device.h>
     40 #include <sys/kmem.h>
     41 #include <sys/systm.h>
     42 
     43 #include <dev/pci/pcireg.h>
     44 #include <dev/pci/pcidevs.h>
     45 #include <dev/pci/ppbreg.h>
     46 
     47 #include <dev/acpi/acpireg.h>
     48 #include <dev/acpi/acpivar.h>
     49 #include <dev/acpi/acpi_pci.h>
     50 
     51 #define _COMPONENT	  ACPI_BUS_COMPONENT
     52 ACPI_MODULE_NAME	  ("acpi_pci")
     53 
     54 #define ACPI_HILODWORD(x) ACPI_HIWORD(ACPI_LODWORD((x)))
     55 #define ACPI_LOLODWORD(x) ACPI_LOWORD(ACPI_LODWORD((x)))
     56 
     57 static ACPI_STATUS	  acpi_pcidev_pciroot_bus(ACPI_HANDLE, uint16_t *);
     58 static ACPI_STATUS	  acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *,
     59 							   void *);
     60 static ACPI_STATUS	  acpi_pcidev_scan_rec(struct acpi_devnode *);
     61 
     62 
     63 /*
     64  * Regarding PCI Segment Groups, the ACPI spec says (cf. ACPI 4.0, p. 277):
     65  *
     66  * "The optional _SEG object is located under a PCI host bridge and
     67  * evaluates to an integer that describes the PCI Segment Group (see PCI
     68  * Firmware Specification v3.0)."
     69  *
     70  * "PCI Segment Group supports more than 256 buses in a system by allowing
     71  * the reuse of the PCI bus numbers.  Within each PCI Segment Group, the bus
     72  * numbers for the PCI buses must be unique. PCI buses in different PCI
     73  * Segment Group are permitted to have the same bus number."
     74  *
     75  * "If _SEG does not exist, OSPM assumes that all PCI bus segments are in
     76  * PCI Segment Group 0."
     77  *
     78  * "The lower 16 bits of _SEG returned integer is the PCI Segment Group
     79  * number.  Other bits are reserved."
     80  */
     81 
     82 /*
     83  * Regarding PCI Base Bus Numbers, the ACPI spec says (cf. ACPI 4.0, p. 277):
     84  *
     85  * "For multi-root PCI platforms, the _BBN object evaluates to the PCI bus
     86  * number that the BIOS assigns.  This is needed to access a PCI_Config
     87  * operation region for the specified bus.  The _BBN object is located under
     88  * a PCI host bridge and must be unique for every host bridge within a
     89  * segment since it is the PCI bus number."
     90  *
     91  * Moreover, the ACPI FAQ (http://www.acpi.info/acpi_faq.htm) says:
     92  *
     93  * "For a multiple root bus machine, _BBN is required for each bus.  _BBN
     94  * should provide the bus number assigned to this bus by the BIOS at boot
     95  * time."
     96  */
     97 
     98 
     99 /*
    100  * acpi_pcidev_pciroot_bus:
    101  *
    102  *	Derive the PCI bus number of a PCI root bridge from its resources.
    103  *	If successful, return AE_OK and fill *busp.  Otherwise, return an
    104  *	exception code and leave *busp unchanged.
    105  *
    106  * XXX	Use ACPI resource parsing functions (acpi_resource.c) once bus number
    107  *	ranges are implemented there.
    108  */
    109 static ACPI_STATUS
    110 acpi_pcidev_pciroot_bus(ACPI_HANDLE handle, uint16_t *busp)
    111 {
    112 	ACPI_STATUS rv;
    113 	int32_t bus;
    114 
    115 	bus = -1;
    116 	rv = AcpiWalkResources(handle, METHOD_NAME__CRS,
    117 	    acpi_pcidev_pciroot_bus_callback, &bus);
    118 
    119 	if (ACPI_FAILURE(rv))
    120 		return rv;
    121 
    122 	if (bus < 0 || bus > 0xFFFF)
    123 		return AE_NOT_EXIST;
    124 
    125 	*busp = (uint16_t)bus;
    126 	return rv;
    127 }
    128 
    129 static ACPI_STATUS
    130 acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *res, void *context)
    131 {
    132 	int32_t *bus = context;
    133 	ACPI_RESOURCE_ADDRESS64 addr64;
    134 
    135 	if ((res->Type != ACPI_RESOURCE_TYPE_ADDRESS16) &&
    136 	    (res->Type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
    137 	    (res->Type != ACPI_RESOURCE_TYPE_ADDRESS64))
    138 		return AE_OK;	/* continue the walk */
    139 
    140 	if (ACPI_FAILURE(AcpiResourceToAddress64(res, &addr64)))
    141 		return AE_OK;	/* continue the walk */
    142 
    143 	if (addr64.ResourceType != ACPI_BUS_NUMBER_RANGE)
    144 		return AE_OK;	/* continue the walk */
    145 
    146 	if (*bus != -1)
    147 		return AE_ALREADY_EXISTS;
    148 
    149 	*bus = addr64.Minimum;
    150 	return AE_OK;		/* continue the walk */
    151 }
    152 
    153 /*
    154  * acpi_pcidev_scan_rec:
    155  *
    156  *	Scan the ACPI device tree for PCI devices.  A node is detected as a
    157  *	PCI device if it has an ancestor that is a PCI root bridge and such
    158  *	that all intermediate nodes are PCI-to-PCI bridges.  Depth-first
    159  *	recursive implementation.
    160  */
    161 static ACPI_STATUS
    162 acpi_pcidev_scan_rec(struct acpi_devnode *ad)
    163 {
    164 	struct acpi_devnode *child;
    165 	struct acpi_pci_info *ap;
    166 	ACPI_INTEGER val;
    167 	ACPI_STATUS rv;
    168 
    169 	if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
    170 	    !(ad->ad_devinfo->Valid & ACPI_VALID_ADR)) {
    171 		ad->ad_pciinfo = NULL;
    172 		goto rec;
    173 	}
    174 
    175 	if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) {
    176 		ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
    177 		if (ap == NULL)
    178 			return AE_NO_MEMORY;
    179 
    180 		rv = acpi_eval_integer(ad->ad_handle, METHOD_NAME__SEG, &val);
    181 		if (ACPI_SUCCESS(rv))
    182 			ap->ap_segment = ACPI_LOWORD(val);
    183 		else
    184 			ap->ap_segment = 0;
    185 
    186 		/* try to get bus number using _CRS first */
    187 		rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_bus);
    188 		if (ACPI_FAILURE(rv)) {
    189 			rv = acpi_eval_integer(ad->ad_handle, METHOD_NAME__BBN, &val);
    190 			if (ACPI_SUCCESS(rv))
    191 				ap->ap_bus = ACPI_LOWORD(val);
    192 			else
    193 				ap->ap_bus = 0;
    194 		}
    195 
    196 		ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
    197 		ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
    198 
    199 		ap->ap_bridge = true;
    200 		ap->ap_downbus = ap->ap_bus;
    201 
    202 		ad->ad_pciinfo = ap;
    203 		goto rec;
    204 	}
    205 
    206 	if ((ad->ad_parent != NULL) &&
    207 	    (ad->ad_parent->ad_pciinfo != NULL) &&
    208 	    (ad->ad_parent->ad_pciinfo->ap_bridge)) {
    209 		/*
    210 		 * Our parent is a PCI root bridge or a PCI-to-PCI bridge.  We
    211 		 * have the same PCI segment#, and our bus# is its downstream
    212 		 * bus number.
    213 		 */
    214 		ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
    215 		if (ap == NULL)
    216 			return AE_NO_MEMORY;
    217 
    218 		ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment;
    219 		ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus;
    220 
    221 		ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
    222 		ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
    223 
    224 		/*
    225 		 * Check whether this device is a PCI-to-PCI bridge and get its
    226 		 * secondary bus#.
    227 		 */
    228 		rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus,
    229 		    ap->ap_device, ap->ap_function, &ap->ap_downbus);
    230 		if (ACPI_SUCCESS(rv))
    231 			ap->ap_bridge = true;
    232 		else
    233 			ap->ap_bridge = false;
    234 
    235 		ad->ad_pciinfo = ap;
    236 		goto rec;
    237 	}
    238  rec:
    239 	SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
    240 		rv = acpi_pcidev_scan_rec(child);
    241 		if (ACPI_FAILURE(rv))
    242 			return rv;
    243 	}
    244 
    245 	return AE_OK;
    246 }
    247 
    248 /*
    249  * acpi_pcidev_ppb_downbus:
    250  *
    251  *	Retrieve the secondary bus number of the PCI-to-PCI bridge having the
    252  *	given PCI id.  If successful, return AE_OK and fill *busp.  Otherwise,
    253  *	return an exception code and leave *busp unchanged.
    254  *
    255  * XXX	Need to deal with PCI segment groups (see also acpica/OsdHardware.c).
    256  */
    257 ACPI_STATUS
    258 acpi_pcidev_ppb_downbus(uint16_t segment, uint16_t bus, uint16_t device,
    259     uint16_t function, uint16_t *downbus)
    260 {
    261 	struct acpi_softc *sc = acpi_softc;
    262 	pci_chipset_tag_t pc;
    263 	pcitag_t tag;
    264 	pcireg_t val;
    265 
    266 	if (bus > 255 || device > 31 || function > 7)
    267 		return AE_BAD_PARAMETER;
    268 
    269 	if (sc == NULL)
    270 		pc = NULL;
    271 	else
    272 		pc = sc->sc_pc;
    273 
    274 	tag = pci_make_tag(pc, bus, device, function);
    275 
    276 	/* Check that this device exists. */
    277 	val = pci_conf_read(pc, tag, PCI_ID_REG);
    278 	if (PCI_VENDOR(val) == PCI_VENDOR_INVALID ||
    279 	    PCI_VENDOR(val) == 0)
    280 		return AE_NOT_EXIST;
    281 
    282 	/* Check that this device is a PCI-to-PCI bridge. */
    283 	val = pci_conf_read(pc, tag, PCI_BHLC_REG);
    284 	if (PCI_HDRTYPE_TYPE(val) != PCI_HDRTYPE_PPB)
    285 		return AE_TYPE;
    286 
    287 	/* This is a PCI-to-PCI bridge.  Get its secondary bus#. */
    288 	val = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
    289 	*downbus = PPB_BUSINFO_SECONDARY(val);
    290 	return AE_OK;
    291 }
    292 
    293 static void
    294 acpi_pcidev_print(struct acpi_devnode *ad)
    295 {
    296 	aprint_debug(" ");
    297 	if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE)
    298 		aprint_debug("*");
    299 	aprint_debug("%s@%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16,
    300 	    ad->ad_name,
    301 	    ad->ad_pciinfo->ap_segment,
    302 	    ad->ad_pciinfo->ap_bus,
    303 	    ad->ad_pciinfo->ap_device,
    304 	    ad->ad_pciinfo->ap_function);
    305 	if (ad->ad_pciinfo->ap_bridge)
    306 		aprint_debug(">%"PRIx16, ad->ad_pciinfo->ap_downbus);
    307 }
    308 
    309 void
    310 acpi_pcidev_scan(struct acpi_softc *sc)
    311 {
    312 	struct acpi_devnode *ad;
    313 
    314 	acpi_pcidev_scan_rec(sc->sc_root);
    315 	aprint_debug_dev(sc->sc_dev, "pci devices:");
    316 	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
    317 		if (ad->ad_pciinfo != NULL)
    318 			acpi_pcidev_print(ad);
    319 	}
    320 	aprint_debug("\n");
    321 }
    322 
    323 /*
    324  * acpi_pcidev_find:
    325  *
    326  *      Finds a PCI device in the ACPI name space.
    327  *      The return status is either:
    328  *      - AE_NOT_FOUND if no such device was found.
    329  *      - AE_OK if one and only one such device was found.
    330  */
    331 ACPI_STATUS
    332 acpi_pcidev_find(uint16_t segment, uint16_t bus, uint16_t device,
    333     uint16_t function, struct acpi_devnode **devnodep)
    334 {
    335 	struct acpi_softc *sc = acpi_softc;
    336 	struct acpi_devnode *ad;
    337 
    338 	if (sc == NULL)
    339 		return AE_NOT_FOUND;
    340 
    341 	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
    342 		if ((ad->ad_pciinfo != NULL) &&
    343 		    (ad->ad_pciinfo->ap_segment == segment) &&
    344 		    (ad->ad_pciinfo->ap_bus == bus) &&
    345 		    (ad->ad_pciinfo->ap_device == device) &&
    346 		    (ad->ad_pciinfo->ap_function == function)) {
    347 			*devnodep = ad;
    348 			return AE_OK;
    349 		}
    350 	}
    351 	return AE_NOT_FOUND;
    352 }
    353