root/arch/m68k/amiga/amikeyb.c

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

DEFINITIONS

This source file includes following definitions.
  1. amikeyb_rep
  2. keyboard_interrupt
  3. amiga_keyb_init
  4. amiga_kbdrate

   1 /*
   2  * linux/amiga/amikeyb.c
   3  *
   4  * Amiga 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  * Amiga support by Hamish Macdonald
  13  */
  14 
  15 #include <linux/types.h>
  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/bootinfo.h>
  26 #include <asm/amigatypes.h>
  27 #include <asm/amigaints.h>
  28 #include <asm/amigahw.h>
  29 #include <asm/irq.h>
  30 
  31 extern int do_poke_blanked_console;
  32 extern void process_keycode (int);
  33 
  34 #define AMIKEY_CAPS     (0x62)
  35 #define BREAK_MASK      (0x80)
  36 
  37 static u_short amiplain_map[NR_KEYS] = {
  38         0xf060, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
  39         0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf05c, 0xf200, 0xf300,
  40         0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
  41         0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf200, 0xf301, 0xf302, 0xf303,
  42         0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b,
  43         0xfb6c, 0xf03b, 0xf027, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
  44         0xf200, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, 0xfb62, 0xfb6e, 0xfb6d,
  45         0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
  46         0xf020, 0xf07f, 0xf009, 0xf30e, 0xf201, 0xf01b, 0xf07f, 0xf200,
  47         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
  48         0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
  49         0xf108, 0xf109, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf10a,
  50         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
  51         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  52         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  53         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  54 };
  55 
  56 static u_short amishift_map[NR_KEYS] = {
  57         0xf07e, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026,
  58         0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07c, 0xf200, 0xf300,
  59         0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
  60         0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf200, 0xf301, 0xf302, 0xf303,
  61         0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b,
  62         0xfb4c, 0xf03a, 0xf022, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
  63         0xf200, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, 0xfb42, 0xfb4e, 0xfb4d,
  64         0xf03c, 0xf03e, 0xf03f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
  65         0xf020, 0xf07f, 0xf009, 0xf30e, 0xf201, 0xf01b, 0xf07f, 0xf200,
  66         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
  67         0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, 0xf10f, 0xf110, 0xf111,
  68         0xf112, 0xf113, 0xf208, 0xf203, 0xf30d, 0xf30c, 0xf30a, 0xf10a,
  69         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
  70         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  71         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  72         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  73 };
  74 
  75 static u_short amialtgr_map[NR_KEYS] = {
  76         0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, 0xf07b,
  77         0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, 0xf300,
  78         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  79         0xf200, 0xf200, 0xf200, 0xf07e, 0xf200, 0xf301, 0xf302, 0xf303,
  80         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  81         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
  82         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  83         0xf200, 0xf200, 0xf200, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
  84         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
  85         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
  86         0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, 0xf511, 0xf512, 0xf513,
  87         0xf514, 0xf515, 0xf208, 0xf202, 0xf30d, 0xf30c, 0xf30a, 0xf516,
  88         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
  89         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  90         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  91         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  92 };
  93 
  94 static u_short amictrl_map[NR_KEYS] = {
  95         0xf000, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
  96         0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf01c, 0xf200, 0xf300,
  97         0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
  98         0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf200, 0xf301, 0xf302, 0xf303,
  99         0xf001, 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b,
 100         0xf00c, 0xf200, 0xf007, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
 101         0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, 0xf002, 0xf00e, 0xf00d,
 102         0xf200, 0xf200, 0xf07f, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
 103         0xf000, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
 104         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
 105         0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
 106         0xf108, 0xf109, 0xf208, 0xf204, 0xf30d, 0xf30c, 0xf30a, 0xf10a,
 107         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
 108         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 109         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 110         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 111 };
 112 
 113 static u_short amishift_ctrl_map[NR_KEYS] = {
 114         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 115         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf300,
 116         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 117         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302, 0xf303,
 118         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 119         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
 120         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 121         0xf200, 0xf200, 0xf200, 0xf200, 0xf310, 0xf307, 0xf308, 0xf309,
 122         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
 123         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
 124         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 125         0xf200, 0xf200, 0xf208, 0xf200, 0xf30d, 0xf30c, 0xf30a, 0xf200,
 126         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
 127         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 128         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 129         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 130 };
 131 
 132 static u_short amialt_map[NR_KEYS] = {
 133         0xf860, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, 0xf837,
 134         0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf85c, 0xf200, 0xf900,
 135         0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
 136         0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf200, 0xf901, 0xf902, 0xf903,
 137         0xf861, 0xf873, 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b,
 138         0xf86c, 0xf83b, 0xf827, 0xf200, 0xf200, 0xf904, 0xf905, 0xf906,
 139         0xf200, 0xf87a, 0xf878, 0xf863, 0xf876, 0xf862, 0xf86e, 0xf86d,
 140         0xf82c, 0xf82e, 0xf82f, 0xf200, 0xf310, 0xf907, 0xf908, 0xf909,
 141         0xf820, 0xf87f, 0xf809, 0xf30e, 0xf80d, 0xf81b, 0xf87f, 0xf200,
 142         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
 143         0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506, 0xf507,
 144         0xf508, 0xf509, 0xf208, 0xf209, 0xf30d, 0xf30c, 0xf30a, 0xf50a,
 145         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
 146         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 147         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 148         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 149 };
 150 
 151 static u_short amictrl_alt_map[NR_KEYS] = {
 152         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 153         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf300,
 154         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 155         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf301, 0xf302, 0xf303,
 156         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 157         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf304, 0xf305, 0xf306,
 158         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 159         0xf200, 0xf200, 0xf200, 0xf200, 0xf20c, 0xf307, 0xf308, 0xf309,
 160         0xf200, 0xf07f, 0xf200, 0xf30e, 0xf201, 0xf200, 0xf200, 0xf200,
 161         0xf200, 0xf200, 0xf30b, 0xf200, 0xf603, 0xf600, 0xf602, 0xf601,
 162         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 163         0xf200, 0xf200, 0xf208, 0xf200, 0xf30d, 0xf30c, 0xf30a, 0xf200,
 164         0xf700, 0xf700, 0xf207, 0xf702, 0xf703, 0xf701, 0xf200, 0xf200,
 165         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 166         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 167         0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 168 };
 169 
 170 #define DEFAULT_KEYB_REP_DELAY  (HZ/4)
 171 #define DEFAULT_KEYB_REP_RATE   (HZ/25)
 172 
 173 /* These could be settable by some ioctl() in future... */
 174 static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
 175 static unsigned int key_repeat_rate  = DEFAULT_KEYB_REP_RATE;
 176 
 177 static unsigned char rep_scancode;
 178 static void amikeyb_rep (unsigned long ignore);
 179 static struct timer_list amikeyb_rep_timer = {NULL, NULL, 0, 0, amikeyb_rep};
 180 
 181 extern struct pt_regs *pt_regs;
 182 
 183 static void amikeyb_rep (unsigned long ignore)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         unsigned long flags;
 186         save_flags(flags);
 187         cli();
 188 
 189         pt_regs = NULL;
 190 
 191         amikeyb_rep_timer.expires = jiffies + key_repeat_rate;
 192         amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL;
 193         add_timer(&amikeyb_rep_timer);
 194         process_keycode (rep_scancode);
 195 
 196         restore_flags(flags);
 197 }
 198 
 199 static void keyboard_interrupt (int irq, struct pt_regs *fp, void *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201     unsigned char scancode, break_flag;
 202 
 203     /* save frame for register dump */
 204     pt_regs = (struct pt_regs *)fp;
 205 
 206     /* get and invert scancode (keyboard is active low) */
 207     scancode = ~ciaa.sdr;
 208 
 209     /* switch SP pin to output for handshake */
 210     ciaa.cra |= 0x40;
 211     /* wait until 85 us have expired */
 212     udelay(85);
 213     /* switch CIA serial port to input mode */
 214     ciaa.cra &= ~0x40;
 215 
 216     /* rotate scan code to get up/down bit in proper position */
 217     __asm__ __volatile__ ("rorb #1,%0" : "=g" (scancode) : "0" (scancode));
 218 
 219     /*
 220      * do machine independent keyboard processing of "normalized" scancode
 221      * A "normalized" scancode is one that an IBM PC might generate
 222      * Check make/break first
 223      */
 224     break_flag = scancode & BREAK_MASK;
 225     scancode &= (unsigned char )~BREAK_MASK;
 226 
 227     if (scancode == AMIKEY_CAPS) {
 228             /* if the key is CAPS, fake a press/release. */
 229             process_keycode (AMIKEY_CAPS);
 230             process_keycode (BREAK_MASK | AMIKEY_CAPS);
 231     } else {
 232             /* handle repeat */
 233             if (break_flag) {
 234                     del_timer(&amikeyb_rep_timer);
 235                     rep_scancode = 0;
 236             } else {
 237                     del_timer(&amikeyb_rep_timer);
 238                     rep_scancode = break_flag | scancode;
 239                     amikeyb_rep_timer.expires = jiffies + key_repeat_delay;
 240                     amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL;
 241                     add_timer(&amikeyb_rep_timer);
 242             }
 243             process_keycode (break_flag | scancode);
 244     }
 245 
 246     do_poke_blanked_console = 1;
 247     mark_bh(CONSOLE_BH);
 248     add_keyboard_randomness(scancode);
 249 
 250     return;
 251 }
 252 
 253 int amiga_keyb_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255     if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
 256         return -EIO;
 257 
 258     /* setup key map */
 259     key_maps[0]  = amiplain_map;
 260     key_maps[1]  = amishift_map;
 261     key_maps[2]  = amialtgr_map;
 262     key_maps[4]  = amictrl_map;
 263     key_maps[5]  = amishift_ctrl_map;
 264     key_maps[8]  = amialt_map;
 265     key_maps[12] = amictrl_alt_map;
 266     memcpy (plain_map, amiplain_map, sizeof(plain_map));
 267 
 268     /*
 269      * Initialize serial data direction.
 270      */
 271     ciaa.cra &= ~0x41;       /* serial data in, turn off TA */
 272 
 273     /*
 274      * arrange for processing of keyboard interrupt
 275      */
 276     add_isr (IRQ_AMIGA_CIAA_SP, keyboard_interrupt, 0, NULL, "keyboard");
 277 
 278     return 0;
 279 }
 280 
 281 int amiga_kbdrate( struct kbd_repeat *k )
     /* [previous][next][first][last][top][bottom][index][help] */
 282 
 283 {
 284         if (k->delay > 0) {
 285                 /* convert from msec to jiffies */
 286                 key_repeat_delay = (k->delay * HZ + 500) / 1000;
 287                 if (key_repeat_delay < 1)
 288                         key_repeat_delay = 1;
 289         }
 290         if (k->rate > 0) {
 291                 key_repeat_rate = (k->rate * HZ + 500) / 1000;
 292                 if (key_repeat_rate < 1)
 293                         key_repeat_rate = 1;
 294         }
 295 
 296         k->delay = key_repeat_delay * 1000 / HZ;
 297         k->rate  = key_repeat_rate  * 1000 / HZ;
 298         
 299         return( 0 );
 300 }

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