[BACK]Return to pckbd.c CVS log [TXT][DIR] Up to [local] / sys / dev / pckbc

Annotation of sys/dev/pckbc/pckbd.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: pckbd.c,v 1.9 2007/01/30 20:45:05 jcs Exp $ */
        !             2: /* $NetBSD: pckbd.c,v 1.24 2000/06/05 22:20:57 sommerfeld Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Charles M. Hannum.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*-
        !            41:  * Copyright (c) 1990 The Regents of the University of California.
        !            42:  * All rights reserved.
        !            43:  *
        !            44:  * This code is derived from software contributed to Berkeley by
        !            45:  * William Jolitz and Don Ahn.
        !            46:  *
        !            47:  * Redistribution and use in source and binary forms, with or without
        !            48:  * modification, are permitted provided that the following conditions
        !            49:  * are met:
        !            50:  * 1. Redistributions of source code must retain the above copyright
        !            51:  *    notice, this list of conditions and the following disclaimer.
        !            52:  * 2. Redistributions in binary form must reproduce the above copyright
        !            53:  *    notice, this list of conditions and the following disclaimer in the
        !            54:  *    documentation and/or other materials provided with the distribution.
        !            55:  * 3. Neither the name of the University nor the names of its contributors
        !            56:  *    may be used to endorse or promote products derived from this software
        !            57:  *    without specific prior written permission.
        !            58:  *
        !            59:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            60:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            61:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            62:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            63:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            64:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            65:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            66:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            67:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            68:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            69:  * SUCH DAMAGE.
        !            70:  *
        !            71:  *     @(#)pccons.c    5.11 (Berkeley) 5/21/91
        !            72:  */
        !            73:
        !            74: /*
        !            75:  * code to work keyboard for PC-style console
        !            76:  */
        !            77:
        !            78: #include <sys/param.h>
        !            79: #include <sys/systm.h>
        !            80: #include <sys/device.h>
        !            81: #include <sys/malloc.h>
        !            82: #include <sys/ioctl.h>
        !            83:
        !            84: #include <machine/bus.h>
        !            85:
        !            86: #ifndef __sparc64__
        !            87: #include <dev/isa/isavar.h>            /* XXX XXX XXX */
        !            88: #endif
        !            89:
        !            90: #include <dev/ic/pckbcvar.h>
        !            91:
        !            92: #include <dev/pckbc/pckbdreg.h>
        !            93: #include <dev/pckbc/pckbdvar.h>
        !            94: #include <dev/pckbc/wskbdmap_mfii.h>
        !            95:
        !            96: #include <dev/wscons/wsconsio.h>
        !            97: #include <dev/wscons/wskbdvar.h>
        !            98: #include <dev/wscons/wsksymdef.h>
        !            99: #include <dev/wscons/wsksymvar.h>
        !           100:
        !           101: #if defined(__i386__) || defined(__alpha__)
        !           102: #include <sys/kernel.h> /* XXX for hz */
        !           103: #endif
        !           104:
        !           105: struct pckbd_internal {
        !           106:        int t_isconsole;
        !           107:        pckbc_tag_t t_kbctag;
        !           108:        pckbc_slot_t t_kbcslot;
        !           109:
        !           110:        int t_lastchar;
        !           111:        int t_extended;
        !           112:        int t_extended1;
        !           113:
        !           114:        struct pckbd_softc *t_sc; /* back pointer */
        !           115: };
        !           116:
        !           117: struct pckbd_softc {
        !           118:         struct  device sc_dev;
        !           119:
        !           120:        struct pckbd_internal *id;
        !           121:        int sc_enabled;
        !           122:
        !           123:        int sc_ledstate;
        !           124:
        !           125:        struct device *sc_wskbddev;
        !           126: #ifdef WSDISPLAY_COMPAT_RAWKBD
        !           127:        int rawkbd;
        !           128: #endif
        !           129: };
        !           130:
        !           131: static int pckbd_is_console(pckbc_tag_t, pckbc_slot_t);
        !           132:
        !           133: int pckbdprobe(struct device *, void *, void *);
        !           134: void pckbdattach(struct device *, struct device *, void *);
        !           135:
        !           136: struct cfattach pckbd_ca = {
        !           137:        sizeof(struct pckbd_softc), pckbdprobe, pckbdattach,
        !           138: };
        !           139:
        !           140: int    pckbd_enable(void *, int);
        !           141: void   pckbd_set_leds(void *, int);
        !           142: int    pckbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
        !           143:
        !           144: const struct wskbd_accessops pckbd_accessops = {
        !           145:        pckbd_enable,
        !           146:        pckbd_set_leds,
        !           147:        pckbd_ioctl,
        !           148: };
        !           149:
        !           150: void   pckbd_cngetc(void *, u_int *, int *);
        !           151: void   pckbd_cnpollc(void *, int);
        !           152: void   pckbd_cnbell(void *, u_int, u_int, u_int);
        !           153:
        !           154: const struct wskbd_consops pckbd_consops = {
        !           155:        pckbd_cngetc,
        !           156:        pckbd_cnpollc,
        !           157:        pckbd_cnbell,
        !           158: };
        !           159:
        !           160: const struct wskbd_mapdata pckbd_keymapdata = {
        !           161:        pckbd_keydesctab,
        !           162: #ifdef PCKBD_LAYOUT
        !           163:        PCKBD_LAYOUT,
        !           164: #else
        !           165:        KB_US,
        !           166: #endif
        !           167: };
        !           168:
        !           169: /*
        !           170:  * Hackish support for a bell on the PC Keyboard; when a suitable feeper
        !           171:  * is found, it attaches itself into the pckbd driver here.
        !           172:  */
        !           173: void   (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int);
        !           174: void   *pckbd_bell_fn_arg;
        !           175:
        !           176: void   pckbd_bell(u_int, u_int, u_int, int);
        !           177:
        !           178: int    pckbd_set_xtscancode(pckbc_tag_t, pckbc_slot_t);
        !           179: int    pckbd_init(struct pckbd_internal *, pckbc_tag_t, pckbc_slot_t,
        !           180:                        int);
        !           181: void   pckbd_input(void *, int);
        !           182:
        !           183: static int     pckbd_decode(struct pckbd_internal *, int,
        !           184:                                  u_int *, int *);
        !           185: static int     pckbd_led_encode(int);
        !           186: static int     pckbd_led_decode(int);
        !           187:
        !           188: struct pckbd_internal pckbd_consdata;
        !           189:
        !           190: int
        !           191: pckbd_set_xtscancode(kbctag, kbcslot)
        !           192:        pckbc_tag_t kbctag;
        !           193:        pckbc_slot_t kbcslot;
        !           194: {
        !           195:        /* default to have the 8042 translate the keyboard with table 3. */
        !           196:        int table = 3;
        !           197:
        !           198:        if (!pckbc_xt_translation(kbctag, kbcslot, 1)) {
        !           199: #ifdef DEBUG
        !           200:                printf("pckbd: enabling of translation failed\n");
        !           201: #endif
        !           202:                /* just set the basic XT table and hope it works. */
        !           203:                table = 1;
        !           204:        }
        !           205:
        !           206:        /* keep falling back until we hit a table that looks usable. */
        !           207:        for (; table >= 1; table--) {
        !           208:                u_char cmd[2];
        !           209: #ifdef DEBUG
        !           210:                printf("pckbd: trying table %d\n", table);
        !           211: #endif
        !           212:                cmd[0] = KBC_SETTABLE;
        !           213:                cmd[1] = table;
        !           214:                if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0)) {
        !           215:                        u_char cmd[1];
        !           216: #ifdef DEBUG
        !           217:                        printf("pckbd: table set of %d failed\n", table);
        !           218: #endif
        !           219:                        if (table > 1) {
        !           220:                                cmd[0] = KBC_RESET;
        !           221:                                (void)pckbc_poll_cmd(kbctag, kbcslot, cmd,
        !           222:                                    1, 1, 0, 1);
        !           223:                                pckbc_flush(kbctag, kbcslot);
        !           224:
        !           225:                                continue;
        !           226:                        }
        !           227:                }
        !           228:
        !           229:                /*
        !           230:                 * the 8042 took the table set request, however, not all that
        !           231:                 * report they can work with table 3 actually work, so ask what
        !           232:                 * table it reports it's in.
        !           233:                 */
        !           234:                if (table == 3) {
        !           235:                        u_char cmd[1], resp[0];
        !           236:
        !           237:                        cmd[0] = KBC_SETTABLE;
        !           238:                        cmd[1] = 0;
        !           239:                        if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 1, resp, 0)) {
        !           240:                                /*
        !           241:                                 * query failed, step down to table 2 to be
        !           242:                                 * safe.
        !           243:                                 */
        !           244: #ifdef DEBUG
        !           245:                                printf("pckbd: table 3 verification failed\n");
        !           246: #endif
        !           247:                                continue;
        !           248:                        } else if (resp[0] == 3) {
        !           249: #ifdef DEBUG
        !           250:                                printf("pckbd: settling on table 3\n");
        !           251: #endif
        !           252:                                return (0);
        !           253:                        }
        !           254: #ifdef DEBUG
        !           255:                        else
        !           256:                                printf("pckbd: table \"%x\" != 3, trying 2\n",
        !           257:                                        resp[0]);
        !           258: #endif
        !           259:                } else {
        !           260: #ifdef DEBUG
        !           261:                        printf("pckbd: settling on table %d\n", table);
        !           262: #endif
        !           263:                        return (0);
        !           264:                }
        !           265:        }
        !           266:
        !           267:        return (1);
        !           268: }
        !           269:
        !           270: static int
        !           271: pckbd_is_console(tag, slot)
        !           272:        pckbc_tag_t tag;
        !           273:        pckbc_slot_t slot;
        !           274: {
        !           275:        return (pckbd_consdata.t_isconsole &&
        !           276:                (tag == pckbd_consdata.t_kbctag) &&
        !           277:                (slot == pckbd_consdata.t_kbcslot));
        !           278: }
        !           279:
        !           280: /*
        !           281:  * these are both bad jokes
        !           282:  */
        !           283: int
        !           284: pckbdprobe(parent, match, aux)
        !           285:        struct device *parent;
        !           286:        void *match;
        !           287:        void *aux;
        !           288: {
        !           289:        struct cfdata *cf = match;
        !           290:        struct pckbc_attach_args *pa = aux;
        !           291:        u_char cmd[1], resp[1];
        !           292:        int res;
        !           293:
        !           294:        /*
        !           295:         * XXX There are rumours that a keyboard can be connected
        !           296:         * to the aux port as well. For me, this didn't work.
        !           297:         * For further experiments, allow it if explicitly
        !           298:         * wired in the config file.
        !           299:         */
        !           300:        if ((pa->pa_slot != PCKBC_KBD_SLOT) &&
        !           301:            (cf->cf_loc[PCKBCCF_SLOT] == PCKBCCF_SLOT_DEFAULT))
        !           302:                return (0);
        !           303:
        !           304:        /* Flush any garbage. */
        !           305:        pckbc_flush(pa->pa_tag, pa->pa_slot);
        !           306:
        !           307:        /* Reset the keyboard. */
        !           308:        cmd[0] = KBC_RESET;
        !           309:        res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
        !           310:        if (res) {
        !           311: #ifdef DEBUG
        !           312:                printf("pckbdprobe: reset error %d\n", res);
        !           313: #endif
        !           314:                /*
        !           315:                 * There is probably no keyboard connected.
        !           316:                 * Let the probe succeed if the keyboard is used
        !           317:                 * as console input - it can be connected later.
        !           318:                 */
        !           319:                return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0);
        !           320:        }
        !           321:        if (resp[0] != KBR_RSTDONE) {
        !           322:                printf("pckbdprobe: reset response 0x%x\n", resp[0]);
        !           323:                return (0);
        !           324:        }
        !           325:
        !           326:        /*
        !           327:         * Some keyboards seem to leave a second ack byte after the reset.
        !           328:         * This is kind of stupid, but we account for them anyway by just
        !           329:         * flushing the buffer.
        !           330:         */
        !           331:        pckbc_flush(pa->pa_tag, pa->pa_slot);
        !           332:
        !           333:        if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot))
        !           334:                return (0);
        !           335:
        !           336:        return (2);
        !           337: }
        !           338:
        !           339: void
        !           340: pckbdattach(parent, self, aux)
        !           341:        struct device *parent, *self;
        !           342:        void *aux;
        !           343: {
        !           344:        struct pckbd_softc *sc = (void *)self;
        !           345:        struct pckbc_attach_args *pa = aux;
        !           346:        int isconsole;
        !           347:        struct wskbddev_attach_args a;
        !           348:        u_char cmd[1];
        !           349:
        !           350:        printf("\n");
        !           351:
        !           352:        isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
        !           353:
        !           354:        if (isconsole) {
        !           355:                sc->id = &pckbd_consdata;
        !           356:                /*
        !           357:                 * Some keyboards are not enabled after a reset,
        !           358:                 * so make sure it is enabled now.
        !           359:                 */
        !           360:                cmd[0] = KBC_ENABLE;
        !           361:                (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           362:                    cmd, 1, 0, 0, 0);
        !           363:                sc->sc_enabled = 1;
        !           364:        } else {
        !           365:                sc->id = malloc(sizeof(struct pckbd_internal),
        !           366:                                M_DEVBUF, M_WAITOK);
        !           367:                (void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
        !           368:
        !           369:                /* no interrupts until enabled */
        !           370:                cmd[0] = KBC_DISABLE;
        !           371:                (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           372:                                      cmd, 1, 0, 0, 0);
        !           373:                sc->sc_enabled = 0;
        !           374:        }
        !           375:
        !           376:        sc->id->t_sc = sc;
        !           377:
        !           378:        pckbc_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           379:                               pckbd_input, sc, sc->sc_dev.dv_xname);
        !           380:
        !           381:        a.console = isconsole;
        !           382:
        !           383:        a.keymap = &pckbd_keymapdata;
        !           384:
        !           385:        a.accessops = &pckbd_accessops;
        !           386:        a.accesscookie = sc;
        !           387:
        !           388:        /*
        !           389:         * Attach the wskbd, saving a handle to it.
        !           390:         * XXX XXX XXX
        !           391:         */
        !           392:        sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
        !           393: }
        !           394:
        !           395: int
        !           396: pckbd_enable(v, on)
        !           397:        void *v;
        !           398:        int on;
        !           399: {
        !           400:        struct pckbd_softc *sc = v;
        !           401:        u_char cmd[1];
        !           402:        int res;
        !           403:
        !           404:        if (on) {
        !           405:                if (sc->sc_enabled)
        !           406:                        return (EBUSY);
        !           407:
        !           408:                pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
        !           409:
        !           410:                cmd[0] = KBC_ENABLE;
        !           411:                res = pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           412:                                        cmd, 1, 0, NULL, 0);
        !           413:                if (res) {
        !           414:                        printf("pckbd_enable: command error\n");
        !           415:                        return (res);
        !           416:                }
        !           417:
        !           418:                res = pckbd_set_xtscancode(sc->id->t_kbctag,
        !           419:                                           sc->id->t_kbcslot);
        !           420:                if (res)
        !           421:                        return (res);
        !           422:
        !           423:                sc->sc_enabled = 1;
        !           424:        } else {
        !           425:                if (sc->id->t_isconsole)
        !           426:                        return (EBUSY);
        !           427:
        !           428:                cmd[0] = KBC_DISABLE;
        !           429:                res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           430:                                        cmd, 1, 0, 1, 0);
        !           431:                if (res) {
        !           432:                        printf("pckbd_disable: command error\n");
        !           433:                        return (res);
        !           434:                }
        !           435:
        !           436:                pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
        !           437:
        !           438:                sc->sc_enabled = 0;
        !           439:        }
        !           440:
        !           441:        return (0);
        !           442: }
        !           443:
        !           444: static int
        !           445: pckbd_decode(id, datain, type, dataout)
        !           446:        struct pckbd_internal *id;
        !           447:        int datain;
        !           448:        u_int *type;
        !           449:        int *dataout;
        !           450: {
        !           451:        int key;
        !           452:
        !           453:        if (datain == KBR_EXTENDED0) {
        !           454:                id->t_extended = 1;
        !           455:                return(0);
        !           456:        } else if (datain == KBR_EXTENDED1) {
        !           457:                id->t_extended1 = 2;
        !           458:                return(0);
        !           459:        }
        !           460:
        !           461:        /* map extended keys to (unused) codes 128-254 */
        !           462:        key = (datain & 0x7f) | (id->t_extended ? 0x80 : 0);
        !           463:        id->t_extended = 0;
        !           464:
        !           465:        /*
        !           466:         * process BREAK key (EXT1 1D 45  EXT1 9D C5):
        !           467:         * map to (unused) code 7F
        !           468:         */
        !           469:        if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
        !           470:                id->t_extended1 = 1;
        !           471:                return(0);
        !           472:        } else if (id->t_extended1 == 1 &&
        !           473:                   (datain == 0x45 || datain == 0xc5)) {
        !           474:                id->t_extended1 = 0;
        !           475:                key = 0x7f;
        !           476:        } else if (id->t_extended1 > 0) {
        !           477:                id->t_extended1 = 0;
        !           478:        }
        !           479:
        !           480:        if (datain & 0x80) {
        !           481:                id->t_lastchar = 0;
        !           482:                *type = WSCONS_EVENT_KEY_UP;
        !           483:        } else {
        !           484:                /* Always ignore typematic keys */
        !           485:                if (key == id->t_lastchar)
        !           486:                        return(0);
        !           487:                id->t_lastchar = key;
        !           488:                *type = WSCONS_EVENT_KEY_DOWN;
        !           489:        }
        !           490:
        !           491:        *dataout = key;
        !           492:        return(1);
        !           493: }
        !           494:
        !           495: int
        !           496: pckbd_init(t, kbctag, kbcslot, console)
        !           497:        struct pckbd_internal *t;
        !           498:        pckbc_tag_t kbctag;
        !           499:        pckbc_slot_t kbcslot;
        !           500:        int console;
        !           501: {
        !           502:        bzero(t, sizeof(struct pckbd_internal));
        !           503:
        !           504:        t->t_isconsole = console;
        !           505:        t->t_kbctag = kbctag;
        !           506:        t->t_kbcslot = kbcslot;
        !           507:
        !           508:        return (pckbd_set_xtscancode(kbctag, kbcslot));
        !           509: }
        !           510:
        !           511: static int
        !           512: pckbd_led_encode(led)
        !           513:        int led;
        !           514: {
        !           515:        int res;
        !           516:
        !           517:        res = 0;
        !           518:
        !           519:        if (led & WSKBD_LED_SCROLL)
        !           520:                res |= 0x01;
        !           521:        if (led & WSKBD_LED_NUM)
        !           522:                res |= 0x02;
        !           523:        if (led & WSKBD_LED_CAPS)
        !           524:                res |= 0x04;
        !           525:        return(res);
        !           526: }
        !           527:
        !           528: static int
        !           529: pckbd_led_decode(led)
        !           530:        int led;
        !           531: {
        !           532:        int res;
        !           533:
        !           534:        res = 0;
        !           535:        if (led & 0x01)
        !           536:                res |= WSKBD_LED_SCROLL;
        !           537:        if (led & 0x02)
        !           538:                res |= WSKBD_LED_NUM;
        !           539:        if (led & 0x04)
        !           540:                res |= WSKBD_LED_CAPS;
        !           541:        return(res);
        !           542: }
        !           543:
        !           544: void
        !           545: pckbd_set_leds(v, leds)
        !           546:        void *v;
        !           547:        int leds;
        !           548: {
        !           549:        struct pckbd_softc *sc = v;
        !           550:        u_char cmd[2];
        !           551:
        !           552:        cmd[0] = KBC_MODEIND;
        !           553:        cmd[1] = pckbd_led_encode(leds);
        !           554:        sc->sc_ledstate = cmd[1];
        !           555:
        !           556:        (void) pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           557:                                 cmd, 2, 0, 0, 0);
        !           558: }
        !           559:
        !           560: /*
        !           561:  * Got a console receive interrupt -
        !           562:  * the console processor wants to give us a character.
        !           563:  */
        !           564: void
        !           565: pckbd_input(vsc, data)
        !           566:        void *vsc;
        !           567:        int data;
        !           568: {
        !           569:        struct pckbd_softc *sc = vsc;
        !           570:        int type, key;
        !           571:
        !           572: #ifdef WSDISPLAY_COMPAT_RAWKBD
        !           573:        if (sc->rawkbd) {
        !           574:                char d = data;
        !           575:                wskbd_rawinput(sc->sc_wskbddev, &d, 1);
        !           576:                return;
        !           577:        }
        !           578: #endif
        !           579:        if (pckbd_decode(sc->id, data, &type, &key))
        !           580:                wskbd_input(sc->sc_wskbddev, type, key);
        !           581: }
        !           582:
        !           583: int
        !           584: pckbd_ioctl(v, cmd, data, flag, p)
        !           585:        void *v;
        !           586:        u_long cmd;
        !           587:        caddr_t data;
        !           588:        int flag;
        !           589:        struct proc *p;
        !           590: {
        !           591:        struct pckbd_softc *sc = v;
        !           592:
        !           593:        switch (cmd) {
        !           594:            case WSKBDIO_GTYPE:
        !           595:                *(int *)data = WSKBD_TYPE_PC_XT;
        !           596:                return 0;
        !           597:            case WSKBDIO_SETLEDS: {
        !           598:                char cmd[2];
        !           599:                int res;
        !           600:                cmd[0] = KBC_MODEIND;
        !           601:                cmd[1] = pckbd_led_encode(*(int *)data);
        !           602:                sc->sc_ledstate = cmd[1];
        !           603:                res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
        !           604:                                        cmd, 2, 0, 1, 0);
        !           605:                return (res);
        !           606:                }
        !           607:            case WSKBDIO_GETLEDS:
        !           608:                *(int *)data = pckbd_led_decode(sc->sc_ledstate);
        !           609:                return (0);
        !           610:            case WSKBDIO_COMPLEXBELL:
        !           611: #define d ((struct wskbd_bell_data *)data)
        !           612:                /*
        !           613:                 * Keyboard can't beep directly; we have an
        !           614:                 * externally-provided global hook to do this.
        !           615:                 */
        !           616:                pckbd_bell(d->pitch, d->period, d->volume, 0);
        !           617: #undef d
        !           618:                return (0);
        !           619: #ifdef WSDISPLAY_COMPAT_RAWKBD
        !           620:            case WSKBDIO_SETMODE:
        !           621:                sc->rawkbd = (*(int *)data == WSKBD_RAW);
        !           622:                return (0);
        !           623: #endif
        !           624:        }
        !           625:        return -1;
        !           626: }
        !           627:
        !           628: void
        !           629: pckbd_bell(pitch, period, volume, poll)
        !           630:        u_int pitch, period, volume;
        !           631:        int poll;
        !           632: {
        !           633:
        !           634:        if (pckbd_bell_fn != NULL)
        !           635:                (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
        !           636:                    volume, poll);
        !           637: }
        !           638:
        !           639: void
        !           640: pckbd_hookup_bell(fn, arg)
        !           641:        void (*fn)(void *, u_int, u_int, u_int, int);
        !           642:        void *arg;
        !           643: {
        !           644:
        !           645:        if (pckbd_bell_fn == NULL) {
        !           646:                pckbd_bell_fn = fn;
        !           647:                pckbd_bell_fn_arg = arg;
        !           648:        }
        !           649: }
        !           650:
        !           651: int
        !           652: pckbd_cnattach(kbctag, kbcslot)
        !           653:        pckbc_tag_t kbctag;
        !           654:        int kbcslot;
        !           655: {
        !           656:        char cmd[1];
        !           657:        int res;
        !           658:
        !           659:        res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1);
        !           660: #if 0 /* we allow the console to be attached if no keyboard is present */
        !           661:        if (res)
        !           662:                return (res);
        !           663: #endif
        !           664:
        !           665:        /* Just to be sure. */
        !           666:        cmd[0] = KBC_ENABLE;
        !           667:        res = pckbc_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0);
        !           668: #if 0
        !           669:        if (res)
        !           670:                return (res);
        !           671: #endif
        !           672:
        !           673:        wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
        !           674:
        !           675:        return (0);
        !           676: }
        !           677:
        !           678: /* ARGSUSED */
        !           679: void
        !           680: pckbd_cngetc(v, type, data)
        !           681:        void *v;
        !           682:        u_int *type;
        !           683:        int *data;
        !           684: {
        !           685:         struct pckbd_internal *t = v;
        !           686:        int val;
        !           687:
        !           688:        for (;;) {
        !           689:                val = pckbc_poll_data(t->t_kbctag, t->t_kbcslot);
        !           690:                if ((val != -1) && pckbd_decode(t, val, type, data))
        !           691:                        return;
        !           692:        }
        !           693: }
        !           694:
        !           695: void
        !           696: pckbd_cnpollc(v, on)
        !           697:        void *v;
        !           698:         int on;
        !           699: {
        !           700:        struct pckbd_internal *t = v;
        !           701:
        !           702:        pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on);
        !           703: }
        !           704:
        !           705: void
        !           706: pckbd_cnbell(v, pitch, period, volume)
        !           707:        void *v;
        !           708:        u_int pitch, period, volume;
        !           709: {
        !           710:
        !           711:        pckbd_bell(pitch, period, volume, 1);
        !           712: }
        !           713:
        !           714: struct cfdriver pckbd_cd = {
        !           715:        NULL, "pckbd", DV_DULL
        !           716: };

CVSweb