[142] | 1 | /* $Id: emu10k1-joy.c 142 2000-04-23 14:55:46Z ktk $ */
|
---|
| 2 |
|
---|
| 3 |
|
---|
| 4 | /*
|
---|
| 5 | **********************************************************************
|
---|
| 6 | * emu10k1-joy.c - Creative EMU10K1 Joystick port driver
|
---|
| 7 | * Copyright 2000 Rui Sousa.
|
---|
| 8 | *
|
---|
| 9 | **********************************************************************
|
---|
| 10 | *
|
---|
| 11 | * Date Author Summary of changes
|
---|
| 12 | * ---- ------ ------------------
|
---|
| 13 | * April 1, 2000 Rui Sousa initial version
|
---|
| 14 | *
|
---|
| 15 | **********************************************************************
|
---|
| 16 | *
|
---|
| 17 | * This program is free software; you can redistribute it and/or
|
---|
| 18 | * modify it under the terms of the GNU General Public License as
|
---|
| 19 | * published by the Free Software Foundation; either version 2 of
|
---|
| 20 | * the License, or (at your option) any later version.
|
---|
| 21 | *
|
---|
| 22 | * This program is distributed in the hope that it will be useful,
|
---|
| 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 25 | * GNU General Public License for more details.
|
---|
| 26 | *
|
---|
| 27 | * You should have received a copy of the GNU General Public
|
---|
| 28 | * License along with this program; if not, write to the Free
|
---|
| 29 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
---|
| 30 | * USA.
|
---|
| 31 | *
|
---|
| 32 | **********************************************************************/
|
---|
| 33 |
|
---|
| 34 | #include <linux/module.h>
|
---|
| 35 | #include <linux/init.h>
|
---|
| 36 | #include <linux/pci.h>
|
---|
| 37 | #include <linux/malloc.h>
|
---|
| 38 | #include <linux/ioport.h>
|
---|
| 39 | #include <linux/list.h>
|
---|
| 40 |
|
---|
| 41 | #include <emu_wrapper.h>
|
---|
| 42 |
|
---|
| 43 | #define DRIVER_VERSION "0.1"
|
---|
| 44 |
|
---|
| 45 | #ifndef PCI_VENDOR_ID_CREATIVE
|
---|
| 46 | #define PCI_VENDOR_ID_CREATIVE 0x1102
|
---|
| 47 | #endif
|
---|
| 48 |
|
---|
| 49 | #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK
|
---|
| 50 | #define PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK 0x7002
|
---|
| 51 | #endif
|
---|
| 52 |
|
---|
| 53 | #define EMU10K1_JOYSTICK_EXTENT 0x8 /* 8 byte I/O space */
|
---|
| 54 |
|
---|
| 55 | #define NR_DEV 5
|
---|
| 56 |
|
---|
| 57 | static int io[NR_DEV] = { 0, };
|
---|
| 58 |
|
---|
| 59 | enum {
|
---|
| 60 | EMU10K1_JOYSTICK = 0
|
---|
| 61 | };
|
---|
| 62 |
|
---|
| 63 | static char *card_names[] = {
|
---|
| 64 | "EMU10K1 Joystick Port"
|
---|
| 65 | };
|
---|
| 66 |
|
---|
| 67 | static struct pci_device_id emu10k1_joy_pci_tbl[] __devinitdata = {
|
---|
| 68 | {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1_JOYSTICK,
|
---|
| 69 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1_JOYSTICK},
|
---|
| 70 | {0,}
|
---|
| 71 | };
|
---|
| 72 |
|
---|
| 73 | MODULE_DEVICE_TABLE(pci, emu10k1_joy_pci_tbl);
|
---|
| 74 |
|
---|
| 75 | struct emu10k1_joy_card {
|
---|
| 76 | struct list_head list;
|
---|
| 77 |
|
---|
| 78 | struct pci_dev *pci_dev;
|
---|
| 79 | unsigned long iobase;
|
---|
| 80 | int addr_changed;
|
---|
| 81 | };
|
---|
| 82 |
|
---|
| 83 | static LIST_HEAD(emu10k1_joy_devs);
|
---|
| 84 | static unsigned int devindex = 0;
|
---|
| 85 |
|
---|
| 86 | /* Driver initialization routine */
|
---|
| 87 | static int __devinit emu10k1_joy_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
|
---|
| 88 | {
|
---|
| 89 | struct emu10k1_joy_card *card;
|
---|
| 90 | u8 chiprev;
|
---|
| 91 |
|
---|
| 92 | if ((card = kmalloc(sizeof(struct emu10k1_joy_card), GFP_KERNEL)) == NULL) {
|
---|
| 93 | printk(KERN_ERR "emu10k1-joy: out of memory\n");
|
---|
| 94 | return -ENOMEM;
|
---|
| 95 | }
|
---|
| 96 | memset(card, 0, sizeof(struct emu10k1_joy_card));
|
---|
| 97 |
|
---|
| 98 | #if LINUX_VERSION_CODE > 0x020320
|
---|
| 99 | if (pci_enable_device(pci_dev)) {
|
---|
| 100 | printk(KERN_ERR "emu10k1-joy: couldn't enable device\n");
|
---|
| 101 | kfree(card);
|
---|
| 102 | return -ENODEV;
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | card->iobase = pci_dev->resource[0].start;
|
---|
| 106 |
|
---|
| 107 | if (request_region(card->iobase, EMU10K1_JOYSTICK_EXTENT, card_names[pci_id->driver_data])
|
---|
| 108 | == NULL) {
|
---|
| 109 | printk(KERN_ERR "emu10k1-joy: %s IO space in use\n",
|
---|
| 110 | card_names[pci_id->driver_data]);
|
---|
| 111 | kfree(card);
|
---|
| 112 | return -ENODEV;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | pci_dev->driver_data = card;
|
---|
| 116 | #else
|
---|
| 117 | card->iobase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
|
---|
| 118 |
|
---|
| 119 | if (check_region(card->iobase, EMU10K1_JOYSTICK_EXTENT)) {
|
---|
| 120 | printk(KERN_ERR "emu10k1-joy: IO space in use\n");
|
---|
| 121 | kfree(card);
|
---|
| 122 | return -ENODEV;
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | request_region(card->iobase, EMU10K1_JOYSTICK_EXTENT, card_names[pci_id->driver_data]);
|
---|
| 126 | #endif
|
---|
| 127 |
|
---|
| 128 | pci_read_config_byte(pci_dev, PCI_REVISION_ID, &chiprev);
|
---|
| 129 |
|
---|
| 130 | printk(KERN_INFO "emu10k1-joy: %s rev %d found at IO 0x%04lx\n",
|
---|
| 131 | card_names[pci_id->driver_data], chiprev, card->iobase);
|
---|
| 132 |
|
---|
| 133 | if (io[devindex]) {
|
---|
| 134 | if ((io[devindex] & ~0x18) != 0x200) {
|
---|
| 135 | printk(KERN_ERR "emu10k1-joy: invalid io value\n");
|
---|
| 136 | release_region(card->iobase, EMU10K1_JOYSTICK_EXTENT);
|
---|
| 137 | kfree(card);
|
---|
| 138 | return -ENODEV;
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | card->addr_changed = 1;
|
---|
| 142 | pci_write_config_dword(pci_dev, PCI_BASE_ADDRESS_0, io[devindex]);
|
---|
| 143 | printk(KERN_INFO "emu10k1-joy: IO ports mirrored at 0x%03x\n", io[devindex]);
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | list_add(&card->list, &emu10k1_joy_devs);
|
---|
| 147 | devindex++;
|
---|
| 148 |
|
---|
| 149 | return 0;
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | static void __devexit emu10k1_joy_remove(struct pci_dev *pci_dev)
|
---|
| 153 | {
|
---|
| 154 |
|
---|
| 155 | #if LINUX_VERSION_CODE > 0x020320
|
---|
| 156 | struct emu10k1_joy_card *card = pci_dev->driver_data;
|
---|
| 157 | #else
|
---|
| 158 | struct emu10k1_joy_card *card =
|
---|
| 159 |
|
---|
| 160 | list_entry(emu10k1_joy_devs.next, struct emu10k1_joy_card, list);
|
---|
| 161 | #endif
|
---|
| 162 | if(card->addr_changed)
|
---|
| 163 | pci_write_config_dword(pci_dev, PCI_BASE_ADDRESS_0, card->iobase);
|
---|
| 164 |
|
---|
| 165 | release_region(card->iobase, EMU10K1_JOYSTICK_EXTENT);
|
---|
| 166 |
|
---|
| 167 | list_del(&card->list);
|
---|
| 168 | kfree(card);
|
---|
| 169 | return;
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | MODULE_PARM(io, "1-" __MODULE_STRING(NR_DEV) "i");
|
---|
| 173 | MODULE_PARM_DESC(io, "sets joystick port address");
|
---|
| 174 | MODULE_AUTHOR("Rui Sousa (Email to: emu10k1-devel@opensource.creative.com)");
|
---|
| 175 | MODULE_DESCRIPTION("Creative EMU10K1 PCI Joystick Port v" DRIVER_VERSION
|
---|
| 176 | "\nCopyright (C) 2000 Rui Sousa");
|
---|
| 177 |
|
---|
| 178 | static struct pci_driver emu10k1_joy_pci_driver = {
|
---|
| 179 | name:"emu10k1 joystick",
|
---|
| 180 | id_table:emu10k1_joy_pci_tbl,
|
---|
| 181 | probe:emu10k1_joy_probe,
|
---|
| 182 | remove:emu10k1_joy_remove,
|
---|
| 183 | };
|
---|
| 184 |
|
---|
| 185 | #if LINUX_VERSION_CODE > 0x020320
|
---|
| 186 | static int __init emu10k1_joy_init_module(void)
|
---|
| 187 | {
|
---|
| 188 | printk(KERN_INFO "Creative EMU10K1 PCI Joystick Port, version " DRIVER_VERSION ", " __TIME__
|
---|
| 189 | " " __DATE__ "\n");
|
---|
| 190 |
|
---|
| 191 | return pci_module_init(&emu10k1_joy_pci_driver);
|
---|
| 192 | }
|
---|
| 193 |
|
---|
| 194 | static void __exit emu10k1_joy_cleanup_module(void)
|
---|
| 195 | {
|
---|
| 196 | pci_unregister_driver(&emu10k1_joy_pci_driver);
|
---|
| 197 | return;
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 | #else
|
---|
| 201 | static int __init emu10k1_joy_init_module(void)
|
---|
| 202 | {
|
---|
| 203 | struct pci_dev *dev = NULL;
|
---|
| 204 | const struct pci_device_id *pci_id = emu10k1_joy_pci_driver.id_table;
|
---|
| 205 |
|
---|
| 206 | printk(KERN_INFO "Creative EMU10K1 PCI Joystick Port, version " DRIVER_VERSION ", " __TIME__
|
---|
| 207 | " " __DATE__ "\n");
|
---|
| 208 |
|
---|
| 209 | if (!pci_present())
|
---|
| 210 | return -ENODEV;
|
---|
| 211 |
|
---|
| 212 | while (pci_id->vendor) {
|
---|
| 213 | while ((dev = pci_find_device(pci_id->vendor, pci_id->device, dev)))
|
---|
| 214 | emu10k1_joy_probe(dev, pci_id);
|
---|
| 215 |
|
---|
| 216 | pci_id++;
|
---|
| 217 | }
|
---|
| 218 | return 0;
|
---|
| 219 | }
|
---|
| 220 |
|
---|
| 221 | static void __exit emu10k1_joy_cleanup_module(void)
|
---|
| 222 | {
|
---|
| 223 | struct emu10k1_joy_card *card;
|
---|
| 224 |
|
---|
| 225 | while (!list_empty(&emu10k1_joy_devs)) {
|
---|
| 226 | card = list_entry(emu10k1_joy_devs.next, struct emu10k1_joy_card, list);
|
---|
| 227 |
|
---|
| 228 | emu10k1_joy_remove(card->pci_dev);
|
---|
| 229 | }
|
---|
| 230 | return;
|
---|
| 231 | }
|
---|
| 232 | #endif
|
---|
| 233 |
|
---|
| 234 | module_init(emu10k1_joy_init_module);
|
---|
| 235 | module_exit(emu10k1_joy_cleanup_module);
|
---|