|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ********************************************************************** ! 27: File: kd_event.c ! 28: Description: Driver for event interface to keyboard. ! 29: ! 30: $ Header: $ ! 31: ! 32: Copyright Ing. C. Olivetti & C. S.p.A. 1989. All rights reserved. ! 33: ********************************************************************** */ ! 34: /* ! 35: Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., ! 36: Cupertino, California. ! 37: ! 38: All Rights Reserved ! 39: ! 40: Permission to use, copy, modify, and distribute this software and ! 41: its documentation for any purpose and without fee is hereby ! 42: granted, provided that the above copyright notice appears in all ! 43: copies and that both the copyright notice and this permission notice ! 44: appear in supporting documentation, and that the name of Olivetti ! 45: not be used in advertising or publicity pertaining to distribution ! 46: of the software without specific, written prior permission. ! 47: ! 48: OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 49: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, ! 50: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 51: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 52: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 53: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION ! 54: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 55: */ ! 56: ! 57: #include <mach/boolean.h> ! 58: #include <sys/types.h> ! 59: #ifdef MACH_KERNEL ! 60: #include <device/errno.h> ! 61: #include <device/io_req.h> ! 62: #else MACH_KERNEL ! 63: #include <sys/file.h> ! 64: #include <sys/errno.h> ! 65: #include <kern/thread.h> ! 66: #include <sys/user.h> ! 67: #include <sys/proc.h> ! 68: #include <sys/kernel.h> ! 69: #include <sys/ioctl.h> ! 70: #include <sys/tty.h> ! 71: #endif MACH_KERNEL ! 72: #include <i386/machspl.h> ! 73: #include <i386at/kd.h> ! 74: #include <i386at/kd_queue.h> ! 75: ! 76: /* ! 77: * Code for /dev/kbd. The interrupt processing is done in kd.c, ! 78: * which calls into this module to enqueue scancode events when ! 79: * the keyboard is in Event mode. ! 80: */ ! 81: ! 82: /* ! 83: * Note: These globals are protected by raising the interrupt level ! 84: * via SPLKD. ! 85: */ ! 86: ! 87: kd_event_queue kbd_queue; /* queue of keyboard events */ ! 88: #ifdef MACH_KERNEL ! 89: queue_head_t kbd_read_queue = { &kbd_read_queue, &kbd_read_queue }; ! 90: #else MACH_KERNEL ! 91: struct proc *kbd_sel = 0; /* selecting process, if any */ ! 92: short kbdpgrp = 0; /* process group leader when dev is open */ ! 93: ! 94: int kbdflag = 0; ! 95: #define KBD_COLL 1 /* select collision */ ! 96: #define KBD_ASYNC 2 /* user wants asynch notification */ ! 97: #define KBD_NBIO 4 /* user wants non-blocking I/O */ ! 98: #endif MACH_KERNEL ! 99: ! 100: ! 101: void kbd_enqueue(); ! 102: #ifdef MACH_KERNEL ! 103: io_return_t X_kdb_enter_init(); ! 104: io_return_t X_kdb_exit_init(); ! 105: #endif MACH_KERNEL ! 106: ! 107: static boolean_t initialized = FALSE; ! 108: ! 109: ! 110: /* ! 111: * kbdinit - set up event queue. ! 112: */ ! 113: ! 114: kbdinit() ! 115: { ! 116: spl_t s = SPLKD(); ! 117: ! 118: if (!initialized) { ! 119: kdq_reset(&kbd_queue); ! 120: initialized = TRUE; ! 121: } ! 122: splx(s); ! 123: } ! 124: ! 125: ! 126: /* ! 127: * kbdopen - Verify that open is read-only and remember process ! 128: * group leader. ! 129: */ ! 130: ! 131: /*ARGSUSED*/ ! 132: kbdopen(dev, flags) ! 133: dev_t dev; ! 134: int flags; ! 135: { ! 136: kbdinit(); ! 137: ! 138: #ifdef MACH_KERNEL ! 139: #else MACH_KERNEL ! 140: if (flags & FWRITE) ! 141: return(ENODEV); ! 142: ! 143: if (kbdpgrp == 0) ! 144: kbdpgrp = u.u_procp->p_pgrp; ! 145: #endif MACH_KERNEL ! 146: return(0); ! 147: } ! 148: ! 149: ! 150: /* ! 151: * kbdclose - Make sure that the kd driver is in Ascii mode and ! 152: * reset various flags. ! 153: */ ! 154: ! 155: /*ARGSUSED*/ ! 156: kbdclose(dev, flags) ! 157: dev_t dev; ! 158: int flags; ! 159: { ! 160: spl_t s = SPLKD(); ! 161: ! 162: kb_mode = KB_ASCII; ! 163: #ifdef MACH_KERNEL ! 164: #else MACH_KERNEL ! 165: kbdpgrp = 0; ! 166: kbdflag = 0; ! 167: kbd_sel = 0; ! 168: #endif MACH_KERNEL ! 169: kdq_reset(&kbd_queue); ! 170: splx(s); ! 171: } ! 172: ! 173: ! 174: #ifdef MACH_KERNEL ! 175: io_return_t kbdgetstat(dev, flavor, data, count) ! 176: dev_t dev; ! 177: int flavor; ! 178: int * data; /* pointer to OUT array */ ! 179: unsigned int *count; /* OUT */ ! 180: { ! 181: io_return_t result; ! 182: ! 183: switch (flavor) { ! 184: case KDGKBDTYPE: ! 185: *data = KB_VANILLAKB; ! 186: *count = 1; ! 187: break; ! 188: default: ! 189: return (D_INVALID_OPERATION); ! 190: } ! 191: return (D_SUCCESS); ! 192: } ! 193: ! 194: io_return_t kbdsetstat(dev, flavor, data, count) ! 195: dev_t dev; ! 196: int flavor; ! 197: int * data; ! 198: unsigned int count; ! 199: { ! 200: io_return_t result; ! 201: ! 202: switch (flavor) { ! 203: case KDSKBDMODE: ! 204: kb_mode = *data; ! 205: /* XXX - what to do about unread events? */ ! 206: /* XXX - should check that 'data' contains an OK valud */ ! 207: break; ! 208: case K_X_KDB_ENTER: ! 209: return X_kdb_enter_init(data, count); ! 210: case K_X_KDB_EXIT: ! 211: return X_kdb_exit_init(data, count); ! 212: default: ! 213: return (D_INVALID_OPERATION); ! 214: } ! 215: return (D_SUCCESS); ! 216: } ! 217: ! 218: #else MACH_KERNEL ! 219: /* ! 220: * kbdioctl - handling for asynch & non-blocking I/O. ! 221: */ ! 222: ! 223: /*ARGSUSED*/ ! 224: kbdioctl(dev, cmd, data, flag) ! 225: dev_t dev; ! 226: int cmd; ! 227: caddr_t data; ! 228: int flag; ! 229: { ! 230: spl_t s = SPLKD(); ! 231: int err = 0; ! 232: ! 233: switch (cmd) { ! 234: case KDSKBDMODE: ! 235: kb_mode = *(int *)data; ! 236: /* XXX - what to do about unread events? */ ! 237: /* XXX - should check that "data" contains an OK value */ ! 238: break; ! 239: case KDGKBDTYPE: ! 240: *(int *)data = KB_VANILLAKB; ! 241: break; ! 242: case K_X_KDB_ENTER: ! 243: X_kdb_enter_init((struct X_kdb *) data); ! 244: break; ! 245: case K_X_KDB_EXIT: ! 246: X_kdb_exit_init( (struct X_kdb *) data); ! 247: break; ! 248: case FIONBIO: ! 249: if (*(int *)data) ! 250: kbdflag |= KBD_NBIO; ! 251: else ! 252: kbdflag &= ~KBD_NBIO; ! 253: break; ! 254: case FIOASYNC: ! 255: if (*(int *)data) ! 256: kbdflag |= KBD_ASYNC; ! 257: else ! 258: kbdflag &= ~KBD_ASYNC; ! 259: break; ! 260: default: ! 261: err = ENOTTY; ! 262: break; ! 263: } ! 264: ! 265: splx(s); ! 266: return(err); ! 267: } ! 268: ! 269: ! 270: /* ! 271: * kbdselect ! 272: */ ! 273: ! 274: /*ARGSUSED*/ ! 275: kbdselect(dev, rw) ! 276: { ! 277: spl_t s = SPLKD(); ! 278: ! 279: if (!kdq_empty(&kbd_queue)) { ! 280: splx(s); ! 281: return(1); ! 282: } ! 283: ! 284: if (kbd_sel) ! 285: kbdflag |= KBD_COLL; ! 286: else ! 287: kbd_sel = (struct proc *)current_thread(); ! 288: /* eeeyuck */ ! 289: ! 290: splx(s); ! 291: return(0); ! 292: } ! 293: #endif MACH_KERNEL ! 294: ! 295: ! 296: /* ! 297: * kbdread - dequeue and return any queued events. ! 298: */ ! 299: ! 300: #ifdef MACH_KERNEL ! 301: boolean_t kbd_read_done(); /* forward */ ! 302: ! 303: kbdread(dev, ior) ! 304: dev_t dev; ! 305: register io_req_t ior; ! 306: { ! 307: register int err, count; ! 308: register spl_t s; ! 309: ! 310: err = device_read_alloc(ior, (vm_size_t)ior->io_count); ! 311: if (err != KERN_SUCCESS) ! 312: return (err); ! 313: ! 314: s = SPLKD(); ! 315: if (kdq_empty(&kbd_queue)) { ! 316: if (ior->io_mode & D_NOWAIT) { ! 317: splx(s); ! 318: return (D_WOULD_BLOCK); ! 319: } ! 320: ior->io_done = kbd_read_done; ! 321: enqueue_tail(&kbd_read_queue, (queue_entry_t) ior); ! 322: splx(s); ! 323: return (D_IO_QUEUED); ! 324: } ! 325: count = 0; ! 326: while (!kdq_empty(&kbd_queue) && count < ior->io_count) { ! 327: register kd_event *ev; ! 328: ! 329: ev = kdq_get(&kbd_queue); ! 330: *(kd_event *)(&ior->io_data[count]) = *ev; ! 331: count += sizeof(kd_event); ! 332: } ! 333: splx(s); ! 334: ior->io_residual = ior->io_count - count; ! 335: return (D_SUCCESS); ! 336: } ! 337: ! 338: boolean_t kbd_read_done(ior) ! 339: register io_req_t ior; ! 340: { ! 341: register int count; ! 342: register spl_t s; ! 343: ! 344: s = SPLKD(); ! 345: if (kdq_empty(&kbd_queue)) { ! 346: ior->io_done = kbd_read_done; ! 347: enqueue_tail(&kbd_read_queue, (queue_entry_t)ior); ! 348: splx(s); ! 349: return (FALSE); ! 350: } ! 351: ! 352: count = 0; ! 353: while (!kdq_empty(&kbd_queue) && count < ior->io_count) { ! 354: register kd_event *ev; ! 355: ! 356: ev = kdq_get(&kbd_queue); ! 357: *(kd_event *)(&ior->io_data[count]) = *ev; ! 358: count += sizeof(kd_event); ! 359: } ! 360: splx(s); ! 361: ! 362: ior->io_residual = ior->io_count - count; ! 363: ds_read_done(ior); ! 364: ! 365: return (TRUE); ! 366: } ! 367: ! 368: #else MACH_KERNEL ! 369: /*ARGSUSED*/ ! 370: kbdread(dev, uio) ! 371: dev_t dev; ! 372: struct uio *uio; ! 373: { ! 374: int s = SPLKD(); ! 375: int err = 0; ! 376: kd_event *ev; ! 377: int i; ! 378: char *cp; ! 379: ! 380: if (kdq_empty(&kbd_queue)) ! 381: if (kbdflag & KBD_NBIO) { ! 382: err = EWOULDBLOCK; ! 383: goto done; ! 384: } else ! 385: while (kdq_empty(&kbd_queue)) { ! 386: splx(s); ! 387: sleep((caddr_t)&kbd_queue, TTIPRI); ! 388: s = SPLKD(); ! 389: } ! 390: ! 391: while (!kdq_empty(&kbd_queue) && uio->uio_resid >= sizeof(kd_event)) { ! 392: ev = kdq_get(&kbd_queue); ! 393: for (cp = (char *)ev, i = 0; i < sizeof(kd_event); ! 394: ++i, ++cp) { ! 395: err = ureadc(*cp, uio); ! 396: if (err) ! 397: goto done; ! 398: } ! 399: } ! 400: ! 401: done: ! 402: splx(s); ! 403: return(err); ! 404: } ! 405: #endif MACH_KERNEL ! 406: ! 407: ! 408: /* ! 409: * kd_enqsc - enqueue a scancode. Should be called at SPLKD. ! 410: */ ! 411: ! 412: void ! 413: kd_enqsc(sc) ! 414: Scancode sc; ! 415: { ! 416: kd_event ev; ! 417: ! 418: ev.type = KEYBD_EVENT; ! 419: ev.time = time; ! 420: ev.value.sc = sc; ! 421: kbd_enqueue(&ev); ! 422: } ! 423: ! 424: ! 425: /* ! 426: * kbd_enqueue - enqueue an event and wake up selecting processes, if ! 427: * any. Should be called at SPLKD. ! 428: */ ! 429: ! 430: void ! 431: kbd_enqueue(ev) ! 432: kd_event *ev; ! 433: { ! 434: if (kdq_full(&kbd_queue)) ! 435: printf("kbd: queue full\n"); ! 436: else ! 437: kdq_put(&kbd_queue, ev); ! 438: ! 439: #ifdef MACH_KERNEL ! 440: { ! 441: register io_req_t ior; ! 442: while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0) ! 443: iodone(ior); ! 444: } ! 445: #else MACH_KERNEL ! 446: if (kbd_sel) { ! 447: selwakeup(kbd_sel, kbdflag & KBD_COLL); ! 448: kbd_sel = 0; ! 449: kbdflag &= ~KBD_COLL; ! 450: } ! 451: if (kbdflag & KBD_ASYNC) ! 452: gsignal(kbdpgrp, SIGIO); ! 453: wakeup((caddr_t)&kbd_queue); ! 454: #endif MACH_KERNEL ! 455: } ! 456: ! 457: u_int X_kdb_enter_str[512], X_kdb_exit_str[512]; ! 458: int X_kdb_enter_len = 0, X_kdb_exit_len = 0; ! 459: ! 460: kdb_in_out(p) ! 461: u_int *p; ! 462: { ! 463: register int t = p[0]; ! 464: ! 465: switch (t & K_X_TYPE) { ! 466: case K_X_IN|K_X_BYTE: ! 467: inb(t & K_X_PORT); ! 468: break; ! 469: ! 470: case K_X_IN|K_X_WORD: ! 471: inw(t & K_X_PORT); ! 472: break; ! 473: ! 474: case K_X_IN|K_X_LONG: ! 475: inl(t & K_X_PORT); ! 476: break; ! 477: ! 478: case K_X_OUT|K_X_BYTE: ! 479: outb(t & K_X_PORT, p[1]); ! 480: break; ! 481: ! 482: case K_X_OUT|K_X_WORD: ! 483: outw(t & K_X_PORT, p[1]); ! 484: break; ! 485: ! 486: case K_X_OUT|K_X_LONG: ! 487: outl(t & K_X_PORT, p[1]); ! 488: break; ! 489: } ! 490: } ! 491: ! 492: X_kdb_enter() ! 493: { ! 494: register u_int *u_ip, *endp; ! 495: ! 496: for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len]; ! 497: u_ip < endp; ! 498: u_ip += 2) ! 499: kdb_in_out(u_ip); ! 500: } ! 501: ! 502: X_kdb_exit() ! 503: { ! 504: register u_int *u_ip, *endp; ! 505: ! 506: for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len]; ! 507: u_ip < endp; ! 508: u_ip += 2) ! 509: kdb_in_out(u_ip); ! 510: } ! 511: ! 512: #ifdef MACH_KERNEL ! 513: io_return_t ! 514: X_kdb_enter_init(data, count) ! 515: u_int *data; ! 516: u_int count; ! 517: { ! 518: if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str) ! 519: return D_INVALID_OPERATION; ! 520: ! 521: bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]); ! 522: X_kdb_enter_len = count; ! 523: return D_SUCCESS; ! 524: } ! 525: ! 526: io_return_t ! 527: X_kdb_exit_init(data, count) ! 528: u_int *data; ! 529: u_int count; ! 530: { ! 531: if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str) ! 532: return D_INVALID_OPERATION; ! 533: ! 534: bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]); ! 535: X_kdb_exit_len = count; ! 536: return D_SUCCESS; ! 537: } ! 538: #else MACH_KERNEL ! 539: X_kdb_enter_init(kp) ! 540: struct X_kdb *kp; ! 541: { ! 542: if (kp->size > sizeof X_kdb_enter_str) ! 543: u.u_error = ENOENT; ! 544: else if(copyin(kp->ptr, X_kdb_enter_str, kp->size) == EFAULT) ! 545: u.u_error = EFAULT; ! 546: ! 547: X_kdb_enter_len = kp->size>>2; ! 548: } ! 549: ! 550: X_kdb_exit_init(kp) ! 551: struct X_kdb *kp; ! 552: { ! 553: if (kp->size > sizeof X_kdb_exit_str) ! 554: u.u_error = ENOENT; ! 555: else if(copyin(kp->ptr, X_kdb_exit_str, kp->size) == EFAULT) ! 556: u.u_error = EFAULT; ! 557: ! 558: X_kdb_exit_len = kp->size>>2; ! 559: } ! 560: #endif MACH_KERNEL
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.