OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [sbus/] [char/] [sunkbd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/* 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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
545
{
546
        if (rep)
547
                return;
548
        chg_vc_kbd_led(kbd, VC_CAPSLOCK);
549
}
550
 
551
static void caps_on(void)
552
{
553
        if (rep)
554
                return;
555
        set_vc_kbd_led(kbd, VC_CAPSLOCK);
556
}
557
 
558
static void show_ptregs(void)
559
{
560
        if (pt_regs)
561
                show_regs(pt_regs);
562
}
563
 
564
static void hold(void)
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)
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)
595
{
596
        if (!rep)
597
                chg_vc_kbd_led(kbd,VC_NUMLOCK);
598
}
599
 
600
static void lastcons(void)
601
{
602
        /* switch to the last used console, ChN */
603
        set_console(last_console);
604
}
605
 
606
static void decr_console(void)
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)
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)
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)
641
{
642
        scrollfront(0);
643
}
644
 
645
static void scroll_back(void)
646
{
647
        scrollback(0);
648
}
649
 
650
static void boot_it(void)
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)
662
{
663
        dead_key_next = 1;
664
}
665
 
666
int spawnpid, spawnsig;
667
 
668
static void spawn_console(void)
669
{
670
        if (spawnpid)
671
           if(kill_proc(spawnpid, spawnsig, 1))
672
             spawnpid = 0;
673
}
674
 
675
static void SAK(void)
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)
694
{
695
}
696
 
697
static void do_null()
698
{
699
        compute_shiftstate();
700
}
701
 
702
static void do_spec(unsigned char value, char up_flag)
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)
712
{
713
        printk("keyboard.c: do_lowercase was called - impossible\n");
714
}
715
 
716
static void do_self(unsigned char value, char up_flag)
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
#define A_CEDIL  ','
739
static unsigned char ret_diacr[NR_DEAD] =
740
        {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
741
 
742
/* If a dead key pressed twice, output a character corresponding to it, */
743
/* otherwise just remember the dead key.                                */
744
 
745
static void do_dead(unsigned char value, char up_flag)
746
{
747
        if (up_flag)
748
                return;
749
 
750
        value = ret_diacr[value];
751
        if (diacr == value) {   /* pressed twice */
752
                diacr = 0;
753
                put_queue(value);
754
                return;
755
        }
756
        diacr = value;
757
}
758
 
759
 
760
/* If space is pressed, return the character corresponding the pending  */
761
/* dead key, otherwise try to combine the two.                          */
762
 
763
unsigned char handle_diacr(unsigned char ch)
764
{
765
        int d = diacr;
766
        int i;
767
 
768
        diacr = 0;
769
        if (ch == ' ')
770
                return d;
771
 
772
        for (i = 0; i < accent_table_size; i++) {
773
                if (accent_table[i].diacr == d && accent_table[i].base == ch)
774
                        return accent_table[i].result;
775
        }
776
 
777
        put_queue(d);
778
        return ch;
779
}
780
 
781
static void do_cons(unsigned char value, char up_flag)
782
{
783
        if (up_flag)
784
                return;
785
        want_console = value;
786
}
787
 
788
static void do_fn(unsigned char value, char up_flag)
789
{
790
        if (up_flag)
791
                return;
792
        if (value < SIZE(func_table)) {
793
                if (func_table[value])
794
                        puts_queue(func_table[value]);
795
        } else
796
                printk("do_fn called with value=%d\n", value);
797
}
798
 
799
static void do_pad(unsigned char value, char up_flag)
800
{
801
        static const char *pad_chars = "0123456789+-*/\015,.?";
802
        static const char *app_map = "pqrstuvwxylSRQMnn?";
803
 
804
        if (up_flag)
805
                return;         /* no action, if this is a key release */
806
 
807
        /* kludge... shift forces cursor/number keys */
808
        if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
809
                applkey(app_map[value], 1);
810
                return;
811
        }
812
 
813
        if (!vc_kbd_led(kbd,VC_NUMLOCK))
814
                switch (value) {
815
                        case KVAL(K_PCOMMA):
816
                        case KVAL(K_PDOT):
817
                                do_fn(KVAL(K_REMOVE), 0);
818
                                return;
819
                        case KVAL(K_P0):
820
                                do_fn(KVAL(K_INSERT), 0);
821
                                return;
822
                        case KVAL(K_P1):
823
                                do_fn(KVAL(K_SELECT), 0);
824
                                return;
825
                        case KVAL(K_P2):
826
                                do_cur(KVAL(K_DOWN), 0);
827
                                return;
828
                        case KVAL(K_P3):
829
                                do_fn(KVAL(K_PGDN), 0);
830
                                return;
831
                        case KVAL(K_P4):
832
                                do_cur(KVAL(K_LEFT), 0);
833
                                return;
834
                        case KVAL(K_P6):
835
                                do_cur(KVAL(K_RIGHT), 0);
836
                                return;
837
                        case KVAL(K_P7):
838
                                do_fn(KVAL(K_FIND), 0);
839
                                return;
840
                        case KVAL(K_P8):
841
                                do_cur(KVAL(K_UP), 0);
842
                                return;
843
                        case KVAL(K_P9):
844
                                do_fn(KVAL(K_PGUP), 0);
845
                                return;
846
                        case KVAL(K_P5):
847
                                applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
848
                                return;
849
                }
850
 
851
        put_queue(pad_chars[value]);
852
        if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
853
                put_queue(10);
854
}
855
 
