diff options
author | nate <nate@FreeBSD.org> | 1996-11-15 06:17:36 +0000 |
---|---|---|
committer | nate <nate@FreeBSD.org> | 1996-11-15 06:17:36 +0000 |
commit | 7ad9f1fc7f0c7f952767e11d81a8bec53d055d0b (patch) | |
tree | d8efc933a14207e6af94b920565da539e1ac7035 /sys/i386/isa/psm.c | |
parent | 244d25ed3a8775c648b5096a16f56b9a56921a02 (diff) | |
download | FreeBSD-src-7ad9f1fc7f0c7f952767e11d81a8bec53d055d0b.zip FreeBSD-src-7ad9f1fc7f0c7f952767e11d81a8bec53d055d0b.tar.gz |
KNF'ify and fix boo-boo I made in last commit.
Diffstat (limited to 'sys/i386/isa/psm.c')
-rw-r--r-- | sys/i386/isa/psm.c | 1795 |
1 files changed, 910 insertions, 885 deletions
diff --git a/sys/i386/isa/psm.c b/sys/i386/isa/psm.c index 9acfc30..03faf6c 100644 --- a/sys/i386/isa/psm.c +++ b/sys/i386/isa/psm.c @@ -19,7 +19,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: psm.c,v 1.26 1996/11/15 05:30:52 nate Exp $ + * $Id: psm.c,v 1.27 1996/11/15 05:41:34 nate Exp $ */ /* @@ -48,7 +48,7 @@ * * Hardware access routines and probe logic rewritten by * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp> - * - 3 October 1996. + * - 3 October 1996. * - 14 October 1996. * - 22 October 1996. * - 28 October 1996. Start adding IOCTLs. @@ -70,7 +70,7 @@ #include <sys/syslog.h> #ifdef DEVFS #include <sys/devfsext.h> -#endif /*DEVFS*/ +#endif #include <i386/include/mouse.h> #include <i386/include/clock.h> @@ -79,23 +79,22 @@ #include <i386/isa/isa_device.h> #include <i386/isa/kbdio.h> -/* driver specific options: the following options may be set by - `options' statements in the kernel configuration file. */ +/* + * driver specific options: the following options may be set by + * `options' statements in the kernel configuration file. + */ /* debugging */ #ifndef PSM_DEBUG -#define PSM_DEBUG 0 /* controls debug logging: - 0: no logging, 1: brief, 2: verbose */ +#define PSM_DEBUG 0 /* logging: 0: none, 1: brief, 2: verbose */ #endif /* features */ -/* #define PSM_NOCHECKSYNC the driver does not check the header data - byte, if defined */ +/* #define PSM_NOCHECKSYNC if defined, don't check the header data byte */ #ifndef PSM_ACCEL -#define PSM_ACCEL 2 /* the default acceleration factor, must - be one or greater; acceleration will be - disabled if zero */ +#define PSM_ACCEL 2 /* must be one or greater; acceleration will be + * disabled if zero */ #endif /* #define PSM_NOEMULATION disables protocol emulation */ @@ -112,59 +111,58 @@ #define PSM_MKMINOR(unit,block) (((unit) << 1) | ((block) ? 0:1)) #ifndef max -#define max(x,y) ((x) > (y) ? (x) : (y)) +#define max(x,y) ((x) > (y) ? (x) : (y)) #endif #ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) +#define min(x,y) ((x) < (y) ? (x) : (y)) #endif /* mouse status block */ typedef struct mousestatus { - int button; /* button status */ - int obutton; /* previous button status */ - int dx; /* x movement */ - int dy; /* y movement */ + int button; /* button status */ + int obutton; /* previous button status */ + int dx; /* x movement */ + int dy; /* y movement */ } mousestatus_t; /* ring buffer */ -#define PSM_BUFSIZE 256 +#define PSM_BUFSIZE 256 typedef struct ringbuf { - int count; - int head; - int tail; - mousestatus_t buf[PSM_BUFSIZE]; + int count; + int head; + int tail; + mousestatus_t buf[PSM_BUFSIZE]; } ringbuf_t; /* driver control block */ typedef int (*packetfunc_t) __P((unsigned char *, int *, int, mousestatus_t *)); -static struct psm_softc { /* Driver status information */ - struct selinfo rsel; /* Process selecting for Input */ - unsigned char state; /* Mouse driver state */ - int addr; /* I/O port address */ - int command_byte; /* controller command byte */ - mousehw_t hw; /* hardware information */ - mousemode_t mode; /* operation mode */ - ringbuf_t queue; /* mouse status queue */ - packetfunc_t mkpacket; /* func. to turn queued data - into output format */ - char ipacket[MOUSE_PS2_PACKETSIZE]; /* interim input buffer */ - unsigned char opacket[PSM_BUFSIZE]; /* output buffer */ - int inputbytes; /* # of bytes in the input buffer */ - int outputbytes; /* # of bytes in the output buffer */ - int outputhead; /* points the head of the output buffer */ - int button; /* the latest button state */ +static struct psm_softc { /* Driver status information */ + struct selinfo rsel; /* Process selecting for Input */ + unsigned char state; /* Mouse driver state */ + int addr; /* I/O port address */ + int command_byte; /* controller command byte */ + mousehw_t hw; /* hardware information */ + mousemode_t mode; /* operation mode */ + ringbuf_t queue; /* mouse status queue */ + packetfunc_t mkpacket; /* func. to turn queued data into output format */ + char ipacket[MOUSE_PS2_PACKETSIZE]; /* interim input buffer */ + unsigned char opacket[PSM_BUFSIZE]; /* output buffer */ + int inputbytes; /* # of bytes in the input buffer */ + int outputbytes; /* # of bytes in the output buffer */ + int outputhead; /* points the head of the output buffer */ + int button; /* the latest button state */ #ifdef DEVFS - void *devfs_token; - void *n_devfs_token; + void *devfs_token; + void *n_devfs_token; #endif } psm_softc[NPSM]; /* driver state flags (state) */ -#define PSM_VALID 0x80 -#define PSM_OPEN 1 /* Device is open */ -#define PSM_ASLP 2 /* Waiting for mouse data */ +#define PSM_VALID 0x80 +#define PSM_OPEN 1 /* Device is open */ +#define PSM_ASLP 2 /* Waiting for mouse data */ /* function prototypes */ static int psmprobe __P((struct isa_device *)); @@ -181,13 +179,12 @@ static d_select_t psmselect; /* device driver declarateion */ struct isa_driver psmdriver = { psmprobe, psmattach, "psm", FALSE }; +#define CDEV_MAJOR 21 -#define CDEV_MAJOR 21 - -static struct cdevsw psm_cdevsw = { +static struct cdevsw psm_cdevsw = { psmopen, psmclose, psmread, nowrite, /* 21 */ - psmioctl, nostop, nullreset, nodevtotty, - psmselect, nommap, NULL, "psm", NULL, -1 + psmioctl, nostop, nullreset, nodevtotty, + psmselect, nommap, NULL, "psm", NULL, -1 }; /* debug message level */ @@ -197,216 +194,227 @@ static int verbose = PSM_DEBUG; static int enable_aux_dev(int port) { - int res; + int res; - res = send_aux_command(port,PSMC_ENABLE_DEV); - if (verbose >= 2) - log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n",res); + res = send_aux_command(port, PSMC_ENABLE_DEV); + if (verbose >= 2) + log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res); - return (res == PSM_ACK); + return (res == PSM_ACK); } static int disable_aux_dev(int port) { - int res; + int res; - res = send_aux_command(port, PSMC_DISABLE_DEV); - if (verbose >= 2) - log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n",res); + res = send_aux_command(port, PSMC_DISABLE_DEV); + if (verbose >= 2) + log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res); - return (res == PSM_ACK); + return (res == PSM_ACK); } static int get_mouse_status(int port, int *status) { - int res; + int res; - empty_both_buffers(port); - res = send_aux_command(port,PSMC_SEND_DEV_STATUS); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SEND_AUX_STATUS return code:%04x\n",res); - if (res != PSM_ACK) - return FALSE; + empty_both_buffers(port); + res = send_aux_command(port, PSMC_SEND_DEV_STATUS); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SEND_AUX_STATUS return code:%04x\n", res); + if (res != PSM_ACK) + return FALSE; - status[0] = read_aux_data(port); - status[1] = read_aux_data(port); - status[2] = read_aux_data(port); + status[0] = read_aux_data(port); + status[1] = read_aux_data(port); + status[2] = read_aux_data(port); - return TRUE; + return TRUE; } static int get_aux_id(int port) { - int retry; - int id; - int c; - - for(retry = KBD_MAXRETRY; retry > 0; --retry) { - empty_both_buffers(port); - write_aux_command(port,PSMC_SEND_DEV_ID); - /* 10ms delay */ - DELAY(10000); - c = read_controller_data(port); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n",c); - if (c == PSM_ACK) - break; - } - if (retry <= 0) - return -1; - - id = read_aux_data(port); - if (verbose >= 2) - log(LOG_DEBUG, "psm: device ID: %04x\n",id); - - return id; + int retry; + int id; + int c; + + for (retry = KBD_MAXRETRY; retry > 0; --retry) { + empty_both_buffers(port); + write_aux_command(port, PSMC_SEND_DEV_ID); + /* 10ms delay */ + DELAY(10000); + c = read_controller_data(port); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", c); + if (c == PSM_ACK) + break; + } + if (retry <= 0) + return -1; + + id = read_aux_data(port); + if (verbose >= 2) + log(LOG_DEBUG, "psm: device ID: %04x\n", id); + + return id; } static int set_mouse_sampling_rate(int port, int rate) { - int res; + int res; - res = send_aux_command_and_data(port,PSMC_SET_SAMPLING_RATE,rate); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n",rate,res); + res = send_aux_command_and_data(port, PSMC_SET_SAMPLING_RATE, rate); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res); - return ((res == PSM_ACK) ? rate : -1); + return ((res == PSM_ACK) ? rate : -1); } static int set_mouse_scaling(int port) { - int res; + int res; - res = send_aux_command(port,PSMC_SET_SCALING11); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SET_SCALING11 return code:%04x\n",res); + res = send_aux_command(port, PSMC_SET_SCALING11); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SET_SCALING11 return code:%04x\n", res); - return (res == PSM_ACK); + return (res == PSM_ACK); } static int set_mouse_resolution(int port, int res) { - static struct { - int resolution; - int code; - } rescode[] = { - { 25, PSMD_RESOLUTION_25 }, - { 50, PSMD_RESOLUTION_50 }, - { 100, PSMD_RESOLUTION_100 }, - { 200, PSMD_RESOLUTION_200 }, - { 400, PSMD_RESOLUTION_400 }, /* ?? */ - { 800, PSMD_RESOLUTION_800 }, /* ?? */ - { INT_MAX, PSMD_MAX_RESOLUTION }, - }; - int ret; - int i; - - if (res <= 0) - return FALSE; - for(i = 0; rescode[i].resolution > 0; ++i) { - if (rescode[i].resolution >= res) - break; - } - - for(; i >= 0; --i) { - ret = send_aux_command_and_data(port, - PSMC_SET_RESOLUTION,rescode[i].code); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", - rescode[i].code,ret); - if (ret == PSM_ACK) - return rescode[i].resolution; - } - - return (-1); + static struct { + int resolution; + int code; + } rescode[] = { + { 25, PSMD_RESOLUTION_25 }, + { 50, PSMD_RESOLUTION_50 }, + { 100, PSMD_RESOLUTION_100 }, + { 200, PSMD_RESOLUTION_200 }, + { 400, PSMD_RESOLUTION_400 }, /* ?? */ + { 800, PSMD_RESOLUTION_800 }, /* ?? */ + { INT_MAX, PSMD_MAX_RESOLUTION }, + }; + int ret; + int i; + + if (res <= 0) + return FALSE; + for (i = 0; rescode[i].resolution > 0; ++i) + if (rescode[i].resolution >= res) + break; + + for (; i >= 0; --i) { + ret = send_aux_command_and_data(port, + PSMC_SET_RESOLUTION, rescode[i].code); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", + rescode[i].code, ret); + if (ret == PSM_ACK) + return rescode[i].resolution; + } + + return (-1); } -/* NOTE: once `set_mouse_mode()' is called, the mouse device must be - re-enabled by calling `enable_aux_dev()' */ +/* + * NOTE: once `set_mouse_mode()' is called, the mouse device must be + * re-enabled by calling `enable_aux_dev()' + */ static int set_mouse_mode(int port) { - int res; + int res; - res = send_aux_command(port,PSMC_SET_STREAM_MODE); - if (verbose >= 2) - log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n",res); + res = send_aux_command(port, PSMC_SET_STREAM_MODE); + if (verbose >= 2) + log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res); - return (res == PSM_ACK); + return (res == PSM_ACK); } static int get_mouse_buttons(int port) { - int c = 2; /* assume two buttons by default */ - int status[3]; - - /* NOTE: a special sequence to obtain Logitech-Mouse-specific - information: set resolution to 25 ppi, set scaling to 1:1, - set scaling to 1:1, set scaling to 1:1. Then the second - byte of the mouse status bytes is the number of available - buttons. */ - if (!set_mouse_resolution(port,25)) - return c; - if (set_mouse_scaling(port) && set_mouse_scaling(port) - && set_mouse_scaling(port) && get_mouse_status(port,status)) { - if (verbose) { - log(LOG_DEBUG, "psm: status %02x %02x %02x (get_mouse_buttons)\n", - status[0],status[1],status[2]); - } - if (status[1] == 3) - return 3; - } - return c; + int c = 2; /* assume two buttons by default */ + int status[3]; + + /* + * NOTE: a special sequence to obtain Logitech-Mouse-specific + * information: set resolution to 25 ppi, set scaling to 1:1, set + * scaling to 1:1, set scaling to 1:1. Then the second byte of the + * mouse status bytes is the number of available buttons. + */ + if (!set_mouse_resolution(port, 25)) + return c; + if (set_mouse_scaling(port) && set_mouse_scaling(port) + && set_mouse_scaling(port) && get_mouse_status(port, status)) { + if (verbose) { + log(LOG_DEBUG, "psm: status %02x %02x %02x (get_mouse_buttons)\n", + status[0], status[1], status[2]); + } + if (status[1] == 3) + return 3; + } + return c; } -/* FIXME: someday, I will get the list of valid pointing devices and - their IDs... */ +/* + * FIXME:XXX + * someday, I will get the list of valid pointing devices and + * their IDs... + */ static int is_a_mouse(int id) { - static int valid_ids[] = { - PSM_MOUSE_ID, /* mouse */ - PSM_BALLPOINT_ID, /* ballpoint device */ - -1 /* end of table */ - }; - /* - int i; - - for(i = 0; valid_ids[i] >= 0; ++i) { - if (valid_ids[i] == id) - return TRUE; - } - return FALSE; - */ - return TRUE; + static int valid_ids[] = { + PSM_MOUSE_ID, /* mouse */ + PSM_BALLPOINT_ID, /* ballpoint device */ + -1 /* end of table */ + }; +#if 0 + int i; + + for(i = 0; valid_ids[i] >= 0; ++i) + if (valid_ids[i] == id) + return TRUE; + return FALSE; +#endif + return TRUE; } static void recover_from_error(int port) { - /* discard anything left in the output buffer */ - empty_both_buffers(port); - - /* NOTE: KBDC_RESET_KBD may not restore the communication between - the keyboard and the controller. */ - /* reset_kbd(port); */ - /* NOTE: somehow diagnostic and keyboard port test commands bring - the keyboard back. */ - test_controller(port); - test_kbd_port(port); + /* discard anything left in the output buffer */ + empty_both_buffers(port); + +#if 0 + /* + * NOTE: KBDC_RESET_KBD may not restore the communication between the + * keyboard and the controller. + */ + reset_kbd(port); +#else + /* + * NOTE: somehow diagnostic and keyboard port test commands bring the + * keyboard back. + */ + test_controller(port); + test_kbd_port(port); +#endif } static void restore_controller(int port, int command_byte) { - set_controller_command_byte(port,command_byte,0); + set_controller_command_byte(port, command_byte, 0); } /* psm driver entry points */ @@ -414,756 +422,773 @@ restore_controller(int port, int command_byte) static int psmprobe(struct isa_device *dvp) { - int unit = dvp->id_unit; - int ioport = dvp->id_iobase; - struct psm_softc *sc; - int stat[3]; - int i; - - /* validate unit number */ - if (unit >= NPSM) - return (0); - - sc = &psm_softc[unit]; - sc->addr = ioport; - if (bootverbose) - ++verbose; - - /* FIXME: the keyboard interrupt should be disabled while - probing a mouse? */ - - /* NOTE: two bits in the command byte controls the operation of - the aux port (mouse port): the aux port disable bit (bit 5) and - the aux port interrupt (IRQ 12) enable bit (bit 2). - When this probe routine is called, there are following possibilities - about the presence of the aux port and the PS/2 mouse. - - Case 1: aux port disabled (bit 5:1), aux int. disabled (bit 2:0) - The aux port most certainly exists. A device may or may not be - connected to the port. No driver is probably installed yet. - - Case 2: aux port enabled (bit 5:0), aux int. disabled (bit 2:0) - Three possibile situations here: - - Case 2a: - The aux port does not exist, therefore, is not explicitly disabled. - Case 2b: - The aux port exists. A device and a driver may exist, - using the device in the polling(remote) mode. - Case 2c: - The aux port exists. A device may exist, but someone who knows - nothing about the aux port has set the command byte this way - (this is the case with `syscons'). - - Case 3: aux port disabled (bit 5:1), aux int. enabled (bit 2:1) - The aux port exists, but someone is controlloing the device and - temporalily disabled the port. - - Case 4: aux port enabled (bit 5:0), aux int. enabled (bit 2:1) - The aux port exists, a device is attached to the port, and - someone is controlling the device. Some BIOS set the bits this - way after boot. - - All in all, it is no use examing the bits for detecting - the presence of the port and the mouse device. - */ - - /* save the current command byte; it will be used later */ - write_controller_command(ioport,KBDC_GET_COMMAND_BYTE); - sc->command_byte = read_controller_data(ioport); - if (verbose) { - printf("psm%d: current command byte:%04x\n", - unit,sc->command_byte); - } - if (sc->command_byte == -1) { - printf("psm%d: unable to get the current command byte value.\n", - unit); - return (0); - } - - /* disable the keyboard port while probing the aux port, which - must be enabled during this routine */ - write_controller_command(ioport,KBDC_DISABLE_KBD_PORT); - set_controller_command_byte(ioport, - sc->command_byte - & ~(KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS), - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - - /* NOTE: `test_aux_port()' is designed to return with zero - if the aux port exists and is functioning. However, some - controllers appears to respond with zero even when the aux port - doesn't exist. (It may be that this is only the case when the - controller DOES have the aux port but the port is not wired - on the motherboard.) The keyboard controllers without the port, - such as the original AT, are supporsed to return with - an error code or simply time out. In any case, we have to - continue probing the port even when the controller passes - this test. - */ - switch((i = test_aux_port(ioport))) { - case 0: /* no error */ - break; - case -1: /* time out */ - default: /* error */ - recover_from_error(ioport); - restore_controller(ioport,sc->command_byte); - if (verbose) - printf("psm%d: the aux port is not functioning (%d).\n", - unit,i); - if (bootverbose) - --verbose; - return (0); - } - - /* NOTE: some controllers appears to hang the `keyboard' when - the aux port doesn't exist and `PSMC_RESET_DEV' is issued. */ - if (!reset_aux_dev(ioport)) { - recover_from_error(ioport); - restore_controller(ioport,sc->command_byte); - if (verbose) - printf("psm%d: failed to reset the aux device.\n",unit); - return (0); - } - - /* both the aux port and the aux device is functioning, see - if the device can be enabled. - NOTE: when enabled, the device will start sending data; - we shall immediately disable the device once we know - the device can be enabled. */ - if (!enable_aux_dev(ioport) || !disable_aux_dev(ioport)) { - restore_controller(ioport,sc->command_byte); - if (verbose) - printf("psm%d: failed to enable the aux device.\n",unit); - if (bootverbose) - --verbose; - return (0); - } - empty_both_buffers(ioport); /* remove stray data if any */ - - /* hardware information */ - sc->hw.iftype = MOUSE_IF_PS2; - - /* verify the device is a mouse */ - sc->hw.hwid = get_aux_id(ioport); - if (!is_a_mouse(sc->hw.hwid)) { - restore_controller(ioport,sc->command_byte); - if (verbose) - printf("psm%d: unknown device type (%d).\n",unit,sc->hw.hwid); - if (bootverbose) - --verbose; - return (0); - } - switch (sc->hw.hwid) { - case PSM_BALLPOINT_ID: - sc->hw.type = MOUSE_TRACKBALL; - break; - case PSM_MOUSE_ID: - sc->hw.type = MOUSE_MOUSE; - break; - default: - sc->hw.type = MOUSE_UNKNOWN; - break; - } - - /* # of buttons */ - sc->hw.buttons = get_mouse_buttons(ioport); - - /* set mouse parameters */ - /* FIXME: I don't know if these parameters are reasonable */ - /* FIXME: should we set them in `psmattach()' rather than here? */ - sc->mode.rate = set_mouse_sampling_rate(ioport,PSMD_DEFAULT_RATE); - sc->mode.resolution = - set_mouse_resolution(ioport,PSMD_DEFAULT_RESOLUTION); - set_mouse_scaling(ioport); /* 1:1 scaling */ - set_mouse_mode(ioport); /* stream mode */ - - /* just check the status of the mouse */ - if (verbose) { - get_mouse_status(ioport,stat); - log(LOG_DEBUG, "psm%d: status %02x %02x %02x\n", - unit,stat[0],stat[1],stat[2]); - } - - /* disable the aux port for now... */ - /* WARNING: we save the controller command byte and use it later - during `psmopen()' and `psmclose()'. This will be OK, so long - as the keyboard/console device driver won't change the command - byte in the course of its operation (this is the case with - `syscons'). If not,... */ - sc->command_byte &= ~KBD_AUX_CONTROL_BITS; - set_controller_command_byte(ioport,sc->command_byte, - KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - - /* done */ - return (IO_PSMSIZE); + int unit = dvp->id_unit; + int ioport = dvp->id_iobase; + struct psm_softc *sc; + int stat[3]; + int i; + + /* validate unit number */ + if (unit >= NPSM) + return (0); + + sc = &psm_softc[unit]; + sc->addr = ioport; + if (bootverbose) + ++verbose; + + /* + * FIXME:XXX + * the keyboard interrupt should be disabled while probing a + * mouse? + */ + + /* + * NOTE: two bits in the command byte controls the operation of the + * aux port (mouse port): the aux port disable bit (bit 5) and the aux + * port interrupt (IRQ 12) enable bit (bit 2). When this probe routine + * is called, there are following possibilities about the presence of + * the aux port and the PS/2 mouse. + * + * Case 1: aux port disabled (bit 5:1), aux int. disabled (bit 2:0) The + * aux port most certainly exists. A device may or may not be + * connected to the port. No driver is probably installed yet. + * + * Case 2: aux port enabled (bit 5:0), aux int. disabled (bit 2:0) Three + * possibile situations here: + * + * Case 2a: The aux port does not exist, therefore, is not explicitly + * disabled. Case 2b: The aux port exists. A device and a driver may + * exist, using the device in the polling(remote) mode. Case 2c: The + * aux port exists. A device may exist, but someone who knows nothing + * about the aux port has set the command byte this way (this is the + * case with `syscons'). + * + * Case 3: aux port disabled (bit 5:1), aux int. enabled (bit 2:1) The + * aux port exists, but someone is controlloing the device and + * temporalily disabled the port. + * + * Case 4: aux port enabled (bit 5:0), aux int. enabled (bit 2:1) The aux + * port exists, a device is attached to the port, and someone is + * controlling the device. Some BIOS set the bits this way after boot. + * + * All in all, it is no use examing the bits for detecting the presence + * of the port and the mouse device. + */ + + /* save the current command byte; it will be used later */ + write_controller_command(ioport, KBDC_GET_COMMAND_BYTE); + sc->command_byte = read_controller_data(ioport); + if (verbose) { + printf("psm%d: current command byte:%04x\n", + unit, sc->command_byte); + } + if (sc->command_byte == -1) { + printf("psm%d: unable to get the current command byte value.\n", + unit); + return (0); + } + + /* + * disable the keyboard port while probing the aux port, which must be + * enabled during this routine + */ + write_controller_command(ioport, KBDC_DISABLE_KBD_PORT); + set_controller_command_byte(ioport, + sc->command_byte + & ~(KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS), + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + + /* + * NOTE: `test_aux_port()' is designed to return with zero if the aux + * port exists and is functioning. However, some controllers appears + * to respond with zero even when the aux port doesn't exist. (It may + * be that this is only the case when the controller DOES have the aux + * port but the port is not wired on the motherboard.) The keyboard + * controllers without the port, such as the original AT, are + * supporsed to return with an error code or simply time out. In any + * case, we have to continue probing the port even when the controller + * passes this test. + */ + switch ((i = test_aux_port(ioport))) { + case 0: /* no error */ + break; + case -1: /* time out */ + default: /* error */ + recover_from_error(ioport); + restore_controller(ioport, sc->command_byte); + if (verbose) + printf("psm%d: the aux port is not functioning (%d).\n", + unit, i); + if (bootverbose) + --verbose; + return (0); + } + + /* + * NOTE: some controllers appears to hang the `keyboard' when the aux + * port doesn't exist and `PSMC_RESET_DEV' is issued. + */ + if (!reset_aux_dev(ioport)) { + recover_from_error(ioport); + restore_controller(ioport, sc->command_byte); + if (verbose) + printf("psm%d: failed to reset the aux device.\n", unit); + return (0); + } + /* + * both the aux port and the aux device is functioning, see if the + * device can be enabled. NOTE: when enabled, the device will start + * sending data; we shall immediately disable the device once we know + * the device can be enabled. + */ + if (!enable_aux_dev(ioport) || !disable_aux_dev(ioport)) { + restore_controller(ioport, sc->command_byte); + if (verbose) + printf("psm%d: failed to enable the aux device.\n", unit); + if (bootverbose) + --verbose; + return (0); + } + empty_both_buffers(ioport); /* remove stray data if any */ + + /* hardware information */ + sc->hw.iftype = MOUSE_IF_PS2; + + /* verify the device is a mouse */ + sc->hw.hwid = get_aux_id(ioport); + if (!is_a_mouse(sc->hw.hwid)) { + restore_controller(ioport, sc->command_byte); + if (verbose) + printf("psm%d: unknown device type (%d).\n", unit, sc->hw.hwid); + if (bootverbose) + --verbose; + return (0); + } + switch (sc->hw.hwid) { + case PSM_BALLPOINT_ID: + sc->hw.type = MOUSE_TRACKBALL; + break; + case PSM_MOUSE_ID: + sc->hw.type = MOUSE_MOUSE; + break; + default: + sc->hw.type = MOUSE_UNKNOWN; + break; + } + + /* # of buttons */ + sc->hw.buttons = get_mouse_buttons(ioport); + + /* set mouse parameters */ + + /* FIXME:XXX I don't know if these parameters are reasonable */ + /* FIXME:XXX should we set them in `psmattach()' rather than here? */ + sc->mode.rate = set_mouse_sampling_rate(ioport, PSMD_DEFAULT_RATE); + sc->mode.resolution = + set_mouse_resolution(ioport, PSMD_DEFAULT_RESOLUTION); + set_mouse_scaling(ioport); /* 1:1 scaling */ + set_mouse_mode(ioport); /* stream mode */ + + /* just check the status of the mouse */ + if (verbose) { + get_mouse_status(ioport, stat); + log(LOG_DEBUG, "psm%d: status %02x %02x %02x\n", + unit, stat[0], stat[1], stat[2]); + } + + /* disable the aux port for now... */ + + /* + * WARNING: we save the controller command byte and use it later + * during `psmopen()' and `psmclose()'. This will be OK, so long as + * the keyboard/console device driver won't change the command byte in + * the course of its operation (this is the case with `syscons'). If + * not,... + */ + sc->command_byte &= ~KBD_AUX_CONTROL_BITS; + set_controller_command_byte(ioport, sc->command_byte, + KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + + /* done */ + return (IO_PSMSIZE); } static int psmattach(struct isa_device *dvp) { - int unit = dvp->id_unit; - struct psm_softc *sc = &psm_softc[unit]; - - /* initial operation mode */ - sc->mode.accelfactor = PSM_ACCEL; - sc->mode.protocol = MOUSE_PROTO_PS2; - sc->mkpacket = mkps2; - - /* Setup initial state */ - sc->state = PSM_VALID; - - /* Done */ -#ifdef DEVFS - sc->devfs_token = - devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit,TRUE), - DV_CHR, 0, 0, 0666, "psm%d", unit); - sc->n_devfs_token = - devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit,FALSE), - DV_CHR,0, 0, 0666, "npsm%d", unit); + int unit = dvp->id_unit; + struct psm_softc *sc = &psm_softc[unit]; + + /* initial operation mode */ + sc->mode.accelfactor = PSM_ACCEL; + sc->mode.protocol = MOUSE_PROTO_PS2; + sc->mkpacket = mkps2; + + /* Setup initial state */ + sc->state = PSM_VALID; + + /* Done */ +#ifdef DEVFS + sc->devfs_token = + devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit, TRUE), + DV_CHR, 0, 0, 0666, "psm%d", unit); + sc->n_devfs_token = + devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit, FALSE), + DV_CHR, 0, 0, 0666, "npsm%d", unit); #endif - printf("psm%d: device ID %d, %d buttons?\n", - unit,sc->hw.hwid,sc->hw.buttons); + printf("psm%d: device ID %d, %d buttons?\n", + unit, sc->hw.hwid, sc->hw.buttons); - if (bootverbose) - --verbose; + if (bootverbose) + --verbose; - return (1); - /* return (0); XXX eh? usually 1 indicates success */ + return (1); } static int psmopen(dev_t dev, int flag, int fmt, struct proc *p) { - int unit = PSM_UNIT(dev); - int ioport; - struct psm_softc *sc; - int stat[3]; - - /* Validate unit number */ - if (unit >= NPSM) - return (ENXIO); - - /* Get device data */ - sc = &psm_softc[unit]; - if ((sc->state & PSM_VALID) == 0) - return (ENXIO); - ioport = sc->addr; - - /* Disallow multiple opens */ - if (sc->state & PSM_OPEN) - return (EBUSY); - - /* Initialize state */ - sc->state |= PSM_OPEN; - sc->rsel.si_flags = 0; - sc->rsel.si_pid = 0; - - /* flush the event queue */ - sc->queue.count = 0; - sc->queue.head = 0; - sc->queue.tail = 0; - sc->button = 0; - - /* empty input/output buffers */ - sc->inputbytes = 0; - sc->outputbytes = 0; - sc->outputhead = 0; - - /* enable the aux port and temporalily disable the keyboard */ - write_controller_command(ioport,KBDC_DISABLE_KBD_PORT); - set_controller_command_byte(ioport, - sc->command_byte & ~KBD_KBD_CONTROL_BITS, - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - - /* enable the mouse device */ - if (!enable_aux_dev(ioport)) { - set_controller_command_byte(ioport,sc->command_byte, - KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - log(LOG_ERR, "psm%d: unable to enable the pointing device.\n",unit); - return (EIO); - } - - if (verbose >= 2) { - get_mouse_status(ioport,stat); - log(LOG_DEBUG,"psm%d: status %02x %02x %02x\n", - unit,stat[0],stat[1],stat[2]); - } - - /* enable the aux port and interrupt */ - set_controller_command_byte(ioport,sc->command_byte, - KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT); - - /* done */ - return (0); + int unit = PSM_UNIT(dev); + int ioport; + struct psm_softc *sc; + int stat[3]; + + /* Validate unit number */ + if (unit >= NPSM) + return (ENXIO); + + /* Get device data */ + sc = &psm_softc[unit]; + if ((sc->state & PSM_VALID) == 0) + return (ENXIO); + ioport = sc->addr; + + /* Disallow multiple opens */ + if (sc->state & PSM_OPEN) + return (EBUSY); + + /* Initialize state */ + sc->state |= PSM_OPEN; + sc->rsel.si_flags = 0; + sc->rsel.si_pid = 0; + + /* flush the event queue */ + sc->queue.count = 0; + sc->queue.head = 0; + sc->queue.tail = 0; + sc->button = 0; + + /* empty input/output buffers */ + sc->inputbytes = 0; + sc->outputbytes = 0; + sc->outputhead = 0; + + /* enable the aux port and temporalily disable the keyboard */ + write_controller_command(ioport, KBDC_DISABLE_KBD_PORT); + set_controller_command_byte(ioport, + sc->command_byte & ~KBD_KBD_CONTROL_BITS, + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + + /* enable the mouse device */ + if (!enable_aux_dev(ioport)) { + set_controller_command_byte(ioport, sc->command_byte, + KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + log(LOG_ERR, "psm%d: unable to enable the pointing device.\n", unit); + return (EIO); + } + if (verbose >= 2) { + get_mouse_status(ioport, stat); + log(LOG_DEBUG, "psm%d: status %02x %02x %02x\n", + unit, stat[0], stat[1], stat[2]); + } + /* enable the aux port and interrupt */ + set_controller_command_byte(ioport, sc->command_byte, + KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT); + + /* done */ + return (0); } static int psmclose(dev_t dev, int flag, int fmt, struct proc *p) { - struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; - int ioport = sc->addr; + struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; + int ioport = sc->addr; - /* disable the aux interrupt */ - set_controller_command_byte(ioport,sc->command_byte, - KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + /* disable the aux interrupt */ + set_controller_command_byte(ioport, sc->command_byte, + KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - /* remove anything left in the output buffer */ - empty_aux_buffer(ioport); + /* remove anything left in the output buffer */ + empty_aux_buffer(ioport); - /* disable the aux device, port and interrupt */ - disable_aux_dev(ioport); - set_controller_command_byte(ioport,sc->command_byte, - KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + /* disable the aux device, port and interrupt */ + disable_aux_dev(ioport); + set_controller_command_byte(ioport, sc->command_byte, + KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - /* remove anything left in the output buffer */ - empty_aux_buffer(ioport); + /* remove anything left in the output buffer */ + empty_aux_buffer(ioport); - /* Complete the close */ - sc->state &= ~PSM_OPEN; + /* Complete the close */ + sc->state &= ~PSM_OPEN; - /* close is almost always successful */ - return (0); + /* close is almost always successful */ + return (0); } static int mkms(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) { - static int butmap[] = { - 0, MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON2DOWN, - MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON2DOWN, - MOUSE_MSS_BUTTON1DOWN, - MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON1DOWN, - MOUSE_MSS_BUTTON2DOWN | MOUSE_MSS_BUTTON1DOWN, - MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON2DOWN | MOUSE_MSS_BUTTON1DOWN, - }; - unsigned char delta; - - if (maxlen - *len < MOUSE_MSS_PACKETSIZE) - return FALSE; - - buf[0] = MOUSE_MSS_SYNC; - buf[0] |= butmap[status->button & BUTSTATMASK]; - - if (status->dx < -128) - delta = 0x80; /* -128 */ - else if (status->dx > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char)status->dx; - buf[0] |= (delta & 0xc0) >> 6; /* bit 6-7 */ - buf[1] = delta & 0x3f; /* bit 0-5 */ - - if (status->dy < -128) - delta = 0x80; /* -128 */ - else if (status->dy > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char)status->dy; - buf[0] |= (delta & 0xc0) >> 4; /* bit 6-7 */ - buf[2] = delta & 0x3f; /* bit 0-5 */ - - *len += MOUSE_MSS_PACKETSIZE; - - return TRUE; + static int butmap[] = { + 0, + MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON2DOWN, + MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON2DOWN, + MOUSE_MSS_BUTTON1DOWN, + MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON1DOWN, + MOUSE_MSS_BUTTON2DOWN | MOUSE_MSS_BUTTON1DOWN, + MOUSE_MSS_BUTTON3DOWN | MOUSE_MSS_BUTTON2DOWN | MOUSE_MSS_BUTTON1DOWN, + }; + unsigned char delta; + + if (maxlen - *len < MOUSE_MSS_PACKETSIZE) + return FALSE; + + buf[0] = MOUSE_MSS_SYNC; + buf[0] |= butmap[status->button & BUTSTATMASK]; + + if (status->dx < -128) + delta = 0x80; /* -128 */ + else + if (status->dx > 127) + delta = 0x7f; /* 127 */ + else + delta = (unsigned char) status->dx; + buf[0] |= (delta & 0xc0) >> 6; /* bit 6-7 */ + buf[1] = delta & 0x3f; /* bit 0-5 */ + + if (status->dy < -128) + delta = 0x80; /* -128 */ + else + if (status->dy > 127) + delta = 0x7f; /* 127 */ + else + delta = (unsigned char) status->dy; + buf[0] |= (delta & 0xc0) >> 4; /* bit 6-7 */ + buf[2] = delta & 0x3f; /* bit 0-5 */ + + *len += MOUSE_MSS_PACKETSIZE; + + return TRUE; } static int mkmsc(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) { - static int butmap[] = { - 0, MOUSE_MSC_BUTTON3UP, MOUSE_MSC_BUTTON2UP, - MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON2UP, - MOUSE_MSC_BUTTON1UP, - MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON1UP, - MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON1UP, - MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON1UP, - }; - unsigned char delta; - - if (maxlen - *len < MOUSE_PS2_PACKETSIZE) - return FALSE; - - buf[0] = MOUSE_MSC_SYNC; - buf[0] |= ~butmap[status->button & BUTSTATMASK] & MOUSE_MSC_BUTTONS; - - if (status->dx < -128) - delta = 0x80; /* -128 */ - else if (status->dx > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char)status->dx; - buf[1] = delta >> 2; - buf[3] = delta - buf[1]; - - if (status->dy < -128) - delta = 0x80; /* -128 */ - else if (status->dy > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char)status->dy; - buf[2] = delta >> 2; - buf[4] = delta - buf[2]; - - *len += MOUSE_MSC_PACKETSIZE; - - return TRUE; + static int butmap[] = { + 0, + MOUSE_MSC_BUTTON3UP, MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON1UP, + MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON1UP, + MOUSE_MSC_BUTTON3UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON1UP, + }; + unsigned char delta; + + if (maxlen - *len < MOUSE_PS2_PACKETSIZE) + return FALSE; + + buf[0] = MOUSE_MSC_SYNC; + buf[0] |= ~butmap[status->button & BUTSTATMASK] & MOUSE_MSC_BUTTONS; + + if (status->dx < -128) + delta = 0x80; /* -128 */ + else + if (status->dx > 127) + delta = 0x7f; /* 127 */ + else + delta = (unsigned char) status->dx; + buf[1] = delta >> 2; + buf[3] = delta - buf[1]; + + if (status->dy < -128) + delta = 0x80; /* -128 */ + else + if (status->dy > 127) + delta = 0x7f; /* 127 */ + else + delta = (unsigned char) status->dy; + buf[2] = delta >> 2; + buf[4] = delta - buf[2]; + + *len += MOUSE_MSC_PACKETSIZE; + + return TRUE; } static int -mkps2(unsigned char *buf, int *len, int maxlen,r egister mousestatus_t *status) +mkps2(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) { - static int butmap[] = { - 0, MOUSE_PS2_BUTTON3DOWN, MOUSE_PS2_BUTTON2DOWN, - MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON2DOWN, - MOUSE_PS2_BUTTON1DOWN, - MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON1DOWN, - MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON1DOWN, - MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON1DOWN, - }; - register int delta; - - if (maxlen - *len < MOUSE_PS2_PACKETSIZE) - return FALSE; - - buf[0] = MOUSE_PS2_SYNC; - buf[0] |= butmap[status->button & BUTSTATMASK]; - - if (status->dx < -128) - delta = -128; - else if (status->dx > 127) - delta = 127; - else - delta = status->dx; - if (delta < 0) - buf[0] |= MOUSE_PS2_XNEG; - buf[1] = delta; - - if (status->dy < -128) - delta = -128; - else if (status->dy > 127) - delta = 127; - else - delta = status->dy; - if (delta < 0) - buf[0] |= MOUSE_PS2_YNEG; - buf[2] = delta; - - *len += MOUSE_PS2_PACKETSIZE; - - return TRUE; + static int butmap[] = { + 0, + MOUSE_PS2_BUTTON3DOWN, MOUSE_PS2_BUTTON2DOWN, + MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON2DOWN, + MOUSE_PS2_BUTTON1DOWN, + MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON1DOWN, + MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON1DOWN, + MOUSE_PS2_BUTTON3DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON1DOWN, + }; + register int delta; + + if (maxlen - *len < MOUSE_PS2_PACKETSIZE) + return FALSE; + + buf[0] = MOUSE_PS2_SYNC; + buf[0] |= butmap[status->button & BUTSTATMASK]; + + if (status->dx < -128) + delta = -128; + else + if (status->dx > 127) + delta = 127; + else + delta = status->dx; + if (delta < 0) + buf[0] |= MOUSE_PS2_XNEG; + buf[1] = delta; + + if (status->dy < -128) + delta = -128; + else + if (status->dy > 127) + delta = 127; + else + delta = status->dy; + if (delta < 0) + buf[0] |= MOUSE_PS2_YNEG; + buf[2] = delta; + + *len += MOUSE_PS2_PACKETSIZE; + + return TRUE; } static int psmread(dev_t dev, struct uio *uio, int flag) { - register struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; - unsigned int length; - int error; - int s; - int i; - - /* block until mouse activity occured */ - s = spltty(); - if ((sc->outputbytes <= 0) && (sc->queue.count <= 0)) { - while (sc->queue.count <= 0) { - if (PSM_NBLOCKIO(dev)) { - splx(s); - return (EWOULDBLOCK); - } - sc->state |= PSM_ASLP; - error = tsleep((caddr_t)sc, PZERO | PCATCH, - "psmread", 0); - if (error) { - splx(s); - return (error); - } - } - } - - if (sc->outputbytes >= uio->uio_resid) { - /* nothing to be done */ - } else { - if (sc->outputbytes > 0) { - bcopy(&sc->opacket[sc->outputhead],sc->opacket, - sc->outputbytes); - } - sc->outputhead = 0; - for(i = sc->queue.head; sc->queue.count > 0; - i = (i + 1) % PSM_BUFSIZE, --sc->queue.count) { - if (!(*sc->mkpacket)(&sc->opacket[sc->outputbytes], - &sc->outputbytes,PSM_BUFSIZE,&sc->queue.buf[i])) - break; - } - sc->queue.head = i; - } - - /* allow interrupts again */ - splx(s); - - /* copy data to user process */ - length = min(sc->outputbytes,uio->uio_resid); - error = uiomove(&sc->opacket[sc->outputhead], length, uio); - if (error) - return (error); - sc->outputhead += length; - sc->outputbytes -= length; - - return (error); + register struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; + unsigned int length; + int error; + int s; + int i; + + /* block until mouse activity occured */ + s = spltty(); + if ((sc->outputbytes <= 0) && (sc->queue.count <= 0)) { + while (sc->queue.count <= 0) { + if (PSM_NBLOCKIO(dev)) { + splx(s); + return (EWOULDBLOCK); + } + sc->state |= PSM_ASLP; + error = tsleep((caddr_t) sc, PZERO | PCATCH, + "psmread", 0); + if (error) { + splx(s); + return (error); + } + } + } + if (sc->outputbytes >= uio->uio_resid) { + /* nothing to be done */ + } else { + if (sc->outputbytes > 0) { + bcopy(&sc->opacket[sc->outputhead], sc->opacket, + sc->outputbytes); + } + sc->outputhead = 0; + for (i = sc->queue.head; sc->queue.count > 0; + i = (i + 1) % PSM_BUFSIZE, --sc->queue.count) { + if (!(*sc->mkpacket) (&sc->opacket[sc->outputbytes], + &sc->outputbytes, PSM_BUFSIZE, &sc->queue.buf[i])) + break; + } + sc->queue.head = i; + } + + /* allow interrupts again */ + splx(s); + + /* copy data to user process */ + length = min(sc->outputbytes, uio->uio_resid); + error = uiomove(&sc->opacket[sc->outputhead], length, uio); + if (error) + return (error); + sc->outputhead += length; + sc->outputbytes -= length; + + return (error); } static int psmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p) { - struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; - mouseinfo_t info; - mousestatus_t *ms; - packetfunc_t func; - int error = 0; - int s; - - /* Perform IOCTL command */ - switch (cmd) { - - case MOUSE_GETINFO: - *(mousehw_t *)addr = sc->hw; - break; - - case MOUSE_GETMODE: - *(mousemode_t *)addr = sc->mode; - break; - - case MOUSE_SETMODE: - if (((mousemode_t *)addr)->rate < 0) { - error = EINVAL; - break; - } - if (((mousemode_t *)addr)->resolution < 0) { - error = EINVAL; - break; - } + struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; + mouseinfo_t info; + mousestatus_t *ms; + packetfunc_t func; + int error = 0; + int s; + + /* Perform IOCTL command */ + switch (cmd) { + + case MOUSE_GETINFO: + *(mousehw_t *) addr = sc->hw; + break; + + case MOUSE_GETMODE: + *(mousemode_t *) addr = sc->mode; + break; + + case MOUSE_SETMODE: + if (((mousemode_t *) addr)->rate < 0) { + error = EINVAL; + break; + } + if (((mousemode_t *) addr)->resolution < 0) { + error = EINVAL; + break; + } #ifndef PSM_NOEMULATION - switch (((mousemode_t *)addr)->protocol) { - case MOUSE_PROTO_MS: - func = mkms; - break; - case MOUSE_PROTO_MSC: - func = mkmsc; - break; - case MOUSE_PROTO_PS2: - func = mkps2; - break; - default: - error = EINVAL; - func = (packetfunc_t)NULL; - break; - } - if (error) - break; -#endif /* PSM_NOEMULATION */ - if (((mousemode_t *)addr)->accelfactor < 0) { - error = EINVAL; - break; - } - - s = spltty(); /* disable interrupt while updating */ - sc->mode.rate = (((mousemode_t *)addr)->rate == 0) ? - PSMD_DEFAULT_RATE : - min(((mousemode_t *)addr)->rate,PSMD_MAX_RATE); - sc->mode.resolution = (((mousemode_t *)addr)->resolution == 0) ? - PSMD_DEFAULT_RESOLUTION : - ((mousemode_t *)addr)->resolution; - - /* temporalily disable the keyboard */ - write_controller_command(sc->addr,KBDC_DISABLE_KBD_PORT); - set_controller_command_byte(sc->addr, - sc->command_byte & ~KBD_KBD_CONTROL_BITS, - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); - - /* program the mouse */ - sc->mode.rate = set_mouse_sampling_rate(sc->addr,sc->mode.rate); - sc->mode.resolution = - set_mouse_resolution(sc->addr,sc->mode.resolution); - - /* enable the aux port and interrupt */ - set_controller_command_byte(sc->addr,sc->command_byte, - KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT); + switch (((mousemode_t *) addr)->protocol) { + case MOUSE_PROTO_MS: + func = mkms; + break; + case MOUSE_PROTO_MSC: + func = mkmsc; + break; + case MOUSE_PROTO_PS2: + func = mkps2; + break; + default: + error = EINVAL; + func = (packetfunc_t) NULL; + break; + } + if (error) + break; +#endif /* PSM_NOEMULATION */ + if (((mousemode_t *) addr)->accelfactor < 0) { + error = EINVAL; + break; + } + s = spltty(); /* disable interrupt while updating */ + sc->mode.rate = (((mousemode_t *) addr)->rate == 0) ? + PSMD_DEFAULT_RATE : + min(((mousemode_t *) addr)->rate, PSMD_MAX_RATE); + sc->mode.resolution = (((mousemode_t *) addr)->resolution == 0) ? + PSMD_DEFAULT_RESOLUTION : + ((mousemode_t *) addr)->resolution; + + /* temporalily disable the keyboard */ + write_controller_command(sc->addr, KBDC_DISABLE_KBD_PORT); + set_controller_command_byte(sc->addr, + sc->command_byte & ~KBD_KBD_CONTROL_BITS, + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT); + + /* program the mouse */ + sc->mode.rate = set_mouse_sampling_rate(sc->addr, sc->mode.rate); + sc->mode.resolution = + set_mouse_resolution(sc->addr, sc->mode.resolution); + + /* enable the aux port and interrupt */ + set_controller_command_byte(sc->addr, sc->command_byte, + KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT); #ifndef PSM_NOEMULATION - sc->mode.protocol = ((mousemode_t *)addr)->protocol; - sc->mkpacket = func; - sc->outputbytes = 0; - sc->outputhead = 0; -#endif /* PSM_NOEMULATION */ - sc->mode.accelfactor = ((mousemode_t *)addr)->accelfactor; - - splx(s); - break; - - case MOUSEIOCREAD: /* FIXME: this should go... */ - error = EINVAL; - break; - - case MOUSE_GETSTATE: - info.status = 0; - info.xmotion = 0; - info.ymotion = 0; - - s = spltty(); - if (sc->queue.count > 0) { - ms = &sc->queue.buf[sc->queue.head]; - - /* button status */ - info.status = ms->button; /* BUT?STAT bits */ - info.status |= /* BUT?CHNG bits */ - ((ms->button ^ ms->obutton) << 3); - /* mouse motion */ - info.xmotion = ms->dx; - info.ymotion = ms->dy; - if ((info.xmotion != 0) || (info.ymotion != 0)) - info.status |= MOVEMENT; - - sc->queue.head = (sc->queue.head + 1) % PSM_BUFSIZE; - --sc->queue.count; - } - splx(s); - - *(mouseinfo_t *)addr = info; - break; - - default: - error = EINVAL; - break; - } - - /* Return error code */ - return (error); + sc->mode.protocol = ((mousemode_t *) addr)->protocol; + sc->mkpacket = func; + sc->outputbytes = 0; + sc->outputhead = 0; +#endif /* PSM_NOEMULATION */ + sc->mode.accelfactor = ((mousemode_t *) addr)->accelfactor; + + splx(s); + break; + + case MOUSEIOCREAD: /* FIXME:XXX this should go... */ + error = EINVAL; + break; + + case MOUSE_GETSTATE: + info.status = 0; + info.xmotion = 0; + info.ymotion = 0; + + s = spltty(); + if (sc->queue.count > 0) { + ms = &sc->queue.buf[sc->queue.head]; + + /* button status */ + info.status = ms->button; /* BUT?STAT bits */ + info.status |= /* BUT?CHNG bits */ + ((ms->button ^ ms->obutton) << 3); + /* mouse motion */ + info.xmotion = ms->dx; + info.ymotion = ms->dy; + if ((info.xmotion != 0) || (info.ymotion != 0)) + info.status |= MOVEMENT; + + sc->queue.head = (sc->queue.head + 1) % PSM_BUFSIZE; + --sc->queue.count; + } + splx(s); + + *(mouseinfo_t *) addr = info; + break; + + default: + error = EINVAL; + break; + } + + /* Return error code */ + return (error); } void psmintr(int unit) { - /* the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN) - into `mouseinfo' button bits (BUT?STAT). */ - static butmap[8] = { - 0, BUT1STAT, BUT3STAT, BUT1STAT | BUT3STAT, - BUT2STAT, BUT1STAT | BUT2STAT, BUT2STAT | BUT3STAT, - BUT1STAT | BUT2STAT | BUT3STAT - }; - register struct psm_softc *sc = &psm_softc[unit]; - int ioport = sc->addr; - mousestatus_t *ms; - unsigned char c; - int x, y; - - /* is this really for us? */ - if ((inb(ioport + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) - != KBDS_AUX_BUFFER_FULL) - return; - - /* read a byte */ - c = inb(ioport + KBD_DATA_PORT); - - /* discard the byte if the device is not open */ - if ((sc->state & PSM_OPEN) == 0) - return; - - /* interpret data bytes - FIXME: there seems no way to reliably re-synchronize with - the PS/2 mouse once we are out of sync. Sure, there is - sync bits in the first data byte, but the second and the - third bytes may have these bits on (they are not functioning - as sync bits then!). There need to be two consequtive - bytes with these bits off to re-sync. (This can be done - if the user clicks buttons without moving the mouse?) - */ - if (sc->inputbytes == 0) { + /* + * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN) + * into `mouseinfo' button bits (BUT?STAT). + */ + static butmap[8] = { + 0, BUT1STAT, BUT3STAT, BUT1STAT | BUT3STAT, + BUT2STAT, BUT1STAT | BUT2STAT, BUT2STAT | BUT3STAT, + BUT1STAT | BUT2STAT | BUT3STAT + }; + register struct psm_softc *sc = &psm_softc[unit]; + int ioport = sc->addr; + mousestatus_t *ms; + unsigned char c; + int x, y; + + /* is this really for us? */ + if ((inb(ioport + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) + != KBDS_AUX_BUFFER_FULL) + return; + + /* read a byte */ + c = inb(ioport + KBD_DATA_PORT); + + /* discard the byte if the device is not open */ + if ((sc->state & PSM_OPEN) == 0) + return; + + /* + * interpret data bytes FIXME: there seems no way to reliably + * re-synchronize with the PS/2 mouse once we are out of sync. Sure, + * there is sync bits in the first data byte, but the second and the + * third bytes may have these bits on (they are not functioning as + * sync bits then!). There need to be two consequtive bytes with these + * bits off to re-sync. (This can be done if the user clicks buttons + * without moving the mouse?) + */ + if (sc->inputbytes == 0) { #ifndef PSM_NOCHECKSYNC - if ((c & MOUSE_PS2_SYNCMASK) == MOUSE_PS2_SYNC) -#endif /* PSM_NOCHECKSYNC */ - sc->ipacket[sc->inputbytes++] = c; - } else { - sc->ipacket[sc->inputbytes++] = c; - if (sc->inputbytes >= MOUSE_PS2_PACKETSIZE) { - if (sc->queue.count >= PSM_BUFSIZE) { - /* no room in the queue */ - sc->inputbytes = 0; - return; - } - if (sc->mode.accelfactor >= 1) { - x = (sc->ipacket[0] & MOUSE_PS2_XOVERFLOW) ? - 128 : sc->ipacket[1]; - if (x != 0) { - x = x*x/sc->mode.accelfactor; - if (x == 0) - x = 1; - if (sc->ipacket[0] & MOUSE_PS2_XNEG) - x = -x; - } - y = (sc->ipacket[0] & MOUSE_PS2_YOVERFLOW) ? - 128 : sc->ipacket[2]; - if (y != 0) { - y = y*y/sc->mode.accelfactor; - if (y == 0) - y = 1; - if (sc->ipacket[0] & MOUSE_PS2_YNEG) - y = -y; - } - } else { /* sc->mode.accelfactor <= 0 */ - x = (sc->ipacket[0] & MOUSE_PS2_XOVERFLOW) ? - ((sc->ipacket[0] & MOUSE_PS2_XNEG) ? - -128 : 127) : sc->ipacket[1]; - y = (sc->ipacket[0] & MOUSE_PS2_YOVERFLOW) ? - ((sc->ipacket[0] & MOUSE_PS2_YNEG) ? - -128 : 127) : sc->ipacket[2]; - } - - /* FIXME: we shouldn't store data if no movement - and no button status change is detected? */ - ms = &sc->queue.buf[sc->queue.tail]; - ms->dx = x; - ms->dy = y; - ms->obutton = sc->button; /* previous button state */ - sc->button = ms->button = /* latest button state */ - butmap[sc->ipacket[0] & MOUSE_PS2_BUTTONS]; - sc->queue.tail = - (sc->queue.tail + 1) % PSM_BUFSIZE; - ++sc->queue.count; - sc->inputbytes = 0; - } - } - - if (sc->state & PSM_ASLP) { - sc->state &= ~PSM_ASLP; - wakeup((caddr_t)sc); - } - selwakeup(&sc->rsel); + if ((c & MOUSE_PS2_SYNCMASK) == MOUSE_PS2_SYNC) +#endif /* PSM_NOCHECKSYNC */ + sc->ipacket[sc->inputbytes++] = c; + } else { + sc->ipacket[sc->inputbytes++] = c; + if (sc->inputbytes >= MOUSE_PS2_PACKETSIZE) { + if (sc->queue.count >= PSM_BUFSIZE) { + /* no room in the queue */ + sc->inputbytes = 0; + return; + } + if (sc->mode.accelfactor >= 1) { + x = (sc->ipacket[0] & MOUSE_PS2_XOVERFLOW) ? + 128 : sc->ipacket[1]; + if (x != 0) { + x = x * x / sc->mode.accelfactor; + if (x == 0) + x = 1; + if (sc->ipacket[0] & MOUSE_PS2_XNEG) + x = -x; + } + y = (sc->ipacket[0] & MOUSE_PS2_YOVERFLOW) ? + 128 : sc->ipacket[2]; + if (y != 0) { + y = y * y / sc->mode.accelfactor; + if (y == 0) + y = 1; + if (sc->ipacket[0] & MOUSE_PS2_YNEG) + y = -y; + } + } else {/* sc->mode.accelfactor <= 0 */ + x = (sc->ipacket[0] & MOUSE_PS2_XOVERFLOW) ? + ((sc->ipacket[0] & MOUSE_PS2_XNEG) ? + -128 : 127) : sc->ipacket[1]; + y = (sc->ipacket[0] & MOUSE_PS2_YOVERFLOW) ? + ((sc->ipacket[0] & MOUSE_PS2_YNEG) ? + -128 : 127) : sc->ipacket[2]; + } + + /* + * FIXME:XXX + * we shouldn't store data if no movement and + * no button status change is detected? + */ + ms = &sc->queue.buf[sc->queue.tail]; + ms->dx = x; + ms->dy = y; + ms->obutton = sc->button; /* previous button state */ + sc->button = ms->button = /* latest button state */ + butmap[sc->ipacket[0] & MOUSE_PS2_BUTTONS]; + sc->queue.tail = + (sc->queue.tail + 1) % PSM_BUFSIZE; + ++sc->queue.count; + sc->inputbytes = 0; + } + } + + if (sc->state & PSM_ASLP) { + sc->state &= ~PSM_ASLP; + wakeup((caddr_t) sc); + } + selwakeup(&sc->rsel); } static int psmselect(dev_t dev, int rw, struct proc *p) { - struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; - int s, ret; - - /* Silly to select for output */ - if (rw == FWRITE) - return (0); - - /* Return true if a mouse event available */ - s = spltty(); - if ((sc->outputbytes > 0) || (sc->queue.count > 0)) { - ret = 1; - } else { - selrecord(p, &sc->rsel); - ret = 0; - } - splx(s); - - return (ret); + struct psm_softc *sc = &psm_softc[PSM_UNIT(dev)]; + int s, ret; + + /* Silly to select for output */ + if (rw == FWRITE) + return (0); + + /* Return true if a mouse event available */ + s = spltty(); + if ((sc->outputbytes > 0) || (sc->queue.count > 0)) { + ret = 1; + } else { + selrecord(p, &sc->rsel); + ret = 0; + } + splx(s); + + return (ret); } static int psm_devsw_installed = FALSE; @@ -1171,15 +1196,15 @@ static int psm_devsw_installed = FALSE; static void psm_drvinit(void *unused) { - dev_t dev; + dev_t dev; - if (!psm_devsw_installed) { - dev = makedev(CDEV_MAJOR, 0); - cdevsw_add(&dev,&psm_cdevsw, NULL); - psm_devsw_installed = TRUE; - } + if (!psm_devsw_installed) { + dev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&dev, &psm_cdevsw, NULL); + psm_devsw_installed = TRUE; + } } -SYSINIT(psmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE + CDEV_MAJOR,psm_drvinit,NULL) +SYSINIT(psmdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, psm_drvinit, NULL) #endif /* NPSM > 0 */ |