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