summaryrefslogtreecommitdiffstats
path: root/drivers/char/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/keyboard.c')
-rw-r--r--drivers/char/keyboard.c290
1 files changed, 192 insertions, 98 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1f8b86b73..f5c3e8568 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -18,17 +18,22 @@
#define KEYBOARD_IRQ 1
+#include <linux/autoconf.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/mm.h>
#include <linux/ptrace.h>
-#include <linux/config.h>
#include <linux/signal.h>
#include <linux/string.h>
+#include <linux/ioport.h>
#include <asm/bitops.h>
+#ifdef __mips__
+#include <asm/bootinfo.h>
+#include <asm/jazz.h>
+#endif
#include "kbd_kern.h"
#include "diacr.h"
@@ -75,28 +80,115 @@ extern void scrollback(int);
extern void scrollfront(int);
extern int vc_cons_allocated(unsigned int);
-#if defined (__i386__)
-#define fake_keyboard_interrupt() \
-__asm__ __volatile__("int $0x21")
-#elif defined (__mips__)
-extern void fake_keyboard_interrupt(void);
+#ifdef __i386__
+#define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21")
+#define kbd_inb_p(port) inb_p(port)
+#define kbd_inb(port) inb(port)
+#define kbd_outb_p(data,port) outb_p(data,port)
+#define kbd_outb(data,port) outb(data,port)
+
+#elif defined (CONFIG_MIPS_JAZZ)
+
+static volatile keyboard_hardware *kh = (void *) JAZZ_KEYBOARD_ADDRESS;
+
+extern __inline__ void
+fake_keyboard_interrupt(void)
+{
+printk("fake_keyboard_interrupt()\n");
+__asm__ __volatile__(
+ ".set\tnoat\n\t"
+ "mfc0\t$1,$13\n\t"
+ "ori\t$1,0x0100\n\t"
+ "mtc0\t$1,$13\n\t"
+ ".set\tat"
+ :::"$1");
+}
+
+#if 1
+extern __inline__ int
+kbd_inb_p(unsigned short port)
+{
+ int result;
+
+ if(port == 0x60)
+ result = kh->data;
+ else if(port == 0x64)
+ result = kh->command;
+ else printk("Eeeeks - bad port in kbd_inb_p()\n");
+ inb(0x80);
+
+ return result;
+}
+
+extern __inline__ int
+kbd_inb(unsigned short port)
+{
+ int result;
+
+ if(port == 0x60)
+ result = kh->data;
+ else if(port == 0x64)
+ result = kh->command;
+ else printk("Eeeeks - bad port in kbd_inb()\n");
+
+ return result;
+}
+
+extern __inline__ void
+kbd_outb_p(unsigned char data, unsigned short port)
+{
+ if(port == 0x60)
+ kh->data = data;
+ else if(port == 0x64)
+ kh->command = data;
+ else printk("Eeeeks - bad port in kbd_outb_p()\n");
+ inb(0x80);
+}
+
+extern __inline__ void
+kbd_outb(unsigned char data, unsigned short port)
+{
+ if(port == 0x60)
+ kh->data = data;
+ else if(port == 0x64)
+ kh->command = data;
+ else printk("Eeeeks - bad port in kbd_outb()\n");
+}
+#else /* !1 */
+
+#define kbd_inb_p(port) inb_p(port)
+#define kbd_inb(port) inb(port)
+#define kbd_outb_p(data,port) outb_p(data,port)
+#define kbd_outb(data,port) outb(data,port)
+
+#endif /* !1 */
+
+#else /* defined (__alpha__) || defined (CONFIG_DESKSTATION_TYNE) */
+
+#define fake_keyboard_interrupt() do ; while (0)
+#define kbd_inb_p(port) inb_p(port)
+#define kbd_inb(port) inb(port)
+#define kbd_outb_p(data,port) outb_p(data,port)
+#define kbd_outb(data,port) outb(data,port)
+
#endif
unsigned char kbd_read_mask = 0x01; /* modified by psaux.c */
/*
* global state includes the following, and various static variables
- * in this module: prev_scancode, shift_state, diacr, npadch,
- * dead_key_next, last_console
+ * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
+ * (last_console is now a global variable)
*/
/* shift state counters.. */
static unsigned char k_down[NR_SHIFT] = {0, };
/* keyboard key bitmap */
-static unsigned long key_down[8] = { 0, };
+#define BITS_PER_LONG (8*sizeof(unsigned long))
+static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
+extern int last_console;
static int want_console = -1;
-static int last_console = 0; /* last used VC */
static int dead_key_next = 0;
/*
* In order to retrieve the shift_state (for the mouse server), either
@@ -137,14 +229,14 @@ typedef void (void_fn)(void);
static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
- SAK, decr_console, incr_console;
+ SAK, decr_console, incr_console, spawn_console, bare_num;
static void_fnp spec_fn_table[] = {
do_null, enter, show_ptregs, show_mem,
show_state, send_intr, lastcons, caps_toggle,
num, hold, scroll_forw, scroll_back,
boot_it, caps_on, compose, SAK,
- decr_console, incr_console
+ decr_console, incr_console, spawn_console, bare_num
};
/* maximum values each key_handler can handle */
@@ -166,15 +258,16 @@ static inline void kb_wait(void)
{
int i;
- for (i=0; i<0x10000; i++)
- if ((inb_p(0x64) & 0x02) == 0)
- break;
+ for (i=0; i<0x100000; i++)
+ if ((kbd_inb_p(0x64) & 0x02) == 0)
+ return;
+ printk("Keyboard timed out\n");
}
static inline void send_cmd(unsigned char c)
{
kb_wait();
- outb(c,0x64);
+ kbd_outb(c,0x64);
}
/*
@@ -194,7 +287,7 @@ void to_utf8(ushort c) {
put_queue(0x80 | ((c >> 6) & 0x3f));
put_queue(0x80 | (c & 0x3f));
}
- /* utf-8 is defined for words of up to 36 bits,
+ /* UTF-8 is defined for words of up to 31 bits,
but we need only 16 bits here */
}
@@ -332,19 +425,19 @@ int getkeycode(unsigned int scancode)
e0_keys[scancode - 128];
}
-static void keyboard_interrupt(int int_pt_regs)
+static void keyboard_interrupt(int irq, struct pt_regs *regs)
{
unsigned char scancode, keycode;
static unsigned int prev_scancode = 0; /* remember E0, E1 */
char up_flag; /* 0 or 0200 */
char raw_mode;
- pt_regs = (struct pt_regs *) int_pt_regs;
+ pt_regs = regs;
send_cmd(0xAD); /* disable keyboard */
kb_wait();
- if ((inb_p(0x64) & kbd_read_mask) != 0x01)
+ if ((kbd_inb_p(0x64) & kbd_read_mask) != 0x01)
goto end_kbd_intr;
- scancode = inb(0x60);
+ scancode = kbd_inb(0x60);
mark_bh(KEYBOARD_BH);
if (reply_expected) {
/* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
@@ -370,25 +463,29 @@ static void keyboard_interrupt(int int_pt_regs)
prev_scancode = 0;
goto end_kbd_intr;
}
+
+ tty = ttytab[fg_console];
+ kbd = kbd_table + fg_console;
+ if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
+ put_queue(scancode);
+ /* we do not return yet, because we want to maintain
+ the key_down array, so that we have the correct
+ values when finishing RAW mode or when changing VT's */
+ }
+
if (scancode == 0xff) {
+ /* in scancode mode 1, my ESC key generates 0xff */
/* the calculator keys on a FOCUS 9000 generate 0xff */
#ifndef KBD_IS_FOCUS_9000
#ifdef KBD_REPORT_ERR
- printk("keyboard error\n");
+ if (!raw_mode)
+ printk("keyboard error\n");
#endif
#endif
prev_scancode = 0;
goto end_kbd_intr;
}
- tty = ttytab[fg_console];
- kbd = kbd_table + fg_console;
- if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
- put_queue(scancode);
- /* we do not return yet, because we want to maintain
- the key_down array, so that we have the correct
- values when finishing RAW mode or when changing VT's */
- }
if (scancode == 0xe0 || scancode == 0xe1) {
prev_scancode = scancode;
goto end_kbd_intr;
@@ -414,7 +511,8 @@ static void keyboard_interrupt(int int_pt_regs)
prev_scancode = 0;
} else {
#ifdef KBD_REPORT_UNKN
- printk("keyboard: unknown e1 escape sequence\n");
+ if (!raw_mode)
+ printk("keyboard: unknown e1 escape sequence\n");
#endif
prev_scancode = 0;
goto end_kbd_intr;
@@ -616,26 +714,8 @@ static void caps_on(void)
static void show_ptregs(void)
{
- if (!pt_regs)
- return;
-#if defined (__i386__)
- printk("\n");
- printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
- if (pt_regs->cs & 3)
- printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
- printk(" EFLAGS: %08lx\n",pt_regs->eflags);
- printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
- pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
- printk("ESI: %08lx EDI: %08lx EBP: %08lx",
- pt_regs->esi, pt_regs->edi, pt_regs->ebp);
- printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
- 0xffff & pt_regs->ds,0xffff & pt_regs->es,
- 0xffff & pt_regs->fs,0xffff & pt_regs->gs);
-#elif defined (__mips__)
- /*
- * FIXME...
- */
-#endif
+ if (pt_regs)
+ show_regs(pt_regs);
}
static void hold(void)
@@ -656,11 +736,21 @@ static void hold(void)
static void num(void)
{
- if (vc_kbd_mode(kbd,VC_APPLIC)) {
+ if (vc_kbd_mode(kbd,VC_APPLIC))
applkey('P', 1);
- return;
- }
- if (!rep) /* no autorepeat for numlock, ChN */
+ else
+ bare_num();
+}
+
+/*
+ * Bind this to Shift-NumLock if you work in application keypad mode
+ * but want to be able to change the NumLock flag.
+ * Bind this to NumLock if you prefer that the NumLock key always
+ * changes the NumLock flag.
+ */
+static void bare_num(void)
+{
+ if (!rep)
chg_vc_kbd_led(kbd,VC_NUMLOCK);
}
@@ -724,6 +814,15 @@ static void compose(void)
dead_key_next = 1;
}
+int spawnpid, spawnsig;
+
+static void spawn_console(void)
+{
+ if (spawnpid)
+ if(kill_proc(spawnpid, spawnsig, 1))
+ spawnpid = 0;
+}
+
static void SAK(void)
{
do_SAK(tty);
@@ -738,7 +837,7 @@ static void SAK(void)
* work.
*/
reset_vc(fg_console);
- unblank_screen(); /* not in interrupt routine? */
+ do_unblank_screen(); /* not in interrupt routine? */
#endif
}
@@ -964,8 +1063,8 @@ void compute_shiftstate(void)
for(i=0; i < SIZE(key_down); i++)
if(key_down[i]) { /* skip this word if not a single bit on */
- k = (i<<5);
- for(j=0; j<32; j++,k++)
+ k = i*BITS_PER_LONG;
+ for(j=0; j<BITS_PER_LONG; j++,k++)
if(test_bit(k, key_down)) {
sym = U(plain_map[k]);
if(KTYP(sym) == KT_SHIFT) {
@@ -1033,9 +1132,9 @@ static int send_data(unsigned char data)
acknowledge = 0;
resend = 0;
reply_expected = 1;
- outb_p(data, 0x60);
- for(i=0; i<0x20000; i++) {
- inb_p(0x64); /* just as a delay */
+ kbd_outb_p(data, 0x60);
+ for(i=0; i<0x200000; i++) {
+ kbd_inb_p(0x64); /* just as a delay */
if (acknowledge)
return 1;
if (resend)
@@ -1141,7 +1240,6 @@ static void kbd_bh(void * unused)
}
if (want_console >= 0) {
if (want_console != fg_console) {
- last_console = fg_console;
change_console(want_console);
/* we only changed when the console had already
been allocated - a new console is not created
@@ -1151,46 +1249,11 @@ static void kbd_bh(void * unused)
}
poke_blanked_console();
cli();
- if ((inb_p(0x64) & kbd_read_mask) == 0x01)
+ if ((kbd_inb_p(0x64) & kbd_read_mask) == 0x01)
fake_keyboard_interrupt();
sti();
}
-#ifdef __i386__
-long no_idt[2] = {0, 0};
-#endif
-
-/*
- * This routine reboots the machine by asking the keyboard
- * controller to pulse the reset-line low. We try that for a while,
- * and if it doesn't work, we do some other stupid things.
- */
-void hard_reset_now(void)
-{
- int i, j;
-#ifdef __i386__
- extern unsigned long pg0[1024];
-#endif
-
- sti();
-/* rebooting needs to touch the page at absolute addr 0 */
-#ifdef __i386__
- pg0[0] = 7;
- *((unsigned short *)0x472) = 0x1234;
-#endif
- for (;;) {
- for (i=0; i<100; i++) {
- kb_wait();
- for(j = 0; j < 100000 ; j++)
- /* nothing */;
- outb(0xfe,0x64); /* pulse reset low */
- }
-#ifdef __i386__
- __asm__("\tlidt _no_idt");
-#endif
- }
-}
-
unsigned long kbd_init(unsigned long kmem_start)
{
int i;
@@ -1210,6 +1273,37 @@ unsigned long kbd_init(unsigned long kmem_start)
bh_base[KEYBOARD_BH].routine = kbd_bh;
request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
+ request_region(0x60,1,"kbd");
+ request_region(0x64,1,"kbd");
+#ifdef __alpha__
+ /* enable keyboard interrupts, PC/AT mode */
+ kb_wait();
+ kbd_outb(0x60,0x64); /* write PS/2 Mode Register */
+ kb_wait();
+ kbd_outb(0x65,0x60); /* KCC | DMS | SYS | EKI */
+ kb_wait();
+ if (!send_data(0xf0) || !send_data(0x02))
+ printk("Scanmode 2 change failed\n");
+#elif defined (__mips__)
+ /*
+ * No special setup required for Deskstation Tyne
+ */
+ if (boot_info.machtype == MACH_ACER_PICA_61 ||
+ boot_info.machtype == MACH_MIPS_MAGNUM_4000) {
+ *((volatile u16 *)JAZZ_IO_IRQ_ENABLE) |= JAZZ_IE_KEYBOARD;
+ set_cp0_cause(IE_SW0, 0);
+ set_cp0_status(IE_SW0|IE_IRQ1, IE_SW0|IE_IRQ1);
+ /* enable keyboard interrupts, PC/AT mode */
+ kb_wait();
+ kbd_outb(0x60,0x64); /* write PS/2 Mode Register */
+ kb_wait();
+ kbd_outb(0x41,0x60); /* KCC | EKI */
+ kb_wait();
+ if (!send_data(0xf0) || !send_data(0x02))
+ printk("Scanmode 2 change failed\n");
+ }
+#endif
mark_bh(KEYBOARD_BH);
+ enable_bh(KEYBOARD_BH);
return kmem_start;
}