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:
Linus Torvalds 2006-07-05 13:02:56 -07:00
commit e8f75588dd
68 changed files with 7760 additions and 1103 deletions

View File

@ -2039,9 +2039,10 @@ L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
NI5010 NETWORK DRIVER NI5010 NETWORK DRIVER
P: Jan-Pascal van Best and Andreas Mohr P: Jan-Pascal van Best
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl> M: janpascal@vanbest.org
M: Andreas Mohr <100.30936@germany.net> P: Andreas Mohr
M: andi@lisas.de
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained

View File

@ -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 && if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) { 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", dev_err(&pdev->dev,
pci_name(pdev), pdev->vendor, pdev->device, pci_rev); "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
printk(KERN_ERR PFX "Try the \"8139too\" driver instead.\n"); pdev->vendor, pdev->device, pci_rev);
dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
return -ENODEV; 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); pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) { if (!pciaddr) {
rc = -EIO; rc = -EIO;
printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n", dev_err(&pdev->dev, "no MMIO resource\n");
pci_name(pdev));
goto err_out_res; goto err_out_res;
} }
if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) { if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
rc = -EIO; rc = -EIO;
printk(KERN_ERR PFX "MMIO resource (%llx) too small on pci dev %s\n", dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
(unsigned long long)pci_resource_len(pdev, 1), pci_name(pdev)); (unsigned long long)pci_resource_len(pdev, 1));
goto err_out_res; 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); rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) { if (rc) {
printk(KERN_ERR PFX "No usable DMA configuration, " dev_err(&pdev->dev,
"aborting.\n"); "No usable DMA configuration, aborting.\n");
goto err_out_res; goto err_out_res;
} }
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) { if (rc) {
printk(KERN_ERR PFX "No usable consistent DMA configuration, " dev_err(&pdev->dev,
"aborting.\n"); "No usable consistent DMA configuration, "
"aborting.\n");
goto err_out_res; 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); regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) { if (!regs) {
rc = -EIO; rc = -EIO;
printk(KERN_ERR PFX "Cannot map PCI MMIO (%llx@%llx) on pci dev %s\n", dev_err(&pdev->dev, "Cannot map PCI MMIO (%lx@%lx)\n",
(unsigned long long)pci_resource_len(pdev, 1), (unsigned long long)pci_resource_len(pdev, 1),
(unsigned long long)pciaddr, pci_name(pdev)); (unsigned long long)pciaddr);
goto err_out_res; goto err_out_res;
} }
dev->base_addr = (unsigned long) regs; 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 */ /* enable busmastering and memory-write-invalidate */
pci_set_master(pdev); pci_set_master(pdev);
if (cp->wol_enabled) cp_set_d3_state (cp); if (cp->wol_enabled)
cp_set_d3_state (cp);
return 0; return 0;
@ -2011,7 +2013,8 @@ static void cp_remove_one (struct pci_dev *pdev)
BUG_ON(!dev); BUG_ON(!dev);
unregister_netdev(dev); unregister_netdev(dev);
iounmap(cp->regs); 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_release_regions(pdev);
pci_clear_mwi(pdev); pci_clear_mwi(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);

View File

@ -768,7 +768,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* dev and priv zeroed in alloc_etherdev */ /* dev and priv zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp)); dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) { 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; return -ENOMEM;
} }
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
@ -800,31 +800,31 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
#ifdef USE_IO_OPS #ifdef USE_IO_OPS
/* make sure PCI base addr 0 is PIO */ /* make sure PCI base addr 0 is PIO */
if (!(pio_flags & IORESOURCE_IO)) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
/* check for weird/broken PCI region reporting */ /* check for weird/broken PCI region reporting */
if (pio_len < RTL_MIN_IO_SIZE) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
#else #else
/* make sure PCI base addr 1 is MMIO */ /* make sure PCI base addr 1 is MMIO */
if (!(mmio_flags & IORESOURCE_MEM)) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
if (mmio_len < RTL_MIN_IO_SIZE) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
#endif #endif
rc = pci_request_regions (pdev, "8139too"); rc = pci_request_regions (pdev, DRV_NAME);
if (rc) if (rc)
goto err_out; goto err_out;
disable_dev_on_err = 1; disable_dev_on_err = 1;
@ -835,7 +835,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
#ifdef USE_IO_OPS #ifdef USE_IO_OPS
ioaddr = ioport_map(pio_start, pio_len); ioaddr = ioport_map(pio_start, pio_len);
if (!ioaddr) { 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; rc = -EIO;
goto err_out; goto err_out;
} }
@ -846,7 +846,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* ioremap MMIO region */ /* ioremap MMIO region */
ioaddr = pci_iomap(pdev, 1, 0); ioaddr = pci_iomap(pdev, 1, 0);
if (ioaddr == NULL) { 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; rc = -EIO;
goto err_out; goto err_out;
} }
@ -860,8 +860,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* check for missing/broken hardware */ /* check for missing/broken hardware */
if (RTL_R32 (TxConfig) == 0xFFFFFFFF) { if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n", dev_err(&pdev->dev, "Chip not responding, ignoring board\n");
pci_name(pdev));
rc = -EIO; rc = -EIO;
goto err_out; 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 */ /* 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", dev_printk (KERN_DEBUG, &pdev->dev,
pci_name(pdev)); "unknown chip version, assuming RTL-8139\n");
printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig)); dev_printk (KERN_DEBUG, &pdev->dev,
"TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
tp->chipset = 0; tp->chipset = 0;
match: match:
@ -954,9 +954,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
if (pdev->vendor == PCI_VENDOR_ID_REALTEK && if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { 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", dev_info(&pdev->dev,
pci_name(pdev), pdev->vendor, pdev->device, pci_rev); "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\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); i = rtl8139_init_board (pdev, &dev);

View File

@ -2120,13 +2120,14 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
printk(KERN_ERR PFX "Cannot enable PCI device, " dev_err(&pdev->dev, "Cannot enable PCI device, "
"aborting.\n"); "aborting.\n");
return err; return err;
} }
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 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"); "base address, aborting.\n");
err = -ENODEV; err = -ENODEV;
goto err_out_disable_pdev; 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); err = pci_request_regions(pdev, DRV_MODULE_NAME);
if (err) { if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, " dev_err(&pdev->dev,
"aborting.\n"); "Cannot obtain PCI resources, aborting.\n");
goto err_out_disable_pdev; 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); err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) { if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, " dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
"aborting.\n");
goto err_out_free_res; goto err_out_free_res;
} }
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) { if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, " dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
"aborting.\n");
goto err_out_free_res; goto err_out_free_res;
} }
@ -2160,7 +2159,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*bp)); dev = alloc_etherdev(sizeof(*bp));
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
err = -ENOMEM; err = -ENOMEM;
goto err_out_free_res; 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); bp->regs = ioremap(b44reg_base, b44reg_len);
if (bp->regs == 0UL) { if (bp->regs == 0UL) {
printk(KERN_ERR PFX "Cannot map device registers, " dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
"aborting.\n");
err = -ENOMEM; err = -ENOMEM;
goto err_out_free_dev; goto err_out_free_dev;
} }
@ -2212,8 +2210,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = b44_get_invariants(bp); err = b44_get_invariants(bp);
if (err) { if (err) {
printk(KERN_ERR PFX "Problem fetching invariants of chip, " dev_err(&pdev->dev,
"aborting.\n"); "Problem fetching invariants of chip, aborting.\n");
goto err_out_iounmap; goto err_out_iounmap;
} }
@ -2233,8 +2231,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
printk(KERN_ERR PFX "Cannot register net device, " dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
"aborting.\n");
goto err_out_iounmap; goto err_out_iounmap;
} }

View File

@ -5575,20 +5575,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
/* enable device (incl. PCI PM wakeup), and bus-mastering */ /* enable device (incl. PCI PM wakeup), and bus-mastering */
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) { if (rc) {
printk(KERN_ERR PFX "Cannot enable PCI device, aborting."); dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
goto err_out; goto err_out;
} }
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find PCI device base address, " dev_err(&pdev->dev,
"aborting.\n"); "Cannot find PCI device base address, aborting.\n");
rc = -ENODEV; rc = -ENODEV;
goto err_out_disable; goto err_out_disable;
} }
rc = pci_request_regions(pdev, DRV_MODULE_NAME); rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) { 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; 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); bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) { if (bp->pm_cap == 0) {
printk(KERN_ERR PFX "Cannot find power management capability, " dev_err(&pdev->dev,
"aborting.\n"); "Cannot find power management capability, aborting.\n");
rc = -EIO; rc = -EIO;
goto err_out_release; goto err_out_release;
} }
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
if (bp->pcix_cap == 0) { 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; rc = -EIO;
goto err_out_release; 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) { if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
bp->flags |= USING_DAC_FLAG; bp->flags |= USING_DAC_FLAG;
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) { if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
printk(KERN_ERR PFX "pci_set_consistent_dma_mask " dev_err(&pdev->dev,
"failed, aborting.\n"); "pci_set_consistent_dma_mask failed, aborting.\n");
rc = -EIO; rc = -EIO;
goto err_out_release; goto err_out_release;
} }
} }
else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) { 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; rc = -EIO;
goto err_out_release; 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); bp->regview = ioremap_nocache(dev->base_addr, mem_len);
if (!bp->regview) { 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; rc = -ENOMEM;
goto err_out_release; 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) && else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
!(bp->flags & PCIX_FLAG)) { !(bp->flags & PCIX_FLAG)) {
printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, " dev_err(&pdev->dev,
"aborting.\n"); "5706 A1 can only be used in a PCIX bus, aborting.\n");
goto err_out_unmap; 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) != if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
BNX2_DEV_INFO_SIGNATURE_MAGIC) { 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; rc = -ENODEV;
goto err_out_unmap; goto err_out_unmap;
} }
@ -5895,7 +5895,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif #endif
if ((rc = register_netdev(dev))) { 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) if (bp->regview)
iounmap(bp->regview); iounmap(bp->regview);
pci_release_regions(pdev); pci_release_regions(pdev);

View File

