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