Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 | 2 | /* |
1da177e4 LT |
3 | * Copyright (c) 2001 Vojtech Pavlik |
4 | */ | |
5 | ||
6 | /* | |
7 | * EMU10k1 - SB Live / Audigy - gameport driver for Linux | |
8 | */ | |
9 | ||
1da177e4 LT |
10 | #include <asm/io.h> |
11 | ||
12 | #include <linux/module.h> | |
13 | #include <linux/ioport.h> | |
1da177e4 LT |
14 | #include <linux/gameport.h> |
15 | #include <linux/slab.h> | |
16 | #include <linux/pci.h> | |
17 | ||
18 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |
19 | MODULE_DESCRIPTION("EMU10k1 gameport driver"); | |
20 | MODULE_LICENSE("GPL"); | |
21 | ||
22 | struct emu { | |
23 | struct pci_dev *dev; | |
24 | struct gameport *gameport; | |
25 | int io; | |
26 | int size; | |
27 | }; | |
28 | ||
a9844b18 | 29 | static const struct pci_device_id emu_tbl[] = { |
1da177e4 LT |
30 | |
31 | { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ | |
32 | { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ | |
33 | { 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */ | |
34 | { 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */ | |
35 | { 0, } | |
36 | }; | |
37 | ||
38 | MODULE_DEVICE_TABLE(pci, emu_tbl); | |
39 | ||
5298cc4c | 40 | static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
1da177e4 | 41 | { |
1da177e4 LT |
42 | struct emu *emu; |
43 | struct gameport *port; | |
7aed3fb7 | 44 | int error; |
1da177e4 | 45 | |
a97e148a | 46 | emu = kzalloc(sizeof(struct emu), GFP_KERNEL); |
1da177e4 LT |
47 | port = gameport_allocate_port(); |
48 | if (!emu || !port) { | |
49 | printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); | |
7aed3fb7 DT |
50 | error = -ENOMEM; |
51 | goto err_out_free; | |
1da177e4 LT |
52 | } |
53 | ||
7aed3fb7 DT |
54 | error = pci_enable_device(pdev); |
55 | if (error) | |
56 | goto err_out_free; | |
57 | ||
58 | emu->io = pci_resource_start(pdev, 0); | |
59 | emu->size = pci_resource_len(pdev, 0); | |
60 | ||
1da177e4 LT |
61 | emu->dev = pdev; |
62 | emu->gameport = port; | |
63 | ||
64 | gameport_set_name(port, "EMU10K1"); | |
65 | gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); | |
66 | port->dev.parent = &pdev->dev; | |
7aed3fb7 DT |
67 | port->io = emu->io; |
68 | ||
69 | if (!request_region(emu->io, emu->size, "emu10k1-gp")) { | |
70 | printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n", | |
71 | emu->io, emu->io + emu->size - 1); | |
72 | error = -EBUSY; | |
73 | goto err_out_disable_dev; | |
74 | } | |
1da177e4 LT |
75 | |
76 | pci_set_drvdata(pdev, emu); | |
77 | ||
78 | gameport_register_port(port); | |
79 | ||
80 | return 0; | |
7aed3fb7 DT |
81 | |
82 | err_out_disable_dev: | |
83 | pci_disable_device(pdev); | |
84 | err_out_free: | |
85 | gameport_free_port(port); | |
86 | kfree(emu); | |
87 | return error; | |
1da177e4 LT |
88 | } |
89 | ||
e2619cf7 | 90 | static void emu_remove(struct pci_dev *pdev) |
1da177e4 LT |
91 | { |
92 | struct emu *emu = pci_get_drvdata(pdev); | |
93 | ||
94 | gameport_unregister_port(emu->gameport); | |
95 | release_region(emu->io, emu->size); | |
96 | kfree(emu); | |
d345d970 DT |
97 | |
98 | pci_disable_device(pdev); | |
1da177e4 LT |
99 | } |
100 | ||
101 | static struct pci_driver emu_driver = { | |
102 | .name = "Emu10k1_gameport", | |
103 | .id_table = emu_tbl, | |
104 | .probe = emu_probe, | |
1cb0aa88 | 105 | .remove = emu_remove, |
1da177e4 LT |
106 | }; |
107 | ||
5d066474 | 108 | module_pci_driver(emu_driver); |