@ -4887,13 +4887,12 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
printk(KERN_ERR PFX "Cannot enable PCI device, " dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
"aborting.\n");
return err; return err;
} }
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 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"); "base address, aborting.\n");
err = -ENODEV; err = -ENODEV;
goto err_out_disable_pdev; goto err_out_disable_pdev;
@ -4901,7 +4900,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*cp)); dev = alloc_etherdev(sizeof(*cp));
if (!dev) { if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
err = -ENOMEM; err = -ENOMEM;
goto err_out_disable_pdev; 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); err = pci_request_regions(pdev, dev->name);
if (err) { if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, " dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
"aborting.\n");
goto err_out_free_netdev; goto err_out_free_netdev;
} }
pci_set_master(pdev); pci_set_master(pdev);
@ -4941,7 +4939,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
if (pci_write_config_byte(pdev, if (pci_write_config_byte(pdev,
PCI_CACHE_LINE_SIZE, PCI_CACHE_LINE_SIZE,
cas_cacheline_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"); "line size\n");
goto err_write_cacheline; 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, err = pci_set_consistent_dma_mask(pdev,
DMA_64BIT_MASK); DMA_64BIT_MASK);
if (err < 0) { 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"); "for consistent allocations\n");
goto err_out_free_res; goto err_out_free_res;
} }
@ -4963,7 +4961,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
} else { } else {
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) { if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, " dev_err(&pdev->dev, "No usable DMA configuration, "
"aborting.\n"); "aborting.\n");
goto err_out_free_res; 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 */ /* give us access to cassini registers */
cp->regs = pci_iomap(pdev, 0, casreg_len); cp->regs = pci_iomap(pdev, 0, casreg_len);
if (cp->regs == 0UL) { if (cp->regs == 0UL) {
printk(KERN_ERR PFX "Cannot map device registers, " dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
"aborting.\n");
goto err_out_free_res; goto err_out_free_res;
} }
cp->casreg_len = casreg_len; 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), pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
&cp->block_dvma); &cp->block_dvma);
if (!cp->init_block) { if (!cp->init_block) {
printk(KERN_ERR PFX "Cannot allocate init block, " dev_err(&pdev->dev, "Cannot allocate init block, aborting.\n");
"aborting.\n");
goto err_out_iounmap; goto err_out_iounmap;
} }
@ -5085,8 +5081,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_HIGHDMA;
if (register_netdev(dev)) { if (register_netdev(dev)) {
printk(KERN_ERR PFX "Cannot register net device, " dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
"aborting.\n");
goto err_out_free_consistent; goto err_out_free_consistent;
} }

View File

@ -703,8 +703,8 @@ static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t static irqreturn_t lance_interrupt(const int irq, void *dev_id,
lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *) dev_id; struct net_device *dev = (struct net_device *) dev_id;
struct lance_private *lp = netdev_priv(dev); 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; return 0;
err_out_free_dev: err_out_free_dev:
kfree(dev); free_netdev(dev);
err_out: err_out:
return ret; return ret;
@ -1299,6 +1299,7 @@ static void __exit dec_lance_cleanup(void)
while (root_lance_dev) { while (root_lance_dev) {
struct net_device *dev = root_lance_dev; struct net_device *dev = root_lance_dev;
struct lance_private *lp = netdev_priv(dev); struct lance_private *lp = netdev_priv(dev);
unregister_netdev(dev); unregister_netdev(dev);
#ifdef CONFIG_TC #ifdef CONFIG_TC
if (lp->slot >= 0) if (lp->slot >= 0)

View File

@ -9,49 +9,10 @@
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (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_NAME "D-Link DL2000-based linux driver"
#define DRV_VERSION "v1.17b" #define DRV_VERSION "v1.18"
#define DRV_RELDATE "2006/03/10" #define DRV_RELDATE "2006/06/27"
#include "dl2k.h" #include "dl2k.h"
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>

View File

@ -555,12 +555,12 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
if (!request_region(pci_resource_start(pdev, 1), if (!request_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1), "eepro100")) { 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; goto err_out_none;
} }
if (!request_mem_region(pci_resource_start(pdev, 0), if (!request_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0), "eepro100")) { 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; 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); ioaddr = pci_iomap(pdev, pci_bar, 0);
if (!ioaddr) { 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; goto err_out_free_mmio_region;
} }

View File

@ -19,62 +19,15 @@
Information and updates available at Information and updates available at
http://www.scyld.com/network/epic100.html 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_NAME "epic100"
#define DRV_VERSION "1.11+LK1.1.14+AC1.1.14" #define DRV_VERSION "2.0"
#define DRV_RELDATE "June 2, 2004" #define DRV_RELDATE "June 27, 2006"
/* The user-configurable values. /* The user-configurable values.
These may be modified when a driver module is loaded.*/ These may be modified when a driver module is loaded.*/
@ -204,19 +157,15 @@ typedef enum {
struct epic_chip_info { struct epic_chip_info {
const char *name; const char *name;
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. */
}; };
/* indexed by chip_t */ /* indexed by chip_t */
static const struct epic_chip_info pci_id_tbl[] = { static const struct epic_chip_info pci_id_tbl[] = {
{ "SMSC EPIC/100 83c170", { "SMSC EPIC/100 83c170", TYPE2_INTR | NO_MII | MII_PWRDWN },
EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN }, { "SMSC EPIC/100 83c170", TYPE2_INTR },
{ "SMSC EPIC/100 83c170", { "SMSC EPIC/C 83c175", TYPE2_INTR | MII_PWRDWN },
EPIC_TOTAL_SIZE, TYPE2_INTR },
{ "SMSC EPIC/C 83c175",
EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
}; };
@ -385,8 +334,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
goto out; goto out;
irq = pdev->irq; irq = pdev->irq;
if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { if (pci_resource_len(pdev, 0) < EPIC_TOTAL_SIZE) {
printk (KERN_ERR "card %d: no PCI region space\n", card_idx); dev_err(&pdev->dev, "no PCI region space\n");
ret = -ENODEV; ret = -ENODEV;
goto err_out_disable; goto err_out_disable;
} }
@ -401,7 +350,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
dev = alloc_etherdev(sizeof (*ep)); dev = alloc_etherdev(sizeof (*ep));
if (!dev) { 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; goto err_out_free_res;
} }
SET_MODULE_OWNER(dev); 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 = pci_resource_start (pdev, 1);
ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
if (!ioaddr) { 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; goto err_out_free_netdev;
} }
#endif #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)); ((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
if (debug > 2) { if (debug > 2) {
printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n", dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
pci_name(pdev));
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
printk(" %4.4x%s", read_eeprom(ioaddr, i), printk(" %4.4x%s", read_eeprom(ioaddr, i),
i % 16 == 15 ? "\n" : ""); 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); int mii_status = mdio_read(dev, phy, MII_BMSR);
if (mii_status != 0xffff && mii_status != 0x0000) { if (mii_status != 0xffff && mii_status != 0x0000) {
ep->phys[phy_idx++] = phy; ep->phys[phy_idx++] = phy;
printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control " dev_info(&pdev->dev,
"%4.4x status %4.4x.\n", "MII transceiver #%d control "
pci_name(pdev), phy, mdio_read(dev, phy, 0), mii_status); "%4.4x status %4.4x.\n",
phy, mdio_read(dev, phy, 0), mii_status);
} }
} }
ep->mii_phy_cnt = phy_idx; ep->mii_phy_cnt = phy_idx;
if (phy_idx != 0) { if (phy_idx != 0) {
phy = ep->phys[0]; phy = ep->phys[0];
ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE); 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", "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)) { } else if ( ! (ep->chip_flags & NO_MII)) {
printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n", dev_warn(&pdev->dev,
pci_name(pdev)); "***WARNING***: No MII transceiver found!\n");
/* Use the known PHY address of the EPII. */ /* Use the known PHY address of the EPII. */
ep->phys[0] = 3; 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. */ /* The lower four bits are the media type. */
if (duplex) { if (duplex) {
ep->mii.force_media = ep->mii.full_duplex = 1; ep->mii.force_media = ep->mii.full_duplex = 1;
printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n", dev_info(&pdev->dev, "Forced full duplex requested.\n");
pci_name(pdev));
} }
dev->if_port = ep->default_port = option; dev->if_port = ep->default_port = option;

View File

@ -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(options, "fealnx: Bits 0-3: media type, bit 17: full duplex");
MODULE_PARM_DESC(full_duplex, "fealnx full duplex setting(s) (1)"); 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. */ /* A chip capabilities table, matching the entries in pci_tbl[] above. */
enum chip_capability_flags { enum chip_capability_flags {
@ -146,14 +148,13 @@ enum phy_type_flags {
struct chip_info { struct chip_info {
char *chip_name; char *chip_name;
int io_size;
int flags; int flags;
}; };
static const struct chip_info skel_netdrv_tbl[] = { static const struct chip_info skel_netdrv_tbl[] __devinitdata = {
{"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR}, { "100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
{"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR}, { "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR },
{"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR}, { "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
}; };
/* Offsets to the Command and Status Registers. */ /* 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); len = pci_resource_len(pdev, bar);
if (len < MIN_REGION_SIZE) { if (len < MIN_REGION_SIZE) {
printk(KERN_ERR "%s: region size %ld too small, aborting\n", dev_err(&pdev->dev,
boardname, len); "region size %ld too small, aborting\n", len);
return -ENODEV; return -ENODEV;
} }
i = pci_request_regions(pdev, boardname); i = pci_request_regions(pdev, boardname);
if (i) return i; if (i)
return i;
irq = pdev->irq; irq = pdev->irq;
@ -576,9 +578,9 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (mii_status != 0xffff && mii_status != 0x0000) { if (mii_status != 0xffff && mii_status != 0x0000) {
np->phys[phy_idx++] = phy; np->phys[phy_idx++] = phy;
printk(KERN_INFO dev_info(&pdev->dev,
"%s: MII PHY found at address %d, status " "MII PHY found at address %d, status "
"0x%4.4x.\n", dev->name, phy, mii_status); "0x%4.4x.\n", phy, mii_status);
/* get phy type */ /* get phy type */
{ {
unsigned int data; unsigned int data;
@ -601,10 +603,10 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
} }
np->mii_cnt = phy_idx; np->mii_cnt = phy_idx;
if (phy_idx == 0) { if (phy_idx == 0)
printk(KERN_WARNING "%s: MII PHY not found -- this device may " dev_warn(&pdev->dev,
"not operate correctly.\n", dev->name); "MII PHY not found -- this device may "
} "not operate correctly.\n");
} else { } else {
np->phys[0] = 32; np->phys[0] = 32;
/* 89/6/23 add, (begin) */ /* 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]; np->mii.full_duplex = full_duplex[card_idx];
if (np->mii.full_duplex) { 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) */ /* 89/6/13 add, (begin) */
// if (np->PHYType==MarvellPHY) // if (np->PHYType==MarvellPHY)
if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) { if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {

View File

@ -699,7 +699,6 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
memset(gp, 0, sizeof(*gp)); // clear it memset(gp, 0, sizeof(*gp)); // clear it
gp->port_num = port_num; gp->port_num = port_num;
gp->io_size = GT96100_ETH_IO_SIZE;
gp->port_offset = port_num * GT96100_ETH_IO_SIZE; gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
gp->phy_addr = phy_addr; gp->phy_addr = phy_addr;
gp->chip_rev = chip_rev; gp->chip_rev = chip_rev;
@ -1531,7 +1530,7 @@ static void gt96100_cleanup_module(void)
+ sizeof(gt96100_td_t) * TX_RING_SIZE, + sizeof(gt96100_td_t) * TX_RING_SIZE,
gp->rx_ring); gp->rx_ring);
free_netdev(gtif->dev); free_netdev(gtif->dev);
release_region(gtif->iobase, gp->io_size); release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
} }
} }
} }

