mse.c revision 32726
1637Snate/* 2637Snate * Copyright 1992 by the University of Guelph 3637Snate * 4637Snate * Permission to use, copy and modify this 5637Snate * software and its documentation for any purpose and without 6637Snate * fee is hereby granted, provided that the above copyright 7637Snate * notice appear in all copies and that both that copyright 8637Snate * notice and this permission notice appear in supporting 9637Snate * documentation. 10637Snate * University of Guelph makes no representations about the suitability of 11637Snate * this software for any purpose. It is provided "as is" 12637Snate * without express or implied warranty. 131817Sdg * 1432726Seivind * $Id: mse.c,v 1.36 1997/12/07 08:09:16 yokota Exp $ 15637Snate */ 16637Snate/* 17637Snate * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 18637Snate * the X386 port, courtesy of 19637Snate * Rick Macklem, rick@snowhite.cis.uoguelph.ca 20637Snate * Caveats: The driver currently uses spltty(), but doesn't use any 21637Snate * generic tty code. It could use splmse() (that only masks off the 22637Snate * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 23637Snate * (This may be worth the effort, since the Logitech generates 30/60 24637Snate * interrupts/sec continuously while it is open.) 25637Snate * NB: The ATI has NOT been tested yet! 26637Snate */ 27637Snate 28637Snate/* 29637Snate * Modification history: 304259Sjkh * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 314259Sjkh * improved probe based on input from Logitech. 32637Snate * 33637Snate * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 34637Snate * fixes to make it work with Microsoft InPort busmouse 35637Snate * 36637Snate * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 37637Snate * added patches for new "select" interface 38637Snate * 39637Snate * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 40637Snate * changed position of some spl()'s in mseread 41637Snate * 42637Snate * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 43637Snate * limit maximum negative x/y value to -127 to work around XFree problem 44637Snate * that causes spurious button pushes. 45637Snate */ 46637Snate 47637Snate#include "mse.h" 48637Snate#if NMSE > 0 4932726Seivind#include "opt_devfs.h" 5032726Seivind 512056Swollman#include <sys/param.h> 523745Swollman#include <sys/systm.h> 5312658Sbde#include <sys/conf.h> 542056Swollman#include <sys/kernel.h> 5529368Speter#include <sys/poll.h> 5631254Sbde#include <sys/select.h> 572056Swollman#include <sys/uio.h> 5812675Sjulian#ifdef DEVFS 5912675Sjulian#include <sys/devfsext.h> 6012675Sjulian#endif /*DEVFS*/ 61637Snate 627430Sbde#include <machine/clock.h> 6331603Syokota#include <machine/mouse.h> 647430Sbde 652056Swollman#include <i386/isa/isa_device.h> 66637Snate 6731603Syokota/* driver configuration flags (config) */ 6831603Syokota#define MSE_CONFIG_ACCEL 0x00f0 /* acceleration factor */ 6931603Syokota#define MSE_CONFIG_FLAGS (MSE_CONFIG_ACCEL) 7031603Syokota 71798Swollmanstatic int mseprobe(struct isa_device *); 72798Swollmanstatic int mseattach(struct isa_device *); 73637Snate 74637Snatestruct isa_driver msedriver = { 75637Snate mseprobe, mseattach, "mse" 76637Snate}; 77637Snate 7812675Sjulianstatic d_open_t mseopen; 7912675Sjulianstatic d_close_t mseclose; 8012675Sjulianstatic d_read_t mseread; 8131603Syokotastatic d_ioctl_t mseioctl; 8229368Speterstatic d_poll_t msepoll; 8312675Sjulian 8412675Sjulian#define CDEV_MAJOR 27 8512678Sphkstatic struct cdevsw mse_cdevsw = 8612675Sjulian { mseopen, mseclose, mseread, nowrite, /*27*/ 8731603Syokota mseioctl, nostop, nullreset, nodevtotty,/* mse */ 8829368Speter msepoll, nommap, NULL, "mse", NULL, -1 }; 8912675Sjulian 9012675Sjulian 91637Snate/* 92637Snate * Software control structure for mouse. The sc_enablemouse(), 93637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 94637Snate */ 9512724Sphkstatic struct mse_softc { 96637Snate int sc_flags; 97637Snate int sc_mousetype; 981549Srgrimes struct selinfo sc_selp; 99637Snate u_int sc_port; 10012854Sbde void (*sc_enablemouse) __P((u_int port)); 10112854Sbde void (*sc_disablemouse) __P((u_int port)); 10212854Sbde void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 103637Snate int sc_deltax; 104637Snate int sc_deltay; 105637Snate int sc_obuttons; 106637Snate int sc_buttons; 107637Snate int sc_bytesread; 10831603Syokota u_char sc_bytes[MOUSE_SYS_PACKETSIZE]; 10931603Syokota mousehw_t hw; 11031603Syokota mousemode_t mode; 11131603Syokota mousestatus_t status; 11212675Sjulian#ifdef DEVFS 11312675Sjulian void *devfs_token; 11412675Sjulian void *n_devfs_token; 11512675Sjulian#endif 116637Snate} mse_sc[NMSE]; 117637Snate 118637Snate/* Flags */ 119637Snate#define MSESC_OPEN 0x1 120637Snate#define MSESC_WANT 0x2 121637Snate 122637Snate/* and Mouse Types */ 12320688Sjoerg#define MSE_NONE 0 /* don't move this! */ 124637Snate#define MSE_LOGITECH 0x1 125637Snate#define MSE_ATIINPORT 0x2 1264259Sjkh#define MSE_LOGI_SIG 0xA5 127637Snate 128637Snate#define MSE_PORTA 0 129637Snate#define MSE_PORTB 1 130637Snate#define MSE_PORTC 2 131637Snate#define MSE_PORTD 3 132637Snate 133637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 134637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 135637Snate 136637Snate/* 137637Snate * Logitech bus mouse definitions 138637Snate */ 139637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1404259Sjkh /* The definition for the control port */ 1414259Sjkh /* is as follows: */ 1428876Srgrimes 1434259Sjkh /* D7 = Mode set flag (1 = active) */ 1448876Srgrimes /* D6,D5 = Mode selection (port A) */ 1454259Sjkh /* 00 = Mode 0 = Basic I/O */ 1464259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1474259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1484259Sjkh /* D4 = Port A direction (1 = input)*/ 1494259Sjkh /* D3 = Port C (upper 4 bits) */ 1504259Sjkh /* direction. (1 = input) */ 1514259Sjkh /* D2 = Mode selection (port B & C) */ 1524259Sjkh /* 0 = Mode 0 = Basic I/O */ 1534259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1544259Sjkh /* D1 = Port B direction (1 = input)*/ 1554259Sjkh /* D0 = Port C (lower 4 bits) */ 1564259Sjkh /* direction. (1 = input) */ 1578876Srgrimes 1584259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1594259Sjkh /* Port A is an input port, B is an */ 1604259Sjkh /* output port, C is split with upper */ 1614259Sjkh /* 4 bits being an output port and lower*/ 1624259Sjkh /* 4 bits an input port, and enable the */ 1634259Sjkh /* sucker. */ 1644259Sjkh /* Courtesy Intel 8255 databook. Lars */ 165637Snate#define MSE_HOLD 0x80 166637Snate#define MSE_RXLOW 0x00 167637Snate#define MSE_RXHIGH 0x20 168637Snate#define MSE_RYLOW 0x40 169637Snate#define MSE_RYHIGH 0x60 170637Snate#define MSE_DISINTR 0x10 171637Snate#define MSE_INTREN 0x00 172637Snate 17312854Sbdestatic int mse_probelogi __P((struct isa_device *idp)); 17412854Sbdestatic void mse_disablelogi __P((u_int port)); 17512854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 17612854Sbdestatic void mse_enablelogi __P((u_int port)); 177637Snate 178637Snate/* 179637Snate * ATI Inport mouse definitions 180637Snate */ 181637Snate#define MSE_INPORT_RESET 0x80 182637Snate#define MSE_INPORT_STATUS 0x00 183637Snate#define MSE_INPORT_DX 0x01 184637Snate#define MSE_INPORT_DY 0x02 185637Snate#define MSE_INPORT_MODE 0x07 186637Snate#define MSE_INPORT_HOLD 0x20 187637Snate#define MSE_INPORT_INTREN 0x09 188637Snate 18912854Sbdestatic int mse_probeati __P((struct isa_device *idp)); 19012854Sbdestatic void mse_enableati __P((u_int port)); 19112854Sbdestatic void mse_disableati __P((u_int port)); 19212854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 193637Snate 194637Snate#define MSEPRI (PZERO + 3) 195637Snate 196637Snate/* 197637Snate * Table of mouse types. 198637Snate * Keep the Logitech last, since I haven't figured out how to probe it 199637Snate * properly yet. (Someday I'll have the documentation.) 200637Snate */ 20112724Sphkstatic struct mse_types { 202637Snate int m_type; /* Type of bus mouse */ 20312854Sbde int (*m_probe) __P((struct isa_device *idp)); 20412854Sbde /* Probe routine to test for it */ 20512854Sbde void (*m_enable) __P((u_int port)); 20612854Sbde /* Start routine */ 20712854Sbde void (*m_disable) __P((u_int port)); 20812854Sbde /* Disable interrupts routine */ 20912854Sbde void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 21012854Sbde /* and get mouse status */ 21131603Syokota mousehw_t m_hw; /* buttons iftype type model hwid */ 21231603Syokota mousemode_t m_mode; /* proto rate res accel level size mask */ 213637Snate} mse_types[] = { 21431603Syokota { MSE_ATIINPORT, 21531603Syokota mse_probeati, mse_enableati, mse_disableati, mse_getati, 21631603Syokota { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 21731603Syokota { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 21831603Syokota { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 21931603Syokota { MSE_LOGITECH, 22031603Syokota mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, 22131603Syokota { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 22231603Syokota { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 22331603Syokota { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 224637Snate { 0, }, 225637Snate}; 226637Snate 227798Swollmanint 228637Snatemseprobe(idp) 229637Snate register struct isa_device *idp; 230637Snate{ 231637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 232637Snate register int i; 233637Snate 234637Snate /* 235637Snate * Check for each mouse type in the table. 236637Snate */ 237637Snate i = 0; 238637Snate while (mse_types[i].m_type) { 239637Snate if ((*mse_types[i].m_probe)(idp)) { 240637Snate sc->sc_mousetype = mse_types[i].m_type; 241637Snate sc->sc_enablemouse = mse_types[i].m_enable; 242637Snate sc->sc_disablemouse = mse_types[i].m_disable; 243637Snate sc->sc_getmouse = mse_types[i].m_get; 24431603Syokota sc->hw = mse_types[i].m_hw; 24531603Syokota sc->mode = mse_types[i].m_mode; 246637Snate return (1); 247637Snate } 248637Snate i++; 249637Snate } 250637Snate return (0); 251637Snate} 252637Snate 253798Swollmanint 254637Snatemseattach(idp) 255637Snate struct isa_device *idp; 256637Snate{ 25712675Sjulian int unit = idp->id_unit; 25812675Sjulian struct mse_softc *sc = &mse_sc[unit]; 259637Snate 260637Snate sc->sc_port = idp->id_iobase; 26131603Syokota sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; 26212675Sjulian#ifdef DEVFS 26314873Sscrappy sc->devfs_token = 26414873Sscrappy devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 26514873Sscrappy 0600, "mse%d", unit); 26614873Sscrappy sc->n_devfs_token = 26714873Sscrappy devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 26814873Sscrappy 0600, "nmse%d", unit); 26912675Sjulian#endif 270637Snate return (1); 271637Snate} 272637Snate 273637Snate/* 274637Snate * Exclusive open the mouse, initialize it and enable interrupts. 275637Snate */ 27612675Sjulianstatic int 27710624Sbdemseopen(dev, flags, fmt, p) 278637Snate dev_t dev; 27910624Sbde int flags; 28010624Sbde int fmt; 28110624Sbde struct proc *p; 282637Snate{ 283637Snate register struct mse_softc *sc; 284637Snate int s; 285637Snate 286637Snate if (MSE_UNIT(dev) >= NMSE) 287637Snate return (ENXIO); 288637Snate sc = &mse_sc[MSE_UNIT(dev)]; 28920688Sjoerg if (sc->sc_mousetype == MSE_NONE) 29020688Sjoerg return (ENXIO); 291637Snate if (sc->sc_flags & MSESC_OPEN) 292637Snate return (EBUSY); 293637Snate sc->sc_flags |= MSESC_OPEN; 29431603Syokota sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS; 295637Snate sc->sc_deltax = sc->sc_deltay = 0; 29631603Syokota sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; 29731603Syokota sc->mode.level = 0; 29831603Syokota sc->status.flags = 0; 29931603Syokota sc->status.button = sc->status.obutton = 0; 30031603Syokota sc->status.dx = sc->status.dy = sc->status.dz = 0; 301637Snate 302637Snate /* 303637Snate * Initialize mouse interface and enable interrupts. 304637Snate */ 305637Snate s = spltty(); 306637Snate (*sc->sc_enablemouse)(sc->sc_port); 307637Snate splx(s); 308637Snate return (0); 309637Snate} 310637Snate 311637Snate/* 312637Snate * mseclose: just turn off mouse innterrupts. 313637Snate */ 31412675Sjulianstatic int 31510624Sbdemseclose(dev, flags, fmt, p) 316798Swollman dev_t dev; 31710624Sbde int flags; 31810624Sbde int fmt; 31910624Sbde struct proc *p; 320637Snate{ 321637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 322637Snate int s; 323637Snate 324637Snate s = spltty(); 325637Snate (*sc->sc_disablemouse)(sc->sc_port); 326637Snate sc->sc_flags &= ~MSESC_OPEN; 327637Snate splx(s); 328637Snate return(0); 329637Snate} 330637Snate 3318876Srgrimes/* 332637Snate * mseread: return mouse info using the MSC serial protocol, but without 333637Snate * using bytes 4 and 5. 334637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 335637Snate */ 33612675Sjulianstatic int 33710624Sbdemseread(dev, uio, ioflag) 338637Snate dev_t dev; 339637Snate struct uio *uio; 34010624Sbde int ioflag; 341637Snate{ 342637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 343637Snate int xfer, s, error; 344637Snate 345637Snate /* 346637Snate * If there are no protocol bytes to be read, set up a new protocol 347637Snate * packet. 348637Snate */ 349637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 35031603Syokota if (sc->sc_bytesread >= sc->mode.packetsize) { 351637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 352637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 353637Snate if (MSE_NBLOCKIO(dev)) { 354637Snate splx(s); 355637Snate return (0); 356637Snate } 357637Snate sc->sc_flags |= MSESC_WANT; 358637Snate if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 359637Snate "mseread", 0)) { 360637Snate splx(s); 361637Snate return (error); 362637Snate } 363637Snate } 364637Snate 365637Snate /* 366637Snate * Generate protocol bytes. 367637Snate * For some reason X386 expects 5 bytes but never uses 368637Snate * the fourth or fifth? 369637Snate */ 37031603Syokota sc->sc_bytes[0] = sc->mode.syncmask[1] 37131603Syokota | (sc->sc_buttons & ~sc->mode.syncmask[0]); 372637Snate if (sc->sc_deltax > 127) 373637Snate sc->sc_deltax = 127; 374637Snate if (sc->sc_deltax < -127) 375637Snate sc->sc_deltax = -127; 376637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 377637Snate if (sc->sc_deltay > 127) 378637Snate sc->sc_deltay = 127; 379637Snate if (sc->sc_deltay < -127) 380637Snate sc->sc_deltay = -127; 381637Snate sc->sc_bytes[1] = sc->sc_deltax; 382637Snate sc->sc_bytes[2] = sc->sc_deltay; 383637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 38431603Syokota sc->sc_bytes[5] = sc->sc_bytes[6] = 0; 38531603Syokota sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS; 386637Snate sc->sc_obuttons = sc->sc_buttons; 387637Snate sc->sc_deltax = sc->sc_deltay = 0; 388637Snate sc->sc_bytesread = 0; 389637Snate } 390637Snate splx(s); 39131603Syokota xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread); 392637Snate if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 393637Snate return (error); 394637Snate sc->sc_bytesread += xfer; 395637Snate return(0); 396637Snate} 397637Snate 398637Snate/* 39931603Syokota * mseioctl: process ioctl commands. 40031603Syokota */ 40131603Syokotastatic int 40231603Syokotamseioctl(dev, cmd, addr, flag, p) 40331603Syokota dev_t dev; 40431603Syokota int cmd; 40531603Syokota caddr_t addr; 40631603Syokota int flag; 40731603Syokota struct proc *p; 40831603Syokota{ 40931603Syokota register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 41031603Syokota mousestatus_t status; 41131603Syokota int err = 0; 41231603Syokota int s; 41331603Syokota 41431603Syokota switch (cmd) { 41531603Syokota 41631603Syokota case MOUSE_GETHWINFO: 41731603Syokota s = spltty(); 41831603Syokota *(mousehw_t *)addr = sc->hw; 41931603Syokota if (sc->mode.level == 0) 42031603Syokota ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; 42131603Syokota splx(s); 42231603Syokota break; 42331603Syokota 42431603Syokota case MOUSE_GETMODE: 42531603Syokota s = spltty(); 42631603Syokota *(mousemode_t *)addr = sc->mode; 42731603Syokota switch (sc->mode.level) { 42831603Syokota case 0: 42931603Syokota break; 43031603Syokota case 1: 43131603Syokota ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; 43231603Syokota ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; 43331603Syokota ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; 43431603Syokota break; 43531603Syokota } 43631603Syokota splx(s); 43731603Syokota break; 43831603Syokota 43931603Syokota case MOUSE_SETMODE: 44031603Syokota switch (((mousemode_t *)addr)->level) { 44131603Syokota case 0: 44231603Syokota case 1: 44331603Syokota break; 44431603Syokota default: 44531603Syokota return (EINVAL); 44631603Syokota } 44731603Syokota if (((mousemode_t *)addr)->accelfactor < -1) 44831603Syokota return (EINVAL); 44931603Syokota else if (((mousemode_t *)addr)->accelfactor >= 0) 45031603Syokota sc->mode.accelfactor = 45131603Syokota ((mousemode_t *)addr)->accelfactor; 45231603Syokota sc->mode.level = ((mousemode_t *)addr)->level; 45331603Syokota switch (sc->mode.level) { 45431603Syokota case 0: 45531603Syokota sc->sc_bytesread = sc->mode.packetsize 45631603Syokota = MOUSE_MSC_PACKETSIZE; 45731603Syokota break; 45831603Syokota case 1: 45931603Syokota sc->sc_bytesread = sc->mode.packetsize 46031603Syokota = MOUSE_SYS_PACKETSIZE; 46131603Syokota break; 46231603Syokota } 46331603Syokota break; 46431603Syokota 46531603Syokota case MOUSE_GETLEVEL: 46631603Syokota *(int *)addr = sc->mode.level; 46731603Syokota break; 46831603Syokota 46931603Syokota case MOUSE_SETLEVEL: 47031603Syokota switch (*(int *)addr) { 47131603Syokota case 0: 47231603Syokota sc->mode.level = *(int *)addr; 47331603Syokota sc->sc_bytesread = sc->mode.packetsize 47431603Syokota = MOUSE_MSC_PACKETSIZE; 47531603Syokota break; 47631603Syokota case 1: 47731603Syokota sc->mode.level = *(int *)addr; 47831603Syokota sc->sc_bytesread = sc->mode.packetsize 47931603Syokota = MOUSE_SYS_PACKETSIZE; 48031603Syokota break; 48131603Syokota default: 48231603Syokota return (EINVAL); 48331603Syokota } 48431603Syokota break; 48531603Syokota 48631603Syokota case MOUSE_GETSTATUS: 48731603Syokota s = spltty(); 48831603Syokota status = sc->status; 48931603Syokota sc->status.flags = 0; 49031603Syokota sc->status.obutton = sc->status.button; 49131603Syokota sc->status.button = 0; 49231603Syokota sc->status.dx = 0; 49331603Syokota sc->status.dy = 0; 49431603Syokota sc->status.dz = 0; 49531603Syokota splx(s); 49631603Syokota *(mousestatus_t *)addr = status; 49731603Syokota break; 49831603Syokota 49931603Syokota case MOUSE_READSTATE: 50031603Syokota case MOUSE_READDATA: 50131603Syokota return (ENODEV); 50231603Syokota 50331603Syokota#if (defined(MOUSE_GETVARS)) 50431603Syokota case MOUSE_GETVARS: 50531603Syokota case MOUSE_SETVARS: 50631603Syokota return (ENODEV); 50731603Syokota#endif 50831603Syokota 50931603Syokota default: 51031603Syokota return (ENOTTY); 51131603Syokota } 51231603Syokota return (err); 51331603Syokota} 51431603Syokota 51531603Syokota/* 51629368Speter * msepoll: check for mouse input to be processed. 517637Snate */ 51812675Sjulianstatic int 51929368Spetermsepoll(dev, events, p) 520637Snate dev_t dev; 52129368Speter int events; 522637Snate struct proc *p; 523637Snate{ 524637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 525637Snate int s; 52629368Speter int revents = 0; 527637Snate 528637Snate s = spltty(); 52929368Speter if (events & (POLLIN | POLLRDNORM)) 53031603Syokota if (sc->sc_bytesread != sc->mode.packetsize || 53131603Syokota sc->sc_deltax != 0 || sc->sc_deltay != 0 || 53229368Speter (sc->sc_obuttons ^ sc->sc_buttons) != 0) 53329368Speter revents |= events & (POLLIN | POLLRDNORM); 53429368Speter else { 53529368Speter /* 53629368Speter * Since this is an exclusive open device, any previous 53729368Speter * proc pointer is trash now, so we can just assign it. 53829368Speter */ 53929368Speter selrecord(p, &sc->sc_selp); 54029368Speter } 541637Snate 542637Snate splx(s); 54329368Speter return (revents); 544637Snate} 545637Snate 546637Snate/* 547637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 548637Snate */ 549798Swollmanvoid 550637Snatemseintr(unit) 551637Snate int unit; 552637Snate{ 55331603Syokota /* 55431603Syokota * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP) 55531603Syokota * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 55631603Syokota */ 55731603Syokota static int butmap[8] = { 55831603Syokota 0, 55931603Syokota MOUSE_BUTTON3DOWN, 56031603Syokota MOUSE_BUTTON2DOWN, 56131603Syokota MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 56231603Syokota MOUSE_BUTTON1DOWN, 56331603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 56431603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 56531603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 56631603Syokota }; 567637Snate register struct mse_softc *sc = &mse_sc[unit]; 56831603Syokota int dx, dy, but; 56931603Syokota int sign; 570637Snate 571637Snate#ifdef DEBUG 572637Snate static int mse_intrcnt = 0; 573637Snate if((mse_intrcnt++ % 10000) == 0) 574637Snate printf("mseintr\n"); 575637Snate#endif /* DEBUG */ 576637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 577637Snate return; 578637Snate 57931603Syokota (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but); 58031603Syokota if (sc->mode.accelfactor > 0) { 58131603Syokota sign = (dx < 0); 58231603Syokota dx = dx * dx / sc->mode.accelfactor; 58331603Syokota if (dx == 0) 58431603Syokota dx = 1; 58531603Syokota if (sign) 58631603Syokota dx = -dx; 58731603Syokota sign = (dy < 0); 58831603Syokota dy = dy * dy / sc->mode.accelfactor; 58931603Syokota if (dy == 0) 59031603Syokota dy = 1; 59131603Syokota if (sign) 59231603Syokota dy = -dy; 59331603Syokota } 59431603Syokota sc->sc_deltax += dx; 59531603Syokota sc->sc_deltay += dy; 59631603Syokota sc->sc_buttons = but; 597637Snate 59831603Syokota but = butmap[~but & MOUSE_MSC_BUTTONS]; 59931603Syokota sc->status.dx += dx; 60031603Syokota sc->status.dy += dy; 60131603Syokota sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0) 60231603Syokota | (sc->status.button ^ but); 60331603Syokota sc->status.button = but; 60431603Syokota 605637Snate /* 606637Snate * If mouse state has changed, wake up anyone wanting to know. 607637Snate */ 608637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 609637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 6108876Srgrimes if (sc->sc_flags & MSESC_WANT) { 6118876Srgrimes sc->sc_flags &= ~MSESC_WANT; 6128876Srgrimes wakeup((caddr_t)sc); 6138876Srgrimes } 6141549Srgrimes selwakeup(&sc->sc_selp); 615637Snate } 616637Snate} 617637Snate 618637Snate/* 619637Snate * Routines for the Logitech mouse. 620637Snate */ 621637Snate/* 622637Snate * Test for a Logitech bus mouse and return 1 if it is. 623637Snate * (until I know how to use the signature port properly, just disable 624637Snate * interrupts and return 1) 625637Snate */ 626637Snatestatic int 627637Snatemse_probelogi(idp) 628637Snate register struct isa_device *idp; 629637Snate{ 630637Snate 6314259Sjkh int sig; 6324259Sjkh 6334259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 6344259Sjkh /* set the signature port */ 6354259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 6364259Sjkh 6374259Sjkh DELAY(30000); /* 30 ms delay */ 6384259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 6394259Sjkh if (sig == MSE_LOGI_SIG) { 6404259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 6414259Sjkh return(1); 6424259Sjkh } else { 64316074Sjoerg if (bootverbose) 64416074Sjoerg printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 6454259Sjkh return(0); 646637Snate } 647637Snate} 648637Snate 649637Snate/* 650637Snate * Initialize Logitech mouse and enable interrupts. 651637Snate */ 652637Snatestatic void 653637Snatemse_enablelogi(port) 654637Snate register u_int port; 655637Snate{ 656637Snate int dx, dy, but; 657637Snate 658637Snate outb(port + MSE_PORTD, MSE_SETUP); 659637Snate mse_getlogi(port, &dx, &dy, &but); 660637Snate} 661637Snate 662637Snate/* 663637Snate * Disable interrupts for Logitech mouse. 664637Snate */ 665637Snatestatic void 666637Snatemse_disablelogi(port) 667637Snate register u_int port; 668637Snate{ 669637Snate 670637Snate outb(port + MSE_PORTC, MSE_DISINTR); 671637Snate} 672637Snate 673637Snate/* 674637Snate * Get the current dx, dy and button up/down state. 675637Snate */ 676637Snatestatic void 677637Snatemse_getlogi(port, dx, dy, but) 678637Snate register u_int port; 679637Snate int *dx; 680637Snate int *dy; 681637Snate int *but; 682637Snate{ 683637Snate register char x, y; 684637Snate 685637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 686637Snate x = inb(port + MSE_PORTA); 68731603Syokota *but = (x >> 5) & MOUSE_MSC_BUTTONS; 688637Snate x &= 0xf; 689637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 690637Snate x |= (inb(port + MSE_PORTA) << 4); 691637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 692637Snate y = (inb(port + MSE_PORTA) & 0xf); 693637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 694637Snate y |= (inb(port + MSE_PORTA) << 4); 69531603Syokota *dx = x; 69631603Syokota *dy = y; 697637Snate outb(port + MSE_PORTC, MSE_INTREN); 698637Snate} 699637Snate 700637Snate/* 701637Snate * Routines for the ATI Inport bus mouse. 702637Snate */ 703637Snate/* 704637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 705637Snate * (do not enable interrupts) 706637Snate */ 707637Snatestatic int 708637Snatemse_probeati(idp) 709637Snate register struct isa_device *idp; 710637Snate{ 711637Snate int i; 712637Snate 713637Snate for (i = 0; i < 2; i++) 714637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 715637Snate return (1); 716637Snate return (0); 717637Snate} 718637Snate 719637Snate/* 720637Snate * Initialize ATI Inport mouse and enable interrupts. 721637Snate */ 722637Snatestatic void 723637Snatemse_enableati(port) 724637Snate register u_int port; 725637Snate{ 726637Snate 727637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 728637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 729637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 730637Snate} 731637Snate 732637Snate/* 733637Snate * Disable interrupts for ATI Inport mouse. 734637Snate */ 735637Snatestatic void 736637Snatemse_disableati(port) 737637Snate register u_int port; 738637Snate{ 739637Snate 740637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 741637Snate outb(port + MSE_PORTB, 0); 742637Snate} 743637Snate 744637Snate/* 745637Snate * Get current dx, dy and up/down button state. 746637Snate */ 747637Snatestatic void 748637Snatemse_getati(port, dx, dy, but) 749637Snate register u_int port; 750637Snate int *dx; 751637Snate int *dy; 752637Snate int *but; 753637Snate{ 754637Snate register char byte; 755637Snate 756637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 757637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 758637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 75931603Syokota *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS; 760637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 761637Snate byte = inb(port + MSE_PORTB); 76231603Syokota *dx = byte; 763637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 764637Snate byte = inb(port + MSE_PORTB); 76531603Syokota *dy = byte; 766637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 767637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 768637Snate} 76912502Sjulian 77012502Sjulianstatic mse_devsw_installed = 0; 77112502Sjulian 77212517Sjulianstatic void mse_drvinit(void *unused) 77312502Sjulian{ 77412517Sjulian dev_t dev; 77512517Sjulian 77612502Sjulian if( ! mse_devsw_installed ) { 77712675Sjulian dev = makedev(CDEV_MAJOR, 0); 77812675Sjulian cdevsw_add(&dev,&mse_cdevsw, NULL); 77912502Sjulian mse_devsw_installed = 1; 78012517Sjulian } 78112502Sjulian} 78212517Sjulian 78312517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 78412517Sjulian 78512517Sjulian 786637Snate#endif /* NMSE */ 787