source: branches/minix3-book/drivers/tty/keyboard.c

Last change on this file was 4, checked in by Mattia Monga, 14 years ago

Importazione sorgenti libro

File size: 21.7 KB
RevLine 
[4]1/* Keyboard driver for PC's and AT's.
2 *
3 * Changes:
4 * Jul 13, 2004 processes can observe function keys (Jorrit N. Herder)
5 * Jun 15, 2004 removed wreboot(), except panic dumps (Jorrit N. Herder)
6 * Feb 04, 1994 loadable keymaps (Marcus Hampel)
7 */
8
9#include "../drivers.h"
10#include <sys/time.h>
11#include <sys/select.h>
12#include <termios.h>
13#include <signal.h>
14#include <unistd.h>
15#include <minix/callnr.h>
16#include <minix/com.h>
17#include <minix/keymap.h>
18#include "tty.h"
19#include "keymaps/us-std.src"
20#include "../../kernel/const.h"
21#include "../../kernel/config.h"
22#include "../../kernel/type.h"
23#include "../../kernel/proc.h"
24
25int irq_hook_id = -1;
26
27/* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */
28#define KEYBD 0x60 /* I/O port for keyboard data */
29
30/* AT keyboard. */
31#define KB_COMMAND 0x64 /* I/O port for commands on AT */
32#define KB_STATUS 0x64 /* I/O port for status on AT */
33#define KB_ACK 0xFA /* keyboard ack response */
34#define KB_OUT_FULL 0x01 /* status bit set when keypress char pending */
35#define KB_IN_FULL 0x02 /* status bit set when not ready to receive */
36#define LED_CODE 0xED /* command to keyboard to set LEDs */
37#define MAX_KB_ACK_RETRIES 0x1000 /* max #times to wait for kb ack */
38#define MAX_KB_BUSY_RETRIES 0x1000 /* max #times to loop while kb busy */
39#define KBIT 0x80 /* bit used to ack characters to keyboard */
40
41/* Miscellaneous. */
42#define ESC_SCAN 0x01 /* reboot key when panicking */
43#define SLASH_SCAN 0x35 /* to recognize numeric slash */
44#define RSHIFT_SCAN 0x36 /* to distinguish left and right shift */
45#define HOME_SCAN 0x47 /* first key on the numeric keypad */
46#define INS_SCAN 0x52 /* INS for use in CTRL-ALT-INS reboot */
47#define DEL_SCAN 0x53 /* DEL for use in CTRL-ALT-DEL reboot */
48
49#define CONSOLE 0 /* line number for console */
50#define KB_IN_BYTES 32 /* size of keyboard input buffer */
51PRIVATE char ibuf[KB_IN_BYTES]; /* input buffer */
52PRIVATE char *ihead = ibuf; /* next free spot in input buffer */
53PRIVATE char *itail = ibuf; /* scan code to return to TTY */
54PRIVATE int icount; /* # codes in buffer */
55
56PRIVATE int esc; /* escape scan code detected? */
57PRIVATE int alt_l; /* left alt key state */
58PRIVATE int alt_r; /* right alt key state */
59PRIVATE int alt; /* either alt key */
60PRIVATE int ctrl_l; /* left control key state */
61PRIVATE int ctrl_r; /* right control key state */
62PRIVATE int ctrl; /* either control key */
63PRIVATE int shift_l; /* left shift key state */
64PRIVATE int shift_r; /* right shift key state */
65PRIVATE int shift; /* either shift key */
66PRIVATE int num_down; /* num lock key depressed */
67PRIVATE int caps_down; /* caps lock key depressed */
68PRIVATE int scroll_down; /* scroll lock key depressed */
69PRIVATE int locks[NR_CONS]; /* per console lock keys state */
70
71/* Lock key active bits. Chosen to be equal to the keyboard LED bits. */
72#define SCROLL_LOCK 0x01
73#define NUM_LOCK 0x02
74#define CAPS_LOCK 0x04
75
76PRIVATE char numpad_map[] =
77 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
78
79/* Variables and definition for observed function keys. */
80typedef struct observer { int proc_nr; int events; } obs_t;
81PRIVATE obs_t fkey_obs[12]; /* observers for F1-F12 */
82PRIVATE obs_t sfkey_obs[12]; /* observers for SHIFT F1-F12 */
83
84FORWARD _PROTOTYPE( int kb_ack, (void) );
85FORWARD _PROTOTYPE( int kb_wait, (void) );
86FORWARD _PROTOTYPE( int func_key, (int scode) );
87FORWARD _PROTOTYPE( int scan_keyboard, (void) );
88FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
89FORWARD _PROTOTYPE( void set_leds, (void) );
90FORWARD _PROTOTYPE( void show_key_mappings, (void) );
91FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
92FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
93
94/*===========================================================================*
95 * map_key0 *
96 *===========================================================================*/
97/* Map a scan code to an ASCII code ignoring modifiers. */
98#define map_key0(scode) \
99 ((unsigned) keymap[(scode) * MAP_COLS])
100
101/*===========================================================================*
102 * map_key *
103 *===========================================================================*/
104PRIVATE unsigned map_key(scode)
105int scode;
106{
107/* Map a scan code to an ASCII code. */
108
109 int caps, column, lk;
110 u16_t *keyrow;
111
112 if (scode == SLASH_SCAN && esc) return '/'; /* don't map numeric slash */
113
114 keyrow = &keymap[scode * MAP_COLS];
115
116 caps = shift;
117 lk = locks[ccurrent];
118 if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
119 if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;
120
121 if (alt) {
122 column = 2;
123 if (ctrl || alt_r) column = 3; /* Ctrl + Alt == AltGr */
124 if (caps) column = 4;
125 } else {
126 column = 0;
127 if (caps) column = 1;
128 if (ctrl) column = 5;
129 }
130 return keyrow[column] & ~HASCAPS;
131}
132
133/*===========================================================================*
134 * kbd_interrupt *
135 *===========================================================================*/
136PUBLIC void kbd_interrupt(m_ptr)
137message *m_ptr;
138{
139/* A keyboard interrupt has occurred. Process it. */
140 int scode;
141 static timer_t timer; /* timer must be static! */
142
143 /* Fetch the character from the keyboard hardware and acknowledge it. */
144 scode = scan_keyboard();
145
146 /* Store the scancode in memory so the task can get at it later. */
147 if (icount < KB_IN_BYTES) {
148 *ihead++ = scode;
149 if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
150 icount++;
151 tty_table[ccurrent].tty_events = 1;
152 if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
153 select_retry(&tty_table[ccurrent]);
154 }
155 }
156}
157
158/*===========================================================================*
159 * kb_read *
160 *===========================================================================*/
161PRIVATE int kb_read(tp, try)
162tty_t *tp;
163int try;
164{
165/* Process characters from the circular keyboard buffer. */
166 char buf[3];
167 int scode;
168 unsigned ch;
169
170 tp = &tty_table[ccurrent]; /* always use the current console */
171
172 if (try) {
173 if (icount > 0) return 1;
174 return 0;
175 }
176
177 while (icount > 0) {
178 scode = *itail++; /* take one key scan code */
179 if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
180 icount--;
181
182 /* Function keys are being used for debug dumps. */
183 if (func_key(scode)) continue;
184
185 /* Perform make/break processing. */
186 ch = make_break(scode);
187
188 if (ch <= 0xFF) {
189 /* A normal character. */
190 buf[0] = ch;
191 (void) in_process(tp, buf, 1);
192 } else
193 if (HOME <= ch && ch <= INSRT) {
194 /* An ASCII escape sequence generated by the numeric pad. */
195 buf[0] = ESC;
196 buf[1] = '[';
197 buf[2] = numpad_map[ch - HOME];
198 (void) in_process(tp, buf, 3);
199 } else
200 if (ch == ALEFT) {
201 /* Choose lower numbered console as current console. */
202 select_console(ccurrent - 1);
203 set_leds();
204 } else
205 if (ch == ARIGHT) {
206 /* Choose higher numbered console as current console. */
207 select_console(ccurrent + 1);
208 set_leds();
209 } else
210 if (AF1 <= ch && ch <= AF12) {
211 /* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
212 select_console(ch - AF1);
213 set_leds();
214 } else
215 if (CF1 <= ch && ch <= CF12) {
216 switch(ch) {
217 case CF1: show_key_mappings(); break;
218 case CF3: toggle_scroll(); break; /* hardware <-> software */
219 case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;
220 case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;
221 case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;
222 }
223 }
224 }
225
226 return 1;
227}
228
229/*===========================================================================*
230 * make_break *
231 *===========================================================================*/
232PRIVATE unsigned make_break(scode)
233int scode; /* scan code of key just struck or released */
234{
235/* This routine can handle keyboards that interrupt only on key depression,
236 * as well as keyboards that interrupt on key depression and key release.
237 * For efficiency, the interrupt routine filters out most key releases.
238 */
239 int ch, make, escape;
240 static int CAD_count = 0;
241
242 /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
243 * be better done in keyboard() in case TTY is hung, except control and
244 * alt are set in the high level code.
245 */
246 if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))
247 {
248 if (++CAD_count == 3) sys_abort(RBT_HALT);
249 sys_kill(INIT_PROC_NR, SIGABRT);
250 return -1;
251 }
252
253 /* High-order bit set on key release. */
254 make = (scode & KEY_RELEASE) == 0; /* true if pressed */
255
256 ch = map_key(scode &= ASCII_MASK); /* map to ASCII */
257
258 escape = esc; /* Key is escaped? (true if added since the XT) */
259 esc = 0;
260
261 switch (ch) {
262 case CTRL: /* Left or right control key */
263 *(escape ? &ctrl_r : &ctrl_l) = make;
264 ctrl = ctrl_l | ctrl_r;
265 break;
266 case SHIFT: /* Left or right shift key */
267 *(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;
268 shift = shift_l | shift_r;
269 break;
270 case ALT: /* Left or right alt key */
271 *(escape ? &alt_r : &alt_l) = make;
272 alt = alt_l | alt_r;
273 break;
274 case CALOCK: /* Caps lock - toggle on 0 -> 1 transition */
275 if (caps_down < make) {
276 locks[ccurrent] ^= CAPS_LOCK;
277 set_leds();
278 }
279 caps_down = make;
280 break;
281 case NLOCK: /* Num lock */
282 if (num_down < make) {
283 locks[ccurrent] ^= NUM_LOCK;
284 set_leds();
285 }
286 num_down = make;
287 break;
288 case SLOCK: /* Scroll lock */
289 if (scroll_down < make) {
290 locks[ccurrent] ^= SCROLL_LOCK;
291 set_leds();
292 }
293 scroll_down = make;
294 break;
295 case EXTKEY: /* Escape keycode */
296 esc = 1; /* Next key is escaped */
297 return(-1);
298 default: /* A normal key */
299 if (make) return(ch);
300 }
301
302 /* Key release, or a shift type key. */
303 return(-1);
304}
305
306/*===========================================================================*
307 * set_leds *
308 *===========================================================================*/
309PRIVATE void set_leds()
310{
311/* Set the LEDs on the caps, num, and scroll lock keys */
312 int s;
313 if (! machine.pc_at) return; /* PC/XT doesn't have LEDs */
314
315 kb_wait(); /* wait for buffer empty */
316 if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
317 printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);
318 /* prepare keyboard to accept LED values */
319 kb_ack(); /* wait for ack response */
320
321 kb_wait(); /* wait for buffer empty */
322 if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)
323 printf("Warning, sys_outb couldn't give LED values: %d\n", s);
324 /* give keyboard LED values */
325 kb_ack(); /* wait for ack response */
326}
327
328/*===========================================================================*
329 * kb_wait *
330 *===========================================================================*/
331PRIVATE int kb_wait()
332{
333/* Wait until the controller is ready; return zero if this times out. */
334
335 int retries, status, temp;
336 int s;
337
338 retries = MAX_KB_BUSY_RETRIES + 1; /* wait until not busy */
339 do {
340 s = sys_inb(KB_STATUS, &status);
341 if (status & KB_OUT_FULL) {
342 s = sys_inb(KEYBD, &temp); /* discard value */
343 }
344 if (! (status & (KB_IN_FULL|KB_OUT_FULL)) )
345 break; /* wait until ready */
346 } while (--retries != 0); /* continue unless timeout */
347 return(retries); /* zero on timeout, positive if ready */
348}
349
350/*===========================================================================*
351 * kb_ack *
352 *===========================================================================*/
353PRIVATE int kb_ack()
354{
355/* Wait until kbd acknowledges last command; return zero if this times out. */
356
357 int retries, s;
358 u8_t u8val;
359
360 retries = MAX_KB_ACK_RETRIES + 1;
361 do {
362 s = sys_inb(KEYBD, &u8val);
363 if (u8val == KB_ACK)
364 break; /* wait for ack */
365 } while(--retries != 0); /* continue unless timeout */
366
367 return(retries); /* nonzero if ack received */
368}
369
370/*===========================================================================*
371 * kb_init *
372 *===========================================================================*/
373PUBLIC void kb_init(tp)
374tty_t *tp;
375{
376/* Initialize the keyboard driver. */
377
378 tp->tty_devread = kb_read; /* input function */
379}
380
381/*===========================================================================*
382 * kb_init_once *
383 *===========================================================================*/
384PUBLIC void kb_init_once(void)
385{
386 int i;
387
388 set_leds(); /* turn off numlock led */
389 scan_keyboard(); /* discard leftover keystroke */
390
391 /* Clear the function key observers array. Also see func_key(). */
392 for (i=0; i<12; i++) {
393 fkey_obs[i].proc_nr = NONE; /* F1-F12 observers */
394 fkey_obs[i].events = 0; /* F1-F12 observers */
395 sfkey_obs[i].proc_nr = NONE; /* Shift F1-F12 observers */
396 sfkey_obs[i].events = 0; /* Shift F1-F12 observers */
397 }
398
399 /* Set interrupt handler and enable keyboard IRQ. */
400 irq_hook_id = KEYBOARD_IRQ; /* id to be returned on interrupt */
401 if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK)
402 panic("TTY", "Couldn't set keyboard IRQ policy", i);
403 if ((i=sys_irqenable(&irq_hook_id)) != OK)
404 panic("TTY", "Couldn't enable keyboard IRQs", i);
405 kbd_irq_set |= (1 << KEYBOARD_IRQ);
406}
407
408/*===========================================================================*
409 * kbd_loadmap *
410 *===========================================================================*/
411PUBLIC int kbd_loadmap(m)
412message *m;
413{
414/* Load a new keymap. */
415 int result;
416 result = sys_vircopy(m->PROC_NR, D, (vir_bytes) m->ADDRESS,
417 SELF, D, (vir_bytes) keymap,
418 (vir_bytes) sizeof(keymap));
419 return(result);
420}
421
422/*===========================================================================*
423 * do_fkey_ctl *
424 *===========================================================================*/
425PUBLIC void do_fkey_ctl(m_ptr)
426message *m_ptr; /* pointer to the request message */
427{
428/* This procedure allows processes to register a function key to receive
429 * notifications if it is pressed. At most one binding per key can exist.
430 */
431 int i;
432 int result;
433
434 switch (m_ptr->FKEY_REQUEST) { /* see what we must do */
435 case FKEY_MAP: /* request for new mapping */
436 result = OK; /* assume everything will be ok*/
437 for (i=0; i < 12; i++) { /* check F1-F12 keys */
438 if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
439 if (fkey_obs[i].proc_nr == NONE) {
440 fkey_obs[i].proc_nr = m_ptr->m_source;
441 fkey_obs[i].events = 0;
442 bit_unset(m_ptr->FKEY_FKEYS, i+1);
443 } else {
444 printf("WARNING, fkey_map failed F%d\n", i+1);
445 result = EBUSY; /* report failure, but try rest */
446 }
447 }
448 }
449 for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */
450 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
451 if (sfkey_obs[i].proc_nr == NONE) {
452 sfkey_obs[i].proc_nr = m_ptr->m_source;
453 sfkey_obs[i].events = 0;
454 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
455 } else {
456 printf("WARNING, fkey_map failed Shift F%d\n", i+1);
457 result = EBUSY; /* report failure but try rest */
458 }
459 }
460 }
461 break;
462 case FKEY_UNMAP:
463 result = OK; /* assume everything will be ok*/
464 for (i=0; i < 12; i++) { /* check F1-F12 keys */
465 if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
466 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
467 fkey_obs[i].proc_nr = NONE;
468 fkey_obs[i].events = 0;
469 bit_unset(m_ptr->FKEY_FKEYS, i+1);
470 } else {
471 result = EPERM; /* report failure, but try rest */
472 }
473 }
474 }
475 for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */
476 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
477 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
478 sfkey_obs[i].proc_nr = NONE;
479 sfkey_obs[i].events = 0;
480 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
481 } else {
482 result = EPERM; /* report failure, but try rest */
483 }
484 }
485 }
486 break;
487 case FKEY_EVENTS:
488 m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0;
489 for (i=0; i < 12; i++) { /* check (Shift+) F1-F12 keys */
490 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
491 if (fkey_obs[i].events) {
492 bit_set(m_ptr->FKEY_FKEYS, i+1);
493 fkey_obs[i].events = 0;
494 }
495 }
496 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
497 if (sfkey_obs[i].events) {
498 bit_set(m_ptr->FKEY_SFKEYS, i+1);
499 sfkey_obs[i].events = 0;
500 }
501 }
502 }
503 break;
504 default:
505 result = EINVAL; /* key cannot be observed */
506 }
507
508 /* Almost done, return result to caller. */
509 m_ptr->m_type = result;
510 send(m_ptr->m_source, m_ptr);
511}
512
513/*===========================================================================*
514 * func_key *
515 *===========================================================================*/
516PRIVATE int func_key(scode)
517int scode; /* scan code for a function key */
518{
519/* This procedure traps function keys for debugging purposes. Observers of
520 * function keys are kept in a global array. If a subject (a key) is pressed
521 * the observer is notified of the event. Initialization of the arrays is done
522 * in kb_init, where NONE is set to indicate there is no interest in the key.
523 * Returns FALSE on a key release or if the key is not observable.
524 */
525 message m;
526 int key;
527 int proc_nr;
528 int i,s;
529
530 /* Ignore key releases. If this is a key press, get full key code. */
531 if (scode & KEY_RELEASE) return(FALSE); /* key release */
532 key = map_key(scode); /* include modifiers */
533
534 /* Key pressed, now see if there is an observer for the pressed key.
535 * F1-F12 observers are in fkey_obs array.
536 * SHIFT F1-F12 observers are in sfkey_req array.
537 * CTRL F1-F12 reserved (see kb_read)
538 * ALT F1-F12 reserved (see kb_read)
539 * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet
540 * defined in <minix/keymap.h>, and thus is easy for future extensions.
541 */
542 if (F1 <= key && key <= F12) { /* F1-F12 */
543 proc_nr = fkey_obs[key - F1].proc_nr;
544 fkey_obs[key - F1].events ++ ;
545 } else if (SF1 <= key && key <= SF12) { /* Shift F2-F12 */
546 proc_nr = sfkey_obs[key - SF1].proc_nr;
547 sfkey_obs[key - SF1].events ++;
548 }
549 else {
550 return(FALSE); /* not observable */
551 }
552
553 /* See if an observer is registered and send it a message. */
554 if (proc_nr != NONE) {
555 m.NOTIFY_TYPE = FKEY_PRESSED;
556 notify(proc_nr);
557 }
558 return(TRUE);
559}
560
561/*===========================================================================*
562 * show_key_mappings *
563 *===========================================================================*/
564PRIVATE void show_key_mappings()
565{
566 int i,s;
567 struct proc proc;
568
569 printf("\n");
570 printf("System information. Known function key mappings to request debug dumps:\n");
571 printf("-------------------------------------------------------------------------\n");
572 for (i=0; i<12; i++) {
573
574 printf(" %sF%d: ", i+1<10? " ":"", i+1);
575 if (fkey_obs[i].proc_nr != NONE) {
576 if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
577 printf("sys_getproc: %d\n", s);
578 printf("%-14.14s", proc.p_name);
579 } else {
580 printf("%-14.14s", "<none>");
581 }
582
583 printf(" %sShift-F%d: ", i+1<10? " ":"", i+1);
584 if (sfkey_obs[i].proc_nr != NONE) {
585 if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
586 printf("sys_getproc: %d\n", s);
587 printf("%-14.14s", proc.p_name);
588 } else {
589 printf("%-14.14s", "<none>");
590 }
591 printf("\n");
592 }
593 printf("\n");
594 printf("Press one of the registered function keys to trigger a debug dump.\n");
595 printf("\n");
596}
597
598/*===========================================================================*
599 * scan_keyboard *
600 *===========================================================================*/
601PRIVATE int scan_keyboard()
602{
603/* Fetch the character from the keyboard hardware and acknowledge it. */
604 pvb_pair_t byte_in[2], byte_out[2];
605
606 byte_in[0].port = KEYBD; /* get the scan code for the key struck */
607 byte_in[1].port = PORT_B; /* strobe the keyboard to ack the char */
608 sys_vinb(byte_in, 2); /* request actual input */
609
610 pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
611 pv_set(byte_out[1], PORT_B, byte_in[1].value); /* then strobe low */
612 sys_voutb(byte_out, 2); /* request actual output */
613
614 return(byte_in[0].value); /* return scan code */
615}
616
617/*===========================================================================*
618 * do_panic_dumps *
619 *===========================================================================*/
620PUBLIC void do_panic_dumps(m)
621message *m; /* request message to TTY */
622{
623/* Wait for keystrokes for printing debugging info and reboot. */
624 int quiet, code;
625
626 /* A panic! Allow debug dumps until user wants to shutdown. */
627 printf("\nHit ESC to reboot, DEL to shutdown, F-keys for debug dumps\n");
628
629 (void) scan_keyboard(); /* ack any old input */
630 quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/
631 for (;;) {
632 tickdelay(10);
633 /* See if there are pending request for output, but don't block.
634 * Diagnostics can span multiple printf()s, so do it in a loop.
635 */
636 while (nb_receive(ANY, m) == OK) {
637 switch(m->m_type) {
638 case FKEY_CONTROL: do_fkey_ctl(m); break;
639 case SYS_SIG: do_new_kmess(m); break;
640 case DIAGNOSTICS: do_diagnostics(m); break;
641 default: ; /* do nothing */
642 }
643 tickdelay(1); /* allow more */
644 }
645 code = scan_keyboard();
646 if (code != quiet) {
647 /* A key has been pressed. */
648 switch (code) { /* possibly abort MINIX */
649 case ESC_SCAN: sys_abort(RBT_REBOOT); return;
650 case DEL_SCAN: sys_abort(RBT_HALT); return;
651 }
652 (void) func_key(code); /* check for function key */
653 quiet = scan_keyboard();
654 }
655 }
656}
657
Note: See TracBrowser for help on using the repository browser.