]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/kbd.c
Initial revision
[karo-tx-uboot.git] / board / mpl / common / kbd.c
1 /*
2  * (C) Copyright 2001
3  * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  *
24  * Source partly derived from:
25  * linux/drivers/char/pc_keyb.c
26  *
27  *
28  */
29 #include <common.h>
30 #include <asm/processor.h>
31 #include <devices.h>
32 #include "isa.h"
33 #include "kbd.h"
34
35
36 unsigned char kbd_read_status(void);
37 unsigned char kbd_read_input(void);
38 void kbd_send_data(unsigned char data);
39 void disable_8259A_irq(unsigned int irq);
40 void enable_8259A_irq(unsigned int irq);
41
42 /* used only by send_data - set by keyboard_interrupt */
43
44
45 #undef KBG_DEBUG
46
47 #ifdef KBG_DEBUG
48 #define PRINTF(fmt,args...)     printf (fmt ,##args)
49 #else
50 #define PRINTF(fmt,args...)
51 #endif
52
53 #define KBD_STAT_KOBF           0x01
54 #define KBD_STAT_IBF            0x02
55 #define KBD_STAT_SYS            0x04
56 #define KBD_STAT_CD                     0x08
57 #define KBD_STAT_LOCK           0x10
58 #define KBD_STAT_MOBF           0x20
59 #define KBD_STAT_TI_OUT 0x40
60 #define KBD_STAT_PARERR 0x80
61
62 #define KBD_INIT_TIMEOUT 1000           /* Timeout in ms for initializing the keyboard */
63 #define KBC_TIMEOUT 250                 /* Timeout in ms for sending to keyboard controller */
64 #define KBD_TIMEOUT 2000                /* Timeout in ms for keyboard command acknowledge */
65 /*
66  *      Keyboard Controller Commands
67  */
68
69 #define KBD_CCMD_READ_MODE                      0x20    /* Read mode bits */
70 #define KBD_CCMD_WRITE_MODE                     0x60    /* Write mode bits */
71 #define KBD_CCMD_GET_VERSION            0xA1    /* Get controller version */
72 #define KBD_CCMD_MOUSE_DISABLE  0xA7    /* Disable mouse interface */
73 #define KBD_CCMD_MOUSE_ENABLE           0xA8    /* Enable mouse interface */
74 #define KBD_CCMD_TEST_MOUSE                     0xA9    /* Mouse interface test */
75 #define KBD_CCMD_SELF_TEST                      0xAA    /* Controller self test */
76 #define KBD_CCMD_KBD_TEST                               0xAB    /* Keyboard interface test */
77 #define KBD_CCMD_KBD_DISABLE            0xAD    /* Keyboard interface disable */
78 #define KBD_CCMD_KBD_ENABLE                     0xAE    /* Keyboard interface enable */
79 #define KBD_CCMD_WRITE_AUX_OBUF 0xD3    /* Write to output buffer as if
80                                            initiated by the auxiliary device */
81 #define KBD_CCMD_WRITE_MOUSE            0xD4    /* Write the following byte to the mouse */
82
83 /*
84  *      Keyboard Commands
85  */
86
87 #define KBD_CMD_SET_LEDS                                0xED    /* Set keyboard leds */
88 #define KBD_CMD_SET_RATE                                0xF3    /* Set typematic rate */
89 #define KBD_CMD_ENABLE                                  0xF4    /* Enable scanning */
90 #define KBD_CMD_DISABLE                                 0xF5    /* Disable scanning */
91 #define KBD_CMD_RESET                                           0xFF    /* Reset */
92
93 /*
94  *      Keyboard Replies
95  */
96
97 #define KBD_REPLY_POR                                           0xAA    /* Power on reset */
98 #define KBD_REPLY_ACK                                           0xFA    /* Command ACK */
99 #define KBD_REPLY_RESEND                                0xFE    /* Command NACK, send the cmd again */
100
101 /*
102  *      Status Register Bits
103  */
104
105 #define KBD_STAT_OBF                                            0x01    /* Keyboard output buffer full */
106 #define KBD_STAT_IBF                                            0x02    /* Keyboard input buffer full */
107 #define KBD_STAT_SELFTEST                               0x04    /* Self test successful */
108 #define KBD_STAT_CMD                                            0x08    /* Last write was a command write (0=data) */
109 #define KBD_STAT_UNLOCKED                               0x10    /* Zero if keyboard locked */
110 #define KBD_STAT_MOUSE_OBF                      0x20    /* Mouse output buffer full */
111 #define KBD_STAT_GTO                                            0x40    /* General receive/xmit timeout */
112 #define KBD_STAT_PERR                                   0x80    /* Parity error */
113
114 #define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
115
116 /*
117  *      Controller Mode Register Bits
118  */
119
120 #define KBD_MODE_KBD_INT                                0x01    /* Keyboard data generate IRQ1 */
121 #define KBD_MODE_MOUSE_INT                      0x02    /* Mouse data generate IRQ12 */
122 #define KBD_MODE_SYS                                            0x04    /* The system flag (?) */
123 #define KBD_MODE_NO_KEYLOCK                     0x08    /* The keylock doesn't affect the keyboard if set */
124 #define KBD_MODE_DISABLE_KBD            0x10    /* Disable keyboard interface */
125 #define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
126 #define KBD_MODE_KCC                                            0x40    /* Scan code conversion to PC format */
127 #define KBD_MODE_RFU                                            0x80
128
129
130 #define KDB_DATA_PORT                   0x60
131 #define KDB_COMMAND_PORT        0x64
132
133 #define         LED_SCR         0x01    /* scroll lock led */
134 #define         LED_CAP         0x04    /* caps lock led */
135 #define         LED_NUM         0x02    /* num lock led */
136
137 #define         KBD_BUFFER_LEN 0x20  /* size of the keyboardbuffer */
138
139
140
141
142 static volatile char kbd_buffer[KBD_BUFFER_LEN];
143 static volatile int in_pointer = 0;
144 static volatile int out_pointer = 0;
145
146
147 static unsigned char num_lock = 0;
148 static unsigned char caps_lock = 0;
149 static unsigned char scroll_lock = 0;
150 static unsigned char shift = 0;
151 static unsigned char ctrl = 0;
152 static unsigned char alt = 0;
153 static unsigned char e0 = 0;
154 static unsigned char leds = 0;
155
156 #define DEVNAME "kbd"
157
158 /* Simple translation table for the keys */
159
160 static unsigned char kbd_plain_xlate[] = {
161         0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t',        /* 0x00 - 0x0f */
162          'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's',        /* 0x10 - 0x1f */
163          'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v',        /* 0x20 - 0x2f */
164          'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
165         0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
166          '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
167         '\r',0xff,0xff
168         };
169
170 static unsigned char kbd_shift_xlate[] = {
171         0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t',        /* 0x00 - 0x0f */
172          'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S',        /* 0x10 - 0x1f */
173          'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V',        /* 0x20 - 0x2f */
174          'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
175         0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
176          '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
177         '\r',0xff,0xff
178         };
179
180 static unsigned char kbd_ctrl_xlate[] = {
181         0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t',        /* 0x00 - 0x0f */
182         0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13,        /* 0x10 - 0x1f */
183         0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16,        /* 0x20 - 0x2f */
184         0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
185         0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
186          '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
187         '\r',0xff,0xff
188         };
189
190 /******************************************************************
191  * Init
192  ******************************************************************/
193 int isa_kbd_init(void)
194 {
195         char* result;
196         result=kbd_initialize();
197         if(result==NULL) {
198                 PRINTF("AT Keyboard initialized\n");
199                 irq_install_handler(25, (interrupt_handler_t *)handle_isa_int, NULL);
200                 isa_irq_install_handler(KBD_INTERRUPT, (interrupt_handler_t *)kbd_interrupt, NULL);
201                 return (1);
202         }
203         else {
204                 printf("%s\n",result);
205                 return (-1);
206         }
207 }
208
209 #ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
210 extern int overwrite_console (void);
211 #else
212 int overwrite_console (void)
213 {
214         return (0);
215 }
216 #endif
217
218 int drv_isa_kbd_init (void)
219 {
220         int error;
221         device_t kbddev ;
222         char *stdinname  = getenv ("stdin");
223
224         if(isa_kbd_init()==-1)
225                 return -1;
226         memset (&kbddev, 0, sizeof(kbddev));
227         strcpy(kbddev.name, DEVNAME);
228         kbddev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
229         kbddev.putc = NULL ;
230         kbddev.puts = NULL ;
231         kbddev.getc = kbd_getc ;
232         kbddev.tstc = kbd_testc ;
233
234         error = device_register (&kbddev);
235         if(error==0) {
236                 /* check if this is the standard input device */
237                 if(strcmp(stdinname,DEVNAME)==0) {
238                         /* reassign the console */
239                         if(overwrite_console()) {
240                                 return 1;
241                         }
242                         error=console_assign(stdin,DEVNAME);
243                         if(error==0)
244                                 return 1;
245                         else
246                                 return error;
247                 }
248                 return 1;
249         }
250         return error;
251 }
252
253 /******************************************************************
254  * Queue handling
255  ******************************************************************/
256 /* puts character in the queue and sets up the in and out pointer */
257 void kbd_put_queue(char data)
258 {
259         if((in_pointer+1)==KBD_BUFFER_LEN) {
260                 if(out_pointer==0) {
261                         return; /* buffer full */
262                 } else{
263                         in_pointer=0;
264                 }
265         } else {
266                 if((in_pointer+1)==out_pointer)
267                         return; /* buffer full */
268                 in_pointer++;
269         }
270         kbd_buffer[in_pointer]=data;
271         return;
272 }
273
274 /* test if a character is in the queue */
275 int kbd_testc(void)
276 {
277         if(in_pointer==out_pointer)
278                 return(0); /* no data */
279         else
280                 return(1);
281 }
282 /* gets the character from the queue */
283 int kbd_getc(void)
284 {
285         char c;
286         while(in_pointer==out_pointer);
287         if((out_pointer+1)==KBD_BUFFER_LEN)
288                 out_pointer=0;
289         else
290                 out_pointer++;
291         c=kbd_buffer[out_pointer];
292         return (int)c;
293
294 }
295
296
297 /* set LEDs */
298
299 void kbd_set_leds(void)
300 {
301         if(caps_lock==0)
302                 leds&=~LED_CAP; /* switch caps_lock off */
303         else
304                 leds|=LED_CAP; /* switch on LED */
305         if(num_lock==0)
306                 leds&=~LED_NUM; /* switch LED off */
307         else
308                 leds|=LED_NUM;  /* switch on LED */
309         if(scroll_lock==0)
310                 leds&=~LED_SCR; /* switch LED off */
311         else
312                 leds|=LED_SCR; /* switch on LED */
313         kbd_send_data(KBD_CMD_SET_LEDS);
314         kbd_send_data(leds);
315 }
316
317
318 void handle_keyboard_event(unsigned char scancode)
319 {
320         unsigned char keycode;
321
322         /*  Convert scancode to keycode */
323         PRINTF("scancode %x\n",scancode);
324         if(scancode==0xe0) {
325                 e0=1; /* special charakters */
326                 return;
327         }
328         if(e0==1) {
329                 e0=0; /* delete flag */
330                 if(!(   ((scancode&0x7F)==0x38)|| /* the right ctrl key */
331                                         ((scancode&0x7F)==0x1D)|| /* the right alt key */
332                                         ((scancode&0x7F)==0x35)||       /* the right '/' key */
333                                         ((scancode&0x7F)==0x1C) ))  /* the right enter key */
334                         /* we swallow unknown e0 codes */
335                         return;
336         }
337         /* special cntrl keys */
338         switch(scancode)
339         {
340                 case 0x2A:
341                 case 0x36: /* shift pressed */
342                         shift=1;
343                         return; /* do nothing else */
344                 case 0xAA:
345                 case 0xB6: /* shift released */
346                         shift=0;
347                         return; /* do nothing else */
348                 case 0x38: /* alt pressed */
349                         alt=1;
350                         return; /* do nothing else */
351                 case 0xB8: /* alt released */
352                         alt=0;
353                         return; /* do nothing else */
354                 case 0x1d: /* ctrl pressed */
355                         ctrl=1;
356                         return; /* do nothing else */
357                 case 0x9d: /* ctrl released */
358                         ctrl=0;
359                         return; /* do nothing else */
360                 case 0x46: /* scrollock pressed */
361                         scroll_lock=~scroll_lock;
362                         kbd_set_leds();
363                         return; /* do nothing else */
364                 case 0x3A: /* capslock pressed */
365                         caps_lock=~caps_lock;
366                         kbd_set_leds();
367                         return;
368                 case 0x45: /* numlock pressed */
369                         num_lock=~num_lock;
370                         kbd_set_leds();
371                         return;
372                 case 0xC6: /* scroll lock released */
373                 case 0xC5: /* num lock released */
374                 case 0xBA: /* caps lock released */
375                         return; /* just swallow */
376         }
377         if((scancode&0x80)==0x80) /* key released */
378                 return;
379         /* now, decide which table we need */
380         if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */
381                 PRINTF("unkown scancode %X\n",scancode);
382                 return; /* swallow it */
383         }
384         /* setup plain code first */
385         keycode=kbd_plain_xlate[scancode];
386         if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */
387                 if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
388                         PRINTF("unkown caps-locked scancode %X\n",scancode);
389                         return; /* swallow it */
390                 }
391                 keycode=kbd_shift_xlate[scancode];
392                 if(keycode<'A') { /* we only want the alphas capital */
393                         keycode=kbd_plain_xlate[scancode];
394                 }
395         }
396         if(shift==1) { /* shift overwrites caps_lock */
397                 if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
398                         PRINTF("unkown shifted scancode %X\n",scancode);
399                         return; /* swallow it */
400                 }
401                 keycode=kbd_shift_xlate[scancode];
402         }
403         if(ctrl==1) { /* ctrl overwrites caps_lock and shift */
404                 if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */
405                         PRINTF("unkown ctrl scancode %X\n",scancode);
406                         return; /* swallow it */
407                 }
408                 keycode=kbd_ctrl_xlate[scancode];
409         }
410         /* check if valid keycode */
411         if(keycode==0xff) {
412                 PRINTF("unkown scancode %X\n",scancode);
413                 return; /* swallow unknown codes */
414         }
415
416         kbd_put_queue(keycode);
417         PRINTF("%x\n",keycode);
418 }
419
420 /*
421  * This reads the keyboard status port, and does the
422  * appropriate action.
423  *
424  */
425 unsigned char handle_kbd_event(void)
426 {
427         unsigned char status = kbd_read_status();
428         unsigned int work = 10000;
429
430         while ((--work > 0) && (status & KBD_STAT_OBF)) {
431                 unsigned char scancode;
432
433                 scancode = kbd_read_input();
434
435                 /* Error bytes must be ignored to make the
436                    Synaptics touchpads compaq use work */
437                 /* Ignore error bytes */
438                 if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
439                 {
440                         if (status & KBD_STAT_MOUSE_OBF)
441                                 ; /* not supported: handle_mouse_event(scancode); */
442                         else
443                                 handle_keyboard_event(scancode);
444                 }
445                 status = kbd_read_status();
446         }
447         if (!work)
448                 PRINTF("pc_keyb: controller jammed (0x%02X).\n", status);
449         return status;
450 }
451
452
453
454 /******************************************************************************
455  * Lowlevel Part of keyboard section
456  */
457 unsigned char kbd_read_status(void)
458 {
459         return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT));
460 }
461
462 unsigned char kbd_read_input(void)
463 {
464         return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT));
465 }
466
467 void kbd_write_command(unsigned char cmd)
468 {
469         out8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd);
470 }
471
472 void kbd_write_output(unsigned char data)
473 {
474         out8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data);
475 }
476
477 int kbd_read_data(void)
478 {
479         int val;
480         unsigned char status;
481
482         val=-1;
483         status = kbd_read_status();
484         if (status & KBD_STAT_OBF) {
485                 val = kbd_read_input();
486                 if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
487                         val = -2;
488         }
489         return val;
490 }
491
492 int kbd_wait_for_input(void)
493 {
494         unsigned long timeout;
495         int val;
496
497         timeout = KBD_TIMEOUT;
498         val=kbd_read_data();
499         while(val < 0)
500         {
501                 if(timeout--==0)
502                         return -1;
503                 udelay(1000);
504                 val=kbd_read_data();
505         }
506         return val;
507 }
508
509
510 int kb_wait(void)
511 {
512         unsigned long timeout = KBC_TIMEOUT * 10;
513
514         do {
515                 unsigned char status = handle_kbd_event();
516                 if (!(status & KBD_STAT_IBF))
517                         return 0; /* ok */
518                 udelay(1000);
519                 timeout--;
520         } while (timeout);
521         return 1;
522 }
523
524 void kbd_write_command_w(int data)
525 {
526         if(kb_wait())
527                 PRINTF("timeout in kbd_write_command_w\n");
528         kbd_write_command(data);
529 }
530
531 void kbd_write_output_w(int data)
532 {
533         if(kb_wait())
534                 PRINTF("timeout in kbd_write_output_w\n");
535         kbd_write_output(data);
536 }
537
538 void kbd_send_data(unsigned char data)
539 {
540         unsigned char status;
541         disable_8259A_irq(1); /* disable interrupt */
542         kbd_write_output_w(data);
543         status = kbd_wait_for_input();
544         if (status == KBD_REPLY_ACK)
545                 enable_8259A_irq(1); /* enable interrupt */
546 }
547
548
549 char * kbd_initialize(void)
550 {
551         int status;
552
553         in_pointer = 0; /* delete in Buffer */
554         out_pointer = 0;
555         /*
556          * Test the keyboard interface.
557          * This seems to be the only way to get it going.
558          * If the test is successful a x55 is placed in the input buffer.
559          */
560         kbd_write_command_w(KBD_CCMD_SELF_TEST);
561         if (kbd_wait_for_input() != 0x55)
562                 return "Kbd:   failed self test";
563         /*
564          * Perform a keyboard interface test.  This causes the controller
565          * to test the keyboard clock and data lines.  The results of the
566          * test are placed in the input buffer.
567          */
568         kbd_write_command_w(KBD_CCMD_KBD_TEST);
569         if (kbd_wait_for_input() != 0x00)
570                 return "Kbd:   interface failed self test";
571         /*
572          * Enable the keyboard by allowing the keyboard clock to run.
573          */
574         kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
575         status = kbd_wait_for_input();
576         /*
577          * Reset keyboard. If the read times out
578          * then the assumption is that no keyboard is
579          * plugged into the machine.
580          * This defaults the keyboard to scan-code set 2.
581          *
582          * Set up to try again if the keyboard asks for RESEND.
583          */
584         do {
585                 kbd_write_output_w(KBD_CMD_RESET);
586                 status = kbd_wait_for_input();
587                 if (status == KBD_REPLY_ACK)
588                         break;
589                 if (status != KBD_REPLY_RESEND)
590                 {
591                         PRINTF("status: %X\n",status);
592                         return "Kbd:   reset failed, no ACK";
593                 }
594         } while (1);
595         if (kbd_wait_for_input() != KBD_REPLY_POR)
596                 return "Kbd:   reset failed, no POR";
597
598         /*
599          * Set keyboard controller mode. During this, the keyboard should be
600          * in the disabled state.
601          *
602          * Set up to try again if the keyboard asks for RESEND.
603          */
604         do {
605                 kbd_write_output_w(KBD_CMD_DISABLE);
606                 status = kbd_wait_for_input();
607                 if (status == KBD_REPLY_ACK)
608                         break;
609                 if (status != KBD_REPLY_RESEND)
610                         return "Kbd:   disable keyboard: no ACK";
611         } while (1);
612
613         kbd_write_command_w(KBD_CCMD_WRITE_MODE);
614         kbd_write_output_w(KBD_MODE_KBD_INT
615                               | KBD_MODE_SYS
616                               | KBD_MODE_DISABLE_MOUSE
617                               | KBD_MODE_KCC);
618
619         /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
620         kbd_write_command_w(KBD_CCMD_READ_MODE);
621         if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
622                 /*
623                  * If the controller does not support conversion,
624                  * Set the keyboard to scan-code set 1.
625                  */
626                 kbd_write_output_w(0xF0);
627                 kbd_wait_for_input();
628                 kbd_write_output_w(0x01);
629                 kbd_wait_for_input();
630         }
631         kbd_write_output_w(KBD_CMD_ENABLE);
632         if (kbd_wait_for_input() != KBD_REPLY_ACK)
633                 return "Kbd:   enable keyboard: no ACK";
634
635         /*
636          * Finally, set the typematic rate to maximum.
637          */
638         kbd_write_output_w(KBD_CMD_SET_RATE);
639         if (kbd_wait_for_input() != KBD_REPLY_ACK)
640                 return "Kbd:   Set rate: no ACK";
641         kbd_write_output_w(0x00);
642         if (kbd_wait_for_input() != KBD_REPLY_ACK)
643                 return "Kbd:   Set rate: no ACK";
644         return NULL;
645 }
646
647 void kbd_interrupt(void)
648 {
649         handle_kbd_event();
650 }
651
652
653
654 /* eof */
655