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