aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorMichael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de>2007-05-01 16:32:38 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-04 20:59:05 -0400
commitc04cb856e20a8bf68762d60737b84328c1ab5900 (patch)
treec8046787b2fa708b0a5a0972444bac9df67fadff /arch/m68k
parent3130d905ba86d5f2636b2f45d5beefe82cb03df6 (diff)
m68k: Atari keyboard and mouse support.
Atari keyboard and mouse support. (reformating and Kconfig fixes by Roman Zippel) Signed-off-by: Michael Schmitz <schmitz@debian.org> Signed-off-by: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/Kconfig3
-rw-r--r--arch/m68k/atari/Makefile1
-rw-r--r--arch/m68k/atari/atakeyb.c730
3 files changed, 734 insertions, 0 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index a8e1e604dfa8..b8536c7c0877 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -409,6 +409,9 @@ config STRAM_PROC
409 help 409 help
410 Say Y here to report ST-RAM usage statistics in /proc/stram. 410 Say Y here to report ST-RAM usage statistics in /proc/stram.
411 411
412config ATARI_KBD_CORE
413 bool
414
412config HEARTBEAT 415config HEARTBEAT
413 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40 416 bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
414 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300 417 default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 8cb6236b39db..2cb86191f0aa 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -8,3 +8,4 @@ obj-y := config.o time.o debug.o ataints.o stdma.o \
8ifeq ($(CONFIG_PCI),y) 8ifeq ($(CONFIG_PCI),y)
9obj-$(CONFIG_HADES) += hades-pci.o 9obj-$(CONFIG_HADES) += hades-pci.o
10endif 10endif
11obj-$(CONFIG_ATARI_KBD_CORE) += atakeyb.o
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
new file mode 100644
index 000000000000..1c29603b16b3
--- /dev/null
+++ b/arch/m68k/atari/atakeyb.c
@@ -0,0 +1,730 @@
1/*
2 * linux/atari/atakeyb.c
3 *
4 * Atari Keyboard driver for 680x0 Linux
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 * Atari support by Robert de Vries
13 * enhanced by Bjoern Brauel and Roman Hodek
14 */
15
16#include <linux/sched.h>
17#include <linux/kernel.h>
18#include <linux/interrupt.h>
19#include <linux/errno.h>
20#include <linux/keyboard.h>
21#include <linux/delay.h>
22#include <linux/timer.h>
23#include <linux/kd.h>
24#include <linux/random.h>
25#include <linux/init.h>
26#include <linux/kbd_kern.h>
27
28#include <asm/atariints.h>
29#include <asm/atarihw.h>
30#include <asm/atarikb.h>
31#include <asm/atari_joystick.h>
32#include <asm/irq.h>
33
34static void atakeyb_rep(unsigned long ignore);
35extern unsigned int keymap_count;
36
37/* Hook for MIDI serial driver */
38void (*atari_MIDI_interrupt_hook) (void);
39/* Hook for mouse driver */
40void (*atari_mouse_interrupt_hook) (char *);
41/* Hook for keyboard inputdev driver */
42void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
43/* Hook for mouse inputdev driver */
44void (*atari_input_mouse_interrupt_hook) (char *);
45
46/* variables for IKBD self test: */
47
48/* state: 0: off; >0: in progress; >1: 0xf1 received */
49static volatile int ikbd_self_test;
50/* timestamp when last received a char */
51static volatile unsigned long self_test_last_rcv;
52/* bitmap of keys reported as broken */
53static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
54
55#define BREAK_MASK (0x80)
56
57/*
58 * ++roman: The following changes were applied manually:
59 *
60 * - The Alt (= Meta) key works in combination with Shift and
61 * Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
62 * Meta-Ctrl-A (0x81) ...
63 *
64 * - The parentheses on the keypad send '(' and ')' with all
65 * modifiers (as would do e.g. keypad '+'), but they cannot be used as
66 * application keys (i.e. sending Esc O c).
67 *
68 * - HELP and UNDO are mapped to be F21 and F24, resp, that send the
69 * codes "\E[M" and "\E[P". (This is better than the old mapping to
70 * F11 and F12, because these codes are on Shift+F1/2 anyway.) This
71 * way, applications that allow their own keyboard mappings
72 * (e.g. tcsh, X Windows) can be configured to use them in the way
73 * the label suggests (providing help or undoing).
74 *
75 * - Console switching is done with Alt+Fx (consoles 1..10) and
76 * Shift+Alt+Fx (consoles 11..20).
77 *
78 * - The misc. special function implemented in the kernel are mapped
79 * to the following key combinations:
80 *
81 * ClrHome -> Home/Find
82 * Shift + ClrHome -> End/Select
83 * Shift + Up -> Page Up
84 * Shift + Down -> Page Down
85 * Alt + Help -> show system status
86 * Shift + Help -> show memory info
87 * Ctrl + Help -> show registers
88 * Ctrl + Alt + Del -> Reboot
89 * Alt + Undo -> switch to last console
90 * Shift + Undo -> send interrupt
91 * Alt + Insert -> stop/start output (same as ^S/^Q)
92 * Alt + Up -> Scroll back console (if implemented)
93 * Alt + Down -> Scroll forward console (if implemented)
94 * Alt + CapsLock -> NumLock
95 *
96 * ++Andreas:
97 *
98 * - Help mapped to K_HELP
99 * - Undo mapped to K_UNDO (= K_F246)
100 * - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
101 */
102
103static u_short ataplain_map[NR_KEYS] __initdata = {
104 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
105 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
106 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
107 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
108 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
109 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
110 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200,
111 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
112 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
113 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
114 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
115 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
116 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
117 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
118 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
119 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
120};
121
122typedef enum kb_state_t {
123 KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
124} KB_STATE_T;
125
126#define IS_SYNC_CODE(sc) ((sc) >= 0x04 && (sc) <= 0xfb)
127
128typedef struct keyboard_state {
129 unsigned char buf[6];
130 int len;
131 KB_STATE_T state;
132} KEYBOARD_STATE;
133
134KEYBOARD_STATE kb_state;
135
136#define DEFAULT_KEYB_REP_DELAY (HZ/4)
137#define DEFAULT_KEYB_REP_RATE (HZ/25)
138
139/* These could be settable by some ioctl() in future... */
140static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
141static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
142
143static unsigned char rep_scancode;
144static struct timer_list atakeyb_rep_timer = {
145 .function = atakeyb_rep,
146};
147
148static void atakeyb_rep(unsigned long ignore)
149{
150 /* Disable keyboard for the time we call handle_scancode(), else a race
151 * in the keyboard tty queue may happen */
152 atari_disable_irq(IRQ_MFP_ACIA);
153 del_timer(&atakeyb_rep_timer);
154
155 /* A keyboard int may have come in before we disabled the irq, so
156 * double-check whether rep_scancode is still != 0 */
157 if (rep_scancode) {
158 init_timer(&atakeyb_rep_timer);
159 atakeyb_rep_timer.expires = jiffies + key_repeat_rate;
160 add_timer(&atakeyb_rep_timer);
161
162 //handle_scancode(rep_scancode, 1);
163 if (atari_input_keyboard_interrupt_hook)
164 atari_input_keyboard_interrupt_hook(rep_scancode, 1);
165 }
166
167 atari_enable_irq(IRQ_MFP_ACIA);
168}
169
170
171/* ++roman: If a keyboard overrun happened, we can't tell in general how much
172 * bytes have been lost and in which state of the packet structure we are now.
173 * This usually causes keyboards bytes to be interpreted as mouse movements
174 * and vice versa, which is very annoying. It seems better to throw away some
175 * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
176 * introduced the RESYNC state for IKBD data. In this state, the bytes up to
177 * one that really looks like a key event (0x04..0xf2) or the start of a mouse
178 * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
179 * speeds up the resynchronization of the event structure, even if maybe a
180 * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
181 * it's really hard to decide whether they're mouse or keyboard bytes. Since
182 * overruns usually occur when moving the Atari mouse rapidly, they're seen as
183 * mouse bytes here. If this is wrong, only a make code of the keyboard gets
184 * lost, which isn't too bad. Loosing a break code would be disastrous,
185 * because then the keyboard repeat strikes...
186 */
187
188static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
189{
190 u_char acia_stat;
191 int scancode;
192 int break_flag;
193
194repeat:
195 if (acia.mid_ctrl & ACIA_IRQ)
196 if (atari_MIDI_interrupt_hook)
197 atari_MIDI_interrupt_hook();
198 acia_stat = acia.key_ctrl;
199 /* check out if the interrupt came from this ACIA */
200 if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
201 return IRQ_HANDLED;
202
203 if (acia_stat & ACIA_OVRN) {
204 /* a very fast typist or a slow system, give a warning */
205 /* ...happens often if interrupts were disabled for too long */
206 printk(KERN_DEBUG "Keyboard overrun\n");
207 scancode = acia.key_data;
208 /* Turn off autorepeating in case a break code has been lost */
209 del_timer(&atakeyb_rep_timer);
210 rep_scancode = 0;
211 if (ikbd_self_test)
212 /* During self test, don't do resyncing, just process the code */
213 goto interpret_scancode;
214 else if (IS_SYNC_CODE(scancode)) {
215 /* This code seem already to be the start of a new packet or a
216 * single scancode */
217 kb_state.state = KEYBOARD;
218 goto interpret_scancode;
219 } else {
220 /* Go to RESYNC state and skip this byte */
221 kb_state.state = RESYNC;
222 kb_state.len = 1; /* skip max. 1 another byte */
223 goto repeat;
224 }
225 }
226
227 if (acia_stat & ACIA_RDRF) {
228 /* received a character */
229 scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */
230 tasklet_schedule(&keyboard_tasklet);
231 interpret_scancode:
232 switch (kb_state.state) {
233 case KEYBOARD:
234 switch (scancode) {
235 case 0xF7:
236 kb_state.state = AMOUSE;
237 kb_state.len = 0;
238 break;
239
240 case 0xF8:
241 case 0xF9:
242 case 0xFA:
243 case 0xFB:
244 kb_state.state = RMOUSE;
245 kb_state.len = 1;
246 kb_state.buf[0] = scancode;
247 break;
248
249 case 0xFC:
250 kb_state.state = CLOCK;
251 kb_state.len = 0;
252 break;
253
254 case 0xFE:
255 case 0xFF:
256 kb_state.state = JOYSTICK;
257 kb_state.len = 1;
258 kb_state.buf[0] = scancode;
259 break;
260
261 case 0xF1:
262 /* during self-test, note that 0xf1 received */
263 if (ikbd_self_test) {
264 ++ikbd_self_test;
265 self_test_last_rcv = jiffies;
266 break;
267 }
268 /* FALL THROUGH */
269
270 default:
271 break_flag = scancode & BREAK_MASK;
272 scancode &= ~BREAK_MASK;
273 if (ikbd_self_test) {
274 /* Scancodes sent during the self-test stand for broken
275 * keys (keys being down). The code *should* be a break
276 * code, but nevertheless some AT keyboard interfaces send
277 * make codes instead. Therefore, simply ignore
278 * break_flag...
279 */
280 int keyval = plain_map[scancode], keytyp;
281
282 set_bit(scancode, broken_keys);
283 self_test_last_rcv = jiffies;
284 keyval = plain_map[scancode];
285 keytyp = KTYP(keyval) - 0xf0;
286 keyval = KVAL(keyval);
287
288 printk(KERN_WARNING "Key with scancode %d ", scancode);
289 if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
290 if (keyval < ' ')
291 printk("('^%c') ", keyval + '@');
292 else
293 printk("('%c') ", keyval);
294 }
295 printk("is broken -- will be ignored.\n");
296 break;
297 } else if (test_bit(scancode, broken_keys))
298 break;
299
300#if 0 // FIXME; hangs at boot
301 if (break_flag) {
302 del_timer(&atakeyb_rep_timer);
303 rep_scancode = 0;
304 } else {
305 del_timer(&atakeyb_rep_timer);
306 rep_scancode = scancode;
307 atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
308 add_timer(&atakeyb_rep_timer);
309 }
310#endif
311
312 // handle_scancode(scancode, !break_flag);
313 if (atari_input_keyboard_interrupt_hook)
314 atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
315 break;
316 }
317 break;
318
319 case AMOUSE:
320 kb_state.buf[kb_state.len++] = scancode;
321 if (kb_state.len == 5) {
322 kb_state.state = KEYBOARD;
323 /* not yet used */
324 /* wake up someone waiting for this */
325 }
326 break;
327
328 case RMOUSE:
329 kb_state.buf[kb_state.len++] = scancode;
330 if (kb_state.len == 3) {
331 kb_state.state = KEYBOARD;
332 if (atari_mouse_interrupt_hook)
333 atari_mouse_interrupt_hook(kb_state.buf);
334 }
335 break;
336
337 case JOYSTICK:
338 kb_state.buf[1] = scancode;
339 kb_state.state = KEYBOARD;
340#ifdef FIXED_ATARI_JOYSTICK
341 atari_joystick_interrupt(kb_state.buf);
342#endif
343 break;
344
345 case CLOCK:
346 kb_state.buf[kb_state.len++] = scancode;
347 if (kb_state.len == 6) {
348 kb_state.state = KEYBOARD;
349 /* wake up someone waiting for this.
350 But will this ever be used, as Linux keeps its own time.
351 Perhaps for synchronization purposes? */
352 /* wake_up_interruptible(&clock_wait); */
353 }
354 break;
355
356 case RESYNC:
357 if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
358 kb_state.state = KEYBOARD;
359 goto interpret_scancode;
360 }
361 kb_state.len--;
362 break;
363 }
364 }
365
366#if 0
367 if (acia_stat & ACIA_CTS)
368 /* cannot happen */;
369#endif
370
371 if (acia_stat & (ACIA_FE | ACIA_PE)) {
372 printk("Error in keyboard communication\n");
373 }
374
375 /* handle_scancode() can take a lot of time, so check again if
376 * some character arrived
377 */
378 goto repeat;
379}
380
381/*
382 * I write to the keyboard without using interrupts, I poll instead.
383 * This takes for the maximum length string allowed (7) at 7812.5 baud
384 * 8 data 1 start 1 stop bit: 9.0 ms
385 * If this takes too long for normal operation, interrupt driven writing
386 * is the solution. (I made a feeble attempt in that direction but I
387 * kept it simple for now.)
388 */
389void ikbd_write(const char *str, int len)
390{
391 u_char acia_stat;
392
393 if ((len < 1) || (len > 7))
394 panic("ikbd: maximum string length exceeded");
395 while (len) {
396 acia_stat = acia.key_ctrl;
397 if (acia_stat & ACIA_TDRE) {
398 acia.key_data = *str++;
399 len--;
400 }
401 }
402}
403
404/* Reset (without touching the clock) */
405void ikbd_reset(void)
406{
407 static const char cmd[2] = { 0x80, 0x01 };
408
409 ikbd_write(cmd, 2);
410
411 /*
412 * if all's well code 0xF1 is returned, else the break codes of
413 * all keys making contact
414 */
415}
416
417/* Set mouse button action */
418void ikbd_mouse_button_action(int mode)
419{
420 char cmd[2] = { 0x07, mode };
421
422 ikbd_write(cmd, 2);
423}
424
425/* Set relative mouse position reporting */
426void ikbd_mouse_rel_pos(void)
427{
428 static const char cmd[1] = { 0x08 };
429
430 ikbd_write(cmd, 1);
431}
432
433/* Set absolute mouse position reporting */
434void ikbd_mouse_abs_pos(int xmax, int ymax)
435{
436 char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
437
438 ikbd_write(cmd, 5);
439}
440
441/* Set mouse keycode mode */
442void ikbd_mouse_kbd_mode(int dx, int dy)
443{
444 char cmd[3] = { 0x0A, dx, dy };
445
446 ikbd_write(cmd, 3);
447}
448
449/* Set mouse threshold */
450void ikbd_mouse_thresh(int x, int y)
451{
452 char cmd[3] = { 0x0B, x, y };
453
454 ikbd_write(cmd, 3);
455}
456
457/* Set mouse scale */
458void ikbd_mouse_scale(int x, int y)
459{
460 char cmd[3] = { 0x0C, x, y };
461
462 ikbd_write(cmd, 3);
463}
464
465/* Interrogate mouse position */
466void ikbd_mouse_pos_get(int *x, int *y)
467{
468 static const char cmd[1] = { 0x0D };
469
470 ikbd_write(cmd, 1);
471
472 /* wait for returning bytes */
473}
474
475/* Load mouse position */
476void ikbd_mouse_pos_set(int x, int y)
477{
478 char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
479
480 ikbd_write(cmd, 6);
481}
482
483/* Set Y=0 at bottom */
484void ikbd_mouse_y0_bot(void)
485{
486 static const char cmd[1] = { 0x0F };
487
488 ikbd_write(cmd, 1);
489}
490
491/* Set Y=0 at top */
492void ikbd_mouse_y0_top(void)
493{
494 static const char cmd[1] = { 0x10 };
495
496 ikbd_write(cmd, 1);
497}
498
499/* Resume */
500void ikbd_resume(void)
501{
502 static const char cmd[1] = { 0x11 };
503
504 ikbd_write(cmd, 1);
505}
506
507/* Disable mouse */
508void ikbd_mouse_disable(void)
509{
510 static const char cmd[1] = { 0x12 };
511
512 ikbd_write(cmd, 1);
513}
514
515/* Pause output */
516void ikbd_pause(void)
517{
518 static const char cmd[1] = { 0x13 };
519
520 ikbd_write(cmd, 1);
521}
522
523/* Set joystick event reporting */
524void ikbd_joystick_event_on(void)
525{
526 static const char cmd[1] = { 0x14 };
527
528 ikbd_write(cmd, 1);
529}
530
531/* Set joystick interrogation mode */
532void ikbd_joystick_event_off(void)
533{
534 static const char cmd[1] = { 0x15 };
535
536 ikbd_write(cmd, 1);
537}
538
539/* Joystick interrogation */
540void ikbd_joystick_get_state(void)
541{
542 static const char cmd[1] = { 0x16 };
543
544 ikbd_write(cmd, 1);
545}
546
547#if 0
548/* This disables all other ikbd activities !!!! */
549/* Set joystick monitoring */
550void ikbd_joystick_monitor(int rate)
551{
552 static const char cmd[2] = { 0x17, rate };
553
554 ikbd_write(cmd, 2);
555
556 kb_state.state = JOYSTICK_MONITOR;
557}
558#endif
559
560/* some joystick routines not in yet (0x18-0x19) */
561
562/* Disable joysticks */
563void ikbd_joystick_disable(void)
564{
565 static const char cmd[1] = { 0x1A };
566
567 ikbd_write(cmd, 1);
568}
569
570/* Time-of-day clock set */
571void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
572{
573 char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
574
575 ikbd_write(cmd, 7);
576}
577
578/* Interrogate time-of-day clock */
579void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
580{
581 static const char cmd[1] = { 0x1C };
582
583 ikbd_write(cmd, 1);
584}
585
586/* Memory load */
587void ikbd_mem_write(int address, int size, char *data)
588{
589 panic("Attempt to write data into keyboard memory");
590}
591
592/* Memory read */
593void ikbd_mem_read(int address, char data[6])
594{
595 char cmd[3] = { 0x21, address>>8, address&0xFF };
596
597 ikbd_write(cmd, 3);
598
599 /* receive data and put it in data */
600}
601
602/* Controller execute */
603void ikbd_exec(int address)
604{
605 char cmd[3] = { 0x22, address>>8, address&0xFF };
606
607 ikbd_write(cmd, 3);
608}
609
610/* Status inquiries (0x87-0x9A) not yet implemented */
611
612/* Set the state of the caps lock led. */
613void atari_kbd_leds(unsigned int leds)
614{
615 char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
616
617 ikbd_write(cmd, 6);
618}
619
620/*
621 * The original code sometimes left the interrupt line of
622 * the ACIAs low forever. I hope, it is fixed now.
623 *
624 * Martin Rogge, 20 Aug 1995
625 */
626
627static int atari_keyb_done = 0;
628
629int __init atari_keyb_init(void)
630{
631 if (atari_keyb_done)
632 return 0;
633
634 /* setup key map */
635 memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
636
637 kb_state.state = KEYBOARD;
638 kb_state.len = 0;
639
640 request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
641 "keyboard/mouse/MIDI", atari_keyboard_interrupt);
642
643 atari_turnoff_irq(IRQ_MFP_ACIA);
644 do {
645 /* reset IKBD ACIA */
646 acia.key_ctrl = ACIA_RESET |
647 (atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0;
648 (void)acia.key_ctrl;
649 (void)acia.key_data;
650
651 /* reset MIDI ACIA */
652 acia.mid_ctrl = ACIA_RESET |
653 (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
654 (void)acia.mid_ctrl;
655 (void)acia.mid_data;
656
657 /* divide 500kHz by 64 gives 7812.5 baud */
658 /* 8 data no parity 1 start 1 stop bit */
659 /* receive interrupt enabled */
660 /* RTS low (except if switch selected), transmit interrupt disabled */
661 acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) |
662 ((atari_switches & ATARI_SWITCH_IKBD) ?
663 ACIA_RHTID : ACIA_RLTID);
664
665 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
666 (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
667
668 /* make sure the interrupt line is up */
669 } while ((mfp.par_dt_reg & 0x10) == 0);
670
671 /* enable ACIA Interrupts */
672 mfp.active_edge &= ~0x10;
673 atari_turnon_irq(IRQ_MFP_ACIA);
674
675 ikbd_self_test = 1;
676 ikbd_reset();
677 /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
678 * self-test is finished */
679 self_test_last_rcv = jiffies;
680 while (time_before(jiffies, self_test_last_rcv + HZ/4))
681 barrier();
682 /* if not incremented: no 0xf1 received */
683 if (ikbd_self_test == 1)
684 printk(KERN_ERR "WARNING: keyboard self test failed!\n");
685 ikbd_self_test = 0;
686
687 ikbd_mouse_disable();
688 ikbd_joystick_disable();
689
690#ifdef FIXED_ATARI_JOYSTICK
691 atari_joystick_init();
692#endif
693
694 // flag init done
695 atari_keyb_done = 1;
696 return 0;
697}
698
699
700int atari_kbdrate(struct kbd_repeat *k)
701{
702 if (k->delay > 0) {
703 /* convert from msec to jiffies */
704 key_repeat_delay = (k->delay * HZ + 500) / 1000;
705 if (key_repeat_delay < 1)
706 key_repeat_delay = 1;
707 }
708 if (k->period > 0) {
709 key_repeat_rate = (k->period * HZ + 500) / 1000;
710 if (key_repeat_rate < 1)
711 key_repeat_rate = 1;
712 }
713
714 k->delay = key_repeat_delay * 1000 / HZ;
715 k->period = key_repeat_rate * 1000 / HZ;
716
717 return 0;
718}
719
720int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
721{
722#ifdef CONFIG_MAGIC_SYSRQ
723 /* ALT+HELP pressed? */
724 if ((keycode == 98) && ((shift_state & 0xff) == 8))
725 *keycodep = 0xff;
726 else
727#endif
728 *keycodep = keycode;
729 return 1;
730}