xref: /linux/drivers/input/gameport/emu10k1-gp.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  Copyright (c) 2001 Vojtech Pavlik
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds /*
71da177e4SLinus Torvalds  * EMU10k1 - SB Live / Audigy - gameport driver for Linux
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include <asm/io.h>
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds #include <linux/ioport.h>
141da177e4SLinus Torvalds #include <linux/gameport.h>
151da177e4SLinus Torvalds #include <linux/slab.h>
161da177e4SLinus Torvalds #include <linux/pci.h>
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
191da177e4SLinus Torvalds MODULE_DESCRIPTION("EMU10k1 gameport driver");
201da177e4SLinus Torvalds MODULE_LICENSE("GPL");
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds struct emu {
231da177e4SLinus Torvalds 	struct pci_dev *dev;
241da177e4SLinus Torvalds 	struct gameport *gameport;
251da177e4SLinus Torvalds 	int io;
261da177e4SLinus Torvalds 	int size;
271da177e4SLinus Torvalds };
281da177e4SLinus Torvalds 
29a9844b18SMárton Németh static const struct pci_device_id emu_tbl[] = {
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
321da177e4SLinus Torvalds 	{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
331da177e4SLinus Torvalds 	{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
341da177e4SLinus Torvalds 	{ 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
351da177e4SLinus Torvalds 	{ 0, }
361da177e4SLinus Torvalds };
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, emu_tbl);
391da177e4SLinus Torvalds 
emu_probe(struct pci_dev * pdev,const struct pci_device_id * ent)405298cc4cSBill Pemberton static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
411da177e4SLinus Torvalds {
421da177e4SLinus Torvalds 	struct emu *emu;
431da177e4SLinus Torvalds 	struct gameport *port;
447aed3fb7SDmitry Torokhov 	int error;
451da177e4SLinus Torvalds 
46*5bbcece6SErick Archer 	emu = kzalloc(sizeof(*emu), GFP_KERNEL);
471da177e4SLinus Torvalds 	port = gameport_allocate_port();
481da177e4SLinus Torvalds 	if (!emu || !port) {
491da177e4SLinus Torvalds 		printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
507aed3fb7SDmitry Torokhov 		error = -ENOMEM;
517aed3fb7SDmitry Torokhov 		goto err_out_free;
521da177e4SLinus Torvalds 	}
531da177e4SLinus Torvalds 
547aed3fb7SDmitry Torokhov 	error = pci_enable_device(pdev);
557aed3fb7SDmitry Torokhov 	if (error)
567aed3fb7SDmitry Torokhov 		goto err_out_free;
577aed3fb7SDmitry Torokhov 
587aed3fb7SDmitry Torokhov 	emu->io = pci_resource_start(pdev, 0);
597aed3fb7SDmitry Torokhov 	emu->size = pci_resource_len(pdev, 0);
607aed3fb7SDmitry Torokhov 
611da177e4SLinus Torvalds 	emu->dev = pdev;
621da177e4SLinus Torvalds 	emu->gameport = port;
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds 	gameport_set_name(port, "EMU10K1");
651da177e4SLinus Torvalds 	gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
661da177e4SLinus Torvalds 	port->dev.parent = &pdev->dev;
677aed3fb7SDmitry Torokhov 	port->io = emu->io;
687aed3fb7SDmitry Torokhov 
697aed3fb7SDmitry Torokhov 	if (!request_region(emu->io, emu->size, "emu10k1-gp")) {
707aed3fb7SDmitry Torokhov 		printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n",
717aed3fb7SDmitry Torokhov 			emu->io, emu->io + emu->size - 1);
727aed3fb7SDmitry Torokhov 		error = -EBUSY;
737aed3fb7SDmitry Torokhov 		goto err_out_disable_dev;
747aed3fb7SDmitry Torokhov 	}
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 	pci_set_drvdata(pdev, emu);
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 	gameport_register_port(port);
791da177e4SLinus Torvalds 
801da177e4SLinus Torvalds 	return 0;
817aed3fb7SDmitry Torokhov 
827aed3fb7SDmitry Torokhov  err_out_disable_dev:
837aed3fb7SDmitry Torokhov 	pci_disable_device(pdev);
847aed3fb7SDmitry Torokhov  err_out_free:
857aed3fb7SDmitry Torokhov 	gameport_free_port(port);
867aed3fb7SDmitry Torokhov 	kfree(emu);
877aed3fb7SDmitry Torokhov 	return error;
881da177e4SLinus Torvalds }
891da177e4SLinus Torvalds 
emu_remove(struct pci_dev * pdev)90e2619cf7SBill Pemberton static void emu_remove(struct pci_dev *pdev)
911da177e4SLinus Torvalds {
921da177e4SLinus Torvalds 	struct emu *emu = pci_get_drvdata(pdev);
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds 	gameport_unregister_port(emu->gameport);
951da177e4SLinus Torvalds 	release_region(emu->io, emu->size);
961da177e4SLinus Torvalds 	kfree(emu);
97d345d970SDmitry Torokhov 
98d345d970SDmitry Torokhov 	pci_disable_device(pdev);
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds static struct pci_driver emu_driver = {
1021da177e4SLinus Torvalds         .name =         "Emu10k1_gameport",
1031da177e4SLinus Torvalds         .id_table =     emu_tbl,
1041da177e4SLinus Torvalds         .probe =        emu_probe,
1051cb0aa88SBill Pemberton 	.remove =	emu_remove,
1061da177e4SLinus Torvalds };
1071da177e4SLinus Torvalds 
1085d066474SAxel Lin module_pci_driver(emu_driver);
109