OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [char/] [keyb_arc.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * linux/arch/arm/drivers/block/keyboard.c
3
 *
4
 * Keyboard driver for ARM Linux.
5
 */
6
 
7
#include <linux/config.h>
8
#include <linux/sched.h>
9
#include <linux/interrupt.h>
10
#include <linux/tty.h>
11
#include <linux/tty_flip.h>
12
#include <linux/mm.h>
13
#include <linux/malloc.h>
14
#include <linux/ptrace.h>
15
#include <linux/signal.h>
16
#include <linux/timer.h>
17
#include <linux/random.h>
18
#include <linux/ctype.h>
19
 
20
#include <asm/bitops.h>
21
#include <asm/irq.h>
22
#include <asm/hardware.h>
23
 
24
#include "kbd_kern.h"
25
#include "diacr.h"
26
#include "vt_kern.h"
27
 
28
#define IRQ_KEYBOARDRX 15
29
#define IRQ_KEYBOARDTX 14
30
 
31
extern void kbd_keyboardkey(unsigned int keycode, unsigned int up_flag);
32
extern void kbd_reset(void);
33
extern void kbd_setregs(struct pt_regs *regs);
34
 
35
#define VERSION 107
36
 
37
#define KBD_REPORT_ERR
38
#define KBD_REPORT_UNKN
39
 
40
#include <asm/io.h>
41
#include <asm/system.h>
42
 
43
static char kbd_txval;
44
static int kbd_id            = -1;
45
static struct wait_queue *kbd_waitq;
46
 
47
/*
48
 * Protocol codes to send the keyboard.
49
 */
50
#define HRST 0xff       /* reset keyboard */
51
#define RAK1 0xfe       /* reset response */
52
#define RAK2 0xfd       /* reset response */
53
#define BACK 0x3f       /* Ack for first keyboard pair */
54
#define SMAK 0x33       /* Last data byte ack (key scanning + mouse movement scanning) */
55
#define MACK 0x32       /* Last data byte ack (mouse movement scanning) */
56
#define SACK 0x31       /* Last data byte ack (key scanning) */
57
#define NACK 0x30       /* Last data byte ack (no scanning, mouse data) */
58
#define RQMP 0x22       /* Request mouse data */
59
#define PRST 0x21       /* nothing */
60
#define RQID 0x20       /* Request ID */
61
 
62
#define UP_FLAG 1
63
 
64
/*
65
 * This array converts the scancode that we get from the keyboard to the
66
 * real rows/columns on the A5000 keyboard.  This might be keyboard specific...
67
 *
68
 * It is these values that we use to maintain the key down array.  That way, we
69
 * should pick up on the ghost key presses (which is what happens when you press
70
 * three keys, and the keyboard thinks you have pressed four!)
71
 *
72
 * Row 8 (0x80+c) is actually a column with one key per row.  It is isolated from
73
 * the other keys, and can't cause these problems (its used for shift, ctrl, alt etc).
74
 *
75
 * Illegal scancodes are denoted by an 0xff (in other words, we don't know about
76
 * them, and can't process them for ghosts).  This does however, cause problems with
77
 * autorepeat processing...
78
 */
79
static unsigned char scancode_2_colrow[256] = {
80
  0x01, 0x42, 0x32, 0x33, 0x43, 0x56, 0x5a, 0x6c, 0x7c, 0x5c, 0x5b, 0x6b, 0x7b, 0x84, 0x70, 0x60,
81
  0x11, 0x51, 0x62, 0x63, 0x44, 0x54, 0x55, 0x45, 0x46, 0x4a, 0x3c, 0x4b, 0x59, 0x49, 0x69, 0x79,
82
  0x83, 0x40, 0x30, 0x3b, 0x39, 0x38, 0x31, 0x61, 0x72, 0x73, 0x64, 0x74, 0x75, 0x65, 0x66, 0x6a,
83
  0x1c, 0x2c, 0x7a, 0x36, 0x48, 0x68, 0x78, 0x20, 0x2b, 0x29, 0x28, 0x81, 0x71, 0x22, 0x23, 0x34,
84
  0x24, 0x25, 0x35, 0x26, 0x3a, 0x0c, 0x2a, 0x76, 0x10, 0x1b, 0x19, 0x18, 0x82, 0xff, 0x21, 0x12,
85
  0x13, 0x14, 0x04, 0x05, 0x15, 0x16, 0x1a, 0x0a, 0x85, 0x77, 0x00, 0x0b, 0x09, 0x02, 0x80, 0x03,
86
  0x87, 0x86, 0x06, 0x17, 0x27, 0x07, 0x37, 0x08, 0xff,
87
};
88
 
89
#define BITS_PER_SHORT (8*sizeof(unsigned short))
90
static unsigned short ghost_down[128/BITS_PER_SHORT];
91
 
92
static void kbd_drv_key(unsigned int keycode, unsigned int up_flag)
93
{
94
        unsigned int real_keycode;
95
 
96
        if (keycode > 0x72) {
97
#ifdef KBD_REPORT_UNKN
98
                printk ("kbd: unknown scancode 0x%04x\n", keycode);
99
#endif
100
                return;
101
        }
102
        if (keycode >= 0x70) {
103
#ifdef CONFIG_KBDMOUSE
104
                unsigned char buttons;
105
                switch (keycode) {
106
                        case 0x70: /* Left mouse button */
107
                                buttons = add_mouse_buttonchange(4, up_flag ? 4 : 0);
108
                                break;
109
 
110
                        case 0x71: /* Middle mouse button */
111
                                buttons = add_mouse_buttonchange(2, up_flag ? 2 : 0);
112
                                break;
113
 
114
                        case 0x72:/* Right mouse button */
115
                                buttons = add_mouse_buttonchange(1, up_flag ? 1 : 0);
116
                                break;
117
                        default:
118
                                buttons = 0;
119
                }
120
                add_mouse_randomness (buttons << 16);
121
#endif
122
                return;
123
        }
124
 
125
        /*
126
         * We have to work out if we accept this key press as a real key, or
127
         * if it is a ghost.  IE. If you press three keys, the keyboard will think
128
         * that you've pressed a fouth: (@ = key down, # = ghost)
129
         *
130
         *   0 1 2 3 4 5 6 7
131
         *   | | | | | | | |
132
         * 0-+-+-+-+-+-+-+-+-
133
         *   | | | | | | | |
134
         * 1-+-@-+-+-+-@-+-+-
135
         *   | | | | | | | |
136
         * 2-+-+-+-+-+-+-+-+-
137
         *   | | | | | | | |
138
         * 3-+-@-+-+-+-#-+-+-
139
         *   | | | | | | | |
140
         *
141
         * This is what happens when you have a matrix keyboard...
142
         */
143
 
144
        real_keycode = scancode_2_colrow[keycode];
145
 
146
        if ((real_keycode & 0x80) == 0) {
147
                int rr, kc = (real_keycode >> 4) & 7;
148
                int cc;
149
                unsigned short res, kdownkc;
150
 
151
                kdownkc = ghost_down[kc] | (1 << (real_keycode & 15));
152
 
153
                for (rr = 0; rr < 128/BITS_PER_SHORT; rr++)
154
                        if (rr != kc && (res = ghost_down[rr] & kdownkc)) {
155
                                /*
156
                                 * we have found a second row with at least one key pressed in the
157
                                 * same column.
158
                                 */
159
                                for (cc = 0; res; res >>= 1)
160
                                        cc += (res & 1);
161
                                if (cc > 1)
162
                                        return; /* ignore it */
163
                        }
164
                if (up_flag)
165
                        clear_bit (real_keycode, ghost_down);
166
                else
167
                        set_bit (real_keycode, ghost_down);
168
        }
169
 
170
        kbd_keyboardkey(keycode, up_flag);
171
}
172
 
173
static inline void kbd_drv_sendbyte(unsigned char val)
174
{
175
        kbd_txval = val;
176
        enable_irq(IRQ_KEYBOARDTX);
177
}
178
 
179
static inline void kbd_drv_reset(void)
180
{
181
        int i;
182
 
183
        for (i = 0; i < 128/BITS_PER_SHORT; i++)
184
                ghost_down[i] = 0;
185
 
186
        kbd_reset();
187
}
188
 
189
void kbd_drv_setleds(unsigned int leds)
190
{
191
        leds =  ((leds & (1<<VC_SCROLLOCK))?4:0) | ((leds & (1<<VC_NUMLOCK))?2:0) |
192
                ((leds & (1<<VC_CAPSLOCK))?1:0);
193
        kbd_drv_sendbyte(leds);
194
}
195
 
196
/*
197
 * Keyboard states:
198
 *  0 initial reset condition, sent HRST, wait for HRST
199
 *  1 Send HRST, wait for HRST acknowledge
200
 *  2 Sent RAK1, wait for RAK1
201
 *  3 Sent RAK2, wait for RAK2
202
 *  4 Sent SMAK, wait for anything
203
 *  5 Wait for second keyboard nibble for key pressed
204
 *  6 Wait for second keyboard nibble for key released
205
 *  7 Wait for second part of mouse data
206
 */
207
#define KBD_INITRST     0
208
#define KBD_RAK1        1
209
#define KBD_RAK2        2
210
#define KBD_ID          3
211
#define KBD_IDLE        4
212
#define KBD_KEYDOWN     5
213
#define KBD_KEYUP       6
214
#define KBD_MOUSE       7
215
 
216
static int handle_rawcode(unsigned int keyval)
217
{
218
        static signed char kbd_mousedx = 0;
219
               signed char kbd_mousedy;
220
        static unsigned char kbd_state = KBD_INITRST;
221
        static unsigned char kbd_keyhigh=0;
222
 
223
    switch(kbd_state) {
224
    case KBD_INITRST: /* hard reset - sent HRST */
225
        if (keyval == HRST) {
226
            kbd_drv_reset ();
227
            kbd_drv_sendbyte (RAK1);
228
            kbd_state = KBD_RAK1;
229
        } else
230
            goto kbd_wontreset;
231
        break;
232
 
233
    case KBD_RAK1:/* Sent RAK1 */
234
        switch (keyval) {
235
        case HRST:
236
            kbd_drv_sendbyte (RAK1);
237
            kbd_state = KBD_INITRST;
238
            break;
239
        case RAK1:
240
            kbd_drv_sendbyte (RAK2);
241
            kbd_state = KBD_RAK2;
242
            break;
243
        default:
244
            goto kbd_wontreset;
245
        }
246
        break;
247
 
248
    case KBD_RAK2:/* Sent RAK2 */
249
        switch (keyval) {
250
        case HRST:
251
            kbd_drv_sendbyte (HRST);
252
            kbd_state = KBD_INITRST;
253
            break;
254
        case RAK2:
255
            if (kbd_id == -1) {
256
                kbd_drv_sendbyte (NACK);
257
                kbd_drv_sendbyte (RQID);
258
                kbd_state = KBD_ID;
259
            } else {
260
                kbd_drv_sendbyte (SMAK);
261
                kbd_state = KBD_IDLE;
262
            }
263
            break;
264
        default:
265
            goto kbd_wontreset;
266
        }
267
        break;
268
 
269
    case KBD_ID:
270
        if (keyval == HRST) {
271
            kbd_drv_sendbyte (HRST);
272
            kbd_state = KBD_INITRST;
273
            kbd_id = -2;
274
            wake_up(&kbd_waitq);
275
            break;
276
        } else
277
        if ((keyval & 0xc0) == 0x80) {
278
            kbd_id = keyval & 0x3f;
279
            kbd_drv_sendbyte (SMAK);
280
            kbd_state = KBD_IDLE;
281
            wake_up(&kbd_waitq);
282
            break;
283
        }
284
        break;
285
 
286
    case KBD_IDLE:/* Send SMAK, ready for any reply */
287
        if (keyval == HRST) {
288
            kbd_drv_sendbyte (HRST);
289
            kbd_state = KBD_INITRST;
290
        } else
291
        if (keyval & 0x80) {
292
            if (!(keyval & 0x40)) {
293
                if (kbd_id == -1)
294
                    kbd_id = keyval & 0x3f;
295
                else {
296
                    kbd_state = KBD_INITRST;
297
                    kbd_drv_sendbyte (HRST);
298
                }
299
                break;
300
            }
301
            switch (keyval & 0xf0) {
302
            case 0xc0:
303
                kbd_keyhigh = keyval;
304
                kbd_state   = KBD_KEYDOWN;
305
                kbd_drv_sendbyte (BACK);
306
                break;
307
 
308
            case 0xd0:
309
                kbd_keyhigh = keyval;
310
                kbd_state   = KBD_KEYUP;
311
                kbd_drv_sendbyte (BACK);
312
                break;
313
 
314
            default:
315
                kbd_state = KBD_INITRST;
316
                kbd_drv_sendbyte (HRST);
317
            }
318
        } else {
319
            kbd_mousedx = keyval & 0x40 ? keyval|0x80 : keyval;
320
            kbd_state   = KBD_MOUSE;
321
            kbd_drv_sendbyte (BACK);
322
        }
323
        break;
324
 
325
    case KBD_KEYDOWN:
326
        if ((keyval & 0xf0) != 0xc0)
327
            goto kbd_error;
328
        else {
329
            kbd_state = KBD_IDLE;
330
            kbd_drv_sendbyte (SMAK);
331
            if (((kbd_keyhigh ^ keyval) & 0xf0) == 0)
332
                kbd_drv_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), 0);
333
            return 1;
334
        }
335
        break;
336
 
337
    case KBD_KEYUP:
338
        if ((keyval & 0xf0) != 0xd0)
339
            goto kbd_error;
340
        else {
341
            kbd_state = KBD_IDLE;
342
            kbd_drv_sendbyte (SMAK);
343
            if (((kbd_keyhigh ^ keyval) & 0xf0) == 0)
344
                kbd_drv_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), UP_FLAG);
345
            return 1;
346
        }
347
        break;
348
 
349
    case KBD_MOUSE:
350
                if (keyval & 0x80)
351
                        goto kbd_error;
352
                else {
353
                        kbd_state = KBD_IDLE;
354
                        kbd_drv_sendbyte (SMAK);
355
                        kbd_mousedy = (char)(keyval & 0x40 ? keyval | 0x80 : keyval);
356
#ifdef CONFIG_KBDMOUSE
357
                        add_mouse_movement((int)kbd_mousedx, (int)kbd_mousedy);
358
                        add_mouse_randomness((kbd_mousedy << 8) + kbd_mousedx);
359
#endif
360
                }
361
                return 1;
362
        }
363
        return 0;
364
 
365
kbd_wontreset:
366
#ifdef KBD_REPORT_ERR
367
        printk ("kbd: keyboard won't reset (kbdstate %d, keyval %02X)\n",
368
                kbd_state, keyval);
369
#endif
370
        kbd_drv_sendbyte (HRST);
371
        kbd_state = KBD_INITRST;
372
        return 0;
373
 
374
kbd_error:
375
#ifdef KBD_REPORT_ERR
376
        printk ("kbd: keyboard out of sync - resetting\n");
377
#endif
378
        kbd_drv_sendbyte (HRST);
