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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [q40_keyb.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/drivers/char/q40_keyb.c
3
 *
4
 */
5
 
6
#include <linux/config.h>
7
 
8
#include <linux/spinlock.h>
9
#include <linux/sched.h>
10
#include <linux/interrupt.h>
11
#include <linux/tty.h>
12
#include <linux/mm.h>
13
#include <linux/keyboard.h>
14
#include <linux/signal.h>
15
#include <linux/ioport.h>
16
#include <linux/init.h>
17
#include <linux/kbd_ll.h>
18
#include <linux/kbd_kern.h>
19
#include <linux/delay.h>
20
#include <linux/sysrq.h>
21
#include <linux/random.h>
22
#include <linux/poll.h>
23
#include <linux/miscdevice.h>
24
#include <linux/slab.h>
25
 
26
#include <asm/keyboard.h>
27
#include <asm/bitops.h>
28
#include <asm/io.h>
29
#include <asm/uaccess.h>
30
#include <asm/q40_master.h>
31
#include <asm/irq.h>
32
#include <asm/q40ints.h>
33
 
34
 
35
/* Simple translation table for the SysRq keys */
36
 
37
#define SYSRQ_KEY 0x54
38
 
39
#ifdef CONFIG_MAGIC_SYSRQ
40
unsigned char q40kbd_sysrq_xlate[128] =
41
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
42
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
43
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
44
        "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
45
        "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
46
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
47
        "\r\000/";                                      /* 0x60 - 0x6f */
48
#endif
49
 
50
/* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/
51
/* 0x00 means not a valid entry or no conversion known                    */
52
 
53
unsigned static char q40cl[256] =
54
{/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
55
 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00,     /* 0x00 - 0x0f */
56
 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00,     /* 0x10 - 0x1f */
57
 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00,     /* 0x20 - 0x2f  'f' is at 0x2b, what is 0x28 ???*/
58
 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00,     /* 0x30 - 0x3f */
59
 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00,     /* 0x40 - 0x4f */
60
 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00,     /* 0x50 - 0x5f*/
61
 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f */
62
 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00,     /* 0x70 - 0x7f */
63
 0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f  0x84/0x37 is SySrq*/
64
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f */
65
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf */
66
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf */
67
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf */
68
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf */
69
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef */
70
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xf0 - 0xff */
71
};
72
 
73
/* another table, AT 0xe0 codes to PC 0xe0 codes,
74
   0xff special entry for SysRq - DROPPED right now  */
75
static unsigned char q40ecl[]=
76
{/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
77
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x00 - 0x0f*/
78
 0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x10 - 0x1f */
79
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x20 - 0x2f*/
80
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x30 - 0x3f*/
81
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00,     /* 0x40 - 0x4f*/
82
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,     /* 0x50 - 0x5f*/
83
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f*/
84
 0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00,     /* 0x70 - 0x7f*/
85
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f*/
86
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f*/
87
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf*/
88
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf*/
89
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf*/
90
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf*/
91
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef*/
92
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00      /* 0xf0 - 0xff*/
93
};
94
 
95
 
96
static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
97
 
98
 
99
/*
100
 * Translation of escaped scancodes to keycodes.
101
 * This is now user-settable.
102
 * The keycodes 1-88,96-111,119 are fairly standard, and
103
 * should probably not be changed - changing might confuse X.
104
 * X also interprets scancode 0x5d (KEY_Begin).
105
 *
106
 * For 1-88 keycode equals scancode.
107
 */
108
 
109
#define E0_KPENTER 96
110
#define E0_RCTRL   97
111
#define E0_KPSLASH 98
112
#define E0_PRSCR   99
113
#define E0_RALT    100
114
#define E0_BREAK   101  /* (control-pause) */
115
#define E0_HOME    102
116
#define E0_UP      103
117
#define E0_PGUP    104
118
#define E0_LEFT    105
119
#define E0_RIGHT   106
120
#define E0_END     107
121
#define E0_DOWN    108
122
#define E0_PGDN    109
123
#define E0_INS     110
124
#define E0_DEL     111
125
 
126
#define E1_PAUSE   119
127
 
128
/*
129
 * The keycodes below are randomly located in 89-95,112-118,120-127.
130
 * They could be thrown away (and all occurrences below replaced by 0),
131
 * but that would force many users to use the `setkeycodes' utility, where
132
 * they needed not before. It does not matter that there are duplicates, as
133
 * long as no duplication occurs for any single keyboard.
134
 */
135
#define SC_LIM 89
136
 
137
#define FOCUS_PF1 85           /* actual code! */
138
#define FOCUS_PF2 89
139
#define FOCUS_PF3 90
140
#define FOCUS_PF4 91
141
#define FOCUS_PF5 92
142
#define FOCUS_PF6 93
143
#define FOCUS_PF7 94
144
#define FOCUS_PF8 95
145
#define FOCUS_PF9 120
146
#define FOCUS_PF10 121
147
#define FOCUS_PF11 122
148
#define FOCUS_PF12 123
149
 
150
#define JAP_86     124
151
/* tfj@olivia.ping.dk:
152
 * The four keys are located over the numeric keypad, and are
153
 * labelled A1-A4. It's an rc930 keyboard, from
154
 * Regnecentralen/RC International, Now ICL.
155
 * Scancodes: 59, 5a, 5b, 5c.
156
 */
157
#define RGN1 124
158
#define RGN2 125
159
#define RGN3 126
160
#define RGN4 127
161
 
162
static unsigned char high_keys[128 - SC_LIM] = {
163
  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
164
  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
165
  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
166
  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
167
  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
168
  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
169
};
170
 
171
/* BTC */
172
#define E0_MACRO   112
173
/* LK450 */
174
#define E0_F13     113
175
#define E0_F14     114
176
#define E0_HELP    115
177
#define E0_DO      116
178
#define E0_F17     117
179
#define E0_KPMINPLUS 118
180
/*
181
 * My OmniKey generates e0 4c for  the "OMNI" key and the
182
 * right alt key does nada. [kkoller@nyx10.cs.du.edu]
183
 */
184
#define E0_OK   124
185
/*
186
 * New microsoft keyboard is rumoured to have
187
 * e0 5b (left window button), e0 5c (right window button),
188
 * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
189
 * [or: Windows_L, Windows_R, TaskMan]
190
 */
191
#define E0_MSLW 125
192
#define E0_MSRW 126
193
#define E0_MSTM 127
194
 
195
/* this can be changed using setkeys : */
196
static unsigned char e0_keys[128] = {
197
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x00-0x07 */
198
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x08-0x0f */
199
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x10-0x17 */
200
  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,           /* 0x18-0x1f */
201
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x20-0x27 */
202
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x28-0x2f */
203
  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,           /* 0x30-0x37 */
204
  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,           /* 0x38-0x3f */
205
  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,           /* 0x40-0x47 */
206
  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
207
  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,           /* 0x50-0x57 */
208
  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,        /* 0x58-0x5f */
209
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x60-0x67 */
210
  0, 0, 0, 0, 0, 0, 0, E0_MACRO,                     /* 0x68-0x6f */
211
  0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x70-0x77 */
212
  0, 0, 0, 0, 0, 0, 0, 0                              /* 0x78-0x7f */
213
};
214
 
215
 
216
int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode)
217
{
218
        if (scancode < SC_LIM || scancode > 255 || keycode > 127)
219
          return -EINVAL;
220
        if (scancode < 128)
221
          high_keys[scancode - SC_LIM] = keycode;
222
        else
223
          e0_keys[scancode - 128] = keycode;
224
        return 0;
225
}
226
 
