aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/m68k/Kconfig3
-rw-r--r--arch/m68k/atari/Makefile1
-rw-r--r--arch/m68k/atari/atakeyb.c730
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atakbd.c134
-rw-r--r--drivers/input/mouse/Kconfig11
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/atarimouse.c160
-rw-r--r--include/asm-m68k/atarikb.h6
-rw-r--r--include/linux/input.h1
11 files changed, 1059 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}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f17e9c7d4b36..c845d5c4cbba 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -164,6 +164,17 @@ config KEYBOARD_AMIGA
164 To compile this driver as a module, choose M here: the 164 To compile this driver as a module, choose M here: the
165 module will be called amikbd. 165 module will be called amikbd.
166 166
167config KEYBOARD_ATARI
168 tristate "Atari keyboard"
169 depends on ATARI
170 select ATARI_KBD_CORE
171 help
172 Say Y here if you are running Linux on any Atari and have a keyboard
173 attached.
174
175 To compile this driver as a module, choose M here: the
176 module will be called atakbd.
177
167config KEYBOARD_HIL_OLD 178config KEYBOARD_HIL_OLD
168 tristate "HP HIL keyboard support (simple driver)" 179 tristate "HP HIL keyboard support (simple driver)"
169 depends on GSC || HP300 180 depends on GSC || HP300
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 586a0fe53be6..7aa59ee5a0b6 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
9obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o 9obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
10obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o 10obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
11obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o 11obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
12obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
12obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o 13obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
13obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o 14obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
14obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o 15obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c
new file mode 100644
index 000000000000..ded1d6ac6ff3
--- /dev/null
+++ b/drivers/input/keyboard/atakbd.c
@@ -0,0 +1,134 @@
1/*
2 * atakbd.c
3 *
4 * Copyright (c) 2005 Michael Schmitz
5 *
6 * Based on amikbd.c, which is
7 *
8 * Copyright (c) 2000-2001 Vojtech Pavlik
9 *
10 * Based on the work of:
11 * Hamish Macdonald
12 */
13
14/*
15 * Atari keyboard driver for Linux/m68k
16 *
17 * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
18 * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
19 * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
20 * This driver only deals with handing key events off to the input layer.
21 */
22
23/*
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 *
38 * Should you need to contact me, the author, you can do so either by
39 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
40 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
41 */
42
43#include <linux/module.h>
44#include <linux/init.h>
45#include <linux/input.h>
46#include <linux/delay.h>
47#include <linux/interrupt.h>
48
49#include <asm/atariints.h>
50#include <asm/atarihw.h>
51#include <asm/atarikb.h>
52#include <asm/irq.h>
53
54MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
55MODULE_DESCRIPTION("Atari keyboard driver");
56MODULE_LICENSE("GPL");
57
58static unsigned char atakbd_keycode[0x72];
59
60static struct input_dev *atakbd_dev;
61
62static void atakbd_interrupt(unsigned char scancode, char down)
63{
64
65 if (scancode < 0x72) { /* scancodes < 0xf2 are keys */
66
67 // report raw events here?
68
69 scancode = atakbd_keycode[scancode];
70
71 if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
72 input_report_key(atakbd_dev, scancode, 1);
73 input_report_key(atakbd_dev, scancode, 0);
74 input_sync(atakbd_dev);
75 } else {
76 input_report_key(atakbd_dev, scancode, down);
77 input_sync(atakbd_dev);
78 }
79 } else /* scancodes >= 0xf2 are mouse data, most likely */
80 printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
81
82 return;
83}
84
85static int __init atakbd_init(void)
86{
87 int i;
88
89 if (!ATARIHW_PRESENT(ST_MFP))
90 return -EIO;
91
92 // TODO: request_mem_region if not done in arch code
93
94 if (!(atakbd_dev = input_allocate_device()))
95 return -ENOMEM;
96
97 // need to init core driver if not already done so
98 if (atari_keyb_init())
99 return -ENODEV;
100
101 atakbd_dev->name = "Atari Keyboard";
102 atakbd_dev->phys = "atakbd/input0";
103 atakbd_dev->id.bustype = BUS_ATARI;
104 atakbd_dev->id.vendor = 0x0001;
105 atakbd_dev->id.product = 0x0001;
106 atakbd_dev->id.version = 0x0100;
107
108 atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
109 atakbd_dev->keycode = atakbd_keycode;
110 atakbd_dev->keycodesize = sizeof(unsigned char);
111 atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
112
113 for (i = 1; i < 0x72; i++) {
114 atakbd_keycode[i] = i;
115 set_bit(atakbd_keycode[i], atakbd_dev->keybit);
116 }
117
118 input_register_device(atakbd_dev);
119
120 atari_input_keyboard_interrupt_hook = atakbd_interrupt;
121
122 printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name);
123
124 return 0;
125}
126
127static void __exit atakbd_exit(void)
128{
129 atari_input_keyboard_interrupt_hook = NULL;
130 input_unregister_device(atakbd_dev);
131}
132
133module_init(atakbd_init);
134module_exit(atakbd_exit);
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 35d998c3e578..b40784a60aa1 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -96,6 +96,17 @@ config MOUSE_AMIGA
96 To compile this driver as a module, choose M here: the 96 To compile this driver as a module, choose M here: the
97 module will be called amimouse. 97 module will be called amimouse.
98 98
99config MOUSE_ATARI
100 tristate "Atari mouse"
101 depends on ATARI
102 select ATARI_KBD_CORE
103 help
104 Say Y here if you have an Atari and want its native mouse
105 supported by the kernel.
106
107 To compile this driver as a module, choose M here: the
108 module will be called atarimouse.
109
99config MOUSE_RISCPC 110config MOUSE_RISCPC
100 tristate "Acorn RiscPC mouse" 111 tristate "Acorn RiscPC mouse"
101 depends on ARCH_ACORN 112 depends on ARCH_ACORN
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 21a1de61a79b..700f61200dfc 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -5,6 +5,7 @@
5# Each configuration option enables a list of files. 5# Each configuration option enables a list of files.
6 6
7obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o 7obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
8obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
8obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o 9obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
9obj-$(CONFIG_MOUSE_INPORT) += inport.o 10obj-$(CONFIG_MOUSE_INPORT) += inport.o
10obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o 11obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
new file mode 100644
index 000000000000..43ab6566fb65
--- /dev/null
+++ b/drivers/input/mouse/atarimouse.c
@@ -0,0 +1,160 @@
1/*
2 * Atari mouse driver for Linux/m68k
3 *
4 * Copyright (c) 2005 Michael Schmitz
5 *
6 * Based on:
7 * Amiga mouse driver for Linux/m68k
8 *
9 * Copyright (c) 2000-2002 Vojtech Pavlik
10 *
11 */
12/*
13 * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
14 * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
15 * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
16 * This driver only deals with handing key events off to the input layer.
17 *
18 * Largely based on the old:
19 *
20 * Atari Mouse Driver for Linux
21 * by Robert de Vries (robert@and.nl) 19Jul93
22 *
23 * 16 Nov 1994 Andreas Schwab
24 * Compatibility with busmouse
25 * Support for three button mouse (shamelessly stolen from MiNT)
26 * third button wired to one of the joystick directions on joystick 1
27 *
28 * 1996/02/11 Andreas Schwab
29 * Module support
30 * Allow multiple open's
31 *
32 * Converted to use new generic busmouse code. 5 Apr 1998
33 * Russell King <rmk@arm.uk.linux.org>
34 */
35
36
37/*
38 * This program is free software; you can redistribute it and/or modify it
39 * under the terms of the GNU General Public License version 2 as published by
40 * the Free Software Foundation
41 */
42
43#include <linux/module.h>
44#include <linux/init.h>
45#include <linux/input.h>
46#include <linux/interrupt.h>
47
48#include <asm/irq.h>
49#include <asm/setup.h>
50#include <asm/system.h>
51#include <asm/uaccess.h>
52#include <asm/atarihw.h>
53#include <asm/atarikb.h>
54#include <asm/atariints.h>
55
56MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
57MODULE_DESCRIPTION("Atari mouse driver");
58MODULE_LICENSE("GPL");
59
60static int mouse_threshold[2] = {2,2};
61
62#ifdef __MODULE__
63MODULE_PARM(mouse_threshold, "2i");
64#endif
65#ifdef FIXED_ATARI_JOYSTICK
66extern int atari_mouse_buttons;
67#endif
68static int atamouse_used = 0;
69
70static struct input_dev *atamouse_dev;
71
72static void atamouse_interrupt(char *buf)
73{
74 int buttons, dx, dy;
75
76/* ikbd_mouse_disable(); */
77
78 buttons = (buf[0] & 1) | ((buf[0] & 2) << 1);
79#ifdef FIXED_ATARI_JOYSTICK
80 buttons |= atari_mouse_buttons & 2;
81 atari_mouse_buttons = buttons;
82#endif
83/* ikbd_mouse_rel_pos(); */
84
85 /* only relative events get here */
86 dx = buf[1];
87 dy = -buf[2];
88
89 input_report_rel(atamouse_dev, REL_X, dx);
90 input_report_rel(atamouse_dev, REL_Y, dy);
91
92 input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x1);
93 input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
94 input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x4);
95
96 input_sync(atamouse_dev);
97
98 return;
99}
100
101static int atamouse_open(struct input_dev *dev)
102{
103 if (atamouse_used++)
104 return 0;
105
106#ifdef FIXED_ATARI_JOYSTICK
107 atari_mouse_buttons = 0;
108#endif
109 ikbd_mouse_y0_top();
110 ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
111 ikbd_mouse_rel_pos();
112 atari_input_mouse_interrupt_hook = atamouse_interrupt;
113 return 0;
114}
115
116static void atamouse_close(struct input_dev *dev)
117{
118 if (!--atamouse_used) {
119 ikbd_mouse_disable();
120 atari_mouse_interrupt_hook = NULL;
121 }
122}
123
124static int __init atamouse_init(void)
125{
126 if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
127 return -ENODEV;
128
129 if (!(atamouse_dev = input_allocate_device()))
130 return -ENOMEM;
131
132 if (!(atari_keyb_init()))
133 return -ENODEV;
134
135 atamouse_dev->name = "Atari mouse";
136 atamouse_dev->phys = "atamouse/input0";
137 atamouse_dev->id.bustype = BUS_ATARI;
138 atamouse_dev->id.vendor = 0x0001;
139 atamouse_dev->id.product = 0x0002;
140 atamouse_dev->id.version = 0x0100;
141
142 atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
143 atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
144 atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
145 atamouse_dev->open = atamouse_open;
146 atamouse_dev->close = atamouse_close;
147
148 input_register_device(atamouse_dev);
149
150 printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name);
151 return 0;
152}
153
154static void __exit atamouse_exit(void)
155{
156 input_unregister_device(atamouse_dev);
157}
158
159module_init(atamouse_init);
160module_exit(atamouse_exit);
diff --git a/include/asm-m68k/atarikb.h b/include/asm-m68k/atarikb.h
index 18926058fde7..546e7da5804f 100644
--- a/include/asm-m68k/atarikb.h
+++ b/include/asm-m68k/atarikb.h
@@ -36,5 +36,11 @@ void ikbd_joystick_disable(void);
36extern void (*atari_MIDI_interrupt_hook) (void); 36extern void (*atari_MIDI_interrupt_hook) (void);
37/* Hook for mouse driver */ 37/* Hook for mouse driver */
38extern void (*atari_mouse_interrupt_hook) (char *); 38extern void (*atari_mouse_interrupt_hook) (char *);
39/* Hook for keyboard inputdev driver */
40extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
41/* Hook for mouse inputdev driver */
42extern void (*atari_input_mouse_interrupt_hook) (char *);
43
44int atari_keyb_init(void);
39 45
40#endif /* _LINUX_ATARIKB_H */ 46#endif /* _LINUX_ATARIKB_H */
diff --git a/include/linux/input.h b/include/linux/input.h
index bde65c8a3519..327122548c4d 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -676,6 +676,7 @@ struct input_absinfo {
676#define BUS_I2C 0x18 676#define BUS_I2C 0x18
677#define BUS_HOST 0x19 677#define BUS_HOST 0x19
678#define BUS_GSC 0x1A 678#define BUS_GSC 0x1A
679#define BUS_ATARI 0x1B
679 680
680/* 681/*
681 * Values describing the status of a force-feedback effect 682 * Values describing the status of a force-feedback effect