patch-2.0.9 linux/drivers/char/keyboard.c

Next file: linux/drivers/char/mem.c
Previous file: linux/drivers/cdrom/mcdx.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.8/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
@@ -18,6 +18,7 @@
  */
 
 #define KEYBOARD_IRQ 1
+#define DISABLE_KBD_DURING_INTERRUPTS 0
 
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -69,14 +70,6 @@
 #define KBD_DEFLOCK 0
 #endif
 
-/*
- * The default IO slowdown is doing 'inb()'s from 0x61, which should be
- * safe. But as that is the keyboard controller chip address, we do our
- * slowdowns here by doing short jumps: the keyboard controller should
- * be able to keep up
- */
-#define REALLY_SLOW_IO
-#define SLOW_IO_BY_JUMPING
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -337,48 +330,31 @@
 	    e0_keys[scancode - 128];
 }
 
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#if DISABLE_KBD_DURING_INTERRUPTS
+#define disable_keyboard()	do { send_cmd(0xAD); kb_wait(); } while (0)
+#define enable_keyboard()	send_cmd(0xAE)
+#else
+#define disable_keyboard()	/* nothing */
+#define enable_keyboard()	/* nothing */
+#endif
+
+static void handle_scancode(unsigned char scancode)
 {
-	unsigned char scancode, keycode;
+	unsigned char keycode;
 	static unsigned int prev_scancode = 0;   /* remember E0, E1 */
 	char up_flag;				 /* 0 or 0200 */
 	char raw_mode;
-	int status;
 
-	pt_regs = regs;
-	send_cmd(0xAD);		/* disable keyboard */
-	kb_wait();
-	status = inb_p(0x64);
-	if ((status & kbd_read_mask) != 0x01) {
-	  /*
-	   * On some platforms (Alpha XL for one), the init code may leave
-	   *  an interrupt hanging, yet with status indicating no data.
-	   * After making sure that there's no data indicated and its not a
-	   *  mouse interrupt, we will read the data register to clear it.
-	   * If we don't do this, the data reg stays full and will not
-	   *  allow new data or interrupt from the keyboard. Sigh...
-	   */
-	  if (!(status & 0x21)) { /* neither ODS nor OBF */
-	    scancode = inb(0x60); /* read data anyway */
-#if 0
-	    printk(KERN_DEBUG "keyboard: status 0x%x  mask 0x%x  data 0x%x\n",
-		   status, kbd_read_mask, scancode);
-#endif
-	  }
-	  goto end_kbd_intr;
-	}
-	scancode = inb(0x60);
-	mark_bh(KEYBOARD_BH);
 	if (reply_expected) {
 	  /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
 	  /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
 		reply_expected = 0;
 		if (scancode == 0xfa) {
 			acknowledge = 1;
-			goto end_kbd_intr;
+			return;
 		} else if (scancode == 0xfe) {
 			resend = 1;
-			goto end_kbd_intr;
+			return;
 		}
 		/* strange ... */
 		reply_expected = 1;
@@ -392,7 +368,7 @@
 		printk(KERN_INFO "keyboard buffer overflow\n");
 #endif
 		prev_scancode = 0;
-		goto end_kbd_intr;
+		return;
 	}
 	do_poke_blanked_console = 1;
 	mark_bh(CONSOLE_BH);
@@ -417,12 +393,12 @@
 #endif
 #endif
 		prev_scancode = 0;
-		goto end_kbd_intr;
+		return;
 	}
 
 	if (scancode == 0xe0 || scancode == 0xe1) {
 		prev_scancode = scancode;
-		goto end_kbd_intr;
+		return;
  	}
 
  	/*
@@ -439,7 +415,7 @@
 	  if (prev_scancode != 0xe0) {
 	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
 		  prev_scancode = 0x100;
-		  goto end_kbd_intr;
+		  return;
 	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
 		  keycode = E1_PAUSE;
 		  prev_scancode = 0;
@@ -449,7 +425,7 @@
 		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
 #endif
 		  prev_scancode = 0;
-		  goto end_kbd_intr;
+		  return;
 	      }
 	  } else {
 	      prev_scancode = 0;
@@ -467,7 +443,7 @@
 	       *  So, we should also ignore the latter. - aeb@cwi.nl
 	       */
 	      if (scancode == 0x2a || scancode == 0x36)
-		goto end_kbd_intr;
+		return;
 
 	      if (e0_keys[scancode])
 		keycode = e0_keys[scancode];
@@ -477,7 +453,7 @@
 		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
 			   scancode);
 #endif
-		  goto end_kbd_intr;
+		  return;
 	      }
 	  }
 	} else if (scancode >= SC_LIM) {
@@ -500,7 +476,7 @@
 			 " - ignored\n", scancode);
 #endif
 	      }
-	      goto end_kbd_intr;
+	      return;
 	  }
  	} else
 	  keycode = scancode;
@@ -526,12 +502,12 @@
  		rep = set_bit(keycode, key_down);
 
 	if (raw_mode)
-		goto end_kbd_intr;
+		return;
 
 	if (kbd->kbdmode == VC_MEDIUMRAW) {
 		/* soon keycodes will require more than one byte */
  		put_queue(keycode + up_flag);
-		goto end_kbd_intr;
+		return;
  	}
 
  	/*
@@ -592,9 +568,32 @@
 #endif
 		}
 	}
+}
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char status;
 
-end_kbd_intr:
-	send_cmd(0xAE);         /* enable keyboard */
+	pt_regs = regs;
+	disable_keyboard();
+
+	status = inb_p(0x64);
+	do {
+		unsigned char scancode;
+
+		/* mouse data? */
+		if (status & kbd_read_mask & 0x20)
+			break;
+
+		scancode = inb(0x60);
+		if (status & 0x01)
+			handle_scancode(scancode);
+
+		status = inb(0x64);
+	} while (status & 0x01);
+
+	mark_bh(KEYBOARD_BH);
+	enable_keyboard();
 }
 
 static void put_queue(int ch)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov