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