Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (39 commits) [PATCH] myri10ge - Export more parameters to ethtool [PATCH] myri10ge - Use dev_info() when printing parameters after probe [PATCH] myri10ge - Drop ununsed nvidia chipset id [PATCH] myri10ge - Drop unused pm_state [PATCH] Fix freeing of net device [PATCH] remove dead entry in net wan Kconfig [PATCH] NI5010 netcard cleanup [PATCH] lock validator: fix ns83820.c irq-flags bug [PATCH] pcnet32: Cleanup rx buffers after loopback test. [PATCH] pcnet32: Suspend the chip rather than restart when changing multicast/promisc [PATCH] pcnet32: Handle memory allocation failures cleanly when resizing tx/rx rings [PATCH] pcnet32: Use kcalloc instead of kmalloc and memset [PATCH] pcnet32: Fix off-by-one in get_ringparam [PATCH] pcnet32: Use PCI_DEVICE macro [PATCH] pcnet32: Fix Section mismatch error [PATCH] Add support for the Cicada 8201 PHY [PATCH] zd1211rw: disable TX queue during stop [PATCH] ZyDAS ZD1211 USB-WLAN driver [PATCH] softmac: fix build-break from 881ee6999d66c8fc903b429b73bbe6045b38c549 [PATCH] CONFIG_WIRELESS_EXT is neccessary after all ...
This commit is contained in:
commit
e8f75588dd
68 changed files with 7760 additions and 1103 deletions
|
@ -2039,9 +2039,10 @@ L: linux-kernel@vger.kernel.org
|
|||
S: Maintained
|
||||
|
||||
NI5010 NETWORK DRIVER
|
||||
P: Jan-Pascal van Best and Andreas Mohr
|
||||
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
|
||||
M: Andreas Mohr <100.30936@germany.net>
|
||||
P: Jan-Pascal van Best
|
||||
M: janpascal@vanbest.org
|
||||
P: Andreas Mohr
|
||||
M: andi@lisas.de
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
|
|
|
@ -1836,9 +1836,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
|
||||
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
|
||||
printk(KERN_ERR PFX "pci dev %s (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
|
||||
pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
|
||||
printk(KERN_ERR PFX "Try the \"8139too\" driver instead.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
|
||||
pdev->vendor, pdev->device, pci_rev);
|
||||
dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1876,14 +1877,13 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
pciaddr = pci_resource_start(pdev, 1);
|
||||
if (!pciaddr) {
|
||||
rc = -EIO;
|
||||
printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n",
|
||||
pci_name(pdev));
|
||||
dev_err(&pdev->dev, "no MMIO resource\n");
|
||||
goto err_out_res;
|
||||
}
|
||||
if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
|
||||
rc = -EIO;
|
||||
printk(KERN_ERR PFX "MMIO resource (%llx) too small on pci dev %s\n",
|
||||
(unsigned long long)pci_resource_len(pdev, 1), pci_name(pdev));
|
||||
dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
|
||||
(unsigned long long)pci_resource_len(pdev, 1));
|
||||
goto err_out_res;
|
||||
}
|
||||
|
||||
|
@ -1897,14 +1897,15 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (rc) {
|
||||
printk(KERN_ERR PFX "No usable DMA configuration, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"No usable DMA configuration, aborting.\n");
|
||||
goto err_out_res;
|
||||
}
|
||||
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (rc) {
|
||||
printk(KERN_ERR PFX "No usable consistent DMA configuration, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"No usable consistent DMA configuration, "
|
||||
"aborting.\n");
|
||||
goto err_out_res;
|
||||
}
|
||||
}
|
||||
|
@ -1915,9 +1916,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
regs = ioremap(pciaddr, CP_REGS_SIZE);
|
||||
if (!regs) {
|
||||
rc = -EIO;
|
||||
printk(KERN_ERR PFX "Cannot map PCI MMIO (%llx@%llx) on pci dev %s\n",
|
||||
(unsigned long long)pci_resource_len(pdev, 1),
|
||||
(unsigned long long)pciaddr, pci_name(pdev));
|
||||
dev_err(&pdev->dev, "Cannot map PCI MMIO (%lx@%lx)\n",
|
||||
(unsigned long long)pci_resource_len(pdev, 1),
|
||||
(unsigned long long)pciaddr);
|
||||
goto err_out_res;
|
||||
}
|
||||
dev->base_addr = (unsigned long) regs;
|
||||
|
@ -1986,7 +1987,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
/* enable busmastering and memory-write-invalidate */
|
||||
pci_set_master(pdev);
|
||||
|
||||
if (cp->wol_enabled) cp_set_d3_state (cp);
|
||||
if (cp->wol_enabled)
|
||||
cp_set_d3_state (cp);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2011,7 +2013,8 @@ static void cp_remove_one (struct pci_dev *pdev)
|
|||
BUG_ON(!dev);
|
||||
unregister_netdev(dev);
|
||||
iounmap(cp->regs);
|
||||
if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
|
||||
if (cp->wol_enabled)
|
||||
pci_set_power_state (pdev, PCI_D0);
|
||||
pci_release_regions(pdev);
|
||||
pci_clear_mwi(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
|
|
@ -768,7 +768,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
/* dev and priv zeroed in alloc_etherdev */
|
||||
dev = alloc_etherdev (sizeof (*tp));
|
||||
if (dev == NULL) {
|
||||
printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "Unable to alloc new net device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
SET_MODULE_OWNER(dev);
|
||||
|
@ -800,31 +800,31 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
#ifdef USE_IO_OPS
|
||||
/* make sure PCI base addr 0 is PIO */
|
||||
if (!(pio_flags & IORESOURCE_IO)) {
|
||||
printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
/* check for weird/broken PCI region reporting */
|
||||
if (pio_len < RTL_MIN_IO_SIZE) {
|
||||
printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
#else
|
||||
/* make sure PCI base addr 1 is MMIO */
|
||||
if (!(mmio_flags & IORESOURCE_MEM)) {
|
||||
printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
if (mmio_len < RTL_MIN_IO_SIZE) {
|
||||
printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = pci_request_regions (pdev, "8139too");
|
||||
rc = pci_request_regions (pdev, DRV_NAME);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
disable_dev_on_err = 1;
|
||||
|
@ -835,7 +835,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
#ifdef USE_IO_OPS
|
||||
ioaddr = ioport_map(pio_start, pio_len);
|
||||
if (!ioaddr) {
|
||||
printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "cannot map PIO, aborting\n");
|
||||
rc = -EIO;
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
/* ioremap MMIO region */
|
||||
ioaddr = pci_iomap(pdev, 1, 0);
|
||||
if (ioaddr == NULL) {
|
||||
printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
|
||||
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
|
||||
rc = -EIO;
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -860,8 +860,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
|
||||
/* check for missing/broken hardware */
|
||||
if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
|
||||
printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n",
|
||||
pci_name(pdev));
|
||||
dev_err(&pdev->dev, "Chip not responding, ignoring board\n");
|
||||
rc = -EIO;
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -875,9 +874,10 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
|
||||
printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n",
|
||||
pci_name(pdev));
|
||||
printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig));
|
||||
dev_printk (KERN_DEBUG, &pdev->dev,
|
||||
"unknown chip version, assuming RTL-8139\n");
|
||||
dev_printk (KERN_DEBUG, &pdev->dev,
|
||||
"TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
|
||||
tp->chipset = 0;
|
||||
|
||||
match:
|
||||
|
@ -954,9 +954,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
|
|||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
|
||||
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) {
|
||||
printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
|
||||
pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
|
||||
printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n");
|
||||
dev_info(&pdev->dev,
|
||||
"This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
|
||||
pdev->vendor, pdev->device, pci_rev);
|
||||
dev_info(&pdev->dev,
|
||||
"Use the \"8139cp\" driver for improved performance and stability.\n");
|
||||
}
|
||||
|
||||
i = rtl8139_init_board (pdev, &dev);
|
||||
|
|
|
@ -2120,13 +2120,14 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Cannot enable PCI device, "
|
||||
dev_err(&pdev->dev, "Cannot enable PCI device, "
|
||||
"aborting.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
|
||||
printk(KERN_ERR PFX "Cannot find proper PCI device "
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot find proper PCI device "
|
||||
"base address, aborting.\n");
|
||||
err = -ENODEV;
|
||||
goto err_out_disable_pdev;
|
||||
|
@ -2134,8 +2135,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_request_regions(pdev, DRV_MODULE_NAME);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot obtain PCI resources, aborting.\n");
|
||||
goto err_out_disable_pdev;
|
||||
}
|
||||
|
||||
|
@ -2143,15 +2144,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "No usable DMA configuration, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
||||
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "No usable DMA configuration, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
||||
|
@ -2160,7 +2159,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
dev = alloc_etherdev(sizeof(*bp));
|
||||
if (!dev) {
|
||||
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
|
||||
dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
|
||||
err = -ENOMEM;
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
@ -2181,8 +2180,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
bp->regs = ioremap(b44reg_base, b44reg_len);
|
||||
if (bp->regs == 0UL) {
|
||||
printk(KERN_ERR PFX "Cannot map device registers, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
|
||||
err = -ENOMEM;
|
||||
goto err_out_free_dev;
|
||||
}
|
||||
|
@ -2212,8 +2210,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = b44_get_invariants(bp);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Problem fetching invariants of chip, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Problem fetching invariants of chip, aborting.\n");
|
||||
goto err_out_iounmap;
|
||||
}
|
||||
|
||||
|
@ -2233,8 +2231,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Cannot register net device, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
|
||||
goto err_out_iounmap;
|
||||
}
|
||||
|
||||
|
|
|
@ -5575,20 +5575,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
/* enable device (incl. PCI PM wakeup), and bus-mastering */
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
printk(KERN_ERR PFX "Cannot enable PCI device, aborting.");
|
||||
dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
|
||||
printk(KERN_ERR PFX "Cannot find PCI device base address, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot find PCI device base address, aborting.\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out_disable;
|
||||
}
|
||||
|
||||
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
|
||||
if (rc) {
|
||||
printk(KERN_ERR PFX "Cannot obtain PCI resources, aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
|
||||
goto err_out_disable;
|
||||
}
|
||||
|
||||
|
@ -5596,15 +5596,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
|
||||
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
|
||||
if (bp->pm_cap == 0) {
|
||||
printk(KERN_ERR PFX "Cannot find power management capability, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot find power management capability, aborting.\n");
|
||||
rc = -EIO;
|
||||
goto err_out_release;
|
||||
}
|
||||
|
||||
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
|
||||
if (bp->pcix_cap == 0) {
|
||||
printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n");
|
||||
rc = -EIO;
|
||||
goto err_out_release;
|
||||
}
|
||||
|
@ -5612,14 +5612,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
|
||||
bp->flags |= USING_DAC_FLAG;
|
||||
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
|
||||
printk(KERN_ERR PFX "pci_set_consistent_dma_mask "
|
||||
"failed, aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"pci_set_consistent_dma_mask failed, aborting.\n");
|
||||
rc = -EIO;
|
||||
goto err_out_release;
|
||||
}
|
||||
}
|
||||
else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
|
||||
printk(KERN_ERR PFX "System does not support DMA, aborting.\n");
|
||||
dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
|
||||
rc = -EIO;
|
||||
goto err_out_release;
|
||||
}
|
||||
|
@ -5639,7 +5639,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
bp->regview = ioremap_nocache(dev->base_addr, mem_len);
|
||||
|
||||
if (!bp->regview) {
|
||||
printk(KERN_ERR PFX "Cannot map register space, aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_out_release;
|
||||
}
|
||||
|
@ -5711,8 +5711,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
|
||||
!(bp->flags & PCIX_FLAG)) {
|
||||
|
||||
printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev,
|
||||
"5706 A1 can only be used in a PCIX bus, aborting.\n");
|
||||
goto err_out_unmap;
|
||||
}
|
||||
|
||||
|
@ -5733,7 +5733,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
|
||||
if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
|
||||
BNX2_DEV_INFO_SIGNATURE_MAGIC) {
|
||||
printk(KERN_ERR PFX "Firmware not running, aborting.\n");
|
||||
dev_err(&pdev->dev, "Firmware not running, aborting.\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out_unmap;
|
||||
}
|
||||
|
@ -5895,7 +5895,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
#endif
|
||||
|
||||
if ((rc = register_netdev(dev))) {
|
||||
printk(KERN_ERR PFX "Cannot register net device\n");
|
||||
dev_err(&pdev->dev, "Cannot register net device\n");
|
||||
if (bp->regview)
|
||||
iounmap(bp->regview);
|
||||
pci_release_regions(pdev);
|
||||
|
|
|
@ -4887,13 +4887,12 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Cannot enable PCI device, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
|
||||
printk(KERN_ERR PFX "Cannot find proper PCI device "
|
||||
dev_err(&pdev->dev, "Cannot find proper PCI device "
|
||||
"base address, aborting.\n");
|
||||
err = -ENODEV;
|
||||
goto err_out_disable_pdev;
|
||||
|
@ -4901,7 +4900,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
|
||||
dev = alloc_etherdev(sizeof(*cp));
|
||||
if (!dev) {
|
||||
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
|
||||
dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
|
||||
err = -ENOMEM;
|
||||
goto err_out_disable_pdev;
|
||||
}
|
||||
|
@ -4910,8 +4909,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
|
||||
err = pci_request_regions(pdev, dev->name);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
|
||||
goto err_out_free_netdev;
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
@ -4941,7 +4939,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
if (pci_write_config_byte(pdev,
|
||||
PCI_CACHE_LINE_SIZE,
|
||||
cas_cacheline_size)) {
|
||||
printk(KERN_ERR PFX "Could not set PCI cache "
|
||||
dev_err(&pdev->dev, "Could not set PCI cache "
|
||||
"line size\n");
|
||||
goto err_write_cacheline;
|
||||
}
|
||||
|
@ -4955,7 +4953,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
err = pci_set_consistent_dma_mask(pdev,
|
||||
DMA_64BIT_MASK);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR PFX "Unable to obtain 64-bit DMA "
|
||||
dev_err(&pdev->dev, "Unable to obtain 64-bit DMA "
|
||||
"for consistent allocations\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
@ -4963,7 +4961,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
} else {
|
||||
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "No usable DMA configuration, "
|
||||
dev_err(&pdev->dev, "No usable DMA configuration, "
|
||||
"aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
@ -5023,8 +5021,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
/* give us access to cassini registers */
|
||||
cp->regs = pci_iomap(pdev, 0, casreg_len);
|
||||
if (cp->regs == 0UL) {
|
||||
printk(KERN_ERR PFX "Cannot map device registers, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
cp->casreg_len = casreg_len;
|
||||
|
@ -5040,8 +5037,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
|
||||
&cp->block_dvma);
|
||||
if (!cp->init_block) {
|
||||
printk(KERN_ERR PFX "Cannot allocate init block, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot allocate init block, aborting.\n");
|
||||
goto err_out_iounmap;
|
||||
}
|
||||
|
||||
|
@ -5085,8 +5081,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
|
|||
dev->features |= NETIF_F_HIGHDMA;
|
||||
|
||||
if (register_netdev(dev)) {
|
||||
printk(KERN_ERR PFX "Cannot register net device, "
|
||||
"aborting.\n");
|
||||
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
|
||||
goto err_out_free_consistent;
|
||||
}
|
||||
|
||||
|
|
|
@ -703,8 +703,8 @@ static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
|
||||
static irqreturn_t lance_interrupt(const int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) dev_id;
|
||||
struct lance_private *lp = netdev_priv(dev);
|
||||
|
@ -1253,7 +1253,7 @@ static int __init dec_lance_init(const int type, const int slot)
|
|||
return 0;
|
||||
|
||||
err_out_free_dev:
|
||||
kfree(dev);
|
||||
free_netdev(dev);
|
||||
|
||||
err_out:
|
||||
return ret;
|
||||
|
@ -1299,6 +1299,7 @@ static void __exit dec_lance_cleanup(void)
|
|||
while (root_lance_dev) {
|
||||
struct net_device *dev = root_lance_dev;
|
||||
struct lance_private *lp = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
#ifdef CONFIG_TC
|
||||
if (lp->slot >= 0)
|
||||
|
|
|
@ -9,49 +9,10 @@
|
|||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
*/
|
||||
/*
|
||||
Rev Date Description
|
||||
==========================================================================
|
||||
0.01 2001/05/03 Created DL2000-based linux driver
|
||||
0.02 2001/05/21 Added VLAN and hardware checksum support.
|
||||
1.00 2001/06/26 Added jumbo frame support.
|
||||
1.01 2001/08/21 Added two parameters, rx_coalesce and rx_timeout.
|
||||
1.02 2001/10/08 Supported fiber media.
|
||||
Added flow control parameters.
|
||||
1.03 2001/10/12 Changed the default media to 1000mbps_fd for
|
||||
the fiber devices.
|
||||
1.04 2001/11/08 Fixed Tx stopped when tx very busy.
|
||||
1.05 2001/11/22 Fixed Tx stopped when unidirectional tx busy.
|
||||
1.06 2001/12/13 Fixed disconnect bug at 10Mbps mode.
|
||||
Fixed tx_full flag incorrect.
|
||||
Added tx_coalesce paramter.
|
||||
1.07 2002/01/03 Fixed miscount of RX frame error.
|
||||
1.08 2002/01/17 Fixed the multicast bug.
|
||||
1.09 2002/03/07 Move rx-poll-now to re-fill loop.
|
||||
Added rio_timer() to watch rx buffers.
|
||||
1.10 2002/04/16 Fixed miscount of carrier error.
|
||||
1.11 2002/05/23 Added ISR schedule scheme
|
||||
Fixed miscount of rx frame error for DGE-550SX.
|
||||
Fixed VLAN bug.
|
||||
1.12 2002/06/13 Lock tx_coalesce=1 on 10/100Mbps mode.
|
||||
1.13 2002/08/13 1. Fix disconnection (many tx:carrier/rx:frame
|
||||
errs) with some mainboards.
|
||||
2. Use definition "DRV_NAME" "DRV_VERSION"
|
||||
"DRV_RELDATE" for flexibility.
|
||||
1.14 2002/08/14 Support ethtool.
|
||||
1.15 2002/08/27 Changed the default media to Auto-Negotiation
|
||||
for the fiber devices.
|
||||
1.16 2002/09/04 More power down time for fiber devices auto-
|
||||
negotiation.
|
||||
Fix disconnect bug after ifup and ifdown.
|
||||
1.17 2002/10/03 Fix RMON statistics overflow.
|
||||
Always use I/O mapping to access eeprom,
|
||||
avoid system freezing with some chipsets.
|
||||
|
||||
*/
|
||||
#define DRV_NAME "D-Link DL2000-based linux driver"
|
||||
#define DRV_VERSION "v1.17b"
|
||||
#define DRV_RELDATE "2006/03/10"
|
||||
#define DRV_VERSION "v1.18"
|
||||
#define DRV_RELDATE "2006/06/27"
|
||||
#include "dl2k.h"
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
|
|
|
@ -555,12 +555,12 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
|
|||
|
||||
if (!request_region(pci_resource_start(pdev, 1),
|
||||
pci_resource_len(pdev, 1), "eepro100")) {
|
||||
printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");
|
||||
dev_err(&pdev->dev, "eepro100: cannot reserve I/O ports\n");
|
||||
goto err_out_none;
|
||||
}
|
||||
if (!request_mem_region(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0), "eepro100")) {
|
||||
printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");
|
||||
dev_err(&pdev->dev, "eepro100: cannot reserve MMIO region\n");
|
||||
goto err_out_free_pio_region;
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
|
|||
|
||||
ioaddr = pci_iomap(pdev, pci_bar, 0);
|
||||
if (!ioaddr) {
|
||||
printk (KERN_ERR "eepro100: cannot remap IO\n");
|
||||
dev_err(&pdev->dev, "eepro100: cannot remap IO\n");
|
||||
goto err_out_free_mmio_region;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,62 +19,15 @@
|
|||
|
||||
Information and updates available at
|
||||
http://www.scyld.com/network/epic100.html
|
||||
[this link no longer provides anything useful -jgarzik]
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Linux kernel-specific changes:
|
||||
|
||||
LK1.1.2 (jgarzik):
|
||||
* Merge becker version 1.09 (4/08/2000)
|
||||
|
||||
LK1.1.3:
|
||||
* Major bugfix to 1.09 driver (Francis Romieu)
|
||||
|
||||
LK1.1.4 (jgarzik):
|
||||
* Merge becker test version 1.09 (5/29/2000)
|
||||
|
||||
LK1.1.5:
|
||||
* Fix locking (jgarzik)
|
||||
* Limit 83c175 probe to ethernet-class PCI devices (rgooch)
|
||||
|
||||
LK1.1.6:
|
||||
* Merge becker version 1.11
|
||||
* Move pci_enable_device before any PCI BAR len checks
|
||||
|
||||
LK1.1.7:
|
||||
* { fill me in }
|
||||
|
||||
LK1.1.8:
|
||||
* ethtool driver info support (jgarzik)
|
||||
|
||||
LK1.1.9:
|
||||
* ethtool media get/set support (jgarzik)
|
||||
|
||||
LK1.1.10:
|
||||
* revert MII transceiver init change (jgarzik)
|
||||
|
||||
LK1.1.11:
|
||||
* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
|
||||
* replace some MII-related magic numbers with constants
|
||||
|
||||
LK1.1.12:
|
||||
* fix power-up sequence
|
||||
|
||||
LK1.1.13:
|
||||
* revert version 1.1.12, power-up sequence "fix"
|
||||
|
||||
LK1.1.14 (Kryzsztof Halasa):
|
||||
* fix spurious bad initializations
|
||||
* pound phy a la SMSC's app note on the subject
|
||||
|
||||
AC1.1.14ac
|
||||
* fix power up/down for ethtool that broke in 1.11
|
||||
|
||||
*/
|
||||
|
||||
#define DRV_NAME "epic100"
|
||||
#define DRV_VERSION "1.11+LK1.1.14+AC1.1.14"
|
||||
#define DRV_RELDATE "June 2, 2004"
|
||||
#define DRV_VERSION "2.0"
|
||||
#define DRV_RELDATE "June 27, 2006"
|
||||
|
||||
/* The user-configurable values.
|
||||
These may be modified when a driver module is loaded.*/
|
||||
|
@ -204,19 +157,15 @@ typedef enum {
|
|||
|
||||
struct epic_chip_info {
|
||||
const char *name;
|
||||
int io_size; /* Needed for I/O region check or ioremap(). */
|
||||
int drv_flags; /* Driver use, intended as capability flags. */
|
||||
};
|
||||
|
||||
|
||||
/* indexed by chip_t */
|
||||
static const struct epic_chip_info pci_id_tbl[] = {
|
||||
{ "SMSC EPIC/100 83c170",
|
||||
EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
|
||||
{ "SMSC EPIC/100 83c170",
|
||||
EPIC_TOTAL_SIZE, TYPE2_INTR },
|
||||
{ "SMSC EPIC/C 83c175",
|
||||
EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
|
||||
{ "SMSC EPIC/100 83c170", TYPE2_INTR | NO_MII | MII_PWRDWN },
|
||||
{ "SMSC EPIC/100 83c170", TYPE2_INTR },
|
||||
{ "SMSC EPIC/C 83c175", TYPE2_INTR | MII_PWRDWN },
|
||||
};
|
||||
|
||||
|
||||
|
@ -385,8 +334,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
goto out;
|
||||
irq = pdev->irq;
|
||||
|
||||
if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
|
||||
printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
|
||||
if (pci_resource_len(pdev, 0) < EPIC_TOTAL_SIZE) {
|
||||
dev_err(&pdev->dev, "no PCI region space\n");
|
||||
ret = -ENODEV;
|
||||
goto err_out_disable;
|
||||
}
|
||||
|
@ -401,7 +350,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
|
||||
dev = alloc_etherdev(sizeof (*ep));
|
||||
if (!dev) {
|
||||
printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
|
||||
dev_err(&pdev->dev, "no memory for eth device\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
SET_MODULE_OWNER(dev);
|
||||
|
@ -413,7 +362,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
ioaddr = pci_resource_start (pdev, 1);
|
||||
ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
|
||||
if (!ioaddr) {
|
||||
printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
goto err_out_free_netdev;
|
||||
}
|
||||
#endif
|
||||
|
@ -473,8 +422,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
|
||||
|
||||
if (debug > 2) {
|
||||
printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n",
|
||||
pci_name(pdev));
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
|
||||
for (i = 0; i < 64; i++)
|
||||
printk(" %4.4x%s", read_eeprom(ioaddr, i),
|
||||
i % 16 == 15 ? "\n" : "");
|
||||
|
@ -496,21 +444,23 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
int mii_status = mdio_read(dev, phy, MII_BMSR);
|
||||
if (mii_status != 0xffff && mii_status != 0x0000) {
|
||||
ep->phys[phy_idx++] = phy;
|
||||
printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
|
||||
"%4.4x status %4.4x.\n",
|
||||
pci_name(pdev), phy, mdio_read(dev, phy, 0), mii_status);
|
||||
dev_info(&pdev->dev,
|
||||
"MII transceiver #%d control "
|
||||
"%4.4x status %4.4x.\n",
|
||||
phy, mdio_read(dev, phy, 0), mii_status);
|
||||
}
|
||||
}
|
||||
ep->mii_phy_cnt = phy_idx;
|
||||
if (phy_idx != 0) {
|
||||
phy = ep->phys[0];
|
||||
ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
|
||||
printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
|
||||
dev_info(&pdev->dev,
|
||||
"Autonegotiation advertising %4.4x link "
|
||||
"partner %4.4x.\n",
|
||||
pci_name(pdev), ep->mii.advertising, mdio_read(dev, phy, 5));
|
||||
ep->mii.advertising, mdio_read(dev, phy, 5));
|
||||
} else if ( ! (ep->chip_flags & NO_MII)) {
|
||||
printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
|
||||
pci_name(pdev));
|
||||
dev_warn(&pdev->dev,
|
||||
"***WARNING***: No MII transceiver found!\n");
|
||||
/* Use the known PHY address of the EPII. */
|
||||
ep->phys[0] = 3;
|
||||
}
|
||||
|
@ -525,8 +475,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
|||
/* The lower four bits are the media type. */
|
||||
if (duplex) {
|
||||
ep->mii.force_media = ep->mii.full_duplex = 1;
|
||||
printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n",
|
||||
pci_name(pdev));
|
||||
dev_info(&pdev->dev, "Forced full duplex requested.\n");
|
||||
}
|
||||
dev->if_port = ep->default_port = option;
|
||||
|
||||
|
|
|
@ -124,7 +124,9 @@ MODULE_PARM_DESC(multicast_filter_limit, "fealnx maximum number of filtered mult
|
|||
MODULE_PARM_DESC(options, "fealnx: Bits 0-3: media type, bit 17: full duplex");
|
||||
MODULE_PARM_DESC(full_duplex, "fealnx full duplex setting(s) (1)");
|
||||
|
||||
#define MIN_REGION_SIZE 136
|
||||
enum {
|
||||
MIN_REGION_SIZE = 136,
|
||||
};
|
||||
|
||||
/* A chip capabilities table, matching the entries in pci_tbl[] above. */
|
||||
enum chip_capability_flags {
|
||||
|
@ -146,14 +148,13 @@ enum phy_type_flags {
|
|||
|
||||
struct chip_info {
|
||||
char *chip_name;
|
||||
int io_size;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static const struct chip_info skel_netdrv_tbl[] = {
|
||||
{"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
|
||||
{"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR},
|
||||
{"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
|
||||
static const struct chip_info skel_netdrv_tbl[] __devinitdata = {
|
||||
{ "100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
|
||||
{ "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR },
|
||||
{ "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
|
||||
};
|
||||
|
||||
/* Offsets to the Command and Status Registers. */
|
||||
|
@ -504,13 +505,14 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
|
|||
|
||||
len = pci_resource_len(pdev, bar);
|
||||
if (len < MIN_REGION_SIZE) {
|
||||
printk(KERN_ERR "%s: region size %ld too small, aborting\n",
|
||||
boardname, len);
|
||||
dev_err(&pdev->dev,
|
||||
"region size %ld too small, aborting\n", len);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
i = pci_request_regions(pdev, boardname);
|
||||
if (i) return i;
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
irq = pdev->irq;
|
||||
|
||||
|
@ -576,9 +578,9 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
|
|||
|
||||
if (mii_status != 0xffff && mii_status != 0x0000) {
|
||||
np->phys[phy_idx++] = phy;
|
||||
printk(KERN_INFO
|
||||
"%s: MII PHY found at address %d, status "
|
||||
"0x%4.4x.\n", dev->name, phy, mii_status);
|
||||
dev_info(&pdev->dev,
|
||||
"MII PHY found at address %d, status "
|
||||
"0x%4.4x.\n", phy, mii_status);
|
||||
/* get phy type */
|
||||
{
|
||||
unsigned int data;
|
||||
|
@ -601,10 +603,10 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
np->mii_cnt = phy_idx;
|
||||
if (phy_idx == 0) {
|
||||
printk(KERN_WARNING "%s: MII PHY not found -- this device may "
|
||||
"not operate correctly.\n", dev->name);
|
||||
}
|
||||
if (phy_idx == 0)
|
||||
dev_warn(&pdev->dev,
|
||||
"MII PHY not found -- this device may "
|
||||
"not operate correctly.\n");
|
||||
} else {
|
||||
np->phys[0] = 32;
|
||||
/* 89/6/23 add, (begin) */
|
||||
|
@ -630,7 +632,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
|
|||
np->mii.full_duplex = full_duplex[card_idx];
|
||||
|
||||
if (np->mii.full_duplex) {
|
||||
printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
|
||||
dev_info(&pdev->dev, "Media type forced to Full Duplex.\n");
|
||||
/* 89/6/13 add, (begin) */
|
||||
// if (np->PHYType==MarvellPHY)
|
||||
if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {
|
||||
|
|
|
@ -699,7 +699,6 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
|
|||
memset(gp, 0, sizeof(*gp)); // clear it
|
||||
|
||||
gp->port_num = port_num;
|
||||
gp->io_size = GT96100_ETH_IO_SIZE;
|
||||
gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
|
||||
gp->phy_addr = phy_addr;
|
||||
gp->chip_rev = chip_rev;
|
||||
|
@ -1531,7 +1530,7 @@ static void gt96100_cleanup_module(void)
|
|||
+ sizeof(gt96100_td_t) * TX_RING_SIZE,
|
||||
gp->rx_ring);
|
||||
free_netdev(gtif->dev);
|
||||
release_region(gtif->iobase, gp->io_size);
|
||||
release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,7 +331,6 @@ struct gt96100_private {
|
|||
mib_counters_t mib;
|
||||
struct net_device_stats stats;
|
||||
|
||||
int io_size;
|
||||
int port_num; // 0 or 1
|
||||
int chip_rev;
|
||||
u32 port_offset;
|
||||
|
@ -340,7 +339,6 @@ struct gt96100_private {
|
|||
u32 last_psr; // last value of the port status register
|
||||
|
||||
int options; /* User-settable misc. driver options. */
|
||||
int drv_flags;
|
||||
struct timer_list timer;
|
||||
spinlock_t lock; /* Serialise access to device */
|
||||
};
|
||||
|
|
|
@ -20,22 +20,15 @@
|
|||
|
||||
Support and updates available at
|
||||
http://www.scyld.com/network/hamachi.html
|
||||
[link no longer provides useful info -jgarzik]
|
||||
or
|
||||
http://www.parl.clemson.edu/~keithu/hamachi.html
|
||||
|
||||
|
||||
|
||||
Linux kernel changelog:
|
||||
|
||||
LK1.0.1:
|
||||
- fix lack of pci_dev<->dev association
|
||||
- ethtool support (jgarzik)
|
||||
|
||||
*/
|
||||
|
||||
#define DRV_NAME "hamachi"
|
||||
#define DRV_VERSION "1.01+LK1.0.1"
|
||||
#define DRV_RELDATE "5/18/2001"
|
||||
#define DRV_VERSION "2.0"
|
||||
#define DRV_RELDATE "June 27, 2006"
|
||||
|
||||
|
||||
/* A few user-configurable values. */
|
||||
|
@ -608,7 +601,8 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
|
|||
pci_set_master(pdev);
|
||||
|
||||
i = pci_request_regions(pdev, DRV_NAME);
|
||||
if (i) return i;
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
irq = pdev->irq;
|
||||
ioaddr = ioremap(base, 0x400);
|
||||
|
|
|
@ -188,7 +188,6 @@ struct myri10ge_priv {
|
|||
int vendor_specific_offset;
|
||||
u32 devctl;
|
||||
u16 msi_flags;
|
||||
u32 pm_state[16];
|
||||
u32 read_dma;
|
||||
u32 write_dma;
|
||||
u32 read_write_dma;
|
||||
|
@ -1289,6 +1288,7 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
|
|||
"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
|
||||
"tx_heartbeat_errors", "tx_window_errors",
|
||||
/* device-specific stats */
|
||||
"tx_boundary", "WC", "irq", "MSI",
|
||||
"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
|
||||
"serial_number", "tx_pkt_start", "tx_pkt_done",
|
||||
"tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
|
||||
|
@ -1327,6 +1327,10 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
|
|||
for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
|
||||
data[i] = ((unsigned long *)&mgp->stats)[i];
|
||||
|
||||
data[i++] = (unsigned int)mgp->tx.boundary;
|
||||
data[i++] = (unsigned int)(mgp->mtrr >= 0);
|
||||
data[i++] = (unsigned int)mgp->pdev->irq;
|
||||
data[i++] = (unsigned int)mgp->msi_enabled;
|
||||
data[i++] = (unsigned int)mgp->read_dma;
|
||||
data[i++] = (unsigned int)mgp->write_dma;
|
||||
data[i++] = (unsigned int)mgp->read_write_dma;
|
||||
|
@ -2197,8 +2201,6 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
|
|||
* any other device, except if forced with myri10ge_ecrc_enable > 1.
|
||||
*/
|
||||
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE 0x005d
|
||||
|
||||
static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
|
||||
{
|
||||
struct pci_dev *bridge = mgp->pdev->bus->self;
|
||||
|
@ -2737,11 +2739,10 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
|
||||
goto abort_with_irq;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n",
|
||||
netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"),
|
||||
pdev->irq, mgp->tx.boundary, mgp->fw_name,
|
||||
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
|
||||
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
|
||||
(mgp->msi_enabled ? "MSI" : "xPIC"),
|
||||
pdev->irq, mgp->tx.boundary, mgp->fw_name,
|
||||
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -20,120 +20,9 @@
|
|||
|
||||
Support information and updates available at
|
||||
http://www.scyld.com/network/netsemi.html
|
||||
[link no longer provides useful info -jgarzik]
|
||||
|
||||
|
||||
Linux kernel modifications:
|
||||
|
||||
Version 1.0.1:
|
||||
- Spinlock fixes
|
||||
- Bug fixes and better intr performance (Tjeerd)
|
||||
Version 1.0.2:
|
||||
- Now reads correct MAC address from eeprom
|
||||
Version 1.0.3:
|
||||
- Eliminate redundant priv->tx_full flag
|
||||
- Call netif_start_queue from dev->tx_timeout
|
||||
- wmb() in start_tx() to flush data
|
||||
- Update Tx locking
|
||||
- Clean up PCI enable (davej)
|
||||
Version 1.0.4:
|
||||
- Merge Donald Becker's natsemi.c version 1.07
|
||||
Version 1.0.5:
|
||||
- { fill me in }
|
||||
Version 1.0.6:
|
||||
* ethtool support (jgarzik)
|
||||
* Proper initialization of the card (which sometimes
|
||||
fails to occur and leaves the card in a non-functional
|
||||
state). (uzi)
|
||||
|
||||
* Some documented register settings to optimize some
|
||||
of the 100Mbit autodetection circuitry in rev C cards. (uzi)
|
||||
|
||||
* Polling of the PHY intr for stuff like link state
|
||||
change and auto- negotiation to finally work properly. (uzi)
|
||||
|
||||
* One-liner removal of a duplicate declaration of
|
||||
netdev_error(). (uzi)
|
||||
|
||||
Version 1.0.7: (Manfred Spraul)
|
||||
* pci dma
|
||||
* SMP locking update
|
||||
* full reset added into tx_timeout
|
||||
* correct multicast hash generation (both big and little endian)
|
||||
[copied from a natsemi driver version
|
||||
from Myrio Corporation, Greg Smith]
|
||||
* suspend/resume
|
||||
|
||||
version 1.0.8 (Tim Hockin <thockin@sun.com>)
|
||||
* ETHTOOL_* support
|
||||
* Wake on lan support (Erik Gilling)
|
||||
* MXDMA fixes for serverworks
|
||||
* EEPROM reload
|
||||
|
||||
version 1.0.9 (Manfred Spraul)
|
||||
* Main change: fix lack of synchronize
|
||||
netif_close/netif_suspend against a last interrupt
|
||||
or packet.
|
||||
* do not enable superflous interrupts (e.g. the
|
||||
drivers relies on TxDone - TxIntr not needed)
|
||||
* wait that the hardware has really stopped in close
|
||||
and suspend.
|
||||
* workaround for the (at least) gcc-2.95.1 compiler
|
||||
problem. Also simplifies the code a bit.
|
||||
* disable_irq() in tx_timeout - needed to protect
|
||||
against rx interrupts.
|
||||
* stop the nic before switching into silent rx mode
|
||||
for wol (required according to docu).
|
||||
|
||||
version 1.0.10:
|
||||
* use long for ee_addr (various)
|
||||
* print pointers properly (DaveM)
|
||||
* include asm/irq.h (?)
|
||||
|
||||
version 1.0.11:
|
||||
* check and reset if PHY errors appear (Adrian Sun)
|
||||
* WoL cleanup (Tim Hockin)
|
||||
* Magic number cleanup (Tim Hockin)
|
||||
* Don't reload EEPROM on every reset (Tim Hockin)
|
||||
* Save and restore EEPROM state across reset (Tim Hockin)
|
||||
* MDIO Cleanup (Tim Hockin)
|
||||
* Reformat register offsets/bits (jgarzik)
|
||||
|
||||
version 1.0.12:
|
||||
* ETHTOOL_* further support (Tim Hockin)
|
||||
|
||||
version 1.0.13:
|
||||
* ETHTOOL_[G]EEPROM support (Tim Hockin)
|
||||
|
||||
version 1.0.13:
|
||||
* crc cleanup (Matt Domsch <Matt_Domsch@dell.com>)
|
||||
|
||||
version 1.0.14:
|
||||
* Cleanup some messages and autoneg in ethtool (Tim Hockin)
|
||||
|
||||
version 1.0.15:
|
||||
* Get rid of cable_magic flag
|
||||
* use new (National provided) solution for cable magic issue
|
||||
|
||||
version 1.0.16:
|
||||
* call netdev_rx() for RxErrors (Manfred Spraul)
|
||||
* formatting and cleanups
|
||||
* change options and full_duplex arrays to be zero
|
||||
initialized
|
||||
* enable only the WoL and PHY interrupts in wol mode
|
||||
|
||||
version 1.0.17:
|
||||
* only do cable_magic on 83815 and early 83816 (Tim Hockin)
|
||||
* create a function for rx refill (Manfred Spraul)
|
||||
* combine drain_ring and init_ring (Manfred Spraul)
|
||||
* oom handling (Manfred Spraul)
|
||||
* hands_off instead of playing with netif_device_{de,a}ttach
|
||||
(Manfred Spraul)
|
||||
* be sure to write the MAC back to the chip (Manfred Spraul)
|
||||
* lengthen EEPROM timeout, and always warn about timeouts
|
||||
(Manfred Spraul)
|
||||
* comments update (Manfred)
|
||||
* do the right thing on a phy-reset (Manfred and Tim)
|
||||
|
||||
TODO:
|
||||
* big endian support with CFG:BEM instead of cpu_to_le32
|
||||
*/
|
||||
|
@ -165,8 +54,8 @@
|
|||
#include <asm/uaccess.h>
|
||||
|
||||
#define DRV_NAME "natsemi"
|
||||
#define DRV_VERSION "1.07+LK1.0.17"
|
||||
#define DRV_RELDATE "Sep 27, 2002"
|
||||
#define DRV_VERSION "2.0"
|
||||
#define DRV_RELDATE "June 27, 2006"
|
||||
|
||||
#define RX_OFFSET 2
|
||||
|
||||
|
|
|
@ -231,12 +231,12 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
|
|||
irq = pdev->irq;
|
||||
|
||||
if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
|
||||
printk (KERN_ERR PFX "no I/O resource at PCI BAR #0\n");
|
||||
dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) {
|
||||
printk (KERN_ERR PFX "I/O resource 0x%x @ 0x%lx busy\n",
|
||||
dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n",
|
||||
NE_IO_EXTENT, ioaddr);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
|
|||
/* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
|
||||
dev = alloc_ei_netdev();
|
||||
if (!dev) {
|
||||
printk (KERN_ERR PFX "cannot allocate ethernet device\n");
|
||||
dev_err(&pdev->dev, "cannot allocate ethernet device\n");
|
||||
goto err_out_free_res;
|
||||
}
|
||||
SET_MODULE_OWNER(dev);
|
||||
|
@ -281,7 +281,8 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
|
|||
while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
|
||||
/* Limit wait: '2' avoids jiffy roll-over. */
|
||||
if (jiffies - reset_start_time > 2) {
|
||||
printk(KERN_ERR PFX "Card failure (no reset ack).\n");
|
||||
dev_err(&pdev->dev,
|
||||
"Card failure (no reset ack).\n");
|
||||
goto err_out_free_netdev;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
/* ni5010.c: A network driver for the MiCom-Interlan NI5010 ethercard.
|
||||
*
|
||||
* Copyright 1996,1997 Jan-Pascal van Best and Andreas Mohr.
|
||||
* Copyright 1996,1997,2006 Jan-Pascal van Best and Andreas Mohr.
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
* The authors may be reached as:
|
||||
* jvbest@wi.leidenuniv.nl a.mohr@mailto.de
|
||||
* or by snail mail as
|
||||
* Jan-Pascal van Best Andreas Mohr
|
||||
* Klikspaanweg 58-4 Stauferstr. 6
|
||||
* 2324 LZ Leiden D-71272 Renningen
|
||||
* The Netherlands Germany
|
||||
* janpascal@vanbest.org andi@lisas.de
|
||||
*
|
||||
* Sources:
|
||||
* Donald Becker's "skeleton.c"
|
||||
|
@ -27,8 +22,9 @@
|
|||
* 970503 v0.93: Fixed auto-irq failure on warm reboot (JB)
|
||||
* 970623 v1.00: First kernel version (AM)
|
||||
* 970814 v1.01: Added detection of onboard receive buffer size (AM)
|
||||
* 060611 v1.02: slight cleanup: email addresses, driver modernization.
|
||||
* Bugs:
|
||||
* - None known...
|
||||
* - not SMP-safe (no locking of I/O accesses)
|
||||
* - Note that you have to patch ifconfig for the new /proc/net/dev
|
||||
* format. It gives incorrect stats otherwise.
|
||||
*
|
||||
|
@ -39,7 +35,7 @@
|
|||
* Complete merge with Andreas' driver
|
||||
* Implement ring buffers (Is this useful? You can't squeeze
|
||||
* too many packet in a 2k buffer!)
|
||||
* Implement DMA (Again, is this useful? Some docs says DMA is
|
||||
* Implement DMA (Again, is this useful? Some docs say DMA is
|
||||
* slower than programmed I/O)
|
||||
*
|
||||
* Compile with:
|
||||
|
@ -47,7 +43,7 @@
|
|||
* -DMODULE -c ni5010.c
|
||||
*
|
||||
* Insert with e.g.:
|
||||
* insmod ni5010.o io=0x300 irq=5
|
||||
* insmod ni5010.ko io=0x300 irq=5
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -69,15 +65,15 @@
|
|||
|
||||
#include "ni5010.h"
|
||||
|
||||
static const char *boardname = "NI5010";
|
||||
static char *version =
|
||||
"ni5010.c: v1.00 06/23/97 Jan-Pascal van Best and Andreas Mohr\n";
|
||||
static const char boardname[] = "NI5010";
|
||||
static char version[] __initdata =
|
||||
"ni5010.c: v1.02 20060611 Jan-Pascal van Best and Andreas Mohr\n";
|
||||
|
||||
/* bufsize_rcv == 0 means autoprobing */
|
||||
static unsigned int bufsize_rcv;
|
||||
|
||||
#define jumpered_interrupts /* IRQ line jumpered on board */
|
||||
#undef jumpered_dma /* No DMA used */
|
||||
#define JUMPERED_INTERRUPTS /* IRQ line jumpered on board */
|
||||
#undef JUMPERED_DMA /* No DMA used */
|
||||
#undef FULL_IODETECT /* Only detect in portlist */
|
||||
|
||||
#ifndef FULL_IODETECT
|
||||
|
@ -281,7 +277,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
|
|||
|
||||
PRINTK2((KERN_DEBUG "%s: I/O #4 passed!\n", dev->name));
|
||||
|
||||
#ifdef jumpered_interrupts
|
||||
#ifdef JUMPERED_INTERRUPTS
|
||||
if (dev->irq == 0xff)
|
||||
;
|
||||
else if (dev->irq < 2) {
|
||||
|
@ -305,7 +301,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
|
|||
} else if (dev->irq == 2) {
|
||||
dev->irq = 9;
|
||||
}
|
||||
#endif /* jumpered_irq */
|
||||
#endif /* JUMPERED_INTERRUPTS */
|
||||
PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name));
|
||||
|
||||
/* DMA is not supported (yet?), so no use detecting it */
|
||||
|
@ -334,7 +330,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
|
|||
outw(0, IE_GP); /* Point GP at start of packet */
|
||||
outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */
|
||||
}
|
||||
printk("// bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
|
||||
printk("-> bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
|
||||
memset(dev->priv, 0, sizeof(struct ni5010_local));
|
||||
|
||||
dev->open = ni5010_open;
|
||||
|
@ -354,11 +350,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
|
|||
outb(0xff, EDLC_XCLR); /* Kill all pending xmt interrupts */
|
||||
|
||||
printk(KERN_INFO "%s: NI5010 found at 0x%x, using IRQ %d", dev->name, ioaddr, dev->irq);
|
||||
if (dev->dma) printk(" & DMA %d", dev->dma);
|
||||
if (dev->dma)
|
||||
printk(" & DMA %d", dev->dma);
|
||||
printk(".\n");
|
||||
|
||||
printk(KERN_INFO "Join the NI5010 driver development team!\n");
|
||||
printk(KERN_INFO "Mail to a.mohr@mailto.de or jvbest@wi.leidenuniv.nl\n");
|
||||
return 0;
|
||||
out:
|
||||
release_region(dev->base_addr, NI5010_IO_EXTENT);
|
||||
|
@ -371,7 +365,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
|
|||
*
|
||||
* This routine should set everything up anew at each open, even
|
||||
* registers that "should" only need to be set once at boot, so that
|
||||
* there is non-reboot way to recover if something goes wrong.
|
||||
* there is a non-reboot way to recover if something goes wrong.
|
||||
*/
|
||||
|
||||
static int ni5010_open(struct net_device *dev)
|
||||
|
@ -390,13 +384,13 @@ static int ni5010_open(struct net_device *dev)
|
|||
* Always allocate the DMA channel after the IRQ,
|
||||
* and clean up on failure.
|
||||
*/
|
||||
#ifdef jumpered_dma
|
||||
#ifdef JUMPERED_DMA
|
||||
if (request_dma(dev->dma, cardname)) {
|
||||
printk(KERN_WARNING "%s: Cannot get dma %#2x\n", dev->name, dev->dma);
|
||||
free_irq(dev->irq, NULL);
|
||||
return -EAGAIN;
|
||||
}
|
||||
#endif /* jumpered_dma */
|
||||
#endif /* JUMPERED_DMA */
|
||||
|
||||
PRINTK3((KERN_DEBUG "%s: passed open() #2\n", dev->name));
|
||||
/* Reset the hardware here. Don't forget to set the station address. */
|
||||
|
@ -633,7 +627,7 @@ static int ni5010_close(struct net_device *dev)
|
|||
int ioaddr = dev->base_addr;
|
||||
|
||||
PRINTK2((KERN_DEBUG "%s: entering ni5010_close\n", dev->name));
|
||||
#ifdef jumpered_interrupts
|
||||
#ifdef JUMPERED_INTERRUPTS
|
||||
free_irq(dev->irq, NULL);
|
||||
#endif
|
||||
/* Put card in held-RESET state */
|
||||
|
@ -771,7 +765,7 @@ module_param(irq, int, 0);
|
|||
MODULE_PARM_DESC(io, "ni5010 I/O base address");
|
||||
MODULE_PARM_DESC(irq, "ni5010 IRQ number");
|
||||
|
||||
int init_module(void)
|
||||
static int __init ni5010_init_module(void)
|
||||
{
|
||||
PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));
|
||||
/*
|
||||
|
@ -792,13 +786,15 @@ int init_module(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
static void __exit ni5010_cleanup_module(void)
|
||||
{
|
||||
PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));
|
||||
unregister_netdev(dev_ni5010);
|
||||
release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);
|
||||
free_netdev(dev_ni5010);
|
||||
}
|
||||
module_init(ni5010_init_module);
|
||||
module_exit(ni5010_cleanup_module);
|
||||
#endif /* MODULE */
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
|
@ -803,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
|
|||
|
||||
writel(dev->IMR_cache, dev->base + IMR);
|
||||
writel(1, dev->base + IER);
|
||||
spin_unlock_irq(&dev->misc_lock);
|
||||
spin_unlock(&dev->misc_lock);
|
||||
|
||||
kick_rx(ndev);
|
||||
|
||||
|
@ -1012,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev)
|
|||
struct ns83820 *dev = PRIV(ndev);
|
||||
u32 cmdsts, tx_done_idx, *desc;
|
||||
|
||||
spin_lock_irq(&dev->tx_lock);
|
||||
|
||||
dprintk("do_tx_done(%p)\n", ndev);
|
||||
tx_done_idx = dev->tx_done_idx;
|
||||
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
||||
|
@ -1069,7 +1067,6 @@ static void do_tx_done(struct net_device *ndev)
|
|||
netif_start_queue(ndev);
|
||||
netif_wake_queue(ndev);
|
||||
}
|
||||
spin_unlock_irq(&dev->tx_lock);
|
||||
}
|
||||
|
||||
static void ns83820_cleanup_tx(struct ns83820 *dev)
|
||||
|
@ -1281,11 +1278,13 @@ static struct ethtool_ops ops = {
|
|||
.get_link = ns83820_get_link
|
||||
};
|
||||
|
||||
/* this function is called in irq context from the ISR */
|
||||
static void ns83820_mib_isr(struct ns83820 *dev)
|
||||
{
|
||||
spin_lock(&dev->misc_lock);
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&dev->misc_lock, flags);
|
||||
ns83820_update_stats(dev);
|
||||
spin_unlock(&dev->misc_lock);
|
||||
spin_unlock_irqrestore(&dev->misc_lock, flags);
|
||||
}
|
||||
|
||||
static void ns83820_do_isr(struct net_device *ndev, u32 isr);
|
||||
|
@ -1307,6 +1306,8 @@ static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs)
|
|||
static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
||||
{
|
||||
struct ns83820 *dev = PRIV(ndev);
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC))
|
||||
Dprintk("odd isr? 0x%08x\n", isr);
|
||||
|
@ -1321,10 +1322,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|||
if ((ISR_RXDESC | ISR_RXOK) & isr) {
|
||||
prefetch(dev->rx_info.next_rx_desc);
|
||||
|
||||
spin_lock_irq(&dev->misc_lock);
|
||||
spin_lock_irqsave(&dev->misc_lock, flags);
|
||||
dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK);
|
||||
writel(dev->IMR_cache, dev->base + IMR);
|
||||
spin_unlock_irq(&dev->misc_lock);
|
||||
spin_unlock_irqrestore(&dev->misc_lock, flags);
|
||||
|
||||
tasklet_schedule(&dev->rx_tasklet);
|
||||
//rx_irq(ndev);
|
||||
|
@ -1370,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|||
* work has accumulated
|
||||
*/
|
||||
if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) {
|
||||
spin_lock_irqsave(&dev->tx_lock, flags);
|
||||
do_tx_done(ndev);
|
||||
spin_unlock_irqrestore(&dev->tx_lock, flags);
|
||||
|
||||
/* Disable TxOk if there are no outstanding tx packets.
|
||||
*/
|
||||
if ((dev->tx_done_idx == dev->tx_free_idx) &&
|
||||
(dev->IMR_cache & ISR_TXOK)) {
|
||||
spin_lock_irq(&dev->misc_lock);
|
||||
spin_lock_irqsave(&dev->misc_lock, flags);
|
||||
dev->IMR_cache &= ~ISR_TXOK;
|
||||
writel(dev->IMR_cache, dev->base + IMR);
|
||||
spin_unlock_irq(&dev->misc_lock);
|
||||
spin_unlock_irqrestore(&dev->misc_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1390,10 +1393,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|||
* nature are expected, we must enable TxOk.
|
||||
*/
|
||||
if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) {
|
||||
spin_lock_irq(&dev->misc_lock);
|
||||
spin_lock_irqsave(&dev->misc_lock, flags);
|
||||
dev->IMR_cache |= ISR_TXOK;
|
||||
writel(dev->IMR_cache, dev->base + IMR);
|
||||
spin_unlock_irq(&dev->misc_lock);
|
||||
spin_unlock_irqrestore(&dev->misc_lock, flags);
|
||||
}
|
||||
|
||||
/* MIB interrupt: one of the statistics counters is about to overflow */
|
||||
|
@ -1455,7 +1458,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
|
|||
u32 tx_done_idx, *desc;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
spin_lock_irqsave(&dev->tx_lock, flags);
|
||||
|
||||
tx_done_idx = dev->tx_done_idx;
|
||||
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
||||
|
@ -1482,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
|
|||
ndev->name,
|
||||
tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS]));
|
||||
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(&dev->tx_lock, flags);
|
||||
}
|
||||
|
||||
static void ns83820_tx_watch(unsigned long data)
|
||||
|
@ -1832,7 +1835,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
} else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
|
||||
using_dac = 0;
|
||||
} else {
|
||||
printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n");
|
||||
dev_warn(&pci_dev->dev, "pci_set_dma_mask failed!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1855,7 +1858,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
|
||||
err = pci_enable_device(pci_dev);
|
||||
if (err) {
|
||||
printk(KERN_INFO "ns83820: pci_enable_dev failed: %d\n", err);
|
||||
dev_info(&pci_dev->dev, "pci_enable_dev failed: %d\n", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -1884,8 +1887,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
err = request_irq(pci_dev->irq, ns83820_irq, IRQF_SHARED,
|
||||
DRV_NAME, ndev);
|
||||
if (err) {
|
||||
printk(KERN_INFO "ns83820: unable to register irq %d\n",
|
||||
pci_dev->irq);
|
||||
dev_info(&pci_dev->dev, "unable to register irq %d, err %d\n",
|
||||
pci_dev->irq, err);
|
||||
goto out_disable;
|
||||
}
|
||||
|
||||
|
@ -1899,7 +1902,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
|
|||
rtnl_lock();
|
||||
err = dev_alloc_name(ndev, ndev->name);
|
||||
if (err < 0) {
|
||||
printk(KERN_INFO "ns83820: unable to get netdev name: %d\n", err);
|
||||
dev_info(&pci_dev->dev, "unable to get netdev name: %d\n", err);
|
||||
goto out_free_irq;
|
||||
}
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
|
|||
/* dev zeroed in alloc_etherdev */
|
||||
dev = alloc_etherdev (sizeof (*tp));
|
||||
if (dev == NULL) {
|
||||
printk (KERN_ERR PFX "unable to alloc new ethernet\n");
|
||||
dev_err(&pdev->dev, "unable to alloc new ethernet\n");
|
||||
DPRINTK ("EXIT, returning -ENOMEM\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -631,14 +631,14 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
|
|||
|
||||
/* make sure PCI base addr 0 is PIO */
|
||||
if (!(pio_flags & IORESOURCE_IO)) {
|
||||
printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");
|
||||
dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* make sure PCI base addr 1 is MMIO */
|
||||
if (!(mmio_flags & IORESOURCE_MEM)) {
|
||||
printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
|
||||
dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -646,12 +646,12 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
|
|||
/* check for weird/broken PCI region reporting */
|
||||
if ((pio_len < NETDRV_MIN_IO_SIZE) ||
|
||||
(mmio_len < NETDRV_MIN_IO_SIZE)) {
|
||||
printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
|
||||
dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rc = pci_request_regions (pdev, "pci-skeleton");
|
||||
rc = pci_request_regions (pdev, MODNAME);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
|
@ -663,7 +663,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
|
|||
/* ioremap MMIO region */
|
||||
ioaddr = ioremap (mmio_start, mmio_len);
|
||||
if (ioaddr == NULL) {
|
||||
printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
|
||||
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
|
||||
rc = -EIO;
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
@ -699,9 +699,10 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
|
||||
printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
|
||||
pci_name(pdev));
|
||||
printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pci_name(pdev), NETDRV_R32 (TxConfig));
|
||||
dev_printk (KERN_DEBUG, &pdev->dev,
|
||||
"unknown chip version, assuming RTL-8139\n");
|
||||
dev_printk (KERN_DEBUG, &pdev->dev, "TxConfig = 0x%lx\n",
|
||||
NETDRV_R32 (TxConfig));
|
||||
tp->chipset = 0;
|
||||
|
||||
match:
|
||||
|
|
|
@ -58,18 +58,15 @@ static const char *const version =
|
|||
* PCI device identifiers for "new style" Linux PCI Device Drivers
|
||||
*/
|
||||
static struct pci_device_id pcnet32_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
|
||||
|
||||
/*
|
||||
* Adapters that were sold with IBM's RS/6000 or pSeries hardware have
|
||||
* the incorrect vendor id.
|
||||
*/
|
||||
{ PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
|
||||
.class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, },
|
||||
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
@ -188,6 +185,23 @@ static int homepna[MAX_UNITS];
|
|||
|
||||
#define PCNET32_TOTAL_SIZE 0x20
|
||||
|
||||
#define CSR0 0
|
||||
#define CSR0_INIT 0x1
|
||||
#define CSR0_START 0x2
|
||||
#define CSR0_STOP 0x4
|
||||
#define CSR0_TXPOLL 0x8
|
||||
#define CSR0_INTEN 0x40
|
||||
#define CSR0_IDON 0x0100
|
||||
#define CSR0_NORMAL (CSR0_START | CSR0_INTEN)
|
||||
#define PCNET32_INIT_LOW 1
|
||||
#define PCNET32_INIT_HIGH 2
|
||||
#define CSR3 3
|
||||
#define CSR4 4
|
||||
#define CSR5 5
|
||||
#define CSR5_SUSPEND 0x0001
|
||||
#define CSR15 15
|
||||
#define PCNET32_MC_FILTER 8
|
||||
|
||||
/* The PCNET32 Rx and Tx ring descriptors. */
|
||||
struct pcnet32_rx_head {
|
||||
u32 base;
|
||||
|
@ -277,7 +291,6 @@ struct pcnet32_private {
|
|||
u32 phymask;
|
||||
};
|
||||
|
||||
static void pcnet32_probe_vlbus(void);
|
||||
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
|
||||
static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
|
||||
static int pcnet32_open(struct net_device *);
|
||||
|
@ -419,6 +432,238 @@ static struct pcnet32_access pcnet32_dwio = {
|
|||
.reset = pcnet32_dwio_reset
|
||||
};
|
||||
|
||||
static void pcnet32_netif_stop(struct net_device *dev)
|
||||
{
|
||||
dev->trans_start = jiffies;
|
||||
netif_poll_disable(dev);
|
||||
netif_tx_disable(dev);
|
||||
}
|
||||
|
||||
static void pcnet32_netif_start(struct net_device *dev)
|
||||
{
|
||||
netif_wake_queue(dev);
|
||||
netif_poll_enable(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the new sized tx ring.
|
||||
* Free old resources
|
||||
* Save new resources.
|
||||
* Any failure keeps old resources.
|
||||
* Must be called with lp->lock held.
|
||||
*/
|
||||
static void pcnet32_realloc_tx_ring(struct net_device *dev,
|
||||
struct pcnet32_private *lp,
|
||||
unsigned int size)
|
||||
{
|
||||
dma_addr_t new_ring_dma_addr;
|
||||
dma_addr_t *new_dma_addr_list;
|
||||
struct pcnet32_tx_head *new_tx_ring;
|
||||
struct sk_buff **new_skb_list;
|
||||
|
||||
pcnet32_purge_tx_ring(dev);
|
||||
|
||||
new_tx_ring = pci_alloc_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_tx_head) *
|
||||
(1 << size),
|
||||
&new_ring_dma_addr);
|
||||
if (new_tx_ring == NULL) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Consistent memory allocation failed.\n",
|
||||
dev->name);
|
||||
return;
|
||||
}
|
||||
memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
|
||||
|
||||
new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
|
||||
GFP_ATOMIC);
|
||||
if (!new_dma_addr_list) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Memory allocation failed.\n", dev->name);
|
||||
goto free_new_tx_ring;
|
||||
}
|
||||
|
||||
new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
|
||||
GFP_ATOMIC);
|
||||
if (!new_skb_list) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Memory allocation failed.\n", dev->name);
|
||||
goto free_new_lists;
|
||||
}
|
||||
|
||||
kfree(lp->tx_skbuff);
|
||||
kfree(lp->tx_dma_addr);
|
||||
pci_free_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_tx_head) *
|
||||
lp->tx_ring_size, lp->tx_ring,
|
||||
lp->tx_ring_dma_addr);
|
||||
|
||||
lp->tx_ring_size = (1 << size);
|
||||
lp->tx_mod_mask = lp->tx_ring_size - 1;
|
||||
lp->tx_len_bits = (size << 12);
|
||||
lp->tx_ring = new_tx_ring;
|
||||
lp->tx_ring_dma_addr = new_ring_dma_addr;
|
||||
lp->tx_dma_addr = new_dma_addr_list;
|
||||
lp->tx_skbuff = new_skb_list;
|
||||
return;
|
||||
|
||||
free_new_lists:
|
||||
kfree(new_dma_addr_list);
|
||||
free_new_tx_ring:
|
||||
pci_free_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_tx_head) *
|
||||
(1 << size),
|
||||
new_tx_ring,
|
||||
new_ring_dma_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the new sized rx ring.
|
||||
* Re-use old receive buffers.
|
||||
* alloc extra buffers
|
||||
* free unneeded buffers
|
||||
* free unneeded buffers
|
||||
* Save new resources.
|
||||
* Any failure keeps old resources.
|
||||
* Must be called with lp->lock held.
|
||||
*/
|
||||
static void pcnet32_realloc_rx_ring(struct net_device *dev,
|
||||
struct pcnet32_private *lp,
|
||||
unsigned int size)
|
||||
{
|
||||
dma_addr_t new_ring_dma_addr;
|
||||
dma_addr_t *new_dma_addr_list;
|
||||
struct pcnet32_rx_head *new_rx_ring;
|
||||
struct sk_buff **new_skb_list;
|
||||
int new, overlap;
|
||||
|
||||
new_rx_ring = pci_alloc_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_rx_head) *
|
||||
(1 << size),
|
||||
&new_ring_dma_addr);
|
||||
if (new_rx_ring == NULL) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Consistent memory allocation failed.\n",
|
||||
dev->name);
|
||||
return;
|
||||
}
|
||||
memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
|
||||
|
||||
new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
|
||||
GFP_ATOMIC);
|
||||
if (!new_dma_addr_list) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Memory allocation failed.\n", dev->name);
|
||||
goto free_new_rx_ring;
|
||||
}
|
||||
|
||||
new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
|
||||
GFP_ATOMIC);
|
||||
if (!new_skb_list) {
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR
|
||||
"%s: Memory allocation failed.\n", dev->name);
|
||||
goto free_new_lists;
|
||||
}
|
||||
|
||||
/* first copy the current receive buffers */
|
||||
overlap = min(size, lp->rx_ring_size);
|
||||
for (new = 0; new < overlap; new++) {
|
||||
new_rx_ring[new] = lp->rx_ring[new];
|
||||
new_dma_addr_list[new] = lp->rx_dma_addr[new];
|
||||
new_skb_list[new] = lp->rx_skbuff[new];
|
||||
}
|
||||
/* now allocate any new buffers needed */
|
||||
for (; new < size; new++ ) {
|
||||
struct sk_buff *rx_skbuff;
|
||||
new_skb_list[new] = dev_alloc_skb(PKT_BUF_SZ);
|
||||
if (!(rx_skbuff = new_skb_list[new])) {
|
||||
/* keep the original lists and buffers */
|
||||
if (netif_msg_drv(lp))
|
||||
printk(KERN_ERR
|
||||
"%s: pcnet32_realloc_rx_ring dev_alloc_skb failed.\n",
|
||||
dev->name);
|
||||
goto free_all_new;
|
||||
}
|
||||
skb_reserve(rx_skbuff, 2);
|
||||
|
||||
new_dma_addr_list[new] =
|
||||
pci_map_single(lp->pci_dev, rx_skbuff->data,
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
new_rx_ring[new].base = (u32) le32_to_cpu(new_dma_addr_list[new]);
|
||||
new_rx_ring[new].buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
|
||||
new_rx_ring[new].status = le16_to_cpu(0x8000);
|
||||
}
|
||||
/* and free any unneeded buffers */
|
||||
for (; new < lp->rx_ring_size; new++) {
|
||||
if (lp->rx_skbuff[new]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(lp->rx_skbuff[new]);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(lp->rx_skbuff);
|
||||
kfree(lp->rx_dma_addr);
|
||||
pci_free_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_rx_head) *
|
||||
lp->rx_ring_size, lp->rx_ring,
|
||||
lp->rx_ring_dma_addr);
|
||||
|
||||
lp->rx_ring_size = (1 << size);
|
||||
lp->rx_mod_mask = lp->rx_ring_size - 1;
|
||||
lp->rx_len_bits = (size << 4);
|
||||
lp->rx_ring = new_rx_ring;
|
||||
lp->rx_ring_dma_addr = new_ring_dma_addr;
|
||||
lp->rx_dma_addr = new_dma_addr_list;
|
||||
lp->rx_skbuff = new_skb_list;
|
||||
return;
|
||||
|
||||
free_all_new:
|
||||
for (; --new >= lp->rx_ring_size; ) {
|
||||
if (new_skb_list[new]) {
|
||||
pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(new_skb_list[new]);
|
||||
}
|
||||
}
|
||||
kfree(new_skb_list);
|
||||
free_new_lists:
|
||||
kfree(new_dma_addr_list);
|
||||
free_new_rx_ring:
|
||||
pci_free_consistent(lp->pci_dev,
|
||||
sizeof(struct pcnet32_rx_head) *
|
||||
(1 << size),
|
||||
new_rx_ring,
|
||||
new_ring_dma_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pcnet32_purge_rx_ring(struct net_device *dev)
|
||||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
int i;
|
||||
|
||||
/* free all allocated skbuffs */
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
lp->rx_ring[i].status = 0; /* CPU owns buffer */
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->rx_skbuff[i]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb_any(lp->rx_skbuff[i]);
|
||||
}
|
||||
lp->rx_skbuff[i] = NULL;
|
||||
lp->rx_dma_addr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void pcnet32_poll_controller(struct net_device *dev)
|
||||
{
|
||||
|
@ -519,10 +764,10 @@ static void pcnet32_get_ringparam(struct net_device *dev,
|
|||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
|
||||
ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
|
||||
ering->tx_pending = lp->tx_ring_size - 1;
|
||||
ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
|
||||
ering->rx_pending = lp->rx_ring_size - 1;
|
||||
ering->tx_max_pending = TX_MAX_RING_SIZE;
|
||||
ering->tx_pending = lp->tx_ring_size;
|
||||
ering->rx_max_pending = RX_MAX_RING_SIZE;
|
||||
ering->rx_pending = lp->rx_ring_size;
|
||||
}
|
||||
|
||||
static int pcnet32_set_ringparam(struct net_device *dev,
|
||||
|
@ -530,56 +775,53 @@ static int pcnet32_set_ringparam(struct net_device *dev,
|
|||
{
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
unsigned long flags;
|
||||
unsigned int size;
|
||||
ulong ioaddr = dev->base_addr;
|
||||
int i;
|
||||
|
||||
if (ering->rx_mini_pending || ering->rx_jumbo_pending)
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev))
|
||||
pcnet32_close(dev);
|
||||
pcnet32_netif_stop(dev);
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
pcnet32_free_ring(dev);
|
||||
lp->tx_ring_size =
|
||||
min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
|
||||
lp->rx_ring_size =
|
||||
min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
|
||||
|
||||
size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
|
||||
|
||||
/* set the minimum ring size to 4, to allow the loopback test to work
|
||||
* unchanged.
|
||||
*/
|
||||
for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
|
||||
if (lp->tx_ring_size <= (1 << i))
|
||||
if (size <= (1 << i))
|
||||
break;
|
||||
}
|
||||
lp->tx_ring_size = (1 << i);
|
||||
lp->tx_mod_mask = lp->tx_ring_size - 1;
|
||||
lp->tx_len_bits = (i << 12);
|
||||
|
||||
if ((1 << i) != lp->tx_ring_size)
|
||||
pcnet32_realloc_tx_ring(dev, lp, i);
|
||||
|
||||
size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
|
||||
for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
|
||||
if (lp->rx_ring_size <= (1 << i))
|
||||
if (size <= (1 << i))
|
||||
break;
|
||||
}
|
||||
lp->rx_ring_size = (1 << i);
|
||||
lp->rx_mod_mask = lp->rx_ring_size - 1;
|
||||
lp->rx_len_bits = (i << 4);
|
||||
if ((1 << i) != lp->rx_ring_size)
|
||||
pcnet32_realloc_rx_ring(dev, lp, i);
|
||||
|
||||
dev->weight = lp->rx_ring_size / 2;
|
||||
|
||||
if (pcnet32_alloc_ring(dev, dev->name)) {
|
||||
pcnet32_free_ring(dev);
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
return -ENOMEM;
|
||||
if (netif_running(dev)) {
|
||||
pcnet32_netif_start(dev);
|
||||
pcnet32_restart(dev, CSR0_NORMAL);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
printk(KERN_INFO PFX
|
||||
if (netif_msg_drv(lp))
|
||||
printk(KERN_INFO
|
||||
"%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name,
|
||||
lp->rx_ring_size, lp->tx_ring_size);
|
||||
|
||||
if (netif_running(dev))
|
||||
pcnet32_open(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -633,29 +875,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
|||
unsigned long flags;
|
||||
unsigned long ticks;
|
||||
|
||||
*data1 = 1; /* status of test, default to fail */
|
||||
rc = 1; /* default to fail */
|
||||
|
||||
if (netif_running(dev))
|
||||
pcnet32_close(dev);
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
|
||||
|
||||
numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
|
||||
|
||||
/* Reset the PCNET32 */
|
||||
lp->a.reset(ioaddr);
|
||||
lp->a.write_csr(ioaddr, CSR4, 0x0915);
|
||||
|
||||
/* switch pcnet32 to 32bit mode */
|
||||
lp->a.write_bcr(ioaddr, 20, 2);
|
||||
|
||||
lp->init_block.mode =
|
||||
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
|
||||
lp->init_block.filter[0] = 0;
|
||||
lp->init_block.filter[1] = 0;
|
||||
|
||||
/* purge & init rings but don't actually restart */
|
||||
pcnet32_restart(dev, 0x0000);
|
||||
|
||||
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
|
||||
|
||||
/* Initialize Transmit buffers. */
|
||||
size = data_len + 15;
|
||||
|
@ -697,14 +937,15 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
|||
}
|
||||
}
|
||||
|
||||
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
|
||||
x = x | 0x0002;
|
||||
a->write_bcr(ioaddr, 32, x);
|
||||
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */
|
||||
a->write_bcr(ioaddr, 32, x | 0x0002);
|
||||
|
||||
lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */
|
||||
/* set int loopback in CSR15 */
|
||||
x = a->read_csr(ioaddr, CSR15) & 0xfffc;
|
||||
lp->a.write_csr(ioaddr, CSR15, x | 0x0044);
|
||||
|
||||
teststatus = le16_to_cpu(0x8000);
|
||||
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
|
||||
|
||||
/* Check status of descriptors */
|
||||
for (x = 0; x < numbuffs; x++) {
|
||||
|
@ -712,7 +953,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
|||
rmb();
|
||||
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
mdelay(1);
|
||||
msleep(1);
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
rmb();
|
||||
ticks++;
|
||||
|
@ -725,7 +966,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
|||
}
|
||||
}
|
||||
|
||||
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
|
||||
wmb();
|
||||
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
|
||||
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
|
||||
|
@ -758,25 +999,24 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
|||
}
|
||||
x++;
|
||||
}
|
||||
if (!rc) {
|
||||
*data1 = 0;
|
||||
}
|
||||
|
||||
clean_up:
|
||||
*data1 = rc;
|
||||
pcnet32_purge_tx_ring(dev);
|
||||
x = a->read_csr(ioaddr, 15) & 0xFFFF;
|
||||
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
|
||||
|
||||
x = a->read_csr(ioaddr, CSR15);
|
||||
a->write_csr(ioaddr, CSR15, (x & ~0x0044)); /* reset bits 6 and 2 */
|
||||
|
||||
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
|
||||
x = x & ~0x0002;
|
||||
a->write_bcr(ioaddr, 32, x);
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
a->write_bcr(ioaddr, 32, (x & ~0x0002));
|
||||
|
||||
if (netif_running(dev)) {
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
pcnet32_open(dev);
|
||||
} else {
|
||||
pcnet32_purge_rx_ring(dev);
|
||||
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
}
|
||||
|
||||
return (rc);
|
||||
|
@ -839,6 +1079,43 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lp->lock must be held.
|
||||
*/
|
||||
static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
|
||||
int can_sleep)
|
||||
{
|
||||
int csr5;
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
struct pcnet32_access *a = &lp->a;
|
||||
ulong ioaddr = dev->base_addr;
|
||||
int ticks;
|
||||
|
||||
/* set SUSPEND (SPND) - CSR5 bit 0 */
|
||||
csr5 = a->read_csr(ioaddr, CSR5);
|
||||
a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
|
||||
|
||||
/* poll waiting for bit to be set */
|
||||
ticks = 0;
|
||||
while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) {
|
||||
spin_unlock_irqrestore(&lp->lock, *flags);
|
||||
if (can_sleep)
|
||||
msleep(1);
|
||||
else
|
||||
mdelay(1);
|
||||
spin_lock_irqsave(&lp->lock, *flags);
|
||||
ticks++;
|
||||
if (ticks > 200) {
|
||||
if (netif_msg_hw(lp))
|
||||
printk(KERN_DEBUG
|
||||
"%s: Error getting into suspend!\n",
|
||||
dev->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PCNET32_REGS_PER_PHY 32
|
||||
#define PCNET32_MAX_PHYS 32
|
||||
static int pcnet32_get_regs_len(struct net_device *dev)
|
||||
|
@ -857,32 +1134,13 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
|
|||
struct pcnet32_private *lp = dev->priv;
|
||||
struct pcnet32_access *a = &lp->a;
|
||||
ulong ioaddr = dev->base_addr;
|
||||
int ticks;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
|
||||
csr0 = a->read_csr(ioaddr, 0);
|
||||
if (!(csr0 & 0x0004)) { /* If not stopped */
|
||||
/* set SUSPEND (SPND) - CSR5 bit 0 */
|
||||
a->write_csr(ioaddr, 5, 0x0001);
|
||||
|
||||
/* poll waiting for bit to be set */
|
||||
ticks = 0;
|
||||
while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
mdelay(1);
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
ticks++;
|
||||
if (ticks > 200) {
|
||||
if (netif_msg_hw(lp))
|
||||
printk(KERN_DEBUG
|
||||
"%s: Error getting into suspend!\n",
|
||||
dev->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
csr0 = a->read_csr(ioaddr, CSR0);
|
||||
if (!(csr0 & CSR0_STOP)) /* If not stopped */
|
||||
pcnet32_suspend(dev, &flags, 1);
|
||||
|
||||
/* read address PROM */
|
||||
for (i = 0; i < 16; i += 2)
|
||||
|
@ -919,9 +1177,12 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
|
|||
}
|
||||
}
|
||||
|
||||
if (!(csr0 & 0x0004)) { /* If not stopped */
|
||||
if (!(csr0 & CSR0_STOP)) { /* If not stopped */
|
||||
int csr5;
|
||||
|
||||
/* clear SUSPEND (SPND) - CSR5 bit 0 */
|
||||
a->write_csr(ioaddr, 5, 0x0000);
|
||||
csr5 = a->read_csr(ioaddr, CSR5);
|
||||
a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
@ -952,7 +1213,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
|
|||
/* only probes for non-PCI devices, the rest are handled by
|
||||
* pci_register_driver via pcnet32_probe_pci */
|
||||
|
||||
static void __devinit pcnet32_probe_vlbus(void)
|
||||
static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
|
||||
{
|
||||
unsigned int *port, ioaddr;
|
||||
|
||||
|
@ -1436,7 +1697,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
|
|||
lp->tx_ring_size,
|
||||
&lp->tx_ring_dma_addr);
|
||||
if (lp->tx_ring == NULL) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Consistent memory allocation failed.\n",
|
||||
name);
|
||||
|
@ -1448,52 +1709,48 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
|
|||
lp->rx_ring_size,
|
||||
&lp->rx_ring_dma_addr);
|
||||
if (lp->rx_ring == NULL) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Consistent memory allocation failed.\n",
|
||||
name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size,
|
||||
lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t),
|
||||
GFP_ATOMIC);
|
||||
if (!lp->tx_dma_addr) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Memory allocation failed.\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
|
||||
|
||||
lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size,
|
||||
lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t),
|
||||
GFP_ATOMIC);
|
||||
if (!lp->rx_dma_addr) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Memory allocation failed.\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
|
||||
|
||||
lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size,
|
||||
lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *),
|
||||
GFP_ATOMIC);
|
||||
if (!lp->tx_skbuff) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Memory allocation failed.\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
|
||||
|
||||
lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size,
|
||||
lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *),
|
||||
GFP_ATOMIC);
|
||||
if (!lp->rx_skbuff) {
|
||||
if (pcnet32_debug & NETIF_MSG_DRV)
|
||||
if (netif_msg_drv(lp))
|
||||
printk("\n" KERN_ERR PFX
|
||||
"%s: Memory allocation failed.\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1757,16 +2014,7 @@ static int pcnet32_open(struct net_device *dev)
|
|||
|
||||
err_free_ring:
|
||||
/* free any allocated skbuffs */
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
lp->rx_ring[i].status = 0;
|
||||
if (lp->rx_skbuff[i]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(lp->rx_skbuff[i]);
|
||||
}
|
||||
lp->rx_skbuff[i] = NULL;
|
||||
lp->rx_dma_addr[i] = 0;
|
||||
}
|
||||
pcnet32_purge_rx_ring(dev);
|
||||
|
||||
/*
|
||||
* Switch back to 16bit mode to avoid problems with dumb
|
||||
|
@ -2348,7 +2596,6 @@ static int pcnet32_close(struct net_device *dev)
|
|||
{
|
||||
unsigned long ioaddr = dev->base_addr;
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
del_timer_sync(&lp->watchdog_timer);
|
||||
|
@ -2379,31 +2626,8 @@ static int pcnet32_close(struct net_device *dev)
|
|||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
|
||||
/* free all allocated skbuffs */
|
||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||
lp->rx_ring[i].status = 0;
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->rx_skbuff[i]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(lp->rx_skbuff[i]);
|
||||
}
|
||||
lp->rx_skbuff[i] = NULL;
|
||||
lp->rx_dma_addr[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < lp->tx_ring_size; i++) {
|
||||
lp->tx_ring[i].status = 0; /* CPU owns buffer */
|
||||
wmb(); /* Make sure adapter sees owner change */
|
||||
if (lp->tx_skbuff[i]) {
|
||||
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
|
||||
lp->tx_skbuff[i]->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb(lp->tx_skbuff[i]);
|
||||
}
|
||||
lp->tx_skbuff[i] = NULL;
|
||||
lp->tx_dma_addr[i] = 0;
|
||||
}
|
||||
pcnet32_purge_rx_ring(dev);
|
||||
pcnet32_purge_tx_ring(dev);
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
|
@ -2433,6 +2657,7 @@ static void pcnet32_load_multicast(struct net_device *dev)
|
|||
volatile struct pcnet32_init_block *ib = &lp->init_block;
|
||||
volatile u16 *mcast_table = (u16 *) & ib->filter;
|
||||
struct dev_mc_list *dmi = dev->mc_list;
|
||||
unsigned long ioaddr = dev->base_addr;
|
||||
char *addrs;
|
||||
int i;
|
||||
u32 crc;
|
||||
|
@ -2441,6 +2666,10 @@ static void pcnet32_load_multicast(struct net_device *dev)
|
|||
if (dev->flags & IFF_ALLMULTI) {
|
||||
ib->filter[0] = 0xffffffff;
|
||||
ib->filter[1] = 0xffffffff;
|
||||
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff);
|
||||
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff);
|
||||
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff);
|
||||
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff);
|
||||
return;
|
||||
}
|
||||
/* clear the multicast filter */
|
||||
|
@ -2462,6 +2691,9 @@ static void pcnet32_load_multicast(struct net_device *dev)
|
|||
le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) |
|
||||
(1 << (crc & 0xf)));
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER + i,
|
||||
le16_to_cpu(mcast_table[i]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2472,8 +2704,11 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
|
|||
{
|
||||
unsigned long ioaddr = dev->base_addr, flags;
|
||||
struct pcnet32_private *lp = dev->priv;
|
||||
int csr15, suspended;
|
||||
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
suspended = pcnet32_suspend(dev, &flags, 0);
|
||||
csr15 = lp->a.read_csr(ioaddr, CSR15);
|
||||
if (dev->flags & IFF_PROMISC) {
|
||||
/* Log any net taps. */
|
||||
if (netif_msg_hw(lp))
|
||||
|
@ -2482,15 +2717,24 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
|
|||
lp->init_block.mode =
|
||||
le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
|
||||
7);
|
||||
lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000);
|
||||
} else {
|
||||
lp->init_block.mode =
|
||||
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
|
||||
lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff);
|
||||
pcnet32_load_multicast(dev);
|
||||
}
|
||||
|
||||
lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */
|
||||
pcnet32_restart(dev, 0x0042); /* Resume normal operation */
|
||||
netif_wake_queue(dev);
|
||||
if (suspended) {
|
||||
int csr5;
|
||||
/* clear SUSPEND (SPND) - CSR5 bit 0 */
|
||||
csr5 = lp->a.read_csr(ioaddr, CSR5);
|
||||
lp->a.write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
|
||||
} else {
|
||||
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
|
||||
pcnet32_restart(dev, CSR0_NORMAL);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
}
|
||||
|
@ -2730,7 +2974,7 @@ static int __init pcnet32_init_module(void)
|
|||
|
||||
/* should we find any remaining VLbus devices ? */
|
||||
if (pcnet32vlb)
|
||||
pcnet32_probe_vlbus();
|
||||
pcnet32_probe_vlbus(pcnet32_portlist);
|
||||
|
||||
if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
|
||||
printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
|
||||
|
|
|
@ -103,7 +103,22 @@ static int cis820x_config_intr(struct phy_device *phydev)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Cicada 820x */
|
||||
/* Cicada 8201, a.k.a Vitesse VSC8201 */
|
||||
static struct phy_driver cis8201_driver = {
|
||||
.phy_id = 0x000fc410,
|
||||
.name = "Cicada Cis8201",
|
||||
.phy_id_mask = 0x000ffff0,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.flags = PHY_HAS_INTERRUPT,
|
||||
.config_init = &cis820x_config_init,
|
||||
.config_aneg = &genphy_config_aneg,
|
||||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &cis820x_ack_interrupt,
|
||||
.config_intr = &cis820x_config_intr,
|
||||
.driver = { .owner = THIS_MODULE,},
|
||||
};
|
||||
|
||||
/* Cicada 8204 */
|
||||
static struct phy_driver cis8204_driver = {
|
||||
.phy_id = 0x000fc440,
|
||||
.name = "Cicada Cis8204",
|
||||
|
@ -118,15 +133,30 @@ static struct phy_driver cis8204_driver = {
|
|||
.driver = { .owner = THIS_MODULE,},
|
||||
};
|
||||
|
||||
static int __init cis8204_init(void)
|
||||
static int __init cicada_init(void)
|
||||
{
|
||||
return phy_driver_register(&cis8204_driver);
|
||||
int ret;
|
||||
|
||||
ret = phy_driver_register(&cis8204_driver);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
ret = phy_driver_register(&cis8201_driver);
|
||||
if (ret)
|
||||
goto err2;
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
phy_driver_unregister(&cis8204_driver);
|
||||
err1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit cis8204_exit(void)
|
||||
static void __exit cicada_exit(void)
|
||||
{
|
||||
phy_driver_unregister(&cis8204_driver);
|
||||
phy_driver_unregister(&cis8201_driver);
|
||||
}
|
||||
|
||||
module_init(cis8204_init);
|
||||
module_exit(cis8204_exit);
|
||||
module_init(cicada_init);
|
||||
module_exit(cicada_exit);
|
||||
|
|
|
@ -1406,7 +1406,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
dev = alloc_etherdev(sizeof (*tp));
|
||||
if (dev == NULL) {
|
||||
if (netif_msg_drv(&debug))
|
||||
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
|
||||
dev_err(&pdev->dev, "unable to alloc new ethernet\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
@ -1418,10 +1418,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
/* enable device (incl. PCI PM wakeup and hotplug setup) */
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc < 0) {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX "%s: enable failure\n",
|
||||
pci_name(pdev));
|
||||
}
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev, "enable failure\n");
|
||||
goto err_out_free_dev;
|
||||
}
|
||||
|
||||
|
@ -1437,37 +1435,32 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
|
||||
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
|
||||
} else {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev,
|
||||
"PowerManagement capability not found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure PCI base addr 1 is MMIO */
|
||||
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev,
|
||||
"region #1 not an MMIO resource, aborting\n");
|
||||
}
|
||||
rc = -ENODEV;
|
||||
goto err_out_mwi;
|
||||
}
|
||||
/* check for weird/broken PCI region reporting */
|
||||
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev,
|
||||
"Invalid PCI region size(s), aborting\n");
|
||||
}
|
||||
rc = -ENODEV;
|
||||
goto err_out_mwi;
|
||||
}
|
||||
|
||||
rc = pci_request_regions(pdev, MODULENAME);
|
||||
if (rc < 0) {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX "%s: could not request regions.\n",
|
||||
pci_name(pdev));
|
||||
}
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev, "could not request regions.\n");
|
||||
goto err_out_mwi;
|
||||
}
|
||||
|
||||
|
@ -1480,10 +1473,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
} else {
|
||||
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (rc < 0) {
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_ERR PFX
|
||||
if (netif_msg_probe(tp))
|
||||
dev_err(&pdev->dev,
|
||||
"DMA configuration failed.\n");
|
||||
}
|
||||
goto err_out_free_res;
|
||||
}
|
||||
}
|
||||
|
@ -1494,7 +1486,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
|
||||
if (ioaddr == NULL) {
|
||||
if (netif_msg_probe(tp))
|
||||
printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
|
||||
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
|
||||
rc = -EIO;
|
||||
goto err_out_free_res;
|
||||
}
|
||||
|
@ -1526,9 +1518,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
if (i < 0) {
|
||||
/* Unknown chip: assume array element #0, original RTL-8169 */
|
||||
if (netif_msg_probe(tp)) {
|
||||
printk(KERN_DEBUG PFX "PCI device %s: "
|
||||
dev_printk(KERN_DEBUG, &pdev->dev,
|
||||
"unknown chip version, assuming %s\n",
|
||||
pci_name(pdev), rtl_chip_info[0].name);
|
||||
rtl_chip_info[0].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -22,129 +22,13 @@
|
|||
|
||||
Support and updates available at
|
||||
http://www.scyld.com/network/starfire.html
|
||||
[link no longer provides useful info -jgarzik]
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
Linux kernel-specific changes:
|
||||
|
||||
LK1.1.1 (jgarzik):
|
||||
- Use PCI driver interface
|
||||
- Fix MOD_xxx races
|
||||
- softnet fixups
|
||||
|
||||
LK1.1.2 (jgarzik):
|
||||
- Merge Becker version 0.15
|
||||
|
||||
LK1.1.3 (Andrew Morton)
|
||||
- Timer cleanups
|
||||
|
||||
LK1.1.4 (jgarzik):
|
||||
- Merge Becker version 1.03
|
||||
|
||||
LK1.2.1 (Ion Badulescu <ionut@cs.columbia.edu>)
|
||||
- Support hardware Rx/Tx checksumming
|
||||
- Use the GFP firmware taken from Adaptec's Netware driver
|
||||
|
||||
LK1.2.2 (Ion Badulescu)
|
||||
- Backported to 2.2.x
|
||||
|
||||
LK1.2.3 (Ion Badulescu)
|
||||
- Fix the flaky mdio interface
|
||||
- More compat clean-ups
|
||||
|
||||
LK1.2.4 (Ion Badulescu)
|
||||
- More 2.2.x initialization fixes
|
||||
|
||||
LK1.2.5 (Ion Badulescu)
|
||||
- Several fixes from Manfred Spraul
|
||||
|
||||
LK1.2.6 (Ion Badulescu)
|
||||
- Fixed ifup/ifdown/ifup problem in 2.4.x
|
||||
|
||||
LK1.2.7 (Ion Badulescu)
|
||||
- Removed unused code
|
||||
- Made more functions static and __init
|
||||
|
||||
LK1.2.8 (Ion Badulescu)
|
||||
- Quell bogus error messages, inform about the Tx threshold
|
||||
- Removed #ifdef CONFIG_PCI, this driver is PCI only
|
||||
|
||||
LK1.2.9 (Ion Badulescu)
|
||||
- Merged Jeff Garzik's changes from 2.4.4-pre5
|
||||
- Added 2.2.x compatibility stuff required by the above changes
|
||||
|
||||
LK1.2.9a (Ion Badulescu)
|
||||
- More updates from Jeff Garzik
|
||||
|
||||
LK1.3.0 (Ion Badulescu)
|
||||
- Merged zerocopy support
|
||||
|
||||
LK1.3.1 (Ion Badulescu)
|
||||
- Added ethtool support
|
||||
- Added GPIO (media change) interrupt support
|
||||
|
||||
LK1.3.2 (Ion Badulescu)
|
||||
- Fixed 2.2.x compatibility issues introduced in 1.3.1
|
||||
- Fixed ethtool ioctl returning uninitialized memory
|
||||
|
||||
LK1.3.3 (Ion Badulescu)
|
||||
- Initialize the TxMode register properly
|
||||
- Don't dereference dev->priv after freeing it
|
||||
|
||||
LK1.3.4 (Ion Badulescu)
|
||||
- Fixed initialization timing problems
|
||||
- Fixed interrupt mask definitions
|
||||
|
||||
LK1.3.5 (jgarzik)
|
||||
- ethtool NWAY_RST, GLINK, [GS]MSGLVL support
|
||||
|
||||
LK1.3.6:
|
||||
- Sparc64 support and fixes (Ion Badulescu)
|
||||
- Better stats and error handling (Ion Badulescu)
|
||||
- Use new pci_set_mwi() PCI API function (jgarzik)
|
||||
|
||||
LK1.3.7 (Ion Badulescu)
|
||||
- minimal implementation of tx_timeout()
|
||||
- correctly shutdown the Rx/Tx engines in netdev_close()
|
||||
- added calls to netif_carrier_on/off
|
||||
(patch from Stefan Rompf <srompf@isg.de>)
|
||||
- VLAN support
|
||||
|
||||
LK1.3.8 (Ion Badulescu)
|
||||
- adjust DMA burst size on sparc64
|
||||
- 64-bit support
|
||||
- reworked zerocopy support for 64-bit buffers
|
||||
- working and usable interrupt mitigation/latency
|
||||
- reduced Tx interrupt frequency for lower interrupt overhead
|
||||
|
||||
LK1.3.9 (Ion Badulescu)
|
||||
- bugfix for mcast filter
|
||||
- enable the right kind of Tx interrupts (TxDMADone, not TxDone)
|
||||
|
||||
LK1.4.0 (Ion Badulescu)
|
||||
- NAPI support
|
||||
|
||||
LK1.4.1 (Ion Badulescu)
|
||||
- flush PCI posting buffers after disabling Rx interrupts
|
||||
- put the chip to a D3 slumber on driver unload
|
||||
- added config option to enable/disable NAPI
|
||||
|
||||
LK1.4.2 (Ion Badulescu)
|
||||
- finally added firmware (GPL'ed by Adaptec)
|
||||
- removed compatibility code for 2.2.x
|
||||
|
||||
LK1.4.2.1 (Ion Badulescu)
|
||||
- fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM
|
||||
- added 32-bit padding to outgoing skb's, removed previous workaround
|
||||
|
||||
TODO: - fix forced speed/duplexing code (broken a long time ago, when
|
||||
somebody converted the driver to use the generic MII code)
|
||||
- fix VLAN support
|
||||
*/
|
||||
|
||||
#define DRV_NAME "starfire"
|
||||
#define DRV_VERSION "1.03+LK1.4.2.1"
|
||||
#define DRV_RELDATE "October 3, 2005"
|
||||
#define DRV_VERSION "2.0"
|
||||
#define DRV_RELDATE "June 27, 2006"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -846,7 +730,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
|
|||
goto err_out_free_netdev;
|
||||
}
|
||||
|
||||
/* ioremap is borken in Linux-2.2.x/sparc64 */
|
||||
base = ioremap(ioaddr, io_size);
|
||||
if (!base) {
|
||||
printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",
|
||||
|
|
|
@ -16,91 +16,13 @@
|
|||
|
||||
Support and updates available at
|
||||
http://www.scyld.com/network/sundance.html
|
||||
[link no longer provides useful info -jgarzik]
|
||||
|
||||
|
||||
Version LK1.01a (jgarzik):
|
||||
- Replace some MII-related magic numbers with constants
|
||||
|
||||
Version LK1.02 (D-Link):
|
||||
- Add new board to PCI ID list
|
||||
- Fix multicast bug
|
||||
|
||||
Version LK1.03 (D-Link):
|
||||
- New Rx scheme, reduce Rx congestion
|
||||
- Option to disable flow control
|
||||
|
||||
Version LK1.04 (D-Link):
|
||||
- Tx timeout recovery
|
||||
- More support for ethtool.
|
||||
|
||||
Version LK1.04a:
|
||||
- Remove unused/constant members from struct pci_id_info
|
||||
(which then allows removal of 'drv_flags' from private struct)
|
||||
(jgarzik)
|
||||
- If no phy is found, fail to load that board (jgarzik)
|
||||
- Always start phy id scan at id 1 to avoid problems (Donald Becker)
|
||||
- Autodetect where mii_preable_required is needed,
|
||||
default to not needed. (Donald Becker)
|
||||
|
||||
Version LK1.04b:
|
||||
- Remove mii_preamble_required module parameter (Donald Becker)
|
||||
- Add per-interface mii_preamble_required (setting is autodetected)
|
||||
(Donald Becker)
|
||||
- Remove unnecessary cast from void pointer (jgarzik)
|
||||
- Re-align comments in private struct (jgarzik)
|
||||
|
||||
Version LK1.04c (jgarzik):
|
||||
- Support bitmapped message levels (NETIF_MSG_xxx), and the
|
||||
two ethtool ioctls that get/set them
|
||||
- Don't hand-code MII ethtool support, use standard API/lib
|
||||
|
||||
Version LK1.04d:
|
||||
- Merge from Donald Becker's sundance.c: (Jason Lunz)
|
||||
* proper support for variably-sized MTUs
|
||||
* default to PIO, to fix chip bugs
|
||||
- Add missing unregister_netdev (Jason Lunz)
|
||||
- Add CONFIG_SUNDANCE_MMIO config option (jgarzik)
|
||||
- Better rx buf size calculation (Donald Becker)
|
||||
|
||||
Version LK1.05 (D-Link):
|
||||
- Fix DFE-580TX packet drop issue (for DL10050C)
|
||||
- Fix reset_tx logic
|
||||
|
||||
Version LK1.06 (D-Link):
|
||||
- Fix crash while unloading driver
|
||||
|
||||
Versin LK1.06b (D-Link):
|
||||
- New tx scheme, adaptive tx_coalesce
|
||||
|
||||
Version LK1.07 (D-Link):
|
||||
- Fix tx bugs in big-endian machines
|
||||
- Remove unused max_interrupt_work module parameter, the new
|
||||
NAPI-like rx scheme doesn't need it.
|
||||
- Remove redundancy get_stats() in intr_handler(), those
|
||||
I/O access could affect performance in ARM-based system
|
||||
- Add Linux software VLAN support
|
||||
|
||||
Version LK1.08 (Philippe De Muyter phdm@macqel.be):
|
||||
- Fix bug of custom mac address
|
||||
(StationAddr register only accept word write)
|
||||
|
||||
Version LK1.09 (D-Link):
|
||||
- Fix the flowctrl bug.
|
||||
- Set Pause bit in MII ANAR if flow control enabled.
|
||||
|
||||
Version LK1.09a (ICPlus):
|
||||
- Add the delay time in reading the contents of EEPROM
|
||||
|
||||
Version LK1.10 (Philippe De Muyter phdm@macqel.be):
|
||||
- Make 'unblock interface after Tx underrun' work
|
||||
|
||||
Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com):
|
||||
- Add support for IC Plus Corporation IP100A chipset
|
||||
*/
|
||||
|
||||
#define DRV_NAME "sundance"
|
||||
#define DRV_VERSION "1.01+LK1.11"
|
||||
#define DRV_RELDATE "14-Jun-2006"
|
||||
#define DRV_VERSION "1.1"
|
||||
#define DRV_RELDATE "27-Jun-2006"
|
||||
|
||||
|
||||
/* The user-configurable values.
|
||||
|
@ -282,15 +204,15 @@ IVc. Errata
|
|||
#define USE_IO_OPS 1
|
||||
#endif
|
||||
|
||||
static struct pci_device_id sundance_pci_tbl[] = {
|
||||
{0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0},
|
||||
{0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1},
|
||||
{0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2},
|
||||
{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
|
||||
{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
|
||||
{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
|
||||
{0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
|
||||
{0,}
|
||||
static const struct pci_device_id sundance_pci_tbl[] = {
|
||||
{ 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
|
||||
{ 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
|
||||
{ 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
|
||||
{ 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 },
|
||||
{ 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
|
||||
{ 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
|
||||
{ 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
|
||||
|
||||
|
@ -301,7 +223,7 @@ enum {
|
|||
struct pci_id_info {
|
||||
const char *name;
|
||||
};
|
||||
static const struct pci_id_info pci_id_tbl[] = {
|
||||
static const struct pci_id_info pci_id_tbl[] __devinitdata = {
|
||||
{"D-Link DFE-550TX FAST Ethernet Adapter"},
|
||||
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
|
||||
{"D-Link DFE-580TX 4 port Server Adapter"},
|
||||
|
@ -309,7 +231,7 @@ static const struct pci_id_info pci_id_tbl[] = {
|
|||
{"D-Link DL10050-based FAST Ethernet Adapter"},
|
||||
{"Sundance Technology Alta"},
|
||||
{"IC Plus Corporation IP100A FAST Ethernet Adapter"},
|
||||
{NULL,}, /* 0 terminated list. */
|
||||
{ } /* terminate list. */
|
||||
};
|
||||
|
||||
/* This driver was written to use PCI memory space, however x86-oriented
|
||||
|
|
|
@ -224,24 +224,21 @@ static const struct pci_device_id w840_pci_tbl[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(pci, w840_pci_tbl);
|
||||
|
||||
enum {
|
||||
netdev_res_size = 128, /* size of PCI BAR resource */
|
||||
};
|
||||
|
||||
struct pci_id_info {
|
||||
const char *name;
|
||||
struct match_info {
|
||||
int pci, pci_mask, subsystem, subsystem_mask;
|
||||
int revision, revision_mask; /* Only 8 bits. */
|
||||
} id;
|
||||
int io_size; /* Needed for I/O region check or ioremap(). */
|
||||
int drv_flags; /* Driver use, intended as capability flags. */
|
||||
int drv_flags; /* Driver use, intended as capability flags. */
|
||||
};
|
||||
static struct pci_id_info pci_id_tbl[] = {
|
||||
{"Winbond W89c840", /* Sometime a Level-One switch card. */
|
||||
{ 0x08401050, 0xffffffff, 0x81530000, 0xffff0000 },
|
||||
128, CanHaveMII | HasBrokenTx | FDXOnNoMII},
|
||||
{"Winbond W89c840", { 0x08401050, 0xffffffff, },
|
||||
128, CanHaveMII | HasBrokenTx},
|
||||
{"Compex RL100-ATX", { 0x201111F6, 0xffffffff,},
|
||||
128, CanHaveMII | HasBrokenTx},
|
||||
{NULL,}, /* 0 terminated list. */
|
||||
|
||||
static const struct pci_id_info pci_id_tbl[] __devinitdata = {
|
||||
{ /* Sometime a Level-One switch card. */
|
||||
"Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII},
|
||||
{ "Winbond W89c840", CanHaveMII | HasBrokenTx},
|
||||
{ "Compex RL100-ATX", CanHaveMII | HasBrokenTx},
|
||||
{ } /* terminate list. */
|
||||
};
|
||||
|
||||
/* This driver was written to use PCI memory space, however some x86 systems
|
||||
|
@ -399,7 +396,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
|
|||
#ifdef USE_IO_OPS
|
||||
bar = 0;
|
||||
#endif
|
||||
ioaddr = pci_iomap(pdev, bar, pci_id_tbl[chip_idx].io_size);
|
||||
ioaddr = pci_iomap(pdev, bar, netdev_res_size);
|
||||
if (!ioaddr)
|
||||
goto err_out_free_res;
|
||||
|
||||
|
|
|
@ -10,26 +10,11 @@
|
|||
410 Severn Ave., Suite 210
|
||||
Annapolis MD 21403
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
Linux kernel-specific changes:
|
||||
|
||||
LK1.0 (Ion Badulescu)
|
||||
- Major cleanup
|
||||
- Use 2.4 PCI API
|
||||
- Support ethtool
|
||||
- Rewrite perfect filter/hash code
|
||||
- Use interrupts for media changes
|
||||
|
||||
LK1.1 (Ion Badulescu)
|
||||
- Disallow negotiation of unsupported full-duplex modes
|
||||
*/
|
||||
|
||||
#define DRV_NAME "xircom_tulip_cb"
|
||||
#define DRV_VERSION "0.91+LK1.1"
|
||||
#define DRV_RELDATE "October 11, 2001"
|
||||
|
||||
#define CARDBUS 1
|
||||
#define DRV_VERSION "0.92"
|
||||
#define DRV_RELDATE "June 27, 2006"
|
||||
|
||||
/* A few user-configurable values. */
|
||||
|
||||
|
@ -306,10 +291,10 @@ struct xircom_private {
|
|||
struct xircom_tx_desc tx_ring[TX_RING_SIZE];
|
||||
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
|
||||
struct sk_buff* tx_skbuff[TX_RING_SIZE];
|
||||
#ifdef CARDBUS
|
||||
|
||||
/* The X3201-3 requires 4-byte aligned tx bufs */
|
||||
struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
|
||||
#endif
|
||||
|
||||
/* The addresses of receive-in-place skbuffs. */
|
||||
struct sk_buff* rx_skbuff[RX_RING_SIZE];
|
||||
u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)]; /* Pseudo-Tx frame to init address table. */
|
||||
|
@ -908,10 +893,8 @@ static void xircom_init_ring(struct net_device *dev)
|
|||
tp->tx_skbuff[i] = NULL;
|
||||
tp->tx_ring[i].status = 0;
|
||||
tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
|
||||
#ifdef CARDBUS
|
||||
if (tp->chip_id == X3201_3)
|
||||
tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
|
||||
#endif /* CARDBUS */
|
||||
}
|
||||
tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
|
||||
}
|
||||
|
@ -931,12 +914,10 @@ xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
entry = tp->cur_tx % TX_RING_SIZE;
|
||||
|
||||
tp->tx_skbuff[entry] = skb;
|
||||
#ifdef CARDBUS
|
||||
if (tp->chip_id == X3201_3) {
|
||||
memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len);
|
||||
tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
|
||||
} else
|
||||
#endif
|
||||
tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
|
||||
|
||||
if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
|
||||
|
|
|
@ -25,117 +25,13 @@
|
|||
version. He may or may not be interested in bug reports on this
|
||||
code. You can find his versions at:
|
||||
http://www.scyld.com/network/via-rhine.html
|
||||
|
||||
|
||||
Linux kernel version history:
|
||||
|
||||
LK1.1.0:
|
||||
- Jeff Garzik: softnet 'n stuff
|
||||
|
||||
LK1.1.1:
|
||||
- Justin Guyett: softnet and locking fixes
|
||||
- Jeff Garzik: use PCI interface
|
||||
|
||||
LK1.1.2:
|
||||
- Urban Widmark: minor cleanups, merges from Becker 1.03a/1.04 versions
|
||||
|
||||
LK1.1.3:
|
||||
- Urban Widmark: use PCI DMA interface (with thanks to the eepro100.c
|
||||
code) update "Theory of Operation" with
|
||||
softnet/locking changes
|
||||
- Dave Miller: PCI DMA and endian fixups
|
||||
- Jeff Garzik: MOD_xxx race fixes, updated PCI resource allocation
|
||||
|
||||
LK1.1.4:
|
||||
- Urban Widmark: fix gcc 2.95.2 problem and
|
||||
remove writel's to fixed address 0x7c
|
||||
|
||||
LK1.1.5:
|
||||
- Urban Widmark: mdio locking, bounce buffer changes
|
||||
merges from Beckers 1.05 version
|
||||
added netif_running_on/off support
|
||||
|
||||
LK1.1.6:
|
||||
- Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio)
|
||||
set netif_running_on/off on startup, del_timer_sync
|
||||
|
||||
LK1.1.7:
|
||||
- Manfred Spraul: added reset into tx_timeout
|
||||
|
||||
LK1.1.9:
|
||||
- Urban Widmark: merges from Beckers 1.10 version
|
||||
(media selection + eeprom reload)
|
||||
- David Vrabel: merges from D-Link "1.11" version
|
||||
(disable WOL and PME on startup)
|
||||
|
||||
LK1.1.10:
|
||||
- Manfred Spraul: use "singlecopy" for unaligned buffers
|
||||
don't allocate bounce buffers for !ReqTxAlign cards
|
||||
|
||||
LK1.1.11:
|
||||
- David Woodhouse: Set dev->base_addr before the first time we call
|
||||
wait_for_reset(). It's a lot happier that way.
|
||||
Free np->tx_bufs only if we actually allocated it.
|
||||
|
||||
LK1.1.12:
|
||||
- Martin Eriksson: Allow Memory-Mapped IO to be enabled.
|
||||
|
||||
LK1.1.13 (jgarzik):
|
||||
- Add ethtool support
|
||||
- Replace some MII-related magic numbers with constants
|
||||
|
||||
LK1.1.14 (Ivan G.):
|
||||
- fixes comments for Rhine-III
|
||||
- removes W_MAX_TIMEOUT (unused)
|
||||
- adds HasDavicomPhy for Rhine-I (basis: linuxfet driver; my card
|
||||
is R-I and has Davicom chip, flag is referenced in kernel driver)
|
||||
- sends chip_id as a parameter to wait_for_reset since np is not
|
||||
initialized on first call
|
||||
- changes mmio "else if (chip_id==VT6102)" to "else" so it will work
|
||||
for Rhine-III's (documentation says same bit is correct)
|
||||
- transmit frame queue message is off by one - fixed
|
||||
- adds IntrNormalSummary to "Something Wicked" exclusion list
|
||||
so normal interrupts will not trigger the message (src: Donald Becker)
|
||||
(Roger Luethi)
|
||||
- show confused chip where to continue after Tx error
|
||||
- location of collision counter is chip specific
|
||||
- allow selecting backoff algorithm (module parameter)
|
||||
|
||||
LK1.1.15 (jgarzik):
|
||||
- Use new MII lib helper generic_mii_ioctl
|
||||
|
||||
LK1.1.16 (Roger Luethi)
|
||||
- Etherleak fix
|
||||
- Handle Tx buffer underrun
|
||||
- Fix bugs in full duplex handling
|
||||
- New reset code uses "force reset" cmd on Rhine-II
|
||||
- Various clean ups
|
||||
|
||||
LK1.1.17 (Roger Luethi)
|
||||
- Fix race in via_rhine_start_tx()
|
||||
- On errors, wait for Tx engine to turn off before scavenging
|
||||
- Handle Tx descriptor write-back race on Rhine-II
|
||||
- Force flushing for PCI posted writes
|
||||
- More reset code changes
|
||||
|
||||
LK1.1.18 (Roger Luethi)
|
||||
- No filtering multicast in promisc mode (Edward Peng)
|
||||
- Fix for Rhine-I Tx timeouts
|
||||
|
||||
LK1.1.19 (Roger Luethi)
|
||||
- Increase Tx threshold for unspecified errors
|
||||
|
||||
LK1.2.0-2.6 (Roger Luethi)
|
||||
- Massive clean-up
|
||||
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
|
||||
- Fix Tx engine race for good
|
||||
- Craig Brind: Zero padded aligned buffers for short packets.
|
||||
[link no longer provides useful info -jgarzik]
|
||||
|
||||
*/
|
||||
|
||||
#define DRV_NAME "via-rhine"
|
||||
#define DRV_VERSION "1.2.0-2.6"
|
||||
#define DRV_RELDATE "June-10-2004"
|
||||
#define DRV_VERSION "1.4.0"
|
||||
#define DRV_RELDATE "June-27-2006"
|
||||
|
||||
|
||||
/* A few user-configurable values.
|
||||
|
@ -356,12 +252,11 @@ enum rhine_quirks {
|
|||
/* Beware of PCI posted writes */
|
||||
#define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
|
||||
|
||||
static struct pci_device_id rhine_pci_tbl[] =
|
||||
{
|
||||
{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */
|
||||
{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */
|
||||
{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */
|
||||
{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */
|
||||
static const struct pci_device_id rhine_pci_tbl[] = {
|
||||
{ 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */
|
||||
{ 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */
|
||||
{ 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */
|
||||
{ 0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6105M */
|
||||
{ } /* terminate list */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
|
||||
|
|
|
@ -229,7 +229,8 @@ static int rx_copybreak = 200;
|
|||
module_param(rx_copybreak, int, 0644);
|
||||
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
|
||||
|
||||
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
|
||||
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
|
||||
const struct velocity_info_tbl *info);
|
||||
static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
|
||||
static void velocity_print_info(struct velocity_info *vptr);
|
||||
static int velocity_open(struct net_device *dev);
|
||||
|
@ -294,9 +295,9 @@ static void velocity_unregister_notifier(void)
|
|||
* Internal board variants. At the moment we have only one
|
||||
*/
|
||||
|
||||
static struct velocity_info_tbl chip_info_table[] = {
|
||||
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, 0x00FFFFFFUL},
|
||||
{0, NULL}
|
||||
static const struct velocity_info_tbl chip_info_table[] __devinitdata = {
|
||||
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -304,10 +305,9 @@ static struct velocity_info_tbl chip_info_table[] = {
|
|||
* device driver. Used for hotplug autoloading.
|
||||
*/
|
||||
|
||||
static struct pci_device_id velocity_id_table[] __devinitdata = {
|
||||
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table},
|
||||
{0, }
|
||||
static const struct pci_device_id velocity_id_table[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, velocity_id_table);
|
||||
|
@ -341,7 +341,7 @@ static char __devinit *get_chip_name(enum chip_type chip_id)
|
|||
static void __devexit velocity_remove1(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned long flags;
|
||||
|
@ -686,21 +686,23 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
|
|||
static int first = 1;
|
||||
struct net_device *dev;
|
||||
int i;
|
||||
struct velocity_info_tbl *info = (struct velocity_info_tbl *) ent->driver_data;
|
||||
const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
|
||||
struct velocity_info *vptr;
|
||||
struct mac_regs __iomem * regs;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/* FIXME: this driver, like almost all other ethernet drivers,
|
||||
* can support more than MAX_UNITS.
|
||||
*/
|
||||
if (velocity_nics >= MAX_UNITS) {
|
||||
printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n",
|
||||
velocity_nics);
|
||||
dev_notice(&pdev->dev, "already found %d NICs.\n",
|
||||
velocity_nics);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct velocity_info));
|
||||
|
||||
if (dev == NULL) {
|
||||
printk(KERN_ERR VELOCITY_NAME ": allocate net device failed.\n");
|
||||
if (!dev) {
|
||||
dev_err(&pdev->dev, "allocate net device failed.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -708,7 +710,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
|
|||
|
||||
SET_MODULE_OWNER(dev);
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
vptr = dev->priv;
|
||||
vptr = netdev_priv(dev);
|
||||
|
||||
|
||||
if (first) {
|
||||
|
@ -731,17 +733,17 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
|
|||
|
||||
ret = velocity_get_pci_info(vptr, pdev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
|
||||
/* error message already printed */
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
ret = pci_request_regions(pdev, VELOCITY_NAME);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
|
||||
dev_err(&pdev->dev, "No PCI resources.\n");
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
regs = ioremap(vptr->memaddr, vptr->io_size);
|
||||
regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
|
||||
if (regs == NULL) {
|
||||
ret = -EIO;
|
||||
goto err_release_res;
|
||||
|
@ -859,13 +861,14 @@ static void __devinit velocity_print_info(struct velocity_info *vptr)
|
|||
* discovered.
|
||||
*/
|
||||
|
||||
static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info)
|
||||
static void __devinit velocity_init_info(struct pci_dev *pdev,
|
||||
struct velocity_info *vptr,
|
||||
const struct velocity_info_tbl *info)
|
||||
{
|
||||
memset(vptr, 0, sizeof(struct velocity_info));
|
||||
|
||||
vptr->pdev = pdev;
|
||||
vptr->chip_id = info->chip_id;
|
||||
vptr->io_size = info->io_size;
|
||||
vptr->num_txq = info->txqueue;
|
||||
vptr->multicast_limit = MCAM_SIZE;
|
||||
spin_lock_init(&vptr->lock);
|
||||
|
@ -883,8 +886,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_i
|
|||
|
||||
static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
|
||||
{
|
||||
|
||||
if(pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
|
||||
if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
|
||||
return -EIO;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
@ -892,24 +894,20 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
|
|||
vptr->ioaddr = pci_resource_start(pdev, 0);
|
||||
vptr->memaddr = pci_resource_start(pdev, 1);
|
||||
|
||||
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO))
|
||||
{
|
||||
printk(KERN_ERR "%s: region #0 is not an I/O resource, aborting.\n",
|
||||
pci_name(pdev));
|
||||
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
|
||||
dev_err(&pdev->dev,
|
||||
"region #0 is not an I/O resource, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if((pci_resource_flags(pdev, 1) & IORESOURCE_IO))
|
||||
{
|
||||
printk(KERN_ERR "%s: region #1 is an I/O resource, aborting.\n",
|
||||
pci_name(pdev));
|
||||
if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
|
||||
dev_err(&pdev->dev,
|
||||
"region #1 is an I/O resource, aborting.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(pci_resource_len(pdev, 1) < 256)
|
||||
{
|
||||
printk(KERN_ERR "%s: region #1 is too small.\n",
|
||||
pci_name(pdev));
|
||||
if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
|
||||
dev_err(&pdev->dev, "region #1 is too small.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
vptr->pdev = pdev;
|
||||
|
@ -1728,7 +1726,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_
|
|||
|
||||
static int velocity_open(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);
|
||||
|
@ -1785,7 +1783,7 @@ static int velocity_open(struct net_device *dev)
|
|||
|
||||
static int velocity_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int oldmtu = dev->mtu;
|
||||
int ret = 0;
|
||||
|
@ -1861,7 +1859,7 @@ static void velocity_shutdown(struct velocity_info *vptr)
|
|||
|
||||
static int velocity_close(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
|
||||
netif_stop_queue(dev);
|
||||
velocity_shutdown(vptr);
|
||||
|
@ -1894,7 +1892,7 @@ static int velocity_close(struct net_device *dev)
|
|||
|
||||
static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
int qnum = 0;
|
||||
struct tx_desc *td_ptr;
|
||||
struct velocity_td_info *tdinfo;
|
||||
|
@ -2049,7 +2047,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = dev_instance;
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
u32 isr_status;
|
||||
int max_count = 0;
|
||||
|
||||
|
@ -2104,7 +2102,7 @@ static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
|
|||
|
||||
static void velocity_set_multi(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
struct mac_regs __iomem * regs = vptr->mac_regs;
|
||||
u8 rx_mode;
|
||||
int i;
|
||||
|
@ -2153,7 +2151,7 @@ static void velocity_set_multi(struct net_device *dev)
|
|||
|
||||
static struct net_device_stats *velocity_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
|
||||
/* If the hardware is down, don't touch MII */
|
||||
if(!netif_running(dev))
|
||||
|
@ -2196,7 +2194,7 @@ static struct net_device_stats *velocity_get_stats(struct net_device *dev)
|
|||
|
||||
static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* If we are asked for information and the device is power
|
||||
|
@ -2825,7 +2823,7 @@ static void enable_flow_control_ability(struct velocity_info *vptr)
|
|||
|
||||
static int velocity_ethtool_up(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
if (!netif_running(dev))
|
||||
pci_set_power_state(vptr->pdev, PCI_D0);
|
||||
return 0;
|
||||
|
@ -2841,14 +2839,14 @@ static int velocity_ethtool_up(struct net_device *dev)
|
|||
|
||||
static void velocity_ethtool_down(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
if (!netif_running(dev))
|
||||
pci_set_power_state(vptr->pdev, PCI_D3hot);
|
||||
}
|
||||
|
||||
static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
struct mac_regs __iomem * regs = vptr->mac_regs;
|
||||
u32 status;
|
||||
status = check_connection_type(vptr->mac_regs);
|
||||
|
@ -2873,7 +2871,7 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd
|
|||
|
||||
static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
u32 curr_status;
|
||||
u32 new_status = 0;
|
||||
int ret = 0;
|
||||
|
@ -2896,14 +2894,14 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd
|
|||
|
||||
static u32 velocity_get_link(struct net_device *dev)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
struct mac_regs __iomem * regs = vptr->mac_regs;
|
||||
return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
strcpy(info->driver, VELOCITY_NAME);
|
||||
strcpy(info->version, VELOCITY_VERSION);
|
||||
strcpy(info->bus_info, pci_name(vptr->pdev));
|
||||
|
@ -2911,7 +2909,7 @@ static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
|
|||
|
||||
static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP;
|
||||
wol->wolopts |= WAKE_MAGIC;
|
||||
/*
|
||||
|
@ -2927,7 +2925,7 @@ static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_woli
|
|||
|
||||
static int velocity_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
|
||||
if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP)))
|
||||
return -EFAULT;
|
||||
|
@ -2992,7 +2990,7 @@ static struct ethtool_ops velocity_ethtool_ops = {
|
|||
|
||||
static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct velocity_info *vptr = dev->priv;
|
||||
struct velocity_info *vptr = netdev_priv(dev);
|
||||
struct mac_regs __iomem * regs = vptr->mac_regs;
|
||||
unsigned long flags;
|
||||
struct mii_ioctl_data *miidata = if_mii(ifr);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
|
||||
#define VELOCITY_VERSION "1.13"
|
||||
|
||||
#define VELOCITY_IO_SIZE 256
|
||||
|
||||
#define PKT_BUF_SZ 1540
|
||||
|
||||
#define MAX_UNITS 8
|
||||
|
@ -1191,7 +1193,6 @@ enum chip_type {
|
|||
struct velocity_info_tbl {
|
||||
enum chip_type chip_id;
|
||||
char *name;
|
||||
int io_size;
|
||||
int txqueue;
|
||||
u32 flags;
|
||||
};
|
||||
|
@ -1751,7 +1752,6 @@ struct velocity_info {
|
|||
struct mac_regs __iomem * mac_regs;
|
||||
unsigned long memaddr;
|
||||
unsigned long ioaddr;
|
||||
u32 io_size;
|
||||
|
||||
u8 rev_id;
|
||||
|
||||
|
|
|
@ -134,18 +134,6 @@ config SEALEVEL_4021
|
|||
The driver will be compiled as a module: the
|
||||
module will be called sealevel.
|
||||
|
||||
config SYNCLINK_SYNCPPP
|
||||
tristate "SyncLink HDLC/SYNCPPP support"
|
||||
depends on WAN
|
||||
help
|
||||
Enables HDLC/SYNCPPP support for the SyncLink WAN driver.
|
||||
|
||||
Normally the SyncLink WAN driver works with the main PPP driver
|
||||
<file:drivers/net/ppp_generic.c> and pppd program.
|
||||
HDLC/SYNCPPP support allows use of the Cisco HDLC/PPP driver
|
||||
<file:drivers/net/wan/syncppp.c>. The SyncLink WAN driver (in
|
||||
character devices) must also be enabled.
|
||||
|
||||
# Generic HDLC
|
||||
config HDLC
|
||||
tristate "Generic HDLC layer"
|
||||
|
|
|
@ -28,7 +28,6 @@ obj-$(CONFIG_COSA) += syncppp.o cosa.o
|
|||
obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o
|
||||
obj-$(CONFIG_DSCC4) += dscc4.o
|
||||
obj-$(CONFIG_LANMEDIA) += syncppp.o
|
||||
obj-$(CONFIG_SYNCLINK_SYNCPPP) += syncppp.o
|
||||
obj-$(CONFIG_X25_ASY) += x25_asy.o
|
||||
|
||||
obj-$(CONFIG_LANMEDIA) += lmc/
|
||||
|
|
|
@ -550,6 +550,7 @@ config USB_ZD1201
|
|||
|
||||
source "drivers/net/wireless/hostap/Kconfig"
|
||||
source "drivers/net/wireless/bcm43xx/Kconfig"
|
||||
source "drivers/net/wireless/zd1211rw/Kconfig"
|
||||
|
||||
# yes, this works even when no drivers are selected
|
||||
config NET_WIRELESS
|
||||
|
|
|
@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/
|
|||
|
||||
obj-$(CONFIG_HOSTAP) += hostap/
|
||||
obj-$(CONFIG_BCM43XX) += bcm43xx/
|
||||
obj-$(CONFIG_ZD1211RW) += zd1211rw/
|
||||
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
|
|
|
@ -1885,6 +1885,15 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
|
|||
|
||||
spin_lock(&bcm->irq_lock);
|
||||
|
||||
/* Only accept IRQs, if we are initialized properly.
|
||||
* This avoids an RX race while initializing.
|
||||
* We should probably not enable IRQs before we are initialized
|
||||
* completely, but some careful work is needed to fix this. I think it
|
||||
* is best to stay with this cheap workaround for now... .
|
||||
*/
|
||||
if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
|
||||
goto out;
|
||||
|
||||
reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
|
||||
if (reason == 0xffffffff) {
|
||||
/* irq not for us (shared irq) */
|
||||
|
@ -1906,19 +1915,11 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
|
|||
|
||||
bcm43xx_interrupt_ack(bcm, reason);
|
||||
|
||||
/* Only accept IRQs, if we are initialized properly.
|
||||
* This avoids an RX race while initializing.
|
||||
* We should probably not enable IRQs before we are initialized
|
||||
* completely, but some careful work is needed to fix this. I think it
|
||||
* is best to stay with this cheap workaround for now... .
|
||||
*/
|
||||
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
|
||||
/* disable all IRQs. They are enabled again in the bottom half. */
|
||||
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
/* save the reason code and call our bottom half. */
|
||||
bcm->irq_reason = reason;
|
||||
tasklet_schedule(&bcm->isr_tasklet);
|
||||
}
|
||||
/* disable all IRQs. They are enabled again in the bottom half. */
|
||||
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
/* save the reason code and call our bottom half. */
|
||||
bcm->irq_reason = reason;
|
||||
tasklet_schedule(&bcm->isr_tasklet);
|
||||
|
||||
out:
|
||||
mmiowb();
|
||||
|
@ -3698,6 +3699,10 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
|
|||
secinfo->encrypt = sec->encrypt;
|
||||
dprintk(", .encrypt = %d", sec->encrypt);
|
||||
}
|
||||
if (sec->flags & SEC_AUTH_MODE) {
|
||||
secinfo->auth_mode = sec->auth_mode;
|
||||
dprintk(", .auth_mode = %d\n", sec->auth_mode);
|
||||
}
|
||||
dprintk("\n");
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
|
||||
!bcm->ieee->host_encrypt) {
|
||||
|
|
|
@ -112,30 +112,6 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
|
|||
return bcm43xx_channel_to_freq_bg(channel);
|
||||
}
|
||||
|
||||
/* Lightweight function to check if a channel number is valid.
|
||||
* Note that this does _NOT_ check for geographical restrictions!
|
||||
*/
|
||||
static inline
|
||||
int bcm43xx_is_valid_channel_a(u8 channel)
|
||||
{
|
||||
return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
|
||||
&& channel <= IEEE80211_52GHZ_MAX_CHANNEL);
|
||||
}
|
||||
static inline
|
||||
int bcm43xx_is_valid_channel_bg(u8 channel)
|
||||
{
|
||||
return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
|
||||
&& channel <= IEEE80211_24GHZ_MAX_CHANNEL);
|
||||
}
|
||||
static inline
|
||||
int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
|
||||
u8 channel)
|
||||
{
|
||||
if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
|
||||
return bcm43xx_is_valid_channel_a(channel);
|
||||
return bcm43xx_is_valid_channel_bg(channel);
|
||||
}
|
||||
|
||||
void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
|
||||
void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
|
||||
|
||||
|
|
|
@ -1594,11 +1594,11 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
|
|||
u16 r8, tmp;
|
||||
u16 freq;
|
||||
|
||||
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
|
||||
return -EINVAL;
|
||||
if ((radio->manufact == 0x17F) &&
|
||||
(radio->version == 0x2060) &&
|
||||
(radio->revision == 1)) {
|
||||
if (channel > 200)
|
||||
return -EINVAL;
|
||||
freq = channel2freq_a(channel);
|
||||
|
||||
r8 = bcm43xx_radio_read16(bcm, 0x0008);
|
||||
|
@ -1651,9 +1651,6 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
|
|||
TODO(); //TODO: TSSI2dbm workaround
|
||||
bcm43xx_phy_xmitpower(bcm);//FIXME correct?
|
||||
} else {
|
||||
if ((channel < 1) || (channel > 14))
|
||||
return -EINVAL;
|
||||
|
||||
if (synthetic_pu_workaround)
|
||||
bcm43xx_synth_pu_workaround(bcm, channel);
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
|
|||
channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
|
||||
freq = data->freq.m;
|
||||
}
|
||||
if (!bcm43xx_is_valid_channel(bcm, channel))
|
||||
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
|
||||
goto out_unlock;
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
|
||||
//ieee80211softmac_disassoc(softmac, $REASON);
|
||||
|
|
|
@ -296,11 +296,14 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
|
|||
u16 control = 0;
|
||||
u16 wsec_rate = 0;
|
||||
u16 encrypt_frame;
|
||||
const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
|
||||
const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
|
||||
|
||||
/* Now construct the TX header. */
|
||||
memset(txhdr, 0, sizeof(*txhdr));
|
||||
|
||||
bitrate = bcm->softmac->txrates.default_rate;
|
||||
bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
|
||||
is_multicast_ether_addr(wireless_header->addr1), is_mgt);
|
||||
ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
|
||||
fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
|
||||
fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
|
||||
|
|
|
@ -66,10 +66,12 @@ static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
|
|||
PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
|
||||
PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
|
||||
PLXDEV(0x126c, 0x8030, "Nortel emobility"),
|
||||
PLXDEV(0x1562, 0x0001, "Symbol LA-4123"),
|
||||
PLXDEV(0x1385, 0x4100, "Netgear MA301"),
|
||||
PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
|
||||
PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
|
||||
PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
|
||||
PLXDEV(0x16ab, 0x1100, "Global Sun Tech GL24110P"),
|
||||
PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
|
||||
PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
|
||||
PLXDEV(0x16ab, 0x1103, "Longshine 8031"),
|
||||
|
|
19
drivers/net/wireless/zd1211rw/Kconfig
Normal file
19
drivers/net/wireless/zd1211rw/Kconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
config ZD1211RW
|
||||
tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
|
||||
depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
|
||||
chip, present in many USB-wireless adapters.
|
||||
|
||||
Device firmware is required alongside this driver. You can download the
|
||||
firmware distribution from http://zd1211.ath.cx/get-firmware
|
||||
|
||||
config ZD1211RW_DEBUG
|
||||
bool "ZyDAS ZD1211 debugging"
|
||||
depends on ZD1211RW
|
||||
---help---
|
||||
ZD1211 debugging messages. Choosing Y will result in additional debug
|
||||
messages being saved to your kernel logs, which may help debug any
|
||||
problems.
|
||||
|
11
drivers/net/wireless/zd1211rw/Makefile
Normal file
11
drivers/net/wireless/zd1211rw/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
obj-$(CONFIG_ZD1211RW) += zd1211rw.o
|
||||
|
||||
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
|
||||
zd_mac.o zd_netdev.o \
|
||||
zd_rf_al2230.o zd_rf_rf2959.o \
|
||||
zd_rf.o zd_usb.o zd_util.o
|
||||
|
||||
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
1615
drivers/net/wireless/zd1211rw/zd_chip.c
Normal file
1615
drivers/net/wireless/zd1211rw/zd_chip.c
Normal file
File diff suppressed because it is too large
Load diff
825
drivers/net/wireless/zd1211rw/zd_chip.h
Normal file
825
drivers/net/wireless/zd1211rw/zd_chip.h
Normal file
|
@ -0,0 +1,825 @@
|
|||
/* zd_chip.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_CHIP_H
|
||||
#define _ZD_CHIP_H
|
||||
|
||||
#include "zd_types.h"
|
||||
#include "zd_rf.h"
|
||||
#include "zd_usb.h"
|
||||
|
||||
/* Header for the Media Access Controller (MAC) and the Baseband Processor
|
||||
* (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and
|
||||
* adds a processor for handling the USB protocol.
|
||||
*/
|
||||
|
||||
/* 8-bit hardware registers */
|
||||
#define CR0 CTL_REG(0x0000)
|
||||
#define CR1 CTL_REG(0x0004)
|
||||
#define CR2 CTL_REG(0x0008)
|
||||
#define CR3 CTL_REG(0x000C)
|
||||
|
||||
#define CR5 CTL_REG(0x0010)
|
||||
/* bit 5: if set short preamble used
|
||||
* bit 6: filter band - Japan channel 14 on, else off
|
||||
*/
|
||||
#define CR6 CTL_REG(0x0014)
|
||||
#define CR7 CTL_REG(0x0018)
|
||||
#define CR8 CTL_REG(0x001C)
|
||||
|
||||
#define CR4 CTL_REG(0x0020)
|
||||
|
||||
#define CR9 CTL_REG(0x0024)
|
||||
/* bit 2: antenna switch (together with CR10) */
|
||||
#define CR10 CTL_REG(0x0028)
|
||||
/* bit 1: antenna switch (together with CR9)
|
||||
* RF2959 controls with CR11 radion on and off
|
||||
*/
|
||||
#define CR11 CTL_REG(0x002C)
|
||||
/* bit 6: TX power control for OFDM
|
||||
* RF2959 controls with CR10 radio on and off
|
||||
*/
|
||||
#define CR12 CTL_REG(0x0030)
|
||||
#define CR13 CTL_REG(0x0034)
|
||||
#define CR14 CTL_REG(0x0038)
|
||||
#define CR15 CTL_REG(0x003C)
|
||||
#define CR16 CTL_REG(0x0040)
|
||||
#define CR17 CTL_REG(0x0044)
|
||||
#define CR18 CTL_REG(0x0048)
|
||||
#define CR19 CTL_REG(0x004C)
|
||||
#define CR20 CTL_REG(0x0050)
|
||||
#define CR21 CTL_REG(0x0054)
|
||||
#define CR22 CTL_REG(0x0058)
|
||||
#define CR23 CTL_REG(0x005C)
|
||||
#define CR24 CTL_REG(0x0060) /* CCA threshold */
|
||||
#define CR25 CTL_REG(0x0064)
|
||||
#define CR26 CTL_REG(0x0068)
|
||||
#define CR27 CTL_REG(0x006C)
|
||||
#define CR28 CTL_REG(0x0070)
|
||||
#define CR29 CTL_REG(0x0074)
|
||||
#define CR30 CTL_REG(0x0078)
|
||||
#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */
|
||||
#define CR32 CTL_REG(0x0080)
|
||||
#define CR33 CTL_REG(0x0084)
|
||||
#define CR34 CTL_REG(0x0088)
|
||||
#define CR35 CTL_REG(0x008C)
|
||||
#define CR36 CTL_REG(0x0090)
|
||||
#define CR37 CTL_REG(0x0094)
|
||||
#define CR38 CTL_REG(0x0098)
|
||||
#define CR39 CTL_REG(0x009C)
|
||||
#define CR40 CTL_REG(0x00A0)
|
||||
#define CR41 CTL_REG(0x00A4)
|
||||
#define CR42 CTL_REG(0x00A8)
|
||||
#define CR43 CTL_REG(0x00AC)
|
||||
#define CR44 CTL_REG(0x00B0)
|
||||
#define CR45 CTL_REG(0x00B4)
|
||||
#define CR46 CTL_REG(0x00B8)
|
||||
#define CR47 CTL_REG(0x00BC) /* CCK baseband gain
|
||||
* (patch value might be in EEPROM)
|
||||
*/
|
||||
#define CR48 CTL_REG(0x00C0)
|
||||
#define CR49 CTL_REG(0x00C4)
|
||||
#define CR50 CTL_REG(0x00C8)
|
||||
#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */
|
||||
#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */
|
||||
#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */
|
||||
#define CR54 CTL_REG(0x00D8)
|
||||
#define CR55 CTL_REG(0x00DC)
|
||||
#define CR56 CTL_REG(0x00E0)
|
||||
#define CR57 CTL_REG(0x00E4)
|
||||
#define CR58 CTL_REG(0x00E8)
|
||||
#define CR59 CTL_REG(0x00EC)
|
||||
#define CR60 CTL_REG(0x00F0)
|
||||
#define CR61 CTL_REG(0x00F4)
|
||||
#define CR62 CTL_REG(0x00F8)
|
||||
#define CR63 CTL_REG(0x00FC)
|
||||
#define CR64 CTL_REG(0x0100)
|
||||
#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */
|
||||
#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */
|
||||
#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */
|
||||
#define CR68 CTL_REG(0x0110) /* CCK calibration */
|
||||
#define CR69 CTL_REG(0x0114)
|
||||
#define CR70 CTL_REG(0x0118)
|
||||
#define CR71 CTL_REG(0x011C)
|
||||
#define CR72 CTL_REG(0x0120)
|
||||
#define CR73 CTL_REG(0x0124)
|
||||
#define CR74 CTL_REG(0x0128)
|
||||
#define CR75 CTL_REG(0x012C)
|
||||
#define CR76 CTL_REG(0x0130)
|
||||
#define CR77 CTL_REG(0x0134)
|
||||
#define CR78 CTL_REG(0x0138)
|
||||
#define CR79 CTL_REG(0x013C)
|
||||
#define CR80 CTL_REG(0x0140)
|
||||
#define CR81 CTL_REG(0x0144)
|
||||
#define CR82 CTL_REG(0x0148)
|
||||
#define CR83 CTL_REG(0x014C)
|
||||
#define CR84 CTL_REG(0x0150)
|
||||
#define CR85 CTL_REG(0x0154)
|
||||
#define CR86 CTL_REG(0x0158)
|
||||
#define CR87 CTL_REG(0x015C)
|
||||
#define CR88 CTL_REG(0x0160)
|
||||
#define CR89 CTL_REG(0x0164)
|
||||
#define CR90 CTL_REG(0x0168)
|
||||
#define CR91 CTL_REG(0x016C)
|
||||
#define CR92 CTL_REG(0x0170)
|
||||
#define CR93 CTL_REG(0x0174)
|
||||
#define CR94 CTL_REG(0x0178)
|
||||
#define CR95 CTL_REG(0x017C)
|
||||
#define CR96 CTL_REG(0x0180)
|
||||
#define CR97 CTL_REG(0x0184)
|
||||
#define CR98 CTL_REG(0x0188)
|
||||
#define CR99 CTL_REG(0x018C)
|
||||
#define CR100 CTL_REG(0x0190)
|
||||
#define CR101 CTL_REG(0x0194)
|
||||
#define CR102 CTL_REG(0x0198)
|
||||
#define CR103 CTL_REG(0x019C)
|
||||
#define CR104 CTL_REG(0x01A0)
|
||||
#define CR105 CTL_REG(0x01A4)
|
||||
#define CR106 CTL_REG(0x01A8)
|
||||
#define CR107 CTL_REG(0x01AC)
|
||||
#define CR108 CTL_REG(0x01B0)
|
||||
#define CR109 CTL_REG(0x01B4)
|
||||
#define CR110 CTL_REG(0x01B8)
|
||||
#define CR111 CTL_REG(0x01BC)
|
||||
#define CR112 CTL_REG(0x01C0)
|
||||
#define CR113 CTL_REG(0x01C4)
|
||||
#define CR114 CTL_REG(0x01C8)
|
||||
#define CR115 CTL_REG(0x01CC)
|
||||
#define CR116 CTL_REG(0x01D0)
|
||||
#define CR117 CTL_REG(0x01D4)
|
||||
#define CR118 CTL_REG(0x01D8)
|
||||
#define CR119 CTL_REG(0x01DC)
|
||||
#define CR120 CTL_REG(0x01E0)
|
||||
#define CR121 CTL_REG(0x01E4)
|
||||
#define CR122 CTL_REG(0x01E8)
|
||||
#define CR123 CTL_REG(0x01EC)
|
||||
#define CR124 CTL_REG(0x01F0)
|
||||
#define CR125 CTL_REG(0x01F4)
|
||||
#define CR126 CTL_REG(0x01F8)
|
||||
#define CR127 CTL_REG(0x01FC)
|
||||
#define CR128 CTL_REG(0x0200)
|
||||
#define CR129 CTL_REG(0x0204)
|
||||
#define CR130 CTL_REG(0x0208)
|
||||
#define CR131 CTL_REG(0x020C)
|
||||
#define CR132 CTL_REG(0x0210)
|
||||
#define CR133 CTL_REG(0x0214)
|
||||
#define CR134 CTL_REG(0x0218)
|
||||
#define CR135 CTL_REG(0x021C)
|
||||
#define CR136 CTL_REG(0x0220)
|
||||
#define CR137 CTL_REG(0x0224)
|
||||
#define CR138 CTL_REG(0x0228)
|
||||
#define CR139 CTL_REG(0x022C)
|
||||
#define CR140 CTL_REG(0x0230)
|
||||
#define CR141 CTL_REG(0x0234)
|
||||
#define CR142 CTL_REG(0x0238)
|
||||
#define CR143 CTL_REG(0x023C)
|
||||
#define CR144 CTL_REG(0x0240)
|
||||
#define CR145 CTL_REG(0x0244)
|
||||
#define CR146 CTL_REG(0x0248)
|
||||
#define CR147 CTL_REG(0x024C)
|
||||
#define CR148 CTL_REG(0x0250)
|
||||
#define CR149 CTL_REG(0x0254)
|
||||
#define CR150 CTL_REG(0x0258)
|
||||
#define CR151 CTL_REG(0x025C)
|
||||
#define CR152 CTL_REG(0x0260)
|
||||
#define CR153 CTL_REG(0x0264)
|
||||
#define CR154 CTL_REG(0x0268)
|
||||
#define CR155 CTL_REG(0x026C)
|
||||
#define CR156 CTL_REG(0x0270)
|
||||
#define CR157 CTL_REG(0x0274)
|
||||
#define CR158 CTL_REG(0x0278)
|
||||
#define CR159 CTL_REG(0x027C)
|
||||
#define CR160 CTL_REG(0x0280)
|
||||
#define CR161 CTL_REG(0x0284)
|
||||
#define CR162 CTL_REG(0x0288)
|
||||
#define CR163 CTL_REG(0x028C)
|
||||
#define CR164 CTL_REG(0x0290)
|
||||
#define CR165 CTL_REG(0x0294)
|
||||
#define CR166 CTL_REG(0x0298)
|
||||
#define CR167 CTL_REG(0x029C)
|
||||
#define CR168 CTL_REG(0x02A0)
|
||||
#define CR169 CTL_REG(0x02A4)
|
||||
#define CR170 CTL_REG(0x02A8)
|
||||
#define CR171 CTL_REG(0x02AC)
|
||||
#define CR172 CTL_REG(0x02B0)
|
||||
#define CR173 CTL_REG(0x02B4)
|
||||
#define CR174 CTL_REG(0x02B8)
|
||||
#define CR175 CTL_REG(0x02BC)
|
||||
#define CR176 CTL_REG(0x02C0)
|
||||
#define CR177 CTL_REG(0x02C4)
|
||||
#define CR178 CTL_REG(0x02C8)
|
||||
#define CR179 CTL_REG(0x02CC)
|
||||
#define CR180 CTL_REG(0x02D0)
|
||||
#define CR181 CTL_REG(0x02D4)
|
||||
#define CR182 CTL_REG(0x02D8)
|
||||
#define CR183 CTL_REG(0x02DC)
|
||||
#define CR184 CTL_REG(0x02E0)
|
||||
#define CR185 CTL_REG(0x02E4)
|
||||
#define CR186 CTL_REG(0x02E8)
|
||||
#define CR187 CTL_REG(0x02EC)
|
||||
#define CR188 CTL_REG(0x02F0)
|
||||
#define CR189 CTL_REG(0x02F4)
|
||||
#define CR190 CTL_REG(0x02F8)
|
||||
#define CR191 CTL_REG(0x02FC)
|
||||
#define CR192 CTL_REG(0x0300)
|
||||
#define CR193 CTL_REG(0x0304)
|
||||
#define CR194 CTL_REG(0x0308)
|
||||
#define CR195 CTL_REG(0x030C)
|
||||
#define CR196 CTL_REG(0x0310)
|
||||
#define CR197 CTL_REG(0x0314)
|
||||
#define CR198 CTL_REG(0x0318)
|
||||
#define CR199 CTL_REG(0x031C)
|
||||
#define CR200 CTL_REG(0x0320)
|
||||
#define CR201 CTL_REG(0x0324)
|
||||
#define CR202 CTL_REG(0x0328)
|
||||
#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */
|
||||
#define CR204 CTL_REG(0x0330)
|
||||
#define CR205 CTL_REG(0x0334)
|
||||
#define CR206 CTL_REG(0x0338)
|
||||
#define CR207 CTL_REG(0x033C)
|
||||
#define CR208 CTL_REG(0x0340)
|
||||
#define CR209 CTL_REG(0x0344)
|
||||
#define CR210 CTL_REG(0x0348)
|
||||
#define CR211 CTL_REG(0x034C)
|
||||
#define CR212 CTL_REG(0x0350)
|
||||
#define CR213 CTL_REG(0x0354)
|
||||
#define CR214 CTL_REG(0x0358)
|
||||
#define CR215 CTL_REG(0x035C)
|
||||
#define CR216 CTL_REG(0x0360)
|
||||
#define CR217 CTL_REG(0x0364)
|
||||
#define CR218 CTL_REG(0x0368)
|
||||
#define CR219 CTL_REG(0x036C)
|
||||
#define CR220 CTL_REG(0x0370)
|
||||
#define CR221 CTL_REG(0x0374)
|
||||
#define CR222 CTL_REG(0x0378)
|
||||
#define CR223 CTL_REG(0x037C)
|
||||
#define CR224 CTL_REG(0x0380)
|
||||
#define CR225 CTL_REG(0x0384)
|
||||
#define CR226 CTL_REG(0x0388)
|
||||
#define CR227 CTL_REG(0x038C)
|
||||
#define CR228 CTL_REG(0x0390)
|
||||
#define CR229 CTL_REG(0x0394)
|
||||
#define CR230 CTL_REG(0x0398)
|
||||
#define CR231 CTL_REG(0x039C)
|
||||
#define CR232 CTL_REG(0x03A0)
|
||||
#define CR233 CTL_REG(0x03A4)
|
||||
#define CR234 CTL_REG(0x03A8)
|
||||
#define CR235 CTL_REG(0x03AC)
|
||||
#define CR236 CTL_REG(0x03B0)
|
||||
|
||||
#define CR240 CTL_REG(0x03C0)
|
||||
/* bit 7: host-controlled RF register writes
|
||||
* CR241-CR245: for hardware controlled writing of RF bits, not needed for
|
||||
* USB
|
||||
*/
|
||||
#define CR241 CTL_REG(0x03C4)
|
||||
#define CR242 CTL_REG(0x03C8)
|
||||
#define CR243 CTL_REG(0x03CC)
|
||||
#define CR244 CTL_REG(0x03D0)
|
||||
#define CR245 CTL_REG(0x03D4)
|
||||
|
||||
#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of
|
||||
* Airoha RFs AL2230 and AL7230B
|
||||
*/
|
||||
#define CR252 CTL_REG(0x03F0)
|
||||
#define CR253 CTL_REG(0x03F4)
|
||||
#define CR254 CTL_REG(0x03F8)
|
||||
#define CR255 CTL_REG(0x03FC)
|
||||
|
||||
#define CR_MAX_PHY_REG 255
|
||||
|
||||
/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211
|
||||
* driver.
|
||||
*/
|
||||
|
||||
#define CR_RF_IF_CLK CTL_REG(0x0400)
|
||||
#define CR_RF_IF_DATA CTL_REG(0x0404)
|
||||
#define CR_PE1_PE2 CTL_REG(0x0408)
|
||||
#define CR_PE2_DLY CTL_REG(0x040C)
|
||||
#define CR_LE1 CTL_REG(0x0410)
|
||||
#define CR_LE2 CTL_REG(0x0414)
|
||||
/* Seems to enable/disable GPI (General Purpose IO?) */
|
||||
#define CR_GPI_EN CTL_REG(0x0418)
|
||||
#define CR_RADIO_PD CTL_REG(0x042C)
|
||||
#define CR_RF2948_PD CTL_REG(0x042C)
|
||||
#define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C)
|
||||
#define CR_CONFIG_PHILIPS CTL_REG(0x0440)
|
||||
#define CR_SA2400_SER_AP CTL_REG(0x0444)
|
||||
#define CR_I2C_WRITE CTL_REG(0x0444)
|
||||
#define CR_SA2400_SER_RP CTL_REG(0x0448)
|
||||
#define CR_RADIO_PE CTL_REG(0x0458)
|
||||
#define CR_RST_BUS_MASTER CTL_REG(0x045C)
|
||||
#define CR_RFCFG CTL_REG(0x0464)
|
||||
#define CR_HSTSCHG CTL_REG(0x046C)
|
||||
#define CR_PHY_ON CTL_REG(0x0474)
|
||||
#define CR_RX_DELAY CTL_REG(0x0478)
|
||||
#define CR_RX_PE_DELAY CTL_REG(0x047C)
|
||||
#define CR_GPIO_1 CTL_REG(0x0490)
|
||||
#define CR_GPIO_2 CTL_REG(0x0494)
|
||||
#define CR_EncryBufMux CTL_REG(0x04A8)
|
||||
#define CR_PS_CTRL CTL_REG(0x0500)
|
||||
#define CR_ADDA_PWR_DWN CTL_REG(0x0504)
|
||||
#define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508)
|
||||
#define CR_MAC_PS_STATE CTL_REG(0x050C)
|
||||
|
||||
#define CR_INTERRUPT CTL_REG(0x0510)
|
||||
#define INT_TX_COMPLETE 0x00000001
|
||||
#define INT_RX_COMPLETE 0x00000002
|
||||
#define INT_RETRY_FAIL 0x00000004
|
||||
#define INT_WAKEUP 0x00000008
|
||||
#define INT_DTIM_NOTIFY 0x00000020
|
||||
#define INT_CFG_NEXT_BCN 0x00000040
|
||||
#define INT_BUS_ABORT 0x00000080
|
||||
#define INT_TX_FIFO_READY 0x00000100
|
||||
#define INT_UART 0x00000200
|
||||
#define INT_TX_COMPLETE_EN 0x00010000
|
||||
#define INT_RX_COMPLETE_EN 0x00020000
|
||||
#define INT_RETRY_FAIL_EN 0x00040000
|
||||
#define INT_WAKEUP_EN 0x00080000
|
||||
#define INT_DTIM_NOTIFY_EN 0x00200000
|
||||
#define INT_CFG_NEXT_BCN_EN 0x00400000
|
||||
#define INT_BUS_ABORT_EN 0x00800000
|
||||
#define INT_TX_FIFO_READY_EN 0x01000000
|
||||
#define INT_UART_EN 0x02000000
|
||||
|
||||
#define CR_TSF_LOW_PART CTL_REG(0x0514)
|
||||
#define CR_TSF_HIGH_PART CTL_REG(0x0518)
|
||||
|
||||
/* Following three values are in time units (1024us)
|
||||
* Following condition must be met:
|
||||
* atim < tbtt < bcn
|
||||
*/
|
||||
#define CR_ATIM_WND_PERIOD CTL_REG(0x051C)
|
||||
#define CR_BCN_INTERVAL CTL_REG(0x0520)
|
||||
#define CR_PRE_TBTT CTL_REG(0x0524)
|
||||
/* in units of TU(1024us) */
|
||||
|
||||
/* for UART support */
|
||||
#define CR_UART_RBR_THR_DLL CTL_REG(0x0540)
|
||||
#define CR_UART_DLM_IER CTL_REG(0x0544)
|
||||
#define CR_UART_IIR_FCR CTL_REG(0x0548)
|
||||
#define CR_UART_LCR CTL_REG(0x054c)
|
||||
#define CR_UART_MCR CTL_REG(0x0550)
|
||||
#define CR_UART_LSR CTL_REG(0x0554)
|
||||
#define CR_UART_MSR CTL_REG(0x0558)
|
||||
#define CR_UART_ECR CTL_REG(0x055c)
|
||||
#define CR_UART_STATUS CTL_REG(0x0560)
|
||||
|
||||
#define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600)
|
||||
#define CR_PCI_TX_AddR_P2 CTL_REG(0x0604)
|
||||
#define CR_PCI_RX_AddR_P1 CTL_REG(0x0608)
|
||||
#define CR_PCI_RX_AddR_P2 CTL_REG(0x060C)
|
||||
|
||||
/* must be overwritten if custom MAC address will be used */
|
||||
#define CR_MAC_ADDR_P1 CTL_REG(0x0610)
|
||||
#define CR_MAC_ADDR_P2 CTL_REG(0x0614)
|
||||
#define CR_BSSID_P1 CTL_REG(0x0618)
|
||||
#define CR_BSSID_P2 CTL_REG(0x061C)
|
||||
#define CR_BCN_PLCP_CFG CTL_REG(0x0620)
|
||||
#define CR_GROUP_HASH_P1 CTL_REG(0x0624)
|
||||
#define CR_GROUP_HASH_P2 CTL_REG(0x0628)
|
||||
#define CR_RX_TIMEOUT CTL_REG(0x062C)
|
||||
|
||||
/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
|
||||
* device will use a rate in this table that is less than or equal to the rate
|
||||
* of the incoming frame which prompted the response */
|
||||
#define CR_BASIC_RATE_TBL CTL_REG(0x0630)
|
||||
#define CR_RATE_1M 0x0001 /* 802.11b */
|
||||
#define CR_RATE_2M 0x0002 /* 802.11b */
|
||||
#define CR_RATE_5_5M 0x0004 /* 802.11b */
|
||||
#define CR_RATE_11M 0x0008 /* 802.11b */
|
||||
#define CR_RATE_6M 0x0100 /* 802.11g */
|
||||
#define CR_RATE_9M 0x0200 /* 802.11g */
|
||||
#define CR_RATE_12M 0x0400 /* 802.11g */
|
||||
#define CR_RATE_18M 0x0800 /* 802.11g */
|
||||
#define CR_RATE_24M 0x1000 /* 802.11g */
|
||||
#define CR_RATE_36M 0x2000 /* 802.11g */
|
||||
#define CR_RATE_48M 0x4000 /* 802.11g */
|
||||
#define CR_RATE_54M 0x8000 /* 802.11g */
|
||||
#define CR_RATES_80211G 0xff00
|
||||
#define CR_RATES_80211B 0x000f
|
||||
|
||||
/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if
|
||||
* the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will
|
||||
* look for a rate in this table that is less than or equal to the rate of
|
||||
* the incoming frame. */
|
||||
#define CR_MANDATORY_RATE_TBL CTL_REG(0x0634)
|
||||
#define CR_RTS_CTS_RATE CTL_REG(0x0638)
|
||||
|
||||
#define CR_WEP_PROTECT CTL_REG(0x063C)
|
||||
#define CR_RX_THRESHOLD CTL_REG(0x0640)
|
||||
|
||||
/* register for controlling the LEDS */
|
||||
#define CR_LED CTL_REG(0x0644)
|
||||
/* masks for controlling LEDs */
|
||||
#define LED1 0x0100
|
||||
#define LED2 0x0200
|
||||
|
||||
/* Seems to indicate that the configuration is over.
|
||||
*/
|
||||
#define CR_AFTER_PNP CTL_REG(0x0648)
|
||||
#define CR_ACK_TIME_80211 CTL_REG(0x0658)
|
||||
|
||||
#define CR_RX_OFFSET CTL_REG(0x065c)
|
||||
|
||||
#define CR_PHY_DELAY CTL_REG(0x066C)
|
||||
#define CR_BCN_FIFO CTL_REG(0x0670)
|
||||
#define CR_SNIFFER_ON CTL_REG(0x0674)
|
||||
|
||||
#define CR_ENCRYPTION_TYPE CTL_REG(0x0678)
|
||||
#define NO_WEP 0
|
||||
#define WEP64 1
|
||||
#define WEP128 5
|
||||
#define WEP256 6
|
||||
#define ENC_SNIFFER 8
|
||||
|
||||
#define CR_ZD1211_RETRY_MAX CTL_REG(0x067C)
|
||||
|
||||
#define CR_REG1 CTL_REG(0x0680)
|
||||
/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical
|
||||
* registers, so one could argue it is a LOCK bit. But calling it
|
||||
* LOCK_PHY_REGS makes it confusing.
|
||||
*/
|
||||
#define UNLOCK_PHY_REGS 0x0080
|
||||
|
||||
#define CR_DEVICE_STATE CTL_REG(0x0684)
|
||||
#define CR_UNDERRUN_CNT CTL_REG(0x0688)
|
||||
|
||||
#define CR_RX_FILTER CTL_REG(0x068c)
|
||||
#define RX_FILTER_ASSOC_RESPONSE 0x0002
|
||||
#define RX_FILTER_PROBE_RESPONSE 0x0020
|
||||
#define RX_FILTER_BEACON 0x0100
|
||||
#define RX_FILTER_AUTH 0x0800
|
||||
/* Sniff modus sets filter to 0xfffff */
|
||||
|
||||
#define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690)
|
||||
#define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694)
|
||||
#define CR_IFS_VALUE CTL_REG(0x0698)
|
||||
#define CR_RX_TIME_OUT CTL_REG(0x069C)
|
||||
#define CR_TOTAL_RX_FRM CTL_REG(0x06A0)
|
||||
#define CR_CRC32_CNT CTL_REG(0x06A4)
|
||||
#define CR_CRC16_CNT CTL_REG(0x06A8)
|
||||
#define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC)
|
||||
#define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0)
|
||||
|
||||
#define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC)
|
||||
|
||||
#define CR_NAV_CNT CTL_REG(0x06C4)
|
||||
#define CR_NAV_CCA CTL_REG(0x06C8)
|
||||
#define CR_RETRY_CNT CTL_REG(0x06CC)
|
||||
|
||||
#define CR_READ_TCB_ADDR CTL_REG(0x06E8)
|
||||
#define CR_READ_RFD_ADDR CTL_REG(0x06EC)
|
||||
#define CR_CWMIN_CWMAX CTL_REG(0x06F0)
|
||||
#define CR_TOTAL_TX_FRM CTL_REG(0x06F4)
|
||||
|
||||
/* CAM: Continuous Access Mode (power management) */
|
||||
#define CR_CAM_MODE CTL_REG(0x0700)
|
||||
#define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704)
|
||||
#define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708)
|
||||
#define CR_CAM_ADDRESS CTL_REG(0x070C)
|
||||
#define CR_CAM_DATA CTL_REG(0x0710)
|
||||
|
||||
#define CR_ROMDIR CTL_REG(0x0714)
|
||||
|
||||
#define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714)
|
||||
#define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718)
|
||||
|
||||
#define CR_WEPKEY0 CTL_REG(0x0720)
|
||||
#define CR_WEPKEY1 CTL_REG(0x0724)
|
||||
#define CR_WEPKEY2 CTL_REG(0x0728)
|
||||
#define CR_WEPKEY3 CTL_REG(0x072C)
|
||||
#define CR_WEPKEY4 CTL_REG(0x0730)
|
||||
#define CR_WEPKEY5 CTL_REG(0x0734)
|
||||
#define CR_WEPKEY6 CTL_REG(0x0738)
|
||||
#define CR_WEPKEY7 CTL_REG(0x073C)
|
||||
#define CR_WEPKEY8 CTL_REG(0x0740)
|
||||
#define CR_WEPKEY9 CTL_REG(0x0744)
|
||||
#define CR_WEPKEY10 CTL_REG(0x0748)
|
||||
#define CR_WEPKEY11 CTL_REG(0x074C)
|
||||
#define CR_WEPKEY12 CTL_REG(0x0750)
|
||||
#define CR_WEPKEY13 CTL_REG(0x0754)
|
||||
#define CR_WEPKEY14 CTL_REG(0x0758)
|
||||
#define CR_WEPKEY15 CTL_REG(0x075c)
|
||||
#define CR_TKIP_MODE CTL_REG(0x0760)
|
||||
|
||||
#define CR_EEPROM_PROTECT0 CTL_REG(0x0758)
|
||||
#define CR_EEPROM_PROTECT1 CTL_REG(0x075C)
|
||||
|
||||
#define CR_DBG_FIFO_RD CTL_REG(0x0800)
|
||||
#define CR_DBG_SELECT CTL_REG(0x0804)
|
||||
#define CR_FIFO_Length CTL_REG(0x0808)
|
||||
|
||||
|
||||
#define CR_RSSI_MGC CTL_REG(0x0810)
|
||||
|
||||
#define CR_PON CTL_REG(0x0818)
|
||||
#define CR_RX_ON CTL_REG(0x081C)
|
||||
#define CR_TX_ON CTL_REG(0x0820)
|
||||
#define CR_CHIP_EN CTL_REG(0x0824)
|
||||
#define CR_LO_SW CTL_REG(0x0828)
|
||||
#define CR_TXRX_SW CTL_REG(0x082C)
|
||||
#define CR_S_MD CTL_REG(0x0830)
|
||||
|
||||
#define CR_USB_DEBUG_PORT CTL_REG(0x0888)
|
||||
|
||||
#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00)
|
||||
#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04)
|
||||
#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08)
|
||||
#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c)
|
||||
#define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10)
|
||||
#define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14)
|
||||
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
|
||||
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
|
||||
|
||||
#define AP_RX_FILTER 0x0400feff
|
||||
#define STA_RX_FILTER 0x0000ffff
|
||||
|
||||
#define CWIN_SIZE 0x007f043f
|
||||
|
||||
|
||||
#define HWINT_ENABLED 0x004f0000
|
||||
#define HWINT_DISABLED 0
|
||||
|
||||
#define E2P_PWR_INT_GUARD 8
|
||||
#define E2P_CHANNEL_COUNT 14
|
||||
|
||||
/* If you compare this addresses with the ZYDAS orignal driver, please notify
|
||||
* that we use word mapping for the EEPROM.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Upper 16 bit contains the regulatory domain.
|
||||
*/
|
||||
#define E2P_SUBID E2P_REG(0x00)
|
||||
#define E2P_POD E2P_REG(0x02)
|
||||
#define E2P_MAC_ADDR_P1 E2P_REG(0x04)
|
||||
#define E2P_MAC_ADDR_P2 E2P_REG(0x06)
|
||||
#define E2P_PWR_CAL_VALUE1 E2P_REG(0x08)
|
||||
#define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a)
|
||||
#define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c)
|
||||
#define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e)
|
||||
#define E2P_PWR_INT_VALUE1 E2P_REG(0x10)
|
||||
#define E2P_PWR_INT_VALUE2 E2P_REG(0x12)
|
||||
#define E2P_PWR_INT_VALUE3 E2P_REG(0x14)
|
||||
#define E2P_PWR_INT_VALUE4 E2P_REG(0x16)
|
||||
|
||||
/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30)
|
||||
* also only 11 channels. */
|
||||
#define E2P_ALLOWED_CHANNEL E2P_REG(0x18)
|
||||
|
||||
#define E2P_PHY_REG E2P_REG(0x1a)
|
||||
#define E2P_DEVICE_VER E2P_REG(0x20)
|
||||
#define E2P_36M_CAL_VALUE1 E2P_REG(0x28)
|
||||
#define E2P_36M_CAL_VALUE2 E2P_REG(0x2a)
|
||||
#define E2P_36M_CAL_VALUE3 E2P_REG(0x2c)
|
||||
#define E2P_36M_CAL_VALUE4 E2P_REG(0x2e)
|
||||
#define E2P_11A_INT_VALUE1 E2P_REG(0x30)
|
||||
#define E2P_11A_INT_VALUE2 E2P_REG(0x32)
|
||||
#define E2P_11A_INT_VALUE3 E2P_REG(0x34)
|
||||
#define E2P_11A_INT_VALUE4 E2P_REG(0x36)
|
||||
#define E2P_48M_CAL_VALUE1 E2P_REG(0x38)
|
||||
#define E2P_48M_CAL_VALUE2 E2P_REG(0x3a)
|
||||
#define E2P_48M_CAL_VALUE3 E2P_REG(0x3c)
|
||||
#define E2P_48M_CAL_VALUE4 E2P_REG(0x3e)
|
||||
#define E2P_48M_INT_VALUE1 E2P_REG(0x40)
|
||||
#define E2P_48M_INT_VALUE2 E2P_REG(0x42)
|
||||
#define E2P_48M_INT_VALUE3 E2P_REG(0x44)
|
||||
#define E2P_48M_INT_VALUE4 E2P_REG(0x46)
|
||||
#define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */
|
||||
#define E2P_54M_CAL_VALUE2 E2P_REG(0x4a)
|
||||
#define E2P_54M_CAL_VALUE3 E2P_REG(0x4c)
|
||||
#define E2P_54M_CAL_VALUE4 E2P_REG(0x4e)
|
||||
#define E2P_54M_INT_VALUE1 E2P_REG(0x50)
|
||||
#define E2P_54M_INT_VALUE2 E2P_REG(0x52)
|
||||
#define E2P_54M_INT_VALUE3 E2P_REG(0x54)
|
||||
#define E2P_54M_INT_VALUE4 E2P_REG(0x56)
|
||||
|
||||
/* All 16 bit values */
|
||||
#define FW_FIRMWARE_VER FW_REG(0)
|
||||
/* non-zero if USB high speed connection */
|
||||
#define FW_USB_SPEED FW_REG(1)
|
||||
#define FW_FIX_TX_RATE FW_REG(2)
|
||||
/* Seems to be able to control LEDs over the firmware */
|
||||
#define FW_LINK_STATUS FW_REG(3)
|
||||
#define FW_SOFT_RESET FW_REG(4)
|
||||
#define FW_FLASH_CHK FW_REG(5)
|
||||
|
||||
enum {
|
||||
CR_BASE_OFFSET = 0x9000,
|
||||
FW_START_OFFSET = 0xee00,
|
||||
FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d,
|
||||
EEPROM_START_OFFSET = 0xf800,
|
||||
EEPROM_SIZE = 0x800, /* words */
|
||||
LOAD_CODE_SIZE = 0xe, /* words */
|
||||
LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */
|
||||
EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE,
|
||||
E2P_BASE_OFFSET = EEPROM_START_OFFSET +
|
||||
EEPROM_REGS_OFFSET,
|
||||
};
|
||||
|
||||
#define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d)
|
||||
|
||||
enum {
|
||||
/* indices for ofdm_cal_values */
|
||||
OFDM_36M_INDEX = 0,
|
||||
OFDM_48M_INDEX = 1,
|
||||
OFDM_54M_INDEX = 2,
|
||||
};
|
||||
|
||||
struct zd_chip {
|
||||
struct zd_usb usb;
|
||||
struct zd_rf rf;
|
||||
struct mutex mutex;
|
||||
u8 e2p_mac[ETH_ALEN];
|
||||
/* EepSetPoint in the vendor driver */
|
||||
u8 pwr_cal_values[E2P_CHANNEL_COUNT];
|
||||
/* integration values in the vendor driver */
|
||||
u8 pwr_int_values[E2P_CHANNEL_COUNT];
|
||||
/* SetPointOFDM in the vendor driver */
|
||||
u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
|
||||
u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
|
||||
is_zd1211b:1;
|
||||
};
|
||||
|
||||
static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
|
||||
{
|
||||
return container_of(usb, struct zd_chip, usb);
|
||||
}
|
||||
|
||||
static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
|
||||
{
|
||||
return container_of(rf, struct zd_chip, rf);
|
||||
}
|
||||
|
||||
#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
|
||||
|
||||
void zd_chip_init(struct zd_chip *chip,
|
||||
struct net_device *netdev,
|
||||
struct usb_interface *intf);
|
||||
void zd_chip_clear(struct zd_chip *chip);
|
||||
int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
|
||||
int zd_chip_reset(struct zd_chip *chip);
|
||||
|
||||
static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
|
||||
const zd_addr_t *addresses,
|
||||
unsigned int count)
|
||||
{
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
return zd_usb_ioread16v(&chip->usb, values, addresses, count);
|
||||
}
|
||||
|
||||
static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value,
|
||||
const zd_addr_t addr)
|
||||
{
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
return zd_usb_ioread16(&chip->usb, value, addr);
|
||||
}
|
||||
|
||||
int zd_ioread32v_locked(struct zd_chip *chip, u32 *values,
|
||||
const zd_addr_t *addresses, unsigned int count);
|
||||
|
||||
static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value,
|
||||
const zd_addr_t addr)
|
||||
{
|
||||
return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1);
|
||||
}
|
||||
|
||||
static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value,
|
||||
zd_addr_t addr)
|
||||
{
|
||||
struct zd_ioreq16 ioreq;
|
||||
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
ioreq.addr = addr;
|
||||
ioreq.value = value;
|
||||
|
||||
return zd_usb_iowrite16v(&chip->usb, &ioreq, 1);
|
||||
}
|
||||
|
||||
int zd_iowrite16a_locked(struct zd_chip *chip,
|
||||
const struct zd_ioreq16 *ioreqs, unsigned int count);
|
||||
|
||||
int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
|
||||
unsigned int count);
|
||||
|
||||
static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value,
|
||||
zd_addr_t addr)
|
||||
{
|
||||
struct zd_ioreq32 ioreq;
|
||||
|
||||
ioreq.addr = addr;
|
||||
ioreq.value = value;
|
||||
|
||||
return _zd_iowrite32v_locked(chip, &ioreq, 1);
|
||||
}
|
||||
|
||||
int zd_iowrite32a_locked(struct zd_chip *chip,
|
||||
const struct zd_ioreq32 *ioreqs, unsigned int count);
|
||||
|
||||
static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
|
||||
{
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
return zd_usb_rfwrite(&chip->usb, value, bits);
|
||||
}
|
||||
|
||||
int zd_rfwritev_locked(struct zd_chip *chip,
|
||||
const u32* values, unsigned int count, u8 bits);
|
||||
|
||||
/* Locking functions for reading and writing registers.
|
||||
* The different parameters are intentional.
|
||||
*/
|
||||
int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value);
|
||||
int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value);
|
||||
int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value);
|
||||
int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value);
|
||||
int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
|
||||
u32 *values, unsigned int count);
|
||||
int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
|
||||
unsigned int count);
|
||||
|
||||
int zd_chip_set_channel(struct zd_chip *chip, u8 channel);
|
||||
static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
|
||||
{
|
||||
return chip->rf.channel;
|
||||
}
|
||||
u8 zd_chip_get_channel(struct zd_chip *chip);
|
||||
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
|
||||
void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
|
||||
int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
|
||||
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
|
||||
int zd_chip_switch_radio_on(struct zd_chip *chip);
|
||||
int zd_chip_switch_radio_off(struct zd_chip *chip);
|
||||
int zd_chip_enable_int(struct zd_chip *chip);
|
||||
void zd_chip_disable_int(struct zd_chip *chip);
|
||||
int zd_chip_enable_rx(struct zd_chip *chip);
|
||||
void zd_chip_disable_rx(struct zd_chip *chip);
|
||||
int zd_chip_enable_hwint(struct zd_chip *chip);
|
||||
int zd_chip_disable_hwint(struct zd_chip *chip);
|
||||
|
||||
static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
|
||||
{
|
||||
return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
|
||||
}
|
||||
|
||||
static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type)
|
||||
{
|
||||
return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type);
|
||||
}
|
||||
|
||||
static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
|
||||
{
|
||||
return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
|
||||
}
|
||||
|
||||
int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
|
||||
|
||||
static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter)
|
||||
{
|
||||
return zd_iowrite32(chip, CR_RX_FILTER, filter);
|
||||
}
|
||||
|
||||
int zd_chip_lock_phy_regs(struct zd_chip *chip);
|
||||
int zd_chip_unlock_phy_regs(struct zd_chip *chip);
|
||||
|
||||
enum led_status {
|
||||
LED_OFF = 0,
|
||||
LED_ON = 1,
|
||||
LED_FLIP = 2,
|
||||
LED_STATUS = 3,
|
||||
};
|
||||
|
||||
int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
|
||||
int zd_chip_led_flip(struct zd_chip *chip, int led,
|
||||
const unsigned int *phases_msecs, unsigned int count);
|
||||
|
||||
int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
|
||||
|
||||
static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
|
||||
{
|
||||
return zd_ioread32(chip, CR_BCN_INTERVAL, interval);
|
||||
}
|
||||
|
||||
struct rx_status;
|
||||
|
||||
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
|
||||
const struct rx_status *status);
|
||||
u8 zd_rx_strength_percent(u8 rssi);
|
||||
|
||||
u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
|
||||
|
||||
#endif /* _ZD_CHIP_H */
|
48
drivers/net/wireless/zd1211rw/zd_def.h
Normal file
48
drivers/net/wireless/zd1211rw/zd_def.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* zd_def.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_DEF_H
|
||||
#define _ZD_DEF_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define dev_printk_f(level, dev, fmt, args...) \
|
||||
dev_printk(level, dev, "%s() " fmt, __func__, ##args)
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dev_dbg_f(dev, fmt, args...) \
|
||||
dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
|
||||
#else
|
||||
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef DEBUG
|
||||
# define ZD_ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
|
||||
__FILE__, __LINE__, __stringify(x)); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define ZD_ASSERT(x) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _ZD_DEF_H */
|
191
drivers/net/wireless/zd1211rw/zd_ieee80211.c
Normal file
191
drivers/net/wireless/zd1211rw/zd_ieee80211.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/* zd_ieee80211.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* A lot of this code is generic and should be moved into the upper layers
|
||||
* at some point.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#include "zd_def.h"
|
||||
#include "zd_ieee80211.h"
|
||||
#include "zd_mac.h"
|
||||
|
||||
static const struct channel_range channel_ranges[] = {
|
||||
[0] = { 0, 0},
|
||||
[ZD_REGDOMAIN_FCC] = { 1, 12},
|
||||
[ZD_REGDOMAIN_IC] = { 1, 12},
|
||||
[ZD_REGDOMAIN_ETSI] = { 1, 14},
|
||||
[ZD_REGDOMAIN_JAPAN] = { 1, 14},
|
||||
[ZD_REGDOMAIN_SPAIN] = { 1, 14},
|
||||
[ZD_REGDOMAIN_FRANCE] = { 1, 14},
|
||||
[ZD_REGDOMAIN_JAPAN_ADD] = {14, 15},
|
||||
};
|
||||
|
||||
const struct channel_range *zd_channel_range(u8 regdomain)
|
||||
{
|
||||
if (regdomain >= ARRAY_SIZE(channel_ranges))
|
||||
regdomain = 0;
|
||||
return &channel_ranges[regdomain];
|
||||
}
|
||||
|
||||
int zd_regdomain_supports_channel(u8 regdomain, u8 channel)
|
||||
{
|
||||
const struct channel_range *range = zd_channel_range(regdomain);
|
||||
return range->start <= channel && channel < range->end;
|
||||
}
|
||||
|
||||
int zd_regdomain_supported(u8 regdomain)
|
||||
{
|
||||
const struct channel_range *range = zd_channel_range(regdomain);
|
||||
return range->start != 0;
|
||||
}
|
||||
|
||||
/* Stores channel frequencies in MHz. */
|
||||
static const u16 channel_frequencies[] = {
|
||||
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
|
||||
2452, 2457, 2462, 2467, 2472, 2484,
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies)
|
||||
|
||||
static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz)
|
||||
{
|
||||
u32 factor;
|
||||
|
||||
freq->e = 0;
|
||||
if (mhz >= 1000000000U) {
|
||||
pr_debug("zd1211 mhz %u to large\n", mhz);
|
||||
freq->m = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
factor = 1000;
|
||||
while (mhz >= factor) {
|
||||
|
||||
freq->e += 1;
|
||||
factor *= 10;
|
||||
}
|
||||
|
||||
factor /= 1000U;
|
||||
freq->m = mhz * (1000000U/factor) + hz/factor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zd_channel_to_freq(struct iw_freq *freq, u8 channel)
|
||||
{
|
||||
if (channel > NUM_CHANNELS) {
|
||||
freq->m = 0;
|
||||
freq->e = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!channel) {
|
||||
freq->m = 0;
|
||||
freq->e = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
return compute_freq(freq, channel_frequencies[channel-1], 0);
|
||||
}
|
||||
|
||||
static int freq_to_mhz(const struct iw_freq *freq)
|
||||
{
|
||||
u32 factor;
|
||||
int e;
|
||||
|
||||
/* Such high frequencies are not supported. */
|
||||
if (freq->e > 6)
|
||||
return -EINVAL;
|
||||
|
||||
factor = 1;
|
||||
for (e = freq->e; e > 0; --e) {
|
||||
factor *= 10;
|
||||
}
|
||||
factor = 1000000U / factor;
|
||||
|
||||
if (freq->m % factor) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return freq->m / factor;
|
||||
}
|
||||
|
||||
int zd_find_channel(u8 *channel, const struct iw_freq *freq)
|
||||
{
|
||||
int i, r;
|
||||
u32 mhz;
|
||||
|
||||
if (!(freq->flags & IW_FREQ_FIXED))
|
||||
return 0;
|
||||
|
||||
if (freq->m < 1000) {
|
||||
if (freq->m > NUM_CHANNELS || freq->m == 0)
|
||||
return -EINVAL;
|
||||
*channel = freq->m;
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = freq_to_mhz(freq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
mhz = r;
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (mhz == channel_frequencies[i]) {
|
||||
*channel = i+1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
|
||||
{
|
||||
struct ieee80211_geo geo;
|
||||
const struct channel_range *range;
|
||||
int i;
|
||||
u8 channel;
|
||||
|
||||
dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
|
||||
"regdomain %#04x\n", regdomain);
|
||||
|
||||
range = zd_channel_range(regdomain);
|
||||
if (range->start == 0) {
|
||||
dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
|
||||
"zd1211 regdomain %#04x not supported\n",
|
||||
regdomain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&geo, 0, sizeof(geo));
|
||||
|
||||
for (i = 0, channel = range->start; channel < range->end; channel++) {
|
||||
struct ieee80211_channel *chan = &geo.bg[i++];
|
||||
chan->freq = channel_frequencies[channel - 1];
|
||||
chan->channel = channel;
|
||||
}
|
||||
|
||||
geo.bg_channels = i;
|
||||
memcpy(geo.name, "XX ", 4);
|
||||
ieee80211_set_geo(ieee, &geo);
|
||||
return 0;
|
||||
}
|
85
drivers/net/wireless/zd1211rw/zd_ieee80211.h
Normal file
85
drivers/net/wireless/zd1211rw/zd_ieee80211.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#ifndef _ZD_IEEE80211_H
|
||||
#define _ZD_IEEE80211_H
|
||||
|
||||
#include <net/ieee80211.h>
|
||||
#include "zd_types.h"
|
||||
|
||||
/* Additional definitions from the standards.
|
||||
*/
|
||||
|
||||
#define ZD_REGDOMAIN_FCC 0x10
|
||||
#define ZD_REGDOMAIN_IC 0x20
|
||||
#define ZD_REGDOMAIN_ETSI 0x30
|
||||
#define ZD_REGDOMAIN_SPAIN 0x31
|
||||
#define ZD_REGDOMAIN_FRANCE 0x32
|
||||
#define ZD_REGDOMAIN_JAPAN_ADD 0x40
|
||||
#define ZD_REGDOMAIN_JAPAN 0x41
|
||||
|
||||
enum {
|
||||
MIN_CHANNEL24 = 1,
|
||||
MAX_CHANNEL24 = 14,
|
||||
};
|
||||
|
||||
struct channel_range {
|
||||
u8 start;
|
||||
u8 end; /* exclusive (channel must be less than end) */
|
||||
};
|
||||
|
||||
struct iw_freq;
|
||||
|
||||
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain);
|
||||
|
||||
const struct channel_range *zd_channel_range(u8 regdomain);
|
||||
int zd_regdomain_supports_channel(u8 regdomain, u8 channel);
|
||||
int zd_regdomain_supported(u8 regdomain);
|
||||
|
||||
/* for 2.4 GHz band */
|
||||
int zd_channel_to_freq(struct iw_freq *freq, u8 channel);
|
||||
int zd_find_channel(u8 *channel, const struct iw_freq *freq);
|
||||
|
||||
#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
|
||||
|
||||
struct ofdm_plcp_header {
|
||||
u8 prefix[3];
|
||||
__le16 service;
|
||||
} __attribute__((packed));
|
||||
|
||||
static inline u8 zd_ofdm_plcp_header_rate(
|
||||
const struct ofdm_plcp_header *header)
|
||||
{
|
||||
return header->prefix[0] & 0xf;
|
||||
}
|
||||
|
||||
#define ZD_OFDM_RATE_6M 0xb
|
||||
#define ZD_OFDM_RATE_9M 0xf
|
||||
#define ZD_OFDM_RATE_12M 0xa
|
||||
#define ZD_OFDM_RATE_18M 0xe
|
||||
#define ZD_OFDM_RATE_24M 0x9
|
||||
#define ZD_OFDM_RATE_36M 0xd
|
||||
#define ZD_OFDM_RATE_48M 0x8
|
||||
#define ZD_OFDM_RATE_54M 0xc
|
||||
|
||||
struct cck_plcp_header {
|
||||
u8 signal;
|
||||
u8 service;
|
||||
__le16 length;
|
||||
__le16 crc16;
|
||||
} __attribute__((packed));
|
||||
|
||||
static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header)
|
||||
{
|
||||
return header->signal;
|
||||
}
|
||||
|
||||
#define ZD_CCK_SIGNAL_1M 0x0a
|
||||
#define ZD_CCK_SIGNAL_2M 0x14
|
||||
#define ZD_CCK_SIGNAL_5M5 0x37
|
||||
#define ZD_CCK_SIGNAL_11M 0x6e
|
||||
|
||||
enum ieee80211_std {
|
||||
IEEE80211B = 0x01,
|
||||
IEEE80211A = 0x02,
|
||||
IEEE80211G = 0x04,
|
||||
};
|
||||
|
||||
#endif /* _ZD_IEEE80211_H */
|
1057
drivers/net/wireless/zd1211rw/zd_mac.c
Normal file
1057
drivers/net/wireless/zd1211rw/zd_mac.c
Normal file
File diff suppressed because it is too large
Load diff
190
drivers/net/wireless/zd1211rw/zd_mac.h
Normal file
190
drivers/net/wireless/zd1211rw/zd_mac.h
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* zd_mac.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_MAC_H
|
||||
#define _ZD_MAC_H
|
||||
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <net/ieee80211.h>
|
||||
#include <net/ieee80211softmac.h>
|
||||
|
||||
#include "zd_chip.h"
|
||||
#include "zd_netdev.h"
|
||||
|
||||
struct zd_ctrlset {
|
||||
u8 modulation;
|
||||
__le16 tx_length;
|
||||
u8 control;
|
||||
/* stores only the difference to tx_length on ZD1211B */
|
||||
__le16 packet_length;
|
||||
__le16 current_length;
|
||||
u8 service;
|
||||
__le16 next_frame_length;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ZD_CS_RESERVED_SIZE 25
|
||||
|
||||
/* zd_crtlset field modulation */
|
||||
#define ZD_CS_RATE_MASK 0x0f
|
||||
#define ZD_CS_TYPE_MASK 0x10
|
||||
#define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK)
|
||||
#define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK)
|
||||
|
||||
#define ZD_CS_CCK 0x00
|
||||
#define ZD_CS_OFDM 0x10
|
||||
|
||||
#define ZD_CS_CCK_RATE_1M 0x00
|
||||
#define ZD_CS_CCK_RATE_2M 0x01
|
||||
#define ZD_CS_CCK_RATE_5_5M 0x02
|
||||
#define ZD_CS_CCK_RATE_11M 0x03
|
||||
/* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*.
|
||||
*/
|
||||
|
||||
/* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */
|
||||
#define ZD_CS_CCK_PREA_LONG 0x00
|
||||
#define ZD_CS_CCK_PREA_SHORT 0x20
|
||||
#define ZD_CS_OFDM_MODE_11G 0x00
|
||||
#define ZD_CS_OFDM_MODE_11A 0x20
|
||||
|
||||
/* zd_ctrlset control field */
|
||||
#define ZD_CS_NEED_RANDOM_BACKOFF 0x01
|
||||
#define ZD_CS_MULTICAST 0x02
|
||||
|
||||
#define ZD_CS_FRAME_TYPE_MASK 0x0c
|
||||
#define ZD_CS_DATA_FRAME 0x00
|
||||
#define ZD_CS_PS_POLL_FRAME 0x04
|
||||
#define ZD_CS_MANAGEMENT_FRAME 0x08
|
||||
#define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c
|
||||
|
||||
#define ZD_CS_WAKE_DESTINATION 0x10
|
||||
#define ZD_CS_RTS 0x20
|
||||
#define ZD_CS_ENCRYPT 0x40
|
||||
#define ZD_CS_SELF_CTS 0x80
|
||||
|
||||
/* Incoming frames are prepended by a PLCP header */
|
||||
#define ZD_PLCP_HEADER_SIZE 5
|
||||
|
||||
struct rx_length_info {
|
||||
__le16 length[3];
|
||||
__le16 tag;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define RX_LENGTH_INFO_TAG 0x697e
|
||||
|
||||
struct rx_status {
|
||||
/* rssi */
|
||||
u8 signal_strength;
|
||||
u8 signal_quality_cck;
|
||||
u8 signal_quality_ofdm;
|
||||
u8 decryption_type;
|
||||
u8 frame_status;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* rx_status field decryption_type */
|
||||
#define ZD_RX_NO_WEP 0
|
||||
#define ZD_RX_WEP64 1
|
||||
#define ZD_RX_TKIP 2
|
||||
#define ZD_RX_AES 4
|
||||
#define ZD_RX_WEP128 5
|
||||
#define ZD_RX_WEP256 6
|
||||
|
||||
/* rx_status field frame_status */
|
||||
#define ZD_RX_FRAME_MODULATION_MASK 0x01
|
||||
#define ZD_RX_CCK 0x00
|
||||
#define ZD_RX_OFDM 0x01
|
||||
|
||||
#define ZD_RX_TIMEOUT_ERROR 0x02
|
||||
#define ZD_RX_FIFO_OVERRUN_ERROR 0x04
|
||||
#define ZD_RX_DECRYPTION_ERROR 0x08
|
||||
#define ZD_RX_CRC32_ERROR 0x10
|
||||
#define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20
|
||||
#define ZD_RX_CRC16_ERROR 0x40
|
||||
#define ZD_RX_ERROR 0x80
|
||||
|
||||
enum mac_flags {
|
||||
MAC_FIXED_CHANNEL = 0x01,
|
||||
};
|
||||
|
||||
struct zd_mac {
|
||||
struct net_device *netdev;
|
||||
struct zd_chip chip;
|
||||
spinlock_t lock;
|
||||
/* Unlocked reading possible */
|
||||
struct iw_statistics iw_stats;
|
||||
u8 qual_average;
|
||||
u8 rssi_average;
|
||||
u8 regdomain;
|
||||
u8 default_regdomain;
|
||||
u8 requested_channel;
|
||||
};
|
||||
|
||||
static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac)
|
||||
{
|
||||
return zd_netdev_ieee80211(mac->netdev);
|
||||
}
|
||||
|
||||
static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev)
|
||||
{
|
||||
return ieee80211softmac_priv(netdev);
|
||||
}
|
||||
|
||||
static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
|
||||
{
|
||||
return container_of(chip, struct zd_mac, chip);
|
||||
}
|
||||
|
||||
static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
|
||||
{
|
||||
return zd_chip_to_mac(zd_usb_to_chip(usb));
|
||||
}
|
||||
|
||||
#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
|
||||
|
||||
int zd_mac_init(struct zd_mac *mac,
|
||||
struct net_device *netdev,
|
||||
struct usb_interface *intf);
|
||||
void zd_mac_clear(struct zd_mac *mac);
|
||||
|
||||
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
|
||||
|
||||
int zd_mac_open(struct net_device *netdev);
|
||||
int zd_mac_stop(struct net_device *netdev);
|
||||
int zd_mac_set_mac_address(struct net_device *dev, void *p);
|
||||
|
||||
int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
|
||||
|
||||
int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
|
||||
u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
|
||||
|
||||
int zd_mac_request_channel(struct zd_mac *mac, u8 channel);
|
||||
int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags);
|
||||
|
||||
int zd_mac_set_mode(struct zd_mac *mac, u32 mode);
|
||||
int zd_mac_get_mode(struct zd_mac *mac, u32 *mode);
|
||||
|
||||
int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range);
|
||||
|
||||
struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev);
|
||||
|
||||
#ifdef DEBUG
|
||||
void zd_dump_rx_status(const struct rx_status *status);
|
||||
#else
|
||||
#define zd_dump_rx_status(status)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* _ZD_MAC_H */
|
267
drivers/net/wireless/zd1211rw/zd_netdev.c
Normal file
267
drivers/net/wireless/zd1211rw/zd_netdev.c
Normal file
|
@ -0,0 +1,267 @@
|
|||
/* zd_netdev.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/ieee80211.h>
|
||||
#include <net/ieee80211softmac.h>
|
||||
#include <net/ieee80211softmac_wx.h>
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
#include "zd_def.h"
|
||||
#include "zd_netdev.h"
|
||||
#include "zd_mac.h"
|
||||
#include "zd_ieee80211.h"
|
||||
|
||||
/* Region 0 means reset regdomain to default. */
|
||||
static int zd_set_regdomain(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
const u8 *regdomain = (u8 *)req;
|
||||
return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
|
||||
}
|
||||
|
||||
static int zd_get_regdomain(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
u8 *regdomain = (u8 *)req;
|
||||
if (!regdomain)
|
||||
return -EINVAL;
|
||||
*regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iw_priv_args zd_priv_args[] = {
|
||||
{
|
||||
.cmd = ZD_PRIV_SET_REGDOMAIN,
|
||||
.set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
|
||||
.name = "set_regdomain",
|
||||
},
|
||||
{
|
||||
.cmd = ZD_PRIV_GET_REGDOMAIN,
|
||||
.get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
|
||||
.name = "get_regdomain",
|
||||
},
|
||||
};
|
||||
|
||||
#define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
|
||||
|
||||
static const iw_handler zd_priv_handler[] = {
|
||||
PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
|
||||
PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
|
||||
};
|
||||
|
||||
static int iw_get_name(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
/* FIXME: check whether 802.11a will also supported, add also
|
||||
* zd1211B, if we support it.
|
||||
*/
|
||||
strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iw_set_freq(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
int r;
|
||||
struct zd_mac *mac = zd_netdev_mac(netdev);
|
||||
struct iw_freq *freq = &req->freq;
|
||||
u8 channel;
|
||||
|
||||
r = zd_find_channel(&channel, freq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = zd_mac_request_channel(mac, channel);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int iw_get_freq(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
int r;
|
||||
struct zd_mac *mac = zd_netdev_mac(netdev);
|
||||
struct iw_freq *freq = &req->freq;
|
||||
u8 channel;
|
||||
u8 flags;
|
||||
|
||||
r = zd_mac_get_channel(mac, &channel, &flags);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
freq->flags = (flags & MAC_FIXED_CHANNEL) ?
|
||||
IW_FREQ_FIXED : IW_FREQ_AUTO;
|
||||
dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
|
||||
(flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
|
||||
return zd_channel_to_freq(freq, channel);
|
||||
}
|
||||
|
||||
static int iw_set_mode(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
|
||||
}
|
||||
|
||||
static int iw_get_mode(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
|
||||
}
|
||||
|
||||
static int iw_get_range(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *req, char *extra)
|
||||
{
|
||||
struct iw_range *range = (struct iw_range *)extra;
|
||||
|
||||
dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
|
||||
req->data.length = sizeof(*range);
|
||||
return zd_mac_get_range(zd_netdev_mac(netdev), range);
|
||||
}
|
||||
|
||||
static int iw_set_encode(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *data,
|
||||
char *extra)
|
||||
{
|
||||
return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
|
||||
data, extra);
|
||||
}
|
||||
|
||||
static int iw_get_encode(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *data,
|
||||
char *extra)
|
||||
{
|
||||
return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
|
||||
data, extra);
|
||||
}
|
||||
|
||||
static int iw_set_encodeext(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *data,
|
||||
char *extra)
|
||||
{
|
||||
return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
|
||||
data, extra);
|
||||
}
|
||||
|
||||
static int iw_get_encodeext(struct net_device *netdev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *data,
|
||||
char *extra)
|
||||
{
|
||||
return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
|
||||
data, extra);
|
||||
}
|
||||
|
||||
#define WX(x) [(x)-SIOCIWFIRST]
|
||||
|
||||
static const iw_handler zd_standard_iw_handlers[] = {
|
||||
WX(SIOCGIWNAME) = iw_get_name,
|
||||
WX(SIOCSIWFREQ) = iw_set_freq,
|
||||
WX(SIOCGIWFREQ) = iw_get_freq,
|
||||
WX(SIOCSIWMODE) = iw_set_mode,
|
||||
WX(SIOCGIWMODE) = iw_get_mode,
|
||||
WX(SIOCGIWRANGE) = iw_get_range,
|
||||
WX(SIOCSIWENCODE) = iw_set_encode,
|
||||
WX(SIOCGIWENCODE) = iw_get_encode,
|
||||
WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
|
||||
WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
|
||||
WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
|
||||
WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
|
||||
WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
|
||||
WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
|
||||
WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
|
||||
WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
|
||||
WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
|
||||
WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
|
||||
WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
|
||||
WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
|
||||
WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
|
||||
WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
|
||||
WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
|
||||
};
|
||||
|
||||
static const struct iw_handler_def iw_handler_def = {
|
||||
.standard = zd_standard_iw_handlers,
|
||||
.num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
|
||||
.private = zd_priv_handler,
|
||||
.num_private = ARRAY_SIZE(zd_priv_handler),
|
||||
.private_args = zd_priv_args,
|
||||
.num_private_args = ARRAY_SIZE(zd_priv_args),
|
||||
.get_wireless_stats = zd_mac_get_wireless_stats,
|
||||
};
|
||||
|
||||
struct net_device *zd_netdev_alloc(struct usb_interface *intf)
|
||||
{
|
||||
int r;
|
||||
struct net_device *netdev;
|
||||
struct zd_mac *mac;
|
||||
|
||||
netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
|
||||
if (!netdev) {
|
||||
dev_dbg_f(&intf->dev, "out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mac = zd_netdev_mac(netdev);
|
||||
r = zd_mac_init(mac, netdev, intf);
|
||||
if (r) {
|
||||
usb_set_intfdata(intf, NULL);
|
||||
free_ieee80211(netdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SET_MODULE_OWNER(netdev);
|
||||
SET_NETDEV_DEV(netdev, &intf->dev);
|
||||
|
||||
dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
|
||||
dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
|
||||
|
||||
netdev->open = zd_mac_open;
|
||||
netdev->stop = zd_mac_stop;
|
||||
/* netdev->get_stats = */
|
||||
/* netdev->set_multicast_list = */
|
||||
netdev->set_mac_address = zd_mac_set_mac_address;
|
||||
netdev->wireless_handlers = &iw_handler_def;
|
||||
/* netdev->ethtool_ops = */
|
||||
|
||||
return netdev;
|
||||
}
|
||||
|
||||
void zd_netdev_free(struct net_device *netdev)
|
||||
{
|
||||
if (!netdev)
|
||||
return;
|
||||
|
||||
zd_mac_clear(zd_netdev_mac(netdev));
|
||||
free_ieee80211(netdev);
|
||||
}
|
||||
|
||||
void zd_netdev_disconnect(struct net_device *netdev)
|
||||
{
|
||||
unregister_netdev(netdev);
|
||||
}
|
45
drivers/net/wireless/zd1211rw/zd_netdev.h
Normal file
45
drivers/net/wireless/zd1211rw/zd_netdev.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* zd_netdev.h: Header for net device related functions.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_NETDEV_H
|
||||
#define _ZD_NETDEV_H
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
||||
#define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV)
|
||||
#define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1)
|
||||
|
||||
static inline struct ieee80211_device *zd_netdev_ieee80211(
|
||||
struct net_device *ndev)
|
||||
{
|
||||
return netdev_priv(ndev);
|
||||
}
|
||||
|
||||
static inline struct net_device *zd_ieee80211_to_netdev(
|
||||
struct ieee80211_device *ieee)
|
||||
{
|
||||
return ieee->dev;
|
||||
}
|
||||
|
||||
struct net_device *zd_netdev_alloc(struct usb_interface *intf);
|
||||
void zd_netdev_free(struct net_device *netdev);
|
||||
|
||||
void zd_netdev_disconnect(struct net_device *netdev);
|
||||
|
||||
#endif /* _ZD_NETDEV_H */
|
151
drivers/net/wireless/zd1211rw/zd_rf.c
Normal file
151
drivers/net/wireless/zd1211rw/zd_rf.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* zd_rf.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "zd_def.h"
|
||||
#include "zd_rf.h"
|
||||
#include "zd_ieee80211.h"
|
||||
#include "zd_chip.h"
|
||||
|
||||
static const char *rfs[] = {
|
||||
[0] = "unknown RF0",
|
||||
[1] = "unknown RF1",
|
||||
[UW2451_RF] = "UW2451_RF",
|
||||
[UCHIP_RF] = "UCHIP_RF",
|
||||
[AL2230_RF] = "AL2230_RF",
|
||||
[AL7230B_RF] = "AL7230B_RF",
|
||||
[THETA_RF] = "THETA_RF",
|
||||
[AL2210_RF] = "AL2210_RF",
|
||||
[MAXIM_NEW_RF] = "MAXIM_NEW_RF",
|
||||
[UW2453_RF] = "UW2453_RF",
|
||||
[AL2230S_RF] = "AL2230S_RF",
|
||||
[RALINK_RF] = "RALINK_RF",
|
||||
[INTERSIL_RF] = "INTERSIL_RF",
|
||||
[RF2959_RF] = "RF2959_RF",
|
||||
[MAXIM_NEW2_RF] = "MAXIM_NEW2_RF",
|
||||
[PHILIPS_RF] = "PHILIPS_RF",
|
||||
};
|
||||
|
||||
const char *zd_rf_name(u8 type)
|
||||
{
|
||||
if (type & 0xf0)
|
||||
type = 0;
|
||||
return rfs[type];
|
||||
}
|
||||
|
||||
void zd_rf_init(struct zd_rf *rf)
|
||||
{
|
||||
memset(rf, 0, sizeof(*rf));
|
||||
}
|
||||
|
||||
void zd_rf_clear(struct zd_rf *rf)
|
||||
{
|
||||
memset(rf, 0, sizeof(*rf));
|
||||
}
|
||||
|
||||
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
|
||||
{
|
||||
int r, t;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
switch (type) {
|
||||
case RF2959_RF:
|
||||
r = zd_rf_init_rf2959(rf);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
case AL2230_RF:
|
||||
r = zd_rf_init_al2230(rf);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
default:
|
||||
dev_err(zd_chip_dev(chip),
|
||||
"RF %s %#x is not supported\n", zd_rf_name(type), type);
|
||||
rf->type = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rf->type = type;
|
||||
|
||||
r = zd_chip_lock_phy_regs(chip);
|
||||
if (r)
|
||||
return r;
|
||||
t = rf->init_hw(rf);
|
||||
r = zd_chip_unlock_phy_regs(chip);
|
||||
if (t)
|
||||
r = t;
|
||||
return r;
|
||||
}
|
||||
|
||||
int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size)
|
||||
{
|
||||
return scnprintf(buffer, size, "%s", zd_rf_name(rf->type));
|
||||
}
|
||||
|
||||
int zd_rf_set_channel(struct zd_rf *rf, u8 channel)
|
||||
{
|
||||
int r;
|
||||
|
||||
ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex));
|
||||
if (channel < MIN_CHANNEL24)
|
||||
return -EINVAL;
|
||||
if (channel > MAX_CHANNEL24)
|
||||
return -EINVAL;
|
||||
dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel);
|
||||
|
||||
r = rf->set_channel(rf, channel);
|
||||
if (r >= 0)
|
||||
rf->channel = channel;
|
||||
return r;
|
||||
}
|
||||
|
||||
int zd_switch_radio_on(struct zd_rf *rf)
|
||||
{
|
||||
int r, t;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
r = zd_chip_lock_phy_regs(chip);
|
||||
if (r)
|
||||
return r;
|
||||
t = rf->switch_radio_on(rf);
|
||||
r = zd_chip_unlock_phy_regs(chip);
|
||||
if (t)
|
||||
r = t;
|
||||
return r;
|
||||
}
|
||||
|
||||
int zd_switch_radio_off(struct zd_rf *rf)
|
||||
{
|
||||
int r, t;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
/* TODO: move phy regs handling to zd_chip */
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
r = zd_chip_lock_phy_regs(chip);
|
||||
if (r)
|
||||
return r;
|
||||
t = rf->switch_radio_off(rf);
|
||||
r = zd_chip_unlock_phy_regs(chip);
|
||||
if (t)
|
||||
r = t;
|
||||
return r;
|
||||
}
|
82
drivers/net/wireless/zd1211rw/zd_rf.h
Normal file
82
drivers/net/wireless/zd1211rw/zd_rf.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* zd_rf.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_RF_H
|
||||
#define _ZD_RF_H
|
||||
|
||||
#include "zd_types.h"
|
||||
|
||||
#define UW2451_RF 0x2
|
||||
#define UCHIP_RF 0x3
|
||||
#define AL2230_RF 0x4
|
||||
#define AL7230B_RF 0x5 /* a,b,g */
|
||||
#define THETA_RF 0x6
|
||||
#define AL2210_RF 0x7
|
||||
#define MAXIM_NEW_RF 0x8
|
||||
#define UW2453_RF 0x9
|
||||
#define AL2230S_RF 0xa
|
||||
#define RALINK_RF 0xb
|
||||
#define INTERSIL_RF 0xc
|
||||
#define RF2959_RF 0xd
|
||||
#define MAXIM_NEW2_RF 0xe
|
||||
#define PHILIPS_RF 0xf
|
||||
|
||||
#define RF_CHANNEL(ch) [(ch)-1]
|
||||
|
||||
/* Provides functions of the RF transceiver. */
|
||||
|
||||
enum {
|
||||
RF_REG_BITS = 6,
|
||||
RF_VALUE_BITS = 18,
|
||||
RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS,
|
||||
};
|
||||
|
||||
struct zd_rf {
|
||||
u8 type;
|
||||
|
||||
u8 channel;
|
||||
/*
|
||||
* Whether this RF should patch the 6M band edge
|
||||
* (assuming E2P_POD agrees)
|
||||
*/
|
||||
u8 patch_6m_band_edge:1;
|
||||
|
||||
/* RF-specific functions */
|
||||
int (*init_hw)(struct zd_rf *rf);
|
||||
int (*set_channel)(struct zd_rf *rf, u8 channel);
|
||||
int (*switch_radio_on)(struct zd_rf *rf);
|
||||
int (*switch_radio_off)(struct zd_rf *rf);
|
||||
};
|
||||
|
||||
const char *zd_rf_name(u8 type);
|
||||
void zd_rf_init(struct zd_rf *rf);
|
||||
void zd_rf_clear(struct zd_rf *rf);
|
||||
int zd_rf_init_hw(struct zd_rf *rf, u8 type);
|
||||
|
||||
int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size);
|
||||
|
||||
int zd_rf_set_channel(struct zd_rf *rf, u8 channel);
|
||||
|
||||
int zd_switch_radio_on(struct zd_rf *rf);
|
||||
int zd_switch_radio_off(struct zd_rf *rf);
|
||||
|
||||
/* Functions for individual RF chips */
|
||||
|
||||
int zd_rf_init_rf2959(struct zd_rf *rf);
|
||||
int zd_rf_init_al2230(struct zd_rf *rf);
|
||||
|
||||
#endif /* _ZD_RF_H */
|
308
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
Normal file
308
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
/* zd_rf_al2230.c: Functions for the AL2230 RF controller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "zd_rf.h"
|
||||
#include "zd_usb.h"
|
||||
#include "zd_chip.h"
|
||||
|
||||
static const u32 al2230_table[][3] = {
|
||||
RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
|
||||
RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
|
||||
};
|
||||
|
||||
static int zd1211_al2230_init_hw(struct zd_rf *rf)
|
||||
{
|
||||
int r;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 },
|
||||
{ CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 },
|
||||
{ CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a },
|
||||
{ CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b },
|
||||
{ CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 },
|
||||
/* for newest (3rd cut) AL2300 */
|
||||
{ CR17, 0x28 },
|
||||
{ CR26, 0x93 }, { CR34, 0x30 },
|
||||
/* for newest (3rd cut) AL2300 */
|
||||
{ CR35, 0x3e },
|
||||
{ CR41, 0x24 }, { CR44, 0x32 },
|
||||
/* for newest (3rd cut) AL2300 */
|
||||
{ CR46, 0x96 },
|
||||
{ CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 },
|
||||
{ CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
|
||||
{ CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 },
|
||||
{ CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 },
|
||||
{ CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 },
|
||||
{ CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 },
|
||||
{ CR114, 0x27 },
|
||||
/* for newest (3rd cut) AL2300 */
|
||||
{ CR115, 0x24 },
|
||||
{ CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc },
|
||||
{ CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 },
|
||||
{ CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff },
|
||||
{ CR253, 0xff },
|
||||
|
||||
/* These following happen separately in the vendor driver */
|
||||
{ },
|
||||
|
||||
/* shdnb(PLL_ON)=0 */
|
||||
{ CR251, 0x2f },
|
||||
/* shdnb(PLL_ON)=1 */
|
||||
{ CR251, 0x3f },
|
||||
{ CR138, 0x28 }, { CR203, 0x06 },
|
||||
};
|
||||
|
||||
static const u32 rv[] = {
|
||||
/* Channel 1 */
|
||||
0x03f790,
|
||||
0x033331,
|
||||
0x00000d,
|
||||
|
||||
0x0b3331,
|
||||
0x03b812,
|
||||
0x00fff3,
|
||||
0x000da4,
|
||||
0x0f4dc5, /* fix freq shift, 0x04edc5 */
|
||||
0x0805b6,
|
||||
0x011687,
|
||||
0x000688,
|
||||
0x0403b9, /* external control TX power (CR31) */
|
||||
0x00dbba,
|
||||
0x00099b,
|
||||
0x0bdffc,
|
||||
0x00000d,
|
||||
0x00500f,
|
||||
|
||||
/* These writes happen separately in the vendor driver */
|
||||
0x00d00f,
|
||||
0x004c0f,
|
||||
0x00540f,
|
||||
0x00700f,
|
||||
0x00500f,
|
||||
};
|
||||
|
||||
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zd1211b_al2230_init_hw(struct zd_rf *rf)
|
||||
{
|
||||
int r;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
static const struct zd_ioreq16 ioreqs1[] = {
|
||||
{ CR10, 0x89 }, { CR15, 0x20 },
|
||||
{ CR17, 0x2B }, /* for newest(3rd cut) AL2230 */
|
||||
{ CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 },
|
||||
{ CR28, 0x3e }, { CR29, 0x00 },
|
||||
{ CR33, 0x28 }, /* 5621 */
|
||||
{ CR34, 0x30 },
|
||||
{ CR35, 0x3e }, /* for newest(3rd cut) AL2230 */
|
||||
{ CR41, 0x24 }, { CR44, 0x32 },
|
||||
{ CR46, 0x99 }, /* for newest(3rd cut) AL2230 */
|
||||
{ CR47, 0x1e },
|
||||
|
||||
/* ZD1211B 05.06.10 */
|
||||
{ CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 },
|
||||
{ CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 },
|
||||
{ CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 },
|
||||
{ CR69, 0x28 },
|
||||
|
||||
{ CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 },
|
||||
{ CR87, 0x0a }, { CR89, 0x04 },
|
||||
{ CR91, 0x00 }, /* 5621 */
|
||||
{ CR92, 0x0a },
|
||||
{ CR98, 0x8d }, /* 4804, for 1212 new algorithm */
|
||||
{ CR99, 0x00 }, /* 5621 */
|
||||
{ CR101, 0x13 }, { CR102, 0x27 },
|
||||
{ CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
|
||||
{ CR107, 0x2a },
|
||||
{ CR109, 0x13 }, /* 4804, for 1212 new algorithm */
|
||||
{ CR110, 0x1f }, /* 4804, for 1212 new algorithm */
|
||||
{ CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 },
|
||||
{ CR114, 0x27 },
|
||||
{ CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */
|
||||
{ CR116, 0x24 },
|
||||
{ CR117, 0xfa }, /* for 1211b */
|
||||
{ CR118, 0xfa }, /* for 1211b */
|
||||
{ CR119, 0x10 },
|
||||
{ CR120, 0x4f },
|
||||
{ CR121, 0x6c }, /* for 1211b */
|
||||
{ CR122, 0xfc }, /* E0->FC at 4902 */
|
||||
{ CR123, 0x57 }, /* 5623 */
|
||||
{ CR125, 0xad }, /* 4804, for 1212 new algorithm */
|
||||
{ CR126, 0x6c }, /* 5614 */
|
||||
{ CR127, 0x03 }, /* 4804, for 1212 new algorithm */
|
||||
{ CR137, 0x50 }, /* 5614 */
|
||||
{ CR138, 0xa8 },
|
||||
{ CR144, 0xac }, /* 5621 */
|
||||
{ CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 },
|
||||
};
|
||||
|
||||
static const u32 rv1[] = {
|
||||
/* channel 1 */
|
||||
0x03f790,
|
||||
0x033331,
|
||||
0x00000d,
|
||||
|
||||
0x0b3331,
|
||||
0x03b812,
|
||||
0x00fff3,
|
||||
0x0005a4,
|
||||
0x0f4dc5, /* fix freq shift 0x044dc5 */
|
||||
0x0805b6,
|
||||
0x0146c7,
|
||||
0x000688,
|
||||
0x0403b9, /* External control TX power (CR31) */
|
||||
0x00dbba,
|
||||
0x00099b,
|
||||
0x0bdffc,
|
||||
0x00000d,
|
||||
0x00580f,
|
||||
};
|
||||
|
||||
static const struct zd_ioreq16 ioreqs2[] = {
|
||||
{ CR47, 0x1e }, { CR_RFCFG, 0x03 },
|
||||
};
|
||||
|
||||
static const u32 rv2[] = {
|
||||
0x00880f,
|
||||
0x00080f,
|
||||
};
|
||||
|
||||
static const struct zd_ioreq16 ioreqs3[] = {
|
||||
{ CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f },
|
||||
};
|
||||
|
||||
static const u32 rv3[] = {
|
||||
0x00d80f,
|
||||
0x00780f,
|
||||
0x00580f,
|
||||
};
|
||||
|
||||
static const struct zd_ioreq16 ioreqs4[] = {
|
||||
{ CR138, 0x28 }, { CR203, 0x06 },
|
||||
};
|
||||
|
||||
r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4));
|
||||
}
|
||||
|
||||
static int al2230_set_channel(struct zd_rf *rf, u8 channel)
|
||||
{
|
||||
int r;
|
||||
const u32 *rv = al2230_table[channel-1];
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR138, 0x28 },
|
||||
{ CR203, 0x06 },
|
||||
};
|
||||
|
||||
r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR11, 0x00 },
|
||||
{ CR251, 0x3f },
|
||||
};
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR11, 0x00 },
|
||||
{ CR251, 0x7f },
|
||||
};
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
static int al2230_switch_radio_off(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR11, 0x04 },
|
||||
{ CR251, 0x2f },
|
||||
};
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
int zd_rf_init_al2230(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
rf->set_channel = al2230_set_channel;
|
||||
rf->switch_radio_off = al2230_switch_radio_off;
|
||||
if (chip->is_zd1211b) {
|
||||
rf->init_hw = zd1211b_al2230_init_hw;
|
||||
rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
|
||||
} else {
|
||||
rf->init_hw = zd1211_al2230_init_hw;
|
||||
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
|
||||
}
|
||||
rf->patch_6m_band_edge = 1;
|
||||
return 0;
|
||||
}
|
279
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Normal file
279
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
/* zd_rf_rfmd.c: Functions for the RFMD RF controller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "zd_rf.h"
|
||||
#include "zd_usb.h"
|
||||
#include "zd_chip.h"
|
||||
|
||||
static u32 rf2959_table[][2] = {
|
||||
RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
|
||||
RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
|
||||
RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
|
||||
RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 },
|
||||
RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 },
|
||||
RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 },
|
||||
RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 },
|
||||
RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 },
|
||||
RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 },
|
||||
RF_CHANNEL(10) = { 0x181a09, 0x1e6666 },
|
||||
RF_CHANNEL(11) = { 0x181a19, 0x1e6666 },
|
||||
RF_CHANNEL(12) = { 0x181a29, 0x1e6666 },
|
||||
RF_CHANNEL(13) = { 0x181a39, 0x1e6666 },
|
||||
RF_CHANNEL(14) = { 0x181a60, 0x1c0000 },
|
||||
};
|
||||
|
||||
#if 0
|
||||
static int bits(u32 rw, int from, int to)
|
||||
{
|
||||
rw &= ~(0xffffffffU << (to+1));
|
||||
rw >>= from;
|
||||
return rw;
|
||||
}
|
||||
|
||||
static int bit(u32 rw, int bit)
|
||||
{
|
||||
return bits(rw, bit, bit);
|
||||
}
|
||||
|
||||
static void dump_regwrite(u32 rw)
|
||||
{
|
||||
int reg = bits(rw, 18, 22);
|
||||
int rw_flag = bits(rw, 23, 23);
|
||||
PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d"
|
||||
" if_vco_reg_en %d if_vga_en %d",
|
||||
bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1),
|
||||
bit(rw, 0));
|
||||
break;
|
||||
case 1:
|
||||
PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d"
|
||||
" cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d"
|
||||
" ifloopc %d dac1 %d",
|
||||
bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
|
||||
bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
|
||||
bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3));
|
||||
break;
|
||||
case 2:
|
||||
PDEBUG("reg2 IFPLL2 n1 %d num1 %d",
|
||||
bits(rw, 6, 17), bits(rw, 0, 5));
|
||||
break;
|
||||
case 3:
|
||||
PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17));
|
||||
break;
|
||||
case 4:
|
||||
PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d",
|
||||
bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
|
||||
break;
|
||||
case 5:
|
||||
PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d"
|
||||
" pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d"
|
||||
" dac %d",
|
||||
bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
|
||||
bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
|
||||
bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3));
|
||||
break;
|
||||
case 6:
|
||||
PDEBUG("reg6 RFPLL2 n %d num %d",
|
||||
bits(rw, 6, 17), bits(rw, 0, 5));
|
||||
break;
|
||||
case 7:
|
||||
PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17));
|
||||
break;
|
||||
case 8:
|
||||
PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d",
|
||||
bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
|
||||
break;
|
||||
case 9:
|
||||
PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d",
|
||||
bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7),
|
||||
bits(rw, 0, 2));
|
||||
break;
|
||||
case 10:
|
||||
PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d"
|
||||
" rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d"
|
||||
" intbiasen %d tybypass %d",
|
||||
bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14),
|
||||
bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2),
|
||||
bit(rw, 1), bit(rw, 0));
|
||||
break;
|
||||
case 11:
|
||||
PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d"
|
||||
" tx_delay %d",
|
||||
bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8),
|
||||
bits(rw, 0, 2));
|
||||
break;
|
||||
case 12:
|
||||
PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d",
|
||||
bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5));
|
||||
break;
|
||||
case 13:
|
||||
PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d"
|
||||
" lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d"
|
||||
" rf_biasvco %d",
|
||||
bit(rw, 17), bit(rw, 16), bit(rw, 15),
|
||||
bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4),
|
||||
bits(rw, 0, 2));
|
||||
break;
|
||||
case 14:
|
||||
PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d"
|
||||
" tx_acal %d tx_pcal %d",
|
||||
bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8),
|
||||
bits(rw, 0, 3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static int rf2959_init_hw(struct zd_rf *rf)
|
||||
{
|
||||
int r;
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 },
|
||||
{ CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 },
|
||||
{ CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E },
|
||||
{ CR23, 0x48 },
|
||||
/* normal size for cca threshold */
|
||||
{ CR24, 0x14 },
|
||||
/* { CR24, 0x20 }, */
|
||||
{ CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 },
|
||||
{ CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 },
|
||||
{ CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 },
|
||||
{ CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E },
|
||||
{ CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 },
|
||||
{ CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 },
|
||||
{ CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 },
|
||||
{ CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A },
|
||||
{ CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 },
|
||||
/* { CR91, 0x18 }, */
|
||||
/* should solve continous CTS frame problems */
|
||||
{ CR91, 0x00 },
|
||||
{ CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 },
|
||||
{ CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 },
|
||||
{ CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 },
|
||||
{ CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 },
|
||||
{ CR104, 0x18 }, { CR105, 0x12 },
|
||||
/* normal size */
|
||||
{ CR106, 0x1a },
|
||||
/* { CR106, 0x22 }, */
|
||||
{ CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 },
|
||||
{ CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 },
|
||||
{ CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 },
|
||||
{ CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 },
|
||||
{ CR119, 0x16 },
|
||||
/* no TX continuation */
|
||||
{ CR122, 0x00 },
|
||||
/* { CR122, 0xff }, */
|
||||
{ CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 },
|
||||
{ CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB },
|
||||
{ CR170, 0xBB },
|
||||
};
|
||||
|
||||
static const u32 rv[] = {
|
||||
0x000007, /* REG0(CFG1) */
|
||||
0x07dd43, /* REG1(IFPLL1) */
|
||||
0x080959, /* REG2(IFPLL2) */
|
||||
0x0e6666,
|
||||
0x116a57, /* REG4 */
|
||||
0x17dd43, /* REG5 */
|
||||
0x1819f9, /* REG6 */
|
||||
0x1e6666,
|
||||
0x214554,
|
||||
0x25e7fa,
|
||||
0x27fffa,
|
||||
/* The Zydas driver somehow forgets to set this value. It's
|
||||
* only set for Japan. We are using internal power control
|
||||
* for now.
|
||||
*/
|
||||
0x294128, /* internal power */
|
||||
/* 0x28252c, */ /* External control TX power */
|
||||
/* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */
|
||||
0x2c0000,
|
||||
0x300000,
|
||||
0x340000, /* REG13(0xD) */
|
||||
0x381e0f, /* REG14(0xE) */
|
||||
/* Bogus, RF2959's data sheet doesn't know register 27, which is
|
||||
* actually referenced here. The commented 0x11 is 17.
|
||||
*/
|
||||
0x6c180f, /* REG27(0x11) */
|
||||
};
|
||||
|
||||
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
|
||||
}
|
||||
|
||||
static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
|
||||
{
|
||||
int i, r;
|
||||
u32 *rv = rf2959_table[channel-1];
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rf2959_switch_radio_on(struct zd_rf *rf)
|
||||
{
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR10, 0x89 },
|
||||
{ CR11, 0x00 },
|
||||
};
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
static int rf2959_switch_radio_off(struct zd_rf *rf)
|
||||
{
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR10, 0x15 },
|
||||
{ CR11, 0x81 },
|
||||
};
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
}
|
||||
|
||||
int zd_rf_init_rf2959(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
if (chip->is_zd1211b) {
|
||||
dev_err(zd_chip_dev(chip),
|
||||
"RF2959 is currently not supported for ZD1211B"
|
||||
" devices\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rf->init_hw = rf2959_init_hw;
|
||||
rf->set_channel = rf2959_set_channel;
|
||||
rf->switch_radio_on = rf2959_switch_radio_on;
|
||||
rf->switch_radio_off = rf2959_switch_radio_off;
|
||||
return 0;
|
||||
}
|
71
drivers/net/wireless/zd1211rw/zd_types.h
Normal file
71
drivers/net/wireless/zd1211rw/zd_types.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* zd_types.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_TYPES_H
|
||||
#define _ZD_TYPES_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* We have three register spaces mapped into the overall USB address space of
|
||||
* 64K words (16-bit values). There is the control register space of
|
||||
* double-word registers, the eeprom register space and the firmware register
|
||||
* space. The control register space is byte mapped, the others are word
|
||||
* mapped.
|
||||
*
|
||||
* For that reason, we are using byte offsets for control registers and word
|
||||
* offsets for everything else.
|
||||
*/
|
||||
|
||||
typedef u32 __nocast zd_addr_t;
|
||||
|
||||
enum {
|
||||
ADDR_BASE_MASK = 0xff000000,
|
||||
ADDR_OFFSET_MASK = 0x0000ffff,
|
||||
ADDR_ZERO_MASK = 0x00ff0000,
|
||||
NULL_BASE = 0x00000000,
|
||||
USB_BASE = 0x01000000,
|
||||
CR_BASE = 0x02000000,
|
||||
CR_MAX_OFFSET = 0x0b30,
|
||||
E2P_BASE = 0x03000000,
|
||||
E2P_MAX_OFFSET = 0x007e,
|
||||
FW_BASE = 0x04000000,
|
||||
FW_MAX_OFFSET = 0x0005,
|
||||
};
|
||||
|
||||
#define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK)
|
||||
#define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK)
|
||||
|
||||
#define ZD_ADDR(base, offset) \
|
||||
((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK)))
|
||||
|
||||
#define ZD_NULL_ADDR ((zd_addr_t)0)
|
||||
#define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */
|
||||
#define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */
|
||||
#define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */
|
||||
#define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */
|
||||
|
||||
static inline zd_addr_t zd_inc_word(zd_addr_t addr)
|
||||
{
|
||||
u32 base = ZD_ADDR_BASE(addr);
|
||||
u32 offset = ZD_OFFSET(addr);
|
||||
|
||||
offset += base == CR_BASE ? 2 : 1;
|
||||
|
||||
return base | offset;
|
||||
}
|
||||
|
||||
#endif /* _ZD_TYPES_H */
|
1316
drivers/net/wireless/zd1211rw/zd_usb.c
Normal file
1316
drivers/net/wireless/zd1211rw/zd_usb.c
Normal file
File diff suppressed because it is too large
Load diff
240
drivers/net/wireless/zd1211rw/zd_usb.h
Normal file
240
drivers/net/wireless/zd1211rw/zd_usb.h
Normal file
|
@ -0,0 +1,240 @@
|
|||
/* zd_usb.h: Header for USB interface implemented by ZD1211 chip
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_USB_H
|
||||
#define _ZD_USB_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "zd_def.h"
|
||||
#include "zd_types.h"
|
||||
|
||||
enum devicetype {
|
||||
DEVICE_ZD1211 = 0,
|
||||
DEVICE_ZD1211B = 1,
|
||||
};
|
||||
|
||||
enum endpoints {
|
||||
EP_CTRL = 0,
|
||||
EP_DATA_OUT = 1,
|
||||
EP_DATA_IN = 2,
|
||||
EP_INT_IN = 3,
|
||||
EP_REGS_OUT = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
USB_MAX_TRANSFER_SIZE = 4096, /* bytes */
|
||||
/* FIXME: The original driver uses this value. We have to check,
|
||||
* whether the MAX_TRANSFER_SIZE is sufficient and this needs only be
|
||||
* used if one combined frame is split over two USB transactions.
|
||||
*/
|
||||
USB_MAX_RX_SIZE = 4800, /* bytes */
|
||||
USB_MAX_IOWRITE16_COUNT = 15,
|
||||
USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2,
|
||||
USB_MAX_IOREAD16_COUNT = 15,
|
||||
USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2,
|
||||
USB_MIN_RFWRITE_BIT_COUNT = 16,
|
||||
USB_MAX_RFWRITE_BIT_COUNT = 28,
|
||||
USB_MAX_EP_INT_BUFFER = 64,
|
||||
USB_ZD1211B_BCD_DEVICE = 0x4810,
|
||||
};
|
||||
|
||||
enum control_requests {
|
||||
USB_REQ_WRITE_REGS = 0x21,
|
||||
USB_REQ_READ_REGS = 0x22,
|
||||
USB_REQ_WRITE_RF = 0x23,
|
||||
USB_REQ_PROG_FLASH = 0x24,
|
||||
USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */
|
||||
USB_REQ_EEPROM_MID = 0x28,
|
||||
USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */
|
||||
USB_REQ_FIRMWARE_DOWNLOAD = 0x30,
|
||||
USB_REQ_FIRMWARE_CONFIRM = 0x31,
|
||||
USB_REQ_FIRMWARE_READ_DATA = 0x32,
|
||||
};
|
||||
|
||||
struct usb_req_read_regs {
|
||||
__le16 id;
|
||||
__le16 addr[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct reg_data {
|
||||
__le16 addr;
|
||||
__le16 value;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_req_write_regs {
|
||||
__le16 id;
|
||||
struct reg_data reg_writes[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
enum {
|
||||
RF_IF_LE = 0x02,
|
||||
RF_CLK = 0x04,
|
||||
RF_DATA = 0x08,
|
||||
};
|
||||
|
||||
struct usb_req_rfwrite {
|
||||
__le16 id;
|
||||
__le16 value;
|
||||
/* 1: 3683a */
|
||||
/* 2: other (default) */
|
||||
__le16 bits;
|
||||
/* RF2595: 24 */
|
||||
__le16 bit_values[0];
|
||||
/* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* USB interrupt */
|
||||
|
||||
enum usb_int_id {
|
||||
USB_INT_TYPE = 0x01,
|
||||
USB_INT_ID_REGS = 0x90,
|
||||
USB_INT_ID_RETRY_FAILED = 0xa0,
|
||||
};
|
||||
|
||||
enum usb_int_flags {
|
||||
USB_INT_READ_REGS_EN = 0x01,
|
||||
};
|
||||
|
||||
struct usb_int_header {
|
||||
u8 type; /* must always be 1 */
|
||||
u8 id;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_int_regs {
|
||||
struct usb_int_header hdr;
|
||||
struct reg_data regs[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_int_retry_fail {
|
||||
struct usb_int_header hdr;
|
||||
u8 new_rate;
|
||||
u8 _dummy;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 ibss_wakeup_dest;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct read_regs_int {
|
||||
struct completion completion;
|
||||
/* Stores the USB int structure and contains the USB address of the
|
||||
* first requested register before request.
|
||||
*/
|
||||
u8 buffer[USB_MAX_EP_INT_BUFFER];
|
||||
int length;
|
||||
__le16 cr_int_addr;
|
||||
};
|
||||
|
||||
struct zd_ioreq16 {
|
||||
zd_addr_t addr;
|
||||
u16 value;
|
||||
};
|
||||
|
||||
struct zd_ioreq32 {
|
||||
zd_addr_t addr;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct zd_usb_interrupt {
|
||||
struct read_regs_int read_regs;
|
||||
spinlock_t lock;
|
||||
struct urb *urb;
|
||||
int interval;
|
||||
u8 read_regs_enabled:1;
|
||||
};
|
||||
|
||||
static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
|
||||
{
|
||||
return (struct usb_int_regs *)intr->read_regs.buffer;
|
||||
}
|
||||
|
||||
#define URBS_COUNT 5
|
||||
|
||||
struct zd_usb_rx {
|
||||
spinlock_t lock;
|
||||
u8 fragment[2*USB_MAX_RX_SIZE];
|
||||
unsigned int fragment_length;
|
||||
unsigned int usb_packet_size;
|
||||
struct urb **urbs;
|
||||
int urbs_count;
|
||||
};
|
||||
|
||||
struct zd_usb_tx {
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/* Contains the usb parts. The structure doesn't require a lock, because intf
|
||||
* and fw_base_offset, will not be changed after initialization.
|
||||
*/
|
||||
struct zd_usb {
|
||||
struct zd_usb_interrupt intr;
|
||||
struct zd_usb_rx rx;
|
||||
struct zd_usb_tx tx;
|
||||
struct usb_interface *intf;
|
||||
u16 fw_base_offset;
|
||||
};
|
||||
|
||||
#define zd_usb_dev(usb) (&usb->intf->dev)
|
||||
|
||||
static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
|
||||
{
|
||||
return interface_to_usbdev(usb->intf);
|
||||
}
|
||||
|
||||
static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf)
|
||||
{
|
||||
return usb_get_intfdata(intf);
|
||||
}
|
||||
|
||||
static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb)
|
||||
{
|
||||
return zd_intf_to_netdev(usb->intf);
|
||||
}
|
||||
|
||||
void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
|
||||
struct usb_interface *intf);
|
||||
int zd_usb_init_hw(struct zd_usb *usb);
|
||||
void zd_usb_clear(struct zd_usb *usb);
|
||||
|
||||
int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
|
||||
|
||||
int zd_usb_enable_int(struct zd_usb *usb);
|
||||
void zd_usb_disable_int(struct zd_usb *usb);
|
||||
|
||||
int zd_usb_enable_rx(struct zd_usb *usb);
|
||||
void zd_usb_disable_rx(struct zd_usb *usb);
|
||||
|
||||
int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length);
|
||||
|
||||
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
|
||||
const zd_addr_t *addresses, unsigned int count);
|
||||
|
||||
static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
|
||||
const zd_addr_t addr)
|
||||
{
|
||||
return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1);
|
||||
}
|
||||
|
||||
int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
|
||||
unsigned int count);
|
||||
|
||||
int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
|
||||
|
||||
#endif /* _ZD_USB_H */
|
82
drivers/net/wireless/zd1211rw/zd_util.c
Normal file
82
drivers/net/wireless/zd1211rw/zd_util.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* zd_util.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Utility program
|
||||
*/
|
||||
|
||||
#include "zd_def.h"
|
||||
#include "zd_util.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
static char hex(u8 v)
|
||||
{
|
||||
v &= 0xf;
|
||||
return (v < 10 ? '0' : 'a' - 10) + v;
|
||||
}
|
||||
|
||||
static char hex_print(u8 c)
|
||||
{
|
||||
return (0x20 <= c && c < 0x7f) ? c : '.';
|
||||
}
|
||||
|
||||
static void dump_line(const u8 *bytes, size_t size)
|
||||
{
|
||||
char c;
|
||||
size_t i;
|
||||
|
||||
size = size <= 8 ? size : 8;
|
||||
printk(KERN_DEBUG "zd1211 %p ", bytes);
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
case 5:
|
||||
c = '.';
|
||||
break;
|
||||
case 3:
|
||||
c = ':';
|
||||
break;
|
||||
default:
|
||||
c = ' ';
|
||||
}
|
||||
if (i < size) {
|
||||
printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c);
|
||||
} else {
|
||||
printk(" %c", c);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
printk("%c", hex_print(bytes[i]));
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
void zd_hexdump(const void *bytes, size_t size)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
do {
|
||||
dump_line((u8 *)bytes + i, size-i);
|
||||
i += 8;
|
||||
} while (i < size);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size)
|
||||
{
|
||||
if (buffer_size < tail_size)
|
||||
return NULL;
|
||||
return (u8 *)buffer + (buffer_size - tail_size);
|
||||
}
|
29
drivers/net/wireless/zd1211rw/zd_util.h
Normal file
29
drivers/net/wireless/zd1211rw/zd_util.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* zd_util.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZD_UTIL_H
|
||||
#define _ZD_UTIL_H
|
||||
|
||||
void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size);
|
||||
|
||||
#ifdef DEBUG
|
||||
void zd_hexdump(const void *bytes, size_t size);
|
||||
#else
|
||||
#define zd_hexdump(bytes, size)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* _ZD_UTIL_H */
|
|
@ -19,37 +19,13 @@
|
|||
|
||||
Support and updates available at
|
||||
http://www.scyld.com/network/yellowfin.html
|
||||
[link no longer provides useful info -jgarzik]
|
||||
|
||||
|
||||
Linux kernel changelog:
|
||||
-----------------------
|
||||
|
||||
LK1.1.1 (jgarzik): Port to 2.4 kernel
|
||||
|
||||
LK1.1.2 (jgarzik):
|
||||
* Merge in becker version 1.05
|
||||
|
||||
LK1.1.3 (jgarzik):
|
||||
* Various cleanups
|
||||
* Update yellowfin_timer to correctly calculate duplex.
|
||||
(suggested by Manfred Spraul)
|
||||
|
||||
LK1.1.4 (val@nmt.edu):
|
||||
* Fix three endian-ness bugs
|
||||
* Support dual function SYM53C885E ethernet chip
|
||||
|
||||
LK1.1.5 (val@nmt.edu):
|
||||
* Fix forced full-duplex bug I introduced
|
||||
|
||||
LK1.1.6 (val@nmt.edu):
|
||||
* Only print warning on truly "oversized" packets
|
||||
* Fix theoretical bug on gigabit cards - return to 1.1.3 behavior
|
||||
|
||||
*/
|
||||
|
||||
#define DRV_NAME "yellowfin"
|
||||
#define DRV_VERSION "1.05+LK1.1.6"
|
||||
#define DRV_RELDATE "Feb 11, 2002"
|
||||
#define DRV_VERSION "2.0"
|
||||
#define DRV_RELDATE "Jun 27, 2006"
|
||||
|
||||
#define PFX DRV_NAME ": "
|
||||
|
||||
|
@ -239,8 +215,11 @@ enum capability_flags {
|
|||
HasMACAddrBug=32, /* Only on early revs. */
|
||||
DontUseEeprom=64, /* Don't read the MAC from the EEPROm. */
|
||||
};
|
||||
|
||||
/* The PCI I/O space extent. */
|
||||
#define YELLOWFIN_SIZE 0x100
|
||||
enum {
|
||||
YELLOWFIN_SIZE = 0x100,
|
||||
};
|
||||
|
||||
struct pci_id_info {
|
||||
const char *name;
|
||||
|
@ -248,16 +227,14 @@ struct pci_id_info {
|
|||
int pci, pci_mask, subsystem, subsystem_mask;
|
||||
int revision, revision_mask; /* Only 8 bits. */
|
||||
} id;
|
||||
int io_size; /* Needed for I/O region check or ioremap(). */
|
||||
int drv_flags; /* Driver use, intended as capability flags. */
|
||||
};
|
||||
|
||||
static const struct pci_id_info pci_id_tbl[] = {
|
||||
{"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
|
||||
YELLOWFIN_SIZE,
|
||||
FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom},
|
||||
{"Symbios SYM83C885", { 0x07011000, 0xffffffff},
|
||||
YELLOWFIN_SIZE, HasMII | DontUseEeprom },
|
||||
HasMII | DontUseEeprom },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ struct ieee80211softmac_assoc_info {
|
|||
*/
|
||||
u8 static_essid:1,
|
||||
associating:1,
|
||||
assoc_wait:1,
|
||||
bssvalid:1,
|
||||
bssfixed:1;
|
||||
|
||||
|
|
|
@ -368,6 +368,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|||
|
||||
/* Put this code here so that we avoid duplicating it in all
|
||||
* Rx paths. - Jean II */
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
|
||||
/* If spy monitoring on */
|
||||
if (ieee->spy_data.spy_number > 0) {
|
||||
|
@ -396,15 +397,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|||
wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
|
||||
}
|
||||
#endif /* IW_WIRELESS_SPY */
|
||||
#endif /* CONFIG_WIRELESS_EXT */
|
||||
|
||||
#ifdef NOT_YET
|
||||
hostap_update_rx_stats(local->ap, hdr, rx_stats);
|
||||
#endif
|
||||
|
||||
if (ieee->iw_mode == IW_MODE_MONITOR) {
|
||||
ieee80211_monitor_rx(ieee, skb, rx_stats);
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
ieee80211_monitor_rx(ieee, skb, rx_stats);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -562,10 +562,13 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
|||
struct net_device_stats *stats = &ieee->stats;
|
||||
struct sk_buff *skb_frag;
|
||||
int priority = -1;
|
||||
int fraglen = total_len;
|
||||
int headroom = ieee->tx_headroom;
|
||||
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
if (encrypt_mpdu && !ieee->sec.encrypt)
|
||||
if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
|
||||
encrypt_mpdu = 0;
|
||||
|
||||
/* If there is no driver handler to take the TXB, dont' bother
|
||||
|
@ -581,20 +584,24 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
|||
goto success;
|
||||
}
|
||||
|
||||
if (encrypt_mpdu)
|
||||
if (encrypt_mpdu) {
|
||||
frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
fraglen += crypt->ops->extra_mpdu_prefix_len +
|
||||
crypt->ops->extra_mpdu_postfix_len;
|
||||
headroom += crypt->ops->extra_mpdu_prefix_len;
|
||||
}
|
||||
|
||||
/* When we allocate the TXB we allocate enough space for the reserve
|
||||
* and full fragment bytes (bytes_per_frag doesn't include prefix,
|
||||
* postfix, header, FCS, etc.) */
|
||||
txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
|
||||
txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC);
|
||||
if (unlikely(!txb)) {
|
||||
printk(KERN_WARNING "%s: Could not allocate TXB\n",
|
||||
ieee->dev->name);
|
||||
goto failed;
|
||||
}
|
||||
txb->encrypted = 0;
|
||||
txb->payload_size = total_len;
|
||||
txb->payload_size = fraglen;
|
||||
|
||||
skb_frag = txb->fragments[0];
|
||||
|
||||
|
|
|
@ -47,9 +47,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
|
|||
|
||||
dprintk(KERN_INFO PFX "sent association request!\n");
|
||||
|
||||
/* Change the state to associating */
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
mac->associnfo.associating = 1;
|
||||
mac->associated = 0; /* just to make sure */
|
||||
|
||||
/* Set a timer for timeout */
|
||||
|
@ -63,6 +61,7 @@ void
|
|||
ieee80211softmac_assoc_timeout(void *d)
|
||||
{
|
||||
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
|
||||
struct ieee80211softmac_network *n;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
|
@ -75,11 +74,12 @@ ieee80211softmac_assoc_timeout(void *d)
|
|||
mac->associnfo.associating = 0;
|
||||
mac->associnfo.bssvalid = 0;
|
||||
mac->associated = 0;
|
||||
|
||||
n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
|
||||
dprintk(KERN_INFO PFX "assoc request timed out!\n");
|
||||
/* FIXME: we need to know the network here. that requires a bit of restructuring */
|
||||
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
|
||||
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -203,6 +203,10 @@ ieee80211softmac_assoc_work(void *d)
|
|||
if (mac->associated)
|
||||
ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
|
||||
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
mac->associnfo.associating = 1;
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
|
||||
/* try to find the requested network in our list, if we found one already */
|
||||
if (bssvalid || mac->associnfo.bssfixed)
|
||||
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
|
||||
|
@ -295,19 +299,32 @@ ieee80211softmac_assoc_work(void *d)
|
|||
memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
|
||||
|
||||
/* we found a network! authenticate (if necessary) and associate to it. */
|
||||
if (!found->authenticated) {
|
||||
if (found->authenticating) {
|
||||
dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
|
||||
if(!mac->associnfo.assoc_wait) {
|
||||
mac->associnfo.assoc_wait = 1;
|
||||
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!found->authenticated && !found->authenticating) {
|
||||
/* This relies on the fact that _auth_req only queues the work,
|
||||
* otherwise adding the notification would be racy. */
|
||||
if (!ieee80211softmac_auth_req(mac, found)) {
|
||||
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
|
||||
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
|
||||
if(!mac->associnfo.assoc_wait) {
|
||||
dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
|
||||
mac->associnfo.assoc_wait = 1;
|
||||
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
|
||||
}
|
||||
} else {
|
||||
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
|
||||
mac->associnfo.assoc_wait = 0;
|
||||
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* finally! now we can start associating */
|
||||
mac->associnfo.assoc_wait = 0;
|
||||
ieee80211softmac_assoc(mac, found);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,9 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
|
|||
struct ieee80211softmac_auth_queue_item *auth;
|
||||
unsigned long flags;
|
||||
|
||||
if (net->authenticating)
|
||||
if (net->authenticating || net->authenticated)
|
||||
return 0;
|
||||
net->authenticating = 1;
|
||||
|
||||
/* Add the network if it's not already added */
|
||||
ieee80211softmac_add_network(mac, net);
|
||||
|
@ -92,7 +93,6 @@ ieee80211softmac_auth_queue(void *data)
|
|||
return;
|
||||
}
|
||||
net->authenticated = 0;
|
||||
net->authenticating = 1;
|
||||
/* add a timeout call so we eventually give up waiting for an auth reply */
|
||||
schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
|
||||
auth->retry--;
|
||||
|
|
|
@ -229,6 +229,9 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
|
|||
return 0;
|
||||
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
|
||||
|
||||
/* Fill in the capabilities */
|
||||
(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
|
||||
|
||||
/* Fill in Listen Interval (?) */
|
||||
(*pkt)->listen_interval = cpu_to_le16(10);
|
||||
|
||||
|
|
|
@ -70,12 +70,44 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
|
|||
char *extra)
|
||||
{
|
||||
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
|
||||
struct ieee80211softmac_network *n;
|
||||
struct ieee80211softmac_auth_queue_item *authptr;
|
||||
int length = 0;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
/* Check if we're already associating to this or another network
|
||||
* If it's another network, cancel and start over with our new network
|
||||
* If it's our network, ignore the change, we're already doing it!
|
||||
*/
|
||||
if((sm->associnfo.associating || sm->associated) &&
|
||||
(data->essid.flags && data->essid.length && extra)) {
|
||||
/* Get the associating network */
|
||||
n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
|
||||
if(n && n->essid.len == (data->essid.length - 1) &&
|
||||
!memcmp(n->essid.data, extra, n->essid.len)) {
|
||||
dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
|
||||
MAC_ARG(sm->associnfo.bssid));
|
||||
return 0;
|
||||
} else {
|
||||
dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
|
||||
spin_lock_irqsave(&sm->lock,flags);
|
||||
/* Cancel assoc work */
|
||||
cancel_delayed_work(&sm->associnfo.work);
|
||||
/* We don't have to do this, but it's a little cleaner */
|
||||
list_for_each_entry(authptr, &sm->auth_queue, list)
|
||||
cancel_delayed_work(&authptr->work);
|
||||
sm->associnfo.bssvalid = 0;
|
||||
sm->associnfo.bssfixed = 0;
|
||||
spin_unlock_irqrestore(&sm->lock,flags);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
|
||||
|
||||
sm->associnfo.static_essid = 0;
|
||||
sm->associnfo.assoc_wait = 0;
|
||||
|
||||
if (data->essid.flags && data->essid.length && extra /*required?*/) {
|
||||
length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
|
||||
|
|
Loading…
Reference in a new issue