Home | History | Annotate | Line # | Download | only in pci
pci_machdep_ofw.c revision 1.12.20.1
      1  1.12.20.1  uebayasi /* $NetBSD: pci_machdep_ofw.c,v 1.12.20.1 2010/04/30 14:39:44 uebayasi Exp $ */
      2        1.2   garbled 
      3        1.2   garbled /*-
      4        1.2   garbled  * Copyright (c) 2007 The NetBSD Foundation, Inc.
      5        1.2   garbled  * All rights reserved.
      6        1.2   garbled  *
      7        1.2   garbled  * This code is derived from software contributed to The NetBSD Foundation
      8        1.2   garbled  * by Tim Rightnour
      9        1.2   garbled  *
     10        1.2   garbled  * Redistribution and use in source and binary forms, with or without
     11        1.2   garbled  * modification, are permitted provided that the following conditions
     12        1.2   garbled  * are met:
     13        1.2   garbled  * 1. Redistributions of source code must retain the above copyright
     14        1.2   garbled  *    notice, this list of conditions and the following disclaimer.
     15        1.2   garbled  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.2   garbled  *    notice, this list of conditions and the following disclaimer in the
     17        1.2   garbled  *    documentation and/or other materials provided with the distribution.
     18        1.2   garbled  *
     19        1.2   garbled  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.2   garbled  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.2   garbled  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.2   garbled  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.2   garbled  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.2   garbled  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.2   garbled  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.2   garbled  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.2   garbled  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.2   garbled  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.2   garbled  * POSSIBILITY OF SUCH DAMAGE.
     30        1.2   garbled  */
     31        1.2   garbled 
     32        1.2   garbled /*
     33        1.2   garbled  * Generic OFW routines for pci_machdep
     34        1.2   garbled  */
     35        1.2   garbled 
     36        1.2   garbled #include <sys/cdefs.h>
     37  1.12.20.1  uebayasi __KERNEL_RCSID(0, "$NetBSD: pci_machdep_ofw.c,v 1.12.20.1 2010/04/30 14:39:44 uebayasi Exp $");
     38        1.2   garbled 
     39        1.2   garbled #include <sys/types.h>
     40        1.2   garbled #include <sys/param.h>
     41        1.2   garbled #include <sys/time.h>
     42        1.2   garbled #include <sys/systm.h>
     43        1.2   garbled #include <sys/errno.h>
     44        1.2   garbled #include <sys/device.h>
     45        1.2   garbled #include <sys/malloc.h>
     46        1.2   garbled 
     47        1.2   garbled #include <uvm/uvm_extern.h>
     48        1.2   garbled 
     49        1.2   garbled #include <machine/bus.h>
     50        1.2   garbled 
     51        1.2   garbled #include <machine/autoconf.h>
     52        1.2   garbled #include <machine/pio.h>
     53        1.2   garbled #include <machine/intr.h>
     54        1.2   garbled 
     55        1.2   garbled #include <dev/pci/pcivar.h>
     56        1.2   garbled #include <dev/pci/pcireg.h>
     57        1.2   garbled #include <dev/pci/ppbreg.h>
     58        1.2   garbled #include <dev/pci/pcidevs.h>
     59        1.2   garbled #include <dev/pci/pciconf.h>
     60        1.2   garbled 
     61        1.2   garbled #include <dev/ofw/openfirm.h>
     62        1.2   garbled #include <dev/ofw/ofw_pci.h>
     63        1.2   garbled 
     64        1.2   garbled pcitag_t genppc_pci_indirect_make_tag(void *, int, int, int);
     65        1.2   garbled void genppc_pci_indirect_decompose_tag(void *, pcitag_t, int *, int *, int *);
     66        1.2   garbled 
     67        1.2   garbled ofw_pic_node_t picnodes[8];
     68        1.2   garbled int nrofpics = 0;
     69        1.2   garbled 
     70        1.2   garbled int
     71        1.2   garbled genofw_find_picnode(int node)
     72        1.2   garbled {
     73        1.2   garbled 	int i;
     74        1.2   garbled 
     75        1.2   garbled 	for (i = 0; i < 8; i++)
     76        1.2   garbled 		if (node == picnodes[i].node)
     77        1.2   garbled 			return i;
     78        1.2   garbled 	return -1;
     79        1.2   garbled }
     80        1.2   garbled 
     81        1.2   garbled void
     82        1.2   garbled genofw_find_ofpics(int startnode)
     83        1.2   garbled {
     84        1.8   garbled 	int node, iparent, child, iranges[6], irgot=0, i;
     85        1.8   garbled 	uint32_t reg[12];
     86        1.2   garbled 	char name[32];
     87        1.2   garbled 
     88        1.2   garbled 	for (node = startnode; node; node = OF_peer(node)) {
     89        1.2   garbled 		if ((child = OF_child(node)) != 0)
     90        1.2   garbled 			genofw_find_ofpics(child);
     91        1.2   garbled 		memset(name, 0, sizeof(name));
     92        1.2   garbled 		if (OF_getprop(node, "name", name, sizeof(name)) == -1)
     93        1.2   garbled 			continue;
     94        1.2   garbled 		if (strncmp(name, "interrupt-controller", 20) == 0)
     95        1.2   garbled 			goto foundic;
     96        1.3   garbled 
     97        1.2   garbled 		if (OF_getprop(node, "interrupt-controller", name,
     98        1.2   garbled 		    sizeof(name)) > -1)
     99        1.2   garbled 			goto foundic;
    100        1.3   garbled 
    101        1.3   garbled 		if (OF_getprop(node, "device_type", name, sizeof(name)) == -1)
    102        1.2   garbled 			continue;
    103        1.2   garbled 		if (strncmp(name, "interrupt-controller", 20) == 0)
    104        1.2   garbled 			goto foundic;
    105        1.3   garbled 
    106        1.3   garbled 		/* if we didn't find one, skip to the next */
    107        1.3   garbled 		continue;
    108        1.2   garbled foundic:
    109        1.2   garbled 		picnodes[nrofpics].node = node;
    110        1.2   garbled 		if (OF_getprop(node, "interrupt-parent", &iparent,
    111        1.2   garbled 		    sizeof(iparent)) == sizeof(iparent))
    112        1.2   garbled 			picnodes[nrofpics].parent = iparent;
    113        1.2   garbled 		if (OF_getprop(node, "#interrupt-cells", &iparent,
    114        1.2   garbled 		    sizeof(iparent)) == sizeof(iparent))
    115        1.2   garbled 			picnodes[nrofpics].cells = iparent;
    116        1.2   garbled 		else
    117        1.2   garbled 			picnodes[nrofpics].cells = 1;
    118        1.8   garbled 
    119        1.8   garbled 		picnodes[nrofpics].intrs = 0;
    120        1.8   garbled 		irgot = OF_getprop(node, "interrupt-ranges", iranges,
    121        1.8   garbled 		    sizeof(int)*6); /* XXX is this ok? */
    122        1.8   garbled 		if (irgot >= sizeof(int)) {
    123        1.8   garbled 			for (i=0; i < irgot/4; i++)
    124        1.8   garbled 				if (!picnodes[nrofpics].intrs)
    125        1.8   garbled 					picnodes[nrofpics].intrs = iranges[i];
    126        1.8   garbled 		}
    127        1.8   garbled 
    128        1.8   garbled 		irgot = OF_getprop(node, "reg", reg, sizeof(reg));
    129  1.12.20.1  uebayasi 
    130        1.8   garbled 		if (!picnodes[nrofpics].intrs)
    131        1.2   garbled 			picnodes[nrofpics].intrs = 16;
    132  1.12.20.1  uebayasi 
    133        1.2   garbled 		if (nrofpics > 0)
    134        1.2   garbled 			picnodes[nrofpics].offset = picnodes[nrofpics-1].offset
    135        1.2   garbled 			    + picnodes[nrofpics-1].intrs;
    136        1.2   garbled 		else
    137        1.2   garbled 			picnodes[nrofpics].offset = 0;
    138        1.3   garbled 		OF_getprop(node, "device_type", name, sizeof(name));
    139        1.2   garbled 		if (strcmp(name, "open-pic") == 0)
    140        1.2   garbled 			picnodes[nrofpics].type = PICNODE_TYPE_OPENPIC;
    141        1.2   garbled 		if (strcmp(name, "interrupt-controller") == 0) {
    142        1.2   garbled 			OF_getprop(node, "compatible", name, sizeof(name));
    143        1.8   garbled 			if (strcmp(name, "heathrow") == 0)
    144        1.2   garbled 				picnodes[nrofpics].type = PICNODE_TYPE_HEATHROW;
    145       1.10   garbled 			if (strcmp(name, "pnpPNP,0") == 0)
    146       1.10   garbled 				picnodes[nrofpics].type = PICNODE_TYPE_8259;
    147        1.8   garbled 			if (strcmp(name, "chrp,iic") == 0) {
    148        1.2   garbled 				picnodes[nrofpics].type = PICNODE_TYPE_8259;
    149        1.8   garbled 				if (irgot >= 9 * sizeof(uint32_t) &&
    150        1.8   garbled 				    reg[7] == 0x4d0)
    151        1.8   garbled 					picnodes[nrofpics].type =
    152        1.8   garbled 					    PICNODE_TYPE_IVR;
    153        1.8   garbled 			}
    154        1.2   garbled 		}
    155        1.3   garbled 		if (strlen(name) == 0) {
    156        1.3   garbled 			/* probably a Pegasos, assume 8259 */
    157        1.3   garbled 			picnodes[nrofpics].type = PICNODE_TYPE_8259;
    158        1.3   garbled 		}
    159        1.2   garbled 		nrofpics++;
    160        1.2   garbled 	}
    161        1.2   garbled }
    162        1.2   garbled 
    163        1.2   garbled /* Fix up the various picnode offsets */
    164        1.2   garbled void
    165        1.2   garbled genofw_fixup_picnode_offsets(void)
    166        1.2   garbled {
    167        1.2   garbled 	int i, curoff;
    168        1.2   garbled 
    169        1.2   garbled 	curoff=0;
    170        1.2   garbled 
    171        1.2   garbled 	for (i=0; i < nrofpics; i++) {
    172        1.8   garbled 		if (picnodes[i].type == PICNODE_TYPE_8259 ||
    173        1.8   garbled 		    picnodes[i].type == PICNODE_TYPE_IVR) {
    174        1.2   garbled 			picnodes[i].offset = 0;
    175        1.2   garbled 			curoff = picnodes[i].intrs;
    176        1.2   garbled 		}
    177        1.2   garbled 	}
    178        1.2   garbled 	for (i=0; i < nrofpics; i++) {
    179        1.2   garbled 		/* now skip the 8259 */
    180        1.2   garbled 		if (picnodes[i].type == PICNODE_TYPE_8259)
    181        1.2   garbled 			continue;
    182        1.8   garbled 		if (picnodes[i].type == PICNODE_TYPE_IVR)
    183        1.8   garbled 			continue;
    184  1.12.20.1  uebayasi 
    185        1.2   garbled 		picnodes[i].offset = curoff;
    186        1.2   garbled 		curoff += picnodes[i].intrs;
    187        1.2   garbled 	}
    188        1.2   garbled }
    189        1.2   garbled 
    190        1.2   garbled /* we are given a pci devnode, and dig from there */
    191        1.2   garbled void
    192        1.4   garbled genofw_setup_pciintr_map(void *v, struct genppc_pci_chipset_businfo *pbi,
    193        1.4   garbled     int pcinode)
    194        1.2   garbled {
    195        1.2   garbled 	int node;
    196        1.2   garbled 	u_int32_t map[160];
    197        1.2   garbled 	int parent, len;
    198        1.4   garbled 	int curdev, foundirqs=0;
    199        1.2   garbled 	int i, reclen, nrofpcidevs=0;
    200        1.2   garbled 	u_int32_t acells, icells, pcells;
    201        1.2   garbled 	prop_dictionary_t dict;
    202        1.2   garbled 	prop_dictionary_t sub=0;
    203        1.4   garbled 	pci_chipset_tag_t pc = (pci_chipset_tag_t)v;
    204        1.2   garbled 
    205        1.2   garbled 	len = OF_getprop(pcinode, "interrupt-map", map, sizeof(map));
    206        1.2   garbled 	if (len == -1)
    207        1.2   garbled 		goto nomap;
    208        1.2   garbled 
    209        1.2   garbled 	if (OF_getprop(pcinode, "#address-cells", &acells,
    210        1.2   garbled 	    sizeof(acells)) == -1)
    211        1.2   garbled 		acells = 1;
    212        1.2   garbled 	if (OF_getprop(pcinode, "#interrupt-cells", &icells,
    213        1.2   garbled 	    sizeof(icells)) == -1)
    214        1.2   garbled 		icells = 1;
    215        1.2   garbled 
    216        1.8   garbled 	parent = map[acells+icells];
    217        1.2   garbled 	if (OF_getprop(parent, "#interrupt-cells", &pcells,
    218        1.2   garbled 	    sizeof(pcells)) == -1)
    219        1.2   garbled 		pcells = 1;
    220        1.2   garbled 
    221        1.2   garbled 	reclen = acells+pcells+icells+1;
    222        1.2   garbled 	nrofpcidevs = len / (reclen * sizeof(int));
    223        1.2   garbled 
    224        1.2   garbled 	dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
    225        1.2   garbled 	KASSERT(dict != NULL);
    226        1.2   garbled 
    227        1.2   garbled 	curdev = -1;
    228        1.2   garbled 	prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
    229        1.2   garbled 	for (i = 0; i < nrofpcidevs; i++) {
    230        1.2   garbled 		prop_number_t intr_num;
    231        1.8   garbled 		int dev, pin, pic, func;
    232        1.2   garbled 		char key[20];
    233        1.2   garbled 
    234        1.2   garbled 		pic = genofw_find_picnode(map[i*reclen + acells + icells]);
    235        1.2   garbled 		KASSERT(pic != -1);
    236        1.2   garbled 		dev = (map[i*reclen] >> 8) / 0x8;
    237        1.8   garbled 		func = (map[i*reclen] >> 8) % 0x8;
    238        1.2   garbled 		if (curdev != dev)
    239        1.2   garbled 			sub = prop_dictionary_create_with_capacity(4);
    240        1.2   garbled 		pin = map[i*reclen + acells];
    241        1.2   garbled 		intr_num = prop_number_create_integer(map[i*reclen + acells + icells + 1] + picnodes[pic].offset);
    242        1.8   garbled 		sprintf(key, "pin-%c", 'A' + (pin-1));
    243        1.2   garbled 		prop_dictionary_set(sub, key, intr_num);
    244        1.2   garbled 		prop_object_release(intr_num);
    245        1.2   garbled 		/* should we care about level? */
    246        1.2   garbled 
    247        1.8   garbled 		sprintf(key, "devfunc-%d", dev*0x8 + func);
    248        1.2   garbled 		prop_dictionary_set(dict, key, sub);
    249        1.2   garbled 		if (curdev != dev) {
    250        1.2   garbled 			prop_object_release(sub);
    251        1.2   garbled 			curdev = dev;
    252        1.2   garbled 		}
    253        1.2   garbled 	}
    254        1.2   garbled 	/* the mapping is complete */
    255        1.2   garbled 	prop_object_release(dict);
    256        1.8   garbled 	aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
    257        1.2   garbled 	return;
    258        1.2   garbled 
    259        1.2   garbled nomap:
    260        1.2   garbled 	/* so, we have one of those annoying machines that doesn't provide
    261        1.2   garbled 	 * a nice simple map of interrupts.  We get to do this the hard
    262        1.2   garbled 	 * way instead.  Lucky us.
    263        1.2   garbled 	 */
    264        1.2   garbled 	for (node = OF_child(pcinode), nrofpcidevs=0; node;
    265        1.2   garbled 	    node = OF_peer(node))
    266        1.2   garbled 		nrofpcidevs++;
    267        1.2   garbled 	dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
    268        1.2   garbled 	KASSERT(dict != NULL);
    269        1.2   garbled 	prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
    270        1.2   garbled 
    271        1.2   garbled 	for (node = OF_child(pcinode); node; node = OF_peer(node)) {
    272        1.2   garbled 		uint32_t irqs[4], reg[5];
    273        1.2   garbled 		prop_number_t intr_num;
    274        1.8   garbled 		int dev, pin, func;
    275        1.2   garbled 		char key[20];
    276        1.2   garbled 
    277        1.2   garbled 		/* walk the bus looking for pci devices and map them */
    278        1.2   garbled 		if (OF_getprop(node, "AAPL,interrupts", irqs, 4) > 0) {
    279        1.2   garbled 			dev = 0;
    280        1.8   garbled 			if (OF_getprop(node, "reg", reg, 5) > 0) {
    281        1.2   garbled 				dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    282        1.8   garbled 				func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    283        1.8   garbled 			} else if (OF_getprop(node, "assigned-addresses",
    284        1.8   garbled 				       reg, 5) > 0) {
    285        1.2   garbled 				dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    286        1.8   garbled 				func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    287        1.8   garbled 			}
    288        1.2   garbled 			if (dev == 0) {
    289        1.2   garbled 				aprint_error("cannot figure out device num "
    290        1.2   garbled 				    "for node 0x%x\n", node);
    291        1.2   garbled 				continue;
    292        1.2   garbled 			}
    293        1.2   garbled 			sub = prop_dictionary_create_with_capacity(4);
    294        1.2   garbled 			if (OF_getprop(node, "interrupts", &pin, 4) < 0)
    295        1.2   garbled 				pin = 1;
    296        1.2   garbled 			intr_num = prop_number_create_integer(irqs[0]);
    297        1.8   garbled 			sprintf(key, "pin-%c", 'A' + (pin-1));
    298        1.2   garbled 			prop_dictionary_set(sub, key, intr_num);
    299        1.2   garbled 			prop_object_release(intr_num);
    300        1.8   garbled 			sprintf(key, "devfunc-%d", dev*0x8 + func);
    301        1.2   garbled 			prop_dictionary_set(dict, key, sub);
    302        1.2   garbled 			prop_object_release(sub);
    303        1.4   garbled 			foundirqs++;
    304        1.4   garbled 		}
    305        1.4   garbled 	}
    306        1.4   garbled 	if (foundirqs)
    307        1.4   garbled 		return;
    308        1.4   garbled 
    309        1.4   garbled 	/*
    310        1.4   garbled 	 * If we got this far, we have a super-annoying OFW.
    311        1.4   garbled 	 * They didn't bother to fill in any interrupt properties anywhere,
    312        1.4   garbled 	 * so we pray that they filled in the ones on the pci devices.
    313        1.4   garbled 	 */
    314        1.4   garbled 	for (node = OF_child(pcinode); node; node = OF_peer(node)) {
    315        1.4   garbled 		uint32_t reg[5], irq;
    316        1.4   garbled 		prop_number_t intr_num;
    317        1.4   garbled 		pcitag_t tag;
    318        1.4   garbled 		int dev, pin, func;
    319        1.4   garbled 		char key[20];
    320        1.4   garbled 
    321        1.4   garbled 		if (OF_getprop(node, "reg", reg, 5) > 0) {
    322        1.4   garbled 			dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    323        1.4   garbled 			func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    324        1.4   garbled 
    325        1.4   garbled 			tag = pci_make_tag(pc, pc->pc_bus, dev, func);
    326        1.4   garbled 			irq = PCI_INTERRUPT_LINE(pci_conf_read(pc, tag,
    327        1.4   garbled 			    PCI_INTERRUPT_REG));
    328        1.4   garbled 			if (irq == 255)
    329        1.4   garbled 				irq = 0;
    330        1.4   garbled 
    331        1.4   garbled 			sub = prop_dictionary_create_with_capacity(4);
    332        1.4   garbled 			if (OF_getprop(node, "interrupts", &pin, 4) < 0)
    333        1.4   garbled 				pin = 1;
    334        1.4   garbled 			intr_num = prop_number_create_integer(irq);
    335        1.5   garbled 			sprintf(key, "pin-%c", 'A' + (pin-1));
    336        1.4   garbled 			prop_dictionary_set(sub, key, intr_num);
    337        1.4   garbled 			prop_object_release(intr_num);
    338        1.4   garbled 			sprintf(key, "devfunc-%d", dev*0x8 + func);
    339        1.4   garbled 			prop_dictionary_set(dict, key, sub);
    340        1.4   garbled 			prop_object_release(sub);
    341        1.2   garbled 		}
    342        1.2   garbled 	}
    343        1.6   garbled 	aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
    344        1.2   garbled }
    345        1.2   garbled 
    346        1.2   garbled int
    347        1.2   garbled genofw_find_node_by_devfunc(int startnode, int bus, int dev, int func)
    348        1.2   garbled {
    349        1.2   garbled 	int node, sz, p=0;
    350        1.2   garbled 	uint32_t reg;
    351  1.12.20.1  uebayasi 
    352        1.2   garbled 	for (node = startnode; node; node = p) {
    353        1.2   garbled 		sz = OF_getprop(node, "reg", &reg, sizeof(reg));
    354        1.2   garbled 		if (sz != sizeof(reg))
    355        1.2   garbled 			continue;
    356        1.2   garbled 		if (OFW_PCI_PHYS_HI_BUS(reg) == bus &&
    357        1.2   garbled 		    OFW_PCI_PHYS_HI_DEVICE(reg) == dev &&
    358        1.2   garbled 		    OFW_PCI_PHYS_HI_FUNCTION(reg) == func)
    359        1.2   garbled 			return node;
    360        1.2   garbled 		if ((p = OF_child(node)))
    361        1.2   garbled 			continue;
    362        1.2   garbled 		while (node) {
    363        1.2   garbled 			if ((p = OF_peer(node)))
    364        1.2   garbled 				break;
    365        1.2   garbled 			node = OF_parent(node);
    366        1.2   garbled 		}
    367        1.2   garbled 	}
    368        1.2   garbled 	/* couldn't find it */
    369        1.2   garbled 	return -1;
    370        1.2   garbled }
    371        1.2   garbled 
    372        1.2   garbled int
    373        1.2   garbled genofw_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
    374        1.2   garbled {
    375        1.2   garbled 	struct genppc_pci_chipset_businfo *pbi;
    376        1.2   garbled 	prop_dictionary_t dict, devsub;
    377        1.2   garbled 	prop_object_t pinsub;
    378        1.2   garbled 	prop_number_t pbus;
    379        1.4   garbled 	int busno, bus, pin, line, swiz, dev, origdev, func, i;
    380        1.2   garbled 	char key[20];
    381        1.2   garbled 
    382        1.2   garbled 	pin = pa->pa_intrpin;
    383        1.2   garbled 	line = pa->pa_intrline;
    384        1.2   garbled 	bus = busno = pa->pa_bus;
    385        1.2   garbled 	swiz = pa->pa_intrswiz;
    386        1.2   garbled 	origdev = dev = pa->pa_device;
    387        1.4   garbled 	func = pa->pa_function;
    388        1.2   garbled 	i = 0;
    389        1.2   garbled 
    390        1.2   garbled 	pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
    391        1.2   garbled 	while (busno--)
    392        1.2   garbled 		pbi = SIMPLEQ_NEXT(pbi, next);
    393        1.2   garbled 	KASSERT(pbi != NULL);
    394        1.2   garbled 
    395        1.2   garbled 	dict = prop_dictionary_get(pbi->pbi_properties, "ofw-pci-intrmap");
    396        1.2   garbled 
    397        1.2   garbled 	if (dict != NULL)
    398        1.2   garbled 		i = prop_dictionary_count(dict);
    399        1.2   garbled 
    400        1.2   garbled 	if (dict == NULL || i == 0) {
    401        1.2   garbled 		/* We have an unmapped bus, now it gets hard */
    402        1.2   garbled 		pbus = prop_dictionary_get(pbi->pbi_properties,
    403        1.2   garbled 		    "ofw-pcibus-parent");
    404        1.2   garbled 		if (pbus == NULL)
    405        1.2   garbled 			goto bad;
    406        1.2   garbled 		busno = prop_number_integer_value(pbus);
    407        1.2   garbled 		pbus = prop_dictionary_get(pbi->pbi_properties,
    408        1.2   garbled 		    "ofw-pcibus-rawdevnum");
    409        1.2   garbled 		dev = prop_number_integer_value(pbus);
    410        1.2   garbled 
    411        1.2   garbled 		/* now that we know the parent bus, we need to find it's pbi */
    412        1.2   garbled 		pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
    413        1.2   garbled 		while (busno--)
    414        1.2   garbled 			pbi = SIMPLEQ_NEXT(pbi, next);
    415        1.2   garbled 		KASSERT(pbi != NULL);
    416        1.2   garbled 
    417        1.2   garbled 		/* swizzle the pin */
    418        1.2   garbled 		pin = ((pin + origdev - 1) & 3) + 1;
    419        1.2   garbled 
    420        1.2   garbled 		/* now we have the pbi, ask for dict again */
    421        1.2   garbled 		dict = prop_dictionary_get(pbi->pbi_properties,
    422        1.2   garbled 		    "ofw-pci-intrmap");
    423        1.2   garbled 		if (dict == NULL)
    424        1.2   garbled 			goto bad;
    425        1.2   garbled 	}
    426        1.2   garbled 
    427        1.2   garbled 	/* No IRQ used. */
    428        1.2   garbled 	if (pin == 0)
    429        1.2   garbled 		goto bad;
    430        1.2   garbled 	if (pin > 4) {
    431        1.2   garbled 		aprint_error("pci_intr_map: bad interrupt pin %d\n", pin);
    432        1.2   garbled 		goto bad;
    433        1.2   garbled 	}
    434        1.2   garbled 
    435        1.4   garbled 	sprintf(key, "devfunc-%d", dev*0x8 + func);
    436        1.2   garbled 	devsub = prop_dictionary_get(dict, key);
    437        1.2   garbled 	if (devsub == NULL)
    438        1.2   garbled 		goto bad;
    439        1.2   garbled 	sprintf(key, "pin-%c", 'A' + (pin-1));
    440        1.2   garbled 	pinsub = prop_dictionary_get(devsub, key);
    441        1.2   garbled 	if (pinsub == NULL)
    442        1.2   garbled 		goto bad;
    443        1.2   garbled 	line = prop_number_integer_value(pinsub);
    444        1.2   garbled 
    445        1.2   garbled 	if (line == 0 || line == 255) {
    446        1.2   garbled 		aprint_error("pci_intr_map: no mapping for pin %c\n",'@' + pin);
    447        1.2   garbled 		goto bad;
    448        1.2   garbled 	}
    449        1.2   garbled 
    450        1.2   garbled 	*ihp = line;
    451        1.2   garbled 	return 0;
    452        1.2   garbled 
    453        1.2   garbled bad:
    454        1.2   garbled 	*ihp = -1;
    455        1.2   garbled 	return 1;
    456        1.2   garbled }
    457        1.2   garbled 
    458        1.2   garbled int
    459        1.2   garbled genofw_pci_conf_hook(pci_chipset_tag_t pct, int bus, int dev, int func,
    460        1.2   garbled 	pcireg_t id)
    461        1.2   garbled {
    462        1.2   garbled 	struct genppc_pci_chipset_businfo *pbi;
    463        1.2   garbled 	prop_number_t pbus;
    464        1.2   garbled 	pcitag_t tag;
    465        1.2   garbled 	pcireg_t class;
    466        1.2   garbled 	int node;
    467        1.2   garbled 
    468        1.2   garbled 	/* We have already mapped MPIC's if we have them, so leave them alone */
    469        1.2   garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
    470        1.2   garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC2)
    471        1.2   garbled 		return 0;
    472        1.2   garbled 
    473        1.2   garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
    474        1.2   garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC)
    475        1.2   garbled 		return 0;
    476        1.2   garbled 
    477        1.2   garbled 	/* I highly doubt there are any CHRP ravens, but just in case */
    478        1.2   garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_MOT &&
    479        1.2   garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_MOT_RAVEN)
    480        1.2   garbled 		return (PCI_CONF_ALL & ~PCI_CONF_MAP_MEM);
    481        1.2   garbled 
    482        1.7       mrg 	/*
    483        1.7       mrg 	 * Pegasos2 specific stuff.
    484        1.7       mrg 	 */
    485        1.7       mrg 	if (strncmp(model_name, "Pegasos2", 8) == 0) {
    486        1.7       mrg 
    487       1.11       phx 		/* never reconfigure the MV64361 host bridge */
    488       1.11       phx 		if (PCI_VENDOR(id) == PCI_VENDOR_MARVELL &&
    489       1.11       phx 		    PCI_PRODUCT(id) == PCI_PRODUCT_MARVELL_GT64360)
    490       1.11       phx 			return 0;
    491       1.11       phx 
    492        1.7       mrg 		/* we want to leave viaide(4) alone */
    493        1.7       mrg 		if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
    494        1.7       mrg 		    PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C586A_IDE)
    495        1.7       mrg 			return 0;
    496        1.7       mrg 
    497        1.9   garbled 		/* leave the audio IO alone */
    498        1.7       mrg 		if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
    499        1.9   garbled 		    PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C686A_AC97)
    500        1.9   garbled 			return (PCI_CONF_ALL & ~PCI_CONF_MAP_IO);
    501        1.9   garbled 
    502        1.7       mrg 	}
    503  1.12.20.1  uebayasi 
    504        1.9   garbled 	tag = pci_make_tag(pct, bus, dev, func);
    505        1.9   garbled 	class = pci_conf_read(pct, tag, PCI_CLASS_REG);
    506        1.7       mrg 
    507        1.9   garbled 	/* leave video cards alone */
    508        1.9   garbled 	if (PCI_CLASS(class) == PCI_CLASS_DISPLAY)
    509        1.9   garbled 		return 0;
    510  1.12.20.1  uebayasi 
    511        1.2   garbled 	/* NOTE, all device specific stuff must be above this line */
    512        1.2   garbled 	/* don't do this on the primary host bridge */
    513        1.2   garbled 	if (bus == 0 && dev == 0 && func == 0)
    514        1.2   garbled 		return PCI_CONF_DEFAULT;
    515        1.2   garbled 
    516        1.2   garbled 	/*
    517        1.2   garbled 	 * PCI bridges have special needs.  We need to discover where they
    518        1.2   garbled 	 * came from, and wire them appropriately.
    519        1.2   garbled 	 */
    520        1.2   garbled 	if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
    521        1.2   garbled 	    PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_PCI) {
    522        1.2   garbled 		pbi = malloc(sizeof(struct genppc_pci_chipset_businfo),
    523        1.2   garbled 		    M_DEVBUF, M_NOWAIT);
    524        1.2   garbled 		KASSERT(pbi != NULL);
    525        1.2   garbled 		pbi->pbi_properties = prop_dictionary_create();
    526        1.2   garbled 		KASSERT(pbi->pbi_properties != NULL);
    527        1.2   garbled 		node = genofw_find_node_by_devfunc(pct->pc_node, bus, dev,
    528        1.2   garbled 		    func);
    529        1.2   garbled 		if (node == -1) {
    530        1.2   garbled 			aprint_error("Cannot find node for device "
    531        1.2   garbled 			    "bus %d dev %d func %d\n", bus, dev, func);
    532        1.2   garbled 			prop_object_release(pbi->pbi_properties);
    533        1.2   garbled 			free(pbi, M_DEVBUF);
    534        1.2   garbled 			return (PCI_CONF_DEFAULT);
    535        1.2   garbled 		}
    536        1.4   garbled 		genofw_setup_pciintr_map((void *)pct, pbi, node);
    537        1.2   garbled 
    538        1.2   garbled 		/* record the parent bus, and the parent device number */
    539        1.2   garbled 		pbus = prop_number_create_integer(bus);
    540        1.2   garbled 		prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-parent",
    541        1.2   garbled 		    pbus);
    542        1.2   garbled 		prop_object_release(pbus);
    543        1.2   garbled 		pbus = prop_number_create_integer(dev);
    544        1.2   garbled 		prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-rawdevnum",
    545        1.2   garbled 		    pbus);
    546        1.2   garbled 		prop_object_release(pbus);
    547        1.2   garbled 
    548        1.2   garbled 		SIMPLEQ_INSERT_TAIL(&pct->pc_pbi, pbi, next);
    549        1.2   garbled 	}
    550        1.2   garbled 
    551        1.2   garbled 	return (PCI_CONF_DEFAULT);
    552        1.2   garbled }
    553