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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [keyb_m68k.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * linux/drivers/char/keyboard.c
3
 *
4
 * Keyboard driver for Linux v0.99 using Latin-1.
5
 *
6
 * Written for linux by Johan Myreen as a translation from
7
 * the assembly version by Linus (with diacriticals added)
8
 *
9
 * Some additional features added by Christoph Niemann (ChN), March 1993
10
 *
11
 * Loadable keymaps by Risto Kankkunen, May 1993
12
 *
13
 * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
14
 * Added decr/incr_console, dynamic keymaps, Unicode support,
15
 * dynamic function/string keys, led setting,  Sept 1994
16
 * `Sticky' modifier keys, 951006.
17
 *
18
 */
19
 
20
/*
21
 * modified to provide 'generic' keyboard support by Hamish Macdonald
22
 */
23
 
24
#include <linux/sched.h>
25
#include <linux/interrupt.h>
26
#include <linux/tty.h>
27
#include <linux/tty_flip.h>
28
#include <linux/mm.h>
29
#include <linux/random.h>
30
 
31
#include <asm/bitops.h>
32
#include <asm/machdep.h>
33
 
34
#include "kbd_kern.h"
35
#include "diacr.h"
36
#include "vt_kern.h"
37
 
38
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
39
 
40
#define KBD_REPORT_ERR
41
#define KBD_REPORT_UNKN
42
/* #define KBD_IS_FOCUS_9000 */
43
 
44
#ifndef KBD_DEFMODE
45
#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
46
#endif
47
 
48
#ifndef KBD_DEFLEDS
49
/*
50
 * Some laptops take the 789uiojklm,. keys as number pad when NumLock
51
 * is on. This seems a good reason to start with NumLock off.
52
 */
53
#define KBD_DEFLEDS 0
54
#endif
55
 
56
#ifndef KBD_DEFLOCK
57
#define KBD_DEFLOCK 0
58
#endif
59
 
60
/*
61
 * The default IO slowdown is doing 'inb()'s from 0x61, which should be
62
 * safe. But as that is the keyboard controller chip address, we do our
63
 * slowdowns here by doing short jumps: the keyboard controller should
64
 * be able to keep up
65
 */
66
#define REALLY_SLOW_IO
67
#define SLOW_IO_BY_JUMPING
68
#include <asm/io.h>
69
#include <asm/system.h>
70
 
71
extern void poke_blanked_console(void);
72
extern void ctrl_alt_del(void);
73
extern void reset_vc(unsigned int new_console);
74
extern void scrollback(int);
75
extern void scrollfront(int);
76
extern int vc_cons_allocated(unsigned int);
77
 
78
unsigned char kbd_read_mask = 0x01;     /* modified by psaux.c */
79
 
80
/*
81
 * global state includes the following, and various static variables
82
 * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
83
 * (last_console is now a global variable)
84
 */
85
 
86
/* shift state counters.. */
87
static unsigned char k_down[NR_SHIFT] = {0, };
88
/* keyboard key bitmap */
89
#define BITS_PER_LONG (8*sizeof(unsigned long))
90
static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
91
 
92
static int dead_key_next = 0;
93
/*
94
 * In order to retrieve the shift_state (for the mouse server), either
95
 * the variable must be global, or a new procedure must be created to
96
 * return the value. I chose the former way.
97
 */
98
/*static*/ int shift_state = 0;
99
static int npadch = -1;                 /* -1 or number assembled on pad */
100
static unsigned char diacr = 0;
101
static char rep = 0;                     /* flag telling character repeat */
102
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
103
static struct tty_struct **ttytab;
104
static struct kbd_struct *kbd = kbd_table;
105
static struct tty_struct *tty = NULL;
106
 
107
extern void compute_shiftstate(void);
108
 
109
typedef void (*k_hand)(unsigned char value, char up_flag);
110
typedef void (k_handfn)(unsigned char value, char up_flag);
111
 
112
static k_handfn
113
        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
114
        do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_ignore;
115
 
116
static k_hand key_handler[16] = {
117
        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
118
        do_meta, do_ascii, do_lock, do_lowercase, do_slock,
119
        do_ignore, do_ignore, do_ignore
120
};
121
 
122
typedef void (*void_fnp)(void);
123
typedef void (void_fn)(void);
124
 
125
static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
126
        num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
127
        SAK, decr_console, incr_console, spawn_console, bare_num;
128
 
129
static void_fnp spec_fn_table[] = {
130
        do_null,        enter,          show_ptregs,    show_mem,
131
        show_state,     send_intr,      lastcons,       caps_toggle,
132
        num,            hold,           scroll_forw,    scroll_back,
133
        boot_it,        caps_on,        compose,        SAK,
134
        decr_console,   incr_console,   spawn_console,  bare_num
135
};
136
 
137
/* maximum values each key_handler can handle */
138
const int max_vals[] = {
139
        255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
140
        NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
141
        255, NR_ASCII - 1, NR_LOCK - 1, 255,
142
        NR_LOCK - 1
143
};
144
 
145
const int NR_TYPES = SIZE(max_vals);
146
 
147
static void put_queue(int);
148
static unsigned char handle_diacr(unsigned char);
149
 
150
/*
151
 * Many other routines do put_queue, but I think either
152
 * they produce ASCII, or they produce some user-assigned
153
 * string, and in both cases we might assume that it is
154
 * in utf-8 already.
155
 */
156
void to_utf8(ushort c) {
157
    if (c < 0x80)
158
        put_queue(c);                   /*  0*******  */
159
    else if (c < 0x800) {
160
        put_queue(0xc0 | (c >> 6));     /*  110***** 10******  */
161
        put_queue(0x80 | (c & 0x3f));
162
    } else {
163
        put_queue(0xe0 | (c >> 12));    /*  1110**** 10****** 10******  */
164
        put_queue(0x80 | ((c >> 6) & 0x3f));
165
        put_queue(0x80 | (c & 0x3f));
166
    }
167
    /* UTF-8 is defined for words of up to 31 bits,
168
       but we need only 16 bits here */
169
}
170
 
171
void process_keycode (int keycode)
172
{
173
        char up_flag;                            /* 0 or 0200 */
174
        char raw_mode;
175
 
176
        do_poke_blanked_console = 1;
177
        mark_bh(KEYBOARD_BH);
178
        add_keyboard_randomness(keycode);
179
 
180
        tty = ttytab[fg_console];
181
        kbd = kbd_table + fg_console;
182
        if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
183
                put_queue(keycode);
184
                /* we do not return yet, because we want to maintain
185
                   the key_down array, so that we have the correct
186
                   values when finishing RAW mode or when changing VT's */
187
        }
188
 
189
        /*
190
         * At this point the variable `keycode' contains the keycode.
191
         * Note: the keycode must not be 0.
192
         * We keep track of the up/down status of the key, and
193
         * return the keycode if in MEDIUMRAW mode.
194
         */
195
 
196
        up_flag = (keycode & 0200);
197
        keycode &= 0x7f;
198
        if (up_flag) {
199
                rep = 0;
200
                if(!clear_bit(keycode, key_down)) {
201
                    /* unexpected, but this can happen:
202
                       maybe this was a key release for a FOCUS 9000
203
                       PF key; if we want to see it, we have to clear
204
                       up_flag */
205
#ifndef __mc68000__
206
                    if (keycode >= SC_LIM || keycode == 85)
207
                      up_flag = 0;
208
#endif
209
                }
210
        } else
211
                rep = set_bit(keycode, key_down);
212
 
213
        if (raw_mode)
214
                return;
215
 
216
        if (kbd->kbdmode == VC_MEDIUMRAW) {
217
                /* soon keycodes will require more than one byte */
218
                put_queue(keycode + up_flag);
219
                return;
220
        }
221
 
222
        /*
223
         * Small change in philosophy: earlier we defined repetition by
224
         *       rep = keycode == prev_keycode;
225
         *       prev_keycode = keycode;
226
         * but now by the fact that the depressed key was down already.
227
         * Does this ever make a difference? Yes.
228
         */
229
 
230
        /*
231
         *  Repeat a key only if the input buffers are empty or the
232
         *  characters get echoed locally. This makes key repeat usable
233
         *  with slow applications and under heavy loads.
234
         */
235
        if (!rep ||
236
            (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
237
             (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
238
                u_short keysym;
239
                u_char type;
240
 
241
                /* the XOR below used to be an OR */
242
                int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
243
                ushort *key_map = key_maps[shift_final];
244
 
245
                if (key_map != NULL) {
246
                        keysym = key_map[keycode];
247
                        type = KTYP(keysym);
248
 
249
                        if (type >= 0xf0) {
250
                            type -= 0xf0;
251
                            if (type == KT_LETTER) {
252
                                type = KT_LATIN;
253
                                if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
254
                                    key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
255
                                    if (key_map)
256
                                      keysym = key_map[keycode];
257
                                }
258
                            }
259
                            (*key_handler[type])(keysym & 0xff, up_flag);
260
                            if (type != KT_SLOCK)
261
                              kbd->slockstate = 0;
262
                        } else {
263
                            /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
264
                            if (!up_flag)
265
                              to_utf8(keysym);
266
                        }
267
                } else {
268
                        /* maybe beep? */
269
                        /* we have at least to update shift_state */
270
#if 1                   /* how? two almost equivalent choices follow */
271
                        compute_shiftstate();
272
#else
273
                        keysym = U(plain_map[keycode]);
274
                        type = KTYP(keysym);
275
                        if (type == KT_SHIFT)
276
                          (*key_handler[type])(keysym & 0xff, up_flag);
277
#endif
278
                }
279
        }
280
}
281
 
282
static void put_queue(int ch)
283
{
284
        wake_up(&keypress_wait);
285
        if (tty) {
286
                tty_insert_flip_char(tty, ch, 0);
287
                tty_schedule_flip(tty);
288
        }
289
}
290
 
291
static void puts_queue(char *cp)
292
{
293
        wake_up(&keypress_wait);
294
        if (!tty)
295
                return;
296
 
297
        while (*cp) {
298
                tty_insert_flip_char(tty, *cp, 0);
299
                cp++;
300
        }
301
        tty_schedule_flip(tty);
302
}
303
 
304
static void applkey(int key, char mode)
305
{
306
        static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
307
 
308
        buf[1] = (mode ? 'O' : '[');
309
        buf[2] = key;
310
        puts_queue(buf);
311
}
312
 
313
static void enter(void)
314
{
315
        put_queue(13);
316
        if (vc_kbd_mode(kbd,VC_CRLF))
317
                put_queue(10);
318
}
319
 
320
static void caps_toggle(void)
321
{
322
        if (rep)
323
                return;
324
        chg_vc_kbd_led(kbd, VC_CAPSLOCK);
325
}
326
 
327
static void caps_on(void)
328
{
329
        if (rep)
330
                return;
331
        set_vc_kbd_led(kbd, VC_CAPSLOCK);
332
}
333
 
334
struct pt_regs *pt_regs;
335
 
336
static void show_ptregs(void)
337
{
338
        if (pt_regs)
339
                show_regs(pt_regs);
340
        return;
341
}
342
 
343
static void hold(void)
344
{
345
        if (rep || !tty)
346
                return;
347
 
348
        /*
349
         * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
350
         * these routines are also activated by ^S/^Q.
351
         * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
352
         */
353
        if (tty->stopped)
354
                start_tty(tty);
355
        else
356
                stop_tty(tty);
357
}
358
 
359
static void num(void)
360
{
361
        if (vc_kbd_mode(kbd,VC_APPLIC))
362
                applkey('P', 1);
363
        else
364
                bare_num();
365
}
366
 
367
/*
368
 * Bind this to Shift-NumLock if you work in application keypad mode
369
 * but want to be able to change the NumLock flag.
370
 * Bind this to NumLock if you prefer that the NumLock key always
371
 * changes the NumLock flag.
372
 */
373
static void bare_num(void)
374
{
375
        if (!rep)
376
                chg_vc_kbd_led(kbd,VC_NUMLOCK);
377
}
378
 
379
static void lastcons(void)
380
{
381
        /* switch to the last used console, ChN */
382
        set_console(last_console);
383
}
384
 
385
static void decr_console(void)
386
{
387
        int i;
388
 
389
        for (i = fg_console-1; i != fg_console; i--) {
390
                if (i == -1)
391
                        i = MAX_NR_CONSOLES-1;
392
                if (vc_cons_allocated(i))
393
                        break;
394
        }
395
        set_console(i);
396
}
397
 
398
static void incr_console(void)
399
{
400
        int i;
401
 
402
        for (i = fg_console+1; i != fg_console; i++) {
403
                if (i == MAX_NR_CONSOLES)
404
                        i = 0;
405
                if (vc_cons_allocated(i))
406
                        break;
407
        }
408
        set_console(i);
409
}
410
 
411
static void send_intr(void)
412
{
413
        if (!tty)
414
                return;
415
        tty_insert_flip_char(tty, 0, TTY_BREAK);
416
        tty_schedule_flip(tty);
417
}
418
 
419
static void scroll_forw(void)
420
{
421
        scrollfront(0);
422
}
423
 
424
static void scroll_back(void)
425
{
426
        scrollback(0);
427
}
428
 
429
static void boot_it(void)
430
{
431
        ctrl_alt_del();
432
}
433
 
434
static void compose(void)
435
{
436
        dead_key_next = 1;
437
}
438
 
439
int spawnpid, spawnsig;
440
 
441
static void spawn_console(void)
442
{
443
        if (spawnpid)
444
           if(kill_proc(spawnpid, spawnsig, 1))
445
             spawnpid = 0;
446
}
447
 
448
static void SAK(void)
449
{
450
        do_SAK(tty);
451
#if 0
452
        /*
453
         * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
454
         * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
455
         * handling.
456
         *
457
         * We should do this some day --- the whole point of a secure
458
         * attention key is that it should be guaranteed to always
459
         * work.
460
         */
461
        reset_vc(fg_console);
462
        do_unblank_screen();    /* not in interrupt routine? */
463
#endif
464
}
465
 
466
static void do_ignore(unsigned char value, char up_flag)
467
{
468
}
469
 
470
static void do_null()
471
{
472
        compute_shiftstate();
473
}
474
 
475
static void do_spec(unsigned char value, char up_flag)
476
{
477
        if (up_flag)
478
                return;
479
        if (value >= SIZE(spec_fn_table))
480
                return;
481
        spec_fn_table[value]();
482
}
483
 
484
static void do_lowercase(unsigned char value, char up_flag)
485
{
486
        printk("keyboard.c: do_lowercase was called - impossible\n");
487
}
488
 
489
static void do_self(unsigned char value, char up_flag)
490
{
491
        if (up_flag)
492
                return;         /* no action, if this is a key release */
493
 
494
        if (diacr)
495
                value = handle_diacr(value);
496
 
497
        if (dead_key_next) {
498
                dead_key_next = 0;
499
                diacr = value;
500
                return;
501
        }
502
 
503
        put_queue(value);
504
}
505
 
506
#define A_GRAVE  '`'
507
#define A_ACUTE  '\''
508
#define A_CFLEX  '^'
509
#define A_TILDE  '~'
510
#define A_DIAER  '"'
511
#define A_CEDIL  ','
512
static unsigned char ret_diacr[NR_DEAD] =
513
        {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
514
 
515
/* If a dead key pressed twice, output a character corresponding to it, */
516
/* otherwise just remember the dead key.                                */
517
 
518
static void do_dead(unsigned char value, char up_flag)
519
{
520
        if (up_flag)
521
                return;
522
 
523
        value = ret_diacr[value];
524
        if (diacr == value) {   /* pressed twice */
525
                diacr = 0;
526
                put_queue(value);
527
                return;
528
        }
529
        diacr = value;
530
}
531
 
532
 
533
/* If space is pressed, return the character corresponding the pending  */
534
/* dead key, otherwise try to combine the two.                          */
535
 
536
unsigned char handle_diacr(unsigned char ch)
537
{
538
        int d = diacr;
539
        int i;
540
 
541
        diacr = 0;
542
        if (ch == ' ')
543
                return d;
544
 
545
        for (i = 0; i < accent_table_size; i++) {
546
                if (accent_table[i].diacr == d && accent_table[i].base == ch)
547
                        return accent_table[i].result;
548
        }
549
 
550
        put_queue(d);
551
        return ch;
552
}
553
 
554
static void do_cons(unsigned char value, char up_flag)
555
{
556
        if (up_flag)
557
                return;
558
        set_console(value);
559
}
560
 
561
static void do_fn(unsigned char value, char up_flag)
562
{
563
        if (up_flag)
564
                return;
565
        if (value < SIZE(func_table)) {
566
                if (func_table[value])
567
                        puts_queue(func_table[value]);
568
        } else
569
                printk("do_fn called with value=%d\n", value);
570
}
571
 
572
static void do_pad(unsigned char value, char up_flag)
573
{
574
        static const char *pad_chars = "0123456789+-*/\015,.?";
575
        static const char *app_map = "pqrstuvwxylSRQMnn?";
576
 
577
        if (up_flag)
578
                return;         /* no action, if this is a key release */
579
 
580
        /* kludge... shift forces cursor/number keys */
581
        if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
582
                applkey(app_map[value], 1);
583
                return;
584
        }
585
 
586
        if (!vc_kbd_led(kbd,VC_NUMLOCK))
587
                switch (value) {
588
                        case KVAL(K_PCOMMA):
589
                        case KVAL(K_PDOT):
590
                                do_fn(KVAL(K_REMOVE), 0);
591
                                return;
592
                        case KVAL(K_P0):
593
                                do_fn(KVAL(K_INSERT), 0);
594
                                return;
595
                        case KVAL(K_P1):
596
                                do_fn(KVAL(K_SELECT), 0);
597
                                return;
598
                        case KVAL(K_P2):
599
                                do_cur(KVAL(K_DOWN), 0);
600
                                return;
601
                        case KVAL(K_P3):
602
                                do_fn(KVAL(K_PGDN), 0);
603
                                return;
604
                        case KVAL(K_P4):
605
                                do_cur(KVAL(K_LEFT), 0);
606
                                return;
607
                        case KVAL(K_P6):
608
                                do_cur(KVAL(K_RIGHT), 0);
609
                                return;
610
                        case KVAL(K_P7):
611
                                do_fn(KVAL(K_FIND), 0);
612
                                return;
613
                        case KVAL(K_P8):
614
                                do_cur(KVAL(K_UP), 0);
615
                                return;
616
                        case KVAL(K_P9):
617
                                do_fn(KVAL(K_PGUP), 0);
618
                                return;
619
                        case KVAL(K_P5):
620
                                applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
621
                                return;
622
                }
623
 
624
        put_queue(pad_chars[value]);
625
        if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
626
                put_queue(10);
627
}
628
 
629
static void do_cur(unsigned char value, char up_flag)
630
{
631
        static const char *cur_chars = "BDCA";
632
        if (up_flag)
633
                return;
634
 
635
        applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
636
}
637
 
638
static void do_shift(unsigned char value, char up_flag)
639
{
640
        int old_state = shift_state;
641
 
642
        if (rep)
643
                return;
644
 
645
        /* Mimic typewriter:
646
           a CapsShift key acts like Shift but undoes CapsLock */
647
        if (value == KVAL(K_CAPSSHIFT)) {
648
                value = KVAL(K_SHIFT);
649
                if (!up_flag)
650
                        clr_vc_kbd_led(kbd, VC_CAPSLOCK);
651
        }
652
 
653
        if (up_flag) {
654
                /* handle the case that two shift or control
655
                   keys are depressed simultaneously */
656
                if (k_down[value])
657
                        k_down[value]--;
658
        } else
659
                k_down[value]++;
660
 
661
        if (k_down[value])
662
                shift_state |= (1 << value);
663
        else
664
                shift_state &= ~ (1 << value);
665
 
666
        /* kludge */
667
        if (up_flag && shift_state != old_state && npadch != -1) {
668
                if (kbd->kbdmode == VC_UNICODE)
669
                  to_utf8(npadch & 0xffff);
670
                else
671
                  put_queue(npadch & 0xff);
672
                npadch = -1;
673
        }
674
}
675
 
676
/* called after returning from RAW mode or when changing consoles -
677
   recompute k_down[] and shift_state from key_down[] */
678
/* maybe called when keymap is undefined, so that shiftkey release is seen */
679
void compute_shiftstate(void)
680
{
681
        int i, j, k, sym, val;
682
 
683
        shift_state = 0;
684
        for(i=0; i < SIZE(k_down); i++)
685
          k_down[i] = 0;
686
 
687
        for(i=0; i < SIZE(key_down); i++)
688
          if(key_down[i]) {     /* skip this word if not a single bit on */
689
            k = i*BITS_PER_LONG;
690
            for(j=0; j<BITS_PER_LONG; j++,k++)
691
              if(test_bit(k, key_down)) {
692
                sym = U(plain_map[k]);
693
                if(KTYP(sym) == KT_SHIFT) {
694
                  val = KVAL(sym);
695
                  if (val == KVAL(K_CAPSSHIFT))
696
                    val = KVAL(K_SHIFT);
697
                  k_down[val]++;
698
                  shift_state |= (1<<val);
699
                }
700
              }
701
          }
702
}
703
 
704
static void do_meta(unsigned char value, char up_flag)
705
{
706
        if (up_flag)
707
                return;
708
 
709
        if (vc_kbd_mode(kbd, VC_META)) {
710
                put_queue('\033');
711
                put_queue(value);
712
        } else
713
                put_queue(value | 0x80);
714
}
715
 
716
static void do_ascii(unsigned char value, char up_flag)
717
{
718
        int base;
719
 
720
        if (up_flag)
721
                return;
722
 
723
        if (value < 10)    /* decimal input of code, while Alt depressed */
724
            base = 10;
725
        else {       /* hexadecimal input of code, while AltGr depressed */
726
            value -= 10;
727
            base = 16;
728
        }
729
 
730
        if (npadch == -1)
731
                npadch = value;
732
        else
733
                npadch = npadch * base + value;
734
}
735
 
736
static void do_lock(unsigned char value, char up_flag)
737
{
738
        if (up_flag || rep)
739
                return;
740
        chg_vc_kbd_lock(kbd, value);
741
}
742
 
743
static void do_slock(unsigned char value, char up_flag)
744
{
745
        if (up_flag || rep)
746
                return;
747
        chg_vc_kbd_slock(kbd, value);
748
}
749
 
750
/*
751
 * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
752
 * or (ii) whatever pattern of lights people want to show using KDSETLED,
753
 * or (iii) specified bits of specified words in kernel memory.
754
 */
755
 
756
static unsigned char ledstate = 0xff; /* undefined */
757
static unsigned char ledioctl;
758
 
759
unsigned char getledstate(void) {
760
    return ledstate;
761
}
762
 
763
void setledstate(struct kbd_struct *kbd, unsigned int led) {
764
    if (!(led & ~7)) {
765
        ledioctl = led;
766
        kbd->ledmode = LED_SHOW_IOCTL;
767
    } else
768
        kbd->ledmode = LED_SHOW_FLAGS;
769
    set_leds();
770
}
771
 
772
static struct ledptr {
773
    unsigned int *addr;
774
    unsigned int mask;
775
    unsigned char valid:1;
776
} ledptrs[3];
777
 
778
void register_leds(int console, unsigned int led,
779
                   unsigned int *addr, unsigned int mask) {
780
    struct kbd_struct *kbd = kbd_table + console;
781
    if (led < 3) {
782
        ledptrs[led].addr = addr;
783
        ledptrs[led].mask = mask;
784
        ledptrs[led].valid = 1;
785
        kbd->ledmode = LED_SHOW_MEM;
786
    } else
787
        kbd->ledmode = LED_SHOW_FLAGS;
788
}
789
 
790
static inline unsigned char getleds(void){
791
    struct kbd_struct *kbd = kbd_table + fg_console;
792
    unsigned char leds;
793
 
794
    if (kbd->ledmode == LED_SHOW_IOCTL)
795
      return ledioctl;
796
    leds = kbd->ledflagstate;
797
    if (kbd->ledmode == LED_SHOW_MEM) {
798
        if (ledptrs[0].valid) {
799
            if (*ledptrs[0].addr & ledptrs[0].mask)
800
              leds |= 1;
801
            else
802
              leds &= ~1;
803
        }
804
        if (ledptrs[1].valid) {
805
            if (*ledptrs[1].addr & ledptrs[1].mask)
806
              leds |= 2;
807
            else
808
              leds &= ~2;
809
        }
810
        if (ledptrs[2].valid) {
811
            if (*ledptrs[2].addr & ledptrs[2].mask)
812
              leds |= 4;
813
            else
814
              leds &= ~4;
815
        }
816
    }
817
    return leds;
818
}
819
 
820
/*
821
 * This routine is the bottom half of the keyboard interrupt
822
 * routine, and runs with all interrupts enabled. It does
823
 * console changing, led setting and copy_to_cooked, which can
824
 * take a reasonably long time.
825
 *
826
 * Aside from timing (which isn't really that important for
827
 * keyboard interrupts as they happen often), using the software
828
 * interrupt routines for this thing allows us to easily mask
829
 * this when we don't want any of the above to happen. Not yet
830
 * used, but this allows for easy and efficient race-condition
831
 * prevention later on.
832
 */
833
static void kbd_bh(void)
834
{
835
        unsigned char leds = getleds();
836
 
837
        if (leds != ledstate) {
838
                ledstate = leds;
839
                if (mach_kbd_leds)
840
                        mach_kbd_leds(leds);
841
        }
842
}
843
 
844
int kbd_init(void)
845
{
846
        int i;
847
        struct kbd_struct kbd0;
848
        extern struct tty_driver console_driver;
849
 
850
        kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
851
        kbd0.ledmode = LED_SHOW_FLAGS;
852
        kbd0.lockstate = KBD_DEFLOCK;
853
        kbd0.slockstate = 0;
854
        kbd0.modeflags = KBD_DEFMODE;
855
        kbd0.kbdmode = VC_XLATE;
856
 
857
        for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
858
                kbd_table[i] = kbd0;
859
 
860
        ttytab = console_driver.table;
861
 
862
        init_bh(KEYBOARD_BH, kbd_bh);
863
        mark_bh(KEYBOARD_BH);
864
 
865
        mach_keyb_init ();
866
 
867
        return 0;
868
}

powered by: WebSVN 2.1.0

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