Deleted Added
full compact
joy.c (14873) joy.c (18207)
1/*-
2 * Copyright (c) 1995 Jean-Marc Zucconi
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 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include "joy.h"
30
31#if NJOY > 0
32
1/*-
2 * Copyright (c) 1995 Jean-Marc Zucconi
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 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include "joy.h"
30
31#if NJOY > 0
32
33#include
34
33#include <sys/errno.h>
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/conf.h>
38#include <sys/kernel.h>
39#ifdef DEVFS
40#include <sys/devfsext.h>
41#endif /*DEVFS*/
42
43#include <machine/clock.h>
44#include <machine/joystick.h>
45
46#include <i386/isa/isa.h>
47#include <i386/isa/isa_device.h>
48#include <i386/isa/timerreg.h>
49
50/* The game port can manage 4 buttons and 4 variable resistors (usually 2
51 * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201.
52 * Getting the state of the buttons is done by reading the game port:
53 * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2)
54 * to bits 0-3.
55 * if button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5, 6, 7) is set to 0
56 * to get the value of a resistor, write the value 0xff at port and
57 * wait until the corresponding bit returns to 0.
58 */
59
60
61/* the formulae below only work if u is ``not too large''. See also
62 * the discussion in microtime.s */
63#define usec2ticks(u) (((u) * 19549)>>14)
64#define ticks2usec(u) (((u) * 3433)>>12)
65
66
67#define joypart(d) minor(d)&1
68#define UNIT(d) minor(d)>>1&3
69#ifndef JOY_TIMEOUT
70#define JOY_TIMEOUT 2000 /* 2 milliseconds */
71#endif
72
73static struct {
74 int port;
75 int x_off[2], y_off[2];
76 int timeout[2];
77#ifdef DEVFS
78 void *devfs_token;
79#endif
80} joy[NJOY];
81
82
83static int joyprobe (struct isa_device *);
84static int joyattach (struct isa_device *);
85
86struct isa_driver joydriver = {joyprobe, joyattach, "joy"};
87
88#define CDEV_MAJOR 51
89static d_open_t joyopen;
90static d_close_t joyclose;
91static d_read_t joyread;
92static d_ioctl_t joyioctl;
93
94static struct cdevsw joy_cdevsw =
95 { joyopen, joyclose, joyread, nowrite, /*51*/
96 joyioctl, nostop, nullreset, nodevtotty,/*joystick */
97 seltrue, nommap, NULL, "joy", NULL, -1 };
98
99static int get_tick __P((void));
100
101
102static int
103joyprobe (struct isa_device *dev)
104{
105#ifdef WANT_JOYSTICK_CONNECTED
106 outb (dev->id_iobase, 0xff);
107 DELAY (10000); /* 10 ms delay */
108 return (inb (dev->id_iobase) & 0x0f) != 0x0f;
109#else
110 return 1;
111#endif
112}
113
114static int
115joyattach (struct isa_device *dev)
116{
117 int unit = dev->id_unit;
118
119 joy[unit].port = dev->id_iobase;
120 joy[unit].timeout[0] = joy[unit].timeout[1] = 0;
121 printf("joy%d: joystick\n", unit);
122#ifdef DEVFS
123 joy[dev->id_unit].devfs_token =
124 devfs_add_devswf(&joy_cdevsw, 0, DV_CHR, 0, 0,
125 0600, "joy%d", unit);
126#endif
127 return 1;
128}
129
130static int
131joyopen (dev_t dev, int flags, int fmt, struct proc *p)
132{
133 int unit = UNIT (dev);
134 int i = joypart (dev);
135
136 if (joy[unit].timeout[i])
137 return EBUSY;
138 joy[unit].x_off[i] = joy[unit].y_off[i] = 0;
139 joy[unit].timeout[i] = JOY_TIMEOUT;
140 return 0;
141}
142static int
143joyclose (dev_t dev, int flags, int fmt, struct proc *p)
144{
145 int unit = UNIT (dev);
146 int i = joypart (dev);
147
148 joy[unit].timeout[i] = 0;
149 return 0;
150}
151
152static int
153joyread (dev_t dev, struct uio *uio, int flag)
154{
155 int unit = UNIT(dev);
156 int port = joy[unit].port;
157 int i, t0, t1;
158 int state = 0, x = 0, y = 0;
159 struct joystick c;
160
161 disable_intr ();
162 outb (port, 0xff);
163 t0 = get_tick ();
164 t1 = t0;
165 i = usec2ticks(joy[unit].timeout[joypart(dev)]);
166 while (t0-t1 < i) {
167 state = inb (port);
168 if (joypart(dev) == 1)
169 state >>= 2;
170 t1 = get_tick ();
171 if (t1 > t0)
172 t1 -= timer0_max_count;
173 if (!x && !(state & 0x01))
174 x = t1;
175 if (!y && !(state & 0x02))
176 y = t1;
177 if (x && y)
178 break;
179 }
180 enable_intr ();
181 c.x = x ? joy[unit].x_off[joypart(dev)] + ticks2usec(t0-x) : 0x80000000;
182 c.y = y ? joy[unit].y_off[joypart(dev)] + ticks2usec(t0-y) : 0x80000000;
183 state >>= 4;
184 c.b1 = ~state & 1;
185 c.b2 = ~(state >> 1) & 1;
186 return uiomove ((caddr_t)&c, sizeof(struct joystick), uio);
187}
188
189static int
190joyioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
191{
192 int unit = UNIT (dev);
193 int i = joypart (dev);
194 int x;
195
196 switch (cmd) {
197 case JOY_SETTIMEOUT:
198 x = *(int *) data;
199 if (x < 1 || x > 10000) /* 10ms maximum! */
200 return EINVAL;
201 joy[unit].timeout[i] = x;
202 break;
203 case JOY_GETTIMEOUT:
204 *(int *) data = joy[unit].timeout[i];
205 break;
206 case JOY_SET_X_OFFSET:
207 joy[unit].x_off[i] = *(int *) data;
208 break;
209 case JOY_SET_Y_OFFSET:
210 joy[unit].y_off[i] = *(int *) data;
211 break;
212 case JOY_GET_X_OFFSET:
213 *(int *) data = joy[unit].x_off[i];
214 break;
215 case JOY_GET_Y_OFFSET:
216 *(int *) data = joy[unit].y_off[i];
217 break;
218 default:
219 return ENXIO;
220 }
221 return 0;
222}
223
224static int
225get_tick ()
226{
227 int low, high;
228
229 outb (TIMER_MODE, TIMER_SEL0);
230 low = inb (TIMER_CNTR0);
231 high = inb (TIMER_CNTR0);
232
233 return (high << 8) | low;
234}
235
236
237static joy_devsw_installed = 0;
238
239static void joy_drvinit(void *unused)
240{
241 dev_t dev;
242
243 if( ! joy_devsw_installed ) {
244 dev = makedev(CDEV_MAJOR,0);
245 cdevsw_add(&dev,&joy_cdevsw,NULL);
246 joy_devsw_installed = 1;
247 }
248}
249
250SYSINIT(joydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,joy_drvinit,NULL)
251
252#ifdef JOY_MODULE
253
254#include <sys/exec.h>
255#include <sys/sysent.h>
256#include <sys/sysproto.h>
257#include <sys/lkm.h>
258
259MOD_DEV (joy, LM_DT_CHAR, CDEV_MAJOR, &joy_cdevsw);
260
261static struct isa_device dev = {0, &joydriver, IO_GAME, 0, -1, (caddr_t) 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
262
263int
264joy_load (struct lkm_table *lkmtp, int cmd)
265{
266 if (joyprobe (&dev)) {
267 joyattach (&dev);
268/* joy_drvinit (0);*/
269 uprintf ("Joystick driver loaded\n");
270 return 0;
271 } else {
272 uprintf ("Joystick driver: probe failed\n");
273 return 1;
274 }
275}
276
277int
278joy_unload (struct lkm_table *lkmtp, int cmd)
279{
280 uprintf ("Joystick driver unloaded\n");
281 return 0;
282}
283int
284joy_stat (struct lkm_table *lkmtp, int cmd)
285{
286 return 0;
287}
288int
289joy_mod (struct lkm_table *lkmtp, int cmd, int ver)
290{
291#define _module joy_module
292 DISPATCH(lkmtp, cmd, ver, joy_load, joy_unload, joy_stat);
293}
294
295#endif /* JOY_MODULE */
296
297
298#endif /* NJOY > 0 */
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/conf.h>
37#include <sys/kernel.h>
38#ifdef DEVFS
39#include <sys/devfsext.h>
40#endif /*DEVFS*/
41
42#include <machine/clock.h>
43#include <machine/joystick.h>
44
45#include <i386/isa/isa.h>
46#include <i386/isa/isa_device.h>
47#include <i386/isa/timerreg.h>
48
49/* The game port can manage 4 buttons and 4 variable resistors (usually 2
50 * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201.
51 * Getting the state of the buttons is done by reading the game port:
52 * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2)
53 * to bits 0-3.
54 * if button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5, 6, 7) is set to 0
55 * to get the value of a resistor, write the value 0xff at port and
56 * wait until the corresponding bit returns to 0.
57 */
58
59
60/* the formulae below only work if u is ``not too large''. See also
61 * the discussion in microtime.s */
62#define usec2ticks(u) (((u) * 19549)>>14)
63#define ticks2usec(u) (((u) * 3433)>>12)
64
65
66#define joypart(d) minor(d)&1
67#define UNIT(d) minor(d)>>1&3
68#ifndef JOY_TIMEOUT
69#define JOY_TIMEOUT 2000 /* 2 milliseconds */
70#endif
71
72static struct {
73 int port;
74 int x_off[2], y_off[2];
75 int timeout[2];
76#ifdef DEVFS
77 void *devfs_token;
78#endif
79} joy[NJOY];
80
81
82static int joyprobe (struct isa_device *);
83static int joyattach (struct isa_device *);
84
85struct isa_driver joydriver = {joyprobe, joyattach, "joy"};
86
87#define CDEV_MAJOR 51
88static d_open_t joyopen;
89static d_close_t joyclose;
90static d_read_t joyread;
91static d_ioctl_t joyioctl;
92
93static struct cdevsw joy_cdevsw =
94 { joyopen, joyclose, joyread, nowrite, /*51*/
95 joyioctl, nostop, nullreset, nodevtotty,/*joystick */
96 seltrue, nommap, NULL, "joy", NULL, -1 };
97
98static int get_tick __P((void));
99
100
101static int
102joyprobe (struct isa_device *dev)
103{
104#ifdef WANT_JOYSTICK_CONNECTED
105 outb (dev->id_iobase, 0xff);
106 DELAY (10000); /* 10 ms delay */
107 return (inb (dev->id_iobase) & 0x0f) != 0x0f;
108#else
109 return 1;
110#endif
111}
112
113static int
114joyattach (struct isa_device *dev)
115{
116 int unit = dev->id_unit;
117
118 joy[unit].port = dev->id_iobase;
119 joy[unit].timeout[0] = joy[unit].timeout[1] = 0;
120 printf("joy%d: joystick\n", unit);
121#ifdef DEVFS
122 joy[dev->id_unit].devfs_token =
123 devfs_add_devswf(&joy_cdevsw, 0, DV_CHR, 0, 0,
124 0600, "joy%d", unit);
125#endif
126 return 1;
127}
128
129static int
130joyopen (dev_t dev, int flags, int fmt, struct proc *p)
131{
132 int unit = UNIT (dev);
133 int i = joypart (dev);
134
135 if (joy[unit].timeout[i])
136 return EBUSY;
137 joy[unit].x_off[i] = joy[unit].y_off[i] = 0;
138 joy[unit].timeout[i] = JOY_TIMEOUT;
139 return 0;
140}
141static int
142joyclose (dev_t dev, int flags, int fmt, struct proc *p)
143{
144 int unit = UNIT (dev);
145 int i = joypart (dev);
146
147 joy[unit].timeout[i] = 0;
148 return 0;
149}
150
151static int
152joyread (dev_t dev, struct uio *uio, int flag)
153{
154 int unit = UNIT(dev);
155 int port = joy[unit].port;
156 int i, t0, t1;
157 int state = 0, x = 0, y = 0;
158 struct joystick c;
159
160 disable_intr ();
161 outb (port, 0xff);
162 t0 = get_tick ();
163 t1 = t0;
164 i = usec2ticks(joy[unit].timeout[joypart(dev)]);
165 while (t0-t1 < i) {
166 state = inb (port);
167 if (joypart(dev) == 1)
168 state >>= 2;
169 t1 = get_tick ();
170 if (t1 > t0)
171 t1 -= timer0_max_count;
172 if (!x && !(state & 0x01))
173 x = t1;
174 if (!y && !(state & 0x02))
175 y = t1;
176 if (x && y)
177 break;
178 }
179 enable_intr ();
180 c.x = x ? joy[unit].x_off[joypart(dev)] + ticks2usec(t0-x) : 0x80000000;
181 c.y = y ? joy[unit].y_off[joypart(dev)] + ticks2usec(t0-y) : 0x80000000;
182 state >>= 4;
183 c.b1 = ~state & 1;
184 c.b2 = ~(state >> 1) & 1;
185 return uiomove ((caddr_t)&c, sizeof(struct joystick), uio);
186}
187
188static int
189joyioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
190{
191 int unit = UNIT (dev);
192 int i = joypart (dev);
193 int x;
194
195 switch (cmd) {
196 case JOY_SETTIMEOUT:
197 x = *(int *) data;
198 if (x < 1 || x > 10000) /* 10ms maximum! */
199 return EINVAL;
200 joy[unit].timeout[i] = x;
201 break;
202 case JOY_GETTIMEOUT:
203 *(int *) data = joy[unit].timeout[i];
204 break;
205 case JOY_SET_X_OFFSET:
206 joy[unit].x_off[i] = *(int *) data;
207 break;
208 case JOY_SET_Y_OFFSET:
209 joy[unit].y_off[i] = *(int *) data;
210 break;
211 case JOY_GET_X_OFFSET:
212 *(int *) data = joy[unit].x_off[i];
213 break;
214 case JOY_GET_Y_OFFSET:
215 *(int *) data = joy[unit].y_off[i];
216 break;
217 default:
218 return ENXIO;
219 }
220 return 0;
221}
222
223static int
224get_tick ()
225{
226 int low, high;
227
228 outb (TIMER_MODE, TIMER_SEL0);
229 low = inb (TIMER_CNTR0);
230 high = inb (TIMER_CNTR0);
231
232 return (high << 8) | low;
233}
234
235
236static joy_devsw_installed = 0;
237
238static void joy_drvinit(void *unused)
239{
240 dev_t dev;
241
242 if( ! joy_devsw_installed ) {
243 dev = makedev(CDEV_MAJOR,0);
244 cdevsw_add(&dev,&joy_cdevsw,NULL);
245 joy_devsw_installed = 1;
246 }
247}
248
249SYSINIT(joydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,joy_drvinit,NULL)
250
251#ifdef JOY_MODULE
252
253#include <sys/exec.h>
254#include <sys/sysent.h>
255#include <sys/sysproto.h>
256#include <sys/lkm.h>
257
258MOD_DEV (joy, LM_DT_CHAR, CDEV_MAJOR, &joy_cdevsw);
259
260static struct isa_device dev = {0, &joydriver, IO_GAME, 0, -1, (caddr_t) 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
261
262int
263joy_load (struct lkm_table *lkmtp, int cmd)
264{
265 if (joyprobe (&dev)) {
266 joyattach (&dev);
267/* joy_drvinit (0);*/
268 uprintf ("Joystick driver loaded\n");
269 return 0;
270 } else {
271 uprintf ("Joystick driver: probe failed\n");
272 return 1;
273 }
274}
275
276int
277joy_unload (struct lkm_table *lkmtp, int cmd)
278{
279 uprintf ("Joystick driver unloaded\n");
280 return 0;
281}
282int
283joy_stat (struct lkm_table *lkmtp, int cmd)
284{
285 return 0;
286}
287int
288joy_mod (struct lkm_table *lkmtp, int cmd, int ver)
289{
290#define _module joy_module
291 DISPATCH(lkmtp, cmd, ver, joy_load, joy_unload, joy_stat);
292}
293
294#endif /* JOY_MODULE */
295
296
297#endif /* NJOY > 0 */