aboutsummaryrefslogtreecommitdiff
path: root/sys/isa/kbdio.c
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>1996-12-01 19:05:50 +0000
committerSøren Schmidt <sos@FreeBSD.org>1996-12-01 19:05:50 +0000
commit1f9d9075e43147bf28dfb2ab3d39c63eff1c0e3d (patch)
tree54352ee80d9cef4ec7de46e9031694a7e6a7126f /sys/isa/kbdio.c
parent661a46b5a163770aa911b4314e6ea6f5e621f989 (diff)
downloadsrc-1f9d9075e43147bf28dfb2ab3d39c63eff1c0e3d.tar.gz
src-1f9d9075e43147bf28dfb2ab3d39c63eff1c0e3d.zip
Alot of fixes from kazu:
1. All the suggestions earlier made by Bruce: renaming some symbols, stricter error checking, removing redundant code, etc. 2. The `psm' driver preserves the default counter resolution and report rate, whatever they are after reset. (Based on reports and suggestion from Nate and Rob Bolin). 3. The `psm' driver now does not check the so-called sync. bit in the first byte of the data packet by default, so that the tapping feature of ALPUS GlidePoint works (based on reports from Louis Mamakos). I tested the code with ALPUS Desktop GlidePoint (M/N GP101) and found no problem; tapping worked. It appears ALPUS produces several models of GlidePoint. I hope the other models are OK too. The check code can still be activated by defining the PSM_CHECKSYNC option in the config file. (The bit checking slightly reduces, if not completely eliminates, weird mouse behavior cased by unsynchronized mouse data packets. It also helps us to detect if the mouse interrupt can ever be lost. But, well, if there are devices which cannot be supported this way...) 4. The `psm' driver does not include the protocol emulation code by default. The code can still be compiled in if the PSM_EMULATION option is specified in the config file. Louis Mamakos suggests the emulation code is putting too much in the kernel, and `moused' works well. I will think about this later and decide if the entire emulation code should be removed. 5. And, of course, the fix in `scprobe()' from Bruce to cure the UserConfig problem. My code in `kbdio.c' is slightly different from his patch, but has the same effect. There still is a possibility that `scprobe()' gets confused, if, for whatever reasons, the user holds down a key for very long time during the boot process. But we cannot cope with everything, can we? Submitted by: Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
Notes
Notes: svn path=/head/; revision=20073
Diffstat (limited to 'sys/isa/kbdio.c')
-rw-r--r--sys/isa/kbdio.c255
1 files changed, 151 insertions, 104 deletions
diff --git a/sys/isa/kbdio.c b/sys/isa/kbdio.c
index f3262958a8f5..797dcff62580 100644
--- a/sys/isa/kbdio.c
+++ b/sys/isa/kbdio.c
@@ -26,16 +26,23 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: kbdio.c,v 1.1 1996/11/14 22:19:06 sos Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/syslog.h>
#include <machine/clock.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <i386/isa/kbdio.h>
+#ifndef KBDIO_DEBUG
+#define KBDIO_DEBUG 0
+#endif
+
+static int verbose = KBDIO_DEBUG;
+
/*
* device I/O routines
*/
@@ -45,22 +52,7 @@ wait_while_controller_busy(int port)
/* CPU will stay inside the loop for 100msec at most */
int retry = 5000;
- while (inb(port + KBD_STATUS_PORT) & KBDS_CONTROLLER_BUSY) {
- DELAY(20);
- if (--retry < 0)
- return FALSE;
- }
- return TRUE;
-}
-
-int
-wait_until_controller_is_really_idle(int port)
-{
- /* CPU will stay inside the loop for 100msec at most */
- int retry = 5000;
-
- while (inb(port + KBD_STATUS_PORT)
- & (KBDS_CONTROLLER_BUSY | KBDS_ANY_BUFFER_FULL)) {
+ while (inb(port + KBD_STATUS_PORT) & KBDS_INPUT_BUFFER_FULL) {
DELAY(20);
if (--retry < 0)
return FALSE;
@@ -83,6 +75,7 @@ wait_for_data(int port)
if (--retry < 0)
return FALSE;
}
+ DELAY(7);
return TRUE;
}
@@ -99,6 +92,7 @@ wait_for_kbd_data(int port)
if (--retry < 0)
return FALSE;
}
+ DELAY(7);
return TRUE;
}
@@ -115,46 +109,54 @@ wait_for_aux_data(int port)
if (--retry < 0)
return FALSE;
}
+ DELAY(7);
return TRUE;
}
-void
+int
write_controller_command(int port, int c)
{
- wait_until_controller_is_really_idle(port);
+ if (!wait_while_controller_busy(port))
+ return FALSE;
outb(port + KBD_COMMAND_PORT, c);
+ return TRUE;
}
-void
+int
write_controller_data(int port, int c)
{
- wait_until_controller_is_really_idle(port);
+ if (!wait_while_controller_busy(port))
+ return FALSE;
outb(port + KBD_DATA_PORT, c);
+ return TRUE;
}
-void
+int
write_kbd_command(int port, int c)
{
- wait_until_controller_is_really_idle(port);
+ if (!wait_while_controller_busy(port))
+ return FALSE;
outb(port + KBD_DATA_PORT, c);
+ return TRUE;
}
-void
+int
write_aux_command(int port, int c)
{
- write_controller_command(port,KBDC_WRITE_TO_AUX);
- write_controller_data(port, c);
+ if (!write_controller_command(port,KBDC_WRITE_TO_AUX))
+ return FALSE;
+ return write_controller_data(port, c);
}
int
send_kbd_command(int port, int c)
{
int retry = KBD_MAXRETRY;
- int res;
+ int res = -1;
while (retry-- > 0) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, c);
+ if (!write_kbd_command(port, c))
+ continue;
res = read_controller_data(port);
if (res == KBD_ACK)
break;
@@ -166,13 +168,11 @@ int
send_aux_command(int port, int c)
{
int retry = KBD_MAXRETRY;
- int res;
+ int res = -1;
while (retry-- > 0) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_COMMAND_PORT, KBDC_WRITE_TO_AUX);
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, c);
+ if (!write_aux_command(port, c))
+ continue;
res = read_aux_data(port);
if (res == PSM_ACK)
break;
@@ -184,19 +184,23 @@ int
send_kbd_command_and_data(int port, int c, int d)
{
int retry;
- int res;
+ int res = -1;
for (retry = KBD_MAXRETRY; retry > 0; --retry) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, c);
+ if (!write_kbd_command(port, c))
+ continue;
res = read_controller_data(port);
if (res == KBD_ACK)
break;
+ else if (res != PSM_RESEND)
+ return res;
}
+ if (retry <= 0)
+ return res;
- for (retry = KBD_MAXRETRY; retry > 0; --retry) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, d);
+ for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
+ if (!write_kbd_command(port, d))
+ continue;
res = read_controller_data(port);
if (res != KBD_RESEND)
break;
@@ -208,25 +212,23 @@ int
send_aux_command_and_data(int port, int c, int d)
{
int retry;
- int res;
+ int res = -1;
for (retry = KBD_MAXRETRY; retry > 0; --retry) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_COMMAND_PORT, KBDC_WRITE_TO_AUX);
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, c);
+ if (!write_aux_command(port, c))
+ continue;
res = read_aux_data(port);
if (res == PSM_ACK)
break;
else if (res != PSM_RESEND)
return res;
}
+ if (retry <= 0)
+ return res;
- for (retry = KBD_MAXRETRY; retry > 0; --retry) {
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_COMMAND_PORT, KBDC_WRITE_TO_AUX);
- wait_until_controller_is_really_idle(port);
- outb(port + KBD_DATA_PORT, d);
+ for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
+ if (!write_aux_command(port, d))
+ continue;
res = read_aux_data(port);
if (res != PSM_RESEND)
break;
@@ -241,7 +243,6 @@ send_aux_command_and_data(int port, int c, int d)
int
read_controller_data(int port)
{
- wait_while_controller_busy(port);
if (!wait_for_data(port))
return -1; /* timeout */
return inb(port + KBD_DATA_PORT);
@@ -251,7 +252,6 @@ read_controller_data(int port)
int
read_kbd_data(int port)
{
- wait_while_controller_busy(port);
if (!wait_for_kbd_data(port))
return -1; /* timeout */
return inb(port + KBD_DATA_PORT);
@@ -263,10 +263,10 @@ read_kbd_data(int port)
int
read_kbd_data_no_wait(int port)
{
- wait_while_controller_busy(port);
if ((inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
!= KBDS_KBD_BUFFER_FULL)
return -1; /* no data */
+ DELAY(7);
return inb(port + KBD_DATA_PORT);
}
@@ -274,7 +274,6 @@ read_kbd_data_no_wait(int port)
int
read_aux_data(int port)
{
- wait_while_controller_busy(port);
if (!wait_for_aux_data(port))
return -1; /* timeout */
return inb(port + KBD_DATA_PORT);
@@ -282,55 +281,64 @@ read_aux_data(int port)
/* discard data from the keyboard */
void
-empty_kbd_buffer(int port)
+empty_kbd_buffer(int port, int t)
{
int b;
int c = 0;
+ int delta = 2;
- while ((inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
+ for (; t > 0; t -= delta) {
+ if ((inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
== KBDS_KBD_BUFFER_FULL) {
+ DELAY(7);
b = inb(port + KBD_DATA_PORT);
++c;
- DELAY(20);
}
-#ifdef KBDIO_DEBUG
+ DELAY(delta*1000);
+ }
+ if ((verbose >= 2) && (c > 0))
log(LOG_DEBUG,"kbdio: %d char read (empty_kbd_buffer)\n",c);
-#endif
}
/* discard data from the aux device */
void
-empty_aux_buffer(int port)
+empty_aux_buffer(int port, int t)
{
int b;
int c = 0;
+ int delta = 2;
- while ((inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
+ for (; t > 0; t -= delta) {
+ if ((inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
== KBDS_AUX_BUFFER_FULL) {
+ DELAY(7);
b = inb(port + KBD_DATA_PORT);
++c;
- DELAY(20);
}
-#ifdef KBDIO_DEBUG
+ DELAY(delta*1000);
+ }
+ if ((verbose >= 2) && (c > 0))
log(LOG_DEBUG,"kbdio: %d char read (empty_aux_buffer)\n",c);
-#endif
}
/* discard any data from the keyboard or the aux device */
void
-empty_both_buffers(int port)
+empty_both_buffers(int port, int t)
{
int b;
int c = 0;
+ int delta = 2;
- while (inb(port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
+ for (; t > 0; t -= delta) {
+ if (inb(port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
+ DELAY(7);
b = inb(port + KBD_DATA_PORT);
++c;
- DELAY(20);
}
-#ifdef KBDIO_DEBUG
+ DELAY(delta*1000);
+ }
+ if ((verbose >= 2) && (c > 0))
log(LOG_DEBUG,"kbdio: %d char read (empty_both_buffers)\n",c);
-#endif
}
/* keyboard and mouse device control */
@@ -343,15 +351,15 @@ reset_kbd(int port)
{
int retry = KBD_MAXRETRY;
int again = KBD_MAXWAIT;
- int c;
+ int c = KBD_RESEND; /* keep the compiler happy */
while (retry-- > 0) {
- empty_both_buffers(port);
- write_kbd_command(port, KBDC_RESET_KBD);
+ empty_both_buffers(port, 10);
+ if (!write_kbd_command(port, KBDC_RESET_KBD))
+ continue;
c = read_controller_data(port);
-#ifdef KBDIO_DEBUG
+ if (verbose)
log(LOG_DEBUG,"kbdio: RESET_KBD return code:%04x\n",c);
-#endif
if (c == KBD_ACK) /* keyboard has agreed to reset itself... */
break;
}
@@ -365,9 +373,8 @@ reset_kbd(int port)
if (c != -1) /* wait again if the controller is not ready */
break;
}
-#ifdef KBDIO_DEBUG
+ if (verbose)
log(LOG_DEBUG,"kbdio: RESET_KBD status:%04x\n",c);
-#endif
if (c != KBD_RESET_DONE)
return FALSE;
return TRUE;
@@ -381,15 +388,15 @@ reset_aux_dev(int port)
{
int retry = KBD_MAXRETRY;
int again = KBD_MAXWAIT;
- int c;
+ int c = PSM_RESEND; /* keep the compiler happy */
while (retry-- > 0) {
- empty_both_buffers(port);
- write_aux_command(port, PSMC_RESET_DEV);
- c = read_controller_data(port); /* read_aux_data()? */
-#ifdef KBDIO_DEBUG
+ empty_both_buffers(port, 10);
+ if (!write_aux_command(port, PSMC_RESET_DEV))
+ continue;
+ c = read_controller_data(port);
+ if (verbose)
log(LOG_DEBUG,"kbdio: RESET_AUX return code:%04x\n",c);
-#endif
if (c == PSM_ACK) /* aux dev is about to reset... */
break;
}
@@ -403,16 +410,14 @@ reset_aux_dev(int port)
if (c != -1) /* wait again if the controller is not ready */
break;
}
-#ifdef KBDIO_DEBUG
+ if (verbose)
log(LOG_DEBUG,"kbdio: RESET_AUX status:%04x\n",c);
-#endif
if (c != PSM_RESET_DONE) /* reset status */
return FALSE;
c = read_aux_data(port); /* device ID */
-#ifdef KBDIO_DEBUG
+ if (verbose)
log(LOG_DEBUG,"kbdio: RESET_AUX ID:%04x\n",c);
-#endif
/* NOTE: we could check the device ID now, but leave it later... */
return TRUE;
}
@@ -422,49 +427,91 @@ reset_aux_dev(int port)
int
test_controller(int port)
{
- int c;
+ int retry = KBD_MAXRETRY;
+ int again = KBD_MAXWAIT;
+ int c = KBD_DIAG_FAIL;
+
+ while (retry-- > 0) {
+ empty_both_buffers(port, 10);
+ if (write_controller_command(port, KBDC_DIAGNOSE))
+ break;
+ }
+ if (retry < 0)
+ return FALSE;
- empty_both_buffers(port);
- write_controller_command(port, KBDC_DIAGNOSE);
+ while (again-- > 0) {
+ /* wait awhile */
+ DELAY(KBD_RESETDELAY*1000);
c = read_controller_data(port); /* DIAG_DONE/DIAG_FAIL */
-#ifdef KBDIO_DEBUG
+ if (c != -1) /* wait again if the controller is not ready */
+ break;
+ }
+ if (verbose)
log(LOG_DEBUG,"kbdio: DIAGNOSE status:%04x\n",c);
-#endif
return (c == KBD_DIAG_DONE);
}
int
test_kbd_port(int port)
{
- int c;
+ int retry = KBD_MAXRETRY;
+ int again = KBD_MAXWAIT;
+ int c = -1;
- empty_both_buffers(port);
- write_controller_command(port, KBDC_TEST_KBD_PORT);
+ while (retry-- > 0) {
+ empty_both_buffers(port, 10);
+ if (write_controller_command(port, KBDC_TEST_KBD_PORT))
+ break;
+ }
+ if (retry < 0)
+ return FALSE;
+
+ while (again-- > 0) {
c = read_controller_data(port);
-#ifdef KBDIO_DEBUG
+ if (c != -1) /* try again if the controller is not ready */
+ break;
+ }
+ if (verbose)
log(LOG_DEBUG,"kbdio: TEST_KBD_PORT status:%04x\n",c);
-#endif
return c;
}
int
test_aux_port(int port)
{
- int c;
+ int retry = KBD_MAXRETRY;
+ int again = KBD_MAXWAIT;
+ int c = -1;
- empty_both_buffers(port);
- write_controller_command(port, KBDC_TEST_AUX_PORT);
+ while (retry-- > 0) {
+ empty_both_buffers(port, 10);
+ if (write_controller_command(port, KBDC_TEST_AUX_PORT))
+ break;
+ }
+ if (retry < 0)
+ return FALSE;
+
+ while (again-- > 0) {
c = read_controller_data(port);
-#ifdef KBDIO_DEBUG
+ if (c != -1) /* try again if the controller is not ready */
+ break;
+ }
+ if (verbose)
log(LOG_DEBUG,"kbdio: TEST_AUX_PORT status:%04x\n",c);
-#endif
return c;
}
-void
+int
set_controller_command_byte(int port, int command, int flag)
{
- write_controller_command(port, KBDC_SET_COMMAND_BYTE);
- write_controller_data(port, command | flag);
+ if ((command | flag) & KBD_DISABLE_KBD_PORT) {
+ if (!write_controller_command(port, KBDC_DISABLE_KBD_PORT))
+ return FALSE;
+ }
+ if (!write_controller_command(port, KBDC_SET_COMMAND_BYTE))
+ return FALSE;
+ if (!write_controller_data(port, command | flag))
+ return FALSE;
wait_while_controller_busy(port);
+ return TRUE;
}