patch-2.1.106 linux/arch/m68k/hp300/hil.c
Next file: linux/arch/m68k/hp300/ints.c
Previous file: linux/arch/m68k/hp300/config.c
Back to the patch index
Back to the overall index
- Lines: 251
- Date:
Sat Jun 13 13:14:31 1998
- Orig file:
v2.1.105/linux/arch/m68k/hp300/hil.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.105/linux/arch/m68k/hp300/hil.c linux/arch/m68k/hp300/hil.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/m68k/hp300/hil.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *
+ * HP300 Human Interface Loop driver. This handles the keyboard and mouse.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/keyboard.h>
+#include <linux/kbd_ll.h>
+#include <asm/io.h>
+#include <asm/hwtest.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#define HILBASE 0xf0428000
+#define HIL_DATA 0x1
+#define HIL_CMD 0x3
+
+#define HIL_BUSY 0x02
+#define HIL_DATA_RDY 0x01
+
+#define hil_busy() (readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available() (readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status() (readb(HILBASE + HIL_CMD))
+#define hil_command(x) do { writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data() (readb(HILBASE + HIL_DATA))
+#define hil_write_data(x) do { writeb((x), HILBASE + HIL_DATA); } while (0)
+
+#define HIL_SETARD 0xA0 /* set auto-repeat delay */
+#define HIL_SETARR 0xA2 /* set auto-repeat rate */
+#define HIL_SETTONE 0xA3 /* set tone generator */
+#define HIL_CNMT 0xB2 /* clear nmi */
+#define HIL_INTON 0x5C /* Turn on interrupts. */
+#define HIL_INTOFF 0x5D /* Turn off interrupts. */
+#define HIL_TRIGGER 0xC5 /* trigger command */
+#define HIL_STARTCMD 0xE0 /* start loop command */
+#define HIL_TIMEOUT 0xFE /* timeout */
+#define HIL_READTIME 0x13 /* Read real time register */
+
+#define HIL_READBUSY 0x02 /* internal "busy" register */
+#define HIL_READKBDLANG 0x12 /* read keyboard language code */
+#define HIL_READKBDSADR 0xF9
+#define HIL_WRITEKBDSADR 0xE9
+#define HIL_READLPSTAT 0xFA
+#define HIL_WRITELPSTAT 0xEA
+#define HIL_READLPCTRL 0xFB
+#define HIL_WRITELPCTRL 0xEB
+
+#define HIL_IRQ 1
+
+static u_short hp_plain_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf702, 0xf036,
+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73,
+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76,
+ 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200,
+ 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200,
+ 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303,
+ 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+static u_short hp_shift_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf01b, 0xf20e, 0xf700, 0xf700, 0xf700, 0xf002, 0xf036,
+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+ 0xfb62, 0xfb76, 0xf063, 0xfb78, 0xfb7a, 0xf702, 0xfb61, 0xfb73,
+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+ 0xfb68, 0xfb67, 0xfb66, 0xfb64, 0xfb73, 0xfb61, 0xfb63, 0xfb76,
+ 0xfb75, 0xfb79, 0xfb74, 0xfb72, 0xfb65, 0xfb77, 0xfb71, 0xf200,
+ 0xf037, 0xf036, 0xf035, 0xf034, 0xf033, 0xf032, 0xf031, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf038, 0xf039, 0xf030, 0xf200, 0xf200, 0xf008, 0xf200, 0xf200,
+ 0xfb69, 0xfb6f, 0xfb70, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xfb6a, 0xfb6b, 0xfb6c, 0xf305, 0xf306, 0xf00d, 0xf302, 0xf303,
+ 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xfb6e, 0xf020, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+static u_short hp_ctrl_map[NR_KEYS] __initdata = {
+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
+ 0xf00f, 0xf010, 0xf003, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200,
+ 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+ 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
+ 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+struct {
+ unsigned char s, c;
+ int valid;
+} hil_last;
+
+#define hil_getlast(s,c) do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0)
+
+struct {
+ unsigned char data[16];
+ unsigned int ptr;
+} poll;
+
+unsigned char curdev = 0;
+
+static void poll_finished(void)
+{
+ switch (poll.data[0])
+ {
+ case 0x40:
+ {
+ unsigned char scode = (poll.data[1] >> 1) | ((poll.data[1] & 1)?0x80:0);
+#if 0
+ if (scode & 0x80)
+ printk("[%02x]", scode & 0x7f);
+#endif
+ handle_scancode(scode);
+ }
+ break;
+ }
+ curdev = 0;
+}
+
+static inline void handle_status(unsigned char s, unsigned char c)
+{
+ if (c & 0x8) {
+ /* End of block */
+ if (c & 0x10)
+ poll_finished();
+ } else {
+ if (c & 0x10) {
+ if (curdev)
+ poll_finished(); /* just in case */
+ curdev = c & 7;
+ poll.ptr = 0;
+ }
+ }
+}
+
+static inline void handle_data(unsigned char s, unsigned char c)
+{
+ if (curdev)
+ poll.data[poll.ptr++] = c;
+}
+
+/*
+ * Handle HIL interrupts.
+ */
+
+static void hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+{
+ unsigned char s, c;
+ s = hil_status(); c = hil_read_data();
+ switch (s >> 4)
+ {
+ case 0x5:
+ handle_status(s, c);
+ break;
+ case 0x6:
+ handle_data(s, c);
+ break;
+ case 0x4:
+ hil_last.s = s;
+ hil_last.c = c;
+ mb();
+ hil_last.valid = 1;
+ break;
+ }
+}
+
+/*
+ * Send a command to the HIL
+ */
+
+static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+{
+ unsigned long flags;
+ save_flags(flags); cli();
+ while (hil_busy());
+ hil_command(cmd);
+ while (len--) {
+ while (hil_busy());
+ hil_write_data(*(data++));
+ }
+ restore_flags(flags);
+}
+
+/*
+ * Initialise HIL.
+ */
+
+__initfunc(void hp300_hil_init(void))
+{
+ unsigned char s, c, kbid;
+ unsigned int n = 0;
+
+ memcpy(key_maps[0], hp_plain_map, sizeof(plain_map));
+ memcpy(key_maps[1], hp_shift_map, sizeof(plain_map));
+ memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map));
+
+ if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
+ return; /* maybe this can happen */
+
+ request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL);
+
+ /* Turn on interrupts */
+ hil_do(HIL_INTON, NULL, 0);
+
+ /* Look for keyboards */
+ hil_do(HIL_READKBDSADR, NULL, 0);
+ while (!hil_last.valid) {
+ if (n++ > 1000) {
+ printk("HIL: timed out, assuming no keyboard present.\n");
+ return;
+ }
+ mb();
+ }
+ hil_getlast(s, c);
+ if (c == 0) {
+ printk("HIL: no keyboard present.\n");
+ return;
+ }
+ for (kbid = 0; (kbid < 8) && ((c & (1<<kbid)) == 0); kbid++);
+ printk("HIL: keyboard found at id %d\n", kbid);
+ /* set it to raw mode */
+ c = 0;
+ hil_do(HIL_WRITEKBDSADR, &c, 1);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov