mse_cbus.c revision 144783
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: head/sys/dev/mse/mse_cbus.c 144783 2005-04-08 05:22:58Z imp $ 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/clock.h> 86138755Simp#include <machine/resource.h> 87138755Simp#include <sys/rman.h> 88138755Simp 89138755Simp#include <isa/isavar.h> 90138755Simp 91138755Simp#include <dev/mse/msevar.h> 92138755Simp 93144783Simpstatic int mse_cbus_probe(device_t dev); 94144783Simpstatic int mse_cbus_attach(device_t dev); 95144783Simpstatic int mse_cbus_detach(device_t dev); 96138755Simp 97138755Simpstatic device_method_t mse_methods[] = { 98144783Simp DEVMETHOD(device_probe, mse_cbus_probe), 99144783Simp DEVMETHOD(device_attach, mse_cbus_attach), 100144783Simp DEVMETHOD(device_detach, mse_cbus_detach), 101138755Simp { 0, 0 } 102138755Simp}; 103138755Simp 104138755Simpstatic driver_t mse_driver = { 105138755Simp "mse", 106138755Simp mse_methods, 107138755Simp sizeof(mse_softc_t), 108138755Simp}; 109138755Simp 110138755SimpDRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0); 111138755Simp 112138755Simpstatic struct isa_pnp_id mse_ids[] = { 113138755Simp#if 0 114138755Simp { 0x001fa3b8, "PC-98 bus mouse" }, /* NEC1F00 */ 115138755Simp#endif 116138755Simp { 0 } 117138755Simp}; 118138755Simp 119138755Simp/* 120138755Simp * PC-9801 Bus mouse definitions 121138755Simp */ 122138755Simp 123138755Simp#define MODE MSE_PORTD 124138755Simp#define HC MSE_PORTD 125138755Simp#define INT MSE_PORTD 126138755Simp 127138755Simp#define XL 0x00 128138755Simp#define XH 0x20 129138755Simp#define YL 0x40 130138755Simp#define YH 0x60 131138755Simp 132138755Simp#define INT_ENABLE 0x8 133138755Simp#define INT_DISABLE 0x9 134138755Simp#define HC_NO_CLEAR 0xe 135138755Simp#define HC_CLEAR 0xf 136138755Simp 137138755Simpstatic bus_addr_t mse_port[] = {0, 2, 4, 6}; 138138755Simp 139138755Simpstatic int mse_probe98m(device_t dev, mse_softc_t *sc); 140138755Simpstatic void mse_disable98m(bus_space_tag_t t, bus_space_handle_t h); 141138755Simpstatic void mse_get98m(bus_space_tag_t t, bus_space_handle_t h, 142138755Simp int *dx, int *dy, int *but); 143138755Simpstatic void mse_enable98m(bus_space_tag_t t, bus_space_handle_t h); 144138755Simp 145138755Simpstatic struct mse_types mse_types[] = { 146138755Simp { MSE_98BUSMOUSE, 147138755Simp mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m, 148138755Simp { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 149138755Simp { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 150138755Simp { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 151138755Simp { 0, }, 152138755Simp}; 153138755Simp 154144783Simpstatic int 155144783Simpmse_cbus_probe(device_t dev) 156138755Simp{ 157138755Simp mse_softc_t *sc; 158138755Simp int error; 159138755Simp int rid; 160138755Simp int i; 161138755Simp 162138755Simp /* check PnP IDs */ 163138755Simp error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids); 164138755Simp if (error == ENXIO) 165138755Simp return error; 166138755Simp 167138755Simp sc = device_get_softc(dev); 168138755Simp rid = 0; 169138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 170138755Simp MSE_IOSIZE, RF_ACTIVE); 171138755Simp if (sc->sc_port == NULL) 172138755Simp return ENXIO; 173138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 174138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 175138755Simp return ENXIO; 176138755Simp } 177138755Simp sc->sc_iot = rman_get_bustag(sc->sc_port); 178138755Simp sc->sc_ioh = rman_get_bushandle(sc->sc_port); 179138755Simp 180138755Simp /* 181138755Simp * Check for each mouse type in the table. 182138755Simp */ 183138755Simp i = 0; 184138755Simp while (mse_types[i].m_type) { 185138755Simp if ((*mse_types[i].m_probe)(dev, sc)) { 186138755Simp sc->sc_mousetype = mse_types[i].m_type; 187138755Simp sc->sc_enablemouse = mse_types[i].m_enable; 188138755Simp sc->sc_disablemouse = mse_types[i].m_disable; 189138755Simp sc->sc_getmouse = mse_types[i].m_get; 190138755Simp sc->hw = mse_types[i].m_hw; 191138755Simp sc->mode = mse_types[i].m_mode; 192138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, 193138755Simp sc->sc_port); 194138755Simp device_set_desc(dev, "Bus/InPort Mouse"); 195138755Simp return 0; 196138755Simp } 197138755Simp i++; 198138755Simp } 199138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 200138755Simp return ENXIO; 201138755Simp} 202138755Simp 203144783Simpstatic int 204144783Simpmse_cbus_attach(device_t dev) 205138755Simp{ 206138755Simp mse_softc_t *sc; 207138755Simp int rid; 208138755Simp 209138755Simp sc = device_get_softc(dev); 210138755Simp 211138755Simp rid = 0; 212138755Simp sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 213138755Simp MSE_IOSIZE, RF_ACTIVE); 214138755Simp if (sc->sc_port == NULL) 215138755Simp return ENXIO; 216138755Simp if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 217138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 218138755Simp return ENXIO; 219138755Simp } 220138755Simp sc->sc_iot = rman_get_bustag(sc->sc_port); 221138755Simp sc->sc_ioh = rman_get_bushandle(sc->sc_port); 222138755Simp 223138755Simp return (mse_common_attach(dev)); 224138755Simp} 225138755Simp 226144783Simpstatic int 227144783Simpmse_cbus_detach(device_t dev) 228138755Simp{ 229138755Simp mse_softc_t *sc; 230138755Simp int rid; 231138755Simp 232138755Simp sc = device_get_softc(dev); 233138755Simp if (sc->sc_flags & MSESC_OPEN) 234138755Simp return EBUSY; 235138755Simp 236138755Simp rid = 0; 237138755Simp BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->sc_intr, sc->sc_ih); 238138755Simp bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr); 239138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 240138755Simp 241138755Simp destroy_dev(sc->sc_dev); 242138755Simp destroy_dev(sc->sc_ndev); 243138755Simp 244138755Simp return 0; 245138755Simp} 246138755Simp 247138755Simp/* 248138755Simp * Routines for the PC98 bus mouse. 249138755Simp */ 250138755Simp 251138755Simp/* 252138755Simp * Test for a PC98 bus mouse and return 1 if it is. 253138755Simp * (do not enable interrupts) 254138755Simp */ 255138755Simpstatic int 256144783Simpmse_probe98m(device_t dev, mse_softc_t *sc) 257138755Simp{ 258138755Simp /* mode set */ 259138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, MODE, 0x93); 260138755Simp 261138755Simp /* initialize */ 262138755Simp /* INT disable */ 263138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, INT, INT_DISABLE); 264138755Simp /* HC = 0 */ 265138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_NO_CLEAR); 266138755Simp /* HC = 1 */ 267138755Simp bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_CLEAR); 268138755Simp 269138755Simp return (1); 270138755Simp} 271138755Simp 272138755Simp/* 273138755Simp * Initialize PC98 bus mouse and enable interrupts. 274138755Simp */ 275138755Simpstatic void 276144783Simpmse_enable98m(bus_space_tag_t tag, bus_space_handle_t handle) 277138755Simp{ 278138755Simp bus_space_write_1(tag, handle, INT, INT_ENABLE); /* INT enable */ 279138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 280138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 281138755Simp} 282138755Simp 283138755Simp/* 284138755Simp * Disable interrupts for PC98 Bus mouse. 285138755Simp */ 286138755Simpstatic void 287144783Simpmse_disable98m(bus_space_tag_t tag, bus_space_handle_t handle) 288138755Simp{ 289138755Simp bus_space_write_1(tag, handle, INT, INT_DISABLE); /* INT disable */ 290138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 291138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 292138755Simp} 293138755Simp 294138755Simp/* 295138755Simp * Get current dx, dy and up/down button state. 296138755Simp */ 297138755Simpstatic void 298144783Simpmse_get98m(bus_space_tag_t tag, bus_space_handle_t handle, int *dx, int *dy, 299144783Simp int *but) 300138755Simp{ 301138755Simp register char x, y; 302138755Simp 303138755Simp bus_space_write_1(tag, handle, INT, INT_DISABLE); /* INT disable */ 304138755Simp 305138755Simp bus_space_write_1(tag, handle, HC, HC_CLEAR); /* HC = 1 */ 306138755Simp 307138755Simp /* X low */ 308138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XL); 309138755Simp x = bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f; 310138755Simp /* X high */ 311138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XH); 312138755Simp x |= ((bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f) << 4); 313138755Simp 314138755Simp /* Y low */ 315138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YL); 316138755Simp y = (bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f); 317138755Simp /* Y high */ 318138755Simp bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YH); 319138755Simp y |= ((bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f) << 4); 320138755Simp 321138755Simp *but = (bus_space_read_1(tag, handle, MSE_PORTA) >> 5) & 7; 322138755Simp 323138755Simp *dx = x; 324138755Simp *dy = y; 325138755Simp 326138755Simp bus_space_write_1(tag, handle, HC, HC_NO_CLEAR); /* HC = 0 */ 327138755Simp 328138755Simp bus_space_write_1(tag, handle, INT, INT_ENABLE); /* INT enable */ 329138755Simp} 330