mse.c revision 46571
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 * 1446571Speter * $Id: mse.c,v 1.41 1999/05/06 18:12:28 peter 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 9040565Sbdestatic ointhand2_t mseintr; 9112675Sjulian 92637Snate/* 93637Snate * Software control structure for mouse. The sc_enablemouse(), 94637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 95637Snate */ 9612724Sphkstatic struct mse_softc { 97637Snate int sc_flags; 98637Snate int sc_mousetype; 991549Srgrimes struct selinfo sc_selp; 100637Snate u_int sc_port; 10112854Sbde void (*sc_enablemouse) __P((u_int port)); 10212854Sbde void (*sc_disablemouse) __P((u_int port)); 10312854Sbde void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 104637Snate int sc_deltax; 105637Snate int sc_deltay; 106637Snate int sc_obuttons; 107637Snate int sc_buttons; 108637Snate int sc_bytesread; 10931603Syokota u_char sc_bytes[MOUSE_SYS_PACKETSIZE]; 11031603Syokota mousehw_t hw; 11131603Syokota mousemode_t mode; 11231603Syokota mousestatus_t status; 11312675Sjulian#ifdef DEVFS 11412675Sjulian void *devfs_token; 11512675Sjulian void *n_devfs_token; 11612675Sjulian#endif 117637Snate} mse_sc[NMSE]; 118637Snate 119637Snate/* Flags */ 120637Snate#define MSESC_OPEN 0x1 121637Snate#define MSESC_WANT 0x2 122637Snate 123637Snate/* and Mouse Types */ 12420688Sjoerg#define MSE_NONE 0 /* don't move this! */ 125637Snate#define MSE_LOGITECH 0x1 126637Snate#define MSE_ATIINPORT 0x2 1274259Sjkh#define MSE_LOGI_SIG 0xA5 128637Snate 129637Snate#define MSE_PORTA 0 130637Snate#define MSE_PORTB 1 131637Snate#define MSE_PORTC 2 132637Snate#define MSE_PORTD 3 133637Snate 134637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 135637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 136637Snate 137637Snate/* 138637Snate * Logitech bus mouse definitions 139637Snate */ 140637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1414259Sjkh /* The definition for the control port */ 1424259Sjkh /* is as follows: */ 1438876Srgrimes 1444259Sjkh /* D7 = Mode set flag (1 = active) */ 1458876Srgrimes /* D6,D5 = Mode selection (port A) */ 1464259Sjkh /* 00 = Mode 0 = Basic I/O */ 1474259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1484259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1494259Sjkh /* D4 = Port A direction (1 = input)*/ 1504259Sjkh /* D3 = Port C (upper 4 bits) */ 1514259Sjkh /* direction. (1 = input) */ 1524259Sjkh /* D2 = Mode selection (port B & C) */ 1534259Sjkh /* 0 = Mode 0 = Basic I/O */ 1544259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1554259Sjkh /* D1 = Port B direction (1 = input)*/ 1564259Sjkh /* D0 = Port C (lower 4 bits) */ 1574259Sjkh /* direction. (1 = input) */ 1588876Srgrimes 1594259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1604259Sjkh /* Port A is an input port, B is an */ 1614259Sjkh /* output port, C is split with upper */ 1624259Sjkh /* 4 bits being an output port and lower*/ 1634259Sjkh /* 4 bits an input port, and enable the */ 1644259Sjkh /* sucker. */ 1654259Sjkh /* Courtesy Intel 8255 databook. Lars */ 166637Snate#define MSE_HOLD 0x80 167637Snate#define MSE_RXLOW 0x00 168637Snate#define MSE_RXHIGH 0x20 169637Snate#define MSE_RYLOW 0x40 170637Snate#define MSE_RYHIGH 0x60 171637Snate#define MSE_DISINTR 0x10 172637Snate#define MSE_INTREN 0x00 173637Snate 17412854Sbdestatic int mse_probelogi __P((struct isa_device *idp)); 17512854Sbdestatic void mse_disablelogi __P((u_int port)); 17612854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 17712854Sbdestatic void mse_enablelogi __P((u_int port)); 178637Snate 179637Snate/* 180637Snate * ATI Inport mouse definitions 181637Snate */ 182637Snate#define MSE_INPORT_RESET 0x80 183637Snate#define MSE_INPORT_STATUS 0x00 184637Snate#define MSE_INPORT_DX 0x01 185637Snate#define MSE_INPORT_DY 0x02 186637Snate#define MSE_INPORT_MODE 0x07 187637Snate#define MSE_INPORT_HOLD 0x20 188637Snate#define MSE_INPORT_INTREN 0x09 189637Snate 19012854Sbdestatic int mse_probeati __P((struct isa_device *idp)); 19112854Sbdestatic void mse_enableati __P((u_int port)); 19212854Sbdestatic void mse_disableati __P((u_int port)); 19312854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 194637Snate 195637Snate#define MSEPRI (PZERO + 3) 196637Snate 197637Snate/* 198637Snate * Table of mouse types. 199637Snate * Keep the Logitech last, since I haven't figured out how to probe it 200637Snate * properly yet. (Someday I'll have the documentation.) 201637Snate */ 20212724Sphkstatic struct mse_types { 203637Snate int m_type; /* Type of bus mouse */ 20412854Sbde int (*m_probe) __P((struct isa_device *idp)); 20512854Sbde /* Probe routine to test for it */ 20612854Sbde void (*m_enable) __P((u_int port)); 20712854Sbde /* Start routine */ 20812854Sbde void (*m_disable) __P((u_int port)); 20912854Sbde /* Disable interrupts routine */ 21012854Sbde void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 21112854Sbde /* and get mouse status */ 21231603Syokota mousehw_t m_hw; /* buttons iftype type model hwid */ 21331603Syokota mousemode_t m_mode; /* proto rate res accel level size mask */ 214637Snate} mse_types[] = { 21531603Syokota { MSE_ATIINPORT, 21631603Syokota mse_probeati, mse_enableati, mse_disableati, mse_getati, 21731603Syokota { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 21831603Syokota { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 21931603Syokota { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 22031603Syokota { MSE_LOGITECH, 22131603Syokota mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, 22231603Syokota { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 22331603Syokota { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 22431603Syokota { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 225637Snate { 0, }, 226637Snate}; 227637Snate 228798Swollmanint 229637Snatemseprobe(idp) 230637Snate register struct isa_device *idp; 231637Snate{ 232637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 233637Snate register int i; 234637Snate 235637Snate /* 236637Snate * Check for each mouse type in the table. 237637Snate */ 238637Snate i = 0; 239637Snate while (mse_types[i].m_type) { 240637Snate if ((*mse_types[i].m_probe)(idp)) { 241637Snate sc->sc_mousetype = mse_types[i].m_type; 242637Snate sc->sc_enablemouse = mse_types[i].m_enable; 243637Snate sc->sc_disablemouse = mse_types[i].m_disable; 244637Snate sc->sc_getmouse = mse_types[i].m_get; 24531603Syokota sc->hw = mse_types[i].m_hw; 24631603Syokota sc->mode = mse_types[i].m_mode; 247637Snate return (1); 248637Snate } 249637Snate i++; 250637Snate } 251637Snate return (0); 252637Snate} 253637Snate 254798Swollmanint 255637Snatemseattach(idp) 256637Snate struct isa_device *idp; 257637Snate{ 25812675Sjulian int unit = idp->id_unit; 25912675Sjulian struct mse_softc *sc = &mse_sc[unit]; 260637Snate 26140565Sbde idp->id_ointr = mseintr; 262637Snate sc->sc_port = idp->id_iobase; 26331603Syokota sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; 26412675Sjulian#ifdef DEVFS 26514873Sscrappy sc->devfs_token = 26614873Sscrappy devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 26714873Sscrappy 0600, "mse%d", unit); 26814873Sscrappy sc->n_devfs_token = 26914873Sscrappy devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 27014873Sscrappy 0600, "nmse%d", unit); 27112675Sjulian#endif 272637Snate return (1); 273637Snate} 274637Snate 275637Snate/* 276637Snate * Exclusive open the mouse, initialize it and enable interrupts. 277637Snate */ 27812675Sjulianstatic int 27910624Sbdemseopen(dev, flags, fmt, p) 280637Snate dev_t dev; 28110624Sbde int flags; 28210624Sbde int fmt; 28310624Sbde struct proc *p; 284637Snate{ 285637Snate register struct mse_softc *sc; 286637Snate int s; 287637Snate 288637Snate if (MSE_UNIT(dev) >= NMSE) 289637Snate return (ENXIO); 290637Snate sc = &mse_sc[MSE_UNIT(dev)]; 29120688Sjoerg if (sc->sc_mousetype == MSE_NONE) 29220688Sjoerg return (ENXIO); 293637Snate if (sc->sc_flags & MSESC_OPEN) 294637Snate return (EBUSY); 295637Snate sc->sc_flags |= MSESC_OPEN; 29631603Syokota sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS; 297637Snate sc->sc_deltax = sc->sc_deltay = 0; 29831603Syokota sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; 29931603Syokota sc->mode.level = 0; 30031603Syokota sc->status.flags = 0; 30131603Syokota sc->status.button = sc->status.obutton = 0; 30231603Syokota sc->status.dx = sc->status.dy = sc->status.dz = 0; 303637Snate 304637Snate /* 305637Snate * Initialize mouse interface and enable interrupts. 306637Snate */ 307637Snate s = spltty(); 308637Snate (*sc->sc_enablemouse)(sc->sc_port); 309637Snate splx(s); 310637Snate return (0); 311637Snate} 312637Snate 313637Snate/* 314637Snate * mseclose: just turn off mouse innterrupts. 315637Snate */ 31612675Sjulianstatic int 31710624Sbdemseclose(dev, flags, fmt, p) 318798Swollman dev_t dev; 31910624Sbde int flags; 32010624Sbde int fmt; 32110624Sbde struct proc *p; 322637Snate{ 323637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 324637Snate int s; 325637Snate 326637Snate s = spltty(); 327637Snate (*sc->sc_disablemouse)(sc->sc_port); 328637Snate sc->sc_flags &= ~MSESC_OPEN; 329637Snate splx(s); 330637Snate return(0); 331637Snate} 332637Snate 3338876Srgrimes/* 334637Snate * mseread: return mouse info using the MSC serial protocol, but without 335637Snate * using bytes 4 and 5. 336637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 337637Snate */ 33812675Sjulianstatic int 33910624Sbdemseread(dev, uio, ioflag) 340637Snate dev_t dev; 341637Snate struct uio *uio; 34210624Sbde int ioflag; 343637Snate{ 344637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 345637Snate int xfer, s, error; 346637Snate 347637Snate /* 348637Snate * If there are no protocol bytes to be read, set up a new protocol 349637Snate * packet. 350637Snate */ 351637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 35231603Syokota if (sc->sc_bytesread >= sc->mode.packetsize) { 353637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 354637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 355637Snate if (MSE_NBLOCKIO(dev)) { 356637Snate splx(s); 357637Snate return (0); 358637Snate } 359637Snate sc->sc_flags |= MSESC_WANT; 36046571Speter error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 36146571Speter "mseread", 0); 36246571Speter if (error) { 363637Snate splx(s); 364637Snate return (error); 365637Snate } 366637Snate } 367637Snate 368637Snate /* 369637Snate * Generate protocol bytes. 370637Snate * For some reason X386 expects 5 bytes but never uses 371637Snate * the fourth or fifth? 372637Snate */ 37331603Syokota sc->sc_bytes[0] = sc->mode.syncmask[1] 37431603Syokota | (sc->sc_buttons & ~sc->mode.syncmask[0]); 375637Snate if (sc->sc_deltax > 127) 376637Snate sc->sc_deltax = 127; 377637Snate if (sc->sc_deltax < -127) 378637Snate sc->sc_deltax = -127; 379637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 380637Snate if (sc->sc_deltay > 127) 381637Snate sc->sc_deltay = 127; 382637Snate if (sc->sc_deltay < -127) 383637Snate sc->sc_deltay = -127; 384637Snate sc->sc_bytes[1] = sc->sc_deltax; 385637Snate sc->sc_bytes[2] = sc->sc_deltay; 386637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 38731603Syokota sc->sc_bytes[5] = sc->sc_bytes[6] = 0; 38831603Syokota sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS; 389637Snate sc->sc_obuttons = sc->sc_buttons; 390637Snate sc->sc_deltax = sc->sc_deltay = 0; 391637Snate sc->sc_bytesread = 0; 392637Snate } 393637Snate splx(s); 39431603Syokota xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread); 39546571Speter error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio); 39646571Speter if (error) 397637Snate return (error); 398637Snate sc->sc_bytesread += xfer; 399637Snate return(0); 400637Snate} 401637Snate 402637Snate/* 40331603Syokota * mseioctl: process ioctl commands. 40431603Syokota */ 40531603Syokotastatic int 40631603Syokotamseioctl(dev, cmd, addr, flag, p) 40731603Syokota dev_t dev; 40836735Sdfr u_long cmd; 40931603Syokota caddr_t addr; 41031603Syokota int flag; 41131603Syokota struct proc *p; 41231603Syokota{ 41331603Syokota register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 41431603Syokota mousestatus_t status; 41531603Syokota int err = 0; 41631603Syokota int s; 41731603Syokota 41831603Syokota switch (cmd) { 41931603Syokota 42031603Syokota case MOUSE_GETHWINFO: 42131603Syokota s = spltty(); 42231603Syokota *(mousehw_t *)addr = sc->hw; 42331603Syokota if (sc->mode.level == 0) 42431603Syokota ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; 42531603Syokota splx(s); 42631603Syokota break; 42731603Syokota 42831603Syokota case MOUSE_GETMODE: 42931603Syokota s = spltty(); 43031603Syokota *(mousemode_t *)addr = sc->mode; 43131603Syokota switch (sc->mode.level) { 43231603Syokota case 0: 43331603Syokota break; 43431603Syokota case 1: 43531603Syokota ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; 43631603Syokota ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; 43731603Syokota ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; 43831603Syokota break; 43931603Syokota } 44031603Syokota splx(s); 44131603Syokota break; 44231603Syokota 44331603Syokota case MOUSE_SETMODE: 44431603Syokota switch (((mousemode_t *)addr)->level) { 44531603Syokota case 0: 44631603Syokota case 1: 44731603Syokota break; 44831603Syokota default: 44931603Syokota return (EINVAL); 45031603Syokota } 45131603Syokota if (((mousemode_t *)addr)->accelfactor < -1) 45231603Syokota return (EINVAL); 45331603Syokota else if (((mousemode_t *)addr)->accelfactor >= 0) 45431603Syokota sc->mode.accelfactor = 45531603Syokota ((mousemode_t *)addr)->accelfactor; 45631603Syokota sc->mode.level = ((mousemode_t *)addr)->level; 45731603Syokota switch (sc->mode.level) { 45831603Syokota case 0: 45931603Syokota sc->sc_bytesread = sc->mode.packetsize 46031603Syokota = MOUSE_MSC_PACKETSIZE; 46131603Syokota break; 46231603Syokota case 1: 46331603Syokota sc->sc_bytesread = sc->mode.packetsize 46431603Syokota = MOUSE_SYS_PACKETSIZE; 46531603Syokota break; 46631603Syokota } 46731603Syokota break; 46831603Syokota 46931603Syokota case MOUSE_GETLEVEL: 47031603Syokota *(int *)addr = sc->mode.level; 47131603Syokota break; 47231603Syokota 47331603Syokota case MOUSE_SETLEVEL: 47431603Syokota switch (*(int *)addr) { 47531603Syokota case 0: 47631603Syokota sc->mode.level = *(int *)addr; 47731603Syokota sc->sc_bytesread = sc->mode.packetsize 47831603Syokota = MOUSE_MSC_PACKETSIZE; 47931603Syokota break; 48031603Syokota case 1: 48131603Syokota sc->mode.level = *(int *)addr; 48231603Syokota sc->sc_bytesread = sc->mode.packetsize 48331603Syokota = MOUSE_SYS_PACKETSIZE; 48431603Syokota break; 48531603Syokota default: 48631603Syokota return (EINVAL); 48731603Syokota } 48831603Syokota break; 48931603Syokota 49031603Syokota case MOUSE_GETSTATUS: 49131603Syokota s = spltty(); 49231603Syokota status = sc->status; 49331603Syokota sc->status.flags = 0; 49431603Syokota sc->status.obutton = sc->status.button; 49531603Syokota sc->status.button = 0; 49631603Syokota sc->status.dx = 0; 49731603Syokota sc->status.dy = 0; 49831603Syokota sc->status.dz = 0; 49931603Syokota splx(s); 50031603Syokota *(mousestatus_t *)addr = status; 50131603Syokota break; 50231603Syokota 50331603Syokota case MOUSE_READSTATE: 50431603Syokota case MOUSE_READDATA: 50531603Syokota return (ENODEV); 50631603Syokota 50731603Syokota#if (defined(MOUSE_GETVARS)) 50831603Syokota case MOUSE_GETVARS: 50931603Syokota case MOUSE_SETVARS: 51031603Syokota return (ENODEV); 51131603Syokota#endif 51231603Syokota 51331603Syokota default: 51431603Syokota return (ENOTTY); 51531603Syokota } 51631603Syokota return (err); 51731603Syokota} 51831603Syokota 51931603Syokota/* 52029368Speter * msepoll: check for mouse input to be processed. 521637Snate */ 52212675Sjulianstatic int 52329368Spetermsepoll(dev, events, p) 524637Snate dev_t dev; 52529368Speter int events; 526637Snate struct proc *p; 527637Snate{ 528637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 529637Snate int s; 53029368Speter int revents = 0; 531637Snate 532637Snate s = spltty(); 53346568Speter if (events & (POLLIN | POLLRDNORM)) { 53431603Syokota if (sc->sc_bytesread != sc->mode.packetsize || 53531603Syokota sc->sc_deltax != 0 || sc->sc_deltay != 0 || 53629368Speter (sc->sc_obuttons ^ sc->sc_buttons) != 0) 53729368Speter revents |= events & (POLLIN | POLLRDNORM); 53829368Speter else { 53929368Speter /* 54029368Speter * Since this is an exclusive open device, any previous 54129368Speter * proc pointer is trash now, so we can just assign it. 54229368Speter */ 54329368Speter selrecord(p, &sc->sc_selp); 54429368Speter } 54546568Speter } 546637Snate splx(s); 54729368Speter return (revents); 548637Snate} 549637Snate 550637Snate/* 551637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 552637Snate */ 55340565Sbdestatic void 554637Snatemseintr(unit) 555637Snate int unit; 556637Snate{ 55731603Syokota /* 55831603Syokota * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP) 55931603Syokota * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 56031603Syokota */ 56131603Syokota static int butmap[8] = { 56231603Syokota 0, 56331603Syokota MOUSE_BUTTON3DOWN, 56431603Syokota MOUSE_BUTTON2DOWN, 56531603Syokota MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 56631603Syokota MOUSE_BUTTON1DOWN, 56731603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 56831603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 56931603Syokota MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 57031603Syokota }; 571637Snate register struct mse_softc *sc = &mse_sc[unit]; 57231603Syokota int dx, dy, but; 57331603Syokota int sign; 574637Snate 575637Snate#ifdef DEBUG 576637Snate static int mse_intrcnt = 0; 577637Snate if((mse_intrcnt++ % 10000) == 0) 578637Snate printf("mseintr\n"); 579637Snate#endif /* DEBUG */ 580637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 581637Snate return; 582637Snate 58331603Syokota (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but); 58431603Syokota if (sc->mode.accelfactor > 0) { 58531603Syokota sign = (dx < 0); 58631603Syokota dx = dx * dx / sc->mode.accelfactor; 58731603Syokota if (dx == 0) 58831603Syokota dx = 1; 58931603Syokota if (sign) 59031603Syokota dx = -dx; 59131603Syokota sign = (dy < 0); 59231603Syokota dy = dy * dy / sc->mode.accelfactor; 59331603Syokota if (dy == 0) 59431603Syokota dy = 1; 59531603Syokota if (sign) 59631603Syokota dy = -dy; 59731603Syokota } 59831603Syokota sc->sc_deltax += dx; 59931603Syokota sc->sc_deltay += dy; 60031603Syokota sc->sc_buttons = but; 601637Snate 60231603Syokota but = butmap[~but & MOUSE_MSC_BUTTONS]; 60331603Syokota sc->status.dx += dx; 60431603Syokota sc->status.dy += dy; 60531603Syokota sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0) 60631603Syokota | (sc->status.button ^ but); 60731603Syokota sc->status.button = but; 60831603Syokota 609637Snate /* 610637Snate * If mouse state has changed, wake up anyone wanting to know. 611637Snate */ 612637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 613637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 6148876Srgrimes if (sc->sc_flags & MSESC_WANT) { 6158876Srgrimes sc->sc_flags &= ~MSESC_WANT; 6168876Srgrimes wakeup((caddr_t)sc); 6178876Srgrimes } 6181549Srgrimes selwakeup(&sc->sc_selp); 619637Snate } 620637Snate} 621637Snate 622637Snate/* 623637Snate * Routines for the Logitech mouse. 624637Snate */ 625637Snate/* 626637Snate * Test for a Logitech bus mouse and return 1 if it is. 627637Snate * (until I know how to use the signature port properly, just disable 628637Snate * interrupts and return 1) 629637Snate */ 630637Snatestatic int 631637Snatemse_probelogi(idp) 632637Snate register struct isa_device *idp; 633637Snate{ 634637Snate 6354259Sjkh int sig; 6364259Sjkh 6374259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 6384259Sjkh /* set the signature port */ 6394259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 6404259Sjkh 6414259Sjkh DELAY(30000); /* 30 ms delay */ 6424259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 6434259Sjkh if (sig == MSE_LOGI_SIG) { 6444259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 6454259Sjkh return(1); 6464259Sjkh } else { 64716074Sjoerg if (bootverbose) 64816074Sjoerg printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 6494259Sjkh return(0); 650637Snate } 651637Snate} 652637Snate 653637Snate/* 654637Snate * Initialize Logitech mouse and enable interrupts. 655637Snate */ 656637Snatestatic void 657637Snatemse_enablelogi(port) 658637Snate register u_int port; 659637Snate{ 660637Snate int dx, dy, but; 661637Snate 662637Snate outb(port + MSE_PORTD, MSE_SETUP); 663637Snate mse_getlogi(port, &dx, &dy, &but); 664637Snate} 665637Snate 666637Snate/* 667637Snate * Disable interrupts for Logitech mouse. 668637Snate */ 669637Snatestatic void 670637Snatemse_disablelogi(port) 671637Snate register u_int port; 672637Snate{ 673637Snate 674637Snate outb(port + MSE_PORTC, MSE_DISINTR); 675637Snate} 676637Snate 677637Snate/* 678637Snate * Get the current dx, dy and button up/down state. 679637Snate */ 680637Snatestatic void 681637Snatemse_getlogi(port, dx, dy, but) 682637Snate register u_int port; 683637Snate int *dx; 684637Snate int *dy; 685637Snate int *but; 686637Snate{ 687637Snate register char x, y; 688637Snate 689637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 690637Snate x = inb(port + MSE_PORTA); 69131603Syokota *but = (x >> 5) & MOUSE_MSC_BUTTONS; 692637Snate x &= 0xf; 693637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 694637Snate x |= (inb(port + MSE_PORTA) << 4); 695637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 696637Snate y = (inb(port + MSE_PORTA) & 0xf); 697637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 698637Snate y |= (inb(port + MSE_PORTA) << 4); 69931603Syokota *dx = x; 70031603Syokota *dy = y; 701637Snate outb(port + MSE_PORTC, MSE_INTREN); 702637Snate} 703637Snate 704637Snate/* 705637Snate * Routines for the ATI Inport bus mouse. 706637Snate */ 707637Snate/* 708637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 709637Snate * (do not enable interrupts) 710637Snate */ 711637Snatestatic int 712637Snatemse_probeati(idp) 713637Snate register struct isa_device *idp; 714637Snate{ 715637Snate int i; 716637Snate 717637Snate for (i = 0; i < 2; i++) 718637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 719637Snate return (1); 720637Snate return (0); 721637Snate} 722637Snate 723637Snate/* 724637Snate * Initialize ATI Inport mouse and enable interrupts. 725637Snate */ 726637Snatestatic void 727637Snatemse_enableati(port) 728637Snate register u_int port; 729637Snate{ 730637Snate 731637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 732637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 733637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 734637Snate} 735637Snate 736637Snate/* 737637Snate * Disable interrupts for ATI Inport mouse. 738637Snate */ 739637Snatestatic void 740637Snatemse_disableati(port) 741637Snate register u_int port; 742637Snate{ 743637Snate 744637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 745637Snate outb(port + MSE_PORTB, 0); 746637Snate} 747637Snate 748637Snate/* 749637Snate * Get current dx, dy and up/down button state. 750637Snate */ 751637Snatestatic void 752637Snatemse_getati(port, dx, dy, but) 753637Snate register u_int port; 754637Snate int *dx; 755637Snate int *dy; 756637Snate int *but; 757637Snate{ 758637Snate register char byte; 759637Snate 760637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 761637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 762637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 76331603Syokota *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS; 764637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 765637Snate byte = inb(port + MSE_PORTB); 76631603Syokota *dx = byte; 767637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 768637Snate byte = inb(port + MSE_PORTB); 76931603Syokota *dy = byte; 770637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 771637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 772637Snate} 77312502Sjulian 77446153Sdtstatic int mse_devsw_installed; 77512502Sjulian 77612517Sjulianstatic void mse_drvinit(void *unused) 77712502Sjulian{ 77812517Sjulian dev_t dev; 77912517Sjulian 78012502Sjulian if( ! mse_devsw_installed ) { 78112675Sjulian dev = makedev(CDEV_MAJOR, 0); 78212675Sjulian cdevsw_add(&dev,&mse_cdevsw, NULL); 78312502Sjulian mse_devsw_installed = 1; 78412517Sjulian } 78512502Sjulian} 78612517Sjulian 78712517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 78812517Sjulian 78912517Sjulian 790637Snate#endif /* NMSE */ 791