linux-old/arch/m68k/hp300/hil.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68k/hp300/hil.c
   3 *
   4 *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
   5 *
   6 *  HP300 Human Interface Loop driver.  This handles the keyboard and mouse.
   7 */
   8
   9#include <linux/stddef.h>
  10#include <linux/kernel.h>
  11#include <linux/sched.h>
  12#include <linux/init.h>
  13#include <linux/keyboard.h>
  14#include <linux/kbd_ll.h>
  15#include <asm/io.h>
  16#include <asm/hwtest.h>
  17#include <asm/ptrace.h>
  18#include <asm/irq.h>
  19#include <asm/system.h>
  20
  21#define HILBASE                 0xf0428000
  22#define HIL_DATA                        0x1
  23#define HIL_CMD                 0x3
  24
  25#define HIL_BUSY                0x02
  26#define HIL_DATA_RDY            0x01
  27
  28#define hil_busy()              (in_8(HILBASE + HIL_CMD) & HIL_BUSY)
  29#define hil_data_available()    (in_8(HILBASE + HIL_CMD) & HIL_DATA_RDY)
  30#define hil_status()            (in_8(HILBASE + HIL_CMD))
  31#define hil_command(x)          out_8(HILBASE + HIL_CMD, (x))
  32#define hil_read_data()         (in_8(HILBASE + HIL_DATA))
  33#define hil_write_data(x)       out_8(HILBASE + HIL_DATA, (x))
  34
  35#define HIL_SETARD              0xA0            /* set auto-repeat delay */
  36#define HIL_SETARR              0xA2            /* set auto-repeat rate */
  37#define HIL_SETTONE             0xA3            /* set tone generator */
  38#define HIL_CNMT                0xB2            /* clear nmi */
  39#define HIL_INTON               0x5C            /* Turn on interrupts. */
  40#define HIL_INTOFF              0x5D            /* Turn off interrupts. */
  41#define HIL_TRIGGER             0xC5            /* trigger command */
  42#define HIL_STARTCMD            0xE0            /* start loop command */
  43#define HIL_TIMEOUT             0xFE            /* timeout */
  44#define HIL_READTIME            0x13            /* Read real time register */
  45
  46#define HIL_READBUSY            0x02            /* internal "busy" register */
  47#define HIL_READKBDLANG         0x12            /* read keyboard language code */
  48#define HIL_READKBDSADR         0xF9
  49#define HIL_WRITEKBDSADR        0xE9
  50#define HIL_READLPSTAT          0xFA
  51#define HIL_WRITELPSTAT         0xEA
  52#define HIL_READLPCTRL          0xFB
  53#define HIL_WRITELPCTRL         0xEB
  54
  55#define HIL_IRQ                 1
  56
  57#define plain_map               hp_plain_map
  58#define shift_map               hp_shift_map
  59#define altgr_map               hp_altgr_map
  60#define ctrl_map                hp_ctrl_map
  61#define shift_ctrl_map          hp_shift_ctrl_map
  62#define alt_map                 hp_alt_map
  63#define ctrl_alt_map            hp_ctrl_alt_map
  64
  65u_short plain_map[NR_KEYS] = {
  66        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
  67        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  68        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  69        0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xf200, 0xf200, 0xf01b,
  70        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  71        0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf200, 0xf207,
  72        0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf009,
  73        0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf060,
  74        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  75        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
  76        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
  77        0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf200, 0xf200,
  78        0xfb69, 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf05c, 0xf200, 0xf200,
  79        0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, 0xf027, 0xf201, 0xf200, 0xf200,
  80        0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200,
  81        0xfb6e, 0xf020, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
  82};
  83
  84u_short shift_map[NR_KEYS] = {
  85        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
  86        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  87        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  88        0xfb42, 0xfb56, 0xfb43, 0xfb58, 0xfb5a, 0xf200, 0xf200, 0xf07f,
  89        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  90        0xfb48, 0xfb47, 0xfb46, 0xfb44, 0xfb53, 0xfb41, 0xf200, 0xf207,
  91        0xfb55, 0xfb59, 0xfb54, 0xfb52, 0xfb45, 0xfb57, 0xfb51, 0xf009,
  92        0xf026, 0xf05e, 0xf025, 0xf024, 0xf023, 0xf040, 0xf021, 0xf07e,
  93        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
  94        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
  95        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
  96        0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf200, 0xf200, 0xf200,
  97        0xfb49, 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf07c, 0xf200, 0xf200,
  98        0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf201, 0xf200, 0xf200,
  99        0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf200, 0xf200, 0xf200, 0xf200,
 100        0xfb4e, 0xf020, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 101};
 102
 103u_short altgr_map[NR_KEYS] = {
 104        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
 105        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 106        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 107        0xfb62, 0xfb76, 0xfb63, 0xfb78, 0xfb7a, 0xf200, 0xf200, 0xf200,
 108        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 109        0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xf200, 0xf207,
 110        0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200,
 111        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf040, 0xf021, 0xf200,
 112        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 113        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
 114        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
 115        0xf02a, 0xf05b, 0xf05d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 116        0xfb69, 0xfb6f, 0xfb70, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 117        0xfb6a, 0xfb6b, 0xfb6c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200,
 118        0xfb6d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 119        0xfb6e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 120};
 121
 122u_short ctrl_map[NR_KEYS] = {
 123        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
 124        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 125        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 126        0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xf200, 0xf200, 0xf200,
 127        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 128        0xf008, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf200, 0xf207,
 129        0xf015, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200,
 130        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf000,
 131        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 132        0xf200, 0xf503, 0xf502, 0xf501, 0xf500, 0xf200, 0xf200, 0xf200,
 133        0xf200, 0xf504, 0xf505, 0xf506, 0xf507, 0xf200, 0xf200, 0xf200,
 134        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 135        0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf01c, 0xf200, 0xf200,
 136        0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf201, 0xf200, 0xf200,
 137        0xf00d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 138        0xf00e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 139};
 140
 141u_short shift_ctrl_map[NR_KEYS] = {
 142        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
 143        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 144        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 145        0xf002, 0xf016, 0xf003, 0xf018, 0xf01a, 0xf200, 0xf200, 0xf200,
 146        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 147        0xf008, 0xf007, 0xf006, 0xf004, 0xf013, 0xf001, 0xf200, 0xf207,
 148        0xf015, 0xf019, 0xf014, 0xf012, 0xf005, 0xf017, 0xf011, 0xf200,
 149        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 150        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 151        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
 152        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
 153        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 154        0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 155        0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200,
 156        0xf00d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 157        0xf00e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 158};
 159
 160u_short alt_map[NR_KEYS] = {
 161        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
 162        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 163        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 164        0xf862, 0xf876, 0xf863, 0xf878, 0xf87a, 0xf200, 0xf200, 0xf200,
 165        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 166        0xf868, 0xf867, 0xf866, 0xf864, 0xf873, 0xf861, 0xf200, 0xf207,
 167        0xf875, 0xf879, 0xf874, 0xf872, 0xf865, 0xf877, 0xf871, 0xf809,
 168        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf860,
 169        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 170        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
 171        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
 172        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 173        0xf869, 0xf86f, 0xf870, 0xf200, 0xf200, 0xf85c, 0xf200, 0xf200,
 174        0xf86a, 0xf86b, 0xf86c, 0xf83b, 0xf827, 0xf201, 0xf200, 0xf200,
 175        0xf86d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 176        0xf86e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 177};
 178
 179u_short ctrl_alt_map[NR_KEYS] = {
 180        0xf200, 0xf200, 0xf703, 0xf703, 0xf700, 0xf700, 0xf702, 0xf200,
 181        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 182        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 183        0xf802, 0xf816, 0xf803, 0xf818, 0xf81a, 0xf200, 0xf200, 0xf200,
 184        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 185        0xf808, 0xf807, 0xf806, 0xf804, 0xf813, 0xf801, 0xf200, 0xf207,
 186        0xf815, 0xf819, 0xf814, 0xf812, 0xf805, 0xf817, 0xf811, 0xf200,
 187        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 188        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 189        0xf200, 0xf103, 0xf102, 0xf101, 0xf100, 0xf200, 0xf200, 0xf200,
 190        0xf200, 0xf104, 0xf105, 0xf106, 0xf107, 0xf200, 0xf200, 0xf200,
 191        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 192        0xf809, 0xf80f, 0xf810, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 193        0xf80a, 0xf80b, 0xf80c, 0xf200, 0xf200, 0xf201, 0xf200, 0xf200,
 194        0xf80d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
 195        0xf80e, 0xf200, 0xf200, 0xf200, 0xf601, 0xf600, 0xf603, 0xf602,
 196};
 197
 198#undef plain_map
 199#undef ctrl_alt_map
 200#undef shift_map
 201#undef altgr_map
 202#undef ctrl_map
 203#undef shift_ctrl_map
 204#undef alt_map
 205
 206struct {
 207  unsigned char s, c;
 208  int valid;
 209} hil_last;
 210
 211#define hil_getlast(s,c)  do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0)
 212
 213struct {
 214  unsigned char data[16];
 215  unsigned int ptr;
 216} poll;
 217
 218unsigned char curdev = 0;
 219
 220static void poll_finished(void)
 221{
 222  switch (poll.data[0])
 223  {
 224  case 0x40:
 225    {
 226      int down = (poll.data[1] & 1) == 0;
 227      unsigned char scode = poll.data[1] >> 1;
 228#if 0
 229      if (down)
 230        printk("[%02x]", scode);
 231#endif
 232      handle_scancode(scode, down);
 233    }
 234    break;
 235  }
 236  curdev = 0;
 237}
 238
 239static inline void handle_status(unsigned char s, unsigned char c)
 240{
 241  if (c & 0x8) {
 242    /* End of block */
 243    if (c & 0x10)
 244      poll_finished();
 245  } else {
 246    if (c & 0x10) {
 247      if (curdev)
 248        poll_finished();                /* just in case */
 249      curdev = c & 7;
 250      poll.ptr = 0;
 251    }
 252  }
 253}
 254
 255static inline void handle_data(unsigned char s, unsigned char c)
 256{
 257  if (curdev)
 258    poll.data[poll.ptr++] = c;
 259}
 260
 261/* 
 262 * Handle HIL interrupts.
 263 */
 264
 265static void hil_interrupt(int irq, void *handle, struct pt_regs *regs)
 266{
 267  unsigned char s, c;
 268  s = hil_status(); c = hil_read_data();
 269  switch (s >> 4)
 270  {
 271  case 0x5:
 272    handle_status(s, c);
 273    break;
 274  case 0x6:
 275    handle_data(s, c);
 276    break;
 277  case 0x4:
 278    hil_last.s = s;
 279    hil_last.c = c;
 280    mb();
 281    hil_last.valid = 1;
 282    break;
 283  }
 284}
 285
 286/*
 287 * Send a command to the HIL
 288 */
 289
 290static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
 291{
 292  unsigned long flags;
 293  save_flags(flags); cli();
 294  while (hil_busy());
 295  hil_command(cmd);
 296  while (len--) {
 297    while (hil_busy());
 298    hil_write_data(*(data++));
 299  }
 300  restore_flags(flags);
 301}
 302
 303/*
 304 * Initialise HIL. 
 305 */
 306
 307int __init hp300_keyb_init(void)
 308{
 309  unsigned char s, c, kbid;
 310  unsigned int n = 0;
 311
 312  memcpy(key_maps[0], hp_plain_map, sizeof(plain_map));
 313  memcpy(key_maps[1], hp_shift_map, sizeof(plain_map));
 314  memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map));
 315
 316  if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
 317    return 1;           /* maybe this can happen */
 318
 319  request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL);
 320
 321  /* Turn on interrupts */
 322  hil_do(HIL_INTON, NULL, 0);
 323
 324  /* Look for keyboards */
 325  hil_do(HIL_READKBDSADR, NULL, 0);
 326  while (!hil_last.valid) {
 327    if (n++ > 100000) {
 328      printk("HIL: timed out, assuming no keyboard present.\n");
 329      return 1;
 330    }
 331    mb();
 332  }
 333  hil_getlast(s, c);
 334  if (c == 0) {
 335    printk("HIL: no keyboard present.\n");
 336    return 1;
 337  }
 338  for (kbid = 0; (kbid < 8) && ((c & (1<<kbid)) == 0); kbid++);
 339  printk("HIL: keyboard found at id %d\n", kbid);
 340  /* set it to raw mode */
 341  c = 0;
 342  hil_do(HIL_WRITEKBDSADR, &c, 1);
 343  return 0;
 344}
 345
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.