379
        kbd_state = KBD_INITRST;
380
        return 0;
381
}
382
 
383
static void kbd_drv_rx(int irq, void *dev_id, struct pt_regs *regs)
384
{
385
        if (handle_rawcode(inb(IOC_KARTRX)))
386
                mark_bh (KEYBOARD_BH);
387
        kbd_setregs(regs);
388
}
389
 
390
static void kbd_drv_tx(int irq, void *dev_id, struct pt_regs *regs)
391
{
392
        outb (kbd_txval, IOC_KARTTX);
393
}
394
 
395
int kbd_drv_init (void)
396
{
397
        unsigned long flags;
398
 
399
        save_flags_cli (flags);
400
        if (request_irq (IRQ_KEYBOARDRX, kbd_drv_rx, 0, "keyboard", NULL) != 0)
401
                panic("Could not allocate keyboard receive IRQ!");
402
        if (request_irq (IRQ_KEYBOARDTX, kbd_drv_tx, 0, "keyboard", NULL) != 0)
403
                panic("Could not allocate keyboard transmit IRQ!");
404
        disable_irq (IRQ_KEYBOARDTX);
405
        (void)inb(IOC_KARTRX);
406
        restore_flags (flags);
407
 
408
        kbd_drv_sendbyte (HRST);
409
 
410
        current->timeout = jiffies + HZ; /* wait 1s for keyboard to initialise */
411
        interruptible_sleep_on(&kbd_waitq);
412
 
413
        printk (KERN_INFO "Keyboard driver v%d.%02d. (", VERSION/100, VERSION%100);
414
        if (kbd_id != -1)
415
              printk ("id=%d ", kbd_id);
416
        printk ("English)\n");
417
        return 0;
418
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.