diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-27 17:47:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-27 17:47:31 -0400 |
commit | 3e0777b8fa96f7073ed5d13d3bc1d573b766bef9 (patch) | |
tree | 3849e8457dd8f038ab7da025c708e275b43ea9c1 /drivers/input/gameport | |
parent | a94130e00038ebeb2f66901a4a4a9e05a03051c1 (diff) | |
parent | e5119885f00874453e837e3407014b73de2f4741 (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually
Some manual fixups required due to clashes with the PF_FREEZE cleanups.
Diffstat (limited to 'drivers/input/gameport')
-rw-r--r-- | drivers/input/gameport/Kconfig | 14 | ||||
-rw-r--r-- | drivers/input/gameport/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/gameport/cs461x.c | 322 | ||||
-rw-r--r-- | drivers/input/gameport/ns558.c | 12 | ||||
-rw-r--r-- | drivers/input/gameport/vortex.c | 186 |
5 files changed, 6 insertions, 530 deletions
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 1d93f5092904..7524bd7d8b8f 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig | |||
@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 | |||
49 | To compile this driver as a module, choose M here: the | 49 | To compile this driver as a module, choose M here: the |
50 | module will be called emu10k1-gp. | 50 | module will be called emu10k1-gp. |
51 | 51 | ||
52 | config GAMEPORT_VORTEX | ||
53 | tristate "Aureal Vortex, Vortex 2 gameport support" | ||
54 | depends on PCI | ||
55 | help | ||
56 | Say Y here if you have an Aureal Vortex 1 or 2 card and want | ||
57 | to use its gameport. | ||
58 | |||
59 | To compile this driver as a module, choose M here: the | ||
60 | module will be called vortex. | ||
61 | |||
62 | config GAMEPORT_FM801 | 52 | config GAMEPORT_FM801 |
63 | tristate "ForteMedia FM801 gameport support" | 53 | tristate "ForteMedia FM801 gameport support" |
64 | depends on PCI | 54 | depends on PCI |
65 | 55 | ||
66 | config GAMEPORT_CS461X | ||
67 | tristate "Crystal SoundFusion gameport support" | ||
68 | depends on PCI | ||
69 | |||
70 | endif | 56 | endif |
diff --git a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile index 5367b4267adf..b6f6097bd8c4 100644 --- a/drivers/input/gameport/Makefile +++ b/drivers/input/gameport/Makefile | |||
@@ -5,9 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_GAMEPORT) += gameport.o | 7 | obj-$(CONFIG_GAMEPORT) += gameport.o |
8 | obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o | ||
9 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o | 8 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o |
10 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o | 9 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o |
11 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o | 10 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o |
12 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o | 11 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o |
13 | obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o | ||
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c deleted file mode 100644 index d4013ff98623..000000000000 --- a/drivers/input/gameport/cs461x.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | The all defines and part of code (such as cs461x_*) are | ||
3 | contributed from ALSA 0.5.8 sources. | ||
4 | See http://www.alsa-project.org/ for sources | ||
5 | |||
6 | Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/ioport.h> | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/gameport.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | MODULE_AUTHOR("Victor Krapivin"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | /* | ||
23 | These options are experimental | ||
24 | |||
25 | #define CS461X_FULL_MAP | ||
26 | */ | ||
27 | |||
28 | |||
29 | #ifndef PCI_VENDOR_ID_CIRRUS | ||
30 | #define PCI_VENDOR_ID_CIRRUS 0x1013 | ||
31 | #endif | ||
32 | #ifndef PCI_DEVICE_ID_CIRRUS_4610 | ||
33 | #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 | ||
34 | #endif | ||
35 | #ifndef PCI_DEVICE_ID_CIRRUS_4612 | ||
36 | #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 | ||
37 | #endif | ||
38 | #ifndef PCI_DEVICE_ID_CIRRUS_4615 | ||
39 | #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 | ||
40 | #endif | ||
41 | |||
42 | /* Registers */ | ||
43 | |||
44 | #define BA0_JSPT 0x00000480 | ||
45 | #define BA0_JSCTL 0x00000484 | ||
46 | #define BA0_JSC1 0x00000488 | ||
47 | #define BA0_JSC2 0x0000048C | ||
48 | #define BA0_JSIO 0x000004A0 | ||
49 | |||
50 | /* Bits for JSPT */ | ||
51 | |||
52 | #define JSPT_CAX 0x00000001 | ||
53 | #define JSPT_CAY 0x00000002 | ||
54 | #define JSPT_CBX 0x00000004 | ||
55 | #define JSPT_CBY 0x00000008 | ||
56 | #define JSPT_BA1 0x00000010 | ||
57 | #define JSPT_BA2 0x00000020 | ||
58 | #define JSPT_BB1 0x00000040 | ||
59 | #define JSPT_BB2 0x00000080 | ||
60 | |||
61 | /* Bits for JSCTL */ | ||
62 | |||
63 | #define JSCTL_SP_MASK 0x00000003 | ||
64 | #define JSCTL_SP_SLOW 0x00000000 | ||
65 | #define JSCTL_SP_MEDIUM_SLOW 0x00000001 | ||
66 | #define JSCTL_SP_MEDIUM_FAST 0x00000002 | ||
67 | #define JSCTL_SP_FAST 0x00000003 | ||
68 | #define JSCTL_ARE 0x00000004 | ||
69 | |||
70 | /* Data register pairs masks */ | ||
71 | |||
72 | #define JSC1_Y1V_MASK 0x0000FFFF | ||
73 | #define JSC1_X1V_MASK 0xFFFF0000 | ||
74 | #define JSC1_Y1V_SHIFT 0 | ||
75 | #define JSC1_X1V_SHIFT 16 | ||
76 | #define JSC2_Y2V_MASK 0x0000FFFF | ||
77 | #define JSC2_X2V_MASK 0xFFFF0000 | ||
78 | #define JSC2_Y2V_SHIFT 0 | ||
79 | #define JSC2_X2V_SHIFT 16 | ||
80 | |||
81 | /* JS GPIO */ | ||
82 | |||
83 | #define JSIO_DAX 0x00000001 | ||
84 | #define JSIO_DAY 0x00000002 | ||
85 | #define JSIO_DBX 0x00000004 | ||
86 | #define JSIO_DBY 0x00000008 | ||
87 | #define JSIO_AXOE 0x00000010 | ||
88 | #define JSIO_AYOE 0x00000020 | ||
89 | #define JSIO_BXOE 0x00000040 | ||
90 | #define JSIO_BYOE 0x00000080 | ||
91 | |||
92 | /* | ||
93 | The card initialization code is obfuscated; the module cs461x | ||
94 | need to be loaded after ALSA modules initialized and something | ||
95 | played on the CS 4610 chip (see sources for details of CS4610 | ||
96 | initialization code from ALSA) | ||
97 | */ | ||
98 | |||
99 | /* Card specific definitions */ | ||
100 | |||
101 | #define CS461X_BA0_SIZE 0x2000 | ||
102 | #define CS461X_BA1_DATA0_SIZE 0x3000 | ||
103 | #define CS461X_BA1_DATA1_SIZE 0x3800 | ||
104 | #define CS461X_BA1_PRG_SIZE 0x7000 | ||
105 | #define CS461X_BA1_REG_SIZE 0x0100 | ||
106 | |||
107 | #define BA1_SP_DMEM0 0x00000000 | ||
108 | #define BA1_SP_DMEM1 0x00010000 | ||
109 | #define BA1_SP_PMEM 0x00020000 | ||
110 | #define BA1_SP_REG 0x00030000 | ||
111 | |||
112 | #define BA1_DWORD_SIZE (13 * 1024 + 512) | ||
113 | #define BA1_MEMORY_COUNT 3 | ||
114 | |||
115 | /* | ||
116 | Only one CS461x card is still suppoted; the code requires | ||
117 | redesign to avoid this limitatuion. | ||
118 | */ | ||
119 | |||
120 | static unsigned long ba0_addr; | ||
121 | static unsigned int __iomem *ba0; | ||
122 | |||
123 | #ifdef CS461X_FULL_MAP | ||
124 | static unsigned long ba1_addr; | ||
125 | static union ba1_t { | ||
126 | struct { | ||
127 | unsigned int __iomem *data0; | ||
128 | unsigned int __iomem *data1; | ||
129 | unsigned int __iomem *pmem; | ||
130 | unsigned int __iomem *reg; | ||
131 | } name; | ||
132 | unsigned int __iomem *idx[4]; | ||
133 | } ba1; | ||
134 | |||
135 | static void cs461x_poke(unsigned long reg, unsigned int val) | ||
136 | { | ||
137 | writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
138 | } | ||
139 | |||
140 | static unsigned int cs461x_peek(unsigned long reg) | ||
141 | { | ||
142 | return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
143 | } | ||
144 | |||
145 | #endif | ||
146 | |||
147 | static void cs461x_pokeBA0(unsigned long reg, unsigned int val) | ||
148 | { | ||
149 | writel(val, &ba0[reg >> 2]); | ||
150 | } | ||
151 | |||
152 | static unsigned int cs461x_peekBA0(unsigned long reg) | ||
153 | { | ||
154 | return readl(&ba0[reg >> 2]); | ||
155 | } | ||
156 | |||
157 | static int cs461x_free(struct pci_dev *pdev) | ||
158 | { | ||
159 | struct gameport *port = pci_get_drvdata(pdev); | ||
160 | |||
161 | if (port) | ||
162 | gameport_unregister_port(port); | ||
163 | |||
164 | if (ba0) iounmap(ba0); | ||
165 | #ifdef CS461X_FULL_MAP | ||
166 | if (ba1.name.data0) iounmap(ba1.name.data0); | ||
167 | if (ba1.name.data1) iounmap(ba1.name.data1); | ||
168 | if (ba1.name.pmem) iounmap(ba1.name.pmem); | ||
169 | if (ba1.name.reg) iounmap(ba1.name.reg); | ||
170 | #endif | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void cs461x_gameport_trigger(struct gameport *gameport) | ||
175 | { | ||
176 | cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); | ||
177 | } | ||
178 | |||
179 | static unsigned char cs461x_gameport_read(struct gameport *gameport) | ||
180 | { | ||
181 | return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); | ||
182 | } | ||
183 | |||
184 | static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
185 | { | ||
186 | unsigned js1, js2, jst; | ||
187 | |||
188 | js1 = cs461x_peekBA0(BA0_JSC1); | ||
189 | js2 = cs461x_peekBA0(BA0_JSC2); | ||
190 | jst = cs461x_peekBA0(BA0_JSPT); | ||
191 | |||
192 | *buttons = (~jst >> 4) & 0x0F; | ||
193 | |||
194 | axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; | ||
195 | axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; | ||
196 | axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; | ||
197 | axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; | ||
198 | |||
199 | for(jst=0;jst<4;++jst) | ||
200 | if(axes[jst]==0xFFFF) axes[jst] = -1; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int cs461x_gameport_open(struct gameport *gameport, int mode) | ||
205 | { | ||
206 | switch (mode) { | ||
207 | case GAMEPORT_MODE_COOKED: | ||
208 | case GAMEPORT_MODE_RAW: | ||
209 | return 0; | ||
210 | default: | ||
211 | return -1; | ||
212 | } | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct pci_device_id cs461x_pci_tbl[] = { | ||
217 | { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ | ||
218 | { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ | ||
219 | { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ | ||
220 | { 0, } | ||
221 | }; | ||
222 | MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); | ||
223 | |||
224 | static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
225 | { | ||
226 | int rc; | ||
227 | struct gameport* port; | ||
228 | |||
229 | rc = pci_enable_device(pdev); | ||
230 | if (rc) { | ||
231 | printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", | ||
232 | pdev->bus->number, pdev->devfn, rc); | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | ba0_addr = pci_resource_start(pdev, 0); | ||
237 | #ifdef CS461X_FULL_MAP | ||
238 | ba1_addr = pci_resource_start(pdev, 1); | ||
239 | #endif | ||
240 | if (ba0_addr == 0 || ba0_addr == ~0 | ||
241 | #ifdef CS461X_FULL_MAP | ||
242 | || ba1_addr == 0 || ba1_addr == ~0 | ||
243 | #endif | ||
244 | ) { | ||
245 | printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); | ||
246 | #ifdef CS461X_FULL_MAP | ||
247 | printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); | ||
248 | #endif | ||
249 | cs461x_free(pdev); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); | ||
254 | #ifdef CS461X_FULL_MAP | ||
255 | ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); | ||
256 | ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); | ||
257 | ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); | ||
258 | ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); | ||
259 | |||
260 | if (ba0 == NULL || ba1.name.data0 == NULL || | ||
261 | ba1.name.data1 == NULL || ba1.name.pmem == NULL || | ||
262 | ba1.name.reg == NULL) { | ||
263 | cs461x_free(pdev); | ||
264 | return -ENOMEM; | ||
265 | } | ||
266 | #else | ||
267 | if (ba0 == NULL) { | ||
268 | cs461x_free(pdev); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | if (!(port = gameport_allocate_port())) { | ||
274 | printk(KERN_ERR "cs461x: Memory allocation failed\n"); | ||
275 | cs461x_free(pdev); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | |||
279 | pci_set_drvdata(pdev, port); | ||
280 | |||
281 | port->open = cs461x_gameport_open; | ||
282 | port->trigger = cs461x_gameport_trigger; | ||
283 | port->read = cs461x_gameport_read; | ||
284 | port->cooked_read = cs461x_gameport_cooked_read; | ||
285 | |||
286 | gameport_set_name(port, "CS416x"); | ||
287 | gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); | ||
288 | port->dev.parent = &pdev->dev; | ||
289 | |||
290 | cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? | ||
291 | cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); | ||
292 | |||
293 | gameport_register_port(port); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void __devexit cs461x_pci_remove(struct pci_dev *pdev) | ||
299 | { | ||
300 | cs461x_free(pdev); | ||
301 | } | ||
302 | |||
303 | static struct pci_driver cs461x_pci_driver = { | ||
304 | .name = "CS461x_gameport", | ||
305 | .id_table = cs461x_pci_tbl, | ||
306 | .probe = cs461x_pci_probe, | ||
307 | .remove = __devexit_p(cs461x_pci_remove), | ||
308 | }; | ||
309 | |||
310 | static int __init cs461x_init(void) | ||
311 | { | ||
312 | return pci_register_driver(&cs461x_pci_driver); | ||
313 | } | ||
314 | |||
315 | static void __exit cs461x_exit(void) | ||
316 | { | ||
317 | pci_unregister_driver(&cs461x_pci_driver); | ||
318 | } | ||
319 | |||
320 | module_init(cs461x_init); | ||
321 | module_exit(cs461x_exit); | ||
322 | |||
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 7c5c6318eeb9..1ab5f2dc8a2a 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
@@ -258,18 +258,18 @@ static int __init ns558_init(void) | |||
258 | { | 258 | { |
259 | int i = 0; | 259 | int i = 0; |
260 | 260 | ||
261 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
262 | pnp_registered = 1; | ||
263 | |||
261 | /* | 264 | /* |
262 | * Probe ISA ports first so that PnP gets to choose free port addresses | 265 | * Probe ISA ports after PnP, so that PnP ports that are already |
263 | * not occupied by the ISA ports. | 266 | * enabled get detected as PnP. This may be suboptimal in multi-device |
267 | * configurations, but saves hassle with simple setups. | ||
264 | */ | 268 | */ |
265 | 269 | ||
266 | while (ns558_isa_portlist[i]) | 270 | while (ns558_isa_portlist[i]) |
267 | ns558_isa_probe(ns558_isa_portlist[i++]); | 271 | ns558_isa_probe(ns558_isa_portlist[i++]); |
268 | 272 | ||
269 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
270 | pnp_registered = 1; | ||
271 | |||
272 | |||
273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; | 273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; |
274 | } | 274 | } |
275 | 275 | ||
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c deleted file mode 100644 index 36b0309c8bf6..000000000000 --- a/drivers/input/gameport/vortex.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * Based on the work of: | ||
7 | * Raymond Ingles | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Trident 4DWave and Aureal Vortex gameport driver for Linux | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | * | ||
29 | * Should you need to contact me, the author, you can do so either by | ||
30 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
31 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
32 | */ | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/ioport.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/gameport.h> | ||
45 | |||
46 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | ||
47 | MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver"); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | #define VORTEX_GCR 0x0c /* Gameport control register */ | ||
51 | #define VORTEX_LEG 0x08 /* Legacy port location */ | ||
52 | #define VORTEX_AXD 0x10 /* Axes start */ | ||
53 | #define VORTEX_DATA_WAIT 20 /* 20 ms */ | ||
54 | |||
55 | struct vortex { | ||
56 | struct gameport *gameport; | ||
57 | struct pci_dev *dev; | ||
58 | unsigned char __iomem *base; | ||
59 | unsigned char __iomem *io; | ||
60 | }; | ||
61 | |||
62 | static unsigned char vortex_read(struct gameport *gameport) | ||
63 | { | ||
64 | struct vortex *vortex = gameport->port_data; | ||
65 | return readb(vortex->io + VORTEX_LEG); | ||
66 | } | ||
67 | |||
68 | static void vortex_trigger(struct gameport *gameport) | ||
69 | { | ||
70 | struct vortex *vortex = gameport->port_data; | ||
71 | writeb(0xff, vortex->io + VORTEX_LEG); | ||
72 | } | ||
73 | |||
74 | static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
75 | { | ||
76 | struct vortex *vortex = gameport->port_data; | ||
77 | int i; | ||
78 | |||
79 | *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf; | ||
80 | |||
81 | for (i = 0; i < 4; i++) { | ||
82 | axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); | ||
83 | if (axes[i] == 0x1fff) axes[i] = -1; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int vortex_open(struct gameport *gameport, int mode) | ||
90 | { | ||
91 | struct vortex *vortex = gameport->port_data; | ||
92 | |||
93 | switch (mode) { | ||
94 | case GAMEPORT_MODE_COOKED: | ||
95 | writeb(0x40, vortex->io + VORTEX_GCR); | ||
96 | msleep(VORTEX_DATA_WAIT); | ||
97 | return 0; | ||
98 | case GAMEPORT_MODE_RAW: | ||
99 | writeb(0x00, vortex->io + VORTEX_GCR); | ||
100 | return 0; | ||
101 | default: | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
109 | { | ||
110 | struct vortex *vortex; | ||
111 | struct gameport *port; | ||
112 | int i; | ||
113 | |||
114 | vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL); | ||
115 | port = gameport_allocate_port(); | ||
116 | if (!vortex || !port) { | ||
117 | printk(KERN_ERR "vortex: Memory allocation failed.\n"); | ||
118 | kfree(vortex); | ||
119 | gameport_free_port(port); | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | |||
123 | for (i = 0; i < 6; i++) | ||
124 | if (~pci_resource_flags(dev, i) & IORESOURCE_IO) | ||
125 | break; | ||
126 | |||
127 | pci_enable_device(dev); | ||
128 | |||
129 | vortex->dev = dev; | ||
130 | vortex->gameport = port; | ||
131 | vortex->base = ioremap(pci_resource_start(vortex->dev, i), | ||
132 | pci_resource_len(vortex->dev, i)); | ||
133 | vortex->io = vortex->base + id->driver_data; | ||
134 | |||
135 | pci_set_drvdata(dev, vortex); | ||
136 | |||
137 | port->port_data = vortex; | ||
138 | port->fuzz = 64; | ||
139 | |||
140 | gameport_set_name(port, "AU88x0"); | ||
141 | gameport_set_phys(port, "pci%s/gameport0", pci_name(dev)); | ||
142 | port->dev.parent = &dev->dev; | ||
143 | port->read = vortex_read; | ||
144 | port->trigger = vortex_trigger; | ||
145 | port->cooked_read = vortex_cooked_read; | ||
146 | port->open = vortex_open; | ||
147 | |||
148 | gameport_register_port(port); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void __devexit vortex_remove(struct pci_dev *dev) | ||
154 | { | ||
155 | struct vortex *vortex = pci_get_drvdata(dev); | ||
156 | |||
157 | gameport_unregister_port(vortex->gameport); | ||
158 | iounmap(vortex->base); | ||
159 | kfree(vortex); | ||
160 | } | ||
161 | |||
162 | static struct pci_device_id vortex_id_table[] = { | ||
163 | { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 }, | ||
164 | { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 }, | ||
165 | { 0 } | ||
166 | }; | ||
167 | |||
168 | static struct pci_driver vortex_driver = { | ||
169 | .name = "vortex_gameport", | ||
170 | .id_table = vortex_id_table, | ||
171 | .probe = vortex_probe, | ||
172 | .remove = __devexit_p(vortex_remove), | ||
173 | }; | ||
174 | |||
175 | static int __init vortex_init(void) | ||
176 | { | ||
177 | return pci_register_driver(&vortex_driver); | ||
178 | } | ||
179 | |||
180 | static void __exit vortex_exit(void) | ||
181 | { | ||
182 | pci_unregister_driver(&vortex_driver); | ||
183 | } | ||
184 | |||
185 | module_init(vortex_init); | ||
186 | module_exit(vortex_exit); | ||