227
int q40kbd_getkeycode(unsigned int scancode)
228
{
229
        return
230
          (scancode < SC_LIM || scancode > 255) ? -EINVAL :
231
          (scancode < 128) ? high_keys[scancode - SC_LIM] :
232
            e0_keys[scancode - 128];
233
}
234
 
235
 
236
#define disable_keyboard()      
237
#define enable_keyboard()       
238
 
239
 
240
 
241
 
242
int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
243
                    char raw_mode)
244
{
245
        static int prev_scancode;
246
 
247
        /* special prefix scancodes.. */
248
        if (scancode == 0xe0 || scancode == 0xe1) {
249
                prev_scancode = scancode;
250
                return 0;
251
        }
252
 
253
        /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
254
        if (scancode == 0x00 || scancode == 0xff) {
255
                prev_scancode = 0;
256
                return 0;
257
        }
258
 
259
        scancode &= 0x7f;
260
 
261
        if (prev_scancode) {
262
          /*
263
           * usually it will be 0xe0, but a Pause key generates
264
           * e1 1d 45 e1 9d c5 when pressed, and nothing when released
265
           */
266
          if (prev_scancode != 0xe0) {
267
              if (prev_scancode == 0xe1 && scancode == 0x1d) {
268
                  prev_scancode = 0x100;
269
                  return 0;
270
              } else if (prev_scancode == 0x100 && scancode == 0x45) {
271
                  *keycode = E1_PAUSE;
272
                  prev_scancode = 0;
273
              } else {
274
#ifdef KBD_REPORT_UNKN
275
                  if (!raw_mode)
276
                    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
277
#endif
278
                  prev_scancode = 0;
279
                  return 0;
280
              }
281
          } else {
282
              prev_scancode = 0;
283
              /*
284
               *  The keyboard maintains its own internal caps lock and
285
               *  num lock statuses. In caps lock mode E0 AA precedes make
286
               *  code and E0 2A follows break code. In num lock mode,
287
               *  E0 2A precedes make code and E0 AA follows break code.
288
               *  We do our own book-keeping, so we will just ignore these.
289
               */
290
              /*
291
               *  For my keyboard there is no caps lock mode, but there are
292
               *  both Shift-L and Shift-R modes. The former mode generates
293
               *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
294
               *  So, we should also ignore the latter. - aeb@cwi.nl
295
               */
296
              if (scancode == 0x2a || scancode == 0x36)
297
                return 0;
298
 
299
              if (e0_keys[scancode])
300
                *keycode = e0_keys[scancode];
301
              else {
302
#ifdef KBD_REPORT_UNKN
303
                  if (!raw_mode)
304
                    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
305
                           scancode);
306
#endif
307
                  return 0;
308
              }
309
          }
310
        } else if (scancode >= SC_LIM) {
311
            /* This happens with the FOCUS 9000 keyboard
312
               Its keys PF1..PF12 are reported to generate
313
               55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
314
               Moreover, unless repeated, they do not generate
315
               key-down events, so we have to zero up_flag below */
316
            /* Also, Japanese 86/106 keyboards are reported to
317
               generate 0x73 and 0x7d for \ - and \ | respectively. */
318
            /* Also, some Brazilian keyboard is reported to produce
319
               0x73 and 0x7e for \ ? and KP-dot, respectively. */
320
 
321
          *keycode = high_keys[scancode - SC_LIM];
322
 
323
          if (!*keycode) {
324
              if (!raw_mode) {
325
#ifdef KBD_REPORT_UNKN
326
                  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
327
                         " - ignored\n", scancode);
328
#endif
329
              }
330
              return 0;
331
          }