View File

@ -331,7 +331,6 @@ struct gt96100_private {
mib_counters_t mib; mib_counters_t mib;
struct net_device_stats stats; struct net_device_stats stats;
int io_size;
int port_num; // 0 or 1 int port_num; // 0 or 1
int chip_rev; int chip_rev;
u32 port_offset; u32 port_offset;
@ -340,7 +339,6 @@ struct gt96100_private {
u32 last_psr; // last value of the port status register u32 last_psr; // last value of the port status register
int options; /* User-settable misc. driver options. */ int options; /* User-settable misc. driver options. */
int drv_flags;
struct timer_list timer; struct timer_list timer;
spinlock_t lock; /* Serialise access to device */ spinlock_t lock; /* Serialise access to device */
}; };

View File

@ -20,22 +20,15 @@
Support and updates available at Support and updates available at
http://www.scyld.com/network/hamachi.html http://www.scyld.com/network/hamachi.html
[link no longer provides useful info -jgarzik]
or or
http://www.parl.clemson.edu/~keithu/hamachi.html 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_NAME "hamachi"
#define DRV_VERSION "1.01+LK1.0.1" #define DRV_VERSION "2.0"
#define DRV_RELDATE "5/18/2001" #define DRV_RELDATE "June 27, 2006"
/* A few user-configurable values. */ /* A few user-configurable values. */
@ -608,7 +601,8 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
pci_set_master(pdev); pci_set_master(pdev);
i = pci_request_regions(pdev, DRV_NAME); i = pci_request_regions(pdev, DRV_NAME);
if (i) return i; if (i)
return i;
irq = pdev->irq; irq = pdev->irq;
ioaddr = ioremap(base, 0x400); ioaddr = ioremap(base, 0x400);

View File

@ -188,7 +188,6 @@ struct myri10ge_priv {
int vendor_specific_offset; int vendor_specific_offset;
u32 devctl; u32 devctl;
u16 msi_flags; u16 msi_flags;
u32 pm_state[16];
u32 read_dma; u32 read_dma;
u32 write_dma; u32 write_dma;
u32 read_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_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
"tx_heartbeat_errors", "tx_window_errors", "tx_heartbeat_errors", "tx_window_errors",
/* device-specific stats */ /* device-specific stats */
"tx_boundary", "WC", "irq", "MSI",
"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
"serial_number", "tx_pkt_start", "tx_pkt_done", "serial_number", "tx_pkt_start", "tx_pkt_done",
"tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", "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++) for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
data[i] = ((unsigned long *)&mgp->stats)[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->read_dma;
data[i++] = (unsigned int)mgp->write_dma; data[i++] = (unsigned int)mgp->write_dma;
data[i++] = (unsigned int)mgp->read_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. * 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) static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
{ {
struct pci_dev *bridge = mgp->pdev->bus->self; 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); dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
goto abort_with_irq; goto abort_with_irq;
} }
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n", (mgp->msi_enabled ? "MSI" : "xPIC"),
netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"), pdev->irq, mgp->tx.boundary, mgp->fw_name,
pdev->irq, mgp->tx.boundary, mgp->fw_name, (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
return 0; return 0;

View File

@ -20,120 +20,9 @@
Support information and updates available at Support information and updates available at
http://www.scyld.com/network/netsemi.html 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: TODO:
* big endian support with CFG:BEM instead of cpu_to_le32 * big endian support with CFG:BEM instead of cpu_to_le32
*/ */
@ -165,8 +54,8 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define DRV_NAME "natsemi" #define DRV_NAME "natsemi"
#define DRV_VERSION "1.07+LK1.0.17" #define DRV_VERSION "2.0"
#define DRV_RELDATE "Sep 27, 2002" #define DRV_RELDATE "June 27, 2006"
#define RX_OFFSET 2 #define RX_OFFSET 2

View File

@ -231,12 +231,12 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
irq = pdev->irq; irq = pdev->irq;
if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { 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; return -ENODEV;
} }
if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) { 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); NE_IO_EXTENT, ioaddr);
return -EBUSY; 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. */ /* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
dev = alloc_ei_netdev(); dev = alloc_ei_netdev();
if (!dev) { 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; goto err_out_free_res;
} }
SET_MODULE_OWNER(dev); 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) while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
/* Limit wait: '2' avoids jiffy roll-over. */ /* Limit wait: '2' avoids jiffy roll-over. */
if (jiffies - reset_start_time > 2) { 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; goto err_out_free_netdev;
} }

View File

