mse_cbus.c revision 272956
1/*- 2 * Copyright (c) 2004 M. Warner Losh 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/mse/mse_cbus.c 272956 2014-10-11 19:36:59Z jhb $ 27 */ 28 29/*- 30 * Copyright 1992 by the University of Guelph 31 * 32 * Permission to use, copy and modify this 33 * software and its documentation for any purpose and without 34 * fee is hereby granted, provided that the above copyright 35 * notice appear in all copies and that both that copyright 36 * notice and this permission notice appear in supporting 37 * documentation. 38 * University of Guelph makes no representations about the suitability of 39 * this software for any purpose. It is provided "as is" 40 * without express or implied warranty. 41 */ 42/* 43 * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 44 * the X386 port, courtesy of 45 * Rick Macklem, rick@snowhite.cis.uoguelph.ca 46 * Caveats: The driver currently uses spltty(), but doesn't use any 47 * generic tty code. It could use splmse() (that only masks off the 48 * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 49 * (This may be worth the effort, since the Logitech generates 30/60 50 * interrupts/sec continuously while it is open.) 51 * NB: The ATI has NOT been tested yet! 52 */ 53 54/* 55 * Modification history: 56 * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 57 * improved probe based on input from Logitech. 58 * 59 * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 60 * fixes to make it work with Microsoft InPort busmouse 61 * 62 * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 63 * added patches for new "select" interface 64 * 65 * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 66 * changed position of some spl()'s in mseread 67 * 68 * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 69 * limit maximum negative x/y value to -127 to work around XFree problem 70 * that causes spurious button pushes. 71 */ 72 73#include <sys/param.h> 74#include <sys/systm.h> 75#include <sys/conf.h> 76#include <sys/kernel.h> 77#include <sys/module.h> 78#include <sys/bus.h> 79#include <sys/poll.h> 80#include <sys/selinfo.h> 81#include <sys/uio.h> 82#include <sys/mouse.h> 83 84#include <machine/bus.h> 85#include <machine/resource.h> 86#include <sys/rman.h> 87 88#include <isa/isavar.h> 89 90#include <dev/mse/msevar.h> 91 92static int mse_cbus_probe(device_t dev); 93static int mse_cbus_attach(device_t dev); 94 95static device_method_t mse_methods[] = { 96 DEVMETHOD(device_probe, mse_cbus_probe), 97 DEVMETHOD(device_attach, mse_cbus_attach), 98 DEVMETHOD(device_detach, mse_detach), 99 { 0, 0 } 100}; 101 102static driver_t mse_driver = { 103 "mse", 104 mse_methods, 105 sizeof(mse_softc_t), 106}; 107 108DRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0); 109 110static struct isa_pnp_id mse_ids[] = { 111#if 0 112 { 0x001fa3b8, "PC-98 bus mouse" }, /* NEC1F00 */ 113#endif 114 { 0 } 115}; 116 117/* 118 * PC-9801 Bus mouse definitions 119 */ 120 121#define MODE MSE_PORTD 122#define HC MSE_PORTD 123#define INT MSE_PORTD 124 125#define XL 0x00 126#define XH 0x20 127#define YL 0x40 128#define YH 0x60 129 130#define INT_ENABLE 0x8 131#define INT_DISABLE 0x9 132#define HC_NO_CLEAR 0xe 133#define HC_CLEAR 0xf 134 135static bus_addr_t mse_port[] = {0, 2, 4, 6}; 136 137static int mse_probe98m(device_t dev, mse_softc_t *sc); 138static void mse_disable98m(struct resource *port); 139static void mse_get98m(struct resource *port, 140 int *dx, int *dy, int *but); 141static void mse_enable98m(struct resource *port); 142 143static struct mse_types mse_types[] = { 144 { MSE_98BUSMOUSE, 145 mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m, 146 { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 147 { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 148 { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 149 { 0, }, 150}; 151 152static int 153mse_cbus_probe(device_t dev) 154{ 155 mse_softc_t *sc; 156 int error; 157 int rid; 158 int i; 159 160 /* check PnP IDs */ 161 error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids); 162 if (error == ENXIO) 163 return error; 164 165 sc = device_get_softc(dev); 166 rid = 0; 167 sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 168 MSE_IOSIZE, RF_ACTIVE); 169 if (sc->sc_port == NULL) 170 return ENXIO; 171 if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 172 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 173 return ENXIO; 174 } 175 176 /* 177 * Check for each mouse type in the table. 178 */ 179 i = 0; 180 while (mse_types[i].m_type) { 181 if ((*mse_types[i].m_probe)(dev, sc)) { 182 sc->sc_mousetype = mse_types[i].m_type; 183 sc->sc_enablemouse = mse_types[i].m_enable; 184 sc->sc_disablemouse = mse_types[i].m_disable; 185 sc->sc_getmouse = mse_types[i].m_get; 186 sc->hw = mse_types[i].m_hw; 187 sc->mode = mse_types[i].m_mode; 188 bus_release_resource(dev, SYS_RES_IOPORT, rid, 189 sc->sc_port); 190 device_set_desc(dev, "Bus/InPort Mouse"); 191 return 0; 192 } 193 i++; 194 } 195 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 196 return ENXIO; 197} 198 199static int 200mse_cbus_attach(device_t dev) 201{ 202 mse_softc_t *sc; 203 int rid; 204 205 sc = device_get_softc(dev); 206 207 rid = 0; 208 sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port, 209 MSE_IOSIZE, RF_ACTIVE); 210 if (sc->sc_port == NULL) 211 return ENXIO; 212 if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) { 213 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 214 return ENXIO; 215 } 216 217 return (mse_common_attach(dev)); 218} 219 220/* 221 * Routines for the PC98 bus mouse. 222 */ 223 224/* 225 * Test for a PC98 bus mouse and return 1 if it is. 226 * (do not enable interrupts) 227 */ 228static int 229mse_probe98m(device_t dev, mse_softc_t *sc) 230{ 231 /* mode set */ 232 bus_write_1(sc->sc_port, MODE, 0x93); 233 234 /* initialize */ 235 /* INT disable */ 236 bus_write_1(sc->sc_port, INT, INT_DISABLE); 237 /* HC = 0 */ 238 bus_write_1(sc->sc_port, HC, HC_NO_CLEAR); 239 /* HC = 1 */ 240 bus_write_1(sc->sc_port, HC, HC_CLEAR); 241 242 return (1); 243} 244 245/* 246 * Initialize PC98 bus mouse and enable interrupts. 247 */ 248static void 249mse_enable98m(struct resource *port) 250{ 251 bus_write_1(port, INT, INT_ENABLE); /* INT enable */ 252 bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 253 bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 254} 255 256/* 257 * Disable interrupts for PC98 Bus mouse. 258 */ 259static void 260mse_disable98m(struct resource *port) 261{ 262 bus_write_1(port, INT, INT_DISABLE); /* INT disable */ 263 bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 264 bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 265} 266 267/* 268 * Get current dx, dy and up/down button state. 269 */ 270static void 271mse_get98m(struct resource *port, int *dx, int *dy, int *but) 272{ 273 register char x, y; 274 275 bus_write_1(port, INT, INT_DISABLE); /* INT disable */ 276 277 bus_write_1(port, HC, HC_CLEAR); /* HC = 1 */ 278 279 /* X low */ 280 bus_write_1(port, MSE_PORTC, 0x90 | XL); 281 x = bus_read_1(port, MSE_PORTA) & 0x0f; 282 /* X high */ 283 bus_write_1(port, MSE_PORTC, 0x90 | XH); 284 x |= ((bus_read_1(port, MSE_PORTA) & 0x0f) << 4); 285 286 /* Y low */ 287 bus_write_1(port, MSE_PORTC, 0x90 | YL); 288 y = (bus_read_1(port, MSE_PORTA) & 0x0f); 289 /* Y high */ 290 bus_write_1(port, MSE_PORTC, 0x90 | YH); 291 y |= ((bus_read_1(port, MSE_PORTA) & 0x0f) << 4); 292 293 *but = (bus_read_1(port, MSE_PORTA) >> 5) & 7; 294 295 *dx = x; 296 *dy = y; 297 298 bus_write_1(port, HC, HC_NO_CLEAR); /* HC = 0 */ 299 300 bus_write_1(port, INT, INT_ENABLE); /* INT enable */ 301} 302