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