@ -1,17 +1,12 @@
/* ni5010.c: A network driver for the MiCom-Interlan NI5010 ethercard. /* 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 * This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference. * of the GNU General Public License, incorporated herein by reference.
* *
* The authors may be reached as: * The authors may be reached as:
* jvbest@wi.leidenuniv.nl a.mohr@mailto.de * janpascal@vanbest.org andi@lisas.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
* *
* Sources: * Sources:
* Donald Becker's "skeleton.c" * Donald Becker's "skeleton.c"
@ -27,8 +22,9 @@
* 970503 v0.93: Fixed auto-irq failure on warm reboot (JB) * 970503 v0.93: Fixed auto-irq failure on warm reboot (JB)
* 970623 v1.00: First kernel version (AM) * 970623 v1.00: First kernel version (AM)
* 970814 v1.01: Added detection of onboard receive buffer size (AM) * 970814 v1.01: Added detection of onboard receive buffer size (AM)
* 060611 v1.02: slight cleanup: email addresses, driver modernization.
* Bugs: * 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 * - Note that you have to patch ifconfig for the new /proc/net/dev
* format. It gives incorrect stats otherwise. * format. It gives incorrect stats otherwise.
* *
@ -39,7 +35,7 @@
* Complete merge with Andreas' driver * Complete merge with Andreas' driver
* Implement ring buffers (Is this useful? You can't squeeze * Implement ring buffers (Is this useful? You can't squeeze
* too many packet in a 2k buffer!) * 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) * slower than programmed I/O)
* *
* Compile with: * Compile with:
@ -47,7 +43,7 @@
* -DMODULE -c ni5010.c * -DMODULE -c ni5010.c
* *
* Insert with e.g.: * Insert with e.g.:
* insmod ni5010.o io=0x300 irq=5 * insmod ni5010.ko io=0x300 irq=5
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -69,15 +65,15 @@
#include "ni5010.h" #include "ni5010.h"
static const char *boardname = "NI5010"; static const char boardname[] = "NI5010";
static char *version = static char version[] __initdata =
"ni5010.c: v1.00 06/23/97 Jan-Pascal van Best and Andreas Mohr\n"; "ni5010.c: v1.02 20060611 Jan-Pascal van Best and Andreas Mohr\n";
/* bufsize_rcv == 0 means autoprobing */ /* bufsize_rcv == 0 means autoprobing */
static unsigned int bufsize_rcv; static unsigned int bufsize_rcv;
#define jumpered_interrupts /* IRQ line jumpered on board */ #define JUMPERED_INTERRUPTS /* IRQ line jumpered on board */
#undef jumpered_dma /* No DMA used */ #undef JUMPERED_DMA /* No DMA used */
#undef FULL_IODETECT /* Only detect in portlist */ #undef FULL_IODETECT /* Only detect in portlist */
#ifndef FULL_IODETECT #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)); PRINTK2((KERN_DEBUG "%s: I/O #4 passed!\n", dev->name));
#ifdef jumpered_interrupts #ifdef JUMPERED_INTERRUPTS
if (dev->irq == 0xff) if (dev->irq == 0xff)
; ;
else if (dev->irq < 2) { 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) { } else if (dev->irq == 2) {
dev->irq = 9; dev->irq = 9;
} }
#endif /* jumpered_irq */ #endif /* JUMPERED_INTERRUPTS */
PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name));
/* DMA is not supported (yet?), so no use detecting it */ /* 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 */ outw(0, IE_GP); /* Point GP at start of packet */
outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */ 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)); memset(dev->priv, 0, sizeof(struct ni5010_local));
dev->open = ni5010_open; 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 */ 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); 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(".\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; return 0;
out: out:
release_region(dev->base_addr, NI5010_IO_EXTENT); 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 * This routine should set everything up anew at each open, even
* registers that "should" only need to be set once at boot, so that * 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) 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, * Always allocate the DMA channel after the IRQ,
* and clean up on failure. * and clean up on failure.
*/ */
#ifdef jumpered_dma #ifdef JUMPERED_DMA
if (request_dma(dev->dma, cardname)) { if (request_dma(dev->dma, cardname)) {
printk(KERN_WARNING "%s: Cannot get dma %#2x\n", dev->name, dev->dma); printk(KERN_WARNING "%s: Cannot get dma %#2x\n", dev->name, dev->dma);
free_irq(dev->irq, NULL); free_irq(dev->irq, NULL);
return -EAGAIN; return -EAGAIN;
} }
#endif /* jumpered_dma */ #endif /* JUMPERED_DMA */
PRINTK3((KERN_DEBUG "%s: passed open() #2\n", dev->name)); PRINTK3((KERN_DEBUG "%s: passed open() #2\n", dev->name));
/* Reset the hardware here. Don't forget to set the station address. */ /* 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; int ioaddr = dev->base_addr;
PRINTK2((KERN_DEBUG "%s: entering ni5010_close\n", dev->name)); PRINTK2((KERN_DEBUG "%s: entering ni5010_close\n", dev->name));
#ifdef jumpered_interrupts #ifdef JUMPERED_INTERRUPTS
free_irq(dev->irq, NULL); free_irq(dev->irq, NULL);
#endif #endif
/* Put card in held-RESET state */ /* 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(io, "ni5010 I/O base address");
MODULE_PARM_DESC(irq, "ni5010 IRQ number"); 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)); PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));
/* /*
@ -792,13 +786,15 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void __exit ni5010_cleanup_module(void)
{ {
PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname)); PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));
unregister_netdev(dev_ni5010); unregister_netdev(dev_ni5010);
release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT); release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);
free_netdev(dev_ni5010); free_netdev(dev_ni5010);
} }
module_init(ni5010_init_module);
module_exit(ni5010_cleanup_module);
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -803,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
writel(dev->IMR_cache, dev->base + IMR); writel(dev->IMR_cache, dev->base + IMR);
writel(1, dev->base + IER); writel(1, dev->base + IER);
spin_unlock_irq(&dev->misc_lock); spin_unlock(&dev->misc_lock);
kick_rx(ndev); kick_rx(ndev);
@ -1012,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev)
struct ns83820 *dev = PRIV(ndev); struct ns83820 *dev = PRIV(ndev);
u32 cmdsts, tx_done_idx, *desc; u32 cmdsts, tx_done_idx, *desc;
spin_lock_irq(&dev->tx_lock);
dprintk("do_tx_done(%p)\n", ndev); dprintk("do_tx_done(%p)\n", ndev);
tx_done_idx = dev->tx_done_idx; tx_done_idx = dev->tx_done_idx;
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); 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_start_queue(ndev);
netif_wake_queue(ndev); netif_wake_queue(ndev);
} }
spin_unlock_irq(&dev->tx_lock);
} }
static void ns83820_cleanup_tx(struct ns83820 *dev) static void ns83820_cleanup_tx(struct ns83820 *dev)
@ -1281,11 +1278,13 @@ static struct ethtool_ops ops = {
.get_link = ns83820_get_link .get_link = ns83820_get_link
}; };
/* this function is called in irq context from the ISR */
static void ns83820_mib_isr(struct ns83820 *dev) 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); 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); 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) static void ns83820_do_isr(struct net_device *ndev, u32 isr)
{ {
struct ns83820 *dev = PRIV(ndev); struct ns83820 *dev = PRIV(ndev);
unsigned long flags;
#ifdef DEBUG #ifdef DEBUG
if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC)) 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); 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) { if ((ISR_RXDESC | ISR_RXOK) & isr) {
prefetch(dev->rx_info.next_rx_desc); 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); dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK);
writel(dev->IMR_cache, dev->base + IMR); 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); tasklet_schedule(&dev->rx_tasklet);
//rx_irq(ndev); //rx_irq(ndev);
@ -1370,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
* work has accumulated * work has accumulated
*/ */
if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) { if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) {
spin_lock_irqsave(&dev->tx_lock, flags);
do_tx_done(ndev); do_tx_done(ndev);
spin_unlock_irqrestore(&dev->tx_lock, flags);
/* Disable TxOk if there are no outstanding tx packets. /* Disable TxOk if there are no outstanding tx packets.
*/ */
if ((dev->tx_done_idx == dev->tx_free_idx) && if ((dev->tx_done_idx == dev->tx_free_idx) &&
(dev->IMR_cache & ISR_TXOK)) { (dev->IMR_cache & ISR_TXOK)) {
spin_lock_irq(&dev->misc_lock); spin_lock_irqsave(&dev->misc_lock, flags);
dev->IMR_cache &= ~ISR_TXOK; dev->IMR_cache &= ~ISR_TXOK;
writel(dev->IMR_cache, dev->base + IMR); 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. * nature are expected, we must enable TxOk.
*/ */
if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) { 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; dev->IMR_cache |= ISR_TXOK;
writel(dev->IMR_cache, dev->base + IMR); 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 */ /* 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; u32 tx_done_idx, *desc;
unsigned long flags; unsigned long flags;
local_irq_save(flags); spin_lock_irqsave(&dev->tx_lock, flags);
tx_done_idx = dev->tx_done_idx; tx_done_idx = dev->tx_done_idx;
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
@ -1482,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
ndev->name, ndev->name,
tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS])); 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) 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)) { } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
using_dac = 0; using_dac = 0;
} else { } 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; 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); err = pci_enable_device(pci_dev);
if (err) { 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; 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, err = request_irq(pci_dev->irq, ns83820_irq, IRQF_SHARED,
DRV_NAME, ndev); DRV_NAME, ndev);
if (err) { if (err) {
printk(KERN_INFO "ns83820: unable to register irq %d\n", dev_info(&pci_dev->dev, "unable to register irq %d, err %d\n",
pci_dev->irq); pci_dev->irq, err);
goto out_disable; goto out_disable;
} }
@ -1899,7 +1902,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
rtnl_lock(); rtnl_lock();
err = dev_alloc_name(ndev, ndev->name); err = dev_alloc_name(ndev, ndev->name);
if (err < 0) { 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; goto out_free_irq;
} }

View File

@ -601,7 +601,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* dev zeroed in alloc_etherdev */ /* dev zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp)); dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) { 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"); DPRINTK ("EXIT, returning -ENOMEM\n");
return -ENOMEM; return -ENOMEM;
} }
@ -631,14 +631,14 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* make sure PCI base addr 0 is PIO */ /* make sure PCI base addr 0 is PIO */
if (!(pio_flags & IORESOURCE_IO)) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
/* make sure PCI base addr 1 is MMIO */ /* make sure PCI base addr 1 is MMIO */
if (!(mmio_flags & IORESOURCE_MEM)) { 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; rc = -ENODEV;
goto err_out; goto err_out;
} }
@ -646,12 +646,12 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* check for weird/broken PCI region reporting */ /* check for weird/broken PCI region reporting */
if ((pio_len < NETDRV_MIN_IO_SIZE) || if ((pio_len < NETDRV_MIN_IO_SIZE) ||
(mmio_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; rc = -ENODEV;
goto err_out; goto err_out;
} }
rc = pci_request_regions (pdev, "pci-skeleton"); rc = pci_request_regions (pdev, MODNAME);
if (rc) if (rc)
goto err_out; goto err_out;
@ -663,7 +663,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* ioremap MMIO region */ /* ioremap MMIO region */
ioaddr = ioremap (mmio_start, mmio_len); ioaddr = ioremap (mmio_start, mmio_len);
if (ioaddr == NULL) { if (ioaddr == NULL) {
printk (KERN_ERR PFX "cannot remap MMIO, aborting\n"); dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
rc = -EIO; rc = -EIO;
goto err_out_free_res; 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 */ /* 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", dev_printk (KERN_DEBUG, &pdev->dev,
pci_name(pdev)); "unknown chip version, assuming RTL-8139\n");
printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pci_name(pdev), NETDRV_R32 (TxConfig)); dev_printk (KERN_DEBUG, &pdev->dev, "TxConfig = 0x%lx\n",
NETDRV_R32 (TxConfig));
tp->chipset = 0; tp->chipset = 0;
match: match:

View File

@ -58,18 +58,15 @@ static const char *const version =
* PCI device identifiers for "new style" Linux PCI Device Drivers * PCI device identifiers for "new style" Linux PCI Device Drivers
*/ */
static struct pci_device_id pcnet32_pci_tbl[] = { static struct pci_device_id pcnet32_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* /*
* Adapters that were sold with IBM's RS/6000 or pSeries hardware have * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
* the incorrect vendor id. * the incorrect vendor id.
*/ */
{ PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, { PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
PCI_ANY_ID, PCI_ANY_ID, .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, },
PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{ } /* terminate list */ { } /* terminate list */
}; };
@ -188,6 +185,23 @@ static int homepna[MAX_UNITS];
#define PCNET32_TOTAL_SIZE 0x20 #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. */ /* The PCNET32 Rx and Tx ring descriptors. */
struct pcnet32_rx_head { struct pcnet32_rx_head {
u32 base; u32 base;
@ -277,7 +291,6 @@ struct pcnet32_private {
u32 phymask; u32 phymask;
}; };
static void pcnet32_probe_vlbus(void);
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); 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_probe1(unsigned long, int, struct pci_dev *);
static int pcnet32_open(struct net_device *); static int pcnet32_open(struct net_device *);
@ -419,6 +432,238 @@ static struct pcnet32_access pcnet32_dwio = {
.reset = pcnet32_dwio_reset .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 #ifdef CONFIG_NET_POLL_CONTROLLER
static void pcnet32_poll_controller(struct net_device *dev) 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; struct pcnet32_private *lp = dev->priv;
ering->tx_max_pending = TX_MAX_RING_SIZE - 1; ering->tx_max_pending = TX_MAX_RING_SIZE;
ering->tx_pending = lp->tx_ring_size - 1; ering->tx_pending = lp->tx_ring_size;
ering->rx_max_pending = RX_MAX_RING_SIZE - 1; ering->rx_max_pending = RX_MAX_RING_SIZE;
ering->rx_pending = lp->rx_ring_size - 1; ering->rx_pending = lp->rx_ring_size;
} }
static int pcnet32_set_ringparam(struct net_device *dev, 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; struct pcnet32_private *lp = dev->priv;
unsigned long flags; unsigned long flags;
unsigned int size;
ulong ioaddr = dev->base_addr;
int i; int i;
if (ering->rx_mini_pending || ering->rx_jumbo_pending) if (ering->rx_mini_pending || ering->rx_jumbo_pending)
return -EINVAL; return -EINVAL;
if (netif_running(dev)) if (netif_running(dev))
pcnet32_close(dev); pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
pcnet32_free_ring(dev); lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
lp->tx_ring_size =
min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE); 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);
/* set the minimum ring size to 4, to allow the loopback test to work /* set the minimum ring size to 4, to allow the loopback test to work
* unchanged. * unchanged.
*/ */
for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) { for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
if (lp->tx_ring_size <= (1 << i)) if (size <= (1 << i))
break; break;
} }
lp->tx_ring_size = (1 << i); if ((1 << i) != lp->tx_ring_size)
lp->tx_mod_mask = lp->tx_ring_size - 1; pcnet32_realloc_tx_ring(dev, lp, i);
lp->tx_len_bits = (i << 12);
size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) { for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
if (lp->rx_ring_size <= (1 << i)) if (size <= (1 << i))
break; break;
} }
lp->rx_ring_size = (1 << i); if ((1 << i) != lp->rx_ring_size)
lp->rx_mod_mask = lp->rx_ring_size - 1; pcnet32_realloc_rx_ring(dev, lp, i);
lp->rx_len_bits = (i << 4);
dev->weight = lp->rx_ring_size / 2;
if (pcnet32_alloc_ring(dev, dev->name)) { if (netif_running(dev)) {
pcnet32_free_ring(dev); pcnet32_netif_start(dev);
spin_unlock_irqrestore(&lp->lock, flags); pcnet32_restart(dev, CSR0_NORMAL);
return -ENOMEM;
} }
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk(KERN_INFO PFX printk(KERN_INFO
"%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name, "%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name,
lp->rx_ring_size, lp->tx_ring_size); lp->rx_ring_size, lp->tx_ring_size);
if (netif_running(dev))
pcnet32_open(dev);
return 0; return 0;
} }
@ -633,29 +875,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
unsigned long flags; unsigned long flags;
unsigned long ticks; unsigned long ticks;
*data1 = 1; /* status of test, default to fail */
rc = 1; /* default to fail */ rc = 1; /* default to fail */
if (netif_running(dev)) if (netif_running(dev))
pcnet32_close(dev); pcnet32_close(dev);
spin_lock_irqsave(&lp->lock, flags); 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 */ /* Reset the PCNET32 */
lp->a.reset(ioaddr); lp->a.reset(ioaddr);
lp->a.write_csr(ioaddr, CSR4, 0x0915);
/* switch pcnet32 to 32bit mode */ /* switch pcnet32 to 32bit mode */
lp->a.write_bcr(ioaddr, 20, 2); 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 */ /* purge & init rings but don't actually restart */
pcnet32_restart(dev, 0x0000); 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. */ /* Initialize Transmit buffers. */
size = data_len + 15; 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 = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */
x = x | 0x0002; a->write_bcr(ioaddr, 32, x | 0x0002);
a->write_bcr(ioaddr, 32, x);
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); 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 */ /* Check status of descriptors */
for (x = 0; x < numbuffs; x++) { for (x = 0; x < numbuffs; x++) {
@ -712,7 +953,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
rmb(); rmb();
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) { while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1); msleep(1);
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
rmb(); rmb();
ticks++; 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(); wmb();
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); 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++; x++;
} }
if (!rc) {
*data1 = 0;
}
clean_up: clean_up:
*data1 = rc;
pcnet32_purge_tx_ring(dev); 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 = a->read_bcr(ioaddr, 32); /* reset internal loopback */
x = x & ~0x0002; a->write_bcr(ioaddr, 32, (x & ~0x0002));
a->write_bcr(ioaddr, 32, x);
spin_unlock_irqrestore(&lp->lock, flags);
if (netif_running(dev)) { if (netif_running(dev)) {
spin_unlock_irqrestore(&lp->lock, flags);
pcnet32_open(dev); pcnet32_open(dev);
} else { } else {
pcnet32_purge_rx_ring(dev);
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(&lp->lock, flags);
} }
return (rc); return (rc);
@ -839,6 +1079,43 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
return 0; 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_REGS_PER_PHY 32
#define PCNET32_MAX_PHYS 32 #define PCNET32_MAX_PHYS 32
static int pcnet32_get_regs_len(struct net_device *dev) 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_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a; struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr; ulong ioaddr = dev->base_addr;
int ticks;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0); csr0 = a->read_csr(ioaddr, CSR0);
if (!(csr0 & 0x0004)) { /* If not stopped */ if (!(csr0 & CSR0_STOP)) /* If not stopped */
/* set SUSPEND (SPND) - CSR5 bit 0 */ pcnet32_suspend(dev, &flags, 1);
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;
}
}
}
/* read address PROM */ /* read address PROM */
for (i = 0; i < 16; i += 2) 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 */ /* 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); 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 /* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */ * 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; 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_size,
&lp->tx_ring_dma_addr); &lp->tx_ring_dma_addr);
if (lp->tx_ring == NULL) { if (lp->tx_ring == NULL) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Consistent memory allocation failed.\n", "%s: Consistent memory allocation failed.\n",
name); name);
@ -1448,52 +1709,48 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
lp->rx_ring_size, lp->rx_ring_size,
&lp->rx_ring_dma_addr); &lp->rx_ring_dma_addr);
if (lp->rx_ring == NULL) { if (lp->rx_ring == NULL) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Consistent memory allocation failed.\n", "%s: Consistent memory allocation failed.\n",
name); name);
return -ENOMEM; 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); GFP_ATOMIC);
if (!lp->tx_dma_addr) { if (!lp->tx_dma_addr) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name); "%s: Memory allocation failed.\n", name);
return -ENOMEM; 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); GFP_ATOMIC);
if (!lp->rx_dma_addr) { if (!lp->rx_dma_addr) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name); "%s: Memory allocation failed.\n", name);
return -ENOMEM; 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); GFP_ATOMIC);
if (!lp->tx_skbuff) { if (!lp->tx_skbuff) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name); "%s: Memory allocation failed.\n", name);
return -ENOMEM; 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); GFP_ATOMIC);
if (!lp->rx_skbuff) { if (!lp->rx_skbuff) {
if (pcnet32_debug & NETIF_MSG_DRV) if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name); "%s: Memory allocation failed.\n", name);
return -ENOMEM; return -ENOMEM;
} }
memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
return 0; return 0;
} }
@ -1757,16 +2014,7 @@ static int pcnet32_open(struct net_device *dev)
err_free_ring: err_free_ring:
/* free any allocated skbuffs */ /* free any allocated skbuffs */
for (i = 0; i < lp->rx_ring_size; i++) { pcnet32_purge_rx_ring(dev);
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;
}
/* /*
* Switch back to 16bit mode to avoid problems with dumb * 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; unsigned long ioaddr = dev->base_addr;
struct pcnet32_private *lp = dev->priv; struct pcnet32_private *lp = dev->priv;
int i;
unsigned long flags; unsigned long flags;
del_timer_sync(&lp->watchdog_timer); del_timer_sync(&lp->watchdog_timer);
@ -2379,31 +2626,8 @@ static int pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */ pcnet32_purge_rx_ring(dev);
for (i = 0; i < lp->rx_ring_size; i++) { pcnet32_purge_tx_ring(dev);
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;
}
spin_unlock_irqrestore(&lp->lock, flags); 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 struct pcnet32_init_block *ib = &lp->init_block;
volatile u16 *mcast_table = (u16 *) & ib->filter; volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list; struct dev_mc_list *dmi = dev->mc_list;
unsigned long ioaddr = dev->base_addr;
char *addrs; char *addrs;
int i; int i;
u32 crc; u32 crc;
@ -2441,6 +2666,10 @@ static void pcnet32_load_multicast(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
ib->filter[0] = 0xffffffff; ib->filter[0] = 0xffffffff;
ib->filter[1] = 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; return;
} }
/* clear the multicast filter */ /* 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]) | le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) |
(1 << (crc & 0xf))); (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; return;
} }
@ -2472,8 +2704,11 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
{ {
unsigned long ioaddr = dev->base_addr, flags; unsigned long ioaddr = dev->base_addr, flags;
struct pcnet32_private *lp = dev->priv; struct pcnet32_private *lp = dev->priv;
int csr15, suspended;
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
suspended = pcnet32_suspend(dev, &flags, 0);
csr15 = lp->a.read_csr(ioaddr, CSR15);
if (dev->flags & IFF_PROMISC) { if (dev->flags & IFF_PROMISC) {
/* Log any net taps. */ /* Log any net taps. */
if (netif_msg_hw(lp)) if (netif_msg_hw(lp))
@ -2482,15 +2717,24 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
lp->init_block.mode = lp->init_block.mode =
le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
7); 7);
lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000);
} else { } else {
lp->init_block.mode = lp->init_block.mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff);
pcnet32_load_multicast(dev); pcnet32_load_multicast(dev);
} }
lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ if (suspended) {
pcnet32_restart(dev, 0x0042); /* Resume normal operation */ int csr5;
netif_wake_queue(dev); /* 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); spin_unlock_irqrestore(&lp->lock, flags);
} }
@ -2730,7 +2974,7 @@ static int __init pcnet32_init_module(void)
/* should we find any remaining VLbus devices ? */ /* should we find any remaining VLbus devices ? */
if (pcnet32vlb) if (pcnet32vlb)
pcnet32_probe_vlbus(); pcnet32_probe_vlbus(pcnet32_portlist);
if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE)) if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
printk(KERN_INFO PFX "%d cards_found.\n", cards_found); printk(KERN_INFO PFX "%d cards_found.\n", cards_found);

