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