2 * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
4 * Copyright (c) 1999-2000 Vojtech Pavlik
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
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
)
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
;
74 if (gameport_open(gameport
, NULL
, GAMEPORT_MODE_RAW
))
79 for(i
= 0; i
< 50; i
++) {
80 save_flags(flags
); /* Yes, all CPUs */
83 for(t
= 0; t
< 50; t
++) gameport_read(gameport
);
88 if ((t
= DELTA(t2
,t1
) - DELTA(t3
,t2
)) < tx
) tx
= t
;
91 return 59659 / (tx
< 1 ? 1 : tx
);
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;
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
) {
113 dev
->connect(gameport
, dev
);
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
);
148 void gameport_register_device(struct gameport_dev
*dev
)
150 struct gameport
*gameport
= gameport_list
;
152 dev
->next
= gameport_dev
;
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
;
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
))
184 if (mode
!= GAMEPORT_MODE_RAW
)
196 void gameport_close(struct gameport
*gameport
)
198 gameport
->dev
= NULL
;
199 if (gameport
->close
) gameport
->close(gameport
);