This source file includes following definitions.
- kb_wait
- keyboard_interrupt
- put_queue
- puts_queue
- applkey
- enter
- caps_toggle
- show_ptregs
- hold
- num
- lastcons
- send_intr
- do_spec
- do_self
- do_dead
- handle_diacr
- do_cons
- do_fn
- do_pad
- do_cur
- do_shift
- send_data
- kbd_bh
- hard_reset_now
- kbd_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #define KEYBOARD_IRQ 1
15
16 #include <linux/sched.h>
17 #include <linux/tty.h>
18 #include <linux/mm.h>
19 #include <linux/ptrace.h>
20 #include <linux/keyboard.h>
21 #include <linux/interrupt.h>
22 #include <linux/config.h>
23 #include <linux/signal.h>
24
25 #ifndef KBD_DEFFLAGS
26 #ifdef CONFIG_KBD_META
27 #define KBD_DEFFLAGS ((1 << VC_NUMLOCK) | (1 << VC_REPEAT) | (1 << VC_META))
28 #else
29 #define KBD_DEFFLAGS ((1 << VC_NUMLOCK) | (1 << VC_REPEAT))
30 #endif
31 #endif
32
33 #define SHIFT_KEYS ((1 << KG_LSHIFT) | (1 << KG_RSHIFT))
34 #define CTRL_KEYS ((1 << KG_LCTRL) | (1 << KG_RCTRL))
35 #define ALT_KEYS ((1 << KG_LALT) | (1 << KG_RALT))
36 #define ALTGR_KEYS ((1 << KG_LALTGR) | (1 << KG_RALTGR))
37
38
39
40
41
42
43
44 #define REALLY_SLOW_IO
45 #define SLOW_IO_BY_JUMPING
46 #include <asm/io.h>
47 #include <asm/system.h>
48
49 extern void do_keyboard_interrupt(void);
50 extern void ctrl_alt_del(void);
51 extern void change_console(unsigned int new_console);
52 extern void scrollback(int);
53 extern void scrollfront(int);
54
55 #define fake_keyboard_interrupt() \
56 __asm__ __volatile__("int $0x21")
57
58 unsigned long kbd_flags = 0;
59 unsigned long kbd_dead_keys = 0;
60 unsigned long kbd_prev_dead_keys = 0;
61
62 static int want_console = -1;
63 static int last_console = 0;
64 static char rep = 0;
65 struct kbd_struct kbd_table[NR_CONSOLES];
66 static struct kbd_struct * kbd = kbd_table;
67 static struct tty_struct * tty = NULL;
68
69 static volatile unsigned char acknowledge = 0;
70 static volatile unsigned char resend = 0;
71
72 typedef unsigned short u_word;
73 typedef void (*k_hand)(unsigned char value, char up_flag);
74
75 static void do_self(unsigned char value, char up_flag);
76 static void do_fn(unsigned char value, char up_flag);
77 static void do_spec(unsigned char value, char up_flag);
78 static void do_pad(unsigned char value, char up_flag);
79 static void do_dead(unsigned char value, char up_flag);
80 static void do_cons(unsigned char value, char up_flag);
81 static void do_cur(unsigned char value, char up_flag);
82 static void do_shift(unsigned char value, char up_flag);
83
84 static k_hand key_handler[] = {
85 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift
86 };
87
88
89 const u_char max_vals[] = {
90 255, 25, 13, 16, 4, 255, 3, 255
91 };
92
93 const int NR_TYPES = (sizeof(max_vals) / sizeof(u_char));
94
95 #define E0_BASE 96
96
97 static int shift_state = 0;
98 static int diacr = -1;
99 static int npadch = 0;
100
101 static void put_queue(int);
102 static unsigned int handle_diacr(unsigned int);
103
104 static struct pt_regs * pt_regs;
105
106 static inline void kb_wait(void)
107 {
108 int i;
109
110 for (i=0; i<0x10000; i++)
111 if ((inb_p(0x64) & 0x02) == 0)
112 break;
113 }
114
115 static void keyboard_interrupt(int int_pt_regs)
116 {
117 unsigned char scancode;
118 static unsigned char prev_scancode = 0;
119
120 pt_regs = (struct pt_regs *) int_pt_regs;
121 kbd_prev_dead_keys |= kbd_dead_keys;
122 if (!kbd_dead_keys)
123 kbd_prev_dead_keys = 0;
124 kbd_dead_keys = 0;
125 kb_wait();
126 if (!(inb_p(0x64) & 0x01))
127 goto end_kbd_intr;
128 scancode = inb(0x60);
129 mark_bh(KEYBOARD_BH);
130 if (scancode == 0xfa) {
131 acknowledge = 1;
132 goto end_kbd_intr;
133 } else if (scancode == 0xfe) {
134 resend = 1;
135 goto end_kbd_intr;
136 }
137 tty = TTY_TABLE(0);
138 kbd = kbd_table + fg_console;
139 if (vc_kbd_flag(kbd,VC_RAW)) {
140 kbd_flags = 0;
141 put_queue(scancode);
142 goto end_kbd_intr;
143 }
144 if (scancode == 0xe0) {
145 set_kbd_dead(KGD_E0);
146 goto end_kbd_intr;
147 } else if (scancode == 0xe1) {
148 set_kbd_dead(KGD_E1);
149 goto end_kbd_intr;
150 }
151
152
153
154
155
156
157
158 if (kbd_dead(KGD_E0) && (scancode == 0x2a || scancode == 0xaa))
159 goto end_kbd_intr;
160
161
162
163
164
165 rep = scancode == prev_scancode;
166 prev_scancode = scancode;
167 if (!rep ||
168 (vc_kbd_flag(kbd,VC_REPEAT) && tty &&
169 (L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q))))) {
170 static unsigned char e0_keys[] = {
171 0x1c,
172 0x1d,
173 0x35,
174 0x37,
175 0x38,
176 0x46,
177 0x47,
178 0x48,
179 0x49,
180 0x4b,
181 0x4d,
182 0x4f,
183 0x50,
184 0x51,
185 0x52,
186 0x53
187 };
188 u_word key_code;
189 char break_flag = scancode > 0x7f;
190
191 scancode &= 0x7f;
192 if (scancode >= E0_BASE) {
193 #if 0
194 printk("keyboard: scancode (%02x) not in range 00 - %2x\n", scancode, E0_BASE - 1);
195 #endif
196 scancode = 0;
197 }
198
199 if (kbd_dead(KGD_E0)) {
200 int i;
201 for (i = 0; i < sizeof(e0_keys); i++)
202 if (scancode == e0_keys[i]) {
203 scancode = E0_BASE + i;
204 i = -1;
205 break;
206 }
207 if (i != -1)
208 printk("keyboard: unknown scancode e0 %02x\n", scancode);
209 }
210
211 key_code = key_map[shift_state][scancode];
212 (*key_handler[key_code >> 8])(key_code & 0xff, break_flag);
213 }
214 end_kbd_intr:
215 }
216
217 static void put_queue(int ch)
218 {
219 struct tty_queue *qp;
220
221 wake_up(&keypress_wait);
222 if (!tty)
223 return;
224 qp = &tty->read_q;
225
226 if (LEFT(qp)) {
227 qp->buf[qp->head] = ch;
228 INC(qp->head);
229 wake_up_interruptible(&qp->proc_list);
230 }
231 }
232
233 static void puts_queue(char *cp)
234 {
235 struct tty_queue *qp;
236 char ch;
237
238
239 wake_up_interruptible(&keypress_wait);
240 if (!tty)
241 return;
242 qp = &tty->read_q;
243
244 while ((ch = *(cp++)) != 0) {
245 if (LEFT(qp)) {
246 qp->buf[qp->head] = ch;
247 INC(qp->head);
248 }
249 }
250 wake_up_interruptible(&qp->proc_list);
251 }
252
253 static void applkey(int key, char mode)
254 {
255 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
256
257 buf[1] = (mode ? 'O' : '[');
258 buf[2] = key;
259 puts_queue(buf);
260 }
261
262 static void enter(void)
263 {
264 put_queue(13);
265 if (vc_kbd_flag(kbd,VC_CRLF))
266 put_queue(10);
267 }
268
269 static void caps_toggle(void)
270 {
271 if (rep)
272 return;
273 set_kbd_flag(KG_CAPSLOCK);
274 chg_vc_kbd_flag(kbd,VC_CAPSLOCK);
275 }
276
277 static void show_ptregs(void)
278 {
279 if (!pt_regs)
280 return;
281 printk("\n");
282 printk("EIP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
283 if (pt_regs->cs & 3)
284 printk(" ESP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
285 printk(" EFLAGS: %08x\n",pt_regs->eflags);
286 printk("EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n",
287 pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
288 printk("ESI: %08x EDI: %08x EBP: %08x",
289 pt_regs->esi, pt_regs->edi, pt_regs->ebp);
290 printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
291 0xffff & pt_regs->ds,0xffff & pt_regs->es,
292 0xffff & pt_regs->fs,0xffff & pt_regs->gs);
293 }
294
295 static void hold(void)
296 {
297
298 if (kbd_flags & CTRL_KEYS) {
299 show_state();
300 return;
301 }
302
303 if (rep || !tty)
304 return;
305 if (vc_kbd_flag(kbd, VC_SCROLLOCK))
306
307 put_queue(START_CHAR(tty));
308 else
309
310 put_queue(STOP_CHAR(tty));
311 chg_vc_kbd_flag(kbd,VC_SCROLLOCK);
312 }
313
314 static void num(void)
315 {
316 #if 0
317 if (kbd_flags & CTRL_KEYS) {
318
319 chg_vc_kbd_flag(kbd,VC_PAUSE);
320 return;
321 }
322 #endif
323 if (vc_kbd_flag(kbd,VC_APPLIC)) {
324 applkey('P', 1);
325 return;
326 }
327 if (!rep)
328 chg_vc_kbd_flag(kbd,VC_NUMLOCK);
329 }
330
331 static void lastcons(void)
332 {
333
334 want_console = last_console;
335 }
336
337 static void send_intr(void)
338 {
339 if (tty)
340 put_queue(INTR_CHAR(tty));
341 }
342
343 static void do_spec(unsigned char value, char up_flag)
344 {
345 typedef void (*fnp)(void);
346 fnp fn_table[] = {
347 NULL, enter, show_ptregs, show_mem,
348 show_state, send_intr, lastcons, caps_toggle,
349 num, hold
350 };
351
352 if (value >= sizeof(fn_table)/sizeof(fnp))
353 return;
354 if (up_flag)
355 return;
356 if (!fn_table[value])
357 return;
358 fn_table[value]();
359 }
360
361 static void do_self(unsigned char value, char up_flag)
362 {
363 if (up_flag)
364 return;
365
366 value = handle_diacr(value);
367
368
369 if (vc_kbd_flag(kbd,VC_CAPSLOCK))
370 if ((value >= 'a' && value <= 'z')
371 || (value >= 224 && value <= 254)) {
372 value -= 32;
373 }
374
375 if (kbd_flags & CTRL_KEYS) {
376 if (value >= 64 && value < 127)
377 value &= 0x1f;
378 else if (value == ' ' || value == '2')
379 value = 0;
380 else if (value >= '3' && value < '8')
381 value -= 24;
382 else if (value == '?' || value == '8' || value == '/')
383 value = 127;
384 else if (value == '-' || value == '_')
385 value = 0x1f;
386 else
387 return;
388 }
389
390 if (kbd_flags & ALT_KEYS)
391 if (vc_kbd_flag(kbd,VC_META)) {
392 put_queue('\033');
393 put_queue(value);
394 } else
395 put_queue(value|0x80);
396 else
397 put_queue(value);
398 }
399
400 static unsigned char ret_diacr[] =
401 {'`', '\'', '^', '~', '"' };
402
403
404
405
406 static void do_dead(unsigned char value, char up_flag)
407 {
408 if (up_flag)
409 return;
410
411 if (diacr == value) {
412 diacr = -1;
413 put_queue(ret_diacr[value]);
414 return;
415 }
416 diacr = value;
417 }
418
419
420
421
422
423 unsigned int handle_diacr(unsigned int ch)
424 {
425 static unsigned char accent_table[5][64] = {
426 " \300BCD\310FGH\314JKLMN\322PQRST\331VWXYZ[\\]^_"
427 "`\340bcd\350fgh\354jklmn\362pqrst\371vwxyz{|}~",
428
429 " \301BCD\311FGH\315JKLMN\323PQRST\332VWX\335Z[\\]^_"
430 "`\341bcd\351fgh\355jklmn\363pqrst\372vwxyz{|}~",
431
432 " \302BCD\312FGH\316JKLMN\324PQRST\333VWXYZ[\\]^_"
433 "`\342bcd\352fgh\356jklmn\364pqrst\373vwxyz{|}~",
434
435 " \303BCDEFGHIJKLMN\325PQRSTUVWXYZ[\\]^_"
436 "`\343bcdefghijklm\361\365pqrstuvwxyz{|}~",
437
438 " \304BCD\313FGH\316JKLMN\326PQRST\334VWXYZ[\\]^_"
439 "`\344bcd\353fgh\357jklmn\366pqrst\374vwx\377z{|}~"
440 };
441 int d = diacr;
442
443 if (diacr == -1)
444 return ch;
445
446 diacr = -1;
447 if (ch == ' ')
448 return ret_diacr[d];
449
450 if (ch < 64 || ch > 122)
451 return ch;
452
453 return accent_table[d][ch - 64];
454 }
455
456 static void do_cons(unsigned char value, char up_flag)
457 {
458 if (up_flag)
459 return;
460 want_console = value;
461 }
462
463 static char *func_table[] = {
464 "\033[[A", "\033[[B", "\033[[C", "\033[[D", "\033[[E",
465 "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~",
466 "\033[23~", "\033[24~", "\033[25~", "\033[26~", "\033[28~",
467 "\033[29~", "\033[31~", "\033[32~", "\033[33~", "\033[34~",
468 "\033[1~",
469 "\033[2~",
470 "\033[3~",
471 "\033[4~",
472 "\033[5~",
473 "\033[6~"
474 };
475
476 static void do_fn(unsigned char value, char up_flag)
477 {
478 if (up_flag)
479 return;
480 if (kbd_flags & SHIFT_KEYS) {
481 if (value == KVAL(K_PGDN)) {
482 scrollfront(0);
483 return;
484 }
485 if (value == KVAL(K_PGUP)) {
486 scrollback(0);
487 return;
488 }
489 }
490 if (kbd_flags & ALT_KEYS) {
491 want_console = value;
492 return;
493 }
494 puts_queue(func_table[value]);
495 }
496
497 static void do_pad(unsigned char value, char up_flag)
498 {
499 static char *pad_chars = "0123456789+-*/\015,.";
500 static char *app_map = "pqrstuvwxylSRQMnn";
501
502 if (up_flag)
503 return;
504
505 if ((value == KVAL(K_PCOMMA) || value == KVAL(K_PDOT)) &&
506 (kbd_flags & CTRL_KEYS) && (kbd_flags & (ALT_KEYS | ALTGR_KEYS))) {
507 ctrl_alt_del();
508 return;
509 }
510
511 if ((kbd_flags & ALT_KEYS) && value <= 9) {
512 npadch = (npadch * 10 + value) % 1000;
513 return;
514 }
515
516
517 if (vc_kbd_flag(kbd,VC_APPLIC) && shift_state != 1) {
518 applkey(app_map[value], 1);
519 return;
520 }
521
522 if (!vc_kbd_flag(kbd,VC_NUMLOCK))
523 switch (value) {
524 case KVAL(K_PCOMMA):
525 case KVAL(K_PDOT):
526 do_fn(KVAL(K_REMOVE), 0);
527 return;
528 case KVAL(K_P0):
529 do_fn(KVAL(K_INSERT), 0);
530 return;
531 case KVAL(K_P1):
532 do_fn(KVAL(K_SELECT), 0);
533 return;
534 case KVAL(K_P2):
535 do_cur(KVAL(K_DOWN), 0);
536 return;
537 case KVAL(K_P3):
538 do_fn(KVAL(K_PGDN), 0);
539 return;
540 case KVAL(K_P4):
541 do_cur(KVAL(K_LEFT), 0);
542 return;
543 case KVAL(K_P6):
544 do_cur(KVAL(K_RIGHT), 0);
545 return;
546 case KVAL(K_P7):
547 do_fn(KVAL(K_FIND), 0);
548 return;
549 case KVAL(K_P8):
550 do_cur(KVAL(K_UP), 0);
551 return;
552 case KVAL(K_P9):
553 do_fn(KVAL(K_PGUP), 0);
554 return;
555 case KVAL(K_P5):
556 applkey('G', vc_kbd_flag(kbd,VC_APPLIC));
557 return;
558 }
559
560 put_queue(pad_chars[value]);
561 if (value == KVAL(K_PENTER) && vc_kbd_flag(kbd,VC_CRLF))
562 put_queue(10);
563 }
564
565 static void do_cur(unsigned char value, char up_flag)
566 {
567 static char *cur_chars = "BDCA";
568 if (up_flag)
569 return;
570
571 applkey(cur_chars[value], vc_kbd_flag(kbd,VC_CKMODE));
572 }
573
574 static void do_shift(unsigned char value, char up_flag)
575 {
576 shift_state = 0;
577 if (up_flag)
578 clr_kbd_flag(value);
579 else
580 set_kbd_flag(value);
581 if (kbd_flags & SHIFT_KEYS)
582 shift_state = 1;
583 if (kbd_flags & ALTGR_KEYS)
584 shift_state = 2;
585
586 if (up_flag && value == KG_LALT && npadch != 0) {
587 put_queue(npadch);
588 npadch=0;
589 }
590 }
591
592 #define C(x) ((KT_CONS<<8)|x)
593
594 u_word key_map[NR_KEYMAPS][NR_KEYS] = {
595 {
596 K_HOLE, 27, '1', '2', '3', '4', '5', '6',
597 '7', '8', '9', '0', '-', '=', 127, 9,
598 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
599 'o', 'p', '[', ']', K_ENTER, K_LCTRL, 'a', 's',
600 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
601 '\'', '`', K_LSHIFT, '\\', 'z', 'x', 'c', 'v',
602 'b', 'n', 'm', ',', '.', '/', K_RSHIFT, K_PSTAR,
603 K_ALT, ' ', K_CAPS, K_F1, K_F2, K_F3, K_F4, K_F5,
604 K_F6, K_F7, K_F8, K_F9, K_F10, K_NUM, K_HOLD, K_P7,
605 K_P8, K_P9, K_PMINUS, K_P4, K_P5, K_P6, K_PPLUS, K_P1,
606 K_P2, K_P3, K_P0, K_PDOT, K_CONS, K_HOLE, '<', K_F11,
607 K_F12, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
608
609 K_PENTER, K_RCTRL, K_PSLASH, 28, K_ALTGR, K_BREAK, K_FIND, K_UP,
610 K_PGUP, K_LEFT, K_RIGHT, K_SELECT, K_DOWN, K_PGDN, K_INSERT, K_REMOVE },
611 {
612 K_HOLE, 27, '!', '@', '#', '$', '%', '^',
613 '&', '*', '(', ')', '_', '+', 127, 9,
614 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
615 'O', 'P', '{', '}', K_ENTER, K_LCTRL, 'A', 'S',
616 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
617 '"', '~', K_LSHIFT, '|', 'Z', 'X', 'C', 'V',
618 'B', 'N', 'M', '<', '>', '?', K_RSHIFT, K_PSTAR,
619 K_ALT, 32, K_CAPS, K_F11, K_F12, K_F13, K_F14, K_F15,
620 K_F16, K_F17, K_F18, K_F19, K_F20, K_NUM, K_SH_MEM, K_P7,
621 K_P8, K_P9, K_PMINUS, K_P4, K_P5, K_P6, K_PPLUS, K_P1,
622 K_P2, K_P3, K_P0, K_PDOT, K_CONS, K_HOLE, '>', K_F11,
623 K_F12, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
624
625 K_PENTER, K_RCTRL, K_PSLASH, K_HOLE, K_ALTGR, K_BREAK, K_FIND, K_UP,
626 K_PGUP, K_LEFT, K_RIGHT, K_SELECT, K_DOWN, K_PGDN, K_INSERT, K_REMOVE },
627 {
628 K_HOLE, K_HOLE, K_HOLE, '@', K_HOLE, '$', K_HOLE, K_HOLE,
629 '{', '[', ']', '}', '\\', K_HOLE, K_HOLE, K_HOLE,
630 K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
631 K_HOLE, K_HOLE, K_HOLE, '~', K_ENTER, K_LCTRL, K_HOLE, K_HOLE,
632 K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
633 K_HOLE, K_HOLE, K_LSHIFT, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
634 K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_RSHIFT, K_HOLE,
635 K_ALT, K_HOLE, K_CAPS, C(12), C(13), C(14), C(15), C(16),
636 C(17), C(18), C(19), C(20), C(21), K_NUM, K_SH_REGS, K_P7,
637 K_P8, K_P9, K_PMINUS, K_P4, K_P5, K_P6, K_PPLUS, K_P1,
638 K_P2, K_P3, K_P0, K_PDOT, K_CONS, K_HOLE, '|', C(22),
639 C(23), K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE, K_HOLE,
640
641 K_PENTER, K_RCTRL, K_PSLASH, K_HOLE, K_ALTGR, K_BREAK, K_FIND, K_UP,
642 K_PGUP, K_LEFT, K_RIGHT, K_SELECT, K_DOWN, K_PGDN, K_INSERT, K_REMOVE }};
643
644
645
646
647
648
649 static int send_data(unsigned char data)
650 {
651 int retries = 3;
652 int i;
653
654 do {
655 kb_wait();
656 acknowledge = 0;
657 resend = 0;
658 outb_p(data, 0x60);
659 for(i=0; i<0x20000; i++) {
660 inb_p(0x64);
661 if (acknowledge)
662 return 1;
663 if (resend)
664 goto repeat;
665 }
666 return 0;
667 repeat:
668 } while (retries-- > 0);
669 return 0;
670 }
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685 static void kbd_bh(void * unused)
686 {
687 static unsigned char old_leds = -1;
688 unsigned char leds = kbd_table[fg_console].flags & LED_MASK;
689
690 if (leds != old_leds) {
691 old_leds = leds;
692 if (!send_data(0xed) || !send_data(leds))
693 send_data(0xf4);
694 }
695 if (want_console >= 0) {
696 if (want_console != fg_console) {
697 last_console = fg_console;
698 change_console(want_console);
699 }
700 want_console = -1;
701 }
702 do_keyboard_interrupt();
703 cli();
704 if (inb_p(0x64) & 0x01)
705 fake_keyboard_interrupt();
706 sti();
707 }
708
709 long no_idt[2] = {0, 0};
710
711
712
713
714
715
716 void hard_reset_now(void)
717 {
718 int i, j;
719 extern unsigned long pg0[1024];
720
721 sti();
722
723 pg0[0] = 7;
724 *((unsigned short *)0x472) = 0x1234;
725 for (;;) {
726 for (i=0; i<100; i++) {
727 kb_wait();
728 for(j = 0; j < 100000 ; j++)
729 ;
730 outb(0xfe,0x64);
731 }
732 __asm__("\tlidt _no_idt"::);
733 }
734 }
735
736 unsigned long kbd_init(unsigned long kmem_start)
737 {
738 int i;
739 struct kbd_struct * kbd;
740
741 kbd = kbd_table + 0;
742 for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
743 kbd->flags = KBD_DEFFLAGS;
744 kbd->default_flags = KBD_DEFFLAGS;
745 }
746 bh_base[KEYBOARD_BH].routine = kbd_bh;
747 request_irq(KEYBOARD_IRQ,keyboard_interrupt);
748 mark_bh(KEYBOARD_BH);
749 return kmem_start;
750 }