856
static void do_cur(unsigned char value, char up_flag)
857
{
858
        static const char *cur_chars = "BDCA";
859
        if (up_flag)
860
                return;
861
 
862
        applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
863
}
864
 
865
static void do_shift(unsigned char value, char up_flag)
866
{
867
        int old_state = shift_state;
868
 
869
        if (rep)
870
                return;
871
 
872
        /* Mimic typewriter:
873
           a CapsShift key acts like Shift but undoes CapsLock */
874
        if (value == KVAL(K_CAPSSHIFT)) {
875
                value = KVAL(K_SHIFT);
876
                if (!up_flag)
877
                        clr_vc_kbd_led(kbd, VC_CAPSLOCK);
878
        }
879
 
880
        if (up_flag) {
881
                /* handle the case that two shift or control
882
                   keys are depressed simultaneously */
883
                if (k_down[value])
884
                        k_down[value]--;
885
        } else
886
                k_down[value]++;
887
 
888
        if (k_down[value])
889
                shift_state |= (1 << value);
890
        else
891
                shift_state &= ~ (1 << value);
892
 
893
        /* kludge, no joke... */
894
        if (up_flag && shift_state != old_state && npadch != -1) {
895
                put_queue(npadch & 0xff);
896
                npadch = -1;
897
        }
898
}
899
 
900
/* called after returning from RAW mode or when changing consoles -
901
   recompute k_down[] and shift_state from key_down[] */
902
/* maybe called when keymap is undefined, so that shiftkey release is seen */
903
void compute_shiftstate(void)
904
{
905
        int i, j, k, sym, val;
906
 
907
        shift_state = 0;
908
        for(i=0; i < SIZE(k_down); i++)
909
          k_down[i] = 0;
910
 
911
        for(i=0; i < SIZE(key_down); i++)
912
          if(key_down[i]) {     /* skip this word if not a single bit on */
913
            k = i*BITS_PER_LONG;
914
            for(j=0; j<BITS_PER_LONG; j++,k++)
915
              if(test_bit(k, key_down)) {
916
                sym = U(plain_map[k]);
917
                if(KTYP(sym) == KT_SHIFT) {
918
                  val = KVAL(sym);
919
                  if (val == KVAL(K_CAPSSHIFT))
920
                    val = KVAL(K_SHIFT);
921
                  k_down[val]++;
922
                  shift_state |= (1<<val);
923
                }
924
              }
925
          }
926
}
927
 
928
static void do_meta(unsigned char value, char up_flag)
929
{
930
        if (up_flag)
931
                return;
932
 
933
        if (vc_kbd_mode(kbd, VC_META)) {
934
                put_queue('\033');
935
                put_queue(value);
936
        } else
937
                put_queue(value | 0x80);
938
}
939
 
940
static void do_ascii(unsigned char value, char up_flag)
941
{
942
        int base;
943
 
944
        if (up_flag)
945
                return;
946
 
947
        if (value < 10)    /* decimal input of code, while Alt depressed */
948
            base = 10;
949
        else {       /* hexadecimal input of code, while AltGr depressed */
950
            value -= 10;
951
            base = 16;
952
        }
953
 
954
        if (npadch == -1)
955
          npadch = value;
956
        else
957
          npadch = npadch * base + value;
958
}
959
 
960
static void do_lock(unsigned char value, char up_flag)
961
{
962
        if (up_flag || rep)
963
                return;
964
        chg_vc_kbd_lock(kbd, value);
965
}
966
 
