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