Commit 43dcbb87 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Add vortex anf fm801 gameport drivers, remove obsolete pcigame driver.

parent 696fcc30
/*
* 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");
/*
* $Id: pcigame.c,v 1.10 2001/04/26 10:24:46 vojtech Exp $
* $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
*
* Sponsored by SuSE
*/
/*
......@@ -29,8 +27,8 @@
* 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
* 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>
......@@ -44,74 +42,61 @@
#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 */
};
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver");
MODULE_LICENSE("GPL");
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 }};
#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 pcigame {
struct vortex {
struct gameport gameport;
struct pci_dev *dev;
unsigned char *base;
struct pcigame_data *data;
unsigned char *io;
char phys[32];
};
static unsigned char pcigame_read(struct gameport *gameport)
static unsigned char vortex_read(struct gameport *gameport)
{
struct pcigame *pcigame = gameport->private;
return readb(pcigame->base + pcigame->data->legacy);
struct vortex *vortex = gameport->driver;
return readb(vortex->io + VORTEX_LEG);
}
static void pcigame_trigger(struct gameport *gameport)
static void vortex_trigger(struct gameport *gameport)
{
struct pcigame *pcigame = gameport->private;
writeb(0xff, pcigame->base + pcigame->data->legacy);
struct vortex *vortex = gameport->driver;
writeb(0xff, vortex->io + VORTEX_LEG);
}
static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons)
static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
struct pcigame *pcigame = gameport->private;
struct vortex *vortex = gameport->driver;
int i;
*buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf;
*buttons = (~readb(vortex->base + VORTEX_LEG) >> 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;
axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32));
if (axes[i] == 0x1fff) axes[i] = -1;
}
return 0;
}
static int pcigame_open(struct gameport *gameport, int mode)
static int vortex_open(struct gameport *gameport, int mode)
{
struct pcigame *pcigame = gameport->private;
struct vortex *vortex = gameport->driver;
switch (mode) {
case GAMEPORT_MODE_COOKED:
writeb(pcigame->data->adcmode, pcigame->base + pcigame->data->gcr);
wait_ms(PCIGAME_DATA_WAIT);
writeb(0x40, vortex->io + VORTEX_GCR);
wait_ms(VORTEX_DATA_WAIT);
return 0;
case GAMEPORT_MODE_RAW:
writeb(0, pcigame->base + pcigame->data->gcr);
writeb(0x00, vortex->io + VORTEX_GCR);
return 0;
default:
return -1;
......@@ -120,28 +105,33 @@ static int pcigame_open(struct gameport *gameport, int mode)
return 0;
}
static int __devinit pcigame_probe(struct pci_dev *dev, const struct pci_device_id *id)
static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct pcigame *pcigame;
struct vortex *vortex;
int i;
if (!(pcigame = kmalloc(sizeof(struct pcigame), GFP_KERNEL)))
if (!(vortex = kmalloc(sizeof(struct vortex), GFP_KERNEL)))
return -1;
memset(pcigame, 0, sizeof(struct pcigame));
memset(vortex, 0, sizeof(struct vortex));
vortex->dev = dev;
sprintf(vortex->phys, "pci%s/gameport0", dev->slot_name);
pcigame->data = pcigame_data + id->driver_data;
pci_set_drvdata(dev, vortex);
pcigame->dev = dev;
pci_set_drvdata(dev, pcigame);
vortex->gameport.driver = vortex;
vortex->gameport.fuzz = 64;
pcigame->gameport.private = pcigame;
pcigame->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;
pcigame->gameport.read = pcigame_read;
pcigame->gameport.trigger = pcigame_trigger;
pcigame->gameport.cooked_read = pcigame_cooked_read;
pcigame->gameport.open = pcigame_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)
......@@ -149,51 +139,47 @@ static int __devinit pcigame_probe(struct pci_dev *dev, const struct pci_device_
pci_enable_device(dev);
pcigame->base = ioremap(pci_resource_start(pcigame->dev, i),
pci_resource_len(pcigame->dev, i));
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(&pcigame->gameport);
gameport_register_port(&vortex->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);
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 pcigame_remove(struct pci_dev *dev)
static void __devexit vortex_remove(struct pci_dev *dev)
{
struct pcigame *pcigame = pci_get_drvdata(dev);
gameport_unregister_port(&pcigame->gameport);
iounmap(pcigame->base);
kfree(pcigame);
struct vortex *vortex = pci_get_drvdata(dev);
gameport_unregister_port(&vortex->gameport);
iounmap(vortex->base);
kfree(vortex);
}
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 },
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 pcigame_driver = {
name: "pcigame",
id_table: pcigame_id_table,
probe: pcigame_probe,
remove: __devexit_p(pcigame_remove),
static struct pci_driver vortex_driver = {
name: "vortex",
id_table: vortex_id_table,
probe: vortex_probe,
remove: vortex_remove,
};
int __init pcigame_init(void)
int __init vortex_init(void)
{
return pci_module_init(&pcigame_driver);
return pci_module_init(&vortex_driver);
}
void __exit pcigame_exit(void)
void __exit vortex_exit(void)
{
pci_unregister_driver(&pcigame_driver);
pci_unregister_driver(&vortex_driver);
}
module_init(pcigame_init);
module_exit(pcigame_exit);
MODULE_LICENSE("GPL");
module_init(vortex_init);
module_exit(vortex_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment