ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / tc / lk201.c
1 /*
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  */
8 #include <linux/errno.h>
9 #include <linux/tty.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/delay.h>
13 #include <linux/kbd_ll.h>
14 #include <asm/wbflush.h>
15 #include <asm/dec/tc.h>
16 #include <asm/dec/machtype.h>
17
18 #include "zs.h"
19 #include "lk201.h"
20
21 /* Simple translation table for the SysRq keys */
22
23 #ifdef CONFIG_MAGIC_SYSRQ
24 /*
25  * Actually no translation at all, at least until we figure out
26  * how to define SysRq for LK201 and friends. --macro
27  */
28 unsigned char lk201_sysrq_xlate[128];
29 unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
30 #endif
31
32 #define KEYB_LINE       3
33
34 static int __init lk201_init(struct dec_serial *);
35 static void __init lk201_info(struct dec_serial *);
36 static void lk201_kbd_rx_char(unsigned char, unsigned char);
37
38 struct zs_hook lk201_kbdhook = {
39         .init_channel   = lk201_init,
40         .init_info      = lk201_info,
41         .cflags         = B4800 | CS8 | CSTOPB | CLOCAL
42 };
43
44 /*
45  * This is used during keyboard initialisation
46  */
47 static unsigned char lk201_reset_string[] = {
48         LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */
49         LK_CMD_SET_DEFAULTS,
50         LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
51         LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
52         LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
53         LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
54         LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
55         LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
56         LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
57         LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
58         LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
59         LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
60         LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
61         LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
62         LK_CMD_MODE(LK_MODE_DOWN, 13),
63         LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
64         LK_CMD_ENB_RPT,
65         LK_CMD_DIS_KEYCLK,
66         LK_CMD_RESUME,
67         LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
68         LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
69 };
70
71 static int __init lk201_reset(struct dec_serial *info)
72 {
73         int i;
74
75         for (i = 0; i < sizeof(lk201_reset_string); i++)
76                 if (info->hook->poll_tx_char(info, lk201_reset_string[i])) {
77                         printk("%s transmit timeout\n", __FUNCTION__);
78                         return -EIO;
79                 }
80         return 0;
81 }
82
83 void kbd_leds(unsigned char leds)
84 {
85         return;
86 }
87
88 int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
89 {
90         return -EINVAL;
91 }
92
93 int kbd_getkeycode(unsigned int scancode)
94 {
95         return -EINVAL;
96 }
97
98 int kbd_translate(unsigned char scancode, unsigned char *keycode,
99                   char raw_mode)
100 {
101         *keycode = scancode;
102         return 1;
103 }
104
105 char kbd_unexpected_up(unsigned char keycode)
106 {
107         return 0x80;
108 }
109
110 static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
111 {
112         static int shift_state = 0;
113         static int prev_scancode;
114         unsigned char c = scancodeRemap[ch];
115
116         if (!stat || stat == 4) {
117                 switch (ch) {
118                 case LK_KEY_ACK:
119                         break;
120                 case LK_KEY_LOCK:
121                         shift_state ^= LK_LOCK;
122                         handle_scancode(c, shift_state && LK_LOCK ? 1 : 0);
123                         break;
124                 case LK_KEY_SHIFT:
125                         shift_state ^= LK_SHIFT;
126                         handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0);
127                         break;
128                 case LK_KEY_CTRL:
129                         shift_state ^= LK_CTRL;
130                         handle_scancode(c, shift_state && LK_CTRL ? 1 : 0);
131                         break;
132                 case LK_KEY_COMP:
133                         shift_state ^= LK_COMP;
134                         handle_scancode(c, shift_state && LK_COMP ? 1 : 0);
135                         break;
136                 case LK_KEY_RELEASE:
137                         if (shift_state & LK_SHIFT)
138                                 handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
139                         if (shift_state & LK_CTRL)
140                                 handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
141                         if (shift_state & LK_COMP)
142                                 handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
143                         if (shift_state & LK_LOCK)
144                                 handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
145                         shift_state = 0;
146                         break;
147                 case LK_KEY_REPEAT:
148                         handle_scancode(prev_scancode, 1);
149                         break;
150                 default:
151                         prev_scancode = c;
152                         handle_scancode(c, 1);
153                         break;
154                 }
155         } else
156                 printk("Error reading LKx01 keyboard: 0x%02x\n", stat);
157 }
158
159 static void __init lk201_info(struct dec_serial *info)
160 {
161 }
162
163 static int __init lk201_init(struct dec_serial *info)
164 {
165         unsigned int ch, id = 0;
166         int result;
167
168         printk("DECstation LK keyboard driver v0.04... ");
169
170         result = lk201_reset(info);
171         if (result)
172                 return result;
173         mdelay(10);
174
175         /*
176          * Detect whether there is an LK201 or an LK401
177          * The LK401 has ALT keys...
178          */
179         info->hook->poll_tx_char(info, LK_CMD_REQ_ID);
180         while ((ch = info->hook->poll_rx_char(info)) > 0)
181                 id = ch;
182
183         switch (id) {
184         case 1:
185                 printk("LK201 detected\n");
186                 break;
187         case 2:
188                 printk("LK401 detected\n");
189                 break;
190         default:
191                 printk("unknown keyboard, ID %d,\n", id);
192                 printk("... please report to <linux-mips@oss.sgi.com>\n");
193         }
194
195         /*
196          * now we're ready
197          */
198         info->hook->rx_char = lk201_kbd_rx_char;
199
200         return 0;
201 }
202
203 void __init kbd_init_hw(void)
204 {
205         extern int register_zs_hook(unsigned int, struct zs_hook *);
206         extern int unregister_zs_hook(unsigned int);
207
208         if (TURBOCHANNEL) {
209                 if (mips_machtype != MACH_DS5000_XX) {
210                         /*
211                          * This is not a MAXINE, so:
212                          *
213                          * kbd_init_hw() is being called before
214                          * rs_init() so just register the kbd hook
215                          * and let zs_init do the rest :-)
216                          */
217                         if (mips_machtype == MACH_DS5000_200)
218                                 printk("LK201 Support for DS5000/200 not yet ready ...\n");
219                         else
220                                 if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
221                                         unregister_zs_hook(KEYB_LINE);
222                 }
223         } else {
224                 /*
225                  * TODO: modify dz.c to allow similar hooks
226                  * for LK201 handling on DS2100, DS3100, and DS5000/200
227                  */
228                 printk("LK201 Support for DS3100 not yet ready ...\n");
229         }
230 }
231
232
233
234