Annotation of sys/arch/i386/isa/mms.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mms.c,v 1.19 2007/04/10 22:37:17 miod Exp $ */
2: /* $NetBSD: mms.c,v 1.35 2000/01/08 02:57:25 takemura Exp $ */
3:
4: /*-
5: * Copyright (c) 1993, 1994 Charles M. Hannum.
6: * Copyright (c) 1992, 1993 Erik Forsberg.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: *
15: * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18: * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: #include <sys/param.h>
28: #include <sys/systm.h>
29: #include <sys/ioctl.h>
30: #include <sys/device.h>
31:
32: #include <machine/intr.h>
33: #include <machine/bus.h>
34:
35: #include <dev/isa/isavar.h>
36:
37: #include <dev/wscons/wsconsio.h>
38: #include <dev/wscons/wsmousevar.h>
39:
40: #define MMS_ADDR 0 /* offset for register select */
41: #define MMS_DATA 1 /* offset for InPort data */
42: #define MMS_IDENT 2 /* offset for identification register */
43: #define MMS_NPORTS 4
44:
45: struct mms_softc { /* driver status information */
46: struct device sc_dev;
47: void *sc_ih;
48:
49: bus_space_tag_t sc_iot;
50: bus_space_handle_t sc_ioh;
51:
52: int sc_enabled; /* device is open */
53:
54: struct device *sc_wsmousedev;
55: };
56:
57: int mmsprobe(struct device *, void *, void *);
58: void mmsattach(struct device *, struct device *, void *);
59: int mmsintr(void *);
60:
61: struct cfattach mms_ca = {
62: sizeof(struct mms_softc), mmsprobe, mmsattach
63: };
64:
65: int mms_enable(void *);
66: int mms_ioctl(void *, u_long, caddr_t, int, struct proc *);
67: void mms_disable(void *);
68:
69: const struct wsmouse_accessops mms_accessops = {
70: mms_enable,
71: mms_ioctl,
72: mms_disable,
73: };
74:
75: int
76: mmsprobe(struct device *parent, void *match, void *aux)
77: {
78: struct isa_attach_args *ia = aux;
79: bus_space_tag_t iot = ia->ia_iot;
80: bus_space_handle_t ioh;
81: int rv;
82:
83: /* Disallow wildcarded i/o address. */
84: if (ia->ia_iobase == IOBASEUNK)
85: return 0;
86:
87: /* Map the i/o space. */
88: if (bus_space_map(iot, ia->ia_iobase, MMS_NPORTS, 0, &ioh))
89: return 0;
90:
91: rv = 0;
92:
93: /* Read identification register to see if present */
94: if (bus_space_read_1(iot, ioh, MMS_IDENT) != 0xde)
95: goto out;
96:
97: /* Seems it was there; reset. */
98: bus_space_write_1(iot, ioh, MMS_ADDR, 0x87);
99:
100: rv = 1;
101: ia->ia_iosize = MMS_NPORTS;
102: ia->ia_msize = 0;
103:
104: out:
105: bus_space_unmap(iot, ioh, MMS_NPORTS);
106: return rv;
107: }
108:
109: void
110: mmsattach(struct device *parent, struct device *self, void *aux)
111: {
112: struct mms_softc *sc = (void *)self;
113: struct isa_attach_args *ia = aux;
114: bus_space_tag_t iot = ia->ia_iot;
115: bus_space_handle_t ioh;
116: struct wsmousedev_attach_args a;
117:
118: printf("\n");
119:
120: if (bus_space_map(iot, ia->ia_iobase, MMS_NPORTS, 0, &ioh)) {
121: printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
122: return;
123: }
124:
125: /* Other initialization was done by mmsprobe. */
126: sc->sc_iot = iot;
127: sc->sc_ioh = ioh;
128: sc->sc_enabled = 0;
129:
130: sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_PULSE,
131: IPL_TTY, mmsintr, sc, sc->sc_dev.dv_xname);
132:
133: a.accessops = &mms_accessops;
134: a.accesscookie = sc;
135:
136: /*
137: * Attach the wsmouse, saving a handle to it.
138: * Note that we don't need to check this pointer against NULL
139: * here or in psmintr, because if this fails lms_enable() will
140: * never be called, so lmsintr() will never be called.
141: */
142: sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
143: }
144:
145: int
146: mms_enable(void *v)
147: {
148: struct mms_softc *sc = v;
149:
150: if (sc->sc_enabled)
151: return EBUSY;
152:
153: sc->sc_enabled = 1;
154:
155: /* Enable interrupts. */
156: bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_ADDR, 0x07);
157: bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_DATA, 0x09);
158:
159: return 0;
160: }
161:
162: void
163: mms_disable(void *v)
164: {
165: struct mms_softc *sc = v;
166:
167: /* Disable interrupts. */
168: bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_ADDR, 0x87);
169:
170: sc->sc_enabled = 0;
171: }
172:
173: int
174: mms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
175: {
176: #if 0
177: struct mms_softc *sc = v;
178: #endif
179:
180: switch (cmd) {
181: case WSMOUSEIO_GTYPE:
182: *(u_int *)data = WSMOUSE_TYPE_MMS;
183: return (0);
184: }
185: return (-1);
186: }
187:
188: int
189: mmsintr(void *arg)
190: {
191: struct mms_softc *sc = arg;
192: bus_space_tag_t iot = sc->sc_iot;
193: bus_space_handle_t ioh = sc->sc_ioh;
194: u_char status;
195: signed char dx, dy;
196: u_int buttons;
197: int changed;
198:
199: if (!sc->sc_enabled)
200: /* Interrupts are not expected. */
201: return 0;
202:
203: /* Freeze InPort registers (disabling interrupts). */
204: bus_space_write_1(iot, ioh, MMS_ADDR, 0x07);
205: bus_space_write_1(iot, ioh, MMS_DATA, 0x29);
206:
207: bus_space_write_1(iot, ioh, MMS_ADDR, 0x00);
208: status = bus_space_read_1(iot, ioh, MMS_DATA);
209:
210: if (status & 0x40) {
211: bus_space_write_1(iot, ioh, MMS_ADDR, 1);
212: dx = bus_space_read_1(iot, ioh, MMS_DATA);
213: /* Bounding at -127 avoids a bug in XFree86. */
214: dx = (dx == -128) ? -127 : dx;
215:
216: bus_space_write_1(iot, ioh, MMS_ADDR, 2);
217: dy = bus_space_read_1(iot, ioh, MMS_DATA);
218: dy = (dy == -128) ? 127 : -dy;
219: } else
220: dx = dy = 0;
221:
222: /* Unfreeze InPort registers (reenabling interrupts). */
223: bus_space_write_1(iot, ioh, MMS_ADDR, 0x07);
224: bus_space_write_1(iot, ioh, MMS_DATA, 0x09);
225:
226: buttons = ((status & 0x04) ? 0x1 : 0) |
227: ((status & 0x02) ? 0x2 : 0) |
228: ((status & 0x01) ? 0x4 : 0);
229: changed = status & 0x38;
230:
231: if (dx || dy || changed)
232: wsmouse_input(sc->sc_wsmousedev,
233: buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
234:
235: return -1;
236: }
237:
238: struct cfdriver mms_cd = {
239: NULL, "mms", DV_DULL
240: };
CVSweb