View File

@ -103,7 +103,22 @@ static int cis820x_config_intr(struct phy_device *phydev)
return err; 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 = { static struct phy_driver cis8204_driver = {
.phy_id = 0x000fc440, .phy_id = 0x000fc440,
.name = "Cicada Cis8204", .name = "Cicada Cis8204",
@ -118,15 +133,30 @@ static struct phy_driver cis8204_driver = {
.driver = { .owner = THIS_MODULE,}, .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(&cis8204_driver);
phy_driver_unregister(&cis8201_driver);
} }
module_init(cis8204_init); module_init(cicada_init);
module_exit(cis8204_exit); module_exit(cicada_exit);

View File

@ -1406,7 +1406,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
dev = alloc_etherdev(sizeof (*tp)); dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) { if (dev == NULL) {
if (netif_msg_drv(&debug)) 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; 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) */ /* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX "%s: enable failure\n", dev_err(&pdev->dev, "enable failure\n");
pci_name(pdev));
}
goto err_out_free_dev; 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); pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
} else { } else {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX dev_err(&pdev->dev,
"PowerManagement capability not found.\n"); "PowerManagement capability not found.\n");
}
} }
/* make sure PCI base addr 1 is MMIO */ /* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX dev_err(&pdev->dev,
"region #1 not an MMIO resource, aborting\n"); "region #1 not an MMIO resource, aborting\n");
}
rc = -ENODEV; rc = -ENODEV;
goto err_out_mwi; goto err_out_mwi;
} }
/* check for weird/broken PCI region reporting */ /* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX dev_err(&pdev->dev,
"Invalid PCI region size(s), aborting\n"); "Invalid PCI region size(s), aborting\n");
}
rc = -ENODEV; rc = -ENODEV;
goto err_out_mwi; goto err_out_mwi;
} }
rc = pci_request_regions(pdev, MODULENAME); rc = pci_request_regions(pdev, MODULENAME);
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX "%s: could not request regions.\n", dev_err(&pdev->dev, "could not request regions.\n");
pci_name(pdev));
}
goto err_out_mwi; goto err_out_mwi;
} }
@ -1480,10 +1473,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} else { } else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp))
printk(KERN_ERR PFX dev_err(&pdev->dev,
"DMA configuration failed.\n"); "DMA configuration failed.\n");
}
goto err_out_free_res; 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); ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
if (ioaddr == NULL) { if (ioaddr == NULL) {
if (netif_msg_probe(tp)) 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; rc = -EIO;
goto err_out_free_res; goto err_out_free_res;
} }
@ -1526,9 +1518,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
if (i < 0) { if (i < 0) {
/* Unknown chip: assume array element #0, original RTL-8169 */ /* Unknown chip: assume array element #0, original RTL-8169 */
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp)) {
printk(KERN_DEBUG PFX "PCI device %s: " dev_printk(KERN_DEBUG, &pdev->dev,
"unknown chip version, assuming %s\n", "unknown chip version, assuming %s\n",
pci_name(pdev), rtl_chip_info[0].name); rtl_chip_info[0].name);
} }
i++; i++;
} }

