Import 2.1.118
[davej-history.git] / drivers / sbus / char / sunkbd.c
blob59b77a5e4d265edb6393a9c7f1f3b436755a4ada
1 /* keyboard.c: Sun keyboard driver.
3 * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
5 * Added vuid event generation and /dev/kbd device for SunOS
6 * compatibility - Miguel (miguel@nuclecu.unam.mx)
8 * Added PCI 8042 controller support -DaveM
9 * Added Magic SysRq support -MJ
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>
28 #include <asm/kbio.h>
29 #include <asm/vuid_event.h>
30 #include <asm/bitops.h>
31 #include <asm/oplib.h>
32 #include <asm/uaccess.h>
34 #include <linux/kbd_kern.h>
35 #include <linux/kbd_diacr.h>
36 #include <linux/vt_kern.h>
38 #ifdef CONFIG_PCI
39 #include <linux/pci.h>
40 #include <asm/pbm.h>
41 #include <asm/ebus.h>
42 #endif
44 #include "sunkbd.h"
46 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
48 /* Define this one if you are making a new frame buffer driver */
49 /* it will not block the keyboard */
50 /* #define CODING_NEW_DRIVER */
52 /* KBD device number, temporal */
53 #define KBD_MAJOR 11
55 #define KBD_REPORT_ERR
56 #define KBD_REPORT_UNKN
58 #ifndef KBD_DEFMODE
59 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
60 #endif
62 #ifndef KBD_DEFLEDS
64 * Some laptops take the 789uiojklm,. keys as number pad when NumLock
65 * is on. This seems a good reason to start with NumLock off.
67 #define KBD_DEFLEDS 0
68 #endif
70 #ifndef KBD_DEFLOCK
71 #define KBD_DEFLOCK 0
72 #endif
74 extern void poke_blanked_console(void);
75 extern void ctrl_alt_del(void);
76 extern void reset_vc(unsigned int new_console);
77 extern void scrollback(int);
78 extern void scrollfront(int);
80 struct l1a_kbd_state l1a_state = { 0, 0 };
82 /* Dummy function for now, we need it to link. -DaveM */
83 void kbd_reset_setup(char *str, int *ints)
87 #ifndef CONFIG_PCI
88 struct wait_queue * keypress_wait = NULL;
89 #endif
91 int keyboard_wait_for_keypress(struct console *co)
93 sleep_on(&keypress_wait);
94 return 0;
98 * global state includes the following, and various static variables
99 * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
100 * (last_console is now a global variable)
103 /* shift state counters.. */
104 static unsigned char k_down[NR_SHIFT] = {0, };
105 /* keyboard key bitmap */
106 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
108 void push_kbd (int scan);
109 int kbd_redirected = 0;
111 static int dead_key_next = 0;
113 * In order to retrieve the shift_state (for the mouse server), either
114 * the variable must be global, or a new procedure must be created to
115 * return the value. I chose the former way.
117 #ifndef CONFIG_PCI
118 /*static*/ int shift_state = 0;
119 #endif
120 static int npadch = -1; /* -1 or number assembled on pad */
121 static unsigned char diacr = 0;
122 static char rep = 0; /* flag telling character repeat */
123 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
124 static struct tty_struct **ttytab;
125 static struct kbd_struct * kbd = kbd_table;
126 static struct tty_struct * tty = NULL;
127 static int compose_led_on = 0;
128 static int kbd_delay_ticks = HZ / 5;
129 static int kbd_rate_ticks = HZ / 20;
131 void sun_compute_shiftstate(void);
133 typedef void (*k_hand)(unsigned char value, char up_flag);
134 typedef void (k_handfn)(unsigned char value, char up_flag);
136 static k_handfn
137 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
138 do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
140 static k_hand key_handler[16] = {
141 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
142 do_meta, do_ascii, do_lock, do_lowercase,
143 do_ignore, do_ignore, do_ignore, do_ignore
146 typedef void (*void_fnp)(void);
147 typedef void (void_fn)(void);
149 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
150 num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
151 SAK, decr_console, incr_console, spawn_console, bare_num;
153 static void_fnp spec_fn_table[] = {
154 do_null, enter, show_ptregs, show_mem,
155 show_state, send_intr, lastcons, caps_toggle,
156 num, hold, scroll_forw, scroll_back,
157 boot_it, caps_on, compose, SAK,
158 decr_console, incr_console, spawn_console, bare_num
161 /* maximum values each key_handler can handle */
162 #ifndef CONFIG_PCI
163 const int max_vals[] = {
164 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
165 NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
166 255, NR_ASCII - 1, NR_LOCK - 1, 255,
167 NR_LOCK - 1
170 const int NR_TYPES = SIZE(max_vals);
171 #endif
173 static void put_queue(int);
174 static unsigned char handle_diacr(unsigned char);
176 /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
177 static struct pt_regs * pt_regs;
179 #ifdef CONFIG_MAGIC_SYSRQ
180 unsigned char sun_sysrq_xlate[128] =
181 "\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0" /* 0x00 - 0x0f */
182 "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312" /* 0x10 - 0x1f */
183 "34567890-=`\177\0=/*" /* 0x20 - 0x2f */
184 "\0\0.\0\0\011qwertyuiop" /* 0x30 - 0x3f */
185 "[]\177\000789-\0\0\0\0\0asd" /* 0x40 - 0x4f */
186 "fghjkl;'\\\015\0154560\0" /* 0x50 - 0x5f */
187 "\0\0\0\0zxcvbnm,./\0\012" /* 0x60 - 0x6f */
188 "123\0\0\0\0\0\0 \0\0\0\0\0\0"; /* 0x70 - 0x7f */
189 #endif
191 volatile unsigned char sunkbd_layout;
192 volatile unsigned char sunkbd_type;
193 #define SUNKBD_TYPE2 0x02
194 #define SUNKBD_TYPE3 0x03
195 #define SUNKBD_TYPE4 0x04
197 #define SUNKBD_LOUT_TYP4 0x00
198 #define SUNKBD_LOUT_TYP5_MASK 0x20
200 volatile int kbd_reset_pending;
201 volatile int kbd_layout_pending;
203 /* commands */
204 #define SKBDCMD_RESET 0x1
205 #define SKBDCMD_GLAYOUT 0xf
206 #define SKBDCMD_BELLON 0x2
207 #define SKBDCMD_BELLOFF 0x3
208 #define SKBDCMD_SETLED 0xe
209 #define SKBDCMD_NOCLICK 0xb
210 #define SKBDCMD_CLICK 0xa
212 static unsigned char sunkbd_clickp;
214 /* The led set commands require sending the SETLED byte then
215 * a byte encoding which led's to have set. Here are the bit
216 * values, a bit set = led-on.
218 #define LED_NLOCK 0x1 /* Num-lock */
219 #define LED_CMPOSE 0x2 /* Compose */
220 #define LED_SCRLCK 0x4 /* Scroll-lock */
221 #define LED_CLOCK 0x8 /* Caps-lock */
223 /* Special state characters */
224 #define SKBD_RESET 0xff
225 #define SKBD_ALLUP 0x7f
226 #define SKBD_LYOUT 0xfe
228 /* On the Sparc the keyboard could be one of two things.
229 * It could be a real keyboard speaking over one of the
230 * channels of the second zs8530 chip (other channel is
231 * used by the Sun mouse). Else we have serial console
232 * going, and thus the other zs8530 chip is who we speak
233 * to. Either way, we communicate through the zs8530
234 * driver for all our I/O.
237 #define SUNKBD_UBIT 0x80 /* If set, key went up */
238 #define SUNKBD_KMASK 0x7f /* Other bits are the keycode */
240 #define KEY_LSHIFT 0x81
241 #define KEY_RSHIFT 0x82
242 #define KEY_CONTROL 0x83
243 #define KEY_NILL 0x84
244 #define KEY_CAPSLOCK 0x85
245 #define KEY_ALT 0x86
246 #define KEY_L1 0x87
248 /* Do to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing:
250 * init_bh(KEYBOARD_BH, kbd_bh);
251 * mark_bh(KEYBOARD_BH);
253 * this might well be called before some driver has claimed interest in
254 * handling the keyboard input/output. So we need to assign an initial nop.
256 * Otherwise this would lead to the following (DaveM might want to look at):
258 * sparc64_dtlb_refbit_catch(),
259 * do_sparc64_fault(),
260 * kernel NULL pointer dereference at do_sparc64_fault + 0x2c0 ;-(
262 static void nop_kbd_put_char(unsigned char c) { }
263 static void (*kbd_put_char)(unsigned char) = nop_kbd_put_char;
265 static inline void send_cmd(unsigned char c)
267 kbd_put_char(c);
270 /* kbd_bh() calls this to send the SKBDCMD_SETLED to the sun keyboard
271 * with the proper bit pattern for the leds to be set. It basically
272 * converts the kbd->ledflagstate values to corresponding sun kbd led
273 * bit value.
275 static inline unsigned char vcleds_to_sunkbd(unsigned char vcleds)
277 unsigned char retval = 0;
279 if(vcleds & (1<<VC_SCROLLOCK))
280 retval |= LED_SCRLCK;
281 if(vcleds & (1<<VC_NUMLOCK))
282 retval |= LED_NLOCK;
283 if(vcleds & (1<<VC_CAPSLOCK))
284 retval |= LED_CLOCK;
285 if(compose_led_on)
286 retval |= LED_CMPOSE;
287 return retval;
291 * Translation of escaped scancodes to keycodes.
292 * This is now user-settable.
293 * The keycodes 1-88,96-111,119 are fairly standard, and
294 * should probably not be changed - changing might confuse X.
295 * X also interprets scancode 0x5d (KEY_Begin).
297 * For 1-88 keycode equals scancode.
300 #define E0_KPENTER 96
301 #define E0_RCTRL 97
302 #define E0_KPSLASH 98
303 #define E0_PRSCR 99
304 #define E0_RALT 100
305 #define E0_BREAK 101 /* (control-pause) */
306 #define E0_HOME 102
307 #define E0_UP 103
308 #define E0_PGUP 104
309 #define E0_LEFT 105
310 #define E0_RIGHT 106
311 #define E0_END 107
312 #define E0_DOWN 108
313 #define E0_PGDN 109
314 #define E0_INS 110
315 #define E0_DEL 111
317 #define E1_PAUSE 119
320 * The keycodes below are randomly located in 89-95,112-118,120-127.
321 * They could be thrown away (and all occurrences below replaced by 0),
322 * but that would force many users to use the `setkeycodes' utility, where
323 * they needed not before. It does not matter that there are duplicates, as
324 * long as no duplication occurs for any single keyboard.
326 #define SC_LIM 89
328 #define FOCUS_PF1 85 /* actual code! */
329 #define FOCUS_PF2 89
330 #define FOCUS_PF3 90
331 #define FOCUS_PF4 91
332 #define FOCUS_PF5 92
333 #define FOCUS_PF6 93
334 #define FOCUS_PF7 94
335 #define FOCUS_PF8 95
336 #define FOCUS_PF9 120
337 #define FOCUS_PF10 121
338 #define FOCUS_PF11 122
339 #define FOCUS_PF12 123
341 #define JAP_86 124
342 /* tfj@olivia.ping.dk:
343 * The four keys are located over the numeric keypad, and are
344 * labelled A1-A4. It's an rc930 keyboard, from
345 * Regnecentralen/RC International, Now ICL.
346 * Scancodes: 59, 5a, 5b, 5c.
348 #define RGN1 124
349 #define RGN2 125
350 #define RGN3 126
351 #define RGN4 127
353 static unsigned char high_keys[128 - SC_LIM] = {
354 RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
355 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
356 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
357 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
358 FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
359 FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
362 /* BTC */
363 #define E0_MACRO 112
364 /* LK450 */
365 #define E0_F13 113
366 #define E0_F14 114
367 #define E0_HELP 115
368 #define E0_DO 116
369 #define E0_F17 117
370 #define E0_KPMINPLUS 118
372 * My OmniKey generates e0 4c for the "OMNI" key and the
373 * right alt key does nada. [kkoller@nyx10.cs.du.edu]
375 #define E0_OK 124
377 * New microsoft keyboard is rumoured to have
378 * e0 5b (left window button), e0 5c (right window button),
379 * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
380 * [or: Windows_L, Windows_R, TaskMan]
382 #define E0_MSLW 125
383 #define E0_MSRW 126
384 #define E0_MSTM 127
386 static unsigned char e0_keys[128] = {
387 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
388 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
389 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
390 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
391 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
392 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
393 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
394 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
395 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
396 E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
397 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
398 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
399 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
400 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
401 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
402 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
405 /* we use this map to determine if a particular key should not be
406 autorepeated. We don't autorepeat CONTROL, LSHIFT, CAPS,
407 ALT, LMETA, RSHIFT, RMETA, ALTG and COMPOSE */
408 static unsigned char norepeat_keys[128] = {
409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* 0x00-0x0f */
410 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1f */
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x2f */
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3f */
413 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, /* 0x40-0x4f */
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50-0x5f */
415 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 0x60-0x6f */
416 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, /* 0x70-0x7f */
420 int sun_setkeycode(unsigned int scancode, unsigned int keycode)
422 if (scancode < SC_LIM || scancode > 255 || keycode > 127)
423 return -EINVAL;
424 if (scancode < 128)
425 high_keys[scancode - SC_LIM] = keycode;
426 else
427 e0_keys[scancode - 128] = keycode;
428 return 0;
431 int sun_getkeycode(unsigned int scancode)
433 return
434 (scancode < SC_LIM || scancode > 255) ? -EINVAL :
435 (scancode < 128) ? high_keys[scancode - SC_LIM] :
436 e0_keys[scancode - 128];
439 void sunkbd_inchar(unsigned char ch, struct pt_regs *regs);
440 static void keyboard_timer (unsigned long ignored);
442 static struct timer_list
443 auto_repeat_timer = { NULL, NULL, 0, 0, keyboard_timer };
445 /* Keeps track of the last pressed key */
446 static unsigned char last_keycode;
448 static void
449 keyboard_timer (unsigned long ignored)
451 unsigned long flags;
453 save_flags(flags); cli();
455 /* Auto repeat: send regs = 0 to indicate autorepeat */
456 sunkbd_inchar (last_keycode, 0);
457 del_timer (&auto_repeat_timer);
458 if (kbd_rate_ticks) {
459 auto_repeat_timer.expires = jiffies + kbd_rate_ticks;
460 add_timer (&auto_repeat_timer);
462 restore_flags(flags);
465 /* #define SKBD_DEBUG */
466 /* This is our keyboard 'interrupt' routine. */
467 void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
469 unsigned char keycode;
470 char up_flag; /* 0 or SUNKBD_UBIT */
471 char raw_mode;
473 if(ch == SKBD_RESET) {
474 kbd_reset_pending = 1;
475 goto out;
477 if(ch == SKBD_LYOUT) {
478 kbd_layout_pending = 1;
479 goto out;
481 if(kbd_reset_pending) {
482 sunkbd_type = ch;
483 kbd_reset_pending = 0;
484 if(ch == SUNKBD_TYPE4)
485 send_cmd(SKBDCMD_GLAYOUT);
486 goto out;
487 } else if(kbd_layout_pending) {
488 sunkbd_layout = ch;
489 kbd_layout_pending = 0;
490 goto out;
491 } else if(ch == SKBD_ALLUP) {
492 del_timer (&auto_repeat_timer);
493 memset(key_down, 0, sizeof(key_down));
494 sun_compute_shiftstate();
495 goto out;
497 #ifdef SKBD_DEBUG
498 if(ch == 0x7f)
499 printk("KBD<ALL KEYS UP>");
500 else
501 printk("KBD<%x %s>", ch,
502 ((ch&0x80) ? "UP" : "DOWN"));
503 #endif
505 /* Whee, a real character. */
506 if(regs) {
507 pt_regs = regs;
508 last_keycode = keycode = ch;
509 } else {
510 keycode = ch;
513 do_poke_blanked_console = 1;
514 mark_bh(CONSOLE_BH);
515 add_keyboard_randomness(keycode);
517 kbd = kbd_table + fg_console;
518 tty = ttytab[fg_console];
519 if((raw_mode = (kbd->kbdmode == VC_RAW))) {
520 if (kbd_redirected == fg_console+1)
521 push_kbd (keycode);
522 else
523 put_queue(keycode);
524 /* we do not return yet, because we want to maintain
525 * the key_down array, so that we have the correct
526 * values when finishing RAW mode or when changing VT's.
529 up_flag = (keycode & SUNKBD_UBIT); /* The 'up' bit */
530 keycode &= SUNKBD_KMASK; /* all the rest */
531 del_timer (&auto_repeat_timer);
532 if(up_flag) {
533 rep = 0;
534 clear_bit(keycode, key_down);
535 } else {
536 if (!norepeat_keys[keycode]) {
537 if (kbd_rate_ticks) {
538 auto_repeat_timer.expires =
539 jiffies + kbd_delay_ticks;
540 add_timer (&auto_repeat_timer);
543 rep = test_and_set_bit(keycode, key_down);
546 #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq hack */
547 if (l1a_state.l1_down) {
548 if (!up_flag)
549 handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty);
550 goto out;
552 #endif
554 if(raw_mode)
555 goto out;
557 if(kbd->kbdmode == VC_MEDIUMRAW) {
558 put_queue(keycode + up_flag);
559 goto out;
563 * Small change in philosophy: earlier we defined repetition by
564 * rep = keycode == prev_keycode;
565 * prev_keycode = keycode;
566 * but now by the fact that the depressed key was down already.
567 * Does this ever make a difference? Yes.
571 * Repeat a key only if the input buffers are empty or the
572 * characters get echoed locally. This makes key repeat usable
573 * with slow applications and under heavy loads.
575 if (!rep ||
576 (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
577 (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
578 u_short keysym;
579 u_char type;
581 /* the XOR below used to be an OR */
582 int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
583 ushort *key_map = key_maps[shift_final];
585 if (key_map != NULL) {
586 keysym = key_map[keycode];
587 type = KTYP(keysym);
589 if (type >= 0xf0) {
590 type -= 0xf0;
591 if (type == KT_LETTER) {
592 type = KT_LATIN;
593 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
594 key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
595 if (key_map)
596 keysym = key_map[keycode];
599 (*key_handler[type])(keysym & 0xff, up_flag);
600 if (type != KT_SLOCK)
601 kbd->slockstate = 0;
603 } else {
604 /* maybe beep? */
605 /* we have at least to update shift_state */
606 sun_compute_shiftstate();
609 out:
610 mark_bh(KEYBOARD_BH);
613 static void put_queue(int ch)
615 wake_up(&keypress_wait);
616 if (tty) {
617 tty_insert_flip_char(tty, ch, 0);
618 tty_schedule_flip(tty);
622 static void puts_queue(char *cp)
624 wake_up(&keypress_wait);
625 if (!tty)
626 return;
628 while (*cp) {
629 tty_insert_flip_char(tty, *cp, 0);
630 cp++;
632 tty_schedule_flip(tty);
635 static void applkey(int key, char mode)
637 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
639 buf[1] = (mode ? 'O' : '[');
640 buf[2] = key;
641 puts_queue(buf);
644 static void enter(void)
646 put_queue(13);
647 if (vc_kbd_mode(kbd,VC_CRLF))
648 put_queue(10);
651 static void caps_toggle(void)
653 if (rep)
654 return;
655 chg_vc_kbd_led(kbd, VC_CAPSLOCK);
658 static void caps_on(void)
660 if (rep)
661 return;
662 set_vc_kbd_led(kbd, VC_CAPSLOCK);
665 static void show_ptregs(void)
667 if (pt_regs)
668 show_regs(pt_regs);
671 static void hold(void)
673 if (rep || !tty)
674 return;
677 * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
678 * these routines are also activated by ^S/^Q.
679 * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
681 if (tty->stopped)
682 start_tty(tty);
683 else
684 stop_tty(tty);
687 static void num(void)
689 if (vc_kbd_mode(kbd,VC_APPLIC))
690 applkey('P', 1);
691 else
692 bare_num();
696 * Bind this to Shift-NumLock if you work in application keypad mode
697 * but want to be able to change the NumLock flag.
698 * Bind this to NumLock if you prefer that the NumLock key always
699 * changes the NumLock flag.
701 static void bare_num(void)
703 if (!rep)
704 chg_vc_kbd_led(kbd,VC_NUMLOCK);
707 static void lastcons(void)
709 /* switch to the last used console, ChN */
710 set_console(last_console);
713 static void decr_console(void)
715 int i;
717 for (i = fg_console-1; i != fg_console; i--) {
718 if (i == -1)
719 i = MAX_NR_CONSOLES-1;
720 if (vc_cons_allocated(i))
721 break;
723 set_console(i);
726 static void incr_console(void)
728 int i;
730 for (i = fg_console+1; i != fg_console; i++) {
731 if (i == MAX_NR_CONSOLES)
732 i = 0;
733 if (vc_cons_allocated(i))
734 break;
736 set_console(i);
739 static void send_intr(void)
741 if (!tty)
742 return;
743 tty_insert_flip_char(tty, 0, TTY_BREAK);
744 tty_schedule_flip(tty);
747 static void scroll_forw(void)
749 scrollfront(0);
752 static void scroll_back(void)
754 scrollback(0);
757 static void boot_it(void)
759 extern int obp_system_intr(void);
761 if (!obp_system_intr())
762 ctrl_alt_del();
763 /* sigh.. attempt to prevent multiple entry */
764 last_keycode=1;
765 rep = 0;
768 static void compose(void)
770 dead_key_next = 1;
771 compose_led_on = 1;
772 set_leds();
775 int spawnpid, spawnsig;
777 static void spawn_console(void)
779 if (spawnpid)
780 if(kill_proc(spawnpid, spawnsig, 1))
781 spawnpid = 0;
784 static void SAK(void)
786 do_SAK(tty);
787 #if 0
789 * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
790 * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
791 * handling.
793 * We should do this some day --- the whole point of a secure
794 * attention key is that it should be guaranteed to always
795 * work.
797 reset_vc(fg_console);
798 do_unblank_screen(); /* not in interrupt routine? */
799 #endif
802 static void do_ignore(unsigned char value, char up_flag)
806 static void do_null()
808 sun_compute_shiftstate();
811 static void do_spec(unsigned char value, char up_flag)
813 if (up_flag)
814 return;
815 if (value >= SIZE(spec_fn_table))
816 return;
817 spec_fn_table[value]();
820 static void do_lowercase(unsigned char value, char up_flag)
822 printk("keyboard.c: do_lowercase was called - impossible\n");
825 static void do_self(unsigned char value, char up_flag)
827 if (up_flag)
828 return; /* no action, if this is a key release */
830 if (diacr) {
831 value = handle_diacr(value);
832 compose_led_on = 0;
833 set_leds();
836 if (dead_key_next) {
837 dead_key_next = 0;
838 diacr = value;
839 return;
842 put_queue(value);
845 #define A_GRAVE '`'
846 #define A_ACUTE '\''
847 #define A_CFLEX '^'
848 #define A_TILDE '~'
849 #define A_DIAER '"'
850 #define A_CEDIL ','
851 static unsigned char ret_diacr[NR_DEAD] =
852 {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
854 /* If a dead key pressed twice, output a character corresponding to it, */
855 /* otherwise just remember the dead key. */
857 static void do_dead(unsigned char value, char up_flag)
859 if (up_flag)
860 return;
862 value = ret_diacr[value];
863 if (diacr == value) { /* pressed twice */
864 diacr = 0;
865 put_queue(value);
866 return;
868 diacr = value;
872 /* If space is pressed, return the character corresponding the pending */
873 /* dead key, otherwise try to combine the two. */
875 unsigned char handle_diacr(unsigned char ch)
877 int d = diacr;
878 int i;
880 diacr = 0;
881 if (ch == ' ')
882 return d;
884 for (i = 0; i < accent_table_size; i++) {
885 if (accent_table[i].diacr == d && accent_table[i].base == ch)
886 return accent_table[i].result;
889 put_queue(d);
890 return ch;
893 static void do_cons(unsigned char value, char up_flag)
895 if (up_flag)
896 return;
897 set_console(value);
900 static void do_fn(unsigned char value, char up_flag)
902 if (up_flag)
903 return;
904 if (value < SIZE(func_table)) {
905 if (func_table[value])
906 puts_queue(func_table[value]);
907 } else
908 printk("do_fn called with value=%d\n", value);
911 static void do_pad(unsigned char value, char up_flag)
913 static const char *pad_chars = "0123456789+-*/\015,.?";
914 static const char *app_map = "pqrstuvwxylSRQMnn?";
916 if (up_flag)
917 return; /* no action, if this is a key release */
919 /* kludge... shift forces cursor/number keys */
920 if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
921 applkey(app_map[value], 1);
922 return;
925 if (!vc_kbd_led(kbd,VC_NUMLOCK))
926 switch (value) {
927 case KVAL(K_PCOMMA):
928 case KVAL(K_PDOT):
929 do_fn(KVAL(K_REMOVE), 0);
930 return;
931 case KVAL(K_P0):
932 do_fn(KVAL(K_INSERT), 0);
933 return;
934 case KVAL(K_P1):
935 do_fn(KVAL(K_SELECT), 0);
936 return;
937 case KVAL(K_P2):
938 do_cur(KVAL(K_DOWN), 0);
939 return;
940 case KVAL(K_P3):
941 do_fn(KVAL(K_PGDN), 0);
942 return;
943 case KVAL(K_P4):
944 do_cur(KVAL(K_LEFT), 0);
945 return;
946 case KVAL(K_P6):
947 do_cur(KVAL(K_RIGHT), 0);
948 return;
949 case KVAL(K_P7):
950 do_fn(KVAL(K_FIND), 0);
951 return;
952 case KVAL(K_P8):
953 do_cur(KVAL(K_UP), 0);
954 return;
955 case KVAL(K_P9):
956 do_fn(KVAL(K_PGUP), 0);
957 return;
958 case KVAL(K_P5):
959 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
960 return;
963 put_queue(pad_chars[value]);
964 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
965 put_queue(10);
968 static void do_cur(unsigned char value, char up_flag)
970 static const char *cur_chars = "BDCA";
971 if (up_flag)
972 return;
974 applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
977 static void do_shift(unsigned char value, char up_flag)
979 int old_state = shift_state;
981 if (rep)
982 return;
984 /* Mimic typewriter:
985 a CapsShift key acts like Shift but undoes CapsLock */
986 if (value == KVAL(K_CAPSSHIFT)) {
987 value = KVAL(K_SHIFT);
988 if (!up_flag)
989 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
992 if (up_flag) {
993 /* handle the case that two shift or control
994 keys are depressed simultaneously */
995 if (k_down[value])
996 k_down[value]--;
997 } else
998 k_down[value]++;
1000 if (k_down[value])
1001 shift_state |= (1 << value);
1002 else
1003 shift_state &= ~ (1 << value);
1005 /* kludge, no joke... */
1006 if (up_flag && shift_state != old_state && npadch != -1) {
1007 put_queue(npadch & 0xff);
1008 npadch = -1;
1012 /* called after returning from RAW mode or when changing consoles -
1013 recompute k_down[] and shift_state from key_down[] */
1014 /* maybe called when keymap is undefined, so that shiftkey release is seen */
1015 void sun_compute_shiftstate(void)
1017 int i, j, k, sym, val;
1019 shift_state = 0;
1020 for(i=0; i < SIZE(k_down); i++)
1021 k_down[i] = 0;
1023 for(i=0; i < SIZE(key_down); i++)
1024 if(key_down[i]) { /* skip this word if not a single bit on */
1025 k = i*BITS_PER_LONG;
1026 for(j=0; j<BITS_PER_LONG; j++,k++)
1027 if(test_bit(k, key_down)) {
1028 sym = U(plain_map[k]);
1029 if(KTYP(sym) == KT_SHIFT) {
1030 val = KVAL(sym);
1031 if (val == KVAL(K_CAPSSHIFT))
1032 val = KVAL(K_SHIFT);
1033 k_down[val]++;
1034 shift_state |= (1<<val);
1040 static void do_meta(unsigned char value, char up_flag)
1042 if (up_flag)
1043 return;
1045 if (vc_kbd_mode(kbd, VC_META)) {
1046 put_queue('\033');
1047 put_queue(value);
1048 } else
1049 put_queue(value | 0x80);
1052 static void do_ascii(unsigned char value, char up_flag)
1054 int base;
1056 if (up_flag)
1057 return;
1059 if (value < 10) /* decimal input of code, while Alt depressed */
1060 base = 10;
1061 else { /* hexadecimal input of code, while AltGr depressed */
1062 value -= 10;
1063 base = 16;
1066 if (npadch == -1)
1067 npadch = value;
1068 else
1069 npadch = npadch * base + value;
1072 static void do_lock(unsigned char value, char up_flag)
1074 if (up_flag || rep)
1075 return;
1076 chg_vc_kbd_lock(kbd, value);
1080 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1081 * or (ii) whatever pattern of lights people want to show using KDSETLED,
1082 * or (iii) specified bits of specified words in kernel memory.
1085 static unsigned char ledstate = 0xff; /* undefined */
1086 static unsigned char sunkbd_ledstate = 0xff; /* undefined */
1087 static unsigned char ledioctl;
1089 unsigned char sun_getledstate(void) {
1090 return ledstate;
1093 void sun_setledstate(struct kbd_struct *kbd, unsigned int led) {
1094 if (!(led & ~7)) {
1095 ledioctl = led;
1096 kbd->ledmode = LED_SHOW_IOCTL;
1097 } else
1098 kbd->ledmode = LED_SHOW_FLAGS;
1099 set_leds();
1102 static struct ledptr {
1103 unsigned int *addr;
1104 unsigned int mask;
1105 unsigned char valid:1;
1106 } ledptrs[3];
1108 void register_leds(int console, unsigned int led,
1109 unsigned int *addr, unsigned int mask) {
1110 struct kbd_struct *kbd = kbd_table + console;
1111 if (led < 3) {
1112 ledptrs[led].addr = addr;
1113 ledptrs[led].mask = mask;
1114 ledptrs[led].valid = 1;
1115 kbd->ledmode = LED_SHOW_MEM;
1116 } else
1117 kbd->ledmode = LED_SHOW_FLAGS;
1120 static inline unsigned char getleds(void){
1121 struct kbd_struct *kbd = kbd_table + fg_console;
1122 unsigned char leds;
1124 if (kbd->ledmode == LED_SHOW_IOCTL)
1125 return ledioctl;
1126 leds = kbd->ledflagstate;
1127 if (kbd->ledmode == LED_SHOW_MEM) {
1128 if (ledptrs[0].valid) {
1129 if (*ledptrs[0].addr & ledptrs[0].mask)
1130 leds |= 1;
1131 else
1132 leds &= ~1;
1134 if (ledptrs[1].valid) {
1135 if (*ledptrs[1].addr & ledptrs[1].mask)
1136 leds |= 2;
1137 else
1138 leds &= ~2;
1140 if (ledptrs[2].valid) {
1141 if (*ledptrs[2].addr & ledptrs[2].mask)
1142 leds |= 4;
1143 else
1144 leds &= ~4;
1147 return leds;
1151 * This routine is the bottom half of the keyboard interrupt
1152 * routine, and runs with all interrupts enabled. It does
1153 * console changing, led setting and copy_to_cooked, which can
1154 * take a reasonably long time.
1156 * Aside from timing (which isn't really that important for
1157 * keyboard interrupts as they happen often), using the software
1158 * interrupt routines for this thing allows us to easily mask
1159 * this when we don't want any of the above to happen. Not yet
1160 * used, but this allows for easy and efficient race-condition
1161 * prevention later on.
1163 static void kbd_bh(void)
1165 unsigned char leds = getleds();
1166 unsigned char kbd_leds = vcleds_to_sunkbd(leds);
1168 if (kbd_leds != sunkbd_ledstate) {
1169 ledstate = leds;
1170 sunkbd_ledstate = kbd_leds;
1171 send_cmd(SKBDCMD_SETLED);
1172 send_cmd(kbd_leds);
1176 /* Support for keyboard "beeps". */
1178 /* Timer routine to turn off the beep after the interval expires. */
1179 static void sunkbd_kd_nosound(unsigned long __unused)
1181 send_cmd(SKBDCMD_BELLOFF);
1185 * Initiate a keyboard beep. If the frequency is zero, then we stop
1186 * the beep. Any other frequency will start a monotone beep. The beep
1187 * will be stopped by a timer after "ticks" jiffies. If ticks is 0,
1188 * then we do not start a timer.
1190 static void sunkbd_kd_mksound(unsigned int hz, unsigned int ticks)
1192 unsigned long flags;
1193 static struct timer_list sound_timer = { NULL, NULL, 0, 0,
1194 sunkbd_kd_nosound };
1196 save_flags(flags);
1197 cli();
1199 del_timer(&sound_timer);
1201 if (hz) {
1202 send_cmd(SKBDCMD_BELLON);
1203 if (ticks) {
1204 sound_timer.expires = jiffies + ticks;
1205 add_timer(&sound_timer);
1207 } else
1208 send_cmd(SKBDCMD_BELLOFF);
1210 restore_flags(flags);
1213 extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
1215 __initfunc(int sun_kbd_init(void))
1217 int i, opt_node;
1218 struct kbd_struct kbd0;
1219 extern struct tty_driver console_driver;
1221 kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1222 kbd0.ledmode = LED_SHOW_FLAGS;
1223 kbd0.lockstate = KBD_DEFLOCK;
1224 kbd0.slockstate = 0;
1225 kbd0.modeflags = KBD_DEFMODE;
1226 kbd0.kbdmode = VC_XLATE;
1228 for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1229 kbd_table[i] = kbd0;
1231 ttytab = console_driver.table;
1233 kd_mksound = sunkbd_kd_mksound;
1235 /* XXX Check keyboard-click? property in 'options' PROM node XXX */
1236 if(sparc_cpu_model != sun4) {
1237 opt_node = prom_getchild(prom_root_node);
1238 opt_node = prom_searchsiblings(opt_node, "options");
1239 i = prom_getintdefault(opt_node, "keyboard-click?", -1);
1240 if(i != -1)
1241 sunkbd_clickp = 1;
1242 else
1243 sunkbd_clickp = 0;
1244 } else {
1245 sunkbd_clickp = 0;
1247 init_bh(KEYBOARD_BH, kbd_bh);
1248 mark_bh(KEYBOARD_BH);
1249 return 0;
1252 /* /dev/kbd support */
1254 #define KBD_QSIZE 32
1255 static Firm_event kbd_queue [KBD_QSIZE];
1256 static int kbd_head, kbd_tail;
1257 char kbd_opened;
1258 static int kbd_active = 0;
1259 static struct wait_queue *kbd_wait;
1260 static struct fasync_struct *kb_fasync;
1262 void
1263 push_kbd (int scan)
1265 int next = (kbd_head + 1) % KBD_QSIZE;
1267 if (scan == KBD_IDLE)
1268 return;
1269 if (next != kbd_tail){
1270 kbd_queue [kbd_head].id = scan & KBD_KEYMASK;
1271 kbd_queue [kbd_head].value=scan & KBD_UP ? VKEY_UP : VKEY_DOWN;
1272 kbd_queue [kbd_head].time = xtime;
1273 kbd_head = next;
1275 if (kb_fasync)
1276 kill_fasync (kb_fasync, SIGIO);
1277 wake_up_interruptible (&kbd_wait);
1280 static ssize_t
1281 kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos)
1283 struct wait_queue wait = { current, NULL };
1284 char *end, *p;
1286 /* Return EWOULDBLOCK, because this is what the X server expects */
1287 if (kbd_head == kbd_tail){
1288 if (f->f_flags & O_NONBLOCK)
1289 return -EWOULDBLOCK;
1290 add_wait_queue (&kbd_wait, &wait);
1291 while (kbd_head == kbd_tail && !signal_pending(current)) {
1292 current->state = TASK_INTERRUPTIBLE;
1293 schedule ();
1295 current->state = TASK_RUNNING;
1296 remove_wait_queue (&kbd_wait, &wait);
1298 /* There is data in the keyboard, fill the user buffer */
1299 end = buffer+count;
1300 p = buffer;
1301 for (; p < end && kbd_head != kbd_tail;){
1302 #ifdef CONFIG_SPARC32_COMPAT
1303 if (current->tss.flags & SPARC_FLAG_32BIT) {
1304 copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail],
1305 sizeof(Firm_event)-sizeof(struct timeval), -EFAULT);
1306 p += sizeof(Firm_event)-sizeof(struct timeval);
1307 __put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT);
1308 p += sizeof(u32);
1309 __put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT);
1310 p += sizeof(u32);
1311 } else
1312 #endif
1314 copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail],
1315 sizeof(Firm_event), -EFAULT);
1316 p += sizeof (Firm_event);
1318 #ifdef KBD_DEBUG
1319 printk ("[%s]", kbd_queue [kbd_tail].value == VKEY_UP ? "UP" : "DOWN");
1320 #endif
1321 kbd_tail++;
1322 kbd_tail %= KBD_QSIZE;
1324 return p-buffer;
1327 /* Needed by X */
1328 static int kbd_fasync (struct file *filp, int on)
1330 int retval;
1332 retval = fasync_helper (filp, on, &kb_fasync);
1333 if (retval < 0)
1334 return retval;
1335 return 0;
1338 static unsigned int kbd_poll (struct file *f, poll_table *wait)
1340 poll_wait(f, &kbd_wait, wait);
1341 if (kbd_head != kbd_tail)
1342 return POLLIN | POLLRDNORM;
1343 return 0;
1346 static int
1347 kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
1349 unsigned char c;
1350 unsigned char leds = 0;
1351 int value;
1353 switch (cmd){
1354 case KIOCTYPE: /* return keyboard type */
1355 put_user_ret(sunkbd_type, (int *) arg, -EFAULT);
1356 break;
1357 case KIOCGTRANS:
1358 put_user_ret(TR_UNTRANS_EVENT, (int *) arg, -EFAULT);
1359 break;
1360 case KIOCTRANS:
1361 get_user_ret(value, (int *) arg, -EFAULT);
1362 if (value != TR_UNTRANS_EVENT)
1363 return -EINVAL;
1364 break;
1365 case KIOCLAYOUT:
1366 put_user_ret(sunkbd_layout, (int *) arg, -EFAULT);
1367 break;
1368 case KIOCSDIRECT:
1369 #ifndef CODING_NEW_DRIVER
1370 get_user_ret(value, (int *) arg, -EFAULT);
1371 if(value)
1372 kbd_redirected = fg_console + 1;
1373 else
1374 kbd_redirected = 0;
1375 kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE;
1376 #endif
1377 break;
1378 case KIOCCMD:
1379 get_user_ret(value, (int *) arg, -EFAULT);
1380 c = (unsigned char) value;
1381 switch (c) {
1382 case SKBDCMD_CLICK:
1383 case SKBDCMD_NOCLICK:
1384 send_cmd(c);
1385 return 0;
1386 case SKBDCMD_BELLON:
1387 kd_mksound(1,0);
1388 return 0;
1389 case SKBDCMD_BELLOFF:
1390 kd_mksound(0,0);
1391 return 0;
1392 default:
1393 return -EINVAL;
1395 case KIOCSLED:
1396 get_user_ret(c, (unsigned char *) arg, -EFAULT);
1398 if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK);
1399 if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK);
1400 if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK);
1401 compose_led_on = !!(c & LED_CMPOSE);
1402 sun_setledstate(kbd_table + fg_console, leds);
1403 break;
1404 case KIOCGLED:
1405 put_user_ret(vcleds_to_sunkbd(getleds()), (unsigned char *) arg, -EFAULT);
1406 break;
1407 case KIOCGRATE:
1409 struct kbd_rate rate;
1411 rate.delay = kbd_delay_ticks;
1412 if (kbd_rate_ticks)
1413 rate.rate = HZ / kbd_rate_ticks;
1414 else
1415 rate.rate = 0;
1417 copy_to_user_ret((struct kbd_rate *)arg, &rate,
1418 sizeof(struct kbd_rate), -EFAULT);
1420 return 0;
1422 case KIOCSRATE:
1424 struct kbd_rate rate;
1426 if (verify_area(VERIFY_READ, (void *)arg,
1427 sizeof(struct kbd_rate)))
1428 return -EFAULT;
1429 copy_from_user(&rate, (struct kbd_rate *)arg,
1430 sizeof(struct kbd_rate));
1432 if (rate.rate > 50)
1433 return -EINVAL;
1434 if (rate.rate == 0)
1435 kbd_rate_ticks = 0;
1436 else
1437 kbd_rate_ticks = HZ / rate.rate;
1438 kbd_delay_ticks = rate.delay;
1440 return 0;
1442 case FIONREAD: /* return number of bytes in kbd queue */
1444 int count;
1446 count = kbd_head - kbd_tail;
1447 put_user_ret((count < 0) ? KBD_QSIZE - count : count, (int *) arg, -EFAULT);
1448 return 0;
1450 default:
1451 printk ("Unknown Keyboard ioctl: %8.8x\n", cmd);
1452 return -EINVAL;
1454 return 0;
1457 static int
1458 kbd_open (struct inode *i, struct file *f)
1460 kbd_active++;
1462 if (kbd_opened)
1463 return 0;
1465 kbd_opened = fg_console + 1;
1466 kbd_head = kbd_tail = 0;
1467 return 0;
1470 static int
1471 kbd_close (struct inode *i, struct file *f)
1473 if (--kbd_active)
1474 return 0;
1476 if (kbd_redirected)
1477 kbd_table [kbd_opened-1].kbdmode = VC_XLATE;
1479 kbd_redirected = 0;
1480 kbd_opened = 0;
1482 kbd_fasync (f, 0);
1483 return 0;
1486 static struct
1487 file_operations kbd_fops =
1489 NULL, /* seek */
1490 kbd_read, /* read */
1491 NULL, /* write */
1492 NULL, /* readdir */
1493 kbd_poll, /* poll */
1494 kbd_ioctl, /* ioctl */
1495 NULL, /* mmap */
1496 kbd_open, /* open */
1497 NULL, /* flush */
1498 kbd_close, /* close */
1499 NULL, /* fsync */
1500 kbd_fasync, /* fasync */
1501 NULL, /* check_media_change */
1502 NULL, /* revalidate */
1505 __initfunc(void keyboard_zsinit(void (*put_char)(unsigned char)))
1507 int timeout = 0;
1509 kbd_put_char = put_char;
1510 if (!kbd_put_char)
1511 panic("keyboard_zsinit: no put_char parameter");
1513 /* Test out the leds */
1514 sunkbd_type = 255;
1515 sunkbd_layout = 0;
1517 send_cmd(SKBDCMD_RESET);
1518 send_cmd(SKBDCMD_RESET);
1519 while((sunkbd_type==255) && timeout++ < 25000) {
1520 udelay(100);
1521 barrier();
1524 if(timeout>=25000) {
1525 printk("keyboard: not present\n");
1526 return;
1529 if(sunkbd_type != SUNKBD_TYPE4) {
1530 printk("Sun TYPE %d keyboard detected ", sunkbd_type);
1531 } else {
1532 timeout=0;
1533 while((sunkbd_layout==0) && timeout++ < 10000) {
1534 udelay(100);
1535 barrier();
1537 printk("Sun TYPE %d keyboard detected ",
1538 ((sunkbd_layout & SUNKBD_LOUT_TYP5_MASK) ? 5 : 4));
1540 if(sunkbd_type == SUNKBD_TYPE2)
1541 sunkbd_clickp = 0;
1543 if(sunkbd_clickp) {
1544 send_cmd(SKBDCMD_CLICK);
1545 printk("with keyclick\n");
1546 } else {
1547 send_cmd(SKBDCMD_NOCLICK);
1548 printk("without keyclick\n");
1551 /* Dork with led lights, then turn them all off */
1552 send_cmd(SKBDCMD_SETLED); send_cmd(0xf); /* All on */
1553 send_cmd(SKBDCMD_SETLED); send_cmd(0x0); /* All off */
1555 /* Register the /dev/kbd interface */
1556 if (register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
1557 printk ("Could not register /dev/kbd device\n");
1558 return;
1560 return;