diff options
author | Søren Schmidt <sos@FreeBSD.org> | 1996-12-01 19:05:50 +0000 |
---|---|---|
committer | Søren Schmidt <sos@FreeBSD.org> | 1996-12-01 19:05:50 +0000 |
commit | 1f9d9075e43147bf28dfb2ab3d39c63eff1c0e3d (patch) | |
tree | 54352ee80d9cef4ec7de46e9031694a7e6a7126f /sys/isa/kbdio.c | |
parent | 661a46b5a163770aa911b4314e6ea6f5e621f989 (diff) | |
download | src-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.c | 255 |
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; } |