source: rtems/c/src/lib/libbsp/i386/pc386/console/keyboard.c @ e9b4f29a

4.104.114.84.95
Last change on this file since e9b4f29a was 63a4538, checked in by Ralf Corsepius <ralf.corsepius@…>, on 07/06/05 at 11:34:10

2005-07-06 Ralf Corsepius <ralf.corsepius@…>

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