Mercurial > illumos > illumos-gate
changeset 3803:d9abbd815428
6531689 i8042: PS/2 mouse doesn't work until opening/closing /dev/kdmouse once
author | myers |
---|---|
date | Mon, 12 Mar 2007 11:20:47 -0700 |
parents | 6d539848fb03 |
children | 513de1daa569 |
files | usr/src/uts/common/io/i8042.c |
diffstat | 1 files changed, 48 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/i8042.c Mon Mar 12 11:14:37 2007 -0700 +++ b/usr/src/uts/common/io/i8042.c Mon Mar 12 11:20:47 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -473,13 +473,58 @@ return (DDI_SUCCESS); } +#define OBF_WAIT_COUNT 1000 /* in granules of 10uS */ + +/* + * Wait for the 8042 to fill the 'output' (from 8042 to host) + * buffer. If 8042 fails to fill the output buffer within an + * allowed time, return 1 (which means there is no data available), + * otherwise return 0 + */ +static int +i8042_wait_obf(struct i8042 *global) +{ + int timer = 0; + + while (!(ddi_get8(global->io_handle, global->io_addr + I8042_STAT) & + I8042_STAT_OUTBF)) { + if (++timer > OBF_WAIT_COUNT) + return (1); + drv_usecwait(10); + } + return (0); +} + +/* + * Drain all queued bytes from the 8042. + * Return 0 for no error, <> 0 if there was an error. + */ +static int +i8042_purge_outbuf(struct i8042 *global) +{ + int i; + + for (i = 0; i < MAX_JUNK_ITERATIONS; i++) { + if (i8042_wait_obf(global)) + break; + (void) ddi_get8(global->io_handle, + global->io_addr + I8042_DATA); + } + + /* + * If we hit the maximum number of iterations, then there + * was a serious problem (e.g. our hardware may not be + * present or working properly). + */ + return (i == MAX_JUNK_ITERATIONS); +} + static int i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { struct i8042_port *port; enum i8042_ports which_port; int i; - unsigned char stat; static ddi_device_acc_attr_t attr = { DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, @@ -632,21 +677,7 @@ global->init_state &= ~I8042_INIT_INTRS_ENABLED; /* Discard any junk data that may have been left around */ - for (i = 0; i < MAX_JUNK_ITERATIONS; i++) { - stat = ddi_get8(global->io_handle, - global->io_addr + I8042_STAT); - if (! (stat & I8042_STAT_OUTBF)) - break; - (void) ddi_get8(global->io_handle, - global->io_addr + I8042_DATA); - } - - /* - * If we hit the maximum number of iterations, then there - * was a serious problem (e.g. our hardware may not be - * present or working properly). - */ - if (i == MAX_JUNK_ITERATIONS) + if (i8042_purge_outbuf(global) != 0) goto fail; /* @@ -676,7 +707,6 @@ * Enable the main and aux data ports and interrupts */ i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL); - global->init_state |= I8042_INIT_INTRS_ENABLED; #ifdef __sparc