Linux 2.4.0-test7-pre6
[davej-history.git] / drivers / char / joystick / gameport.c
blob7bff7c2e2e868fca18e7e3ca13884b02ad089a98
1 /*
2 * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
4 * Copyright (c) 1999-2000 Vojtech Pavlik
6 * Sponsored by SuSE
7 */
9 /*
10 * Generic gameport layer
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Should you need to contact me, the author, you can do so either by
29 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
30 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
33 #include <asm/io.h>
34 #include <linux/module.h>
35 #include <linux/ioport.h>
36 #include <linux/init.h>
37 #include <linux/gameport.h>
38 #include <linux/malloc.h>
39 #include <linux/isapnp.h>
40 #include <linux/stddef.h>
41 #include <linux/module.h>
42 #include <linux/gameport.h>
43 #include <linux/delay.h>
45 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
47 EXPORT_SYMBOL(gameport_register_port);
48 EXPORT_SYMBOL(gameport_unregister_port);
49 EXPORT_SYMBOL(gameport_register_device);
50 EXPORT_SYMBOL(gameport_unregister_device);
51 EXPORT_SYMBOL(gameport_open);
52 EXPORT_SYMBOL(gameport_close);
53 EXPORT_SYMBOL(gameport_rescan);
54 EXPORT_SYMBOL(gameport_cooked_read);
56 static struct gameport *gameport_list = NULL;
57 static struct gameport_dev *gameport_dev = NULL;
58 static int gameport_number = 0;
61 * gameport_measure_speed() measures the gameport i/o speed.
64 static int gameport_measure_speed(struct gameport *gameport)
66 #ifdef __i386__
68 #define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
69 #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180L/HZ:0))
71 unsigned int i, t, t1, t2, t3, tx;
72 unsigned long flags;
74 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
75 return 0;
77 tx = 1 << 30;
79 for(i = 0; i < 50; i++) {
80 save_flags(flags); /* Yes, all CPUs */
81 cli();
82 GET_TIME(t1);
83 for(t = 0; t < 50; t++) gameport_read(gameport);
84 GET_TIME(t2);
85 GET_TIME(t3);
86 restore_flags(flags);
87 udelay(i * 10);
88 if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
91 return 59659 / (tx < 1 ? 1 : tx);
93 #else
95 unsigned int j, t = 0;
97 j = jiffies; while (j == jiffies);
98 j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
100 return t * HZ / 1000;
102 #endif
104 gameport_close(gameport);
107 static void gameport_find_dev(struct gameport *gameport)
109 struct gameport_dev *dev = gameport_dev;
111 while (dev && !gameport->dev) {
112 if (dev->connect)
113 dev->connect(gameport, dev);
114 dev = dev->next;
118 void gameport_rescan(struct gameport *gameport)
120 gameport_close(gameport);
121 gameport_find_dev(gameport);
124 void gameport_register_port(struct gameport *gameport)
126 gameport->number = gameport_number++;
127 gameport->next = gameport_list;
128 gameport_list = gameport;
130 gameport->speed = gameport_measure_speed(gameport);
132 gameport_find_dev(gameport);
135 void gameport_unregister_port(struct gameport *gameport)
137 struct gameport **gameportptr = &gameport_list;
139 while (*gameportptr && (*gameportptr != gameport)) gameportptr = &((*gameportptr)->next);
140 *gameportptr = (*gameportptr)->next;
142 if (gameport->dev && gameport->dev->disconnect)
143 gameport->dev->disconnect(gameport);
145 gameport_number--;
148 void gameport_register_device(struct gameport_dev *dev)
150 struct gameport *gameport = gameport_list;
152 dev->next = gameport_dev;
153 gameport_dev = dev;
155 while (gameport) {
156 if (!gameport->dev && dev->connect)
157 dev->connect(gameport, dev);
158 gameport = gameport->next;
162 void gameport_unregister_device(struct gameport_dev *dev)
164 struct gameport_dev **devptr = &gameport_dev;
165 struct gameport *gameport = gameport_list;
167 while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
168 *devptr = (*devptr)->next;
170 while (gameport) {
171 if (gameport->dev == dev && dev->disconnect)
172 dev->disconnect(gameport);
173 gameport_find_dev(gameport);
174 gameport = gameport->next;
178 int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
180 if (gameport->open) {
181 if (gameport->open(gameport, mode))
182 return -1;
183 } else {
184 if (mode != GAMEPORT_MODE_RAW)
185 return -1;
188 if (gameport->dev)
189 return -1;
191 gameport->dev = dev;
193 return 0;
196 void gameport_close(struct gameport *gameport)
198 gameport->dev = NULL;
199 if (gameport->close) gameport->close(gameport);