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

4.104.114.84.95
Last change on this file since 1235164 was 1235164, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 10, 2007 at 2:27:46 PM

2007-09-10 Joel Sherrill <joel.sherrill@…>

  • console/keyboard.c: Replaced tabs with spaces.
  • Property mode set to 100644
File size: 19.6 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.