patch-2.1.121 linux/drivers/char/pc_keyb.c

Next file: linux/drivers/misc/parport_pc.c
Previous file: linux/drivers/char/pc110pad.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.120/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
@@ -43,194 +43,6 @@
 	"\r\000/";					/* 0x60 - 0x6f */
 #endif
 
-/*
- * In case we run on a non-x86 hardware we need to initialize both the keyboard
- * controller and the keyboard. On a x86, the BIOS will already have initialized
- * them.
- */
-
-/*
- * Some x86 BIOSes do not correctly initialize the keyboard, so the
- * "kbd-reset" command line options can be given to force a reset.
- * [Ranger]
- */
-#ifdef __i386__
- int kbd_startup_reset __initdata = 0;
-#else
- int kbd_startup_reset __initdata = 1;
-#endif
-
-__initfunc(static int kbd_wait_for_input(void))
-{
-	long timeout = KBD_INIT_TIMEOUT;
-	int retval = -1;
-
-	goto in_loop;
-	for (;;) {
-		unsigned char status, data;
-		if (--timeout < 0)
-			break;
-		mdelay(1);
-in_loop:
-		status = inb(KBD_STATUS_REG);
-
-		/*
-		 * Wait for input data to become available.  This bit will
-		 * then be cleared by the following read of the DATA
-		 * register.
-		 */
-		if (!(status & KBD_STAT_OBF))
-			continue;
-
-		data = inb(KBD_DATA_REG);
-
-		/*
-		 * Check to see if a timeout error has occurred.  This means
-		 * that transmission was started but did not complete in the
-		 * normal time cycle.  PERR is set when a parity error occurred
-		 * in the last transmission.
-		 */
-		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
-			continue;
-
-		retval = data;
-		break;
-	}
-	return retval;
-}
-
-__initfunc(static void kbd_write(int address, int data))
-{
-	int status;
-
-	do {
-		status = inb(KBD_STATUS_REG);
-	} while (status & KBD_STAT_IBF);
-	outb(data, address);
-}
-
-__initfunc(static char *initialize_kbd2(void))
-{
-	int status;
-
-	/* Flush any pending input. */
-
-	while (kbd_wait_for_input() != -1)
-		;
-
-	/*
-	 * Test the keyboard interface.
-	 * This seems to be the only way to get it going.
-	 * If the test is successful a x55 is placed in the input buffer.
-	 */
-
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
-	if (kbd_wait_for_input() != 0x55)
-		return "Keyboard failed self test";
-
-	/*
-	 * Perform a keyboard interface test.  This causes the controller
-	 * to test the keyboard clock and data lines.  The results of the
-	 * test are placed in the input buffer.
-	 */
-
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
-	if (kbd_wait_for_input() != 0x00)
-		return "Keyboard interface failed self test";
-
-	/* Enable the keyboard by allowing the keyboard clock to run. */
-
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);
-
-	/*
-	 * Reset keyboard. If the read times out
-	 * then the assumption is that no keyboard is
-	 * plugged into the machine.
-	 * This defaults the keyboard to scan-code set 2.
-	 *
-	 * Set up to try again if the keyboard asks for RESEND.
-	 */
-
-	do {
-		kbd_write(KBD_DATA_REG, KBD_CMD_RESET);
-		status = kbd_wait_for_input();
-		if (status == KBD_REPLY_ACK)
-			break;
-		else if (status != KBD_REPLY_RESEND)
-			return "Keyboard reset failed, no ACK";
-	} while (1);
-
-	if (kbd_wait_for_input() != KBD_REPLY_POR)
-		return "Keyboard reset failed, no POR";
-
-	/*
-	 * Set keyboard controller mode. During this, the keyboard should be
-	 * in the disabled state.
-	 *
-	 * Set up to try again if the keyboard asks for RESEND.
-	 */
-
-	do {
-		kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
-		status = kbd_wait_for_input();
-		if (status == KBD_REPLY_ACK)
-			break;
-		else if (status != KBD_REPLY_RESEND)
-			return "Disable keyboard: no ACK";
-	} while (1);
-
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
-	kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT
-			      | KBD_MODE_SYS
-			      | KBD_MODE_DISABLE_MOUSE
-			      | KBD_MODE_KCC);
-
-	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);
-	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
-		/*
-		 * If the controller does not support conversion,
-		 * Set the keyboard to scan-code set 1.
-		 */
-		kbd_write(KBD_DATA_REG, 0xF0);
-		kbd_wait_for_input();
-		kbd_write(KBD_DATA_REG, 0x01);
-		kbd_wait_for_input();
-	}
-
-	
-	kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
-		return "Enable keyboard: no ACK";
-
-	/*
-	 * Finally, set the typematic rate to maximum.
-	 */
-
-	kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
-		return "Set rate: no ACK";
-	kbd_write(KBD_DATA_REG, 0x00);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
-		return "Set rate: no ACK";
-
-	return NULL;
-}
-
-__initfunc(static void initialize_kbd(void))
-{
-	char *msg;
-
-	disable_irq(KEYBOARD_IRQ);
-	msg = initialize_kbd2();
-	enable_irq(KEYBOARD_IRQ);
-
-	if (msg)
-		printk(KERN_WARNING "initialize_kbd: %s\n", msg);
-}
-
-
-
 unsigned char pckbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */
 
 /* used only by send_data - set by keyboard_interrupt */
