root/arch/m68k/atari/atakeyb.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atakeyb_rep
  2. keyboard_interrupt
  3. ikbd_write
  4. ikbd_write
  5. ikbd_reset
  6. ikbd_mouse_button_action
  7. ikbd_mouse_rel_pos
  8. ikbd_mouse_abs_pos
  9. ikbd_mouse_kbd_mode
  10. ikbd_mouse_thresh
  11. ikbd_mouse_scale
  12. ikbd_mouse_pos_get
  13. ikbd_mouse_pos_set
  14. ikbd_mouse_y0_bot
  15. ikbd_mouse_y0_top
  16. ikbd_resume
  17. ikbd_mouse_disable
  18. ikbd_pause
  19. ikbd_joystick_event_on
  20. ikbd_joystick_event_off
  21. ikbd_joystick_get_state
  22. ikbd_joystick_monitor
  23. ikbd_joystick_disable
  24. ikbd_clock_set
  25. ikbd_clock_get
  26. ikbd_mem_write
  27. ikbd_mem_read
  28. ikbd_exec
  29. atari_kbd_leds
  30. atari_keyb_init
  31. atari_kbdrate

   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 README.legal 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/interrupt.h>
  18 #include <linux/errno.h>
  19 #include <linux/keyboard.h>
  20 #include <linux/delay.h>
  21 #include <linux/timer.h>
  22 #include <linux/kd.h>
  23 #include <linux/random.h>
  24 
  25 #include <asm/atariints.h>
  26 #include <asm/atarihw.h>
  27 #include <asm/atarikb.h>
  28 #include <asm/atari_mouse.h>
  29 #include <asm/atari_joystick.h>
  30 #include <asm/irq.h>
  31 
  32 extern int do_poke_blanked_console;
  33 extern void process_keycode (int);
  34 extern int ovsc_switchmode;
  35 unsigned char mach_keyboard_type;
  36 static void atakeyb_rep( unsigned long ignore );
  37 extern unsigned int keymap_count;
  38 
  39 /* Hook for MIDI serial driver */
  40 void (*atari_MIDI_interrupt_hook) (void);
  41 /* Hook for mouse driver */
  42 void (*atari_mouse_interrupt_hook) (char *);
  43 
  44 #define ATAKEY_CAPS     (58)
  45 #define BREAK_MASK      (0x80)
  46 
  47 /*
  48  * ++roman: The following changes were applied manually:
  49  *
  50  *  - The Alt (= Meta) key works in combination with Shift and
  51  *    Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
  52  *    Meta-Ctrl-A (0x81) ...
  53  *
  54  *  - The parentheses on the keypad send '(' and ')' with all
  55  *    modifiers (as would do e.g. keypad '+'), but they cannot be used as
  56  *    application keys (i.e. sending Esc O c).
  57  *
  58  *  - HELP and UNDO are mapped to be F21 and F24, resp, that send the
  59  *    codes "\E[M" and "\E[P". (This is better than the old mapping to
  60  *    F11 and F12, because these codes are on Shift+F1/2 anyway.) This
  61  *    way, applications that allow their own keyboard mappings
  62  *    (e.g. tcsh, X Windows) can be configured to use them in the way
  63  *    the label suggests (providing help or undoing).
  64  *
  65  *  - Console switching is done with Alt+Fx (consoles 1..10) and
  66  *    Shift+Alt+Fx (consoles 11..20).
  67  *
  68  *  - The misc. special function implemented in the kernel are mapped
  69  *    to the following key combinations:
  70  *
  71  *      ClrHome          -> Home/Find
  72  *      Shift + ClrHome  -> End/Select
  73  *      Shift + Up       -> Page Up
  74  *      Shift + Down     -> Page Down
  75  *      Alt + Help       -> show system status
  76  *      Shift + Help     -> show memory info
  77  *      Ctrl + Help      -> show registers
  78  *      Ctrl + Alt + Del -> Reboot
  79  *      Alt + Undo       -> switch to last console
  80  *      Shift + Undo     -> send interrupt
  81  *      Alt + Insert     -> stop/start output (same as ^S/^Q)
  82  *      Alt + Up         -> Scroll back console (if implemented)
  83  *      Alt + Down       -> Scroll forward console (if implemented)
  84  *      Alt + CapsLock   -> NumLock
  85  *
  86  */
  87 
  88 static u_short ataplain_map[NR_KEYS] = {
  89         0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
  90         0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
  91         0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
  92         0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
  93         0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
  94         0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
  95         0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200,
  96         0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
  97         0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
  98         0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
  99         0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
 100         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 101         0xf200, 0xf121, 0xf11b, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 102         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 103         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 104         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 105 };
 106 
 107 static u_short atashift_map[NR_KEYS] = {
 108         0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
 109         0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf008, 0xf009,
 110         0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
 111         0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
 112         0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
 113         0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
 114         0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf200,
 115         0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
 116         0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf200, 0xf200, 0xf117,
 117         0xf118, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 118         0xf119, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
 119         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 120         0xf200, 0xf205, 0xf203, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 121         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 122         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 123         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 124 };
 125 
 126 static u_short atactrl_map[NR_KEYS] = {
 127         0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
 128         0xf01f, 0xf07f, 0xf200, 0xf200, 0xf07f, 0xf200, 0xf008, 0xf200,
 129         0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
 130         0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
 131         0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
 132         0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
 133         0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200,
 134         0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
 135         0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
 136         0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 137         0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
 138         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 139         0xf200, 0xf121, 0xf202, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 140         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 141         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 142         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 143 };
 144 
 145 static u_short atashift_ctrl_map[NR_KEYS] = {
 146         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 147         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf008, 0xf200,
 148         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 149         0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200,
 150         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 151         0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 152         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200,
 153         0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 154         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117,
 155         0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 156         0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 157         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 158         0xf200, 0xf200, 0xf200, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 159         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 160         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 161         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 162 };
 163 
 164 static u_short ataalt_map[NR_KEYS] = {
 165         0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
 166         0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf808, 0xf809,
 167         0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
 168         0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
 169         0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
 170         0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
 171         0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf200,
 172         0xf703, 0xf820, 0xf208, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
 173         0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf200, 0xf200, 0xf114,
 174         0xf20b, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 175         0xf20a, 0xf200, 0xf209, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200,
 176         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 177         0xf200, 0xf206, 0xf204, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf907,
 178         0xf908, 0xf909, 0xf904, 0xf905, 0xf906, 0xf901, 0xf902, 0xf903,
 179         0xf900, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 180         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 181 };
 182 
 183 static u_short atashift_alt_map[NR_KEYS] = {
 184         0xf200, 0xf81b, 0xf821, 0xf840, 0xf823, 0xf824, 0xf825, 0xf85e,
 185         0xf826, 0xf82a, 0xf828, 0xf829, 0xf85f, 0xf82b, 0xf808, 0xf809,
 186         0xf851, 0xf857, 0xf845, 0xf852, 0xf854, 0xf859, 0xf855, 0xf849,
 187         0xf84f, 0xf850, 0xf87b, 0xf87d, 0xf201, 0xf702, 0xf841, 0xf853,
 188         0xf844, 0xf846, 0xf847, 0xf848, 0xf84a, 0xf84b, 0xf84c, 0xf83a,
 189         0xf822, 0xf87e, 0xf700, 0xf87c, 0xf85a, 0xf858, 0xf843, 0xf856,
 190         0xf842, 0xf84e, 0xf84d, 0xf83c, 0xf83e, 0xf83f, 0xf700, 0xf200,
 191         0xf703, 0xf820, 0xf207, 0xf50a, 0xf50b, 0xf50c, 0xf50d, 0xf50e,
 192         0xf50f, 0xf510, 0xf511, 0xf512, 0xf513, 0xf200, 0xf200, 0xf117,
 193         0xf118, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 194         0xf119, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200,
 195         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 196         0xf200, 0xf200, 0xf200, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 197         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 198         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 199         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 200 };
 201 
 202 static u_short atactrl_alt_map[NR_KEYS] = {
 203         0xf200, 0xf200, 0xf200, 0xf800, 0xf81b, 0xf81c, 0xf81d, 0xf81e,
 204         0xf81f, 0xf87f, 0xf200, 0xf200, 0xf87f, 0xf200, 0xf808, 0xf200,
 205         0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
 206         0xf80f, 0xf810, 0xf81b, 0xf81d, 0xf201, 0xf702, 0xf801, 0xf813,
 207         0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
 208         0xf807, 0xf800, 0xf700, 0xf81c, 0xf81a, 0xf818, 0xf803, 0xf816,
 209         0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf87f, 0xf700, 0xf200,
 210         0xf703, 0xf800, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
 211         0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
 212         0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 213         0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
 214         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 215         0xf200, 0xf121, 0xf202, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 216         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 217         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 218         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 219 };
 220 
 221 static u_short atashift_ctrl_alt_map[NR_KEYS] = {
 222         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 223         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf808, 0xf200,
 224         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 225         0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200,
 226         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 227         0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 228         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200,
 229         0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 230         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117,
 231         0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
 232         0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 233         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 234         0xf200, 0xf200, 0xf200, 0xf028, 0xf029, 0xf30d, 0xf30c, 0xf307,
 235         0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
 236         0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 237         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
 238 };
 239 
 240 typedef enum kb_state_t
 241 {
 242     KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
 243 } KB_STATE_T;
 244 
 245 #define IS_SYNC_CODE(sc)        ((sc) >= 0x04 && (sc) <= 0xfb)
 246 
 247 typedef struct keyboard_state
 248 {
 249     unsigned char  buf[6];
 250     int            len;
 251     KB_STATE_T     state;
 252 } KEYBOARD_STATE;
 253 
 254 KEYBOARD_STATE kb_state;
 255 
 256 #define DEFAULT_KEYB_REP_DELAY  (HZ/4)
 257 #define DEFAULT_KEYB_REP_RATE   (HZ/25)
 258 
 259 /* These could be settable by some ioctl() in future... */
 260 static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
 261 static unsigned int key_repeat_rate  = DEFAULT_KEYB_REP_RATE;
 262 
 263 static unsigned char rep_scancode;
 264 static struct timer_list atakeyb_rep_timer = { NULL, NULL, 0, 0, atakeyb_rep };
 265 
 266 extern struct pt_regs *pt_regs;
 267 
 268 static void atakeyb_rep( unsigned long ignore )
     /* [previous][next][first][last][top][bottom][index][help] */
 269 
 270 {
 271         pt_regs = NULL;
 272 
 273         /* Disable keyboard it for the time we call process_keycode(), else a race
 274          * in the keyboard tty queue may happen */
 275         atari_disable_irq( IRQ_MFP_ACIA );
 276         del_timer( &atakeyb_rep_timer );
 277 
 278         /* A keyboard int may have come in before we disabled the irq, so
 279          * double-check whether rep_scancode is still != 0 */
 280         if (rep_scancode) {
 281                 atakeyb_rep_timer.expires = jiffies + key_repeat_rate;
 282                 atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL;
 283                 add_timer( &atakeyb_rep_timer );
 284 
 285                 process_keycode (rep_scancode);
 286         }
 287 
 288         atari_enable_irq( IRQ_MFP_ACIA );
 289 }
 290 
 291 
 292 /* ++roman: If a keyboard overrun happened, we can't tell in general how much
 293  * bytes have been lost and in which state of the packet structure we are now.
 294  * This usually causes keyboards bytes to be interpreted as mouse movements
 295  * and vice versa, which is very annoying. It seems better to throw away some
 296  * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
 297  * introduced the RESYNC state for IKBD data. In this state, the bytes up to
 298  * one that really looks like a key event (0x04..0xf2) or the start of a mouse
 299  * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
 300  * speeds up the resynchronization of the event structure, even if maybe a
 301  * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
 302  * it's really hard to decide whether they're mouse or keyboard bytes. Since
 303  * overruns usually occur when moving the Atari mouse rapidly, they're seen as
 304  * mouse bytes here. If this is wrong, only a make code of the keyboard gets
 305  * lost, which isn't too bad. Loosing a break code would be disastrous,
 306  * because then the keyboard repeat strikes...
 307  */
 308 
 309 static void keyboard_interrupt(int irq, struct pt_regs *fp, void *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 310 {
 311   u_char acia_stat;
 312   int scancode;
 313   int break_flag;
 314 
 315   /* save frame for register dump */
 316   pt_regs = (struct pt_regs *)fp;
 317 
 318  repeat:
 319   if (acia.mid_ctrl & ACIA_IRQ)
 320         if (atari_MIDI_interrupt_hook)
 321                 atari_MIDI_interrupt_hook();
 322   acia_stat = acia.key_ctrl;
 323   /* check out if the interrupt came from this ACIA */
 324   if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
 325         return;
 326 
 327     if (acia_stat & ACIA_OVRN)
 328     {
 329         /* a very fast typist or a slow system, give a warning */
 330         /* ...happens often if interrupts were disabled for too long */
 331         printk( "Keyboard overrun\n" );
 332         scancode = acia.key_data;
 333         /* Turn off autorepeating in case a break code has been lost */
 334         del_timer( &atakeyb_rep_timer );
 335         rep_scancode = 0;
 336         if (IS_SYNC_CODE(scancode)) {
 337             /* This code seem already to be the start of a new packet or a
 338              * single keycode */
 339             kb_state.state = KEYBOARD;
 340             goto interpret_scancode;
 341         }
 342         else {
 343             /* Go to RESYNC state and skip this byte */
 344             kb_state.state = RESYNC;
 345             kb_state.len = 1; /* skip max. 1 another byte */
 346             goto repeat;
 347         }
 348     }
 349 
 350     if (acia_stat & ACIA_RDRF)  /* received a character */
 351     {
 352         scancode = acia.key_data;       /* get it or reset the ACIA, I'll get it! */
 353       interpret_scancode:
 354         switch (kb_state.state)
 355         {
 356           case KEYBOARD:
 357             switch (scancode)
 358             {
 359               case 0xF7:
 360                 kb_state.state = AMOUSE;
 361                 kb_state.len = 0;
 362                 break;
 363 
 364               case 0xF8:
 365               case 0xF9:
 366               case 0xFA:
 367               case 0xFB:
 368                 kb_state.state = RMOUSE;
 369                 kb_state.len = 1;
 370                 kb_state.buf[0] = scancode;
 371                 break;
 372 
 373               case 0xFC:
 374                 kb_state.state = CLOCK;
 375                 kb_state.len = 0;
 376                 break;
 377 
 378               case 0xFE:
 379               case 0xFF:
 380                 kb_state.state = JOYSTICK;
 381                 kb_state.len = 1;
 382                 kb_state.buf[0] = scancode;
 383                 break;
 384 
 385               default:
 386                 break_flag = scancode & BREAK_MASK;
 387                 scancode &= ~BREAK_MASK;
 388 
 389                 if (break_flag) {
 390                     del_timer( &atakeyb_rep_timer );
 391                     rep_scancode = 0;
 392                 }
 393                 else {
 394                     del_timer( &atakeyb_rep_timer );
 395                     rep_scancode = scancode;
 396                     atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
 397                     atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL;
 398                     add_timer( &atakeyb_rep_timer );
 399                 }
 400 
 401                 process_keycode( break_flag | scancode );
 402                 do_poke_blanked_console = 1;
 403                 mark_bh(CONSOLE_BH);
 404                 add_keyboard_randomness(scancode);
 405 
 406                 break;
 407             }
 408             break;
 409 
 410           case AMOUSE:
 411             kb_state.buf[kb_state.len++] = scancode;
 412             if (kb_state.len == 5)
 413             {
 414                 kb_state.state = KEYBOARD;
 415                 /* not yet used */
 416                 /* wake up someone waiting for this */
 417             }
 418             break;      
 419 
 420           case RMOUSE:
 421             kb_state.buf[kb_state.len++] = scancode;
 422             if (kb_state.len == 3)
 423             {
 424                 kb_state.state = KEYBOARD;
 425                 if (atari_mouse_interrupt_hook)
 426                         atari_mouse_interrupt_hook(kb_state.buf);
 427             }
 428             break;
 429 
 430           case JOYSTICK:
 431             kb_state.buf[1] = scancode;
 432             kb_state.state = KEYBOARD;
 433             atari_joystick_interrupt(kb_state.buf);
 434             break;
 435 
 436           case CLOCK:
 437             kb_state.buf[kb_state.len++] = scancode;
 438             if (kb_state.len == 6)
 439             {
 440                 kb_state.state = KEYBOARD;
 441                 /* wake up someone waiting for this.
 442                    But will this ever be used, as Linux keeps its own time.
 443                    Perhaps for synchronization purposes? */
 444                 /* wake_up_interruptible(&clock_wait); */
 445             }
 446             break;
 447 
 448           case RESYNC:
 449             if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
 450                 kb_state.state = KEYBOARD;
 451                 goto interpret_scancode;
 452             }
 453             kb_state.len--;
 454             break;
 455         }
 456     }
 457 
 458 #ifdef KEYB_WRITE_INTERRUPT
 459     if (acia_stat & ACIA_TDRE)  /* transmit of character is finished */
 460     {
 461         if (kb_state.buf)
 462         {
 463             acia.key_data = *kb_state.buf++;
 464             kb_state.len--;
 465             if (kb_state.len == 0)
 466             {
 467                 kb_state.buf = NULL;
 468                 if (!kb_state.kernel_mode)
 469                         /* unblock something */;
 470             }
 471         }
 472     }
 473 #endif
 474 
 475 #if 0
 476     if (acia_stat & ACIA_CTS)
 477         /* cannot happen */;
 478 #endif
 479 
 480     if (acia_stat & (ACIA_FE | ACIA_PE))
 481     {
 482         printk("Error in keyboard communication\n");
 483     }
 484 
 485     /* process_keycode() can take a lot of time, so check again if
 486          * some character arrived
 487          */
 488     goto repeat;
 489 }
 490 
 491 #ifdef KEYB_WRITE_INTERRUPT
 492 void ikbd_write(const char *str, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494     u_char acia_stat;
 495 
 496     if (kb_stat.buf)
 497         /* wait */;
 498     acia_stat = acia.key_ctrl;
 499     if (acia_stat & ACIA_TDRE)
 500     {
 501         if (len != 1)
 502         {
 503             kb_stat.buf = str + 1;
 504             kb_stat.len = len - 1;
 505         }
 506         acia.key_data = *str;
 507         /* poll */
 508     }
 509 }
 510 #else
 511 /*
 512  * I write to the keyboard without using interrupts, I poll instead.
 513  * This takes for the maximum length string allowed (7) at 7812.5 baud
 514  * 8 data 1 start 1 stop bit: 9.0 ms
 515  * If this takes too long for normal operation, interrupt driven writing
 516  * is the solution. (I made a feeble attempt in that direction but I
 517  * kept it simple for now.)
 518  */
 519 void ikbd_write(const char *str, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 520 {
 521     u_char acia_stat;
 522 
 523     if ((len < 1) || (len > 7))
 524         panic("ikbd: maximum string length exceeded");
 525     while (len)
 526     {
 527         acia_stat = acia.key_ctrl;
 528         if (acia_stat & ACIA_TDRE)
 529         {
 530             acia.key_data = *str++;
 531             len--;
 532         }
 533     }
 534 }
 535 #endif
 536 
 537 /* Reset (without touching the clock) */
 538 void ikbd_reset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540     static const char cmd[2] = { 0x80, 0x01 };
 541     
 542     ikbd_write(cmd, 2);
 543 
 544     /* if all's well code 0xF1 is returned, else the break codes of
 545        all keys making contact */
 546 }
 547 
 548 /* Set mouse button action */
 549 void ikbd_mouse_button_action(int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 550 {
 551     char cmd[2] = { 0x07, mode };
 552 
 553     ikbd_write(cmd, 2);
 554 }
 555 
 556 /* Set relative mouse position reporting */
 557 void ikbd_mouse_rel_pos(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 558 {
 559     static const char cmd[1] = { 0x08 };
 560 
 561     ikbd_write(cmd, 1);
 562 }
 563 
 564 /* Set absolute mouse position reporting */
 565 void ikbd_mouse_abs_pos(int xmax, int ymax)
     /* [previous][next][first][last][top][bottom][index][help] */
 566 {
 567     char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
 568 
 569     ikbd_write(cmd, 5);
 570 }
 571 
 572 /* Set mouse keycode mode */
 573 void ikbd_mouse_kbd_mode(int dx, int dy)
     /* [previous][next][first][last][top][bottom][index][help] */
 574 {
 575     char cmd[3] = { 0x0A, dx, dy };
 576 
 577     ikbd_write(cmd, 3);
 578 }
 579 
 580 /* Set mouse threshold */
 581 void ikbd_mouse_thresh(int x, int y)
     /* [previous][next][first][last][top][bottom][index][help] */
 582 {
 583     char cmd[3] = { 0x0B, x, y };
 584 
 585     ikbd_write(cmd, 3);
 586 }
 587 
 588 /* Set mouse scale */
 589 void ikbd_mouse_scale(int x, int y)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591     char cmd[3] = { 0x0C, x, y };
 592 
 593     ikbd_write(cmd, 3);
 594 }
 595 
 596 /* Interrogate mouse position */
 597 void ikbd_mouse_pos_get(int *x, int *y)
     /* [previous][next][first][last][top][bottom][index][help] */
 598 {
 599     static const char cmd[1] = { 0x0D };
 600 
 601     ikbd_write(cmd, 1);
 602 
 603     /* wait for returning bytes */
 604 }
 605 
 606 /* Load mouse position */
 607 void ikbd_mouse_pos_set(int x, int y)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609     char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
 610 
 611     ikbd_write(cmd, 6);
 612 }
 613 
 614 /* Set Y=0 at bottom */
 615 void ikbd_mouse_y0_bot(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 616 {
 617     static const char cmd[1] = { 0x0F };
 618 
 619     ikbd_write(cmd, 1);
 620 }
 621 
 622 /* Set Y=0 at top */
 623 void ikbd_mouse_y0_top(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 624 {
 625     static const char cmd[1] = { 0x10 };
 626 
 627     ikbd_write(cmd, 1);
 628 }
 629 
 630 /* Resume */
 631 void ikbd_resume(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 632 {
 633     static const char cmd[1] = { 0x11 };
 634 
 635     ikbd_write(cmd, 1);
 636 }
 637 
 638 /* Disable mouse */
 639 void ikbd_mouse_disable(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 640 {
 641     static const char cmd[1] = { 0x12 };
 642 
 643     ikbd_write(cmd, 1);
 644 }
 645 
 646 /* Pause output */
 647 void ikbd_pause(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 648 {
 649     static const char cmd[1] = { 0x13 };
 650 
 651     ikbd_write(cmd, 1);
 652 }
 653 
 654 /* Set joystick event reporting */
 655 void ikbd_joystick_event_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 656 {
 657     static const char cmd[1] = { 0x14 };
 658 
 659     ikbd_write(cmd, 1);
 660 }
 661 
 662 /* Set joystick interrogation mode */
 663 void ikbd_joystick_event_off(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 664 {
 665     static const char cmd[1] = { 0x15 };
 666 
 667     ikbd_write(cmd, 1);
 668 }
 669 
 670 /* Joystick interrogation */
 671 void ikbd_joystick_get_state(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673     static const char cmd[1] = { 0x16 };
 674 
 675     ikbd_write(cmd, 1);
 676 }
 677 
 678 #if 0
 679 /* This disables all other ikbd activities !!!! */
 680 /* Set joystick monitoring */
 681 void ikbd_joystick_monitor(int rate)
     /* [previous][next][first][last][top][bottom][index][help] */
 682 {
 683     static const char cmd[2] = { 0x17, rate };
 684 
 685     ikbd_write(cmd, 2);
 686 
 687     kb_state.state = JOYSTICK_MONITOR;
 688 }
 689 #endif
 690 
 691 /* some joystick routines not in yet (0x18-0x19) */
 692 
 693 /* Disable joysticks */
 694 void ikbd_joystick_disable(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 695 {
 696     static const char cmd[1] = { 0x1A };
 697 
 698     ikbd_write(cmd, 1);
 699 }
 700 
 701 /* Time-of-day clock set */
 702 void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
     /* [previous][next][first][last][top][bottom][index][help] */
 703 {
 704     char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
 705 
 706     ikbd_write(cmd, 7);
 707 }
 708 
 709 /* Interrogate time-of-day clock */
 710 void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
     /* [previous][next][first][last][top][bottom][index][help] */
 711 {
 712     static const char cmd[1] = { 0x1C };
 713 
 714     ikbd_write(cmd, 1);
 715 }
 716 
 717 /* Memory load */
 718 void ikbd_mem_write(int address, int size, char *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 719 {
 720     panic("Attempt to write data into keyboard memory");
 721 }
 722 
 723 /* Memory read */
 724 void ikbd_mem_read(int address, char data[6])
     /* [previous][next][first][last][top][bottom][index][help] */
 725 {
 726     char cmd[3] = { 0x21, address>>8, address&0xFF };
 727 
 728     ikbd_write(cmd, 3);
 729 
 730     /* receive data and put it in data */
 731 }
 732 
 733 /* Controller execute */
 734 void ikbd_exec(int address)
     /* [previous][next][first][last][top][bottom][index][help] */
 735 {
 736     char cmd[3] = { 0x22, address>>8, address&0xFF };
 737 
 738     ikbd_write(cmd, 3);
 739 }
 740 
 741 /* Status inquiries (0x87-0x9A) not yet implemented */
 742 
 743 /* Set the state of the caps lock led. */
 744 void atari_kbd_leds (unsigned int leds)
     /* [previous][next][first][last][top][bottom][index][help] */
 745 {
 746     char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
 747     ikbd_write(cmd, 6);
 748 }
 749 
 750 /*
 751  * The original code sometimes left the interrupt line of 
 752  * the ACIAs low forever. I hope, it is fixed now.
 753  *
 754  * Martin Rogge, 20 Aug 1995
 755  */
 756  
 757 int atari_keyb_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 758 {
 759     /* setup key map */
 760     key_maps[0]  = ataplain_map;
 761     key_maps[1]  = atashift_map;
 762     key_maps[2]  = 0; /* ataaltgr_map */
 763     key_maps[4]  = atactrl_map;
 764     key_maps[5]  = atashift_ctrl_map;
 765     key_maps[8]  = ataalt_map;
 766     key_maps[9]  = atashift_alt_map;
 767     key_maps[12] = atactrl_alt_map;
 768     key_maps[13] = atashift_ctrl_alt_map;
 769     memcpy (plain_map, ataplain_map, sizeof(plain_map));
 770     keymap_count = 8;
 771 
 772     /* say that we don't have an AltGr key */
 773     mach_keyboard_type = KB_84;
 774 
 775     kb_state.state = KEYBOARD;
 776     kb_state.len = 0;
 777 
 778     add_isr(IRQ_MFP_ACIA, keyboard_interrupt, IRQ_TYPE_SLOW, NULL,
 779             "keyboard/mouse/MIDI");
 780 
 781     atari_turnoff_irq(IRQ_MFP_ACIA);
 782     do {
 783         acia.key_ctrl = ACIA_RESET;             /* reset ACIA */
 784         (void)acia.key_ctrl;
 785         (void)acia.key_data;
 786 
 787         acia.mid_ctrl = ACIA_RESET;             /* reset other ACIA */
 788         (void)acia.mid_ctrl;
 789         (void)acia.mid_data;
 790 
 791         /* divide 500kHz by 64 gives 7812.5 baud */
 792         /* 8 data no parity 1 start 1 stop bit */
 793         /* receive interrupt enabled */
 794 #ifdef KEYB_WRITE_INTERRUPT
 795         /* RTS low, transmit interrupt enabled */
 796         if (ovsc_switchmode == 1)
 797             acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RHTIE|ACIA_RIE);
 798             /* switch on OverScan via keyboard ACIA */
 799         else
 800             acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RLTIE|ACIA_RIE);
 801 #else
 802         /* RTS low, transmit interrupt disabled */
 803         if (ovsc_switchmode == 1)
 804             acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RHTID|ACIA_RIE);
 805         else
 806             acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RLTID|ACIA_RIE);
 807 #endif
 808            
 809         acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S;
 810     }
 811     /* make sure the interrupt line is up */
 812     while ((mfp.par_dt_reg & 0x10) == 0);
 813 
 814     /* enable ACIA Interrupts */ 
 815     mfp.active_edge &= ~0x10;
 816     atari_turnon_irq(IRQ_MFP_ACIA);
 817 
 818     ikbd_reset();
 819     ikbd_mouse_disable();
 820     ikbd_joystick_disable();
 821 
 822     atari_joystick_init();
 823   
 824     return 0;
 825 }
 826 
 827 
 828 int atari_kbdrate( struct kbd_repeat *k )
     /* [previous][next][first][last][top][bottom][index][help] */
 829 
 830 {
 831         if (k->delay > 0) {
 832                 /* convert from msec to jiffies */
 833                 key_repeat_delay = (k->delay * HZ + 500) / 1000;
 834                 if (key_repeat_delay < 1)
 835                         key_repeat_delay = 1;
 836         }
 837         if (k->rate > 0) {
 838                 key_repeat_rate = (k->rate * HZ + 500) / 1000;
 839                 if (key_repeat_rate < 1)
 840                         key_repeat_rate = 1;
 841         }
 842 
 843         k->delay = key_repeat_delay * 1000 / HZ;
 844         k->rate  = key_repeat_rate  * 1000 / HZ;
 845         
 846         return( 0 );
 847 }

/* [previous][next][first][last][top][bottom][index][help] */