967
/*
968
 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
969
 * or (ii) whatever pattern of lights people want to show using KDSETLED,
970
 * or (iii) specified bits of specified words in kernel memory.
971
 */
972
 
973
static unsigned char ledstate = 0xff; /* undefined */
974
static unsigned char ledioctl;
975
 
976
unsigned char getledstate(void) {
977
    return ledstate;
978
}
979
 
980
void setledstate(struct kbd_struct *kbd, unsigned int led) {
981
    if (!(led & ~7)) {
982
        ledioctl = led;
983
        kbd->ledmode = LED_SHOW_IOCTL;
984
    } else
985
        kbd->ledmode = LED_SHOW_FLAGS;
986
    set_leds();
987
}
988
 
989
static struct ledptr {
990
    unsigned int *addr;
991
    unsigned int mask;
992
    unsigned char valid:1;
993
} ledptrs[3];
994
 
995
void register_leds(int console, unsigned int led,
996
                   unsigned int *addr, unsigned int mask) {
997
    struct kbd_struct *kbd = kbd_table + console;
998
    if (led < 3) {
999
        ledptrs[led].addr = addr;
1000
        ledptrs[led].mask = mask;
1001
        ledptrs[led].valid = 1;
1002
        kbd->ledmode = LED_SHOW_MEM;
1003
    } else
1004
        kbd->ledmode = LED_SHOW_FLAGS;
1005
}
1006
 
1007
static inline unsigned char getleds(void){
1008
    struct kbd_struct *kbd = kbd_table + fg_console;
1009
    unsigned char leds;
1010
 
1011
    if (kbd->ledmode == LED_SHOW_IOCTL)
1012
      return ledioctl;
1013
    leds = kbd->ledflagstate;
1014
    if (kbd->ledmode == LED_SHOW_MEM) {
1015
        if (ledptrs[0].valid) {
1016
            if (*ledptrs[0].addr & ledptrs[0].mask)
1017
              leds |= 1;
1018
            else
1019
              leds &= ~1;
1020
        }
1021
        if (ledptrs[1].valid) {
1022
            if (*ledptrs[1].addr & ledptrs[1].mask)
1023
              leds |= 2;
1024
            else
1025
              leds &= ~2;
1026
        }
1027
        if (ledptrs[2].valid) {
1028
            if (*ledptrs[2].addr & ledptrs[2].mask)
1029
              leds |= 4;
1030
            else
1031
              leds &= ~4;
1032
        }
1033
    }
1034
    return leds;
1035
}
1036
 
1037
/*
1038
 * This routine is the bottom half of the keyboard interrupt
1039
 * routine, and runs with all interrupts enabled. It does
1040
 * console changing, led setting and copy_to_cooked, which can
1041
 * take a reasonably long time.
1042
 *
1043
 * Aside from timing (which isn't really that important for
1044
 * keyboard interrupts as they happen often), using the software
1045
 * interrupt routines for this thing allows us to easily mask
1046
 * this when we don't want any of the above to happen. Not yet
1047
 * used, but this allows for easy and efficient race-condition
1048
 * prevention later on.
1049
 */
1050
static void kbd_bh(void)
1051
{
1052
        unsigned char leds = getleds();
1053
 
1054
        if (leds != ledstate) {
1055
                ledstate = leds;
1056
                send_cmd(SKBDCMD_SETLED);
1057
                send_cmd(vcleds_to_sunkbd(leds));
1058
        }
1059
}
1060
 
1061
int kbd_init(void)
1062
{
1063
        int i, opt_node;
1064
        struct kbd_struct kbd0;
1065
        extern struct tty_driver console_driver;
1066
 
1067
        kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1068
        kbd0.ledmode = LED_SHOW_FLAGS;
1069
        kbd0.lockstate = KBD_DEFLOCK;
1070
        kbd0.modeflags = KBD_DEFMODE;
1071
        kbd0.kbdmode = VC_XLATE;
1072
 
1073
        for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1074
                kbd_table[i] = kbd0;
1075
 
1076
        ttytab = console_driver.table;
1077
 
1078
        /* XXX Check keyboard-click? property in 'options' PROM node XXX */
1079
        if(sparc_cpu_model != sun4) {
1080
                opt_node = prom_getchild(prom_root_node);
1081
                opt_node = prom_searchsiblings(opt_node, "options");
1082
                i = prom_getintdefault(opt_node, "keyboard-click?", -1);
1083
                if(i != -1)
1084
                        sunkbd_clickp = 1;
1085
                else
1086
                        sunkbd_clickp = 0;
1087
        } else {
1088
                sunkbd_clickp = 0;
1089
        }
1090
        init_bh(KEYBOARD_BH, kbd_bh);
1091
        mark_bh(KEYBOARD_BH);
1092
        return 0;
1093
}
1094
 
