1
2
3
4
5
6
7
8
9
10
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/tty.h>
16#include <linux/tty_flip.h>
17#include <linux/mm.h>
18#include <linux/ptrace.h>
19#include <linux/signal.h>
20#include <linux/string.h>
21#include <linux/fcntl.h>
22#include <linux/poll.h>
23#include <linux/random.h>
24#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/sysrq.h>
27#include <linux/spinlock.h>
28#include <linux/smp_lock.h>
29#include <linux/devfs_fs_kernel.h>
30
31#include <asm/kbio.h>
32#include <asm/vuid_event.h>
33#include <asm/bitops.h>
34#include <asm/oplib.h>
35#include <asm/uaccess.h>
36
37#include <linux/kbd_kern.h>
38#include <linux/kbd_diacr.h>
39#include <linux/vt_kern.h>
40
41#ifdef CONFIG_PCI
42#include <linux/pci.h>
43#include <asm/pbm.h>
44#include <asm/ebus.h>
45#endif
46
47#include "sunkbd.h"
48
49#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
50
51
52
53
54
55
56#define KBD_MAJOR 11
57
58#define KBD_REPORT_ERR
59#define KBD_REPORT_UNKN
60
61#ifndef KBD_DEFMODE
62#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
63#endif
64
65#ifndef KBD_DEFLEDS
66
67
68
69
70#define KBD_DEFLEDS 0
71#endif
72
73#ifndef KBD_DEFLOCK
74#define KBD_DEFLOCK 0
75#endif
76
77extern void poke_blanked_console(void);
78extern void ctrl_alt_del(void);
79extern void reset_vc(unsigned int new_console);
80extern void scrollback(int);
81extern void scrollfront(int);
82
83struct l1a_kbd_state l1a_state;
84
85static spinlock_t sunkbd_lock = SPIN_LOCK_UNLOCKED;
86
87
88
89
90
91
92
93
94static unsigned char k_down[NR_SHIFT];
95
96static unsigned long key_down[256/BITS_PER_LONG];
97
98void push_kbd (int scan);
99int kbd_redirected;
100
101static int dead_key_next;
102
103
104
105
106
107#ifndef CONFIG_PCI
108int shift_state;
109struct kbd_struct kbd_table[MAX_NR_CONSOLES];
110#endif
111static int npadch = -1;
112static unsigned char diacr;
113static char rep;
114static struct tty_struct **ttytab;
115static struct kbd_struct * kbd = kbd_table;
116static struct tty_struct * tty;
117static int compose_led_on;
118static int kbd_delay_ticks = HZ / 5;
119static int kbd_rate_ticks = HZ / 20;
120
121void sun_compute_shiftstate(void);
122
123typedef void (*k_hand)(unsigned char value, char up_flag);
124typedef void (k_handfn)(unsigned char value, char up_flag);
125
126static k_handfn
127 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
128 do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
129
130static k_hand key_handler[16] = {
131 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
132 do_meta, do_ascii, do_lock, do_lowercase,
133 do_ignore, do_ignore, do_ignore, do_ignore
134};
135
136typedef void (*void_fnp)(void);
137typedef void (void_fn)(void);
138
139static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
140 num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
141 SAK, decr_console, incr_console, spawn_console, bare_num;
142
143static void_fnp spec_fn_table[] = {
144 do_null, enter, show_ptregs, show_mem,
145 show_state, send_intr, lastcons, caps_toggle,
146 num, hold, scroll_forw, scroll_back,
147 boot_it, caps_on, compose, SAK,
148 decr_console, incr_console, spawn_console, bare_num
149};
150
151
152#ifndef CONFIG_PCI
153const int max_vals[] = {
154 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
155 NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
156 255, NR_ASCII - 1, NR_LOCK - 1, 255,
157 NR_LOCK - 1
158};
159
160const int NR_TYPES = SIZE(max_vals);
161#endif
162
163static void put_queue(int);
164static unsigned char handle_diacr(unsigned char);
165
166
167static struct pt_regs * pt_regs;
168
169#ifdef CONFIG_MAGIC_SYSRQ
170unsigned char sun_sysrq_xlate[128] =
171 "\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0"
172 "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312"
173 "34567890-=`\177\0=/*"
174 "\0\0.\0\0\011qwertyuiop"
175 "[]\177\000789-\0\0\0\0\0asd"
176 "fghjkl;'\\\015\0154560\0"
177 "\0\0\0\0zxcvbnm,./\0\012"
178 "123\0\0\0\0\0\0 \0\0\0\0\0\0";
179#endif
180
181volatile unsigned char sunkbd_layout;
182volatile unsigned char sunkbd_type;
183#define SUNKBD_TYPE2 0x02
184#define SUNKBD_TYPE3 0x03
185#define SUNKBD_TYPE4 0x04
186
187#define SUNKBD_LOUT_TYP4 0x00
188#define SUNKBD_LOUT_TYP5_MASK 0x20
189
190volatile int kbd_reset_pending;
191volatile int kbd_layout_pending;
192
193
194#define SKBDCMD_RESET 0x1
195#define SKBDCMD_GLAYOUT 0xf
196#define SKBDCMD_BELLON 0x2
197#define SKBDCMD_BELLOFF 0x3
198#define SKBDCMD_SETLED 0xe
199#define SKBDCMD_NOCLICK 0xb
200#define SKBDCMD_CLICK 0xa
201
202static unsigned char sunkbd_clickp;
203
204
205
206
207
208#define LED_NLOCK 0x1
209#define LED_CMPOSE 0x2
210#define LED_SCRLCK 0x4
211#define LED_CLOCK 0x8
212
213
214#define SKBD_RESET 0xff
215#define SKBD_ALLUP 0x7f
216#define SKBD_LYOUT 0xfe
217
218
219
220
221
222
223
224
225
226
227#define SUNKBD_UBIT 0x80
228#define SUNKBD_KMASK 0x7f
229
230#define KEY_LSHIFT 0x81
231#define KEY_RSHIFT 0x82
232#define KEY_CONTROL 0x83
233#define KEY_NILL 0x84
234#define KEY_CAPSLOCK 0x85
235#define KEY_ALT 0x86
236#define KEY_L1 0x87
237
238
239
240
241
242
243
244
245
246static void nop_kbd_put_char(unsigned char c) { }
247static void (*kbd_put_char)(unsigned char) = nop_kbd_put_char;
248
249
250static inline void send_cmd(unsigned char c)
251{
252 kbd_put_char(c);
253}
254
255
256
257
258
259
260static inline unsigned char vcleds_to_sunkbd(unsigned char vcleds)
261{
262 unsigned char retval = 0;
263
264 if(vcleds & (1<<VC_SCROLLOCK))
265 retval |= LED_SCRLCK;
266 if(vcleds & (1<<VC_NUMLOCK))
267 retval |= LED_NLOCK;
268 if(vcleds & (1<<VC_CAPSLOCK))
269 retval |= LED_CLOCK;
270 if(compose_led_on)
271 retval |= LED_CMPOSE;
272 return retval;
273}
274
275
276
277
278
279
280
281
282
283
284
285#define E0_KPENTER 96
286#define E0_RCTRL 97
287#define E0_KPSLASH 98
288#define E0_PRSCR 99
289#define E0_RALT 100
290#define E0_BREAK 101
291#define E0_HOME 102
292#define E0_UP 103
293#define E0_PGUP 104
294#define E0_LEFT 105
295#define E0_RIGHT 106
296#define E0_END 107
297#define E0_DOWN 108
298#define E0_PGDN 109
299#define E0_INS 110
300#define E0_DEL 111
301
302#define E1_PAUSE 119
303
304
305
306
307
308
309
310
311#define SC_LIM 89
312
313#define FOCUS_PF1 85
314#define FOCUS_PF2 89
315#define FOCUS_PF3 90
316#define FOCUS_PF4 91
317#define FOCUS_PF5 92
318#define FOCUS_PF6 93
319#define FOCUS_PF7 94
320#define FOCUS_PF8 95
321#define FOCUS_PF9 120
322#define FOCUS_PF10 121
323#define FOCUS_PF11 122
324#define FOCUS_PF12 123
325
326#define JAP_86 124
327
328
329
330
331
332
333#define RGN1 124
334#define RGN2 125
335#define RGN3 126
336#define RGN4 127
337
338static unsigned char high_keys[128 - SC_LIM] = {
339 RGN1, RGN2, RGN3, RGN4, 0, 0, 0,
340 0, 0, 0, 0, 0, 0, 0, 0,
341 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,
342 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,
343 FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,
344 FOCUS_PF8, JAP_86, FOCUS_PF10, 0
345};
346
347
348#define E0_MACRO 112
349
350#define E0_F13 113
351#define E0_F14 114
352#define E0_HELP 115
353#define E0_DO 116
354#define E0_F17 117
355#define E0_KPMINPLUS 118
356
357
358
359
360#define E0_OK 124
361
362
363
364
365
366
367#define E0_MSLW 125
368#define E0_MSRW 126
369#define E0_MSTM 127
370
371static unsigned char e0_keys[128] = {
372 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0,
377 0, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,
379 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,
380 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,
381 E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
382 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,
383 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,
384 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 0, 0, 0, 0, 0, 0, E0_MACRO,
386 0, 0, 0, 0, 0, 0, 0, 0,
387 0, 0, 0, 0, 0, 0, 0, 0
388};
389
390
391
392
393static unsigned char norepeat_keys[128] = {
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
395 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
400 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
401 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0,
402};
403
404
405int sun_setkeycode(unsigned int scancode, unsigned int keycode)
406{
407 if (scancode < SC_LIM || scancode > 255 || keycode > 127)
408 return -EINVAL;
409 if (scancode < 128)
410 high_keys[scancode - SC_LIM] = keycode;
411 else
412 e0_keys[scancode - 128] = keycode;
413 return 0;
414}
415
416int sun_getkeycode(unsigned int scancode)
417{
418 return
419 (scancode < SC_LIM || scancode > 255) ? -EINVAL :
420 (scancode < 128) ? high_keys[scancode - SC_LIM] :
421 e0_keys[scancode - 128];
422}
423
424static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs);
425void sunkbd_inchar(unsigned char ch, struct pt_regs *regs);
426static void keyboard_timer (unsigned long ignored);
427
428static struct timer_list
429auto_repeat_timer = { function: keyboard_timer };
430
431
432static unsigned char last_keycode;
433
434static void
435keyboard_timer (unsigned long ignored)
436{
437 unsigned long flags;
438
439 spin_lock_irqsave(&sunkbd_lock, flags);
440
441
442 __sunkbd_inchar (last_keycode, 0);
443 del_timer (&auto_repeat_timer);
444 if (kbd_rate_ticks) {
445 auto_repeat_timer.expires = jiffies + kbd_rate_ticks;
446 add_timer (&auto_repeat_timer);
447 }
448
449 spin_unlock_irqrestore(&sunkbd_lock, flags);
450}
451
452#ifndef CONFIG_PCI
453DECLARE_TASKLET_DISABLED(keyboard_tasklet, sun_kbd_bh, 0);
454#endif
455
456
457
458
459
460static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
461{
462 unsigned char keycode;
463 char up_flag;
464 char raw_mode;
465
466 if(ch == SKBD_RESET) {
467 kbd_reset_pending = 1;
468 goto out;
469 }
470 if(ch == SKBD_LYOUT) {
471 kbd_layout_pending = 1;
472 goto out;
473 }
474 if(kbd_reset_pending) {
475 sunkbd_type = ch;
476 kbd_reset_pending = 0;
477 if(ch == SUNKBD_TYPE4)
478 send_cmd(SKBDCMD_GLAYOUT);
479 goto out;
480 } else if(kbd_layout_pending) {
481 sunkbd_layout = ch;
482 kbd_layout_pending = 0;
483 goto out;
484 } else if(ch == SKBD_ALLUP) {
485 del_timer (&auto_repeat_timer);
486 memset(key_down, 0, sizeof(key_down));
487 sun_compute_shiftstate();
488 goto out;
489 }
490#ifdef SKBD_DEBUG
491 if(ch == 0x7f)
492 printk("KBD<ALL KEYS UP>");
493 else
494 printk("KBD<%x %s>", ch,
495 ((ch&0x80) ? "UP" : "DOWN"));
496#endif
497
498
499 if(regs) {
500 pt_regs = regs;
501 last_keycode = keycode = ch;
502 } else {
503 keycode = ch;
504 }
505
506 do_poke_blanked_console = 1;
507 schedule_console_callback();
508 add_keyboard_randomness(keycode);
509
510 tty = ttytab? ttytab[fg_console]: NULL;
511 if (tty && (!tty->driver_data)) {
512
513
514 tty = NULL;
515 }
516 kbd = kbd_table + fg_console;
517 if((raw_mode = (kbd->kbdmode == VC_RAW))) {
518 if (kbd_redirected == fg_console+1)
519 push_kbd (keycode);
520 else
521 put_queue(keycode);
522
523
524
525
526 }
527 up_flag = (keycode & SUNKBD_UBIT);
528 keycode &= SUNKBD_KMASK;
529 del_timer (&auto_repeat_timer);
530 if(up_flag) {
531 rep = 0;
532 clear_bit(keycode, key_down);
533 } else {
534 if (!norepeat_keys[keycode]) {
535 if (kbd_rate_ticks) {
536 auto_repeat_timer.expires =
537 jiffies + kbd_delay_ticks;
538 add_timer (&auto_repeat_timer);
539 }
540 }
541 rep = test_and_set_bit(keycode, key_down);
542 }
543
544#ifdef CONFIG_MAGIC_SYSRQ
545 if (l1a_state.l1_down) {
546 if (!up_flag)
547 handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty);
548 goto out;
549 }
550#endif
551
552 if(raw_mode)
553 goto out;
554
555 if(kbd->kbdmode == VC_MEDIUMRAW) {
556 put_queue(keycode + up_flag);
557 goto out;
558 }
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573 if (!rep ||
574 (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
575 (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
576 u_short keysym;
577 u_char type;
578
579
580 int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
581 ushort *key_map = key_maps[shift_final];
582
583 if (key_map != NULL) {
584 keysym = key_map[keycode];
585 type = KTYP(keysym);
586
587 if (type >= 0xf0) {
588 type -= 0xf0;
589 if (type == KT_LETTER) {
590 type = KT_LATIN;
591 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
592 key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
593 if (key_map)
594 keysym = key_map[keycode];
595 }
596 }
597 (*key_handler[type])(keysym & 0xff, up_flag);
598 if (type != KT_SLOCK)
599 kbd->slockstate = 0;
600 }
601 } else {
602
603
604 sun_compute_shiftstate();
605 }
606 }
607out:
608 tasklet_schedule(&keyboard_tasklet);
609}
610
611void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
612{
613 unsigned long flags;
614
615 spin_lock_irqsave(&sunkbd_lock, flags);
616 __sunkbd_inchar(ch, regs);
617 spin_unlock_irqrestore(&sunkbd_lock, flags);
618}
619
620static void put_queue(int ch)
621{
622 if (tty) {
623 tty_insert_flip_char(tty, ch, 0);
624 con_schedule_flip(tty);
625 }
626}
627
628static void puts_queue(char *cp)
629{
630 if (!tty)
631 return;
632
633 while (*cp) {
634 tty_insert_flip_char(tty, *cp, 0);
635 cp++;
636 }
637 con_schedule_flip(tty);
638}
639
640static void applkey(int key, char mode)
641{
642 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
643
644 buf[1] = (mode ? 'O' : '[');
645 buf[2] = key;
646 puts_queue(buf);
647}
648
649static void enter(void)
650{
651 put_queue(13);
652 if (vc_kbd_mode(kbd,VC_CRLF))
653 put_queue(10);
654}
655
656static void caps_toggle(void)
657{
658 if (rep)
659 return;
660 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
661}
662
663static void caps_on(void)
664{
665 if (rep)
666 return;
667 set_vc_kbd_led(kbd, VC_CAPSLOCK);
668}
669
670static void show_ptregs(void)
671{
672 if (pt_regs)
673 show_regs(pt_regs);
674}
675
676static void hold(void)
677{
678 if (rep || !tty)
679 return;
680
681
682
683
684
685
686 if (tty->stopped)
687 start_tty(tty);
688 else
689 stop_tty(tty);
690}
691
692static void num(void)
693{
694 if (vc_kbd_mode(kbd,VC_APPLIC))
695 applkey('P', 1);
696 else
697 bare_num();
698}
699
700
701
702
703
704
705
706static void bare_num(void)
707{
708 if (!rep)
709 chg_vc_kbd_led(kbd,VC_NUMLOCK);
710}
711
712static void lastcons(void)
713{
714
715 set_console(last_console);
716}
717
718static void decr_console(void)
719{
720 int i;
721
722 for (i = fg_console-1; i != fg_console; i--) {
723 if (i == -1)
724 i = MAX_NR_CONSOLES-1;
725 if (vc_cons_allocated(i))
726 break;
727 }
728 set_console(i);
729}
730
731static void incr_console(void)
732{
733 int i;
734
735 for (i = fg_console+1; i != fg_console; i++) {
736 if (i == MAX_NR_CONSOLES)
737 i = 0;
738 if (vc_cons_allocated(i))
739 break;
740 }
741 set_console(i);
742}
743
744static void send_intr(void)
745{
746 if (!tty)
747 return;
748 tty_insert_flip_char(tty, 0, TTY_BREAK);
749 con_schedule_flip(tty);
750}
751
752static void scroll_forw(void)
753{
754 scrollfront(0);
755}
756
757static void scroll_back(void)
758{
759 scrollback(0);
760}
761
762static void boot_it(void)
763{
764 extern int obp_system_intr(void);
765
766 if (!obp_system_intr())
767 ctrl_alt_del();
768
769 last_keycode=1;
770 rep = 0;
771}
772
773static void compose(void)
774{
775 dead_key_next = 1;
776 compose_led_on = 1;
777 set_leds();
778}
779
780#ifdef CONFIG_PCI
781extern int spawnpid, spawnsig;
782#else
783int spawnpid, spawnsig;
784#endif
785
786
787static void spawn_console(void)
788{
789 if (spawnpid)
790 if(kill_proc(spawnpid, spawnsig, 1))
791 spawnpid = 0;
792}
793
794static void SAK(void)
795{
796 do_SAK(tty);
797#if 0
798
799
800
801
802
803
804
805
806
807 reset_vc(fg_console);
808 do_unblank_screen();
809#endif
810}
811
812static void do_ignore(unsigned char value, char up_flag)
813{
814}
815
816static void do_null()
817{
818 sun_compute_shiftstate();
819}
820
821static void do_spec(unsigned char value, char up_flag)
822{
823 if (up_flag)
824 return;
825 if (value >= SIZE(spec_fn_table))
826 return;
827 spec_fn_table[value]();
828}
829
830static void do_lowercase(unsigned char value, char up_flag)
831{
832 printk("keyboard.c: do_lowercase was called - impossible\n");
833}
834
835static void do_self(unsigned char value, char up_flag)
836{
837 if (up_flag)
838 return;
839
840 if (diacr) {
841 value = handle_diacr(value);
842 compose_led_on = 0;
843 set_leds();
844 }
845
846 if (dead_key_next) {
847 dead_key_next = 0;
848 diacr = value;
849 return;
850 }
851
852 put_queue(value);
853}
854
855#define A_GRAVE '`'
856#define A_ACUTE '\''
857#define A_CFLEX '^'
858#define A_TILDE '~'
859#define A_DIAER '"'
860#define A_CEDIL ','
861static unsigned char ret_diacr[NR_DEAD] =
862 {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
863
864
865
866
867static void do_dead(unsigned char value, char up_flag)
868{
869 if (up_flag)
870 return;
871
872 value = ret_diacr[value];
873 if (diacr == value) {
874 diacr = 0;
875 put_queue(value);
876 return;
877 }
878 diacr = value;
879}
880
881
882
883
884
885unsigned char handle_diacr(unsigned char ch)
886{
887 int d = diacr;
888 int i;
889
890 diacr = 0;
891 if (ch == ' ')
892 return d;
893
894 for (i = 0; i < accent_table_size; i++) {
895 if (accent_table[i].diacr == d && accent_table[i].base == ch)
896 return accent_table[i].result;
897 }
898
899 put_queue(d);
900 return ch;
901}
902
903static void do_cons(unsigned char value, char up_flag)
904{
905 if (up_flag)
906 return;
907 set_console(value);
908}
909
910static void do_fn(unsigned char value, char up_flag)
911{
912 if (up_flag)
913 return;
914 if (value < SIZE(func_table)) {
915 if (func_table[value])
916 puts_queue(func_table[value]);
917 } else
918 printk("do_fn called with value=%d\n", value);
919}
920
921static void do_pad(unsigned char value, char up_flag)
922{
923 static const char *pad_chars = "0123456789+-*/\015,.?";
924 static const char *app_map = "pqrstuvwxylSRQMnn?";
925
926 if (up_flag)
927 return;
928
929
930 if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
931 applkey(app_map[value], 1);
932 return;
933 }
934
935 if (!vc_kbd_led(kbd,VC_NUMLOCK))
936 switch (value) {
937 case KVAL(K_PCOMMA):
938 case KVAL(K_PDOT):
939 do_fn(KVAL(K_REMOVE), 0);
940 return;
941 case KVAL(K_P0):
942 do_fn(KVAL(K_INSERT), 0);
943 return;
944 case KVAL(K_P1):
945 do_fn(KVAL(K_SELECT), 0);
946 return;
947 case KVAL(K_P2):
948 do_cur(KVAL(K_DOWN), 0);
949 return;
950 case KVAL(K_P3):
951 do_fn(KVAL(K_PGDN), 0);
952 return;
953 case KVAL(K_P4):
954 do_cur(KVAL(K_LEFT), 0);
955 return;
956 case KVAL(K_P6):
957 do_cur(KVAL(K_RIGHT), 0);
958 return;
959 case KVAL(K_P7):
960 do_fn(KVAL(K_FIND), 0);
961 return;
962 case KVAL(K_P8):
963 do_cur(KVAL(K_UP), 0);
964 return;
965 case KVAL(K_P9):
966 do_fn(KVAL(K_PGUP), 0);
967 return;
968 case KVAL(K_P5):
969 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
970 return;
971 }
972
973 put_queue(pad_chars[value]);
974 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
975 put_queue(10);
976}
977
978static void do_cur(unsigned char value, char up_flag)
979{
980 static const char *cur_chars = "BDCA";
981 if (up_flag)
982 return;
983
984 applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
985}
986
987static void do_shift(unsigned char value, char up_flag)
988{
989 int old_state = shift_state;
990
991 if (rep)
992 return;
993
994
995
996 if (value == KVAL(K_CAPSSHIFT)) {
997 value = KVAL(K_SHIFT);
998 if (!up_flag)
999 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
1000 }
1001
1002 if (up_flag) {
1003
1004
1005 if (k_down[value])
1006 k_down[value]--;
1007 } else
1008 k_down[value]++;
1009
1010 if (k_down[value])
1011 shift_state |= (1 << value);
1012 else
1013 shift_state &= ~ (1 << value);
1014
1015
1016 if (up_flag && shift_state != old_state && npadch != -1) {
1017 put_queue(npadch & 0xff);
1018 npadch = -1;
1019 }
1020}
1021
1022
1023
1024
1025void sun_compute_shiftstate(void)
1026{
1027 int i, j, k, sym, val;
1028
1029 shift_state = 0;
1030 for(i=0; i < SIZE(k_down); i++)
1031 k_down[i] = 0;
1032
1033 for(i=0; i < SIZE(key_down); i++)
1034 if(key_down[i]) {
1035 k = i*BITS_PER_LONG;
1036 for(j=0; j<BITS_PER_LONG; j++,k++)
1037 if(test_bit(k, key_down)) {
1038 sym = U(plain_map[k]);
1039 if(KTYP(sym) == KT_SHIFT) {
1040 val = KVAL(sym);
1041 if (val == KVAL(K_CAPSSHIFT))
1042 val = KVAL(K_SHIFT);
1043 k_down[val]++;
1044 shift_state |= (1<<val);
1045 }
1046 }
1047 }
1048}
1049
1050static void do_meta(unsigned char value, char up_flag)
1051{
1052 if (up_flag)
1053 return;
1054
1055 if (vc_kbd_mode(kbd, VC_META)) {
1056 put_queue('\033');
1057 put_queue(value);
1058 } else
1059 put_queue(value | 0x80);
1060}
1061
1062static void do_ascii(unsigned char value, char up_flag)
1063{
1064 int base;
1065
1066 if (up_flag)
1067 return;
1068
1069 if (value < 10)
1070 base = 10;
1071 else {
1072 value -= 10;
1073 base = 16;
1074 }
1075
1076 if (npadch == -1)
1077 npadch = value;
1078 else
1079 npadch = npadch * base + value;
1080}
1081
1082static void do_lock(unsigned char value, char up_flag)
1083{
1084 if (up_flag || rep)
1085 return;
1086 chg_vc_kbd_lock(kbd, value);
1087}
1088
1089
1090
1091
1092
1093
1094
1095static unsigned char ledstate = 0xff;
1096static unsigned char ledioctl;
1097
1098unsigned char sun_getledstate(void) {
1099 return ledstate;
1100}
1101
1102void sun_setledstate(struct kbd_struct *kbd, unsigned int led) {
1103 if (!(led & ~7)) {
1104 ledioctl = led;
1105 kbd->ledmode = LED_SHOW_IOCTL;
1106 } else
1107 kbd->ledmode = LED_SHOW_FLAGS;
1108 set_leds();
1109}
1110
1111static struct ledptr {
1112 unsigned int *addr;
1113 unsigned int mask;
1114 unsigned char valid:1;
1115} ledptrs[3];
1116
1117void register_leds(int console, unsigned int led,
1118 unsigned int *addr, unsigned int mask) {
1119 struct kbd_struct *kbd = kbd_table + console;
1120 if (led < 3) {
1121 ledptrs[led].addr = addr;
1122 ledptrs[led].mask = mask;
1123 ledptrs[led].valid = 1;
1124 kbd->ledmode = LED_SHOW_MEM;
1125 } else
1126 kbd->ledmode = LED_SHOW_FLAGS;
1127}
1128
1129static inline unsigned char getleds(void){
1130 struct kbd_struct *kbd = kbd_table + fg_console;
1131 unsigned char leds;
1132
1133 if (kbd->ledmode == LED_SHOW_IOCTL)
1134 return ledioctl;
1135 leds = kbd->ledflagstate;
1136 if (kbd->ledmode == LED_SHOW_MEM) {
1137 if (ledptrs[0].valid) {
1138 if (*ledptrs[0].addr & ledptrs[0].mask)
1139 leds |= 1;
1140 else
1141 leds &= ~1;
1142 }
1143 if (ledptrs[1].valid) {
1144 if (*ledptrs[1].addr & ledptrs[1].mask)
1145 leds |= 2;
1146 else
1147 leds &= ~2;
1148 }
1149 if (ledptrs[2].valid) {
1150 if (*ledptrs[2].addr & ledptrs[2].mask)
1151 leds |= 4;
1152 else
1153 leds &= ~4;
1154 }
1155 }
1156 return leds;
1157}
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172static unsigned char sunkbd_ledstate = 0xff;
1173void sun_kbd_bh(unsigned long dummy)
1174{
1175 unsigned long flags;
1176 unsigned char leds, kbd_leds;
1177
1178 spin_lock_irqsave(&sunkbd_lock, flags);
1179
1180 leds = getleds();
1181 kbd_leds = vcleds_to_sunkbd(leds);
1182 if (kbd_leds != sunkbd_ledstate) {
1183 ledstate = leds;
1184 sunkbd_ledstate = kbd_leds;
1185 send_cmd(SKBDCMD_SETLED);
1186 send_cmd(kbd_leds);
1187 }
1188
1189 spin_unlock_irqrestore(&sunkbd_lock, flags);
1190}
1191
1192
1193
1194
1195static void sunkbd_kd_nosound(unsigned long __unused)
1196{
1197 unsigned long flags;
1198
1199 spin_lock_irqsave(&sunkbd_lock, flags);
1200 send_cmd(SKBDCMD_BELLOFF);
1201 spin_unlock_irqrestore(&sunkbd_lock, flags);
1202}
1203
1204
1205
1206
1207
1208
1209
1210static void sunkbd_kd_mksound(unsigned int hz, unsigned int ticks)
1211{
1212 unsigned long flags;
1213 static struct timer_list sound_timer = { function: sunkbd_kd_nosound };
1214
1215 spin_lock_irqsave(&sunkbd_lock, flags);
1216
1217 del_timer(&sound_timer);
1218
1219 if (hz) {
1220 send_cmd(SKBDCMD_BELLON);
1221 if (ticks) {
1222 sound_timer.expires = jiffies + ticks;
1223 add_timer(&sound_timer);
1224 }
1225 } else
1226 send_cmd(SKBDCMD_BELLOFF);
1227
1228 spin_unlock_irqrestore(&sunkbd_lock, flags);
1229}
1230
1231extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
1232
1233int __init sun_kbd_init(void)
1234{
1235 int i, opt_node;
1236 struct kbd_struct kbd0;
1237 extern struct tty_driver console_driver;
1238
1239 kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1240 kbd0.ledmode = LED_SHOW_FLAGS;
1241 kbd0.lockstate = KBD_DEFLOCK;
1242 kbd0.slockstate = 0;
1243 kbd0.modeflags = KBD_DEFMODE;
1244 kbd0.kbdmode = VC_XLATE;
1245
1246 for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1247 kbd_table[i] = kbd0;
1248
1249 ttytab = console_driver.table;
1250
1251 kd_mksound = sunkbd_kd_mksound;
1252
1253
1254 if(sparc_cpu_model != sun4) {
1255 opt_node = prom_getchild(prom_root_node);
1256 opt_node = prom_searchsiblings(opt_node, "options");
1257 i = prom_getintdefault(opt_node, "keyboard-click?", -1);
1258 if(i != -1)
1259 sunkbd_clickp = 1;
1260 else
1261 sunkbd_clickp = 0;
1262 } else {
1263 sunkbd_clickp = 0;
1264 }
1265
1266 keyboard_tasklet.func = sun_kbd_bh;
1267
1268 tasklet_enable(&keyboard_tasklet);
1269 tasklet_schedule(&keyboard_tasklet);
1270
1271 return 0;
1272}
1273
1274
1275
1276#define KBD_QSIZE 32
1277static Firm_event kbd_queue [KBD_QSIZE];
1278static int kbd_head, kbd_tail;
1279static spinlock_t kbd_queue_lock = SPIN_LOCK_UNLOCKED;
1280char kbd_opened;
1281static int kbd_active = 0;
1282static DECLARE_WAIT_QUEUE_HEAD(kbd_wait);
1283static struct fasync_struct *kb_fasync;
1284
1285void
1286push_kbd (int scan)
1287{
1288 unsigned long flags;
1289 int next;
1290
1291 if (scan == KBD_IDLE)
1292 return;
1293
1294 spin_lock_irqsave(&kbd_queue_lock, flags);
1295 next = (kbd_head + 1) % KBD_QSIZE;
1296 if (next != kbd_tail){
1297 kbd_queue [kbd_head].id = scan & KBD_KEYMASK;
1298 kbd_queue [kbd_head].value=scan & KBD_UP ? VKEY_UP : VKEY_DOWN;
1299 kbd_queue [kbd_head].time = xtime;
1300 kbd_head = next;
1301 }
1302 spin_unlock_irqrestore(&kbd_queue_lock, flags);
1303
1304 kill_fasync (&kb_fasync, SIGIO, POLL_IN);
1305 wake_up_interruptible (&kbd_wait);
1306}
1307
1308static ssize_t
1309kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos)
1310{
1311 DECLARE_WAITQUEUE(wait, current);
1312 unsigned long flags;
1313 char *end, *p;
1314
1315
1316 if (kbd_head == kbd_tail){
1317 if (f->f_flags & O_NONBLOCK)
1318 return -EWOULDBLOCK;
1319 add_wait_queue (&kbd_wait, &wait);
1320repeat:
1321 set_current_state(TASK_INTERRUPTIBLE);
1322 if (kbd_head == kbd_tail && !signal_pending(current)) {
1323 schedule();
1324 goto repeat;
1325 }
1326 current->state = TASK_RUNNING;
1327 remove_wait_queue (&kbd_wait, &wait);
1328 }
1329
1330 end = buffer+count;
1331 p = buffer;
1332 spin_lock_irqsave(&kbd_queue_lock, flags);
1333 for (; p < end && kbd_head != kbd_tail;){
1334 Firm_event this_event = kbd_queue[kbd_tail];
1335
1336 kbd_tail = (kbd_tail + 1) % KBD_QSIZE;
1337
1338 spin_unlock_irqrestore(&kbd_queue_lock, flags);
1339
1340#ifdef CONFIG_SPARC32_COMPAT
1341 if (current->thread.flags & SPARC_FLAG_32BIT) {
1342 if (copy_to_user((Firm_event *)p, &this_event,
1343 sizeof(Firm_event)-sizeof(struct timeval)))
1344 return -EFAULT;
1345 p += sizeof(Firm_event)-sizeof(struct timeval);
1346 if (__put_user(this_event.time.tv_sec, (u32 *)p))
1347 return -EFAULT;
1348 p += sizeof(u32);
1349 if (__put_user(this_event.time.tv_usec, (u32 *)p))
1350 return -EFAULT;
1351 p += sizeof(u32);
1352 } else
1353#endif
1354 {
1355 if (copy_to_user((Firm_event *)p, &this_event,
1356 sizeof(Firm_event)))
1357 return -EFAULT;
1358 p += sizeof (Firm_event);
1359 }
1360#ifdef KBD_DEBUG
1361 printk ("[%s]", this_event.value == VKEY_UP ? "UP" : "DOWN");
1362#endif
1363
1364 spin_lock_irqsave(&kbd_queue_lock, flags);
1365 }
1366
1367 spin_unlock_irqrestore(&kbd_queue_lock, flags);
1368
1369 return p-buffer;
1370}
1371
1372
1373static int kbd_fasync (int fd, struct file *filp, int on)
1374{
1375 int retval;
1376
1377 retval = fasync_helper (fd, filp, on, &kb_fasync);
1378 if (retval < 0)
1379 return retval;
1380 return 0;
1381}
1382
1383static unsigned int kbd_poll (struct file *f, poll_table *wait)
1384{
1385 poll_wait(f, &kbd_wait, wait);
1386 if (kbd_head != kbd_tail)
1387 return POLLIN | POLLRDNORM;
1388 return 0;
1389}
1390
1391static int
1392kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
1393{
1394 unsigned char c;
1395 unsigned char leds = 0;
1396 int value;
1397
1398 switch (cmd){
1399 case KIOCTYPE:
1400 if (put_user(sunkbd_type, (int *) arg))
1401 return -EFAULT;
1402 break;
1403 case KIOCGTRANS:
1404 if (put_user(TR_UNTRANS_EVENT, (int *) arg))
1405 return -EFAULT;
1406 break;
1407 case KIOCTRANS:
1408 if (get_user(value, (int *) arg))
1409 return -EFAULT;
1410 if (value != TR_UNTRANS_EVENT)
1411 return -EINVAL;
1412 break;
1413 case KIOCLAYOUT:
1414 if (put_user(sunkbd_layout, (int *) arg))
1415 return -EFAULT;
1416 break;
1417 case KIOCSDIRECT:
1418#ifndef CODING_NEW_DRIVER
1419 if (get_user(value, (int *) arg))
1420 return -EFAULT;
1421 if(value)
1422 kbd_redirected = fg_console + 1;
1423 else
1424 kbd_redirected = 0;
1425 kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE;
1426#endif
1427 break;
1428 case KIOCCMD:
1429 if (get_user(value, (int *) arg))
1430 return -EFAULT;
1431 c = (unsigned char) value;
1432 switch (c) {
1433 case SKBDCMD_CLICK:
1434 case SKBDCMD_NOCLICK:
1435 spin_lock_irq(&sunkbd_lock);
1436 send_cmd(c);
1437 spin_unlock_irq(&sunkbd_lock);
1438 return 0;
1439 case SKBDCMD_BELLON:
1440 kd_mksound(1,0);
1441 return 0;
1442 case SKBDCMD_BELLOFF:
1443 kd_mksound(0,0);
1444 return 0;
1445 default:
1446 return -EINVAL;
1447 }
1448 case KIOCSLED:
1449 if (get_user(c, (unsigned char *) arg))
1450 return -EFAULT;
1451
1452 if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK);
1453 if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK);
1454 if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK);
1455 compose_led_on = !!(c & LED_CMPOSE);
1456 sun_setledstate(kbd_table + fg_console, leds);
1457 break;
1458 case KIOCGLED:
1459 if (put_user(vcleds_to_sunkbd(getleds()), (unsigned char *) arg))
1460 return -EFAULT;
1461 break;
1462 case KIOCGRATE:
1463 {
1464 struct kbd_rate rate;
1465
1466 rate.delay = kbd_delay_ticks;
1467 if (kbd_rate_ticks)
1468 rate.rate = HZ / kbd_rate_ticks;
1469 else
1470 rate.rate = 0;
1471
1472 if (copy_to_user((struct kbd_rate *)arg, &rate,
1473 sizeof(struct kbd_rate)))
1474 return -EFAULT;
1475
1476 return 0;
1477 }
1478 case KIOCSRATE:
1479 {
1480 struct kbd_rate rate;
1481
1482 if (verify_area(VERIFY_READ, (void *)arg,
1483 sizeof(struct kbd_rate)))
1484 return -EFAULT;
1485 copy_from_user(&rate, (struct kbd_rate *)arg,
1486 sizeof(struct kbd_rate));
1487
1488 if (rate.rate > 50)
1489 return -EINVAL;
1490 if (rate.rate == 0)
1491 kbd_rate_ticks = 0;
1492 else
1493 kbd_rate_ticks = HZ / rate.rate;
1494 kbd_delay_ticks = rate.delay;
1495
1496 return 0;
1497 }
1498 case FIONREAD:
1499 {
1500 int count;
1501
1502 count = kbd_head - kbd_tail;
1503 if (put_user((count < 0) ? KBD_QSIZE - count : count, (int *) arg))
1504 return -EFAULT;
1505 return 0;
1506 }
1507 default:
1508 printk ("Unknown Keyboard ioctl: %8.8x\n", cmd);
1509 return -EINVAL;
1510 }
1511 return 0;
1512}
1513
1514static int
1515kbd_open (struct inode *i, struct file *f)
1516{
1517 spin_lock_irq(&kbd_queue_lock);
1518 kbd_active++;
1519
1520 if (kbd_opened)
1521 goto out;
1522
1523 kbd_opened = fg_console + 1;
1524
1525 kbd_head = kbd_tail = 0;
1526
1527 out:
1528 spin_unlock_irq(&kbd_queue_lock);
1529
1530 return 0;
1531}
1532
1533static int
1534kbd_close (struct inode *i, struct file *f)
1535{
1536 spin_lock_irq(&kbd_queue_lock);
1537 if (!--kbd_active) {
1538 if (kbd_redirected)
1539 kbd_table [kbd_redirected-1].kbdmode = VC_XLATE;
1540 kbd_redirected = 0;
1541 kbd_opened = 0;
1542 kbd_fasync (-1, f, 0);
1543 }
1544 spin_unlock_irq(&kbd_queue_lock);
1545
1546 return 0;
1547}
1548
1549static struct file_operations kbd_fops =
1550{
1551 read: kbd_read,
1552 poll: kbd_poll,
1553 ioctl: kbd_ioctl,
1554 open: kbd_open,
1555 release: kbd_close,
1556 fasync: kbd_fasync,
1557};
1558
1559void __init keyboard_zsinit(void (*put_char)(unsigned char))
1560{
1561 int timeout = 0;
1562
1563 kbd_put_char = put_char;
1564 if (!kbd_put_char)
1565 panic("keyboard_zsinit: no put_char parameter");
1566
1567
1568 sunkbd_type = 255;
1569 sunkbd_layout = 0;
1570
1571 send_cmd(SKBDCMD_RESET);
1572 send_cmd(SKBDCMD_RESET);
1573 while((sunkbd_type==255) && timeout++ < 25000) {
1574 udelay(100);
1575 barrier();
1576 }
1577
1578 if(timeout>=25000) {
1579 printk("keyboard: not present\n");
1580 return;
1581 }
1582
1583 if(sunkbd_type != SUNKBD_TYPE4) {
1584 printk("Sun TYPE %d keyboard detected ", sunkbd_type);
1585 } else {
1586 timeout=0;
1587 while((sunkbd_layout==0) && timeout++ < 10000) {
1588 udelay(100);
1589 barrier();
1590 }
1591 printk("Sun TYPE %d keyboard detected ",
1592 ((sunkbd_layout & SUNKBD_LOUT_TYP5_MASK) ? 5 : 4));
1593 }
1594 if(sunkbd_type == SUNKBD_TYPE2)
1595 sunkbd_clickp = 0;
1596
1597 spin_lock_irq(&sunkbd_lock);
1598
1599 if(sunkbd_clickp) {
1600 send_cmd(SKBDCMD_CLICK);
1601 printk("with keyclick\n");
1602 } else {
1603 send_cmd(SKBDCMD_NOCLICK);
1604 printk("without keyclick\n");
1605 }
1606
1607
1608 send_cmd(SKBDCMD_SETLED); send_cmd(0xf);
1609 send_cmd(SKBDCMD_SETLED); send_cmd(0x0);
1610
1611 spin_unlock_irq(&sunkbd_lock);
1612
1613
1614 devfs_register (NULL, "kbd", DEVFS_FL_DEFAULT,
1615 KBD_MAJOR, 0,
1616 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
1617 &kbd_fops, NULL);
1618 if (devfs_register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
1619 printk ("Could not register /dev/kbd device\n");
1620 return;
1621 }
1622 return;
1623}
1624