root/drivers/sbus/char/sunkbd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_cmd
  2. vcleds_to_sunkbd
  3. setkeycode
  4. getkeycode
  5. keyboard_timer
  6. sunkbd_inchar
  7. put_queue
  8. puts_queue
  9. applkey
  10. enter
  11. caps_toggle
  12. caps_on
  13. show_ptregs
  14. hold
  15. num
  16. bare_num
  17. lastcons
  18. decr_console
  19. incr_console
  20. send_intr
  21. scroll_forw
  22. scroll_back
  23. boot_it
  24. compose
  25. spawn_console
  26. SAK
  27. do_ignore
  28. do_null
  29. do_spec
  30. do_lowercase
  31. do_self
  32. do_dead
  33. handle_diacr
  34. do_cons
  35. do_fn
  36. do_pad
  37. do_cur
  38. do_shift
  39. compute_shiftstate
  40. do_meta
  41. do_ascii
  42. do_lock
  43. getledstate
  44. setledstate
  45. register_leds
  46. getleds
  47. kbd_bh
  48. kbd_init
  49. push_kbd
  50. kbd_read
  51. kbd_fasync
  52. kbd_select
  53. kbd_ioctl
  54. kbd_open
  55. kbd_close
  56. keyboard_zsinit

   1 /* keyboard.c: Sun keyboard driver.
   2  *
   3  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   4  * Added vuid event generation and /dev/kbd device for SunOS
   5  * compatibility - Miguel (miguel@nuclecu.unam.mx)
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/sched.h>
  10 #include <linux/tty.h>
  11 #include <linux/tty_flip.h>
  12 #include <linux/mm.h>
  13 #include <linux/ptrace.h>
  14 #include <linux/signal.h>
  15 #include <linux/string.h>
  16 #include <linux/fcntl.h>
  17 #include <asm/kbio.h>
  18 #include <asm/vuid_event.h>
  19 #include <asm/delay.h>
  20 #include <asm/bitops.h>
  21 #include <asm/oplib.h>
  22 
  23 #include "../../char/kbd_kern.h"
  24 #include "../../char/diacr.h"
  25 #include "../../char/vt_kern.h"
  26 
  27 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  28 
  29 /* Define this one if you are making a new frame buffer driver */
  30 /* it will not block the keyboard */
  31 /* #define CODING_NEW_DRIVER */
  32 
  33 /* KBD device number, temporal */
  34 #define KBD_MAJOR 11
  35 
  36 #define KBD_REPORT_ERR
  37 #define KBD_REPORT_UNKN
  38 
  39 #ifndef KBD_DEFMODE
  40 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
  41 #endif
  42 
  43 #ifndef KBD_DEFLEDS
  44 /*
  45  * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  46  * is on. This seems a good reason to start with NumLock off.
  47  */
  48 #define KBD_DEFLEDS 0
  49 #endif
  50 
  51 #ifndef KBD_DEFLOCK
  52 #define KBD_DEFLOCK 0
  53 #endif
  54 
  55 extern void poke_blanked_console(void);
  56 extern void ctrl_alt_del(void);
  57 extern void reset_vc(unsigned int new_console);
  58 extern void scrollback(int);
  59 extern void scrollfront(int);
  60 
  61 unsigned char kbd_read_mask = 0x01;     /* modified by psaux.c */
  62 
  63 /*
  64  * global state includes the following, and various static variables
  65  * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
  66  * (last_console is now a global variable)
  67  */
  68 
  69 /* shift state counters.. */
  70 static unsigned char k_down[NR_SHIFT] = {0, };
  71 /* keyboard key bitmap */
  72 #define BITS_PER_LONG (8*sizeof(unsigned long))
  73 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
  74 
  75 void push_kbd (int scan);
  76 int kbd_redirected = 0;
  77 
  78 static int dead_key_next = 0;
  79 /* 
  80  * In order to retrieve the shift_state (for the mouse server), either
  81  * the variable must be global, or a new procedure must be created to 
  82  * return the value. I chose the former way.
  83  */
  84 /*static*/ int shift_state = 0;
  85 static int npadch = -1;                 /* -1 or number assembled on pad */
  86 static unsigned char diacr = 0;
  87 static char rep = 0;                    /* flag telling character repeat */
  88 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
  89 static struct tty_struct **ttytab;
  90 static struct kbd_struct * kbd = kbd_table;
  91 static struct tty_struct * tty = NULL;
  92 
  93 extern void compute_shiftstate(void);
  94 
  95 typedef void (*k_hand)(unsigned char value, char up_flag);
  96 typedef void (k_handfn)(unsigned char value, char up_flag);
  97 
  98 static k_handfn
  99         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 100         do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
 101 
 102 static k_hand key_handler[16] = {
 103         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 104         do_meta, do_ascii, do_lock, do_lowercase,
 105         do_ignore, do_ignore, do_ignore, do_ignore
 106 };
 107 
 108 typedef void (*void_fnp)(void);
 109 typedef void (void_fn)(void);
 110 
 111 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 112         num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
 113         SAK, decr_console, incr_console, spawn_console, bare_num;
 114 
 115 static void_fnp spec_fn_table[] = {
 116         do_null,        enter,          show_ptregs,    show_mem,
 117         show_state,     send_intr,      lastcons,       caps_toggle,
 118         num,            hold,           scroll_forw,    scroll_back,
 119         boot_it,        caps_on,        compose,        SAK,
 120         decr_console,   incr_console,   spawn_console,  bare_num
 121 };
 122 
 123 /* maximum values each key_handler can handle */
 124 const int max_vals[] = {
 125         255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
 126         NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
 127         255, NR_ASCII - 1, NR_LOCK - 1, 255
 128 };
 129 
 130 const int NR_TYPES = SIZE(max_vals);
 131 
 132 static void put_queue(int);
 133 static unsigned char handle_diacr(unsigned char);
 134 
 135 /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
 136 static struct pt_regs * pt_regs;
 137 
 138 volatile unsigned char sunkbd_layout;
 139 volatile unsigned char sunkbd_type;
 140 #define SUNKBD_TYPE2        0x02
 141 #define SUNKBD_TYPE3        0x03
 142 #define SUNKBD_TYPE4        0x04
 143 
 144 #define SUNKBD_LOUT_TYP4    0x00
 145 #define SUNKBD_LOUT_TYP5    0x22
 146 
 147 volatile int kbd_reset_pending;
 148 volatile int kbd_layout_pending;
 149 
 150 /* commands */
 151 #define SKBDCMD_RESET       0x1
 152 #define SKBDCMD_GLAYOUT     0xf
 153 #define SKBDCMD_BELLON      0x2
 154 #define SKBDCMD_BELLOFF     0x3
 155 #define SKBDCMD_SETLED      0xe
 156 #define SKBDCMD_NOCLICK     0xb
 157 #define SKBDCMD_CLICK       0xa
 158 
 159 static unsigned char sunkbd_clickp;
 160 
 161 /* The led set commands require sending the SETLED byte then
 162  * a byte encoding which led's to have set.  Here are the bit
 163  * values, a bit set = led-on.
 164  */
 165 #define LED_NLOCK           0x1   /* Num-lock */
 166 #define LED_CMPOSE          0x2   /* Compose */
 167 #define LED_SCRLCK          0x4   /* Scroll-lock */
 168 #define LED_CLOCK           0x8   /* Caps-lock */
 169 
 170 /* Special state characters */
 171 #define SKBD_RESET          0xff
 172 #define SKBD_ALLUP          0x7f
 173 #define SKBD_LYOUT          0xfe
 174 
 175 /* On the Sparc the keyboard could be one of two things.
 176  * It could be a real keyboard speaking over one of the
 177  * channels of the second zs8530 chip (other channel is
 178  * used by the Sun mouse).  Else we have serial console
 179  * going, and thus the other zs8530 chip is who we speak
 180  * to.  Either way, we communicate through the zs8530
 181  * driver for all our I/O.
 182  */
 183 
 184 #define SUNKBD_UBIT     0x80      /* If set, key went up */
 185 #define SUNKBD_KMASK    0x7f      /* Other bits are the keycode */
 186 
 187 #define KEY_LSHIFT      0x81
 188 #define KEY_RSHIFT      0x82
 189 #define KEY_CONTROL     0x83
 190 #define KEY_NILL        0x84
 191 #define KEY_CAPSLOCK    0x85
 192 #define KEY_ALT         0x86
 193 #define KEY_L1          0x87
 194 
 195 extern void kbd_put_char(unsigned char ch);
 196 static inline void send_cmd(unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 197 {
 198         kbd_put_char(c);
 199 }
 200 
 201 /* kbd_bh() calls this to send the SKBDCMD_SETLED to the sun keyboard
 202  * with the proper bit pattern for the leds to be set.  It basically
 203  * converts the kbd->ledflagstate values to corresponding sun kbd led
 204  * bit value.
 205  */
 206 static inline unsigned char vcleds_to_sunkbd(unsigned char vcleds)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208         unsigned char retval = 0;
 209 
 210         if(vcleds & (1<<VC_SCROLLOCK))
 211                 retval |= LED_SCRLCK;
 212         if(vcleds & (1<<VC_NUMLOCK))
 213                 retval |= LED_NLOCK;
 214         if(vcleds & (1<<VC_CAPSLOCK))
 215                 retval |= LED_CLOCK;
 216         return retval;
 217 }
 218 
 219 /*
 220  * Translation of escaped scancodes to keycodes.
 221  * This is now user-settable.
 222  * The keycodes 1-88,96-111,119 are fairly standard, and
 223  * should probably not be changed - changing might confuse X.
 224  * X also interprets scancode 0x5d (KEY_Begin).
 225  *
 226  * For 1-88 keycode equals scancode.
 227  */
 228 
 229 #define E0_KPENTER 96
 230 #define E0_RCTRL   97
 231 #define E0_KPSLASH 98
 232 #define E0_PRSCR   99
 233 #define E0_RALT    100
 234 #define E0_BREAK   101  /* (control-pause) */
 235 #define E0_HOME    102
 236 #define E0_UP      103
 237 #define E0_PGUP    104
 238 #define E0_LEFT    105
 239 #define E0_RIGHT   106
 240 #define E0_END     107
 241 #define E0_DOWN    108
 242 #define E0_PGDN    109
 243 #define E0_INS     110
 244 #define E0_DEL     111
 245 
 246 #define E1_PAUSE   119
 247 
 248 /*
 249  * The keycodes below are randomly located in 89-95,112-118,120-127.
 250  * They could be thrown away (and all occurrences below replaced by 0),
 251  * but that would force many users to use the `setkeycodes' utility, where
 252  * they needed not before. It does not matter that there are duplicates, as
 253  * long as no duplication occurs for any single keyboard.
 254  */
 255 #define SC_LIM 89
 256 
 257 #define FOCUS_PF1 85           /* actual code! */
 258 #define FOCUS_PF2 89
 259 #define FOCUS_PF3 90
 260 #define FOCUS_PF4 91
 261 #define FOCUS_PF5 92
 262 #define FOCUS_PF6 93
 263 #define FOCUS_PF7 94
 264 #define FOCUS_PF8 95
 265 #define FOCUS_PF9 120
 266 #define FOCUS_PF10 121
 267 #define FOCUS_PF11 122
 268 #define FOCUS_PF12 123
 269 
 270 #define JAP_86     124
 271 /* tfj@olivia.ping.dk:
 272  * The four keys are located over the numeric keypad, and are
 273  * labelled A1-A4. It's an rc930 keyboard, from
 274  * Regnecentralen/RC International, Now ICL.
 275  * Scancodes: 59, 5a, 5b, 5c.
 276  */
 277 #define RGN1 124
 278 #define RGN2 125
 279 #define RGN3 126
 280 #define RGN4 127
 281 
 282 static unsigned char high_keys[128 - SC_LIM] = {
 283   RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
 284   0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
 285   0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
 286   0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
 287   FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
 288   FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
 289 };
 290 
 291 /* BTC */
 292 #define E0_MACRO   112
 293 /* LK450 */
 294 #define E0_F13     113
 295 #define E0_F14     114
 296 #define E0_HELP    115
 297 #define E0_DO      116
 298 #define E0_F17     117
 299 #define E0_KPMINPLUS 118
 300 /*
 301  * My OmniKey generates e0 4c for  the "OMNI" key and the
 302  * right alt key does nada. [kkoller@nyx10.cs.du.edu]
 303  */
 304 #define E0_OK   124
 305 /*
 306  * New microsoft keyboard is rumoured to have
 307  * e0 5b (left window button), e0 5c (right window button),
 308  * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
 309  * [or: Windows_L, Windows_R, TaskMan]
 310  */
 311 #define E0_MSLW 125
 312 #define E0_MSRW 126
 313 #define E0_MSTM 127
 314 
 315 static unsigned char e0_keys[128] = {
 316   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x00-0x07 */
 317   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x08-0x0f */
 318   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x10-0x17 */
 319   0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,             /* 0x18-0x1f */
 320   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x20-0x27 */
 321   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x28-0x2f */
 322   0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,             /* 0x30-0x37 */
 323   E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,       /* 0x38-0x3f */
 324   E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,       /* 0x40-0x47 */
 325   E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
 326   E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,       /* 0x50-0x57 */
 327   0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,           /* 0x58-0x5f */
 328   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x60-0x67 */
 329   0, 0, 0, 0, 0, 0, 0, E0_MACRO,                      /* 0x68-0x6f */
 330   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x70-0x77 */
 331   0, 0, 0, 0, 0, 0, 0, 0                              /* 0x78-0x7f */
 332 };
 333 
 334 int setkeycode(unsigned int scancode, unsigned int keycode)
     /* [previous][next][first][last][top][bottom][index][help] */
 335 {
 336         if (scancode < SC_LIM || scancode > 255 || keycode > 127)
 337           return -EINVAL;
 338         if (scancode < 128)
 339           high_keys[scancode - SC_LIM] = keycode;
 340         else
 341           e0_keys[scancode - 128] = keycode;
 342         return 0;
 343 }
 344 
 345 int getkeycode(unsigned int scancode)
     /* [previous][next][first][last][top][bottom][index][help] */
 346 {
 347         return
 348           (scancode < SC_LIM || scancode > 255) ? -EINVAL :
 349           (scancode < 128) ? high_keys[scancode - SC_LIM] :
 350             e0_keys[scancode - 128];
 351 }
 352 
 353 void sunkbd_inchar(unsigned char ch, unsigned char status, struct pt_regs *regs);
 354 static void keyboard_timer (unsigned long ignored);
 355 
 356 static struct timer_list
 357 auto_repeat_timer = { NULL, NULL, 0, 0, keyboard_timer };
 358 
 359 /* Keeps track of the last pressed key */
 360 static unsigned char last_keycode;
 361 
 362 static void
 363 keyboard_timer (unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
 364 {
 365         unsigned long flags;
 366 
 367         save_flags(flags); cli();
 368 
 369         /* Auto repeat: send regs = 0 to indicate autorepeat */
 370         sunkbd_inchar (last_keycode, 0, 0);
 371         del_timer (&auto_repeat_timer);
 372         auto_repeat_timer.expires = jiffies + HZ/20;
 373         add_timer (&auto_repeat_timer);
 374         restore_flags(flags);
 375 }
 376 
 377 /* #define SKBD_DEBUG */
 378 /* This is our keyboard 'interrupt' routine. */
 379 void sunkbd_inchar(unsigned char ch, unsigned char status, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 380 {
 381         unsigned char keycode;
 382         char up_flag;                          /* 0 or SUNKBD_UBIT */
 383         char raw_mode;
 384 
 385         if(ch == SKBD_RESET) {
 386                 kbd_reset_pending = 1;
 387                 return;
 388         }
 389         if(ch == SKBD_LYOUT) {
 390                 kbd_layout_pending = 1;
 391                 return;
 392         }
 393         if(kbd_reset_pending) {
 394                 sunkbd_type = ch;
 395                 kbd_reset_pending = 0;
 396                 if(ch == SUNKBD_TYPE4)
 397                         send_cmd(SKBDCMD_GLAYOUT);
 398                 return;
 399         } else if(kbd_layout_pending) {
 400                 sunkbd_layout = ch;
 401                 kbd_layout_pending = 0;
 402                 return;
 403         } else if(ch == SKBD_ALLUP) {
 404                 /* eat it */
 405                 return;
 406         }
 407 #ifdef SKBD_DEBUG
 408         if(ch == 0x7f)
 409                 printk("KBD<ALL KEYS UP>");
 410         else
 411                 printk("KBD<%x %s>", ch,
 412                        ((ch&0x80) ? "UP" : "DOWN"));
 413 #endif
 414 
 415         /* Whee, a real character. */
 416         if (regs){
 417                 pt_regs = regs;
 418                 last_keycode = keycode = ch;
 419         } else
 420                 keycode = ch;
 421         
 422         mark_bh(KEYBOARD_BH);
 423         do_poke_blanked_console = 1;
 424         mark_bh(CONSOLE_BH);
 425         kbd = kbd_table + fg_console;
 426         tty = ttytab[fg_console];
 427         if((raw_mode = (kbd->kbdmode == VC_RAW))) {
 428                 if (kbd_redirected == fg_console+1)
 429                         push_kbd (keycode);
 430                 else
 431                         put_queue(keycode);
 432                 /* we do not return yet, because we want to maintain
 433                  * the key_down array, so that we have the correct
 434                  * values  when finishing RAW mode or when changing VT's.
 435                  */
 436         }
 437         up_flag = (keycode & SUNKBD_UBIT);  /* The 'up' bit */
 438         keycode &= SUNKBD_KMASK;            /* all the rest */
 439         del_timer (&auto_repeat_timer);
 440         if(up_flag) {
 441                 rep = 0;
 442                 clear_bit(keycode, key_down);
 443         } else {
 444                 auto_repeat_timer.expires = jiffies+HZ/5;
 445                 add_timer (&auto_repeat_timer);
 446                 rep = set_bit(keycode, key_down);
 447         }
 448 
 449         if(raw_mode)
 450                 return;
 451 
 452         if(kbd->kbdmode == VC_MEDIUMRAW) {
 453                 put_queue(keycode + up_flag);
 454                 return;
 455         }
 456 
 457         /*
 458          * Small change in philosophy: earlier we defined repetition by
 459          *       rep = keycode == prev_keycode;
 460          *       prev_keycode = keycode;
 461          * but now by the fact that the depressed key was down already.
 462          * Does this ever make a difference? Yes.
 463          */
 464 
 465         /*
 466          *  Repeat a key only if the input buffers are empty or the
 467          *  characters get echoed locally. This makes key repeat usable
 468          *  with slow applications and under heavy loads.
 469          */
 470         if (!rep ||
 471             (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 472              (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
 473                 u_short keysym;
 474                 u_char type;
 475 
 476                 /* the XOR below used to be an OR */
 477                 int shift_final = shift_state ^ kbd->lockstate;
 478                 ushort *key_map = key_maps[shift_final];
 479 
 480                 if (key_map != NULL) {
 481                         keysym = key_map[keycode];
 482                         type = KTYP(keysym);
 483 
 484                         if (type >= 0xf0) {
 485                             type -= 0xf0;
 486                             if (type == KT_LETTER) {
 487                                 type = KT_LATIN;
 488                                 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
 489                                     key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
 490                                     if (key_map)
 491                                       keysym = key_map[keycode];
 492                                 }
 493                             }
 494                             (*key_handler[type])(keysym & 0xff, up_flag);
 495                             if (type != KT_SLOCK)
 496                               kbd->slockstate = 0;
 497                         }
 498                 } else {
 499                         /* maybe beep? */
 500                         /* we have at least to update shift_state */
 501                         compute_shiftstate();
 502                 }
 503         }
 504 }
 505 
 506 static void put_queue(int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 507 {
 508         wake_up(&keypress_wait);
 509         if (tty) {
 510                 tty_insert_flip_char(tty, ch, 0);
 511                 tty_schedule_flip(tty);
 512         }
 513 }
 514 
 515 static void puts_queue(char *cp)
     /* [previous][next][first][last][top][bottom][index][help] */
 516 {
 517         wake_up(&keypress_wait);
 518         if (!tty)
 519                 return;
 520 
 521         while (*cp) {
 522                 tty_insert_flip_char(tty, *cp, 0);
 523                 cp++;
 524         }
 525         tty_schedule_flip(tty);
 526 }
 527 
 528 static void applkey(int key, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 529 {
 530         static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
 531 
 532         buf[1] = (mode ? 'O' : '[');
 533         buf[2] = key;
 534         puts_queue(buf);
 535 }
 536 
 537 static void enter(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 538 {
 539         put_queue(13);
 540         if (vc_kbd_mode(kbd,VC_CRLF))
 541                 put_queue(10);
 542 }
 543 
 544 static void caps_toggle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 545 {
 546         if (rep)
 547                 return;
 548         chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 549 }
 550 
 551 static void caps_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 552 {
 553         if (rep)
 554                 return;
 555         set_vc_kbd_led(kbd, VC_CAPSLOCK);
 556 }
 557 
 558 static void show_ptregs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560         if (pt_regs)
 561                 show_regs(pt_regs);
 562 }
 563 
 564 static void hold(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 565 {
 566         if (rep || !tty)
 567                 return;
 568 
 569         /*
 570          * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 571          * these routines are also activated by ^S/^Q.
 572          * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 573          */
 574         if (tty->stopped)
 575                 start_tty(tty);
 576         else
 577                 stop_tty(tty);
 578 }
 579 
 580 static void num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         if (vc_kbd_mode(kbd,VC_APPLIC))
 583                 applkey('P', 1);
 584         else
 585                 bare_num();
 586 }
 587 
 588 /*
 589  * Bind this to Shift-NumLock if you work in application keypad mode
 590  * but want to be able to change the NumLock flag.
 591  * Bind this to NumLock if you prefer that the NumLock key always
 592  * changes the NumLock flag.
 593  */
 594 static void bare_num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 595 {
 596         if (!rep)
 597                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 598 }
 599 
 600 static void lastcons(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 601 {
 602         /* switch to the last used console, ChN */
 603         set_console(last_console);
 604 }
 605 
 606 static void decr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 607 {
 608         int i;
 609  
 610         for (i = fg_console-1; i != fg_console; i--) {
 611                 if (i == -1)
 612                         i = MAX_NR_CONSOLES-1;
 613                 if (vc_cons_allocated(i))
 614                         break;
 615         }
 616         set_console(i);
 617 }
 618 
 619 static void incr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 620 {
 621         int i;
 622 
 623         for (i = fg_console+1; i != fg_console; i++) {
 624                 if (i == MAX_NR_CONSOLES)
 625                         i = 0;
 626                 if (vc_cons_allocated(i))
 627                         break;
 628         }
 629         set_console(i);
 630 }
 631 
 632 static void send_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         if (!tty)
 635                 return;
 636         tty_insert_flip_char(tty, 0, TTY_BREAK);
 637         tty_schedule_flip(tty);
 638 }
 639 
 640 static void scroll_forw(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 641 {
 642         scrollfront(0);
 643 }
 644 
 645 static void scroll_back(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 646 {
 647         scrollback(0);
 648 }
 649 
 650 static void boot_it(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 651 {
 652         extern int obp_system_intr(void);
 653 
 654         if (!obp_system_intr())
 655                 ctrl_alt_del();
 656         /* sigh.. attempt to prevent multiple entry */
 657         last_keycode=1;
 658         rep = 0;
 659 }
 660 
 661 static void compose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 662 {
 663         dead_key_next = 1;
 664 }
 665 
 666 int spawnpid, spawnsig;
 667 
 668 static void spawn_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 669 {
 670         if (spawnpid)
 671            if(kill_proc(spawnpid, spawnsig, 1))
 672              spawnpid = 0;
 673 }
 674 
 675 static void SAK(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 676 {
 677         do_SAK(tty);
 678 #if 0
 679         /*
 680          * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 681          * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 682          * handling.
 683          * 
 684          * We should do this some day --- the whole point of a secure
 685          * attention key is that it should be guaranteed to always
 686          * work.
 687          */
 688         reset_vc(fg_console);
 689         do_unblank_screen();    /* not in interrupt routine? */
 690 #endif
 691 }
 692 
 693 static void do_ignore(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 694 {
 695 }
 696 
 697 static void do_null()
     /* [previous][next][first][last][top][bottom][index][help] */
 698 {
 699         compute_shiftstate();
 700 }
 701 
 702 static void do_spec(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 703 {
 704         if (up_flag)
 705                 return;
 706         if (value >= SIZE(spec_fn_table))
 707                 return;
 708         spec_fn_table[value]();
 709 }
 710 
 711 static void do_lowercase(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 712 {
 713         printk("keyboard.c: do_lowercase was called - impossible\n");
 714 }
 715 
 716 static void do_self(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 717 {
 718         if (up_flag)
 719                 return;         /* no action, if this is a key release */
 720 
 721         if (diacr)
 722                 value = handle_diacr(value);
 723 
 724         if (dead_key_next) {
 725                 dead_key_next = 0;
 726                 diacr = value;
 727                 return;
 728         }
 729 
 730         put_queue(value);
 731 }
 732 
 733 #define A_GRAVE  '`'
 734 #define A_ACUTE  '\''
 735 #define A_CFLEX  '^'
 736 #define A_TILDE  '~'
 737 #define A_DIAER  '"'
 738 static unsigned char ret_diacr[] =
 739         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 740 
 741 /* If a dead key pressed twice, output a character corresponding to it, */
 742 /* otherwise just remember the dead key.                                */
 743 
 744 static void do_dead(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 745 {
 746         if (up_flag)
 747                 return;
 748 
 749         value = ret_diacr[value];
 750         if (diacr == value) {   /* pressed twice */
 751                 diacr = 0;
 752                 put_queue(value);
 753                 return;
 754         }
 755         diacr = value;
 756 }
 757 
 758 
 759 /* If space is pressed, return the character corresponding the pending  */
 760 /* dead key, otherwise try to combine the two.                          */
 761 
 762 unsigned char handle_diacr(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 763 {
 764         int d = diacr;
 765         int i;
 766 
 767         diacr = 0;
 768         if (ch == ' ')
 769                 return d;
 770 
 771         for (i = 0; i < accent_table_size; i++) {
 772                 if (accent_table[i].diacr == d && accent_table[i].base == ch)
 773                         return accent_table[i].result;
 774         }
 775 
 776         put_queue(d);
 777         return ch;
 778 }
 779 
 780 static void do_cons(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 781 {
 782         if (up_flag)
 783                 return;
 784         want_console = value;
 785 }
 786 
 787 static void do_fn(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789         if (up_flag)
 790                 return;
 791         if (value < SIZE(func_table)) {
 792                 if (func_table[value])
 793                         puts_queue(func_table[value]);
 794         } else
 795                 printk("do_fn called with value=%d\n", value);
 796 }
 797 
 798 static void do_pad(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 799 {
 800         static const char *pad_chars = "0123456789+-*/\015,.?";
 801         static const char *app_map = "pqrstuvwxylSRQMnn?";
 802 
 803         if (up_flag)
 804                 return;         /* no action, if this is a key release */
 805 
 806         /* kludge... shift forces cursor/number keys */
 807         if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
 808                 applkey(app_map[value], 1);
 809                 return;
 810         }
 811 
 812         if (!vc_kbd_led(kbd,VC_NUMLOCK))
 813                 switch (value) {
 814                         case KVAL(K_PCOMMA):
 815                         case KVAL(K_PDOT):
 816                                 do_fn(KVAL(K_REMOVE), 0);
 817                                 return;
 818                         case KVAL(K_P0):
 819                                 do_fn(KVAL(K_INSERT), 0);
 820                                 return;
 821                         case KVAL(K_P1):
 822                                 do_fn(KVAL(K_SELECT), 0);
 823                                 return;
 824                         case KVAL(K_P2):
 825                                 do_cur(KVAL(K_DOWN), 0);
 826                                 return;
 827                         case KVAL(K_P3):
 828                                 do_fn(KVAL(K_PGDN), 0);
 829                                 return;
 830                         case KVAL(K_P4):
 831                                 do_cur(KVAL(K_LEFT), 0);
 832                                 return;
 833                         case KVAL(K_P6):
 834                                 do_cur(KVAL(K_RIGHT), 0);
 835                                 return;
 836                         case KVAL(K_P7):
 837                                 do_fn(KVAL(K_FIND), 0);
 838                                 return;
 839                         case KVAL(K_P8):
 840                                 do_cur(KVAL(K_UP), 0);
 841                                 return;
 842                         case KVAL(K_P9):
 843                                 do_fn(KVAL(K_PGUP), 0);
 844                                 return;
 845                         case KVAL(K_P5):
 846                                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
 847                                 return;
 848                 }
 849 
 850         put_queue(pad_chars[value]);
 851         if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
 852                 put_queue(10);
 853 }
 854 
 855 static void do_cur(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857         static const char *cur_chars = "BDCA";
 858         if (up_flag)
 859                 return;
 860 
 861         applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 862 }
 863 
 864 static void do_shift(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 865 {
 866         int old_state = shift_state;
 867 
 868         if (rep)
 869                 return;
 870 
 871         /* Mimic typewriter:
 872            a CapsShift key acts like Shift but undoes CapsLock */
 873         if (value == KVAL(K_CAPSSHIFT)) {
 874                 value = KVAL(K_SHIFT);
 875                 if (!up_flag)
 876                         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
 877         }
 878 
 879         if (up_flag) {
 880                 /* handle the case that two shift or control
 881                    keys are depressed simultaneously */
 882                 if (k_down[value])
 883                         k_down[value]--;
 884         } else
 885                 k_down[value]++;
 886 
 887         if (k_down[value])
 888                 shift_state |= (1 << value);
 889         else
 890                 shift_state &= ~ (1 << value);
 891 
 892         /* kludge, no joke... */
 893         if (up_flag && shift_state != old_state && npadch != -1) {
 894                 put_queue(npadch & 0xff);
 895                 npadch = -1;
 896         }
 897 }
 898 
 899 /* called after returning from RAW mode or when changing consoles -
 900    recompute k_down[] and shift_state from key_down[] */
 901 /* maybe called when keymap is undefined, so that shiftkey release is seen */
 902 void compute_shiftstate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 903 {
 904         int i, j, k, sym, val;
 905 
 906         shift_state = 0;
 907         for(i=0; i < SIZE(k_down); i++)
 908           k_down[i] = 0;
 909 
 910         for(i=0; i < SIZE(key_down); i++)
 911           if(key_down[i]) {     /* skip this word if not a single bit on */
 912             k = i*BITS_PER_LONG;
 913             for(j=0; j<BITS_PER_LONG; j++,k++)
 914               if(test_bit(k, key_down)) {
 915                 sym = U(plain_map[k]);
 916                 if(KTYP(sym) == KT_SHIFT) {
 917                   val = KVAL(sym);
 918                   if (val == KVAL(K_CAPSSHIFT))
 919                     val = KVAL(K_SHIFT);
 920                   k_down[val]++;
 921                   shift_state |= (1<<val);
 922                 }
 923               }
 924           }
 925 }
 926 
 927 static void do_meta(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 928 {
 929         if (up_flag)
 930                 return;
 931 
 932         if (vc_kbd_mode(kbd, VC_META)) {
 933                 put_queue('\033');
 934                 put_queue(value);
 935         } else
 936                 put_queue(value | 0x80);
 937 }
 938 
 939 static void do_ascii(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 940 {
 941         int base;
 942 
 943         if (up_flag)
 944                 return;
 945 
 946         if (value < 10)    /* decimal input of code, while Alt depressed */
 947             base = 10;
 948         else {       /* hexadecimal input of code, while AltGr depressed */
 949             value -= 10;
 950             base = 16;
 951         }
 952 
 953         if (npadch == -1)
 954           npadch = value;
 955         else
 956           npadch = npadch * base + value;
 957 }
 958 
 959 static void do_lock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 960 {
 961         if (up_flag || rep)
 962                 return;
 963         chg_vc_kbd_lock(kbd, value);
 964 }
 965 
 966 /*
 967  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
 968  * or (ii) whatever pattern of lights people want to show using KDSETLED,
 969  * or (iii) specified bits of specified words in kernel memory.
 970  */
 971 
 972 static unsigned char ledstate = 0xff; /* undefined */
 973 static unsigned char ledioctl;
 974 
 975 unsigned char getledstate(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 976     return ledstate;
 977 }
 978 
 979 void setledstate(struct kbd_struct *kbd, unsigned int led) {
     /* [previous][next][first][last][top][bottom][index][help] */
 980     if (!(led & ~7)) {
 981         ledioctl = led;
 982         kbd->ledmode = LED_SHOW_IOCTL;
 983     } else
 984         kbd->ledmode = LED_SHOW_FLAGS;
 985     set_leds();
 986 }
 987 
 988 static struct ledptr {
 989     unsigned int *addr;
 990     unsigned int mask;
 991     unsigned char valid:1;
 992 } ledptrs[3];
 993 
 994 void register_leds(int console, unsigned int led,
     /* [previous][next][first][last][top][bottom][index][help] */
 995                    unsigned int *addr, unsigned int mask) {
 996     struct kbd_struct *kbd = kbd_table + console;
 997     if (led < 3) {
 998         ledptrs[led].addr = addr;
 999         ledptrs[led].mask = mask;
1000         ledptrs[led].valid = 1;
1001         kbd->ledmode = LED_SHOW_MEM;
1002     } else
1003         kbd->ledmode = LED_SHOW_FLAGS;
1004 }
1005 
1006 static inline unsigned char getleds(void){
     /* [previous][next][first][last][top][bottom][index][help] */
1007     struct kbd_struct *kbd = kbd_table + fg_console;
1008     unsigned char leds;
1009 
1010     if (kbd->ledmode == LED_SHOW_IOCTL)
1011       return ledioctl;
1012     leds = kbd->ledflagstate;
1013     if (kbd->ledmode == LED_SHOW_MEM) {
1014         if (ledptrs[0].valid) {
1015             if (*ledptrs[0].addr & ledptrs[0].mask)
1016               leds |= 1;
1017             else
1018               leds &= ~1;
1019         }
1020         if (ledptrs[1].valid) {
1021             if (*ledptrs[1].addr & ledptrs[1].mask)
1022               leds |= 2;
1023             else
1024               leds &= ~2;
1025         }
1026         if (ledptrs[2].valid) {
1027             if (*ledptrs[2].addr & ledptrs[2].mask)
1028               leds |= 4;
1029             else
1030               leds &= ~4;
1031         }
1032     }
1033     return leds;
1034 }
1035 
1036 /*
1037  * This routine is the bottom half of the keyboard interrupt
1038  * routine, and runs with all interrupts enabled. It does
1039  * console changing, led setting and copy_to_cooked, which can
1040  * take a reasonably long time.
1041  *
1042  * Aside from timing (which isn't really that important for
1043  * keyboard interrupts as they happen often), using the software
1044  * interrupt routines for this thing allows us to easily mask
1045  * this when we don't want any of the above to happen. Not yet
1046  * used, but this allows for easy and efficient race-condition
1047  * prevention later on.
1048  */
1049 static void kbd_bh(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1050 {
1051         unsigned char leds = getleds();
1052 
1053         if (leds != ledstate) {
1054                 ledstate = leds;
1055                 send_cmd(SKBDCMD_SETLED);
1056                 send_cmd(vcleds_to_sunkbd(leds));
1057         }
1058 }
1059 
1060 int kbd_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1061 {
1062         int i, opt_node;
1063         struct kbd_struct kbd0;
1064         extern struct tty_driver console_driver;
1065 
1066         kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1067         kbd0.ledmode = LED_SHOW_FLAGS;
1068         kbd0.lockstate = KBD_DEFLOCK;
1069         kbd0.modeflags = KBD_DEFMODE;
1070         kbd0.kbdmode = VC_XLATE;
1071  
1072         for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1073                 kbd_table[i] = kbd0;
1074 
1075         ttytab = console_driver.table;
1076 
1077         /* XXX Check keyboard-click? property in 'options' PROM node XXX */
1078         if(sparc_cpu_model != sun4) {
1079                 opt_node = prom_getchild(prom_root_node);
1080                 opt_node = prom_searchsiblings(opt_node, "options");
1081                 i = prom_getintdefault(opt_node, "keyboard-click?", -1);
1082                 if(i != -1)
1083                         sunkbd_clickp = 1;
1084                 else
1085                         sunkbd_clickp = 0;
1086         } else {
1087                 sunkbd_clickp = 0;
1088         }
1089         init_bh(KEYBOARD_BH, kbd_bh);
1090         mark_bh(KEYBOARD_BH);
1091         return 0;
1092 }
1093 
1094 /* /dev/kbd support */
1095 
1096 #define KBD_QSIZE 32
1097 static Firm_event kbd_queue [KBD_QSIZE];
1098 static int kbd_head, kbd_tail;
1099 char kbd_opened;
1100 static struct wait_queue *kbd_wait;
1101 static struct fasync_struct *kb_fasync;
1102 
1103 void
1104 push_kbd (int scan)
     /* [previous][next][first][last][top][bottom][index][help] */
1105 {
1106         int next = (kbd_head + 1) % KBD_QSIZE;
1107 
1108         if (scan == KBD_IDLE)
1109                 return;
1110         if (next != kbd_tail){
1111                 kbd_queue [kbd_head].id = scan & KBD_KEYMASK;
1112                 kbd_queue [kbd_head].value=scan & KBD_UP ? VKEY_UP : VKEY_DOWN;
1113                 kbd_queue [kbd_head].time = xtime;
1114                 kbd_head = next;
1115         }
1116         if (kb_fasync)
1117                 kill_fasync (kb_fasync, SIGIO);
1118         wake_up_interruptible (&kbd_wait);
1119 }
1120 
1121 static int
1122 kbd_read (struct inode *inode, struct file *f, char *buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1123 {
1124         struct wait_queue wait = { current, NULL };
1125         char *end, *p;
1126 
1127         /* Return EWOULDBLOCK, because this is what the X server expects */
1128         if (kbd_head == kbd_tail){
1129                 if (f->f_flags & O_NONBLOCK)
1130                         return -EWOULDBLOCK;
1131                 add_wait_queue (&kbd_wait, &wait);
1132                 while (kbd_head == kbd_tail && !(current->signal & ~current->blocked)){
1133                         current->state = TASK_INTERRUPTIBLE;
1134                         schedule ();
1135                 }
1136                 current->state = TASK_RUNNING;
1137                 remove_wait_queue (&kbd_wait, &wait);
1138         }
1139         /* There is data in the keyboard, fill the user buffer */
1140         end = buffer+count;
1141         p = buffer;
1142         for (; p < end && kbd_head != kbd_tail; p += sizeof (Firm_event)){
1143                 *(Firm_event *)p = kbd_queue [kbd_tail];
1144 #ifdef KBD_DEBUG
1145                 printk ("[%s]", kbd_queue [kbd_tail].value == VKEY_UP ? "UP" : "DOWN");
1146 #endif
1147                 kbd_tail++;
1148                 kbd_tail %= KBD_QSIZE;
1149         }
1150         return p-buffer;
1151 }
1152 
1153 /* Needed by X */
1154 static int
1155 kbd_fasync (struct inode *inode, struct file *filp, int on)
     /* [previous][next][first][last][top][bottom][index][help] */
1156 {
1157         int retval;
1158 
1159         retval = fasync_helper (inode, filp, on, &kb_fasync);
1160         if (retval < 0)
1161                 return retval;
1162         return 0;
1163 }
1164 
1165 static int
1166 kbd_select (struct inode *i, struct file *f, int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
1167 {
1168         if (sel_type != SEL_IN)
1169                 return 0;
1170         if (kbd_head != kbd_tail)
1171                 return 1;
1172         select_wait (&kbd_wait, wait);
1173         return 0;
1174 }
1175 
1176 static int
1177 kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1178 {
1179         switch (cmd){
1180         case KIOCTYPE:            /* return keyboard type */
1181                 if (verify_area (VERIFY_WRITE, (void *)arg, sizeof (int)))
1182                         return -EFAULT;
1183                 *(int *) arg = sunkbd_type;
1184                 break;
1185         case KIOCGTRANS:
1186                 if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1187                         return -EFAULT;
1188                 *(int *) arg = TR_UNTRANS_EVENT;
1189                 break;
1190         case KIOCTRANS:
1191                 if (verify_area (VERIFY_READ, (void *) arg, sizeof (int)))
1192                         return -EFAULT;
1193                 if (*(int *) arg != TR_UNTRANS_EVENT)
1194                         return -EINVAL;
1195                 break;
1196         case KIOCLAYOUT:
1197                 if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1198                         return -EFAULT;
1199                 *(int *) arg = sunkbd_layout;
1200                 break;
1201         case KIOCSDIRECT:
1202                 if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1203                         return -EFAULT;
1204 #ifndef CODING_NEW_DRIVER
1205                 if (*(int *) arg)
1206                         kbd_redirected = fg_console + 1;
1207                 else
1208                         kbd_redirected = 0;
1209                 kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE;
1210 #endif
1211                 break;
1212         case KIOCCMD:
1213                 /* Need to support beep on/off, keyclick on/off */
1214                 return 0;
1215         case FIONREAD:          /* return number of bytes in kbd queue */
1216         {
1217                 int count;
1218                 
1219                 if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1220                         return -EFAULT;
1221                 count = kbd_head - kbd_tail;
1222                 * (int *)arg = (count < 0) ? KBD_QSIZE - count : count;
1223                 return 0;
1224         }
1225         default:
1226                 printk ("Unknown Keyboard ioctl: %8.8x\n", cmd);
1227                 return -EINVAL;
1228         }
1229         return 0;
1230 }
1231 
1232 static int
1233 kbd_open (struct inode *i, struct file *f)
     /* [previous][next][first][last][top][bottom][index][help] */
1234 {
1235         if (kbd_opened)
1236                 return 0;
1237         kbd_opened = fg_console + 1;
1238         kbd_head = kbd_tail = 0;
1239         return 0;
1240 }
1241 
1242 static void
1243 kbd_close (struct inode *i, struct file *f)
     /* [previous][next][first][last][top][bottom][index][help] */
1244 {
1245         if (kbd_redirected)
1246                 kbd_table [kbd_opened-1].kbdmode = VC_XLATE;
1247         kbd_redirected = 0;
1248         kbd_opened = 0;
1249 
1250         kbd_fasync (i, f, 0);
1251 }
1252 
1253 static struct
1254 file_operations kbd_fops =
1255 {
1256         NULL,                   /* seek */
1257         kbd_read,               /* read */
1258         NULL,                   /* write */
1259         NULL,                   /* readdir */
1260         kbd_select,             /* select */
1261         kbd_ioctl,              /* ioctl */
1262         NULL,                   /* mmap */
1263         kbd_open,               /* open */
1264         kbd_close,              /* close */
1265         NULL,                   /* fsync */
1266         kbd_fasync,             /* fasync */
1267         NULL,                   /* check_media_change */
1268         NULL,                   /* revalidate */
1269 };
1270 
1271 void
1272 keyboard_zsinit(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1273 {
1274         int timeout = 0;
1275 
1276         /* Test out the leds */
1277         sunkbd_type = 255;
1278         send_cmd(SKBDCMD_RESET);
1279         while((sunkbd_type==255) && timeout < 500000) {
1280                 udelay(100);
1281                 timeout += 20;
1282         }
1283 
1284         if(timeout>=500000) {
1285                 printk("keyboard: not present\n");
1286                 return;
1287         }
1288 
1289         if(sunkbd_type != SUNKBD_TYPE4) {
1290                 printk("Sun TYPE %d keyboard detected ", sunkbd_type);
1291         } else {
1292                 udelay(200);
1293                 timeout=0;
1294                 while(timeout++ < 500000)
1295                         barrier();
1296                 printk("Sun TYPE %d keyboard detected ",
1297                        ((sunkbd_layout==SUNKBD_LOUT_TYP5) ? 5 : 4));
1298         }
1299         if(sunkbd_type == SUNKBD_TYPE2)
1300                 sunkbd_clickp = 0;
1301 
1302         if(sunkbd_clickp)
1303                 printk("with keyclick\n");
1304         else
1305                 printk("without keyclick\n");
1306 
1307         /* Dork with led lights, then turn them all off */
1308         send_cmd(SKBDCMD_SETLED); send_cmd(0xf); /* All on */
1309         send_cmd(SKBDCMD_SETLED); send_cmd(0x0); /* All off */
1310 
1311         /* Register the /dev/kbd interface */
1312         if (register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
1313                 printk ("Could not register /dev/kbd device\n");
1314                 return;
1315         }
1316         return;
1317 }

/* [previous][next][first][last][top][bottom][index][help] */