mse.c revision 27555
138032Speter/* 2112810Sgshapiro * Copyright 1992 by the University of Guelph 338032Speter * 438032Speter * Permission to use, copy and modify this 538032Speter * software and its documentation for any purpose and without 638032Speter * fee is hereby granted, provided that the above copyright 738032Speter * notice appear in all copies and that both that copyright 838032Speter * notice and this permission notice appear in supporting 9112810Sgshapiro * documentation. 10112810Sgshapiro * University of Guelph makes no representations about the suitability of 11112810Sgshapiro * this software for any purpose. It is provided "as is" 12112810Sgshapiro * without express or implied warranty. 13112810Sgshapiro * 14112810Sgshapiro * $Id: mse.c,v 1.32 1997/03/24 11:23:56 bde Exp $ 15112810Sgshapiro */ 16112810Sgshapiro/* 17112810Sgshapiro * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 18112810Sgshapiro * the X386 port, courtesy of 19112810Sgshapiro * Rick Macklem, rick@snowhite.cis.uoguelph.ca 20112810Sgshapiro * Caveats: The driver currently uses spltty(), but doesn't use any 21112810Sgshapiro * generic tty code. It could use splmse() (that only masks off the 22112810Sgshapiro * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 23112810Sgshapiro * (This may be worth the effort, since the Logitech generates 30/60 24112810Sgshapiro * interrupts/sec continuously while it is open.) 25112810Sgshapiro * NB: The ATI has NOT been tested yet! 26112810Sgshapiro */ 27112810Sgshapiro 28112810Sgshapiro/* 29112810Sgshapiro * Modification history: 30112810Sgshapiro * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 31112810Sgshapiro * improved probe based on input from Logitech. 32112810Sgshapiro * 33112810Sgshapiro * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 34112810Sgshapiro * fixes to make it work with Microsoft InPort busmouse 35112810Sgshapiro * 36112810Sgshapiro * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 37112810Sgshapiro * added patches for new "select" interface 38112810Sgshapiro * 39112810Sgshapiro * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 40112810Sgshapiro * changed position of some spl()'s in mseread 41112810Sgshapiro * 42112810Sgshapiro * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 43112810Sgshapiro * limit maximum negative x/y value to -127 to work around XFree problem 44112810Sgshapiro * that causes spurious button pushes. 45112810Sgshapiro */ 46111823Sgshapiro 47111823Sgshapiro#include "mse.h" 48111823Sgshapiro#if NMSE > 0 49111823Sgshapiro#include <sys/param.h> 50111823Sgshapiro#include <sys/systm.h> 51111823Sgshapiro#include <sys/conf.h> 52111823Sgshapiro#include <sys/proc.h> 53111823Sgshapiro#include <sys/kernel.h> 54111823Sgshapiro#include <sys/uio.h> 55111823Sgshapiro#ifdef DEVFS 56111823Sgshapiro#include <sys/devfsext.h> 57111823Sgshapiro#endif /*DEVFS*/ 58111823Sgshapiro 59111823Sgshapiro#include <machine/clock.h> 60111823Sgshapiro 61111823Sgshapiro#include <i386/isa/isa_device.h> 62111823Sgshapiro 63111823Sgshapirostatic int mseprobe(struct isa_device *); 64111823Sgshapirostatic int mseattach(struct isa_device *); 65111823Sgshapiro 66110560Sgshapirostruct isa_driver msedriver = { 67110560Sgshapiro mseprobe, mseattach, "mse" 68110560Sgshapiro}; 69110560Sgshapiro 70110560Sgshapirostatic d_open_t mseopen; 71110560Sgshapirostatic d_close_t mseclose; 72110560Sgshapirostatic d_read_t mseread; 73110560Sgshapirostatic d_select_t mseselect; 74110560Sgshapiro 75110560Sgshapiro#define CDEV_MAJOR 27 76110560Sgshapirostatic struct cdevsw mse_cdevsw = 77110560Sgshapiro { mseopen, mseclose, mseread, nowrite, /*27*/ 78110560Sgshapiro noioc, nostop, nullreset, nodevtotty,/* mse */ 79110560Sgshapiro mseselect, nommap, NULL, "mse", NULL, -1 }; 80110560Sgshapiro 81110560Sgshapiro 82110560Sgshapiro/* 83110560Sgshapiro * Software control structure for mouse. The sc_enablemouse(), 84110560Sgshapiro * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 85110560Sgshapiro */ 86110560Sgshapiro#define PROTOBYTES 5 87110560Sgshapirostatic struct mse_softc { 88110560Sgshapiro int sc_flags; 89110560Sgshapiro int sc_mousetype; 90110560Sgshapiro struct selinfo sc_selp; 91110560Sgshapiro u_int sc_port; 92110560Sgshapiro void (*sc_enablemouse) __P((u_int port)); 93110560Sgshapiro void (*sc_disablemouse) __P((u_int port)); 94110560Sgshapiro void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 95110560Sgshapiro int sc_deltax; 96110560Sgshapiro int sc_deltay; 97110560Sgshapiro int sc_obuttons; 98110560Sgshapiro int sc_buttons; 99110560Sgshapiro int sc_bytesread; 100110560Sgshapiro u_char sc_bytes[PROTOBYTES]; 101110560Sgshapiro#ifdef DEVFS 102110560Sgshapiro void *devfs_token; 103110560Sgshapiro void *n_devfs_token; 104110560Sgshapiro#endif 105110560Sgshapiro} mse_sc[NMSE]; 106110560Sgshapiro 107110560Sgshapiro/* Flags */ 108110560Sgshapiro#define MSESC_OPEN 0x1 109110560Sgshapiro#define MSESC_WANT 0x2 110110560Sgshapiro 111110560Sgshapiro/* and Mouse Types */ 112110560Sgshapiro#define MSE_NONE 0 /* don't move this! */ 113110560Sgshapiro#define MSE_LOGITECH 0x1 114110560Sgshapiro#define MSE_ATIINPORT 0x2 115110560Sgshapiro#define MSE_LOGI_SIG 0xA5 116110560Sgshapiro 117110560Sgshapiro#define MSE_PORTA 0 118110560Sgshapiro#define MSE_PORTB 1 119110560Sgshapiro#define MSE_PORTC 2 120111823Sgshapiro#define MSE_PORTD 3 121110560Sgshapiro 122110560Sgshapiro#define MSE_UNIT(dev) (minor(dev) >> 1) 123110560Sgshapiro#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 124110560Sgshapiro 125110560Sgshapiro/* 126110560Sgshapiro * Logitech bus mouse definitions 127110560Sgshapiro */ 128110560Sgshapiro#define MSE_SETUP 0x91 /* What does this mean? */ 129110560Sgshapiro /* The definition for the control port */ 130110560Sgshapiro /* is as follows: */ 131110560Sgshapiro 132110560Sgshapiro /* D7 = Mode set flag (1 = active) */ 133110560Sgshapiro /* D6,D5 = Mode selection (port A) */ 134110560Sgshapiro /* 00 = Mode 0 = Basic I/O */ 135110560Sgshapiro /* 01 = Mode 1 = Strobed I/O */ 136110560Sgshapiro /* 10 = Mode 2 = Bi-dir bus */ 137110560Sgshapiro /* D4 = Port A direction (1 = input)*/ 138110560Sgshapiro /* D3 = Port C (upper 4 bits) */ 139110560Sgshapiro /* direction. (1 = input) */ 140110560Sgshapiro /* D2 = Mode selection (port B & C) */ 141110560Sgshapiro /* 0 = Mode 0 = Basic I/O */ 142110560Sgshapiro /* 1 = Mode 1 = Strobed I/O */ 143110560Sgshapiro /* D1 = Port B direction (1 = input)*/ 144110560Sgshapiro /* D0 = Port C (lower 4 bits) */ 145110560Sgshapiro /* direction. (1 = input) */ 146110560Sgshapiro 147110560Sgshapiro /* So 91 means Basic I/O on all 3 ports,*/ 148110560Sgshapiro /* Port A is an input port, B is an */ 149110560Sgshapiro /* output port, C is split with upper */ 150110560Sgshapiro /* 4 bits being an output port and lower*/ 151110560Sgshapiro /* 4 bits an input port, and enable the */ 152110560Sgshapiro /* sucker. */ 153110560Sgshapiro /* Courtesy Intel 8255 databook. Lars */ 154110560Sgshapiro#define MSE_HOLD 0x80 155110560Sgshapiro#define MSE_RXLOW 0x00 156110560Sgshapiro#define MSE_RXHIGH 0x20 157110560Sgshapiro#define MSE_RYLOW 0x40 158110560Sgshapiro#define MSE_RYHIGH 0x60 159110560Sgshapiro#define MSE_DISINTR 0x10 160110560Sgshapiro#define MSE_INTREN 0x00 161110560Sgshapiro 162110560Sgshapirostatic int mse_probelogi __P((struct isa_device *idp)); 163110560Sgshapirostatic void mse_disablelogi __P((u_int port)); 164110560Sgshapirostatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 165110560Sgshapirostatic void mse_enablelogi __P((u_int port)); 166110560Sgshapiro 167110560Sgshapiro/* 168110560Sgshapiro * ATI Inport mouse definitions 169110560Sgshapiro */ 170110560Sgshapiro#define MSE_INPORT_RESET 0x80 171110560Sgshapiro#define MSE_INPORT_STATUS 0x00 172110560Sgshapiro#define MSE_INPORT_DX 0x01 173110560Sgshapiro#define MSE_INPORT_DY 0x02 174110560Sgshapiro#define MSE_INPORT_MODE 0x07 175110560Sgshapiro#define MSE_INPORT_HOLD 0x20 176110560Sgshapiro#define MSE_INPORT_INTREN 0x09 177110560Sgshapiro 178102528Sgshapirostatic int mse_probeati __P((struct isa_device *idp)); 179102528Sgshapirostatic void mse_enableati __P((u_int port)); 180102528Sgshapirostatic void mse_disableati __P((u_int port)); 181102528Sgshapirostatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 182102528Sgshapiro 183102528Sgshapiro#define MSEPRI (PZERO + 3) 184102528Sgshapiro 185102528Sgshapiro/* 186102528Sgshapiro * Table of mouse types. 187102528Sgshapiro * Keep the Logitech last, since I haven't figured out how to probe it 188102528Sgshapiro * properly yet. (Someday I'll have the documentation.) 189102528Sgshapiro */ 190102528Sgshapirostatic struct mse_types { 191102528Sgshapiro int m_type; /* Type of bus mouse */ 192102528Sgshapiro int (*m_probe) __P((struct isa_device *idp)); 193102528Sgshapiro /* Probe routine to test for it */ 194102528Sgshapiro void (*m_enable) __P((u_int port)); 195102528Sgshapiro /* Start routine */ 196102528Sgshapiro void (*m_disable) __P((u_int port)); 197102528Sgshapiro /* Disable interrupts routine */ 198102528Sgshapiro void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 199102528Sgshapiro /* and get mouse status */ 200102528Sgshapiro} mse_types[] = { 201102528Sgshapiro { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 202102528Sgshapiro { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 203102528Sgshapiro { 0, }, 204102528Sgshapiro}; 205102528Sgshapiro 206102528Sgshapiroint 207102528Sgshapiromseprobe(idp) 208102528Sgshapiro register struct isa_device *idp; 209102528Sgshapiro{ 210102528Sgshapiro register struct mse_softc *sc = &mse_sc[idp->id_unit]; 211102528Sgshapiro register int i; 212102528Sgshapiro 213102528Sgshapiro /* 214102528Sgshapiro * Check for each mouse type in the table. 215102528Sgshapiro */ 216102528Sgshapiro i = 0; 217102528Sgshapiro while (mse_types[i].m_type) { 218102528Sgshapiro if ((*mse_types[i].m_probe)(idp)) { 219102528Sgshapiro sc->sc_mousetype = mse_types[i].m_type; 220102528Sgshapiro sc->sc_enablemouse = mse_types[i].m_enable; 221102528Sgshapiro sc->sc_disablemouse = mse_types[i].m_disable; 222102528Sgshapiro sc->sc_getmouse = mse_types[i].m_get; 223102528Sgshapiro return (1); 224102528Sgshapiro } 225102528Sgshapiro i++; 226102528Sgshapiro } 227102528Sgshapiro return (0); 228102528Sgshapiro} 229102528Sgshapiro 230102528Sgshapiroint 231102528Sgshapiromseattach(idp) 232102528Sgshapiro struct isa_device *idp; 233102528Sgshapiro{ 234102528Sgshapiro int unit = idp->id_unit; 235102528Sgshapiro struct mse_softc *sc = &mse_sc[unit]; 236102528Sgshapiro 237102528Sgshapiro sc->sc_port = idp->id_iobase; 238102528Sgshapiro#ifdef DEVFS 239102528Sgshapiro sc->devfs_token = 240102528Sgshapiro devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 241102528Sgshapiro 0600, "mse%d", unit); 242102528Sgshapiro sc->n_devfs_token = 243102528Sgshapiro devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 244102528Sgshapiro 0600, "nmse%d", unit); 245102528Sgshapiro#endif 246102528Sgshapiro return (1); 247102528Sgshapiro} 248102528Sgshapiro 249102528Sgshapiro/* 250102528Sgshapiro * Exclusive open the mouse, initialize it and enable interrupts. 251102528Sgshapiro */ 252102528Sgshapirostatic int 253102528Sgshapiromseopen(dev, flags, fmt, p) 254102528Sgshapiro dev_t dev; 255102528Sgshapiro int flags; 256102528Sgshapiro int fmt; 257102528Sgshapiro struct proc *p; 25898841Sgshapiro{ 25998841Sgshapiro register struct mse_softc *sc; 26098841Sgshapiro int s; 26198841Sgshapiro 26298841Sgshapiro if (MSE_UNIT(dev) >= NMSE) 26398841Sgshapiro return (ENXIO); 26498841Sgshapiro sc = &mse_sc[MSE_UNIT(dev)]; 26598841Sgshapiro if (sc->sc_mousetype == MSE_NONE) 26698841Sgshapiro return (ENXIO); 26798841Sgshapiro if (sc->sc_flags & MSESC_OPEN) 26898841Sgshapiro return (EBUSY); 26998841Sgshapiro sc->sc_flags |= MSESC_OPEN; 27098841Sgshapiro sc->sc_obuttons = sc->sc_buttons = 0x7; 27198841Sgshapiro sc->sc_deltax = sc->sc_deltay = 0; 27298841Sgshapiro sc->sc_bytesread = PROTOBYTES; 27398841Sgshapiro 27498841Sgshapiro /* 27598841Sgshapiro * Initialize mouse interface and enable interrupts. 27698841Sgshapiro */ 27798841Sgshapiro s = spltty(); 27898841Sgshapiro (*sc->sc_enablemouse)(sc->sc_port); 27998841Sgshapiro splx(s); 28098841Sgshapiro return (0); 28198841Sgshapiro} 28298841Sgshapiro 28398841Sgshapiro/* 28498841Sgshapiro * mseclose: just turn off mouse innterrupts. 28598841Sgshapiro */ 28698841Sgshapirostatic int 28798841Sgshapiromseclose(dev, flags, fmt, p) 28898841Sgshapiro dev_t dev; 28998841Sgshapiro int flags; 29098841Sgshapiro int fmt; 29198841Sgshapiro struct proc *p; 29298121Sgshapiro{ 29398121Sgshapiro struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 29498121Sgshapiro int s; 29598121Sgshapiro 29698121Sgshapiro s = spltty(); 29798121Sgshapiro (*sc->sc_disablemouse)(sc->sc_port); 29898121Sgshapiro sc->sc_flags &= ~MSESC_OPEN; 29998121Sgshapiro splx(s); 30098121Sgshapiro return(0); 30198121Sgshapiro} 30298121Sgshapiro 30398121Sgshapiro/* 30498121Sgshapiro * mseread: return mouse info using the MSC serial protocol, but without 30598121Sgshapiro * using bytes 4 and 5. 30698121Sgshapiro * (Yes this is cheesy, but it makes the X386 server happy, so...) 30798121Sgshapiro */ 30898121Sgshapirostatic int 30998121Sgshapiromseread(dev, uio, ioflag) 31098121Sgshapiro dev_t dev; 31198121Sgshapiro struct uio *uio; 31298121Sgshapiro int ioflag; 31398121Sgshapiro{ 31498121Sgshapiro register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 31598121Sgshapiro int xfer, s, error; 31698121Sgshapiro 31798121Sgshapiro /* 31898121Sgshapiro * If there are no protocol bytes to be read, set up a new protocol 31998121Sgshapiro * packet. 32098121Sgshapiro */ 32198121Sgshapiro s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 32298121Sgshapiro if (sc->sc_bytesread >= PROTOBYTES) { 32398121Sgshapiro while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 32498121Sgshapiro (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 32598121Sgshapiro if (MSE_NBLOCKIO(dev)) { 32698121Sgshapiro splx(s); 32798121Sgshapiro return (0); 32898121Sgshapiro } 32998121Sgshapiro sc->sc_flags |= MSESC_WANT; 33098121Sgshapiro if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 33198121Sgshapiro "mseread", 0)) { 33298121Sgshapiro splx(s); 33398121Sgshapiro return (error); 33498121Sgshapiro } 33598121Sgshapiro } 33698121Sgshapiro 33798121Sgshapiro /* 33898121Sgshapiro * Generate protocol bytes. 33998121Sgshapiro * For some reason X386 expects 5 bytes but never uses 34098121Sgshapiro * the fourth or fifth? 34198121Sgshapiro */ 34298121Sgshapiro sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 34398121Sgshapiro if (sc->sc_deltax > 127) 34498121Sgshapiro sc->sc_deltax = 127; 34598121Sgshapiro if (sc->sc_deltax < -127) 34698121Sgshapiro sc->sc_deltax = -127; 34798121Sgshapiro sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 34898121Sgshapiro if (sc->sc_deltay > 127) 34998121Sgshapiro sc->sc_deltay = 127; 35098121Sgshapiro if (sc->sc_deltay < -127) 35198121Sgshapiro sc->sc_deltay = -127; 35298121Sgshapiro sc->sc_bytes[1] = sc->sc_deltax; 35398121Sgshapiro sc->sc_bytes[2] = sc->sc_deltay; 35498121Sgshapiro sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 35598121Sgshapiro sc->sc_obuttons = sc->sc_buttons; 35698121Sgshapiro sc->sc_deltax = sc->sc_deltay = 0; 35798121Sgshapiro sc->sc_bytesread = 0; 35898121Sgshapiro } 35998121Sgshapiro splx(s); 36098121Sgshapiro xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 36198121Sgshapiro if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 36298121Sgshapiro return (error); 36398121Sgshapiro sc->sc_bytesread += xfer; 36498121Sgshapiro return(0); 36598121Sgshapiro} 36698121Sgshapiro 36798121Sgshapiro/* 36898121Sgshapiro * mseselect: check for mouse input to be processed. 36998121Sgshapiro */ 37098121Sgshapirostatic int 37198121Sgshapiromseselect(dev, rw, p) 37298121Sgshapiro dev_t dev; 37398121Sgshapiro int rw; 37498121Sgshapiro struct proc *p; 37598121Sgshapiro{ 37698121Sgshapiro register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 37798121Sgshapiro int s; 37898121Sgshapiro 37998121Sgshapiro s = spltty(); 38098121Sgshapiro if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 38198121Sgshapiro sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 38298121Sgshapiro splx(s); 38398121Sgshapiro return (1); 38498121Sgshapiro } 38594334Sgshapiro 38694334Sgshapiro /* 38794334Sgshapiro * Since this is an exclusive open device, any previous proc. 38894334Sgshapiro * pointer is trash now, so we can just assign it. 38994334Sgshapiro */ 39094334Sgshapiro selrecord(p, &sc->sc_selp); 39194334Sgshapiro splx(s); 39294334Sgshapiro return (0); 39394334Sgshapiro} 39494334Sgshapiro 39594334Sgshapiro/* 39694334Sgshapiro * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 39794334Sgshapiro */ 39894334Sgshapirovoid 39994334Sgshapiromseintr(unit) 40094334Sgshapiro int unit; 40194334Sgshapiro{ 40294334Sgshapiro register struct mse_softc *sc = &mse_sc[unit]; 40394334Sgshapiro 40494334Sgshapiro#ifdef DEBUG 40594334Sgshapiro static int mse_intrcnt = 0; 40694334Sgshapiro if((mse_intrcnt++ % 10000) == 0) 40794334Sgshapiro printf("mseintr\n"); 40894334Sgshapiro#endif /* DEBUG */ 40994334Sgshapiro if ((sc->sc_flags & MSESC_OPEN) == 0) 41094334Sgshapiro return; 41194334Sgshapiro 41294334Sgshapiro (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 41394334Sgshapiro 41494334Sgshapiro /* 41594334Sgshapiro * If mouse state has changed, wake up anyone wanting to know. 41694334Sgshapiro */ 41794334Sgshapiro if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 41894334Sgshapiro (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 41994334Sgshapiro if (sc->sc_flags & MSESC_WANT) { 42094334Sgshapiro sc->sc_flags &= ~MSESC_WANT; 42194334Sgshapiro wakeup((caddr_t)sc); 42294334Sgshapiro } 42394334Sgshapiro selwakeup(&sc->sc_selp); 42494334Sgshapiro } 42594334Sgshapiro} 42694334Sgshapiro 42794334Sgshapiro/* 42894334Sgshapiro * Routines for the Logitech mouse. 42994334Sgshapiro */ 43094334Sgshapiro/* 43194334Sgshapiro * Test for a Logitech bus mouse and return 1 if it is. 43294334Sgshapiro * (until I know how to use the signature port properly, just disable 43394334Sgshapiro * interrupts and return 1) 43494334Sgshapiro */ 43594334Sgshapirostatic int 43694334Sgshapiromse_probelogi(idp) 43794334Sgshapiro register struct isa_device *idp; 43894334Sgshapiro{ 43994334Sgshapiro 44094334Sgshapiro int sig; 44194334Sgshapiro 44294334Sgshapiro outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 44394334Sgshapiro /* set the signature port */ 44494334Sgshapiro outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 44594334Sgshapiro 44694334Sgshapiro DELAY(30000); /* 30 ms delay */ 44794334Sgshapiro sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 44894334Sgshapiro if (sig == MSE_LOGI_SIG) { 44994334Sgshapiro outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 45094334Sgshapiro return(1); 45194334Sgshapiro } else { 45294334Sgshapiro if (bootverbose) 45394334Sgshapiro printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 45494334Sgshapiro return(0); 45594334Sgshapiro } 45694334Sgshapiro} 45794334Sgshapiro 45894334Sgshapiro/* 45994334Sgshapiro * Initialize Logitech mouse and enable interrupts. 46094334Sgshapiro */ 46194334Sgshapirostatic void 46294334Sgshapiromse_enablelogi(port) 46394334Sgshapiro register u_int port; 46494334Sgshapiro{ 46594334Sgshapiro int dx, dy, but; 46694334Sgshapiro 46794334Sgshapiro outb(port + MSE_PORTD, MSE_SETUP); 46894334Sgshapiro mse_getlogi(port, &dx, &dy, &but); 46994334Sgshapiro} 47094334Sgshapiro 47194334Sgshapiro/* 47294334Sgshapiro * Disable interrupts for Logitech mouse. 47394334Sgshapiro */ 47494334Sgshapirostatic void 47594334Sgshapiromse_disablelogi(port) 47694334Sgshapiro register u_int port; 47794334Sgshapiro{ 47894334Sgshapiro 47994334Sgshapiro outb(port + MSE_PORTC, MSE_DISINTR); 48094334Sgshapiro} 48194334Sgshapiro 48294334Sgshapiro/* 48394334Sgshapiro * Get the current dx, dy and button up/down state. 48494334Sgshapiro */ 48594334Sgshapirostatic void 48694334Sgshapiromse_getlogi(port, dx, dy, but) 48794334Sgshapiro register u_int port; 48894334Sgshapiro int *dx; 48998121Sgshapiro int *dy; 49094334Sgshapiro int *but; 49194334Sgshapiro{ 49294334Sgshapiro register char x, y; 49394334Sgshapiro 49494334Sgshapiro outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 49594334Sgshapiro x = inb(port + MSE_PORTA); 49694334Sgshapiro *but = (x >> 5) & 0x7; 49794334Sgshapiro x &= 0xf; 49894334Sgshapiro outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 49994334Sgshapiro x |= (inb(port + MSE_PORTA) << 4); 50094334Sgshapiro outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 50194334Sgshapiro y = (inb(port + MSE_PORTA) & 0xf); 50294334Sgshapiro outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 50394334Sgshapiro y |= (inb(port + MSE_PORTA) << 4); 50494334Sgshapiro *dx += x; 50594334Sgshapiro *dy += y; 50694334Sgshapiro outb(port + MSE_PORTC, MSE_INTREN); 50794334Sgshapiro} 50894334Sgshapiro 50994334Sgshapiro/* 51094334Sgshapiro * Routines for the ATI Inport bus mouse. 51194334Sgshapiro */ 51294334Sgshapiro/* 51394334Sgshapiro * Test for a ATI Inport bus mouse and return 1 if it is. 51494334Sgshapiro * (do not enable interrupts) 51594334Sgshapiro */ 51694334Sgshapirostatic int 51794334Sgshapiromse_probeati(idp) 51894334Sgshapiro register struct isa_device *idp; 51994334Sgshapiro{ 52094334Sgshapiro int i; 52194334Sgshapiro 52294334Sgshapiro for (i = 0; i < 2; i++) 52394334Sgshapiro if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 52494334Sgshapiro return (1); 52594334Sgshapiro return (0); 52694334Sgshapiro} 52794334Sgshapiro 52894334Sgshapiro/* 52994334Sgshapiro * Initialize ATI Inport mouse and enable interrupts. 53094334Sgshapiro */ 53194334Sgshapirostatic void 53294334Sgshapiromse_enableati(port) 53394334Sgshapiro register u_int port; 53494334Sgshapiro{ 53594334Sgshapiro 53694334Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_RESET); 53794334Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_MODE); 53898121Sgshapiro outb(port + MSE_PORTB, MSE_INPORT_INTREN); 53998121Sgshapiro} 54094334Sgshapiro 54194334Sgshapiro/* 54294334Sgshapiro * Disable interrupts for ATI Inport mouse. 54394334Sgshapiro */ 54494334Sgshapirostatic void 54594334Sgshapiromse_disableati(port) 54694334Sgshapiro register u_int port; 54794334Sgshapiro{ 54894334Sgshapiro 54994334Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_MODE); 55094334Sgshapiro outb(port + MSE_PORTB, 0); 55194334Sgshapiro} 55294334Sgshapiro 55394334Sgshapiro/* 55494334Sgshapiro * Get current dx, dy and up/down button state. 55594334Sgshapiro */ 55694334Sgshapirostatic void 55794334Sgshapiromse_getati(port, dx, dy, but) 55894334Sgshapiro register u_int port; 55994334Sgshapiro int *dx; 56094334Sgshapiro int *dy; 56194334Sgshapiro int *but; 56294334Sgshapiro{ 56394334Sgshapiro register char byte; 56490792Sgshapiro 56590792Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_MODE); 56690792Sgshapiro outb(port + MSE_PORTB, MSE_INPORT_HOLD); 56790792Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_STATUS); 56890792Sgshapiro *but = ~(inb(port + MSE_PORTB) & 0x7); 56990792Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_DX); 57090792Sgshapiro byte = inb(port + MSE_PORTB); 57190792Sgshapiro *dx += byte; 57290792Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_DY); 57390792Sgshapiro byte = inb(port + MSE_PORTB); 57490792Sgshapiro *dy += byte; 57590792Sgshapiro outb(port + MSE_PORTA, MSE_INPORT_MODE); 57690792Sgshapiro outb(port + MSE_PORTB, MSE_INPORT_INTREN); 57790792Sgshapiro} 57890792Sgshapiro 57990792Sgshapirostatic mse_devsw_installed = 0; 58090792Sgshapiro 58190792Sgshapirostatic void mse_drvinit(void *unused) 58290792Sgshapiro{ 58390792Sgshapiro dev_t dev; 58490792Sgshapiro 58590792Sgshapiro if( ! mse_devsw_installed ) { 58690792Sgshapiro dev = makedev(CDEV_MAJOR, 0); 58790792Sgshapiro cdevsw_add(&dev,&mse_cdevsw, NULL); 58890792Sgshapiro mse_devsw_installed = 1; 58990792Sgshapiro } 59090792Sgshapiro} 59190792Sgshapiro 59290792SgshapiroSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 59390792Sgshapiro 59490792Sgshapiro 59590792Sgshapiro#endif /* NMSE */ 59690792Sgshapiro