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