Annotation of src/sys/arch/powerpc/oea/ofw_consinit.c, Revision 1.2
1.2 ! garbled 1: /* $NetBSD: ofw_consinit.c,v 1.1.2.3 2007/06/21 18:19:47 garbled 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: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed by the NetBSD
! 21: * Foundation, Inc. and its contributors.
! 22: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 23: * contributors may be used to endorse or promote products derived
! 24: * from this software without specific prior written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 36: * POSSIBILITY OF SUCH DAMAGE.
! 37: */
! 38:
! 39: #include <sys/cdefs.h>
! 40: __KERNEL_RCSID(0, "$NetBSD: ofw_consinit.c,v 1.1.2.3 2007/06/21 18:19:47 garbled Exp $");
! 41:
! 42: #include <sys/param.h>
! 43: #include <sys/buf.h>
! 44: #include <sys/tty.h>
! 45:
! 46: #include <machine/autoconf.h>
! 47: #include <machine/trap.h>
! 48: #include <machine/bus.h>
! 49:
! 50: #include <powerpc/ofw_cons.h>
! 51:
! 52: #include <dev/cons.h>
! 53: #include <dev/ofw/openfirm.h>
! 54:
! 55: #include <dev/wscons/wsksymvar.h>
! 56: #include <dev/wscons/wscons_callbacks.h>
! 57:
! 58: #include <machine/stdarg.h>
! 59:
! 60: #include "akbd.h"
! 61: #include "adbkbd.h"
! 62: #include "ofb.h"
! 63: #include "isa.h"
! 64:
! 65: #include "zsc.h"
! 66: #if NZSC > 0
! 67: #include <machine/z8530var.h>
! 68: #endif
! 69:
! 70: #include "adb.h"
! 71: #if (NADB > 0)
! 72: #include <macppc/dev/adbvar.h>
! 73: #endif
! 74:
! 75: #include "ukbd.h"
! 76: #if (NUKBD > 0)
! 77: #include <dev/usb/ukbdvar.h>
! 78: struct usb_kbd_ihandles {
! 79: struct usb_kbd_ihandles *next;
! 80: int ihandle;
! 81: };
! 82: #endif
! 83:
! 84: #include "zstty.h"
! 85: #if (NZSTTY > 0)
! 86: #include <dev/ic/z8530reg.h>
! 87: extern struct consdev consdev_zs;
! 88: #endif
! 89:
! 90: #include "pckbc.h"
! 91: #if (NPCKBC > 0)
! 92: #include <dev/isa/isareg.h>
! 93: #include <dev/ic/i8042reg.h>
! 94: #include <dev/ic/pckbcvar.h>
! 95: #endif
! 96:
! 97: #include "com.h"
! 98: #if (NCOM > 0)
! 99: #include <sys/termios.h>
! 100: #include <dev/ic/comreg.h>
! 101: #include <dev/ic/comvar.h>
! 102: #endif
! 103:
! 104: extern int console_node, console_instance;
! 105: extern struct consdev consdev_ofcons;
! 106:
! 107: int chosen;
! 108: int ofkbd_ihandle;
! 109:
! 110: static void cninit_kd(void);
! 111: static void ofwoea_bootstrap_console(void);
! 112:
! 113: /*#define OFDEBUG*/
! 114:
! 115: #ifdef OFDEBUG
! 116: void ofprint(const char *, ...);
! 117:
! 118: void ofprint(const char *blah, ...)
! 119: {
! 120: va_list va;
! 121: char buf[256];
! 122: int len;
! 123:
! 124: va_start(va, blah);
! 125: len = vsnprintf(buf, sizeof(buf), blah, va);
! 126: OF_write(console_instance, buf, len);
! 127: }
! 128:
! 129: #define OFPRINTF ofprint
! 130: #else
! 131: #define OFPRINTF while(0) printf
! 132: #endif
! 133:
! 134: void
! 135: cninit(void)
! 136: {
! 137: char type[16];
! 138:
! 139: ofwoea_bootstrap_console();
! 140:
! 141: OFPRINTF("console node: %08x\n", console_node);
! 142:
! 143: if (console_node == -1)
! 144: goto nocons;
! 145:
! 146: memset(type, 0, sizeof(type));
! 147: if (OF_getprop(console_node, "device_type", type, sizeof(type)) == -1)
! 148: goto nocons;
! 149:
! 150: OFPRINTF("console type: %s\n", type);
! 151: if (strcmp(type, "display") == 0) {
! 152: cninit_kd();
! 153: return;
! 154: }
! 155:
! 156: if (strcmp(type, "serial") == 0) {
! 157: #if defined(PMAC_G5) || defined (MAMBO) || NZSTTY > 0 || NCOM > 0
! 158: struct consdev *cp;
! 159: #endif
! 160: char name[32];
! 161:
! 162: #if defined(PMAC_G5)
! 163: /* The MMU hasn't been initialized yet, use failsafe for now */
! 164: cp = &failsafe_cons;
! 165: cn_tab = cp;
! 166: (*cp->cn_probe)(cp);
! 167: (*cp->cn_init)(cp);
! 168: aprint_verbose("Early G5 console initialized\n");
! 169: #elif defined(MAMBO)
! 170: goto fallback;
! 171: #else
! 172: OF_getprop(console_node, "name", name, sizeof(name));
! 173: #if NZSTTY > 0
! 174: if (strcmp(name, "ch-a") == 0 || strcmp(name, "ch-b") == 0) {
! 175: cp = &consdev_zs;
! 176: (*cp->cn_probe)(cp);
! 177: (*cp->cn_init)(cp);
! 178: cn_tab = cp;
! 179: }
! 180: return;
! 181: #endif /* NZTTY */
! 182: #if (NCOM > 0 && NISA > 0)
! 183: if (strcmp(name, "serial") == 0) {
! 184: bus_space_tag_t tag = &genppc_isa_io_space_tag;
! 185: u_int32_t freq, reg[3];
! 186:
! 187: if (OF_getprop(console_node, "clock-frequency", &freq,
! 188: sizeof(freq)) != sizeof(freq))
! 189: goto fallback;
! 190: if (OF_getprop(console_node, "reg", reg, sizeof(reg))
! 191: != sizeof(reg))
! 192: goto fallback;
! 193:
! 194: /* We assume 9600. Sorry. */
! 195: if (comcnattach(tag, reg[1], 9600,
! 196: freq, COM_TYPE_NORMAL,
! 197: ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
! 198: goto fallback;
! 199: }
! 200: #endif /* NCOM */
! 201: #endif /* MAMBO || PMACG5 */
! 202: #if 0
! 203: #if (NCOM > 0 || MAMBO)
! 204: fallback:
! 205: /* fallback to ofcons */
! 206: if (strcmp(name, "serial") == 0) {
! 207: cp = &consdev_ofcons;
! 208: cn_tab = cp;
! 209: (*cp->cn_probe)(cp);
! 210: (*cp->cn_init)(cp);
! 211: }
! 212: return;
! 213: #endif
! 214: #endif
! 215: }
! 216: nocons:
! 217: return;
! 218: }
! 219:
! 220:
! 221: static void
! 222: cninit_kd(void)
! 223: {
! 224: int stdin, node;
! 225: char name[16];
! 226: #if (NAKBD > 0) || (NADBKBD > 0)
! 227: int akbd;
! 228: #endif
! 229: #if NUKBD > 0
! 230: struct usb_kbd_ihandles *ukbds;
! 231: int ukbd;
! 232: #endif
! 233:
! 234: /*
! 235: * Attach the console output now (so we can see debugging messages,
! 236: * if any).
! 237: */
! 238: ofb_cnattach();
! 239:
! 240: /*
! 241: * We must determine which keyboard type we have.
! 242: */
! 243: if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin))
! 244: != sizeof(stdin)) {
! 245: printf("WARNING: no `stdin' property in /chosen\n");
! 246: return;
! 247: }
! 248:
! 249: node = OF_instance_to_package(stdin);
! 250: memset(name, 0, sizeof(name));
! 251: OF_getprop(node, "name", name, sizeof(name));
! 252: if (strcmp(name, "keyboard") != 0) {
! 253: printf("WARNING: stdin is not a keyboard: %s\n", name);
! 254: return;
! 255: }
! 256:
! 257: #if NAKBD > 0
! 258: memset(name, 0, sizeof(name));
! 259: OF_getprop(OF_parent(node), "name", name, sizeof(name));
! 260: if (strcmp(name, "adb") == 0) {
! 261: printf("console keyboard type: ADB\n");
! 262: akbd_cnattach();
! 263: goto kbd_found;
! 264: }
! 265: #endif
! 266: #if NADBKBD > 0
! 267: memset(name, 0, sizeof(name));
! 268: OF_getprop(OF_parent(node), "name", name, sizeof(name));
! 269: if (strcmp(name, "adb") == 0) {
! 270: printf("console keyboard type: ADB\n");
! 271: adbkbd_cnattach();
! 272: goto kbd_found;
! 273: }
! 274: #endif
! 275: #if NPCKBC > 0
! 276: memset(name, 0, sizeof(name));
! 277: OF_getprop(OF_parent(node), "name", name, sizeof(name));
! 278: if (strcmp(name, "keyboard") == 0) {
! 279: printf("console keyboard type: PC Keyboard\n");
! 280: pckbc_cnattach(&genppc_isa_io_space_tag, IO_KBD, KBCMDP,
! 281: PCKBC_KBD_SLOT);
! 282: goto kbd_found;
! 283: }
! 284: #endif
! 285:
! 286: /*
! 287: * It is not obviously an ADB/PC keyboard. Could be USB,
! 288: * or ADB on some firmware versions (e.g.: iBook G4)
! 289: * This is not enough, we have a few more problems:
! 290: *
! 291: * (1) The stupid Macintosh firmware uses a
! 292: * `psuedo-hid' (no typo) or `pseudo-hid',
! 293: * which apparently merges all keyboards
! 294: * input into a single input stream.
! 295: * Because of this, we can't actually
! 296: * determine which controller or keyboard
! 297: * is really the console keyboard!
! 298: *
! 299: * (2) Even if we could, the keyboard can be USB,
! 300: * and this requires a lot of the kernel to
! 301: * be running in order for it to work.
! 302: *
! 303: * (3) If the keyboard is behind isa, we don't have enough
! 304: * kernel setup to use it yet, so punt to the ofroutines.
! 305: *
! 306: * So, what we do is this:
! 307: *
! 308: * (1) First check for OpenFirmware implementation
! 309: * that will not let us distinguish between
! 310: * USB and ADB. In that situation, try attaching
! 311: * anything as we can, and hope things get better
! 312: * at autoconfiguration time.
! 313: *
! 314: * (2) Assume the keyboard is USB.
! 315: * Tell the ukbd driver that it is the console.
! 316: * At autoconfiguration time, it will attach the
! 317: * first USB keyboard instance as the console
! 318: * keyboard.
! 319: *
! 320: * (3) Until then, so that we have _something_, we
! 321: * use the OpenFirmware I/O facilities to read
! 322: * the keyboard.
! 323: */
! 324:
! 325: /*
! 326: * stdin is /pseudo-hid/keyboard. There is no
! 327: * `adb-kbd-ihandle or `usb-kbd-ihandles methods
! 328: * available. Try attaching as ADB.
! 329: *
! 330: * XXX This must be called before pmap_bootstrap().
! 331: */
! 332: if (strcmp(name, "pseudo-hid") == 0) {
! 333: printf("console keyboard type: unknown, assuming ADB\n");
! 334: #if NAKBD > 0
! 335: akbd_cnattach();
! 336: #endif
! 337: #if NADBKBD > 0
! 338: adbkbd_cnattach();
! 339: #endif
! 340: goto kbd_found;
! 341: }
! 342:
! 343: /*
! 344: * stdin is /psuedo-hid/keyboard. Test `adb-kbd-ihandle and
! 345: * `usb-kbd-ihandles to figure out the real keyboard(s).
! 346: *
! 347: * XXX This must be called before pmap_bootstrap().
! 348: */
! 349:
! 350: #if NUKBD > 0
! 351: if (OF_call_method("`usb-kbd-ihandles", stdin, 0, 1, &ukbds) >= 0 &&
! 352: ukbds != NULL && ukbds->ihandle != 0 &&
! 353: OF_instance_to_package(ukbds->ihandle) != -1) {
! 354: printf("usb-kbd-ihandles matches\n");
! 355: printf("console keyboard type: USB\n");
! 356: ukbd_cnattach();
! 357: goto kbd_found;
! 358: }
! 359: /* Try old method name. */
! 360: if (OF_call_method("`usb-kbd-ihandle", stdin, 0, 1, &ukbd) >= 0 &&
! 361: ukbd != 0 &&
! 362: OF_instance_to_package(ukbd) != -1) {
! 363: printf("usb-kbd-ihandle matches\n");
! 364: printf("console keyboard type: USB\n");
! 365: stdin = ukbd;
! 366: ukbd_cnattach();
! 367: goto kbd_found;
! 368: }
! 369: #endif
! 370:
! 371: #if (NAKBD > 0) || (NADBKBD > 0)
! 372: if (OF_call_method("`adb-kbd-ihandle", stdin, 0, 1, &akbd) >= 0 &&
! 373: akbd != 0 &&
! 374: OF_instance_to_package(akbd) != -1) {
! 375: printf("adb-kbd-ihandle matches\n");
! 376: printf("console keyboard type: ADB\n");
! 377: stdin = akbd;
! 378: #if NAKBD > 0
! 379: akbd_cnattach();
! 380: #endif
! 381: #if NADBKBD > 0
! 382: adbkbd_cnattach();
! 383: #endif
! 384: goto kbd_found;
! 385: }
! 386: #endif
! 387:
! 388: #if NUKBD > 0
! 389: /*
! 390: * XXX Old firmware does not have `usb-kbd-ihandles method. Assume
! 391: * XXX USB keyboard anyway.
! 392: */
! 393: printf("defaulting to USB...");
! 394: printf("console keyboard type: USB\n");
! 395: ukbd_cnattach();
! 396: goto kbd_found;
! 397: #endif
! 398:
! 399: /*
! 400: * No keyboard is found. Just return.
! 401: */
! 402: printf("no console keyboard\n");
! 403: return;
! 404:
! 405: kbd_found:;
! 406: #if NAKBD + NUKBD + NADBKBD > 0
! 407: /*
! 408: * XXX This is a little gross, but we don't get to call
! 409: * XXX wskbd_cnattach() twice.
! 410: */
! 411: ofkbd_ihandle = stdin;
! 412: #if NWSDISPLAY > 0
! 413: wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL);
! 414: #endif
! 415: #endif
! 416: }
! 417:
! 418: /*
! 419: * Bootstrap console keyboard routines, using OpenFirmware I/O.
! 420: */
! 421: int
! 422: ofkbd_cngetc(dev_t dev)
! 423: {
! 424: u_char c = '\0';
! 425: int len;
! 426:
! 427: do {
! 428: len = OF_read(ofkbd_ihandle, &c, 1);
! 429: } while (len != 1);
! 430:
! 431: return c;
! 432: }
! 433:
! 434: void
! 435: ofwoea_consinit(void)
! 436: {
! 437: static int initted = 0;
! 438:
! 439: if (initted)
! 440: return;
! 441:
! 442: initted = 1;
! 443: cninit();
! 444: }
! 445:
! 446: static void
! 447: ofwoea_bootstrap_console(void)
! 448: {
! 449: int stdout, node;
! 450:
! 451: chosen = OF_finddevice("/chosen");
! 452: if (chosen == -1)
! 453: goto nocons;
! 454:
! 455: if (OF_getprop(chosen, "stdout", &stdout,
! 456: sizeof(stdout)) != sizeof(stdout))
! 457: goto nocons;
! 458: node = OF_instance_to_package(stdout);
! 459: console_node = node;
! 460: console_instance = stdout;
! 461:
! 462: return;
! 463: nocons:
! 464: panic("No /chosen could be found!\n");
! 465: console_node = -1;
! 466: return;
! 467: }
CVSweb <webmaster@jp.NetBSD.org>