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