mse_cbus.c revision 138755
1138755Simp/* 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 9138755Simp * notice, this list of conditions, and the following disclaimer, 10138755Simp * without modification, immediately at the beginning of the file. 11138755Simp * 2. Redistributions in binary form must reproduce the above copyright 12138755Simp * notice, this list of conditions and the following disclaimer in 13138755Simp * the documentation and/or other materials provided with the 14138755Simp * distribution. 15138755Simp * 16138755Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17138755Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18138755Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19138755Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20138755Simp * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21138755Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22138755Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23138755Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24138755Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25138755Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26138755Simp * SUCH DAMAGE. 27138755Simp * 28138755Simp * $FreeBSD: head/sys/dev/mse/mse_cbus.c 138755 2004-12-12 20:05:50Z imp $ 29138755Simp */ 30138755Simp 31138755Simp/* 32138755Simp * Copyright 1992 by the University of Guelph 33138755Simp * 34138755Simp * Permission to use, copy and modify this 35138755Simp * software and its documentation for any purpose and without 36138755Simp * fee is hereby granted, provided that the above copyright 37138755Simp * notice appear in all copies and that both that copyright 38138755Simp * notice and this permission notice appear in supporting 39138755Simp * documentation. 40138755Simp * University of Guelph makes no representations about the suitability of 41138755Simp * this software for any purpose. It is provided "as is" 42138755Simp * without express or implied warranty. 43138755Simp */ 44138755Simp/* 45138755Simp * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 46138755Simp * the X386 port, courtesy of 47138755Simp * Rick Macklem, rick@snowhite.cis.uoguelph.ca 48138755Simp * Caveats: The driver currently uses spltty(), but doesn't use any 49138755Simp * generic tty code. It could use splmse() (that only masks off the 50138755Simp * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 51138755Simp * (This may be worth the effort, since the Logitech generates 30/60 52138755Simp * interrupts/sec continuously while it is open.) 53138755Simp * NB: The ATI has NOT been tested yet! 54138755Simp */ 55138755Simp 56138755Simp/* 57138755Simp * Modification history: 58138755Simp * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 59138755Simp * improved probe based on input from Logitech. 60138755Simp * 61138755Simp * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 62138755Simp * fixes to make it work with Microsoft InPort busmouse 63138755Simp * 64138755Simp * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 65138755Simp * added patches for new "select" interface 66138755Simp * 67138755Simp * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 68138755Simp * changed position of some spl()'s in mseread 69138755Simp * 70138755Simp * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 71138755Simp * limit maximum negative x/y value to -127 to work around XFree problem 72138755Simp * that causes spurious button pushes. 73138755Simp */ 74138755Simp 75138755Simp#include <sys/param.h> 76138755Simp#include <sys/systm.h> 77138755Simp#include <sys/conf.h> 78138755Simp#include <sys/kernel.h> 79138755Simp#include <sys/module.h> 80138755Simp#include <sys/bus.h> 81138755Simp#include <sys/poll.h> 82138755Simp#include <sys/selinfo.h> 83138755Simp#include <sys/uio.h> 84138755Simp#include <sys/mouse.h> 85138755Simp 86138755Simp#include <machine/bus.h> 87138755Simp#include <machine/clock.h> 88138755Simp#include <machine/resource.h> 89138755Simp#include <sys/rman.h> 90138755Simp 91138755Simp#include <isa/isavar.h> 92138755Simp 93138755Simp#include <dev/mse/msevar.h> 94138755Simp 95138755Simpstatic int mse_probe(device_t dev); 96138755Simpstatic int mse_attach(device_t dev); 97138755Simpstatic int mse_detach(device_t dev); 98138755Simp 99138755Simpstatic device_method_t mse_methods[] = { 100138755Simp DEVMETHOD(device_probe, mse_probe), 101138755Simp DEVMETHOD(device_attach, mse_attach), 102138755Simp DEVMETHOD(device_detach, mse_detach), 103138755Simp { 0, 0 } 104138755Simp}; 105138755Simp 106138755Simpstatic driver_t mse_driver = { 107138755Simp "mse", 108138755Simp mse_methods, 109138755Simp sizeof(mse_softc_t), 110138755Simp}; 111138755Simp 112138755SimpDRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0); 113138755Simp 114138755Simpstatic struct isa_pnp_id mse_ids[] = { 115138755Simp#if 0 116138755Simp { 0x001fa3b8, "PC-98 bus mouse" }, /* NEC1F00 */ 117138755Simp#endif 118138755Simp { 0 } 119138755Simp}; 120138755Simp 121138755Simp/* 122138755Simp * PC-9801 Bus mouse definitions 123138755Simp */ 124138755Simp 125138755Simp#define MODE MSE_PORTD 126138755Simp#define HC MSE_PORTD 127138755Simp#define INT MSE_PORTD 128138755Simp 129138755Simp#define XL 0x00 130138755Simp#define XH 0x20 131138755Simp#define YL 0x40 132138755Simp#define YH 0x60 133138755Simp 134138755Simp#define INT_ENABLE 0x8 135138755Simp#define INT_DISABLE 0x9 136138755Simp#define HC_NO_CLEAR 0xe 137138755Simp#define HC_CLEAR 0xf 138138755Simp 139138755Simpstatic bus_addr_t mse_port[] = {0, 2, 4, 6}; 140138755Simp 141138755Simpstatic int mse_probe98m(device_t dev, mse_softc_t *sc); 142138755Simpstatic void mse_disable98m(bus_space_tag_t t, bus_space_handle_t h); 143138755Simpstatic void mse_get98m(bus_space_tag_t t, bus_space_handle_t h, 144138755Simp int *dx, int *dy, int *but); 145138755Simpstatic void mse_enable98m(bus_space_tag_t t, bus_space_handle_t h); 146138755Simp 147138755Simpstatic struct mse_types mse_types[] = { 148138755Simp { MSE_98BUSMOUSE, 149138755Simp mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m, 150138755Simp { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 151138755Simp { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 152138755Simp { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 153138755Simp { 0, }, 154138755Simp}; 155138755Simp 156138755Simpstatic int 157138755Simpmse_probe(dev) 158138755Simp device_t dev; 159138755Simp{ 160138755Simp mse_softc_t *sc; 161138755Simp int error; 162138755Simp int rid; 163138755Simp int i; 164138755Simp 165138755Simp /* check PnP IDs */ 166138755Simp error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids); 167138755Simp if (error == ENXIO) 168138755Simp return error; 169138755Simp 170138755Simp sc = device_get_softc(dev); 171138755Simp rid = 0; 172138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 173138755Simp MSE_IOSIZE, RF_ACTIVE); 174138755Simp if (sc->sc_port == NULL) 175138755Simp return ENXIO; 176138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 177138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 178138755Simp return ENXIO; 179138755Simp } 180138755Simp sc->sc_iot = rman_get_bustag(sc->sc_port); 181138755Simp sc->sc_ioh = rman_get_bushandle(sc->sc_port); 182138755Simp 183138755Simp /* 184138755Simp * Check for each mouse type in the table. 185138755Simp */ 186138755Simp i = 0; 187138755Simp while (mse_types[i].m_type) { 188138755Simp if ((*mse_types[i].m_probe)(dev, sc)) { 189138755Simp sc->sc_mousetype = mse_types[i].m_type; 190138755Simp sc->sc_enablemouse = mse_types[i].m_enable; 191138755Simp sc->sc_disablemouse = mse_types[i].m_disable; 192138755Simp sc->sc_getmouse = mse_types[i].m_get; 193138755Simp sc->hw = mse_types[i].m_hw; 194138755Simp sc->mode = mse_types[i].m_mode; 195138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, 196138755Simp sc->sc_port); 197138755Simp device_set_desc(dev, "Bus/InPort Mouse"); 198138755Simp return 0; 199138755Simp } 200138755Simp i++; 201138755Simp } 202138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 203138755Simp return ENXIO; 204138755Simp} 205138755Simp 206138755Simpstatic int 207138755Simpmse_attach(dev) 208138755Simp device_t dev; 209138755Simp{ 210138755Simp mse_softc_t *sc; 211138755Simp int rid; 212138755Simp 213138755Simp sc = device_get_softc(dev); 214138755Simp 215138755Simp rid = 0; 216138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 217138755Simp MSE_IOSIZE, RF_ACTIVE); 218138755Simp if (sc->sc_port == NULL) 219138755Simp return ENXIO; 220138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 221138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 222138755Simp return ENXIO; 223138755Simp } 224138755Simp sc->sc_iot = rman_get_bustag(sc->sc_port); 225138755Simp sc->sc_ioh = rman_get_bushandle(sc->sc_port); 226138755Simp 227138755Simp return (mse_common_attach(dev)); 228138755Simp} 229138755Simp 230138755Simpstatic int 231138755Simpmse_detach(dev) 232138755Simp device_t dev; 233138755Simp{ 234138755Simp mse_softc_t *sc; 235138755Simp int rid; 236138755Simp 237138755Simp sc = device_get_softc(dev); 238138755Simp if (sc->sc_flags & MSESC_OPEN) 239138755Simp return EBUSY; 240138755Simp 241138755Simp rid = 0; 242138755Simp BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->sc_intr, sc->sc_ih); 243138755Simp bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr); 244138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 245138755Simp 246138755Simp destroy_dev(sc->sc_dev); 247138755Simp destroy_dev(sc->sc_ndev); 248138755Simp 249138755Simp return 0; 250138755Simp} 251138755Simp 252138755Simp/* 253138755Simp * Routines for the PC98 bus mouse. 254138755Simp */ 255138755Simp 256138755Simp/* 257138755Simp * Test for a PC98 bus mouse and return 1 if it is. 258138755Simp * (do not enable interrupts) 259138755Simp */ 260138755Simpstatic int 261138755Simpmse_probe98m(dev, sc) 262138755Simp device_t dev; 263138755Simp mse_softc_t *sc; 264138755Simp{ 265138755Simp /* mode set */ 266138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, MODE, 0x93); 267138755Simp 268138755Simp /* initialize */ 269138755Simp /* INT disable */ 270138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, INT, INT_DISABLE); 271138755Simp /* HC = 0 */ 272138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_NO_CLEAR); 273138755Simp /* HC = 1 */ 274138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_CLEAR); 275138755Simp 276138755Simp return (1); 277138755Simp} 278138755Simp 279138755Simp/* 280138755Simp * Initialize PC98 bus mouse and enable interrupts. 281138755Simp */ 282138755Simpstatic void 283138755Simpmse_enable98m(tag, handle) 284138755Simp bus_space_tag_t tag; 285138755Simp bus_space_handle_t handle; 286138755Simp{ 287138755Simp bus_space_write_1(tag, handle, INT, INT_ENABLE); /* INT enable */ 288138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 289138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 290138755Simp} 291138755Simp 292138755Simp/* 293138755Simp * Disable interrupts for PC98 Bus mouse. 294138755Simp */ 295138755Simpstatic void 296138755Simpmse_disable98m(tag, handle) 297138755Simp bus_space_tag_t tag; 298138755Simp bus_space_handle_t handle; 299138755Simp{ 300138755Simp bus_space_write_1(tag, handle, INT, INT_DISABLE); /* INT disable */ 301138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 302138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 303138755Simp} 304138755Simp 305138755Simp/* 306138755Simp * Get current dx, dy and up/down button state. 307138755Simp */ 308138755Simpstatic void 309138755Simpmse_get98m(tag, handle, dx, dy, but) 310138755Simp bus_space_tag_t tag; 311138755Simp bus_space_handle_t handle; 312138755Simp int *dx; 313138755Simp int *dy; 314138755Simp int *but; 315138755Simp{ 316138755Simp register char x, y; 317138755Simp 318138755Simp bus_space_write_1(tag, handle, INT, INT_DISABLE); /* INT disable */ 319138755Simp 320138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 321138755Simp 322138755Simp /* X low */ 323138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XL); 324138755Simp x = bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f; 325138755Simp /* X high */ 326138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XH); 327138755Simp x |= ((bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f) << 4); 328138755Simp 329138755Simp /* Y low */ 330138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YL); 331138755Simp y = (bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f); 332138755Simp /* Y high */ 333138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YH); 334138755Simp y |= ((bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f) << 4); 335138755Simp 336138755Simp *but = (bus_space_read_1(tag, handle, MSE_PORTA) >> 5) & 7; 337138755Simp 338138755Simp *dx = x; 339138755Simp *dy = y; 340138755Simp 341138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 342138755Simp 343138755Simp bus_space_write_1(tag, handle, INT, INT_ENABLE); /* INT enable */ 344138755Simp} 345