mse.c revision 12658
1168404Spjd/* 2168404Spjd * Copyright 1992 by the University of Guelph 3168404Spjd * 4168404Spjd * Permission to use, copy and modify this 5168404Spjd * software and its documentation for any purpose and without 6168404Spjd * fee is hereby granted, provided that the above copyright 7168404Spjd * notice appear in all copies and that both that copyright 8168404Spjd * notice and this permission notice appear in supporting 9168404Spjd * documentation. 10168404Spjd * University of Guelph makes no representations about the suitability of 11168404Spjd * this software for any purpose. It is provided "as is" 12168404Spjd * without express or implied warranty. 13168404Spjd * 14168404Spjd * $Id: mse.c,v 1.18 1995/11/29 14:39:47 julian Exp $ 15168404Spjd */ 16168404Spjd/* 17168404Spjd * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 18168404Spjd * the X386 port, courtesy of 19168404Spjd * Rick Macklem, rick@snowhite.cis.uoguelph.ca 20168404Spjd * Caveats: The driver currently uses spltty(), but doesn't use any 21168404Spjd * generic tty code. It could use splmse() (that only masks off the 22168404Spjd * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 23168404Spjd * (This may be worth the effort, since the Logitech generates 30/60 24236155Smm * interrupts/sec continuously while it is open.) 25236155Smm * NB: The ATI has NOT been tested yet! 26168404Spjd */ 27168404Spjd 28168404Spjd/* 29168404Spjd * Modification history: 30168404Spjd * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 31168404Spjd * improved probe based on input from Logitech. 32169303Spjd * 33168404Spjd * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 34205346Spjd * fixes to make it work with Microsoft InPort busmouse 35168404Spjd * 36168404Spjd * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 37168404Spjd * added patches for new "select" interface 38168404Spjd * 39169303Spjd * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 40168404Spjd * changed position of some spl()'s in mseread 41168404Spjd * 42168404Spjd * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 43168404Spjd * limit maximum negative x/y value to -127 to work around XFree problem 44168404Spjd * that causes spurious button pushes. 45256956Ssmh */ 46168404Spjd 47168404Spjd#include "mse.h" 48168404Spjd#if NMSE > 0 49256956Ssmh#include <sys/param.h> 50168404Spjd#include <sys/systm.h> 51168404Spjd#include <sys/conf.h> 52168404Spjd#include <sys/proc.h> 53168404Spjd#include <sys/buf.h> 54240868Spjd#include <sys/kernel.h> 55240868Spjd#include <sys/ioctl.h> 56267992Shselasky#include <sys/uio.h> 57267992Shselasky#include <sys/devconf.h> 58219089Spjd 59240868Spjd#include <machine/clock.h> 60267992Shselasky 61267992Shselasky#include <i386/isa/isa_device.h> 62240868Spjd#include <i386/isa/icu.h> 63219089Spjd 64168404Spjd#ifdef JREMOD 65256956Ssmh#include <sys/conf.h> 66256956Ssmh#include <sys/kernel.h> 67256956Ssmh#ifdef DEVFS 68256956Ssmh#include <sys/devfsext.h> 69256956Ssmh#endif /*DEVFS*/ 70256956Ssmh#define CDEV_MAJOR 27 71256956Ssmh#endif /*JREMOD*/ 72256956Ssmh 73256956Ssmhstatic int mseprobe(struct isa_device *); 74256956Ssmhstatic int mseattach(struct isa_device *); 75256956Ssmh 76256956Ssmhstruct isa_driver msedriver = { 77256956Ssmh mseprobe, mseattach, "mse" 78256956Ssmh}; 79256956Ssmh 80256956Ssmh/* 81256956Ssmh * Software control structure for mouse. The sc_enablemouse(), 82256956Ssmh * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 83256956Ssmh */ 84256956Ssmh#define PROTOBYTES 5 85256956Ssmhstruct mse_softc { 86256956Ssmh int sc_flags; 87256956Ssmh int sc_mousetype; 88256956Ssmh struct selinfo sc_selp; 89256956Ssmh u_int sc_port; 90256956Ssmh void (*sc_enablemouse)(); 91256956Ssmh void (*sc_disablemouse)(); 92256956Ssmh void (*sc_getmouse)(); 93168404Spjd int sc_deltax; 94168404Spjd int sc_deltay; 95168404Spjd int sc_obuttons; 96168404Spjd int sc_buttons; 97168404Spjd int sc_bytesread; 98168404Spjd u_char sc_bytes[PROTOBYTES]; 99168404Spjd} mse_sc[NMSE]; 100253754Smav 101253754Smav/* Flags */ 102168404Spjd#define MSESC_OPEN 0x1 103219089Spjd#define MSESC_WANT 0x2 104219089Spjd 105219089Spjd/* and Mouse Types */ 106219089Spjd#define MSE_LOGITECH 0x1 107219089Spjd#define MSE_ATIINPORT 0x2 108219089Spjd#define MSE_LOGI_SIG 0xA5 109219089Spjd 110219089Spjd#define MSE_PORTA 0 111219089Spjd#define MSE_PORTB 1 112219089Spjd#define MSE_PORTC 2 113219089Spjd#define MSE_PORTD 3 114219089Spjd 115219089Spjd#define MSE_UNIT(dev) (minor(dev) >> 1) 116219089Spjd#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 117219089Spjd 118185029Spjd/* 119185029Spjd * Logitech bus mouse definitions 120168404Spjd */ 121168404Spjd#define MSE_SETUP 0x91 /* What does this mean? */ 122168404Spjd /* The definition for the control port */ 123203504Spjd /* is as follows: */ 124168404Spjd 125168404Spjd /* D7 = Mode set flag (1 = active) */ 126168404Spjd /* D6,D5 = Mode selection (port A) */ 127168404Spjd /* 00 = Mode 0 = Basic I/O */ 128168404Spjd /* 01 = Mode 1 = Strobed I/O */ 129168404Spjd /* 10 = Mode 2 = Bi-dir bus */ 130168404Spjd /* D4 = Port A direction (1 = input)*/ 131168404Spjd /* D3 = Port C (upper 4 bits) */ 132168404Spjd /* direction. (1 = input) */ 133169303Spjd /* D2 = Mode selection (port B & C) */ 134169303Spjd /* 0 = Mode 0 = Basic I/O */ 135169303Spjd /* 1 = Mode 1 = Strobed I/O */ 136169303Spjd /* D1 = Port B direction (1 = input)*/ 137169303Spjd /* D0 = Port C (lower 4 bits) */ 138168404Spjd /* direction. (1 = input) */ 139168404Spjd 140168404Spjd /* So 91 means Basic I/O on all 3 ports,*/ 141168404Spjd /* Port A is an input port, B is an */ 142168404Spjd /* output port, C is split with upper */ 143168404Spjd /* 4 bits being an output port and lower*/ 144168404Spjd /* 4 bits an input port, and enable the */ 145168404Spjd /* sucker. */ 146168404Spjd /* Courtesy Intel 8255 databook. Lars */ 147203504Spjd#define MSE_HOLD 0x80 148168404Spjd#define MSE_RXLOW 0x00 149168404Spjd#define MSE_RXHIGH 0x20 150168404Spjd#define MSE_RYLOW 0x40 151168404Spjd#define MSE_RYHIGH 0x60 152168404Spjd#define MSE_DISINTR 0x10 153168404Spjd#define MSE_INTREN 0x00 154168404Spjd 155168404Spjdstatic int mse_probelogi(); 156168404Spjdstatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi(); 157168404Spjd 158168404Spjd/* 159168404Spjd * ATI Inport mouse definitions 160168404Spjd */ 161168404Spjd#define MSE_INPORT_RESET 0x80 162168404Spjd#define MSE_INPORT_STATUS 0x00 163168404Spjd#define MSE_INPORT_DX 0x01 164168404Spjd#define MSE_INPORT_DY 0x02 165168404Spjd#define MSE_INPORT_MODE 0x07 166203504Spjd#define MSE_INPORT_HOLD 0x20 167168404Spjd#define MSE_INPORT_INTREN 0x09 168168404Spjd 169168404Spjdstatic int mse_probeati(); 170168404Spjdstatic void mse_enableati(), mse_disableati(), mse_getati(); 171168404Spjd 172168404Spjd#define MSEPRI (PZERO + 3) 173203504Spjd 174168404Spjd/* 175168404Spjd * Table of mouse types. 176168404Spjd * Keep the Logitech last, since I haven't figured out how to probe it 177168404Spjd * properly yet. (Someday I'll have the documentation.) 178256880Smav */ 179168404Spjdstruct mse_types { 180168404Spjd int m_type; /* Type of bus mouse */ 181168404Spjd int (*m_probe)(); /* Probe routine to test for it */ 182168404Spjd void (*m_enable)(); /* Start routine */ 183168404Spjd void (*m_disable)(); /* Disable interrupts routine */ 184168404Spjd void (*m_get)(); /* and get mouse status */ 185168404Spjd} mse_types[] = { 186168404Spjd { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 187168404Spjd { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 188168404Spjd { 0, }, 189168404Spjd}; 190168404Spjd 191168404Spjdstatic struct kern_devconf kdc_mse[NMSE] = { { 192168404Spjd 0, 0, 0, /* filled in by dev_attach */ 193168404Spjd "mse", 0, { MDDT_ISA, 0, "tty" }, 194168404Spjd isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 195168404Spjd &kdc_isa0, /* parent */ 196168404Spjd 0, /* parentdata */ 197168404Spjd DC_UNCONFIGURED, /* state */ 198168404Spjd "ATI or Logitech bus mouse adapter", 199168404Spjd DC_CLS_MISC /* class */ 200168404Spjd} }; 201168404Spjd 202168404Spjdstatic inline void 203168404Spjdmse_registerdev(struct isa_device *id) 204168404Spjd{ 205168404Spjd if(id->id_unit) 206168404Spjd kdc_mse[id->id_unit] = kdc_mse[0]; 207168404Spjd kdc_mse[id->id_unit].kdc_unit = id->id_unit; 208168404Spjd kdc_mse[id->id_unit].kdc_isa = id; 209185029Spjd dev_attach(&kdc_mse[id->id_unit]); 210185029Spjd} 211185029Spjd 212185029Spjdint 213185029Spjdmseprobe(idp) 214241286Savg register struct isa_device *idp; 215241286Savg{ 216241286Savg register struct mse_softc *sc = &mse_sc[idp->id_unit]; 217185029Spjd register int i; 218185029Spjd 219185029Spjd mse_registerdev(idp); 220185029Spjd /* 221185029Spjd * Check for each mouse type in the table. 222185029Spjd */ 223185029Spjd i = 0; 224208682Spjd while (mse_types[i].m_type) { 225185029Spjd if ((*mse_types[i].m_probe)(idp)) { 226185029Spjd sc->sc_mousetype = mse_types[i].m_type; 227185029Spjd sc->sc_enablemouse = mse_types[i].m_enable; 228185029Spjd sc->sc_disablemouse = mse_types[i].m_disable; 229185029Spjd sc->sc_getmouse = mse_types[i].m_get; 230185029Spjd return (1); 231185029Spjd } 232185029Spjd i++; 233185029Spjd } 234208682Spjd return (0); 235185029Spjd} 236185029Spjd 237208682Spjdint 238185029Spjdmseattach(idp) 239185029Spjd struct isa_device *idp; 240185029Spjd{ 241185029Spjd struct mse_softc *sc = &mse_sc[idp->id_unit]; 242208682Spjd 243185029Spjd sc->sc_port = idp->id_iobase; 244185029Spjd kdc_mse[idp->id_unit].kdc_state = DC_IDLE; 245185029Spjd return (1); 246185029Spjd} 247185029Spjd 248185029Spjd/* 249185029Spjd * Exclusive open the mouse, initialize it and enable interrupts. 250185029Spjd */ 251185029Spjdint 252185029Spjdmseopen(dev, flags, fmt, p) 253185029Spjd dev_t dev; 254241286Savg int flags; 255241286Savg int fmt; 256185029Spjd struct proc *p; 257241286Savg{ 258241286Savg register struct mse_softc *sc; 259241286Savg int s; 260241286Savg 261241286Savg if (MSE_UNIT(dev) >= NMSE) 262241286Savg return (ENXIO); 263241286Savg sc = &mse_sc[MSE_UNIT(dev)]; 264241286Savg if (sc->sc_flags & MSESC_OPEN) 265185029Spjd return (EBUSY); 266185029Spjd sc->sc_flags |= MSESC_OPEN; 267185029Spjd kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY; 268185029Spjd sc->sc_obuttons = sc->sc_buttons = 0x7; 269185029Spjd sc->sc_deltax = sc->sc_deltay = 0; 270185029Spjd sc->sc_bytesread = PROTOBYTES; 271241286Savg 272219089Spjd /* 273185029Spjd * Initialize mouse interface and enable interrupts. 274185029Spjd */ 275185029Spjd s = spltty(); 276185029Spjd (*sc->sc_enablemouse)(sc->sc_port); 277241286Savg splx(s); 278185029Spjd return (0); 279185029Spjd} 280185029Spjd 281185029Spjd/* 282185029Spjd * mseclose: just turn off mouse innterrupts. 283185029Spjd */ 284185029Spjdint 285185174Spjdmseclose(dev, flags, fmt, p) 286185029Spjd dev_t dev; 287185029Spjd int flags; 288185029Spjd int fmt; 289241286Savg struct proc *p; 290185174Spjd{ 291185029Spjd struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 292185029Spjd int s; 293185029Spjd 294185029Spjd s = spltty(); 295185029Spjd (*sc->sc_disablemouse)(sc->sc_port); 296200124Spjd sc->sc_flags &= ~MSESC_OPEN; 297185029Spjd kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE; 298185029Spjd splx(s); 299185029Spjd return(0); 300241286Savg} 301185029Spjd 302185029Spjd/* 303241286Savg * mseread: return mouse info using the MSC serial protocol, but without 304252056Ssmh * using bytes 4 and 5. 305241286Savg * (Yes this is cheesy, but it makes the X386 server happy, so...) 306241286Savg */ 307241286Savgint 308241286Savgmseread(dev, uio, ioflag) 309241286Savg dev_t dev; 310242135Savg struct uio *uio; 311242135Savg int ioflag; 312242135Savg{ 313241286Savg register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 314241286Savg int xfer, s, error; 315241286Savg 316241286Savg /* 317241286Savg * If there are no protocol bytes to be read, set up a new protocol 318241286Savg * packet. 319185029Spjd */ 320185029Spjd s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 321185029Spjd if (sc->sc_bytesread >= PROTOBYTES) { 322241286Savg while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 323185029Spjd (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 324185029Spjd if (MSE_NBLOCKIO(dev)) { 325243502Savg splx(s); 326243502Savg return (0); 327241286Savg } 328243502Savg sc->sc_flags |= MSESC_WANT; 329243502Savg if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 330243502Savg "mseread", 0)) { 331243502Savg splx(s); 332243502Savg return (error); 333244635Savg } 334244635Savg } 335243502Savg 336243502Savg /* 337243502Savg * Generate protocol bytes. 338243502Savg * For some reason X386 expects 5 bytes but never uses 339243502Savg * the fourth or fifth? 340243502Savg */ 341243502Savg sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 342243502Savg if (sc->sc_deltax > 127) 343243502Savg sc->sc_deltax = 127; 344243502Savg if (sc->sc_deltax < -127) 345243502Savg sc->sc_deltax = -127; 346243502Savg sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 347243502Savg if (sc->sc_deltay > 127) 348243502Savg sc->sc_deltay = 127; 349243502Savg if (sc->sc_deltay < -127) 350243502Savg sc->sc_deltay = -127; 351241286Savg sc->sc_bytes[1] = sc->sc_deltax; 352243502Savg sc->sc_bytes[2] = sc->sc_deltay; 353241286Savg sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 354243502Savg sc->sc_obuttons = sc->sc_buttons; 355241286Savg sc->sc_deltax = sc->sc_deltay = 0; 356243502Savg sc->sc_bytesread = 0; 357241286Savg } 358243502Savg splx(s); 359243502Savg xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 360241286Savg if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 361243502Savg return (error); 362243502Savg sc->sc_bytesread += xfer; 363241286Savg return(0); 364243502Savg} 365243502Savg 366243502Savg/* 367243502Savg * mseselect: check for mouse input to be processed. 368243502Savg */ 369243502Savgint 370243502Savgmseselect(dev, rw, p) 371243502Savg dev_t dev; 372243502Savg int rw; 373243502Savg struct proc *p; 374243502Savg{ 375243502Savg register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 376243502Savg int s; 377243502Savg 378243502Savg s = spltty(); 379243502Savg if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 380243502Savg sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 381243502Savg splx(s); 382243502Savg return (1); 383243502Savg } 384243502Savg 385243502Savg /* 386243502Savg * Since this is an exclusive open device, any previous proc. 387243502Savg * pointer is trash now, so we can just assign it. 388243502Savg */ 389243502Savg selrecord(p, &sc->sc_selp); 390243502Savg splx(s); 391243502Savg return (0); 392243502Savg} 393241286Savg 394241286Savg/* 395241286Savg * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 396241286Savg */ 397241286Savgvoid 398241286Savgmseintr(unit) 399241286Savg int unit; 400241286Savg{ 401241286Savg register struct mse_softc *sc = &mse_sc[unit]; 402241286Savg pid_t p; 403241286Savg 404259168Smav#ifdef DEBUG 405259168Smav static int mse_intrcnt = 0; 406259168Smav if((mse_intrcnt++ % 10000) == 0) 407259168Smav printf("mseintr\n"); 408259168Smav#endif /* DEBUG */ 409259168Smav if ((sc->sc_flags & MSESC_OPEN) == 0) 410259168Smav return; 411259168Smav 412241286Savg (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 413241286Savg 414241286Savg /* 415241286Savg * If mouse state has changed, wake up anyone wanting to know. 416241286Savg */ 417169303Spjd if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 418242332Sdelphij (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 419169303Spjd if (sc->sc_flags & MSESC_WANT) { 420241286Savg sc->sc_flags &= ~MSESC_WANT; 421241286Savg wakeup((caddr_t)sc); 422241286Savg } 423169303Spjd selwakeup(&sc->sc_selp); 424241286Savg } 425243502Savg} 426243502Savg 427241286Savg/* 428241286Savg * Routines for the Logitech mouse. 429241286Savg */ 430241286Savg/* 431241286Savg * Test for a Logitech bus mouse and return 1 if it is. 432241286Savg * (until I know how to use the signature port properly, just disable 433243502Savg * interrupts and return 1) 434241286Savg */ 435241286Savgstatic int 436241286Savgmse_probelogi(idp) 437241286Savg register struct isa_device *idp; 438241286Savg{ 439241286Savg 440241286Savg int sig; 441241286Savg 442241286Savg outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 443241286Savg /* set the signature port */ 444243502Savg outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 445243502Savg 446243502Savg DELAY(30000); /* 30 ms delay */ 447241286Savg sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 448241286Savg if (sig == MSE_LOGI_SIG) { 449241286Savg outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 450241286Savg return(1); 451241286Savg } else { 452241286Savg printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 453241286Savg return(0); 454241286Savg } 455241286Savg} 456241286Savg 457241286Savg/* 458241286Savg * Initialize Logitech mouse and enable interrupts. 459241286Savg */ 460241286Savgstatic void 461242332Sdelphijmse_enablelogi(port) 462241286Savg register u_int port; 463241286Savg{ 464241286Savg int dx, dy, but; 465241286Savg 466243502Savg outb(port + MSE_PORTD, MSE_SETUP); 467243502Savg mse_getlogi(port, &dx, &dy, &but); 468241286Savg} 469241286Savg 470241286Savg/* 471241286Savg * Disable interrupts for Logitech mouse. 472241286Savg */ 473241286Savgstatic void 474241286Savgmse_disablelogi(port) 475241286Savg register u_int port; 476243502Savg{ 477243502Savg 478169303Spjd outb(port + MSE_PORTC, MSE_DISINTR); 479169303Spjd} 480241286Savg 481241286Savg/* 482241286Savg * Get the current dx, dy and button up/down state. 483241286Savg */ 484241286Savgstatic void 485241286Savgmse_getlogi(port, dx, dy, but) 486241286Savg register u_int port; 487241286Savg int *dx; 488241286Savg int *dy; 489241286Savg int *but; 490241286Savg{ 491241286Savg register char x, y; 492241286Savg 493241286Savg outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 494241286Savg x = inb(port + MSE_PORTA); 495241286Savg *but = (x >> 5) & 0x7; 496219089Spjd x &= 0xf; 497219089Spjd outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 498169303Spjd x |= (inb(port + MSE_PORTA) << 4); 499169303Spjd outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 500169303Spjd y = (inb(port + MSE_PORTA) & 0xf); 501169303Spjd outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 502219089Spjd y |= (inb(port + MSE_PORTA) << 4); 503219089Spjd *dx += x; 504169303Spjd *dy += y; 505169303Spjd outb(port + MSE_PORTC, MSE_INTREN); 506169303Spjd} 507169303Spjd 508169303Spjd/* 509169303Spjd * Routines for the ATI Inport bus mouse. 510169303Spjd */ 511169303Spjd/* 512219089Spjd * Test for a ATI Inport bus mouse and return 1 if it is. 513169303Spjd * (do not enable interrupts) 514169303Spjd */ 515169303Spjdstatic int 516169303Spjdmse_probeati(idp) 517169303Spjd register struct isa_device *idp; 518169303Spjd{ 519169303Spjd int i; 520241286Savg 521169303Spjd for (i = 0; i < 2; i++) 522169303Spjd if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 523219089Spjd return (1); 524169303Spjd return (0); 525242332Sdelphij} 526219089Spjd 527169303Spjd/* 528219089Spjd * Initialize ATI Inport mouse and enable interrupts. 529219089Spjd */ 530207934Spjdstatic void 531203504Spjdmse_enableati(port) 532169303Spjd register u_int port; 533169303Spjd{ 534219089Spjd 535169303Spjd outb(port + MSE_PORTA, MSE_INPORT_RESET); 536219089Spjd outb(port + MSE_PORTA, MSE_INPORT_MODE); 537219089Spjd outb(port + MSE_PORTB, MSE_INPORT_INTREN); 538169303Spjd} 539219089Spjd 540219089Spjd/* 541169303Spjd * Disable interrupts for ATI Inport mouse. 542169303Spjd */ 543169303Spjdstatic void 544169303Spjdmse_disableati(port) 545169303Spjd register u_int port; 546169303Spjd{ 547169303Spjd 548185029Spjd outb(port + MSE_PORTA, MSE_INPORT_MODE); 549185174Spjd outb(port + MSE_PORTB, 0); 550168404Spjd} 551185174Spjd 552185174Spjd/* 553185174Spjd * Get current dx, dy and up/down button state. 554185174Spjd */ 555219089Spjdstatic void 556219089Spjdmse_getati(port, dx, dy, but) 557185174Spjd register u_int port; 558203504Spjd int *dx; 559185174Spjd int *dy; 560185174Spjd int *but; 561185174Spjd{ 562197842Spjd register char byte; 563185174Spjd 564185174Spjd outb(port + MSE_PORTA, MSE_INPORT_MODE); 565185174Spjd outb(port + MSE_PORTB, MSE_INPORT_HOLD); 566185174Spjd outb(port + MSE_PORTA, MSE_INPORT_STATUS); 567185174Spjd *but = ~(inb(port + MSE_PORTB) & 0x7); 568185174Spjd outb(port + MSE_PORTA, MSE_INPORT_DX); 569185174Spjd byte = inb(port + MSE_PORTB); 570185174Spjd *dx += byte; 571185174Spjd outb(port + MSE_PORTA, MSE_INPORT_DY); 572185174Spjd byte = inb(port + MSE_PORTB); 573185174Spjd *dy += byte; 574185174Spjd outb(port + MSE_PORTA, MSE_INPORT_MODE); 575185174Spjd outb(port + MSE_PORTB, MSE_INPORT_INTREN); 576185174Spjd} 577185174Spjd 578200158Spjd#ifdef JREMOD 579185174Spjdstruct cdevsw mse_cdevsw = 580168404Spjd { mseopen, mseclose, mseread, nowrite, /*27*/ 581168404Spjd noioc, nostop, nullreset, nodevtotty,/* mse */ 582185174Spjd mseselect, nommap, NULL }; 583168404Spjd 584219089Spjdstatic mse_devsw_installed = 0; 585219089Spjd 586169303Spjdstatic void mse_drvinit(void *unused) 587168404Spjd{ 588169303Spjd dev_t dev; 589169303Spjd 590203504Spjd if( ! mse_devsw_installed ) { 591218278Sae dev = makedev(CDEV_MAJOR,0); 592218278Sae cdevsw_add(&dev,&mse_cdevsw,NULL); 593169303Spjd mse_devsw_installed = 1; 594185174Spjd#ifdef DEVFS 595169303Spjd { 596185174Spjd int x; 597169303Spjd/* default for a simple device with no probe routine (usually delete this) */ 598169303Spjd x=devfs_add_devsw( 599185174Spjd/* path name devsw minor type uid gid perm*/ 600185174Spjd "/", "mse", major(dev), 0, DV_CHR, 0, 0, 0600); 601185174Spjd } 602185174Spjd#endif 603185174Spjd } 604185029Spjd} 605185174Spjd 606169303SpjdSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 607168404Spjd 608169303Spjd#endif /* JREMOD */ 609185029Spjd 610185029Spjd#endif /* NMSE */ 611169303Spjd