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