Subversion Repositories shark

Rev

Rev 494 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
494 giacomo 1
/*
2
 * Generic gameport layer
3
 *
4
 * Copyright (c) 1999-2002 Vojtech Pavlik
5
 */
6
 
7
/*
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.
11
 */
12
 
13
#include <linuxcomp.h>
14
 
15
#include <asm/io.h>
16
#include <linux/module.h>
17
#include <linux/ioport.h>
18
#include <linux/init.h>
19
#include <linux/gameport.h>
20
#include <linux/slab.h>
21
#include <linux/stddef.h>
22
#include <linux/delay.h>
23
 
24
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
25
MODULE_DESCRIPTION("Generic gameport layer");
26
MODULE_LICENSE("GPL");
27
 
28
EXPORT_SYMBOL(gameport_register_port);
29
EXPORT_SYMBOL(gameport_unregister_port);
30
EXPORT_SYMBOL(gameport_register_device);
31
EXPORT_SYMBOL(gameport_unregister_device);
32
EXPORT_SYMBOL(gameport_open);
33
EXPORT_SYMBOL(gameport_close);
34
EXPORT_SYMBOL(gameport_rescan);
35
EXPORT_SYMBOL(gameport_cooked_read);
36
 
37
static LIST_HEAD(gameport_list);
38
static LIST_HEAD(gameport_dev_list);
39
 
40
#ifdef __i386__
546 mauro 41
/* !!! Added by Nino !!! */
42
extern TIME sys_gettime(struct timespec *t);
43
#define GET_TIME(x)     (x = sys_gettime(NULL))
44
#define DELTA(x,y)      ((y)-(x))
494 giacomo 45
 
546 mauro 46
/*#define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193182/HZ:0))
494 giacomo 47
#define GET_TIME(x)     do { x = get_time_pit(); } while (0)
48
 
49
static unsigned int get_time_pit(void)
50
{
51
        extern spinlock_t i8253_lock;
52
        unsigned long flags;
53
        unsigned int count;
54
 
55
        spin_lock_irqsave(&i8253_lock, flags);
56
        outb_p(0x00, 0x43);
57
        count = inb_p(0x40);
58
        count |= inb_p(0x40) << 8;
59
        spin_unlock_irqrestore(&i8253_lock, flags);
60
 
61
        return count;
546 mauro 62
}*/
494 giacomo 63
 
64
#endif
65
 
66
/*
67
 * gameport_measure_speed() measures the gameport i/o speed.
68
 */
69
 
70
static int gameport_measure_speed(struct gameport *gameport)
71
{
72
#ifdef __i386__
73
 
74
        unsigned int i, t, t1, t2, t3, tx;
75
        unsigned long flags;
76
 
77
        if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
78
                return 0;
79
 
80
        tx = 1 << 30;
81
 
82
        for(i = 0; i < 50; i++) {
83
                local_irq_save(flags);
84
                GET_TIME(t1);
85
                for(t = 0; t < 50; t++) gameport_read(gameport);
86
                GET_TIME(t2);
87
                GET_TIME(t3);
88
                local_irq_restore(flags);
89
                udelay(i * 10);
90
                if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
91
        }
92
 
93
        gameport_close(gameport);
94
        return 59659 / (tx < 1 ? 1 : tx);
95
 
96
#else
97
 
98
        unsigned int j, t = 0;
99
 
100
        j = jiffies; while (j == jiffies);
101
        j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
102
 
103
        gameport_close(gameport);
104
        return t * HZ / 1000;
105
 
106
#endif
107
}
108
 
109
static void gameport_find_dev(struct gameport *gameport)
110
{
111
        struct gameport_dev *dev;
112
 
113
        list_for_each_entry(dev, &gameport_dev_list, node) {
114
                if (gameport->dev)
115
                        break;
116
                if (dev->connect)
117
                        dev->connect(gameport, dev);
118
        }
119
}
120
 
121
void gameport_rescan(struct gameport *gameport)
122
{
123
        gameport_close(gameport);
124
        gameport_find_dev(gameport);
125
}
126
 
127
void gameport_register_port(struct gameport *gameport)
128
{
129
        list_add_tail(&gameport->node, &gameport_list);
130
        gameport->speed = gameport_measure_speed(gameport);
131
        gameport_find_dev(gameport);
132
}
133
 
134
void gameport_unregister_port(struct gameport *gameport)
135
{
136
        list_del_init(&gameport->node);
137
        if (gameport->dev && gameport->dev->disconnect)
138
                gameport->dev->disconnect(gameport);
139
}
140
 
141
void gameport_register_device(struct gameport_dev *dev)
142
{
143
        struct gameport *gameport;
144
 
145
        list_add_tail(&dev->node, &gameport_dev_list);
146
        list_for_each_entry(gameport, &gameport_list, node)
147
                if (!gameport->dev && dev->connect)
148
                        dev->connect(gameport, dev);
149
}
150
 
151
void gameport_unregister_device(struct gameport_dev *dev)
152
{
153
        struct gameport *gameport;
154
 
155
        list_del_init(&dev->node);
156
        list_for_each_entry(gameport, &gameport_list, node) {
157
                if (gameport->dev == dev && dev->disconnect)
158
                        dev->disconnect(gameport);
159
                gameport_find_dev(gameport);
160
        }
161
}
162
 
163
int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
164
{
165
        if (gameport->open) {
166
                if (gameport->open(gameport, mode))
167
                        return -1;
168
        } else {
169
                if (mode != GAMEPORT_MODE_RAW)
170
                        return -1;
171
        }
172
 
173
        if (gameport->dev)
174
                return -1;
175
 
176
        gameport->dev = dev;
177
 
178
        return 0;
179
}
180
 
181
void gameport_close(struct gameport *gameport)
182
{
183
        gameport->dev = NULL;
184
        if (gameport->close)
185
                gameport->close(gameport);
186
}