[BACK]Return to ofw_consinit.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / powerpc / oea

Annotation of src/sys/arch/powerpc/oea/ofw_consinit.c, Revision 1.6.14.2

1.6.14.1  mjf         1: /* $NetBSD$ */
1.2       garbled     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: #include <sys/cdefs.h>
1.6.14.1  mjf        33: __KERNEL_RCSID(0, "$NetBSD$");
1.2       garbled    34:
                     35: #include <sys/param.h>
                     36: #include <sys/buf.h>
                     37: #include <sys/tty.h>
                     38:
                     39: #include <machine/autoconf.h>
                     40: #include <machine/trap.h>
                     41: #include <machine/bus.h>
                     42:
                     43: #include <powerpc/ofw_cons.h>
                     44:
                     45: #include <dev/cons.h>
                     46: #include <dev/ofw/openfirm.h>
                     47:
                     48: #include <dev/wscons/wsksymvar.h>
                     49: #include <dev/wscons/wscons_callbacks.h>
                     50:
                     51: #include <machine/stdarg.h>
                     52:
                     53: #include "akbd.h"
                     54: #include "adbkbd.h"
1.5       macallan   55: #include "wsdisplay.h"
1.2       garbled    56: #include "ofb.h"
                     57: #include "isa.h"
                     58:
                     59: #include "zsc.h"
                     60: #if NZSC > 0
                     61: #include <machine/z8530var.h>
                     62: #endif
                     63:
                     64: #include "adb.h"
                     65: #if (NADB > 0)
                     66: #include <macppc/dev/adbvar.h>
                     67: #endif
                     68:
                     69: #include "ukbd.h"
                     70: #if (NUKBD > 0)
                     71: #include <dev/usb/ukbdvar.h>
                     72: struct usb_kbd_ihandles {
                     73:        struct usb_kbd_ihandles *next;
                     74:        int ihandle;
                     75: };
                     76: #endif
                     77:
                     78: #include "zstty.h"
                     79: #if (NZSTTY > 0)
                     80: #include <dev/ic/z8530reg.h>
                     81: extern struct consdev consdev_zs;
                     82: #endif
                     83:
                     84: #include "pckbc.h"
                     85: #if (NPCKBC > 0)
                     86: #include <dev/isa/isareg.h>
                     87: #include <dev/ic/i8042reg.h>
                     88: #include <dev/ic/pckbcvar.h>
                     89: #endif
                     90:
                     91: extern int console_node, console_instance;
                     92:
1.3       garbled    93: int chosen, stdin, stdout;
1.2       garbled    94: int ofkbd_ihandle;
                     95:
                     96: static void cninit_kd(void);
                     97: static void ofwoea_bootstrap_console(void);
1.3       garbled    98: static int ofwbootcons_cngetc(dev_t);
                     99: static void ofwbootcons_cnputc(dev_t, int);
1.2       garbled   100:
                    101: /*#define OFDEBUG*/
                    102:
1.3       garbled   103: struct consdev consdev_ofwbootcons = {
                    104:        NULL, NULL,
                    105:        ofwbootcons_cngetc,
                    106:        ofwbootcons_cnputc,
                    107:        nullcnpollc,
                    108:        NULL, NULL, NULL, NODEV, CN_INTERNAL,
                    109: };
                    110:
