vserver 2.0 rc7
[linux-2.6.git] / drivers / input / gameport / vortex.c
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);