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 = >pci0_prot;
2862581e047Skiyohara gtpci_io_bs_tag = >pci0_io_bs_tag;
2872581e047Skiyohara gtpci_mem_bs_tag = >pci0_mem_bs_tag;
2882581e047Skiyohara genppc_gtpci_chipset = &genppc_gtpci0_chipset;
2892581e047Skiyohara iostart = 0;
2902581e047Skiyohara ioend = 0;
2912581e047Skiyohara } else {
2922581e047Skiyohara gtpci_prot = >pci1_prot;
2932581e047Skiyohara gtpci_io_bs_tag = >pci1_io_bs_tag;
2942581e047Skiyohara gtpci_mem_bs_tag = >pci1_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