mse.c revision 31254
177218Sphk/* 277218Sphk * Copyright 1992 by the University of Guelph 377218Sphk * 477218Sphk * Permission to use, copy and modify this 577218Sphk * software and its documentation for any purpose and without 677218Sphk * fee is hereby granted, provided that the above copyright 777218Sphk * notice appear in all copies and that both that copyright 877218Sphk * notice and this permission notice appear in supporting 977218Sphk * documentation. 1077218Sphk * University of Guelph makes no representations about the suitability of 1177218Sphk * this software for any purpose. It is provided "as is" 1291454Sbrooks * without express or implied warranty. 1391454Sbrooks * 1477218Sphk * $Id: mse.c,v 1.34 1997/09/14 03:19:10 peter Exp $ 1577218Sphk */ 1677218Sphk/* 1777218Sphk * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 1877218Sphk * the X386 port, courtesy of 1977218Sphk * Rick Macklem, rick@snowhite.cis.uoguelph.ca 2077218Sphk * Caveats: The driver currently uses spltty(), but doesn't use any 2177218Sphk * generic tty code. It could use splmse() (that only masks off the 2277218Sphk * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 2377218Sphk * (This may be worth the effort, since the Logitech generates 30/60 2477218Sphk * interrupts/sec continuously while it is open.) 2577218Sphk * NB: The ATI has NOT been tested yet! 2677218Sphk */ 2777218Sphk 2877218Sphk/* 2977218Sphk * Modification history: 3077218Sphk * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 3177218Sphk * improved probe based on input from Logitech. 3277218Sphk * 3377218Sphk * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 3477218Sphk * fixes to make it work with Microsoft InPort busmouse 3577218Sphk * 3677218Sphk * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 3777218Sphk * added patches for new "select" interface 3877218Sphk * 3977218Sphk * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 4077218Sphk * changed position of some spl()'s in mseread 4177218Sphk * 4277218Sphk * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 4377218Sphk * limit maximum negative x/y value to -127 to work around XFree problem 4477218Sphk * that causes spurious button pushes. 4577218Sphk */ 4677218Sphk 4777218Sphk#include "mse.h" 4877218Sphk#if NMSE > 0 4977218Sphk#include <sys/param.h> 5077218Sphk#include <sys/systm.h> 5177218Sphk#include <sys/conf.h> 5277218Sphk#include <sys/kernel.h> 5377218Sphk#include <sys/poll.h> 5477218Sphk#include <sys/select.h> 5577218Sphk#include <sys/uio.h> 5677218Sphk#ifdef DEVFS 5777218Sphk#include <sys/devfsext.h> 5877218Sphk#endif /*DEVFS*/ 5977218Sphk 6077218Sphk#include <machine/clock.h> 6177218Sphk 6277218Sphk#include <i386/isa/isa_device.h> 6377218Sphk 6477218Sphkstatic int mseprobe(struct isa_device *); 6577218Sphkstatic int mseattach(struct isa_device *); 6677218Sphk 6777218Sphkstruct isa_driver msedriver = { 6877218Sphk mseprobe, mseattach, "mse" 6977218Sphk}; 7077218Sphk 7177218Sphkstatic d_open_t mseopen; 7277218Sphkstatic d_close_t mseclose; 7377218Sphkstatic d_read_t mseread; 7477218Sphkstatic d_poll_t msepoll; 7577218Sphk 7677218Sphk#define CDEV_MAJOR 27 77138593Ssamstatic struct cdevsw mse_cdevsw = 7877218Sphk { mseopen, mseclose, mseread, nowrite, /*27*/ 79138593Ssam noioc, nostop, nullreset, nodevtotty,/* mse */ 80116957Ssam msepoll, nommap, NULL, "mse", NULL, -1 }; 81120178Ssam 82116957Ssam 8377218Sphk/* 8477218Sphk * Software control structure for mouse. The sc_enablemouse(), 8577218Sphk * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). 8677218Sphk */ 8777218Sphk#define PROTOBYTES 5 88146873Sjhbstatic struct mse_softc { 8977218Sphk int sc_flags; 9077218Sphk int sc_mousetype; 9177218Sphk struct selinfo sc_selp; 9277218Sphk u_int sc_port; 93155931Ssam void (*sc_enablemouse) __P((u_int port)); 9477218Sphk void (*sc_disablemouse) __P((u_int port)); 9577218Sphk void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but)); 9677218Sphk int sc_deltax; 9777218Sphk int sc_deltay; 9877218Sphk int sc_obuttons; 9977218Sphk int sc_buttons; 10077218Sphk int sc_bytesread; 10177218Sphk u_char sc_bytes[PROTOBYTES]; 102138593Ssam#ifdef DEVFS 103138593Ssam void *devfs_token; 104138593Ssam void *n_devfs_token; 105138593Ssam#endif 106138593Ssam} mse_sc[NMSE]; 107138593Ssam 108138593Ssam/* Flags */ 109138593Ssam#define MSESC_OPEN 0x1 11077218Sphk#define MSESC_WANT 0x2 11177218Sphk 11277218Sphk/* and Mouse Types */ 11377218Sphk#define MSE_NONE 0 /* don't move this! */ 114151883Sbrooks#define MSE_LOGITECH 0x1 11577218Sphk#define MSE_ATIINPORT 0x2 11677218Sphk#define MSE_LOGI_SIG 0xA5 117121827Sbrooks 11888748Sambrisko#define MSE_PORTA 0 11988748Sambrisko#define MSE_PORTB 1 12088748Sambrisko#define MSE_PORTC 2 12188748Sambrisko#define MSE_PORTD 3 12277218Sphk 12377218Sphk#define MSE_UNIT(dev) (minor(dev) >> 1) 12477218Sphk#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1) 125151883Sbrooks 126151883Sbrooks/* 12777218Sphk * Logitech bus mouse definitions 12877218Sphk */ 12977218Sphk#define MSE_SETUP 0x91 /* What does this mean? */ 13077218Sphk /* The definition for the control port */ 131138593Ssam /* is as follows: */ 13277218Sphk 13377218Sphk /* D7 = Mode set flag (1 = active) */ 13477218Sphk /* D6,D5 = Mode selection (port A) */ 13577218Sphk /* 00 = Mode 0 = Basic I/O */ 13677218Sphk /* 01 = Mode 1 = Strobed I/O */ 13777218Sphk /* 10 = Mode 2 = Bi-dir bus */ 13877218Sphk /* D4 = Port A direction (1 = input)*/ 13977218Sphk /* D3 = Port C (upper 4 bits) */ 14077218Sphk /* direction. (1 = input) */ 14177218Sphk /* D2 = Mode selection (port B & C) */ 14277218Sphk /* 0 = Mode 0 = Basic I/O */ 14377218Sphk /* 1 = Mode 1 = Strobed I/O */ 144138593Ssam /* D1 = Port B direction (1 = input)*/ 145138593Ssam /* D0 = Port C (lower 4 bits) */ 146138593Ssam /* direction. (1 = input) */ 147138593Ssam 148138593Ssam /* So 91 means Basic I/O on all 3 ports,*/ 149138593Ssam /* Port A is an input port, B is an */ 150138593Ssam /* output port, C is split with upper */ 151138593Ssam /* 4 bits being an output port and lower*/ 152138593Ssam /* 4 bits an input port, and enable the */ 153138593Ssam /* sucker. */ 154138593Ssam /* Courtesy Intel 8255 databook. Lars */ 155138593Ssam#define MSE_HOLD 0x80 156138593Ssam#define MSE_RXLOW 0x00 157138593Ssam#define MSE_RXHIGH 0x20 158138593Ssam#define MSE_RYLOW 0x40 159138593Ssam#define MSE_RYHIGH 0x60 160138593Ssam#define MSE_DISINTR 0x10 161138593Ssam#define MSE_INTREN 0x00 162138593Ssam 163165570Ssamstatic int mse_probelogi __P((struct isa_device *idp)); 164138593Ssamstatic void mse_disablelogi __P((u_int port)); 165138593Ssamstatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but)); 166138593Ssamstatic void mse_enablelogi __P((u_int port)); 167138593Ssam 168138593Ssam/* 169165570Ssam * ATI Inport mouse definitions 170165570Ssam */ 171165570Ssam#define MSE_INPORT_RESET 0x80 172165570Ssam#define MSE_INPORT_STATUS 0x00 173165570Ssam#define MSE_INPORT_DX 0x01 174165570Ssam#define MSE_INPORT_DY 0x02 175165570Ssam#define MSE_INPORT_MODE 0x07 176138593Ssam#define MSE_INPORT_HOLD 0x20 177138593Ssam#define MSE_INPORT_INTREN 0x09 178138593Ssam 179138593Ssamstatic int mse_probeati __P((struct isa_device *idp)); 18077218Sphkstatic void mse_enableati __P((u_int port)); 18177218Sphkstatic void mse_disableati __P((u_int port)); 182138593Ssamstatic void mse_getati __P((u_int port, int *dx, int *dy, int *but)); 183138593Ssam 184138593Ssam#define MSEPRI (PZERO + 3) 185165570Ssam 186138593Ssam/* 187138593Ssam * Table of mouse types. 188116957Ssam * Keep the Logitech last, since I haven't figured out how to probe it 18977218Sphk * properly yet. (Someday I'll have the documentation.) 19077218Sphk */ 191138593Ssamstatic struct mse_types { 19277218Sphk int m_type; /* Type of bus mouse */ 19377218Sphk int (*m_probe) __P((struct isa_device *idp)); 19477218Sphk /* Probe routine to test for it */ 19577218Sphk void (*m_enable) __P((u_int port)); 19691454Sbrooks /* Start routine */ 19777218Sphk void (*m_disable) __P((u_int port)); 19891454Sbrooks /* Disable interrupts routine */ 19977218Sphk void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); 20091454Sbrooks /* and get mouse status */ 20177218Sphk} mse_types[] = { 202138593Ssam { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, 203138593Ssam { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, 204138593Ssam { 0, }, 205138593Ssam}; 20677218Sphk 207150708Sruint 20877218Sphkmseprobe(idp) 20977218Sphk register struct isa_device *idp; 21077218Sphk{ 21177218Sphk register struct mse_softc *sc = &mse_sc[idp->id_unit]; 21277218Sphk register int i; 213138593Ssam 21477218Sphk /* 21577218Sphk * Check for each mouse type in the table. 21677218Sphk */ 21777218Sphk i = 0; 21891454Sbrooks while (mse_types[i].m_type) { 21977218Sphk if ((*mse_types[i].m_probe)(idp)) { 22091454Sbrooks sc->sc_mousetype = mse_types[i].m_type; 22177218Sphk sc->sc_enablemouse = mse_types[i].m_enable; 22291454Sbrooks sc->sc_disablemouse = mse_types[i].m_disable; 22377218Sphk sc->sc_getmouse = mse_types[i].m_get; 22491454Sbrooks return (1); 22577218Sphk } 22691454Sbrooks i++; 22777218Sphk } 22877218Sphk return (0); 229150708Sru} 23077218Sphk 23177218Sphkint 23277218Sphkmseattach(idp) 23377218Sphk struct isa_device *idp; 23477218Sphk{ 235138593Ssam int unit = idp->id_unit; 23677218Sphk struct mse_softc *sc = &mse_sc[unit]; 23777218Sphk 23877218Sphk sc->sc_port = idp->id_iobase; 23977218Sphk#ifdef DEVFS 24077218Sphk sc->devfs_token = 24177218Sphk devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, 24277218Sphk 0600, "mse%d", unit); 24377218Sphk sc->n_devfs_token = 24477218Sphk devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0, 24577218Sphk 0600, "nmse%d", unit); 246138593Ssam#endif 24777218Sphk return (1); 24877218Sphk} 24977218Sphk 25077218Sphk/* 25177218Sphk * Exclusive open the mouse, initialize it and enable interrupts. 252138593Ssam */ 25377218Sphkstatic int 25477218Sphkmseopen(dev, flags, fmt, p) 25577218Sphk dev_t dev; 25677218Sphk int flags; 25791454Sbrooks int fmt; 25877218Sphk struct proc *p; 25991454Sbrooks{ 26077218Sphk register struct mse_softc *sc; 26191454Sbrooks int s; 26277218Sphk 26377218Sphk if (MSE_UNIT(dev) >= NMSE) 264150708Sru return (ENXIO); 26577218Sphk sc = &mse_sc[MSE_UNIT(dev)]; 26677218Sphk if (sc->sc_mousetype == MSE_NONE) 26777218Sphk return (ENXIO); 26877218Sphk if (sc->sc_flags & MSESC_OPEN) 26977218Sphk return (EBUSY); 270138593Ssam sc->sc_flags |= MSESC_OPEN; 27177218Sphk sc->sc_obuttons = sc->sc_buttons = 0x7; 27277218Sphk sc->sc_deltax = sc->sc_deltay = 0; 27377218Sphk sc->sc_bytesread = PROTOBYTES; 27477218Sphk 27577218Sphk /* 276139493Ssam * Initialize mouse interface and enable interrupts. 277139493Ssam */ 278139493Ssam s = spltty(); 279139493Ssam (*sc->sc_enablemouse)(sc->sc_port); 280139493Ssam splx(s); 281139493Ssam return (0); 282138593Ssam} 28377218Sphk 28477218Sphk/* 285139493Ssam * mseclose: just turn off mouse innterrupts. 286139493Ssam */ 287139493Ssamstatic int 288139493Ssammseclose(dev, flags, fmt, p) 28977218Sphk dev_t dev; 29077218Sphk int flags; 291138593Ssam int fmt; 29277218Sphk struct proc *p; 29377218Sphk{ 29477218Sphk struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 29577218Sphk int s; 296120178Ssam 29777218Sphk s = spltty(); 29891454Sbrooks (*sc->sc_disablemouse)(sc->sc_port); 29977218Sphk sc->sc_flags &= ~MSESC_OPEN; 30077218Sphk splx(s); 30177218Sphk return(0); 30277218Sphk} 30377218Sphk 30477218Sphk/* 30577218Sphk * mseread: return mouse info using the MSC serial protocol, but without 30677218Sphk * using bytes 4 and 5. 30777218Sphk * (Yes this is cheesy, but it makes the X386 server happy, so...) 30877218Sphk */ 30977218Sphkstatic int 31077218Sphkmseread(dev, uio, ioflag) 311148686Sstefanf dev_t dev; 312148686Sstefanf struct uio *uio; 31377218Sphk int ioflag; 31477218Sphk{ 315138593Ssam register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 31677218Sphk int xfer, s, error; 31777218Sphk 31877218Sphk /* 31977218Sphk * If there are no protocol bytes to be read, set up a new protocol 320120178Ssam * packet. 32177218Sphk */ 32277218Sphk s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ 32377218Sphk if (sc->sc_bytesread >= PROTOBYTES) { 32491454Sbrooks while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && 32577218Sphk (sc->sc_obuttons ^ sc->sc_buttons) == 0) { 32677218Sphk if (MSE_NBLOCKIO(dev)) { 32777218Sphk splx(s); 32891454Sbrooks return (0); 32977218Sphk } 33077218Sphk sc->sc_flags |= MSESC_WANT; 33177218Sphk if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH, 332151827Sbrooks "mseread", 0)) { 333151827Sbrooks splx(s); 33477218Sphk return (error); 33577218Sphk } 33677218Sphk } 33777218Sphk 33877218Sphk /* 33977218Sphk * Generate protocol bytes. 34077218Sphk * For some reason X386 expects 5 bytes but never uses 34177218Sphk * the fourth or fifth? 34277218Sphk */ 34377218Sphk sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); 34477218Sphk if (sc->sc_deltax > 127) 34577218Sphk sc->sc_deltax = 127; 34691454Sbrooks if (sc->sc_deltax < -127) 34777218Sphk sc->sc_deltax = -127; 34877218Sphk sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */ 34977218Sphk if (sc->sc_deltay > 127) 35077218Sphk sc->sc_deltay = 127; 35177218Sphk if (sc->sc_deltay < -127) 35277218Sphk sc->sc_deltay = -127; 353138593Ssam sc->sc_bytes[1] = sc->sc_deltax; 354127649Ssam sc->sc_bytes[2] = sc->sc_deltay; 355127649Ssam sc->sc_bytes[3] = sc->sc_bytes[4] = 0; 356148416Ssam sc->sc_obuttons = sc->sc_buttons; 357148416Ssam sc->sc_deltax = sc->sc_deltay = 0; 358127649Ssam sc->sc_bytesread = 0; 359127649Ssam } 360138593Ssam splx(s); 361127649Ssam xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); 362127649Ssam if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) 363127649Ssam return (error); 364127649Ssam sc->sc_bytesread += xfer; 365127649Ssam return(0); 366127649Ssam} 367127649Ssam 368127649Ssam/* 369127649Ssam * msepoll: check for mouse input to be processed. 370127649Ssam */ 371127649Ssamstatic int 372150708Srumsepoll(dev, events, p) 373127649Ssam dev_t dev; 374127649Ssam int events; 375127649Ssam struct proc *p; 376127649Ssam{ 377127649Ssam register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; 378138593Ssam int s; 379127649Ssam int revents = 0; 380127649Ssam 381127649Ssam s = spltty(); 382127649Ssam if (events & (POLLIN | POLLRDNORM)) 383127649Ssam if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || 384138593Ssam sc->sc_deltay != 0 || 385138593Ssam (sc->sc_obuttons ^ sc->sc_buttons) != 0) 386138593Ssam revents |= events & (POLLIN | POLLRDNORM); 387138593Ssam else { 388138593Ssam /* 389138593Ssam * Since this is an exclusive open device, any previous 39077218Sphk * proc pointer is trash now, so we can just assign it. 391138593Ssam */ 39277218Sphk selrecord(p, &sc->sc_selp); 393138593Ssam } 394138593Ssam 395138593Ssam splx(s); 396138593Ssam return (revents); 397138593Ssam} 398138593Ssam 399138593Ssam/* 400150708Sru * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. 401138593Ssam */ 402138593Ssamvoid 403138593Ssammseintr(unit) 404138593Ssam int unit; 405138593Ssam{ 406138593Ssam register struct mse_softc *sc = &mse_sc[unit]; 407138593Ssam 408138593Ssam#ifdef DEBUG 409138593Ssam static int mse_intrcnt = 0; 410138593Ssam if((mse_intrcnt++ % 10000) == 0) 411138593Ssam printf("mseintr\n"); 412138593Ssam#endif /* DEBUG */ 413138593Ssam if ((sc->sc_flags & MSESC_OPEN) == 0) 414138593Ssam return; 415138593Ssam 416138593Ssam (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); 417138593Ssam 418138593Ssam /* 419138593Ssam * If mouse state has changed, wake up anyone wanting to know. 420138593Ssam */ 421138593Ssam if (sc->sc_deltax != 0 || sc->sc_deltay != 0 || 422138593Ssam (sc->sc_obuttons ^ sc->sc_buttons) != 0) { 423138593Ssam if (sc->sc_flags & MSESC_WANT) { 424138593Ssam sc->sc_flags &= ~MSESC_WANT; 425138593Ssam wakeup((caddr_t)sc); 426138593Ssam } 427138593Ssam selwakeup(&sc->sc_selp); 428138593Ssam } 429138593Ssam} 430138593Ssam 431138593Ssam/* 432138593Ssam * Routines for the Logitech mouse. 433138593Ssam */ 434138593Ssam/* 435138593Ssam * Test for a Logitech bus mouse and return 1 if it is. 436138593Ssam * (until I know how to use the signature port properly, just disable 437138593Ssam * interrupts and return 1) 438138593Ssam */ 439138593Ssamstatic int 440138593Ssammse_probelogi(idp) 441138593Ssam register struct isa_device *idp; 442138593Ssam{ 443138593Ssam 444138593Ssam int sig; 445146873Sjhb 446138593Ssam outb(idp->id_iobase + MSE_PORTD, MSE_SETUP); 447138593Ssam /* set the signature port */ 448138593Ssam outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG); 449138593Ssam 450138593Ssam DELAY(30000); /* 30 ms delay */ 451146873Sjhb sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF; 452138593Ssam if (sig == MSE_LOGI_SIG) { 453138593Ssam outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR); 454146873Sjhb return(1); 455138593Ssam } else { 456138593Ssam if (bootverbose) 457138593Ssam printf("mse%d: wrong signature %x\n",idp->id_unit,sig); 458138593Ssam return(0); 459138593Ssam } 460138593Ssam} 461138593Ssam 462138593Ssam/* 463138593Ssam * Initialize Logitech mouse and enable interrupts. 464138593Ssam */ 465138593Ssamstatic void 466138593Ssammse_enablelogi(port) 467138593Ssam register u_int port; 468138593Ssam{ 469138593Ssam int dx, dy, but; 470138593Ssam 471138593Ssam outb(port + MSE_PORTD, MSE_SETUP); 472138593Ssam mse_getlogi(port, &dx, &dy, &but); 473138593Ssam} 474138593Ssam 475138593Ssam/* 476138593Ssam * Disable interrupts for Logitech mouse. 477138593Ssam */ 478138593Ssamstatic void 479138593Ssammse_disablelogi(port) 480138593Ssam register u_int port; 481138593Ssam{ 482138593Ssam 483138593Ssam outb(port + MSE_PORTC, MSE_DISINTR); 484155702Ssam} 485138593Ssam 486138593Ssam/* 487138593Ssam * Get the current dx, dy and button up/down state. 488138593Ssam */ 489138593Ssamstatic void 490138593Ssammse_getlogi(port, dx, dy, but) 491138593Ssam register u_int port; 492138593Ssam int *dx; 493138593Ssam int *dy; 494138593Ssam int *but; 495138593Ssam{ 496138593Ssam register char x, y; 497138593Ssam 498138593Ssam outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); 499138593Ssam x = inb(port + MSE_PORTA); 500138593Ssam *but = (x >> 5) & 0x7; 501138593Ssam x &= 0xf; 502138593Ssam outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 503138593Ssam x |= (inb(port + MSE_PORTA) << 4); 504138593Ssam outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW); 505138593Ssam y = (inb(port + MSE_PORTA) & 0xf); 506138593Ssam outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 507138593Ssam y |= (inb(port + MSE_PORTA) << 4); 508138593Ssam *dx += x; 509138593Ssam *dy += y; 510138593Ssam outb(port + MSE_PORTC, MSE_INTREN); 511138593Ssam} 512138593Ssam 513138593Ssam/* 514138593Ssam * Routines for the ATI Inport bus mouse. 515138593Ssam */ 516138593Ssam/* 517138593Ssam * Test for a ATI Inport bus mouse and return 1 if it is. 518138593Ssam * (do not enable interrupts) 519138593Ssam */ 520138593Ssamstatic int 521138593Ssammse_probeati(idp) 522138593Ssam register struct isa_device *idp; 523138593Ssam{ 524138593Ssam int i; 525138593Ssam 526138593Ssam for (i = 0; i < 2; i++) 527138593Ssam if (inb(idp->id_iobase + MSE_PORTC) == 0xde) 528138593Ssam return (1); 529138593Ssam return (0); 530138593Ssam} 531138593Ssam 532138593Ssam/* 533138593Ssam * Initialize ATI Inport mouse and enable interrupts. 534138593Ssam */ 535138593Ssamstatic void 536138593Ssammse_enableati(port) 537138593Ssam register u_int port; 538138593Ssam{ 539138593Ssam 540138593Ssam outb(port + MSE_PORTA, MSE_INPORT_RESET); 541138593Ssam outb(port + MSE_PORTA, MSE_INPORT_MODE); 542138593Ssam outb(port + MSE_PORTB, MSE_INPORT_INTREN); 543148621Ssam} 544138593Ssam 545148621Ssam/* 546138593Ssam * Disable interrupts for ATI Inport mouse. 547148621Ssam */ 548148621Ssamstatic void 549148621Ssammse_disableati(port) 550148621Ssam register u_int port; 551148621Ssam{ 552138593Ssam 553138593Ssam outb(port + MSE_PORTA, MSE_INPORT_MODE); 554148621Ssam outb(port + MSE_PORTB, 0); 555138593Ssam} 556148621Ssam 557138593Ssam/* 558148621Ssam * Get current dx, dy and up/down button state. 559148621Ssam */ 560148621Ssamstatic void 561148621Ssammse_getati(port, dx, dy, but) 562148621Ssam register u_int port; 563138593Ssam int *dx; 564138593Ssam int *dy; 565138593Ssam int *but; 566138593Ssam{ 567138593Ssam register char byte; 568138593Ssam 569138593Ssam outb(port + MSE_PORTA, MSE_INPORT_MODE); 570138593Ssam outb(port + MSE_PORTB, MSE_INPORT_HOLD); 571138593Ssam outb(port + MSE_PORTA, MSE_INPORT_STATUS); 572138593Ssam *but = ~(inb(port + MSE_PORTB) & 0x7); 573138593Ssam outb(port + MSE_PORTA, MSE_INPORT_DX); 574138593Ssam byte = inb(port + MSE_PORTB); 575138593Ssam *dx += byte; 576138593Ssam outb(port + MSE_PORTA, MSE_INPORT_DY); 577138593Ssam byte = inb(port + MSE_PORTB); 578138593Ssam *dy += byte; 579138593Ssam outb(port + MSE_PORTA, MSE_INPORT_MODE); 580138593Ssam outb(port + MSE_PORTB, MSE_INPORT_INTREN); 581138593Ssam} 582138593Ssam 583138593Ssamstatic mse_devsw_installed = 0; 584138593Ssam 585138593Ssamstatic void mse_drvinit(void *unused) 586138593Ssam{ 587138593Ssam dev_t dev; 588138593Ssam 589138593Ssam if( ! mse_devsw_installed ) { 590138593Ssam dev = makedev(CDEV_MAJOR, 0); 591138593Ssam cdevsw_add(&dev,&mse_cdevsw, NULL); 592138593Ssam mse_devsw_installed = 1; 593138593Ssam } 594138593Ssam} 595138593Ssam 596138593SsamSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL) 597138593Ssam 598138593Ssam 599138593Ssam#endif /* NMSE */ 600138593Ssam