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