View File

@ -22,129 +22,13 @@
Support and updates available at Support and updates available at
http://www.scyld.com/network/starfire.html 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_NAME "starfire"
#define DRV_VERSION "1.03+LK1.4.2.1" #define DRV_VERSION "2.0"
#define DRV_RELDATE "October 3, 2005" #define DRV_RELDATE "June 27, 2006"
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -846,7 +730,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
goto err_out_free_netdev; goto err_out_free_netdev;
} }
/* ioremap is borken in Linux-2.2.x/sparc64 */
base = ioremap(ioaddr, io_size); base = ioremap(ioaddr, io_size);
if (!base) { if (!base) {
printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n", printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",

View File

@ -16,91 +16,13 @@
Support and updates available at Support and updates available at
http://www.scyld.com/network/sundance.html 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_NAME "sundance"
#define DRV_VERSION "1.01+LK1.11" #define DRV_VERSION "1.1"
#define DRV_RELDATE "14-Jun-2006" #define DRV_RELDATE "27-Jun-2006"
/* The user-configurable values. /* The user-configurable values.
@ -282,15 +204,15 @@ IVc. Errata
#define USE_IO_OPS 1 #define USE_IO_OPS 1
#endif #endif
static struct pci_device_id sundance_pci_tbl[] = { static const struct pci_device_id sundance_pci_tbl[] = {
{0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0}, { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
{0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1}, { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
{0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2}, { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3}, { 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 },
{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, { 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
{0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
{0,} { }
}; };
MODULE_DEVICE_TABLE(pci, sundance_pci_tbl); MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
@ -301,7 +223,7 @@ enum {
struct pci_id_info { struct pci_id_info {
const char *name; 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-550TX FAST Ethernet Adapter"},
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
{"D-Link DFE-580TX 4 port Server 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"}, {"D-Link DL10050-based FAST Ethernet Adapter"},
{"Sundance Technology Alta"}, {"Sundance Technology Alta"},
{"IC Plus Corporation IP100A FAST Ethernet Adapter"}, {"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 /* This driver was written to use PCI memory space, however x86-oriented

View File

@ -224,24 +224,21 @@ static const struct pci_device_id w840_pci_tbl[] = {
}; };
MODULE_DEVICE_TABLE(pci, w840_pci_tbl); MODULE_DEVICE_TABLE(pci, w840_pci_tbl);
enum {
netdev_res_size = 128, /* size of PCI BAR resource */
};
struct pci_id_info { struct pci_id_info {
const char *name; const char *name;
struct match_info { int drv_flags; /* Driver use, intended as capability flags. */
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 struct pci_id_info pci_id_tbl[] = {
{"Winbond W89c840", /* Sometime a Level-One switch card. */ static const struct pci_id_info pci_id_tbl[] __devinitdata = {
{ 0x08401050, 0xffffffff, 0x81530000, 0xffff0000 }, { /* Sometime a Level-One switch card. */
128, CanHaveMII | HasBrokenTx | FDXOnNoMII}, "Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII},
{"Winbond W89c840", { 0x08401050, 0xffffffff, }, { "Winbond W89c840", CanHaveMII | HasBrokenTx},
128, CanHaveMII | HasBrokenTx}, { "Compex RL100-ATX", CanHaveMII | HasBrokenTx},
{"Compex RL100-ATX", { 0x201111F6, 0xffffffff,}, { } /* terminate list. */
128, CanHaveMII | HasBrokenTx},
{NULL,}, /* 0 terminated list. */
}; };
/* This driver was written to use PCI memory space, however some x86 systems /* 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 #ifdef USE_IO_OPS
bar = 0; bar = 0;
#endif #endif
ioaddr = pci_iomap(pdev, bar, pci_id_tbl[chip_idx].io_size); ioaddr = pci_iomap(pdev, bar, netdev_res_size);
if (!ioaddr) if (!ioaddr)
goto err_out_free_res; goto err_out_free_res;

View File

@ -10,26 +10,11 @@
410 Severn Ave., Suite 210 410 Severn Ave., Suite 210
Annapolis MD 21403 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_NAME "xircom_tulip_cb"
#define DRV_VERSION "0.91+LK1.1" #define DRV_VERSION "0.92"
#define DRV_RELDATE "October 11, 2001" #define DRV_RELDATE "June 27, 2006"
#define CARDBUS 1
/* A few user-configurable values. */ /* A few user-configurable values. */
@ -306,10 +291,10 @@ struct xircom_private {
struct xircom_tx_desc tx_ring[TX_RING_SIZE]; struct xircom_tx_desc tx_ring[TX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE];
#ifdef CARDBUS
/* The X3201-3 requires 4-byte aligned tx bufs */ /* The X3201-3 requires 4-byte aligned tx bufs */
struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE]; struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
#endif
/* The addresses of receive-in-place skbuffs. */ /* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE]; struct sk_buff* rx_skbuff[RX_RING_SIZE];
u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)]; /* Pseudo-Tx frame to init address table. */ 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_skbuff[i] = NULL;
tp->tx_ring[i].status = 0; tp->tx_ring[i].status = 0;
tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]); tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
#ifdef CARDBUS
if (tp->chip_id == X3201_3) if (tp->chip_id == X3201_3)
tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ); 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]); 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; entry = tp->cur_tx % TX_RING_SIZE;
tp->tx_skbuff[entry] = skb; tp->tx_skbuff[entry] = skb;
#ifdef CARDBUS
if (tp->chip_id == X3201_3) { if (tp->chip_id == X3201_3) {
memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len); 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); tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
} else } else
#endif
tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data); tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */

View File

