mse_isa.c revision 331643
1139749Simp/*- 2330897Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330897Seadler * 4138755Simp * Copyright (c) 2004 M. Warner Losh 5138755Simp * All rights reserved. 6138755Simp * 7138755Simp * Redistribution and use in source and binary forms, with or without 8138755Simp * modification, are permitted provided that the following conditions 9138755Simp * are met: 10138755Simp * 1. Redistributions of source code must retain the above copyright 11140040Simp * notice, this list of conditions and the following disclaimer. 12138755Simp * 2. Redistributions in binary form must reproduce the above copyright 13140040Simp * notice, this list of conditions and the following disclaimer in the 14140040Simp * documentation and/or other materials provided with the 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 19140040Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20140040Simp * FOR 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: stable/11/sys/dev/mse/mse_isa.c 331643 2018-03-27 18:52:27Z dim $ 29138755Simp */ 30138755Simp 31140040Simp/*- 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/resource.h> 88138755Simp#include <sys/rman.h> 89138755Simp 90138755Simp#include <isa/isavar.h> 91138755Simp 92138755Simp#include <dev/mse/msevar.h> 93138755Simp 94144783Simpstatic int mse_isa_probe(device_t dev); 95144783Simpstatic int mse_isa_attach(device_t dev); 96138755Simp 97138755Simpstatic device_method_t mse_methods[] = { 98144783Simp DEVMETHOD(device_probe, mse_isa_probe), 99144783Simp DEVMETHOD(device_attach, mse_isa_attach), 100272956Sjhb DEVMETHOD(device_detach, mse_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 { 0x000fd041, "Bus mouse" }, /* PNP0F00 */ 114138755Simp { 0x020fd041, "InPort mouse" }, /* PNP0F02 */ 115138755Simp { 0x0d0fd041, "InPort mouse compatible" }, /* PNP0F0D */ 116138755Simp { 0x110fd041, "Bus mouse compatible" }, /* PNP0F11 */ 117138755Simp { 0x150fd041, "Logitech bus mouse" }, /* PNP0F15 */ 118138755Simp { 0x180fd041, "Logitech bus mouse compatible" },/* PNP0F18 */ 119138755Simp { 0 } 120138755Simp}; 121138755Simp 122138755Simp/* 123138755Simp * Logitech bus mouse definitions 124138755Simp */ 125138755Simp#define MSE_SETUP 0x91 /* What does this mean? */ 126138755Simp /* The definition for the control port */ 127138755Simp /* is as follows: */ 128138755Simp 129138755Simp /* D7 = Mode set flag (1 = active) */ 130138755Simp /* D6,D5 = Mode selection (port A) */ 131138755Simp /* 00 = Mode 0 = Basic I/O */ 132138755Simp /* 01 = Mode 1 = Strobed I/O */ 133138755Simp /* 10 = Mode 2 = Bi-dir bus */ 134138755Simp /* D4 = Port A direction (1 = input)*/ 135138755Simp /* D3 = Port C (upper 4 bits) */ 136138755Simp /* direction. (1 = input) */ 137138755Simp /* D2 = Mode selection (port B & C) */ 138138755Simp /* 0 = Mode 0 = Basic I/O */ 139138755Simp /* 1 = Mode 1 = Strobed I/O */ 140138755Simp /* D1 = Port B direction (1 = input)*/ 141138755Simp /* D0 = Port C (lower 4 bits) */ 142138755Simp /* direction. (1 = input) */ 143138755Simp 144138755Simp /* So 91 means Basic I/O on all 3 ports,*/ 145138755Simp /* Port A is an input port, B is an */ 146138755Simp /* output port, C is split with upper */ 147138755Simp /* 4 bits being an output port and lower*/ 148138755Simp /* 4 bits an input port, and enable the */ 149138755Simp /* sucker. */ 150138755Simp /* Courtesy Intel 8255 databook. Lars */ 151138755Simp#define MSE_HOLD 0x80 152138755Simp#define MSE_RXLOW 0x00 153138755Simp#define MSE_RXHIGH 0x20 154138755Simp#define MSE_RYLOW 0x40 155138755Simp#define MSE_RYHIGH 0x60 156138755Simp#define MSE_DISINTR 0x10 157138755Simp#define MSE_INTREN 0x00 158138755Simp 159138755Simpstatic int mse_probelogi(device_t dev, mse_softc_t *sc); 160272956Sjhbstatic void mse_disablelogi(struct resource *port); 161272956Sjhbstatic void mse_getlogi(struct resource *port, int *dx, int *dy, 162272956Sjhb int *but); 163272956Sjhbstatic void mse_enablelogi(struct resource *port); 164138755Simp 165138755Simp/* 166138755Simp * ATI Inport mouse definitions 167138755Simp */ 168138755Simp#define MSE_INPORT_RESET 0x80 169138755Simp#define MSE_INPORT_STATUS 0x00 170138755Simp#define MSE_INPORT_DX 0x01 171138755Simp#define MSE_INPORT_DY 0x02 172138755Simp#define MSE_INPORT_MODE 0x07 173138755Simp#define MSE_INPORT_HOLD 0x20 174138755Simp#define MSE_INPORT_INTREN 0x09 175138755Simp 176138755Simpstatic int mse_probeati(device_t dev, mse_softc_t *sc); 177272956Sjhbstatic void mse_enableati(struct resource *port); 178272956Sjhbstatic void mse_disableati(struct resource *port); 179272956Sjhbstatic void mse_getati(struct resource *port, int *dx, int *dy, 180272956Sjhb int *but); 181138755Simp 182138755Simpstatic struct mse_types mse_types[] = { 183138755Simp { MSE_ATIINPORT, 184138755Simp mse_probeati, mse_enableati, mse_disableati, mse_getati, 185138755Simp { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 186138755Simp { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 187138755Simp { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 188138755Simp { MSE_LOGITECH, 189138755Simp mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, 190138755Simp { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, 191138755Simp { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 192138755Simp { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, 193138755Simp { 0, }, 194138755Simp}; 195138755Simp 196138755Simpstatic int 197144783Simpmse_isa_probe(device_t dev) 198138755Simp{ 199138755Simp mse_softc_t *sc; 200138755Simp int error; 201138755Simp int rid; 202138755Simp int i; 203138755Simp 204138755Simp /* check PnP IDs */ 205138755Simp error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids); 206138755Simp if (error == ENXIO) 207138755Simp return error; 208138755Simp 209138755Simp sc = device_get_softc(dev); 210138755Simp rid = 0; 211296137Sjhibbits sc->sc_port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid, 212296137Sjhibbits MSE_IOSIZE, RF_ACTIVE); 213138755Simp if (sc->sc_port == NULL) 214138755Simp return ENXIO; 215138755Simp 216138755Simp /* 217138755Simp * Check for each mouse type in the table. 218138755Simp */ 219138755Simp i = 0; 220138755Simp while (mse_types[i].m_type) { 221138755Simp if ((*mse_types[i].m_probe)(dev, sc)) { 222138755Simp sc->sc_mousetype = mse_types[i].m_type; 223138755Simp sc->sc_enablemouse = mse_types[i].m_enable; 224138755Simp sc->sc_disablemouse = mse_types[i].m_disable; 225138755Simp sc->sc_getmouse = mse_types[i].m_get; 226138755Simp sc->hw = mse_types[i].m_hw; 227138755Simp sc->mode = mse_types[i].m_mode; 228138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, 229138755Simp sc->sc_port); 230138755Simp device_set_desc(dev, "Bus/InPort Mouse"); 231138755Simp return 0; 232138755Simp } 233138755Simp i++; 234138755Simp } 235138755Simp bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port); 236138755Simp return ENXIO; 237138755Simp} 238138755Simp 239138755Simpstatic int 240144783Simpmse_isa_attach(device_t dev) 241138755Simp{ 242138755Simp mse_softc_t *sc; 243138755Simp int rid; 244138755Simp 245138755Simp sc = device_get_softc(dev); 246138755Simp 247138755Simp rid = 0; 248296137Sjhibbits sc->sc_port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid, 249296137Sjhibbits MSE_IOSIZE, RF_ACTIVE); 250138755Simp if (sc->sc_port == NULL) 251138755Simp return ENXIO; 252138755Simp 253138755Simp return (mse_common_attach(dev)); 254138755Simp} 255138755Simp 256138755Simp/* 257138755Simp * Routines for the Logitech mouse. 258138755Simp */ 259138755Simp/* 260138755Simp * Test for a Logitech bus mouse and return 1 if it is. 261138755Simp * (until I know how to use the signature port properly, just disable 262138755Simp * interrupts and return 1) 263138755Simp */ 264138755Simpstatic int 265144783Simpmse_probelogi(device_t dev, mse_softc_t *sc) 266138755Simp{ 267138755Simp 268138755Simp int sig; 269138755Simp 270272956Sjhb bus_write_1(sc->sc_port, MSE_PORTD, MSE_SETUP); 271138755Simp /* set the signature port */ 272272956Sjhb bus_write_1(sc->sc_port, MSE_PORTB, MSE_LOGI_SIG); 273138755Simp 274138755Simp DELAY(30000); /* 30 ms delay */ 275272956Sjhb sig = bus_read_1(sc->sc_port, MSE_PORTB) & 0xFF; 276138755Simp if (sig == MSE_LOGI_SIG) { 277272956Sjhb bus_write_1(sc->sc_port, MSE_PORTC, MSE_DISINTR); 278138755Simp return(1); 279138755Simp } else { 280138755Simp if (bootverbose) 281138755Simp device_printf(dev, "wrong signature %x\n", sig); 282138755Simp return(0); 283138755Simp } 284138755Simp} 285138755Simp 286138755Simp/* 287138755Simp * Initialize Logitech mouse and enable interrupts. 288138755Simp */ 289138755Simpstatic void 290272956Sjhbmse_enablelogi(struct resource *port) 291138755Simp{ 292138755Simp int dx, dy, but; 293138755Simp 294272956Sjhb bus_write_1(port, MSE_PORTD, MSE_SETUP); 295272956Sjhb mse_getlogi(port, &dx, &dy, &but); 296138755Simp} 297138755Simp 298138755Simp/* 299138755Simp * Disable interrupts for Logitech mouse. 300138755Simp */ 301138755Simpstatic void 302272956Sjhbmse_disablelogi(struct resource *port) 303138755Simp{ 304138755Simp 305272956Sjhb bus_write_1(port, MSE_PORTC, MSE_DISINTR); 306138755Simp} 307138755Simp 308138755Simp/* 309138755Simp * Get the current dx, dy and button up/down state. 310138755Simp */ 311138755Simpstatic void 312272956Sjhbmse_getlogi(struct resource *port, int *dx, int *dy, int *but) 313138755Simp{ 314331643Sdim char x, y; 315138755Simp 316272956Sjhb bus_write_1(port, MSE_PORTC, MSE_HOLD | MSE_RXLOW); 317272956Sjhb x = bus_read_1(port, MSE_PORTA); 318138755Simp *but = (x >> 5) & MOUSE_MSC_BUTTONS; 319138755Simp x &= 0xf; 320272956Sjhb bus_write_1(port, MSE_PORTC, MSE_HOLD | MSE_RXHIGH); 321272956Sjhb x |= (bus_read_1(port, MSE_PORTA) << 4); 322272956Sjhb bus_write_1(port, MSE_PORTC, MSE_HOLD | MSE_RYLOW); 323272956Sjhb y = (bus_read_1(port, MSE_PORTA) & 0xf); 324272956Sjhb bus_write_1(port, MSE_PORTC, MSE_HOLD | MSE_RYHIGH); 325272956Sjhb y |= (bus_read_1(port, MSE_PORTA) << 4); 326138755Simp *dx = x; 327138755Simp *dy = y; 328272956Sjhb bus_write_1(port, MSE_PORTC, MSE_INTREN); 329138755Simp} 330138755Simp 331138755Simp/* 332138755Simp * Routines for the ATI Inport bus mouse. 333138755Simp */ 334138755Simp/* 335138755Simp * Test for an ATI Inport bus mouse and return 1 if it is. 336138755Simp * (do not enable interrupts) 337138755Simp */ 338138755Simpstatic int 339144783Simpmse_probeati(device_t dev, mse_softc_t *sc) 340138755Simp{ 341138755Simp int i; 342138755Simp 343138755Simp for (i = 0; i < 2; i++) 344272956Sjhb if (bus_read_1(sc->sc_port, MSE_PORTC) == 0xde) 345138755Simp return (1); 346138755Simp return (0); 347138755Simp} 348138755Simp 349138755Simp/* 350138755Simp * Initialize ATI Inport mouse and enable interrupts. 351138755Simp */ 352138755Simpstatic void 353272956Sjhbmse_enableati(struct resource *port) 354138755Simp{ 355138755Simp 356272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_RESET); 357272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_MODE); 358272956Sjhb bus_write_1(port, MSE_PORTB, MSE_INPORT_INTREN); 359138755Simp} 360138755Simp 361138755Simp/* 362138755Simp * Disable interrupts for ATI Inport mouse. 363138755Simp */ 364138755Simpstatic void 365272956Sjhbmse_disableati(struct resource *port) 366138755Simp{ 367138755Simp 368272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_MODE); 369272956Sjhb bus_write_1(port, MSE_PORTB, 0); 370138755Simp} 371138755Simp 372138755Simp/* 373138755Simp * Get current dx, dy and up/down button state. 374138755Simp */ 375138755Simpstatic void 376272956Sjhbmse_getati(struct resource *port, int *dx, int *dy, int *but) 377138755Simp{ 378144783Simp char byte; 379138755Simp 380272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_MODE); 381272956Sjhb bus_write_1(port, MSE_PORTB, MSE_INPORT_HOLD); 382272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_STATUS); 383272956Sjhb *but = ~bus_read_1(port, MSE_PORTB) & MOUSE_MSC_BUTTONS; 384272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_DX); 385272956Sjhb byte = bus_read_1(port, MSE_PORTB); 386138755Simp *dx = byte; 387272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_DY); 388272956Sjhb byte = bus_read_1(port, MSE_PORTB); 389138755Simp *dy = byte; 390272956Sjhb bus_write_1(port, MSE_PORTA, MSE_INPORT_MODE); 391272956Sjhb bus_write_1(port, MSE_PORTB, MSE_INPORT_INTREN); 392138755Simp} 393