~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/board/mpl/common/kbd.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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