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

4.104.115
Last change on this file since debbc9e was 084369e, checked in by Joel Sherrill <joel.sherrill@…>, on 09/22/08 at 21:49:43

2008-09-22 Joel Sherrill <joel.sherrill@…>

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