1139749Simp/*- 2138755Simp * Copyright (c) 2004 M. Warner Losh 3138755Simp * All rights reserved. 4138755Simp * 5138755Simp * Redistribution and use in source and binary forms, with or without 6138755Simp * modification, are permitted provided that the following conditions 7138755Simp * are met: 8138755Simp * 1. Redistributions of source code must retain the above copyright 9140040Simp * notice, this list of conditions and the following disclaimer. 10138755Simp * 2. Redistributions in binary form must reproduce the above copyright 11140040Simp * notice, this list of conditions and the following disclaimer in the 12140040Simp * documentation and/or other materials provided with the distribution. 13138755Simp * 14138755Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15138755Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16138755Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17140040Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18140040Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19138755Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20138755Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21138755Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22138755Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23138755Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24138755Simp * SUCH DAMAGE. 25138755Simp * 26138755Simp * $FreeBSD$ 27138755Simp */ 28138755Simp 29140040Simp/*- 30138755Simp * Copyright 1992 by the University of Guelph 31138755Simp * 32138755Simp * Permission to use, copy and modify this 33138755Simp * software and its documentation for any purpose and without 34138755Simp * fee is hereby granted, provided that the above copyright 35138755Simp * notice appear in all copies and that both that copyright 36138755Simp * notice and this permission notice appear in supporting 37138755Simp * documentation. 38138755Simp * University of Guelph makes no representations about the suitability of 39138755Simp * this software for any purpose. It is provided "as is" 40138755Simp * without express or implied warranty. 41138755Simp */ 42138755Simp/* 43138755Simp * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 44138755Simp * the X386 port, courtesy of 45138755Simp * Rick Macklem, rick@snowhite.cis.uoguelph.ca 46138755Simp * Caveats: The driver currently uses spltty(), but doesn't use any 47138755Simp * generic tty code. It could use splmse() (that only masks off the 48138755Simp * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 49138755Simp * (This may be worth the effort, since the Logitech generates 30/60 50138755Simp * interrupts/sec continuously while it is open.) 51138755Simp * NB: The ATI has NOT been tested yet! 52138755Simp */ 53138755Simp 54138755Simp/* 55138755Simp * Modification history: 56138755Simp * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 57138755Simp * improved probe based on input from Logitech. 58138755Simp * 59138755Simp * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 60138755Simp * fixes to make it work with Microsoft InPort busmouse 61138755Simp * 62138755Simp * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 63138755Simp * added patches for new "select" interface 64138755Simp * 65138755Simp * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 66138755Simp * changed position of some spl()'s in mseread 67138755Simp * 68138755Simp * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 69138755Simp * limit maximum negative x/y value to -127 to work around XFree problem 70138755Simp * that causes spurious button pushes. 71138755Simp */ 72138755Simp 73138755Simp#include <sys/param.h> 74138755Simp#include <sys/systm.h> 75138755Simp#include <sys/conf.h> 76138755Simp#include <sys/kernel.h> 77138755Simp#include <sys/module.h> 78138755Simp#include <sys/bus.h> 79138755Simp#include <sys/poll.h> 80138755Simp#include <sys/selinfo.h> 81138755Simp#include <sys/uio.h> 82138755Simp#include <sys/mouse.h> 83138755Simp 84138755Simp#include <machine/bus.h> 85138755Simp#include <machine/resource.h> 86138755Simp#include <sys/rman.h> 87138755Simp 88138755Simp#include <isa/isavar.h> 89138755Simp 90138755Simp#include <dev/mse/msevar.h> 91138755Simp 92144783Simpstatic int mse_cbus_probe(device_t dev); 93144783Simpstatic int mse_cbus_attach(device_t dev); 94138755Simp 95138755Simpstatic device_method_t mse_methods[] = { 96144783Simp DEVMETHOD(device_probe, mse_cbus_probe), 97144783Simp DEVMETHOD(device_attach, mse_cbus_attach), 98272956Sjhb DEVMETHOD(device_detach, mse_detach), 99138755Simp { 0, 0 } 100138755Simp}; 101138755Simp 102138755Simpstatic driver_t mse_driver = { 103138755Simp "mse", 104138755Simp mse_methods, 105138755Simp sizeof(mse_softc_t), 106138755Simp}; 107138755Simp 108138755SimpDRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0); 109138755Simp 110138755Simpstatic struct isa_pnp_id mse_ids[] = { 111138755Simp#if 0 112138755Simp { 0x001fa3b8, "PC-98 bus mouse" }, /* NEC1F00 */ 113138755Simp#endif 114138755Simp { 0 } 115138755Simp}; 116138755Simp 117138755Simp/* 118138755Simp * PC-9801 Bus mouse definitions 119138755Simp */ 120138755Simp 121138755Simp#define MODE MSE_PORTD 122138755Simp#define HC MSE_PORTD 123138755Simp#define INT MSE_PORTD 124138755Simp 125138755Simp#define XL 0x00 126138755Simp#define XH 0x20 127138755Simp#define YL 0x40 128138755Simp#define YH 0x60 129138755Simp 130138755Simp#define INT_ENABLE 0x8 131138755Simp#define INT_DISABLE 0x9 132138755Simp#define HC_NO_CLEAR 0xe 133138755Simp#define HC_CLEAR 0xf 134138755Simp 135138755Simpstatic bus_addr_t mse_port[] = {0, 2, 4, 6}; 136138755Simp 137138755Simpstatic int mse_probe98m(device_t dev, mse_softc_t *sc); 138272956Sjhbstatic void mse_disable98m(struct resource *port); 139272956Sjhbstatic void mse_get98m(struct resource *port, 140138755Simp int *dx, int *dy, int *but); 141272956Sjhbstatic void mse_enable98m(struct resource *port); 142138755Simp 143138755Simpstatic struct mse_types mse_types[] = { 144138755Simp { MSE_98BUSMOUSE, 145138755Simp mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m, 146138755Simp { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 147138755Simp { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 148138755Simp { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 149138755Simp { 0, }, 150138755Simp}; 151138755Simp 152144783Simpstatic int 153144783Simpmse_cbus_probe(device_t dev) 154138755Simp{ 155138755Simp mse_softc_t *sc; 156138755Simp int error; 157138755Simp int rid; 158138755Simp int i; 159138755Simp 160138755Simp /* check PnP IDs */ 161138755Simp error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids); 162138755Simp if (error == ENXIO) 163138755Simp return error; 164138755Simp 165138755Simp sc = device_get_softc(dev); 166138755Simp rid = 0; 167138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 168138755Simp MSE_IOSIZE, RF_ACTIVE); 169138755Simp if (sc->sc_port == NULL) 170138755Simp return ENXIO; 171138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 172138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 173138755Simp return ENXIO; 174138755Simp } 175138755Simp 176138755Simp /* 177138755Simp * Check for each mouse type in the table. 178138755Simp */ 179138755Simp i = 0; 180138755Simp while (mse_types[i].m_type) { 181138755Simp if ((*mse_types[i].m_probe)(dev, sc)) { 182138755Simp sc->sc_mousetype = mse_types[i].m_type; 183138755Simp sc->sc_enablemouse = mse_types[i].m_enable; 184138755Simp sc->sc_disablemouse = mse_types[i].m_disable; 185138755Simp sc->sc_getmouse = mse_types[i].m_get; 186138755Simp sc->hw = mse_types[i].m_hw; 187138755Simp sc->mode = mse_types[i].m_mode; 188138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, 189138755Simp sc->sc_port); 190138755Simp device_set_desc(dev, "Bus/InPort Mouse"); 191138755Simp return 0; 192138755Simp } 193138755Simp i++; 194138755Simp } 195138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 196138755Simp return ENXIO; 197138755Simp} 198138755Simp 199144783Simpstatic int 200144783Simpmse_cbus_attach(device_t dev) 201138755Simp{ 202138755Simp mse_softc_t *sc; 203138755Simp int rid; 204138755Simp 205138755Simp sc = device_get_softc(dev); 206138755Simp 207138755Simp rid = 0; 208138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 209138755Simp MSE_IOSIZE, RF_ACTIVE); 210138755Simp if (sc->sc_port == NULL) 211138755Simp return ENXIO; 212138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 213138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 214138755Simp return ENXIO; 215138755Simp } 216138755Simp 217138755Simp return (mse_common_attach(dev)); 218138755Simp} 219138755Simp 220138755Simp/* 221138755Simp * Routines for the PC98 bus mouse. 222138755Simp */ 223138755Simp 224138755Simp/* 225138755Simp * Test for a PC98 bus mouse and return 1 if it is. 226138755Simp * (do not enable interrupts) 227138755Simp */ 228138755Simpstatic int 229144783Simpmse_probe98m(device_t dev, mse_softc_t *sc) 230138755Simp{ 231138755Simp /* mode set */ 232272956Sjhb bus_write_1(sc->sc_port, MODE, 0x93); 233138755Simp 234138755Simp /* initialize */ 235138755Simp /* INT disable */ 236272956Sjhb bus_write_1(sc->sc_port, INT, INT_DISABLE); 237138755Simp /* HC = 0 */ 238272956Sjhb bus_write_1(sc->sc_port, HC, HC_NO_CLEAR); 239138755Simp /* HC = 1 */ 240272956Sjhb bus_write_1(sc->sc_port, HC, HC_CLEAR); 241138755Simp 242138755Simp return (1); 243138755Simp} 244138755Simp 245138755Simp/* 246138755Simp * Initialize PC98 bus mouse and enable interrupts. 247138755Simp */ 248138755Simpstatic void 249272956Sjhbmse_enable98m(struct resource *port) 250138755Simp{ 251272956Sjhb bus_write_1(port, INT, INT_ENABLE); /* INT enable */ 252272956Sjhb bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 253272956Sjhb bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 254138755Simp} 255138755Simp 256138755Simp/* 257138755Simp * Disable interrupts for PC98 Bus mouse. 258138755Simp */ 259138755Simpstatic void 260272956Sjhbmse_disable98m(struct resource *port) 261138755Simp{ 262272956Sjhb bus_write_1(port, INT, INT_DISABLE); /* INT disable */ 263272956Sjhb bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 264272956Sjhb bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 265138755Simp} 266138755Simp 267138755Simp/* 268138755Simp * Get current dx, dy and up/down button state. 269138755Simp */ 270138755Simpstatic void 271272956Sjhbmse_get98m(struct resource *port, int *dx, int *dy, int *but) 272138755Simp{ 273138755Simp register char x, y; 274138755Simp 275272956Sjhb bus_write_1(port, INT, INT_DISABLE); /* INT disable */ 276138755Simp 277272956Sjhb bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 278138755Simp 279138755Simp /* X low */ 280272956Sjhb bus_write_1(port, MSE_PORTC, 0x90 | XL); 281272956Sjhb x = bus_read_1(port, MSE_PORTA) & 0x0f; 282138755Simp /* X high */ 283272956Sjhb bus_write_1(port, MSE_PORTC, 0x90 | XH); 284272956Sjhb x |= ((bus_read_1(port, MSE_PORTA) & 0x0f) << 4); 285138755Simp 286138755Simp /* Y low */ 287272956Sjhb bus_write_1(port, MSE_PORTC, 0x90 | YL); 288272956Sjhb y = (bus_read_1(port, MSE_PORTA) & 0x0f); 289138755Simp /* Y high */ 290272956Sjhb bus_write_1(port, MSE_PORTC, 0x90 | YH); 291272956Sjhb y |= ((bus_read_1(port, MSE_PORTA) & 0x0f) << 4); 292138755Simp 293272956Sjhb *but = (bus_read_1(port, MSE_PORTA) >> 5) & 7; 294138755Simp 295138755Simp *dx = x; 296138755Simp *dy = y; 297138755Simp 298272956Sjhb bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 299138755Simp 300272956Sjhb bus_write_1(port, INT, INT_ENABLE); /* INT enable */ 301138755Simp} 302