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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [tc/] [lk201.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *
3
 * This file is subject to the terms and conditions of the GNU General Public
4
 * License.  See the file "COPYING" in the main directory of this archive
5
 * for more details.
6
 *
7
 * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
8
 * Copyright (C) 2001, 2002, 2003  Maciej W. Rozycki <macro@ds2.pg.gda.pl>
9
 */
10
 
11
#include <linux/config.h>
12
 
13
#include <linux/errno.h>
14
#include <linux/sched.h>
15
#include <linux/tty.h>
16
#include <linux/kernel.h>
17
#include <linux/init.h>
18
#include <linux/delay.h>
19
#include <linux/kbd_ll.h>
20
#include <linux/kbd_kern.h>
21
#include <linux/vt_kern.h>
22
 
23
#include <asm/keyboard.h>
24
#include <asm/dec/tc.h>
25
#include <asm/dec/machtype.h>
26
 
27
#include "zs.h"
28
#include "lk201.h"
29
 
30
/*
31
 * Only handle DECstations that have an LK201 interface.
32
 * Maxine uses LK501 at the Access.Bus and various DECsystems
33
 * have no keyboard interface at all.
34
 */
35
#define LK_IFACE        (mips_machtype == MACH_DS23100    || \
36
                         mips_machtype == MACH_DS5000_200 || \
37
                         mips_machtype == MACH_DS5000_1XX || \
38
                         mips_machtype == MACH_DS5000_2X0)
39
/*
40
 * These use the Z8530 SCC.  Others use the DZ11.
41
 */
42
#define LK_IFACE_ZS     (mips_machtype == MACH_DS5000_1XX || \
43
                         mips_machtype == MACH_DS5000_2X0)
44
 
45
/* Simple translation table for the SysRq keys */
46
 
47
#ifdef CONFIG_MAGIC_SYSRQ
48
/*
49
 * Actually no translation at all, at least until we figure out
50
 * how to define SysRq for LK201 and friends. --macro
51
 */
52
unsigned char lk201_sysrq_xlate[128];
53
unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
54
 
55
unsigned char kbd_sysrq_key = -1;
56
#endif
57
 
58
#define KEYB_LINE       3
59
 
60
static int __init lk201_init(struct dec_serial *);
61
static void __init lk201_info(struct dec_serial *);
62
static void lk201_kbd_rx_char(unsigned char, unsigned char);
63
 
64
struct zs_hook lk201_kbdhook = {
65
        .init_channel   = lk201_init,
66
        .init_info      = lk201_info,
67
        .rx_char        = NULL,
68
        .poll_rx_char   = NULL,
69
        .poll_tx_char   = NULL,
70
        .cflags         = B4800 | CS8 | CSTOPB | CLOCAL
71
};
72
 
73
/*
74
 * This is used during keyboard initialisation
75
 */
76
static unsigned char lk201_reset_string[] = {
77
        LK_CMD_SET_DEFAULTS,
78
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
79
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
80
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
81
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
82
        LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
83
        LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
84
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
85
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
86
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
87
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
88
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
89
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
90
        LK_CMD_MODE(LK_MODE_DOWN, 13),
91
        LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
92
        LK_CMD_DIS_KEYCLK,
93
        LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
94
};
95
 
96
static struct dec_serial* lk201kbd_info;
97
 
98
static int lk201_send(struct dec_serial *info, unsigned char ch)
99
{
100
        if (info->hook->poll_tx_char(info, ch)) {
101
                printk(KERN_ERR "lk201: transmit timeout\n");
102
                return -EIO;
103
        }
104
        return 0;
105
}
106
 
107
static inline int lk201_get_id(struct dec_serial *info)
108
{
109
        return lk201_send(info, LK_CMD_REQ_ID);
110
}
111
 
112
static int lk201_reset(struct dec_serial *info)
113
{
114
        int i, r;
115
 
116
        for (i = 0; i < sizeof(lk201_reset_string); i++) {
117
                r = lk201_send(info, lk201_reset_string[i]);
118
                if (r < 0)
119
                        return r;
120
        }
121
        return 0;
122
}
123
 
124
static void lk201_report(unsigned char id[6])
125
{
126
        char *report = "lk201: keyboard attached, ";
127
 
128
        switch (id[2]) {
129
        case LK_STAT_PWRUP_OK:
130
                printk(KERN_INFO "%sself-test OK\n", report);
131
                break;
132
        case LK_STAT_PWRUP_KDOWN:
133
                /* The keyboard will resend the power-up ID
134
                   after all keys are released, so we don't
135
                   bother handling the error specially.  Still
136
                   there may be a short-circuit inside.
137
                 */
138
                printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n",
139
                       report, id[3]);
140
                break;
141
        case LK_STAT_PWRUP_ERROR:
142
                printk(KERN_ERR "%sself-test failure\n", report);
143
                break;
144
        default:
145
                printk(KERN_ERR "%sunknown error: 0x%02x\n",
146
                       report, id[2]);
147
        }
