Home | History | Annotate | Line # | Download | only in pci
pci_machdep_ofw.c revision 1.11
      1  1.11      phx /* $NetBSD: pci_machdep_ofw.c,v 1.11 2008/02/23 21:11:22 phx 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.11      phx __KERNEL_RCSID(0, "$NetBSD: pci_machdep_ofw.c,v 1.11 2008/02/23 21:11:22 phx 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.8  garbled 	int node, iparent, child, iranges[6], irgot=0, i;
     92   1.8  garbled 	uint32_t reg[12];
     93   1.2  garbled 	char name[32];
     94   1.2  garbled 
     95   1.2  garbled 	for (node = startnode; node; node = OF_peer(node)) {
     96   1.2  garbled 		if ((child = OF_child(node)) != 0)
     97   1.2  garbled 			genofw_find_ofpics(child);
     98   1.2  garbled 		memset(name, 0, sizeof(name));
     99   1.2  garbled 		if (OF_getprop(node, "name", name, sizeof(name)) == -1)
    100   1.2  garbled 			continue;
    101   1.2  garbled 		if (strncmp(name, "interrupt-controller", 20) == 0)
    102   1.2  garbled 			goto foundic;
    103   1.3  garbled 
    104   1.2  garbled 		if (OF_getprop(node, "interrupt-controller", name,
    105   1.2  garbled 		    sizeof(name)) > -1)
    106   1.2  garbled 			goto foundic;
    107   1.3  garbled 
    108   1.3  garbled 		if (OF_getprop(node, "device_type", name, sizeof(name)) == -1)
    109   1.2  garbled 			continue;
    110   1.2  garbled 		if (strncmp(name, "interrupt-controller", 20) == 0)
    111   1.2  garbled 			goto foundic;
    112   1.3  garbled 
    113   1.3  garbled 		/* if we didn't find one, skip to the next */
    114   1.3  garbled 		continue;
    115   1.2  garbled foundic:
    116   1.2  garbled 		picnodes[nrofpics].node = node;
    117   1.2  garbled 		if (OF_getprop(node, "interrupt-parent", &iparent,
    118   1.2  garbled 		    sizeof(iparent)) == sizeof(iparent))
    119   1.2  garbled 			picnodes[nrofpics].parent = iparent;
    120   1.2  garbled 		if (OF_getprop(node, "#interrupt-cells", &iparent,
    121   1.2  garbled 		    sizeof(iparent)) == sizeof(iparent))
    122   1.2  garbled 			picnodes[nrofpics].cells = iparent;
    123   1.2  garbled 		else
    124   1.2  garbled 			picnodes[nrofpics].cells = 1;
    125   1.8  garbled 
    126   1.8  garbled 		picnodes[nrofpics].intrs = 0;
    127   1.8  garbled 		irgot = OF_getprop(node, "interrupt-ranges", iranges,
    128   1.8  garbled 		    sizeof(int)*6); /* XXX is this ok? */
    129   1.8  garbled 		if (irgot >= sizeof(int)) {
    130   1.8  garbled 			for (i=0; i < irgot/4; i++)
    131   1.8  garbled 				if (!picnodes[nrofpics].intrs)
    132   1.8  garbled 					picnodes[nrofpics].intrs = iranges[i];
    133   1.8  garbled 		}
    134   1.8  garbled 
    135   1.8  garbled 		irgot = OF_getprop(node, "reg", reg, sizeof(reg));
    136   1.8  garbled 
    137   1.8  garbled 		if (!picnodes[nrofpics].intrs)
    138   1.2  garbled 			picnodes[nrofpics].intrs = 16;
    139   1.8  garbled 
    140   1.2  garbled 		if (nrofpics > 0)
    141   1.2  garbled 			picnodes[nrofpics].offset = picnodes[nrofpics-1].offset
    142   1.2  garbled 			    + picnodes[nrofpics-1].intrs;
    143   1.2  garbled 		else
    144   1.2  garbled 			picnodes[nrofpics].offset = 0;
    145   1.3  garbled 		OF_getprop(node, "device_type", name, sizeof(name));
    146   1.2  garbled 		if (strcmp(name, "open-pic") == 0)
    147   1.2  garbled 			picnodes[nrofpics].type = PICNODE_TYPE_OPENPIC;
    148   1.2  garbled 		if (strcmp(name, "interrupt-controller") == 0) {
    149   1.2  garbled 			OF_getprop(node, "compatible", name, sizeof(name));
    150   1.8  garbled 			if (strcmp(name, "heathrow") == 0)
    151   1.2  garbled 				picnodes[nrofpics].type = PICNODE_TYPE_HEATHROW;
    152  1.10  garbled 			if (strcmp(name, "pnpPNP,0") == 0)
    153  1.10  garbled 				picnodes[nrofpics].type = PICNODE_TYPE_8259;
    154   1.8  garbled 			if (strcmp(name, "chrp,iic") == 0) {
    155   1.2  garbled 				picnodes[nrofpics].type = PICNODE_TYPE_8259;
    156   1.8  garbled 				if (irgot >= 9 * sizeof(uint32_t) &&
    157   1.8  garbled 				    reg[7] == 0x4d0)
    158   1.8  garbled 					picnodes[nrofpics].type =
    159   1.8  garbled 					    PICNODE_TYPE_IVR;
    160   1.8  garbled 			}
    161   1.2  garbled 		}
    162   1.3  garbled 		if (strlen(name) == 0) {
    163   1.3  garbled 			/* probably a Pegasos, assume 8259 */
    164   1.3  garbled 			picnodes[nrofpics].type = PICNODE_TYPE_8259;
    165   1.3  garbled 		}
    166   1.2  garbled 		nrofpics++;
    167   1.2  garbled 	}
    168   1.2  garbled }
    169   1.2  garbled 
    170   1.2  garbled /* Fix up the various picnode offsets */
    171   1.2  garbled void
    172   1.2  garbled genofw_fixup_picnode_offsets(void)
    173   1.2  garbled {
    174   1.2  garbled 	int i, curoff;
    175   1.2  garbled 
    176   1.2  garbled 	curoff=0;
    177   1.2  garbled 
    178   1.2  garbled 	for (i=0; i < nrofpics; i++) {
    179   1.8  garbled 		if (picnodes[i].type == PICNODE_TYPE_8259 ||
    180   1.8  garbled 		    picnodes[i].type == PICNODE_TYPE_IVR) {
    181   1.2  garbled 			picnodes[i].offset = 0;
    182   1.2  garbled 			curoff = picnodes[i].intrs;
    183   1.2  garbled 		}
    184   1.2  garbled 	}
    185   1.2  garbled 	for (i=0; i < nrofpics; i++) {
    186   1.2  garbled 		/* now skip the 8259 */
    187   1.2  garbled 		if (picnodes[i].type == PICNODE_TYPE_8259)
    188   1.2  garbled 			continue;
    189   1.8  garbled 		if (picnodes[i].type == PICNODE_TYPE_IVR)
    190   1.8  garbled 			continue;
    191   1.8  garbled 
    192   1.2  garbled 		picnodes[i].offset = curoff;
    193   1.2  garbled 		curoff += picnodes[i].intrs;
    194   1.2  garbled 	}
    195   1.2  garbled }
    196   1.2  garbled 
    197   1.2  garbled /* we are given a pci devnode, and dig from there */
    198   1.2  garbled void
    199   1.4  garbled genofw_setup_pciintr_map(void *v, struct genppc_pci_chipset_businfo *pbi,
    200   1.4  garbled     int pcinode)
    201   1.2  garbled {
    202   1.2  garbled 	int node;
    203   1.2  garbled 	u_int32_t map[160];
    204   1.2  garbled 	int parent, len;
    205   1.4  garbled 	int curdev, foundirqs=0;
    206   1.2  garbled 	int i, reclen, nrofpcidevs=0;
    207   1.2  garbled 	u_int32_t acells, icells, pcells;
    208   1.2  garbled 	prop_dictionary_t dict;
    209   1.2  garbled 	prop_dictionary_t sub=0;
    210   1.4  garbled 	pci_chipset_tag_t pc = (pci_chipset_tag_t)v;
    211   1.2  garbled 
    212   1.2  garbled 	len = OF_getprop(pcinode, "interrupt-map", map, sizeof(map));
    213   1.2  garbled 	if (len == -1)
    214   1.2  garbled 		goto nomap;
    215   1.2  garbled 
    216   1.2  garbled 	if (OF_getprop(pcinode, "#address-cells", &acells,
    217   1.2  garbled 	    sizeof(acells)) == -1)
    218   1.2  garbled 		acells = 1;
    219   1.2  garbled 	if (OF_getprop(pcinode, "#interrupt-cells", &icells,
    220   1.2  garbled 	    sizeof(icells)) == -1)
    221   1.2  garbled 		icells = 1;
    222   1.2  garbled 
    223   1.8  garbled 	parent = map[acells+icells];
    224   1.2  garbled 	if (OF_getprop(parent, "#interrupt-cells", &pcells,
    225   1.2  garbled 	    sizeof(pcells)) == -1)
    226   1.2  garbled 		pcells = 1;
    227   1.2  garbled 
    228   1.2  garbled 	reclen = acells+pcells+icells+1;
    229   1.2  garbled 	nrofpcidevs = len / (reclen * sizeof(int));
    230   1.2  garbled 
    231   1.2  garbled 	dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
    232   1.2  garbled 	KASSERT(dict != NULL);
    233   1.2  garbled 
    234   1.2  garbled 	curdev = -1;
    235   1.2  garbled 	prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
    236   1.2  garbled 	for (i = 0; i < nrofpcidevs; i++) {
    237   1.2  garbled 		prop_number_t intr_num;
    238   1.8  garbled 		int dev, pin, pic, func;
    239   1.2  garbled 		char key[20];
    240   1.2  garbled 
    241   1.2  garbled 		pic = genofw_find_picnode(map[i*reclen + acells + icells]);
    242   1.2  garbled 		KASSERT(pic != -1);
    243   1.2  garbled 		dev = (map[i*reclen] >> 8) / 0x8;
    244   1.8  garbled 		func = (map[i*reclen] >> 8) % 0x8;
    245   1.2  garbled 		if (curdev != dev)
    246   1.2  garbled 			sub = prop_dictionary_create_with_capacity(4);
    247   1.2  garbled 		pin = map[i*reclen + acells];
    248   1.2  garbled 		intr_num = prop_number_create_integer(map[i*reclen + acells + icells + 1] + picnodes[pic].offset);
    249   1.8  garbled 		sprintf(key, "pin-%c", 'A' + (pin-1));
    250   1.2  garbled 		prop_dictionary_set(sub, key, intr_num);
    251   1.2  garbled 		prop_object_release(intr_num);
    252   1.2  garbled 		/* should we care about level? */
    253   1.2  garbled 
    254   1.8  garbled 		sprintf(key, "devfunc-%d", dev*0x8 + func);
    255   1.2  garbled 		prop_dictionary_set(dict, key, sub);
    256   1.2  garbled 		if (curdev != dev) {
    257   1.2  garbled 			prop_object_release(sub);
    258   1.2  garbled 			curdev = dev;
    259   1.2  garbled 		}
    260   1.2  garbled 	}
    261   1.2  garbled 	/* the mapping is complete */
    262   1.2  garbled 	prop_object_release(dict);
    263   1.8  garbled 	aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
    264   1.2  garbled 	return;
    265   1.2  garbled 
    266   1.2  garbled nomap:
    267   1.2  garbled 	/* so, we have one of those annoying machines that doesn't provide
    268   1.2  garbled 	 * a nice simple map of interrupts.  We get to do this the hard
    269   1.2  garbled 	 * way instead.  Lucky us.
    270   1.2  garbled 	 */
    271   1.2  garbled 	for (node = OF_child(pcinode), nrofpcidevs=0; node;
    272   1.2  garbled 	    node = OF_peer(node))
    273   1.2  garbled 		nrofpcidevs++;
    274   1.2  garbled 	dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
    275   1.2  garbled 	KASSERT(dict != NULL);
    276   1.2  garbled 	prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
    277   1.2  garbled 
    278   1.2  garbled 	for (node = OF_child(pcinode); node; node = OF_peer(node)) {
    279   1.2  garbled 		uint32_t irqs[4], reg[5];
    280   1.2  garbled 		prop_number_t intr_num;
    281   1.8  garbled 		int dev, pin, func;
    282   1.2  garbled 		char key[20];
    283   1.2  garbled 
    284   1.2  garbled 		/* walk the bus looking for pci devices and map them */
    285   1.2  garbled 		if (OF_getprop(node, "AAPL,interrupts", irqs, 4) > 0) {
    286   1.2  garbled 			dev = 0;
    287   1.8  garbled 			if (OF_getprop(node, "reg", reg, 5) > 0) {
    288   1.2  garbled 				dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    289   1.8  garbled 				func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    290   1.8  garbled 			} else if (OF_getprop(node, "assigned-addresses",
    291   1.8  garbled 				       reg, 5) > 0) {
    292   1.2  garbled 				dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    293   1.8  garbled 				func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    294   1.8  garbled 			}
    295   1.2  garbled 			if (dev == 0) {
    296   1.2  garbled 				aprint_error("cannot figure out device num "
    297   1.2  garbled 				    "for node 0x%x\n", node);
    298   1.2  garbled 				continue;
    299   1.2  garbled 			}
    300   1.2  garbled 			sub = prop_dictionary_create_with_capacity(4);
    301   1.2  garbled 			if (OF_getprop(node, "interrupts", &pin, 4) < 0)
    302   1.2  garbled 				pin = 1;
    303   1.2  garbled 			intr_num = prop_number_create_integer(irqs[0]);
    304   1.8  garbled 			sprintf(key, "pin-%c", 'A' + (pin-1));
    305   1.2  garbled 			prop_dictionary_set(sub, key, intr_num);
    306   1.2  garbled 			prop_object_release(intr_num);
    307   1.8  garbled 			sprintf(key, "devfunc-%d", dev*0x8 + func);
    308   1.2  garbled 			prop_dictionary_set(dict, key, sub);
    309   1.2  garbled 			prop_object_release(sub);
    310   1.4  garbled 			foundirqs++;
    311   1.4  garbled 		}
    312   1.4  garbled 	}
    313   1.4  garbled 	if (foundirqs)
    314   1.4  garbled 		return;
    315   1.4  garbled 
    316   1.4  garbled 	/*
    317   1.4  garbled 	 * If we got this far, we have a super-annoying OFW.
    318   1.4  garbled 	 * They didn't bother to fill in any interrupt properties anywhere,
    319   1.4  garbled 	 * so we pray that they filled in the ones on the pci devices.
    320   1.4  garbled 	 */
    321   1.4  garbled 	for (node = OF_child(pcinode); node; node = OF_peer(node)) {
    322   1.4  garbled 		uint32_t reg[5], irq;
    323   1.4  garbled 		prop_number_t intr_num;
    324   1.4  garbled 		pcitag_t tag;
    325   1.4  garbled 		int dev, pin, func;
    326   1.4  garbled 		char key[20];
    327   1.4  garbled 
    328   1.4  garbled 		if (OF_getprop(node, "reg", reg, 5) > 0) {
    329   1.4  garbled 			dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
    330   1.4  garbled 			func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
    331   1.4  garbled 
    332   1.4  garbled 			tag = pci_make_tag(pc, pc->pc_bus, dev, func);
    333   1.4  garbled 			irq = PCI_INTERRUPT_LINE(pci_conf_read(pc, tag,
    334   1.4  garbled 			    PCI_INTERRUPT_REG));
    335   1.4  garbled 			if (irq == 255)
    336   1.4  garbled 				irq = 0;
    337   1.4  garbled 
    338   1.4  garbled 			sub = prop_dictionary_create_with_capacity(4);
    339   1.4  garbled 			if (OF_getprop(node, "interrupts", &pin, 4) < 0)
    340   1.4  garbled 				pin = 1;
    341   1.4  garbled 			intr_num = prop_number_create_integer(irq);
    342   1.5  garbled 			sprintf(key, "pin-%c", 'A' + (pin-1));
    343   1.4  garbled 			prop_dictionary_set(sub, key, intr_num);
    344   1.4  garbled 			prop_object_release(intr_num);
    345   1.4  garbled 			sprintf(key, "devfunc-%d", dev*0x8 + func);
    346   1.4  garbled 			prop_dictionary_set(dict, key, sub);
    347   1.4  garbled 			prop_object_release(sub);
    348   1.2  garbled 		}
    349   1.2  garbled 	}
    350   1.6  garbled 	aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
    351   1.2  garbled }
    352   1.2  garbled 
    353   1.2  garbled int
    354   1.2  garbled genofw_find_node_by_devfunc(int startnode, int bus, int dev, int func)
    355   1.2  garbled {
    356   1.2  garbled 	int node, sz, p=0;
    357   1.2  garbled 	uint32_t reg;
    358   1.2  garbled 
    359   1.2  garbled 	for (node = startnode; node; node = p) {
    360   1.2  garbled 		sz = OF_getprop(node, "reg", &reg, sizeof(reg));
    361   1.2  garbled 		if (sz != sizeof(reg))
    362   1.2  garbled 			continue;
    363   1.2  garbled 		if (OFW_PCI_PHYS_HI_BUS(reg) == bus &&
    364   1.2  garbled 		    OFW_PCI_PHYS_HI_DEVICE(reg) == dev &&
    365   1.2  garbled 		    OFW_PCI_PHYS_HI_FUNCTION(reg) == func)
    366   1.2  garbled 			return node;
    367   1.2  garbled 		if ((p = OF_child(node)))
    368   1.2  garbled 			continue;
    369   1.2  garbled 		while (node) {
    370   1.2  garbled 			if ((p = OF_peer(node)))
    371   1.2  garbled 				break;
    372   1.2  garbled 			node = OF_parent(node);
    373   1.2  garbled 		}
    374   1.2  garbled 	}
    375   1.2  garbled 	/* couldn't find it */
    376   1.2  garbled 	return -1;
    377   1.2  garbled }
    378   1.2  garbled 
    379   1.2  garbled int
    380   1.2  garbled genofw_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
    381   1.2  garbled {
    382   1.2  garbled 	struct genppc_pci_chipset_businfo *pbi;
    383   1.2  garbled 	prop_dictionary_t dict, devsub;
    384   1.2  garbled 	prop_object_t pinsub;
    385   1.2  garbled 	prop_number_t pbus;
    386   1.4  garbled 	int busno, bus, pin, line, swiz, dev, origdev, func, i;
    387   1.2  garbled 	char key[20];
    388   1.2  garbled 
    389   1.2  garbled 	pin = pa->pa_intrpin;
    390   1.2  garbled 	line = pa->pa_intrline;
    391   1.2  garbled 	bus = busno = pa->pa_bus;
    392   1.2  garbled 	swiz = pa->pa_intrswiz;
    393   1.2  garbled 	origdev = dev = pa->pa_device;
    394   1.4  garbled 	func = pa->pa_function;
    395   1.2  garbled 	i = 0;
    396   1.2  garbled 
    397   1.2  garbled 	pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
    398   1.2  garbled 	while (busno--)
    399   1.2  garbled 		pbi = SIMPLEQ_NEXT(pbi, next);
    400   1.2  garbled 	KASSERT(pbi != NULL);
    401   1.2  garbled 
    402   1.2  garbled 	dict = prop_dictionary_get(pbi->pbi_properties, "ofw-pci-intrmap");
    403   1.2  garbled 
    404   1.2  garbled 	if (dict != NULL)
    405   1.2  garbled 		i = prop_dictionary_count(dict);
    406   1.2  garbled 
    407   1.2  garbled 	if (dict == NULL || i == 0) {
    408   1.2  garbled 		/* We have an unmapped bus, now it gets hard */
    409   1.2  garbled 		pbus = prop_dictionary_get(pbi->pbi_properties,
    410   1.2  garbled 		    "ofw-pcibus-parent");
    411   1.2  garbled 		if (pbus == NULL)
    412   1.2  garbled 			goto bad;
    413   1.2  garbled 		busno = prop_number_integer_value(pbus);
    414   1.2  garbled 		pbus = prop_dictionary_get(pbi->pbi_properties,
    415   1.2  garbled 		    "ofw-pcibus-rawdevnum");
    416   1.2  garbled 		dev = prop_number_integer_value(pbus);
    417   1.2  garbled 
    418   1.2  garbled 		/* now that we know the parent bus, we need to find it's pbi */
    419   1.2  garbled 		pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
    420   1.2  garbled 		while (busno--)
    421   1.2  garbled 			pbi = SIMPLEQ_NEXT(pbi, next);
    422   1.2  garbled 		KASSERT(pbi != NULL);
    423   1.2  garbled 
    424   1.2  garbled 		/* swizzle the pin */
    425   1.2  garbled 		pin = ((pin + origdev - 1) & 3) + 1;
    426   1.2  garbled 
    427   1.2  garbled 		/* now we have the pbi, ask for dict again */
    428   1.2  garbled 		dict = prop_dictionary_get(pbi->pbi_properties,
    429   1.2  garbled 		    "ofw-pci-intrmap");
    430   1.2  garbled 		if (dict == NULL)
    431   1.2  garbled 			goto bad;
    432   1.2  garbled 	}
    433   1.2  garbled 
    434   1.2  garbled 	/* No IRQ used. */
    435   1.2  garbled 	if (pin == 0)
    436   1.2  garbled 		goto bad;
    437   1.2  garbled 	if (pin > 4) {
    438   1.2  garbled 		aprint_error("pci_intr_map: bad interrupt pin %d\n", pin);
    439   1.2  garbled 		goto bad;
    440   1.2  garbled 	}
    441   1.2  garbled 
    442   1.4  garbled 	sprintf(key, "devfunc-%d", dev*0x8 + func);
    443   1.2  garbled 	devsub = prop_dictionary_get(dict, key);
    444   1.2  garbled 	if (devsub == NULL)
    445   1.2  garbled 		goto bad;
    446   1.2  garbled 	sprintf(key, "pin-%c", 'A' + (pin-1));
    447   1.2  garbled 	pinsub = prop_dictionary_get(devsub, key);
    448   1.2  garbled 	if (pinsub == NULL)
    449   1.2  garbled 		goto bad;
    450   1.2  garbled 	line = prop_number_integer_value(pinsub);
    451   1.2  garbled 
    452   1.2  garbled 	if (line == 0 || line == 255) {
    453   1.2  garbled 		aprint_error("pci_intr_map: no mapping for pin %c\n",'@' + pin);
    454   1.2  garbled 		goto bad;
    455   1.2  garbled 	}
    456   1.2  garbled 
    457   1.2  garbled 	*ihp = line;
    458   1.2  garbled 	return 0;
    459   1.2  garbled 
    460   1.2  garbled bad:
    461   1.2  garbled 	*ihp = -1;
    462   1.2  garbled 	return 1;
    463   1.2  garbled }
    464   1.2  garbled 
    465   1.2  garbled int
    466   1.2  garbled genofw_pci_conf_hook(pci_chipset_tag_t pct, int bus, int dev, int func,
    467   1.2  garbled 	pcireg_t id)
    468   1.2  garbled {
    469   1.2  garbled 	struct genppc_pci_chipset_businfo *pbi;
    470   1.2  garbled 	prop_number_t pbus;
    471   1.2  garbled 	pcitag_t tag;
    472   1.2  garbled 	pcireg_t class;
    473   1.2  garbled 	int node;
    474   1.2  garbled 
    475   1.2  garbled 	/* We have already mapped MPIC's if we have them, so leave them alone */
    476   1.2  garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
    477   1.2  garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC2)
    478   1.2  garbled 		return 0;
    479   1.2  garbled 
    480   1.2  garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
    481   1.2  garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC)
    482   1.2  garbled 		return 0;
    483   1.2  garbled 
    484   1.2  garbled 	/* I highly doubt there are any CHRP ravens, but just in case */
    485   1.2  garbled 	if (PCI_VENDOR(id) == PCI_VENDOR_MOT &&
    486   1.2  garbled 	    PCI_PRODUCT(id) == PCI_PRODUCT_MOT_RAVEN)
    487   1.2  garbled 		return (PCI_CONF_ALL & ~PCI_CONF_MAP_MEM);
    488   1.2  garbled 
    489   1.7      mrg 	/*
    490   1.7      mrg 	 * Pegasos2 specific stuff.
    491   1.7      mrg 	 */
    492   1.7      mrg 	if (strncmp(model_name, "Pegasos2", 8) == 0) {
    493   1.7      mrg 
    494  1.11      phx 		/* never reconfigure the MV64361 host bridge */
    495  1.11      phx 		if (PCI_VENDOR(id) == PCI_VENDOR_MARVELL &&
    496  1.11      phx 		    PCI_PRODUCT(id) == PCI_PRODUCT_MARVELL_GT64360)
    497  1.11      phx 			return 0;
    498  1.11      phx 
    499   1.7      mrg 		/* we want to leave viaide(4) alone */
    500   1.7      mrg 		if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
    501   1.7      mrg 		    PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C586A_IDE)
    502   1.7      mrg 			return 0;
    503   1.7      mrg 
    504   1.9  garbled 		/* leave the audio IO alone */
    505   1.7      mrg 		if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
    506   1.9  garbled 		    PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C686A_AC97)
    507   1.9  garbled 			return (PCI_CONF_ALL & ~PCI_CONF_MAP_IO);
    508   1.9  garbled 
    509   1.7      mrg 	}
    510   1.9  garbled 
    511   1.9  garbled 	tag = pci_make_tag(pct, bus, dev, func);
    512   1.9  garbled 	class = pci_conf_read(pct, tag, PCI_CLASS_REG);
    513   1.7      mrg 
    514   1.9  garbled 	/* leave video cards alone */
    515   1.9  garbled 	if (PCI_CLASS(class) == PCI_CLASS_DISPLAY)
    516   1.9  garbled 		return 0;
    517   1.9  garbled 
    518   1.2  garbled 	/* NOTE, all device specific stuff must be above this line */
    519   1.2  garbled 	/* don't do this on the primary host bridge */
    520   1.2  garbled 	if (bus == 0 && dev == 0 && func == 0)
    521   1.2  garbled 		return PCI_CONF_DEFAULT;
    522   1.2  garbled 
    523   1.2  garbled 	/*
    524   1.2  garbled 	 * PCI bridges have special needs.  We need to discover where they
    525   1.2  garbled 	 * came from, and wire them appropriately.
    526   1.2  garbled 	 */
    527   1.2  garbled 	if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
    528   1.2  garbled 	    PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_PCI) {
    529   1.2  garbled 		pbi = malloc(sizeof(struct genppc_pci_chipset_businfo),
    530   1.2  garbled 		    M_DEVBUF, M_NOWAIT);
    531   1.2  garbled 		KASSERT(pbi != NULL);
    532   1.2  garbled 		pbi->pbi_properties = prop_dictionary_create();
    533   1.2  garbled 		KASSERT(pbi->pbi_properties != NULL);
    534   1.2  garbled 		node = genofw_find_node_by_devfunc(pct->pc_node, bus, dev,
    535   1.2  garbled 		    func);
    536   1.2  garbled 		if (node == -1) {
    537   1.2  garbled 			aprint_error("Cannot find node for device "
    538   1.2  garbled 			    "bus %d dev %d func %d\n", bus, dev, func);
    539   1.2  garbled 			prop_object_release(pbi->pbi_properties);
    540   1.2  garbled 			free(pbi, M_DEVBUF);
    541   1.2  garbled 			return (PCI_CONF_DEFAULT);
    542   1.2  garbled 		}
    543   1.4  garbled 		genofw_setup_pciintr_map((void *)pct, pbi, node);
    544   1.2  garbled 
    545   1.2  garbled 		/* record the parent bus, and the parent device number */
    546   1.2  garbled 		pbus = prop_number_create_integer(bus);
    547   1.2  garbled 		prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-parent",
    548   1.2  garbled 		    pbus);
    549   1.2  garbled 		prop_object_release(pbus);
    550   1.2  garbled 		pbus = prop_number_create_integer(dev);
    551   1.2  garbled 		prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-rawdevnum",
    552   1.2  garbled 		    pbus);
    553   1.2  garbled 		prop_object_release(pbus);
    554   1.2  garbled 
    555   1.2  garbled 		SIMPLEQ_INSERT_TAIL(&pct->pc_pbi, pbi, next);
    556   1.2  garbled 	}
    557   1.2  garbled 
    558   1.2  garbled 	return (PCI_CONF_DEFAULT);
    559   1.2  garbled }
    560