mse.c revision 12724
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 * 1412724Sphk * $Id: mse.c,v 1.21 1995/12/08 23:20:35 phk 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/buf.h> 542056Swollman#include <sys/kernel.h> 552056Swollman#include <sys/ioctl.h> 562056Swollman#include <sys/uio.h> 573816Swollman#include <sys/devconf.h> 5812675Sjulian#include <sys/conf.h> 5912675Sjulian#ifdef DEVFS 6012675Sjulian#include <sys/devfsext.h> 6112675Sjulian#endif /*DEVFS*/ 62637Snate 637430Sbde#include <machine/clock.h> 647430Sbde 652056Swollman#include <i386/isa/isa_device.h> 662056Swollman#include <i386/isa/icu.h> 67637Snate 6812502Sjulian 69798Swollmanstatic int mseprobe(struct isa_device *); 70798Swollmanstatic int mseattach(struct isa_device *); 71637Snate 72637Snatestruct isa_driver msedriver = { 73637Snate mseprobe, mseattach, "mse" 74637Snate}; 75637Snate 7612675Sjulianstatic d_open_t mseopen; 7712675Sjulianstatic d_close_t mseclose; 7812675Sjulianstatic d_read_t mseread; 7912675Sjulianstatic d_select_t mseselect; 8012675Sjulian 8112675Sjulian#define CDEV_MAJOR 27 8212678Sphkstatic struct cdevsw mse_cdevsw = 8312675Sjulian { mseopen, mseclose, mseread, nowrite, /*27*/ 8412675Sjulian noioc, nostop, nullreset, nodevtotty,/* mse */ 8512675Sjulian mseselect, nommap, NULL, "mse", NULL, -1 }; 8612675Sjulian 8712675Sjulian 88637Snate/* 89637Snate * Software control structure for mouse. The sc_enablemouse(), 90637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 91637Snate */ 92637Snate#define PROTOBYTES 5 9312724Sphkstatic struct mse_softc { 94637Snate int sc_flags; 95637Snate int sc_mousetype; 961549Srgrimes struct selinfo sc_selp; 97637Snate u_int sc_port; 98637Snate void (*sc_enablemouse)(); 99637Snate void (*sc_disablemouse)(); 100637Snate void (*sc_getmouse)(); 101637Snate int sc_deltax; 102637Snate int sc_deltay; 103637Snate int sc_obuttons; 104637Snate int sc_buttons; 105637Snate int sc_bytesread; 106637Snate u_char sc_bytes[PROTOBYTES]; 10712675Sjulian#ifdef DEVFS 10812675Sjulian void *devfs_token; 10912675Sjulian void *n_devfs_token; 11012675Sjulian#endif 111637Snate} mse_sc[NMSE]; 112637Snate 113637Snate/* Flags */ 114637Snate#define MSESC_OPEN 0x1 115637Snate#define MSESC_WANT 0x2 116637Snate 117637Snate/* and Mouse Types */ 118637Snate#define MSE_LOGITECH 0x1 119637Snate#define MSE_ATIINPORT 0x2 1204259Sjkh#define MSE_LOGI_SIG 0xA5 121637Snate 122637Snate#define MSE_PORTA 0 123637Snate#define MSE_PORTB 1 124637Snate#define MSE_PORTC 2 125637Snate#define MSE_PORTD 3 126637Snate 127637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 128637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 129637Snate 130637Snate/* 131637Snate * Logitech bus mouse definitions 132637Snate */ 133637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1344259Sjkh /* The definition for the control port */ 1354259Sjkh /* is as follows: */ 1368876Srgrimes 1374259Sjkh /* D7 = Mode set flag (1 = active) */ 1388876Srgrimes /* D6,D5 = Mode selection (port A) */ 1394259Sjkh /* 00 = Mode 0 = Basic I/O */ 1404259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1414259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1424259Sjkh /* D4 = Port A direction (1 = input)*/ 1434259Sjkh /* D3 = Port C (upper 4 bits) */ 1444259Sjkh /* direction. (1 = input) */ 1454259Sjkh /* D2 = Mode selection (port B & C) */ 1464259Sjkh /* 0 = Mode 0 = Basic I/O */ 1474259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1484259Sjkh /* D1 = Port B direction (1 = input)*/ 1494259Sjkh /* D0 = Port C (lower 4 bits) */ 1504259Sjkh /* direction. (1 = input) */ 1518876Srgrimes 1524259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1534259Sjkh /* Port A is an input port, B is an */ 1544259Sjkh /* output port, C is split with upper */ 1554259Sjkh /* 4 bits being an output port and lower*/ 1564259Sjkh /* 4 bits an input port, and enable the */ 1574259Sjkh /* sucker. */ 1584259Sjkh /* Courtesy Intel 8255 databook. Lars */ 159637Snate#define MSE_HOLD 0x80 160637Snate#define MSE_RXLOW 0x00 161637Snate#define MSE_RXHIGH 0x20 162637Snate#define MSE_RYLOW 0x40 163637Snate#define MSE_RYHIGH 0x60 164637Snate#define MSE_DISINTR 0x10 165637Snate#define MSE_INTREN 0x00 166637Snate 167637Snatestatic int mse_probelogi(); 168637Snatestatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi(); 169637Snate 170637Snate/* 171637Snate * ATI Inport mouse definitions 172637Snate */ 173637Snate#define MSE_INPORT_RESET 0x80 174637Snate#define MSE_INPORT_STATUS 0x00 175637Snate#define MSE_INPORT_DX 0x01 176637Snate#define MSE_INPORT_DY 0x02 177637Snate#define MSE_INPORT_MODE 0x07 178637Snate#define MSE_INPORT_HOLD 0x20 179637Snate#define MSE_INPORT_INTREN 0x09 180637Snate 181637Snatestatic int mse_probeati(); 182637Snatestatic void mse_enableati(), mse_disableati(), mse_getati(); 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 */ 193637Snate int (*m_probe)(); /* Probe routine to test for it */ 194637Snate void (*m_enable)(); /* Start routine */ 195637Snate void (*m_disable)(); /* Disable interrupts routine */ 196637Snate void (*m_get)(); /* and get mouse status */ 197637Snate} mse_types[] = { 198637Snate { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 199637Snate { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 200637Snate { 0, }, 201637Snate}; 202637Snate 2037780Swollmanstatic struct kern_devconf kdc_mse[NMSE] = { { 2047780Swollman 0, 0, 0, /* filled in by dev_attach */ 2057780Swollman "mse", 0, { MDDT_ISA, 0, "tty" }, 2067780Swollman isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 2077780Swollman &kdc_isa0, /* parent */ 2087780Swollman 0, /* parentdata */ 2097780Swollman DC_UNCONFIGURED, /* state */ 2107780Swollman "ATI or Logitech bus mouse adapter", 2117780Swollman DC_CLS_MISC /* class */ 2127780Swollman} }; 2137780Swollman 2147780Swollmanstatic inline void 2157780Swollmanmse_registerdev(struct isa_device *id) 2167780Swollman{ 2177780Swollman if(id->id_unit) 2187780Swollman kdc_mse[id->id_unit] = kdc_mse[0]; 2197780Swollman kdc_mse[id->id_unit].kdc_unit = id->id_unit; 2207780Swollman kdc_mse[id->id_unit].kdc_isa = id; 2217780Swollman dev_attach(&kdc_mse[id->id_unit]); 2227780Swollman} 2237780Swollman 224798Swollmanint 225637Snatemseprobe(idp) 226637Snate register struct isa_device *idp; 227637Snate{ 228637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 229637Snate register int i; 230637Snate 2317780Swollman mse_registerdev(idp); 232637Snate /* 233637Snate * Check for each mouse type in the table. 234637Snate */ 235637Snate i = 0; 236637Snate while (mse_types[i].m_type) { 237637Snate if ((*mse_types[i].m_probe)(idp)) { 238637Snate sc->sc_mousetype = mse_types[i].m_type; 239637Snate sc->sc_enablemouse = mse_types[i].m_enable; 240637Snate sc->sc_disablemouse = mse_types[i].m_disable; 241637Snate sc->sc_getmouse = mse_types[i].m_get; 242637Snate return (1); 243637Snate } 244637Snate i++; 245637Snate } 246637Snate return (0); 247637Snate} 248637Snate 249798Swollmanint 250637Snatemseattach(idp) 251637Snate struct isa_device *idp; 252637Snate{ 25312675Sjulian char name[32]; 25412675Sjulian int unit = idp->id_unit; 25512675Sjulian struct mse_softc *sc = &mse_sc[unit]; 256637Snate 257637Snate sc->sc_port = idp->id_iobase; 25812675Sjulian kdc_mse[unit].kdc_state = DC_IDLE; 25912675Sjulian#ifdef DEVFS 26012675Sjulian sprintf(name,"mse%d", unit); 26112675Sjulian /* path name devsw minor */ 26212675Sjulian sc->devfs_token = devfs_add_devsw( "/", name, &mse_cdevsw, unit << 1, 26312675Sjulian /*type uid gid perm*/ 26412675Sjulian DV_CHR, 0, 0, 0600); 26512675Sjulian sprintf(name,"nmse%d", unit); 26612675Sjulian /* path name devsw minor */ 26712675Sjulian sc->n_devfs_token = devfs_add_devsw("/", name, &mse_cdevsw, (unit<<1)+1, 26812675Sjulian /*type uid gid perm*/ 26912675Sjulian DV_CHR, 0, 0, 0600); 27012675Sjulian#endif 271637Snate return (1); 272637Snate} 273637Snate 274637Snate/* 275637Snate * Exclusive open the mouse, initialize it and enable interrupts. 276637Snate */ 27712675Sjulianstatic int 27810624Sbdemseopen(dev, flags, fmt, p) 279637Snate dev_t dev; 28010624Sbde int flags; 28110624Sbde int fmt; 28210624Sbde struct proc *p; 283637Snate{ 284637Snate register struct mse_softc *sc; 285637Snate int s; 286637Snate 287637Snate if (MSE_UNIT(dev) >= NMSE) 288637Snate return (ENXIO); 289637Snate sc = &mse_sc[MSE_UNIT(dev)]; 290637Snate if (sc->sc_flags & MSESC_OPEN) 291637Snate return (EBUSY); 292637Snate sc->sc_flags |= MSESC_OPEN; 2937780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY; 294637Snate sc->sc_obuttons = sc->sc_buttons = 0x7; 295637Snate sc->sc_deltax = sc->sc_deltay = 0; 296637Snate sc->sc_bytesread = PROTOBYTES; 297637Snate 298637Snate /* 299637Snate * Initialize mouse interface and enable interrupts. 300637Snate */ 301637Snate s = spltty(); 302637Snate (*sc->sc_enablemouse)(sc->sc_port); 303637Snate splx(s); 304637Snate return (0); 305637Snate} 306637Snate 307637Snate/* 308637Snate * mseclose: just turn off mouse innterrupts. 309637Snate */ 31012675Sjulianstatic int 31110624Sbdemseclose(dev, flags, fmt, p) 312798Swollman dev_t dev; 31310624Sbde int flags; 31410624Sbde int fmt; 31510624Sbde struct proc *p; 316637Snate{ 317637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 318637Snate int s; 319637Snate 320637Snate s = spltty(); 321637Snate (*sc->sc_disablemouse)(sc->sc_port); 322637Snate sc->sc_flags &= ~MSESC_OPEN; 3237780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE; 324637Snate splx(s); 325637Snate return(0); 326637Snate} 327637Snate 3288876Srgrimes/* 329637Snate * mseread: return mouse info using the MSC serial protocol, but without 330637Snate * using bytes 4 and 5. 331637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 332637Snate */ 33312675Sjulianstatic int 33410624Sbdemseread(dev, uio, ioflag) 335637Snate dev_t dev; 336637Snate struct uio *uio; 33710624Sbde int ioflag; 338637Snate{ 339637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 340637Snate int xfer, s, error; 341637Snate 342637Snate /* 343637Snate * If there are no protocol bytes to be read, set up a new protocol 344637Snate * packet. 345637Snate */ 346637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 347637Snate if (sc->sc_bytesread >= PROTOBYTES) { 348637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 349637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 350637Snate if (MSE_NBLOCKIO(dev)) { 351637Snate splx(s); 352637Snate return (0); 353637Snate } 354637Snate sc->sc_flags |= MSESC_WANT; 355637Snate if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 356637Snate "mseread", 0)) { 357637Snate splx(s); 358637Snate return (error); 359637Snate } 360637Snate } 361637Snate 362637Snate /* 363637Snate * Generate protocol bytes. 364637Snate * For some reason X386 expects 5 bytes but never uses 365637Snate * the fourth or fifth? 366637Snate */ 367637Snate sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 368637Snate if (sc->sc_deltax > 127) 369637Snate sc->sc_deltax = 127; 370637Snate if (sc->sc_deltax < -127) 371637Snate sc->sc_deltax = -127; 372637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 373637Snate if (sc->sc_deltay > 127) 374637Snate sc->sc_deltay = 127; 375637Snate if (sc->sc_deltay < -127) 376637Snate sc->sc_deltay = -127; 377637Snate sc->sc_bytes[1] = sc->sc_deltax; 378637Snate sc->sc_bytes[2] = sc->sc_deltay; 379637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 380637Snate sc->sc_obuttons = sc->sc_buttons; 381637Snate sc->sc_deltax = sc->sc_deltay = 0; 382637Snate sc->sc_bytesread = 0; 383637Snate } 384637Snate splx(s); 3851567Srgrimes xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 386637Snate if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 387637Snate return (error); 388637Snate sc->sc_bytesread += xfer; 389637Snate return(0); 390637Snate} 391637Snate 392637Snate/* 393637Snate * mseselect: check for mouse input to be processed. 394637Snate */ 39512675Sjulianstatic int 396637Snatemseselect(dev, rw, p) 397637Snate dev_t dev; 398637Snate int rw; 399637Snate struct proc *p; 400637Snate{ 401637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 402637Snate int s; 403637Snate 404637Snate s = spltty(); 405637Snate if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 406637Snate sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 407637Snate splx(s); 408637Snate return (1); 409637Snate } 410637Snate 411637Snate /* 412637Snate * Since this is an exclusive open device, any previous proc. 413637Snate * pointer is trash now, so we can just assign it. 414637Snate */ 4151549Srgrimes selrecord(p, &sc->sc_selp); 416637Snate splx(s); 417637Snate return (0); 418637Snate} 419637Snate 420637Snate/* 421637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 422637Snate */ 423798Swollmanvoid 424637Snatemseintr(unit) 425637Snate int unit; 426637Snate{ 427637Snate register struct mse_softc *sc = &mse_sc[unit]; 428637Snate 429637Snate#ifdef DEBUG 430637Snate static int mse_intrcnt = 0; 431637Snate if((mse_intrcnt++ % 10000) == 0) 432637Snate printf("mseintr\n"); 433637Snate#endif /* DEBUG */ 434637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 435637Snate return; 436637Snate 437637Snate (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 438637Snate 439637Snate /* 440637Snate * If mouse state has changed, wake up anyone wanting to know. 441637Snate */ 442637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 443637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 4448876Srgrimes if (sc->sc_flags & MSESC_WANT) { 4458876Srgrimes sc->sc_flags &= ~MSESC_WANT; 4468876Srgrimes wakeup((caddr_t)sc); 4478876Srgrimes } 4481549Srgrimes selwakeup(&sc->sc_selp); 449637Snate } 450637Snate} 451637Snate 452637Snate/* 453637Snate * Routines for the Logitech mouse. 454637Snate */ 455637Snate/* 456637Snate * Test for a Logitech bus mouse and return 1 if it is. 457637Snate * (until I know how to use the signature port properly, just disable 458637Snate * interrupts and return 1) 459637Snate */ 460637Snatestatic int 461637Snatemse_probelogi(idp) 462637Snate register struct isa_device *idp; 463637Snate{ 464637Snate 4654259Sjkh int sig; 4664259Sjkh 4674259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 4684259Sjkh /* set the signature port */ 4694259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 4704259Sjkh 4714259Sjkh DELAY(30000); /* 30 ms delay */ 4724259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 4734259Sjkh if (sig == MSE_LOGI_SIG) { 4744259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 4754259Sjkh return(1); 4764259Sjkh } else { 4778876Srgrimes printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 4784259Sjkh return(0); 479637Snate } 480637Snate} 481637Snate 482637Snate/* 483637Snate * Initialize Logitech mouse and enable interrupts. 484637Snate */ 485637Snatestatic void 486637Snatemse_enablelogi(port) 487637Snate register u_int port; 488637Snate{ 489637Snate int dx, dy, but; 490637Snate 491637Snate outb(port + MSE_PORTD, MSE_SETUP); 492637Snate mse_getlogi(port, &dx, &dy, &but); 493637Snate} 494637Snate 495637Snate/* 496637Snate * Disable interrupts for Logitech mouse. 497637Snate */ 498637Snatestatic void 499637Snatemse_disablelogi(port) 500637Snate register u_int port; 501637Snate{ 502637Snate 503637Snate outb(port + MSE_PORTC, MSE_DISINTR); 504637Snate} 505637Snate 506637Snate/* 507637Snate * Get the current dx, dy and button up/down state. 508637Snate */ 509637Snatestatic void 510637Snatemse_getlogi(port, dx, dy, but) 511637Snate register u_int port; 512637Snate int *dx; 513637Snate int *dy; 514637Snate int *but; 515637Snate{ 516637Snate register char x, y; 517637Snate 518637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 519637Snate x = inb(port + MSE_PORTA); 520637Snate *but = (x >> 5) & 0x7; 521637Snate x &= 0xf; 522637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 523637Snate x |= (inb(port + MSE_PORTA) << 4); 524637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 525637Snate y = (inb(port + MSE_PORTA) & 0xf); 526637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 527637Snate y |= (inb(port + MSE_PORTA) << 4); 528637Snate *dx += x; 529637Snate *dy += y; 530637Snate outb(port + MSE_PORTC, MSE_INTREN); 531637Snate} 532637Snate 533637Snate/* 534637Snate * Routines for the ATI Inport bus mouse. 535637Snate */ 536637Snate/* 537637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 538637Snate * (do not enable interrupts) 539637Snate */ 540637Snatestatic int 541637Snatemse_probeati(idp) 542637Snate register struct isa_device *idp; 543637Snate{ 544637Snate int i; 545637Snate 546637Snate for (i = 0; i < 2; i++) 547637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 548637Snate return (1); 549637Snate return (0); 550637Snate} 551637Snate 552637Snate/* 553637Snate * Initialize ATI Inport mouse and enable interrupts. 554637Snate */ 555637Snatestatic void 556637Snatemse_enableati(port) 557637Snate register u_int port; 558637Snate{ 559637Snate 560637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 561637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 562637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 563637Snate} 564637Snate 565637Snate/* 566637Snate * Disable interrupts for ATI Inport mouse. 567637Snate */ 568637Snatestatic void 569637Snatemse_disableati(port) 570637Snate register u_int port; 571637Snate{ 572637Snate 573637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 574637Snate outb(port + MSE_PORTB, 0); 575637Snate} 576637Snate 577637Snate/* 578637Snate * Get current dx, dy and up/down button state. 579637Snate */ 580637Snatestatic void 581637Snatemse_getati(port, dx, dy, but) 582637Snate register u_int port; 583637Snate int *dx; 584637Snate int *dy; 585637Snate int *but; 586637Snate{ 587637Snate register char byte; 588637Snate 589637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 590637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 591637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 592637Snate *but = ~(inb(port + MSE_PORTB) & 0x7); 593637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 594637Snate byte = inb(port + MSE_PORTB); 595637Snate *dx += byte; 596637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 597637Snate byte = inb(port + MSE_PORTB); 598637Snate *dy += byte; 599637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 600637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 601637Snate} 60212502Sjulian 60312502Sjulianstatic mse_devsw_installed = 0; 60412502Sjulian 60512517Sjulianstatic void mse_drvinit(void *unused) 60612502Sjulian{ 60712517Sjulian dev_t dev; 60812517Sjulian 60912502Sjulian if( ! mse_devsw_installed ) { 61012675Sjulian dev = makedev(CDEV_MAJOR, 0); 61112675Sjulian cdevsw_add(&dev,&mse_cdevsw, NULL); 61212502Sjulian mse_devsw_installed = 1; 61312517Sjulian } 61412502Sjulian} 61512517Sjulian 61612517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 61712517Sjulian 61812517Sjulian 619637Snate#endif /* NMSE */ 620