diff -u -urN orinoco-0.13e/Makefile orinoco-0.13e+nortel_pci+eth/Makefile --- orinoco-0.13e/Makefile 2003-05-12 08:22:27.000000000 +0200 +++ orinoco-0.13e+nortel_pci+eth/Makefile 2003-06-13 00:43:36.000000000 +0200 @@ -19,14 +19,14 @@ endif endif -MODULES = hermes.o orinoco.o orinoco_cs.o orinoco_plx.o orinoco_tmd.o orinoco_pci.o +MODULES = hermes.o orinoco.o orinoco_cs.o orinoco_plx.o orinoco_tmd.o orinoco_pci.o nortel_pci.o ifeq ($(shell uname -m),ppc) MODULES += airport.o endif SRCS = hermes.c \ orinoco.c \ - airport.c orinoco_cs.c orinoco_plx.c orinoco_tmd.c orinoco_pci.c \ + airport.c orinoco_cs.c orinoco_plx.c orinoco_tmd.c orinoco_pci.c nortel_pci.c \ userhermes.c HDRS = hermes.h hermes_rid.h ieee802_11.h orinoco.h CONF = hermes.conf diff -u -urN orinoco-0.13e/hermes.c orinoco-0.13e+nortel_pci+eth/hermes.c --- orinoco-0.13e/hermes.c 2003-05-12 08:22:27.000000000 +0200 +++ orinoco-0.13e+nortel_pci+eth/hermes.c 2003-08-21 13:09:08.000000000 +0200 @@ -15,7 +15,7 @@ * * Copyright (C) 2000, David Gibson, Linuxcare Australia * Copyright (C) 2001, David Gibson, IBM - * + * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License @@ -116,7 +116,7 @@ hermes_write_regn(hw, PARAM1, 0); hermes_write_regn(hw, PARAM0, param0); hermes_write_regn(hw, CMD, cmd); - + return 0; } @@ -128,6 +128,8 @@ int io_space, int reg_spacing) { hw->iobase = address; + hw->iobase1 = 0; + hw->iobase2 = 0; hw->io_space = io_space; hw->reg_spacing = reg_spacing; hw->inten = 0x0; diff -u -urN orinoco-0.13e/hermes.h orinoco-0.13e+nortel_pci+eth/hermes.h --- orinoco-0.13e/hermes.h 2003-05-12 08:22:27.000000000 +0200 +++ orinoco-0.13e+nortel_pci+eth/hermes.h 2003-08-21 13:12:58.000000000 +0200 @@ -277,7 +277,7 @@ /* Basic control structure */ typedef struct hermes { - unsigned long iobase; + unsigned long iobase, iobase1, iobase2; int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */ #define HERMES_IO 1 #define HERMES_MEM 0 diff -u -urN orinoco-0.13e/nortel_pci.c orinoco-0.13e+nortel_pci+eth/nortel_pci.c --- orinoco-0.13e/nortel_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ orinoco-0.13e+nortel_pci+eth/nortel_pci.c 2003-08-21 13:35:13.000000000 +0200 @@ -0,0 +1,345 @@ +/* nortel_pci.c (based on orinoco_plx.c and orinoco_pci.c) + * + * Driver for Prism II devices which would usually be driven by orinoco_cs, + * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. + * + * Copyright (C) 2002 Tobias Hoffmann + * (C) 2003 Christoph Jungegger + * + * Some of this code is borrowed from orinoco_plx.c + * Copyright (C) 2001 Daniel Barlow + * Some of this code is borrowed from orinoco_pci.c + * Copyright (C) 2001 Jean Tourrilhes + * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing + * has been copied from it. linux-wlan-ng-0.1.10 is originally : + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "hermes.h" +#include "orinoco.h" + +static char dev_info[] = "nortel_pci"; + +#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ + + +/* + * Do a soft reset of the PCI card using the Configuration Option Register + * We need this to get going... + * This is the part of the code that is strongly inspired from wlan-ng + * + * Note bis : Don't try to access HERMES_CMD during the reset phase. + * It just won't work ! + */ +static int +nortel_pci_cor_reset(struct orinoco_private *priv) +{ + unsigned long brg1_ioaddr=priv->hw.iobase1; + unsigned long brg2_ioaddr=priv->hw.iobase2; + + /* Assert the reset until the card notice */ + outw_p(8, brg1_ioaddr+2); + inw(brg2_ioaddr+COR_OFFSET); + outw_p(0x80, brg2_ioaddr+COR_OFFSET); + mdelay(1); + printk(KERN_NOTICE "Reset done;\n"); + + /* Give time for the card to recover from this hard effort */ + outw_p(0, brg2_ioaddr+COR_OFFSET); + outw_p(0, brg2_ioaddr+COR_OFFSET); + mdelay(1); + printk(KERN_NOTICE "Clear Reset\n"); + + /* set COR as usual*/ + outw_p(COR_VALUE, brg2_ioaddr+COR_OFFSET); + outw_p(COR_VALUE, brg2_ioaddr+COR_OFFSET); + mdelay(1); + + outw_p(0x228, brg1_ioaddr+2); + + return 0; +} + +static int nortel_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err = 0; + u16 *attr_mem = NULL; + u32 reg; + struct orinoco_private *priv = NULL; + unsigned long brg1_ioaddr = 0, brg2_ioaddr = 0, pccard_ioaddr = 0; + unsigned long brg1_iolen = 0, brg2_iolen = 0, pccard_iolen = 0; + struct net_device *dev = NULL; + int netdev_registered = 0; + int i; + + err = pci_enable_device(pdev); + if (err) + return -EIO; + + brg1_ioaddr = pci_resource_start(pdev, 0); + brg1_iolen = pci_resource_len(pdev, 0); + if (! request_region(brg1_ioaddr, brg1_iolen, dev_info)) { + printk(KERN_ERR "nortel_pci: Bridge I/O resource 1 0x%lx @ 0x%lx busy\n", + brg1_iolen, brg1_ioaddr); + brg1_ioaddr = 0; + err = -EBUSY; + goto fail; + } + + brg2_ioaddr = pci_resource_start(pdev, 1); + brg2_iolen = pci_resource_len(pdev, 1); + if (! request_region(brg2_ioaddr, brg2_iolen, dev_info)) { + printk(KERN_ERR "nortel_pci: Bridge I/O resource 2 0x%lx @ 0x%lx busy\n", + brg2_iolen, brg2_ioaddr); + brg2_ioaddr = 0; + err = -EBUSY; + goto fail; + } + + pccard_ioaddr = pci_resource_start(pdev, 2); + pccard_iolen = pci_resource_len(pdev, 2); + if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { + printk(KERN_ERR "nortel_pci: I/O resource 0x%lx @ 0x%lx busy\n", + pccard_iolen, pccard_ioaddr); + pccard_ioaddr = 0; + err = -EBUSY; + goto fail; + } + + /* setup bridge */ + if (inw(brg1_ioaddr)&1) { + printk(KERN_ERR "nortel_pci: brg1 answer1 wrong\n"); + goto fail; + } + outw_p(0x118,brg1_ioaddr+2); + outw_p(0x108,brg1_ioaddr+2); + mdelay(30); + outw_p(0x8,brg1_ioaddr+2); + for (i=0; i<30; i++) { + mdelay(30); + if (inw(brg1_ioaddr)&0x10) { + break; + } + } + if (i==30) { + printk(KERN_ERR "nortel_pci: brg1 timed out\n"); + goto fail; + } + if (inw(brg2_ioaddr+0xe0)&1) { + printk(KERN_ERR "nortel_pci: brg2 answer1 wrong\n"); + goto fail; + } + if (inw(brg2_ioaddr+0xe2)&1) { + printk(KERN_ERR "nortel_pci: brg2 answer2 wrong\n"); + goto fail; + } + if (inw(brg2_ioaddr+0xe4)&1) { + printk(KERN_ERR "nortel_pci: brg2 answer3 wrong\n"); + goto fail; + } + + /* set the PCMCIA COR-Register */ + outw_p(COR_VALUE, brg2_ioaddr+COR_OFFSET); + mdelay(1); + reg = inw(brg2_ioaddr+COR_OFFSET); + if (reg != COR_VALUE) { + printk(KERN_ERR "nortel_pci: Error setting COR value (reg=%x)\n", reg); + goto fail; + } + + /* set leds */ + outw_p(1,brg1_ioaddr+10); + + + dev = alloc_orinocodev(0, NULL); + if (! dev) { + err = -ENOMEM; + goto fail; + } + + priv = dev->priv; + dev->base_addr = pccard_ioaddr; + priv->hard_reset = nortel_pci_cor_reset; + SET_MODULE_OWNER(dev); + + printk(KERN_DEBUG + "Detected Nortel PCI device at %s irq:%d, io addr:0x%lx\n", + pdev->slot_name, pdev->irq, pccard_ioaddr); + + hermes_struct_init(&(priv->hw), dev->base_addr, + HERMES_IO, HERMES_16BIT_REGSPACING); + pci_set_drvdata(pdev, dev); + priv->hw.iobase1=brg1_ioaddr; + priv->hw.iobase2=brg2_ioaddr; + + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); + if (err) { + printk(KERN_ERR "nortel_pci: Error allocating IRQ %d.\n", pdev->irq); + err = -EBUSY; + goto fail; + } + dev->irq = pdev->irq; + nortel_pci_cor_reset(priv); + + err = register_netdev(dev); + if (err) { + printk(KERN_ERR "%s: Failed to register net device\n", dev->name); + goto fail; + } + netdev_registered = 1; + + return 0; /* succeeded */ + +fail: + if (!err) { + err=-1; + } + printk(KERN_DEBUG "nortel_pci: init_one(), FAIL!\n"); + + if (priv) { + if (netdev_registered) + unregister_netdev(dev); + + if (dev->irq) + free_irq(dev->irq, dev); + + pci_set_drvdata(pdev, NULL); + kfree(priv); + } + + if (brg1_ioaddr) + release_region(brg1_ioaddr, brg1_iolen); + if (brg2_ioaddr) + release_region(brg2_ioaddr, brg2_iolen); + if (pccard_ioaddr) + release_region(pccard_ioaddr, pccard_iolen); + + if (attr_mem) + iounmap(attr_mem); + + pci_disable_device(pdev); + + return err; +} + +static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + /* clear leds */ + /* outw_p(0,priv->hw.iobase1+10); */ + + if (! dev) + BUG(); + + unregister_netdev(dev); + + if (dev->irq) + free_irq(dev->irq, dev); + + pci_set_drvdata(pdev, NULL); + kfree(dev); + + release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); + release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + + pci_disable_device(pdev); + +} + + +static struct pci_device_id nortel_pci_id_table[] __devinitdata = { + {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, /* Nortel emobility PCI */ + {0,}, +}; + +MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); + +static struct pci_driver nortel_pci_driver = { + .name = "nortel_pci", + .id_table = nortel_pci_id_table, + .probe = nortel_pci_init_one, + .remove = __devexit_p(nortel_pci_remove_one), + .suspend = 0, + .resume = 0 +}; + +static char version[] __initdata = "nortel_pci.c 0.13e (Tobias Hoffmann & Christoph Jungegger )"; +MODULE_AUTHOR("Christoph Jungegger "); +MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("Dual MPL/GPL"); +#endif + +static int __init nortel_pci_init(void) +{ + printk(KERN_DEBUG "%s\n", version); + return pci_module_init(&nortel_pci_driver); +} + +extern void __exit nortel_pci_exit(void) +{ + pci_unregister_driver(&nortel_pci_driver); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); +} + +module_init(nortel_pci_init); +module_exit(nortel_pci_exit); + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -u -urN orinoco-0.13e/orinoco.c orinoco-0.13e+nortel_pci+eth/orinoco.c --- orinoco-0.13e/orinoco.c 2003-05-12 08:22:27.000000000 +0200 +++ orinoco-0.13e+nortel_pci+eth/orinoco.c 2003-08-29 17:45:18.000000000 +0200 @@ -3033,7 +3033,7 @@ if (!priv->has_sensitivity) return -EOPNOTSUPP; - if ((val < 1) || (val > 3)) + if ((val < 0) || (val > 3)) return -EINVAL; err = orinoco_lock(priv, &flags); diff -u -urN orinoco-0.13e/orinoco_cs.c orinoco-0.13e+nortel_pci+eth/orinoco_cs.c --- orinoco-0.13e/orinoco_cs.c 2003-05-12 08:22:27.000000000 +0200 +++ orinoco-0.13e+nortel_pci+eth/orinoco_cs.c 2003-08-29 17:45:18.000000000 +0200 @@ -63,9 +63,13 @@ * don't have any CIS entry for it. This workaround it... */ static int ignore_cis_vcc; /* = 0 */ +/* Control device name allocation. 0 -> dldwdX ; 1 -> ethX */ +static int eth = 1; + MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(ignore_cis_vcc, "i"); +MODULE_PARM(eth, "i"); /********************************************************************/ /* Magic constants */ @@ -87,6 +91,7 @@ struct orinoco_pccard { dev_link_t link; dev_node_t node; + int instance; /* Used to handle hard reset */ /* yuck, we need this hack to work around the insanity of the @@ -100,6 +105,7 @@ * dev_link_t structure (defined in ds.h). */ static dev_link_t *dev_list; /* = NULL */ +static int num_instances = 0; /********************************************************************/ /* Function prototypes */ @@ -199,6 +205,7 @@ card = priv->card; /* Link both structures together */ + card->instance = num_instances++; /* FIXME: Racy? */ link = &card->link; link->priv = dev; @@ -292,6 +299,9 @@ unregister_netdev(dev); } kfree(dev); + + num_instances--; /* FIXME: Racy? */ + } /* orinoco_cs_detach */ /* @@ -491,8 +501,12 @@ SET_MODULE_OWNER(dev); card->node.major = card->node.minor = 0; - /* register_netdev will give us an ethX name */ - dev->name[0] = '\0'; + /* Instance name : by default, use hermesX, on demand use the + * regular ethX (less risky) - Jean II */ + if(!eth) + sprintf(dev->name, "wvlan%d", card->instance); + else + dev->name[0] = '\0'; /* Tell the stack we exist */ if (register_netdev(dev) != 0) { printk(KERN_ERR "orinoco_cs: register_netdev() failed\n"); @@ -679,11 +693,11 @@ printk(KERN_DEBUG "%s\n", version); CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "orinoco_cs: Card Services release " - "does not match!\n"); - return -1; - } +// if (serv.Revision != CS_RELEASE_CODE) { +// printk(KERN_NOTICE "orinoco_cs: Card Services release " +// "does not match!\n"); +// return -1; +// } register_pccard_driver(&dev_info, &orinoco_cs_attach, &orinoco_cs_detach);