|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 University of Utah. ! 3: * Copyright (c) 1990 The Regents of the University of California. ! 4: * All rights reserved. ! 5: * ! 6: * This code is derived from software contributed to Berkeley by ! 7: * the Systems Programming Group of the University of Utah Computer ! 8: * Science Department. ! 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 University of ! 21: * California, Berkeley and its contributors. ! 22: * 4. Neither the name of the University nor the names of its contributors ! 23: * may be used to endorse or promote products derived from this software ! 24: * without specific prior written permission. ! 25: * ! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 36: * SUCH DAMAGE. ! 37: * ! 38: * from: Utah $Hdr: hil.c 1.33 89/12/22$ ! 39: * ! 40: * @(#)hil.c 7.8.1.1 (Berkeley) 6/28/91 ! 41: */ ! 42: ! 43: #include "sys/param.h" ! 44: #include "sys/conf.h" ! 45: #include "sys/proc.h" ! 46: #include "sys/user.h" ! 47: #include "sys/ioctl.h" ! 48: #include "sys/file.h" ! 49: #include "sys/tty.h" ! 50: #include "sys/systm.h" ! 51: #include "sys/uio.h" ! 52: #include "sys/kernel.h" ! 53: ! 54: #include "hilreg.h" ! 55: #include "hilioctl.h" ! 56: #include "hilvar.h" ! 57: #include "kbdmap.h" ! 58: ! 59: #include "machine/cpu.h" ! 60: ! 61: #include "vm/vm_param.h" ! 62: #include "vm/vm_map.h" ! 63: #include "vm/vm_kern.h" ! 64: #include "vm/vm_page.h" ! 65: #include "vm/vm_pager.h" ! 66: ! 67: struct hilloop hil0; ! 68: struct _hilbell default_bell = { BELLDUR, BELLFREQ }; ! 69: ! 70: #ifdef DEBUG ! 71: int hildebug = 0; ! 72: #define HDB_FOLLOW 0x01 ! 73: #define HDB_MMAP 0x02 ! 74: #define HDB_MASK 0x04 ! 75: #define HDB_CONFIG 0x08 ! 76: #define HDB_KEYBOARD 0x10 ! 77: #define HDB_IDMODULE 0x20 ! 78: #define HDB_EVENTS 0x80 ! 79: #endif ! 80: ! 81: /* symbolic sleep message strings */ ! 82: char hilin[] = "hilin"; ! 83: ! 84: hilinit() ! 85: { ! 86: register struct hilloop *hilp = &hil0; /* XXX */ ! 87: register int i; ! 88: ! 89: /* ! 90: * Initialize loop information ! 91: */ ! 92: hilp->hl_addr = HILADDR; ! 93: hilp->hl_cmdending = FALSE; ! 94: hilp->hl_actdev = hilp->hl_cmddev = 0; ! 95: hilp->hl_cmddone = FALSE; ! 96: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 97: hilp->hl_pollbp = hilp->hl_pollbuf; ! 98: hilp->hl_kbddev = 0; ! 99: hilp->hl_kbdlang = KBD_DEFAULT; ! 100: hilp->hl_kbdflags = 0; ! 101: /* ! 102: * Clear all queues and device associations with queues ! 103: */ ! 104: for (i = 0; i < NHILQ; i++) { ! 105: hilp->hl_queue[i].hq_eventqueue = NULL; ! 106: hilp->hl_queue[i].hq_procp = NULL; ! 107: hilp->hl_queue[i].hq_devmask = 0; ! 108: } ! 109: for (i = 0; i < NHILD; i++) ! 110: hilp->hl_device[i].hd_qmask = 0; ! 111: hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO); ! 112: /* ! 113: * Reset the loop hardware, and collect keyboard/id info ! 114: */ ! 115: hilreset(hilp); ! 116: hilinfo(hilp); ! 117: kbdenable(); ! 118: } ! 119: ! 120: /* ARGSUSED */ ! 121: hilopen(dev, flags, mode, p) ! 122: dev_t dev; ! 123: int flags, mode; ! 124: struct proc *p; ! 125: { ! 126: register struct hilloop *hilp = &hil0; /* XXX */ ! 127: register struct hilloopdev *dptr; ! 128: u_char device = HILUNIT(dev); ! 129: ! 130: #ifdef DEBUG ! 131: if (hildebug & HDB_FOLLOW) ! 132: printf("hilopen(%d): device %x\n", p->p_pid, device); ! 133: #endif ! 134: ! 135: if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0) ! 136: return(ENXIO); ! 137: ! 138: dptr = &hilp->hl_device[device]; ! 139: if ((dptr->hd_flags & HIL_ALIVE) == 0) ! 140: return(ENODEV); ! 141: ! 142: /* ! 143: * Pseudo-devices cannot be read, nothing more to do. ! 144: */ ! 145: if (dptr->hd_flags & HIL_PSEUDO) ! 146: return(0); ! 147: ! 148: /* ! 149: * Open semantics: ! 150: * 1. Open devices have only one of HIL_READIN/HIL_QUEUEIN. ! 151: * 2. HPUX processes always get read syscall interface and ! 152: * must have exclusive use of the device. ! 153: * 3. BSD processes default to shared queue interface. ! 154: * Multiple processes can open the device. ! 155: */ ! 156: if (p->p_flag & SHPUX) { ! 157: if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN)) ! 158: return(EBUSY); ! 159: dptr->hd_flags |= HIL_READIN; ! 160: } else { ! 161: if (dptr->hd_flags & HIL_READIN) ! 162: return(EBUSY); ! 163: dptr->hd_flags |= HIL_QUEUEIN; ! 164: } ! 165: if (flags & FNONBLOCK) ! 166: dptr->hd_flags |= HIL_NOBLOCK; ! 167: /* ! 168: * It is safe to flush the read buffer as we are guarenteed ! 169: * that no one else is using it. ! 170: */ ! 171: ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); ! 172: ! 173: send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL); ! 174: /* ! 175: * Opened the keyboard, put in raw mode. ! 176: */ ! 177: (void) splhil(); ! 178: if (device == hilp->hl_kbddev) { ! 179: u_char mask = 0; ! 180: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); ! 181: hilp->hl_kbdflags |= KBD_RAW; ! 182: #ifdef DEBUG ! 183: if (hildebug & HDB_KEYBOARD) ! 184: printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev); ! 185: #endif ! 186: } ! 187: (void) spl0(); ! 188: return (0); ! 189: } ! 190: ! 191: /* ARGSUSED */ ! 192: hilclose(dev, flags) ! 193: dev_t dev; ! 194: { ! 195: struct proc *p = curproc; /* XXX */ ! 196: register struct hilloop *hilp = &hil0; /* XXX */ ! 197: register struct hilloopdev *dptr; ! 198: register int i; ! 199: u_char device = HILUNIT(dev); ! 200: char mask, lpctrl; ! 201: ! 202: #ifdef DEBUG ! 203: if (hildebug & HDB_FOLLOW) ! 204: printf("hilclose(%d): device %x\n", p->p_pid, device); ! 205: #endif ! 206: ! 207: dptr = &hilp->hl_device[device]; ! 208: if (device && (dptr->hd_flags & HIL_PSEUDO)) ! 209: return (0); ! 210: ! 211: if ((p->p_flag & SHPUX) == 0) { ! 212: /* ! 213: * If this is the loop device, ! 214: * free up all queues belonging to this process. ! 215: */ ! 216: if (device == 0) { ! 217: for (i = 0; i < NHILQ; i++) ! 218: if (hilp->hl_queue[i].hq_procp == p) ! 219: (void) hilqfree(i); ! 220: } else { ! 221: mask = ~hildevmask(device); ! 222: (void) splhil(); ! 223: for (i = 0; i < NHILQ; i++) ! 224: if (hilp->hl_queue[i].hq_procp == p) { ! 225: dptr->hd_qmask &= ~hilqmask(i); ! 226: hilp->hl_queue[i].hq_devmask &= mask; ! 227: } ! 228: (void) spl0(); ! 229: } ! 230: } ! 231: /* ! 232: * Always flush the read buffer ! 233: */ ! 234: dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK); ! 235: ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); ! 236: /* ! 237: * Set keyboard back to cooked mode when closed. ! 238: */ ! 239: (void) splhil(); ! 240: if (device && device == hilp->hl_kbddev) { ! 241: mask = 1 << (hilp->hl_kbddev - 1); ! 242: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); ! 243: hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2); ! 244: /* ! 245: * XXX: We have had trouble with keyboards remaining raw ! 246: * after close due to the LPC_KBDCOOK bit getting cleared ! 247: * somewhere along the line. Hence we check and reset ! 248: * LPCTRL if necessary. ! 249: */ ! 250: send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl); ! 251: if ((lpctrl & LPC_KBDCOOK) == 0) { ! 252: printf("hilclose: bad LPCTRL %x, reset to %x\n", ! 253: lpctrl, lpctrl|LPC_KBDCOOK); ! 254: lpctrl |= LPC_KBDCOOK; ! 255: send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL, ! 256: &lpctrl, 1, NULL); ! 257: } ! 258: #ifdef DEBUG ! 259: if (hildebug & HDB_KEYBOARD) ! 260: printf("hilclose: keyboard %d cooked\n", ! 261: hilp->hl_kbddev); ! 262: #endif ! 263: kbdenable(); ! 264: } ! 265: (void) spl0(); ! 266: return (0); ! 267: } ! 268: ! 269: /* ! 270: * Read interface to HIL device. ! 271: */ ! 272: hilread(dev, uio) ! 273: dev_t dev; ! 274: register struct uio *uio; ! 275: { ! 276: struct hilloop *hilp = &hil0; /* XXX */ ! 277: register struct hilloopdev *dptr; ! 278: register int cc; ! 279: u_char device = HILUNIT(dev); ! 280: char buf[HILBUFSIZE]; ! 281: int error; ! 282: ! 283: #if 0 ! 284: /* ! 285: * XXX: Don't do this since HP-UX doesn't. ! 286: * ! 287: * Check device number. ! 288: * This check is necessary since loop can reconfigure. ! 289: */ ! 290: if (device > hilp->hl_maxdev) ! 291: return(ENODEV); ! 292: #endif ! 293: ! 294: dptr = &hilp->hl_device[device]; ! 295: if ((dptr->hd_flags & HIL_READIN) == 0) ! 296: return(ENODEV); ! 297: ! 298: (void) splhil(); ! 299: while (dptr->hd_queue.c_cc == 0) { ! 300: if (dptr->hd_flags & HIL_NOBLOCK) { ! 301: spl0(); ! 302: return(EWOULDBLOCK); ! 303: } ! 304: dptr->hd_flags |= HIL_ASLEEP; ! 305: if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) { ! 306: (void) spl0(); ! 307: return (error); ! 308: } ! 309: } ! 310: (void) spl0(); ! 311: ! 312: error = 0; ! 313: while (uio->uio_resid > 0 && error == 0) { ! 314: cc = hilq_to_b(&dptr->hd_queue, buf, ! 315: MIN(uio->uio_resid, HILBUFSIZE)); ! 316: if (cc <= 0) ! 317: break; ! 318: error = uiomove(buf, cc, uio); ! 319: } ! 320: return(error); ! 321: } ! 322: ! 323: hilioctl(dev, cmd, data, flag, p) ! 324: dev_t dev; ! 325: caddr_t data; ! 326: struct proc *p; ! 327: { ! 328: register struct hilloop *hilp = &hil0; /* XXX */ ! 329: char device = HILUNIT(dev); ! 330: struct hilloopdev *dptr; ! 331: register int i; ! 332: u_char hold; ! 333: int error; ! 334: ! 335: #ifdef DEBUG ! 336: if (hildebug & HDB_FOLLOW) ! 337: printf("hilioctl(%d): dev %x cmd %x\n", ! 338: p->p_pid, device, cmd); ! 339: #endif ! 340: ! 341: dptr = &hilp->hl_device[device]; ! 342: if ((dptr->hd_flags & HIL_ALIVE) == 0) ! 343: return (ENODEV); ! 344: ! 345: /* ! 346: * Don't allow hardware ioctls on virtual devices. ! 347: * Note that though these are the BSD names, they have the same ! 348: * values as the HP-UX equivalents so we catch them as well. ! 349: */ ! 350: if (dptr->hd_flags & HIL_PSEUDO) { ! 351: switch (cmd) { ! 352: case HILIOCSC: ! 353: case HILIOCID: ! 354: case HILIOCRN: ! 355: case HILIOCRS: ! 356: case HILIOCED: ! 357: return(ENODEV); ! 358: ! 359: /* ! 360: * XXX: should also return ENODEV but HP-UX compat ! 361: * breaks if we do. They work ok right now because ! 362: * we only recognize one keyboard on the loop. This ! 363: * will have to change if we remove that restriction. ! 364: */ ! 365: case HILIOCAROFF: ! 366: case HILIOCAR1: ! 367: case HILIOCAR2: ! 368: break; ! 369: ! 370: default: ! 371: break; ! 372: } ! 373: } ! 374: ! 375: #ifdef HPUXCOMPAT ! 376: if (p->p_flag & SHPUX) ! 377: return(hpuxhilioctl(dev, cmd, data, flag)); ! 378: #endif ! 379: ! 380: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 381: bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); ! 382: hilp->hl_cmddev = device; ! 383: error = 0; ! 384: switch (cmd) { ! 385: ! 386: case HILIOCSBP: ! 387: /* Send four data bytes to the tone gererator. */ ! 388: send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); ! 389: /* Send the trigger beeper command to the 8042. */ ! 390: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); ! 391: break; ! 392: ! 393: case HILIOCRRT: ! 394: /* Transfer the real time to the 8042 data buffer */ ! 395: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); ! 396: /* Read each byte of the real time */ ! 397: for (i = 0; i < 5; i++) { ! 398: send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, ! 399: 0, &hold); ! 400: data[4-i] = hold; ! 401: } ! 402: break; ! 403: ! 404: case HILIOCRT: ! 405: for (i = 0; i < 4; i++) { ! 406: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, ! 407: NULL, 0, &hold); ! 408: data[i] = hold; ! 409: } ! 410: break; ! 411: ! 412: case HILIOCID: ! 413: case HILIOCSC: ! 414: case HILIOCRN: ! 415: case HILIOCRS: ! 416: case HILIOCED: ! 417: send_hildev_cmd(hilp, device, (cmd & 0xFF)); ! 418: bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); ! 419: break; ! 420: ! 421: case HILIOCAROFF: ! 422: case HILIOCAR1: ! 423: case HILIOCAR2: ! 424: if (hilp->hl_kbddev) { ! 425: hilp->hl_cmddev = hilp->hl_kbddev; ! 426: send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); ! 427: hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); ! 428: if (cmd == HILIOCAR1) ! 429: hilp->hl_kbdflags |= KBD_AR1; ! 430: else if (cmd == HILIOCAR2) ! 431: hilp->hl_kbdflags |= KBD_AR2; ! 432: } ! 433: break; ! 434: ! 435: case HILIOCBEEP: ! 436: hilbeep(hilp, (struct _hilbell *)data); ! 437: break; ! 438: ! 439: case FIONBIO: ! 440: dptr = &hilp->hl_device[device]; ! 441: if (*(int *)data) ! 442: dptr->hd_flags |= HIL_NOBLOCK; ! 443: else ! 444: dptr->hd_flags &= ~HIL_NOBLOCK; ! 445: break; ! 446: ! 447: /* ! 448: * FIOASYNC must be present for FIONBIO above to work! ! 449: * (See fcntl in kern_descrip.c). ! 450: */ ! 451: case FIOASYNC: ! 452: break; ! 453: ! 454: case HILIOCALLOCQ: ! 455: error = hilqalloc((struct hilqinfo *)data); ! 456: break; ! 457: ! 458: case HILIOCFREEQ: ! 459: error = hilqfree(((struct hilqinfo *)data)->qid); ! 460: break; ! 461: ! 462: case HILIOCMAPQ: ! 463: error = hilqmap(*(int *)data, device); ! 464: break; ! 465: ! 466: case HILIOCUNMAPQ: ! 467: error = hilqunmap(*(int *)data, device); ! 468: break; ! 469: ! 470: case HILIOCHPUX: ! 471: dptr = &hilp->hl_device[device]; ! 472: dptr->hd_flags |= HIL_READIN; ! 473: dptr->hd_flags &= ~HIL_QUEUEIN; ! 474: break; ! 475: ! 476: case HILIOCRESET: ! 477: hilreset(hilp); ! 478: break; ! 479: ! 480: #ifdef DEBUG ! 481: case HILIOCTEST: ! 482: hildebug = *(int *) data; ! 483: break; ! 484: #endif ! 485: ! 486: default: ! 487: error = EINVAL; ! 488: break; ! 489: ! 490: } ! 491: hilp->hl_cmddev = 0; ! 492: return(error); ! 493: } ! 494: ! 495: #ifdef HPUXCOMPAT ! 496: /* ARGSUSED */ ! 497: hpuxhilioctl(dev, cmd, data, flag) ! 498: dev_t dev; ! 499: caddr_t data; ! 500: { ! 501: register struct hilloop *hilp = &hil0; /* XXX */ ! 502: char device = HILUNIT(dev); ! 503: struct hilloopdev *dptr; ! 504: register int i; ! 505: u_char hold; ! 506: ! 507: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 508: bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); ! 509: hilp->hl_cmddev = device; ! 510: switch (cmd) { ! 511: ! 512: case HILSC: ! 513: case HILID: ! 514: case HILRN: ! 515: case HILRS: ! 516: case HILED: ! 517: case HILP1: ! 518: case HILP2: ! 519: case HILP3: ! 520: case HILP4: ! 521: case HILP5: ! 522: case HILP6: ! 523: case HILP7: ! 524: case HILP: ! 525: case HILA1: ! 526: case HILA2: ! 527: case HILA3: ! 528: case HILA4: ! 529: case HILA5: ! 530: case HILA6: ! 531: case HILA7: ! 532: case HILA: ! 533: send_hildev_cmd(hilp, device, (cmd & 0xFF)); ! 534: bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); ! 535: break; ! 536: ! 537: case HILDKR: ! 538: case HILER1: ! 539: case HILER2: ! 540: if (hilp->hl_kbddev) { ! 541: hilp->hl_cmddev = hilp->hl_kbddev; ! 542: send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); ! 543: hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); ! 544: if (cmd == HILIOCAR1) ! 545: hilp->hl_kbdflags |= KBD_AR1; ! 546: else if (cmd == HILIOCAR2) ! 547: hilp->hl_kbdflags |= KBD_AR2; ! 548: } ! 549: break; ! 550: ! 551: case EFTSBP: ! 552: /* Send four data bytes to the tone gererator. */ ! 553: send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); ! 554: /* Send the trigger beeper command to the 8042. */ ! 555: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); ! 556: break; ! 557: ! 558: case EFTRRT: ! 559: /* Transfer the real time to the 8042 data buffer */ ! 560: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); ! 561: /* Read each byte of the real time */ ! 562: for (i = 0; i < 5; i++) { ! 563: send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, ! 564: 0, &hold); ! 565: data[4-i] = hold; ! 566: } ! 567: break; ! 568: ! 569: case EFTRT: ! 570: for (i = 0; i < 4; i++) { ! 571: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, ! 572: NULL, 0, &hold); ! 573: data[i] = hold; ! 574: } ! 575: break; ! 576: ! 577: case EFTRLC: ! 578: case EFTRCC: ! 579: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold); ! 580: *data = hold; ! 581: break; ! 582: ! 583: case EFTSRPG: ! 584: case EFTSRD: ! 585: case EFTSRR: ! 586: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL); ! 587: break; ! 588: ! 589: case EFTSBI: ! 590: hilbeep(hilp, (struct _hilbell *)data); ! 591: break; ! 592: ! 593: case FIONBIO: ! 594: dptr = &hilp->hl_device[device]; ! 595: if (*(int *)data) ! 596: dptr->hd_flags |= HIL_NOBLOCK; ! 597: else ! 598: dptr->hd_flags &= ~HIL_NOBLOCK; ! 599: break; ! 600: ! 601: case FIOASYNC: ! 602: break; ! 603: ! 604: default: ! 605: hilp->hl_cmddev = 0; ! 606: return(EINVAL); ! 607: } ! 608: hilp->hl_cmddev = 0; ! 609: return(0); ! 610: } ! 611: #endif ! 612: ! 613: /* ! 614: * XXX: the mmap interface for HIL devices should be rethought. ! 615: * We used it only briefly in conjuntion with shared queues ! 616: * (instead of HILIOCMAPQ ioctl). Perhaps mmap()ing a device ! 617: * should give a single queue per process. ! 618: */ ! 619: /* ARGSUSED */ ! 620: hilmap(dev, off, prot) ! 621: dev_t dev; ! 622: register int off; ! 623: { ! 624: #ifdef MMAP ! 625: struct proc *p = curproc; /* XXX */ ! 626: register struct hilloop *hilp = &hil0; /* XXX */ ! 627: register struct hiliqueue *qp; ! 628: register int qnum; ! 629: ! 630: /* ! 631: * Only allow mmap() on loop device ! 632: */ ! 633: if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ)) ! 634: return(-1); ! 635: /* ! 636: * Determine which queue we want based on the offset. ! 637: * Queue must belong to calling process. ! 638: */ ! 639: qp = &hilp->hl_queue[off / sizeof(HILQ)]; ! 640: if (qp->hq_procp != p) ! 641: return(-1); ! 642: ! 643: off %= sizeof(HILQ); ! 644: return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT); ! 645: #endif ! 646: } ! 647: ! 648: /*ARGSUSED*/ ! 649: hilselect(dev, rw, p) ! 650: dev_t dev; ! 651: struct proc *p; ! 652: { ! 653: register struct hilloop *hilp = &hil0; /* XXX */ ! 654: register struct hilloopdev *dptr; ! 655: register struct hiliqueue *qp; ! 656: register int mask; ! 657: int s, device; ! 658: ! 659: if (rw == FWRITE) ! 660: return (1); ! 661: device = HILUNIT(dev); ! 662: ! 663: /* ! 664: * Read interface. ! 665: * Return 1 if there is something in the queue, 0 ow. ! 666: */ ! 667: dptr = &hilp->hl_device[device]; ! 668: if (dptr->hd_flags & HIL_READIN) { ! 669: s = splhil(); ! 670: if (dptr->hd_queue.c_cc) { ! 671: splx(s); ! 672: return (1); ! 673: } ! 674: if (dptr->hd_selr && ! 675: dptr->hd_selr->p_wchan == (caddr_t)&selwait) ! 676: dptr->hd_flags |= HIL_SELCOLL; ! 677: else ! 678: dptr->hd_selr = p; ! 679: splx(s); ! 680: return (0); ! 681: } ! 682: ! 683: /* ! 684: * Make sure device is alive and real (or the loop device). ! 685: * Note that we do not do this for the read interface. ! 686: * This is primarily to be consistant with HP-UX. ! 687: */ ! 688: if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) ! 689: return (1); ! 690: ! 691: /* ! 692: * Select on loop device is special. ! 693: * Check to see if there are any data for any loop device ! 694: * provided it is associated with a queue belonging to this user. ! 695: */ ! 696: if (device == 0) ! 697: mask = -1; ! 698: else ! 699: mask = hildevmask(device); ! 700: /* ! 701: * Must check everybody with interrupts blocked to prevent races. ! 702: */ ! 703: s = splhil(); ! 704: for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) ! 705: if (qp->hq_procp == p && (mask & qp->hq_devmask) && ! 706: qp->hq_eventqueue->hil_evqueue.head != ! 707: qp->hq_eventqueue->hil_evqueue.tail) { ! 708: splx(s); ! 709: return (1); ! 710: } ! 711: ! 712: if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait) ! 713: dptr->hd_flags |= HIL_SELCOLL; ! 714: else ! 715: dptr->hd_selr = p; ! 716: splx(s); ! 717: return (0); ! 718: } ! 719: ! 720: hilint() ! 721: { ! 722: struct hilloop *hilp = &hil0; /* XXX */ ! 723: register struct hil_dev *hildevice = hilp->hl_addr; ! 724: u_char c, stat; ! 725: ! 726: stat = hildevice->hil_stat; ! 727: c = hildevice->hil_data; /* clears interrupt */ ! 728: hil_process_int(stat, c); ! 729: } ! 730: ! 731: #include "ite.h" ! 732: ! 733: hil_process_int(stat, c) ! 734: register u_char stat, c; ! 735: { ! 736: register struct hilloop *hilp; ! 737: ! 738: #ifdef DEBUG ! 739: if (hildebug & HDB_EVENTS) ! 740: printf("hilint: %x %x\n", stat, c); ! 741: #endif ! 742: ! 743: /* the shift enables the compiler to generate a jump table */ ! 744: switch ((stat>>HIL_SSHIFT) & HIL_SMASK) { ! 745: ! 746: #if NITE > 0 ! 747: case HIL_KEY: ! 748: case HIL_SHIFT: ! 749: case HIL_CTRL: ! 750: case HIL_CTRLSHIFT: ! 751: itefilter(stat, c); ! 752: return; ! 753: #endif ! 754: ! 755: case HIL_STATUS: /* The status info. */ ! 756: hilp = &hil0; /* XXX */ ! 757: if (c & HIL_ERROR) { ! 758: hilp->hl_cmddone = TRUE; ! 759: if (c == HIL_RECONFIG) ! 760: hilconfig(hilp); ! 761: break; ! 762: } ! 763: if (c & HIL_COMMAND) { ! 764: if (c & HIL_POLLDATA) /* End of data */ ! 765: hilevent(hilp); ! 766: else /* End of command */ ! 767: hilp->hl_cmdending = TRUE; ! 768: hilp->hl_actdev = 0; ! 769: } else { ! 770: if (c & HIL_POLLDATA) { /* Start of polled data */ ! 771: if (hilp->hl_actdev != 0) ! 772: hilevent(hilp); ! 773: hilp->hl_actdev = (c & HIL_DEVMASK); ! 774: hilp->hl_pollbp = hilp->hl_pollbuf; ! 775: } else { /* Start of command */ ! 776: if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { ! 777: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 778: hilp->hl_actdev = 0; ! 779: } ! 780: } ! 781: } ! 782: return; ! 783: ! 784: case HIL_DATA: ! 785: hilp = &hil0; /* XXX */ ! 786: if (hilp->hl_actdev != 0) /* Collecting poll data */ ! 787: *hilp->hl_pollbp++ = c; ! 788: else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ ! 789: if (hilp->hl_cmdending) { ! 790: hilp->hl_cmddone = TRUE; ! 791: hilp->hl_cmdending = FALSE; ! 792: } else ! 793: *hilp->hl_cmdbp++ = c; ! 794: return; ! 795: ! 796: case 0: /* force full jump table */ ! 797: default: ! 798: return; ! 799: } ! 800: } ! 801: ! 802: #if defined(DEBUG) && !defined(PANICBUTTON) ! 803: #define PANICBUTTON ! 804: #endif ! 805: ! 806: /* ! 807: * Optimized macro to compute: ! 808: * eq->head == (eq->tail + 1) % eq->size ! 809: * i.e. has tail caught up with head. We do this because 32 bit long ! 810: * remaidering is expensive (a function call with our compiler). ! 811: */ ! 812: #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1) ! 813: #define HQVALID(eq) \ ! 814: ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE) ! 815: ! 816: hilevent(hilp) ! 817: struct hilloop *hilp; ! 818: { ! 819: register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; ! 820: register int len, mask, qnum; ! 821: register u_char *cp, *pp; ! 822: register HILQ *hq; ! 823: struct timeval ourtime; ! 824: hil_packet *proto; ! 825: int s, len0; ! 826: long tenths; ! 827: ! 828: #ifdef PANICBUTTON ! 829: static int first; ! 830: extern int panicbutton; ! 831: ! 832: cp = hilp->hl_pollbuf; ! 833: if (panicbutton && (*cp & HIL_KBDDATA)) { ! 834: if (*++cp == 0x4E) ! 835: first = 1; ! 836: else if (first && *cp == 0x46 && !panicstr) ! 837: panic("are we having fun yet?"); ! 838: else ! 839: first = 0; ! 840: } ! 841: #endif ! 842: #ifdef DEBUG ! 843: if (hildebug & HDB_EVENTS) { ! 844: printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); ! 845: printhilpollbuf(hilp); ! 846: printf("\n"); ! 847: } ! 848: #endif ! 849: ! 850: /* ! 851: * Note that HIL_READIN effectively "shuts off" any queues ! 852: * that may have been in use at the time of an HILIOCHPUX call. ! 853: */ ! 854: if (dptr->hd_flags & HIL_READIN) { ! 855: hpuxhilevent(hilp, dptr); ! 856: return; ! 857: } ! 858: ! 859: /* ! 860: * If this device isn't on any queue or there are no data ! 861: * in the packet (can this happen?) do nothing. ! 862: */ ! 863: if (dptr->hd_qmask == 0 || ! 864: (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) ! 865: return; ! 866: ! 867: /* ! 868: * Everybody gets the same time stamp ! 869: */ ! 870: s = splclock(); ! 871: ourtime = time; ! 872: splx(s); ! 873: tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); ! 874: ! 875: proto = NULL; ! 876: mask = dptr->hd_qmask; ! 877: for (qnum = 0; mask; qnum++) { ! 878: if ((mask & hilqmask(qnum)) == 0) ! 879: continue; ! 880: mask &= ~hilqmask(qnum); ! 881: hq = hilp->hl_queue[qnum].hq_eventqueue; ! 882: ! 883: /* ! 884: * Ensure that queue fields that we rely on are valid ! 885: * and that there is space in the queue. If either ! 886: * test fails, we just skip this queue. ! 887: */ ! 888: if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) ! 889: continue; ! 890: ! 891: /* ! 892: * Copy data to queue. ! 893: * If this is the first queue we construct the packet ! 894: * with length, timestamp and poll buffer data. ! 895: * For second and sucessive packets we just duplicate ! 896: * the first packet. ! 897: */ ! 898: pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; ! 899: if (proto == NULL) { ! 900: proto = (hil_packet *)pp; ! 901: cp = hilp->hl_pollbuf; ! 902: len = len0; ! 903: *pp++ = len + 6; ! 904: *pp++ = hilp->hl_actdev; ! 905: *(long *)pp = tenths; ! 906: pp += sizeof(long); ! 907: do *pp++ = *cp++; while (--len); ! 908: } else ! 909: *(hil_packet *)pp = *proto; ! 910: ! 911: if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) ! 912: hq->hil_evqueue.tail = 0; ! 913: } ! 914: ! 915: /* ! 916: * Wake up anyone selecting on this device or the loop itself ! 917: */ ! 918: if (dptr->hd_selr) { ! 919: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); ! 920: dptr->hd_selr = NULL; ! 921: dptr->hd_flags &= ~HIL_SELCOLL; ! 922: } ! 923: dptr = &hilp->hl_device[HILLOOPDEV]; ! 924: if (dptr->hd_selr) { ! 925: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); ! 926: dptr->hd_selr = NULL; ! 927: dptr->hd_flags &= ~HIL_SELCOLL; ! 928: } ! 929: } ! 930: ! 931: #undef HQFULL ! 932: ! 933: hpuxhilevent(hilp, dptr) ! 934: register struct hilloop *hilp; ! 935: register struct hilloopdev *dptr; ! 936: { ! 937: register int len; ! 938: struct timeval ourtime; ! 939: long tstamp; ! 940: int s; ! 941: ! 942: /* ! 943: * Everybody gets the same time stamp ! 944: */ ! 945: s = splclock(); ! 946: ourtime = time; ! 947: splx(s); ! 948: tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); ! 949: ! 950: /* ! 951: * Each packet that goes into the buffer must be preceded by the ! 952: * number of bytes in the packet, and the timestamp of the packet. ! 953: * This adds 5 bytes to the packet size. Make sure there is enough ! 954: * room in the buffer for it, and if not, toss the packet. ! 955: */ ! 956: len = hilp->hl_pollbp - hilp->hl_pollbuf; ! 957: if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { ! 958: putc(len+5, &dptr->hd_queue); ! 959: (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); ! 960: (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); ! 961: } ! 962: ! 963: /* ! 964: * Wake up any one blocked on a read or select ! 965: */ ! 966: if (dptr->hd_flags & HIL_ASLEEP) { ! 967: dptr->hd_flags &= ~HIL_ASLEEP; ! 968: wakeup((caddr_t)dptr); ! 969: } ! 970: if (dptr->hd_selr) { ! 971: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); ! 972: dptr->hd_selr = NULL; ! 973: dptr->hd_flags &= ~HIL_SELCOLL; ! 974: } ! 975: } ! 976: ! 977: /* ! 978: * Shared queue manipulation routines ! 979: */ ! 980: ! 981: hilqalloc(qip) ! 982: struct hilqinfo *qip; ! 983: { ! 984: struct proc *p = curproc; /* XXX */ ! 985: ! 986: #ifdef DEBUG ! 987: if (hildebug & HDB_FOLLOW) ! 988: printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr); ! 989: #endif ! 990: return(EINVAL); ! 991: } ! 992: ! 993: hilqfree(qnum) ! 994: register int qnum; ! 995: { ! 996: struct proc *p = curproc; /* XXX */ ! 997: ! 998: #ifdef DEBUG ! 999: if (hildebug & HDB_FOLLOW) ! 1000: printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum); ! 1001: #endif ! 1002: return(EINVAL); ! 1003: } ! 1004: ! 1005: hilqmap(qnum, device) ! 1006: register int qnum, device; ! 1007: { ! 1008: struct proc *p = curproc; /* XXX */ ! 1009: register struct hilloop *hilp = &hil0; /* XXX */ ! 1010: register struct hilloopdev *dptr = &hilp->hl_device[device]; ! 1011: int s; ! 1012: ! 1013: #ifdef DEBUG ! 1014: if (hildebug & HDB_FOLLOW) ! 1015: printf("hilqmap(%d): qnum %d device %x\n", ! 1016: p->p_pid, qnum, device); ! 1017: #endif ! 1018: if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) ! 1019: return(EINVAL); ! 1020: if ((dptr->hd_flags & HIL_QUEUEIN) == 0) ! 1021: return(EINVAL); ! 1022: if (dptr->hd_qmask && p->p_ucred->cr_uid && ! 1023: p->p_ucred->cr_uid != dptr->hd_uid) ! 1024: return(EPERM); ! 1025: ! 1026: hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); ! 1027: if (dptr->hd_qmask == 0) ! 1028: dptr->hd_uid = p->p_ucred->cr_uid; ! 1029: s = splhil(); ! 1030: dptr->hd_qmask |= hilqmask(qnum); ! 1031: splx(s); ! 1032: #ifdef DEBUG ! 1033: if (hildebug & HDB_MASK) ! 1034: printf("hilqmap(%d): devmask %x qmask %x\n", ! 1035: p->p_pid, hilp->hl_queue[qnum].hq_devmask, ! 1036: dptr->hd_qmask); ! 1037: #endif ! 1038: return(0); ! 1039: } ! 1040: ! 1041: hilqunmap(qnum, device) ! 1042: register int qnum, device; ! 1043: { ! 1044: struct proc *p = curproc; /* XXX */ ! 1045: register struct hilloop *hilp = &hil0; /* XXX */ ! 1046: int s; ! 1047: ! 1048: #ifdef DEBUG ! 1049: if (hildebug & HDB_FOLLOW) ! 1050: printf("hilqunmap(%d): qnum %d device %x\n", ! 1051: p->p_pid, qnum, device); ! 1052: #endif ! 1053: ! 1054: if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) ! 1055: return(EINVAL); ! 1056: ! 1057: hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); ! 1058: s = splhil(); ! 1059: hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); ! 1060: splx(s); ! 1061: #ifdef DEBUG ! 1062: if (hildebug & HDB_MASK) ! 1063: printf("hilqunmap(%d): devmask %x qmask %x\n", ! 1064: p->p_pid, hilp->hl_queue[qnum].hq_devmask, ! 1065: hilp->hl_device[device].hd_qmask); ! 1066: #endif ! 1067: return(0); ! 1068: } ! 1069: ! 1070: #include "sys/clist.h" ! 1071: ! 1072: /* ! 1073: * This is just a copy of the virgin q_to_b routine with minor ! 1074: * optimizations for HIL use. It is used because we don't have ! 1075: * to raise the priority to spltty() for most of the clist manipulations. ! 1076: */ ! 1077: hilq_to_b(q, cp, cc) ! 1078: register struct clist *q; ! 1079: register char *cp; ! 1080: { ! 1081: ! 1082: panic("hilq_to_b: missing body"); ! 1083: } ! 1084: ! 1085: /* ! 1086: * Cooked keyboard functions for ite driver. ! 1087: * There is only one "cooked" ITE keyboard (the first keyboard found) ! 1088: * per loop. There may be other keyboards, but they will always be "raw". ! 1089: */ ! 1090: ! 1091: kbdbell() ! 1092: { ! 1093: struct hilloop *hilp = &hil0; /* XXX */ ! 1094: ! 1095: hilbeep(hilp, &default_bell); ! 1096: } ! 1097: ! 1098: kbdenable() ! 1099: { ! 1100: struct hilloop *hilp = &hil0; /* XXX */ ! 1101: register struct hil_dev *hildevice = hilp->hl_addr; ! 1102: char db; ! 1103: ! 1104: /* Set the autorepeat rate register */ ! 1105: db = ar_format(KBD_ARR); ! 1106: send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL); ! 1107: ! 1108: /* Set the autorepeat delay register */ ! 1109: db = ar_format(KBD_ARD); ! 1110: send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL); ! 1111: ! 1112: /* Enable interrupts */ ! 1113: send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); ! 1114: } ! 1115: ! 1116: kbddisable() ! 1117: { ! 1118: } ! 1119: ! 1120: /* ! 1121: * XXX: read keyboard directly and return code. ! 1122: * Used by console getchar routine. Could really screw up anybody ! 1123: * reading from the keyboard in the normal, interrupt driven fashion. ! 1124: */ ! 1125: kbdgetc(statp) ! 1126: int *statp; ! 1127: { ! 1128: struct hilloop *hilp = &hil0; /* XXX */ ! 1129: register struct hil_dev *hildevice = hilp->hl_addr; ! 1130: register int c, stat; ! 1131: int s; ! 1132: ! 1133: s = splhil(); ! 1134: while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0) ! 1135: ; ! 1136: c = hildevice->hil_data; ! 1137: splx(s); ! 1138: *statp = stat; ! 1139: return(c); ! 1140: } ! 1141: ! 1142: /* ! 1143: * Recoginize and clear keyboard generated NMIs. ! 1144: * Returns 1 if it was ours, 0 otherwise. Note that we cannot use ! 1145: * send_hil_cmd() to issue the clear NMI command as that would actually ! 1146: * lower the priority to splimp() and it doesn't wait for the completion ! 1147: * of the command. Either of these conditions could result in the ! 1148: * interrupt reoccuring. Note that we issue the CNMT command twice. ! 1149: * This seems to be needed, once is not always enough!?! ! 1150: */ ! 1151: kbdnmi() ! 1152: { ! 1153: register struct hilloop *hilp = &hil0; /* XXX */ ! 1154: ! 1155: if ((*KBDNMISTAT & KBDNMI) == 0) ! 1156: return(0); ! 1157: HILWAIT(hilp->hl_addr); ! 1158: hilp->hl_addr->hil_cmd = HIL_CNMT; ! 1159: HILWAIT(hilp->hl_addr); ! 1160: hilp->hl_addr->hil_cmd = HIL_CNMT; ! 1161: HILWAIT(hilp->hl_addr); ! 1162: return(1); ! 1163: } ! 1164: ! 1165: #define HILSECURITY 0x33 ! 1166: #define HILIDENTIFY 0x03 ! 1167: #define HILSCBIT 0x04 ! 1168: ! 1169: /* ! 1170: * Called at boot time to print out info about interesting devices ! 1171: */ ! 1172: hilinfo(hilp) ! 1173: register struct hilloop *hilp; ! 1174: { ! 1175: register int id, len; ! 1176: register struct kbdmap *km; ! 1177: ! 1178: /* ! 1179: * Keyboard info. ! 1180: */ ! 1181: if (hilp->hl_kbddev) { ! 1182: printf("hil%d: ", hilp->hl_kbddev); ! 1183: for (km = kbd_map; km->kbd_code; km++) ! 1184: if (km->kbd_code == hilp->hl_kbdlang) { ! 1185: printf("%s ", km->kbd_desc); ! 1186: break; ! 1187: } ! 1188: printf("keyboard\n"); ! 1189: } ! 1190: /* ! 1191: * ID module. ! 1192: * Attempt to locate the first ID module and print out its ! 1193: * security code. Is this a good idea?? ! 1194: */ ! 1195: id = hiliddev(hilp); ! 1196: if (id) { ! 1197: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1198: hilp->hl_cmddev = id; ! 1199: send_hildev_cmd(hilp, id, HILSECURITY); ! 1200: len = hilp->hl_cmdbp - hilp->hl_cmdbuf; ! 1201: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1202: hilp->hl_cmddev = 0; ! 1203: printf("hil%d: security code", id); ! 1204: for (id = 0; id < len; id++) ! 1205: printf(" %x", hilp->hl_cmdbuf[id]); ! 1206: while (id++ < 16) ! 1207: printf(" 0"); ! 1208: printf("\n"); ! 1209: } ! 1210: } ! 1211: ! 1212: #define HILAR1 0x3E ! 1213: #define HILAR2 0x3F ! 1214: ! 1215: /* ! 1216: * Called after the loop has reconfigured. Here we need to: ! 1217: * - determine how many devices are on the loop ! 1218: * (some may have been added or removed) ! 1219: * - locate the ITE keyboard (if any) and ensure ! 1220: * that it is in the proper state (raw or cooked) ! 1221: * and is set to use the proper language mapping table ! 1222: * - ensure all other keyboards are raw ! 1223: * Note that our device state is now potentially invalid as ! 1224: * devices may no longer be where they were. What we should ! 1225: * do here is either track where the devices went and move ! 1226: * state around accordingly or, more simply, just mark all ! 1227: * devices as HIL_DERROR and don't allow any further use until ! 1228: * they are closed. This is a little too brutal for my tastes, ! 1229: * we prefer to just assume people won't move things around. ! 1230: */ ! 1231: hilconfig(hilp) ! 1232: register struct hilloop *hilp; ! 1233: { ! 1234: u_char db; ! 1235: int s; ! 1236: ! 1237: s = splhil(); ! 1238: #ifdef DEBUG ! 1239: if (hildebug & HDB_CONFIG) { ! 1240: printf("hilconfig: reconfigured: "); ! 1241: send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); ! 1242: printf("LPSTAT %x, ", db); ! 1243: send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db); ! 1244: printf("LPCTRL %x, ", db); ! 1245: send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); ! 1246: printf("KBDSADR %x\n", db); ! 1247: hilreport(hilp); ! 1248: } ! 1249: #endif ! 1250: /* ! 1251: * Determine how many devices are on the loop. ! 1252: * Mark those as alive and real, all others as dead. ! 1253: */ ! 1254: db = 0; ! 1255: send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); ! 1256: hilp->hl_maxdev = db & LPS_DEVMASK; ! 1257: for (db = 1; db < NHILD; db++) { ! 1258: if (db <= hilp->hl_maxdev) ! 1259: hilp->hl_device[db].hd_flags |= HIL_ALIVE; ! 1260: else ! 1261: hilp->hl_device[db].hd_flags &= ~HIL_ALIVE; ! 1262: hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO; ! 1263: } ! 1264: #ifdef DEBUG ! 1265: if (hildebug & (HDB_CONFIG|HDB_KEYBOARD)) ! 1266: printf("hilconfig: max device %d\n", hilp->hl_maxdev); ! 1267: #endif ! 1268: if (hilp->hl_maxdev == 0) { ! 1269: hilp->hl_kbddev = 0; ! 1270: splx(s); ! 1271: return; ! 1272: } ! 1273: /* ! 1274: * Find out where the keyboards are and record the ITE keyboard ! 1275: * (first one found). If no keyboards found, we are all done. ! 1276: */ ! 1277: db = 0; ! 1278: send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); ! 1279: #ifdef DEBUG ! 1280: if (hildebug & HDB_KEYBOARD) ! 1281: printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n", ! 1282: db, hilp->hl_kbddev, ffs((int)db)); ! 1283: #endif ! 1284: hilp->hl_kbddev = ffs((int)db); ! 1285: if (hilp->hl_kbddev == 0) { ! 1286: splx(s); ! 1287: return; ! 1288: } ! 1289: /* ! 1290: * Determine if the keyboard should be cooked or raw and configure it. ! 1291: */ ! 1292: db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1); ! 1293: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL); ! 1294: /* ! 1295: * Re-enable autorepeat in raw mode, cooked mode AR is not affected. ! 1296: */ ! 1297: if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) { ! 1298: db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2; ! 1299: hilp->hl_cmddev = hilp->hl_kbddev; ! 1300: send_hildev_cmd(hilp, hilp->hl_kbddev, db); ! 1301: hilp->hl_cmddev = 0; ! 1302: } ! 1303: /* ! 1304: * Determine the keyboard language configuration, but don't ! 1305: * override a user-specified setting. ! 1306: */ ! 1307: db = 0; ! 1308: send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db); ! 1309: #ifdef DEBUG ! 1310: if (hildebug & HDB_KEYBOARD) ! 1311: printf("hilconfig: language: old %x new %x\n", ! 1312: hilp->hl_kbdlang, db); ! 1313: #endif ! 1314: if (hilp->hl_kbdlang != KBD_SPECIAL) { ! 1315: struct kbdmap *km; ! 1316: ! 1317: for (km = kbd_map; km->kbd_code; km++) ! 1318: if (km->kbd_code == db) { ! 1319: hilp->hl_kbdlang = db; ! 1320: /* XXX */ ! 1321: kbd_keymap = km->kbd_keymap; ! 1322: kbd_shiftmap = km->kbd_shiftmap; ! 1323: kbd_ctrlmap = km->kbd_ctrlmap; ! 1324: kbd_ctrlshiftmap = km->kbd_ctrlshiftmap; ! 1325: kbd_stringmap = km->kbd_stringmap; ! 1326: } ! 1327: } ! 1328: splx(s); ! 1329: } ! 1330: ! 1331: hilreset(hilp) ! 1332: struct hilloop *hilp; ! 1333: { ! 1334: register struct hil_dev *hildevice = hilp->hl_addr; ! 1335: u_char db; ! 1336: ! 1337: /* ! 1338: * Initialize the loop: reconfigure, don't report errors, ! 1339: * cook keyboards, and enable autopolling. ! 1340: */ ! 1341: db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; ! 1342: send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL); ! 1343: /* ! 1344: * Delay one second for reconfiguration and then read the the ! 1345: * data register to clear the interrupt (if the loop reconfigured). ! 1346: */ ! 1347: DELAY(1000000); ! 1348: if (hildevice->hil_stat & HIL_DATA_RDY) ! 1349: db = hildevice->hil_data; ! 1350: /* ! 1351: * The HIL loop may have reconfigured. If so we proceed on, ! 1352: * if not we loop until a successful reconfiguration is reported ! 1353: * back to us. The HIL loop will continue to attempt forever. ! 1354: * Probably not very smart. ! 1355: */ ! 1356: do { ! 1357: send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db); ! 1358: } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0); ! 1359: /* ! 1360: * At this point, the loop should have reconfigured. ! 1361: * The reconfiguration interrupt has already called hilconfig() ! 1362: * so the keyboard has been determined. ! 1363: */ ! 1364: send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); ! 1365: } ! 1366: ! 1367: hilbeep(hilp, bp) ! 1368: struct hilloop *hilp; ! 1369: register struct _hilbell *bp; ! 1370: { ! 1371: u_char buf[2]; ! 1372: ! 1373: buf[0] = ~((bp->duration - 10) / 10); ! 1374: buf[1] = bp->frequency; ! 1375: send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL); ! 1376: } ! 1377: ! 1378: /* ! 1379: * Locate and return the address of the first ID module, 0 if none present. ! 1380: */ ! 1381: hiliddev(hilp) ! 1382: register struct hilloop *hilp; ! 1383: { ! 1384: register int i, len; ! 1385: ! 1386: #ifdef DEBUG ! 1387: if (hildebug & HDB_IDMODULE) ! 1388: printf("hiliddev(%x): looking for idmodule...", hilp); ! 1389: #endif ! 1390: for (i = 1; i <= hilp->hl_maxdev; i++) { ! 1391: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1392: hilp->hl_cmddev = i; ! 1393: send_hildev_cmd(hilp, i, HILIDENTIFY); ! 1394: /* ! 1395: * XXX: the final condition checks to ensure that the ! 1396: * device ID byte is in the range of the ID module (0x30-0x3F) ! 1397: */ ! 1398: len = hilp->hl_cmdbp - hilp->hl_cmdbuf; ! 1399: if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) && ! 1400: (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) { ! 1401: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1402: hilp->hl_cmddev = i; ! 1403: send_hildev_cmd(hilp, i, HILSECURITY); ! 1404: break; ! 1405: } ! 1406: } ! 1407: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1408: hilp->hl_cmddev = 0; ! 1409: #ifdef DEBUG ! 1410: if (hildebug & HDB_IDMODULE) ! 1411: if (i <= hilp->hl_maxdev) ! 1412: printf("found at %d\n", i); ! 1413: else ! 1414: printf("not found\n"); ! 1415: #endif ! 1416: return(i <= hilp->hl_maxdev ? i : 0); ! 1417: } ! 1418: ! 1419: /* ! 1420: * Low level routines which actually talk to the 8042 chip. ! 1421: */ ! 1422: ! 1423: /* ! 1424: * Send a command to the 8042 with zero or more bytes of data. ! 1425: * If rdata is non-null, wait for and return a byte of data. ! 1426: * We run at splimp() to make the transaction as atomic as ! 1427: * possible without blocking the clock (is this necessary?) ! 1428: */ ! 1429: send_hil_cmd(hildevice, cmd, data, dlen, rdata) ! 1430: register struct hil_dev *hildevice; ! 1431: u_char cmd, *data, dlen; ! 1432: u_char *rdata; ! 1433: { ! 1434: u_char status; ! 1435: int s = splimp(); ! 1436: ! 1437: HILWAIT(hildevice); ! 1438: hildevice->hil_cmd = cmd; ! 1439: while (dlen--) { ! 1440: HILWAIT(hildevice); ! 1441: hildevice->hil_data = *data++; ! 1442: } ! 1443: if (rdata) { ! 1444: do { ! 1445: HILDATAWAIT(hildevice); ! 1446: status = hildevice->hil_stat; ! 1447: *rdata = hildevice->hil_data; ! 1448: } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); ! 1449: } ! 1450: splx(s); ! 1451: } ! 1452: ! 1453: /* ! 1454: * Send a command to a device on the loop. ! 1455: * Since only one command can be active on the loop at any time, ! 1456: * we must ensure that we are not interrupted during this process. ! 1457: * Hence we mask interrupts to prevent potential access from most ! 1458: * interrupt routines and turn off auto-polling to disable the ! 1459: * internally generated poll commands. ! 1460: * ! 1461: * splhigh is extremely conservative but insures atomic operation, ! 1462: * splimp (clock only interrupts) seems to be good enough in practice. ! 1463: */ ! 1464: send_hildev_cmd(hilp, device, cmd) ! 1465: register struct hilloop *hilp; ! 1466: char device, cmd; ! 1467: { ! 1468: register struct hil_dev *hildevice = hilp->hl_addr; ! 1469: u_char status, c; ! 1470: int s = splimp(); ! 1471: ! 1472: polloff(hildevice); ! 1473: ! 1474: /* ! 1475: * Transfer the command and device info to the chip ! 1476: */ ! 1477: HILWAIT(hildevice); ! 1478: hildevice->hil_cmd = HIL_STARTCMD; ! 1479: HILWAIT(hildevice); ! 1480: hildevice->hil_data = 8 + device; ! 1481: HILWAIT(hildevice); ! 1482: hildevice->hil_data = cmd; ! 1483: HILWAIT(hildevice); ! 1484: hildevice->hil_data = HIL_TIMEOUT; ! 1485: /* ! 1486: * Trigger the command and wait for completion ! 1487: */ ! 1488: HILWAIT(hildevice); ! 1489: hildevice->hil_cmd = HIL_TRIGGER; ! 1490: hilp->hl_cmddone = FALSE; ! 1491: do { ! 1492: HILDATAWAIT(hildevice); ! 1493: status = hildevice->hil_stat; ! 1494: c = hildevice->hil_data; ! 1495: hil_process_int(status, c); ! 1496: } while (!hilp->hl_cmddone); ! 1497: ! 1498: pollon(hildevice); ! 1499: splx(s); ! 1500: } ! 1501: ! 1502: /* ! 1503: * Turn auto-polling off and on. ! 1504: * Also disables and enable auto-repeat. Why? ! 1505: */ ! 1506: polloff(hildevice) ! 1507: register struct hil_dev *hildevice; ! 1508: { ! 1509: register char db; ! 1510: ! 1511: /* ! 1512: * Turn off auto repeat ! 1513: */ ! 1514: HILWAIT(hildevice); ! 1515: hildevice->hil_cmd = HIL_SETARR; ! 1516: HILWAIT(hildevice); ! 1517: hildevice->hil_data = 0; ! 1518: /* ! 1519: * Turn off auto-polling ! 1520: */ ! 1521: HILWAIT(hildevice); ! 1522: hildevice->hil_cmd = HIL_READLPCTRL; ! 1523: HILDATAWAIT(hildevice); ! 1524: db = hildevice->hil_data; ! 1525: db &= ~LPC_AUTOPOLL; ! 1526: HILWAIT(hildevice); ! 1527: hildevice->hil_cmd = HIL_WRITELPCTRL; ! 1528: HILWAIT(hildevice); ! 1529: hildevice->hil_data = db; ! 1530: /* ! 1531: * Must wait til polling is really stopped ! 1532: */ ! 1533: do { ! 1534: HILWAIT(hildevice); ! 1535: hildevice->hil_cmd = HIL_READBUSY; ! 1536: HILDATAWAIT(hildevice); ! 1537: db = hildevice->hil_data; ! 1538: } while (db & BSY_LOOPBUSY); ! 1539: } ! 1540: ! 1541: pollon(hildevice) ! 1542: register struct hil_dev *hildevice; ! 1543: { ! 1544: register char db; ! 1545: ! 1546: /* ! 1547: * Turn on auto polling ! 1548: */ ! 1549: HILWAIT(hildevice); ! 1550: hildevice->hil_cmd = HIL_READLPCTRL; ! 1551: HILDATAWAIT(hildevice); ! 1552: db = hildevice->hil_data; ! 1553: db |= LPC_AUTOPOLL; ! 1554: HILWAIT(hildevice); ! 1555: hildevice->hil_cmd = HIL_WRITELPCTRL; ! 1556: HILWAIT(hildevice); ! 1557: hildevice->hil_data = db; ! 1558: /* ! 1559: * Turn on auto repeat ! 1560: */ ! 1561: HILWAIT(hildevice); ! 1562: hildevice->hil_cmd = HIL_SETARR; ! 1563: HILWAIT(hildevice); ! 1564: hildevice->hil_data = ar_format(KBD_ARR); ! 1565: } ! 1566: ! 1567: #ifdef DEBUG ! 1568: printhilpollbuf(hilp) ! 1569: register struct hilloop *hilp; ! 1570: { ! 1571: register u_char *cp; ! 1572: register int i, len; ! 1573: ! 1574: cp = hilp->hl_pollbuf; ! 1575: len = hilp->hl_pollbp - cp; ! 1576: for (i = 0; i < len; i++) ! 1577: printf("%x ", hilp->hl_pollbuf[i]); ! 1578: printf("\n"); ! 1579: } ! 1580: ! 1581: printhilcmdbuf(hilp) ! 1582: register struct hilloop *hilp; ! 1583: { ! 1584: register u_char *cp; ! 1585: register int i, len; ! 1586: ! 1587: cp = hilp->hl_cmdbuf; ! 1588: len = hilp->hl_cmdbp - cp; ! 1589: for (i = 0; i < len; i++) ! 1590: printf("%x ", hilp->hl_cmdbuf[i]); ! 1591: printf("\n"); ! 1592: } ! 1593: ! 1594: hilreport(hilp) ! 1595: register struct hilloop *hilp; ! 1596: { ! 1597: register int i, len; ! 1598: int s = splhil(); ! 1599: ! 1600: for (i = 1; i <= hilp->hl_maxdev; i++) { ! 1601: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1602: hilp->hl_cmddev = i; ! 1603: send_hildev_cmd(hilp, i, HILIDENTIFY); ! 1604: printf("hil%d: id: ", i); ! 1605: printhilcmdbuf(hilp); ! 1606: len = hilp->hl_cmdbp - hilp->hl_cmdbuf; ! 1607: if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) { ! 1608: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1609: hilp->hl_cmddev = i; ! 1610: send_hildev_cmd(hilp, i, HILSECURITY); ! 1611: printf("hil%d: sc: ", i); ! 1612: printhilcmdbuf(hilp); ! 1613: } ! 1614: } ! 1615: hilp->hl_cmdbp = hilp->hl_cmdbuf; ! 1616: hilp->hl_cmddev = 0; ! 1617: splx(s); ! 1618: } ! 1619: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.