|
|
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>
1.1.1.4 ! root 59: #include <kern/printf.h>
! 60: #include <string.h>
! 61:
! 62: #include <device/ds_routines.h>
! 63: #include <device/device_types.h>
1.1 root 64: #include <device/io_req.h>
65: #include <i386/machspl.h>
1.1.1.4 ! root 66: #include <i386/pio.h>
1.1 root 67: #include <i386at/kd.h>
68: #include <i386at/kd_queue.h>
69:
1.1.1.4 ! root 70: #include "kd_event.h"
! 71:
1.1 root 72: /*
73: * Code for /dev/kbd. The interrupt processing is done in kd.c,
74: * which calls into this module to enqueue scancode events when
75: * the keyboard is in Event mode.
76: */
77:
78: /*
79: * Note: These globals are protected by raising the interrupt level
80: * via SPLKD.
81: */
82:
83: kd_event_queue kbd_queue; /* queue of keyboard events */
84: queue_head_t kbd_read_queue = { &kbd_read_queue, &kbd_read_queue };
85:
86:
87: void kbd_enqueue();
88: io_return_t X_kdb_enter_init();
89: io_return_t X_kdb_exit_init();
90:
91: static boolean_t initialized = FALSE;
92:
93:
94: /*
95: * kbdinit - set up event queue.
96: */
97:
1.1.1.4 ! root 98: void
1.1 root 99: kbdinit()
100: {
101: spl_t s = SPLKD();
1.1.1.3 root 102:
1.1 root 103: if (!initialized) {
104: kdq_reset(&kbd_queue);
105: initialized = TRUE;
106: }
107: splx(s);
108: }
109:
110:
111: /*
112: * kbdopen - Verify that open is read-only and remember process
113: * group leader.
114: */
115:
116: /*ARGSUSED*/
1.1.1.4 ! root 117: int
1.1 root 118: kbdopen(dev, flags)
119: dev_t dev;
120: int flags;
121: {
1.1.1.4 ! root 122: spl_t o_pri = spltty();
! 123: kdinit();
! 124: splx(o_pri);
1.1 root 125: kbdinit();
126:
127: return(0);
128: }
129:
130:
131: /*
132: * kbdclose - Make sure that the kd driver is in Ascii mode and
133: * reset various flags.
134: */
135:
136: /*ARGSUSED*/
1.1.1.4 ! root 137: void
1.1 root 138: kbdclose(dev, flags)
139: dev_t dev;
140: int flags;
141: {
142: spl_t s = SPLKD();
143:
144: kb_mode = KB_ASCII;
145: kdq_reset(&kbd_queue);
146: splx(s);
147: }
148:
149:
150: io_return_t kbdgetstat(dev, flavor, data, count)
151: dev_t dev;
152: int flavor;
153: int * data; /* pointer to OUT array */
154: unsigned int *count; /* OUT */
155: {
156: switch (flavor) {
157: case KDGKBDTYPE:
158: *data = KB_VANILLAKB;
159: *count = 1;
160: break;
1.1.1.2 root 161: case DEV_GET_SIZE:
162: data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
163: data[DEV_GET_SIZE_RECORD_SIZE] = sizeof(kd_event);
164: *count = DEV_GET_SIZE_COUNT;
165: break;
1.1 root 166: default:
167: return (D_INVALID_OPERATION);
168: }
169: return (D_SUCCESS);
170: }
171:
172: io_return_t kbdsetstat(dev, flavor, data, count)
173: dev_t dev;
174: int flavor;
175: int * data;
176: unsigned int count;
177: {
178: switch (flavor) {
179: case KDSKBDMODE:
180: kb_mode = *data;
181: /* XXX - what to do about unread events? */
182: /* XXX - should check that 'data' contains an OK valud */
183: break;
1.1.1.4 ! root 184: case KDSETLEDS:
! 185: if (count != 1)
! 186: return (D_INVALID_OPERATION);
! 187: kd_setleds1 (*data);
! 188: break;
1.1 root 189: case K_X_KDB_ENTER:
190: return X_kdb_enter_init(data, count);
191: case K_X_KDB_EXIT:
192: return X_kdb_exit_init(data, count);
193: default:
194: return (D_INVALID_OPERATION);
195: }
196: return (D_SUCCESS);
197: }
198:
199:
200:
201: /*
202: * kbdread - dequeue and return any queued events.
203: */
204:
205: boolean_t kbd_read_done(); /* forward */
206:
1.1.1.4 ! root 207: int
1.1 root 208: kbdread(dev, ior)
209: dev_t dev;
210: register io_req_t ior;
211: {
212: register int err, count;
213: register spl_t s;
214:
1.1.1.2 root 215: /* Check if IO_COUNT is a multiple of the record size. */
216: if (ior->io_count % sizeof(kd_event) != 0)
217: return D_INVALID_SIZE;
218:
1.1 root 219: err = device_read_alloc(ior, (vm_size_t)ior->io_count);
220: if (err != KERN_SUCCESS)
221: return (err);
222:
223: s = SPLKD();
224: if (kdq_empty(&kbd_queue)) {
225: if (ior->io_mode & D_NOWAIT) {
226: splx(s);
227: return (D_WOULD_BLOCK);
228: }
229: ior->io_done = kbd_read_done;
230: enqueue_tail(&kbd_read_queue, (queue_entry_t) ior);
231: splx(s);
232: return (D_IO_QUEUED);
233: }
234: count = 0;
235: while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
236: register kd_event *ev;
237:
238: ev = kdq_get(&kbd_queue);
239: *(kd_event *)(&ior->io_data[count]) = *ev;
240: count += sizeof(kd_event);
241: }
242: splx(s);
243: ior->io_residual = ior->io_count - count;
244: return (D_SUCCESS);
245: }
246:
247: boolean_t kbd_read_done(ior)
248: register io_req_t ior;
249: {
250: register int count;
251: register spl_t s;
252:
253: s = SPLKD();
254: if (kdq_empty(&kbd_queue)) {
255: ior->io_done = kbd_read_done;
256: enqueue_tail(&kbd_read_queue, (queue_entry_t)ior);
257: splx(s);
258: return (FALSE);
259: }
260:
261: count = 0;
262: while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
263: register kd_event *ev;
264:
265: ev = kdq_get(&kbd_queue);
266: *(kd_event *)(&ior->io_data[count]) = *ev;
267: count += sizeof(kd_event);
268: }
269: splx(s);
270:
271: ior->io_residual = ior->io_count - count;
272: ds_read_done(ior);
273:
274: return (TRUE);
275: }
276:
277:
278:
279: /*
280: * kd_enqsc - enqueue a scancode. Should be called at SPLKD.
281: */
282:
283: void
284: kd_enqsc(sc)
285: Scancode sc;
286: {
287: kd_event ev;
288:
289: ev.type = KEYBD_EVENT;
290: ev.time = time;
291: ev.value.sc = sc;
292: kbd_enqueue(&ev);
293: }
294:
295:
296: /*
297: * kbd_enqueue - enqueue an event and wake up selecting processes, if
298: * any. Should be called at SPLKD.
299: */
300:
301: void
302: kbd_enqueue(ev)
303: kd_event *ev;
304: {
305: if (kdq_full(&kbd_queue))
306: printf("kbd: queue full\n");
307: else
308: kdq_put(&kbd_queue, ev);
309:
310: {
311: register io_req_t ior;
312: while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0)
313: iodone(ior);
314: }
315: }
316:
317: u_int X_kdb_enter_str[512], X_kdb_exit_str[512];
318: int X_kdb_enter_len = 0, X_kdb_exit_len = 0;
319:
1.1.1.4 ! root 320: void
1.1 root 321: kdb_in_out(p)
322: u_int *p;
323: {
324: register int t = p[0];
325:
326: switch (t & K_X_TYPE) {
327: case K_X_IN|K_X_BYTE:
328: inb(t & K_X_PORT);
329: break;
330:
331: case K_X_IN|K_X_WORD:
332: inw(t & K_X_PORT);
333: break;
334:
335: case K_X_IN|K_X_LONG:
336: inl(t & K_X_PORT);
337: break;
338:
339: case K_X_OUT|K_X_BYTE:
340: outb(t & K_X_PORT, p[1]);
341: break;
342:
343: case K_X_OUT|K_X_WORD:
344: outw(t & K_X_PORT, p[1]);
345: break;
346:
347: case K_X_OUT|K_X_LONG:
348: outl(t & K_X_PORT, p[1]);
349: break;
350: }
351: }
352:
1.1.1.4 ! root 353: void
1.1 root 354: X_kdb_enter()
355: {
356: register u_int *u_ip, *endp;
357:
358: for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len];
359: u_ip < endp;
360: u_ip += 2)
361: kdb_in_out(u_ip);
362: }
363:
1.1.1.4 ! root 364: void
1.1 root 365: X_kdb_exit()
366: {
367: register u_int *u_ip, *endp;
368:
369: for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len];
370: u_ip < endp;
371: u_ip += 2)
372: kdb_in_out(u_ip);
373: }
374:
375: io_return_t
376: X_kdb_enter_init(data, count)
377: u_int *data;
378: u_int count;
379: {
380: if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str)
381: return D_INVALID_OPERATION;
382:
1.1.1.4 ! root 383: memcpy(X_kdb_enter_str, data, count * sizeof X_kdb_enter_str[0]);
1.1 root 384: X_kdb_enter_len = count;
385: return D_SUCCESS;
386: }
387:
388: io_return_t
389: X_kdb_exit_init(data, count)
390: u_int *data;
391: u_int count;
392: {
393: if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str)
394: return D_INVALID_OPERATION;
395:
1.1.1.4 ! root 396: memcpy(X_kdb_exit_str, data, count * sizeof X_kdb_exit_str[0]);
1.1 root 397: X_kdb_exit_len = count;
398: return D_SUCCESS;
399: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.