xref: /netbsd-src/sys/arch/powerpc/oea/ofw_autoconf.c (revision 6d5a047a6eca25bd4304ec0a3c86f31779ec9c3a)
1*6d5a047aSandvar /* $NetBSD: ofw_autoconf.c,v 1.26 2023/09/23 21:26:16 andvar Exp $ */
2de2c7f5dSgarbled /*
3de2c7f5dSgarbled  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
4de2c7f5dSgarbled  * Copyright (C) 1995, 1996 TooLs GmbH.
5de2c7f5dSgarbled  * All rights reserved.
6de2c7f5dSgarbled  *
7de2c7f5dSgarbled  * Redistribution and use in source and binary forms, with or without
8de2c7f5dSgarbled  * modification, are permitted provided that the following conditions
9de2c7f5dSgarbled  * are met:
10de2c7f5dSgarbled  * 1. Redistributions of source code must retain the above copyright
11de2c7f5dSgarbled  *    notice, this list of conditions and the following disclaimer.
12de2c7f5dSgarbled  * 2. Redistributions in binary form must reproduce the above copyright
13de2c7f5dSgarbled  *    notice, this list of conditions and the following disclaimer in the
14de2c7f5dSgarbled  *    documentation and/or other materials provided with the distribution.
15de2c7f5dSgarbled  * 3. All advertising materials mentioning features or use of this software
16de2c7f5dSgarbled  *    must display the following acknowledgement:
17de2c7f5dSgarbled  *      This product includes software developed by TooLs GmbH.
18de2c7f5dSgarbled  * 4. The name of TooLs GmbH may not be used to endorse or promote products
19de2c7f5dSgarbled  *    derived from this software without specific prior written permission.
20de2c7f5dSgarbled  *
21de2c7f5dSgarbled  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
22de2c7f5dSgarbled  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23de2c7f5dSgarbled  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24de2c7f5dSgarbled  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25de2c7f5dSgarbled  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26de2c7f5dSgarbled  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27de2c7f5dSgarbled  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28de2c7f5dSgarbled  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29de2c7f5dSgarbled  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30de2c7f5dSgarbled  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31de2c7f5dSgarbled  */
32de2c7f5dSgarbled 
33de2c7f5dSgarbled #include <sys/cdefs.h>
34*6d5a047aSandvar __KERNEL_RCSID(0, "$NetBSD: ofw_autoconf.c,v 1.26 2023/09/23 21:26:16 andvar Exp $");
352581e047Skiyohara 
362581e047Skiyohara #ifdef ofppc
372581e047Skiyohara #include "gtpci.h"
382581e047Skiyohara #endif
39de2c7f5dSgarbled 
40de2c7f5dSgarbled #include <sys/param.h>
41de2c7f5dSgarbled #include <sys/conf.h>
42de2c7f5dSgarbled #include <sys/device.h>
43de2c7f5dSgarbled #include <sys/reboot.h>
44de2c7f5dSgarbled #include <sys/systm.h>
45de2c7f5dSgarbled 
46de2c7f5dSgarbled #include <uvm/uvm_extern.h>
47de2c7f5dSgarbled 
48de2c7f5dSgarbled #include <machine/autoconf.h>
49cf10107dSdyoung #include <sys/bus.h>
50de2c7f5dSgarbled 
51de2c7f5dSgarbled #include <dev/ofw/openfirm.h>
522581e047Skiyohara #include <dev/marvell/marvellvar.h>
53f5f76a59Saymeric #include <dev/pci/pcireg.h>
54de2c7f5dSgarbled #include <dev/pci/pcivar.h>
552581e047Skiyohara #if NGTPCI > 0
562581e047Skiyohara #include <dev/marvell/gtpcivar.h>
572581e047Skiyohara #endif
58de2c7f5dSgarbled #include <dev/scsipi/scsi_all.h>
59de2c7f5dSgarbled #include <dev/scsipi/scsipi_all.h>
60de2c7f5dSgarbled #include <dev/scsipi/scsiconf.h>
61de2c7f5dSgarbled #include <dev/ata/atavar.h>
62de2c7f5dSgarbled #include <dev/ic/wdcvar.h>
63de2c7f5dSgarbled 
64a672a0c5Smacallan #include <dev/wscons/wsconsio.h>
65a672a0c5Smacallan #include <dev/wscons/wsdisplayvar.h>
66a672a0c5Smacallan #include <dev/rasops/rasops.h>
67a672a0c5Smacallan #include <powerpc/oea/ofw_rasconsvar.h>
68a672a0c5Smacallan 
692581e047Skiyohara #include <machine/pci_machdep.h>
702581e047Skiyohara 
712581e047Skiyohara #include <prop/proplib.h>
722581e047Skiyohara 
73de2c7f5dSgarbled extern char bootpath[256];
74de2c7f5dSgarbled char cbootpath[256];
75140b570fSmacallan static int boot_node = 0;	/* points at boot device if we netboot */
76de2c7f5dSgarbled 
77de2c7f5dSgarbled static void canonicalize_bootpath(void);
78de2c7f5dSgarbled 
79de2c7f5dSgarbled /*
80de2c7f5dSgarbled  * Determine device configuration for a machine.
81de2c7f5dSgarbled  */
82de2c7f5dSgarbled void
cpu_configure(void)83de2c7f5dSgarbled cpu_configure(void)
84de2c7f5dSgarbled {
85*6d5a047aSandvar #if NWSDISPLAY > 0
86a672a0c5Smacallan 	rascons_add_rom_font();
87*6d5a047aSandvar #endif
88de2c7f5dSgarbled 	init_interrupt();
89de2c7f5dSgarbled 	canonicalize_bootpath();
90de2c7f5dSgarbled 
91de2c7f5dSgarbled 	if (config_rootfound("mainbus", NULL) == NULL)
92de2c7f5dSgarbled 		panic("configure: mainbus not configured");
93de2c7f5dSgarbled 
94de2c7f5dSgarbled 	genppc_cpu_configure();
95de2c7f5dSgarbled }
96de2c7f5dSgarbled 
97de2c7f5dSgarbled static void
canonicalize_bootpath(void)98de2c7f5dSgarbled canonicalize_bootpath(void)
99de2c7f5dSgarbled {
100140b570fSmacallan 	int node, len;
101de2c7f5dSgarbled 	char *p, *lastp;
102140b570fSmacallan 	char last[32], type[32];
103de2c7f5dSgarbled 
104de2c7f5dSgarbled 	/*
105de2c7f5dSgarbled 	 * If the bootpath doesn't start with a / then it isn't
106de2c7f5dSgarbled 	 * an OFW path and probably is an alias, so look up the alias
107de2c7f5dSgarbled 	 * and regenerate the full bootpath so device_register will work.
108de2c7f5dSgarbled 	 */
109de2c7f5dSgarbled 	if (bootpath[0] != '/' && bootpath[0] != '\0') {
110de2c7f5dSgarbled 		int aliases = OF_finddevice("/aliases");
111de2c7f5dSgarbled 		char tmpbuf[100];
112de2c7f5dSgarbled 		char aliasbuf[256];
113de2c7f5dSgarbled 		if (aliases != 0) {
114de2c7f5dSgarbled 			char *cp1, *cp2, *cp;
115de2c7f5dSgarbled 			char saved_ch = '\0';
116de2c7f5dSgarbled 			cp1 = strchr(bootpath, ':');
117de2c7f5dSgarbled 			cp2 = strchr(bootpath, ',');
118de2c7f5dSgarbled 			cp = cp1;
119de2c7f5dSgarbled 			if (cp1 == NULL || (cp2 != NULL && cp2 < cp1))
120de2c7f5dSgarbled 				cp = cp2;
121de2c7f5dSgarbled 			tmpbuf[0] = '\0';
122de2c7f5dSgarbled 			if (cp != NULL) {
123de2c7f5dSgarbled 				strcpy(tmpbuf, cp);
124de2c7f5dSgarbled 				saved_ch = *cp;
125de2c7f5dSgarbled 				*cp = '\0';
126de2c7f5dSgarbled 			}
127de2c7f5dSgarbled 			len = OF_getprop(aliases, bootpath, aliasbuf,
128de2c7f5dSgarbled 			    sizeof(aliasbuf));
129de2c7f5dSgarbled 			if (len > 0) {
130de2c7f5dSgarbled 				if (aliasbuf[len-1] == '\0')
131de2c7f5dSgarbled 					len--;
132de2c7f5dSgarbled 				memcpy(bootpath, aliasbuf, len);
133de2c7f5dSgarbled 				strcpy(&bootpath[len], tmpbuf);
134de2c7f5dSgarbled 			} else {
135de2c7f5dSgarbled 				*cp = saved_ch;
136de2c7f5dSgarbled 			}
137de2c7f5dSgarbled 		}
138de2c7f5dSgarbled 	}
139de2c7f5dSgarbled 
140de2c7f5dSgarbled 	/*
141de2c7f5dSgarbled 	 * Strip kernel name.  bootpath contains "OF-path"/"kernel".
142de2c7f5dSgarbled 	 *
143de2c7f5dSgarbled 	 * for example:
144de2c7f5dSgarbled 	 *   /bandit@F2000000/gc@10/53c94@10000/sd@0,0/netbsd	(OF-1.x)
145de2c7f5dSgarbled 	 *   /pci/mac-io/ata-3@2000/disk@0:0/netbsd.new		(OF-3.x)
146de2c7f5dSgarbled 	 */
147de2c7f5dSgarbled 	strcpy(cbootpath, bootpath);
148460fa970Sjoerg 
149460fa970Sjoerg 	if ((node = OF_finddevice("/options")) == -1 ||
150460fa970Sjoerg 	    OF_getprop(node, "qemu_boot_hack", type, sizeof(type) - 1) == -1 ||
151460fa970Sjoerg 	    type[0] != 'y') {
152de2c7f5dSgarbled 		while ((node = OF_finddevice(cbootpath)) == -1) {
153de2c7f5dSgarbled 			if ((p = strrchr(cbootpath, '/')) == NULL)
154de2c7f5dSgarbled 				break;
155de2c7f5dSgarbled 			*p = '\0';
156de2c7f5dSgarbled 		}
157460fa970Sjoerg 	} else {
158460fa970Sjoerg 		node = -1;
159460fa970Sjoerg 	}
160de2c7f5dSgarbled 
1615206bb38Smrg 	printf("bootpath: %s\n", bootpath);
162de2c7f5dSgarbled 	if (node == -1) {
163de2c7f5dSgarbled 		/* Cannot canonicalize... use bootpath anyway. */
164de2c7f5dSgarbled 		strcpy(cbootpath, bootpath);
165de2c7f5dSgarbled 
166de2c7f5dSgarbled 		return;
167de2c7f5dSgarbled 	}
168de2c7f5dSgarbled 
169140b570fSmacallan 	/* see if we netbooted */
170140b570fSmacallan 	len = OF_getprop(node, "device_type", type, sizeof(type) - 1);
171140b570fSmacallan 	if (len > -1) {
172140b570fSmacallan 		type[len] = 0;
173140b570fSmacallan 		if (strcmp(type, "network") == 0) {
174140b570fSmacallan 			boot_node = node;
175140b570fSmacallan 		}
176140b570fSmacallan 	}
177140b570fSmacallan 
178de2c7f5dSgarbled 	/*
179de2c7f5dSgarbled 	 * cbootpath is a valid OF path.  Use package-to-path to
180de2c7f5dSgarbled 	 * canonicalize pathname.
181de2c7f5dSgarbled 	 */
182de2c7f5dSgarbled 
183de2c7f5dSgarbled 	/* Back up the last component for later use. */
184de2c7f5dSgarbled 	if ((p = strrchr(cbootpath, '/')) != NULL)
185de2c7f5dSgarbled 		strcpy(last, p + 1);
186de2c7f5dSgarbled 	else
187de2c7f5dSgarbled 		last[0] = '\0';
188de2c7f5dSgarbled 
189de2c7f5dSgarbled 	memset(cbootpath, 0, sizeof(cbootpath));
190de2c7f5dSgarbled 	OF_package_to_path(node, cbootpath, sizeof(cbootpath) - 1);
191de2c7f5dSgarbled 
192de2c7f5dSgarbled 	/*
193de2c7f5dSgarbled 	 * OF_1.x (at least) always returns addr == 0 for
194de2c7f5dSgarbled 	 * SCSI disks (i.e. "/bandit@.../.../sd@0,0").
195a5d06cefSmacallan 	 * also check for .../disk@ which some Adaptec firmware uses
196de2c7f5dSgarbled 	 */
197de2c7f5dSgarbled 	lastp = strrchr(cbootpath, '/');
198de2c7f5dSgarbled 	if (lastp != NULL) {
199de2c7f5dSgarbled 		lastp++;
200a5d06cefSmacallan 		if ((strncmp(lastp, "sd@", 3) == 0
201a5d06cefSmacallan 		     && strncmp(last, "sd@", 3) == 0) ||
202a5d06cefSmacallan 		    (strncmp(lastp, "disk@", 5) == 0
203a5d06cefSmacallan 		     && strncmp(last, "disk@", 5) == 0))
204de2c7f5dSgarbled 			strcpy(lastp, last);
205de2c7f5dSgarbled 	} else {
206de2c7f5dSgarbled 		lastp = cbootpath;
207de2c7f5dSgarbled 	}
208de2c7f5dSgarbled 
209de2c7f5dSgarbled 	/*
210de2c7f5dSgarbled 	 * At this point, cbootpath contains like:
211de2c7f5dSgarbled 	 * "/pci@80000000/mac-io@10/ata-3@20000/disk"
212de2c7f5dSgarbled 	 *
213de2c7f5dSgarbled 	 * The last component may have no address... so append it.
214de2c7f5dSgarbled 	 */
215de2c7f5dSgarbled 	if (strchr(lastp, '@') == NULL) {
216de2c7f5dSgarbled 		/* Append it. */
217de2c7f5dSgarbled 		if ((p = strrchr(last, '@')) != NULL)
218de2c7f5dSgarbled 			strcat(cbootpath, p);
219de2c7f5dSgarbled 	}
220de2c7f5dSgarbled 
221de2c7f5dSgarbled 	if ((p = strrchr(lastp, ':')) != NULL) {
222de2c7f5dSgarbled 		*p++ = '\0';
223de2c7f5dSgarbled 		/* booted_partition = *p - '0';		XXX correct? */
224de2c7f5dSgarbled 	}
225de2c7f5dSgarbled }
226de2c7f5dSgarbled 
227de2c7f5dSgarbled /*
228de2c7f5dSgarbled  * device_register is called from config_attach as each device is
229de2c7f5dSgarbled  * attached. We use it to find the NetBSD device corresponding to the
230de2c7f5dSgarbled  * known OF boot device.
231de2c7f5dSgarbled  */
232de2c7f5dSgarbled void
device_register(device_t dev,void * aux)233036ca983Smatt device_register(device_t dev, void *aux)
234de2c7f5dSgarbled {
235036ca983Smatt 	static device_t parent;
236de2c7f5dSgarbled 	static char *bp = bootpath + 1, *cp = cbootpath;
2375206bb38Smrg 	unsigned long addr, addr2;
238de2c7f5dSgarbled 	char *p;
2392581e047Skiyohara #if NGTPCI > 0
2402581e047Skiyohara 	struct powerpc_bus_space *gtpci_mem_bs_tag = NULL;
2412581e047Skiyohara #endif
242de2c7f5dSgarbled 
243de2c7f5dSgarbled 	/* Skip over devices not represented in the OF tree. */
244de2c7f5dSgarbled 	if (device_is_a(dev, "mainbus")) {
245de2c7f5dSgarbled 		parent = dev;
246de2c7f5dSgarbled 		return;
247de2c7f5dSgarbled 	}
248703675e1Smacallan 
249a539dd3dSmacallan 	/* skip over CPUs */
250a539dd3dSmacallan 	if (device_is_a(dev, "cpu")) {
251a539dd3dSmacallan 		return;
252a539dd3dSmacallan 	}
253a539dd3dSmacallan 
254703675e1Smacallan 	if (device_is_a(dev, "valkyriefb")) {
255703675e1Smacallan 		struct confargs *ca = aux;
256703675e1Smacallan 		prop_dictionary_t dict;
257703675e1Smacallan 
258703675e1Smacallan 		dict = device_properties(dev);
259703675e1Smacallan 		copy_disp_props(dev, ca->ca_node, dict);
260703675e1Smacallan 	}
261703675e1Smacallan 
262020d1d67Sscole 	/* cannot read useful display properties for platinum */
263020d1d67Sscole 	if (device_is_a(dev, "platinumfb")) {
264020d1d67Sscole 		return;
265020d1d67Sscole 	}
266020d1d67Sscole 
2672581e047Skiyohara #if NGTPCI > 0
2682581e047Skiyohara 	if (device_is_a(dev, "gtpci")) {
2692581e047Skiyohara 		extern struct gtpci_prot gtpci0_prot, gtpci1_prot;
2702581e047Skiyohara 		extern struct powerpc_bus_space
2712581e047Skiyohara 		    gtpci0_io_bs_tag, gtpci0_mem_bs_tag,
2722581e047Skiyohara 		    gtpci1_io_bs_tag, gtpci1_mem_bs_tag;
2732581e047Skiyohara 		extern struct genppc_pci_chipset
2742581e047Skiyohara 		    genppc_gtpci0_chipset, genppc_gtpci1_chipset;
2752581e047Skiyohara 
2762581e047Skiyohara 		struct marvell_attach_args *mva = aux;
2772581e047Skiyohara 		struct gtpci_prot *gtpci_prot;
2782581e047Skiyohara 		struct powerpc_bus_space *gtpci_io_bs_tag;
2792581e047Skiyohara 		struct genppc_pci_chipset *genppc_gtpci_chipset;
2802581e047Skiyohara 		prop_dictionary_t dict = device_properties(dev);
2812581e047Skiyohara 		prop_data_t prot, io_bs_tag, mem_bs_tag, pc;
2822581e047Skiyohara 		int iostart, ioend;
2832581e047Skiyohara 
2842581e047Skiyohara 		if (mva->mva_unit == 0) {
2852581e047Skiyohara 			gtpci_prot = &gtpci0_prot;
2862581e047Skiyohara 			gtpci_io_bs_tag = &gtpci0_io_bs_tag;
2872581e047Skiyohara 			gtpci_mem_bs_tag = &gtpci0_mem_bs_tag;
2882581e047Skiyohara 			genppc_gtpci_chipset = &genppc_gtpci0_chipset;
2892581e047Skiyohara 			iostart = 0;
2902581e047Skiyohara 			ioend = 0;
2912581e047Skiyohara 		} else {
2922581e047Skiyohara 			gtpci_prot = &gtpci1_prot;
2932581e047Skiyohara 			gtpci_io_bs_tag = &gtpci1_io_bs_tag;
2942581e047Skiyohara 			gtpci_mem_bs_tag = &gtpci1_mem_bs_tag;
2952581e047Skiyohara 			genppc_gtpci_chipset = &genppc_gtpci1_chipset;
2962581e047Skiyohara 			iostart = 0x1400;
2972581e047Skiyohara 			ioend = 0xffff;
2982581e047Skiyohara 		}
2992581e047Skiyohara 
3002581e047Skiyohara 		prot = prop_data_create_data_nocopy(
3012581e047Skiyohara 		    gtpci_prot, sizeof(struct gtpci_prot));
3022581e047Skiyohara 		KASSERT(prot != NULL);
3032581e047Skiyohara 		prop_dictionary_set(dict, "prot", prot);
3042581e047Skiyohara 		prop_object_release(prot);
3052581e047Skiyohara 
3062581e047Skiyohara 		io_bs_tag = prop_data_create_data_nocopy(
3072581e047Skiyohara 		    gtpci_io_bs_tag, sizeof(struct powerpc_bus_space));
3082581e047Skiyohara 		KASSERT(io_bs_tag != NULL);
3092581e047Skiyohara 		prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
3102581e047Skiyohara 		prop_object_release(io_bs_tag);
3112581e047Skiyohara 		mem_bs_tag = prop_data_create_data_nocopy(
3122581e047Skiyohara 		    gtpci_mem_bs_tag, sizeof(struct powerpc_bus_space));
3132581e047Skiyohara 		KASSERT(mem_bs_tag != NULL);
3142581e047Skiyohara 		prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
3152581e047Skiyohara 		prop_object_release(mem_bs_tag);
3162581e047Skiyohara 
3172581e047Skiyohara 		genppc_gtpci_chipset->pc_conf_v = device_private(dev);
3182581e047Skiyohara 		pc = prop_data_create_data_nocopy(genppc_gtpci_chipset,
3192581e047Skiyohara 		    sizeof(struct genppc_pci_chipset));
3202581e047Skiyohara 		KASSERT(pc != NULL);
3212581e047Skiyohara 		prop_dictionary_set(dict, "pci-chipset", pc);
3222581e047Skiyohara 		prop_object_release(pc);
3232581e047Skiyohara 
3242581e047Skiyohara 		prop_dictionary_set_uint64(dict, "iostart", iostart);
3252581e047Skiyohara 		prop_dictionary_set_uint64(dict, "ioend", ioend);
3262581e047Skiyohara 		prop_dictionary_set_uint64(dict, "memstart",
3272581e047Skiyohara 		    gtpci_mem_bs_tag->pbs_base);
3282581e047Skiyohara 		prop_dictionary_set_uint64(dict, "memend",
3292581e047Skiyohara 		    gtpci_mem_bs_tag->pbs_limit - 1);
3302581e047Skiyohara 		prop_dictionary_set_uint32(dict, "cache-line-size",
3312581e047Skiyohara 		    CACHELINESIZE);
3322581e047Skiyohara 	}
3332581e047Skiyohara #endif
334a539dd3dSmacallan 	if (device_is_a(dev, "atapibus") ||
335a539dd3dSmacallan #ifndef PMAC_G5
336a539dd3dSmacallan 	    device_is_a(dev, "pci") ||
337a539dd3dSmacallan #endif
338de2c7f5dSgarbled 	    device_is_a(dev, "scsibus") || device_is_a(dev, "atabus"))
339de2c7f5dSgarbled 		return;
340de2c7f5dSgarbled 
341de2c7f5dSgarbled 	if (device_is_a(device_parent(dev), "pci")) {
342de2c7f5dSgarbled 		struct pci_attach_args *pa = aux;
343de2c7f5dSgarbled 		prop_dictionary_t dict;
344c6d327a8Sphx 		prop_bool_t b;
345b0f4d9f9Sgarbled 		int node;
346b0f4d9f9Sgarbled 		char name[32];
347de2c7f5dSgarbled 
348de2c7f5dSgarbled 		dict = device_properties(dev);
349de2c7f5dSgarbled 		node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
350b0f4d9f9Sgarbled 
351c6d327a8Sphx 		/* enable configuration of irq 14/15 for VIA native IDE */
352c6d327a8Sphx 		if (device_is_a(dev, "viaide") &&
353c6d327a8Sphx 		    strncmp(model_name, "Pegasos", 7) == 0) {
354c6d327a8Sphx 			b = prop_bool_create(true);
355c6d327a8Sphx 			KASSERT(b != NULL);
356c6d327a8Sphx 			(void)prop_dictionary_set(dict,
357c6d327a8Sphx 			    "use-compat-native-irq", b);
358c6d327a8Sphx 			prop_object_release(b);
359c6d327a8Sphx 		}
360c6d327a8Sphx 
361b795935fSmacallan 		if (node != 0) {
362f5f76a59Saymeric 			int pci_class = 0;
363f5f76a59Saymeric 
364de2c7f5dSgarbled 			prop_dictionary_set_uint32(dict, "device_node", node);
365de2c7f5dSgarbled 
366140b570fSmacallan 			if (node == boot_node) {
367140b570fSmacallan 				/* we netbooted from whatever this is */
368140b570fSmacallan 				booted_device = dev;
369140b570fSmacallan 			}
370c6d327a8Sphx 			/* see if this is going to be console */
371b0f4d9f9Sgarbled 			memset(name, 0, sizeof(name));
372b0f4d9f9Sgarbled 			OF_getprop(node, "device_type", name, sizeof(name));
373f5f76a59Saymeric 
374f5f76a59Saymeric 			OF_getprop(node, "class-code", &pci_class,
375f5f76a59Saymeric 				sizeof pci_class);
376f5f76a59Saymeric 			pci_class = (pci_class >> 16) & 0xff;
377f5f76a59Saymeric 
378f5f76a59Saymeric 			if (strcmp(name, "display") == 0 ||
379cabde683Smacallan 			    strcmp(name, "ATY,DDParent") == 0 ||
380f5f76a59Saymeric 			    pci_class == PCI_CLASS_DISPLAY) {
381b0f4d9f9Sgarbled 				/* setup display properties for fb driver */
382b0f4d9f9Sgarbled 				prop_dictionary_set_bool(dict, "is_console", 0);
383b0f4d9f9Sgarbled 				copy_disp_props(dev, node, dict);
384de2c7f5dSgarbled 			}
385efa2da50Smacallan 			if (pci_class == PCI_CLASS_NETWORK) {
386efa2da50Smacallan 				of_to_dataprop(dict, node, "local-mac-address",
387efa2da50Smacallan 				    "mac-address");
388efa2da50Smacallan 				of_to_dataprop(dict, node, "shared-pins",
389efa2da50Smacallan 				    "shared-pins");
390efa2da50Smacallan 			}
391de2c7f5dSgarbled 		}
39276c99e81Smacallan #ifdef macppc
39376c99e81Smacallan 		/*
39476c99e81Smacallan 		 * XXX
39576c99e81Smacallan 		 * some macppc boxes have onboard devices where parts or all of
39676c99e81Smacallan 		 * the PCI_INTERRUPT register are hardwired to 0
39776c99e81Smacallan 		 */
39876c99e81Smacallan 		if (pa->pa_intrpin == 0)
39976c99e81Smacallan 			pa->pa_intrpin = 1;
40076c99e81Smacallan #endif
401de2c7f5dSgarbled 	}
402de2c7f5dSgarbled 
403b0f4d9f9Sgarbled 	if (booted_device)
404b0f4d9f9Sgarbled 		return;
405de2c7f5dSgarbled 
4065206bb38Smrg 	/*
4075206bb38Smrg 	 * Skip over devices that are really just layers of NetBSD
4085206bb38Smrg 	 * autoconf(9) we should just skip as they do not have any
4095206bb38Smrg 	 * OFW devices.
410a539dd3dSmacallan 	 * XXX except on G5, where we have /ht/pci* instead of /pci*
4115206bb38Smrg 	 */
412de2c7f5dSgarbled 	if (device_is_a(device_parent(dev), "atapibus") ||
413de2c7f5dSgarbled 	    device_is_a(device_parent(dev), "atabus") ||
414a539dd3dSmacallan #ifndef PMAC_G5
415de2c7f5dSgarbled 	    device_is_a(device_parent(dev), "pci") ||
416a539dd3dSmacallan #endif
417de2c7f5dSgarbled 	    device_is_a(device_parent(dev), "scsibus")) {
418a539dd3dSmacallan 		if (device_parent(device_parent(dev)) != parent) {
419de2c7f5dSgarbled 			return;
420a539dd3dSmacallan 		}
421de2c7f5dSgarbled 	} else {
422de2c7f5dSgarbled 		if (device_parent(dev) != parent)
423de2c7f5dSgarbled 			return;
424de2c7f5dSgarbled 	}
425de2c7f5dSgarbled 
4265206bb38Smrg 	/*
4275206bb38Smrg 	 * Get the address part of the current path component. The
428de2c7f5dSgarbled 	 * last component of the canonical bootpath may have no
429de2c7f5dSgarbled 	 * address (eg, "disk"), in which case we need to get the
430de2c7f5dSgarbled 	 * address from the original bootpath instead.
431de2c7f5dSgarbled 	 */
432de2c7f5dSgarbled 	p = strchr(cp, '@');
433de2c7f5dSgarbled 	if (!p) {
434de2c7f5dSgarbled 		if (bp)
435de2c7f5dSgarbled 			p = strchr(bp, '@');
436de2c7f5dSgarbled 		if (!p)
437de2c7f5dSgarbled 			addr = 0;
4385206bb38Smrg 		else
4395206bb38Smrg 			addr = strtoul(p + 1, &p, 16);
440de2c7f5dSgarbled 	} else
441de2c7f5dSgarbled 		addr = strtoul(p + 1, &p, 16);
442de2c7f5dSgarbled 
4435206bb38Smrg 	/* if the current path has more address, grab that too */
4445206bb38Smrg 	if (p && *p == ',')
4455206bb38Smrg 		addr2 = strtoul(p + 1, &p, 16);
4465206bb38Smrg 	else
4475206bb38Smrg 		addr2 = 0;
4485206bb38Smrg 
449de2c7f5dSgarbled 	if (device_is_a(device_parent(dev), "mainbus")) {
450de2c7f5dSgarbled 		struct confargs *ca = aux;
451de2c7f5dSgarbled 		if (strcmp(ca->ca_name, "ofw") == 0)		/* XXX */
452de2c7f5dSgarbled 			return;
4532581e047Skiyohara 		if (strcmp(ca->ca_name, "gt") == 0)
4542581e047Skiyohara 			parent = dev;
455de2c7f5dSgarbled 		if (addr != ca->ca_reg[0])
456de2c7f5dSgarbled 			return;
457a539dd3dSmacallan 		if (addr2 != 0 && addr2 != ca->ca_reg[1])
458a539dd3dSmacallan 			return;
4592581e047Skiyohara 	} else if (device_is_a(device_parent(dev), "gt")) {
4602581e047Skiyohara 		/*
4612581e047Skiyohara 		 * Special handle for MV64361 on PegasosII(ofppc).
4622581e047Skiyohara 		 */
4632581e047Skiyohara 		if (device_is_a(dev, "mvgbec")) {
4642581e047Skiyohara 			/*
4652581e047Skiyohara 			 * Fix cp to /port@N from /ethernet/portN. (N is 0...2)
4662581e047Skiyohara 			 */
4672581e047Skiyohara 			static char fix_cp[8] = "/port@N";
4682581e047Skiyohara 
4692581e047Skiyohara 			if (strlen(cp) != 15 ||
4702581e047Skiyohara 			    strncmp(cp, "/ethernet/port", 14) != 0)
4712581e047Skiyohara 				return;
4722581e047Skiyohara 			fix_cp[7] = *(cp + 15);
4732581e047Skiyohara 			p = fix_cp;
4742581e047Skiyohara #if NGTPCI > 0
4752581e047Skiyohara 		} else if (device_is_a(dev, "gtpci")) {
4762581e047Skiyohara 			if (gtpci_mem_bs_tag != NULL &&
4772581e047Skiyohara 			    addr != gtpci_mem_bs_tag->pbs_base)
4782581e047Skiyohara 				return;
4792581e047Skiyohara #endif
4802581e047Skiyohara 		} else
4812581e047Skiyohara 			return;
482de2c7f5dSgarbled 	} else if (device_is_a(device_parent(dev), "pci")) {
483de2c7f5dSgarbled 		struct pci_attach_args *pa = aux;
484de2c7f5dSgarbled 
4855206bb38Smrg 		if (addr != pa->pa_device ||
4865206bb38Smrg 		    addr2 != pa->pa_function)
487de2c7f5dSgarbled 			return;
488de2c7f5dSgarbled 	} else if (device_is_a(device_parent(dev), "obio")) {
489de2c7f5dSgarbled 		struct confargs *ca = aux;
490de2c7f5dSgarbled 
491de2c7f5dSgarbled 		if (addr != ca->ca_reg[0])
492de2c7f5dSgarbled 			return;
493de2c7f5dSgarbled 	} else if (device_is_a(device_parent(dev), "scsibus") ||
494de2c7f5dSgarbled 		   device_is_a(device_parent(dev), "atapibus")) {
495de2c7f5dSgarbled 		struct scsipibus_attach_args *sa = aux;
496de2c7f5dSgarbled 
497de2c7f5dSgarbled 		/* periph_target is target for scsi, drive # for atapi */
498de2c7f5dSgarbled 		if (addr != sa->sa_periph->periph_target)
499de2c7f5dSgarbled 			return;
5005206bb38Smrg 	} else if (device_is_a(device_parent(device_parent(dev)), "pciide") ||
5015206bb38Smrg 		   device_is_a(device_parent(device_parent(dev)), "viaide") ||
5025206bb38Smrg 		   device_is_a(device_parent(device_parent(dev)), "slide")) {
503de2c7f5dSgarbled 		struct ata_device *adev = aux;
504de2c7f5dSgarbled 
5055206bb38Smrg 		if (addr != adev->adev_channel ||
5065206bb38Smrg 		    addr2 != adev->adev_drv_data->drive)
507de2c7f5dSgarbled 			return;
508de2c7f5dSgarbled 	} else if (device_is_a(device_parent(device_parent(dev)), "wdc")) {
509de2c7f5dSgarbled 		struct ata_device *adev = aux;
510de2c7f5dSgarbled 
511de2c7f5dSgarbled 		if (addr != adev->adev_drv_data->drive)
512de2c7f5dSgarbled 			return;
513a539dd3dSmacallan 	} else if (device_is_a(dev, "pci")) {
514a539dd3dSmacallan 		if (addr != device_unit(dev))
515a539dd3dSmacallan 			return;
516a539dd3dSmacallan 	} else if (device_is_a(device_parent(dev), "atabus")) {
517a539dd3dSmacallan 		/*
518a539dd3dSmacallan 		 * XXX
519a539dd3dSmacallan 		 * on svwsata this is the channel number and we ignore the
520a539dd3dSmacallan 		 * drive number which is always 0 anyway
521a539dd3dSmacallan 		 * needs to be revisited for other (S)ATA cards
522a539dd3dSmacallan 		 */
523a539dd3dSmacallan 		struct ata_device *adev = aux;
524a539dd3dSmacallan 		if (addr != adev->adev_channel)
525a539dd3dSmacallan 			return;
526a539dd3dSmacallan 		/* we have our match, cut off the rest */
527a539dd3dSmacallan 		if (p) *p = 0;
528de2c7f5dSgarbled 	} else
529de2c7f5dSgarbled 		return;
530de2c7f5dSgarbled 
531de2c7f5dSgarbled 	/* If we reach this point, then dev is a match for the current
532de2c7f5dSgarbled 	 * path component.
533de2c7f5dSgarbled 	 */
534de2c7f5dSgarbled 	if (p && *p) {
535de2c7f5dSgarbled 		parent = dev;
536de2c7f5dSgarbled 		cp = p;
537de2c7f5dSgarbled 		bp = strchr(bp, '/');
538de2c7f5dSgarbled 		if (bp)
539de2c7f5dSgarbled 			bp++;
540de2c7f5dSgarbled 		return;
541de2c7f5dSgarbled 	} else {
542de2c7f5dSgarbled 		booted_device = dev;
543de2c7f5dSgarbled 		booted_partition = 0; /* XXX -- should be extracted from bootpath */
544de2c7f5dSgarbled 		return;
545de2c7f5dSgarbled 	}
546de2c7f5dSgarbled }
547de2c7f5dSgarbled 
548de2c7f5dSgarbled /*
549de2c7f5dSgarbled  * Setup root device.
550de2c7f5dSgarbled  * Configure swap area.
551de2c7f5dSgarbled  */
552de2c7f5dSgarbled void
cpu_rootconf(void)553df7f595eScegger cpu_rootconf(void)
554de2c7f5dSgarbled {
555de2c7f5dSgarbled 	printf("boot device: %s\n",
556036ca983Smatt 	    booted_device ? device_xname(booted_device) : "<unknown>");
557de2c7f5dSgarbled 
5588ce44338Smlelstv 	rootconf();
559de2c7f5dSgarbled }
560de2c7f5dSgarbled 
561de2c7f5dSgarbled /*
562de2c7f5dSgarbled  * Find OF-device corresponding to the PCI device.
563de2c7f5dSgarbled  */
564de2c7f5dSgarbled int
pcidev_to_ofdev(pci_chipset_tag_t pc,pcitag_t tag)565de2c7f5dSgarbled pcidev_to_ofdev(pci_chipset_tag_t pc, pcitag_t tag)
566de2c7f5dSgarbled {
567de2c7f5dSgarbled 	int bus, dev, func;
568de2c7f5dSgarbled 	u_int reg[5];
569de2c7f5dSgarbled 	int p, q;
570de2c7f5dSgarbled 	int l, b, d, f;
571de2c7f5dSgarbled 
572de2c7f5dSgarbled 	pci_decompose_tag(pc, tag, &bus, &dev, &func);
573de2c7f5dSgarbled 
574de2c7f5dSgarbled 	for (q = OF_peer(0); q; q = p) {
575de2c7f5dSgarbled 		l = OF_getprop(q, "assigned-addresses", reg, sizeof(reg));
576de2c7f5dSgarbled 		if (l > 4) {
577de2c7f5dSgarbled 			b = (reg[0] >> 16) & 0xff;
578de2c7f5dSgarbled 			d = (reg[0] >> 11) & 0x1f;
579de2c7f5dSgarbled 			f = (reg[0] >> 8) & 0x07;
580de2c7f5dSgarbled 
581de2c7f5dSgarbled 			if (b == bus && d == dev && f == func)
582de2c7f5dSgarbled 				return q;
583de2c7f5dSgarbled 		}
584de2c7f5dSgarbled 		if ((p = OF_child(q)))
585de2c7f5dSgarbled 			continue;
586de2c7f5dSgarbled 		while (q) {
587de2c7f5dSgarbled 			if ((p = OF_peer(q)))
588de2c7f5dSgarbled 				break;
589de2c7f5dSgarbled 			q = OF_parent(q);
590de2c7f5dSgarbled 		}
591de2c7f5dSgarbled 	}
592de2c7f5dSgarbled 	return 0;
593de2c7f5dSgarbled }
594