Annotation of src/sys/arch/powerpc/oea/ofw_autoconf.c, Revision 1.18
1.18 ! macallan 1: /* $NetBSD: ofw_autoconf.c,v 1.17 2012/07/29 18:05:45 mlelstv Exp $ */
1.1 garbled 2: /*
3: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
4: * Copyright (C) 1995, 1996 TooLs GmbH.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by TooLs GmbH.
18: * 4. The name of TooLs GmbH may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #include <sys/cdefs.h>
1.18 ! macallan 34: __KERNEL_RCSID(0, "$NetBSD: ofw_autoconf.c,v 1.17 2012/07/29 18:05:45 mlelstv Exp $");
1.12 kiyohara 35:
36: #ifdef ofppc
37: #include "gtpci.h"
38: #endif
1.1 garbled 39:
40: #include <sys/param.h>
41: #include <sys/conf.h>
42: #include <sys/device.h>
43: #include <sys/reboot.h>
44: #include <sys/systm.h>
45:
46: #include <uvm/uvm_extern.h>
47:
48: #include <machine/autoconf.h>
1.14 dyoung 49: #include <sys/bus.h>
1.1 garbled 50:
51: #include <dev/ofw/openfirm.h>
1.12 kiyohara 52: #include <dev/marvell/marvellvar.h>
1.6 aymeric 53: #include <dev/pci/pcireg.h>
1.1 garbled 54: #include <dev/pci/pcivar.h>
1.12 kiyohara 55: #if NGTPCI > 0
56: #include <dev/marvell/gtpcivar.h>
57: #endif
1.1 garbled 58: #include <dev/scsipi/scsi_all.h>
59: #include <dev/scsipi/scsipi_all.h>
60: #include <dev/scsipi/scsiconf.h>
61: #include <dev/ata/atavar.h>
62: #include <dev/ic/wdcvar.h>
63:
1.12 kiyohara 64: #include <machine/pci_machdep.h>
65:
66: #include <prop/proplib.h>
67:
1.1 garbled 68: extern char bootpath[256];
69: char cbootpath[256];
70: int console_node = 0, console_instance = 0;
71:
72: static void canonicalize_bootpath(void);
73:
74: /*
75: * Determine device configuration for a machine.
76: */
77: void
78: cpu_configure(void)
79: {
80: init_interrupt();
81: canonicalize_bootpath();
82:
83: if (config_rootfound("mainbus", NULL) == NULL)
84: panic("configure: mainbus not configured");
85:
86: genppc_cpu_configure();
87: }
88:
89: static void
90: canonicalize_bootpath(void)
91: {
92: int node;
93: char *p, *lastp;
94: char last[32];
95:
96: /*
97: * If the bootpath doesn't start with a / then it isn't
98: * an OFW path and probably is an alias, so look up the alias
99: * and regenerate the full bootpath so device_register will work.
100: */
101: if (bootpath[0] != '/' && bootpath[0] != '\0') {
102: int aliases = OF_finddevice("/aliases");
103: char tmpbuf[100];
104: char aliasbuf[256];
105: if (aliases != 0) {
106: char *cp1, *cp2, *cp;
107: char saved_ch = '\0';
108: int len;
109: cp1 = strchr(bootpath, ':');
110: cp2 = strchr(bootpath, ',');
111: cp = cp1;
112: if (cp1 == NULL || (cp2 != NULL && cp2 < cp1))
113: cp = cp2;
114: tmpbuf[0] = '\0';
115: if (cp != NULL) {
116: strcpy(tmpbuf, cp);
117: saved_ch = *cp;
118: *cp = '\0';
119: }
120: len = OF_getprop(aliases, bootpath, aliasbuf,
121: sizeof(aliasbuf));
122: if (len > 0) {
123: if (aliasbuf[len-1] == '\0')
124: len--;
125: memcpy(bootpath, aliasbuf, len);
126: strcpy(&bootpath[len], tmpbuf);
127: } else {
128: *cp = saved_ch;
129: }
130: }
131: }
132:
133: /*
134: * Strip kernel name. bootpath contains "OF-path"/"kernel".
135: *
136: * for example:
137: * /bandit@F2000000/gc@10/53c94@10000/sd@0,0/netbsd (OF-1.x)
138: * /pci/mac-io/ata-3@2000/disk@0:0/netbsd.new (OF-3.x)
139: */
140: strcpy(cbootpath, bootpath);
141: while ((node = OF_finddevice(cbootpath)) == -1) {
142: if ((p = strrchr(cbootpath, '/')) == NULL)
143: break;
144: *p = '\0';
145: }
146:
1.7 mrg 147: printf("bootpath: %s\n", bootpath);
1.1 garbled 148: if (node == -1) {
149: /* Cannot canonicalize... use bootpath anyway. */
150: strcpy(cbootpath, bootpath);
151:
152: return;
153: }
154:
155: /*
156: * cbootpath is a valid OF path. Use package-to-path to
157: * canonicalize pathname.
158: */
159:
160: /* Back up the last component for later use. */
161: if ((p = strrchr(cbootpath, '/')) != NULL)
162: strcpy(last, p + 1);
163: else
164: last[0] = '\0';
165:
166: memset(cbootpath, 0, sizeof(cbootpath));
167: OF_package_to_path(node, cbootpath, sizeof(cbootpath) - 1);
168:
169: /*
170: * OF_1.x (at least) always returns addr == 0 for
171: * SCSI disks (i.e. "/bandit@.../.../sd@0,0").
172: */
173: lastp = strrchr(cbootpath, '/');
174: if (lastp != NULL) {
175: lastp++;
176: if (strncmp(lastp, "sd@", 3) == 0
177: && strncmp(last, "sd@", 3) == 0)
178: strcpy(lastp, last);
179: } else {
180: lastp = cbootpath;
181: }
182:
183: /*
184: * At this point, cbootpath contains like:
185: * "/pci@80000000/mac-io@10/ata-3@20000/disk"
186: *
187: * The last component may have no address... so append it.
188: */
189: if (strchr(lastp, '@') == NULL) {
190: /* Append it. */
191: if ((p = strrchr(last, '@')) != NULL)
192: strcat(cbootpath, p);
193: }
194:
195: if ((p = strrchr(lastp, ':')) != NULL) {
196: *p++ = '\0';
197: /* booted_partition = *p - '0'; XXX correct? */
198: }
199: }
200:
201: /*
202: * device_register is called from config_attach as each device is
203: * attached. We use it to find the NetBSD device corresponding to the
204: * known OF boot device.
205: */
206: void
1.13 matt 207: device_register(device_t dev, void *aux)
1.1 garbled 208: {
1.13 matt 209: static device_t parent;
1.1 garbled 210: static char *bp = bootpath + 1, *cp = cbootpath;
1.7 mrg 211: unsigned long addr, addr2;
1.1 garbled 212: char *p;
1.12 kiyohara 213: #if NGTPCI > 0
214: struct powerpc_bus_space *gtpci_mem_bs_tag = NULL;
215: #endif
1.1 garbled 216:
217: /* Skip over devices not represented in the OF tree. */
218: if (device_is_a(dev, "mainbus")) {
219: parent = dev;
220: return;
221: }
1.16 macallan 222:
223: if (device_is_a(dev, "valkyriefb")) {
224: struct confargs *ca = aux;
225: prop_dictionary_t dict;
226:
227: dict = device_properties(dev);
228: copy_disp_props(dev, ca->ca_node, dict);
229: }
230:
1.12 kiyohara 231: #if NGTPCI > 0
232: if (device_is_a(dev, "gtpci")) {
233: extern struct gtpci_prot gtpci0_prot, gtpci1_prot;
234: extern struct powerpc_bus_space
235: gtpci0_io_bs_tag, gtpci0_mem_bs_tag,
236: gtpci1_io_bs_tag, gtpci1_mem_bs_tag;
237: extern struct genppc_pci_chipset
238: genppc_gtpci0_chipset, genppc_gtpci1_chipset;
239:
240: struct marvell_attach_args *mva = aux;
241: struct gtpci_prot *gtpci_prot;
242: struct powerpc_bus_space *gtpci_io_bs_tag;
243: struct genppc_pci_chipset *genppc_gtpci_chipset;
244: prop_dictionary_t dict = device_properties(dev);
245: prop_data_t prot, io_bs_tag, mem_bs_tag, pc;
246: int iostart, ioend;
247:
248: if (mva->mva_unit == 0) {
249: gtpci_prot = >pci0_prot;
250: gtpci_io_bs_tag = >pci0_io_bs_tag;
251: gtpci_mem_bs_tag = >pci0_mem_bs_tag;
252: genppc_gtpci_chipset = &genppc_gtpci0_chipset;
253: iostart = 0;
254: ioend = 0;
255: } else {
256: gtpci_prot = >pci1_prot;
257: gtpci_io_bs_tag = >pci1_io_bs_tag;
258: gtpci_mem_bs_tag = >pci1_mem_bs_tag;
259: genppc_gtpci_chipset = &genppc_gtpci1_chipset;
260: iostart = 0x1400;
261: ioend = 0xffff;
262: }
263:
264: prot = prop_data_create_data_nocopy(
265: gtpci_prot, sizeof(struct gtpci_prot));
266: KASSERT(prot != NULL);
267: prop_dictionary_set(dict, "prot", prot);
268: prop_object_release(prot);
269:
270: io_bs_tag = prop_data_create_data_nocopy(
271: gtpci_io_bs_tag, sizeof(struct powerpc_bus_space));
272: KASSERT(io_bs_tag != NULL);
273: prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
274: prop_object_release(io_bs_tag);
275: mem_bs_tag = prop_data_create_data_nocopy(
276: gtpci_mem_bs_tag, sizeof(struct powerpc_bus_space));
277: KASSERT(mem_bs_tag != NULL);
278: prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
279: prop_object_release(mem_bs_tag);
280:
281: genppc_gtpci_chipset->pc_conf_v = device_private(dev);
282: pc = prop_data_create_data_nocopy(genppc_gtpci_chipset,
283: sizeof(struct genppc_pci_chipset));
284: KASSERT(pc != NULL);
285: prop_dictionary_set(dict, "pci-chipset", pc);
286: prop_object_release(pc);
287:
288: prop_dictionary_set_uint64(dict, "iostart", iostart);
289: prop_dictionary_set_uint64(dict, "ioend", ioend);
290: prop_dictionary_set_uint64(dict, "memstart",
291: gtpci_mem_bs_tag->pbs_base);
292: prop_dictionary_set_uint64(dict, "memend",
293: gtpci_mem_bs_tag->pbs_limit - 1);
294: prop_dictionary_set_uint32(dict, "cache-line-size",
295: CACHELINESIZE);
296: }
297: #endif
1.1 garbled 298: if (device_is_a(dev, "atapibus") || device_is_a(dev, "pci") ||
299: device_is_a(dev, "scsibus") || device_is_a(dev, "atabus"))
300: return;
301:
302: if (device_is_a(device_parent(dev), "pci")) {
303: struct pci_attach_args *pa = aux;
304: prop_dictionary_t dict;
1.5 phx 305: prop_bool_t b;
1.3 garbled 306: int node;
307: char name[32];
1.1 garbled 308:
309: dict = device_properties(dev);
310: node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
311:
1.5 phx 312: /* enable configuration of irq 14/15 for VIA native IDE */
313: if (device_is_a(dev, "viaide") &&
314: strncmp(model_name, "Pegasos", 7) == 0) {
315: b = prop_bool_create(true);
316: KASSERT(b != NULL);
317: (void)prop_dictionary_set(dict,
318: "use-compat-native-irq", b);
319: prop_object_release(b);
320: }
321:
1.4 macallan 322: if (node != 0) {
1.6 aymeric 323: int pci_class = 0;
324:
1.3 garbled 325: prop_dictionary_set_uint32(dict, "device_node", node);
1.1 garbled 326:
1.5 phx 327: /* see if this is going to be console */
1.3 garbled 328: memset(name, 0, sizeof(name));
329: OF_getprop(node, "device_type", name, sizeof(name));
1.6 aymeric 330:
331: OF_getprop(node, "class-code", &pci_class,
332: sizeof pci_class);
333: pci_class = (pci_class >> 16) & 0xff;
334:
335: if (strcmp(name, "display") == 0 ||
1.8 macallan 336: strcmp(name, "ATY,DDParent") == 0 ||
337: pci_class == PCI_CLASS_DISPLAY) {
1.3 garbled 338: /* setup display properties for fb driver */
339: prop_dictionary_set_bool(dict, "is_console", 0);
340: copy_disp_props(dev, node, dict);
1.1 garbled 341: }
1.11 macallan 342: if (pci_class == PCI_CLASS_NETWORK) {
343: of_to_dataprop(dict, node, "local-mac-address",
344: "mac-address");
345: of_to_dataprop(dict, node, "shared-pins",
346: "shared-pins");
347: }
1.1 garbled 348: }
1.18 ! macallan 349: #ifdef macppc
! 350: /*
! 351: * XXX
! 352: * some macppc boxes have onboard devices where parts or all of
! 353: * the PCI_INTERRUPT register are hardwired to 0
! 354: */
! 355: if (pa->pa_intrpin == 0)
! 356: pa->pa_intrpin = 1;
! 357: #endif
1.3 garbled 358: }
1.1 garbled 359:
1.3 garbled 360: if (booted_device)
361: return;
1.1 garbled 362:
1.7 mrg 363: /*
364: * Skip over devices that are really just layers of NetBSD
365: * autoconf(9) we should just skip as they do not have any
366: * OFW devices.
367: */
1.1 garbled 368: if (device_is_a(device_parent(dev), "atapibus") ||
369: device_is_a(device_parent(dev), "atabus") ||
370: device_is_a(device_parent(dev), "pci") ||
371: device_is_a(device_parent(dev), "scsibus")) {
372: if (device_parent(device_parent(dev)) != parent)
373: return;
374: } else {
375: if (device_parent(dev) != parent)
376: return;
377: }
378:
1.7 mrg 379: /*
380: * Get the address part of the current path component. The
1.1 garbled 381: * last component of the canonical bootpath may have no
382: * address (eg, "disk"), in which case we need to get the
383: * address from the original bootpath instead.
384: */
385: p = strchr(cp, '@');
386: if (!p) {
387: if (bp)
388: p = strchr(bp, '@');
389: if (!p)
390: addr = 0;
1.7 mrg 391: else
392: addr = strtoul(p + 1, &p, 16);
1.1 garbled 393: } else
394: addr = strtoul(p + 1, &p, 16);
395:
1.7 mrg 396: /* if the current path has more address, grab that too */
397: if (p && *p == ',')
398: addr2 = strtoul(p + 1, &p, 16);
399: else
400: addr2 = 0;
401:
1.1 garbled 402: if (device_is_a(device_parent(dev), "mainbus")) {
403: struct confargs *ca = aux;
404:
405: if (strcmp(ca->ca_name, "ofw") == 0) /* XXX */
406: return;
1.12 kiyohara 407: if (strcmp(ca->ca_name, "gt") == 0)
408: parent = dev;
1.1 garbled 409: if (addr != ca->ca_reg[0])
410: return;
1.12 kiyohara 411: } else if (device_is_a(device_parent(dev), "gt")) {
412: /*
413: * Special handle for MV64361 on PegasosII(ofppc).
414: */
415: if (device_is_a(dev, "mvgbec")) {
416: /*
417: * Fix cp to /port@N from /ethernet/portN. (N is 0...2)
418: */
419: static char fix_cp[8] = "/port@N";
420:
421: if (strlen(cp) != 15 ||
422: strncmp(cp, "/ethernet/port", 14) != 0)
423: return;
424: fix_cp[7] = *(cp + 15);
425: p = fix_cp;
426: #if NGTPCI > 0
427: } else if (device_is_a(dev, "gtpci")) {
428: if (gtpci_mem_bs_tag != NULL &&
429: addr != gtpci_mem_bs_tag->pbs_base)
430: return;
431: #endif
432: } else
433: return;
1.1 garbled 434: } else if (device_is_a(device_parent(dev), "pci")) {
435: struct pci_attach_args *pa = aux;
436:
1.7 mrg 437: if (addr != pa->pa_device ||
438: addr2 != pa->pa_function)
1.1 garbled 439: return;
440: } else if (device_is_a(device_parent(dev), "obio")) {
441: struct confargs *ca = aux;
442:
443: if (addr != ca->ca_reg[0])
444: return;
445: } else if (device_is_a(device_parent(dev), "scsibus") ||
446: device_is_a(device_parent(dev), "atapibus")) {
447: struct scsipibus_attach_args *sa = aux;
448:
449: /* periph_target is target for scsi, drive # for atapi */
450: if (addr != sa->sa_periph->periph_target)
451: return;
1.7 mrg 452: } else if (device_is_a(device_parent(device_parent(dev)), "pciide") ||
453: device_is_a(device_parent(device_parent(dev)), "viaide") ||
454: device_is_a(device_parent(device_parent(dev)), "slide")) {
1.1 garbled 455: struct ata_device *adev = aux;
456:
1.7 mrg 457: if (addr != adev->adev_channel ||
458: addr2 != adev->adev_drv_data->drive)
1.1 garbled 459: return;
460: } else if (device_is_a(device_parent(device_parent(dev)), "wdc")) {
461: struct ata_device *adev = aux;
462:
463: if (addr != adev->adev_drv_data->drive)
464: return;
465: } else
466: return;
467:
468: /* If we reach this point, then dev is a match for the current
469: * path component.
470: */
471:
472: if (p && *p) {
473: parent = dev;
474: cp = p;
475: bp = strchr(bp, '/');
476: if (bp)
477: bp++;
478: return;
479: } else {
480: booted_device = dev;
481: booted_partition = 0; /* XXX -- should be extracted from bootpath */
482: return;
483: }
484: }
485:
486: /*
487: * Setup root device.
488: * Configure swap area.
489: */
490: void
1.10 cegger 491: cpu_rootconf(void)
1.1 garbled 492: {
493: printf("boot device: %s\n",
1.13 matt 494: booted_device ? device_xname(booted_device) : "<unknown>");
1.1 garbled 495:
1.17 mlelstv 496: rootconf();
1.1 garbled 497: }
498:
499: /*
500: * Find OF-device corresponding to the PCI device.
501: */
502: int
503: pcidev_to_ofdev(pci_chipset_tag_t pc, pcitag_t tag)
504: {
505: int bus, dev, func;
506: u_int reg[5];
507: int p, q;
508: int l, b, d, f;
509:
510: pci_decompose_tag(pc, tag, &bus, &dev, &func);
511:
512: for (q = OF_peer(0); q; q = p) {
513: l = OF_getprop(q, "assigned-addresses", reg, sizeof(reg));
514: if (l > 4) {
515: b = (reg[0] >> 16) & 0xff;
516: d = (reg[0] >> 11) & 0x1f;
517: f = (reg[0] >> 8) & 0x07;
518:
519: if (b == bus && d == dev && f == func)
520: return q;
521: }
522: if ((p = OF_child(q)))
523: continue;
524: while (q) {
525: if ((p = OF_peer(q)))
526: break;
527: q = OF_parent(q);
528: }
529: }
530: return 0;
531: }
CVSweb <webmaster@jp.NetBSD.org>