cleanup
[linux-2.4.21-pre4.git] / drivers / char / amikeyb.c
1 /*
2  * linux/arch/m68k/amiga/amikeyb.c
3  *
4  * Amiga Keyboard driver for Linux/m68k
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive
8  * for more details.
9  */
10
11 /*
12  * Amiga support by Hamish Macdonald
13  */
14
15 #include <linux/config.h>
16 #include <linux/types.h>
17 #include <linux/sched.h>
18 #include <linux/interrupt.h>
19 #include <linux/errno.h>
20 #include <linux/keyboard.h>
21 #include <linux/kd.h>
22 #include <linux/kbd_ll.h>
23 #include <linux/delay.h>
24 #include <linux/timer.h>
25 #include <linux/random.h>
26 #include <linux/kernel.h>
27 #include <linux/ioport.h>
28 #include <linux/init.h>
29 #include <linux/kbd_kern.h>
30
31 #include <asm/amigaints.h>
32 #include <asm/amigahw.h>
33 #include <asm/irq.h>
34
35 #define AMIKEY_CAPS     (0x62)
36 #define BREAK_MASK      (0x80)
37 #define RESET_WARNING   (0xf0)  /* before rotation */
38
39 static u_short amiplain_map[NR_KEYS] __initdata = {
40         0xf060, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
41         0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf05c, 0xf200, 0xf300,
42         0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
43         0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf200, 0xf301, 0xf302, 0xf303,
44         0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b,
45         0xfb6c, 0xf03b, 0xf027, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
46         0xf200, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, 0xfb62, 0xfb6e, 0xfb6d,
47         0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
48         0xf020, 0xf07f, 0xf009, 0xf30e, 0xf201, 0xf01b, 0xf07f, 0xf200,
49         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
50         0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
51         0xf108, 0xf109, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf30a, 0xf11b,
52         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
53         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
54         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
55         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
56 };
57
58 static u_short amishift_map[NR_KEYS] __initdata = {
59         0xf07e, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026,
60         0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07c, 0xf200, 0xf300,
61         0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
62         0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf200, 0xf301, 0xf302, 0xf303,
63         0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b,
64         0xfb4c, 0xf03a, 0xf022, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
65         0xf200, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, 0xfb42, 0xfb4e, 0xfb4d,
66         0xf03c, 0xf03e, 0xf03f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
67         0xf020, 0xf07f, 0xf009, 0xf30e, 0xf201, 0xf01b, 0xf07f, 0xf200,
68         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
69         0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, 0xf10f, 0xf110, 0xf111,
70         0xf112, 0xf113, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf203,
71         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
72         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
73         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
74         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
75 };
76
77 static u_short amialtgr_map[NR_KEYS] __initdata = {
78         0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, 0xf07b,
79         0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, 0xf300,
80         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
81         0xf200, 0xf200, 0xf200, 0xf07e, 0xf200, 0xf301, 0xf302, 0xf303,
82         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
83         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
84         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
85         0xf200, 0xf200, 0xf200, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
86         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
87         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
88         0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, 0xf511, 0xf512, 0xf513,
89         0xf514, 0xf515, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf204,
90         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
91         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
92         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
93         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
94 };
95
96 static u_short amictrl_map[NR_KEYS] __initdata = {
97         0xf000, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
98         0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf01c, 0xf200, 0xf300,
99         0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
100         0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf200, 0xf301, 0xf302, 0xf303,
101         0xf001, 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b,
102         0xf00c, 0xf200, 0xf007, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
103         0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, 0xf002, 0xf00e, 0xf00d,
104         0xf200, 0xf200, 0xf07f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
105         0xf000, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
106         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
107         0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
108         0xf108, 0xf109, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf202,
109         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
110         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
111         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
112         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
113 };
114
115 static u_short amishift_ctrl_map[NR_KEYS] __initdata = {
116         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
117         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf300,
118         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
119         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302, 0xf303,
120         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
121         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
122         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
123         0xf200, 0xf200, 0xf200, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
124         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
125         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
126         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
127         0xf200, 0xf200, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf200,
128         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
129         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
130         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
131         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
132 };
133
134 static u_short amialt_map[NR_KEYS] __initdata = {
135         0xf860, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, 0xf837,
136         0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf85c, 0xf200, 0xf900,
137         0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
138         0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf200, 0xf901, 0xf902, 0xf903,
139         0xf861, 0xf873, 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b,
140         0xf86c, 0xf83b, 0xf827, 0xf200, 0xf200, 0xf904, 0xf905, 0xf906,
141         0xf200, 0xf87a, 0xf878, 0xf863, 0xf876, 0xf862, 0xf86e, 0xf86d,
142         0xf82c, 0xf82e, 0xf82f, 0xf200, 0xf310, 0xf907, 0xf908, 0xf909,
143         0xf820, 0xf87f, 0xf809, 0xf30e, 0xf80d, 0xf81b, 0xf87f, 0xf200,
144         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
145         0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506, 0xf507,
146         0xf508, 0xf509, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf204,
147         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
148         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
149         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
150         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
151 };
152
153 static u_short amictrl_alt_map[NR_KEYS] __initdata = {
154         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
155         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf300,
156         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
157         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302, 0xf303,
158         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
159         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
160         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
161         0xf200, 0xf200, 0xf200, 0xf200, 0xf20c, 0xf307, 0xf308, 0xf309,
162         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
163         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
164         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
165         0xf200, 0xf200, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf200,
166         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
167         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
168         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
169         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
170 };
171
172 #define DEFAULT_KEYB_REP_DELAY  (HZ/4)
173 #define DEFAULT_KEYB_REP_RATE   (HZ/25)
174
175 /* These could be settable by some ioctl() in future... */
176 static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
177 static unsigned int key_repeat_rate  = DEFAULT_KEYB_REP_RATE;
178
179 static unsigned char rep_scancode;
180 static void amikeyb_rep(unsigned long ignore);
181 static struct timer_list amikeyb_rep_timer = {function: amikeyb_rep};
182
183 static void amikeyb_rep(unsigned long ignore)
184 {
185     unsigned long flags;
186     save_flags(flags);
187     cli();
188
189     kbd_pt_regs = NULL;
190
191     amikeyb_rep_timer.expires = jiffies + key_repeat_rate;
192     add_timer(&amikeyb_rep_timer);
193     handle_scancode(rep_scancode, 1);
194
195     restore_flags(flags);
196 }
197
198 static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
199 {
200     unsigned char scancode, break_flag, keycode;
201     static int reset_warning = 0;
202
203     /* save frame for register dump */
204     kbd_pt_regs = fp;
205
206     /* get and invert scancode (keyboard is active low) */
207     scancode = ~ciaa.sdr;
208
209     /* switch SP pin to output for handshake */
210     ciaa.cra |= 0x40;
211
212 #if 0 /* No longer used */
213     /*
214      *  On receipt of the second RESET_WARNING, we must not pull KDAT high
215      *  again to delay the hard reset as long as possible.
216      *
217      *  Note that not all keyboards send reset warnings...
218      */
219     if (reset_warning)
220         if (scancode == RESET_WARNING) {
221             printk(KERN_ALERT "amikeyb: Ctrl-Amiga-Amiga reset warning!!\n"
222                    "The system will be reset within 10 seconds!!\n");
223             /* Panic doesn't sync from within an interrupt, so we do nothing */
224             return;
225         } else
226             /* Probably a mistake, cancel the alert */
227             reset_warning = 0;
228 #endif
229
230     /* wait until 85 us have expired */
231     udelay(85);
232     /* switch CIA serial port to input mode */
233     ciaa.cra &= ~0x40;
234
235     tasklet_schedule(&keyboard_tasklet);
236
237     /* rotate scan code to get up/down bit in proper position */
238     scancode = ((scancode >> 1) & 0x7f) | ((scancode << 7) & 0x80);
239
240     /*
241      * Check make/break first
242      */
243     break_flag = scancode & BREAK_MASK;
244     keycode = scancode & (unsigned char)~BREAK_MASK;
245
246     if (keycode == AMIKEY_CAPS) {
247         /* if the key is CAPS, fake a press/release. */
248         handle_scancode(AMIKEY_CAPS, 1);
249         handle_scancode(AMIKEY_CAPS, 0);
250     } else if (keycode < 0x78) {
251         /* handle repeat */
252         if (break_flag) {
253             del_timer(&amikeyb_rep_timer);
254             rep_scancode = 0;
255         } else {
256             del_timer(&amikeyb_rep_timer);
257             rep_scancode = keycode;
258             amikeyb_rep_timer.expires = jiffies + key_repeat_delay;
259             add_timer(&amikeyb_rep_timer);
260         }
261         handle_scancode(keycode, !break_flag);
262     } else
263         switch (keycode) {
264             case 0x78:
265                 reset_warning = 1;
266                 break;
267             case 0x79:
268                 printk(KERN_WARNING "amikeyb: keyboard lost sync\n");
269                 break;
270             case 0x7a:
271                 printk(KERN_WARNING "amikeyb: keyboard buffer overflow\n");
272                 break;
273 #if 0 /* obsolete according to the HRM */
274             case 0x7b:
275                 printk(KERN_WARNING "amikeyb: keyboard controller failure\n");
276                 break;
277 #endif
278             case 0x7c:
279                 printk(KERN_ERR "amikeyb: keyboard selftest failure\n");
280                 break;
281             case 0x7d:
282                 printk(KERN_INFO "amikeyb: initiate power-up key stream\n");
283                 break;
284             case 0x7e:
285                 printk(KERN_INFO "amikeyb: terminate power-up key stream\n");
286                 break;
287 #if 0 /* obsolete according to the HRM */
288             case 0x7f:
289                 printk(KERN_WARNING "amikeyb: keyboard interrupt\n");
290                 break;
291 #endif
292             default:
293                 printk(KERN_WARNING "amikeyb: unknown keyboard communication code 0x%02x\n",
294                        scancode);
295                 break;
296         }
297 }
298
299 int __init amiga_keyb_init(void)
300 {
301     if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
302         return -EIO;
303     if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
304         return -EBUSY;
305
306     /* setup key map */
307     memcpy(key_maps[0], amiplain_map, sizeof(plain_map));
308     memcpy(key_maps[1], amishift_map, sizeof(plain_map));
309     memcpy(key_maps[2], amialtgr_map, sizeof(plain_map));
310     memcpy(key_maps[4], amictrl_map, sizeof(plain_map));
311     memcpy(key_maps[5], amishift_ctrl_map, sizeof(plain_map));
312     memcpy(key_maps[8], amialt_map, sizeof(plain_map));
313     memcpy(key_maps[12], amictrl_alt_map, sizeof(plain_map));
314
315     /*
316      * Initialize serial data direction.
317      */
318     ciaa.cra &= ~0x41;       /* serial data in, turn off TA */
319
320     /*
321      * arrange for processing of keyboard interrupt
322      */
323     request_irq(IRQ_AMIGA_CIAA_SP, keyboard_interrupt, 0, "keyboard", NULL);
324
325     return 0;
326 }
327
328 int amiga_kbdrate( struct kbd_repeat *k )
329 {
330     if (k->delay > 0) {
331         /* convert from msec to jiffies */
332         key_repeat_delay = (k->delay * HZ + 500) / 1000;
333         if (key_repeat_delay < 1)
334             key_repeat_delay = 1;
335     }
336     if (k->rate > 0) {
337         key_repeat_rate = (k->rate * HZ + 500) / 1000;
338         if (key_repeat_rate < 1)
339             key_repeat_rate = 1;
340     }
341
342     k->delay = key_repeat_delay * 1000 / HZ;
343     k->rate  = key_repeat_rate  * 1000 / HZ;
344     
345     return( 0 );
346 }
347
348 int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
349 {
350 #ifdef CONFIG_MAGIC_SYSRQ
351         /* SHIFT+ALTGR+HELP pressed? */
352         if ((keycode == 0x5f) && ((shift_state & 0xff) == 3))
353                 *keycodep = 0xff;
354         else
355 #endif
356                 *keycodep = keycode;
357         return 1;
358 }
359