|
|
1.1.1.3 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.3 ! root 5: * 1.1 root 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. 1.1.1.3 ! root 11: * 1.1 root 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. 1.1.1.3 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.3 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.3 ! root 22: * 1.1 root 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> 1.1.1.3 ! root 62: #else /* MACH_KERNEL */ 1.1 root 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> 1.1.1.3 ! root 71: #endif /* MACH_KERNEL */ 1.1 root 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 }; 1.1.1.3 ! root 90: #else /* MACH_KERNEL */ 1.1 root 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 */ 1.1.1.3 ! root 98: #endif /* MACH_KERNEL */ 1.1 root 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(); 1.1.1.3 ! root 105: #endif /* MACH_KERNEL */ 1.1 root 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(); 1.1.1.3 ! root 117: 1.1 root 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 1.1.1.3 ! root 139: #else /* MACH_KERNEL */ 1.1 root 140: if (flags & FWRITE) 141: return(ENODEV); 1.1.1.3 ! root 142: 1.1 root 143: if (kbdpgrp == 0) 144: kbdpgrp = u.u_procp->p_pgrp; 1.1.1.3 ! root 145: #endif /* MACH_KERNEL */ 1.1 root 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 1.1.1.3 ! root 164: #else /* MACH_KERNEL */ 1.1 root 165: kbdpgrp = 0; 166: kbdflag = 0; 167: kbd_sel = 0; 1.1.1.3 ! root 168: #endif /* MACH_KERNEL */ 1.1 root 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; 1.1.1.2 root 188: case DEV_GET_SIZE: 189: data[DEV_GET_SIZE_DEVICE_SIZE] = 0; 190: data[DEV_GET_SIZE_RECORD_SIZE] = sizeof(kd_event); 191: *count = DEV_GET_SIZE_COUNT; 192: break; 1.1 root 193: default: 194: return (D_INVALID_OPERATION); 195: } 196: return (D_SUCCESS); 197: } 198: 199: io_return_t kbdsetstat(dev, flavor, data, count) 200: dev_t dev; 201: int flavor; 202: int * data; 203: unsigned int count; 204: { 205: io_return_t result; 206: 207: switch (flavor) { 208: case KDSKBDMODE: 209: kb_mode = *data; 210: /* XXX - what to do about unread events? */ 211: /* XXX - should check that 'data' contains an OK valud */ 212: break; 213: case K_X_KDB_ENTER: 214: return X_kdb_enter_init(data, count); 215: case K_X_KDB_EXIT: 216: return X_kdb_exit_init(data, count); 217: default: 218: return (D_INVALID_OPERATION); 219: } 220: return (D_SUCCESS); 221: } 222: 1.1.1.3 ! root 223: #else /* MACH_KERNEL */ 1.1 root 224: /* 225: * kbdioctl - handling for asynch & non-blocking I/O. 226: */ 227: 228: /*ARGSUSED*/ 229: kbdioctl(dev, cmd, data, flag) 230: dev_t dev; 231: int cmd; 232: caddr_t data; 233: int flag; 234: { 235: spl_t s = SPLKD(); 236: int err = 0; 237: 238: switch (cmd) { 239: case KDSKBDMODE: 240: kb_mode = *(int *)data; 241: /* XXX - what to do about unread events? */ 242: /* XXX - should check that "data" contains an OK value */ 243: break; 244: case KDGKBDTYPE: 245: *(int *)data = KB_VANILLAKB; 246: break; 247: case K_X_KDB_ENTER: 248: X_kdb_enter_init((struct X_kdb *) data); 249: break; 250: case K_X_KDB_EXIT: 251: X_kdb_exit_init( (struct X_kdb *) data); 252: break; 253: case FIONBIO: 254: if (*(int *)data) 255: kbdflag |= KBD_NBIO; 256: else 257: kbdflag &= ~KBD_NBIO; 258: break; 259: case FIOASYNC: 260: if (*(int *)data) 261: kbdflag |= KBD_ASYNC; 262: else 263: kbdflag &= ~KBD_ASYNC; 264: break; 265: default: 266: err = ENOTTY; 267: break; 268: } 269: 270: splx(s); 271: return(err); 272: } 273: 274: 275: /* 276: * kbdselect 277: */ 278: 279: /*ARGSUSED*/ 280: kbdselect(dev, rw) 281: { 282: spl_t s = SPLKD(); 283: 284: if (!kdq_empty(&kbd_queue)) { 285: splx(s); 286: return(1); 287: } 288: 289: if (kbd_sel) 290: kbdflag |= KBD_COLL; 291: else 292: kbd_sel = (struct proc *)current_thread(); 293: /* eeeyuck */ 1.1.1.3 ! root 294: 1.1 root 295: splx(s); 296: return(0); 297: } 1.1.1.3 ! root 298: #endif /* MACH_KERNEL */ 1.1 root 299: 300: 301: /* 302: * kbdread - dequeue and return any queued events. 303: */ 304: 305: #ifdef MACH_KERNEL 306: boolean_t kbd_read_done(); /* forward */ 307: 308: kbdread(dev, ior) 309: dev_t dev; 310: register io_req_t ior; 311: { 312: register int err, count; 313: register spl_t s; 314: 1.1.1.2 root 315: /* Check if IO_COUNT is a multiple of the record size. */ 316: if (ior->io_count % sizeof(kd_event) != 0) 317: return D_INVALID_SIZE; 318: 1.1 root 319: err = device_read_alloc(ior, (vm_size_t)ior->io_count); 320: if (err != KERN_SUCCESS) 321: return (err); 322: 323: s = SPLKD(); 324: if (kdq_empty(&kbd_queue)) { 325: if (ior->io_mode & D_NOWAIT) { 326: splx(s); 327: return (D_WOULD_BLOCK); 328: } 329: ior->io_done = kbd_read_done; 330: enqueue_tail(&kbd_read_queue, (queue_entry_t) ior); 331: splx(s); 332: return (D_IO_QUEUED); 333: } 334: count = 0; 335: while (!kdq_empty(&kbd_queue) && count < ior->io_count) { 336: register kd_event *ev; 337: 338: ev = kdq_get(&kbd_queue); 339: *(kd_event *)(&ior->io_data[count]) = *ev; 340: count += sizeof(kd_event); 341: } 342: splx(s); 343: ior->io_residual = ior->io_count - count; 344: return (D_SUCCESS); 345: } 346: 347: boolean_t kbd_read_done(ior) 348: register io_req_t ior; 349: { 350: register int count; 351: register spl_t s; 352: 353: s = SPLKD(); 354: if (kdq_empty(&kbd_queue)) { 355: ior->io_done = kbd_read_done; 356: enqueue_tail(&kbd_read_queue, (queue_entry_t)ior); 357: splx(s); 358: return (FALSE); 359: } 360: 361: count = 0; 362: while (!kdq_empty(&kbd_queue) && count < ior->io_count) { 363: register kd_event *ev; 364: 365: ev = kdq_get(&kbd_queue); 366: *(kd_event *)(&ior->io_data[count]) = *ev; 367: count += sizeof(kd_event); 368: } 369: splx(s); 370: 371: ior->io_residual = ior->io_count - count; 372: ds_read_done(ior); 373: 374: return (TRUE); 375: } 376: 1.1.1.3 ! root 377: #else /* MACH_KERNEL */ 1.1 root 378: /*ARGSUSED*/ 379: kbdread(dev, uio) 380: dev_t dev; 381: struct uio *uio; 382: { 383: int s = SPLKD(); 384: int err = 0; 385: kd_event *ev; 386: int i; 387: char *cp; 388: 389: if (kdq_empty(&kbd_queue)) 390: if (kbdflag & KBD_NBIO) { 391: err = EWOULDBLOCK; 392: goto done; 1.1.1.3 ! root 393: } else 1.1 root 394: while (kdq_empty(&kbd_queue)) { 395: splx(s); 396: sleep((caddr_t)&kbd_queue, TTIPRI); 397: s = SPLKD(); 398: } 399: 400: while (!kdq_empty(&kbd_queue) && uio->uio_resid >= sizeof(kd_event)) { 401: ev = kdq_get(&kbd_queue); 402: for (cp = (char *)ev, i = 0; i < sizeof(kd_event); 403: ++i, ++cp) { 404: err = ureadc(*cp, uio); 405: if (err) 406: goto done; 407: } 408: } 409: 410: done: 411: splx(s); 412: return(err); 413: } 1.1.1.3 ! root 414: #endif /* MACH_KERNEL */ 1.1 root 415: 416: 417: /* 418: * kd_enqsc - enqueue a scancode. Should be called at SPLKD. 419: */ 420: 421: void 422: kd_enqsc(sc) 423: Scancode sc; 424: { 425: kd_event ev; 426: 427: ev.type = KEYBD_EVENT; 428: ev.time = time; 429: ev.value.sc = sc; 430: kbd_enqueue(&ev); 431: } 432: 433: 434: /* 435: * kbd_enqueue - enqueue an event and wake up selecting processes, if 436: * any. Should be called at SPLKD. 437: */ 438: 439: void 440: kbd_enqueue(ev) 441: kd_event *ev; 442: { 443: if (kdq_full(&kbd_queue)) 444: printf("kbd: queue full\n"); 445: else 446: kdq_put(&kbd_queue, ev); 447: 448: #ifdef MACH_KERNEL 449: { 450: register io_req_t ior; 451: while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0) 452: iodone(ior); 453: } 1.1.1.3 ! root 454: #else /* MACH_KERNEL */ 1.1 root 455: if (kbd_sel) { 456: selwakeup(kbd_sel, kbdflag & KBD_COLL); 457: kbd_sel = 0; 458: kbdflag &= ~KBD_COLL; 459: } 460: if (kbdflag & KBD_ASYNC) 461: gsignal(kbdpgrp, SIGIO); 462: wakeup((caddr_t)&kbd_queue); 1.1.1.3 ! root 463: #endif /* MACH_KERNEL */ 1.1 root 464: } 465: 466: u_int X_kdb_enter_str[512], X_kdb_exit_str[512]; 467: int X_kdb_enter_len = 0, X_kdb_exit_len = 0; 468: 469: kdb_in_out(p) 470: u_int *p; 471: { 472: register int t = p[0]; 473: 474: switch (t & K_X_TYPE) { 475: case K_X_IN|K_X_BYTE: 476: inb(t & K_X_PORT); 477: break; 478: 479: case K_X_IN|K_X_WORD: 480: inw(t & K_X_PORT); 481: break; 482: 483: case K_X_IN|K_X_LONG: 484: inl(t & K_X_PORT); 485: break; 486: 487: case K_X_OUT|K_X_BYTE: 488: outb(t & K_X_PORT, p[1]); 489: break; 490: 491: case K_X_OUT|K_X_WORD: 492: outw(t & K_X_PORT, p[1]); 493: break; 494: 495: case K_X_OUT|K_X_LONG: 496: outl(t & K_X_PORT, p[1]); 497: break; 498: } 499: } 500: 501: X_kdb_enter() 502: { 503: register u_int *u_ip, *endp; 504: 505: for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len]; 506: u_ip < endp; 507: u_ip += 2) 508: kdb_in_out(u_ip); 509: } 510: 511: X_kdb_exit() 512: { 513: register u_int *u_ip, *endp; 514: 515: for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len]; 516: u_ip < endp; 517: u_ip += 2) 518: kdb_in_out(u_ip); 519: } 520: 521: #ifdef MACH_KERNEL 522: io_return_t 523: X_kdb_enter_init(data, count) 524: u_int *data; 525: u_int count; 526: { 527: if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str) 528: return D_INVALID_OPERATION; 529: 530: bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]); 531: X_kdb_enter_len = count; 532: return D_SUCCESS; 533: } 534: 535: io_return_t 536: X_kdb_exit_init(data, count) 537: u_int *data; 538: u_int count; 539: { 540: if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str) 541: return D_INVALID_OPERATION; 542: 543: bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]); 544: X_kdb_exit_len = count; 545: return D_SUCCESS; 546: } 1.1.1.3 ! root 547: #else /* MACH_KERNEL */ 1.1 root 548: X_kdb_enter_init(kp) 549: struct X_kdb *kp; 550: { 551: if (kp->size > sizeof X_kdb_enter_str) 552: u.u_error = ENOENT; 553: else if(copyin(kp->ptr, X_kdb_enter_str, kp->size) == EFAULT) 554: u.u_error = EFAULT; 555: 556: X_kdb_enter_len = kp->size>>2; 557: } 558: 559: X_kdb_exit_init(kp) 560: struct X_kdb *kp; 561: { 562: if (kp->size > sizeof X_kdb_exit_str) 563: u.u_error = ENOENT; 564: else if(copyin(kp->ptr, X_kdb_exit_str, kp->size) == EFAULT) 565: u.u_error = EFAULT; 566: 567: X_kdb_exit_len = kp->size>>2; 568: } 1.1.1.3 ! root 569: #endif /* MACH_KERNEL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.