2 * Generic gameport layer
4 * Copyright (c) 1999-2002 Vojtech Pavlik
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
14 #include <linux/module.h>
15 #include <linux/ioport.h>
16 #include <linux/init.h>
17 #include <linux/gameport.h>
18 #include <linux/slab.h>
19 #include <linux/stddef.h>
20 #include <linux/delay.h>
22 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
23 MODULE_DESCRIPTION("Generic gameport layer");
24 MODULE_LICENSE("GPL");
26 EXPORT_SYMBOL(gameport_register_port
);
27 EXPORT_SYMBOL(gameport_unregister_port
);
28 EXPORT_SYMBOL(gameport_register_device
);
29 EXPORT_SYMBOL(gameport_unregister_device
);
30 EXPORT_SYMBOL(gameport_open
);
31 EXPORT_SYMBOL(gameport_close
);
32 EXPORT_SYMBOL(gameport_rescan
);
33 EXPORT_SYMBOL(gameport_cooked_read
);
35 static LIST_HEAD(gameport_list
);
36 static LIST_HEAD(gameport_dev_list
);
40 #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
41 #define GET_TIME(x) do { x = get_time_pit(); } while (0)
43 static unsigned int get_time_pit(void)
45 extern spinlock_t i8253_lock
;
49 spin_lock_irqsave(&i8253_lock
, flags
);
52 count
|= inb_p(0x40) << 8;
53 spin_unlock_irqrestore(&i8253_lock
, flags
);
61 * gameport_measure_speed() measures the gameport i/o speed.
64 static int gameport_measure_speed(struct gameport
*gameport
)
68 unsigned int i
, t
, t1
, t2
, t3
, tx
;
71 if (gameport_open(gameport
, NULL
, GAMEPORT_MODE_RAW
))
76 for(i
= 0; i
< 50; i
++) {
77 local_irq_save(flags
);
79 for(t
= 0; t
< 50; t
++) gameport_read(gameport
);
82 local_irq_restore(flags
);
84 if ((t
= DELTA(t2
,t1
) - DELTA(t3
,t2
)) < tx
) tx
= t
;
87 gameport_close(gameport
);
88 return 59659 / (tx
< 1 ? 1 : tx
);
92 unsigned int j
, t
= 0;
94 j
= jiffies
; while (j
== jiffies
);
95 j
= jiffies
; while (j
== jiffies
) { t
++; gameport_read(gameport
); }
97 gameport_close(gameport
);
103 static void gameport_find_dev(struct gameport
*gameport
)
105 struct gameport_dev
*dev
;
107 list_for_each_entry(dev
, &gameport_dev_list
, node
) {
111 dev
->connect(gameport
, dev
);
115 void gameport_rescan(struct gameport
*gameport
)
117 gameport_close(gameport
);
118 gameport_find_dev(gameport
);
121 void gameport_register_port(struct gameport
*gameport
)
123 list_add_tail(&gameport
->node
, &gameport_list
);
124 gameport
->speed
= gameport_measure_speed(gameport
);
125 gameport_find_dev(gameport
);
128 void gameport_unregister_port(struct gameport
*gameport
)
130 list_del_init(&gameport
->node
);
131 if (gameport
->dev
&& gameport
->dev
->disconnect
)
132 gameport
->dev
->disconnect(gameport
);
135 void gameport_register_device(struct gameport_dev
*dev
)
137 struct gameport
*gameport
;
139 list_add_tail(&dev
->node
, &gameport_dev_list
);
140 list_for_each_entry(gameport
, &gameport_list
, node
)
141 if (!gameport
->dev
&& dev
->connect
)
142 dev
->connect(gameport
, dev
);
145 void gameport_unregister_device(struct gameport_dev
*dev
)
147 struct gameport
*gameport
;
149 list_del_init(&dev
->node
);
150 list_for_each_entry(gameport
, &gameport_list
, node
) {
151 if (gameport
->dev
== dev
&& dev
->disconnect
)
152 dev
->disconnect(gameport
);
153 gameport_find_dev(gameport
);
157 int gameport_open(struct gameport
*gameport
, struct gameport_dev
*dev
, int mode
)
159 if (gameport
->open
) {
160 if (gameport
->open(gameport
, mode
))
163 if (mode
!= GAMEPORT_MODE_RAW
)
175 void gameport_close(struct gameport
*gameport
)
177 gameport
->dev
= NULL
;
179 gameport
->close(gameport
);