mse.c revision 12502
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 * 1412502Sjulian * $Id: mse.c,v 1.15 1995/11/04 17:07:37 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> 512056Swollman#include <sys/proc.h> 522056Swollman#include <sys/user.h> 532056Swollman#include <sys/buf.h> 542056Swollman#include <sys/kernel.h> 552056Swollman#include <sys/ioctl.h> 562056Swollman#include <sys/uio.h> 573816Swollman#include <sys/devconf.h> 58637Snate 597430Sbde#include <machine/clock.h> 607430Sbde 612056Swollman#include <i386/isa/isa_device.h> 622056Swollman#include <i386/isa/icu.h> 63637Snate 6412502Sjulian#ifdef JREMOD 6512502Sjulian#include <sys/conf.h> 6612502Sjulian#define CDEV_MAJOR 27 6712502Sjulianstatic void mse_devsw_install(); 6812502Sjulian#endif /*JREMOD*/ 6912502Sjulian 70798Swollmanstatic int mseprobe(struct isa_device *); 71798Swollmanstatic int mseattach(struct isa_device *); 72637Snate 73637Snatestruct isa_driver msedriver = { 74637Snate mseprobe, mseattach, "mse" 75637Snate}; 76637Snate 77637Snate/* 78637Snate * Software control structure for mouse. The sc_enablemouse(), 79637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 80637Snate */ 81637Snate#define PROTOBYTES 5 82637Snatestruct mse_softc { 83637Snate int sc_flags; 84637Snate int sc_mousetype; 851549Srgrimes struct selinfo sc_selp; 86637Snate u_int sc_port; 87637Snate void (*sc_enablemouse)(); 88637Snate void (*sc_disablemouse)(); 89637Snate void (*sc_getmouse)(); 90637Snate int sc_deltax; 91637Snate int sc_deltay; 92637Snate int sc_obuttons; 93637Snate int sc_buttons; 94637Snate int sc_bytesread; 95637Snate u_char sc_bytes[PROTOBYTES]; 96637Snate} mse_sc[NMSE]; 97637Snate 98637Snate/* Flags */ 99637Snate#define MSESC_OPEN 0x1 100637Snate#define MSESC_WANT 0x2 101637Snate 102637Snate/* and Mouse Types */ 103637Snate#define MSE_LOGITECH 0x1 104637Snate#define MSE_ATIINPORT 0x2 1054259Sjkh#define MSE_LOGI_SIG 0xA5 106637Snate 107637Snate#define MSE_PORTA 0 108637Snate#define MSE_PORTB 1 109637Snate#define MSE_PORTC 2 110637Snate#define MSE_PORTD 3 111637Snate 112637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 113637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 114637Snate 115637Snate/* 116637Snate * Logitech bus mouse definitions 117637Snate */ 118637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1194259Sjkh /* The definition for the control port */ 1204259Sjkh /* is as follows: */ 1218876Srgrimes 1224259Sjkh /* D7 = Mode set flag (1 = active) */ 1238876Srgrimes /* D6,D5 = Mode selection (port A) */ 1244259Sjkh /* 00 = Mode 0 = Basic I/O */ 1254259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1264259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1274259Sjkh /* D4 = Port A direction (1 = input)*/ 1284259Sjkh /* D3 = Port C (upper 4 bits) */ 1294259Sjkh /* direction. (1 = input) */ 1304259Sjkh /* D2 = Mode selection (port B & C) */ 1314259Sjkh /* 0 = Mode 0 = Basic I/O */ 1324259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1334259Sjkh /* D1 = Port B direction (1 = input)*/ 1344259Sjkh /* D0 = Port C (lower 4 bits) */ 1354259Sjkh /* direction. (1 = input) */ 1368876Srgrimes 1374259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1384259Sjkh /* Port A is an input port, B is an */ 1394259Sjkh /* output port, C is split with upper */ 1404259Sjkh /* 4 bits being an output port and lower*/ 1414259Sjkh /* 4 bits an input port, and enable the */ 1424259Sjkh /* sucker. */ 1434259Sjkh /* Courtesy Intel 8255 databook. Lars */ 144637Snate#define MSE_HOLD 0x80 145637Snate#define MSE_RXLOW 0x00 146637Snate#define MSE_RXHIGH 0x20 147637Snate#define MSE_RYLOW 0x40 148637Snate#define MSE_RYHIGH 0x60 149637Snate#define MSE_DISINTR 0x10 150637Snate#define MSE_INTREN 0x00 151637Snate 152637Snatestatic int mse_probelogi(); 153637Snatestatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi(); 154637Snate 155637Snate/* 156637Snate * ATI Inport mouse definitions 157637Snate */ 158637Snate#define MSE_INPORT_RESET 0x80 159637Snate#define MSE_INPORT_STATUS 0x00 160637Snate#define MSE_INPORT_DX 0x01 161637Snate#define MSE_INPORT_DY 0x02 162637Snate#define MSE_INPORT_MODE 0x07 163637Snate#define MSE_INPORT_HOLD 0x20 164637Snate#define MSE_INPORT_INTREN 0x09 165637Snate 166637Snatestatic int mse_probeati(); 167637Snatestatic void mse_enableati(), mse_disableati(), mse_getati(); 168637Snate 169637Snate#define MSEPRI (PZERO + 3) 170637Snate 171637Snate/* 172637Snate * Table of mouse types. 173637Snate * Keep the Logitech last, since I haven't figured out how to probe it 174637Snate * properly yet. (Someday I'll have the documentation.) 175637Snate */ 176637Snatestruct mse_types { 177637Snate int m_type; /* Type of bus mouse */ 178637Snate int (*m_probe)(); /* Probe routine to test for it */ 179637Snate void (*m_enable)(); /* Start routine */ 180637Snate void (*m_disable)(); /* Disable interrupts routine */ 181637Snate void (*m_get)(); /* and get mouse status */ 182637Snate} mse_types[] = { 183637Snate { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 184637Snate { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 185637Snate { 0, }, 186637Snate}; 187637Snate 1887780Swollmanstatic struct kern_devconf kdc_mse[NMSE] = { { 1897780Swollman 0, 0, 0, /* filled in by dev_attach */ 1907780Swollman "mse", 0, { MDDT_ISA, 0, "tty" }, 1917780Swollman isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 1927780Swollman &kdc_isa0, /* parent */ 1937780Swollman 0, /* parentdata */ 1947780Swollman DC_UNCONFIGURED, /* state */ 1957780Swollman "ATI or Logitech bus mouse adapter", 1967780Swollman DC_CLS_MISC /* class */ 1977780Swollman} }; 1987780Swollman 1997780Swollmanstatic inline void 2007780Swollmanmse_registerdev(struct isa_device *id) 2017780Swollman{ 2027780Swollman if(id->id_unit) 2037780Swollman kdc_mse[id->id_unit] = kdc_mse[0]; 2047780Swollman kdc_mse[id->id_unit].kdc_unit = id->id_unit; 2057780Swollman kdc_mse[id->id_unit].kdc_isa = id; 2067780Swollman dev_attach(&kdc_mse[id->id_unit]); 2077780Swollman} 2087780Swollman 209798Swollmanint 210637Snatemseprobe(idp) 211637Snate register struct isa_device *idp; 212637Snate{ 213637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 214637Snate register int i; 215637Snate 2167780Swollman mse_registerdev(idp); 217637Snate /* 218637Snate * Check for each mouse type in the table. 219637Snate */ 220637Snate i = 0; 221637Snate while (mse_types[i].m_type) { 222637Snate if ((*mse_types[i].m_probe)(idp)) { 223637Snate sc->sc_mousetype = mse_types[i].m_type; 224637Snate sc->sc_enablemouse = mse_types[i].m_enable; 225637Snate sc->sc_disablemouse = mse_types[i].m_disable; 226637Snate sc->sc_getmouse = mse_types[i].m_get; 227637Snate return (1); 228637Snate } 229637Snate i++; 230637Snate } 231637Snate return (0); 232637Snate} 233637Snate 234798Swollmanint 235637Snatemseattach(idp) 236637Snate struct isa_device *idp; 237637Snate{ 238637Snate struct mse_softc *sc = &mse_sc[idp->id_unit]; 239637Snate 240637Snate sc->sc_port = idp->id_iobase; 2417780Swollman kdc_mse[idp->id_unit].kdc_state = DC_IDLE; 24212502Sjulian#ifdef JREMOD 24312502Sjulian mse_devsw_install(); 24412502Sjulian#endif /*JREMOD*/ 245637Snate return (1); 246637Snate} 247637Snate 248637Snate/* 249637Snate * Exclusive open the mouse, initialize it and enable interrupts. 250637Snate */ 251798Swollmanint 25210624Sbdemseopen(dev, flags, fmt, p) 253637Snate dev_t dev; 25410624Sbde int flags; 25510624Sbde int fmt; 25610624Sbde struct proc *p; 257637Snate{ 258637Snate register struct mse_softc *sc; 259637Snate int s; 260637Snate 261637Snate if (MSE_UNIT(dev) >= NMSE) 262637Snate return (ENXIO); 263637Snate sc = &mse_sc[MSE_UNIT(dev)]; 264637Snate if (sc->sc_flags & MSESC_OPEN) 265637Snate return (EBUSY); 266637Snate sc->sc_flags |= MSESC_OPEN; 2677780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY; 268637Snate sc->sc_obuttons = sc->sc_buttons = 0x7; 269637Snate sc->sc_deltax = sc->sc_deltay = 0; 270637Snate sc->sc_bytesread = PROTOBYTES; 271637Snate 272637Snate /* 273637Snate * Initialize mouse interface and enable interrupts. 274637Snate */ 275637Snate s = spltty(); 276637Snate (*sc->sc_enablemouse)(sc->sc_port); 277637Snate splx(s); 278637Snate return (0); 279637Snate} 280637Snate 281637Snate/* 282637Snate * mseclose: just turn off mouse innterrupts. 283637Snate */ 284798Swollmanint 28510624Sbdemseclose(dev, flags, fmt, p) 286798Swollman dev_t dev; 28710624Sbde int flags; 28810624Sbde int fmt; 28910624Sbde struct proc *p; 290637Snate{ 291637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 292637Snate int s; 293637Snate 294637Snate s = spltty(); 295637Snate (*sc->sc_disablemouse)(sc->sc_port); 296637Snate sc->sc_flags &= ~MSESC_OPEN; 2977780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE; 298637Snate splx(s); 299637Snate return(0); 300637Snate} 301637Snate 3028876Srgrimes/* 303637Snate * mseread: return mouse info using the MSC serial protocol, but without 304637Snate * using bytes 4 and 5. 305637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 306637Snate */ 307798Swollmanint 30810624Sbdemseread(dev, uio, ioflag) 309637Snate dev_t dev; 310637Snate struct uio *uio; 31110624Sbde int ioflag; 312637Snate{ 313637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 314637Snate int xfer, s, error; 315637Snate 316637Snate /* 317637Snate * If there are no protocol bytes to be read, set up a new protocol 318637Snate * packet. 319637Snate */ 320637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 321637Snate if (sc->sc_bytesread >= PROTOBYTES) { 322637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 323637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 324637Snate if (MSE_NBLOCKIO(dev)) { 325637Snate splx(s); 326637Snate return (0); 327637Snate } 328637Snate sc->sc_flags |= MSESC_WANT; 329637Snate if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 330637Snate "mseread", 0)) { 331637Snate splx(s); 332637Snate return (error); 333637Snate } 334637Snate } 335637Snate 336637Snate /* 337637Snate * Generate protocol bytes. 338637Snate * For some reason X386 expects 5 bytes but never uses 339637Snate * the fourth or fifth? 340637Snate */ 341637Snate sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 342637Snate if (sc->sc_deltax > 127) 343637Snate sc->sc_deltax = 127; 344637Snate if (sc->sc_deltax < -127) 345637Snate sc->sc_deltax = -127; 346637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 347637Snate if (sc->sc_deltay > 127) 348637Snate sc->sc_deltay = 127; 349637Snate if (sc->sc_deltay < -127) 350637Snate sc->sc_deltay = -127; 351637Snate sc->sc_bytes[1] = sc->sc_deltax; 352637Snate sc->sc_bytes[2] = sc->sc_deltay; 353637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 354637Snate sc->sc_obuttons = sc->sc_buttons; 355637Snate sc->sc_deltax = sc->sc_deltay = 0; 356637Snate sc->sc_bytesread = 0; 357637Snate } 358637Snate splx(s); 3591567Srgrimes xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 360637Snate if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 361637Snate return (error); 362637Snate sc->sc_bytesread += xfer; 363637Snate return(0); 364637Snate} 365637Snate 366637Snate/* 367637Snate * mseselect: check for mouse input to be processed. 368637Snate */ 369798Swollmanint 370637Snatemseselect(dev, rw, p) 371637Snate dev_t dev; 372637Snate int rw; 373637Snate struct proc *p; 374637Snate{ 375637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 376637Snate int s; 377637Snate 378637Snate s = spltty(); 379637Snate if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 380637Snate sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 381637Snate splx(s); 382637Snate return (1); 383637Snate } 384637Snate 385637Snate /* 386637Snate * Since this is an exclusive open device, any previous proc. 387637Snate * pointer is trash now, so we can just assign it. 388637Snate */ 3891549Srgrimes selrecord(p, &sc->sc_selp); 390637Snate splx(s); 391637Snate return (0); 392637Snate} 393637Snate 394637Snate/* 395637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 396637Snate */ 397798Swollmanvoid 398637Snatemseintr(unit) 399637Snate int unit; 400637Snate{ 401637Snate register struct mse_softc *sc = &mse_sc[unit]; 402637Snate pid_t p; 403637Snate 404637Snate#ifdef DEBUG 405637Snate static int mse_intrcnt = 0; 406637Snate if((mse_intrcnt++ % 10000) == 0) 407637Snate printf("mseintr\n"); 408637Snate#endif /* DEBUG */ 409637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 410637Snate return; 411637Snate 412637Snate (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 413637Snate 414637Snate /* 415637Snate * If mouse state has changed, wake up anyone wanting to know. 416637Snate */ 417637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 418637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 4198876Srgrimes if (sc->sc_flags & MSESC_WANT) { 4208876Srgrimes sc->sc_flags &= ~MSESC_WANT; 4218876Srgrimes wakeup((caddr_t)sc); 4228876Srgrimes } 4231549Srgrimes selwakeup(&sc->sc_selp); 424637Snate } 425637Snate} 426637Snate 427637Snate/* 428637Snate * Routines for the Logitech mouse. 429637Snate */ 430637Snate/* 431637Snate * Test for a Logitech bus mouse and return 1 if it is. 432637Snate * (until I know how to use the signature port properly, just disable 433637Snate * interrupts and return 1) 434637Snate */ 435637Snatestatic int 436637Snatemse_probelogi(idp) 437637Snate register struct isa_device *idp; 438637Snate{ 439637Snate 4404259Sjkh int sig; 4414259Sjkh 4424259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 4434259Sjkh /* set the signature port */ 4444259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 4454259Sjkh 4464259Sjkh DELAY(30000); /* 30 ms delay */ 4474259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 4484259Sjkh if (sig == MSE_LOGI_SIG) { 4494259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 4504259Sjkh return(1); 4514259Sjkh } else { 4528876Srgrimes printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 4534259Sjkh return(0); 454637Snate } 455637Snate} 456637Snate 457637Snate/* 458637Snate * Initialize Logitech mouse and enable interrupts. 459637Snate */ 460637Snatestatic void 461637Snatemse_enablelogi(port) 462637Snate register u_int port; 463637Snate{ 464637Snate int dx, dy, but; 465637Snate 466637Snate outb(port + MSE_PORTD, MSE_SETUP); 467637Snate mse_getlogi(port, &dx, &dy, &but); 468637Snate} 469637Snate 470637Snate/* 471637Snate * Disable interrupts for Logitech mouse. 472637Snate */ 473637Snatestatic void 474637Snatemse_disablelogi(port) 475637Snate register u_int port; 476637Snate{ 477637Snate 478637Snate outb(port + MSE_PORTC, MSE_DISINTR); 479637Snate} 480637Snate 481637Snate/* 482637Snate * Get the current dx, dy and button up/down state. 483637Snate */ 484637Snatestatic void 485637Snatemse_getlogi(port, dx, dy, but) 486637Snate register u_int port; 487637Snate int *dx; 488637Snate int *dy; 489637Snate int *but; 490637Snate{ 491637Snate register char x, y; 492637Snate 493637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 494637Snate x = inb(port + MSE_PORTA); 495637Snate *but = (x >> 5) & 0x7; 496637Snate x &= 0xf; 497637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 498637Snate x |= (inb(port + MSE_PORTA) << 4); 499637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 500637Snate y = (inb(port + MSE_PORTA) & 0xf); 501637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 502637Snate y |= (inb(port + MSE_PORTA) << 4); 503637Snate *dx += x; 504637Snate *dy += y; 505637Snate outb(port + MSE_PORTC, MSE_INTREN); 506637Snate} 507637Snate 508637Snate/* 509637Snate * Routines for the ATI Inport bus mouse. 510637Snate */ 511637Snate/* 512637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 513637Snate * (do not enable interrupts) 514637Snate */ 515637Snatestatic int 516637Snatemse_probeati(idp) 517637Snate register struct isa_device *idp; 518637Snate{ 519637Snate int i; 520637Snate 521637Snate for (i = 0; i < 2; i++) 522637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 523637Snate return (1); 524637Snate return (0); 525637Snate} 526637Snate 527637Snate/* 528637Snate * Initialize ATI Inport mouse and enable interrupts. 529637Snate */ 530637Snatestatic void 531637Snatemse_enableati(port) 532637Snate register u_int port; 533637Snate{ 534637Snate 535637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 536637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 537637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 538637Snate} 539637Snate 540637Snate/* 541637Snate * Disable interrupts for ATI Inport mouse. 542637Snate */ 543637Snatestatic void 544637Snatemse_disableati(port) 545637Snate register u_int port; 546637Snate{ 547637Snate 548637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 549637Snate outb(port + MSE_PORTB, 0); 550637Snate} 551637Snate 552637Snate/* 553637Snate * Get current dx, dy and up/down button state. 554637Snate */ 555637Snatestatic void 556637Snatemse_getati(port, dx, dy, but) 557637Snate register u_int port; 558637Snate int *dx; 559637Snate int *dy; 560637Snate int *but; 561637Snate{ 562637Snate register char byte; 563637Snate 564637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 565637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 566637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 567637Snate *but = ~(inb(port + MSE_PORTB) & 0x7); 568637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 569637Snate byte = inb(port + MSE_PORTB); 570637Snate *dx += byte; 571637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 572637Snate byte = inb(port + MSE_PORTB); 573637Snate *dy += byte; 574637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 575637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 576637Snate} 57712502Sjulian 57812502Sjulian#ifdef JREMOD 57912502Sjulianstruct cdevsw mse_cdevsw = 58012502Sjulian { mseopen, mseclose, mseread, nowrite, /*27*/ 58112502Sjulian noioc, nostop, nullreset, nodevtotty,/* mse */ 58212502Sjulian mseselect, nommap, NULL }; 58312502Sjulian 58412502Sjulianstatic mse_devsw_installed = 0; 58512502Sjulian 58612502Sjulianstatic void mse_devsw_install() 58712502Sjulian{ 58812502Sjulian dev_t descript; 58912502Sjulian if( ! mse_devsw_installed ) { 59012502Sjulian descript = makedev(CDEV_MAJOR,0); 59112502Sjulian cdevsw_add(&descript,&mse_cdevsw,NULL); 59212502Sjulian#if defined(BDEV_MAJOR) 59312502Sjulian descript = makedev(BDEV_MAJOR,0); 59412502Sjulian bdevsw_add(&descript,&mse_bdevsw,NULL); 59512502Sjulian#endif /*BDEV_MAJOR*/ 59612502Sjulian mse_devsw_installed = 1; 59712502Sjulian } 59812502Sjulian} 59912502Sjulian#endif /* JREMOD */ 600637Snate#endif /* NMSE */ 601