mse.c revision 29368
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 * 1429368Speter * $Id: mse.c,v 1.33 1997/07/20 14:10:06 bde 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 492056Swollman#include <sys/param.h> 503745Swollman#include <sys/systm.h> 5112658Sbde#include <sys/conf.h> 522056Swollman#include <sys/proc.h> 532056Swollman#include <sys/kernel.h> 5429368Speter#include <sys/poll.h> 552056Swollman#include <sys/uio.h> 5612675Sjulian#ifdef DEVFS 5712675Sjulian#include <sys/devfsext.h> 5812675Sjulian#endif /*DEVFS*/ 59637Snate 607430Sbde#include <machine/clock.h> 617430Sbde 622056Swollman#include <i386/isa/isa_device.h> 63637Snate 64798Swollmanstatic int mseprobe(struct isa_device *); 65798Swollmanstatic int mseattach(struct isa_device *); 66637Snate 67637Snatestruct isa_driver msedriver = { 68637Snate mseprobe, mseattach, "mse" 69637Snate}; 70637Snate 7112675Sjulianstatic d_open_t mseopen; 7212675Sjulianstatic d_close_t mseclose; 7312675Sjulianstatic d_read_t mseread; 7429368Speterstatic d_poll_t msepoll; 7512675Sjulian 7612675Sjulian#define CDEV_MAJOR 27 7712678Sphkstatic struct cdevsw mse_cdevsw = 7812675Sjulian { mseopen, mseclose, mseread, nowrite, /*27*/ 7912675Sjulian noioc, nostop, nullreset, nodevtotty,/* mse */ 8029368Speter msepoll, nommap, NULL, "mse", NULL, -1 }; 8112675Sjulian 8212675Sjulian 83637Snate/* 84637Snate * Software control structure for mouse. The sc_enablemouse(), 85637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 86637Snate */ 87637Snate#define PROTOBYTES 5 8812724Sphkstatic struct mse_softc { 89637Snate int sc_flags; 90637Snate int sc_mousetype; 911549Srgrimes struct selinfo sc_selp; 92637Snate u_int sc_port; 9312854Sbde void (*sc_enablemouse) __P((u_int port)); 9412854Sbde void (*sc_disablemouse) __P((u_int port)); 9512854Sbde void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 96637Snate int sc_deltax; 97637Snate int sc_deltay; 98637Snate int sc_obuttons; 99637Snate int sc_buttons; 100637Snate int sc_bytesread; 101637Snate u_char sc_bytes[PROTOBYTES]; 10212675Sjulian#ifdef DEVFS 10312675Sjulian void *devfs_token; 10412675Sjulian void *n_devfs_token; 10512675Sjulian#endif 106637Snate} mse_sc[NMSE]; 107637Snate 108637Snate/* Flags */ 109637Snate#define MSESC_OPEN 0x1 110637Snate#define MSESC_WANT 0x2 111637Snate 112637Snate/* and Mouse Types */ 11320688Sjoerg#define MSE_NONE 0 /* don't move this! */ 114637Snate#define MSE_LOGITECH 0x1 115637Snate#define MSE_ATIINPORT 0x2 1164259Sjkh#define MSE_LOGI_SIG 0xA5 117637Snate 118637Snate#define MSE_PORTA 0 119637Snate#define MSE_PORTB 1 120637Snate#define MSE_PORTC 2 121637Snate#define MSE_PORTD 3 122637Snate 123637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 124637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 125637Snate 126637Snate/* 127637Snate * Logitech bus mouse definitions 128637Snate */ 129637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1304259Sjkh /* The definition for the control port */ 1314259Sjkh /* is as follows: */ 1328876Srgrimes 1334259Sjkh /* D7 = Mode set flag (1 = active) */ 1348876Srgrimes /* D6,D5 = Mode selection (port A) */ 1354259Sjkh /* 00 = Mode 0 = Basic I/O */ 1364259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1374259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1384259Sjkh /* D4 = Port A direction (1 = input)*/ 1394259Sjkh /* D3 = Port C (upper 4 bits) */ 1404259Sjkh /* direction. (1 = input) */ 1414259Sjkh /* D2 = Mode selection (port B & C) */ 1424259Sjkh /* 0 = Mode 0 = Basic I/O */ 1434259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1444259Sjkh /* D1 = Port B direction (1 = input)*/ 1454259Sjkh /* D0 = Port C (lower 4 bits) */ 1464259Sjkh /* direction. (1 = input) */ 1478876Srgrimes 1484259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1494259Sjkh /* Port A is an input port, B is an */ 1504259Sjkh /* output port, C is split with upper */ 1514259Sjkh /* 4 bits being an output port and lower*/ 1524259Sjkh /* 4 bits an input port, and enable the */ 1534259Sjkh /* sucker. */ 1544259Sjkh /* Courtesy Intel 8255 databook. Lars */ 155637Snate#define MSE_HOLD 0x80 156637Snate#define MSE_RXLOW 0x00 157637Snate#define MSE_RXHIGH 0x20 158637Snate#define MSE_RYLOW 0x40 159637Snate#define MSE_RYHIGH 0x60 160637Snate#define MSE_DISINTR 0x10 161637Snate#define MSE_INTREN 0x00 162637Snate 16312854Sbdestatic int mse_probelogi __P((struct isa_device *idp)); 16412854Sbdestatic void mse_disablelogi __P((u_int port)); 16512854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 16612854Sbdestatic void mse_enablelogi __P((u_int port)); 167637Snate 168637Snate/* 169637Snate * ATI Inport mouse definitions 170637Snate */ 171637Snate#define MSE_INPORT_RESET 0x80 172637Snate#define MSE_INPORT_STATUS 0x00 173637Snate#define MSE_INPORT_DX 0x01 174637Snate#define MSE_INPORT_DY 0x02 175637Snate#define MSE_INPORT_MODE 0x07 176637Snate#define MSE_INPORT_HOLD 0x20 177637Snate#define MSE_INPORT_INTREN 0x09 178637Snate 17912854Sbdestatic int mse_probeati __P((struct isa_device *idp)); 18012854Sbdestatic void mse_enableati __P((u_int port)); 18112854Sbdestatic void mse_disableati __P((u_int port)); 18212854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 183637Snate 184637Snate#define MSEPRI (PZERO + 3) 185637Snate 186637Snate/* 187637Snate * Table of mouse types. 188637Snate * Keep the Logitech last, since I haven't figured out how to probe it 189637Snate * properly yet. (Someday I'll have the documentation.) 190637Snate */ 19112724Sphkstatic struct mse_types { 192637Snate int m_type; /* Type of bus mouse */ 19312854Sbde int (*m_probe) __P((struct isa_device *idp)); 19412854Sbde /* Probe routine to test for it */ 19512854Sbde void (*m_enable) __P((u_int port)); 19612854Sbde /* Start routine */ 19712854Sbde void (*m_disable) __P((u_int port)); 19812854Sbde /* Disable interrupts routine */ 19912854Sbde void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 20012854Sbde /* and get mouse status */ 201637Snate} mse_types[] = { 202637Snate { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 203637Snate { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 204637Snate { 0, }, 205637Snate}; 206637Snate 207798Swollmanint 208637Snatemseprobe(idp) 209637Snate register struct isa_device *idp; 210637Snate{ 211637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 212637Snate register int i; 213637Snate 214637Snate /* 215637Snate * Check for each mouse type in the table. 216637Snate */ 217637Snate i = 0; 218637Snate while (mse_types[i].m_type) { 219637Snate if ((*mse_types[i].m_probe)(idp)) { 220637Snate sc->sc_mousetype = mse_types[i].m_type; 221637Snate sc->sc_enablemouse = mse_types[i].m_enable; 222637Snate sc->sc_disablemouse = mse_types[i].m_disable; 223637Snate sc->sc_getmouse = mse_types[i].m_get; 224637Snate return (1); 225637Snate } 226637Snate i++; 227637Snate } 228637Snate return (0); 229637Snate} 230637Snate 231798Swollmanint 232637Snatemseattach(idp) 233637Snate struct isa_device *idp; 234637Snate{ 23512675Sjulian int unit = idp->id_unit; 23612675Sjulian struct mse_softc *sc = &mse_sc[unit]; 237637Snate 238637Snate sc->sc_port = idp->id_iobase; 23912675Sjulian#ifdef DEVFS 24014873Sscrappy sc->devfs_token = 24114873Sscrappy devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 24214873Sscrappy 0600, "mse%d", unit); 24314873Sscrappy sc->n_devfs_token = 24414873Sscrappy devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 24514873Sscrappy 0600, "nmse%d", unit); 24612675Sjulian#endif 247637Snate return (1); 248637Snate} 249637Snate 250637Snate/* 251637Snate * Exclusive open the mouse, initialize it and enable interrupts. 252637Snate */ 25312675Sjulianstatic int 25410624Sbdemseopen(dev, flags, fmt, p) 255637Snate dev_t dev; 25610624Sbde int flags; 25710624Sbde int fmt; 25810624Sbde struct proc *p; 259637Snate{ 260637Snate register struct mse_softc *sc; 261637Snate int s; 262637Snate 263637Snate if (MSE_UNIT(dev) >= NMSE) 264637Snate return (ENXIO); 265637Snate sc = &mse_sc[MSE_UNIT(dev)]; 26620688Sjoerg if (sc->sc_mousetype == MSE_NONE) 26720688Sjoerg return (ENXIO); 268637Snate if (sc->sc_flags & MSESC_OPEN) 269637Snate return (EBUSY); 270637Snate sc->sc_flags |= MSESC_OPEN; 271637Snate sc->sc_obuttons = sc->sc_buttons = 0x7; 272637Snate sc->sc_deltax = sc->sc_deltay = 0; 273637Snate sc->sc_bytesread = PROTOBYTES; 274637Snate 275637Snate /* 276637Snate * Initialize mouse interface and enable interrupts. 277637Snate */ 278637Snate s = spltty(); 279637Snate (*sc->sc_enablemouse)(sc->sc_port); 280637Snate splx(s); 281637Snate return (0); 282637Snate} 283637Snate 284637Snate/* 285637Snate * mseclose: just turn off mouse innterrupts. 286637Snate */ 28712675Sjulianstatic int 28810624Sbdemseclose(dev, flags, fmt, p) 289798Swollman dev_t dev; 29010624Sbde int flags; 29110624Sbde int fmt; 29210624Sbde struct proc *p; 293637Snate{ 294637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 295637Snate int s; 296637Snate 297637Snate s = spltty(); 298637Snate (*sc->sc_disablemouse)(sc->sc_port); 299637Snate sc->sc_flags &= ~MSESC_OPEN; 300637Snate splx(s); 301637Snate return(0); 302637Snate} 303637Snate 3048876Srgrimes/* 305637Snate * mseread: return mouse info using the MSC serial protocol, but without 306637Snate * using bytes 4 and 5. 307637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 308637Snate */ 30912675Sjulianstatic int 31010624Sbdemseread(dev, uio, ioflag) 311637Snate dev_t dev; 312637Snate struct uio *uio; 31310624Sbde int ioflag; 314637Snate{ 315637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 316637Snate int xfer, s, error; 317637Snate 318637Snate /* 319637Snate * If there are no protocol bytes to be read, set up a new protocol 320637Snate * packet. 321637Snate */ 322637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 323637Snate if (sc->sc_bytesread >= PROTOBYTES) { 324637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 325637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 326637Snate if (MSE_NBLOCKIO(dev)) { 327637Snate splx(s); 328637Snate return (0); 329637Snate } 330637Snate sc->sc_flags |= MSESC_WANT; 331637Snate if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 332637Snate "mseread", 0)) { 333637Snate splx(s); 334637Snate return (error); 335637Snate } 336637Snate } 337637Snate 338637Snate /* 339637Snate * Generate protocol bytes. 340637Snate * For some reason X386 expects 5 bytes but never uses 341637Snate * the fourth or fifth? 342637Snate */ 343637Snate sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 344637Snate if (sc->sc_deltax > 127) 345637Snate sc->sc_deltax = 127; 346637Snate if (sc->sc_deltax < -127) 347637Snate sc->sc_deltax = -127; 348637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 349637Snate if (sc->sc_deltay > 127) 350637Snate sc->sc_deltay = 127; 351637Snate if (sc->sc_deltay < -127) 352637Snate sc->sc_deltay = -127; 353637Snate sc->sc_bytes[1] = sc->sc_deltax; 354637Snate sc->sc_bytes[2] = sc->sc_deltay; 355637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 356637Snate sc->sc_obuttons = sc->sc_buttons; 357637Snate sc->sc_deltax = sc->sc_deltay = 0; 358637Snate sc->sc_bytesread = 0; 359637Snate } 360637Snate splx(s); 3611567Srgrimes xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 362637Snate if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 363637Snate return (error); 364637Snate sc->sc_bytesread += xfer; 365637Snate return(0); 366637Snate} 367637Snate 368637Snate/* 36929368Speter * msepoll: check for mouse input to be processed. 370637Snate */ 37112675Sjulianstatic int 37229368Spetermsepoll(dev, events, p) 373637Snate dev_t dev; 37429368Speter int events; 375637Snate struct proc *p; 376637Snate{ 377637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 378637Snate int s; 37929368Speter int revents = 0; 380637Snate 381637Snate s = spltty(); 38229368Speter if (events & (POLLIN | POLLRDNORM)) 38329368Speter if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 38429368Speter sc->sc_deltay != 0 || 38529368Speter (sc->sc_obuttons ^ sc->sc_buttons) != 0) 38629368Speter revents |= events & (POLLIN | POLLRDNORM); 38729368Speter else { 38829368Speter /* 38929368Speter * Since this is an exclusive open device, any previous 39029368Speter * proc pointer is trash now, so we can just assign it. 39129368Speter */ 39229368Speter selrecord(p, &sc->sc_selp); 39329368Speter } 394637Snate 395637Snate splx(s); 39629368Speter return (revents); 397637Snate} 398637Snate 399637Snate/* 400637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 401637Snate */ 402798Swollmanvoid 403637Snatemseintr(unit) 404637Snate int unit; 405637Snate{ 406637Snate register struct mse_softc *sc = &mse_sc[unit]; 407637Snate 408637Snate#ifdef DEBUG 409637Snate static int mse_intrcnt = 0; 410637Snate if((mse_intrcnt++ % 10000) == 0) 411637Snate printf("mseintr\n"); 412637Snate#endif /* DEBUG */ 413637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 414637Snate return; 415637Snate 416637Snate (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 417637Snate 418637Snate /* 419637Snate * If mouse state has changed, wake up anyone wanting to know. 420637Snate */ 421637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 422637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 4238876Srgrimes if (sc->sc_flags & MSESC_WANT) { 4248876Srgrimes sc->sc_flags &= ~MSESC_WANT; 4258876Srgrimes wakeup((caddr_t)sc); 4268876Srgrimes } 4271549Srgrimes selwakeup(&sc->sc_selp); 428637Snate } 429637Snate} 430637Snate 431637Snate/* 432637Snate * Routines for the Logitech mouse. 433637Snate */ 434637Snate/* 435637Snate * Test for a Logitech bus mouse and return 1 if it is. 436637Snate * (until I know how to use the signature port properly, just disable 437637Snate * interrupts and return 1) 438637Snate */ 439637Snatestatic int 440637Snatemse_probelogi(idp) 441637Snate register struct isa_device *idp; 442637Snate{ 443637Snate 4444259Sjkh int sig; 4454259Sjkh 4464259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 4474259Sjkh /* set the signature port */ 4484259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 4494259Sjkh 4504259Sjkh DELAY(30000); /* 30 ms delay */ 4514259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 4524259Sjkh if (sig == MSE_LOGI_SIG) { 4534259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 4544259Sjkh return(1); 4554259Sjkh } else { 45616074Sjoerg if (bootverbose) 45716074Sjoerg printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 4584259Sjkh return(0); 459637Snate } 460637Snate} 461637Snate 462637Snate/* 463637Snate * Initialize Logitech mouse and enable interrupts. 464637Snate */ 465637Snatestatic void 466637Snatemse_enablelogi(port) 467637Snate register u_int port; 468637Snate{ 469637Snate int dx, dy, but; 470637Snate 471637Snate outb(port + MSE_PORTD, MSE_SETUP); 472637Snate mse_getlogi(port, &dx, &dy, &but); 473637Snate} 474637Snate 475637Snate/* 476637Snate * Disable interrupts for Logitech mouse. 477637Snate */ 478637Snatestatic void 479637Snatemse_disablelogi(port) 480637Snate register u_int port; 481637Snate{ 482637Snate 483637Snate outb(port + MSE_PORTC, MSE_DISINTR); 484637Snate} 485637Snate 486637Snate/* 487637Snate * Get the current dx, dy and button up/down state. 488637Snate */ 489637Snatestatic void 490637Snatemse_getlogi(port, dx, dy, but) 491637Snate register u_int port; 492637Snate int *dx; 493637Snate int *dy; 494637Snate int *but; 495637Snate{ 496637Snate register char x, y; 497637Snate 498637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 499637Snate x = inb(port + MSE_PORTA); 500637Snate *but = (x >> 5) & 0x7; 501637Snate x &= 0xf; 502637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 503637Snate x |= (inb(port + MSE_PORTA) << 4); 504637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 505637Snate y = (inb(port + MSE_PORTA) & 0xf); 506637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 507637Snate y |= (inb(port + MSE_PORTA) << 4); 508637Snate *dx += x; 509637Snate *dy += y; 510637Snate outb(port + MSE_PORTC, MSE_INTREN); 511637Snate} 512637Snate 513637Snate/* 514637Snate * Routines for the ATI Inport bus mouse. 515637Snate */ 516637Snate/* 517637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 518637Snate * (do not enable interrupts) 519637Snate */ 520637Snatestatic int 521637Snatemse_probeati(idp) 522637Snate register struct isa_device *idp; 523637Snate{ 524637Snate int i; 525637Snate 526637Snate for (i = 0; i < 2; i++) 527637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 528637Snate return (1); 529637Snate return (0); 530637Snate} 531637Snate 532637Snate/* 533637Snate * Initialize ATI Inport mouse and enable interrupts. 534637Snate */ 535637Snatestatic void 536637Snatemse_enableati(port) 537637Snate register u_int port; 538637Snate{ 539637Snate 540637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 541637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 542637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 543637Snate} 544637Snate 545637Snate/* 546637Snate * Disable interrupts for ATI Inport mouse. 547637Snate */ 548637Snatestatic void 549637Snatemse_disableati(port) 550637Snate register u_int port; 551637Snate{ 552637Snate 553637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 554637Snate outb(port + MSE_PORTB, 0); 555637Snate} 556637Snate 557637Snate/* 558637Snate * Get current dx, dy and up/down button state. 559637Snate */ 560637Snatestatic void 561637Snatemse_getati(port, dx, dy, but) 562637Snate register u_int port; 563637Snate int *dx; 564637Snate int *dy; 565637Snate int *but; 566637Snate{ 567637Snate register char byte; 568637Snate 569637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 570637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 571637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 572637Snate *but = ~(inb(port + MSE_PORTB) & 0x7); 573637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 574637Snate byte = inb(port + MSE_PORTB); 575637Snate *dx += byte; 576637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 577637Snate byte = inb(port + MSE_PORTB); 578637Snate *dy += byte; 579637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 580637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 581637Snate} 58212502Sjulian 58312502Sjulianstatic mse_devsw_installed = 0; 58412502Sjulian 58512517Sjulianstatic void mse_drvinit(void *unused) 58612502Sjulian{ 58712517Sjulian dev_t dev; 58812517Sjulian 58912502Sjulian if( ! mse_devsw_installed ) { 59012675Sjulian dev = makedev(CDEV_MAJOR, 0); 59112675Sjulian cdevsw_add(&dev,&mse_cdevsw, NULL); 59212502Sjulian mse_devsw_installed = 1; 59312517Sjulian } 59412502Sjulian} 59512517Sjulian 59612517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 59712517Sjulian 59812517Sjulian 599637Snate#endif /* NMSE */ 600