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