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
- Lines: 392
- Date:
Sun Sep 6 13:39:09 1998
- Orig file:
v2.1.120/linux/drivers/char/pc_keyb.c
- Orig date:
Sat Sep 5 16:46:40 1998
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