Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc3 264 lines 7.6 kB view raw
1/* orinoco_pci.c 2 * 3 * Driver for Prism 2.5/3 devices that have a direct PCI interface 4 * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge). 5 * The card contains only one PCI region, which contains all the usual 6 * hermes registers, as well as the COR register. 7 * 8 * Current maintainers are: 9 * Pavel Roskin <proski AT gnu.org> 10 * and David Gibson <hermes AT gibson.dropbear.id.au> 11 * 12 * Some of this code is borrowed from orinoco_plx.c 13 * Copyright (C) 2001 Daniel Barlow <dan AT telent.net> 14 * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing 15 * has been copied from it. linux-wlan-ng-0.1.10 is originally : 16 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. 17 * This file originally written by: 18 * Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com> 19 * And is now maintained by: 20 * (C) Copyright David Gibson, IBM Corp. 2002-2003. 21 * 22 * The contents of this file are subject to the Mozilla Public License 23 * Version 1.1 (the "License"); you may not use this file except in 24 * compliance with the License. You may obtain a copy of the License 25 * at http://www.mozilla.org/MPL/ 26 * 27 * Software distributed under the License is distributed on an "AS IS" 28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 29 * the License for the specific language governing rights and 30 * limitations under the License. 31 * 32 * Alternatively, the contents of this file may be used under the 33 * terms of the GNU General Public License version 2 (the "GPL"), in 34 * which case the provisions of the GPL are applicable instead of the 35 * above. If you wish to allow the use of your version of this file 36 * only under the terms of the GPL and not to allow others to use your 37 * version of this file under the MPL, indicate your decision by 38 * deleting the provisions above and replace them with the notice and 39 * other provisions required by the GPL. If you do not delete the 40 * provisions above, a recipient may use your version of this file 41 * under either the MPL or the GPL. 42 */ 43 44#define DRIVER_NAME "orinoco_pci" 45#define PFX DRIVER_NAME ": " 46 47#include <linux/module.h> 48#include <linux/kernel.h> 49#include <linux/init.h> 50#include <linux/delay.h> 51#include <linux/pci.h> 52 53#include "orinoco.h" 54#include "orinoco_pci.h" 55 56/* Offset of the COR register of the PCI card */ 57#define HERMES_PCI_COR (0x26) 58 59/* Bitmask to reset the card */ 60#define HERMES_PCI_COR_MASK (0x0080) 61 62/* Magic timeouts for doing the reset. 63 * Those times are straight from wlan-ng, and it is claimed that they 64 * are necessary. Alan will kill me. Take your time and grab a coffee. */ 65#define HERMES_PCI_COR_ONT (250) /* ms */ 66#define HERMES_PCI_COR_OFFT (500) /* ms */ 67#define HERMES_PCI_COR_BUSYT (500) /* ms */ 68 69/* 70 * Do a soft reset of the card using the Configuration Option Register 71 * We need this to get going... 72 * This is the part of the code that is strongly inspired from wlan-ng 73 * 74 * Note : This code is done with irq enabled. This mean that many 75 * interrupts will occur while we are there. This is why we use the 76 * jiffies to regulate time instead of a straight mdelay(). Usually we 77 * need only around 245 iteration of the loop to do 250 ms delay. 78 * 79 * Note bis : Don't try to access HERMES_CMD during the reset phase. 80 * It just won't work ! 81 */ 82static int orinoco_pci_cor_reset(struct orinoco_private *priv) 83{ 84 hermes_t *hw = &priv->hw; 85 unsigned long timeout; 86 u16 reg; 87 88 /* Assert the reset until the card notices */ 89 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); 90 mdelay(HERMES_PCI_COR_ONT); 91 92 /* Give time for the card to recover from this hard effort */ 93 hermes_write_regn(hw, PCI_COR, 0x0000); 94 mdelay(HERMES_PCI_COR_OFFT); 95 96 /* The card is ready when it's no longer busy */ 97 timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000); 98 reg = hermes_read_regn(hw, CMD); 99 while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { 100 mdelay(1); 101 reg = hermes_read_regn(hw, CMD); 102 } 103 104 /* Still busy? */ 105 if (reg & HERMES_CMD_BUSY) { 106 printk(KERN_ERR PFX "Busy timeout\n"); 107 return -ETIMEDOUT; 108 } 109 110 return 0; 111} 112 113static int orinoco_pci_init_one(struct pci_dev *pdev, 114 const struct pci_device_id *ent) 115{ 116 int err; 117 struct orinoco_private *priv; 118 struct orinoco_pci_card *card; 119 struct net_device *dev; 120 void __iomem *hermes_io; 121 122 err = pci_enable_device(pdev); 123 if (err) { 124 printk(KERN_ERR PFX "Cannot enable PCI device\n"); 125 return err; 126 } 127 128 err = pci_request_regions(pdev, DRIVER_NAME); 129 if (err) { 130 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 131 goto fail_resources; 132 } 133 134 hermes_io = pci_iomap(pdev, 0, 0); 135 if (!hermes_io) { 136 printk(KERN_ERR PFX "Cannot remap chipset registers\n"); 137 err = -EIO; 138 goto fail_map_hermes; 139 } 140 141 /* Allocate network device */ 142 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); 143 if (!dev) { 144 printk(KERN_ERR PFX "Cannot allocate network device\n"); 145 err = -ENOMEM; 146 goto fail_alloc; 147 } 148 149 priv = netdev_priv(dev); 150 card = priv->card; 151 SET_MODULE_OWNER(dev); 152 SET_NETDEV_DEV(dev, &pdev->dev); 153 154 hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING); 155 156 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, 157 dev->name, dev); 158 if (err) { 159 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); 160 err = -EBUSY; 161 goto fail_irq; 162 } 163 164 err = orinoco_pci_cor_reset(priv); 165 if (err) { 166 printk(KERN_ERR PFX "Initial reset failed\n"); 167 goto fail; 168 } 169 170 err = register_netdev(dev); 171 if (err) { 172 printk(KERN_ERR PFX "Cannot register network device\n"); 173 goto fail; 174 } 175 176 pci_set_drvdata(pdev, dev); 177 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, 178 pci_name(pdev)); 179 180 return 0; 181 182 fail: 183 free_irq(pdev->irq, dev); 184 185 fail_irq: 186 pci_set_drvdata(pdev, NULL); 187 free_orinocodev(dev); 188 189 fail_alloc: 190 pci_iounmap(pdev, hermes_io); 191 192 fail_map_hermes: 193 pci_release_regions(pdev); 194 195 fail_resources: 196 pci_disable_device(pdev); 197 198 return err; 199} 200 201static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) 202{ 203 struct net_device *dev = pci_get_drvdata(pdev); 204 struct orinoco_private *priv = netdev_priv(dev); 205 206 unregister_netdev(dev); 207 free_irq(pdev->irq, dev); 208 pci_set_drvdata(pdev, NULL); 209 free_orinocodev(dev); 210 pci_iounmap(pdev, priv->hw.iobase); 211 pci_release_regions(pdev); 212 pci_disable_device(pdev); 213} 214 215static struct pci_device_id orinoco_pci_id_table[] = { 216 /* Intersil Prism 3 */ 217 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, 218 /* Intersil Prism 2.5 */ 219 {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,}, 220 /* Samsung MagicLAN SWL-2210P */ 221 {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,}, 222 {0,}, 223}; 224 225MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table); 226 227static struct pci_driver orinoco_pci_driver = { 228 .name = DRIVER_NAME, 229 .id_table = orinoco_pci_id_table, 230 .probe = orinoco_pci_init_one, 231 .remove = __devexit_p(orinoco_pci_remove_one), 232 .suspend = orinoco_pci_suspend, 233 .resume = orinoco_pci_resume, 234}; 235 236static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 237 " (Pavel Roskin <proski@gnu.org>," 238 " David Gibson <hermes@gibson.dropbear.id.au> &" 239 " Jean Tourrilhes <jt@hpl.hp.com>)"; 240MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>"); 241MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface"); 242MODULE_LICENSE("Dual MPL/GPL"); 243 244static int __init orinoco_pci_init(void) 245{ 246 printk(KERN_DEBUG "%s\n", version); 247 return pci_module_init(&orinoco_pci_driver); 248} 249 250static void __exit orinoco_pci_exit(void) 251{ 252 pci_unregister_driver(&orinoco_pci_driver); 253} 254 255module_init(orinoco_pci_init); 256module_exit(orinoco_pci_exit); 257 258/* 259 * Local variables: 260 * c-indent-level: 8 261 * c-basic-offset: 8 262 * tab-width: 8 263 * End: 264 */