This source file includes following definitions.
- kb_wait
- send_cmd
- keyboard_interrupt
- put_queue
- puts_queue
- applkey
- enter
- caps_toggle
- caps_on
- show_ptregs
- hold
- pause
- num
- lastcons
- send_intr
- scrll_forw
- scrll_back
- boot_it
- compose
- SAK
- do_spec
- do_lowercase
- do_self
- do_dead
- handle_diacr
- do_cons
- do_fn
- do_pad
- do_cur
- do_shift
- compute_shiftstate
- do_meta
- do_ascii
- do_lock
- 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/interrupt.h>
18 #include <linux/tty.h>
19 #include <linux/tty_flip.h>
20 #include <linux/mm.h>
21 #include <linux/ptrace.h>
22 #include <linux/config.h>
23 #include <linux/signal.h>
24 #include <linux/string.h>
25
26 #include <asm/bitops.h>
27
28 #include "kbd_kern.h"
29 #include "diacr.h"
30 #include "vt_kern.h"
31
32 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
33
34 #define KBD_REPORT_ERR
35 #define KBD_REPORT_UNKN
36
37 #ifndef KBD_DEFMODE
38 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
39 #endif
40
41 #ifndef KBD_DEFLEDS
42
43
44
45
46 #define KBD_DEFLEDS 0
47 #endif
48
49 #ifndef KBD_DEFLOCK
50 #define KBD_DEFLOCK 0
51 #endif
52
53
54
55
56
57
58
59 #define REALLY_SLOW_IO
60 #define SLOW_IO_BY_JUMPING
61 #include <asm/io.h>
62 #include <asm/system.h>
63
64 extern void poke_blanked_console(void);
65 extern void ctrl_alt_del(void);
66 extern void change_console(unsigned int new_console);
67 extern void scrollback(int);
68 extern void scrollfront(int);
69
70 #define fake_keyboard_interrupt() \
71 __asm__ __volatile__("int $0x21")
72
73 unsigned char kbd_read_mask = 0x01;
74
75
76
77
78
79
80
81
82 static unsigned char k_down[NR_SHIFT] = {0, };
83
84 static unsigned long key_down[8] = { 0, };
85
86 static int want_console = -1;
87 static int last_console = 0;
88 static int dead_key_next = 0;
89 static int shift_state = 0;
90 static int npadch = -1;
91 static unsigned char diacr = 0;
92 static char rep = 0;
93 struct kbd_struct kbd_table[NR_CONSOLES];
94 static struct tty_struct **ttytab;
95 static struct kbd_struct * kbd = kbd_table;
96 static struct tty_struct * tty = NULL;
97
98
99 static volatile unsigned char acknowledge = 0;
100 static volatile unsigned char resend = 0;
101
102 typedef void (*k_hand)(unsigned char value, char up_flag);
103 typedef void (k_handfn)(unsigned char value, char up_flag);
104
105 static k_handfn
106 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
107 do_meta, do_ascii, do_lock, do_lowercase;
108
109 static k_hand key_handler[] = {
110 do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
111 do_meta, do_ascii, do_lock, do_lowercase
112 };
113
114
115 const int max_vals[] = {
116 255, NR_FUNC - 1, 15, 17, 4, 255, 3, NR_SHIFT,
117 255, 9, 3, 255
118 };
119
120 const int NR_TYPES = SIZE(max_vals);
121
122 static void put_queue(int);
123 static unsigned char handle_diacr(unsigned char);
124 static void SAK(void);
125
126
127 static struct pt_regs * pt_regs;
128
129 static inline void kb_wait(void)
130 {
131 int i;
132
133 for (i=0; i<0x10000; i++)
134 if ((inb_p(0x64) & 0x02) == 0)
135 break;
136 }
137
138 static inline void send_cmd(unsigned char c)
139 {
140 kb_wait();
141 outb(c,0x64);
142 }
143
144
145
146
147
148 #define E0_BASE 96
149
150 #define E0_KPENTER (E0_BASE+0)
151 #define E0_RCTRL (E0_BASE+1)
152 #define E0_KPSLASH (E0_BASE+2)
153 #define E0_PRSCR (E0_BASE+3)
154 #define E0_RALT (E0_BASE+4)
155 #define E0_BREAK (E0_BASE+5)
156 #define E0_HOME (E0_BASE+6)
157 #define E0_UP (E0_BASE+7)
158 #define E0_PGUP (E0_BASE+8)
159 #define E0_LEFT (E0_BASE+9)
160 #define E0_RIGHT (E0_BASE+10)
161 #define E0_END (E0_BASE+11)
162 #define E0_DOWN (E0_BASE+12)
163 #define E0_PGDN (E0_BASE+13)
164 #define E0_INS (E0_BASE+14)
165 #define E0_DEL (E0_BASE+15)
166
167 #define E0_MACRO (E0_BASE+16)
168
169 #define E0_F13 (E0_BASE+17)
170 #define E0_F14 (E0_BASE+18)
171 #define E0_HELP (E0_BASE+19)
172 #define E0_DO (E0_BASE+20)
173 #define E0_F17 (E0_BASE+21)
174 #define E0_KPMINPLUS (E0_BASE+22)
175
176 #define E1_PAUSE (E0_BASE+23)
177
178 static unsigned char e0_keys[128] = {
179 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,
183 0, 0, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0, 0,
185 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,
186 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,
187 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,
188 E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, E0_KPMINPLUS, E0_END,
189 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, E0_MACRO,
193 0, 0, 0, 0, 0, 0, 0, 0,
194 0, 0, 0, 0, 0, 0, 0, 0
195 };
196
197 static void keyboard_interrupt(int int_pt_regs)
198 {
199 unsigned char scancode;
200 static unsigned int prev_scancode = 0;
201 char up_flag;
202 char raw_mode;
203
204 pt_regs = (struct pt_regs *) int_pt_regs;
205 send_cmd(0xAD);
206 kb_wait();
207 if ((inb_p(0x64) & kbd_read_mask) != 0x01)
208 goto end_kbd_intr;
209 scancode = inb(0x60);
210 mark_bh(KEYBOARD_BH);
211 if (scancode == 0xfa) {
212 acknowledge = 1;
213 goto end_kbd_intr;
214 } else if (scancode == 0xfe) {
215 resend = 1;
216 goto end_kbd_intr;
217 } else if (scancode == 0) {
218 #ifdef KBD_REPORT_ERR
219 printk("keyboard buffer overflow\n");
220 #endif
221 goto end_kbd_intr;
222 } else if (scancode == 0xff) {
223 #ifdef KBD_REPORT_ERR
224 printk("keyboard error\n");
225 #endif
226 prev_scancode = 0;
227 goto end_kbd_intr;
228 }
229 tty = ttytab[fg_console];
230 kbd = kbd_table + fg_console;
231 if ((raw_mode = vc_kbd_mode(kbd,VC_RAW))) {
232 put_queue(scancode);
233
234
235
236 }
237 if (scancode == 0xe0 || scancode == 0xe1) {
238 prev_scancode = scancode;
239 goto end_kbd_intr;
240 }
241
242
243
244
245 up_flag = (scancode & 0200);
246 scancode &= 0x7f;
247
248 if (prev_scancode) {
249
250
251
252
253 if (prev_scancode != 0xe0) {
254 if (prev_scancode == 0xe1 && scancode == 0x1d) {
255 prev_scancode = 0x100;
256 goto end_kbd_intr;
257 } else if (prev_scancode == 0x100 && scancode == 0x45) {
258 scancode = E1_PAUSE;
259 prev_scancode = 0;
260 } else {
261 printk("keyboard: unknown e1 escape sequence\n");
262 prev_scancode = 0;
263 goto end_kbd_intr;
264 }
265 } else {
266 prev_scancode = 0;
267
268
269
270
271
272
273
274
275
276
277
278
279
280 if (scancode == 0x2a || scancode == 0x36)
281 goto end_kbd_intr;
282
283 if (e0_keys[scancode])
284 scancode = e0_keys[scancode];
285 else if (!raw_mode) {
286 #ifdef KBD_REPORT_UNKN
287 printk("keyboard: unknown scancode e0 %02x\n", scancode);
288 #endif
289 goto end_kbd_intr;
290 }
291 }
292 } else if (scancode >= E0_BASE && !raw_mode) {
293 #ifdef KBD_REPORT_UNKN
294 printk("keyboard: scancode (%02x) not in range 00 - %2x\n",
295 scancode, E0_BASE - 1);
296 #endif
297 goto end_kbd_intr;
298 }
299
300
301
302
303
304
305
306
307
308 if (up_flag) {
309 clear_bit(scancode, key_down);
310 rep = 0;
311 } else
312 rep = set_bit(scancode, key_down);
313
314 if (raw_mode)
315 goto end_kbd_intr;
316
317 if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
318 put_queue(scancode + up_flag);
319 goto end_kbd_intr;
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 if (!rep ||
336 (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
337 (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
338 u_short key_code;
339 u_char type;
340
341
342 int shift_final = shift_state ^ kbd->lockstate;
343
344 key_code = key_map[shift_final][scancode];
345 type = KTYP(key_code);
346
347 if (type == KT_LETTER) {
348 type = KT_LATIN;
349 if (vc_kbd_led(kbd,VC_CAPSLOCK))
350 key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode];
351 }
352 (*key_handler[type])(key_code & 0xff, up_flag);
353 }
354
355 end_kbd_intr:
356 send_cmd(0xAE);
357 }
358
359 static void put_queue(int ch)
360 {
361 wake_up(&keypress_wait);
362 if (tty) {
363 tty_insert_flip_char(tty, ch, 0);
364 tty_schedule_flip(tty);
365 }
366 }
367
368 static void puts_queue(char *cp)
369 {
370 wake_up(&keypress_wait);
371 if (!tty)
372 return;
373
374 while (*cp) {
375 tty_insert_flip_char(tty, *cp, 0);
376 cp++;
377 }
378 tty_schedule_flip(tty);
379 }
380
381 static void applkey(int key, char mode)
382 {
383 static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
384
385 buf[1] = (mode ? 'O' : '[');
386 buf[2] = key;
387 puts_queue(buf);
388 }
389
390 static void enter(void)
391 {
392 put_queue(13);
393 if (vc_kbd_mode(kbd,VC_CRLF))
394 put_queue(10);
395 }
396
397 static void caps_toggle(void)
398 {
399 if (rep)
400 return;
401 chg_vc_kbd_led(kbd,VC_CAPSLOCK);
402 }
403
404 static void caps_on(void)
405 {
406 if (rep)
407 return;
408 set_vc_kbd_led(kbd,VC_CAPSLOCK);
409 }
410
411 static void show_ptregs(void)
412 {
413 if (!pt_regs)
414 return;
415 printk("\n");
416 printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
417 if (pt_regs->cs & 3)
418 printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
419 printk(" EFLAGS: %08lx\n",pt_regs->eflags);
420 printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
421 pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
422 printk("ESI: %08lx EDI: %08lx EBP: %08lx",
423 pt_regs->esi, pt_regs->edi, pt_regs->ebp);
424 printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
425 0xffff & pt_regs->ds,0xffff & pt_regs->es,
426 0xffff & pt_regs->fs,0xffff & pt_regs->gs);
427 }
428
429 static void hold(void)
430 {
431 if (rep || !tty)
432 return;
433
434
435
436
437
438
439 if (tty->stopped)
440 start_tty(tty);
441 else
442 stop_tty(tty);
443 }
444
445 #if 0
446
447 static void pause(void)
448 {
449 chg_vc_kbd_mode(kbd,VC_PAUSE);
450 }
451 #endif
452
453 static void num(void)
454 {
455 if (vc_kbd_mode(kbd,VC_APPLIC)) {
456 applkey('P', 1);
457 return;
458 }
459 if (!rep)
460 chg_vc_kbd_led(kbd,VC_NUMLOCK);
461 }
462
463 static void lastcons(void)
464 {
465
466 want_console = last_console;
467 }
468
469 static void send_intr(void)
470 {
471 if (!tty || (tty->termios && I_IGNBRK(tty)))
472 return;
473 tty_insert_flip_char(tty, 0, TTY_BREAK);
474 }
475
476 static void scrll_forw(void)
477 {
478 scrollfront(0);
479 }
480
481 static void scrll_back(void)
482 {
483 scrollback(0);
484 }
485
486 static void boot_it(void)
487 {
488 ctrl_alt_del();
489 }
490
491 static void compose(void)
492 {
493 dead_key_next = 1;
494 }
495
496 static void SAK(void)
497 {
498 do_SAK(tty);
499 #if 0
500
501
502
503
504
505
506
507
508
509 clr_vc_kbd_flag(kbd, VC_RAW);
510 clr_vc_kbd_flag(kbd, VC_MEDIUMRAW);
511 vt_cons[fg_console].vc_mode = KD_TEXT;
512 vt_cons[fg_console].vt_mode.mode = VT_AUTO;
513 vt_cons[fg_console].vt_mode.waitv = 0;
514 vt_cons[fg_console].vt_mode.relsig = 0;
515 vt_cons[fg_console].vt_mode.acqsig = 0;
516 vt_cons[fg_console].vt_mode.frsig = 0;
517 vt_cons[fg_console].vt_pid = -1;
518 vt_cons[fg_console].vt_newvt = -1;
519 unblank_screen();
520 #endif
521 }
522
523 static void do_spec(unsigned char value, char up_flag)
524 {
525 typedef void (*fnp)(void);
526 fnp fn_table[] = {
527 NULL, enter, show_ptregs, show_mem,
528 show_state, send_intr, lastcons, caps_toggle,
529 num, hold, scrll_forw, scrll_back,
530 boot_it, caps_on, compose, SAK
531 };
532
533 if (up_flag)
534 return;
535 if (value >= SIZE(fn_table))
536 return;
537 if (!fn_table[value])
538 return;
539 fn_table[value]();
540 }
541
542 static void do_lowercase(unsigned char value, char up_flag)
543 {
544 printk("keyboard.c: do_lowercase was called - impossible\n");
545 }
546
547 static void do_self(unsigned char value, char up_flag)
548 {
549 if (up_flag)
550 return;
551
552 if (diacr)
553 value = handle_diacr(value);
554
555 if (dead_key_next) {
556 dead_key_next = 0;
557 diacr = value;
558 return;
559 }
560
561 put_queue(value);
562 }
563
564 #define A_GRAVE '`'
565 #define A_ACUTE '\''
566 #define A_CFLEX '^'
567 #define A_TILDE '~'
568 #define A_DIAER '"'
569 static unsigned char ret_diacr[] =
570 {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
571
572
573
574
575 static void do_dead(unsigned char value, char up_flag)
576 {
577 if (up_flag)
578 return;
579
580 value = ret_diacr[value];
581 if (diacr == value) {
582 diacr = 0;
583 put_queue(value);
584 return;
585 }
586 diacr = value;
587 }
588
589
590
591
592
593 unsigned char handle_diacr(unsigned char ch)
594 {
595 int d = diacr;
596 int i;
597
598 diacr = 0;
599 if (ch == ' ')
600 return d;
601
602 for (i = 0; i < accent_table_size; i++) {
603 if (accent_table[i].diacr == d && accent_table[i].base == ch)
604 return accent_table[i].result;
605 }
606
607 put_queue(d);
608 return ch;
609 }
610
611 static void do_cons(unsigned char value, char up_flag)
612 {
613 if (up_flag)
614 return;
615 want_console = value;
616 }
617
618 static void do_fn(unsigned char value, char up_flag)
619 {
620 if (up_flag)
621 return;
622 if (value < SIZE(func_table))
623 puts_queue(func_table[value]);
624 else
625 printk("do_fn called with value=%d\n", value);
626 }
627
628 static void do_pad(unsigned char value, char up_flag)
629 {
630 static char *pad_chars = "0123456789+-*/\015,.?";
631 static char *app_map = "pqrstuvwxylSRQMnn?";
632
633 if (up_flag)
634 return;
635
636
637 if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
638 applkey(app_map[value], 1);
639 return;
640 }
641
642 if (!vc_kbd_led(kbd,VC_NUMLOCK))
643 switch (value) {
644 case KVAL(K_PCOMMA):
645 case KVAL(K_PDOT):
646 do_fn(KVAL(K_REMOVE), 0);
647 return;
648 case KVAL(K_P0):
649 do_fn(KVAL(K_INSERT), 0);
650 return;
651 case KVAL(K_P1):
652 do_fn(KVAL(K_SELECT), 0);
653 return;
654 case KVAL(K_P2):
655 do_cur(KVAL(K_DOWN), 0);
656 return;
657 case KVAL(K_P3):
658 do_fn(KVAL(K_PGDN), 0);
659 return;
660 case KVAL(K_P4):
661 do_cur(KVAL(K_LEFT), 0);
662 return;
663 case KVAL(K_P6):
664 do_cur(KVAL(K_RIGHT), 0);
665 return;
666 case KVAL(K_P7):
667 do_fn(KVAL(K_FIND), 0);
668 return;
669 case KVAL(K_P8):
670 do_cur(KVAL(K_UP), 0);
671 return;
672 case KVAL(K_P9):
673 do_fn(KVAL(K_PGUP), 0);
674 return;
675 case KVAL(K_P5):
676 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
677 return;
678 }
679
680 put_queue(pad_chars[value]);
681 if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
682 put_queue(10);
683 }
684
685 static void do_cur(unsigned char value, char up_flag)
686 {
687 static char *cur_chars = "BDCA";
688 if (up_flag)
689 return;
690
691 applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
692 }
693
694 static void do_shift(unsigned char value, char up_flag)
695 {
696 int old_state = shift_state;
697
698 if (rep)
699 return;
700
701
702 if (value == KVAL(K_CAPSSHIFT)) {
703 value = KVAL(K_SHIFT);
704 if (!up_flag)
705 clr_vc_kbd_led(kbd, VC_CAPSLOCK);
706 }
707
708 if (up_flag) {
709
710
711 if (k_down[value])
712 k_down[value]--;
713 } else
714 k_down[value]++;
715
716 if (k_down[value])
717 shift_state |= (1 << value);
718 else
719 shift_state &= ~ (1 << value);
720
721
722 if (up_flag && shift_state != old_state && npadch != -1) {
723 put_queue(npadch);
724 npadch = -1;
725 }
726 }
727
728
729
730 void compute_shiftstate(void)
731 {
732 int i, j, k, sym, val;
733
734 shift_state = 0;
735 for(i=0; i < SIZE(k_down); i++)
736 k_down[i] = 0;
737
738 for(i=0; i < SIZE(key_down); i++)
739 if(key_down[i]) {
740 k = (i<<5);
741 for(j=0; j<32; j++,k++)
742 if(test_bit(k, key_down)) {
743 sym = key_map[0][k];
744 if(KTYP(sym) == KT_SHIFT) {
745 val = KVAL(sym);
746 k_down[val]++;
747 shift_state |= (1<<val);
748 }
749 }
750 }
751 }
752
753 static void do_meta(unsigned char value, char up_flag)
754 {
755 if (up_flag)
756 return;
757
758 if (vc_kbd_mode(kbd, VC_META)) {
759 put_queue('\033');
760 put_queue(value);
761 } else
762 put_queue(value | 0x80);
763 }
764
765 static void do_ascii(unsigned char value, char up_flag)
766 {
767 if (up_flag)
768 return;
769
770 if (npadch == -1)
771 npadch = value;
772 else
773 npadch = (npadch * 10 + value) % 1000;
774 }
775
776 static void do_lock(unsigned char value, char up_flag)
777 {
778 if (up_flag || rep)
779 return;
780 chg_vc_kbd_lock(kbd, value);
781 }
782
783
784
785
786
787
788 static int send_data(unsigned char data)
789 {
790 int retries = 3;
791 int i;
792
793 do {
794 kb_wait();
795 acknowledge = 0;
796 resend = 0;
797 outb_p(data, 0x60);
798 for(i=0; i<0x20000; i++) {
799 inb_p(0x64);
800 if (acknowledge)
801 return 1;
802 if (resend)
803 break;
804 }
805 if (!resend)
806 return 0;
807 } while (retries-- > 0);
808 return 0;
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 static void kbd_bh(void * unused)
825 {
826 static unsigned char old_leds = 0xff;
827 unsigned char leds = kbd_table[fg_console].ledstate;
828
829 if (leds != old_leds) {
830 old_leds = leds;
831 if (!send_data(0xed) || !send_data(leds))
832 send_data(0xf4);
833 }
834 if (want_console >= 0) {
835 if (want_console != fg_console) {
836 last_console = fg_console;
837 change_console(want_console);
838 }
839 want_console = -1;
840 }
841 poke_blanked_console();
842 cli();
843 if ((inb_p(0x64) & kbd_read_mask) == 0x01)
844 fake_keyboard_interrupt();
845 sti();
846 }
847
848 long no_idt[2] = {0, 0};
849
850
851
852
853
854
855 void hard_reset_now(void)
856 {
857 int i, j;
858 extern unsigned long pg0[1024];
859
860 sti();
861
862 pg0[0] = 7;
863 *((unsigned short *)0x472) = 0x1234;
864 for (;;) {
865 for (i=0; i<100; i++) {
866 kb_wait();
867 for(j = 0; j < 100000 ; j++)
868 ;
869 outb(0xfe,0x64);
870 }
871 __asm__("\tlidt _no_idt");
872 }
873 }
874
875 unsigned long kbd_init(unsigned long kmem_start)
876 {
877 int i;
878 struct kbd_struct * kbd;
879 extern struct tty_driver console_driver;
880
881 kbd = kbd_table + 0;
882 for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
883 kbd->ledstate = KBD_DEFLEDS;
884 kbd->default_ledstate = KBD_DEFLEDS;
885 kbd->lockstate = KBD_DEFLOCK;
886 kbd->modeflags = KBD_DEFMODE;
887 }
888 ttytab = console_driver.table;
889
890 bh_base[KEYBOARD_BH].routine = kbd_bh;
891 request_irq(KEYBOARD_IRQ,keyboard_interrupt);
892 mark_bh(KEYBOARD_BH);
893 return kmem_start;
894 }