1ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin/* orinoco_nortel.c 2b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin * 3ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Driver for Prism II devices which would usually be driven by orinoco_cs, 4d495657200bd3ce10f9cb52401056804bf365811Pavel Roskin * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in 5d495657200bd3ce10f9cb52401056804bf365811Pavel Roskin * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. 6ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * 7ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Copyright (C) 2002 Tobias Hoffmann 8ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * (C) 2003 Christoph Jungegger <disdos@traum404.de> 9ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * 10ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Some of this code is borrowed from orinoco_plx.c 11ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Copyright (C) 2001 Daniel Barlow 12d14c7c1d6aef1175625ea72938b07cee072723dcAndrey Borzenkov * Some of this code is borrowed from orinoco_pci.c 13ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Copyright (C) 2001 Jean Tourrilhes 14ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing 15ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * has been copied from it. linux-wlan-ng-0.1.10 is originally : 16ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. 17d14c7c1d6aef1175625ea72938b07cee072723dcAndrey Borzenkov * 18ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * The contents of this file are subject to the Mozilla Public License 19ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Version 1.1 (the "License"); you may not use this file except in 20ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * compliance with the License. You may obtain a copy of the License 21ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * at http://www.mozilla.org/MPL/ 22ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * 23ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Software distributed under the License is distributed on an "AS IS" 24ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 25ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * the License for the specific language governing rights and 26ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * limitations under the License. 27ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * 28ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Alternatively, the contents of this file may be used under the 29ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * terms of the GNU General Public License version 2 (the "GPL"), in 30ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * which case the provisions of the GPL are applicable instead of the 31ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * above. If you wish to allow the use of your version of this file 32ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * only under the terms of the GPL and not to allow others to use your 33ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * version of this file under the MPL, indicate your decision by 34ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * deleting the provisions above and replace them with the notice and 35ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * other provisions required by the GPL. If you do not delete the 36ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * provisions above, a recipient may use your version of this file 37ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * under either the MPL or the GPL. 38ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin */ 39ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 40ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#define DRIVER_NAME "orinoco_nortel" 41ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#define PFX DRIVER_NAME ": " 42ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 43ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include <linux/module.h> 44ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include <linux/kernel.h> 45ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include <linux/init.h> 46ef846bf04f4c9e1a68ab841e89931f8c26100874Pavel Roskin#include <linux/delay.h> 47ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include <linux/pci.h> 48ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include <pcmcia/cisreg.h> 49ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 50ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#include "orinoco.h" 51b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin#include "orinoco_pci.h" 52ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 53ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ 54ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ 55ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 56ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 57ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin/* 58dc3437d205dcd1a195ebf795f1c54ceb638337fbPavel Roskin * Do a soft reset of the card using the Configuration Option Register 59ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * We need this to get going... 60ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * This is the part of the code that is strongly inspired from wlan-ng 61ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * 62ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Note bis : Don't try to access HERMES_CMD during the reset phase. 63ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * It just won't work ! 64ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin */ 65b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic int orinoco_nortel_cor_reset(struct orinoco_private *priv) 66ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 67b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin struct orinoco_pci_card *card = priv->card; 68ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 69dc3437d205dcd1a195ebf795f1c54ceb638337fbPavel Roskin /* Assert the reset until the card notices */ 70b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(8, card->bridge_io + 2); 71b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin ioread16(card->attr_io + COR_OFFSET); 72b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0x80, card->attr_io + COR_OFFSET); 73ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(1); 74ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 75ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin /* Give time for the card to recover from this hard effort */ 76b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0, card->attr_io + COR_OFFSET); 77b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0, card->attr_io + COR_OFFSET); 78ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(1); 79ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 80b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin /* Set COR as usual */ 81b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); 82b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); 83ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(1); 84ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 85b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0x228, card->bridge_io + 2); 86ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 87ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return 0; 88ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 89ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 90b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic int orinoco_nortel_hw_init(struct orinoco_pci_card *card) 91ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 92ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin int i; 93ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin u32 reg; 94ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 95b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin /* Setup bridge */ 96b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (ioread16(card->bridge_io) & 1) { 97ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "brg1 answer1 wrong\n"); 98ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 99ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 100b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0x118, card->bridge_io + 2); 101b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0x108, card->bridge_io + 2); 102ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(30); 103b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0x8, card->bridge_io + 2); 104ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin for (i = 0; i < 30; i++) { 105ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(30); 106d14c7c1d6aef1175625ea72938b07cee072723dcAndrey Borzenkov if (ioread16(card->bridge_io) & 0x10) 107ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin break; 108ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 109ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (i == 30) { 110ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "brg1 timed out\n"); 111ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 112ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 113b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (ioread16(card->attr_io + COR_OFFSET) & 1) { 114ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "brg2 answer1 wrong\n"); 115ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 116ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 117b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) { 118ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "brg2 answer2 wrong\n"); 119ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 120ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 121b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) { 122ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "brg2 answer3 wrong\n"); 123ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 124ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 125ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 126dc3437d205dcd1a195ebf795f1c54ceb638337fbPavel Roskin /* Set the PCMCIA COR register */ 127b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); 128ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin mdelay(1); 129b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin reg = ioread16(card->attr_io + COR_OFFSET); 130ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (reg != COR_VALUE) { 131ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", 132ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin reg); 133ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return -EBUSY; 134ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 135ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 136b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin /* Set LEDs */ 137b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(1, card->bridge_io + 10); 138ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return 0; 139ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 140ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 141b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic int orinoco_nortel_init_one(struct pci_dev *pdev, 142b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin const struct pci_device_id *ent) 143ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 144ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin int err; 145ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin struct orinoco_private *priv; 146b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin struct orinoco_pci_card *card; 147b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin void __iomem *hermes_io, *bridge_io, *attr_io; 148ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 149ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin err = pci_enable_device(pdev); 150ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (err) { 151ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Cannot enable PCI device\n"); 152ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return err; 153ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 154ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 155ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin err = pci_request_regions(pdev, DRIVER_NAME); 156b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (err) { 157ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 158ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail_resources; 159ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 160ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 161b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin bridge_io = pci_iomap(pdev, 0, 0); 162b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (!bridge_io) { 163b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin printk(KERN_ERR PFX "Cannot map bridge registers\n"); 164b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin err = -EIO; 165b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin goto fail_map_bridge; 166b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin } 167b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin 168b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin attr_io = pci_iomap(pdev, 1, 0); 169b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (!attr_io) { 170b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); 171b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin err = -EIO; 172b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin goto fail_map_attr; 173b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin } 174b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin 175b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin hermes_io = pci_iomap(pdev, 2, 0); 176b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin if (!hermes_io) { 177b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin printk(KERN_ERR PFX "Cannot map chipset registers\n"); 178b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin err = -EIO; 179b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin goto fail_map_hermes; 180ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 181ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 182ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin /* Allocate network device */ 183a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy priv = alloc_orinocodev(sizeof(*card), &pdev->dev, 184a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy orinoco_nortel_cor_reset, NULL); 185a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy if (!priv) { 186ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Cannot allocate network device\n"); 187ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin err = -ENOMEM; 188ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail_alloc; 189ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 190ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 191ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin card = priv->card; 192b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin card->bridge_io = bridge_io; 193b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin card->attr_io = attr_io; 194ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 195b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); 196ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 1971fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, 1985381956b780e82805247c2ec8e32c4c665309394David Kilroy DRIVER_NAME, priv); 199ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (err) { 200ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); 201ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin err = -EBUSY; 202ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail_irq; 203ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 204ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 205b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin err = orinoco_nortel_hw_init(card); 206ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (err) { 207ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Hardware initialization failed\n"); 208ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail; 209ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 210ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 211b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin err = orinoco_nortel_cor_reset(priv); 212ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (err) { 213ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_ERR PFX "Initial reset failed\n"); 214ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail; 215ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 216ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 2178e638267a896e171e49fb9013f5baf96a4ede754David Kilroy err = orinoco_init(priv); 2188e638267a896e171e49fb9013f5baf96a4ede754David Kilroy if (err) { 2198e638267a896e171e49fb9013f5baf96a4ede754David Kilroy printk(KERN_ERR PFX "orinoco_init() failed\n"); 2208e638267a896e171e49fb9013f5baf96a4ede754David Kilroy goto fail; 2218e638267a896e171e49fb9013f5baf96a4ede754David Kilroy } 2228e638267a896e171e49fb9013f5baf96a4ede754David Kilroy 223593ef09c9e70c92c0d76c67a1c03a5d44d3aec82David Kilroy err = orinoco_if_add(priv, 0, 0, NULL); 224ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin if (err) { 2255381956b780e82805247c2ec8e32c4c665309394David Kilroy printk(KERN_ERR PFX "orinoco_if_add() failed\n"); 226ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin goto fail; 227ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin } 228ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 229a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy pci_set_drvdata(pdev, priv); 230ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 231ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return 0; 232ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 233ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin fail: 234a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy free_irq(pdev->irq, priv); 235ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 236ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin fail_irq: 237a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy free_orinocodev(priv); 238ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 239ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin fail_alloc: 240b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_iounmap(pdev, hermes_io); 241b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin 242b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin fail_map_hermes: 243b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_iounmap(pdev, attr_io); 244b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin 245b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin fail_map_attr: 246b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_iounmap(pdev, bridge_io); 247ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 248b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin fail_map_bridge: 249ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin pci_release_regions(pdev); 250ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 251ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin fail_resources: 252ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin pci_disable_device(pdev); 253ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 254ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin return err; 255ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 256ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 257baa366cda6ec9bf033301a4f547c26c833bd5930Bill Pembertonstatic void orinoco_nortel_remove_one(struct pci_dev *pdev) 258ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 259a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy struct orinoco_private *priv = pci_get_drvdata(pdev); 260b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin struct orinoco_pci_card *card = priv->card; 261ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 262b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin /* Clear LEDs */ 263b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin iowrite16(0, card->bridge_io + 10); 264ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 2655381956b780e82805247c2ec8e32c4c665309394David Kilroy orinoco_if_del(priv); 266a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy free_irq(pdev->irq, priv); 267a2608362b22ade22ef5472a8c9b82687d86f976fDavid Kilroy free_orinocodev(priv); 268ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin pci_iounmap(pdev, priv->hw.iobase); 269b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_iounmap(pdev, card->attr_io); 270b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_iounmap(pdev, card->bridge_io); 271ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin pci_release_regions(pdev); 272ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin pci_disable_device(pdev); 273ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 274ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 2759baa3c34ac4e27f7e062f266f50cc5dbea26a6c1Benoit Tainestatic const struct pci_device_id orinoco_nortel_id_table[] = { 276ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin /* Nortel emobility PCI */ 277ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, 278d495657200bd3ce10f9cb52401056804bf365811Pavel Roskin /* Symbol LA-4123 PCI */ 279d495657200bd3ce10f9cb52401056804bf365811Pavel Roskin {0x1562, 0x0001, PCI_ANY_ID, PCI_ANY_ID,}, 280ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin {0,}, 281ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin}; 282ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 283b884c872fa1917614b42a39020ffcca7fa9302b1Pavel RoskinMODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table); 284ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 285b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic struct pci_driver orinoco_nortel_driver = { 286c6fb2e9abef894efc4870e4c1e3aa4365b830a11Pavel Roskin .name = DRIVER_NAME, 287b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin .id_table = orinoco_nortel_id_table, 288b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin .probe = orinoco_nortel_init_one, 289baa366cda6ec9bf033301a4f547c26c833bd5930Bill Pemberton .remove = orinoco_nortel_remove_one, 290b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin .suspend = orinoco_pci_suspend, 291b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin .resume = orinoco_pci_resume, 292ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin}; 293ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 294ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskinstatic char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 295ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)"; 296ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel RoskinMODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>"); 297933d594313a5928ffc5325d7bbb6e2383d79622ePavel RoskinMODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge"); 298ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel RoskinMODULE_LICENSE("Dual MPL/GPL"); 299ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 300b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic int __init orinoco_nortel_init(void) 301ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 302ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin printk(KERN_DEBUG "%s\n", version); 303299176206b266f204be859adf9e66efd06628ab2Jeff Garzik return pci_register_driver(&orinoco_nortel_driver); 304ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 305ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 306b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinstatic void __exit orinoco_nortel_exit(void) 307ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin{ 308b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskin pci_unregister_driver(&orinoco_nortel_driver); 309ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin} 310ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 311b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinmodule_init(orinoco_nortel_init); 312b884c872fa1917614b42a39020ffcca7fa9302b1Pavel Roskinmodule_exit(orinoco_nortel_exit); 313ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin 314ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin/* 315ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * Local variables: 316ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * c-indent-level: 8 317ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * c-basic-offset: 8 318ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * tab-width: 8 319ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin * End: 320ec82905177a22b0fe0abaf4ecb76813d3d45d16ePavel Roskin */ 321