@ -25,117 +25,13 @@
version. He may or may not be interested in bug reports on this version. He may or may not be interested in bug reports on this
code. You can find his versions at: code. You can find his versions at:
http://www.scyld.com/network/via-rhine.html http://www.scyld.com/network/via-rhine.html
[link no longer provides useful info -jgarzik]
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.
*/ */
#define DRV_NAME "via-rhine" #define DRV_NAME "via-rhine"
#define DRV_VERSION "1.2.0-2.6" #define DRV_VERSION "1.4.0"
#define DRV_RELDATE "June-10-2004" #define DRV_RELDATE "June-27-2006"
/* A few user-configurable values. /* A few user-configurable values.
@ -356,12 +252,11 @@ enum rhine_quirks {
/* Beware of PCI posted writes */ /* Beware of PCI posted writes */
#define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0) #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
static struct pci_device_id rhine_pci_tbl[] = static const struct pci_device_id rhine_pci_tbl[] = {
{ { 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */
{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */ { 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */
{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */ { 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */
{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */ { 0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6105M */
{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */
{ } /* terminate list */ { } /* terminate list */
}; };
MODULE_DEVICE_TABLE(pci, rhine_pci_tbl); MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);

View File

@ -229,7 +229,8 @@ static int rx_copybreak = 200;
module_param(rx_copybreak, int, 0644); module_param(rx_copybreak, int, 0644);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); 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 int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
static void velocity_print_info(struct velocity_info *vptr); static void velocity_print_info(struct velocity_info *vptr);
static int velocity_open(struct net_device *dev); 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 * Internal board variants. At the moment we have only one
*/ */
static struct velocity_info_tbl chip_info_table[] = { static const struct velocity_info_tbl chip_info_table[] __devinitdata = {
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, 0x00FFFFFFUL}, {CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
{0, NULL} { }
}; };
/* /*
@ -304,10 +305,9 @@ static struct velocity_info_tbl chip_info_table[] = {
* device driver. Used for hotplug autoloading. * device driver. Used for hotplug autoloading.
*/ */
static struct pci_device_id velocity_id_table[] __devinitdata = { static const struct pci_device_id velocity_id_table[] __devinitdata = {
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table}, { }
{0, }
}; };
MODULE_DEVICE_TABLE(pci, velocity_id_table); 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) static void __devexit velocity_remove1(struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(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 #ifdef CONFIG_PM
unsigned long flags; unsigned long flags;
@ -686,21 +686,23 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
static int first = 1; static int first = 1;
struct net_device *dev; struct net_device *dev;
int i; 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 velocity_info *vptr;
struct mac_regs __iomem * regs; struct mac_regs __iomem * regs;
int ret = -ENOMEM; int ret = -ENOMEM;
/* FIXME: this driver, like almost all other ethernet drivers,
* can support more than MAX_UNITS.
*/
if (velocity_nics >= MAX_UNITS) { if (velocity_nics >= MAX_UNITS) {
printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", dev_notice(&pdev->dev, "already found %d NICs.\n",
velocity_nics); velocity_nics);
return -ENODEV; return -ENODEV;
} }
dev = alloc_etherdev(sizeof(struct velocity_info)); dev = alloc_etherdev(sizeof(struct velocity_info));
if (!dev) {
if (dev == NULL) { dev_err(&pdev->dev, "allocate net device failed.\n");
printk(KERN_ERR VELOCITY_NAME ": allocate net device failed.\n");
goto out; goto out;
} }
@ -708,7 +710,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
vptr = dev->priv; vptr = netdev_priv(dev);
if (first) { 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); ret = velocity_get_pci_info(vptr, pdev);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n"); /* error message already printed */
goto err_disable; goto err_disable;
} }
ret = pci_request_regions(pdev, VELOCITY_NAME); ret = pci_request_regions(pdev, VELOCITY_NAME);
if (ret < 0) { 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; goto err_disable;
} }
regs = ioremap(vptr->memaddr, vptr->io_size); regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
if (regs == NULL) { if (regs == NULL) {
ret = -EIO; ret = -EIO;
goto err_release_res; goto err_release_res;
@ -859,13 +861,14 @@ static void __devinit velocity_print_info(struct velocity_info *vptr)
* discovered. * 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)); memset(vptr, 0, sizeof(struct velocity_info));
vptr->pdev = pdev; vptr->pdev = pdev;
vptr->chip_id = info->chip_id; vptr->chip_id = info->chip_id;
vptr->io_size = info->io_size;
vptr->num_txq = info->txqueue; vptr->num_txq = info->txqueue;
vptr->multicast_limit = MCAM_SIZE; vptr->multicast_limit = MCAM_SIZE;
spin_lock_init(&vptr->lock); 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) 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; return -EIO;
pci_set_master(pdev); 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->ioaddr = pci_resource_start(pdev, 0);
vptr->memaddr = pci_resource_start(pdev, 1); vptr->memaddr = pci_resource_start(pdev, 1);
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
{ dev_err(&pdev->dev,
printk(KERN_ERR "%s: region #0 is not an I/O resource, aborting.\n", "region #0 is not an I/O resource, aborting.\n");
pci_name(pdev));
return -EINVAL; return -EINVAL;
} }
if((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
{ dev_err(&pdev->dev,
printk(KERN_ERR "%s: region #1 is an I/O resource, aborting.\n", "region #1 is an I/O resource, aborting.\n");
pci_name(pdev));
return -EINVAL; return -EINVAL;
} }
if(pci_resource_len(pdev, 1) < 256) if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
{ dev_err(&pdev->dev, "region #1 is too small.\n");
printk(KERN_ERR "%s: region #1 is too small.\n",
pci_name(pdev));
return -EINVAL; return -EINVAL;
} }
vptr->pdev = pdev; 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) static int velocity_open(struct net_device *dev)
{ {
struct velocity_info *vptr = dev->priv; struct velocity_info *vptr = netdev_priv(dev);
int ret; int ret;
vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32); 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) 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; unsigned long flags;
int oldmtu = dev->mtu; int oldmtu = dev->mtu;
int ret = 0; int ret = 0;
@ -1861,7 +1859,7 @@ static void velocity_shutdown(struct velocity_info *vptr)
static int velocity_close(struct net_device *dev) 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); netif_stop_queue(dev);
velocity_shutdown(vptr); 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) 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; int qnum = 0;
struct tx_desc *td_ptr; struct tx_desc *td_ptr;
struct velocity_td_info *tdinfo; 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) static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
{ {
struct net_device *dev = dev_instance; struct net_device *dev = dev_instance;
struct velocity_info *vptr = dev->priv; struct velocity_info *vptr = netdev_priv(dev);
u32 isr_status; u32 isr_status;
int max_count = 0; 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) 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; struct mac_regs __iomem * regs = vptr->mac_regs;
u8 rx_mode; u8 rx_mode;
int i; 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) 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 the hardware is down, don't touch MII */
if(!netif_running(dev)) 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) 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; int ret;
/* If we are asked for information and the device is power /* 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) 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)) if (!netif_running(dev))
pci_set_power_state(vptr->pdev, PCI_D0); pci_set_power_state(vptr->pdev, PCI_D0);
return 0; return 0;
@ -2841,14 +2839,14 @@ static int velocity_ethtool_up(struct net_device *dev)
static void velocity_ethtool_down(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)) if (!netif_running(dev))
pci_set_power_state(vptr->pdev, PCI_D3hot); pci_set_power_state(vptr->pdev, PCI_D3hot);
} }
static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 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; struct mac_regs __iomem * regs = vptr->mac_regs;
u32 status; u32 status;
status = check_connection_type(vptr->mac_regs); 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) 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 curr_status;
u32 new_status = 0; u32 new_status = 0;
int ret = 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) 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; struct mac_regs __iomem * regs = vptr->mac_regs;
return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 0 : 1; return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 0 : 1;
} }
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) 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->driver, VELOCITY_NAME);
strcpy(info->version, VELOCITY_VERSION); strcpy(info->version, VELOCITY_VERSION);
strcpy(info->bus_info, pci_name(vptr->pdev)); 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) 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->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP;
wol->wolopts |= WAKE_MAGIC; 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) 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))) if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP)))
return -EFAULT; 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) 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; struct mac_regs __iomem * regs = vptr->mac_regs;
unsigned long flags; unsigned long flags;
struct mii_ioctl_data *miidata = if_mii(ifr); struct mii_ioctl_data *miidata = if_mii(ifr);

View File

@ -31,6 +31,8 @@
#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver" #define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
#define VELOCITY_VERSION "1.13" #define VELOCITY_VERSION "1.13"
#define VELOCITY_IO_SIZE 256
#define PKT_BUF_SZ 1540 #define PKT_BUF_SZ 1540
#define MAX_UNITS 8 #define MAX_UNITS 8
@ -1191,7 +1193,6 @@ enum chip_type {
struct velocity_info_tbl { struct velocity_info_tbl {
enum chip_type chip_id; enum chip_type chip_id;
char *name; char *name;
int io_size;
int txqueue; int txqueue;
u32 flags; u32 flags;
}; };
@ -1751,7 +1752,6 @@ struct velocity_info {
struct mac_regs __iomem * mac_regs; struct mac_regs __iomem * mac_regs;
unsigned long memaddr; unsigned long memaddr;
unsigned long ioaddr; unsigned long ioaddr;
u32 io_size;
u8 rev_id; u8 rev_id;

View File

@ -134,18 +134,6 @@ config SEALEVEL_4021
The driver will be compiled as a module: the The driver will be compiled as a module: the
module will be called sealevel. 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 # Generic HDLC
config HDLC config HDLC
tristate "Generic HDLC layer" tristate "Generic HDLC layer"

View File

@ -28,7 +28,6 @@ obj-$(CONFIG_COSA) += syncppp.o cosa.o
obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o
obj-$(CONFIG_DSCC4) += dscc4.o obj-$(CONFIG_DSCC4) += dscc4.o
obj-$(CONFIG_LANMEDIA) += syncppp.o obj-$(CONFIG_LANMEDIA) += syncppp.o
obj-$(CONFIG_SYNCLINK_SYNCPPP) += syncppp.o
obj-$(CONFIG_X25_ASY) += x25_asy.o obj-$(CONFIG_X25_ASY) += x25_asy.o
obj-$(CONFIG_LANMEDIA) += lmc/ obj-$(CONFIG_LANMEDIA) += lmc/

View File

@ -550,6 +550,7 @@ config USB_ZD1201
source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
# yes, this works even when no drivers are selected # yes, this works even when no drivers are selected
config NET_WIRELESS config NET_WIRELESS

View File

@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/
obj-$(CONFIG_HOSTAP) += hostap/ obj-$(CONFIG_HOSTAP) += hostap/
obj-$(CONFIG_BCM43XX) += bcm43xx/ obj-$(CONFIG_BCM43XX) += bcm43xx/
obj-$(CONFIG_ZD1211RW) += zd1211rw/
# 16-bit wireless PCMCIA client drivers # 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o

View File

@ -1885,6 +1885,15 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
spin_lock(&bcm->irq_lock); 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); reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) { if (reason == 0xffffffff) {
/* irq not for us (shared irq) */ /* 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); bcm43xx_interrupt_ack(bcm, reason);
/* Only accept IRQs, if we are initialized properly. /* disable all IRQs. They are enabled again in the bottom half. */
* This avoids an RX race while initializing. bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
* We should probably not enable IRQs before we are initialized /* save the reason code and call our bottom half. */
* completely, but some careful work is needed to fix this. I think it bcm->irq_reason = reason;
* is best to stay with this cheap workaround for now... . tasklet_schedule(&bcm->isr_tasklet);
*/
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);
}
out: out:
mmiowb(); mmiowb();
@ -3698,6 +3699,10 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
secinfo->encrypt = sec->encrypt; secinfo->encrypt = sec->encrypt;
dprintk(", .encrypt = %d", 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"); dprintk("\n");
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
!bcm->ieee->host_encrypt) { !bcm->ieee->host_encrypt) {

View File

@ -112,30 +112,6 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
return bcm43xx_channel_to_freq_bg(channel); 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_read(struct bcm43xx_private *bcm, u64 *tsf);
void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);