148
}
149
 
150
static void lk201_id(unsigned char id[6])
151
{
152
        /*
153
         * Report whether there is an LK201 or an LK401
154
         * The LK401 has ALT keys...
155
         */
156
        switch (id[4]) {
157
        case 1:
158
                printk(KERN_INFO "lk201: LK201 detected\n");
159
                break;
160
        case 2:
161
                printk(KERN_INFO "lk201: LK401 detected\n");
162
                break;
163
        case 3:
164
                printk(KERN_INFO "lk201: LK443 detected\n");
165
                break;
166
        case 4:
167
                printk(KERN_INFO "lk201: LK421 detected\n");
168
                break;
169
        default:
170
                printk(KERN_WARNING
171
                       "lk201: unknown keyboard detected, ID %d\n", id[4]);
172
                printk(KERN_WARNING "lk201: ... please report to "
173
                       "<linux-mips@linux-mips.org>\n");
174
        }
175
}
176
 
177
#define DEFAULT_KEYB_REP_DELAY  (250/5) /* [5ms] */
178
#define DEFAULT_KEYB_REP_RATE   30      /* [cps] */
179
 
180
static struct kbd_repeat kbdrate = {
181
        DEFAULT_KEYB_REP_DELAY,
182
        DEFAULT_KEYB_REP_RATE
183
};
184
 
185
static void parse_kbd_rate(struct kbd_repeat *r)
186
{
187
        if (r->delay <= 0)
188
                r->delay = kbdrate.delay;
189
        if (r->rate <= 0)
190
                r->rate = kbdrate.rate;
191
 
192
        if (r->delay < 5)
193
                r->delay = 5;
194
        if (r->delay > 630)
195
                r->delay = 630;
196
        if (r->rate < 12)
197
                r->rate = 12;
198
        if (r->rate > 127)
199
                r->rate = 127;
200
        if (r->rate == 125)
201
                r->rate = 124;
202
}
203
 
204
static int write_kbd_rate(struct kbd_repeat *rep)
205
{
206
        struct dec_serial* info = lk201kbd_info;
207
        int delay, rate;
208
        int i;
209
 
210
        delay = rep->delay / 5;
211
        rate = rep->rate;
212
        for (i = 0; i < 4; i++) {
213
                if (info->hook->poll_tx_char(info, LK_CMD_RPT_RATE(i)))
214
                        return 1;
215
                if (info->hook->poll_tx_char(info, LK_PARAM_DELAY(delay)))
216
                        return 1;
217
                if (info->hook->poll_tx_char(info, LK_PARAM_RATE(rate)))
218
                        return 1;
219
        }
220
        return 0;
221
}
222
 
223
static int lk201kbd_rate(struct kbd_repeat *rep)
224
{
225
        if (rep == NULL)
226
                return -EINVAL;
227
 
228
        parse_kbd_rate(rep);
229
 
230
        if (write_kbd_rate(rep)) {
231
                memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
232
                return -EIO;
233
        }
234
 
235
        memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
236
 
237
        return 0;
238
}
239
 
240
static void lk201kd_mksound(unsigned int hz, unsigned int ticks)
241
{
242
        struct dec_serial* info = lk201kbd_info;
243
 
244
        if (!ticks)
245
                return;
246
 
247
        /*
248
         * Can't set frequency and we "approximate"
249
         * duration by volume. ;-)
250
         */
251
        ticks /= HZ / 32;
252
        if (ticks > 7)
253
                ticks = 7;
254
        ticks = 7 - ticks;
255
 
256
        if (info->hook->poll_tx_char(info, LK_CMD_ENB_BELL))
257
                return;
258
        if (info->hook->poll_tx_char(info, LK_PARAM_VOLUME(ticks)))
259
                return;
260
        if (info->hook->poll_tx_char(info, LK_CMD_BELL))
261
                return;
262
}
263
 
264
void kbd_leds(unsigned char leds)
265
{
266
        struct dec_serial* info = lk201kbd_info;
267
        unsigned char l = 0;
268
 
269
        if (!info)              /* FIXME */
270
                return;
271
 
272
        /* FIXME -- Only Hold and Lock LEDs for now. --macro */
273
        if (leds & LED_SCR)
274
                l |= LK_LED_HOLD;
275
        if (leds & LED_CAP)
276
                l |= LK_LED_LOCK;
277
 
278
        if (info->hook->poll_tx_char(info, LK_CMD_LEDS_ON))
279
                return;
280
        if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(l)))
281
                return;
282
        if (info->hook->poll_tx_char(info, LK_CMD_LEDS_OFF))
283
                return;
284
        if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(~l)))
285
                return;
286
}
287
 
288
int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
289
{
290
        return -EINVAL;
291
}
292
 
293
int kbd_getkeycode(unsigned int scancode)
294
{
295
        return -EINVAL;
296
}
297
 
298
int kbd_translate(unsigned char scancode, unsigned char *keycode,
299
                  char raw_mode)
300
{
301
        *keycode = scancode;
302
        return 1;
303
}
304
 
