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
25 int 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 */
51 PRIVATE char ibuf[KB_IN_BYTES]; /* input buffer */
52 PRIVATE char *ihead = ibuf; /* next free spot in input buffer */
53 PRIVATE char *itail = ibuf; /* scan code to return to TTY */
54 PRIVATE int icount; /* # codes in buffer */
55
56 PRIVATE int esc; /* escape scan code detected? */
57 PRIVATE int alt_l; /* left alt key state */
58 PRIVATE int alt_r; /* right alt key state */
59 PRIVATE int alt; /* either alt key */
60 PRIVATE int ctrl_l; /* left control key state */
61 PRIVATE int ctrl_r; /* right control key state */
62 PRIVATE int ctrl; /* either control key */
63 PRIVATE int shift_l; /* left shift key state */
64 PRIVATE int shift_r; /* right shift key state */
65 PRIVATE int shift; /* either shift key */
66 PRIVATE int num_down; /* num lock key depressed */
67 PRIVATE int caps_down; /* caps lock key depressed */
68 PRIVATE int scroll_down; /* scroll lock key depressed */
69 PRIVATE 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
76 PRIVATE char numpad_map[] =
77 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
78
79 /* Variables and definition for observed function keys. */
80 typedef struct observer { int proc_nr; int events; } obs_t;
81 PRIVATE obs_t fkey_obs[12]; /* observers for F1-F12 */
82 PRIVATE obs_t sfkey_obs[12]; /* observers for SHIFT F1-F12 */
83
84 FORWARD _PROTOTYPE( int kb_ack, (void) );
85 FORWARD _PROTOTYPE( int kb_wait, (void) );
86 FORWARD _PROTOTYPE( int func_key, (int scode) );
87 FORWARD _PROTOTYPE( int scan_keyboard, (void) );
88 FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
89 FORWARD _PROTOTYPE( void set_leds, (void) );
90 FORWARD _PROTOTYPE( void show_key_mappings, (void) );
91 FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
92 FORWARD _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 *===========================================================================*/
104 PRIVATE unsigned map_key(scode)
105 int 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 *===========================================================================*/
136 PUBLIC void kbd_interrupt(m_ptr)
137 message *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 *===========================================================================*/
161 PRIVATE int kb_read(tp, try)
162 tty_t *tp;
163 int 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 *===========================================================================*/
232 PRIVATE unsigned make_break(scode)
233 int 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 *===========================================================================*/
309 PRIVATE 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 *===========================================================================*/
331 PRIVATE 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 *===========================================================================*/
353 PRIVATE 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 *===========================================================================*/
373 PUBLIC void kb_init(tp)
374 tty_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 *===========================================================================*/
384 PUBLIC 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 *===========================================================================*/
411 PUBLIC int kbd_loadmap(m)
412 message *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 *===========================================================================*/
425 PUBLIC void do_fkey_ctl(m_ptr)
426 message *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 DEAD_CODE
440 /* Currently, we don't check if the slot is in use, so that IS
441 * can recover after a crash by overtaking its existing mappings.
442 * In future, a better solution will be implemented.
443 */
444 if (fkey_obs[i].proc_nr == NONE) {
445 #endif
446 fkey_obs[i].proc_nr = m_ptr->m_source;
447 fkey_obs[i].events = 0;
448 bit_unset(m_ptr->FKEY_FKEYS, i+1);
449 #if DEAD_CODE
450 } else {
451 printf("WARNING, fkey_map failed F%d\n", i+1);
452 result = EBUSY; /* report failure, but try rest */
453 }
454 #endif
455 }
456 }
457 for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */
458 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
459 #if DEAD_CODE
460 if (sfkey_obs[i].proc_nr == NONE) {
461 #endif
462 sfkey_obs[i].proc_nr = m_ptr->m_source;
463 sfkey_obs[i].events = 0;
464 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
465 #if DEAD_CODE
466 } else {
467 printf("WARNING, fkey_map failed Shift F%d\n", i+1);
468 result = EBUSY; /* report failure but try rest */
469 }
470 #endif
471 }
472 }
473 break;
474 case FKEY_UNMAP:
475 result = OK; /* assume everything will be ok*/
476 for (i=0; i < 12; i++) { /* check F1-F12 keys */
477 if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
478 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
479 fkey_obs[i].proc_nr = NONE;
480 fkey_obs[i].events = 0;
481 bit_unset(m_ptr->FKEY_FKEYS, i+1);
482 } else {
483 result = EPERM; /* report failure, but try rest */
484 }
485 }
486 }
487 for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */
488 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
489 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
490 sfkey_obs[i].proc_nr = NONE;
491 sfkey_obs[i].events = 0;
492 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
493 } else {
494 result = EPERM; /* report failure, but try rest */
495 }
496 }
497 }
498 break;
499 case FKEY_EVENTS:
500 m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0;
501 for (i=0; i < 12; i++) { /* check (Shift+) F1-F12 keys */
502 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
503 if (fkey_obs[i].events) {
504 bit_set(m_ptr->FKEY_FKEYS, i+1);
505 fkey_obs[i].events = 0;
506 }
507 }
508 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
509 if (sfkey_obs[i].events) {
510 bit_set(m_ptr->FKEY_SFKEYS, i+1);
511 sfkey_obs[i].events = 0;
512 }
513 }
514 }
515 break;
516 default:
517 result = EINVAL; /* key cannot be observed */
518 }
519
520 /* Almost done, return result to caller. */
521 m_ptr->m_type = result;
522 send(m_ptr->m_source, m_ptr);
523 }
524
525 /*===========================================================================*
526 * func_key *
527 *===========================================================================*/
528 PRIVATE int func_key(scode)
529 int scode; /* scan code for a function key */
530 {
531 /* This procedure traps function keys for debugging purposes. Observers of
532 * function keys are kept in a global array. If a subject (a key) is pressed
533 * the observer is notified of the event. Initialization of the arrays is done
534 * in kb_init, where NONE is set to indicate there is no interest in the key.
535 * Returns FALSE on a key release or if the key is not observable.
536 */
537 message m;
538 int key;
539 int proc_nr;
540 int i,s;
541
542 /* Ignore key releases. If this is a key press, get full key code. */
543 if (scode & KEY_RELEASE) return(FALSE); /* key release */
544 key = map_key(scode); /* include modifiers */
545
546 /* Key pressed, now see if there is an observer for the pressed key.
547 * F1-F12 observers are in fkey_obs array.
548 * SHIFT F1-F12 observers are in sfkey_req array.
549 * CTRL F1-F12 reserved (see kb_read)
550 * ALT F1-F12 reserved (see kb_read)
551 * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet
552 * defined in <minix/keymap.h>, and thus is easy for future extensions.
553 */
554 if (F1 <= key && key <= F12) { /* F1-F12 */
555 proc_nr = fkey_obs[key - F1].proc_nr;
556 fkey_obs[key - F1].events ++ ;
557 } else if (SF1 <= key && key <= SF12) { /* Shift F2-F12 */
558 proc_nr = sfkey_obs[key - SF1].proc_nr;
559 sfkey_obs[key - SF1].events ++;
560 }
561 else {
562 return(FALSE); /* not observable */
563 }
564
565 /* See if an observer is registered and send it a message. */
566 if (proc_nr != NONE) {
567 m.NOTIFY_TYPE = FKEY_PRESSED;
568 notify(proc_nr);
569 }
570 return(TRUE);
571 }
572
573 /*===========================================================================*
574 * show_key_mappings *
575 *===========================================================================*/
576 PRIVATE void show_key_mappings()
577 {
578 int i,s;
579 struct proc proc;
580
581 printf("\n");
582 printf("System information. Known function key mappings to request debug dumps:\n");
583 printf("-------------------------------------------------------------------------\n");
584 for (i=0; i<12; i++) {
585
586 printf(" %sF%d: ", i+1<10? " ":"", i+1);
587 if (fkey_obs[i].proc_nr != NONE) {
588 if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
589 printf("sys_getproc: %d\n", s);
590 printf("%-14.14s", proc.p_name);
591 } else {
592 printf("%-14.14s", "<none>");
593 }
594
595 printf(" %sShift-F%d: ", i+1<10? " ":"", i+1);
596 if (sfkey_obs[i].proc_nr != NONE) {
597 if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
598 printf("sys_getproc: %d\n", s);
599 printf("%-14.14s", proc.p_name);
600 } else {
601 printf("%-14.14s", "<none>");
602 }
603 printf("\n");
604 }
605 printf("\n");
606 printf("Press one of the registered function keys to trigger a debug dump.\n");
607 printf("\n");
608 }
609
610 /*===========================================================================*
611 * scan_keyboard *
612 *===========================================================================*/
613 PRIVATE int scan_keyboard()
614 {
615 /* Fetch the character from the keyboard hardware and acknowledge it. */
616 pvb_pair_t byte_in[2], byte_out[2];
617
618 byte_in[0].port = KEYBD; /* get the scan code for the key struck */
619 byte_in[1].port = PORT_B; /* strobe the keyboard to ack the char */
620 sys_vinb(byte_in, 2); /* request actual input */
621
622 pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
623 pv_set(byte_out[1], PORT_B, byte_in[1].value); /* then strobe low */
624 sys_voutb(byte_out, 2); /* request actual output */
625
626 return(byte_in[0].value); /* return scan code */
627 }
628
629 /*===========================================================================*
630 * do_panic_dumps *
631 *===========================================================================*/
632 PUBLIC void do_panic_dumps(m)
633 message *m; /* request message to TTY */
634 {
635 /* Wait for keystrokes for printing debugging info and reboot. */
636 int quiet, code;
637
638 /* A panic! Allow debug dumps until user wants to shutdown. */
639 printf("\nHit ESC to reboot, DEL to shutdown, F-keys for debug dumps\n");
640
641 (void) scan_keyboard(); /* ack any old input */
642 quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/
643 for (;;) {
644 tickdelay(10);
645 /* See if there are pending request for output, but don't block.
646 * Diagnostics can span multiple printf()s, so do it in a loop.
647 */
648 while (nb_receive(ANY, m) == OK) {
649 switch(m->m_type) {
650 case FKEY_CONTROL: do_fkey_ctl(m); break;
651 case SYS_SIG: do_new_kmess(m); break;
652 case DIAGNOSTICS: do_diagnostics(m); break;
653 default: ; /* do nothing */
654 }
655 tickdelay(1); /* allow more */
656 }
657 code = scan_keyboard();
658 if (code != quiet) {
659 /* A key has been pressed. */
660 switch (code) { /* possibly abort MINIX */
661 case ESC_SCAN: sys_abort(RBT_REBOOT); return;
662 case DEL_SCAN: sys_abort(RBT_HALT); return;
663 }
664 (void) func_key(code); /* check for function key */
665 quiet = scan_keyboard();
666 }
667 }
668 }
669
Cache object: cb98324fff17ab087487fbb50420d93b
|