1.2       garbled   111: #ifdef OFDEBUG
                    112: void ofprint(const char *, ...);
                    113:
                    114: void ofprint(const char *blah, ...)
                    115: {
                    116:        va_list va;
                    117:        char buf[256];
                    118:        int len;
                    119:
                    120:        va_start(va, blah);
                    121:        len = vsnprintf(buf, sizeof(buf), blah, va);
                    122:        OF_write(console_instance, buf, len);
                    123: }
                    124:
                    125: #define OFPRINTF ofprint
                    126: #else
                    127: #define OFPRINTF while(0) printf
                    128: #endif
                    129:
                    130: void
                    131: cninit(void)
                    132: {
1.6       garbled   133:        char name[32];
1.2       garbled   134:
                    135:        ofwoea_bootstrap_console();
                    136:
                    137:        OFPRINTF("console node: %08x\n", console_node);
                    138:
                    139:        if (console_node == -1)
                    140:                goto nocons;
                    141:
1.6       garbled   142:        memset(name, 0, sizeof(name));
                    143:        if (OF_getprop(console_node, "device_type", name, sizeof(name)) == -1)
1.2       garbled   144:                goto nocons;
                    145:
1.6       garbled   146:        OFPRINTF("console type: %s\n", name);
1.2       garbled   147:
1.6       garbled   148:        if (strcmp(name, "serial") == 0) {
1.2       garbled   149:                struct consdev *cp;
                    150:
1.3       garbled   151: #ifdef PMAC_G5
1.2       garbled   152:                /* The MMU hasn't been initialized yet, use failsafe for now */
                    153:                cp = &failsafe_cons;
                    154:                cn_tab = cp;
                    155:                (*cp->cn_probe)(cp);
                    156:                (*cp->cn_init)(cp);
                    157:                aprint_verbose("Early G5 console initialized\n");
1.3       garbled   158:                return;
                    159: #endif /* PMAC_G5 */
                    160:
                    161: #if (NZSTTY > 0) && !defined(MAMBO)
1.2       garbled   162:                OF_getprop(console_node, "name", name, sizeof(name));
                    163:                if (strcmp(name, "ch-a") == 0 || strcmp(name, "ch-b") == 0) {
                    164:                        cp = &consdev_zs;
                    165:                        (*cp->cn_probe)(cp);
                    166:                        (*cp->cn_init)(cp);
                    167:                        cn_tab = cp;
                    168:                }
                    169:                return;
                    170: #endif /* NZTTY */
                    171:
1.6       garbled   172:                /* fallback to OFW boot console */
                    173:                cp = &consdev_ofwbootcons;
                    174:                cn_tab = cp;
1.2       garbled   175:                return;
                    176:        }
1.6       garbled   177:        else
                    178:                cninit_kd();
1.2       garbled   179: nocons:
                    180:        return;
                    181: }
                    182:
                    183:
                    184: static void
                    185: cninit_kd(void)
                    186: {
1.3       garbled   187:        int kstdin, node;
1.2       garbled   188:        char name[16];
                    189: #if (NAKBD > 0) || (NADBKBD > 0)
                    190:        int akbd;
                    191: #endif
                    192: #if NUKBD > 0
                    193:        struct usb_kbd_ihandles *ukbds;
                    194:        int ukbd;
                    195: #endif
                    196:
                    197:        /*
                    198:         * Attach the console output now (so we can see debugging messages,
                    199:         * if any).
                    200:         */
1.5       macallan  201: #if NWSDISPLAY > 0
1.6       garbled   202:        rascons_cnattach();
1.4       garbled   203: #endif
1.2       garbled   204:
                    205:        /*
                    206:         * We must determine which keyboard type we have.
                    207:         */
1.3       garbled   208:        if (OF_getprop(chosen, "stdin", &kstdin, sizeof(kstdin))
                    209:            != sizeof(kstdin)) {
1.2       garbled   210:                printf("WARNING: no `stdin' property in /chosen\n");
                    211:                return;
                    212:        }
                    213:
1.3       garbled   214:        node = OF_instance_to_package(kstdin);
1.2       garbled   215:        memset(name, 0, sizeof(name));
                    216:        OF_getprop(node, "name", name, sizeof(name));
                    217:        if (strcmp(name, "keyboard") != 0) {
                    218:                printf("WARNING: stdin is not a keyboard: %s\n", name);
                    219:                return;
                    220:        }
                    221:
                    222: #if NAKBD > 0
                    223:        memset(name, 0, sizeof(name));
                    224:        OF_getprop(OF_parent(node), "name", name, sizeof(name));
                    225:        if (strcmp(name, "adb") == 0) {
                    226:                printf("console keyboard type: ADB\n");
                    227:                akbd_cnattach();
                    228:                goto kbd_found;
                    229:        }
                    230: #endif
                    231: #if NADBKBD > 0
                    232:        memset(name, 0, sizeof(name));
                    233:        OF_getprop(OF_parent(node), "name", name, sizeof(name));
                    234:        if (strcmp(name, "adb") == 0) {
                    235:                printf("console keyboard type: ADB\n");
                    236:                adbkbd_cnattach();
                    237:                goto kbd_found;
                    238:        }
                    239: #endif
                    240: #if NPCKBC > 0
                    241:        memset(name, 0, sizeof(name));
                    242:        OF_getprop(OF_parent(node), "name", name, sizeof(name));
                    243:        if (strcmp(name, "keyboard") == 0) {
                    244:                printf("console keyboard type: PC Keyboard\n");
                    245:                pckbc_cnattach(&genppc_isa_io_space_tag, IO_KBD, KBCMDP,
                    246:                    PCKBC_KBD_SLOT);
                    247:                goto kbd_found;
                    248:        }
                    249: #endif
                    250:
                    251:        /*
                    252:         * It is not obviously an ADB/PC keyboard. Could be USB,
                    253:         * or ADB on some firmware versions (e.g.: iBook G4)
                    254:         * This is not enough, we have a few more problems:
                    255:         *
                    256:         *      (1) The stupid Macintosh firmware uses a
                    257:         *          `psuedo-hid' (no typo) or `pseudo-hid',
                    258:         *          which apparently merges all keyboards
                    259:         *          input into a single input stream.
                    260:         *          Because of this, we can't actually
                    261:         *          determine which controller or keyboard
                    262:         *          is really the console keyboard!
                    263:         *
                    264:         *      (2) Even if we could, the keyboard can be USB,
                    265:         *          and this requires a lot of the kernel to
                    266:         *          be running in order for it to work.
                    267:         *
                    268:         *      (3) If the keyboard is behind isa, we don't have enough
                    269:         *          kernel setup to use it yet, so punt to the ofroutines.
                    270:         *
                    271:         * So, what we do is this:
                    272:         *
                    273:         *      (1) First check for OpenFirmware implementation
                    274:         *          that will not let us distinguish between
                    275:         *          USB and ADB. In that situation, try attaching
                    276:         *          anything as we can, and hope things get better
                    277:         *          at autoconfiguration time.
                    278:         *
                    279:         *      (2) Assume the keyboard is USB.
                    280:         *          Tell the ukbd driver that it is the console.
                    281:         *          At autoconfiguration time, it will attach the
                    282:         *          first USB keyboard instance as the console
                    283:         *          keyboard.
                    284:         *
                    285:         *      (3) Until then, so that we have _something_, we
                    286:         *          use the OpenFirmware I/O facilities to read
                    287:         *          the keyboard.
                    288:         */
                    289:
                    290:        /*
                    291:         * stdin is /pseudo-hid/keyboard.  There is no
                    292:         * `adb-kbd-ihandle or `usb-kbd-ihandles methods
                    293:         * available. Try attaching as ADB.
1.6.14.2! mjf       294:         * But only if ADB support is actually present.
1.2       garbled   295:         *
                    296:         * XXX This must be called before pmap_bootstrap().
                    297:         */
                    298:        if (strcmp(name, "pseudo-hid") == 0) {
1.6.14.2! mjf       299:                int adb_node;
        !           300:
        !           301:                adb_node = OF_finddevice("/pci/mac-io/via-pmu/adb");
        !           302:                if (adb_node > 0) {
        !           303:                        printf("ADB support found\n");
1.2       garbled   304: #if NAKBD > 0
1.6.14.2! mjf       305:                        akbd_cnattach();
1.2       garbled   306: #endif
                    307: #if NADBKBD > 0
1.6.14.2! mjf       308:                        adbkbd_cnattach();
        !           309: #endif
        !           310:                } else {
        !           311:                        /* must be USB */
        !           312:                        printf("No ADB support present, assuming USB "
        !           313:                               "keyboard\n");
        !           314: #if NUKBD > 0
        !           315:                        ukbd_cnattach();
1.2       garbled   316: #endif
1.6.14.2! mjf       317:                }
1.2       garbled   318:                goto kbd_found;
                    319:        }
                    320:
                    321:        /*
                    322:         * stdin is /psuedo-hid/keyboard.  Test `adb-kbd-ihandle and
                    323:         * `usb-kbd-ihandles to figure out the real keyboard(s).
                    324:         *
                    325:         * XXX This must be called before pmap_bootstrap().
                    326:         */
                    327:
                    328: #if NUKBD > 0
                    329:        if (OF_call_method("`usb-kbd-ihandles", stdin, 0, 1, &ukbds) >= 0 &&
                    330:            ukbds != NULL && ukbds->ihandle != 0 &&
                    331:            OF_instance_to_package(ukbds->ihandle) != -1) {
                    332:                printf("usb-kbd-ihandles matches\n");
                    333:                printf("console keyboard type: USB\n");
                    334:                ukbd_cnattach();
                    335:                goto kbd_found;
                    336:        }
                    337:        /* Try old method name. */
1.3       garbled   338:        if (OF_call_method("`usb-kbd-ihandle", kstdin, 0, 1, &ukbd) >= 0 &&
1.2       garbled   339:            ukbd != 0 &&
                    340:            OF_instance_to_package(ukbd) != -1) {
                    341:                printf("usb-kbd-ihandle matches\n");
                    342:                printf("console keyboard type: USB\n");
1.3       garbled   343:                kstdin = ukbd;
1.2       garbled   344:                ukbd_cnattach();
                    345:                goto kbd_found;
                    346:        }
                    347: #endif
                    348:
                    349: #if (NAKBD > 0) || (NADBKBD > 0)
1.3       garbled   350:        if (OF_call_method("`adb-kbd-ihandle", kstdin, 0, 1, &akbd) >= 0 &&
1.2       garbled   351:            akbd != 0 &&
                    352:            OF_instance_to_package(akbd) != -1) {
                    353:                printf("adb-kbd-ihandle matches\n");
                    354:                printf("console keyboard type: ADB\n");
1.3       garbled   355:                kstdin = akbd;
1.2       garbled   356: #if NAKBD > 0
                    357:                akbd_cnattach();
                    358: #endif
                    359: #if NADBKBD > 0
                    360:                adbkbd_cnattach();
                    361: #endif
                    362:                goto kbd_found;
                    363:        }
                    364: #endif
                    365:
                    366: #if NUKBD > 0
                    367:        /*
                    368:         * XXX Old firmware does not have `usb-kbd-ihandles method.  Assume
                    369:         * XXX USB keyboard anyway.
                    370:         */
                    371:        printf("defaulting to USB...");
                    372:        printf("console keyboard type: USB\n");
                    373:        ukbd_cnattach();
                    374:        goto kbd_found;
                    375: #endif
                    376:
                    377:        /*
                    378:         * No keyboard is found.  Just return.
                    379:         */
                    380:        printf("no console keyboard\n");
                    381:        return;
                    382:
                    383: kbd_found:;
1.6.14.2! mjf       384: #if NAKBD + NUKBD + NADBKBD + NPCKBC > 0
1.2       garbled   385:        /*
                    386:         * XXX This is a little gross, but we don't get to call
                    387:         * XXX wskbd_cnattach() twice.
                    388:         */
1.3       garbled   389:        ofkbd_ihandle = kstdin;
1.2       garbled   390: #if NWSDISPLAY > 0
                    391:        wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL);
                    392: #endif
                    393: #endif
                    394: }
                    395:
                    396: /*
                    397:  * Bootstrap console keyboard routines, using OpenFirmware I/O.
                    398:  */
                    399: int
                    400: ofkbd_cngetc(dev_t dev)
                    401: {
                    402:        u_char c = '\0';
                    403:        int len;
                    404:
                    405:        do {
                    406:                len = OF_read(ofkbd_ihandle, &c, 1);
                    407:        } while (len != 1);
                    408:
                    409:        return c;
                    410: }
                    411:
1.3       garbled   412: /*
                    413:  * Bootstrap console support functions
                    414:  */
                    415:
                    416: static int
                    417: ofwbootcons_cngetc(dev_t dev)
                    418: {
                    419:        unsigned char ch = '\0';
                    420:        int l;
                    421:
                    422:        while ((l = OF_read(stdin, &ch, 1)) != 1)
                    423:                if (l != -2 && l != 0)
                    424:                        return -1;
                    425:        return ch;
                    426: }
                    427:
                    428: static void
                    429: ofwbootcons_cnputc(dev_t dev, int c)
                    430: {
                    431:        char ch = c;
                    432:
                    433:        OF_write(stdout, &ch, 1);
                    434: }
                    435:
1.2       garbled   436: void
                    437: ofwoea_consinit(void)
                    438: {
                    439:        static int initted = 0;
                    440:
                    441:        if (initted)
                    442:                return;
                    443:
                    444:        initted = 1;
                    445:        cninit();
                    446: }
                    447:
                    448: static void
                    449: ofwoea_bootstrap_console(void)
                    450: {
1.3       garbled   451:        int node;
1.2       garbled   452:
                    453:        chosen = OF_finddevice("/chosen");
                    454:        if (chosen == -1)
                    455:                goto nocons;
                    456:
                    457:        if (OF_getprop(chosen, "stdout", &stdout,
                    458:            sizeof(stdout)) != sizeof(stdout))
                    459:                goto nocons;
1.3       garbled   460:        if (OF_getprop(chosen, "stdin", &stdin,
                    461:            sizeof(stdin)) != sizeof(stdin))
                    462:                goto nocons;
1.2       garbled   463:        node = OF_instance_to_package(stdout);
                    464:        console_node = node;
                    465:        console_instance = stdout;
                    466:
                    467:        return;
                    468: nocons:
                    469:        panic("No /chosen could be found!\n");
                    470:        console_node = -1;
                    471:        return;
                    472: }

CVSweb <webmaster@jp.NetBSD.org>