linux-old/drivers/sbus/char/sunkbd.c History
<<
>>
Prefs
   1/* keyboard.c: Sun keyboard driver.
   2 *
   3 * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
   4 *
   5 * Added vuid event generation and /dev/kbd device for SunOS
   6 * compatibility - Miguel (miguel@nuclecu.unam.mx)
   7 *
   8 * Added PCI 8042 controller support -DaveM
   9 * Added Magic SysRq support -MJ
  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/* Define this one if you are making a new frame buffer driver */
  52/* it will not block the keyboard */
  53/* #define CODING_NEW_DRIVER */
  54
  55/* KBD device number, temporal */
  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 * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  68 * is on. This seems a good reason to start with NumLock off.
  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 * global state includes the following, and various static variables
  89 * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
  90 * (last_console is now a global variable)
  91 */
  92
  93/* shift state counters.. */
  94static unsigned char k_down[NR_SHIFT];
  95/* keyboard key bitmap */
  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 * In order to retrieve the shift_state (for the mouse server), either
 104 * the variable must be global, or a new procedure must be created to 
 105 * return the value. I chose the former way.
 106 */
 107#ifndef CONFIG_PCI
 108int shift_state;
 109struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 110#endif
 111static int npadch = -1;                 /* -1 or number assembled on pad */
 112static unsigned char diacr;
 113static char rep;                        /* flag telling character repeat */
 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/* maximum values each key_handler can handle */
 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/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
 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"    /* 0x00 - 0x0f */
 172        "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312"                /* 0x10 - 0x1f */
 173        "34567890-=`\177\0=/*"                                  /* 0x20 - 0x2f */
 174        "\0\0.\0\0\011qwertyuiop"                               /* 0x30 - 0x3f */
 175        "[]\177\000789-\0\0\0\0\0asd"                           /* 0x40 - 0x4f */
 176        "fghjkl;'\\\015\0154560\0"                              /* 0x50 - 0x5f */
 177        "\0\0\0\0zxcvbnm,./\0\012"                              /* 0x60 - 0x6f */
 178        "123\0\0\0\0\0\0 \0\0\0\0\0\0";                         /* 0x70 - 0x7f */
 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/* commands */
 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/* The led set commands require sending the SETLED byte then
 205 * a byte encoding which led's to have set.  Here are the bit
 206 * values, a bit set = led-on.
 207 */
 208#define LED_NLOCK           0x1   /* Num-lock */
 209#define LED_CMPOSE          0x2   /* Compose */
 210#define LED_SCRLCK          0x4   /* Scroll-lock */
 211#define LED_CLOCK           0x8   /* Caps-lock */
 212
 213/* Special state characters */
 214#define SKBD_RESET          0xff
 215#define SKBD_ALLUP          0x7f
 216#define SKBD_LYOUT          0xfe
 217
 218/* On the Sparc the keyboard could be one of two things.
 219 * It could be a real keyboard speaking over one of the
 220 * channels of the second zs8530 chip (other channel is
 221 * used by the Sun mouse).  Else we have serial console
 222 * going, and thus the other zs8530 chip is who we speak
 223 * to.  Either way, we communicate through the zs8530
 224 * driver for all our I/O.
 225 */
 226
 227#define SUNKBD_UBIT     0x80      /* If set, key went up */
 228#define SUNKBD_KMASK    0x7f      /* Other bits are the keycode */
 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/* Due to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing:
 239 *
 240 *      tasklet_enable(&keyboard_tasklet);
 241 *      tasklet_schedule(&keyboard_tasklet);
 242 *
 243 * this might well be called before some driver has claimed interest in
 244 * handling the keyboard input/output. So we need to assign an initial nop.
 245 */
 246static void nop_kbd_put_char(unsigned char c) { }
 247static void (*kbd_put_char)(unsigned char) = nop_kbd_put_char;
 248
 249/* Must be invoked under sunkbd_lock. */
 250static inline void send_cmd(unsigned char c)
 251{
 252        kbd_put_char(c);
 253}
 254
 255/* kbd_bh() calls this to send the SKBDCMD_SETLED to the sun keyboard
 256 * with the proper bit pattern for the leds to be set.  It basically
 257 * converts the kbd->ledflagstate values to corresponding sun kbd led
 258 * bit value.
 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 * Translation of escaped scancodes to keycodes.
 277 * This is now user-settable.
 278 * The keycodes 1-88,96-111,119 are fairly standard, and
 279 * should probably not be changed - changing might confuse X.
 280 * X also interprets scancode 0x5d (KEY_Begin).
 281 *
 282 * For 1-88 keycode equals scancode.
 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  /* (control-pause) */
 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 * The keycodes below are randomly located in 89-95,112-118,120-127.
 306 * They could be thrown away (and all occurrences below replaced by 0),
 307 * but that would force many users to use the `setkeycodes' utility, where
 308 * they needed not before. It does not matter that there are duplicates, as
 309 * long as no duplication occurs for any single keyboard.
 310 */
 311#define SC_LIM 89
 312
 313#define FOCUS_PF1 85           /* actual code! */
 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/* tfj@olivia.ping.dk:
 328 * The four keys are located over the numeric keypad, and are
 329 * labelled A1-A4. It's an rc930 keyboard, from
 330 * Regnecentralen/RC International, Now ICL.
 331 * Scancodes: 59, 5a, 5b, 5c.
 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,                   /* 0x59-0x5f */
 340  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
 341  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
 342  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
 343  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
 344  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
 345};
 346
 347/* BTC */
 348#define E0_MACRO   112
 349/* LK450 */
 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 * My OmniKey generates e0 4c for  the "OMNI" key and the
 358 * right alt key does nada. [kkoller@nyx10.cs.du.edu]
 359 */
 360#define E0_OK   124
 361/*
 362 * New microsoft keyboard is rumoured to have
 363 * e0 5b (left window button), e0 5c (right window button),
 364 * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
 365 * [or: Windows_L, Windows_R, TaskMan]
 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,                             /* 0x00-0x07 */
 373  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x08-0x0f */
 374  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x10-0x17 */
 375  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,             /* 0x18-0x1f */
 376  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x20-0x27 */
 377  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x28-0x2f */
 378  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,             /* 0x30-0x37 */
 379  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,       /* 0x38-0x3f */
 380  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,       /* 0x40-0x47 */
 381  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
 382  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,       /* 0x50-0x57 */
 383  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,           /* 0x58-0x5f */
 384  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x60-0x67 */
 385  0, 0, 0, 0, 0, 0, 0, E0_MACRO,                      /* 0x68-0x6f */
 386  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x70-0x77 */
 387  0, 0, 0, 0, 0, 0, 0, 0                              /* 0x78-0x7f */
 388};
 389
 390/* we use this map to determine if a particular key should not be
 391   autorepeated. We don't autorepeat CONTROL, LSHIFT, CAPS,
 392   ALT, LMETA, RSHIFT, RMETA, ALTG and COMPOSE */
 393static unsigned char norepeat_keys[128] = {
 394        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,  /* 0x00-0x0f */
 395        0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x10-0x1f */
 396        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x20-0x2f */
 397        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x30-0x3f */
 398        0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,  /* 0x40-0x4f */
 399        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x50-0x5f */
 400        0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,  /* 0x60-0x6f */
 401        0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0,  /* 0x70-0x7f */
 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/* Keeps track of the last pressed key */
 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        /* Auto repeat: send regs = 0 to indicate autorepeat */
 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/* #define SKBD_DEBUG */
 457/* This is our keyboard 'interrupt' routine.
 458 * Must run under sunkbd_lock.
 459 */
 460static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
 461{
 462        unsigned char keycode;
 463        char up_flag;                          /* 0 or SUNKBD_UBIT */
 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        /* Whee, a real character. */
 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                /* This is to workaround ugly bug in tty_io.c, which
 513                   does not do locking when it should */
 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                /* we do not return yet, because we want to maintain
 523                 * the key_down array, so that we have the correct
 524                 * values  when finishing RAW mode or when changing VT's.
 525                 */
 526        }
 527        up_flag = (keycode & SUNKBD_UBIT);  /* The 'up' bit */
 528        keycode &= SUNKBD_KMASK;            /* all the rest */
 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                       /* Handle the SysRq hack */
 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         * Small change in philosophy: earlier we defined repetition by
 562         *       rep = keycode == prev_keycode;
 563         *       prev_keycode = keycode;
 564         * but now by the fact that the depressed key was down already.
 565         * Does this ever make a difference? Yes.
 566         */
 567
 568        /*
 569         *  Repeat a key only if the input buffers are empty or the
 570         *  characters get echoed locally. This makes key repeat usable
 571         *  with slow applications and under heavy loads.
 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                /* the XOR below used to be an OR */
 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                        /* maybe beep? */
 603                        /* we have at least to update shift_state */
 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         * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 683         * these routines are also activated by ^S/^Q.
 684         * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 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 * Bind this to Shift-NumLock if you work in application keypad mode
 702 * but want to be able to change the NumLock flag.
 703 * Bind this to NumLock if you prefer that the NumLock key always
 704 * changes the NumLock flag.
 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        /* switch to the last used console, ChN */
 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        /* sigh.. attempt to prevent multiple entry */
 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         * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 800         * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 801         * handling.
 802         * 
 803         * We should do this some day --- the whole point of a secure
 804         * attention key is that it should be guaranteed to always
 805         * work.
 806         */
 807        reset_vc(fg_console);
 808        do_unblank_screen();    /* not in interrupt routine? */
 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;         /* no action, if this is a key release */
 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/* If a dead key pressed twice, output a character corresponding to it, */
 865/* otherwise just remember the dead key.                                */
 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) {   /* pressed twice */
 874                diacr = 0;
 875                put_queue(value);
 876                return;
 877        }
 878        diacr = value;
 879}
 880
 881
 882/* If space is pressed, return the character corresponding the pending  */
 883/* dead key, otherwise try to combine the two.                          */
 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;         /* no action, if this is a key release */
 928
 929        /* kludge... shift forces cursor/number keys */
 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        /* Mimic typewriter:
 995           a CapsShift key acts like Shift but undoes CapsLock */
 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                /* handle the case that two shift or control
1004                   keys are depressed simultaneously */
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        /* kludge, no joke... */
1016        if (up_flag && shift_state != old_state && npadch != -1) {
1017                put_queue(npadch & 0xff);
1018                npadch = -1;
1019        }
1020}
1021
1022/* called after returning from RAW mode or when changing consoles -
1023   recompute k_down[] and shift_state from key_down[] */
1024/* maybe called when keymap is undefined, so that shiftkey release is seen */
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]) {     /* skip this word if not a single bit on */
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)    /* decimal input of code, while Alt depressed */
1070            base = 10;
1071        else {       /* hexadecimal input of code, while AltGr depressed */
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 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1091 * or (ii) whatever pattern of lights people want to show using KDSETLED,
1092 * or (iii) specified bits of specified words in kernel memory.
1093 */
1094
1095static unsigned char ledstate = 0xff; /* undefined */
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 * This routine is the bottom half of the keyboard interrupt
1161 * routine, and runs with all interrupts enabled. It does
1162 * console changing, led setting and copy_to_cooked, which can
1163 * take a reasonably long time.
1164 *
1165 * Aside from timing (which isn't really that important for
1166 * keyboard interrupts as they happen often), using the software
1167 * interrupt routines for this thing allows us to easily mask
1168 * this when we don't want any of the above to happen. Not yet
1169 * used, but this allows for easy and efficient race-condition
1170 * prevention later on.
1171 */
1172static unsigned char sunkbd_ledstate = 0xff; /* undefined */
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/* Support for keyboard "beeps". */ 
1193
1194/* Timer routine to turn off the beep after the interval expires. */
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 * Initiate a keyboard beep. If the frequency is zero, then we stop
1206 * the beep. Any other frequency will start a monotone beep. The beep
1207 * will be stopped by a timer after "ticks" jiffies. If ticks is 0,
1208 * then we do not start a timer.
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        /* XXX Check keyboard-click? property in 'options' PROM node XXX */
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/* /dev/kbd support */
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        /* Return EWOULDBLOCK, because this is what the X server expects */
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        /* There is data in the keyboard, fill the user buffer */
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/* Needed by X */
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:            /* return keyboard type */
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:          /* return number of bytes in kbd queue */
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        /* Test out the leds */
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        /* Dork with led lights, then turn them all off */
1608        send_cmd(SKBDCMD_SETLED); send_cmd(0xf); /* All on */
1609        send_cmd(SKBDCMD_SETLED); send_cmd(0x0); /* All off */
1610
1611        spin_unlock_irq(&sunkbd_lock);
1612
1613        /* Register the /dev/kbd interface */
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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.