mse.c revision 14873
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 * 1414873Sscrappy * $Id: mse.c,v 1.24 1995/12/15 00:54:25 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/buf.h> 542056Swollman#include <sys/kernel.h> 552056Swollman#include <sys/ioctl.h> 562056Swollman#include <sys/uio.h> 573816Swollman#include <sys/devconf.h> 5812675Sjulian#ifdef DEVFS 5912675Sjulian#include <sys/devfsext.h> 6012675Sjulian#endif /*DEVFS*/ 61637Snate 627430Sbde#include <machine/clock.h> 637430Sbde 642056Swollman#include <i386/isa/isa_device.h> 652056Swollman#include <i386/isa/icu.h> 66637Snate 6712502Sjulian 68798Swollmanstatic int mseprobe(struct isa_device *); 69798Swollmanstatic int mseattach(struct isa_device *); 70637Snate 71637Snatestruct isa_driver msedriver = { 72637Snate mseprobe, mseattach, "mse" 73637Snate}; 74637Snate 7512675Sjulianstatic d_open_t mseopen; 7612675Sjulianstatic d_close_t mseclose; 7712675Sjulianstatic d_read_t mseread; 7812675Sjulianstatic d_select_t mseselect; 7912675Sjulian 8012675Sjulian#define CDEV_MAJOR 27 8112678Sphkstatic struct cdevsw mse_cdevsw = 8212675Sjulian { mseopen, mseclose, mseread, nowrite, /*27*/ 8312675Sjulian noioc, nostop, nullreset, nodevtotty,/* mse */ 8412675Sjulian mseselect, nommap, NULL, "mse", NULL, -1 }; 8512675Sjulian 8612675Sjulian 87637Snate/* 88637Snate * Software control structure for mouse. The sc_enablemouse(), 89637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 90637Snate */ 91637Snate#define PROTOBYTES 5 9212724Sphkstatic struct mse_softc { 93637Snate int sc_flags; 94637Snate int sc_mousetype; 951549Srgrimes struct selinfo sc_selp; 96637Snate u_int sc_port; 9712854Sbde void (*sc_enablemouse) __P((u_int port)); 9812854Sbde void (*sc_disablemouse) __P((u_int port)); 9912854Sbde void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 100637Snate int sc_deltax; 101637Snate int sc_deltay; 102637Snate int sc_obuttons; 103637Snate int sc_buttons; 104637Snate int sc_bytesread; 105637Snate u_char sc_bytes[PROTOBYTES]; 10612675Sjulian#ifdef DEVFS 10712675Sjulian void *devfs_token; 10812675Sjulian void *n_devfs_token; 10912675Sjulian#endif 110637Snate} mse_sc[NMSE]; 111637Snate 112637Snate/* Flags */ 113637Snate#define MSESC_OPEN 0x1 114637Snate#define MSESC_WANT 0x2 115637Snate 116637Snate/* and Mouse Types */ 117637Snate#define MSE_LOGITECH 0x1 118637Snate#define MSE_ATIINPORT 0x2 1194259Sjkh#define MSE_LOGI_SIG 0xA5 120637Snate 121637Snate#define MSE_PORTA 0 122637Snate#define MSE_PORTB 1 123637Snate#define MSE_PORTC 2 124637Snate#define MSE_PORTD 3 125637Snate 126637Snate#define MSE_UNIT(dev) (minor(dev) >> 1) 127637Snate#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 128637Snate 129637Snate/* 130637Snate * Logitech bus mouse definitions 131637Snate */ 132637Snate#define MSE_SETUP 0x91 /* What does this mean? */ 1334259Sjkh /* The definition for the control port */ 1344259Sjkh /* is as follows: */ 1358876Srgrimes 1364259Sjkh /* D7 = Mode set flag (1 = active) */ 1378876Srgrimes /* D6,D5 = Mode selection (port A) */ 1384259Sjkh /* 00 = Mode 0 = Basic I/O */ 1394259Sjkh /* 01 = Mode 1 = Strobed I/O */ 1404259Sjkh /* 10 = Mode 2 = Bi-dir bus */ 1414259Sjkh /* D4 = Port A direction (1 = input)*/ 1424259Sjkh /* D3 = Port C (upper 4 bits) */ 1434259Sjkh /* direction. (1 = input) */ 1444259Sjkh /* D2 = Mode selection (port B & C) */ 1454259Sjkh /* 0 = Mode 0 = Basic I/O */ 1464259Sjkh /* 1 = Mode 1 = Strobed I/O */ 1474259Sjkh /* D1 = Port B direction (1 = input)*/ 1484259Sjkh /* D0 = Port C (lower 4 bits) */ 1494259Sjkh /* direction. (1 = input) */ 1508876Srgrimes 1514259Sjkh /* So 91 means Basic I/O on all 3 ports,*/ 1524259Sjkh /* Port A is an input port, B is an */ 1534259Sjkh /* output port, C is split with upper */ 1544259Sjkh /* 4 bits being an output port and lower*/ 1554259Sjkh /* 4 bits an input port, and enable the */ 1564259Sjkh /* sucker. */ 1574259Sjkh /* Courtesy Intel 8255 databook. Lars */ 158637Snate#define MSE_HOLD 0x80 159637Snate#define MSE_RXLOW 0x00 160637Snate#define MSE_RXHIGH 0x20 161637Snate#define MSE_RYLOW 0x40 162637Snate#define MSE_RYHIGH 0x60 163637Snate#define MSE_DISINTR 0x10 164637Snate#define MSE_INTREN 0x00 165637Snate 16612854Sbdestatic int mse_probelogi __P((struct isa_device *idp)); 16712854Sbdestatic void mse_disablelogi __P((u_int port)); 16812854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 16912854Sbdestatic void mse_enablelogi __P((u_int port)); 170637Snate 171637Snate/* 172637Snate * ATI Inport mouse definitions 173637Snate */ 174637Snate#define MSE_INPORT_RESET 0x80 175637Snate#define MSE_INPORT_STATUS 0x00 176637Snate#define MSE_INPORT_DX 0x01 177637Snate#define MSE_INPORT_DY 0x02 178637Snate#define MSE_INPORT_MODE 0x07 179637Snate#define MSE_INPORT_HOLD 0x20 180637Snate#define MSE_INPORT_INTREN 0x09 181637Snate 18212854Sbdestatic int mse_probeati __P((struct isa_device *idp)); 18312854Sbdestatic void mse_enableati __P((u_int port)); 18412854Sbdestatic void mse_disableati __P((u_int port)); 18512854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 186637Snate 187637Snate#define MSEPRI (PZERO + 3) 188637Snate 189637Snate/* 190637Snate * Table of mouse types. 191637Snate * Keep the Logitech last, since I haven't figured out how to probe it 192637Snate * properly yet. (Someday I'll have the documentation.) 193637Snate */ 19412724Sphkstatic struct mse_types { 195637Snate int m_type; /* Type of bus mouse */ 19612854Sbde int (*m_probe) __P((struct isa_device *idp)); 19712854Sbde /* Probe routine to test for it */ 19812854Sbde void (*m_enable) __P((u_int port)); 19912854Sbde /* Start routine */ 20012854Sbde void (*m_disable) __P((u_int port)); 20112854Sbde /* Disable interrupts routine */ 20212854Sbde void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 20312854Sbde /* and get mouse status */ 204637Snate} mse_types[] = { 205637Snate { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 206637Snate { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 207637Snate { 0, }, 208637Snate}; 209637Snate 2107780Swollmanstatic struct kern_devconf kdc_mse[NMSE] = { { 2117780Swollman 0, 0, 0, /* filled in by dev_attach */ 2127780Swollman "mse", 0, { MDDT_ISA, 0, "tty" }, 2137780Swollman isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 2147780Swollman &kdc_isa0, /* parent */ 2157780Swollman 0, /* parentdata */ 2167780Swollman DC_UNCONFIGURED, /* state */ 2177780Swollman "ATI or Logitech bus mouse adapter", 2187780Swollman DC_CLS_MISC /* class */ 2197780Swollman} }; 2207780Swollman 2217780Swollmanstatic inline void 2227780Swollmanmse_registerdev(struct isa_device *id) 2237780Swollman{ 2247780Swollman if(id->id_unit) 2257780Swollman kdc_mse[id->id_unit] = kdc_mse[0]; 2267780Swollman kdc_mse[id->id_unit].kdc_unit = id->id_unit; 2277780Swollman kdc_mse[id->id_unit].kdc_isa = id; 2287780Swollman dev_attach(&kdc_mse[id->id_unit]); 2297780Swollman} 2307780Swollman 231798Swollmanint 232637Snatemseprobe(idp) 233637Snate register struct isa_device *idp; 234637Snate{ 235637Snate register struct mse_softc *sc = &mse_sc[idp->id_unit]; 236637Snate register int i; 237637Snate 2387780Swollman mse_registerdev(idp); 239637Snate /* 240637Snate * Check for each mouse type in the table. 241637Snate */ 242637Snate i = 0; 243637Snate while (mse_types[i].m_type) { 244637Snate if ((*mse_types[i].m_probe)(idp)) { 245637Snate sc->sc_mousetype = mse_types[i].m_type; 246637Snate sc->sc_enablemouse = mse_types[i].m_enable; 247637Snate sc->sc_disablemouse = mse_types[i].m_disable; 248637Snate sc->sc_getmouse = mse_types[i].m_get; 249637Snate return (1); 250637Snate } 251637Snate i++; 252637Snate } 253637Snate return (0); 254637Snate} 255637Snate 256798Swollmanint 257637Snatemseattach(idp) 258637Snate struct isa_device *idp; 259637Snate{ 26012675Sjulian int unit = idp->id_unit; 26112675Sjulian struct mse_softc *sc = &mse_sc[unit]; 262637Snate 263637Snate sc->sc_port = idp->id_iobase; 26412675Sjulian kdc_mse[unit].kdc_state = DC_IDLE; 26512675Sjulian#ifdef DEVFS 26614873Sscrappy sc->devfs_token = 26714873Sscrappy devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 26814873Sscrappy 0600, "mse%d", unit); 26914873Sscrappy sc->n_devfs_token = 27014873Sscrappy devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 27114873Sscrappy 0600, "nmse%d", unit); 27212675Sjulian#endif 273637Snate return (1); 274637Snate} 275637Snate 276637Snate/* 277637Snate * Exclusive open the mouse, initialize it and enable interrupts. 278637Snate */ 27912675Sjulianstatic int 28010624Sbdemseopen(dev, flags, fmt, p) 281637Snate dev_t dev; 28210624Sbde int flags; 28310624Sbde int fmt; 28410624Sbde struct proc *p; 285637Snate{ 286637Snate register struct mse_softc *sc; 287637Snate int s; 288637Snate 289637Snate if (MSE_UNIT(dev) >= NMSE) 290637Snate return (ENXIO); 291637Snate sc = &mse_sc[MSE_UNIT(dev)]; 292637Snate if (sc->sc_flags & MSESC_OPEN) 293637Snate return (EBUSY); 294637Snate sc->sc_flags |= MSESC_OPEN; 2957780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY; 296637Snate sc->sc_obuttons = sc->sc_buttons = 0x7; 297637Snate sc->sc_deltax = sc->sc_deltay = 0; 298637Snate sc->sc_bytesread = PROTOBYTES; 299637Snate 300637Snate /* 301637Snate * Initialize mouse interface and enable interrupts. 302637Snate */ 303637Snate s = spltty(); 304637Snate (*sc->sc_enablemouse)(sc->sc_port); 305637Snate splx(s); 306637Snate return (0); 307637Snate} 308637Snate 309637Snate/* 310637Snate * mseclose: just turn off mouse innterrupts. 311637Snate */ 31212675Sjulianstatic int 31310624Sbdemseclose(dev, flags, fmt, p) 314798Swollman dev_t dev; 31510624Sbde int flags; 31610624Sbde int fmt; 31710624Sbde struct proc *p; 318637Snate{ 319637Snate struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 320637Snate int s; 321637Snate 322637Snate s = spltty(); 323637Snate (*sc->sc_disablemouse)(sc->sc_port); 324637Snate sc->sc_flags &= ~MSESC_OPEN; 3257780Swollman kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE; 326637Snate splx(s); 327637Snate return(0); 328637Snate} 329637Snate 3308876Srgrimes/* 331637Snate * mseread: return mouse info using the MSC serial protocol, but without 332637Snate * using bytes 4 and 5. 333637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...) 334637Snate */ 33512675Sjulianstatic int 33610624Sbdemseread(dev, uio, ioflag) 337637Snate dev_t dev; 338637Snate struct uio *uio; 33910624Sbde int ioflag; 340637Snate{ 341637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 342637Snate int xfer, s, error; 343637Snate 344637Snate /* 345637Snate * If there are no protocol bytes to be read, set up a new protocol 346637Snate * packet. 347637Snate */ 348637Snate s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 349637Snate if (sc->sc_bytesread >= PROTOBYTES) { 350637Snate while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 351637Snate (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 352637Snate if (MSE_NBLOCKIO(dev)) { 353637Snate splx(s); 354637Snate return (0); 355637Snate } 356637Snate sc->sc_flags |= MSESC_WANT; 357637Snate if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 358637Snate "mseread", 0)) { 359637Snate splx(s); 360637Snate return (error); 361637Snate } 362637Snate } 363637Snate 364637Snate /* 365637Snate * Generate protocol bytes. 366637Snate * For some reason X386 expects 5 bytes but never uses 367637Snate * the fourth or fifth? 368637Snate */ 369637Snate sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 370637Snate if (sc->sc_deltax > 127) 371637Snate sc->sc_deltax = 127; 372637Snate if (sc->sc_deltax < -127) 373637Snate sc->sc_deltax = -127; 374637Snate sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 375637Snate if (sc->sc_deltay > 127) 376637Snate sc->sc_deltay = 127; 377637Snate if (sc->sc_deltay < -127) 378637Snate sc->sc_deltay = -127; 379637Snate sc->sc_bytes[1] = sc->sc_deltax; 380637Snate sc->sc_bytes[2] = sc->sc_deltay; 381637Snate sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 382637Snate sc->sc_obuttons = sc->sc_buttons; 383637Snate sc->sc_deltax = sc->sc_deltay = 0; 384637Snate sc->sc_bytesread = 0; 385637Snate } 386637Snate splx(s); 3871567Srgrimes xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 388637Snate if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 389637Snate return (error); 390637Snate sc->sc_bytesread += xfer; 391637Snate return(0); 392637Snate} 393637Snate 394637Snate/* 395637Snate * mseselect: check for mouse input to be processed. 396637Snate */ 39712675Sjulianstatic int 398637Snatemseselect(dev, rw, p) 399637Snate dev_t dev; 400637Snate int rw; 401637Snate struct proc *p; 402637Snate{ 403637Snate register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 404637Snate int s; 405637Snate 406637Snate s = spltty(); 407637Snate if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 408637Snate sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 409637Snate splx(s); 410637Snate return (1); 411637Snate } 412637Snate 413637Snate /* 414637Snate * Since this is an exclusive open device, any previous proc. 415637Snate * pointer is trash now, so we can just assign it. 416637Snate */ 4171549Srgrimes selrecord(p, &sc->sc_selp); 418637Snate splx(s); 419637Snate return (0); 420637Snate} 421637Snate 422637Snate/* 423637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 424637Snate */ 425798Swollmanvoid 426637Snatemseintr(unit) 427637Snate int unit; 428637Snate{ 429637Snate register struct mse_softc *sc = &mse_sc[unit]; 430637Snate 431637Snate#ifdef DEBUG 432637Snate static int mse_intrcnt = 0; 433637Snate if((mse_intrcnt++ % 10000) == 0) 434637Snate printf("mseintr\n"); 435637Snate#endif /* DEBUG */ 436637Snate if ((sc->sc_flags & MSESC_OPEN) == 0) 437637Snate return; 438637Snate 439637Snate (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 440637Snate 441637Snate /* 442637Snate * If mouse state has changed, wake up anyone wanting to know. 443637Snate */ 444637Snate if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 445637Snate (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 4468876Srgrimes if (sc->sc_flags & MSESC_WANT) { 4478876Srgrimes sc->sc_flags &= ~MSESC_WANT; 4488876Srgrimes wakeup((caddr_t)sc); 4498876Srgrimes } 4501549Srgrimes selwakeup(&sc->sc_selp); 451637Snate } 452637Snate} 453637Snate 454637Snate/* 455637Snate * Routines for the Logitech mouse. 456637Snate */ 457637Snate/* 458637Snate * Test for a Logitech bus mouse and return 1 if it is. 459637Snate * (until I know how to use the signature port properly, just disable 460637Snate * interrupts and return 1) 461637Snate */ 462637Snatestatic int 463637Snatemse_probelogi(idp) 464637Snate register struct isa_device *idp; 465637Snate{ 466637Snate 4674259Sjkh int sig; 4684259Sjkh 4694259Sjkh outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 4704259Sjkh /* set the signature port */ 4714259Sjkh outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 4724259Sjkh 4734259Sjkh DELAY(30000); /* 30 ms delay */ 4744259Sjkh sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 4754259Sjkh if (sig == MSE_LOGI_SIG) { 4764259Sjkh outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 4774259Sjkh return(1); 4784259Sjkh } else { 4798876Srgrimes printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 4804259Sjkh return(0); 481637Snate } 482637Snate} 483637Snate 484637Snate/* 485637Snate * Initialize Logitech mouse and enable interrupts. 486637Snate */ 487637Snatestatic void 488637Snatemse_enablelogi(port) 489637Snate register u_int port; 490637Snate{ 491637Snate int dx, dy, but; 492637Snate 493637Snate outb(port + MSE_PORTD, MSE_SETUP); 494637Snate mse_getlogi(port, &dx, &dy, &but); 495637Snate} 496637Snate 497637Snate/* 498637Snate * Disable interrupts for Logitech mouse. 499637Snate */ 500637Snatestatic void 501637Snatemse_disablelogi(port) 502637Snate register u_int port; 503637Snate{ 504637Snate 505637Snate outb(port + MSE_PORTC, MSE_DISINTR); 506637Snate} 507637Snate 508637Snate/* 509637Snate * Get the current dx, dy and button up/down state. 510637Snate */ 511637Snatestatic void 512637Snatemse_getlogi(port, dx, dy, but) 513637Snate register u_int port; 514637Snate int *dx; 515637Snate int *dy; 516637Snate int *but; 517637Snate{ 518637Snate register char x, y; 519637Snate 520637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 521637Snate x = inb(port + MSE_PORTA); 522637Snate *but = (x >> 5) & 0x7; 523637Snate x &= 0xf; 524637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 525637Snate x |= (inb(port + MSE_PORTA) << 4); 526637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 527637Snate y = (inb(port + MSE_PORTA) & 0xf); 528637Snate outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 529637Snate y |= (inb(port + MSE_PORTA) << 4); 530637Snate *dx += x; 531637Snate *dy += y; 532637Snate outb(port + MSE_PORTC, MSE_INTREN); 533637Snate} 534637Snate 535637Snate/* 536637Snate * Routines for the ATI Inport bus mouse. 537637Snate */ 538637Snate/* 539637Snate * Test for a ATI Inport bus mouse and return 1 if it is. 540637Snate * (do not enable interrupts) 541637Snate */ 542637Snatestatic int 543637Snatemse_probeati(idp) 544637Snate register struct isa_device *idp; 545637Snate{ 546637Snate int i; 547637Snate 548637Snate for (i = 0; i < 2; i++) 549637Snate if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 550637Snate return (1); 551637Snate return (0); 552637Snate} 553637Snate 554637Snate/* 555637Snate * Initialize ATI Inport mouse and enable interrupts. 556637Snate */ 557637Snatestatic void 558637Snatemse_enableati(port) 559637Snate register u_int port; 560637Snate{ 561637Snate 562637Snate outb(port + MSE_PORTA, MSE_INPORT_RESET); 563637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 564637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 565637Snate} 566637Snate 567637Snate/* 568637Snate * Disable interrupts for ATI Inport mouse. 569637Snate */ 570637Snatestatic void 571637Snatemse_disableati(port) 572637Snate register u_int port; 573637Snate{ 574637Snate 575637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 576637Snate outb(port + MSE_PORTB, 0); 577637Snate} 578637Snate 579637Snate/* 580637Snate * Get current dx, dy and up/down button state. 581637Snate */ 582637Snatestatic void 583637Snatemse_getati(port, dx, dy, but) 584637Snate register u_int port; 585637Snate int *dx; 586637Snate int *dy; 587637Snate int *but; 588637Snate{ 589637Snate register char byte; 590637Snate 591637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 592637Snate outb(port + MSE_PORTB, MSE_INPORT_HOLD); 593637Snate outb(port + MSE_PORTA, MSE_INPORT_STATUS); 594637Snate *but = ~(inb(port + MSE_PORTB) & 0x7); 595637Snate outb(port + MSE_PORTA, MSE_INPORT_DX); 596637Snate byte = inb(port + MSE_PORTB); 597637Snate *dx += byte; 598637Snate outb(port + MSE_PORTA, MSE_INPORT_DY); 599637Snate byte = inb(port + MSE_PORTB); 600637Snate *dy += byte; 601637Snate outb(port + MSE_PORTA, MSE_INPORT_MODE); 602637Snate outb(port + MSE_PORTB, MSE_INPORT_INTREN); 603637Snate} 60412502Sjulian 60512502Sjulianstatic mse_devsw_installed = 0; 60612502Sjulian 60712517Sjulianstatic void mse_drvinit(void *unused) 60812502Sjulian{ 60912517Sjulian dev_t dev; 61012517Sjulian 61112502Sjulian if( ! mse_devsw_installed ) { 61212675Sjulian dev = makedev(CDEV_MAJOR, 0); 61312675Sjulian cdevsw_add(&dev,&mse_cdevsw, NULL); 61412502Sjulian mse_devsw_installed = 1; 61512517Sjulian } 61612502Sjulian} 61712517Sjulian 61812517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 61912517Sjulian 62012517Sjulian 621637Snate#endif /* NMSE */ 622