|
|
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;
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:
223: #else MACH_KERNEL
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 */
294:
295: splx(s);
296: return(0);
297: }
298: #endif MACH_KERNEL
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:
377: #else MACH_KERNEL
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;
393: } else
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: }
414: #endif MACH_KERNEL
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: }
454: #else MACH_KERNEL
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);
463: #endif MACH_KERNEL
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: }
547: #else MACH_KERNEL
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: }
569: #endif MACH_KERNEL
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.