1095
/* /dev/kbd support */
1096
 
1097
#define KBD_QSIZE 32
1098
static Firm_event kbd_queue [KBD_QSIZE];
1099
static int kbd_head, kbd_tail;
1100
char kbd_opened;
1101
static struct wait_queue *kbd_wait;
1102
static struct fasync_struct *kb_fasync;
1103
 
1104
void
1105
push_kbd (int scan)
1106
{
1107
        int next = (kbd_head + 1) % KBD_QSIZE;
1108
 
1109
        if (scan == KBD_IDLE)
1110
                return;
1111
        if (next != kbd_tail){
1112
                kbd_queue [kbd_head].id = scan & KBD_KEYMASK;
1113
                kbd_queue [kbd_head].value=scan & KBD_UP ? VKEY_UP : VKEY_DOWN;
1114
                kbd_queue [kbd_head].time = xtime;
1115
                kbd_head = next;
1116
        }
1117
        if (kb_fasync)
1118
                kill_fasync (kb_fasync, SIGIO);
1119
        wake_up_interruptible (&kbd_wait);
1120
}
1121
 
1122
static int
1123
kbd_read (struct inode *inode, struct file *f, char *buffer, int count)
1124
{
1125
        struct wait_queue wait = { current, NULL };
1126
        char *end, *p;
1127
 
1128
        /* Return EWOULDBLOCK, because this is what the X server expects */
1129
        if (kbd_head == kbd_tail){
1130
                if (f->f_flags & O_NONBLOCK)
1131
                        return -EWOULDBLOCK;
1132
                add_wait_queue (&kbd_wait, &wait);
1133
                while (kbd_head == kbd_tail && !(current->signal & ~current->blocked)){
1134
                        current->state = TASK_INTERRUPTIBLE;
1135
                        schedule ();
1136
                }
1137
                current->state = TASK_RUNNING;
1138
                remove_wait_queue (&kbd_wait, &wait);
1139
        }
1140
        /* There is data in the keyboard, fill the user buffer */
1141
        end = buffer+count;
1142
        p = buffer;
1143
        for (; p < end && kbd_head != kbd_tail; p += sizeof (Firm_event)){
1144
                *(Firm_event *)p = kbd_queue [kbd_tail];
1145
#ifdef KBD_DEBUG
1146
                printk ("[%s]", kbd_queue [kbd_tail].value == VKEY_UP ? "UP" : "DOWN");
1147
#endif
1148
                kbd_tail++;
1149
                kbd_tail %= KBD_QSIZE;
1150
        }
1151
        return p-buffer;
1152
}
1153
 
1154
/* Needed by X */
1155
static int
1156
kbd_fasync (struct inode *inode, struct file *filp, int on)
1157
{
1158
        int retval;
1159
 
1160
        retval = fasync_helper (inode, filp, on, &kb_fasync);
1161
        if (retval < 0)
1162
                return retval;
1163
        return 0;
1164
}
1165
 
1166
static int
1167
kbd_select (struct inode *i, struct file *f, int sel_type, select_table *wait)
1168
{
1169
        if (sel_type != SEL_IN)
1170
                return 0;
1171
        if (kbd_head != kbd_tail)
1172
                return 1;
1173
        select_wait (&kbd_wait, wait);
1174
        return 0;
1175
}
1176
 