@@ -625,15 +437,189 @@
 	    send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */
 }
 
-__initfunc(void pckbd_init_hw(void))
-{
-	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
-	request_region(0x60, 16, "keyboard");
-	if (kbd_startup_reset) initialize_kbd();
-}
+/*
+ * In case we run on a non-x86 hardware we need to initialize both the
+ * keyboard controller and the keyboard.  On a x86, the BIOS will
+ * already have initialized them.
+ *
+ * Some x86 BIOSes do not correctly initialize the keyboard, so the
+ * "kbd-reset" command line options can be given to force a reset.
+ * [Ranger]
+ */
+#ifdef __i386__
+ int kbd_startup_reset __initdata = 0;
+#else
+ int kbd_startup_reset __initdata = 1;
+#endif
 
 /* for "kbd-reset" cmdline param */
-__initfunc(void kbd_reset_setup(char *str, int *ints))
+void __init kbd_reset_setup(char *str, int *ints)
 {
 	kbd_startup_reset = 1;
+}
+
+#define KBD_NO_DATA	(-1)	/* No data */
+#define KBD_BAD_DATA	(-2)	/* Parity or other error */
+
+static int __init kbd_read_input(void)
+{
+	int retval = KBD_NO_DATA;
+	unsigned char status;
+
+	status = inb(KBD_STATUS_REG);
+	if (status & KBD_STAT_OBF) {
+		unsigned char data = inb(KBD_DATA_REG);
+
+		retval = data;
+		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+			retval = KBD_BAD_DATA;
+	}
+	return retval;
+}
+
+static void __init kbd_clear_input(void)
+{
+	int maxread = 100;	/* Random number */
+
+	do {
+		if (kbd_read_input() == KBD_NO_DATA)
+			break;
+	} while (--maxread);
+}
+
+static int __init kbd_wait_for_input(void)
+{
+	long timeout = KBD_INIT_TIMEOUT;
+
+	do {
+		int retval = kbd_read_input();
+		if (retval >= 0)
+			return retval;
+		mdelay(1);
+	} while (--timeout);
+	return -1;
+}
+
+static void __init kbd_write(int address, int data)
+{
+	int status;
+
+	do {
+		status = inb(KBD_STATUS_REG);
+	} while (status & KBD_STAT_IBF);
+	outb(data, address);
+}
+
+static char * __init initialize_kbd(void)
+{
+	int status;
+
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55)
+		return "Keyboard failed self test";
+
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
+	if (kbd_wait_for_input() != 0x00)
+		return "Keyboard interface failed self test";
+
+	/*
+	 * Enable the keyboard by allowing the keyboard clock to run.
+	 */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write(KBD_DATA_REG, KBD_CMD_RESET);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Keyboard reset failed, no ACK";
+	} while (1);
+
+	if (kbd_wait_for_input() != KBD_REPLY_POR)
+		return "Keyboard reset failed, no POR";
+
+	/*
+	 * Set keyboard controller mode. During this, the keyboard should be
+	 * in the disabled state.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Disable keyboard: no ACK";
+	} while (1);
+
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
+	kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT
+			      | KBD_MODE_SYS
+			      | KBD_MODE_DISABLE_MOUSE
+			      | KBD_MODE_KCC);
+
+	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+	kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);
+	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+		/*
+		 * If the controller does not support conversion,
+		 * Set the keyboard to scan-code set 1.
+		 */
+		kbd_write(KBD_DATA_REG, 0xF0);
+		kbd_wait_for_input();
+		kbd_write(KBD_DATA_REG, 0x01);
+		kbd_wait_for_input();
+	}
+
+	
+	kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Enable keyboard: no ACK";
+
+	/*
+	 * Finally, set the typematic rate to maximum.
+	 */
+	kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Set rate: no ACK";
+	kbd_write(KBD_DATA_REG, 0x00);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Set rate: no ACK";
+
+	return NULL;
+}
+
+void __init pckbd_init_hw(void)
+{
+	/* Flush any pending input. */
+	kbd_clear_input();
+
+	if (kbd_startup_reset) {
+		char *msg = initialize_kbd();
+		if (msg)
+			printk(KERN_WARNING "initialize_kbd: %s\n", msg);
+	}
+
+	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
+	request_region(0x60, 16, "keyboard");
 }

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