FreeBSD/Linux Kernel Cross Reference
sys/i386at/kd_event.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: kd_event.c,v $
29 * Revision 2.10 93/11/17 16:51:04 dbg
30 * Use sys_clock instead of 'time'. Remove non-MACH_KERNEL code.
31 * ANSI-fy.
32 * [93/06/10 dbg]
33 *
34 * Revision 2.9 93/05/15 19:32:16 mrt
35 * machparam.h -> machspl.h
36 *
37 * Revision 2.8 93/01/14 17:31:23 danner
38 * Proper spl typing.
39 * [92/11/30 af]
40 *
41 * Revision 2.7 91/05/14 16:27:12 mrt
42 * Correcting copyright
43 *
44 * Revision 2.6 91/02/05 17:19:10 mrt
45 * Changed to new Mach copyright
46 * [91/02/01 17:45:36 mrt]
47 *
48 * Revision 2.5 90/11/26 14:50:31 rvb
49 * jsb beat me to XMK34, sigh ...
50 * [90/11/26 rvb]
51 * Synched 2.5 & 3.0 at I386q (r1.5.1.4) & XMK35 (r2.5)
52 * [90/11/15 rvb]
53 *
54 * Revision 2.4 90/08/09 16:32:32 rpd
55 * Added kdb/X support from rvb.
56 * [90/08/08 rpd]
57 *
58 * Revision 2.3 90/05/21 13:27:21 dbg
59 * Replace stub with real file, converted for pure kernel.
60 *
61 * Revision 1.5.1.3 90/05/14 13:21:36 rvb
62 * Support for entering kdb from X;
63 * [90/04/30 rvb]
64 *
65 * Revision 1.5.1.2 90/02/28 15:50:22 rvb
66 * Fix numerous typo's in Olivetti disclaimer.
67 * [90/02/28 rvb]
68 *
69 * Revision 1.5.1.1 90/01/08 13:30:51 rvb
70 * Add Olivetti copyright.
71 * [90/01/08 rvb]
72 *
73 * Revision 1.5 89/07/17 10:41:17 rvb
74 * Olivetti Changes to X79 upto 5/9/89:
75 * [89/07/11 rvb]
76 *
77 * Revision 1.4.1.1 89/04/27 12:21:11 kupfer
78 * Merge X79 with our latest and greatest.
79 *
80 * Revision 1.1.1.1 89/04/27 11:53:53 kupfer
81 * X79 from CMU.
82 *
83 * Revision 1.4 89/03/09 20:06:41 rpd
84 * More cleanup.
85 *
86 * Revision 1.3 89/02/26 12:42:31 gm0w
87 * Changes for cleanup.
88 *
89 */
90
91 /* **********************************************************************
92 File: kd_event.c
93 Description: Driver for event interface to keyboard.
94
95 $ Header: $
96
97 Copyright Ing. C. Olivetti & C. S.p.A. 1989. All rights reserved.
98 ********************************************************************** */
99 /*
100 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
101 Cupertino, California.
102
103 All Rights Reserved
104
105 Permission to use, copy, modify, and distribute this software and
106 its documentation for any purpose and without fee is hereby
107 granted, provided that the above copyright notice appears in all
108 copies and that both the copyright notice and this permission notice
109 appear in supporting documentation, and that the name of Olivetti
110 not be used in advertising or publicity pertaining to distribution
111 of the software without specific, written prior permission.
112
113 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
114 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
115 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
116 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
117 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
118 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
119 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
120 */
121
122 #include <mach/boolean.h>
123 #include <kern/clock.h>
124 #include <kern/kern_io.h>
125 #include <kern/memory.h>
126 #include <sys/types.h>
127 #include <device/errno.h>
128 #include <device/ds_routines.h>
129 #include <device/io_req.h>
130 #include <i386/machspl.h>
131 #include <i386/pio.h>
132 #include <i386at/kd.h>
133 #include <i386at/kd_queue.h>
134
135 /*
136 * Code for /dev/kbd. The interrupt processing is done in kd.c,
137 * which calls into this module to enqueue scancode events when
138 * the keyboard is in Event mode.
139 */
140
141 /*
142 * Note: These globals are protected by raising the interrupt level
143 * via SPLKD.
144 */
145
146 kd_event_queue kbd_queue; /* queue of keyboard events */
147 queue_head_t kbd_read_queue = { &kbd_read_queue, &kbd_read_queue };
148
149 void kbd_enqueue(kd_event *);
150
151 io_return_t X_kdb_enter_init();
152 io_return_t X_kdb_exit_init();
153
154 static boolean_t initialized = FALSE;
155
156
157 /*
158 * kbdinit - set up event queue.
159 */
160
161 void kbdinit(void)
162 {
163 spl_t s = SPLKD();
164
165 if (!initialized) {
166 kdq_reset(&kbd_queue);
167 initialized = TRUE;
168 }
169 splx(s);
170 }
171
172
173 /*
174 * kbdopen - Verify that open is read-only and remember process
175 * group leader.
176 */
177
178 /*ARGSUSED*/
179 io_return_t kbdopen(
180 int dev)
181 {
182 if (dev != 0)
183 return D_NO_SUCH_DEVICE;
184
185 kbdinit();
186 return D_SUCCESS;
187 }
188
189
190 /*
191 * kbdclose - Make sure that the kd driver is in Ascii mode and
192 * reset various flags.
193 */
194
195 /*ARGSUSED*/
196 io_return_t kbdclose(
197 int dev)
198 {
199 spl_t s = SPLKD();
200
201 kb_mode = KB_ASCII;
202 kdq_reset(&kbd_queue);
203 splx(s);
204
205 return D_SUCCESS;
206 }
207
208
209 io_return_t kbdgetstat(
210 int dev,
211 int flavor,
212 dev_status_t *data, /* pointer to OUT array */
213 natural_t *count) /* OUT */
214 {
215 switch (flavor) {
216 case KDGKBDTYPE:
217 *data = KB_VANILLAKB;
218 *count = 1;
219 break;
220 default:
221 return D_INVALID_OPERATION;
222 }
223 return D_SUCCESS;
224 }
225
226 io_return_t kbdsetstat(
227 int dev,
228 int flavor,
229 dev_status_t data,
230 natural_t count)
231 {
232 switch (flavor) {
233 case KDSKBDMODE:
234 kb_mode = *data;
235 /* XXX - what to do about unread events? */
236 /* XXX - should check that 'data' contains an OK valud */
237 break;
238 case K_X_KDB_ENTER:
239 return X_kdb_enter_init(data, count);
240 case K_X_KDB_EXIT:
241 return X_kdb_exit_init(data, count);
242 default:
243 return D_INVALID_OPERATION;
244 }
245 return D_SUCCESS;
246 }
247
248 /*
249 * kbdread - dequeue and return any queued events.
250 */
251
252 boolean_t kbd_read_done(io_req_t); /* forward */
253
254 io_return_t kbdread(
255 int dev,
256 register io_req_t ior)
257 {
258 register int err, count;
259 register spl_t s;
260
261 err = device_read_alloc(ior, (vm_size_t)ior->io_count);
262 if (err != KERN_SUCCESS)
263 return err;
264
265 s = SPLKD();
266 if (kdq_empty(&kbd_queue)) {
267 if (ior->io_mode & D_NOWAIT) {
268 splx(s);
269 return D_WOULD_BLOCK;
270 }
271 ior->io_done = kbd_read_done;
272 enqueue_tail(&kbd_read_queue, (queue_entry_t) ior);
273 splx(s);
274 return D_IO_QUEUED;
275 }
276 count = 0;
277 while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
278 register kd_event *ev;
279
280 ev = kdq_get(&kbd_queue);
281 *(kd_event *)(&ior->io_data[count]) = *ev;
282 count += sizeof(kd_event);
283 }
284 splx(s);
285 ior->io_residual = ior->io_count - count;
286 return D_SUCCESS;
287 }
288
289 boolean_t kbd_read_done(
290 register io_req_t ior)
291 {
292 register int count;
293 register spl_t s;
294
295 s = SPLKD();
296 if (kdq_empty(&kbd_queue)) {
297 ior->io_done = kbd_read_done;
298 enqueue_tail(&kbd_read_queue, (queue_entry_t)ior);
299 splx(s);
300 return FALSE;
301 }
302
303 count = 0;
304 while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
305 register kd_event *ev;
306
307 ev = kdq_get(&kbd_queue);
308 *(kd_event *)(&ior->io_data[count]) = *ev;
309 count += sizeof(kd_event);
310 }
311 splx(s);
312
313 ior->io_residual = ior->io_count - count;
314 ds_read_done(ior);
315
316 return TRUE;
317 }
318
319
320 /*
321 * kd_enqsc - enqueue a scancode. Should be called at SPLKD.
322 */
323
324 void
325 kd_enqsc(
326 Scancode sc)
327 {
328 kd_event ev;
329 time_spec_t cur_time;
330
331 clock_read(cur_time, sys_clock);
332
333 ev.type = KEYBD_EVENT;
334 ev.time.seconds = cur_time.seconds;
335 ev.time.microseconds = cur_time.nanoseconds / 1000;
336 ev.value.sc = sc;
337 kbd_enqueue(&ev);
338 }
339
340
341 /*
342 * kbd_enqueue - enqueue an event and wake up selecting processes, if
343 * any. Should be called at SPLKD.
344 */
345
346 void
347 kbd_enqueue(
348 kd_event *ev)
349 {
350 register io_req_t ior;
351
352 if (kdq_full(&kbd_queue))
353 printf("kbd: queue full\n");
354 else
355 kdq_put(&kbd_queue, ev);
356
357 while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0)
358 iodone(ior);
359 }
360
361 unsigned int X_kdb_enter_str[512], X_kdb_exit_str[512];
362 int X_kdb_enter_len = 0, X_kdb_exit_len = 0;
363
364 void kdb_in_out(
365 unsigned int *p)
366 {
367 register int t = p[0];
368
369 switch (t & K_X_TYPE) {
370 case K_X_IN|K_X_BYTE:
371 inb(t & K_X_PORT);
372 break;
373
374 case K_X_IN|K_X_WORD:
375 inw(t & K_X_PORT);
376 break;
377
378 case K_X_IN|K_X_LONG:
379 inl(t & K_X_PORT);
380 break;
381
382 case K_X_OUT|K_X_BYTE:
383 outb(t & K_X_PORT, p[1]);
384 break;
385
386 case K_X_OUT|K_X_WORD:
387 outw(t & K_X_PORT, p[1]);
388 break;
389
390 case K_X_OUT|K_X_LONG:
391 outl(t & K_X_PORT, p[1]);
392 break;
393 }
394 }
395
396 void X_kdb_enter()
397 {
398 register unsigned int *u_ip, *endp;
399
400 for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len];
401 u_ip < endp;
402 u_ip += 2)
403 kdb_in_out(u_ip);
404 }
405
406 void X_kdb_exit()
407 {
408 register unsigned int *u_ip, *endp;
409
410 for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len];
411 u_ip < endp;
412 u_ip += 2)
413 kdb_in_out(u_ip);
414 }
415
416 io_return_t
417 X_kdb_enter_init(
418 unsigned int *data,
419 natural_t count)
420 {
421 if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str)
422 return D_INVALID_OPERATION;
423
424 bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]);
425 X_kdb_enter_len = count;
426 return D_SUCCESS;
427 }
428
429 io_return_t
430 X_kdb_exit_init(
431 unsigned int *data,
432 natural_t count)
433 {
434 if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str)
435 return D_INVALID_OPERATION;
436
437 bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]);
438 X_kdb_exit_len = count;
439 return D_SUCCESS;
440 }
Cache object: b9699a2d5b44e894240b35f75ed3a59e
|