This source file includes following definitions.
- kb_wait
- send_cmd
- to_utf8
- keyboard_interrupt
- put_queue
- puts_queue
- applkey
- enter
- caps_toggle
- caps_on
- show_ptregs
- hold
- num
- lastcons
- decr_console
- incr_console
- send_intr
- scroll_forw
- scroll_back
- boot_it
- compose
- SAK
- do_ignore
- do_spec
- do_lowercase
- do_self
- do_dead
- handle_diacr
- do_cons
- do_fn
- do_pad
- do_cur
- do_shift
- compute_shiftstate
- do_meta
- do_ascii
- do_lock
- send_data
- getledstate
- setledstate
- register_leds
- getleds
- kbd_bh
- hard_reset_now
- kbd_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #define KEYBOARD_IRQ 1
20
21 #include <linux/sched.h>
22 #include <linux/interrupt.h>
23 #include <linux/tty.h>
24 #include <linux/tty_flip.h>
25 #include <linux/mm.h>
26 #include <linux/ptrace.h>
27 #include <linux/config.h>
28 #include <linux/signal.h>
29 #include <linux/string.h>
30
31 #include <asm/bitops.h>
32
33 #include "kbd_kern.h"
34 #include "diacr.h"
35 #include "vt_kern.h"
36
37 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
38
39 #define KBD_REPORT_ERR
40 #define KBD_REPORT_UNKN
41
42
43 #ifndef KBD_DEFMODE
44 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
45 #endif
46
47 #ifndef KBD_DEFLEDS
48
49
50
51
52 #define KBD_DEFLEDS 0
53 #endif
54
55 #ifndef KBD_DEFLOCK
56 #define KBD_DEFLOCK 0
57 #endif
58
59
60
61
62
63
64
65 #define REALLY_SLOW_IO
66 #define SLOW_IO_BY_JUMPING
67 #include <asm/io.h>
68 #include <asm/system.h>
69
70 extern void poke_blanked_console(void);
71 extern void ctrl_alt_del(void);
72 extern void reset_vc(unsigned int new_console);
73 extern void change_console(unsigned int new_console);
74 extern void scrollback(int);
75 extern void scrollfront(int);
76 extern int vc_cons_allocated(unsigned int);
77
78 #define fake_keyboard_interrupt() \
79 __asm__ __volatile__("int $0x21")
80
81 unsigned char kbd_read_mask = 0x01;
82
83
84
85
86
87
88
89
90 static unsigned char k_down[NR_SHIFT] = {0, };
91
92 static unsigned long key_down[8] = { 0, };
93
94 static int want_console = -1;
95 static int last_console = 0;
96 static int dead_key_next = 0;
97
98
99
100
101
102 int shift_state = 0;
103 static int npadch = -1;
104 static unsigned char diacr = 0;
105 static char rep = 0;
106 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
107 static struct tty_struct **ttytab;
108 static struct kbd_struct * kbd = kbd_table;
109 static struct tty_struct * tty = NULL;
110
111
112 static volatile unsigned char reply_expected = 0;
113 static volatile unsigned char acknowledge = 0;
114 static volatile unsigned char resend = 0;
115
116 typedef void (*k_hand)(unsigned char value, char up_flag);
117 typedef void (k_handfn)(unsigned char value, char up_flag);
118
119 static k_handfn
120 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
121 do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
122
123 static k_hand key_handler[16] = {
124 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
125 do_meta, do_ascii, do_lock, do_lowercase,
126 do_ignore, do_ignore, do_ignore, do_ignore
127 };
128
129 typedef void (*void_fnp)(void);
130 typedef void (void_fn)(void);
131
132 static void_fn enter, show_ptregs, send_intr, lastcons, caps_toggle,
133 num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
134 SAK, decr_console, incr_console;
135
136 static void_fnp spec_fn_table[] = {
137 NULL, enter, show_ptregs, show_mem,
138 show_state, send_intr, lastcons, caps_toggle,
139 num, hold, scroll_forw, scroll_back,
140 boot_it, caps_on, compose, SAK,
141 decr_console, incr_console
142 };
143
144
145 const int max_vals[] = {
146 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
147 NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
148 255, NR_ASCII - 1, NR_LOCK - 1, 255
149 };
150
151 const int NR_TYPES = SIZE(max_vals);
152
153 static void put_queue(int);
154 static unsigned char handle_diacr(unsigned char);
155
156
157 static struct pt_regs * pt_regs;
158
159 static inline void kb_wait(void)
160 {
161 int i;
162
163 for (i=0; i<0x10000; i++)
164 if ((inb_p(0x64) & 0x02) == 0)
165 break;
166 }
167
168 static inline void send_cmd(unsigned char c)
169 {
170 kb_wait();
171 outb(c,0x64);
172 }
173
174
175
176
177
178
179
180 void to_utf8(ushort c) {
181 if (c < 0x80)
182 put_queue(c);
183 else if (c < 0x800) {
184 put_queue(0xc0 | (c >> 6));
185 put_queue(0x80 | (c & 0x3f));
186 } else {
187 put_queue(0xe0 | (c >> 12));
188 put_queue(0x80 | ((c >> 6) & 0x3f));
189 put_queue(0x80 | (c & 0x3f));
190 }
191
192
193 }
194
195
196
197
198
199 #define E0_BASE 96
200
201 #define E0_KPENTER (E0_BASE+0)
202 #define E0_RCTRL (E0_BASE+1)
203 #define E0_KPSLASH (E0_BASE+2)
204 #define E0_PRSCR (E0_BASE+3)
205 #define E0_RALT (E0_BASE+4)
206 #define E0_BREAK (E0_BASE+5)
207 #define E0_HOME (E0_BASE+6)
208 #define E0_UP (E0_BASE+7)
209 #define E0_PGUP (E0_BASE+8)
210 #define E0_LEFT (E0_BASE+9)
211 #define E0_RIGHT (E0_BASE+10)
212 #define E0_END (E0_BASE+11)
213 #define E0_DOWN (E0_BASE+12)
214 #define E0_PGDN (E0_BASE+13)
215 #define E0_INS (E0_BASE+14)
216 #define E0_DEL (E0_BASE+15)
217
218 #define E0_MACRO (E0_BASE+16)
219
220 #define E0_F13 (E0_BASE+17)
221 #define E0_F14 (E0_BASE+18)
222 #define E0_HELP (E0_BASE+19)
223 #define E0_DO (E0_BASE+20)
224 #define E0_F17 (E0_BASE+21)
225 #define E0_KPMINPLUS (E0_BASE+22)
226
227 #define E1_PAUSE (E0_BASE+23)
228
229 static unsigned char e0_keys[128] = {
230 0, 0, 0, 0, 0, 0, 0, 0,
231 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,
234 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,
237 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,
238 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,
239 E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, E0_KPMINPLUS, E0_END,
240 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0,
243 0, 0, 0, 0, 0, 0, 0, E0_MACRO,
244 0, 0, 0, 0, 0, 0, 0, 0,
245 0, 0, 0, 0, 0, 0, 0, 0
246 };
247
248
249
250
251
252
253
254
255
256 #define SC_LIM 89
257
258 #define FOCUS_PF1 85
259 #define FOCUS_PF2 89
260 #define FOCUS_PF3 90
261 #define FOCUS_PF4 91
262 #define FOCUS_PF5 92
263 #define FOCUS_PF6 93
264 #define FOCUS_PF7 94
265 #define FOCUS_PF8 95
266 #define FOCUS_PF9 (E1_PAUSE + 1)
267 #define FOCUS_PF10 (E1_PAUSE + 2)
268 #define FOCUS_PF11 (E1_PAUSE + 3)
269 #define FOCUS_PF12 (E1_PAUSE + 4)
270 #define JAP_86 (E1_PAUSE + 5)
271
272 static unsigned char high_keys[128 - SC_LIM] = {
273 0, 0, 0, 0, 0, 0, 0,
274 0, 0, 0, 0, 0, 0, 0, 0,
275 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,
276 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,
277 FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,
278 FOCUS_PF8, JAP_86, FOCUS_PF10, 0
279 };
280
281 static void keyboard_interrupt(int int_pt_regs)
282 {
283 unsigned char scancode, keycode;
284 static unsigned int prev_scancode = 0;
285 char up_flag;
286 char raw_mode;
287
288 pt_regs = (struct pt_regs *) int_pt_regs;
289 send_cmd(0xAD);
290 kb_wait();
291 if ((inb_p(0x64) & kbd_read_mask) != 0x01)
292 goto end_kbd_intr;
293 scancode = inb(0x60);
294 mark_bh(KEYBOARD_BH);
295 if (reply_expected) {
296
297
298 reply_expected = 0;
299 if (scancode == 0xfa) {
300 acknowledge = 1;
301 goto end_kbd_intr;
302 } else if (scancode == 0xfe) {
303 resend = 1;
304 goto end_kbd_intr;
305 }
306
307 reply_expected = 1;
308 #if 0
309 printk("keyboard reply expected - got %02x\n", scancode);
310 #endif
311 }
312 if (scancode == 0) {
313 #ifdef KBD_REPORT_ERR
314 printk("keyboard buffer overflow\n");
315 #endif
316 prev_scancode = 0;
317 goto end_kbd_intr;
318 }
319 if (scancode == 0xff) {
320
321 #ifndef KBD_IS_FOCUS_9000
322 #ifdef KBD_REPORT_ERR
323 printk("keyboard error\n");
324 #endif
325 #endif
326 prev_scancode = 0;
327 goto end_kbd_intr;
328 }
329
330 tty = ttytab[fg_console];
331 kbd = kbd_table + fg_console;
332 if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
333 put_queue(scancode);
334
335
336
337 }
338 if (scancode == 0xe0 || scancode == 0xe1) {
339 prev_scancode = scancode;
340 goto end_kbd_intr;
341 }
342
343
344
345
346 up_flag = (scancode & 0200);
347 scancode &= 0x7f;
348
349 if (prev_scancode) {
350
351
352
353
354 if (prev_scancode != 0xe0) {
355 if (prev_scancode == 0xe1 && scancode == 0x1d) {
356 prev_scancode = 0x100;
357 goto end_kbd_intr;
358 } else if (prev_scancode == 0x100 && scancode == 0x45) {
359 keycode = E1_PAUSE;
360 prev_scancode = 0;
361 } else {
362 #ifdef KBD_REPORT_UNKN
363 printk("keyboard: unknown e1 escape sequence\n");
364 #endif
365 prev_scancode = 0;
366 goto end_kbd_intr;
367 }
368 } else {
369 prev_scancode = 0;
370
371
372
373
374
375
376
377
378
379
380
381
382
383 if (scancode == 0x2a || scancode == 0x36)
384 goto end_kbd_intr;
385
386 if (e0_keys[scancode])
387 keycode = e0_keys[scancode];
388 else {
389 #ifdef KBD_REPORT_UNKN
390 if (!raw_mode)
391 printk("keyboard: unknown scancode e0 %02x\n", scancode);
392 #endif
393 goto end_kbd_intr;
394 }
395 }
396 } else if (scancode >= SC_LIM) {
397
398
399
400
401
402
403
404
405
406
407 keycode = high_keys[scancode - SC_LIM];
408
409 if (!keycode) {
410 if (!raw_mode) {
411 #ifdef KBD_REPORT_UNKN
412 printk("keyboard: unrecognized scancode (%02x) - ignored\n"
413 , scancode);
414 #endif
415 }
416 goto end_kbd_intr;
417 }
418 } else
419 keycode = scancode;
420
421
422
423
424
425
426
427
428 if (up_flag) {
429 rep = 0;
430 if(!clear_bit(keycode, key_down)) {
431
432
433
434
435 if (keycode >= SC_LIM || keycode == 85)
436 up_flag = 0;
437 }
438 } else
439 rep = set_bit(keycode, key_down);
440
441 if (raw_mode)
442 goto end_kbd_intr;
443
444 if (kbd->kbdmode == VC_MEDIUMRAW) {
445
446 put_queue(keycode + up_flag);
447 goto end_kbd_intr;
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 if (!rep ||
464 (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
465 (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
466 u_short keysym;
467 u_char type;
468
469
470 int shift_final = shift_state ^ kbd->lockstate;
471 ushort *key_map = key_maps[shift_final];
472
473 if (key_map != NULL) {
474 keysym = key_map[keycode];
475 type = KTYP(keysym);
476
477 if (type >= 0xf0) {
478 type -= 0xf0;
479 if (type == KT_LETTER) {
480 type = KT_LATIN;
481 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
482 key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
483 if (key_map)
484 keysym = key_map[keycode];
485 }
486 }
487 (*key_handler[type])(keysym & 0xff, up_flag);
488 } else {
489
490 if (!up_flag)
491 to_utf8(keysym);
492 }
493 } else {
494
495
496 #if 0
497 compute_shiftstate();
498 #else
499 keysym = U(plain_map[keycode]);
500 type = KTYP(keysym);
501 if (type == KT_SHIFT)
502 (*key_handler[type])(keysym & 0xff, up_flag);
503 #endif
504 }
505 }
506
507 end_kbd_intr:
508 send_cmd(0xAE);
509 }
510
511 static void put_queue(int ch)
512 {
513 wake_up(&keypress_wait);
514 if (tty) {
515 tty_insert_flip_char(tty, ch, 0);
516 tty_schedule_flip(tty);
517 }
518 }
519
520 static void puts_queue(char *cp)
521 {
522 wake_up(&keypress_wait);
523 if (!tty)
524 return;
525
526 while (*cp) {
527 tty_insert_flip_char(tty, *cp, 0);
528 cp++;
529 }
530 tty_schedule_flip(tty);
531 }
532
533 static void applkey(int key, char mode)
534 {
535 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
536
537 buf[1] = (mode ? 'O' : '[');
538 buf[2] = key;
539 puts_queue(buf);
540 }
541
542 static void enter(void)
543 {
544 put_queue(13);
545 if (vc_kbd_mode(kbd,VC_CRLF))
546 put_queue(10);
547 }
548
549 static void caps_toggle(void)
550 {
551 if (rep)
552 return;
553 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
554 }
555
556 static void caps_on(void)
557 {
558 if (rep)
559 return;
560 set_vc_kbd_led(kbd, VC_CAPSLOCK);
561 }
562
563 static void show_ptregs(void)
564 {
565 if (!pt_regs)
566 return;
567 printk("\n");
568 printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
569 if (pt_regs->cs & 3)
570 printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
571 printk(" EFLAGS: %08lx\n",pt_regs->eflags);
572 printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
573 pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
574 printk("ESI: %08lx EDI: %08lx EBP: %08lx",
575 pt_regs->esi, pt_regs->edi, pt_regs->ebp);
576 printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
577 0xffff & pt_regs->ds,0xffff & pt_regs->es,
578 0xffff & pt_regs->fs,0xffff & pt_regs->gs);
579 }
580
581 static void hold(void)
582 {
583 if (rep || !tty)
584 return;
585
586
587
588
589
590
591 if (tty->stopped)
592 start_tty(tty);
593 else
594 stop_tty(tty);
595 }
596
597 static void num(void)
598 {
599 if (vc_kbd_mode(kbd,VC_APPLIC)) {
600 applkey('P', 1);
601 return;
602 }
603 if (!rep)
604 chg_vc_kbd_led(kbd,VC_NUMLOCK);
605 }
606
607 static void lastcons(void)
608 {
609
610 want_console = last_console;
611 }
612
613 static void decr_console(void)
614 {
615 int i;
616
617 for (i = fg_console-1; i != fg_console; i--) {
618 if (i == -1)
619 i = MAX_NR_CONSOLES-1;
620 if (vc_cons_allocated(i))
621 break;
622 }
623 want_console = i;
624 }
625
626 static void incr_console(void)
627 {
628 int i;
629
630 for (i = fg_console+1; i != fg_console; i++) {
631 if (i == MAX_NR_CONSOLES)
632 i = 0;
633 if (vc_cons_allocated(i))
634 break;
635 }
636 want_console = i;
637 }
638
639 static void send_intr(void)
640 {
641 if (!tty || (tty->termios && I_IGNBRK(tty)))
642 return;
643 tty_insert_flip_char(tty, 0, TTY_BREAK);
644 }
645
646 static void scroll_forw(void)
647 {
648 scrollfront(0);
649 }
650
651 static void scroll_back(void)
652 {
653 scrollback(0);
654 }
655
656 static void boot_it(void)
657 {
658 ctrl_alt_del();
659 }
660
661 static void compose(void)
662 {
663 dead_key_next = 1;
664 }
665
666 static void SAK(void)
667 {
668 do_SAK(tty);
669 #if 0
670
671
672
673
674
675
676
677
678
679 reset_vc(fg_console);
680 unblank_screen();
681 #endif
682 }
683
684 static void do_ignore(unsigned char value, char up_flag)
685 {
686 }
687
688 static void do_spec(unsigned char value, char up_flag)
689 {
690 if (up_flag)
691 return;
692 if (value >= SIZE(spec_fn_table))
693 return;
694 if (!spec_fn_table[value])
695 return;
696 spec_fn_table[value]();
697 }
698
699 static void do_lowercase(unsigned char value, char up_flag)
700 {
701 printk("keyboard.c: do_lowercase was called - impossible\n");
702 }
703
704 static void do_self(unsigned char value, char up_flag)
705 {
706 if (up_flag)
707 return;
708
709 if (diacr)
710 value = handle_diacr(value);
711
712 if (dead_key_next) {
713 dead_key_next = 0;
714 diacr = value;
715 return;
716 }
717
718 put_queue(value);
719 }
720
721 #define A_GRAVE '`'
722 #define A_ACUTE '\''
723 #define A_CFLEX '^'
724 #define A_TILDE '~'
725 #define A_DIAER '"'
726 static unsigned char ret_diacr[] =
727 {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
728
729
730
731
732 static void do_dead(unsigned char value, char up_flag)
733 {
734 if (up_flag)
735 return;
736
737 value = ret_diacr[value];
738 if (diacr == value) {
739 diacr = 0;
740 put_queue(value);
741 return;
742 }
743 diacr = value;
744 }
745
746
747
748
749
750 unsigned char handle_diacr(unsigned char ch)
751 {
752 int d = diacr;
753 int i;
754
755 diacr = 0;
756 if (ch == ' ')
757 return d;
758
759 for (i = 0; i < accent_table_size; i++) {
760 if (accent_table[i].diacr == d && accent_table[i].base == ch)
761 return accent_table[i].result;
762 }
763
764 put_queue(d);
765 return ch;
766 }
767
768 static void do_cons(unsigned char value, char up_flag)
769 {
770 if (up_flag)
771 return;
772 want_console = value;
773 }
774
775 static void do_fn(unsigned char value, char up_flag)
776 {
777 if (up_flag)
778 return;
779 if (value < SIZE(func_table)) {
780 if (func_table[value])
781 puts_queue(func_table[value]);
782 } else
783 printk("do_fn called with value=%d\n", value);
784 }
785
786 static void do_pad(unsigned char value, char up_flag)
787 {
788 static char *pad_chars = "0123456789+-*/\015,.?";
789 static char *app_map = "pqrstuvwxylSRQMnn?";
790
791 if (up_flag)
792 return;
793
794
795 if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
796 applkey(app_map[value], 1);
797 return;
798 }
799
800 if (!vc_kbd_led(kbd,VC_NUMLOCK))
801 switch (value) {
802 case KVAL(K_PCOMMA):
803 case KVAL(K_PDOT):
804 do_fn(KVAL(K_REMOVE), 0);
805 return;
806 case KVAL(K_P0):
807 do_fn(KVAL(K_INSERT), 0);
808 return;
809 case KVAL(K_P1):
810 do_fn(KVAL(K_SELECT), 0);
811 return;
812 case KVAL(K_P2):
813 do_cur(KVAL(K_DOWN), 0);
814 return;
815 case KVAL(K_P3):
816 do_fn(KVAL(K_PGDN), 0);
817 return;
818 case KVAL(K_P4):
819 do_cur(KVAL(K_LEFT), 0);
820 return;
821 case KVAL(K_P6):
822 do_cur(KVAL(K_RIGHT), 0);
823 return;
824 case KVAL(K_P7):
825 do_fn(KVAL(K_FIND), 0);
826 return;
827 case KVAL(K_P8):
828 do_cur(KVAL(K_UP), 0);
829 return;
830 case KVAL(K_P9):
831 do_fn(KVAL(K_PGUP), 0);
832 return;
833 case KVAL(K_P5):
834 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
835 return;
836 }
837
838 put_queue(pad_chars[value]);
839 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
840 put_queue(10);
841 }
842
843 static void do_cur(unsigned char value, char up_flag)
844 {
845 static char *cur_chars = "BDCA";
846 if (up_flag)
847 return;
848
849 applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
850 }
851
852 static void do_shift(unsigned char value, char up_flag)
853 {
854 int old_state = shift_state;
855
856 if (rep)
857 return;
858
859
860
861 if (value == KVAL(K_CAPSSHIFT)) {
862 value = KVAL(K_SHIFT);
863 if (!up_flag)
864 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
865 }
866
867 if (up_flag) {
868
869
870 if (k_down[value])
871 k_down[value]--;
872 } else
873 k_down[value]++;
874
875 if (k_down[value])
876 shift_state |= (1 << value);
877 else
878 shift_state &= ~ (1 << value);
879
880
881 if (up_flag && shift_state != old_state && npadch != -1) {
882 if (kbd->kbdmode == VC_UNICODE)
883 to_utf8(npadch & 0xffff);
884 else
885 put_queue(npadch & 0xff);
886 npadch = -1;
887 }
888 }
889
890
891
892
893 void compute_shiftstate(void)
894 {
895 int i, j, k, sym, val;
896
897 shift_state = 0;
898 for(i=0; i < SIZE(k_down); i++)
899 k_down[i] = 0;
900
901 for(i=0; i < SIZE(key_down); i++)
902 if(key_down[i]) {
903 k = (i<<5);
904 for(j=0; j<32; j++,k++)
905 if(test_bit(k, key_down)) {
906 sym = U(plain_map[k]);
907 if(KTYP(sym) == KT_SHIFT) {
908 val = KVAL(sym);
909 if (val == KVAL(K_CAPSSHIFT))
910 val = KVAL(K_SHIFT);
911 k_down[val]++;
912 shift_state |= (1<<val);
913 }
914 }
915 }
916 }
917
918 static void do_meta(unsigned char value, char up_flag)
919 {
920 if (up_flag)
921 return;
922
923 if (vc_kbd_mode(kbd, VC_META)) {
924 put_queue('\033');
925 put_queue(value);
926 } else
927 put_queue(value | 0x80);
928 }
929
930 static void do_ascii(unsigned char value, char up_flag)
931 {
932 int base;
933
934 if (up_flag)
935 return;
936
937 if (value < 10)
938 base = 10;
939 else {
940 value -= 10;
941 base = 16;
942 }
943
944 if (npadch == -1)
945 npadch = value;
946 else
947 npadch = npadch * base + value;
948 }
949
950 static void do_lock(unsigned char value, char up_flag)
951 {
952 if (up_flag || rep)
953 return;
954 chg_vc_kbd_lock(kbd, value);
955 }
956
957
958
959
960
961
962 static int send_data(unsigned char data)
963 {
964 int retries = 3;
965 int i;
966
967 do {
968 kb_wait();
969 acknowledge = 0;
970 resend = 0;
971 reply_expected = 1;
972 outb_p(data, 0x60);
973 for(i=0; i<0x20000; i++) {
974 inb_p(0x64);
975 if (acknowledge)
976 return 1;
977 if (resend)
978 break;
979 }
980 if (!resend)
981 return 0;
982 } while (retries-- > 0);
983 return 0;
984 }
985
986
987
988
989
990
991
992 static unsigned char ledstate = 0xff;
993 static unsigned char ledioctl;
994
995 unsigned char getledstate(void) {
996 return ledstate;
997 }
998
999 void setledstate(struct kbd_struct *kbd, unsigned int led) {
1000 if (!(led & ~7)) {
1001 ledioctl = led;
1002 kbd->ledmode = LED_SHOW_IOCTL;
1003 } else
1004 kbd->ledmode = LED_SHOW_FLAGS;
1005 set_leds();
1006 }
1007
1008 static struct ledptr {
1009 unsigned int *addr;
1010 unsigned int mask;
1011 unsigned char valid:1;
1012 } ledptrs[3];
1013
1014 void register_leds(int console, unsigned int led,
1015 unsigned int *addr, unsigned int mask) {
1016 struct kbd_struct *kbd = kbd_table + console;
1017 if (led < 3) {
1018 ledptrs[led].addr = addr;
1019 ledptrs[led].mask = mask;
1020 ledptrs[led].valid = 1;
1021 kbd->ledmode = LED_SHOW_MEM;
1022 } else
1023 kbd->ledmode = LED_SHOW_FLAGS;
1024 }
1025
1026 static inline unsigned char getleds(void){
1027 struct kbd_struct *kbd = kbd_table + fg_console;
1028 unsigned char leds;
1029
1030 if (kbd->ledmode == LED_SHOW_IOCTL)
1031 return ledioctl;
1032 leds = kbd->ledflagstate;
1033 if (kbd->ledmode == LED_SHOW_MEM) {
1034 if (ledptrs[0].valid) {
1035 if (*ledptrs[0].addr & ledptrs[0].mask)
1036 leds |= 1;
1037 else
1038 leds &= ~1;
1039 }
1040 if (ledptrs[1].valid) {
1041 if (*ledptrs[1].addr & ledptrs[1].mask)
1042 leds |= 2;
1043 else
1044 leds &= ~2;
1045 }
1046 if (ledptrs[2].valid) {
1047 if (*ledptrs[2].addr & ledptrs[2].mask)
1048 leds |= 4;
1049 else
1050 leds &= ~4;
1051 }
1052 }
1053 return leds;
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 static void kbd_bh(void * unused)
1070 {
1071 unsigned char leds = getleds();
1072
1073 if (leds != ledstate) {
1074 ledstate = leds;
1075 if (!send_data(0xed) || !send_data(leds))
1076 send_data(0xf4);
1077 }
1078 if (want_console >= 0) {
1079 if (want_console != fg_console) {
1080 last_console = fg_console;
1081 change_console(want_console);
1082
1083
1084
1085 }
1086 want_console = -1;
1087 }
1088 poke_blanked_console();
1089 cli();
1090 if ((inb_p(0x64) & kbd_read_mask) == 0x01)
1091 fake_keyboard_interrupt();
1092 sti();
1093 }
1094
1095 long no_idt[2] = {0, 0};
1096
1097
1098
1099
1100
1101
1102 void hard_reset_now(void)
1103 {
1104 int i, j;
1105 extern unsigned long pg0[1024];
1106
1107 sti();
1108
1109 pg0[0] = 7;
1110 *((unsigned short *)0x472) = 0x1234;
1111 for (;;) {
1112 for (i=0; i<100; i++) {
1113 kb_wait();
1114 for(j = 0; j < 100000 ; j++)
1115 ;
1116 outb(0xfe,0x64);
1117 }
1118 __asm__("\tlidt _no_idt");
1119 }
1120 }
1121
1122 unsigned long kbd_init(unsigned long kmem_start)
1123 {
1124 int i;
1125 struct kbd_struct kbd0;
1126 extern struct tty_driver console_driver;
1127
1128 kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1129 kbd0.ledmode = LED_SHOW_FLAGS;
1130 kbd0.lockstate = KBD_DEFLOCK;
1131 kbd0.modeflags = KBD_DEFMODE;
1132 kbd0.kbdmode = VC_XLATE;
1133
1134 for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1135 kbd_table[i] = kbd0;
1136
1137 ttytab = console_driver.table;
1138
1139 bh_base[KEYBOARD_BH].routine = kbd_bh;
1140 request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
1141 mark_bh(KEYBOARD_BH);
1142 return kmem_start;
1143 }