1177
static int
1178
kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
1179
{
1180
        switch (cmd){
1181
        case KIOCTYPE:            /* return keyboard type */
1182
                if (verify_area (VERIFY_WRITE, (void *)arg, sizeof (int)))
1183
                        return -EFAULT;
1184
                *(int *) arg = sunkbd_type;
1185
                break;
1186
        case KIOCGTRANS:
1187
                if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1188
                        return -EFAULT;
1189
                *(int *) arg = TR_UNTRANS_EVENT;
1190
                break;
1191
        case KIOCTRANS:
1192
                if (verify_area (VERIFY_READ, (void *) arg, sizeof (int)))
1193
                        return -EFAULT;
1194
                if (*(int *) arg != TR_UNTRANS_EVENT)
1195
                        return -EINVAL;
1196
                break;
1197
        case KIOCLAYOUT:
1198
                if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1199
                        return -EFAULT;
1200
                *(int *) arg = sunkbd_layout;
1201
                break;
1202
        case KIOCSDIRECT:
1203
                if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1204
                        return -EFAULT;
1205
#ifndef CODING_NEW_DRIVER
1206
                if (*(int *) arg)
1207
                        kbd_redirected = fg_console + 1;
1208
                else
1209
                        kbd_redirected = 0;
1210
                kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE;
1211
#endif
1212
                break;
1213
        case KIOCCMD:
1214
                /* Need to support beep on/off, keyclick on/off */
1215
                return 0;
1216
        case FIONREAD:          /* return number of bytes in kbd queue */
1217
        {
1218
                int count;
1219
 
1220
                if (verify_area (VERIFY_WRITE, (void *) arg, sizeof (int)))
1221
                        return -EFAULT;
1222
                count = kbd_head - kbd_tail;
1223
                * (int *)arg = (count < 0) ? KBD_QSIZE - count : count;
1224
                return 0;
1225
        }
1226
        default:
1227
                printk ("Unknown Keyboard ioctl: %8.8x\n", cmd);
1228
                return -EINVAL;
1229
        }
1230
        return 0;
1231
}
1232
 
1233
static int
1234
kbd_open (struct inode *i, struct file *f)
1235
{
1236
        if (kbd_opened)
1237
                return 0;
1238
        kbd_opened = fg_console + 1;
1239
        kbd_head = kbd_tail = 0;
1240
        return 0;
1241
}
1242
 
1243
static void
1244
kbd_close (struct inode *i, struct file *f)
1245
{
1246
        if (kbd_redirected)
1247
                kbd_table [kbd_opened-1].kbdmode = VC_XLATE;
1248
        kbd_redirected = 0;
1249
        kbd_opened = 0;
1250
 
1251
        kbd_fasync (i, f, 0);
1252
}
1253
 
1254
static struct
1255
file_operations kbd_fops =
1256
{
1257
        NULL,                   /* seek */
1258
        kbd_read,               /* read */
1259
        NULL,                   /* write */
1260
        NULL,                   /* readdir */
1261
        kbd_select,             /* select */
1262
        kbd_ioctl,              /* ioctl */
1263
        NULL,                   /* mmap */
1264
        kbd_open,               /* open */
1265
        kbd_close,              /* close */
1266
        NULL,                   /* fsync */
1267
        kbd_fasync,             /* fasync */
1268
        NULL,                   /* check_media_change */
1269
        NULL,                   /* revalidate */
1270
};
1271
 
1272
void
1273
keyboard_zsinit(void)
1274
{
1275
        int timeout = 0;
1276
 
1277
        /* Test out the leds */
1278
        sunkbd_type = 255;
1279
        send_cmd(SKBDCMD_RESET);
1280
        while((sunkbd_type==255) && timeout < 500000) {
1281
                udelay(100);
1282
                timeout += 20;
1283
        }
1284
 
1285
        if(timeout>=500000) {
1286
                printk("keyboard: not present\n");
1287
                return;
1288
        }
1289
 
1290
        if(sunkbd_type != SUNKBD_TYPE4) {
1291
                printk("Sun TYPE %d keyboard detected ", sunkbd_type);
1292
        } else {
1293
                udelay(200);
1294
                timeout=0;
1295
                while(timeout++ < 500000)
1296
                        barrier();
1297
                printk("Sun TYPE %d keyboard detected ",
1298
                       ((sunkbd_layout==SUNKBD_LOUT_TYP5) ? 5 : 4));
1299
        }
1300
        if(sunkbd_type == SUNKBD_TYPE2)
1301
                sunkbd_clickp = 0;
1302
 
1303
        if(sunkbd_clickp)
1304
                printk("with keyclick\n");
1305
        else
1306
                printk("without keyclick\n");
1307
 
1308
        /* Dork with led lights, then turn them all off */
1309
        send_cmd(SKBDCMD_SETLED); send_cmd(0xf); /* All on */
1310
        send_cmd(SKBDCMD_SETLED); send_cmd(0x0); /* All off */
1311
 
1312
        /* Register the /dev/kbd interface */
1313
        if (register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
1314
                printk ("Could not register /dev/kbd device\n");
1315
                return;
1316
        }
1317
        return;
1318
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.