--- /dev/null
+/*
+ * FM801 gameport driver for Linux
+ *
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gameport.h>
+
+#define PCI_VENDOR_ID_FORTEMEDIA 0x1319
+#define PCI_DEVICE_ID_FM801_GP 0x0802
+
+#define HAVE_COOKED
+
+struct fm801_gp {
+ struct gameport gameport;
+ struct resource *res_port;
+ char phys[32];
+ char name[32];
+};
+
+#ifdef HAVE_COOKED
+static int fm801_gp_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+ unsigned short w;
+
+ w = inw(gameport->io + 2);
+ *buttons = (~w >> 14) & 0x03;
+ axes[0] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
+ w = inw(gameport->io + 4);
+ axes[1] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
+ w = inw(gameport->io + 6);
+ *buttons |= ((~w >> 14) & 0x03) << 2;
+ axes[2] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
+ w = inw(gameport->io + 8);
+ axes[3] = (w == 0xffff) ? -1 : ((w & 0x1fff) << 5);
+ outw(0xff, gameport->io); /* reset */
+
+ return 0;
+}
+#endif
+
+static int fm801_gp_open(struct gameport *gameport, int mode)
+{
+ switch (mode) {
+#ifdef HAVE_COOKED
+ case GAMEPORT_MODE_COOKED:
+ return 0;
+#endif
+ case GAMEPORT_MODE_RAW:
+ return 0;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+ struct fm801_gp *gp;
+
+ if (! (gp = kmalloc(sizeof(*gp), GFP_KERNEL))) {
+ printk("cannot malloc for fm801-gp\n");
+ return -1;
+ }
+ memset(gp, 0, sizeof(*gp));
+
+ gp->gameport.open = fm801_gp_open;
+#ifdef HAVE_COOKED
+ gp->gameport.cooked_read = fm801_gp_cooked_read;
+#endif
+
+ pci_enable_device(pci);
+ gp->gameport.io = pci_resource_start(pci, 0);
+ if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) {
+ kfree(gp);
+ printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f);
+ return -1;
+ }
+
+ gp->gameport.phys = gp->phys;
+ gp->gameport.name = gp->name;
+ gp->gameport.idbus = BUS_PCI;
+ gp->gameport.idvendor = pci->vendor;
+ gp->gameport.idproduct = pci->device;
+
+ pci_set_drvdata(pci, gp);
+
+ outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */
+
+ gameport_register_port(&gp->gameport);
+
+ printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
+ pci->name, pci->slot_name, gp->gameport.speed);
+
+ return 0;
+}
+
+static void __devexit fm801_gp_remove(struct pci_dev *pci)
+{
+ struct fm801_gp *gp = pci_get_drvdata(pci);
+ if (gp) {
+ gameport_unregister_port(&gp->gameport);
+ release_resource(gp->res_port);
+ kfree(gp);
+ }
+}
+
+static struct pci_device_id fm801_gp_id_table[] __devinitdata = {
+ { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+
+static struct pci_driver fm801_gp_driver = {
+ name: "FM801 GP",
+ id_table: fm801_gp_id_table,
+ probe: fm801_gp_probe,
+ remove: fm801_gp_remove,
+};
+
+int __init fm801_gp_init(void)
+{
+ return pci_module_init(&fm801_gp_driver);
+}
+
+void __exit fm801_gp_exit(void)
+{
+ pci_unregister_driver(&fm801_gp_driver);
+}
+
+module_init(fm801_gp_init);
+module_exit(fm801_gp_exit);
+
+MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $
- *
- * Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * Based on the work of:
- * Raymond Ingles
- *
- * Sponsored by SuSE
- */
-
-/*
- * Trident 4DWave and Aureal Vortex gameport driver for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
- */
-
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/gameport.h>
-
-#define PCI_VENDOR_ID_AUREAL 0x12eb
-
-#define PCIGAME_DATA_WAIT 20 /* 20 ms */
-
-#define PCIGAME_4DWAVE 0
-#define PCIGAME_VORTEX 1
-#define PCIGAME_VORTEX2 2
-
-struct pcigame_data {
- int gcr; /* Gameport control register */
- int legacy; /* Legacy port location */
- int axes; /* Axes start */
- int axsize; /* Axis field size */
- int axmax; /* Axis field max value */
- int adcmode; /* Value to enable ADC mode in GCR */
-};
-
-static struct pcigame_data pcigame_data[] __devinitdata =
-{{ 0x00030, 0x00031, 0x00034, 2, 0xffff, 0x80 },
- { 0x1100c, 0x11008, 0x11010, 4, 0x1fff, 0x40 },
- { 0x2880c, 0x28808, 0x28810, 4, 0x1fff, 0x40 },
- { 0 }};
-
-struct pcigame {
- struct gameport gameport;
- struct pci_dev *dev;
- unsigned char *base;
- struct pcigame_data *data;
-};
-
-static unsigned char pcigame_read(struct gameport *gameport)
-{
- struct pcigame *pcigame = gameport->private;
- return readb(pcigame->base + pcigame->data->legacy);
-}
-
-static void pcigame_trigger(struct gameport *gameport)
-{
- struct pcigame *pcigame = gameport->private;
- writeb(0xff, pcigame->base + pcigame->data->legacy);
-}
-
-static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons)
-{
- struct pcigame *pcigame = gameport->private;
- int i;
-
- *buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf;
-
- for (i = 0; i < 4; i++) {
- axes[i] = readw(pcigame->base + pcigame->data->axes + i * pcigame->data->axsize);
- if (axes[i] == pcigame->data->axmax) axes[i] = -1;
- }
-
- return 0;
-}
-
-static int pcigame_open(struct gameport *gameport, int mode)
-{
- struct pcigame *pcigame = gameport->private;
-
- switch (mode) {
- case GAMEPORT_MODE_COOKED:
- writeb(pcigame->data->adcmode, pcigame->base + pcigame->data->gcr);
- wait_ms(PCIGAME_DATA_WAIT);
- return 0;
- case GAMEPORT_MODE_RAW:
- writeb(0, pcigame->base + pcigame->data->gcr);
- return 0;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int __devinit pcigame_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- struct pcigame *pcigame;
- int i;
-
- if (!(pcigame = kmalloc(sizeof(struct pcigame), GFP_KERNEL)))
- return -1;
- memset(pcigame, 0, sizeof(struct pcigame));
-
-
- pcigame->data = pcigame_data + id->driver_data;
-
- pcigame->dev = dev;
- pci_set_drvdata(dev, pcigame);
-
- pcigame->gameport.private = pcigame;
- pcigame->gameport.fuzz = 64;
-
- pcigame->gameport.read = pcigame_read;
- pcigame->gameport.trigger = pcigame_trigger;
- pcigame->gameport.cooked_read = pcigame_cooked_read;
- pcigame->gameport.open = pcigame_open;
-
- for (i = 0; i < 6; i++)
- if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
- break;
-
- pci_enable_device(dev);
-
- pcigame->base = ioremap(pci_resource_start(pcigame->dev, i),
- pci_resource_len(pcigame->dev, i));
-
- gameport_register_port(&pcigame->gameport);
-
- printk(KERN_INFO "gameport%d: %s at pci%02x:%02x.%x speed %d kHz\n",
- pcigame->gameport.number, dev->name, dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), pcigame->gameport.speed);
-
- return 0;
-}
-
-static void __devexit pcigame_remove(struct pci_dev *dev)
-{
- struct pcigame *pcigame = pci_get_drvdata(dev);
- gameport_unregister_port(&pcigame->gameport);
- iounmap(pcigame->base);
- kfree(pcigame);
-}
-
-static struct pci_device_id pcigame_id_table[] __devinitdata =
-{{ PCI_VENDOR_ID_TRIDENT, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE },
- { PCI_VENDOR_ID_TRIDENT, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_4DWAVE },
- { PCI_VENDOR_ID_AUREAL, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX },
- { PCI_VENDOR_ID_AUREAL, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCIGAME_VORTEX2 },
- { 0 }};
-
-static struct pci_driver pcigame_driver = {
- name: "pcigame",
- id_table: pcigame_id_table,
- probe: pcigame_probe,
- remove: __devexit_p(pcigame_remove),
-};
-
-int __init pcigame_init(void)
-{
- return pci_module_init(&pcigame_driver);
-}
-
-void __exit pcigame_exit(void)
-{
- pci_unregister_driver(&pcigame_driver);
-}
-
-module_init(pcigame_init);
-module_exit(pcigame_exit);
-
-MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $
+ *
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ * Based on the work of:
+ * Raymond Ingles
+ */
+
+/*
+ * Trident 4DWave and Aureal Vortex gameport driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gameport.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver");
+MODULE_LICENSE("GPL");
+
+#define VORTEX_GCR 0x0c /* Gameport control register */
+#define VORTEX_LEG 0x08 /* Legacy port location */
+#define VORTEX_AXD 0x10 /* Axes start */
+#define VORTEX_DATA_WAIT 20 /* 20 ms */
+
+struct vortex {
+ struct gameport gameport;
+ struct pci_dev *dev;
+ unsigned char *base;
+ unsigned char *io;
+ char phys[32];
+};
+
+static unsigned char vortex_read(struct gameport *gameport)
+{
+ struct vortex *vortex = gameport->driver;
+ return readb(vortex->io + VORTEX_LEG);
+}
+
+static void vortex_trigger(struct gameport *gameport)
+{
+ struct vortex *vortex = gameport->driver;
+ writeb(0xff, vortex->io + VORTEX_LEG);
+}
+
+static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+ struct vortex *vortex = gameport->driver;
+ int i;
+
+ *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
+
+ for (i = 0; i < 4; i++) {
+ axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32));
+ if (axes[i] == 0x1fff) axes[i] = -1;
+ }
+
+ return 0;
+}
+
+static int vortex_open(struct gameport *gameport, int mode)
+{
+ struct vortex *vortex = gameport->driver;
+
+ switch (mode) {
+ case GAMEPORT_MODE_COOKED:
+ writeb(0x40, vortex->io + VORTEX_GCR);
+ wait_ms(VORTEX_DATA_WAIT);
+ return 0;
+ case GAMEPORT_MODE_RAW:
+ writeb(0x00, vortex->io + VORTEX_GCR);
+ return 0;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ struct vortex *vortex;
+ int i;
+
+ if (!(vortex = kmalloc(sizeof(struct vortex), GFP_KERNEL)))
+ return -1;
+ memset(vortex, 0, sizeof(struct vortex));
+
+ vortex->dev = dev;
+ sprintf(vortex->phys, "pci%s/gameport0", dev->slot_name);
+
+ pci_set_drvdata(dev, vortex);
+
+ vortex->gameport.driver = vortex;
+ vortex->gameport.fuzz = 64;
+
+ vortex->gameport.read = vortex_read;
+ vortex->gameport.trigger = vortex_trigger;
+ vortex->gameport.cooked_read = vortex_cooked_read;
+ vortex->gameport.open = vortex_open;
+
+ vortex->gameport.name = dev->name;
+ vortex->gameport.phys = vortex->phys;
+ vortex->gameport.idbus = BUS_PCI;
+ vortex->gameport.idvendor = dev->vendor;
+ vortex->gameport.idproduct = dev->device;
+
+ for (i = 0; i < 6; i++)
+ if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
+ break;
+
+ pci_enable_device(dev);
+
+ vortex->base = ioremap(pci_resource_start(vortex->dev, i),
+ pci_resource_len(vortex->dev, i));
+ vortex->io = vortex->base + id->driver_data;
+
+ gameport_register_port(&vortex->gameport);
+
+ printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
+ dev->name, dev->slot_name, vortex->gameport.speed);
+
+ return 0;
+}
+
+static void __devexit vortex_remove(struct pci_dev *dev)
+{
+ struct vortex *vortex = pci_get_drvdata(dev);
+ gameport_unregister_port(&vortex->gameport);
+ iounmap(vortex->base);
+ kfree(vortex);
+}
+
+static struct pci_device_id vortex_id_table[] __devinitdata =
+{{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
+ { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
+ { 0 }};
+
+static struct pci_driver vortex_driver = {
+ name: "vortex",
+ id_table: vortex_id_table,
+ probe: vortex_probe,
+ remove: vortex_remove,
+};
+
+int __init vortex_init(void)
+{
+ return pci_module_init(&vortex_driver);
+}
+
+void __exit vortex_exit(void)
+{
+ pci_unregister_driver(&vortex_driver);
+}
+
+module_init(vortex_init);
+module_exit(vortex_exit);