1132718Skan/*- 2132718Skan * Copyright (c) 2004 M. Warner Losh 3169689Skan * All rights reserved. 4132718Skan * 5132718Skan * Redistribution and use in source and binary forms, with or without 6132718Skan * modification, are permitted provided that the following conditions 7132718Skan * are met: 8132718Skan * 1. Redistributions of source code must retain the above copyright 9132718Skan * notice, this list of conditions and the following disclaimer. 10132718Skan * 2. Redistributions in binary form must reproduce the above copyright 11132718Skan * notice, this list of conditions and the following disclaimer in the 12132718Skan * documentation and/or other materials provided with the distribution. 13132718Skan * 14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132718Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132718Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132718Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132718Skan * SUCH DAMAGE. 25132718Skan * 26132718Skan * $FreeBSD: releng/11.0/sys/dev/mse/mse_cbus.c 272956 2014-10-11 19:36:59Z jhb $ 27132718Skan */ 28132718Skan 29132718Skan/*- 30132718Skan * Copyright 1992 by the University of Guelph 31169689Skan * 32169689Skan * Permission to use, copy and modify this 33169689Skan * software and its documentation for any purpose and without 34169689Skan * fee is hereby granted, provided that the above copyright 35132718Skan * notice appear in all copies and that both that copyright 36132718Skan * notice and this permission notice appear in supporting 37132718Skan * documentation. 38132718Skan * University of Guelph makes no representations about the suitability of 39132718Skan * this software for any purpose. It is provided "as is" 40132718Skan * without express or implied warranty. 41132718Skan */ 42132718Skan/* 43132718Skan * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and 44132718Skan * the X386 port, courtesy of 45132718Skan * Rick Macklem, rick@snowhite.cis.uoguelph.ca 46132718Skan * Caveats: The driver currently uses spltty(), but doesn't use any 47132718Skan * generic tty code. It could use splmse() (that only masks off the 48132718Skan * bus mouse interrupt, but that would require hacking in i386/isa/icu.s. 49132718Skan * (This may be worth the effort, since the Logitech generates 30/60 50132718Skan * interrupts/sec continuously while it is open.) 51132718Skan * NB: The ATI has NOT been tested yet! 52132718Skan */ 53132718Skan 54132718Skan/* 55132718Skan * Modification history: 56132718Skan * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com) 57132718Skan * improved probe based on input from Logitech. 58132718Skan * 59132718Skan * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu) 60132718Skan * fixes to make it work with Microsoft InPort busmouse 61132718Skan * 62132718Skan * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu) 63132718Skan * added patches for new "select" interface 64132718Skan * 65132718Skan * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu) 66132718Skan * changed position of some spl()'s in mseread 67132718Skan * 68132718Skan * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu) 69132718Skan * limit maximum negative x/y value to -127 to work around XFree problem 70132718Skan * that causes spurious button pushes. 71132718Skan */ 72132718Skan 73132718Skan#include <sys/param.h> 74132718Skan#include <sys/systm.h> 75132718Skan#include <sys/conf.h> 76132718Skan#include <sys/kernel.h> 77132718Skan#include <sys/module.h> 78132718Skan#include <sys/bus.h> 79132718Skan#include <sys/poll.h> 80132718Skan#include <sys/selinfo.h> 81132718Skan#include <sys/uio.h> 82132718Skan#include <sys/mouse.h> 83132718Skan 84132718Skan#include <machine/bus.h> 85169689Skan#include <machine/resource.h> 86169689Skan#include <sys/rman.h> 87169689Skan 88169689Skan#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