|
|
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.