305
char kbd_unexpected_up(unsigned char keycode)
306
{
307
        return 0x80;
308
}
309
 
310
static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
311
{
312
        static unsigned char id[6];
313
        static int id_i;
314
 
315
        static int shift_state = 0;
316
        static int prev_scancode;
317
        unsigned char c = scancodeRemap[ch];
318
 
319
        if (stat && stat != TTY_OVERRUN) {
320
                printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n",
321
                       stat);
322
                return;
323
        }
324
 
325
        /* Assume this is a power-up ID. */
326
        if (ch == LK_STAT_PWRUP_ID && !id_i) {
327
                id[id_i++] = ch;
328
                return;
329
        }
330
 
331
        /* Handle the power-up sequence. */
332
        if (id_i) {
333
                id[id_i++] = ch;
334
                if (id_i == 4) {
335
                        /* OK, the power-up concluded. */
336
                        lk201_report(id);
337
                        if (id[2] == LK_STAT_PWRUP_OK)
338
                                lk201_get_id(lk201kbd_info);
339
                        else {
340
                                id_i = 0;
341
                                printk(KERN_ERR "lk201: keyboard power-up "
342
                                       "error, skipping initialization\n");
343
                        }
344
                } else if (id_i == 6) {
345
                        /* We got the ID; report it and start operation. */
346
                        id_i = 0;
347
                        lk201_id(id);
348
                        lk201_reset(lk201kbd_info);
349
                }
350
                return;
351
        }
352
 
353
        /* Everything else is a scancode/status response. */
354
        id_i = 0;
355
        switch (ch) {
356
        case LK_STAT_RESUME_ERR:
357
        case LK_STAT_ERROR:
358
        case LK_STAT_INHIBIT_ACK:
359
        case LK_STAT_TEST_ACK:
360
        case LK_STAT_MODE_KEYDOWN:
361
        case LK_STAT_MODE_ACK:
362
                break;
363
        case LK_KEY_LOCK:
364
                shift_state ^= LK_LOCK;
365
                handle_scancode(c, (shift_state & LK_LOCK) ? 1 : 0);
366
                break;
367
        case LK_KEY_SHIFT:
368
                shift_state ^= LK_SHIFT;
369
                handle_scancode(c, (shift_state & LK_SHIFT) ? 1 : 0);
370
                break;
371
        case LK_KEY_CTRL:
372
                shift_state ^= LK_CTRL;
373
                handle_scancode(c, (shift_state & LK_CTRL) ? 1 : 0);
374
                break;
375
        case LK_KEY_COMP:
376
                shift_state ^= LK_COMP;
377
                handle_scancode(c, (shift_state & LK_COMP) ? 1 : 0);
378
                break;
379
        case LK_KEY_RELEASE:
380
                if (shift_state & LK_SHIFT)
381
                        handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
382
                if (shift_state & LK_CTRL)
383
                        handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
384
                if (shift_state & LK_COMP)
385
                        handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
386
                if (shift_state & LK_LOCK)
387
                        handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
388
                shift_state = 0;
389
                break;
390
        case LK_KEY_REPEAT:
391
                handle_scancode(prev_scancode, 1);
392
                break;
393
        default:
394
                prev_scancode = c;
395
                handle_scancode(c, 1);
396
                break;
397
        }
398
        tasklet_schedule(&keyboard_tasklet);
399
}
400
 
401
static void __init lk201_info(struct dec_serial *info)
402
{
403
}
404
 
405
static int __init lk201_init(struct dec_serial *info)
406
{
407
        /* First install handlers. */
408
        lk201kbd_info = info;
409
        kbd_rate = lk201kbd_rate;
410
        kd_mksound = lk201kd_mksound;
411
 
412
        info->hook->rx_char = lk201_kbd_rx_char;
413
 
414
        /* Then just issue a reset -- the handlers will do the rest. */
415
        lk201_send(info, LK_CMD_POWER_UP);
416
 
417
        return 0;
418
}
419
 
420
void __init kbd_init_hw(void)
421
{
422
        extern int register_zs_hook(unsigned int, struct zs_hook *);
423
        extern int unregister_zs_hook(unsigned int);
424
 
425
        /* Maxine uses LK501 at the Access.Bus. */
426
        if (!LK_IFACE)
427
                return;
428
 
429
        printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n");
430
 
431
        if (LK_IFACE_ZS) {
432
                /*
433
                 * kbd_init_hw() is being called before
434
                 * rs_init() so just register the kbd hook
435
                 * and let zs_init do the rest :-)
436
                 */
437
                if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
438
                        unregister_zs_hook(KEYB_LINE);
439
        } else {
440
                /*
441
                 * TODO: modify dz.c to allow similar hooks
442
                 * for LK201 handling on DS2100, DS3100, and DS5000/200
443
                 */
444
                printk(KERN_ERR "lk201: support for DZ11 not yet ready.\n");
445
        }
446
}

powered by: WebSVN 2.1.0

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