View File

@ -1594,11 +1594,11 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
u16 r8, tmp; u16 r8, tmp;
u16 freq; u16 freq;
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
return -EINVAL;
if ((radio->manufact == 0x17F) && if ((radio->manufact == 0x17F) &&
(radio->version == 0x2060) && (radio->version == 0x2060) &&
(radio->revision == 1)) { (radio->revision == 1)) {
if (channel > 200)
return -EINVAL;
freq = channel2freq_a(channel); freq = channel2freq_a(channel);
r8 = bcm43xx_radio_read16(bcm, 0x0008); r8 = bcm43xx_radio_read16(bcm, 0x0008);
@ -1651,9 +1651,6 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
TODO(); //TODO: TSSI2dbm workaround TODO(); //TODO: TSSI2dbm workaround
bcm43xx_phy_xmitpower(bcm);//FIXME correct? bcm43xx_phy_xmitpower(bcm);//FIXME correct?
} else { } else {
if ((channel < 1) || (channel > 14))
return -EINVAL;
if (synthetic_pu_workaround) if (synthetic_pu_workaround)
bcm43xx_synth_pu_workaround(bcm, channel); bcm43xx_synth_pu_workaround(bcm, channel);

View File

@ -119,7 +119,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
channel = bcm43xx_freq_to_channel(bcm, data->freq.m); channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
freq = 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; goto out_unlock;
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
//ieee80211softmac_disassoc(softmac, $REASON); //ieee80211softmac_disassoc(softmac, $REASON);

View File

@ -296,11 +296,14 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
u16 control = 0; u16 control = 0;
u16 wsec_rate = 0; u16 wsec_rate = 0;
u16 encrypt_frame; 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. */ /* Now construct the TX header. */
memset(txhdr, 0, sizeof(*txhdr)); 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)); ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));

View File

@ -66,10 +66,12 @@ static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"), PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"), PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
PLXDEV(0x126c, 0x8030, "Nortel emobility"), PLXDEV(0x126c, 0x8030, "Nortel emobility"),
PLXDEV(0x1562, 0x0001, "Symbol LA-4123"),
PLXDEV(0x1385, 0x4100, "Netgear MA301"), PLXDEV(0x1385, 0x4100, "Netgear MA301"),
PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"), PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"), PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"), PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
PLXDEV(0x16ab, 0x1100, "Global Sun Tech GL24110P"),
PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"), PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"), PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
PLXDEV(0x16ab, 0x1103, "Longshine 8031"), PLXDEV(0x16ab, 0x1103, "Longshine 8031"),

View 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.

View 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

File diff suppressed because it is too large Load Diff

View 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 */

View 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 */

View 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;
}

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

View 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);
}

View 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 */

View 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;
}

View 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 */

View 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;
}

View 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;
}

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

View 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);
}

View 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 */

View File

@ -19,37 +19,13 @@
Support and updates available at Support and updates available at
http://www.scyld.com/network/yellowfin.html 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_NAME "yellowfin"
#define DRV_VERSION "1.05+LK1.1.6" #define DRV_VERSION "2.0"
#define DRV_RELDATE "Feb 11, 2002" #define DRV_RELDATE "Jun 27, 2006"
#define PFX DRV_NAME ": " #define PFX DRV_NAME ": "
@ -239,8 +215,11 @@ enum capability_flags {
HasMACAddrBug=32, /* Only on early revs. */ HasMACAddrBug=32, /* Only on early revs. */
DontUseEeprom=64, /* Don't read the MAC from the EEPROm. */ DontUseEeprom=64, /* Don't read the MAC from the EEPROm. */
}; };
/* The PCI I/O space extent. */ /* The PCI I/O space extent. */
#define YELLOWFIN_SIZE 0x100 enum {
YELLOWFIN_SIZE = 0x100,
};
struct pci_id_info { struct pci_id_info {
const char *name; const char *name;
@ -248,16 +227,14 @@ struct pci_id_info {
int pci, pci_mask, subsystem, subsystem_mask; int pci, pci_mask, subsystem, subsystem_mask;
int revision, revision_mask; /* Only 8 bits. */ int revision, revision_mask; /* Only 8 bits. */
} id; } 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 const struct pci_id_info pci_id_tbl[] = { static const struct pci_id_info pci_id_tbl[] = {
{"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff}, {"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
YELLOWFIN_SIZE,
FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom}, FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom},
{"Symbios SYM83C885", { 0x07011000, 0xffffffff}, {"Symbios SYM83C885", { 0x07011000, 0xffffffff},
YELLOWFIN_SIZE, HasMII | DontUseEeprom }, HasMII | DontUseEeprom },
{ } { }
}; };

View File

@ -104,6 +104,7 @@ struct ieee80211softmac_assoc_info {
*/ */
u8 static_essid:1, u8 static_essid:1,
associating:1, associating:1,
assoc_wait:1,
bssvalid:1, bssvalid:1,
bssfixed:1; bssfixed:1;

View File

@ -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 /* Put this code here so that we avoid duplicating it in all
* Rx paths. - Jean II */ * Rx paths. - Jean II */
#ifdef CONFIG_WIRELESS_EXT
#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
/* If spy monitoring on */ /* If spy monitoring on */
if (ieee->spy_data.spy_number > 0) { 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); wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
} }
#endif /* IW_WIRELESS_SPY */ #endif /* IW_WIRELESS_SPY */
#endif /* CONFIG_WIRELESS_EXT */
#ifdef NOT_YET #ifdef NOT_YET
hostap_update_rx_stats(local->ap, hdr, rx_stats); hostap_update_rx_stats(local->ap, hdr, rx_stats);
#endif #endif
if (ieee->iw_mode == IW_MODE_MONITOR) { if (ieee->iw_mode == IW_MODE_MONITOR) {
ieee80211_monitor_rx(ieee, skb, rx_stats);
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += skb->len; stats->rx_bytes += skb->len;
ieee80211_monitor_rx(ieee, skb, rx_stats);
return 1; return 1;
} }

View File

@ -562,10 +562,13 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
struct net_device_stats *stats = &ieee->stats; struct net_device_stats *stats = &ieee->stats;
struct sk_buff *skb_frag; struct sk_buff *skb_frag;
int priority = -1; 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); spin_lock_irqsave(&ieee->lock, flags);
if (encrypt_mpdu && !ieee->sec.encrypt) if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
encrypt_mpdu = 0; encrypt_mpdu = 0;
/* If there is no driver handler to take the TXB, dont' bother /* 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; goto success;
} }
if (encrypt_mpdu) if (encrypt_mpdu) {
frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 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 /* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix, * and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */ * 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)) { if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n", printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name); ieee->dev->name);
goto failed; goto failed;
} }
txb->encrypted = 0; txb->encrypted = 0;
txb->payload_size = total_len; txb->payload_size = fraglen;
skb_frag = txb->fragments[0]; skb_frag = txb->fragments[0];

View File

@ -47,9 +47,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
dprintk(KERN_INFO PFX "sent association request!\n"); dprintk(KERN_INFO PFX "sent association request!\n");
/* Change the state to associating */
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
mac->associated = 0; /* just to make sure */ mac->associated = 0; /* just to make sure */
/* Set a timer for timeout */ /* Set a timer for timeout */
@ -63,6 +61,7 @@ void
ieee80211softmac_assoc_timeout(void *d) ieee80211softmac_assoc_timeout(void *d)
{ {
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
struct ieee80211softmac_network *n;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
@ -75,11 +74,12 @@ ieee80211softmac_assoc_timeout(void *d)
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0; mac->associnfo.bssvalid = 0;
mac->associated = 0; mac->associated = 0;
n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "assoc request timed out!\n"); 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, n);
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
} }
void void
@ -203,6 +203,10 @@ ieee80211softmac_assoc_work(void *d)
if (mac->associated) if (mac->associated)
ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 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 */ /* try to find the requested network in our list, if we found one already */
if (bssvalid || mac->associnfo.bssfixed) if (bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 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); 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. */ /* 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, /* This relies on the fact that _auth_req only queues the work,
* otherwise adding the notification would be racy. */ * otherwise adding the notification would be racy. */
if (!ieee80211softmac_auth_req(mac, found)) { if (!ieee80211softmac_auth_req(mac, found)) {
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); if(!mac->associnfo.assoc_wait) {
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); 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 { } else {
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); 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); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
} }
return; return;
} }
/* finally! now we can start associating */ /* finally! now we can start associating */
mac->associnfo.assoc_wait = 0;
ieee80211softmac_assoc(mac, found); ieee80211softmac_assoc(mac, found);
} }

View File

@ -36,8 +36,9 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
struct ieee80211softmac_auth_queue_item *auth; struct ieee80211softmac_auth_queue_item *auth;
unsigned long flags; unsigned long flags;
if (net->authenticating) if (net->authenticating || net->authenticated)
return 0; return 0;
net->authenticating = 1;
/* Add the network if it's not already added */ /* Add the network if it's not already added */
ieee80211softmac_add_network(mac, net); ieee80211softmac_add_network(mac, net);
@ -92,7 +93,6 @@ ieee80211softmac_auth_queue(void *data)
return; return;
} }
net->authenticated = 0; net->authenticated = 0;
net->authenticating = 1;
/* add a timeout call so we eventually give up waiting for an auth reply */ /* add a timeout call so we eventually give up waiting for an auth reply */
schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
auth->retry--; auth->retry--;

View File

@ -229,6 +229,9 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
return 0; return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 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 (?) */ /* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10); (*pkt)->listen_interval = cpu_to_le16(10);

View File

@ -70,12 +70,44 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
char *extra) char *extra)
{ {
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
struct ieee80211softmac_network *n;
struct ieee80211softmac_auth_queue_item *authptr;
int length = 0; int length = 0;
unsigned long flags; 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); spin_lock_irqsave(&sm->lock, flags);
sm->associnfo.static_essid = 0; sm->associnfo.static_essid = 0;
sm->associnfo.assoc_wait = 0;
if (data->essid.flags && data->essid.length && extra /*required?*/) { if (data->essid.flags && data->essid.length && extra /*required?*/) {
length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE); length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);