332
        } else
333
          *keycode = scancode;
334
        return 1;
335
}
336
 
337
char q40kbd_unexpected_up(unsigned char keycode)
338
{
339
        /* unexpected, but this can happen: maybe this was a key release for a
340
           FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
341
        if (keycode >= SC_LIM || keycode == 85)
342
            return 0;
343
        else
344
            return 0200;
345
}
346
 
347
static int keyup=0;
348
static int qprev=0;
349
 
350
static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
351
{
352
        unsigned char status;
353
 
354
        spin_lock(&kbd_controller_lock);
355
        kbd_pt_regs = regs;
356
 
357
        status = Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
358
        if (status )
359
          {
360
            unsigned char scancode,qcode;
361
 
362
            qcode = master_inb(KEYCODE_REG);
363
 
364
            if (qcode != 0xf0)
365
              {
366
                if (qcode == 0xe0)
367
                  {
368
                    qprev=0xe0;
369
                    handle_scancode(qprev , 1);
370
                    goto exit;
371
                  }
372
 
373
                scancode=qprev ? q40ecl[qcode] : q40cl[qcode];
374
#if 0
375
/* next line is last resort to hanlde some oddities */
376
                if (qprev && !scancode) scancode=q40cl[qcode];
377
#endif
378
                qprev=0;
379
                if (!scancode)
380
                  {
381
                    printk("unknown scancode %x\n",qcode);
382
                    goto exit;
383
                  }
384
                if (scancode==0xff)  /* SySrq */
385
                  scancode=SYSRQ_KEY;
386
 
387
                handle_scancode(scancode, ! keyup );
388
                keyup=0;
389
                tasklet_schedule(&keyboard_tasklet);
390
              }
391
            else
392
              keyup=1;
393
          }
394
exit:
395
        spin_unlock(&kbd_controller_lock);
396
        master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
397
}
398
 
399
 
400
#define KBD_NO_DATA     (-1)    /* No data */
401
#define KBD_BAD_DATA    (-2)    /* Parity or other error */
402
 
403
static int __init q40kbd_read_input(void)
404
{
405
        int retval = KBD_NO_DATA;
406
        unsigned char status;
407
 
408
        status = Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
409
        if (status) {
410
                unsigned char data = master_inb(KEYCODE_REG);
411
 
412
                retval = data;
413
                master_outb(-1,KEYBOARD_UNLOCK_REG);
414
        }
415
        return retval;
416
}
417
 
418
 
419
static void __init kbd_clear_input(void)
420
{
421
        int maxread = 100;      /* Random number */
422
 
423
        do {
424
                if (q40kbd_read_input() == KBD_NO_DATA)
425
                        break;
426
        } while (--maxread);
427
}
428
 
429
 
430
int __init q40kbd_init_hw(void)
431
{
432
 
433
        /* Flush any pending input. */
434
        kbd_clear_input();
435
 
436
        /* Ok, finally allocate the IRQ, and off we go.. */
437
        request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL);
438
        master_outb(-1,KEYBOARD_UNLOCK_REG);
439
        master_outb(1,KEY_IRQ_ENABLE_REG);
440
 
441
        return 0;
442
}
443
 

powered by: WebSVN 2.1.0

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