diff options
Diffstat (limited to 'drivers/net')
193 files changed, 13762 insertions, 9122 deletions
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 29dfd47f41d2..5c5eebdb6914 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -171,12 +171,7 @@ struct net_device * __init el2_probe(int unit) err = do_el2_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -356,6 +351,10 @@ el2_probe1(struct net_device *dev, int ioaddr) dev->poll_controller = ei_poll; #endif + retval = register_netdev(dev); + if (retval) + goto out1; + if (dev->mem_start) printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", dev->name, ei_status.name, (wordlength+1)<<3, @@ -715,11 +714,8 @@ init_module(void) dev->base_addr = io[this_dev]; dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ if (do_el2_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_el2[found++] = dev; - continue; - } - cleanup_card(dev); + dev_el2[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 76fa8cc24085..111601ca4ca3 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -272,7 +272,7 @@ static inline void set_hsf(struct net_device *dev, int hsf) static int start_receive(struct net_device *, pcb_struct *); -inline static void adapter_reset(struct net_device *dev) +static inline void adapter_reset(struct net_device *dev) { unsigned long timeout; elp_device *adapter = dev->priv; @@ -1317,8 +1317,7 @@ static int __init elp_sense(struct net_device *dev) if (orig_HSR & DIR) { /* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */ outb(0, dev->base_addr + PORT_CONTROL); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(30*HZ/100); + msleep(300); if (inb_status(addr) & DIR) { if (elp_debug > 0) printk(notfound_msg, 2); @@ -1327,8 +1326,7 @@ static int __init elp_sense(struct net_device *dev) } else { /* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */ outb(DIR, dev->base_addr + PORT_CONTROL); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(30*HZ/100); + msleep(300); if (!(inb_status(addr) & DIR)) { if (elp_debug > 0) printk(notfound_msg, 3); diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index e843109d4f62..977935a3d898 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -217,6 +217,7 @@ static void el3_poll_controller(struct net_device *dev); static struct eisa_device_id el3_eisa_ids[] = { { "TCM5092" }, { "TCM5093" }, + { "TCM5095" }, { "" } }; diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index c4cf4fcd1344..91d1c4c24d9b 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -365,7 +365,7 @@ static int nopnp; #endif /* __ISAPNP__ */ static struct net_device *corkscrew_scan(int unit); -static void corkscrew_setup(struct net_device *dev, int ioaddr, +static int corkscrew_setup(struct net_device *dev, int ioaddr, struct pnp_dev *idev, int card_number); static int corkscrew_open(struct net_device *dev); static void corkscrew_timer(unsigned long arg); @@ -539,10 +539,9 @@ static struct net_device *corkscrew_scan(int unit) printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); /* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */ - corkscrew_setup(dev, ioaddr, idev, cards_found++); SET_NETDEV_DEV(dev, &idev->dev); pnp_cards++; - err = register_netdev(dev); + err = corkscrew_setup(dev, ioaddr, idev, cards_found++); if (!err) return dev; cleanup_card(dev); @@ -558,8 +557,7 @@ no_pnp: printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); - corkscrew_setup(dev, ioaddr, NULL, cards_found++); - err = register_netdev(dev); + err = corkscrew_setup(dev, ioaddr, NULL, cards_found++); if (!err) return dev; cleanup_card(dev); @@ -568,7 +566,7 @@ no_pnp: return NULL; } -static void corkscrew_setup(struct net_device *dev, int ioaddr, +static int corkscrew_setup(struct net_device *dev, int ioaddr, struct pnp_dev *idev, int card_number) { struct corkscrew_private *vp = netdev_priv(dev); @@ -691,6 +689,8 @@ static void corkscrew_setup(struct net_device *dev, int ioaddr, dev->get_stats = &corkscrew_get_stats; dev->set_multicast_list = &set_rx_mode; dev->ethtool_ops = &netdev_ethtool_ops; + + return register_netdev(dev); } @@ -822,7 +822,7 @@ static int corkscrew_open(struct net_device *dev) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[i].addr = isa_virt_to_bus(skb->tail); + vp->rx_ring[i].addr = isa_virt_to_bus(skb->data); } vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr); @@ -1406,7 +1406,7 @@ static int boomerang_rx(struct net_device *dev) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[entry].addr = isa_virt_to_bus(skb->tail); + vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data); vp->rx_skbuff[entry] = skb; } vp->rx_ring[entry].status = 0; /* Clear complete bit. */ diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 8f6b2fa13e28..9e1fe2e0478c 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -572,6 +572,10 @@ static int __init do_elmc_probe(struct net_device *dev) dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ #endif + retval = register_netdev(dev); + if (retval) + goto err_out; + return 0; err_out: mca_set_adapter_procfn(slot, NULL, NULL); @@ -600,12 +604,7 @@ struct net_device * __init elmc_probe(int unit) err = do_elmc_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -1275,6 +1274,7 @@ module_param_array(irq, int, NULL, 0); module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); +MODULE_LICENSE("GPL"); int init_module(void) { @@ -1288,12 +1288,9 @@ int init_module(void) dev->irq=irq[this_dev]; dev->base_addr=io[this_dev]; if (do_elmc_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_elmc[this_dev] = dev; - found++; - continue; - } - cleanup_card(dev); + dev_elmc[this_dev] = dev; + found++; + continue; } free_netdev(dev); if (io[this_dev]==0) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index b5e076043431..07746b95fd83 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1802,7 +1802,7 @@ vortex_open(struct net_device *dev) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); + vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); } if (i != RX_RING_SIZE) { int j; @@ -2202,9 +2202,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) if (vortex_debug > 6) { printk(KERN_DEBUG "boomerang_start_xmit()\n"); - if (vortex_debug > 3) - printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n", - dev->name, vp->cur_tx); + printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n", + dev->name, vp->cur_tx); } if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { @@ -2633,7 +2632,7 @@ boomerang_rx(struct net_device *dev) pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); /* 'skb_put()' points to the start of sk_buff data area. */ memcpy(skb_put(skb, pkt_len), - vp->rx_skbuff[entry]->tail, + vp->rx_skbuff[entry]->data, pkt_len); pci_dma_sync_single_for_device(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); vp->rx_copy++; @@ -2679,7 +2678,7 @@ boomerang_rx(struct net_device *dev) } skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); + vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); vp->rx_skbuff[entry] = skb; } vp->rx_ring[entry].status = 0; /* Clear complete bit. */ diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index d639cb8dc461..7b293f01c9ed 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -54,12 +54,14 @@ #include <linux/config.h> #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/compiler.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mii.h> @@ -91,16 +93,17 @@ KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver"); +MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL"); static int debug = -1; -MODULE_PARM (debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number"); /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ static int multicast_filter_limit = 32; -MODULE_PARM (multicast_filter_limit, "i"); +module_param(multicast_filter_limit, int, 0); MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses"); #define PFX DRV_NAME ": " @@ -186,6 +189,9 @@ enum { RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ LastFrag = (1 << 28), /* Final segment of a packet */ + LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ + MSSShift = 16, /* MSS value position */ + MSSMask = 0xfff, /* MSS value: 11 bits */ TxError = (1 << 23), /* Tx error summary */ RxError = (1 << 20), /* Rx error summary */ IPCS = (1 << 18), /* Calculate IP checksum */ @@ -312,7 +318,7 @@ struct cp_desc { struct ring_info { struct sk_buff *skb; dma_addr_t mapping; - unsigned frag; + u32 len; }; struct cp_dma_stats { @@ -394,6 +400,9 @@ struct cp_private { static void __cp_set_rx_mode (struct net_device *dev); static void cp_tx (struct cp_private *cp); static void cp_clean_rings (struct cp_private *cp); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void cp_poll_controller(struct net_device *dev); +#endif static struct pci_device_id cp_pci_tbl[] = { { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139, @@ -587,7 +596,7 @@ rx_status_loop: mapping = cp->rx_skb[rx_tail].mapping = - pci_map_single(cp->pdev, new_skb->tail, + pci_map_single(cp->pdev, new_skb->data, buflen, PCI_DMA_FROMDEVICE); cp->rx_skb[rx_tail].skb = new_skb; @@ -688,6 +697,19 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void cp_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + cp_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + static void cp_tx (struct cp_private *cp) { unsigned tx_head = cp->tx_head; @@ -707,7 +729,7 @@ static void cp_tx (struct cp_private *cp) BUG(); pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, - skb->len, PCI_DMA_TODEVICE); + cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { @@ -749,10 +771,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct cp_private *cp = netdev_priv(dev); unsigned entry; - u32 eor; + u32 eor, flags; #if CP_VLAN_TAG_USED u32 vlan_tag = 0; #endif + int mss = 0; spin_lock_irq(&cp->lock); @@ -772,6 +795,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; + if (dev->features & NETIF_F_TSO) + mss = skb_shinfo(skb)->tso_size; + if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; u32 len; @@ -783,26 +809,26 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) txd->addr = cpu_to_le64(mapping); wmb(); - if (skb->ip_summed == CHECKSUM_HW) { + flags = eor | len | DescOwn | FirstFrag | LastFrag; + + if (mss) + flags |= LargeSend | ((mss & MSSMask) << MSSShift); + else if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag | - IPCS | TCPCS); + flags |= IPCS | TCPCS; else if (ip->protocol == IPPROTO_UDP) - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag | - IPCS | UDPCS); + flags |= IPCS | UDPCS; else - BUG(); - } else - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag); + WARN_ON(1); /* we need a WARN() */ + } + + txd->opts1 = cpu_to_le32(flags); wmb(); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; - cp->tx_skb[entry].frag = 0; + cp->tx_skb[entry].len = len; entry = NEXT_TX(entry); } else { struct cp_desc *txd; @@ -820,7 +846,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) first_len, PCI_DMA_TODEVICE); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = first_mapping; - cp->tx_skb[entry].frag = 1; + cp->tx_skb[entry].len = first_len; entry = NEXT_TX(entry); for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { @@ -836,16 +862,19 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) len, PCI_DMA_TODEVICE); eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; - if (skb->ip_summed == CHECKSUM_HW) { - ctrl = eor | len | DescOwn | IPCS; + ctrl = eor | len | DescOwn; + + if (mss) + ctrl |= LargeSend | + ((mss & MSSMask) << MSSShift); + else if (skb->ip_summed == CHECKSUM_HW) { if (ip->protocol == IPPROTO_TCP) - ctrl |= TCPCS; + ctrl |= IPCS | TCPCS; else if (ip->protocol == IPPROTO_UDP) - ctrl |= UDPCS; + ctrl |= IPCS | UDPCS; else BUG(); - } else - ctrl = eor | len | DescOwn; + } if (frag == skb_shinfo(skb)->nr_frags - 1) ctrl |= LastFrag; @@ -860,7 +889,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; - cp->tx_skb[entry].frag = frag + 2; + cp->tx_skb[entry].len = len; entry = NEXT_TX(entry); } @@ -1072,9 +1101,8 @@ static int cp_refill_rx (struct cp_private *cp) skb_reserve(skb, RX_OFFSET); cp->rx_skb[i].mapping = pci_map_single(cp->pdev, - skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE); cp->rx_skb[i].skb = skb; - cp->rx_skb[i].frag = 0; cp->rx_ring[i].opts2 = 0; cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping); @@ -1126,9 +1154,6 @@ static void cp_clean_rings (struct cp_private *cp) { unsigned i; - memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE); - memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE); - for (i = 0; i < CP_RX_RING_SIZE; i++) { if (cp->rx_skb[i].skb) { pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping, @@ -1140,13 +1165,18 @@ static void cp_clean_rings (struct cp_private *cp) for (i = 0; i < CP_TX_RING_SIZE; i++) { if (cp->tx_skb[i].skb) { struct sk_buff *skb = cp->tx_skb[i].skb; + pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb(skb); + cp->tx_skb[i].len, PCI_DMA_TODEVICE); + if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag) + dev_kfree_skb(skb); cp->net_stats.tx_dropped++; } } + memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE); + memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE); + memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE); memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE); } @@ -1486,22 +1516,22 @@ static void cp_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { struct cp_private *cp = netdev_priv(dev); - unsigned int work = 100; int i; + memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); + /* begin NIC statistics dump */ cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); cpr32(StatsAddr); - while (work-- > 0) { + for (i = 0; i < 1000; i++) { if ((cpr32(StatsAddr) & DumpStats) == 0) break; - cpu_relax(); + udelay(10); } - - if (cpr32(StatsAddr) & DumpStats) - return /* -EIO */; + cpw32(StatsAddr, 0); + cpw32(StatsAddr + 4, 0); i = 0; tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); @@ -1538,6 +1568,8 @@ static struct ethtool_ops cp_ethtool_ops = { .set_tx_csum = ethtool_op_set_tx_csum, /* local! */ .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, .get_regs = cp_get_regs, .get_wol = cp_get_wol, .set_wol = cp_set_wol, @@ -1701,19 +1733,19 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) /* Configure DMA attributes. */ if ((sizeof(dma_addr_t) > 4) && - !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) && - !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) && + !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { pci_using_dac = 1; } else { pci_using_dac = 0; - rc = pci_set_dma_mask(pdev, 0xffffffffULL); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); goto err_out_res; } - rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL); + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR PFX "No usable consistent DMA configuration, " "aborting.\n"); @@ -1749,6 +1781,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->get_stats = cp_get_stats; dev->do_ioctl = cp_ioctl; dev->poll = cp_rx_poll; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = cp_poll_controller; +#endif dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */ #ifdef BROKEN dev->change_mtu = cp_change_mtu; @@ -1768,6 +1803,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; +#if 0 /* disabled by default until verified */ + dev->features |= NETIF_F_TSO; +#endif + dev->irq = pdev->irq; rc = register_netdev(dev); diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index d4bd20c21a1f..4c2cf7bbd252 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -126,14 +126,14 @@ #define USE_IO_OPS 1 #endif -/* define to 1 to enable copious debugging info */ -#undef RTL8139_DEBUG +/* define to 1, 2 or 3 to enable copious debugging info */ +#define RTL8139_DEBUG 0 /* define to 1 to disable lightweight runtime debugging checks */ #undef RTL8139_NDEBUG -#ifdef RTL8139_DEBUG +#if RTL8139_DEBUG /* note: prints function name for you */ # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) #else @@ -569,7 +569,7 @@ struct rtl_extra_stats { }; struct rtl8139_private { - void *mmio_addr; + void __iomem *mmio_addr; int drv_flags; struct pci_dev *pci_dev; u32 msg_enable; @@ -614,7 +614,7 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered mu MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); -static int read_eeprom (void *ioaddr, int location, int addr_len); +static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, @@ -638,46 +638,20 @@ static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); static struct ethtool_ops rtl8139_ethtool_ops; -#ifdef USE_IO_OPS - -#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg)) -#define RTL_R16(reg) inw (((unsigned long)ioaddr) + (reg)) -#define RTL_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg))) -#define RTL_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg)) -#define RTL_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg)) -#define RTL_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg)) -#define RTL_W8_F RTL_W8 -#define RTL_W16_F RTL_W16 -#define RTL_W32_F RTL_W32 -#undef readb -#undef readw -#undef readl -#undef writeb -#undef writew -#undef writel -#define readb(addr) inb((unsigned long)(addr)) -#define readw(addr) inw((unsigned long)(addr)) -#define readl(addr) inl((unsigned long)(addr)) -#define writeb(val,addr) outb((val),(unsigned long)(addr)) -#define writew(val,addr) outw((val),(unsigned long)(addr)) -#define writel(val,addr) outl((val),(unsigned long)(addr)) - -#else - /* write MMIO register, with flush */ /* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0) -#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0) -#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0) +#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0) +#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0) +#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0) #define MMIO_FLUSH_AUDIT_COMPLETE 1 #if MMIO_FLUSH_AUDIT_COMPLETE /* write MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) +#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg)) +#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg)) +#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg)) #else @@ -689,11 +663,9 @@ static struct ethtool_ops rtl8139_ethtool_ops; #endif /* MMIO_FLUSH_AUDIT_COMPLETE */ /* read MMIO register */ -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -#endif /* USE_IO_OPS */ +#define RTL_R8(reg) ioread8 (ioaddr + (reg)) +#define RTL_R16(reg) ioread16 (ioaddr + (reg)) +#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg))) static const u16 rtl8139_intr_mask = @@ -740,10 +712,13 @@ static void __rtl8139_cleanup_dev (struct net_device *dev) assert (tp->pci_dev != NULL); pdev = tp->pci_dev; -#ifndef USE_IO_OPS +#ifdef USE_IO_OPS + if (tp->mmio_addr) + ioport_unmap (tp->mmio_addr); +#else if (tp->mmio_addr) - iounmap (tp->mmio_addr); -#endif /* !USE_IO_OPS */ + pci_iounmap (pdev, tp->mmio_addr); +#endif /* USE_IO_OPS */ /* it's ok to call this even if we have no regions to free */ pci_release_regions (pdev); @@ -753,7 +728,7 @@ static void __rtl8139_cleanup_dev (struct net_device *dev) } -static void rtl8139_chip_reset (void *ioaddr) +static void rtl8139_chip_reset (void __iomem *ioaddr) { int i; @@ -773,7 +748,7 @@ static void rtl8139_chip_reset (void *ioaddr) static int __devinit rtl8139_init_board (struct pci_dev *pdev, struct net_device **dev_out) { - void *ioaddr; + void __iomem *ioaddr; struct net_device *dev; struct rtl8139_private *tp; u8 tmp8; @@ -855,13 +830,18 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev, pci_set_master (pdev); #ifdef USE_IO_OPS - ioaddr = (void *) pio_start; + ioaddr = ioport_map(pio_start, pio_len); + if (!ioaddr) { + printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev)); + rc = -EIO; + goto err_out; + } dev->base_addr = pio_start; tp->mmio_addr = ioaddr; tp->regs_len = pio_len; #else /* ioremap MMIO region */ - ioaddr = ioremap (mmio_start, mmio_len); + ioaddr = pci_iomap(pdev, 1, 0); if (ioaddr == NULL) { printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); rc = -EIO; @@ -947,7 +927,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, struct net_device *dev = NULL; struct rtl8139_private *tp; int i, addr_len, option; - void *ioaddr; + void __iomem *ioaddr; static int board_idx = -1; u8 pci_rev; @@ -1147,47 +1127,46 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. */ -#define eeprom_delay() readl(ee_addr) +#define eeprom_delay() RTL_R32(Cfg9346) /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5) #define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) +static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) { int i; unsigned retval = 0; - void *ee_addr = ioaddr + Cfg9346; int read_cmd = location | (EE_READ_CMD << addr_len); - writeb (EE_ENB & ~EE_CS, ee_addr); - writeb (EE_ENB, ee_addr); + RTL_W8 (Cfg9346, EE_ENB & ~EE_CS); + RTL_W8 (Cfg9346, EE_ENB); eeprom_delay (); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - writeb (EE_ENB | dataval, ee_addr); + RTL_W8 (Cfg9346, EE_ENB | dataval); eeprom_delay (); - writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK); eeprom_delay (); } - writeb (EE_ENB, ee_addr); + RTL_W8 (Cfg9346, EE_ENB); eeprom_delay (); for (i = 16; i > 0; i--) { - writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); + RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK); eeprom_delay (); retval = - (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : + (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 : 0); - writeb (EE_ENB, ee_addr); + RTL_W8 (Cfg9346, EE_ENB); eeprom_delay (); } /* Terminate the EEPROM access. */ - writeb (~EE_CS, ee_addr); + RTL_W8 (Cfg9346, ~EE_CS); eeprom_delay (); return retval; @@ -1206,7 +1185,7 @@ static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) #define MDIO_WRITE0 (MDIO_DIR) #define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) -#define mdio_delay(mdio_addr) readb(mdio_addr) +#define mdio_delay() RTL_R8(Config4) static char mii_2_8139_map[8] = { @@ -1223,15 +1202,15 @@ static char mii_2_8139_map[8] = { #ifdef CONFIG_8139TOO_8129 /* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void *mdio_addr) +static void mdio_sync (void __iomem *ioaddr) { int i; for (i = 32; i >= 0; i--) { - writeb (MDIO_WRITE1, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); + RTL_W8 (Config4, MDIO_WRITE1); + mdio_delay (); + RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK); + mdio_delay (); } } #endif @@ -1241,35 +1220,36 @@ static int mdio_read (struct net_device *dev, int phy_id, int location) struct rtl8139_private *tp = netdev_priv(dev); int retval = 0; #ifdef CONFIG_8139TOO_8129 - void *mdio_addr = tp->mmio_addr + Config4; + void __iomem *ioaddr = tp->mmio_addr; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i; #endif if (phy_id > 31) { /* Really a 8139. Use internal registers. */ + void __iomem *ioaddr = tp->mmio_addr; return location < 8 && mii_2_8139_map[location] ? - readw (tp->mmio_addr + mii_2_8139_map[location]) : 0; + RTL_R16 (mii_2_8139_map[location]) : 0; } #ifdef CONFIG_8139TOO_8129 - mdio_sync (mdio_addr); + mdio_sync (ioaddr); /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - writeb (MDIO_DIR | dataval, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); + RTL_W8 (Config4, MDIO_DIR | dataval); + mdio_delay (); + RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK); + mdio_delay (); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (mdio_addr); - retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); + RTL_W8 (Config4, 0); + mdio_delay (); + retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0); + RTL_W8 (Config4, MDIO_CLK); + mdio_delay (); } #endif @@ -1282,13 +1262,13 @@ static void mdio_write (struct net_device *dev, int phy_id, int location, { struct rtl8139_private *tp = netdev_priv(dev); #ifdef CONFIG_8139TOO_8129 - void *mdio_addr = tp->mmio_addr + Config4; + void __iomem *ioaddr = tp->mmio_addr; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; int i; #endif if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; if (location == 0) { RTL_W8 (Cfg9346, Cfg9346_Unlock); RTL_W16 (BasicModeCtrl, value); @@ -1299,23 +1279,23 @@ static void mdio_write (struct net_device *dev, int phy_id, int location, } #ifdef CONFIG_8139TOO_8129 - mdio_sync (mdio_addr); + mdio_sync (ioaddr); /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writeb (dataval, mdio_addr); - mdio_delay (mdio_addr); - writeb (dataval | MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); + RTL_W8 (Config4, dataval); + mdio_delay (); + RTL_W8 (Config4, dataval | MDIO_CLK); + mdio_delay (); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (mdio_addr); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (mdio_addr); + RTL_W8 (Config4, 0); + mdio_delay (); + RTL_W8 (Config4, MDIO_CLK); + mdio_delay (); } #endif } @@ -1325,7 +1305,7 @@ static int rtl8139_open (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); int retval; - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); if (retval) @@ -1382,7 +1362,7 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media) static void rtl8139_hw_start (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; u32 i; u8 tmp; @@ -1484,7 +1464,7 @@ static void rtl8139_tune_twister (struct net_device *dev, struct rtl8139_private *tp) { int linkcase; - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; /* This is a complicated state machine to configure the "twister" for impedance/echos based on the cable length. @@ -1568,7 +1548,7 @@ static void rtl8139_tune_twister (struct net_device *dev, static inline void rtl8139_thread_iter (struct net_device *dev, struct rtl8139_private *tp, - void *ioaddr) + void __iomem *ioaddr) { int mii_lpa; @@ -1626,7 +1606,7 @@ static int rtl8139_thread (void *data) do { timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); /* make swsusp happy with our thread */ - try_to_freeze(PF_FREEZE); + try_to_freeze(); } while (!signal_pending (current) && (timeout > 0)); if (signal_pending (current)) { @@ -1676,7 +1656,7 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) static void rtl8139_tx_timeout (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; int i; u8 tmp8; unsigned long flags; @@ -1721,7 +1701,7 @@ static void rtl8139_tx_timeout (struct net_device *dev) static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; unsigned int entry; unsigned int len = skb->len; @@ -1763,7 +1743,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) static void rtl8139_tx_interrupt (struct net_device *dev, struct rtl8139_private *tp, - void *ioaddr) + void __iomem *ioaddr) { unsigned long dirty_tx, tx_left; @@ -1833,7 +1813,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev, /* TODO: clean this up! Rx reset need not be this intensive */ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, - struct rtl8139_private *tp, void *ioaddr) + struct rtl8139_private *tp, void __iomem *ioaddr) { u8 tmp8; #ifdef CONFIG_8139_OLD_RX_RESET @@ -1930,7 +1910,7 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, static void rtl8139_isr_ack(struct rtl8139_private *tp) { - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; u16 status; status = RTL_R16 (IntrStatus) & RxAckBits; @@ -1949,7 +1929,7 @@ static void rtl8139_isr_ack(struct rtl8139_private *tp) static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int budget) { - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; int received = 0; unsigned char *rx_ring = tp->rx_ring; unsigned int cur_rx = tp->cur_rx; @@ -2087,7 +2067,7 @@ out: static void rtl8139_weird_interrupt (struct net_device *dev, struct rtl8139_private *tp, - void *ioaddr, + void __iomem *ioaddr, int status, int link_changed) { DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n", @@ -2127,7 +2107,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev, static int rtl8139_poll(struct net_device *dev, int *budget) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; int orig_budget = min(*budget, dev->quota); int done = 1; @@ -2165,7 +2145,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, { struct net_device *dev = (struct net_device *) dev_instance; struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; u16 status, ackstat; int link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; @@ -2241,7 +2221,7 @@ static void rtl8139_poll_controller(struct net_device *dev) static int rtl8139_close (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; int ret = 0; unsigned long flags; @@ -2304,7 +2284,7 @@ static int rtl8139_close (struct net_device *dev) static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8139_private *np = netdev_priv(dev); - void *ioaddr = np->mmio_addr; + void __iomem *ioaddr = np->mmio_addr; spin_lock_irq(&np->lock); if (rtl_chip_info[np->chipset].flags & HasLWake) { @@ -2338,7 +2318,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8139_private *np = netdev_priv(dev); - void *ioaddr = np->mmio_addr; + void __iomem *ioaddr = np->mmio_addr; u32 support; u8 cfg3, cfg5; @@ -2506,7 +2486,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; if (netif_running(dev)) { @@ -2525,7 +2505,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) static void __set_rx_mode (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; u32 mc_filter[2]; /* Multicast hash filter */ int i, rx_mode; u32 tmp; @@ -2586,7 +2566,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata (pdev); struct rtl8139_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; + void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; pci_save_state (pdev); diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 65f97b1dc581..13b745b39667 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -546,11 +546,11 @@ static inline void init_rx_bufs(struct net_device *dev) rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1)); rbd->b_addr = WSWAPrbd(virt_to_bus(rbd)); rbd->skb = skb; - rbd->v_data = skb->tail; - rbd->b_data = WSWAPchar(virt_to_bus(skb->tail)); + rbd->v_data = skb->data; + rbd->b_data = WSWAPchar(virt_to_bus(skb->data)); rbd->size = PKT_BUF_SZ; #ifdef __mc68000__ - cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ); + cache_clear(virt_to_phys(skb->data), PKT_BUF_SZ); #endif } lp->rbd_head = lp->rbds; @@ -816,10 +816,10 @@ static inline int i596_rx(struct net_device *dev) rx_in_place = 1; rbd->skb = newskb; newskb->dev = dev; - rbd->v_data = newskb->tail; - rbd->b_data = WSWAPchar(virt_to_bus(newskb->tail)); + rbd->v_data = newskb->data; + rbd->b_data = WSWAPchar(virt_to_bus(newskb->data)); #ifdef __mc68000__ - cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ); + cache_clear(virt_to_phys(newskb->data), PKT_BUF_SZ); #endif } else @@ -840,7 +840,7 @@ memory_squeeze: skb->protocol=eth_type_trans(skb,dev); skb->len = pkt_len; #ifdef __mc68000__ - cache_clear(virt_to_phys(rbd->skb->tail), + cache_clear(virt_to_phys(rbd->skb->data), pkt_len); #endif netif_rx(skb); diff --git a/drivers/net/8390.c b/drivers/net/8390.c index bab16bcc9ae5..6d76f3a99b17 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -225,9 +225,9 @@ void ei_tx_timeout(struct net_device *dev) unsigned long icucr; local_irq_save(flags); - icucr = inl(ICUCR1); + icucr = inl(M32R_ICU_CR1_PORTL); icucr |= M32R_ICUCR_ISMOD11; - outl(icucr, ICUCR1); + outl(icucr, M32R_ICU_CR1_PORTL); local_irq_restore(flags); #endif ei_local->stat.tx_errors++; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f08e01b2fd19..8a835eb58808 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3,6 +3,8 @@ # Network device configuration # +menu "Network device support" + config NETDEVICES depends on NET bool "Network device support" @@ -21,9 +23,12 @@ config NETDEVICES If unsure, say Y. +# All the following symbols are dependent on NETDEVICES - do not repeat +# that for each of the symbols. +if NETDEVICES + config DUMMY tristate "Dummy net driver support" - depends on NETDEVICES ---help--- This is essentially a bit-bucket device (i.e. traffic you send to this device is consigned into oblivion) with a configurable IP @@ -43,7 +48,6 @@ config DUMMY config BONDING tristate "Bonding driver support" - depends on NETDEVICES depends on INET ---help--- Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet @@ -61,7 +65,6 @@ config BONDING config EQUALIZER tristate "EQL (serial line load balancing) support" - depends on NETDEVICES ---help--- If you have two serial connections to some other computer (this usually requires two modems and two telephone lines) and you use @@ -81,7 +84,6 @@ config EQUALIZER config TUN tristate "Universal TUN/TAP device driver support" - depends on NETDEVICES select CRC32 ---help--- TUN/TAP provides packet reception and transmission for user space @@ -105,7 +107,7 @@ config TUN config NET_SB1000 tristate "General Instruments Surfboard 1000" - depends on NETDEVICES && PNP + depends on PNP ---help--- This is a driver for the General Instrument (also known as NextLevel) SURFboard 1000 internal @@ -127,16 +129,14 @@ config NET_SB1000 If you don't have this card, of course say N. -if NETDEVICES source "drivers/net/arcnet/Kconfig" -endif # # Ethernet # menu "Ethernet (10 or 100Mbit)" - depends on NETDEVICES && !UML + depends on !UML config NET_ETHERNET bool "Ethernet (10 or 100Mbit)" @@ -824,6 +824,18 @@ config SMC9194 <file:Documentation/networking/net-modules.txt>. The module will be called smc9194. +config DM9000 + tristate "DM9000 support" + depends on ARM && NET_ETHERNET + select CRC32 + select MII + ---help--- + Support for DM9000 chipset. + + To compile this driver as a module, choose M here and read + <file:Documentation/networking/net-modules.txt>. The module will be + called dm9000. + config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" depends on NET_ETHERNET && ISA @@ -989,21 +1001,6 @@ config EEXPRESS_PRO <file:Documentation/networking/net-modules.txt>. The module will be called eepro. -config FMV18X - tristate "FMV-181/182/183/184 support (OBSOLETE)" - depends on NET_ISA && OBSOLETE - ---help--- - If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card, - say Y and read the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - If you use an FMV-183 or FMV-184 and it is not working, you may need - to disable Plug & Play mode of the card. - - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module - will be called fmv18x. - config HPLAN_PLUS tristate "HP PCLAN+ (27247B and 27252A) support" depends on NET_ISA @@ -1092,14 +1089,6 @@ config SEEQ8005 <file:Documentation/networking/net-modules.txt>. The module will be called seeq8005. -config SK_G16 - tristate "SK_G16 support (OBSOLETE)" - depends on NET_ISA && OBSOLETE - help - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - config SKMC tristate "SKnet MCA support" depends on NET_ETHERNET && MCA && BROKEN @@ -1146,7 +1135,7 @@ config IBMLANA config IBMVETH tristate "IBM LAN Virtual Ethernet support" - depends on NETDEVICES && NET_ETHERNET && PPC_PSERIES + depends on NET_ETHERNET && PPC_PSERIES ---help--- This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. @@ -1331,7 +1320,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on NET_PCI && (ISA || ARCH_IXDP2X01) + depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the @@ -1499,14 +1488,14 @@ config 8139CP will be called 8139cp. This is recommended. config 8139TOO - tristate "RealTek RTL-8139 PCI Fast Ethernet Adapter support" + tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support" depends on NET_PCI && PCI select CRC32 select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on - the RTL8139 chips. If you have one of those, say Y and read - the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>. + the RTL 8129/8130/8139 chips. If you have one of those, say Y and + read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>. To compile this driver as a module, choose M here: the module will be called 8139too. This is recommended. @@ -1769,7 +1758,7 @@ endmenu # menu "Ethernet (1000 Mbit)" - depends on NETDEVICES && !UML + depends on !UML config ACENIC tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" @@ -1932,6 +1921,18 @@ config R8169_VLAN If in doubt, say Y. +config SKGE + tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)" + depends on PCI && EXPERIMENTAL + select CRC32 + ---help--- + This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx + and related Gigabit Ethernet adapters. It is a new smaller driver + driver with better performance and more complete ethtool support. + + It does not support the link failover and network management + features that "portable" vendor supplied sk98lin driver does. + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI @@ -2088,7 +2089,7 @@ endmenu # menu "Ethernet (10000 Mbit)" - depends on NETDEVICES && !UML + depends on !UML config IXGB tristate "Intel(R) PRO/10GbE support" @@ -2183,11 +2184,11 @@ source "drivers/s390/net/Kconfig" config ISERIES_VETH tristate "iSeries Virtual Ethernet driver support" - depends on NETDEVICES && PPC_ISERIES + depends on PPC_ISERIES config FDDI bool "FDDI driver support" - depends on NETDEVICES && (PCI || EISA) + depends on (PCI || EISA) help Fiber Distributed Data Interface is a high speed local area network design; essentially a replacement for high speed Ethernet. FDDI can @@ -2236,7 +2237,7 @@ config SKFP config HIPPI bool "HIPPI driver support (EXPERIMENTAL)" - depends on NETDEVICES && EXPERIMENTAL && INET && PCI + depends on EXPERIMENTAL && INET && PCI help HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI @@ -2268,7 +2269,7 @@ config ROADRUNNER_LARGE_RINGS config PLIP tristate "PLIP (parallel port) support" - depends on NETDEVICES && PARPORT + depends on PARPORT ---help--- PLIP (Parallel Line Internet Protocol) is used to create a reasonably fast mini network consisting of two (or, rarely, more) @@ -2304,7 +2305,6 @@ config PLIP config PPP tristate "PPP (point-to-point protocol) support" - depends on NETDEVICES ---help--- PPP (Point to Point Protocol) is a newer and better SLIP. It serves the same purpose: sending Internet traffic over telephone (and other @@ -2440,7 +2440,6 @@ config PPPOATM config SLIP tristate "SLIP (serial line) support" - depends on NETDEVICES ---help--- Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to connect to your Internet service provider or to connect to some @@ -2507,7 +2506,7 @@ config SLIP_MODE_SLIP6 config NET_FC bool "Fibre Channel driver support" - depends on NETDEVICES && SCSI && PCI + depends on SCSI && PCI help Fibre Channel is a high speed serial protocol mainly used to connect large storage devices to the computer; it is compatible with and @@ -2520,7 +2519,7 @@ config NET_FC config SHAPER tristate "Traffic Shaper (EXPERIMENTAL)" - depends on NETDEVICES && EXPERIMENTAL + depends on EXPERIMENTAL ---help--- The traffic shaper is a virtual network device that allows you to limit the rate of outgoing data flow over some other network device. @@ -2541,8 +2540,27 @@ config SHAPER config NETCONSOLE tristate "Network console logging support (EXPERIMENTAL)" - depends on NETDEVICES && EXPERIMENTAL + depends on EXPERIMENTAL ---help--- If you want to log kernel messages over the network, enable this. See <file:Documentation/networking/netconsole.txt> for details. +endif #NETDEVICES + +config NETPOLL + def_bool NETCONSOLE + +config NETPOLL_RX + bool "Netpoll support for trapping incoming packets" + default n + depends on NETPOLL + +config NETPOLL_TRAP + bool "Netpoll traffic trapping" + default n + depends on NETPOLL + +config NET_POLL_CONTROLLER + def_bool NETPOLL + +endmenu diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 30c7567001fe..63c6d1e6d4d9 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o obj-$(CONFIG_TC35815) += tc35815.o +obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SK98LIN) += sk98lin/ obj-$(CONFIG_SKFP) += skfp/ obj-$(CONFIG_VIA_RHINE) += via-rhine.o @@ -74,7 +75,6 @@ obj-$(CONFIG_MAC8390) += mac8390.o 8390.o obj-$(CONFIG_APNE) += apne.o 8390.o obj-$(CONFIG_PCMCIA_PCNET) += 8390.o obj-$(CONFIG_SHAPER) += shaper.o -obj-$(CONFIG_SK_G16) += sk_g16.o obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o @@ -122,7 +122,6 @@ obj-$(CONFIG_DEFXX) += defxx.o obj-$(CONFIG_SGISEEQ) += sgiseeq.o obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o obj-$(CONFIG_AT1700) += at1700.o -obj-$(CONFIG_FMV18X) += fmv18x.o obj-$(CONFIG_EL1) += 3c501.o obj-$(CONFIG_EL16) += 3c507.o obj-$(CONFIG_ELMC) += 3c523.o @@ -180,6 +179,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o obj-$(CONFIG_IBMVETH) += ibmveth.o obj-$(CONFIG_S2IO) += s2io.o obj-$(CONFIG_SMC91X) += smc91x.o +obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/net/Space.c b/drivers/net/Space.c index fb433325aa27..3707df6b0cfa 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -210,9 +210,6 @@ static struct devprobe2 isa_probes[] __initdata = { #ifdef CONFIG_AT1700 {at1700_probe, 0}, #endif -#ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */ - {fmv18x_probe, 0}, -#endif #ifdef CONFIG_ETH16I {eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */ #endif @@ -243,9 +240,6 @@ static struct devprobe2 isa_probes[] __initdata = { #ifdef CONFIG_ELPLUS /* 3c505 */ {elplus_probe, 0}, #endif -#ifdef CONFIG_SK_G16 - {SK_init, 0}, -#endif #ifdef CONFIG_NI5010 {ni5010_probe, 0}, #endif diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 24fba36b5c1d..91791ba37769 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -146,12 +146,7 @@ struct net_device * __init ac3200_probe(int unit) err = do_ac3200_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -273,7 +268,14 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); + + retval = register_netdev(dev); + if (retval) + goto out2; return 0; +out2: + if (ei_status.reg0) + iounmap((void *)dev->mem_start); out1: free_irq(dev->irq, dev); out: @@ -392,11 +394,8 @@ init_module(void) dev->base_addr = io[this_dev]; dev->mem_start = mem[this_dev]; /* Currently ignored by driver */ if (do_ac3200_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ac32[found++] = dev; - continue; - } - cleanup_card(dev); + dev_ac32[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 6eea3a8accb7..dbecc6bf7851 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -58,6 +58,7 @@ #include <linux/errno.h> #include <linux/ioport.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -1167,9 +1168,9 @@ static int __devinit ace_init(struct net_device *dev) /* * Configure DMA attributes. */ - if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { ap->pci_using_dac = 1; - } else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) { + } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { ap->pci_using_dac = 0; } else { ecode = -ENODEV; diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index b7dd7260cafb..d9ba8be72af8 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -87,6 +87,7 @@ Revision History: #include <linux/if_vlan.h> #include <linux/ctype.h> #include <linux/crc32.h> +#include <linux/dma-mapping.h> #include <asm/system.h> #include <asm/io.h> @@ -1289,7 +1290,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg writel(intr0, mmio + INT0); /* Check if Receive Interrupt has occurred. */ -#if CONFIG_AMD8111E_NAPI +#ifdef CONFIG_AMD8111E_NAPI if(intr0 & RINT0){ if(netif_rx_schedule_prep(dev)){ /* Disable receive interupts */ @@ -2006,12 +2007,11 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, } /* Initialize DMA */ - if(!pci_dma_supported(pdev, 0xffffffff)){ + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) < 0) { printk(KERN_ERR "amd8111e: DMA not supported," "exiting.\n"); - goto err_free_reg; - } else - pdev->dma_mask = 0xffffffff; + goto err_free_reg; + } reg_addr = pci_resource_start(pdev, 0); reg_len = pci_resource_len(pdev, 0); diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig index 69c488d933a2..b14e89004c3a 100644 --- a/drivers/net/appletalk/Kconfig +++ b/drivers/net/appletalk/Kconfig @@ -1,6 +1,33 @@ # # Appletalk driver configuration # +config ATALK + tristate "Appletalk protocol support" + select LLC + ---help--- + AppleTalk is the protocol that Apple computers can use to communicate + on a network. If your Linux box is connected to such a network and you + wish to connect to it, say Y. You will need to use the netatalk package + so that your Linux box can act as a print and file server for Macs as + well as access AppleTalk printers. Check out + <http://www.zettabyte.net/netatalk/> on the WWW for details. + EtherTalk is the name used for AppleTalk over Ethernet and the + cheaper and slower LocalTalk is AppleTalk over a proprietary Apple + network using serial links. EtherTalk and LocalTalk are fully + supported by Linux. + + General information about how to connect Linux, Windows machines and + Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>. The + NET-3-HOWTO, available from + <http://www.tldp.org/docs.html#howto>, contains valuable + information as well. + + To compile this driver as a module, choose M here: the module will be + called appletalk. You almost certainly want to compile it as a + module so you can restart your AppleTalk stack without rebooting + your machine. I hear that the GNU boycott of Apple is over, so + even politically correct people are allowed to say Y here. + config DEV_APPLETALK bool "Appletalk interfaces support" depends on ATALK diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index db4f369637b6..d5666c37cb0d 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1109,8 +1109,7 @@ struct net_device * __init ltpc_probe(void) inb_p(io+1); inb_p(io+3); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(2*HZ/100); + msleep(20); inb_p(io+0); inb_p(io+2); @@ -1120,8 +1119,7 @@ struct net_device * __init ltpc_probe(void) inb_p(io+5); /* enable dma */ inb_p(io+6); /* tri-state interrupt line */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); /* now, figure out which dma channel we're using, unless it's already been specified */ diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index b8ab2b6355eb..e613cc289749 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -34,10 +34,6 @@ only is it difficult to detect, it also moves around in I/O space in response to inb()s from other device probes! */ -/* - 99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa - 99/12/30 port to 2.3.35 by K.Takai -*/ #include <linux/config.h> #include <linux/errno.h> diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 5a2efd343db4..c82b9cd1c924 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -1681,10 +1681,6 @@ static int au1000_init(struct net_device *dev) control |= MAC_FULL_DUPLEX; } - /* fix for startup without cable */ - if (!link) - dev->flags &= ~IFF_RUNNING; - aup->mac->control = control; aup->mac->vlan1_tag = 0x8100; /* activate vlan support */ au_sync(); @@ -1709,16 +1705,14 @@ static void au1000_timer(unsigned long data) if_port = dev->if_port; if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) { if (link) { - if (!(dev->flags & IFF_RUNNING)) { + if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); - dev->flags |= IFF_RUNNING; printk(KERN_INFO "%s: link up\n", dev->name); } } else { - if (dev->flags & IFF_RUNNING) { + if (netif_carrier_ok(dev)) { netif_carrier_off(dev); - dev->flags &= ~IFF_RUNNING; dev->if_port = 0; printk(KERN_INFO "%s: link down\n", dev->name); } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 38844d003e44..94939f570f78 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1285,6 +1285,9 @@ static int b44_open(struct net_device *dev) b44_init_hw(bp); bp->flags |= B44_FLAG_INIT_COMPLETE; + netif_carrier_off(dev); + b44_check_phy(bp); + spin_unlock_irq(&bp->lock); init_timer(&bp->timer); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 734bd4ee3f9b..8dc657fc8afb 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1261,7 +1261,7 @@ static void bmac_reset_and_enable(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); } -static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_match *match) +static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match) { int j, rev, ret; struct bmac_data *bp; @@ -1412,7 +1412,6 @@ static int bmac_open(struct net_device *dev) bp->opened = 1; bmac_reset_and_enable(dev); enable_irq(dev->irq); - dev->flags |= IFF_RUNNING; return 0; } @@ -1425,7 +1424,6 @@ static int bmac_close(struct net_device *dev) int i; bp->sleeping = 1; - dev->flags &= ~(IFF_UP | IFF_RUNNING); /* disable rx and tx */ config = bmread(dev, RXCFG); @@ -1647,16 +1645,13 @@ static int __devexit bmac_remove(struct macio_dev *mdev) return 0; } -static struct of_match bmac_match[] = +static struct of_device_id bmac_match[] = { { .name = "bmac", - .type = OF_ANY_MATCH, - .compatible = OF_ANY_MATCH, .data = (void *)0, }, { - .name = OF_ANY_MATCH, .type = "network", .compatible = "bmac+", .data = (void *)1, diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 6233c4ffb805..a2e8dda5afac 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2346,7 +2346,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) { struct slave *slave, *start_at; struct bonding *bond = dev->priv; - struct ethhdr *data = (struct ethhdr *)skb->data; int slave_agg_no; int slaves_in_agg; int agg_id; @@ -2377,7 +2376,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) goto out; } - slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg; + slave_agg_no = bond->xmit_hash_policy(skb, dev, slaves_in_agg); bond_for_each_slave(bond, slave, i) { struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 269a5e407349..2c930da90a85 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -475,7 +475,18 @@ * Solution is to move call to dev_remove_pack outside of the * spinlock. * Set version to 2.6.1. - * + * 2005/06/05 - Jay Vosburgh <fubar@us.ibm.com> + * - Support for generating gratuitous ARPs in active-backup mode. + * Includes support for VLAN tagging all bonding-generated ARPs + * as needed. Set version to 2.6.2. + * 2005/06/08 - Jason Gabler <jygabler at lbl dot gov> + * - alternate hashing policy support for mode 2 + * * Added kernel parameter "xmit_hash_policy" to allow the selection + * of different hashing policies for mode 2. The original mode 2 + * policy is the default, now found in xmit_hash_policy_layer2(). + * * Added xmit_hash_policy_layer34() + * - Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4. + * Set version to 2.6.3. */ //#define BONDING_DEBUG 1 @@ -490,7 +501,10 @@ #include <linux/ptrace.h> #include <linux/ioport.h> #include <linux/in.h> +#include <net/ip.h> #include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/udp.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/init.h> @@ -519,6 +533,7 @@ #include <linux/ethtool.h> #include <linux/if_vlan.h> #include <linux/if_bonding.h> +#include <net/route.h> #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -537,6 +552,7 @@ static int use_carrier = 1; static char *mode = NULL; static char *primary = NULL; static char *lacp_rate = NULL; +static char *xmit_hash_policy = NULL; static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; @@ -556,6 +572,8 @@ module_param(primary, charp, 0); MODULE_PARM_DESC(primary, "Primary network device to use"); module_param(lacp_rate, charp, 0); MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)"); +module_param(xmit_hash_policy, charp, 0); +MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4"); module_param(arp_interval, int, 0); MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); module_param_array(arp_ip_target, charp, NULL, 0); @@ -574,8 +592,8 @@ static struct proc_dir_entry *bond_proc_dir = NULL; static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; static int arp_ip_count = 0; -static u32 my_ip = 0; static int bond_mode = BOND_MODE_ROUNDROBIN; +static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; static int lacp_fast = 0; static int app_abi_ver = 0; static int orig_app_abi_ver = -1; /* This is used to save the first ABI version @@ -585,7 +603,6 @@ static int orig_app_abi_ver = -1; /* This is used to save the first ABI version * command comes from an application using * another ABI version. */ - struct bond_parm_tbl { char *modename; int mode; @@ -608,9 +625,16 @@ static struct bond_parm_tbl bond_mode_tbl[] = { { NULL, -1}, }; +static struct bond_parm_tbl xmit_hashtype_tbl[] = { +{ "layer2", BOND_XMIT_POLICY_LAYER2}, +{ "layer3+4", BOND_XMIT_POLICY_LAYER34}, +{ NULL, -1}, +}; + /*-------------------------- Forward declarations ---------------------------*/ -static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode); +static inline void bond_set_mode_ops(struct bonding *bond, int mode); +static void bond_send_gratuitous_arp(struct bonding *bond); /*---------------------------- General routines -----------------------------*/ @@ -659,6 +683,7 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id) INIT_LIST_HEAD(&vlan->vlan_list); vlan->vlan_id = vlan_id; + vlan->vlan_ip = 0; write_lock_bh(&bond->lock); @@ -1468,16 +1493,6 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act } } - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { - if (old_active) { - bond_set_slave_inactive_flags(old_active); - } - - if (new_active) { - bond_set_slave_active_flags(new_active); - } - } - if (USES_PRIMARY(bond->params.mode)) { bond_mc_swap(bond, new_active, old_active); } @@ -1488,6 +1503,17 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act } else { bond->curr_active_slave = new_active; } + + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { + if (old_active) { + bond_set_slave_inactive_flags(old_active); + } + + if (new_active) { + bond_set_slave_active_flags(new_active); + } + bond_send_gratuitous_arp(bond); + } } /** @@ -2694,15 +2720,180 @@ out: read_unlock(&bond->lock); } + +static u32 bond_glean_dev_ip(struct net_device *dev) +{ + struct in_device *idev; + struct in_ifaddr *ifa; + u32 addr = 0; + + if (!dev) + return 0; + + rcu_read_lock(); + idev = __in_dev_get(dev); + if (!idev) + goto out; + + ifa = idev->ifa_list; + if (!ifa) + goto out; + + addr = ifa->ifa_local; +out: + rcu_read_unlock(); + return addr; +} + +static int bond_has_ip(struct bonding *bond) +{ + struct vlan_entry *vlan, *vlan_next; + + if (bond->master_ip) + return 1; + + if (list_empty(&bond->vlan_list)) + return 0; + + list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, + vlan_list) { + if (vlan->vlan_ip) + return 1; + } + + return 0; +} + +/* + * We go to the (large) trouble of VLAN tagging ARP frames because + * switches in VLAN mode (especially if ports are configured as + * "native" to a VLAN) might not pass non-tagged frames. + */ +static void bond_arp_send(struct net_device *slave_dev, int arp_op, u32 dest_ip, u32 src_ip, unsigned short vlan_id) +{ + struct sk_buff *skb; + + dprintk("arp %d on slave %s: dst %x src %x vid %d\n", arp_op, + slave_dev->name, dest_ip, src_ip, vlan_id); + + skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip, + NULL, slave_dev->dev_addr, NULL); + + if (!skb) { + printk(KERN_ERR DRV_NAME ": ARP packet allocation failed\n"); + return; + } + if (vlan_id) { + skb = vlan_put_tag(skb, vlan_id); + if (!skb) { + printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n"); + return; + } + } + arp_xmit(skb); +} + + static void bond_arp_send_all(struct bonding *bond, struct slave *slave) { - int i; + int i, vlan_id, rv; u32 *targets = bond->params.arp_targets; + struct vlan_entry *vlan, *vlan_next; + struct net_device *vlan_dev; + struct flowi fl; + struct rtable *rt; for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { - arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev, - my_ip, NULL, slave->dev->dev_addr, - NULL); + dprintk("basa: target %x\n", targets[i]); + if (list_empty(&bond->vlan_list)) { + dprintk("basa: empty vlan: arp_send\n"); + bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], + bond->master_ip, 0); + continue; + } + + /* + * If VLANs are configured, we do a route lookup to + * determine which VLAN interface would be used, so we + * can tag the ARP with the proper VLAN tag. + */ + memset(&fl, 0, sizeof(fl)); + fl.fl4_dst = targets[i]; + fl.fl4_tos = RTO_ONLINK; + + rv = ip_route_output_key(&rt, &fl); + if (rv) { + if (net_ratelimit()) { + printk(KERN_WARNING DRV_NAME + ": %s: no route to arp_ip_target %u.%u.%u.%u\n", + bond->dev->name, NIPQUAD(fl.fl4_dst)); + } + continue; + } + + /* + * This target is not on a VLAN + */ + if (rt->u.dst.dev == bond->dev) { + dprintk("basa: rtdev == bond->dev: arp_send\n"); + bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], + bond->master_ip, 0); + continue; + } + + vlan_id = 0; + list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, + vlan_list) { + vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + if (vlan_dev == rt->u.dst.dev) { + vlan_id = vlan->vlan_id; + dprintk("basa: vlan match on %s %d\n", + vlan_dev->name, vlan_id); + break; + } + } + + if (vlan_id) { + bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], + vlan->vlan_ip, vlan_id); + continue; + } + + if (net_ratelimit()) { + printk(KERN_WARNING DRV_NAME + ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n", + bond->dev->name, NIPQUAD(fl.fl4_dst), + rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); + } + } +} + +/* + * Kick out a gratuitous ARP for an IP on the bonding master plus one + * for each VLAN above us. + */ +static void bond_send_gratuitous_arp(struct bonding *bond) +{ + struct slave *slave = bond->curr_active_slave; + struct vlan_entry *vlan; + struct net_device *vlan_dev; + + dprintk("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name, + slave ? slave->dev->name : "NULL"); + if (!slave) + return; + + if (bond->master_ip) { + bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, + bond->master_ip, 0); + } + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + if (vlan->vlan_ip) { + bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip, + vlan->vlan_ip, vlan->vlan_id); + } } } @@ -2781,7 +2972,7 @@ static void bond_loadbalance_arp_mon(struct net_device *bond_dev) */ if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && - my_ip)) { + bond_has_ip(bond))) { slave->link = BOND_LINK_DOWN; slave->state = BOND_STATE_BACKUP; @@ -2920,7 +3111,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev) if ((slave != bond->curr_active_slave) && (!bond->current_arp_slave) && (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) && - my_ip)) { + bond_has_ip(bond))) { /* a backup slave has gone down; three times * the delta allows the current slave to be * taken out before the backup slave. @@ -2966,8 +3157,8 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev) * if it is up and needs to take over as the curr_active_slave */ if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || - (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && - my_ip)) && + (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && + bond_has_ip(bond))) && ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { slave->link = BOND_LINK_DOWN; @@ -3019,7 +3210,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev) /* the current slave must tx an arp to ensure backup slaves * rx traffic */ - if (slave && my_ip) { + if (slave && bond_has_ip(bond)) { bond_arp_send_all(bond, slave); } } @@ -3471,10 +3662,67 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v return NOTIFY_DONE; } +/* + * bond_inetaddr_event: handle inetaddr notifier chain events. + * + * We keep track of device IPs primarily to use as source addresses in + * ARP monitor probes (rather than spewing out broadcasts all the time). + * + * We track one IP for the main device (if it has one), plus one per VLAN. + */ +static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct in_ifaddr *ifa = ptr; + struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev; + struct bonding *bond, *bond_next; + struct vlan_entry *vlan, *vlan_next; + + list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) { + if (bond->dev == event_dev) { + switch (event) { + case NETDEV_UP: + bond->master_ip = ifa->ifa_local; + return NOTIFY_OK; + case NETDEV_DOWN: + bond->master_ip = bond_glean_dev_ip(bond->dev); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } + } + + if (list_empty(&bond->vlan_list)) + continue; + + list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, + vlan_list) { + vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + if (vlan_dev == event_dev) { + switch (event) { + case NETDEV_UP: + vlan->vlan_ip = ifa->ifa_local; + return NOTIFY_OK; + case NETDEV_DOWN: + vlan->vlan_ip = + bond_glean_dev_ip(vlan_dev); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } + } + } + } + return NOTIFY_DONE; +} + static struct notifier_block bond_netdev_notifier = { .notifier_call = bond_netdev_event, }; +static struct notifier_block bond_inetaddr_notifier = { + .notifier_call = bond_inetaddr_event, +}; + /*-------------------------- Packet type handling ---------------------------*/ /* register to receive lacpdus on a bond */ @@ -3496,6 +3744,46 @@ static void bond_unregister_lacpdu(struct bonding *bond) dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); } +/*---------------------------- Hashing Policies -----------------------------*/ + +/* + * Hash for the the output device based upon layer 3 and layer 4 data. If + * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is + * altogether not IP, mimic bond_xmit_hash_policy_l2() + */ +static int bond_xmit_hash_policy_l34(struct sk_buff *skb, + struct net_device *bond_dev, int count) +{ + struct ethhdr *data = (struct ethhdr *)skb->data; + struct iphdr *iph = skb->nh.iph; + u16 *layer4hdr = (u16 *)((u32 *)iph + iph->ihl); + int layer4_xor = 0; + + if (skb->protocol == __constant_htons(ETH_P_IP)) { + if (!(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) && + (iph->protocol == IPPROTO_TCP || + iph->protocol == IPPROTO_UDP)) { + layer4_xor = htons((*layer4hdr ^ *(layer4hdr + 1))); + } + return (layer4_xor ^ + ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count; + + } + + return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; +} + +/* + * Hash for the output device based upon layer 2 data + */ +static int bond_xmit_hash_policy_l2(struct sk_buff *skb, + struct net_device *bond_dev, int count) +{ + struct ethhdr *data = (struct ethhdr *)skb->data; + + return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; +} + /*-------------------------- Device entry points ----------------------------*/ static int bond_open(struct net_device *bond_dev) @@ -4060,17 +4348,6 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d struct bonding *bond = bond_dev->priv; int res = 1; - /* if we are sending arp packets, try to at least - identify our own ip address */ - if (bond->params.arp_interval && !my_ip && - (skb->protocol == __constant_htons(ETH_P_ARP))) { - char *the_ip = (char *)skb->data + - sizeof(struct ethhdr) + - sizeof(struct arphdr) + - ETH_ALEN; - memcpy(&my_ip, the_ip, 4); - } - read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); @@ -4093,14 +4370,13 @@ out: } /* - * in XOR mode, we determine the output device by performing xor on - * the source and destination hw adresses. If this device is not - * enabled, find the next slave following this xor slave. + * In bond_xmit_xor() , we determine the output device by using a pre- + * determined xmit_hash_policy(), If the selected device is not enabled, + * find the next active slave. */ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; - struct ethhdr *data = (struct ethhdr *)skb->data; struct slave *slave, *start_at; int slave_no; int i; @@ -4112,7 +4388,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) goto out; } - slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt; + slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt); bond_for_each_slave(bond, slave, i) { slave_no--; @@ -4208,8 +4484,10 @@ out: /* * set bond mode specific net device operations */ -static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode) +static inline void bond_set_mode_ops(struct bonding *bond, int mode) { + struct net_device *bond_dev = bond->dev; + switch (mode) { case BOND_MODE_ROUNDROBIN: bond_dev->hard_start_xmit = bond_xmit_roundrobin; @@ -4219,12 +4497,20 @@ static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode) break; case BOND_MODE_XOR: bond_dev->hard_start_xmit = bond_xmit_xor; + if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) + bond->xmit_hash_policy = bond_xmit_hash_policy_l34; + else + bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; case BOND_MODE_BROADCAST: bond_dev->hard_start_xmit = bond_xmit_broadcast; break; case BOND_MODE_8023AD: bond_dev->hard_start_xmit = bond_3ad_xmit_xor; + if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) + bond->xmit_hash_policy = bond_xmit_hash_policy_l34; + else + bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; case BOND_MODE_TLB: case BOND_MODE_ALB: @@ -4273,7 +4559,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par bond_dev->change_mtu = bond_change_mtu; bond_dev->set_mac_address = bond_set_mac_address; - bond_set_mode_ops(bond_dev, bond->params.mode); + bond_set_mode_ops(bond, bond->params.mode); bond_dev->destructor = free_netdev; @@ -4384,6 +4670,25 @@ static int bond_check_params(struct bond_params *params) } } + if (xmit_hash_policy) { + if ((bond_mode != BOND_MODE_XOR) && + (bond_mode != BOND_MODE_8023AD)) { + printk(KERN_INFO DRV_NAME + ": xor_mode param is irrelevant in mode %s\n", + bond_mode_name(bond_mode)); + } else { + xmit_hashtype = bond_parse_parm(xmit_hash_policy, + xmit_hashtype_tbl); + if (xmit_hashtype == -1) { + printk(KERN_ERR DRV_NAME + ": Error: Invalid xmit_hash_policy \"%s\"\n", + xmit_hash_policy == NULL ? "NULL" : + xmit_hash_policy); + return -EINVAL; + } + } + } + if (lacp_rate) { if (bond_mode != BOND_MODE_8023AD) { printk(KERN_INFO DRV_NAME @@ -4595,6 +4900,7 @@ static int bond_check_params(struct bond_params *params) /* fill params struct with the proper values */ params->mode = bond_mode; + params->xmit_policy = xmit_hashtype; params->miimon = miimon; params->arp_interval = arp_interval; params->updelay = updelay; @@ -4669,6 +4975,7 @@ static int __init bonding_init(void) rtnl_unlock(); register_netdevice_notifier(&bond_netdev_notifier); + register_inetaddr_notifier(&bond_inetaddr_notifier); return 0; @@ -4684,6 +4991,7 @@ out_err: static void __exit bonding_exit(void) { unregister_netdevice_notifier(&bond_netdev_notifier); + unregister_inetaddr_notifier(&bond_inetaddr_notifier); rtnl_lock(); bond_free_all(); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 8c325308489d..d27f377b3eeb 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -25,6 +25,10 @@ * * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> * - Code cleanup and style changes + * + * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov> + * - added "xmit_policy" kernel parameter for alternate hashing policy + * support for mode 2 */ #ifndef _LINUX_BONDING_H @@ -36,8 +40,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.6.1" -#define DRV_RELDATE "October 29, 2004" +#define DRV_VERSION "2.6.3" +#define DRV_RELDATE "June 8, 2005" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -137,6 +141,7 @@ struct bond_params { int mode; + int xmit_policy; int miimon; int arp_interval; int use_carrier; @@ -149,6 +154,7 @@ struct bond_params { struct vlan_entry { struct list_head vlan_list; + u32 vlan_ip; unsigned short vlan_id; }; @@ -197,6 +203,8 @@ struct bonding { #endif /* CONFIG_PROC_FS */ struct list_head bond_list; struct dev_mc_list *mc_list; + int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int); + u32 master_ip; u16 flags; struct ad_bond_info ad_info; struct alb_bond_info alb_info; diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 5c5f540da26a..b780307093eb 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -174,6 +174,13 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0}; #include <asm/irq.h> static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; +#elif defined(CONFIG_ARCH_PNX0105) +#include <asm/irq.h> +#include <asm/arch/gpio.h> +#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ +#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */ +static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0}; +static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0}; #else static unsigned int netcard_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; @@ -319,13 +326,7 @@ struct net_device * __init cs89x0_probe(int unit) } if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - outw(PP_ChipID, dev->base_addr + ADD_PORT); - release_region(dev->base_addr, NETCARD_IO_EXTENT); out: free_netdev(dev); printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); @@ -416,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; + int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; @@ -437,6 +439,30 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #endif } +#ifdef CONFIG_ARCH_PNX0105 + initialize_ebi(); + + /* Map GPIO registers for the pins connected to the CS8900a. */ + if (map_cirrus_gpio() < 0) + return -ENODEV; + + reset_cirrus(); + + /* Map event-router registers. */ + if (map_event_router() < 0) + return -ENODEV; + + enable_cirrus_irq(); + + unmap_cirrus_gpio(); + unmap_event_router(); + + dev->base_addr = ioaddr; + + for (i = 0 ; i < 3 ; i++) + readreg(dev, 0); +#endif + /* Grab the region so we can find another board if autoIRQ fails. */ /* WTF is going on here? */ if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { @@ -467,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out2; } } -printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", + ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); ioaddr &= ~3; outw(PP_ChipID, ioaddr + ADD_PORT); - if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { - printk(KERN_ERR "%s: incorrect signature 0x%x\n", - dev->name, inw(ioaddr + DATA_PORT)); + tmp = inw(ioaddr + DATA_PORT); + if (tmp != CHIP_EISA_ID_SIG) { + printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" + CHIP_EISA_ID_SIG_STR "\n", + dev->name, ioaddr + DATA_PORT, tmp); retval = -ENODEV; goto out2; } @@ -678,7 +707,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { -#ifdef CONFIG_ARCH_IXDP2X01 +#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) i = cs8900_irq_map[0]; #else /* Translate the IRQ using the IRQ mapping table. */ @@ -735,7 +764,13 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); printk("\n"); if (net_debug) printk("cs89x0_probe1() successful\n"); + + retval = register_netdev(dev); + if (retval) + goto out3; return 0; +out3: + outw(PP_ChipID, dev->base_addr + ADD_PORT); out2: release_region(ioaddr & ~3, NETCARD_IO_EXTENT); out1: @@ -1145,7 +1180,7 @@ net_open(struct net_device *dev) int i; int ret; -#ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */ +#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */ if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1176,7 +1211,7 @@ net_open(struct net_device *dev) else #endif { -#ifndef CONFIG_ARCH_IXDP2X01 +#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); @@ -1261,6 +1296,9 @@ net_open(struct net_device *dev) case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } +#ifdef CONFIG_ARCH_PNX0105 + result = A_CNF_10B_T; +#endif if (!result) { printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: @@ -1416,6 +1454,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) /* Write the contents of the packet */ outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); spin_unlock_irq(&lp->lock); + lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; dev_kfree_skb (skb); @@ -1831,13 +1870,6 @@ init_module(void) if (ret) goto out; - if (register_netdev(dev) != 0) { - printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io); - ret = -ENXIO; - outw(PP_ChipID, dev->base_addr + ADD_PORT); - release_region(dev->base_addr, NETCARD_IO_EXTENT); - goto out; - } dev_cs89x0 = dev; return 0; out: diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index b0ef7ad2baad..decea264f121 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h @@ -16,7 +16,7 @@ #include <linux/config.h> -#ifdef CONFIG_ARCH_IXDP2X01 +#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) /* IXDP2401/IXDP2801 uses dword-aligned register addressing */ #define CS89x0_PORT(reg) ((reg) * 2) #else @@ -93,6 +93,7 @@ #endif #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ +#define CHIP_EISA_ID_SIG_STR "0x630E" #ifdef IBMEIPKT #define EISA_ID_SIG 0x4D24 /* IBM */ diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index a6aa56598f27..5acd35c312ac 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -191,6 +191,7 @@ * Feb 2001 davej PCI enable cleanups. * 04 Aug 2003 macro Converted to the DMA API. * 14 Aug 2004 macro Fix device names reported. + * 14 Jun 2005 macro Use irqreturn_t. */ /* Include files */ @@ -217,8 +218,8 @@ /* Version information string should be updated prior to each new release! */ #define DRV_NAME "defxx" -#define DRV_VERSION "v1.07" -#define DRV_RELDATE "2004/08/14" +#define DRV_VERSION "v1.08" +#define DRV_RELDATE "2005/06/14" static char version[] __devinitdata = DRV_NAME ": " DRV_VERSION " " DRV_RELDATE @@ -247,7 +248,8 @@ static int dfx_close(struct net_device *dev); static void dfx_int_pr_halt_id(DFX_board_t *bp); static void dfx_int_type_0_process(DFX_board_t *bp); static void dfx_int_common(struct net_device *dev); -static void dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t dfx_interrupt(int irq, void *dev_id, + struct pt_regs *regs); static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev); static void dfx_ctl_set_multicast_list(struct net_device *dev); @@ -437,7 +439,8 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) } SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); + if (pdev != NULL) + SET_NETDEV_DEV(dev, &pdev->dev); bp = dev->priv; @@ -1225,7 +1228,7 @@ static int dfx_open(struct net_device *dev) /* Register IRQ - support shared interrupts by passing device ptr */ - ret = request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev); + ret = request_irq(dev->irq, dfx_interrupt, SA_SHIRQ, dev->name, dev); if (ret) { printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); return ret; @@ -1680,13 +1683,13 @@ static void dfx_int_common(struct net_device *dev) * ================= * = dfx_interrupt = * ================= - * + * * Overview: * Interrupt processing routine - * + * * Returns: - * None - * + * Whether a valid interrupt was seen. + * * Arguments: * irq - interrupt vector * dev_id - pointer to device information @@ -1699,7 +1702,8 @@ static void dfx_int_common(struct net_device *dev) * structure context. * * Return Codes: - * None + * IRQ_HANDLED - an IRQ was handled. + * IRQ_NONE - no IRQ was handled. * * Assumptions: * The interrupt acknowledgement at the hardware level (eg. ACKing the PIC @@ -1712,60 +1716,70 @@ static void dfx_int_common(struct net_device *dev) * Interrupts are disabled, then reenabled at the adapter. */ -static void dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs) - { +static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ struct net_device *dev = dev_id; DFX_board_t *bp; /* private board structure pointer */ - u8 tmp; /* used for disabling/enabling ints */ /* Get board pointer only if device structure is valid */ bp = dev->priv; - spin_lock(&bp->lock); - /* See if we're already servicing an interrupt */ /* Service adapter interrupts */ - if (bp->bus_type == DFX_BUS_TYPE_PCI) - { - /* Disable PDQ-PFI interrupts at PFI */ + if (bp->bus_type == DFX_BUS_TYPE_PCI) { + u32 status; - dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, PFI_MODE_M_DMA_ENB); + dfx_port_read_long(bp, PFI_K_REG_STATUS, &status); + if (!(status & PFI_STATUS_M_PDQ_INT)) + return IRQ_NONE; - /* Call interrupt service routine for this adapter */ + spin_lock(&bp->lock); + + /* Disable PDQ-PFI interrupts at PFI */ + dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, + PFI_MODE_M_DMA_ENB); + /* Call interrupt service routine for this adapter */ dfx_int_common(dev); /* Clear PDQ interrupt status bit and reenable interrupts */ - - dfx_port_write_long(bp, PFI_K_REG_STATUS, PFI_STATUS_M_PDQ_INT); + dfx_port_write_long(bp, PFI_K_REG_STATUS, + PFI_STATUS_M_PDQ_INT); dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, - (PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB)); - } - else - { - /* Disable interrupts at the ESIC */ + (PFI_MODE_M_PDQ_INT_ENB | + PFI_MODE_M_DMA_ENB)); - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); - tmp &= ~PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); + spin_unlock(&bp->lock); + } else { + u8 status; - /* Call interrupt service routine for this adapter */ + dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + if (!(status & PI_CONFIG_STAT_0_M_PEND)) + return IRQ_NONE; + spin_lock(&bp->lock); + + /* Disable interrupts at the ESIC */ + status &= ~PI_CONFIG_STAT_0_M_INT_ENB; + dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); + + /* Call interrupt service routine for this adapter */ dfx_int_common(dev); /* Reenable interrupts at the ESIC */ + dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + status |= PI_CONFIG_STAT_0_M_INT_ENB; + dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); - tmp |= PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); - } - - spin_unlock(&bp->lock); + spin_unlock(&bp->lock); } + return IRQ_HANDLED; +} + /* * ===================== diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index aa42b7a27735..430c628279b3 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -547,7 +547,7 @@ rio_timer (unsigned long data) skb_reserve (skb, 2); np->rx_ring[entry].fraginfo = cpu_to_le64 (pci_map_single - (np->pdev, skb->tail, np->rx_buf_sz, + (np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= @@ -618,7 +618,7 @@ alloc_list (struct net_device *dev) /* Rubicon now supports 40 bits of addressing space. */ np->rx_ring[i].fraginfo = cpu_to_le64 ( pci_map_single ( - np->pdev, skb->tail, np->rx_buf_sz, + np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48; } @@ -906,7 +906,7 @@ receive_packet (struct net_device *dev) /* 16 byte align the IP header */ skb_reserve (skb, 2); eth_copy_and_sum (skb, - np->rx_skbuff[entry]->tail, + np->rx_skbuff[entry]->data, pkt_len, 0); skb_put (skb, pkt_len); pci_dma_sync_single_for_device(np->pdev, @@ -950,7 +950,7 @@ receive_packet (struct net_device *dev) skb_reserve (skb, 2); np->rx_ring[entry].fraginfo = cpu_to_le64 (pci_map_single - (np->pdev, skb->tail, np->rx_buf_sz, + (np->pdev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } np->rx_ring[entry].fraginfo |= diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c new file mode 100644 index 000000000000..5fddc0ff8878 --- /dev/null +++ b/drivers/net/dm9000.c @@ -0,0 +1,1219 @@ +/* + * dm9000.c: Version 1.2 03/18/2003 + * + * A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. + * Copyright (C) 1997 Sten Wang + * + * 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. + * + * (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. + * + * V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match + * 06/22/2001 Support DM9801 progrmming + * E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 + * E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 + * R17 = (R17 & 0xfff0) | NF + 3 + * E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 + * R17 = (R17 & 0xfff0) | NF + * + * v1.00 modify by simon 2001.9.5 + * change for kernel 2.4.x + * + * v1.1 11/09/2001 fix force mode bug + * + * v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>: + * Fixed phy reset. + * Added tx/rx 32 bit mode. + * Cleaned up for kernel merge. + * + * 03/03/2004 Sascha Hauer <s.hauer@pengutronix.de> + * Port to 2.6 kernel + * + * 24-Sep-2004 Ben Dooks <ben@simtec.co.uk> + * Cleanup of code to remove ifdefs + * Allowed platform device data to influence access width + * Reformatting areas of code + * + * 17-Mar-2005 Sascha Hauer <s.hauer@pengutronix.de> + * * removed 2.4 style module parameters + * * removed removed unused stat counter and fixed + * net_device_stats + * * introduced tx_timeout function + * * reworked locking + */ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/version.h> +#include <linux/spinlock.h> +#include <linux/crc32.h> +#include <linux/mii.h> +#include <linux/dm9000.h> +#include <linux/delay.h> + +#include <asm/delay.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include "dm9000.h" + +/* Board/System/Debug information/definition ---------------- */ + +#define DM9000_PHY 0x40 /* PHY address 0x01 */ + +#define TRUE 1 +#define FALSE 0 + +#define CARDNAME "dm9000" +#define PFX CARDNAME ": " + +#define DM9000_TIMER_WUT jiffies+(HZ*2) /* timer wakeup time : 2 second */ + +#define DM9000_DEBUG 0 + +#if DM9000_DEBUG > 2 +#define PRINTK3(args...) printk(CARDNAME ": " args) +#else +#define PRINTK3(args...) do { } while(0) +#endif + +#if DM9000_DEBUG > 1 +#define PRINTK2(args...) printk(CARDNAME ": " args) +#else +#define PRINTK2(args...) do { } while(0) +#endif + +#if DM9000_DEBUG > 0 +#define PRINTK1(args...) printk(CARDNAME ": " args) +#define PRINTK(args...) printk(CARDNAME ": " args) +#else +#define PRINTK1(args...) do { } while(0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +/* + * Transmit timeout, default 5 seconds. + */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +/* Structure/enum declaration ------------------------------- */ +typedef struct board_info { + + void __iomem *io_addr; /* Register I/O base address */ + void __iomem *io_data; /* Data I/O address */ + u16 irq; /* IRQ */ + + u16 tx_pkt_cnt; + u16 queue_pkt_len; + u16 queue_start_addr; + u16 dbug_cnt; + u8 io_mode; /* 0:word, 2:byte */ + u8 phy_addr; + + void (*inblk)(void __iomem *port, void *data, int length); + void (*outblk)(void __iomem *port, void *data, int length); + void (*dumpblk)(void __iomem *port, int length); + + struct resource *addr_res; /* resources found */ + struct resource *data_res; + struct resource *addr_req; /* resources requested */ + struct resource *data_req; + struct resource *irq_res; + + struct timer_list timer; + struct net_device_stats stats; + unsigned char srom[128]; + spinlock_t lock; + + struct mii_if_info mii; + u32 msg_enable; +} board_info_t; + +/* function declaration ------------------------------------- */ +static int dm9000_probe(struct device *); +static int dm9000_open(struct net_device *); +static int dm9000_start_xmit(struct sk_buff *, struct net_device *); +static int dm9000_stop(struct net_device *); +static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int); + + +static void dm9000_timer(unsigned long); +static void dm9000_init_dm9000(struct net_device *); + +static struct net_device_stats *dm9000_get_stats(struct net_device *); + +static irqreturn_t dm9000_interrupt(int, void *, struct pt_regs *); + +static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg); +static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, + int value); +static u16 read_srom_word(board_info_t *, int); +static void dm9000_rx(struct net_device *); +static void dm9000_hash_table(struct net_device *); + +//#define DM9000_PROGRAM_EEPROM +#ifdef DM9000_PROGRAM_EEPROM +static void program_eeprom(board_info_t * db); +#endif +/* DM9000 network board routine ---------------------------- */ + +static void +dm9000_reset(board_info_t * db) +{ + PRINTK1("dm9000x: resetting\n"); + /* RESET device */ + writeb(DM9000_NCR, db->io_addr); + udelay(200); + writeb(NCR_RST, db->io_data); + udelay(200); +} + +/* + * Read a byte from I/O port + */ +static u8 +ior(board_info_t * db, int reg) +{ + writeb(reg, db->io_addr); + return readb(db->io_data); +} + +/* + * Write a byte to I/O port + */ + +static void +iow(board_info_t * db, int reg, int value) +{ + writeb(reg, db->io_addr); + writeb(value, db->io_data); +} + +/* routines for sending block to chip */ + +static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count) +{ + writesb(reg, data, count); +} + +static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count) +{ + writesw(reg, data, (count+1) >> 1); +} + +static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count) +{ + writesl(reg, data, (count+3) >> 2); +} + +/* input block from chip to memory */ + +static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count) +{ + readsb(reg, data, count); +} + + +static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count) +{ + readsw(reg, data, (count+1) >> 1); +} + +static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count) +{ + readsl(reg, data, (count+3) >> 2); +} + +/* dump block from chip to null */ + +static void dm9000_dumpblk_8bit(void __iomem *reg, int count) +{ + int i; + int tmp; + + for (i = 0; i < count; i++) + tmp = readb(reg); +} + +static void dm9000_dumpblk_16bit(void __iomem *reg, int count) +{ + int i; + int tmp; + + count = (count + 1) >> 1; + + for (i = 0; i < count; i++) + tmp = readw(reg); +} + +static void dm9000_dumpblk_32bit(void __iomem *reg, int count) +{ + int i; + int tmp; + + count = (count + 3) >> 2; + + for (i = 0; i < count; i++) + tmp = readl(reg); +} + +/* dm9000_set_io + * + * select the specified set of io routines to use with the + * device + */ + +static void dm9000_set_io(struct board_info *db, int byte_width) +{ + /* use the size of the data resource to work out what IO + * routines we want to use + */ + + switch (byte_width) { + case 1: + db->dumpblk = dm9000_dumpblk_8bit; + db->outblk = dm9000_outblk_8bit; + db->inblk = dm9000_inblk_8bit; + break; + + case 2: + db->dumpblk = dm9000_dumpblk_16bit; + db->outblk = dm9000_outblk_16bit; + db->inblk = dm9000_inblk_16bit; + break; + + case 3: + printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n"); + db->dumpblk = dm9000_dumpblk_16bit; + db->outblk = dm9000_outblk_16bit; + db->inblk = dm9000_inblk_16bit; + break; + + case 4: + default: + db->dumpblk = dm9000_dumpblk_32bit; + db->outblk = dm9000_outblk_32bit; + db->inblk = dm9000_inblk_32bit; + break; + } +} + + +/* Our watchdog timed out. Called by the networking layer */ +static void dm9000_timeout(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + u8 reg_save; + unsigned long flags; + + /* Save previous register address */ + reg_save = readb(db->io_addr); + spin_lock_irqsave(db->lock,flags); + + netif_stop_queue(dev); + dm9000_reset(db); + dm9000_init_dm9000(dev); + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); + + /* Restore previous register address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(db->lock,flags); +} + + +/* dm9000_release_board + * + * release a board, and any mapped resources + */ + +static void +dm9000_release_board(struct platform_device *pdev, struct board_info *db) +{ + if (db->data_res == NULL) { + if (db->addr_res != NULL) + release_mem_region((unsigned long)db->io_addr, 4); + return; + } + + /* unmap our resources */ + + iounmap(db->io_addr); + iounmap(db->io_data); + + /* release the resources */ + + if (db->data_req != NULL) { + release_resource(db->data_req); + kfree(db->data_req); + } + + if (db->addr_res != NULL) { + release_resource(db->addr_res); + kfree(db->addr_req); + } +} + +#define res_size(_r) (((_r)->end - (_r)->start) + 1) + +/* + * Search DM9000 board, allocate space and register it + */ +static int +dm9000_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dm9000_plat_data *pdata = pdev->dev.platform_data; + struct board_info *db; /* Point a board information structure */ + struct net_device *ndev; + unsigned long base; + int ret = 0; + int iosize; + int i; + u32 id_val; + + printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME); + + /* Init network device */ + ndev = alloc_etherdev(sizeof (struct board_info)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + return -ENOMEM; + } + + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, dev); + + PRINTK2("dm9000_probe()"); + + /* setup board info structure */ + db = (struct board_info *) ndev->priv; + memset(db, 0, sizeof (*db)); + + if (pdev->num_resources < 2) { + ret = -ENODEV; + goto out; + } + + switch (pdev->num_resources) { + case 2: + base = pdev->resource[0].start; + + if (!request_mem_region(base, 4, ndev->name)) { + ret = -EBUSY; + goto out; + } + + ndev->base_addr = base; + ndev->irq = pdev->resource[1].start; + db->io_addr = (void *)base; + db->io_data = (void *)(base + 4); + + break; + + case 3: + db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + + if (db->addr_res == NULL || db->data_res == NULL) { + printk(KERN_ERR PFX "insufficient resources\n"); + ret = -ENOENT; + goto out; + } + + i = res_size(db->addr_res); + db->addr_req = request_mem_region(db->addr_res->start, i, + pdev->name); + + if (db->addr_req == NULL) { + printk(KERN_ERR PFX "cannot claim address reg area\n"); + ret = -EIO; + goto out; + } + + db->io_addr = ioremap(db->addr_res->start, i); + + if (db->io_addr == NULL) { + printk(KERN_ERR "failed to ioremap address reg\n"); + ret = -EINVAL; + goto out; + } + + iosize = res_size(db->data_res); + db->data_req = request_mem_region(db->data_res->start, iosize, + pdev->name); + + if (db->data_req == NULL) { + printk(KERN_ERR PFX "cannot claim data reg area\n"); + ret = -EIO; + goto out; + } + + db->io_data = ioremap(db->data_res->start, iosize); + + if (db->io_data == NULL) { + printk(KERN_ERR "failed to ioremap data reg\n"); + ret = -EINVAL; + goto out; + } + + /* fill in parameters for net-dev structure */ + + ndev->base_addr = (unsigned long)db->io_addr; + ndev->irq = db->irq_res->start; + + /* ensure at least we have a default set of IO routines */ + dm9000_set_io(db, iosize); + + } + + /* check to see if anything is being over-ridden */ + if (pdata != NULL) { + /* check to see if the driver wants to over-ride the + * default IO width */ + + if (pdata->flags & DM9000_PLATF_8BITONLY) + dm9000_set_io(db, 1); + + if (pdata->flags & DM9000_PLATF_16BITONLY) + dm9000_set_io(db, 2); + + if (pdata->flags & DM9000_PLATF_32BITONLY) + dm9000_set_io(db, 4); + + /* check to see if there are any IO routine + * over-rides */ + + if (pdata->inblk != NULL) + db->inblk = pdata->inblk; + + if (pdata->outblk != NULL) + db->outblk = pdata->outblk; + + if (pdata->dumpblk != NULL) + db->dumpblk = pdata->dumpblk; + } + + dm9000_reset(db); + + /* try two times, DM9000 sometimes gets the first read wrong */ + for (i = 0; i < 2; i++) { + id_val = ior(db, DM9000_VIDL); + id_val |= (u32)ior(db, DM9000_VIDH) << 8; + id_val |= (u32)ior(db, DM9000_PIDL) << 16; + id_val |= (u32)ior(db, DM9000_PIDH) << 24; + + if (id_val == DM9000_ID) + break; + printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val); + } + + if (id_val != DM9000_ID) { + printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val); + goto release; + } + + /* from this point we assume that we have found a DM9000 */ + + /* driver system function */ + ether_setup(ndev); + + ndev->open = &dm9000_open; + ndev->hard_start_xmit = &dm9000_start_xmit; + ndev->tx_timeout = &dm9000_timeout; + ndev->watchdog_timeo = msecs_to_jiffies(watchdog); + ndev->stop = &dm9000_stop; + ndev->get_stats = &dm9000_get_stats; + ndev->set_multicast_list = &dm9000_hash_table; + ndev->do_ioctl = &dm9000_do_ioctl; + +#ifdef DM9000_PROGRAM_EEPROM + program_eeprom(db); +#endif + db->msg_enable = NETIF_MSG_LINK; + db->mii.phy_id_mask = 0x1f; + db->mii.reg_num_mask = 0x1f; + db->mii.force_media = 0; + db->mii.full_duplex = 0; + db->mii.dev = ndev; + db->mii.mdio_read = dm9000_phy_read; + db->mii.mdio_write = dm9000_phy_write; + + /* Read SROM content */ + for (i = 0; i < 64; i++) + ((u16 *) db->srom)[i] = read_srom_word(db, i); + + /* Set Node Address */ + for (i = 0; i < 6; i++) + ndev->dev_addr[i] = db->srom[i]; + + if (!is_valid_ether_addr(ndev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); + + dev_set_drvdata(dev, ndev); + ret = register_netdev(ndev); + + if (ret == 0) { + printk("%s: dm9000 at %p,%p IRQ %d MAC: ", + ndev->name, db->io_addr, db->io_data, ndev->irq); + for (i = 0; i < 5; i++) + printk("%02x:", ndev->dev_addr[i]); + printk("%02x\n", ndev->dev_addr[5]); + } + return 0; + + release: + out: + printk("%s: not found (%d).\n", CARDNAME, ret); + + dm9000_release_board(pdev, db); + kfree(ndev); + + return ret; +} + +/* + * Open the interface. + * The interface is opened whenever "ifconfig" actives it. + */ +static int +dm9000_open(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + + PRINTK2("entering dm9000_open\n"); + + if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev)) + return -EAGAIN; + + /* Initialize DM9000 board */ + dm9000_reset(db); + dm9000_init_dm9000(dev); + + /* Init driver variable */ + db->dbug_cnt = 0; + + /* set and active a timer process */ + init_timer(&db->timer); + db->timer.expires = DM9000_TIMER_WUT * 2; + db->timer.data = (unsigned long) dev; + db->timer.function = &dm9000_timer; + add_timer(&db->timer); + + mii_check_media(&db->mii, netif_msg_link(db), 1); + netif_start_queue(dev); + + return 0; +} + +/* + * Initilize dm9000 board + */ +static void +dm9000_init_dm9000(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + + PRINTK1("entering %s\n",__FUNCTION__); + + /* I/O mode */ + db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ + + /* GPIO0 on pre-activate PHY */ + iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ + iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ + iow(db, DM9000_GPR, 0); /* Enable PHY */ + + /* Program operating register */ + iow(db, DM9000_TCR, 0); /* TX Polling clear */ + iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ + iow(db, DM9000_FCR, 0xff); /* Flow Control */ + iow(db, DM9000_SMCR, 0); /* Special Mode */ + /* clear TX status */ + iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); + iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ + + /* Set address filter table */ + dm9000_hash_table(dev); + + /* Activate DM9000 */ + iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); + /* Enable TX/RX interrupt mask */ + iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); + + /* Init Driver variable */ + db->tx_pkt_cnt = 0; + db->queue_pkt_len = 0; + dev->trans_start = 0; + spin_lock_init(&db->lock); +} + +/* + * Hardware start transmission. + * Send a packet to media from the upper layer. + */ +static int +dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + + PRINTK3("dm9000_start_xmit\n"); + + if (db->tx_pkt_cnt > 1) + return 1; + + netif_stop_queue(dev); + + /* Disable all interrupts */ + iow(db, DM9000_IMR, IMR_PAR); + + /* Move data to DM9000 TX RAM */ + writeb(DM9000_MWCMD, db->io_addr); + + (db->outblk)(db->io_data, skb->data, skb->len); + db->stats.tx_bytes += skb->len; + + /* TX control: First packet immediately send, second packet queue */ + if (db->tx_pkt_cnt == 0) { + + /* First Packet */ + db->tx_pkt_cnt++; + + /* Set TX length to DM9000 */ + iow(db, DM9000_TXPLL, skb->len & 0xff); + iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff); + + /* Issue TX polling command */ + iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ + + dev->trans_start = jiffies; /* save the time stamp */ + + } else { + /* Second packet */ + db->tx_pkt_cnt++; + db->queue_pkt_len = skb->len; + } + + /* free this SKB */ + dev_kfree_skb(skb); + + /* Re-enable resource check */ + if (db->tx_pkt_cnt == 1) + netif_wake_queue(dev); + + /* Re-enable interrupt */ + iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); + + return 0; +} + +static void +dm9000_shutdown(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + + /* RESET device */ + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ + iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */ + iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */ + iow(db, DM9000_RCR, 0x00); /* Disable RX */ +} + +/* + * Stop the interface. + * The interface is stopped when it is brought. + */ +static int +dm9000_stop(struct net_device *ndev) +{ + board_info_t *db = (board_info_t *) ndev->priv; + + PRINTK1("entering %s\n",__FUNCTION__); + + /* deleted timer */ + del_timer(&db->timer); + + netif_stop_queue(ndev); + netif_carrier_off(ndev); + + /* free interrupt */ + free_irq(ndev->irq, ndev); + + dm9000_shutdown(ndev); + + return 0; +} + +/* + * DM9000 interrupt handler + * receive the packet to upper layer, free the transmitted packet + */ + +void +dm9000_tx_done(struct net_device *dev, board_info_t * db) +{ + int tx_status = ior(db, DM9000_NSR); /* Got TX status */ + + if (tx_status & (NSR_TX2END | NSR_TX1END)) { + /* One packet sent complete */ + db->tx_pkt_cnt--; + db->stats.tx_packets++; + + /* Queue packet check & send */ + if (db->tx_pkt_cnt > 0) { + iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff); + iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff); + iow(db, DM9000_TCR, TCR_TXREQ); + dev->trans_start = jiffies; + } + netif_wake_queue(dev); + } +} + +static irqreturn_t +dm9000_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + board_info_t *db; + int int_status; + u8 reg_save; + + PRINTK3("entering %s\n",__FUNCTION__); + + if (!dev) { + PRINTK1("dm9000_interrupt() without DEVICE arg\n"); + return IRQ_HANDLED; + } + + /* A real interrupt coming */ + db = (board_info_t *) dev->priv; + spin_lock(&db->lock); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Disable all interrupts */ + iow(db, DM9000_IMR, IMR_PAR); + + /* Got DM9000 interrupt status */ + int_status = ior(db, DM9000_ISR); /* Got ISR */ + iow(db, DM9000_ISR, int_status); /* Clear ISR status */ + + /* Received the coming packet */ + if (int_status & ISR_PRS) + dm9000_rx(dev); + + /* Trnasmit Interrupt check */ + if (int_status & ISR_PTS) + dm9000_tx_done(dev, db); + + /* Re-enable interrupt mask */ + iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); + + /* Restore previous register address */ + writeb(reg_save, db->io_addr); + + spin_unlock(&db->lock); + + return IRQ_HANDLED; +} + +/* + * Get statistics from driver. + */ +static struct net_device_stats * +dm9000_get_stats(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + return &db->stats; +} + +/* + * Process the upper socket ioctl command + */ +static int +dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + PRINTK1("entering %s\n",__FUNCTION__); + return 0; +} + +/* + * A periodic timer routine + * Dynamic media sense, allocated Rx buffer... + */ +static void +dm9000_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + board_info_t *db = (board_info_t *) dev->priv; + u8 reg_save; + unsigned long flags; + + PRINTK3("dm9000_timer()\n"); + + spin_lock_irqsave(db->lock,flags); + /* Save previous register address */ + reg_save = readb(db->io_addr); + + mii_check_media(&db->mii, netif_msg_link(db), 0); + + /* Restore previous register address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(db->lock,flags); + + /* Set timer again */ + db->timer.expires = DM9000_TIMER_WUT; + add_timer(&db->timer); +} + +struct dm9000_rxhdr { + u16 RxStatus; + u16 RxLen; +} __attribute__((__packed__)); + +/* + * Received a packet and pass to upper layer + */ +static void +dm9000_rx(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + struct dm9000_rxhdr rxhdr; + struct sk_buff *skb; + u8 rxbyte, *rdptr; + int GoodPacket; + int RxLen; + + /* Check packet ready or not */ + do { + ior(db, DM9000_MRCMDX); /* Dummy read */ + + /* Get most updated data */ + rxbyte = readb(db->io_data); + + /* Status check: this byte must be 0 or 1 */ + if (rxbyte > DM9000_PKT_RDY) { + printk("status check failed: %d\n", rxbyte); + iow(db, DM9000_RCR, 0x00); /* Stop Device */ + iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ + return; + } + + if (rxbyte != DM9000_PKT_RDY) + return; + + /* A packet ready now & Get status/length */ + GoodPacket = TRUE; + writeb(DM9000_MRCMD, db->io_addr); + + (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); + + RxLen = rxhdr.RxLen; + + /* Packet Status check */ + if (RxLen < 0x40) { + GoodPacket = FALSE; + PRINTK1("Bad Packet received (runt)\n"); + } + + if (RxLen > DM9000_PKT_MAX) { + PRINTK1("RST: RX Len:%x\n", RxLen); + } + + if (rxhdr.RxStatus & 0xbf00) { + GoodPacket = FALSE; + if (rxhdr.RxStatus & 0x100) { + PRINTK1("fifo error\n"); + db->stats.rx_fifo_errors++; + } + if (rxhdr.RxStatus & 0x200) { + PRINTK1("crc error\n"); + db->stats.rx_crc_errors++; + } + if (rxhdr.RxStatus & 0x8000) { + PRINTK1("length error\n"); + db->stats.rx_length_errors++; + } + } + + /* Move data from DM9000 */ + if (GoodPacket + && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { + skb->dev = dev; + skb_reserve(skb, 2); + rdptr = (u8 *) skb_put(skb, RxLen - 4); + + /* Read received packet from RX SRAM */ + + (db->inblk)(db->io_data, rdptr, RxLen); + db->stats.rx_bytes += RxLen; + + /* Pass to upper layer */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + db->stats.rx_packets++; + + } else { + /* need to dump the packet's data */ + + (db->dumpblk)(db->io_data, RxLen); + } + } while (rxbyte == DM9000_PKT_RDY); +} + +/* + * Read a word data from SROM + */ +static u16 +read_srom_word(board_info_t * db, int offset) +{ + iow(db, DM9000_EPAR, offset); + iow(db, DM9000_EPCR, EPCR_ERPRR); + mdelay(8); /* according to the datasheet 200us should be enough, + but it doesn't work */ + iow(db, DM9000_EPCR, 0x0); + return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8)); +} + +#ifdef DM9000_PROGRAM_EEPROM +/* + * Write a word data to SROM + */ +static void +write_srom_word(board_info_t * db, int offset, u16 val) +{ + iow(db, DM9000_EPAR, offset); + iow(db, DM9000_EPDRH, ((val >> 8) & 0xff)); + iow(db, DM9000_EPDRL, (val & 0xff)); + iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW); + mdelay(8); /* same shit */ + iow(db, DM9000_EPCR, 0); +} + +/* + * Only for development: + * Here we write static data to the eeprom in case + * we don't have valid content on a new board + */ +static void +program_eeprom(board_info_t * db) +{ + u16 eeprom[] = { 0x0c00, 0x007f, 0x1300, /* MAC Address */ + 0x0000, /* Autoload: accept nothing */ + 0x0a46, 0x9000, /* Vendor / Product ID */ + 0x0000, /* pin control */ + 0x0000, + }; /* Wake-up mode control */ + int i; + for (i = 0; i < 8; i++) + write_srom_word(db, i, eeprom[i]); +} +#endif + + +/* + * Calculate the CRC valude of the Rx packet + * flag = 1 : return the reverse CRC (for the received packet CRC) + * 0 : return the normal CRC (for Hash Table index) + */ + +static unsigned long +cal_CRC(unsigned char *Data, unsigned int Len, u8 flag) +{ + + u32 crc = ether_crc_le(Len, Data); + + if (flag) + return ~crc; + + return crc; +} + +/* + * Set DM9000 multicast address + */ +static void +dm9000_hash_table(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + struct dev_mc_list *mcptr = dev->mc_list; + int mc_cnt = dev->mc_count; + u32 hash_val; + u16 i, oft, hash_table[4]; + unsigned long flags; + + PRINTK2("dm9000_hash_table()\n"); + + spin_lock_irqsave(&db->lock,flags); + + for (i = 0, oft = 0x10; i < 6; i++, oft++) + iow(db, oft, dev->dev_addr[i]); + + /* Clear Hash Table */ + for (i = 0; i < 4; i++) + hash_table[i] = 0x0; + + /* broadcast address */ + hash_table[3] = 0x8000; + + /* the multicast address in Hash Table : 64 bits */ + for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { + hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f; + hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); + } + + /* Write the hash table to MAC MD table */ + for (i = 0, oft = 0x16; i < 4; i++) { + iow(db, oft++, hash_table[i] & 0xff); + iow(db, oft++, (hash_table[i] >> 8) & 0xff); + } + + spin_unlock_irqrestore(&db->lock,flags); +} + + +/* + * Read a word from phyxcer + */ +static int +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) +{ + board_info_t *db = (board_info_t *) dev->priv; + unsigned long flags; + int ret; + + spin_lock_irqsave(&db->lock,flags); + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */ + udelay(100); /* Wait read complete */ + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ + + /* The read data keeps on REG_0D & REG_0E */ + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + + spin_unlock_irqrestore(&db->lock,flags); + + return ret; +} + +/* + * Write a word to phyxcer + */ +static void +dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) +{ + board_info_t *db = (board_info_t *) dev->priv; + unsigned long flags; + + spin_lock_irqsave(&db->lock,flags); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + /* Fill the written data into REG_0D & REG_0E */ + iow(db, DM9000_EPDRL, (value & 0xff)); + iow(db, DM9000_EPDRH, ((value >> 8) & 0xff)); + + iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */ + udelay(500); /* Wait write complete */ + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + + spin_unlock_irqrestore(&db->lock,flags); +} + +static int +dm9000_drv_suspend(struct device *dev, u32 state, u32 level) +{ + struct net_device *ndev = dev_get_drvdata(dev); + + if (ndev && level == SUSPEND_DISABLE) { + if (netif_running(ndev)) { + netif_device_detach(ndev); + dm9000_shutdown(ndev); + } + } + return 0; +} + +static int +dm9000_drv_resume(struct device *dev, u32 level) +{ + struct net_device *ndev = dev_get_drvdata(dev); + board_info_t *db = (board_info_t *) ndev->priv; + + if (ndev && level == RESUME_ENABLE) { + + if (netif_running(ndev)) { + dm9000_reset(db); + dm9000_init_dm9000(ndev); + + netif_device_attach(ndev); + } + } + return 0; +} + +static int +dm9000_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + + dev_set_drvdata(dev, NULL); + + unregister_netdev(ndev); + dm9000_release_board(pdev, (board_info_t *) ndev->priv); + kfree(ndev); /* free device structure */ + + PRINTK1("clean_module() exit\n"); + + return 0; +} + +static struct device_driver dm9000_driver = { + .name = "dm9000", + .bus = &platform_bus_type, + .probe = dm9000_probe, + .remove = dm9000_drv_remove, + .suspend = dm9000_drv_suspend, + .resume = dm9000_drv_resume, +}; + +static int __init +dm9000_init(void) +{ + return driver_register(&dm9000_driver); /* search board and register */ +} + +static void __exit +dm9000_cleanup(void) +{ + driver_unregister(&dm9000_driver); +} + +module_init(dm9000_init); +module_exit(dm9000_cleanup); + +MODULE_AUTHOR("Sascha Hauer, Ben Dooks"); +MODULE_DESCRIPTION("Davicom DM9000 network driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h new file mode 100644 index 000000000000..82cad360bafc --- /dev/null +++ b/drivers/net/dm9000.h @@ -0,0 +1,135 @@ +/* + * dm9000 Ethernet + */ + +#ifndef _DM9000X_H_ +#define _DM9000X_H_ + +#define DM9000_ID 0x90000A46 + +/* although the registers are 16 bit, they are 32-bit aligned. + */ + +#define DM9000_NCR 0x00 +#define DM9000_NSR 0x01 +#define DM9000_TCR 0x02 +#define DM9000_TSR1 0x03 +#define DM9000_TSR2 0x04 +#define DM9000_RCR 0x05 +#define DM9000_RSR 0x06 +#define DM9000_ROCR 0x07 +#define DM9000_BPTR 0x08 +#define DM9000_FCTR 0x09 +#define DM9000_FCR 0x0A +#define DM9000_EPCR 0x0B +#define DM9000_EPAR 0x0C +#define DM9000_EPDRL 0x0D +#define DM9000_EPDRH 0x0E +#define DM9000_WCR 0x0F + +#define DM9000_PAR 0x10 +#define DM9000_MAR 0x16 + +#define DM9000_GPCR 0x1e +#define DM9000_GPR 0x1f +#define DM9000_TRPAL 0x22 +#define DM9000_TRPAH 0x23 +#define DM9000_RWPAL 0x24 +#define DM9000_RWPAH 0x25 + +#define DM9000_VIDL 0x28 +#define DM9000_VIDH 0x29 +#define DM9000_PIDL 0x2A +#define DM9000_PIDH 0x2B + +#define DM9000_CHIPR 0x2C +#define DM9000_SMCR 0x2F + +#define DM9000_MRCMDX 0xF0 +#define DM9000_MRCMD 0xF2 +#define DM9000_MRRL 0xF4 +#define DM9000_MRRH 0xF5 +#define DM9000_MWCMDX 0xF6 +#define DM9000_MWCMD 0xF8 +#define DM9000_MWRL 0xFA +#define DM9000_MWRH 0xFB +#define DM9000_TXPLL 0xFC +#define DM9000_TXPLH 0xFD +#define DM9000_ISR 0xFE +#define DM9000_IMR 0xFF + +#define NCR_EXT_PHY (1<<7) +#define NCR_WAKEEN (1<<6) +#define NCR_FCOL (1<<4) +#define NCR_FDX (1<<3) +#define NCR_LBK (3<<1) +#define NCR_RST (1<<0) + +#define NSR_SPEED (1<<7) +#define NSR_LINKST (1<<6) +#define NSR_WAKEST (1<<5) +#define NSR_TX2END (1<<3) +#define NSR_TX1END (1<<2) +#define NSR_RXOV (1<<1) + +#define TCR_TJDIS (1<<6) +#define TCR_EXCECM (1<<5) +#define TCR_PAD_DIS2 (1<<4) +#define TCR_CRC_DIS2 (1<<3) +#define TCR_PAD_DIS1 (1<<2) +#define TCR_CRC_DIS1 (1<<1) +#define TCR_TXREQ (1<<0) + +#define TSR_TJTO (1<<7) +#define TSR_LC (1<<6) +#define TSR_NC (1<<5) +#define TSR_LCOL (1<<4) +#define TSR_COL (1<<3) +#define TSR_EC (1<<2) + +#define RCR_WTDIS (1<<6) +#define RCR_DIS_LONG (1<<5) +#define RCR_DIS_CRC (1<<4) +#define RCR_ALL (1<<3) +#define RCR_RUNT (1<<2) +#define RCR_PRMSC (1<<1) +#define RCR_RXEN (1<<0) + +#define RSR_RF (1<<7) +#define RSR_MF (1<<6) +#define RSR_LCS (1<<5) +#define RSR_RWTO (1<<4) +#define RSR_PLE (1<<3) +#define RSR_AE (1<<2) +#define RSR_CE (1<<1) +#define RSR_FOE (1<<0) + +#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 ) +#define FCTR_LWOT(ot) ( ot & 0xf ) + +#define IMR_PAR (1<<7) +#define IMR_ROOM (1<<3) +#define IMR_ROM (1<<2) +#define IMR_PTM (1<<1) +#define IMR_PRM (1<<0) + +#define ISR_ROOS (1<<3) +#define ISR_ROS (1<<2) +#define ISR_PTS (1<<1) +#define ISR_PRS (1<<0) +#define ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS) + +#define EPCR_REEP (1<<5) +#define EPCR_WEP (1<<4) +#define EPCR_EPOS (1<<3) +#define EPCR_ERPRR (1<<2) +#define EPCR_ERPRW (1<<1) +#define EPCR_ERRE (1<<0) + +#define GPCR_GEP_CNTL (1<<0) + +#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */ +#define DM9000_PKT_MAX 1536 /* Received packet max size */ + +#endif /* _DM9000X_H_ */ + diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 4a47df5a9ff9..d0fa2448761d 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -143,6 +143,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/mii.h> @@ -1092,11 +1093,16 @@ static int e100_phy_init(struct nic *nic) } if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && - (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) - /* enable/disable MDI/MDI-X auto-switching */ - mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, - nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); + (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) { + /* enable/disable MDI/MDI-X auto-switching. + MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */ + if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) || + (nic->mac == mac_82551_10) || (nic->mii.force_media) || + !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)) + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0); + else + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH); + } return 0; } @@ -1665,8 +1671,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) if(stat_ack & stat_ack_rnr) nic->ru_running = RU_SUSPENDED; - e100_disable_irq(nic); - netif_rx_schedule(netdev); + if(likely(netif_rx_schedule_prep(netdev))) { + e100_disable_irq(nic); + __netif_rx_schedule(netdev); + } return IRQ_HANDLED; } @@ -2286,7 +2294,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_disable_pdev; } - if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) { + if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); goto err_out_free_res; } @@ -2334,11 +2342,11 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_iounmap; } - e100_phy_init(nic); - if((err = e100_eeprom_load(nic))) goto err_out_free; + e100_phy_init(nic); + memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN); if(!is_valid_ether_addr(netdev->dev_addr)) { DPRINTK(PROBE, ERR, "Invalid MAC address from " @@ -2439,9 +2447,8 @@ static int e100_resume(struct pci_dev *pdev) #endif -static void e100_shutdown(struct device *dev) +static void e100_shutdown(struct pci_dev *pdev) { - struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); @@ -2462,11 +2469,7 @@ static struct pci_driver e100_driver = { .suspend = e100_suspend, .resume = e100_resume, #endif - - .driver = { - .shutdown = e100_shutdown, - } - + .shutdown = e100_shutdown, }; static int __init e100_init_module(void) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index af1e82c5b808..092757bc721f 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -140,7 +140,7 @@ struct e1000_adapter; #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0400 +#define E1000_EEPROM_82544_APM 0x0004 #define E1000_EEPROM_APME 0x0400 #ifndef E1000_MASTER_SLAVE @@ -159,7 +159,7 @@ struct e1000_adapter; * so a DMA handle can be stored along with the buffer */ struct e1000_buffer { struct sk_buff *skb; - uint64_t dma; + dma_addr_t dma; unsigned long time_stamp; uint16_t length; uint16_t next_to_watch; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 237247f74df4..f133ff0b0b94 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -105,7 +105,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { static int e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; if(hw->media_type == e1000_media_type_copper) { @@ -141,9 +141,9 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) SUPPORTED_FIBRE | SUPPORTED_Autoneg); - ecmd->advertising = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); + ecmd->advertising = (ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg); ecmd->port = PORT_FIBRE; @@ -179,13 +179,24 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) static int e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; if(ecmd->autoneg == AUTONEG_ENABLE) { hw->autoneg = 1; - hw->autoneg_advertised = 0x002F; - ecmd->advertising = 0x002F; + if(hw->media_type == e1000_media_type_fiber) + hw->autoneg_advertised = ADVERTISED_1000baseT_Full | + ADVERTISED_FIBRE | + ADVERTISED_Autoneg; + else + hw->autoneg_advertised = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full| + ADVERTISED_Autoneg | + ADVERTISED_TP; + ecmd->advertising = hw->autoneg_advertised; } else if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) return -EINVAL; @@ -206,7 +217,7 @@ static void e1000_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pause->autoneg = @@ -226,7 +237,7 @@ static int e1000_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; adapter->fc_autoneg = pause->autoneg; @@ -259,14 +270,14 @@ e1000_set_pauseparam(struct net_device *netdev, static uint32_t e1000_get_rx_csum(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); return adapter->rx_csum; } static int e1000_set_rx_csum(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); adapter->rx_csum = data; if(netif_running(netdev)) { @@ -286,7 +297,7 @@ e1000_get_tx_csum(struct net_device *netdev) static int e1000_set_tx_csum(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); if(adapter->hw.mac_type < e1000_82543) { if (!data) @@ -306,8 +317,8 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data) static int e1000_set_tso(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev->priv; - if ((adapter->hw.mac_type < e1000_82544) || + struct e1000_adapter *adapter = netdev_priv(netdev); + if((adapter->hw.mac_type < e1000_82544) || (adapter->hw.mac_type == e1000_82547)) return data ? -EINVAL : 0; @@ -322,14 +333,14 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) static uint32_t e1000_get_msglevel(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); return adapter->msg_enable; } static void e1000_set_msglevel(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); adapter->msg_enable = data; } @@ -344,7 +355,7 @@ static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint32_t *regs_buff = p; uint16_t phy_data; @@ -432,7 +443,7 @@ e1000_get_regs(struct net_device *netdev, static int e1000_get_eeprom_len(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); return adapter->hw.eeprom.word_size * 2; } @@ -440,7 +451,7 @@ static int e1000_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; int first_word, last_word; @@ -486,7 +497,7 @@ static int e1000_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; @@ -547,7 +558,7 @@ static void e1000_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); @@ -563,7 +574,7 @@ static void e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -584,7 +595,7 @@ static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -651,6 +662,9 @@ err_setup_rx: E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ value = E1000_READ_REG(&adapter->hw, R); \ if(value != (test[pat] & W & M)) { \ + DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ + "0x%08X expected 0x%08X\n", \ + E1000_##R, value, (test[pat] & W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -663,7 +677,9 @@ err_setup_rx: uint32_t value; \ E1000_WRITE_REG(&adapter->hw, R, W & M); \ value = E1000_READ_REG(&adapter->hw, R); \ - if ((W & M) != (value & M)) { \ + if((W & M) != (value & M)) { \ + DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ + "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \ *data = (adapter->hw.mac_type < e1000_82543) ? \ E1000_82542_##R : E1000_##R; \ return 1; \ @@ -673,18 +689,33 @@ err_setup_rx: static int e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) { - uint32_t value; - uint32_t i; + uint32_t value, before, after; + uint32_t i, toggle; /* The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. */ - value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833)); - E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF)); - if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) { + switch (adapter->hw.mac_type) { + case e1000_82573: + toggle = 0x7FFFF033; + break; + default: + toggle = 0xFFFFF833; + break; + } + + before = E1000_READ_REG(&adapter->hw, STATUS); + value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle); + E1000_WRITE_REG(&adapter->hw, STATUS, toggle); + after = E1000_READ_REG(&adapter->hw, STATUS) & toggle; + if(value != after) { + DPRINTK(DRV, ERR, "failed STATUS register test got: " + "0x%08X expected: 0x%08X\n", after, value); *data = 1; return 1; } + /* restore previous status */ + E1000_WRITE_REG(&adapter->hw, STATUS, before); REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); @@ -766,7 +797,7 @@ e1000_test_intr(int irq, struct pt_regs *regs) { struct net_device *netdev = (struct net_device *) data; - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR); @@ -1214,6 +1245,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter) case e1000_82541_rev_2: case e1000_82547: case e1000_82547_rev_2: + case e1000_82573: return e1000_integrated_phy_loopback(adapter); break; @@ -1422,7 +1454,7 @@ static void e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); boolean_t if_running = netif_running(netdev); if(eth_test->flags == ETH_TEST_FL_OFFLINE) { @@ -1482,7 +1514,7 @@ e1000_diag_test(struct net_device *netdev, static void e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1527,7 +1559,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1588,22 +1620,31 @@ e1000_led_blink_callback(unsigned long data) static int e1000_phys_id(struct net_device *netdev, uint32_t data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); - if(!adapter->blink_timer.function) { - init_timer(&adapter->blink_timer); - adapter->blink_timer.function = e1000_led_blink_callback; - adapter->blink_timer.data = (unsigned long) adapter; + if(adapter->hw.mac_type < e1000_82573) { + if(!adapter->blink_timer.function) { + init_timer(&adapter->blink_timer); + adapter->blink_timer.function = e1000_led_blink_callback; + adapter->blink_timer.data = (unsigned long) adapter; + } + e1000_setup_led(&adapter->hw); + mod_timer(&adapter->blink_timer, jiffies); + msleep_interruptible(data * 1000); + del_timer_sync(&adapter->blink_timer); + } + else { + E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE | + E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) | + (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) | + (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT))); + msleep_interruptible(data * 1000); } - e1000_setup_led(&adapter->hw); - mod_timer(&adapter->blink_timer, jiffies); - - msleep_interruptible(data * 1000); - del_timer_sync(&adapter->blink_timer); e1000_led_off(&adapter->hw); clear_bit(E1000_LED_ON, &adapter->led_status); e1000_cleanup_led(&adapter->hw); @@ -1614,7 +1655,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data) static int e1000_nway_reset(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); @@ -1632,7 +1673,7 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); int i; e1000_update_stats(adapter); diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 723589b28be5..045f5426ab9a 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -354,18 +354,27 @@ e1000_set_media_type(struct e1000_hw *hw) hw->media_type = e1000_media_type_internal_serdes; break; default: - if(hw->mac_type >= e1000_82543) { + switch (hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + hw->media_type = e1000_media_type_fiber; + break; + case e1000_82573: + /* The STATUS_TBIMODE bit is reserved or reused for the this + * device. + */ + hw->media_type = e1000_media_type_copper; + break; + default: status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_TBIMODE) { + if (status & E1000_STATUS_TBIMODE) { hw->media_type = e1000_media_type_fiber; /* tbi_compatibility not valid on fiber */ hw->tbi_compatibility_en = FALSE; } else { hw->media_type = e1000_media_type_copper; } - } else { - /* This is an 82542 (fiber only) */ - hw->media_type = e1000_media_type_fiber; + break; } } } @@ -1189,9 +1198,9 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); if(ret_val) return ret_val; - } + } - return E1000_SUCCESS; + return E1000_SUCCESS; } diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index a0263ee96c6b..93e9f8788751 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -66,6 +66,7 @@ typedef enum { e1000_eeprom_spi, e1000_eeprom_microwire, e1000_eeprom_flash, + e1000_eeprom_none, /* No NVM support */ e1000_num_eeprom_types } e1000_eeprom_type; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 325495b8b60c..5e5d2c3c7ce4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -29,6 +29,8 @@ #include "e1000.h" /* Change Log + * 6.0.58 4/20/05 + * o Accepted ethtool cleanup patch from Stephen Hemminger * 6.0.44+ 2/15/05 * o applied Anton's patch to resolve tx hang in hardware * o Applied Andrew Mortons patch - e1000 stops working after resume @@ -41,9 +43,9 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "6.0.54-k2"DRIVERNAPI +#define DRV_VERSION "6.0.60-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; -char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; +char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -160,7 +162,6 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); static void e1000_restore_vlan(struct e1000_adapter *adapter); -static int e1000_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); static int e1000_suspend(struct pci_dev *pdev, uint32_t state); #ifdef CONFIG_PM static int e1000_resume(struct pci_dev *pdev); @@ -171,12 +172,6 @@ static int e1000_resume(struct pci_dev *pdev); static void e1000_netpoll (struct net_device *netdev); #endif -struct notifier_block e1000_notifier_reboot = { - .notifier_call = e1000_notify_reboot, - .next = NULL, - .priority = 0 -}; - /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); @@ -219,9 +214,7 @@ e1000_init_module(void) printk(KERN_INFO "%s\n", e1000_copyright); ret = pci_module_init(&e1000_driver); - if(ret >= 0) { - register_reboot_notifier(&e1000_notifier_reboot); - } + return ret; } @@ -237,7 +230,6 @@ module_init(e1000_init_module); static void __exit e1000_exit_module(void) { - unregister_reboot_notifier(&e1000_notifier_reboot); pci_unregister_driver(&e1000_driver); } @@ -517,7 +509,7 @@ e1000_probe(struct pci_dev *pdev, SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); - adapter = netdev->priv; + adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; @@ -738,7 +730,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t manc, swsm; flush_scheduled_work(); @@ -871,7 +863,7 @@ e1000_sw_init(struct e1000_adapter *adapter) static int e1000_open(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); int err; /* allocate transmit descriptors */ @@ -919,7 +911,7 @@ err_setup_tx: static int e1000_close(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_down(adapter); @@ -1599,7 +1591,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter) static int e1000_set_mac(struct net_device *netdev, void *p) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct sockaddr *addr = p; if(!is_valid_ether_addr(addr->sa_data)) @@ -1634,7 +1626,7 @@ e1000_set_mac(struct net_device *netdev, void *p) static void e1000_set_multi(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct dev_mc_list *mc_ptr; unsigned long flags; @@ -2213,7 +2205,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; @@ -2307,6 +2299,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tso = e1000_tso(adapter, skb); if (tso < 0) { dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } @@ -2343,7 +2336,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static void e1000_tx_timeout(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ schedule_work(&adapter->tx_timeout_task); @@ -2352,7 +2345,7 @@ e1000_tx_timeout(struct net_device *netdev) static void e1000_tx_timeout_task(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_down(adapter); e1000_up(adapter); @@ -2369,7 +2362,7 @@ e1000_tx_timeout_task(struct net_device *netdev) static struct net_device_stats * e1000_get_stats(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_update_stats(adapter); return &adapter->net_stats; @@ -2386,7 +2379,7 @@ e1000_get_stats(struct net_device *netdev) static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || @@ -2597,7 +2590,7 @@ static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint32_t icr = E1000_READ_REG(hw, ICR); #ifndef CONFIG_E1000_NAPI @@ -2660,7 +2653,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) static int e1000_clean(struct net_device *netdev, int *budget) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); int work_to_do = min(*budget, netdev->quota); int tx_cleaned; int work_done = 0; @@ -2671,8 +2664,8 @@ e1000_clean(struct net_device *netdev, int *budget) *budget -= work_done; netdev->quota -= work_done; - /* If no Tx and no Rx work done, exit the polling mode */ if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { + /* If no Tx and not enough Rx work done, exit the polling mode */ netif_rx_complete(netdev); e1000_irq_enable(adapter); return 0; @@ -2768,13 +2761,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); - DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n" + DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" " TDH <%x>\n" " TDT <%x>\n" " next_to_use <%x>\n" " next_to_clean <%x>\n" "buffer_info[next_to_clean]\n" - " dma <%llx>\n" + " dma <%zx>\n" " time_stamp <%lx>\n" " next_to_watch <%x>\n" " jiffies <%lx>\n" @@ -2993,7 +2986,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = rx_desc->wb.middle.status_error; + staterr = le32_to_cpu(rx_desc->wb.middle.status_error); while(staterr & E1000_RXD_STAT_DD) { buffer_info = &rx_ring->buffer_info[i]; @@ -3064,16 +3057,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) #ifdef CONFIG_E1000_NAPI if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.middle.vlan & - E1000_RXD_SPC_VLAN_MASK)); + le16_to_cpu(rx_desc->wb.middle.vlan) & + E1000_RXD_SPC_VLAN_MASK); } else { netif_receive_skb(skb); } #else /* CONFIG_E1000_NAPI */ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { vlan_hwaccel_rx(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.middle.vlan & - E1000_RXD_SPC_VLAN_MASK)); + le16_to_cpu(rx_desc->wb.middle.vlan) & + E1000_RXD_SPC_VLAN_MASK); } else { netif_rx(skb); } @@ -3086,7 +3079,7 @@ next_desc: if(unlikely(++i == rx_ring->count)) i = 0; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = rx_desc->wb.middle.status_error; + staterr = le32_to_cpu(rx_desc->wb.middle.status_error); } rx_ring->next_to_clean = i; adapter->alloc_rx_buf(adapter); @@ -3370,11 +3363,12 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct mii_ioctl_data *data = if_mii(ifr); int retval; uint16_t mii_reg; uint16_t spddplx; + unsigned long flags; if(adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; @@ -3384,22 +3378,29 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) data->phy_id = adapter->hw.phy_addr; break; case SIOCGMIIREG: - if (!capable(CAP_NET_ADMIN)) + if(!capable(CAP_NET_ADMIN)) return -EPERM; - if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) + spin_lock_irqsave(&adapter->stats_lock, flags); + if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + &data->val_out)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; + } + spin_unlock_irqrestore(&adapter->stats_lock, flags); break; case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) + if(!capable(CAP_NET_ADMIN)) return -EPERM; - if (data->reg_num & ~(0x1F)) + if(data->reg_num & ~(0x1F)) return -EFAULT; mii_reg = data->val_in; - if (e1000_write_phy_reg(&adapter->hw, data->reg_num, - mii_reg)) + spin_lock_irqsave(&adapter->stats_lock, flags); + if(e1000_write_phy_reg(&adapter->hw, data->reg_num, + mii_reg)) { + spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; - if (adapter->hw.phy_type == e1000_phy_m88) { + } + if(adapter->hw.phy_type == e1000_phy_m88) { switch (data->reg_num) { case PHY_CTRL: if(mii_reg & MII_CR_POWER_DOWN) @@ -3419,8 +3420,12 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) HALF_DUPLEX; retval = e1000_set_spd_dplx(adapter, spddplx); - if(retval) + if(retval) { + spin_unlock_irqrestore( + &adapter->stats_lock, + flags); return retval; + } } if(netif_running(adapter->netdev)) { e1000_down(adapter); @@ -3430,8 +3435,11 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; case M88E1000_PHY_SPEC_CTRL: case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(&adapter->hw)) + if(e1000_phy_reset(&adapter->hw)) { + spin_unlock_irqrestore( + &adapter->stats_lock, flags); return -EIO; + } break; } } else { @@ -3447,6 +3455,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; } } + spin_unlock_irqrestore(&adapter->stats_lock, flags); break; default: return -EOPNOTSUPP; @@ -3503,7 +3512,7 @@ e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value) static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t ctrl, rctl; e1000_irq_disable(adapter); @@ -3543,7 +3552,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t vfta, index; if((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && @@ -3559,7 +3568,7 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t vfta, index; e1000_irq_disable(adapter); @@ -3600,6 +3609,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) { adapter->hw.autoneg = 0; + /* Fiber NICs only allow 1000 gbps Full duplex */ + if((adapter->hw.media_type == e1000_media_type_fiber) && + spddplx != (SPEED_1000 + DUPLEX_FULL)) { + DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; + } + switch(spddplx) { case SPEED_10 + DUPLEX_HALF: adapter->hw.forced_speed_duplex = e1000_10_half; @@ -3626,27 +3642,10 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) } static int -e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev = NULL; - - switch(event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { - if(pci_dev_driver(pdev) == &e1000_driver) - e1000_suspend(pdev, 3); - } - } - return NOTIFY_DONE; -} - -static int e1000_suspend(struct pci_dev *pdev, uint32_t state) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; uint32_t wufc = adapter->wol; @@ -3739,12 +3738,12 @@ static int e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev->priv; - uint32_t manc, ret, swsm; + struct e1000_adapter *adapter = netdev_priv(netdev); + uint32_t manc, ret_val, swsm; pci_set_power_state(pdev, 0); pci_restore_state(pdev); - ret = pci_enable_device(pdev); + ret_val = pci_enable_device(pdev); pci_set_master(pdev); pci_enable_wake(pdev, 3, 0); @@ -3787,7 +3786,7 @@ e1000_resume(struct pci_dev *pdev) static void e1000_netpoll(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev, NULL); enable_irq(adapter->pdev->irq); diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index 51c9fa260830..f5a4dd7d8564 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -162,12 +162,7 @@ struct net_device * __init e2100_probe(int unit) err = do_e2100_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -286,6 +281,9 @@ static int __init e21_probe1(struct net_device *dev, int ioaddr) #endif NS8390_init(dev, 0); + retval = register_netdev(dev); + if (retval) + goto out; return 0; out: release_region(ioaddr, E21_IO_EXTENT); @@ -453,11 +451,8 @@ init_module(void) dev->mem_start = mem[this_dev]; dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ if (do_e2100_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_e21[found++] = dev; - continue; - } - cleanup_card(dev); + dev_e21[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index cd2475683027..dcb3028bb60f 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -600,12 +600,7 @@ struct net_device * __init eepro_probe(int unit) err = do_eepro_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - release_region(dev->base_addr, EEPRO_IO_EXTENT); out: free_netdev(dev); return ERR_PTR(err); @@ -758,6 +753,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) int i; struct eepro_local *lp; int ioaddr = dev->base_addr; + int err; /* Grab the region so we can find another board if autoIRQ fails. */ if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { @@ -873,10 +869,16 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe) /* reset 82595 */ eepro_reset(ioaddr); + + err = register_netdev(dev); + if (err) + goto err; return 0; exit: + err = -ENODEV; +err: release_region(dev->base_addr, EEPRO_IO_EXTENT); - return -ENODEV; + return err; } /* Open/initialize the board. This is called (in the current kernel) @@ -1834,11 +1836,8 @@ init_module(void) dev->irq = irq[i]; if (do_eepro_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_eepro[n_eepro++] = dev; - continue; - } - release_region(dev->base_addr, EEPRO_IO_EXTENT); + dev_eepro[n_eepro++] = dev; + continue; } free_netdev(dev); break; diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 98b3a2fdce90..1795425f512e 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -1269,7 +1269,7 @@ speedo_init_rx_ring(struct net_device *dev) if (skb == NULL) break; /* OK. Just initially short of Rx bufs. */ skb->dev = dev; /* Mark as being used by this device. */ - rxf = (struct RxFD *)skb->tail; + rxf = (struct RxFD *)skb->data; sp->rx_ringp[i] = rxf; sp->rx_ring_dma[i] = pci_map_single(sp->pdev, rxf, @@ -1661,7 +1661,7 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry) sp->rx_ringp[entry] = NULL; return NULL; } - rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; + rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->data; sp->rx_ring_dma[entry] = pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); @@ -1808,10 +1808,10 @@ speedo_rx(struct net_device *dev) #if 1 || USE_IP_CSUM /* Packet is in one chunk -- we can copy + cksum. */ - eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0); + eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail, + memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->data, pkt_len); #endif pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry], diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index fc8e7947b334..82bd356e4f3a 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -436,11 +436,8 @@ struct net_device * __init express_probe(int unit) netdev_boot_setup_check(dev); err = do_express_probe(dev); - if (!err) { - err = register_netdev(dev); - if (!err) - return dev; - } + if (!err) + return dev; free_netdev(dev); return ERR_PTR(err); } @@ -1205,7 +1202,8 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) dev->set_multicast_list = &eexp_set_multicast; dev->tx_timeout = eexp_timeout; dev->watchdog_timeo = 2*HZ; - return 0; + + return register_netdev(dev); } /* @@ -1716,7 +1714,7 @@ int init_module(void) break; printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); } - if (do_express_probe(dev) == 0 && register_netdev(dev) == 0) { + if (do_express_probe(dev) == 0) { dev_eexp[this_dev] = dev; found++; continue; diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 81ebaedaa240..87f522738bfc 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1003,7 +1003,7 @@ static void epic_init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, - skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn); } ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -1274,7 +1274,7 @@ static int epic_rx(struct net_device *dev, int budget) ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0); + eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, @@ -1308,7 +1308,7 @@ static int epic_rx(struct net_device *dev, int budget) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, - skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); work_done++; } ep->rx_ring[entry].rxstatus = cpu_to_le32(DescOwn); diff --git a/drivers/net/eql.c b/drivers/net/eql.c index dd6865820372..aa1569182fd6 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -132,7 +132,7 @@ static struct net_device_stats *eql_get_stats(struct net_device *dev); #define eql_is_slave(dev) ((dev->flags & IFF_SLAVE) == IFF_SLAVE) #define eql_is_master(dev) ((dev->flags & IFF_MASTER) == IFF_MASTER) -static void eql_kill_one_slave(slave_t *slave); +static void eql_kill_one_slave(slave_queue_t *queue, slave_t *slave); static void eql_timer(unsigned long param) { @@ -149,7 +149,7 @@ static void eql_timer(unsigned long param) if (slave->bytes_queued < 0) slave->bytes_queued = 0; } else { - eql_kill_one_slave(slave); + eql_kill_one_slave(&eql->queue, slave); } } @@ -214,9 +214,10 @@ static int eql_open(struct net_device *dev) return 0; } -static void eql_kill_one_slave(slave_t *slave) +static void eql_kill_one_slave(slave_queue_t *queue, slave_t *slave) { list_del(&slave->list); + queue->num_slaves--; slave->dev->flags &= ~IFF_SLAVE; dev_put(slave->dev); kfree(slave); @@ -232,8 +233,7 @@ static void eql_kill_slave_queue(slave_queue_t *queue) list_for_each_safe(this, tmp, head) { slave_t *s = list_entry(this, slave_t, list); - eql_kill_one_slave(s); - queue->num_slaves--; + eql_kill_one_slave(queue, s); } spin_unlock_bh(&queue->lock); @@ -318,7 +318,7 @@ static slave_t *__eql_schedule_slaves(slave_queue_t *queue) } } else { /* We found a dead slave, kill it. */ - eql_kill_one_slave(slave); + eql_kill_one_slave(queue, slave); } } return best_slave; @@ -393,7 +393,7 @@ static int __eql_insert_slave(slave_queue_t *queue, slave_t *slave) duplicate_slave = __eql_find_slave_dev(queue, slave->dev); if (duplicate_slave != 0) - eql_kill_one_slave(duplicate_slave); + eql_kill_one_slave(queue, duplicate_slave); list_add(&slave->list, &queue->all_slaves); queue->num_slaves++; @@ -471,7 +471,7 @@ static int eql_emancipate(struct net_device *master_dev, slaving_request_t __use slave_dev); if (slave) { - eql_kill_one_slave(slave); + eql_kill_one_slave(&eql->queue, slave); ret = 0; } } diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c index f1e8150ed2a0..50f8e23bb9e5 100644 --- a/drivers/net/es3210.c +++ b/drivers/net/es3210.c @@ -177,12 +177,7 @@ struct net_device * __init es_probe(int unit) err = do_es_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -310,6 +305,10 @@ static int __init es_probe1(struct net_device *dev, int ioaddr) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); + + retval = register_netdev(dev); + if (retval) + goto out1; return 0; out1: free_irq(dev->irq, dev); @@ -445,11 +444,8 @@ init_module(void) dev->base_addr = io[this_dev]; dev->mem_start = mem[this_dev]; if (do_es_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_es3210[found++] = dev; - continue; - } - cleanup_card(dev); + dev_es3210[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index ccae6ba5f7c5..f32a6b3acb2a 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -473,13 +473,7 @@ struct net_device * __init eth16i_probe(int unit) err = do_eth16i_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - free_irq(dev->irq, dev); - release_region(dev->base_addr, ETH16I_IO_EXTENT); out: free_netdev(dev); return ERR_PTR(err); @@ -569,7 +563,13 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr) dev->tx_timeout = eth16i_timeout; dev->watchdog_timeo = TX_TIMEOUT; spin_lock_init(&lp->lock); + + retval = register_netdev(dev); + if (retval) + goto out1; return 0; +out1: + free_irq(dev->irq, dev); out: release_region(ioaddr, ETH16I_IO_EXTENT); return retval; @@ -1462,12 +1462,8 @@ int init_module(void) } if (do_eth16i_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_eth16i[found++] = dev; - continue; - } - free_irq(dev->irq, dev); - release_region(dev->base_addr, ETH16I_IO_EXTENT); + dev_eth16i[found++] = dev; + continue; } printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index dcf969b20be9..b987f9474730 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1308,15 +1308,9 @@ static int __init eisa_probe(struct net_device *dev, u_long ioaddr) if (ioaddr < 0x1000) goto out; - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } + iobase = ioaddr; + i = (ioaddr >> 12); + maxSlots = i + 1; for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { if (EISA_signature(name, EISA_ID) == 0) { diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index d05e9dd1e140..55dbe9a3fd56 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1107,7 +1107,7 @@ static void allocate_rx_buffers(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ np->lack_rxbuf->skbuff = skb; - np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->tail, + np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->lack_rxbuf->status = RXOWN; ++np->really_rx_count; @@ -1300,7 +1300,7 @@ static void init_ring(struct net_device *dev) ++np->really_rx_count; np->rx_ring[i].skbuff = skb; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->tail, + np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->rx_ring[i].status = RXOWN; np->rx_ring[i].control |= RXIC; @@ -1423,8 +1423,7 @@ static void reset_tx_descriptors(struct net_device *dev) if (cur->skbuff) { pci_unmap_single(np->pci_dev, cur->buffer, cur->skbuff->len, PCI_DMA_TODEVICE); - dev_kfree_skb(cur->skbuff); - /* or dev_kfree_skb_irq(cur->skbuff); ? */ + dev_kfree_skb_any(cur->skbuff); cur->skbuff = NULL; } cur->status = 0; @@ -1738,11 +1737,11 @@ static int netdev_rx(struct net_device *dev) #if ! defined(__alpha__) eth_copy_and_sum(skb, - np->cur_rx->skbuff->tail, pkt_len, 0); + np->cur_rx->skbuff->data, pkt_len, 0); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), - np->cur_rx->skbuff->tail, pkt_len); + np->cur_rx->skbuff->data, pkt_len); #endif pci_dma_sync_single_for_device(np->pci_dev, np->cur_rx->buffer, diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c deleted file mode 100644 index 04c748523471..000000000000 --- a/drivers/net/fmv18x.c +++ /dev/null @@ -1,689 +0,0 @@ -/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184. - - Original: at1700.c (1993-94 by Donald Becker). - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp) - Copyright 1994 Fujitsu Laboratories Ltd. - Special thanks to: - Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp) - for testing this driver. - H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp) - for suggestion of some program modification. - Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp> - for suggestion of some program modification. - Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp) - for testing this driver. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - This is a device driver for the Fujitsu FMV-181/182/183/184, which - is a straight-forward Fujitsu MB86965 implementation. - - Sources: - at1700.c - The Fujitsu MB86965 datasheet. - The Fujitsu FMV-181/182 user's guide -*/ - -static const char version[] = - "fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n"; - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/spinlock.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/delay.h> -#include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/dma.h> - -#define DRV_NAME "fmv18x" - -static unsigned fmv18x_probe_list[] __initdata = { - 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 -}; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; - -typedef unsigned char uchar; - -/* Information that need to be kept for each board. */ -struct net_local { - struct net_device_stats stats; - long open_time; /* Useless example local info. */ - uint tx_started:1; /* Number of packet on the Tx queue. */ - uint tx_queue_ready:1; /* Tx queue is ready to be sent. */ - uint rx_started:1; /* Packets are Rxing. */ - uchar tx_queue; /* Number of packet on the Tx queue. */ - ushort tx_queue_len; /* Current length of the Tx queue. */ - spinlock_t lock; -}; - - -/* Offsets from the base address. */ -#define STATUS 0 -#define TX_STATUS 0 -#define RX_STATUS 1 -#define TX_INTR 2 /* Bit-mapped interrupt enable registers. */ -#define RX_INTR 3 -#define TX_MODE 4 -#define RX_MODE 5 -#define CONFIG_0 6 /* Misc. configuration settings. */ -#define CONFIG_1 7 -/* Run-time register bank 2 definitions. */ -#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */ -#define TX_START 10 -#define COL16CNTL 11 /* Controll Reg for 16 collisions */ -#define MODE13 13 -/* Fujitsu FMV-18x Card Configuration */ -#define FJ_STATUS0 0x10 -#define FJ_STATUS1 0x11 -#define FJ_CONFIG0 0x12 -#define FJ_CONFIG1 0x13 -#define FJ_MACADDR 0x14 /* 0x14 - 0x19 */ -#define FJ_BUFCNTL 0x1A -#define FJ_BUFDATA 0x1C -#define FMV18X_IO_EXTENT 32 - -/* Index to functions, as function prototypes. */ - -static int fmv18x_probe1(struct net_device *dev, short ioaddr); -static int net_open(struct net_device *dev); -static int net_send_packet(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void net_rx(struct net_device *dev); -static void net_timeout(struct net_device *dev); -static int net_close(struct net_device *dev); -static struct net_device_stats *net_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ - -static int io = 0x220; -static int irq; - -struct net_device * __init fmv18x_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); - unsigned *port; - int err = 0; - - if (!dev) - return ERR_PTR(-ENODEV); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - io = dev->base_addr; - irq = dev->irq; - } - - SET_MODULE_OWNER(dev); - - if (io > 0x1ff) { /* Check a single specified location. */ - err = fmv18x_probe1(dev, io); - } else if (io != 0) { /* Don't probe at all. */ - err = -ENXIO; - } else { - for (port = fmv18x_probe_list; *port; port++) - if (fmv18x_probe1(dev, *port) == 0) - break; - if (!*port) - err = -ENODEV; - } - if (err) - goto out; - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - free_irq(dev->irq, dev); - release_region(dev->base_addr, FMV18X_IO_EXTENT); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -/* The Fujitsu datasheet suggests that the NIC be probed for by checking its - "signature", the default bit pattern after a reset. This *doesn't* work -- - there is no way to reset the bus interface without a complete power-cycle! - - It turns out that ATI came to the same conclusion I did: the only thing - that can be done is checking a few bits and then diving right into MAC - address check. */ - -static int __init fmv18x_probe1(struct net_device *dev, short ioaddr) -{ - char irqmap[4] = {3, 7, 10, 15}; - char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15}; - unsigned int i, retval; - struct net_local *lp; - - /* Resetting the chip doesn't reset the ISA interface, so don't bother. - That means we have to be careful with the register values we probe for. - */ - - if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME)) - return -EBUSY; - - dev->irq = irq; - dev->base_addr = ioaddr; - - /* Check I/O address configuration and Fujitsu vendor code */ - if (inb(ioaddr+FJ_MACADDR ) != 0x00 - || inb(ioaddr+FJ_MACADDR+1) != 0x00 - || inb(ioaddr+FJ_MACADDR+2) != 0x0e) { - retval = -ENODEV; - goto out; - } - - /* Check PnP mode for FMV-183/184/183A/184A. */ - /* This PnP routine is very poor. IO and IRQ should be known. */ - if (inb(ioaddr + FJ_STATUS1) & 0x20) { - for (i = 0; i < 8; i++) { - if (dev->irq == irqmap_pnp[i]) - break; - } - if (i == 8) { - retval = -ENODEV; - goto out; - } - } else { - if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr) - return -ENODEV; - dev->irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03]; - } - - /* Snarf the interrupt vector now. */ - retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev); - if (retval) { - printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" - "IRQ %d.\n", ioaddr, dev->irq); - goto out; - } - - printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, - ioaddr, dev->irq); - - for(i = 0; i < 6; i++) { - unsigned char val = inb(ioaddr + FJ_MACADDR + i); - printk("%02x", val); - dev->dev_addr[i] = val; - } - - /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals, - rather than 150 ohm shielded twisted pair compensation. - 0x0000 == auto-sense the interface - 0x0800 == use TP interface - 0x1800 == use coax interface - */ - { - const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"}; - ushort setup_value = inb(ioaddr + FJ_STATUS0); - - switch( setup_value & 0x07 ){ - case 0x01 /* 10base5 */: - case 0x02 /* 10base2 */: dev->if_port = 0x18; break; - case 0x04 /* 10baseT */: dev->if_port = 0x08; break; - default /* auto-sense*/: dev->if_port = 0x00; break; - } - printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]); - } - - /* Initialize LAN Controller and LAN Card */ - outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ - outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ - outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ - outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */ - - /* wait for a while */ - udelay(200); - - /* Set the station address in bank zero. */ - outb(0x00, ioaddr + CONFIG_1); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + 8 + i); - - /* Switch to bank 1 and set the multicast table to accept none. */ - outb(0x04, ioaddr + CONFIG_1); - for (i = 0; i < 8; i++) - outb(0x00, ioaddr + 8 + i); - - /* Switch to bank 2 and lock our I/O address. */ - outb(0x08, ioaddr + CONFIG_1); - outb(dev->if_port, ioaddr + MODE13); - outb(0x00, ioaddr + COL16CNTL); - - if (net_debug) - printk(version); - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (!dev->priv) { - retval = -ENOMEM; - goto out_irq; - } - memset(dev->priv, 0, sizeof(struct net_local)); - lp = dev->priv; - spin_lock_init(&lp->lock); - - dev->open = net_open; - dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->tx_timeout = net_timeout; - dev->watchdog_timeo = HZ/10; - dev->get_stats = net_get_stats; - dev->set_multicast_list = set_multicast_list; - return 0; - -out_irq: - free_irq(dev->irq, dev); -out: - release_region(ioaddr, FMV18X_IO_EXTENT); - return retval; -} - - -static int net_open(struct net_device *dev) -{ - struct net_local *lp = dev->priv; - int ioaddr = dev->base_addr; - - /* Set the configuration register 0 to 32K 100ns. byte-wide memory, - 16 bit bus access, and two 4K Tx, enable the Rx and Tx. */ - outb(0x5a, ioaddr + CONFIG_0); - - /* Powerup and switch to register bank 2 for the run-time registers. */ - outb(0xe8, ioaddr + CONFIG_1); - - lp->tx_started = 0; - lp->tx_queue_ready = 1; - lp->rx_started = 0; - lp->tx_queue = 0; - lp->tx_queue_len = 0; - - /* Clear Tx and Rx Status */ - outb(0xff, ioaddr + TX_STATUS); - outb(0xff, ioaddr + RX_STATUS); - lp->open_time = jiffies; - - netif_start_queue(dev); - - /* Enable the IRQ of the LAN Card */ - outb(0x80, ioaddr + FJ_CONFIG1); - - /* Enable both Tx and Rx interrupts */ - outw(0x8182, ioaddr+TX_INTR); - - return 0; -} - -static void net_timeout(struct net_device *dev) -{ - struct net_local *lp = dev->priv; - int ioaddr = dev->base_addr; - unsigned long flags; - - - printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name, - htons(inw(ioaddr + TX_STATUS)), - inb(ioaddr + TX_STATUS) & 0x80 - ? "IRQ conflict" : "network cable problem"); - printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", - dev->name, htons(inw(ioaddr + 0)), - htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), - htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), - htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), - htons(inw(ioaddr +14))); - printk(KERN_WARNING "eth card: %04x %04x\n", - htons(inw(ioaddr+FJ_STATUS0)), - htons(inw(ioaddr+FJ_CONFIG0))); - lp->stats.tx_errors++; - /* ToDo: We should try to restart the adaptor... */ - spin_lock_irqsave(&lp->lock, flags); - - /* Initialize LAN Controller and LAN Card */ - outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ - outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ - outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ - outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ - net_open(dev); - spin_unlock_irqrestore(&lp->lock, flags); - - netif_wake_queue(dev); -} - -static int net_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *lp = dev->priv; - int ioaddr = dev->base_addr; - short length = skb->len; - unsigned char *buf; - unsigned long flags; - - /* Block a transmit from overlapping. */ - - if (length > ETH_FRAME_LEN) { - if (net_debug) - printk("%s: Attempting to send a large packet (%d bytes).\n", - dev->name, length); - return 1; - } - - if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - length = ETH_ZLEN; - } - buf = skb->data; - - if (net_debug > 4) - printk("%s: Transmitting a packet of length %lu.\n", dev->name, - (unsigned long)skb->len); - /* We may not start transmitting unless we finish transferring - a packet into the Tx queue. During executing the following - codes we possibly catch a Tx interrupt. Thus we flag off - tx_queue_ready, so that we prevent the interrupt routine - (net_interrupt) to start transmitting. */ - spin_lock_irqsave(&lp->lock, flags); - lp->tx_queue_ready = 0; - { - outw(length, ioaddr + DATAPORT); - outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - lp->tx_queue++; - lp->tx_queue_len += length + 2; - } - lp->tx_queue_ready = 1; - spin_unlock_irqrestore(&lp->lock, flags); - - if (lp->tx_started == 0) { - /* If the Tx is idle, always trigger a transmit. */ - outb(0x80 | lp->tx_queue, ioaddr + TX_START); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - lp->tx_started = 1; - } else if (lp->tx_queue_len >= 4096 - 1502) /* No room for a packet */ - netif_stop_queue(dev); - - dev_kfree_skb(skb); - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static irqreturn_t -net_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = dev_id; - struct net_local *lp; - int ioaddr, status; - - ioaddr = dev->base_addr; - lp = dev->priv; - status = inw(ioaddr + TX_STATUS); - outw(status, ioaddr + TX_STATUS); - - if (net_debug > 4) - printk("%s: Interrupt with status %04x.\n", dev->name, status); - if (lp->rx_started == 0 && - (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) { - /* Got a packet(s). - We cannot execute net_rx more than once at the same time for - the same device. During executing net_rx, we possibly catch a - Tx interrupt. Thus we flag on rx_started, so that we prevent - the interrupt routine (net_interrupt) to dive into net_rx - again. */ - lp->rx_started = 1; - outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */ - net_rx(dev); - outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */ - lp->rx_started = 0; - } - if (status & 0x00ff) { - if (status & 0x02) { - /* More than 16 collisions occurred */ - if (net_debug > 4) - printk("%s: 16 Collision occur during Txing.\n", dev->name); - /* Cancel sending a packet. */ - outb(0x03, ioaddr + COL16CNTL); - lp->stats.collisions++; - } - if (status & 0x82) { - spin_lock(&lp->lock); - lp->stats.tx_packets++; - if (lp->tx_queue && lp->tx_queue_ready) { - outb(0x80 | lp->tx_queue, ioaddr + TX_START); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - netif_wake_queue(dev); /* Inform upper layers. */ - } else { - lp->tx_started = 0; - netif_wake_queue(dev); /* Inform upper layers. */ - } - spin_unlock(&lp->lock); - } - } - return IRQ_RETVAL(status); -} - -/* We have a good packet(s), get it/them out of the buffers. */ -static void net_rx(struct net_device *dev) -{ - struct net_local *lp = dev->priv; - int ioaddr = dev->base_addr; - int boguscount = 5; - - while ((inb(ioaddr + RX_MODE) & 0x40) == 0) { - /* Clear PKT_RDY bit: by agy 19940922 */ - /* outb(0x80, ioaddr + RX_STATUS); */ - ushort status = inw(ioaddr + DATAPORT); - - if (net_debug > 4) - printk("%s: Rxing packet mode %02x status %04x.\n", - dev->name, inb(ioaddr + RX_MODE), status); -#ifndef final_version - if (status == 0) { - outb(0x05, ioaddr + 14); - break; - } -#endif - - if ((status & 0xF0) != 0x20) { /* There was an error. */ - lp->stats.rx_errors++; - if (status & 0x08) lp->stats.rx_length_errors++; - if (status & 0x04) lp->stats.rx_frame_errors++; - if (status & 0x02) lp->stats.rx_crc_errors++; - if (status & 0x01) lp->stats.rx_over_errors++; - } else { - ushort pkt_len = inw(ioaddr + DATAPORT); - /* Malloc up new buffer. */ - struct sk_buff *skb; - - if (pkt_len > 1550) { - printk("%s: The FMV-18x claimed a very large packet, size %d.\n", - dev->name, pkt_len); - outb(0x05, ioaddr + 14); - lp->stats.rx_errors++; - break; - } - skb = dev_alloc_skb(pkt_len+3); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet (len %d).\n", - dev->name, pkt_len); - outb(0x05, ioaddr + 14); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb,2); - - insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); - - if (net_debug > 5) { - int i; - printk("%s: Rxed packet of length %d: ", dev->name, pkt_len); - for (i = 0; i < 14; i++) - printk(" %02x", skb->data[i]); - printk(".\n"); - } - - skb->protocol=eth_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; - } - if (--boguscount <= 0) - break; - } - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ - { - int i; - for (i = 0; i < 20; i++) { - if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40) - break; - (void)inw(ioaddr + DATAPORT); /* dummy status read */ - outb(0x05, ioaddr + 14); - } - - if (net_debug > 5 && i > 0) - printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", - dev->name, inb(ioaddr + RX_MODE), i); - } - - return; -} - -/* The inverse routine to net_open(). */ -static int net_close(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - - ((struct net_local *)dev->priv)->open_time = 0; - - netif_stop_queue(dev); - - /* Set configuration register 0 to disable Tx and Rx. */ - outb(0xda, ioaddr + CONFIG_0); - - /* Update the statistics -- ToDo. */ - - /* Power-down the chip. Green, green, green! */ - outb(0x00, ioaddr + CONFIG_1); - - /* Set the ethernet adaptor disable IRQ */ - outb(0x00, ioaddr + FJ_CONFIG1); - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct net_device_stats *net_get_stats(struct net_device *dev) -{ - struct net_local *lp = dev->priv; - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. - */ - -static void set_multicast_list(struct net_device *dev) -{ - short ioaddr = dev->base_addr; - if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) - { - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. - AC - */ - dev->flags|=IFF_PROMISC; - - outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ - } - else - outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */ -} - -#ifdef MODULE -static struct net_device *dev_fmv18x; - -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(net_debug, "i"); -MODULE_PARM_DESC(io, "FMV-18X I/O address"); -MODULE_PARM_DESC(irq, "FMV-18X IRQ number"); -MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)"); -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - if (io == 0) - printk("fmv18x: You should not use auto-probing with insmod!\n"); - dev_fmv18x = fmv18x_probe(-1); - if (IS_ERR(dev_fmv18x)) - return PTR_ERR(dev_fmv18x); - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(dev_fmv18x); - free_irq(dev_fmv18x->irq, dev_fmv18x); - release_region(dev_fmv18x->base_addr, FMV18X_IO_EXTENT); - free_netdev(dev_fmv18x); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * c-indent-level: 4 - * End: - */ diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4ebcd052e150..64f0f697c958 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -82,6 +82,9 @@ * 0.31: 14 Nov 2004: ethtool support for getting/setting link * capabilities. * 0.32: 16 Apr 2005: RX_ERROR4 handling added. + * 0.33: 16 May 2005: Support for MCP51 added. + * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics. + * 0.35: 26 Jun 2005: Support for MCP55 added. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -93,7 +96,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.32" +#define FORCEDETH_VERSION "0.35" #define DRV_NAME "forcedeth" #include <linux/module.h> @@ -2005,7 +2008,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* handle different descriptor versions */ if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 || pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 || - pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3) + pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 || + pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || + pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) np->desc_ver = DESC_VER_1; else np->desc_ver = DESC_VER_2; @@ -2215,56 +2220,84 @@ static struct pci_device_id pci_tbl[] = { .device = PCI_DEVICE_ID_NVIDIA_NVENET_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_5, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_6, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_7, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* CK804 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_8, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* CK804 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_9, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* MCP04 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_10, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* MCP04 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_11, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + }, + { /* MCP51 Ethernet Controller */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NVENET_12, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + }, + { /* MCP51 Ethernet Controller */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NVENET_13, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + }, + { /* MCP55 Ethernet Controller */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NVENET_14, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, + }, + { /* MCP55 Ethernet Controller */ + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NVENET_15, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, {0,}, }; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b43b2b11aacd..6518334b9280 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1,4 +1,4 @@ -/* +/* * drivers/net/gianfar.c * * Gianfar Ethernet Driver @@ -22,10 +22,9 @@ * B-V +1.62 * * Theory of operation - * This driver is designed for the Triple-speed Ethernet - * controllers on the Freescale 8540/8560 integrated processors, - * as well as the Fast Ethernet Controller on the 8540. - * + * This driver is designed for the non-CPM ethernet controllers + * on the 85xx and 83xx family of integrated processors + * * The driver is initialized through platform_device. Structures which * define the configuration needed by the board are defined in a * board structure in arch/ppc/platforms (though I do not @@ -39,12 +38,12 @@ * * The Gianfar Ethernet Controller uses a ring of buffer * descriptors. The beginning is indicated by a register - * pointing to the physical address of the start of the ring. - * The end is determined by a "wrap" bit being set in the + * pointing to the physical address of the start of the ring. + * The end is determined by a "wrap" bit being set in the * last descriptor of the ring. * * When a packet is received, the RXF bit in the - * IEVENT register is set, triggering an interrupt when the + * IEVENT register is set, triggering an interrupt when the * corresponding bit in the IMASK register is also set (if * interrupt coalescing is active, then the interrupt may not * happen immediately, but will wait until either a set number @@ -52,7 +51,7 @@ * interrupt handler will signal there is work to be done, and * exit. Without NAPI, the packet(s) will be handled * immediately. Both methods will start at the last known empty - * descriptor, and process every subsequent descriptor until there + * descriptor, and process every subsequent descriptor until there * are none left with data (NAPI will stop after a set number of * packets to give time to other tasks, but will eventually * process all the packets). The data arrives inside a @@ -83,9 +82,13 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> +#include <linux/if_vlan.h> #include <linux/spinlock.h> #include <linux/mm.h> #include <linux/device.h> +#include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/udp.h> #include <asm/io.h> #include <asm/irq.h> @@ -123,7 +126,7 @@ static int gfar_set_mac_address(struct net_device *dev); static int gfar_change_mtu(struct net_device *dev, int new_mtu); static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); -irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void gfar_phy_change(void *data); @@ -139,9 +142,12 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif -static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); +int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); static void gfar_phy_startup_timer(unsigned long data); +static void gfar_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp); +static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); extern struct ethtool_ops gfar_ethtool_ops; @@ -149,6 +155,13 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); +int gfar_uses_fcb(struct gfar_private *priv) +{ + if (priv->vlan_enable || priv->rx_csum_enable) + return 1; + else + return 0; +} static int gfar_probe(struct device *device) { u32 tempval; @@ -159,7 +172,6 @@ static int gfar_probe(struct device *device) struct resource *r; int idx; int err = 0; - int dev_ethtool_ops = 0; einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; @@ -265,15 +277,69 @@ static int gfar_probe(struct device *device) dev->mtu = 1500; dev->set_multicast_list = gfar_set_multi; - /* Index into the array of possible ethtool - * ops to catch all 4 possibilities */ - if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) == 0) - dev_ethtool_ops += 1; + dev->ethtool_ops = &gfar_ethtool_ops; + + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { + priv->rx_csum_enable = 1; + dev->features |= NETIF_F_IP_CSUM; + } else + priv->rx_csum_enable = 0; + + priv->vlgrp = NULL; - if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE) == 0) - dev_ethtool_ops += 2; + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { + dev->vlan_rx_register = gfar_vlan_rx_register; + dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid; - dev->ethtool_ops = gfar_op_array[dev_ethtool_ops]; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + + priv->vlan_enable = 1; + } + + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { + priv->extended_hash = 1; + priv->hash_width = 9; + + priv->hash_regs[0] = &priv->regs->igaddr0; + priv->hash_regs[1] = &priv->regs->igaddr1; + priv->hash_regs[2] = &priv->regs->igaddr2; + priv->hash_regs[3] = &priv->regs->igaddr3; + priv->hash_regs[4] = &priv->regs->igaddr4; + priv->hash_regs[5] = &priv->regs->igaddr5; + priv->hash_regs[6] = &priv->regs->igaddr6; + priv->hash_regs[7] = &priv->regs->igaddr7; + priv->hash_regs[8] = &priv->regs->gaddr0; + priv->hash_regs[9] = &priv->regs->gaddr1; + priv->hash_regs[10] = &priv->regs->gaddr2; + priv->hash_regs[11] = &priv->regs->gaddr3; + priv->hash_regs[12] = &priv->regs->gaddr4; + priv->hash_regs[13] = &priv->regs->gaddr5; + priv->hash_regs[14] = &priv->regs->gaddr6; + priv->hash_regs[15] = &priv->regs->gaddr7; + + } else { + priv->extended_hash = 0; + priv->hash_width = 8; + + priv->hash_regs[0] = &priv->regs->gaddr0; + priv->hash_regs[1] = &priv->regs->gaddr1; + priv->hash_regs[2] = &priv->regs->gaddr2; + priv->hash_regs[3] = &priv->regs->gaddr3; + priv->hash_regs[4] = &priv->regs->gaddr4; + priv->hash_regs[5] = &priv->regs->gaddr5; + priv->hash_regs[6] = &priv->regs->gaddr6; + priv->hash_regs[7] = &priv->regs->gaddr7; + } + + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) + priv->padding = DEFAULT_PADDING; + else + priv->padding = 0; + + dev->hard_header_len += priv->padding; + + if (dev->features & NETIF_F_IP_CSUM) + dev->hard_header_len += GMAC_FCB_LEN; priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; #ifdef CONFIG_GFAR_BUFSTASH @@ -289,6 +355,9 @@ static int gfar_probe(struct device *device) priv->rxcount = DEFAULT_RXCOUNT; priv->rxtime = DEFAULT_RXTIME; + /* Enable most messages by default */ + priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; + err = register_netdev(dev); if (err) { @@ -360,8 +429,9 @@ static int init_phy(struct net_device *dev) GFP_KERNEL); if(NULL == mii_info) { - printk(KERN_ERR "%s: Could not allocate mii_info\n", - dev->name); + if (netif_msg_ifup(priv)) + printk(KERN_ERR "%s: Could not allocate mii_info\n", + dev->name); return -ENOMEM; } @@ -410,7 +480,8 @@ static int init_phy(struct net_device *dev) curphy = get_phy_info(priv->mii_info); if (curphy == NULL) { - printk(KERN_ERR "%s: No PHY found\n", dev->name); + if (netif_msg_ifup(priv)) + printk(KERN_ERR "%s: No PHY found\n", dev->name); err = -1; goto no_phy; } @@ -421,7 +492,7 @@ static int init_phy(struct net_device *dev) if(curphy->init) { err = curphy->init(priv->mii_info); - if (err) + if (err) goto phy_init_fail; } @@ -446,14 +517,14 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); /* Init hash registers to zero */ - gfar_write(&priv->regs->iaddr0, 0); - gfar_write(&priv->regs->iaddr1, 0); - gfar_write(&priv->regs->iaddr2, 0); - gfar_write(&priv->regs->iaddr3, 0); - gfar_write(&priv->regs->iaddr4, 0); - gfar_write(&priv->regs->iaddr5, 0); - gfar_write(&priv->regs->iaddr6, 0); - gfar_write(&priv->regs->iaddr7, 0); + gfar_write(&priv->regs->igaddr0, 0); + gfar_write(&priv->regs->igaddr1, 0); + gfar_write(&priv->regs->igaddr2, 0); + gfar_write(&priv->regs->igaddr3, 0); + gfar_write(&priv->regs->igaddr4, 0); + gfar_write(&priv->regs->igaddr5, 0); + gfar_write(&priv->regs->igaddr6, 0); + gfar_write(&priv->regs->igaddr7, 0); gfar_write(&priv->regs->gaddr0, 0); gfar_write(&priv->regs->gaddr1, 0); @@ -464,9 +535,6 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->gaddr6, 0); gfar_write(&priv->regs->gaddr7, 0); - /* Zero out rctrl */ - gfar_write(&priv->regs->rctrl, 0x00000000); - /* Zero out the rmon mib registers if it has them */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { memset((void *) &(priv->regs->rmon), 0, @@ -497,20 +565,14 @@ static void init_registers(struct net_device *dev) gfar_write(&priv->regs->tbipa, TBIPA_VALUE); } -void stop_gfar(struct net_device *dev) + +/* Halt the receive and transmit queues */ +void gfar_halt(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; - unsigned long flags; u32 tempval; - /* Lock it down */ - spin_lock_irqsave(&priv->lock, flags); - - /* Tell the kernel the link is down */ - priv->mii_info->link = 0; - adjust_link(dev); - /* Mask all interrupts */ gfar_write(®s->imask, IMASK_INIT_CLEAR); @@ -533,13 +595,29 @@ void stop_gfar(struct net_device *dev) tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); gfar_write(®s->maccfg1, tempval); +} + +void stop_gfar(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct gfar *regs = priv->regs; + unsigned long flags; + + /* Lock it down */ + spin_lock_irqsave(&priv->lock, flags); + + /* Tell the kernel the link is down */ + priv->mii_info->link = 0; + adjust_link(dev); + + gfar_halt(dev); if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { /* Clear any pending interrupts */ mii_clear_phy_interrupt(priv->mii_info); /* Disable PHY Interrupts */ - mii_configure_phy_interrupt(priv->mii_info, + mii_configure_phy_interrupt(priv->mii_info, MII_INTERRUPT_DISABLED); } @@ -566,7 +644,7 @@ void stop_gfar(struct net_device *dev) sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, - gfar_read(®s->tbase)); + gfar_read(®s->tbase0)); } /* If there are any tx skbs or rx skbs still around, free them. @@ -620,6 +698,34 @@ void free_skb_resources(struct gfar_private *priv) } } +void gfar_start(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct gfar *regs = priv->regs; + u32 tempval; + + /* Enable Rx and Tx in MACCFG1 */ + tempval = gfar_read(®s->maccfg1); + tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); + gfar_write(®s->maccfg1, tempval); + + /* Initialize DMACTRL to have WWR and WOP */ + tempval = gfar_read(&priv->regs->dmactrl); + tempval |= DMACTRL_INIT_SETTINGS; + gfar_write(&priv->regs->dmactrl, tempval); + + /* Clear THLT, so that the DMA starts polling now */ + gfar_write(®s->tstat, TSTAT_CLEAR_THALT); + + /* Make sure we aren't stopped */ + tempval = gfar_read(&priv->regs->dmactrl); + tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); + gfar_write(&priv->regs->dmactrl, tempval); + + /* Unmask the interrupts we look for */ + gfar_write(®s->imask, IMASK_DEFAULT); +} + /* Bring the controller up and running */ int startup_gfar(struct net_device *dev) { @@ -630,33 +736,34 @@ int startup_gfar(struct net_device *dev) int i; struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; - u32 tempval; int err = 0; + u32 rctrl = 0; gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - vaddr = (unsigned long) dma_alloc_coherent(NULL, + vaddr = (unsigned long) dma_alloc_coherent(NULL, sizeof (struct txbd8) * priv->tx_ring_size + sizeof (struct rxbd8) * priv->rx_ring_size, &addr, GFP_KERNEL); if (vaddr == 0) { - printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", - dev->name); + if (netif_msg_ifup(priv)) + printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", + dev->name); return -ENOMEM; } priv->tx_bd_base = (struct txbd8 *) vaddr; /* enet DMA only understands physical addresses */ - gfar_write(®s->tbase, addr); + gfar_write(®s->tbase0, addr); /* Start the rx descriptor ring where the tx ring leaves off */ addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; priv->rx_bd_base = (struct rxbd8 *) vaddr; - gfar_write(®s->rbase, addr); + gfar_write(®s->rbase0, addr); /* Setup the skbuff rings */ priv->tx_skbuff = @@ -664,8 +771,9 @@ int startup_gfar(struct net_device *dev) priv->tx_ring_size, GFP_KERNEL); if (priv->tx_skbuff == NULL) { - printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", - dev->name); + if (netif_msg_ifup(priv)) + printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", + dev->name); err = -ENOMEM; goto tx_skb_fail; } @@ -678,8 +786,9 @@ int startup_gfar(struct net_device *dev) priv->rx_ring_size, GFP_KERNEL); if (priv->rx_skbuff == NULL) { - printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", - dev->name); + if (netif_msg_ifup(priv)) + printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", + dev->name); err = -ENOMEM; goto rx_skb_fail; } @@ -726,12 +835,13 @@ int startup_gfar(struct net_device *dev) /* If the device has multiple interrupts, register for * them. Otherwise, only register for the one */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - /* Install our interrupt handlers for Error, + /* Install our interrupt handlers for Error, * Transmit, and Receive */ if (request_irq(priv->interruptError, gfar_error, 0, "enet_error", dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptError); + if (netif_msg_intr(priv)) + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptError); err = -1; goto err_irq_fail; @@ -739,8 +849,9 @@ int startup_gfar(struct net_device *dev) if (request_irq(priv->interruptTransmit, gfar_transmit, 0, "enet_tx", dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptTransmit); + if (netif_msg_intr(priv)) + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptTransmit); err = -1; @@ -749,8 +860,9 @@ int startup_gfar(struct net_device *dev) if (request_irq(priv->interruptReceive, gfar_receive, 0, "enet_rx", dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", - dev->name, priv->interruptReceive); + if (netif_msg_intr(priv)) + printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", + dev->name, priv->interruptReceive); err = -1; goto rx_irq_fail; @@ -758,8 +870,9 @@ int startup_gfar(struct net_device *dev) } else { if (request_irq(priv->interruptTransmit, gfar_interrupt, 0, "gfar_interrupt", dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d\n", - dev->name, priv->interruptError); + if (netif_msg_intr(priv)) + printk(KERN_ERR "%s: Can't get IRQ %d\n", + dev->name, priv->interruptError); err = -1; goto err_irq_fail; @@ -787,28 +900,22 @@ int startup_gfar(struct net_device *dev) else gfar_write(®s->rxic, 0); - init_waitqueue_head(&priv->rxcleanupq); + if (priv->rx_csum_enable) + rctrl |= RCTRL_CHECKSUMMING; - /* Enable Rx and Tx in MACCFG1 */ - tempval = gfar_read(®s->maccfg1); - tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); - gfar_write(®s->maccfg1, tempval); + if (priv->extended_hash) + rctrl |= RCTRL_EXTHASH; - /* Initialize DMACTRL to have WWR and WOP */ - tempval = gfar_read(&priv->regs->dmactrl); - tempval |= DMACTRL_INIT_SETTINGS; - gfar_write(&priv->regs->dmactrl, tempval); + if (priv->vlan_enable) + rctrl |= RCTRL_VLAN; - /* Clear THLT, so that the DMA starts polling now */ - gfar_write(®s->tstat, TSTAT_CLEAR_THALT); + /* Init rctrl based on our settings */ + gfar_write(&priv->regs->rctrl, rctrl); - /* Make sure we aren't stopped */ - tempval = gfar_read(&priv->regs->dmactrl); - tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); + if (dev->features & NETIF_F_IP_CSUM) + gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); - /* Unmask the interrupts we look for */ - gfar_write(®s->imask, IMASK_DEFAULT); + gfar_start(dev); return 0; @@ -824,7 +931,7 @@ tx_skb_fail: sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, - gfar_read(®s->tbase)); + gfar_read(®s->tbase0)); if (priv->mii_info->phyinfo->close) priv->mii_info->phyinfo->close(priv->mii_info); @@ -857,11 +964,62 @@ static int gfar_enet_open(struct net_device *dev) return err; } +static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp) +{ + struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); + + memset(fcb, 0, GMAC_FCB_LEN); + + /* Flag the bd so the controller looks for the FCB */ + bdp->status |= TXBD_TOE; + + return fcb; +} + +static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) +{ + int len; + + /* If we're here, it's a IP packet with a TCP or UDP + * payload. We set it to checksum, using a pseudo-header + * we provide + */ + fcb->ip = 1; + fcb->tup = 1; + fcb->ctu = 1; + fcb->nph = 1; + + /* Notify the controller what the protocol is */ + if (skb->nh.iph->protocol == IPPROTO_UDP) + fcb->udp = 1; + + /* l3os is the distance between the start of the + * frame (skb->data) and the start of the IP hdr. + * l4os is the distance between the start of the + * l3 hdr and the l4 hdr */ + fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN); + fcb->l4os = (u16)(skb->h.raw - skb->nh.raw); + + len = skb->nh.iph->tot_len - fcb->l4os; + + /* Provide the pseudoheader csum */ + fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, len, + skb->nh.iph->protocol, 0); +} + +void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) +{ + fcb->vln = 1; + fcb->vlctl = vlan_tx_tag_get(skb); +} + /* This is called by the kernel when a frame is ready for transmission. */ /* It is pointed to by the dev->hard_start_xmit function pointer */ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + struct txfcb *fcb = NULL; struct txbd8 *txbdp; /* Update transmit stats */ @@ -876,9 +1034,24 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Clear all but the WRAP status flags */ txbdp->status &= TXBD_WRAP; + /* Set up checksumming */ + if ((dev->features & NETIF_F_IP_CSUM) + && (CHECKSUM_HW == skb->ip_summed)) { + fcb = gfar_add_fcb(skb, txbdp); + gfar_tx_checksum(skb, fcb); + } + + if (priv->vlan_enable && + unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) { + if (NULL == fcb) + fcb = gfar_add_fcb(skb, txbdp); + + gfar_tx_vlan(skb, fcb); + } + /* Set buffer length and pointer */ txbdp->length = skb->len; - txbdp->bufPtr = dma_map_single(NULL, skb->data, + txbdp->bufPtr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); /* Save the skb pointer so we can free it later */ @@ -972,15 +1145,78 @@ int gfar_set_mac_address(struct net_device *dev) } +/* Enables and disables VLAN insertion/extraction */ +static void gfar_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct gfar_private *priv = netdev_priv(dev); + unsigned long flags; + u32 tempval; + + spin_lock_irqsave(&priv->lock, flags); + + priv->vlgrp = grp; + + if (grp) { + /* Enable VLAN tag insertion */ + tempval = gfar_read(&priv->regs->tctrl); + tempval |= TCTRL_VLINS; + + gfar_write(&priv->regs->tctrl, tempval); + + /* Enable VLAN tag extraction */ + tempval = gfar_read(&priv->regs->rctrl); + tempval |= RCTRL_VLEX; + gfar_write(&priv->regs->rctrl, tempval); + } else { + /* Disable VLAN tag insertion */ + tempval = gfar_read(&priv->regs->tctrl); + tempval &= ~TCTRL_VLINS; + gfar_write(&priv->regs->tctrl, tempval); + + /* Disable VLAN tag extraction */ + tempval = gfar_read(&priv->regs->rctrl); + tempval &= ~RCTRL_VLEX; + gfar_write(&priv->regs->rctrl, tempval); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + + +static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) +{ + struct gfar_private *priv = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->vlgrp) + priv->vlgrp->vlan_devices[vid] = NULL; + + spin_unlock_irqrestore(&priv->lock, flags); +} + + static int gfar_change_mtu(struct net_device *dev, int new_mtu) { int tempsize, tempval; struct gfar_private *priv = netdev_priv(dev); int oldsize = priv->rx_buffer_size; - int frame_size = new_mtu + 18; + int frame_size = new_mtu + ETH_HLEN; + + if (priv->vlan_enable) + frame_size += VLAN_ETH_HLEN; + + if (gfar_uses_fcb(priv)) + frame_size += GMAC_FCB_LEN; + + frame_size += priv->padding; if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { - printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name); + if (netif_msg_drv(priv)) + printk(KERN_ERR "%s: Invalid MTU setting\n", + dev->name); return -EINVAL; } @@ -1120,7 +1356,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) skb->dev = dev; bdp->bufPtr = dma_map_single(NULL, skb->data, - priv->rx_buffer_size + RXBUF_ALIGNMENT, + priv->rx_buffer_size + RXBUF_ALIGNMENT, DMA_FROM_DEVICE); bdp->length = 0; @@ -1190,11 +1426,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) __netif_rx_schedule(dev); } else { -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", - dev->name, gfar_read(&priv->regs->ievent), - gfar_read(&priv->regs->imask)); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", + dev->name, gfar_read(&priv->regs->ievent), + gfar_read(&priv->regs->imask)); } #else @@ -1209,15 +1444,43 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) else gfar_write(&priv->regs->rxic, 0); - /* Just in case we need to wake the ring param changer */ - priv->rxclean = 1; - spin_unlock(&priv->lock); #endif return IRQ_HANDLED; } +static inline int gfar_rx_vlan(struct sk_buff *skb, + struct vlan_group *vlgrp, unsigned short vlctl) +{ +#ifdef CONFIG_GFAR_NAPI + return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl); +#else + return vlan_hwaccel_rx(skb, vlgrp, vlctl); +#endif +} + +static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) +{ + /* If valid headers were found, and valid sums + * were verified, then we tell the kernel that no + * checksumming is necessary. Otherwise, it is */ + if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; +} + + +static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb) +{ + struct rxfcb *fcb = (struct rxfcb *)skb->data; + + /* Remove the FCB from the skb */ + skb_pull(skb, GMAC_FCB_LEN); + + return fcb; +} /* gfar_process_frame() -- handle one incoming packet if skb * isn't NULL. */ @@ -1225,35 +1488,51 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length) { struct gfar_private *priv = netdev_priv(dev); + struct rxfcb *fcb = NULL; if (skb == NULL) { -#ifdef BRIEF_GFAR_ERRORS - printk(KERN_WARNING "%s: Missing skb!!.\n", - dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name); priv->stats.rx_dropped++; priv->extra_stats.rx_skbmissing++; } else { + int ret; + /* Prep the skb for the packet */ skb_put(skb, length); + /* Grab the FCB if there is one */ + if (gfar_uses_fcb(priv)) + fcb = gfar_get_fcb(skb); + + /* Remove the padded bytes, if there are any */ + if (priv->padding) + skb_pull(skb, priv->padding); + + if (priv->rx_csum_enable) + gfar_rx_checksum(skb, fcb); + /* Tell the skb what kind of packet this is */ skb->protocol = eth_type_trans(skb, dev); /* Send the packet up the stack */ - if (RECEIVE(skb) == NET_RX_DROP) { + if (unlikely(priv->vlgrp && fcb->vln)) + ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl); + else + ret = RECEIVE(skb); + + if (NET_RX_DROP == ret) priv->extra_stats.kernel_dropped++; - } } return 0; } /* gfar_clean_rx_ring() -- Processes each frame in the rx ring - * until the budget/quota has been reached. Returns the number + * until the budget/quota has been reached. Returns the number * of frames handled */ -static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) +int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) { struct rxbd8 *bdp; struct sk_buff *skb; @@ -1355,9 +1634,6 @@ static int gfar_poll(struct net_device *dev, int *budget) mk_ic_value(priv->rxcount, priv->rxtime)); else gfar_write(&priv->regs->rxic, 0); - - /* Signal to the ring size changer that it's safe to go */ - priv->rxclean = 1; } return (rx_work_limit < 0) ? 1 : 0; @@ -1393,10 +1669,8 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (events & IEVENT_CRL) priv->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_WARNING "%s: tx underrun. dropped packet\n", - dev->name); -#endif + if (netif_msg_tx_err(priv)) + printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name); priv->stats.tx_dropped++; priv->extra_stats.tx_underrun++; @@ -1415,36 +1689,30 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); #endif -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, - gfar_read(&priv->regs->rstat)); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", + dev->name, + gfar_read(&priv->regs->rstat)); } if (events & IEVENT_BABR) { priv->stats.rx_errors++; priv->extra_stats.rx_babr++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: babbling error\n", dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: babbling error\n", dev->name); } if (events & IEVENT_EBERR) { priv->extra_stats.eberr++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: EBERR\n", dev->name); -#endif - } - if (events & IEVENT_RXC) { -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: control frame\n", dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: EBERR\n", dev->name); } + if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv))) + printk(KERN_DEBUG "%s: control frame\n", dev->name); if (events & IEVENT_BABT) { priv->extra_stats.tx_babt++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: babt error\n", dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: babt error\n", dev->name); } return IRQ_HANDLED; @@ -1510,7 +1778,7 @@ static void gfar_phy_timer(unsigned long data) * If, after GFAR_AN_TIMEOUT seconds, it has not * finished, we switch to forced. * Either way, once the process has completed, we either - * request the interrupt, or switch the timer over to + * request the interrupt, or switch the timer over to * using gfar_phy_timer to check status */ static void gfar_phy_startup_timer(unsigned long data) { @@ -1535,8 +1803,9 @@ static void gfar_phy_startup_timer(unsigned long data) /* Forcing failed! Give up */ if(result) { - printk(KERN_ERR "%s: Forcing failed!\n", - mii_info->dev->name); + if (netif_msg_link(priv)) + printk(KERN_ERR "%s: Forcing failed!\n", + mii_info->dev->name); return; } } @@ -1546,16 +1815,17 @@ static void gfar_phy_startup_timer(unsigned long data) /* Grab the PHY interrupt, if necessary/possible */ if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { - if (request_irq(priv->einfo->interruptPHY, + if (request_irq(priv->einfo->interruptPHY, phy_interrupt, - SA_SHIRQ, - "phy_interrupt", + SA_SHIRQ, + "phy_interrupt", mii_info->dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", - mii_info->dev->name, + if (netif_msg_intr(priv)) + printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", + mii_info->dev->name, priv->einfo->interruptPHY); } else { - mii_configure_phy_interrupt(priv->mii_info, + mii_configure_phy_interrupt(priv->mii_info, MII_INTERRUPT_ENABLED); return; } @@ -1592,15 +1862,17 @@ static void adjust_link(struct net_device *dev) tempval &= ~(MACCFG2_FULL_DUPLEX); gfar_write(®s->maccfg2, tempval); - printk(KERN_INFO "%s: Half Duplex\n", - dev->name); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s: Half Duplex\n", + dev->name); } else { tempval = gfar_read(®s->maccfg2); tempval |= MACCFG2_FULL_DUPLEX; gfar_write(®s->maccfg2, tempval); - printk(KERN_INFO "%s: Full Duplex\n", - dev->name); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s: Full Duplex\n", + dev->name); } priv->oldduplex = mii_info->duplex; @@ -1622,27 +1894,32 @@ static void adjust_link(struct net_device *dev) gfar_write(®s->maccfg2, tempval); break; default: - printk(KERN_WARNING - "%s: Ack! Speed (%d) is not 10/100/1000!\n", - dev->name, mii_info->speed); + if (netif_msg_link(priv)) + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not 10/100/1000!\n", + dev->name, mii_info->speed); break; } - printk(KERN_INFO "%s: Speed %dBT\n", dev->name, - mii_info->speed); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s: Speed %dBT\n", dev->name, + mii_info->speed); priv->oldspeed = mii_info->speed; } if (!priv->oldlink) { - printk(KERN_INFO "%s: Link is up\n", dev->name); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s: Link is up\n", dev->name); priv->oldlink = 1; netif_carrier_on(dev); netif_schedule(dev); } } else { if (priv->oldlink) { - printk(KERN_INFO "%s: Link is down\n", dev->name); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s: Link is down\n", + dev->name); priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; @@ -1664,8 +1941,9 @@ static void gfar_set_multi(struct net_device *dev) u32 tempval; if(dev->flags & IFF_PROMISC) { - printk(KERN_INFO "%s: Entering promiscuous mode.\n", - dev->name); + if (netif_msg_drv(priv)) + printk(KERN_INFO "%s: Entering promiscuous mode.\n", + dev->name); /* Set RCTRL to PROM */ tempval = gfar_read(®s->rctrl); tempval |= RCTRL_PROM; @@ -1679,6 +1957,14 @@ static void gfar_set_multi(struct net_device *dev) if(dev->flags & IFF_ALLMULTI) { /* Set the hash to rx all multicast frames */ + gfar_write(®s->igaddr0, 0xffffffff); + gfar_write(®s->igaddr1, 0xffffffff); + gfar_write(®s->igaddr2, 0xffffffff); + gfar_write(®s->igaddr3, 0xffffffff); + gfar_write(®s->igaddr4, 0xffffffff); + gfar_write(®s->igaddr5, 0xffffffff); + gfar_write(®s->igaddr6, 0xffffffff); + gfar_write(®s->igaddr7, 0xffffffff); gfar_write(®s->gaddr0, 0xffffffff); gfar_write(®s->gaddr1, 0xffffffff); gfar_write(®s->gaddr2, 0xffffffff); @@ -1689,6 +1975,14 @@ static void gfar_set_multi(struct net_device *dev) gfar_write(®s->gaddr7, 0xffffffff); } else { /* zero out the hash */ + gfar_write(®s->igaddr0, 0x0); + gfar_write(®s->igaddr1, 0x0); + gfar_write(®s->igaddr2, 0x0); + gfar_write(®s->igaddr3, 0x0); + gfar_write(®s->igaddr4, 0x0); + gfar_write(®s->igaddr5, 0x0); + gfar_write(®s->igaddr6, 0x0); + gfar_write(®s->igaddr7, 0x0); gfar_write(®s->gaddr0, 0x0); gfar_write(®s->gaddr1, 0x0); gfar_write(®s->gaddr2, 0x0); @@ -1727,16 +2021,15 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) { u32 tempval; struct gfar_private *priv = netdev_priv(dev); - struct gfar *regs = priv->regs; - u32 *hash = ®s->gaddr0; u32 result = ether_crc(MAC_ADDR_LEN, addr); - u8 whichreg = ((result >> 29) & 0x7); - u8 whichbit = ((result >> 24) & 0x1f); + int width = priv->hash_width; + u8 whichbit = (result >> (32 - width)) & 0x1f; + u8 whichreg = result >> (32 - width + 5); u32 value = (1 << (31-whichbit)); - tempval = gfar_read(&hash[whichreg]); + tempval = gfar_read(priv->hash_regs[whichreg]); tempval |= value; - gfar_write(&hash[whichreg], tempval); + gfar_write(priv->hash_regs[whichreg], tempval); return; } @@ -1754,10 +2047,9 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK); /* Hmm... */ -#if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS) - printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", - dev->name, events, gfar_read(&priv->regs->imask)); -#endif + if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv)) + printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", + dev->name, events, gfar_read(&priv->regs->imask)); /* Update the error counters */ if (events & IEVENT_TXE) { @@ -1768,19 +2060,17 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) if (events & IEVENT_CRL) priv->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: underrun. packet dropped.\n", - dev->name); -#endif + if (netif_msg_tx_err(priv)) + printk(KERN_DEBUG "%s: underrun. packet dropped.\n", + dev->name); priv->stats.tx_dropped++; priv->extra_stats.tx_underrun++; /* Reactivate the Tx Queues */ gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); } -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); -#endif + if (netif_msg_tx_err(priv)) + printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); } if (events & IEVENT_BSY) { priv->stats.rx_errors++; @@ -1793,35 +2083,31 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); #endif -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, - gfar_read(&priv->regs->rstat)); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", + dev->name, + gfar_read(&priv->regs->rstat)); } if (events & IEVENT_BABR) { priv->stats.rx_errors++; priv->extra_stats.rx_babr++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: babbling error\n", dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: babbling error\n", dev->name); } if (events & IEVENT_EBERR) { priv->extra_stats.eberr++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: EBERR\n", dev->name); -#endif + if (netif_msg_rx_err(priv)) + printk(KERN_DEBUG "%s: EBERR\n", dev->name); } - if (events & IEVENT_RXC) -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: control frame\n", dev->name); -#endif + if ((events & IEVENT_RXC) && netif_msg_rx_status(priv)) + if (netif_msg_rx_status(priv)) + printk(KERN_DEBUG "%s: control frame\n", dev->name); if (events & IEVENT_BABT) { priv->extra_stats.tx_babt++; -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_DEBUG "%s: babt error\n", dev->name); -#endif + if (netif_msg_tx_err(priv)) + printk(KERN_DEBUG "%s: babt error\n", dev->name); } return IRQ_HANDLED; } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index c2f783a6a9fa..28af087d9fbb 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1,4 +1,4 @@ -/* +/* * drivers/net/gianfar.h * * Gianfar Ethernet Driver @@ -53,6 +53,12 @@ /* The maximum number of packets to be handled in one call of gfar_poll */ #define GFAR_DEV_WEIGHT 64 +/* Length for FCB */ +#define GMAC_FCB_LEN 8 + +/* Default padding amount */ +#define DEFAULT_PADDING 2 + /* Number of bytes to align the rx bufs to */ #define RXBUF_ALIGNMENT 64 @@ -91,7 +97,7 @@ extern const char gfar_driver_version[]; #define JUMBO_FRAME_SIZE 9600 /* Latency of interface clock in nanoseconds */ -/* Interface clock latency , in this case, means the +/* Interface clock latency , in this case, means the * time described by a value of 1 in the interrupt * coalescing registers' time fields. Since those fields * refer to the time it takes for 64 clocks to pass, the @@ -166,9 +172,28 @@ extern const char gfar_driver_version[]; mk_ic_icft(count) | \ mk_ic_ictt(time)) +#define RCTRL_PAL_MASK 0x001f0000 +#define RCTRL_VLEX 0x00002000 +#define RCTRL_FILREN 0x00001000 +#define RCTRL_GHTX 0x00000400 +#define RCTRL_IPCSEN 0x00000200 +#define RCTRL_TUCSEN 0x00000100 +#define RCTRL_PRSDEP_MASK 0x000000c0 +#define RCTRL_PRSDEP_INIT 0x000000c0 #define RCTRL_PROM 0x00000008 +#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \ + | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT) +#define RCTRL_EXTHASH (RCTRL_GHTX) +#define RCTRL_VLAN (RCTRL_PRSDEP_INIT) + + #define RSTAT_CLEAR_RHALT 0x00800000 +#define TCTRL_IPCSEN 0x00004000 +#define TCTRL_TUCSEN 0x00002000 +#define TCTRL_VLINS 0x00001000 +#define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) + #define IEVENT_INIT_CLEAR 0xffffffff #define IEVENT_BABR 0x80000000 #define IEVENT_RXC 0x40000000 @@ -187,12 +212,16 @@ extern const char gfar_driver_version[]; #define IEVENT_RXB0 0x00008000 #define IEVENT_GRSC 0x00000100 #define IEVENT_RXF0 0x00000080 +#define IEVENT_FIR 0x00000008 +#define IEVENT_FIQ 0x00000004 +#define IEVENT_DPE 0x00000002 +#define IEVENT_PERR 0x00000001 #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) #define IEVENT_ERR_MASK \ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ - | IEVENT_CRL | IEVENT_XFUN) + | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR) #define IMASK_INIT_CLEAR 0x00000000 #define IMASK_BABR 0x80000000 @@ -212,10 +241,15 @@ extern const char gfar_driver_version[]; #define IMASK_RXB0 0x00008000 #define IMASK_GTSC 0x00000100 #define IMASK_RXFEN0 0x00000080 +#define IMASK_FIR 0x00000008 +#define IMASK_FIQ 0x00000004 +#define IMASK_DPE 0x00000002 +#define IMASK_PERR 0x00000001 #define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY) #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ - IMASK_XFUN | IMASK_RXC | IMASK_BABT) + IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ + | IMASK_PERR) /* Attribute fields */ @@ -254,6 +288,18 @@ extern const char gfar_driver_version[]; #define TXBD_RETRYLIMIT 0x0040 #define TXBD_RETRYCOUNTMASK 0x003c #define TXBD_UNDERRUN 0x0002 +#define TXBD_TOE 0x0002 + +/* Tx FCB param bits */ +#define TXFCB_VLN 0x80 +#define TXFCB_IP 0x40 +#define TXFCB_IP6 0x20 +#define TXFCB_TUP 0x10 +#define TXFCB_UDP 0x08 +#define TXFCB_CIP 0x04 +#define TXFCB_CTU 0x02 +#define TXFCB_NPH 0x01 +#define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH) /* RxBD status field bits */ #define RXBD_EMPTY 0x8000 @@ -273,6 +319,18 @@ extern const char gfar_driver_version[]; #define RXBD_TRUNCATED 0x0001 #define RXBD_STATS 0x01ff +/* Rx FCB status field bits */ +#define RXFCB_VLN 0x8000 +#define RXFCB_IP 0x4000 +#define RXFCB_IP6 0x2000 +#define RXFCB_TUP 0x1000 +#define RXFCB_CIP 0x0800 +#define RXFCB_CTU 0x0400 +#define RXFCB_EIP 0x0200 +#define RXFCB_ETU 0x0100 +#define RXFCB_PERR_MASK 0x000c +#define RXFCB_PERR_BADL3 0x0008 + struct txbd8 { u16 status; /* Status Fields */ @@ -280,6 +338,22 @@ struct txbd8 u32 bufPtr; /* Buffer Pointer */ }; +struct txfcb { + u8 vln:1, + ip:1, + ip6:1, + tup:1, + udp:1, + cip:1, + ctu:1, + nph:1; + u8 reserved; + u8 l4os; /* Level 4 Header Offset */ + u8 l3os; /* Level 3 Header Offset */ + u16 phcs; /* Pseudo-header Checksum */ + u16 vlctl; /* VLAN control word */ +}; + struct rxbd8 { u16 status; /* Status Fields */ @@ -287,6 +361,21 @@ struct rxbd8 u32 bufPtr; /* Buffer Pointer */ }; +struct rxfcb { + u16 vln:1, + ip:1, + ip6:1, + tup:1, + cip:1, + ctu:1, + eip:1, + etu:1; + u8 rq; /* Receive Queue index */ + u8 pro; /* Layer 4 Protocol */ + u16 reserved; + u16 vlctl; /* VLAN control word */ +}; + struct rmon_mib { u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ @@ -371,90 +460,191 @@ struct gfar_stats { struct gfar { - u8 res1[16]; - u32 ievent; /* 0x.010 - Interrupt Event Register */ - u32 imask; /* 0x.014 - Interrupt Mask Register */ - u32 edis; /* 0x.018 - Error Disabled Register */ + u32 tsec_id; /* 0x.000 - Controller ID register */ + u8 res1[12]; + u32 ievent; /* 0x.010 - Interrupt Event Register */ + u32 imask; /* 0x.014 - Interrupt Mask Register */ + u32 edis; /* 0x.018 - Error Disabled Register */ u8 res2[4]; - u32 ecntrl; /* 0x.020 - Ethernet Control Register */ - u32 minflr; /* 0x.024 - Minimum Frame Length Register */ - u32 ptv; /* 0x.028 - Pause Time Value Register */ - u32 dmactrl; /* 0x.02c - DMA Control Register */ - u32 tbipa; /* 0x.030 - TBI PHY Address Register */ + u32 ecntrl; /* 0x.020 - Ethernet Control Register */ + u32 minflr; /* 0x.024 - Minimum Frame Length Register */ + u32 ptv; /* 0x.028 - Pause Time Value Register */ + u32 dmactrl; /* 0x.02c - DMA Control Register */ + u32 tbipa; /* 0x.030 - TBI PHY Address Register */ u8 res3[88]; - u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ + u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */ u8 res4[8]; - u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ + u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ - u8 res5[96]; - u32 tctrl; /* 0x.100 - Transmit Control Register */ - u32 tstat; /* 0x.104 - Transmit Status Register */ - u8 res6[4]; - u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ - u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ - u8 res7[16]; - u32 ctbptr; /* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */ - u8 res8[92]; - u32 tbptr; /* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */ - u8 res9[124]; - u32 tbase; /* 0x.204 - Transmit Descriptor Base Address Register */ - u8 res10[168]; - u32 ostbd; /* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */ - u32 ostbdp; /* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */ - u8 res11[72]; - u32 rctrl; /* 0x.300 - Receive Control Register */ - u32 rstat; /* 0x.304 - Receive Status Register */ - u8 res12[4]; - u32 rbdlen; /* 0x.30c - RxBD Data Length Register */ - u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ - u8 res13[16]; - u32 crbptr; /* 0x.324 - Current Receive Buffer Descriptor Pointer */ - u8 res14[24]; - u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ - u8 res15[64]; - u32 rbptr; /* 0x.384 - Receive Buffer Descriptor Pointer */ - u8 res16[124]; - u32 rbase; /* 0x.404 - Receive Descriptor Base Address */ - u8 res17[248]; - u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ - u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ - u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ - u32 hafdup; /* 0x.50c - Half Duplex Register */ - u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ + u8 res5[4]; + u32 fifo_rx_pause; /* 0x.0a4 - FIFO receive pause threshold register */ + u32 fifo_rx_alarm; /* 0x.0a8 - FIFO receive alarm threshold register */ + u8 res6[84]; + u32 tctrl; /* 0x.100 - Transmit Control Register */ + u32 tstat; /* 0x.104 - Transmit Status Register */ + u32 dfvlan; /* 0x.108 - Default VLAN Control word */ + u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ + u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ + u32 tqueue; /* 0x.114 - Transmit queue control register */ + u8 res7[40]; + u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */ + u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */ + u8 res8[52]; + u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */ + u8 res9a[4]; + u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */ + u8 res9b[4]; + u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */ + u8 res9c[4]; + u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */ + u8 res9d[4]; + u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */ + u8 res9e[4]; + u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */ + u8 res9f[4]; + u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */ + u8 res9g[4]; + u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */ + u8 res9h[4]; + u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */ + u8 res9[64]; + u32 tbaseh; /* 0x.200 - TxBD base address high */ + u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */ + u8 res10a[4]; + u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */ + u8 res10b[4]; + u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */ + u8 res10c[4]; + u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */ + u8 res10d[4]; + u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */ + u8 res10e[4]; + u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */ + u8 res10f[4]; + u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */ + u8 res10g[4]; + u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */ + u8 res10[192]; + u32 rctrl; /* 0x.300 - Receive Control Register */ + u32 rstat; /* 0x.304 - Receive Status Register */ + u8 res12[8]; + u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ + u32 rqueue; /* 0x.314 - Receive queue control register */ + u8 res13[24]; + u32 rbifx; /* 0x.330 - Receive bit field extract control register */ + u32 rqfar; /* 0x.334 - Receive queue filing table address register */ + u32 rqfcr; /* 0x.338 - Receive queue filing table control register */ + u32 rqfpr; /* 0x.33c - Receive queue filing table property register */ + u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ + u8 res14[56]; + u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */ + u8 res15a[4]; + u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */ + u8 res15b[4]; + u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */ + u8 res15c[4]; + u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */ + u8 res15d[4]; + u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */ + u8 res15e[4]; + u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */ + u8 res15f[4]; + u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */ + u8 res15g[4]; + u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */ + u8 res15h[4]; + u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */ + u8 res16[64]; + u32 rbaseh; /* 0x.400 - RxBD base address high */ + u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */ + u8 res17a[4]; + u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */ + u8 res17b[4]; + u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */ + u8 res17c[4]; + u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */ + u8 res17d[4]; + u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */ + u8 res17e[4]; + u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */ + u8 res17f[4]; + u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */ + u8 res17g[4]; + u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */ + u8 res17[192]; + u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ + u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ + u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ + u32 hafdup; /* 0x.50c - Half Duplex Register */ + u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */ u8 res18[12]; - u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ - u32 miimcom; /* 0x.524 - MII Management Command Register */ - u32 miimadd; /* 0x.528 - MII Management Address Register */ - u32 miimcon; /* 0x.52c - MII Management Control Register */ - u32 miimstat; /* 0x.530 - MII Management Status Register */ - u32 miimind; /* 0x.534 - MII Management Indicator Register */ + u32 miimcfg; /* 0x.520 - MII Management Configuration Register */ + u32 miimcom; /* 0x.524 - MII Management Command Register */ + u32 miimadd; /* 0x.528 - MII Management Address Register */ + u32 miimcon; /* 0x.52c - MII Management Control Register */ + u32 miimstat; /* 0x.530 - MII Management Status Register */ + u32 miimind; /* 0x.534 - MII Management Indicator Register */ u8 res19[4]; - u32 ifstat; /* 0x.53c - Interface Status Register */ - u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ - u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ - u8 res20[312]; - struct rmon_mib rmon; - u8 res21[192]; - u32 iaddr0; /* 0x.800 - Indivdual address register 0 */ - u32 iaddr1; /* 0x.804 - Indivdual address register 1 */ - u32 iaddr2; /* 0x.808 - Indivdual address register 2 */ - u32 iaddr3; /* 0x.80c - Indivdual address register 3 */ - u32 iaddr4; /* 0x.810 - Indivdual address register 4 */ - u32 iaddr5; /* 0x.814 - Indivdual address register 5 */ - u32 iaddr6; /* 0x.818 - Indivdual address register 6 */ - u32 iaddr7; /* 0x.81c - Indivdual address register 7 */ + u32 ifstat; /* 0x.53c - Interface Status Register */ + u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ + u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ + u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */ + u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */ + u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */ + u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */ + u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */ + u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */ + u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */ + u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */ + u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */ + u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */ + u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */ + u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */ + u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */ + u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */ + u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */ + u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */ + u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */ + u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */ + u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/ + u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/ + u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/ + u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/ + u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/ + u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/ + u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/ + u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/ + u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/ + u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/ + u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/ + u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/ + u8 res20[192]; + struct rmon_mib rmon; /* 0x.680-0x.73c */ + u32 rrej; /* 0x.740 - Receive filer rejected packet counter */ + u8 res21[188]; + u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/ + u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/ + u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/ + u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/ + u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/ + u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/ + u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/ + u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/ u8 res22[96]; - u32 gaddr0; /* 0x.880 - Global address register 0 */ - u32 gaddr1; /* 0x.884 - Global address register 1 */ - u32 gaddr2; /* 0x.888 - Global address register 2 */ - u32 gaddr3; /* 0x.88c - Global address register 3 */ - u32 gaddr4; /* 0x.890 - Global address register 4 */ - u32 gaddr5; /* 0x.894 - Global address register 5 */ - u32 gaddr6; /* 0x.898 - Global address register 6 */ - u32 gaddr7; /* 0x.89c - Global address register 7 */ - u8 res23[856]; - u32 attr; /* 0x.bf8 - Attributes Register */ - u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ + u32 gaddr0; /* 0x.880 - Group address register 0 */ + u32 gaddr1; /* 0x.884 - Group address register 1 */ + u32 gaddr2; /* 0x.888 - Group address register 2 */ + u32 gaddr3; /* 0x.88c - Group address register 3 */ + u32 gaddr4; /* 0x.890 - Group address register 4 */ + u32 gaddr5; /* 0x.894 - Group address register 5 */ + u32 gaddr6; /* 0x.898 - Group address register 6 */ + u32 gaddr7; /* 0x.89c - Group address register 7 */ + u8 res23a[352]; + u32 fifocfg; /* 0x.a00 - FIFO interface config register */ + u8 res23b[252]; + u8 res23c[248]; + u32 attr; /* 0x.bf8 - Attributes Register */ + u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ u8 res24[1024]; }; @@ -496,6 +686,8 @@ struct gfar_private { struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ + u32 *hash_regs[16]; + int hash_width; struct gfar *phyregs; struct work_struct tq; struct timer_list phy_info_timer; @@ -506,9 +698,12 @@ struct gfar_private { unsigned int rx_stash_size; unsigned int tx_ring_size; unsigned int rx_ring_size; - wait_queue_head_t rxcleanupq; - unsigned int rxclean; + unsigned char vlan_enable:1, + rx_csum_enable:1, + extended_hash:1; + unsigned short padding; + struct vlan_group *vlgrp; /* Info structure initialized by board setup code */ unsigned int interruptTransmit; unsigned int interruptReceive; @@ -519,6 +714,8 @@ struct gfar_private { int oldspeed; int oldduplex; int oldlink; + + uint32_t msg_enable; }; extern inline u32 gfar_read(volatile unsigned *addr) diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 28046e9e88ba..a451de629197 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -46,16 +46,18 @@ extern int startup_gfar(struct net_device *dev); extern void stop_gfar(struct net_device *dev); -extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs); +extern void gfar_halt(struct net_device *dev); +extern void gfar_start(struct net_device *dev); +extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); -void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, +static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf); -void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); -int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); -void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); -void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); +static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); +static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); +static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); +static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); +static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); +static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); static char stat_gstrings[][ETH_GSTRING_LEN] = { "rx-dropped-by-kernel", @@ -118,57 +120,56 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { "tx-fragmented-frames", }; +/* Fill in a buffer with the strings which correspond to the + * stats */ +static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) +{ + struct gfar_private *priv = netdev_priv(dev); + + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) + memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); + else + memcpy(buf, stat_gstrings, + GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); +} + /* Fill in an array of 64-bit statistics from various sources. * This array will be appended to the end of the ethtool_stats * structure, and returned to user space */ -void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) +static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) { int i; struct gfar_private *priv = netdev_priv(dev); - u32 *rmon = (u32 *) & priv->regs->rmon; u64 *extra = (u64 *) & priv->extra_stats; - struct gfar_stats *stats = (struct gfar_stats *) buf; - for (i = 0; i < GFAR_RMON_LEN; i++) { - stats->rmon[i] = (u64) (rmon[i]); - } - - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { - stats->extra[i] = extra[i]; - } -} + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { + u32 *rmon = (u32 *) & priv->regs->rmon; + struct gfar_stats *stats = (struct gfar_stats *) buf; -/* Returns the number of stats (and their corresponding strings) */ -int gfar_stats_count(struct net_device *dev) -{ - return GFAR_STATS_LEN; -} + for (i = 0; i < GFAR_RMON_LEN; i++) + stats->rmon[i] = (u64) (rmon[i]); -void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf) -{ - memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); + for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) + stats->extra[i] = extra[i]; + } else + for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) + buf[i] = extra[i]; } -void gfar_fill_stats_normon(struct net_device *dev, - struct ethtool_stats *dummy, u64 * buf) +/* Returns the number of stats (and their corresponding strings) */ +static int gfar_stats_count(struct net_device *dev) { - int i; struct gfar_private *priv = netdev_priv(dev); - u64 *extra = (u64 *) & priv->extra_stats; - for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { - buf[i] = extra[i]; - } + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) + return GFAR_STATS_LEN; + else + return GFAR_EXTRA_STATS_LEN; } - -int gfar_stats_count_normon(struct net_device *dev) -{ - return GFAR_EXTRA_STATS_LEN; -} /* Fills in the drvinfo structure with some basic info */ -void gfar_gdrvinfo(struct net_device *dev, struct +static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); @@ -182,7 +183,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct } /* Return the current settings in the ethtool_cmd structure */ -int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) +static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) { struct gfar_private *priv = netdev_priv(dev); uint gigabit_support = @@ -216,13 +217,13 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) } /* Return the length of the register structure */ -int gfar_reglen(struct net_device *dev) +static int gfar_reglen(struct net_device *dev) { return sizeof (struct gfar); } /* Return a dump of the GFAR register space */ -void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) +static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { int i; struct gfar_private *priv = netdev_priv(dev); @@ -233,13 +234,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb buf[i] = theregs[i]; } -/* Fill in a buffer with the strings which correspond to the - * stats */ -void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) -{ - memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); -} - /* Convert microseconds to ethernet clock ticks, which changes * depending on what speed the controller is running at */ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) @@ -291,9 +285,12 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic /* Get the coalescing parameters, and put them in the cvals * structure. */ -int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) +static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); + + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) + return -EOPNOTSUPP; cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); cvals->rx_max_coalesced_frames = priv->rxcount; @@ -337,10 +334,13 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) * Both cvals->*_usecs and cvals->*_frames have to be > 0 * in order for coalescing to be active */ -int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) +static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { struct gfar_private *priv = netdev_priv(dev); + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) + return -EOPNOTSUPP; + /* Set up rx coalescing */ if ((cvals->rx_coalesce_usecs == 0) || (cvals->rx_max_coalesced_frames == 0)) @@ -379,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) /* Fills in rvals with the current ring parameters. Currently, * rx, rx_mini, and rx_jumbo rings are the same size, as mini and * jumbo are ignored by the driver */ -void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) +static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { struct gfar_private *priv = netdev_priv(dev); @@ -401,9 +401,8 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) * necessary so that we don't mess things up while we're in * motion. We wait for the ring to be clean before reallocating * the rings. */ -int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) +static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { - u32 tempval; struct gfar_private *priv = netdev_priv(dev); int err = 0; @@ -425,37 +424,54 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) return -EINVAL; } - /* Stop the controller so we don't rx any more frames */ - /* But first, make sure we clear the bits */ - tempval = gfar_read(&priv->regs->dmactrl); - tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); + if (dev->flags & IFF_UP) { + unsigned long flags; - tempval = gfar_read(&priv->regs->dmactrl); - tempval |= (DMACTRL_GRS | DMACTRL_GTS); - gfar_write(&priv->regs->dmactrl, tempval); + /* Halt TX and RX, and process the frames which + * have already been received */ + spin_lock_irqsave(&priv->lock, flags); + gfar_halt(dev); + gfar_clean_rx_ring(dev, priv->rx_ring_size); + spin_unlock_irqrestore(&priv->lock, flags); - while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))) - cpu_relax(); + /* Now we take down the rings to rebuild them */ + stop_gfar(dev); + } - /* Note that rx is not clean right now */ - priv->rxclean = 0; + /* Change the size */ + priv->rx_ring_size = rvals->rx_pending; + priv->tx_ring_size = rvals->tx_pending; - if (dev->flags & IFF_UP) { - /* Tell the driver to process the rest of the frames */ - gfar_receive(0, (void *) dev, NULL); + /* Rebuild the rings with the new size */ + if (dev->flags & IFF_UP) + err = startup_gfar(dev); - /* Now wait for it to be done */ - wait_event_interruptible(priv->rxcleanupq, priv->rxclean); + return err; +} - /* Ok, all packets have been handled. Now we bring it down, - * change the ring size, and bring it up */ +static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) +{ + struct gfar_private *priv = netdev_priv(dev); + int err = 0; + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) + return -EOPNOTSUPP; + + if (dev->flags & IFF_UP) { + unsigned long flags; + + /* Halt TX and RX, and process the frames which + * have already been received */ + spin_lock_irqsave(&priv->lock, flags); + gfar_halt(dev); + gfar_clean_rx_ring(dev, priv->rx_ring_size); + spin_unlock_irqrestore(&priv->lock, flags); + + /* Now we take down the rings to rebuild them */ stop_gfar(dev); } - priv->rx_ring_size = rvals->rx_pending; - priv->tx_ring_size = rvals->tx_pending; + priv->rx_csum_enable = data; if (dev->flags & IFF_UP) err = startup_gfar(dev); @@ -463,6 +479,61 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) return err; } +static uint32_t gfar_get_rx_csum(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) + return 0; + + return priv->rx_csum_enable; +} + +static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) +{ + unsigned long flags; + struct gfar_private *priv = netdev_priv(dev); + + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) + return -EOPNOTSUPP; + + spin_lock_irqsave(&priv->lock, flags); + gfar_halt(dev); + + if (data) + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; + + gfar_start(dev); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static uint32_t gfar_get_tx_csum(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + + if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) + return 0; + + return (dev->features & NETIF_F_IP_CSUM) != 0; +} + +static uint32_t gfar_get_msglevel(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + return priv->msg_enable; +} + +static void gfar_set_msglevel(struct net_device *dev, uint32_t data) +{ + struct gfar_private *priv = netdev_priv(dev); + priv->msg_enable = data; +} + + struct ethtool_ops gfar_ethtool_ops = { .get_settings = gfar_gsettings, .get_drvinfo = gfar_gdrvinfo, @@ -476,52 +547,10 @@ struct ethtool_ops gfar_ethtool_ops = { .get_strings = gfar_gstrings, .get_stats_count = gfar_stats_count, .get_ethtool_stats = gfar_fill_stats, -}; - -struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = { - .get_settings = gfar_gsettings, - .get_drvinfo = gfar_gdrvinfo, - .get_regs_len = gfar_reglen, - .get_regs = gfar_get_regs, - .get_link = ethtool_op_get_link, - .get_ringparam = gfar_gringparam, - .set_ringparam = gfar_sringparam, - .get_strings = gfar_gstrings_normon, - .get_stats_count = gfar_stats_count_normon, - .get_ethtool_stats = gfar_fill_stats_normon, -}; - -struct ethtool_ops gfar_nocoalesce_ethtool_ops = { - .get_settings = gfar_gsettings, - .get_drvinfo = gfar_gdrvinfo, - .get_regs_len = gfar_reglen, - .get_regs = gfar_get_regs, - .get_link = ethtool_op_get_link, - .get_ringparam = gfar_gringparam, - .set_ringparam = gfar_sringparam, - .get_strings = gfar_gstrings, - .get_stats_count = gfar_stats_count, - .get_ethtool_stats = gfar_fill_stats, -}; - -struct ethtool_ops gfar_normon_ethtool_ops = { - .get_settings = gfar_gsettings, - .get_drvinfo = gfar_gdrvinfo, - .get_regs_len = gfar_reglen, - .get_regs = gfar_get_regs, - .get_link = ethtool_op_get_link, - .get_coalesce = gfar_gcoalesce, - .set_coalesce = gfar_scoalesce, - .get_ringparam = gfar_gringparam, - .set_ringparam = gfar_sringparam, - .get_strings = gfar_gstrings_normon, - .get_stats_count = gfar_stats_count_normon, - .get_ethtool_stats = gfar_fill_stats_normon, -}; - -struct ethtool_ops *gfar_op_array[] = { - &gfar_ethtool_ops, - &gfar_normon_ethtool_ops, - &gfar_nocoalesce_ethtool_ops, - &gfar_normon_nocoalesce_ethtool_ops + .get_rx_csum = gfar_get_rx_csum, + .get_tx_csum = gfar_get_tx_csum, + .set_rx_csum = gfar_set_rx_csum, + .set_tx_csum = gfar_set_tx_csum, + .get_msglevel = gfar_get_msglevel, + .set_msglevel = gfar_set_msglevel, }; diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c index 02b16abc89bd..7c965f268a82 100644 --- a/drivers/net/gianfar_phy.c +++ b/drivers/net/gianfar_phy.c @@ -572,7 +572,7 @@ static struct phy_info phy_info_dm9161 = { static struct phy_info phy_info_marvell = { .phy_id = 0x01410c00, .phy_id_mask = 0xffffff00, - .name = "Marvell 88E1101", + .name = "Marvell 88E1101/88E1111", .features = MII_GBIT_FEATURES, .config_aneg = &marvell_config_aneg, .read_status = &marvell_read_status, diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 3d96714ed3cf..d9df1d9a5739 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1149,7 +1149,7 @@ static void hamachi_tx_timeout(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, - skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); + skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | DescEndPacket | DescIntr | (hmp->rx_buf_sz - 2)); } @@ -1210,7 +1210,7 @@ static void hamachi_init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, - skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); + skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); /* -2 because it doesn't REALLY have that first 2 bytes -KDU */ hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | DescEndPacket | DescIntr | (hmp->rx_buf_sz -2)); @@ -1509,7 +1509,7 @@ static int hamachi_rx(struct net_device *dev) desc->addr, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); - buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail; + buf_addr = (u8 *) hmp->rx_skbuff[entry]->data; frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); if (hamachi_debug > 4) printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", @@ -1678,7 +1678,7 @@ static int hamachi_rx(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, - skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); + skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); } desc->status_n_length = cpu_to_le32(hmp->rx_buf_sz); if (entry >= RX_RING_SIZE-1) @@ -1772,9 +1772,9 @@ static int hamachi_close(struct net_device *dev) readl(ioaddr + RxCurPtr) == (long)&hmp->rx_ring[i] ? '>' : ' ', i, hmp->rx_ring[i].status_n_length, hmp->rx_ring[i].addr); if (hamachi_debug > 6) { - if (*(u8*)hmp->rx_skbuff[i]->tail != 0x69) { + if (*(u8*)hmp->rx_skbuff[i]->data != 0x69) { u16 *addr = (u16 *) - hmp->rx_skbuff[i]->tail; + hmp->rx_skbuff[i]->data; int j; for (j = 0; j < 0x50; j++) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 89454915b857..e44f8e9055ef 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -848,7 +848,7 @@ static void __exit sixpack_exit_driver(void) { int ret; - if ((ret = tty_register_ldisc(N_6PACK, NULL))) + if ((ret = tty_unregister_ldisc(N_6PACK))) printk(msg_unregfail, ret); } diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig index 7cdebe1a0b61..0cd54306e636 100644 --- a/drivers/net/hamradio/Kconfig +++ b/drivers/net/hamradio/Kconfig @@ -17,7 +17,7 @@ config MKISS config 6PACK tristate "Serial port 6PACK driver" - depends on AX25 && BROKEN_ON_SMP + depends on AX25 ---help--- 6pack is a transmission protocol for the data exchange between your PC and your TNC (the Terminal Node Controller acts as a kind of diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 62790511098f..3035422f5ad8 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -934,7 +934,7 @@ static void __exit mkiss_exit_driver(void) kfree(ax25_ctrls); ax25_ctrls = NULL; - if ((i = tty_register_ldisc(N_AX25, NULL))) + if ((i = tty_unregister_ldisc(N_AX25))) printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i); } diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index ece1b1a13186..c27e417f32bf 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -304,7 +304,7 @@ static inline void scc_discard_buffers(struct scc_channel *scc) scc->tx_buff = NULL; } - while (skb_queue_len(&scc->tx_queue)) + while (!skb_queue_empty(&scc->tx_queue)) dev_kfree_skb(skb_dequeue(&scc->tx_queue)); spin_unlock_irqrestore(&scc->lock, flags); @@ -1126,8 +1126,7 @@ static void t_dwait(unsigned long channel) if (scc->stat.tx_state == TXS_WAIT) /* maxkeyup or idle timeout */ { - if (skb_queue_len(&scc->tx_queue) == 0) /* nothing to send */ - { + if (skb_queue_empty(&scc->tx_queue)) { /* nothing to send */ scc->stat.tx_state = TXS_IDLE; netif_wake_queue(scc->dev); /* t_maxkeyup locked it. */ return; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 4834314b676d..0abf5dd08b4c 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -159,12 +159,7 @@ struct net_device * __init hp_plus_probe(int unit) err = do_hpp_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -271,6 +266,9 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) /* Leave the 8390 and HP chip reset. */ outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION); + retval = register_netdev(dev); + if (retval) + goto out; return 0; out: release_region(ioaddr, HP_IO_EXTENT); @@ -463,11 +461,8 @@ init_module(void) dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; if (do_hpp_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_hpp[found++] = dev; - continue; - } - cleanup_card(dev); + dev_hpp[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/hp.c b/drivers/net/hp.c index 026888611d6f..59cf841b14ab 100644 --- a/drivers/net/hp.c +++ b/drivers/net/hp.c @@ -123,12 +123,7 @@ struct net_device * __init hp_probe(int unit) err = do_hp_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -227,7 +222,12 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr) ei_status.block_output = &hp_block_output; hp_init_card(dev); + retval = register_netdev(dev); + if (retval) + goto out1; return 0; +out1: + free_irq(dev->irq, dev); out: release_region(ioaddr, HP_IO_EXTENT); return retval; @@ -432,11 +432,8 @@ init_module(void) dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; if (do_hp_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_hp[found++] = dev; - continue; - } - cleanup_card(dev); + dev_hp[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index b3a898c5a585..cf0ac6fda1a1 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -106,6 +106,7 @@ #include <linux/interrupt.h> #include <linux/eisa.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/spinlock.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -417,12 +418,7 @@ struct net_device * __init hp100_probe(int unit) if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; - out1: - release_region(dev->base_addr, HP100_REGION_SIZE); out: free_netdev(dev); return ERR_PTR(err); @@ -562,7 +558,7 @@ static int __devinit hp100_probe1(struct net_device *dev, int ioaddr, * Also, we can have EISA Busmaster cards (not tested), * so beware !!! - Jean II */ if((bus == HP100_BUS_PCI) && - (pci_set_dma_mask(pci_dev, 0xffffffff))) { + (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK))) { /* Gracefully fallback to shared memory */ goto busmasterfail; } @@ -776,11 +772,22 @@ static int __devinit hp100_probe1(struct net_device *dev, int ioaddr, printk("Warning! Link down.\n"); } + err = register_netdev(dev); + if (err) + goto out3; + return 0; +out3: + if (local_mode == 1) + pci_free_consistent(lp->pci_dev, MAX_RINGSIZE + 0x0f, + lp->page_vaddr_algn, + virt_to_whatever(dev, lp->page_vaddr_algn)); + if (mem_ptr_virt) + iounmap(mem_ptr_virt); out2: release_region(ioaddr, HP100_REGION_SIZE); out1: - return -ENODEV; + return err; } /* This procedure puts the card into a stable init state */ @@ -2875,18 +2882,12 @@ static int __init hp100_eisa_probe (struct device *gendev) if (err) goto out1; - err = register_netdev(dev); - if (err) - goto out2; - #ifdef HP100_DEBUG printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name, dev->base_addr); #endif gendev->driver_data = dev; return 0; - out2: - release_region(dev->base_addr, HP100_REGION_SIZE); out1: free_netdev(dev); return err; @@ -2951,17 +2952,12 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev, err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev); if (err) goto out1; - err = register_netdev(dev); - if (err) - goto out2; #ifdef HP100_DEBUG printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr); #endif pci_set_drvdata(pdev, dev); return 0; - out2: - release_region(dev->base_addr, HP100_REGION_SIZE); out1: free_netdev(dev); out0: @@ -3032,15 +3028,9 @@ static int __init hp100_isa_init(void) SET_MODULE_OWNER(dev); err = hp100_isa_probe(dev, hp100_port[i]); - if (!err) { - err = register_netdev(dev); - if (!err) - hp100_devlist[cards++] = dev; - else - release_region(dev->base_addr, HP100_REGION_SIZE); - } - - if (err) + if (!err) + hp100_devlist[cards++] = dev; + else free_netdev(dev); } diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 7d23aa375908..b8d112348ba4 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -626,7 +626,7 @@ static void __exit irtty_sir_cleanup(void) { int err; - if ((err = tty_register_ldisc(N_IRDA, NULL))) { + if ((err = tty_unregister_ldisc(N_IRDA))) { IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n", __FUNCTION__, err); } diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c index 18cea1099530..c65054364bca 100644 --- a/drivers/net/irda/sir_kthread.c +++ b/drivers/net/irda/sir_kthread.c @@ -135,8 +135,7 @@ static int irda_thread(void *startup) remove_wait_queue(&irda_rq_queue.kick, &wait); /* make swsusp happy with our thread */ - if (current->flags & PF_FREEZE) - refrigerator(PF_FREEZE); + try_to_freeze(); run_irda_queue(); } diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 66f488c13717..15f207323d97 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -763,7 +763,7 @@ static int stir_transmit_thread(void *arg) { #ifdef CONFIG_PM /* if suspending, then power off and wait */ - if (unlikely(current->flags & PF_FREEZE)) { + if (unlikely(freezing(current))) { if (stir->receiving) receive_stop(stir); else @@ -771,7 +771,7 @@ static int stir_transmit_thread(void *arg) write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD); - refrigerator(PF_FREEZE); + refrigerator(); if (change_speed(stir, stir->speed)) break; diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index 50bebb55e9ee..88ae8a04fabc 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -176,12 +176,7 @@ struct net_device * __init netcard_probe(int unit) err = do_netcard_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -316,7 +311,15 @@ static int __init netcard_probe1(struct net_device *dev, int ioaddr) dev->tx_timeout = &net_tx_timeout; dev->watchdog_timeo = MY_TX_TIMEOUT; + + err = register_netdev(dev); + if (err) + goto out2; return 0; +out2: +#ifdef jumpered_dma + free_dma(dev->dma); +#endif out1: #ifdef jumpered_interrupts free_irq(dev->irq, dev); @@ -691,11 +694,8 @@ int init_module(void) dev->dma = dma; dev->mem_start = mem; if (do_netcard_probe(dev) == 0) { - if (register_netdev(dev) == 0) - this_device = dev; - return 0; - } - cleanup_card(dev); + this_device = dev; + return 0; } free_netdev(dev); return -ENXIO; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 35f6a7c271a2..097b90ccf575 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -47,7 +47,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -char ixgb_driver_version[] = "1.0.95-k2"DRIVERNAPI; + +#define DRV_VERSION "1.0.95-k2"DRIVERNAPI +char ixgb_driver_version[] = DRV_VERSION; char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table @@ -140,6 +142,7 @@ static struct pci_driver ixgb_driver = { MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); /* some defines for controlling descriptor fetches in h/w */ #define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */ diff --git a/drivers/net/lance.c b/drivers/net/lance.c index dec557fb6a99..b4929beb33b2 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -356,11 +356,8 @@ int init_module(void) dev->base_addr = io[this_dev]; dev->dma = dma[this_dev]; if (do_lance_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_lance[found++] = dev; - continue; - } - cleanup_card(dev); + dev_lance[found++] = dev; + continue; } free_netdev(dev); break; @@ -448,12 +445,7 @@ struct net_device * __init lance_probe(int unit) err = do_lance_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -724,6 +716,9 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int dev->tx_timeout = lance_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + err = register_netdev(dev); + if (err) + goto out_dma; return 0; out_dma: if (dev->dma != 4) @@ -867,7 +862,7 @@ lance_init_ring(struct net_device *dev, int gfp) lp->rx_skbuff[i] = skb; if (skb) { skb->dev = dev; - rx_buff = skb->tail; + rx_buff = skb->data; } else rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp); if (rx_buff == NULL) diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 5e263fcba669..41bad07ac1ac 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -553,14 +553,14 @@ static inline void init_rx_bufs(struct net_device *dev) if (skb == NULL) panic("%s: alloc_skb() failed", __FILE__); skb_reserve(skb, 2); - dma_addr = dma_map_single(lp->dev, skb->tail,PKT_BUF_SZ, + dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ, DMA_FROM_DEVICE); skb->dev = dev; rbd->v_next = rbd+1; rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1)); rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd)); rbd->skb = skb; - rbd->v_data = skb->tail; + rbd->v_data = skb->data; rbd->b_data = WSWAPchar(dma_addr); rbd->size = PKT_BUF_SZ; } @@ -783,8 +783,8 @@ static inline int i596_rx(struct net_device *dev) rx_in_place = 1; rbd->skb = newskb; newskb->dev = dev; - dma_addr = dma_map_single(lp->dev, newskb->tail, PKT_BUF_SZ, DMA_FROM_DEVICE); - rbd->v_data = newskb->tail; + dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE); + rbd->v_data = newskb->data; rbd->b_data = WSWAPchar(dma_addr); CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); } diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c index 179a97c0af69..27f0d8ac4c40 100644 --- a/drivers/net/lne390.c +++ b/drivers/net/lne390.c @@ -167,12 +167,7 @@ struct net_device * __init lne390_probe(int unit) err = do_lne390_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -296,7 +291,14 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); + + ret = register_netdev(dev); + if (ret) + goto unmap; return 0; +unmap: + if (ei_status.reg0) + iounmap((void *)dev->mem_start); cleanup: free_irq(dev->irq, dev); return ret; @@ -426,11 +428,8 @@ int init_module(void) dev->base_addr = io[this_dev]; dev->mem_start = mem[this_dev]; if (do_lne390_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_lne[found++] = dev; - continue; - } - cleanup_card(dev); + dev_lne[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 6ed2d7dbd44c..81d0a26e4f41 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -109,7 +109,7 @@ bitrev(int b) } -static int __devinit mace_probe(struct macio_dev *mdev, const struct of_match *match) +static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mace = macio_get_of_node(mdev); struct net_device *dev; @@ -1009,12 +1009,10 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static struct of_match mace_match[] = +static struct of_device_id mace_match[] = { { .name = "mace", - .type = OF_ANY_MATCH, - .compatible = OF_ANY_MATCH }, {}, }; diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h index 851eba8a3e00..e9c6e569d1f4 100644 --- a/drivers/net/myri_code.h +++ b/drivers/net/myri_code.h @@ -4775,1288 +4775,7 @@ static unsigned char lanai4_code[76256] __initdata = { /* This is the LANai data */ static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */ -static unsigned char lanai4_data[20472] __initdata = { -0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x01, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, -0x00,0x00, 0x00,0x00, 0x00,0x00, } ; +static unsigned char lanai4_data[20472] __initdata; #ifdef SYMBOL_DEFINES_COMPILED diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index aad5494c83cf..f0996ce5c268 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -369,7 +369,7 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev) * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. */ -static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *dev) +static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; unsigned char *rawp; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index babb59e146ea..9d6d2548c2d3 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1926,7 +1926,7 @@ static void refill_rx(struct net_device *dev) break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ np->rx_dma[entry] = pci_map_single(np->pci_dev, - skb->tail, buflen, PCI_DMA_FROMDEVICE); + skb->data, buflen, PCI_DMA_FROMDEVICE); np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]); } np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz); @@ -2280,7 +2280,7 @@ static void netdev_rx(struct net_device *dev) buflen, PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, - np->rx_skbuff[entry]->tail, pkt_len, 0); + np->rx_skbuff[entry]->data, pkt_len, 0); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index 84e291e24935..8f40368cf2e9 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -180,12 +180,7 @@ struct net_device * __init ne_probe(int unit) err = do_ne_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -325,8 +320,13 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); - return 0; + ret = register_netdev(dev); + if (ret) + goto out_irq; + return 0; +out_irq: + free_irq(dev->irq, dev); err_out: release_region(ioaddr, NE_IO_EXTENT); return ret; @@ -633,11 +633,8 @@ int init_module(void) err = init_reg_offset(dev, dev->base_addr); if (!err) { if (do_ne_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - cleanup_card(dev); + dev_ne[found++] = dev; + continue; } } free_netdev(dev); diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 496433902ade..d209a1556b2e 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -129,9 +129,9 @@ bad_clone_list[] __initdata = { #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -#ifdef CONFIG_PLAT_MAPPI +#if defined(CONFIG_PLAT_MAPPI) # define DCR_VAL 0x4b -#elif CONFIG_PLAT_OAKS32R +#elif defined(CONFIG_PLAT_OAKS32R) # define DCR_VAL 0x48 #else # define DCR_VAL 0x49 @@ -229,12 +229,7 @@ struct net_device * __init ne_probe(int unit) err = do_ne_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -534,8 +529,14 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); + + ret = register_netdev(dev); + if (ret) + goto out_irq; return 0; +out_irq: + free_irq(dev->irq, dev); err_out: release_region(ioaddr, NE_IO_EXTENT); return ret; @@ -826,11 +827,8 @@ int init_module(void) dev->mem_end = bad[this_dev]; dev->base_addr = io[this_dev]; if (do_ne_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - cleanup_card(dev); + dev_ne[found++] = dev; + continue; } free_netdev(dev); if (found) diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c index 6ebef27dbfae..6d62ada85de6 100644 --- a/drivers/net/ne2.c +++ b/drivers/net/ne2.c @@ -301,12 +301,7 @@ struct net_device * __init ne2_probe(int unit) err = do_ne2_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -517,7 +512,14 @@ static int __init ne2_probe1(struct net_device *dev, int slot) dev->poll_controller = ei_poll; #endif NS8390_init(dev, 0); + + retval = register_netdev(dev); + if (retval) + goto out1; return 0; +out1: + mca_set_adapter_procfn( ei_status.priv, NULL, NULL); + free_irq(dev->irq, dev); out: release_region(base_addr, NE_IO_EXTENT); return retval; @@ -798,11 +800,8 @@ int init_module(void) dev->mem_end = bad[this_dev]; dev->base_addr = io[this_dev]; if (do_ne2_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - cleanup_card(dev); + dev_ne[found++] = dev; + continue; } free_netdev(dev); break; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index c336b46bd332..e64df4d0800b 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -101,6 +101,7 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/delay.h> @@ -573,7 +574,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; cmdsts = REAL_RX_BUF_SIZE | CMDSTS_INTR; - buf = pci_map_single(dev->pci_dev, skb->tail, + buf = pci_map_single(dev->pci_dev, skb->data, REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); build_rx_desc(dev, sg, 0, buf, cmdsts, 0); /* update link of previous rx */ @@ -603,7 +604,7 @@ static inline int rx_refill(struct net_device *ndev, int gfp) if (unlikely(!skb)) break; - res = (long)skb->tail & 0xf; + res = (long)skb->data & 0xf; res = 0x10 - res; res &= 0xf; skb_reserve(skb, res); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index c6e8b25f9685..71fd41122c91 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -86,7 +86,6 @@ earlier 3Com products. #include <linux/ethtool.h> #include <linux/bitops.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -312,11 +311,6 @@ static dev_link_t *tc574_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &tc574_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1286,13 +1280,22 @@ static int el3_close(struct net_device *dev) return 0; } +static struct pcmcia_device_id tc574_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, tc574_ids); + static struct pcmcia_driver tc574_driver = { .owner = THIS_MODULE, .drv = { .name = "3c574_cs", }, .attach = tc574_attach, + .event = tc574_event, .detach = tc574_detach, + .id_table = tc574_ids, }; static int __init init_tc574(void) diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 89abdda1d343..d83fdd8c1943 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -40,7 +40,6 @@ #include <linux/ioport.h> #include <linux/bitops.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -226,11 +225,6 @@ static dev_link_t *tc589_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &tc589_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1057,13 +1051,26 @@ static int el3_close(struct net_device *dev) return 0; } +static struct pcmcia_device_id tc589_ids[] = { + PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), + PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), + PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, tc589_ids); + static struct pcmcia_driver tc589_driver = { .owner = THIS_MODULE, .drv = { .name = "3c589_cs", }, .attach = tc589_attach, + .event = tc589_event, .detach = tc589_detach, + .id_table = tc589_ids, }; static int __init init_tc589(void) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 853b586e481a..8bb4e85689ea 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -37,7 +37,6 @@ #include <linux/netdevice.h> #include "../8390.h" -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -181,11 +180,6 @@ static dev_link_t *axnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &axnet_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -850,13 +844,43 @@ static void block_output(struct net_device *dev, int count, outsw(nic_base + AXNET_DATAPORT, buf, count>>1); } +static struct pcmcia_device_id axnet_ids[] = { + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081), + PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106), + PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), + PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef), + PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef), + PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1), + PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc), + PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e), + PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90), + PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), + PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058), + PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6, 0xab9be5ef), + /* this is not specific enough */ + /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */ + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, axnet_ids); + static struct pcmcia_driver axnet_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "axnet_cs", }, .attach = axnet_attach, + .event = axnet_event, .detach = axnet_detach, + .id_table = axnet_ids, }; static int __init init_axnet_cs(void) diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 4294e1e3f156..b9355d9498a3 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -43,7 +43,6 @@ #include <linux/arcdevice.h> #include <linux/com20020.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -200,11 +199,6 @@ static dev_link_t *com20020_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &com20020_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -483,7 +477,11 @@ static int com20020_event(event_t event, int priority, return 0; } /* com20020_event */ - +static struct pcmcia_device_id com20020_ids[] = { + PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, com20020_ids); static struct pcmcia_driver com20020_cs_driver = { .owner = THIS_MODULE, @@ -491,7 +489,9 @@ static struct pcmcia_driver com20020_cs_driver = { .name = "com20020_cs", }, .attach = com20020_attach, + .event = com20020_event, .detach = com20020_detach, + .id_table = com20020_ids, }; static int __init init_com20020_cs(void) diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 0424865e8094..9d8197bb293a 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -49,7 +49,6 @@ #include <linux/ioport.h> #include <linux/crc32.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -288,11 +287,6 @@ static dev_link_t *fmvj18x_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &fmvj18x_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -435,7 +429,9 @@ static void fmvj18x_config(dev_link_t *link) pcmcia_get_status(handle, &status); if (status.CardState & CS_EVENT_3VCARD) link->conf.Vcc = 33; /* inserted in 3.3V slot */ - } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) { + } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 + || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 + || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; @@ -764,13 +760,40 @@ static int fmvj18x_event(event_t event, int priority, return 0; } /* fmvj18x_event */ +static struct pcmcia_device_id fmvj18x_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), + PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59), + PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922), + PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922), + PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db), + PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e), + PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2), + PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4), + PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6), + PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6), + PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666), + PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70), + PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a), + PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2), + PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454), + PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), + PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); + static struct pcmcia_driver fmvj18x_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "fmvj18x_cs", }, .attach = fmvj18x_attach, + .event = fmvj18x_event, .detach = fmvj18x_detach, + .id_table = fmvj18x_ids, }; static int __init init_fmvj18x_cs(void) diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 3107ccfe8f3d..b6c140eb9799 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -57,7 +57,6 @@ #include <linux/trdevice.h> #include <linux/ibmtr.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -119,9 +118,6 @@ static void ibmtr_detach(dev_link_t *); static dev_link_t *dev_list; -extern int ibmtr_probe_card(struct net_device *dev); -extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); - /*====================================================================*/ typedef struct ibmtr_dev_t { @@ -193,11 +189,6 @@ static dev_link_t *ibmtr_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ibmtr_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -511,13 +502,22 @@ static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) return; } +static struct pcmcia_device_id ibmtr_ids[] = { + PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), + PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); + static struct pcmcia_driver ibmtr_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "ibmtr_cs", }, .attach = ibmtr_attach, + .event = ibmtr_event, .detach = ibmtr_detach, + .id_table = ibmtr_ids, }; static int __init init_ibmtr_cs(void) diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 4603807fcafb..980d7e5d66cb 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -146,7 +146,6 @@ Include Files #include <linux/ioport.h> #include <linux/bitops.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cisreg.h> @@ -502,11 +501,6 @@ static dev_link_t *nmclan_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &nmclan_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1675,13 +1669,22 @@ static void set_multicast_list(struct net_device *dev) } /* set_multicast_list */ +static struct pcmcia_device_id nmclan_ids[] = { + PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); + static struct pcmcia_driver nmclan_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "nmclan_cs", }, .attach = nmclan_attach, + .event = nmclan_event, .detach = nmclan_detach, + .id_table = nmclan_ids, }; static int __init init_nmclan_cs(void) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index b0126304ca08..9f22d138e3ad 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -40,7 +40,6 @@ #include <linux/netdevice.h> #include <../drivers/net/8390.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -276,11 +275,6 @@ static dev_link_t *pcnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &pcnet_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1155,11 +1149,13 @@ static int set_config(struct net_device *dev, struct ifmap *map) static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; - pcnet_dev_t *info = PRIV(dev); + pcnet_dev_t *info; irqreturn_t ret = ei_interrupt(irq, dev_id, regs); - if (ret == IRQ_HANDLED) + if (ret == IRQ_HANDLED) { + info = PRIV(dev); info->stale = 0; + } return ret; } @@ -1350,7 +1346,7 @@ static void dma_block_input(struct net_device *dev, int count, if (count & 0x01) buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++; - /* This was for the ALPHA version only, but enough people have + /* This was for the ALPHA version only, but enough people have been encountering problems that it is still here. */ #ifdef PCMCIA_DEBUG if (ei_debug > 4) { /* DMA termination address check... */ @@ -1424,7 +1420,7 @@ static void dma_block_output(struct net_device *dev, int count, dma_start = jiffies; #ifdef PCMCIA_DEBUG - /* This was for the ALPHA version only, but enough people have + /* This was for the ALPHA version only, but enough people have been encountering problems that it is still here. */ if (ei_debug > 4) { /* DMA termination address check... */ int addr, tries = 20; @@ -1537,20 +1533,20 @@ static void shmem_get_8390_hdr(struct net_device *dev, static void shmem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) { - void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8) - + ring_offset + void __iomem *base = ei_status.mem; + unsigned long offset = (TX_PAGES<<8) + ring_offset - (ei_status.rx_start_page << 8); char *buf = skb->data; - if (xfer_start + count > (void __iomem *)ei_status.rmem_end) { + if (offset + count > ei_status.priv) { /* We must wrap the input move. */ - int semi_count = (void __iomem *)ei_status.rmem_end - xfer_start; - copyin(buf, xfer_start, semi_count); + int semi_count = ei_status.priv - offset; + copyin(buf, base + offset, semi_count); buf += semi_count; - xfer_start = ei_status.mem + (TX_PAGES<<8); + offset = TX_PAGES<<8; count -= semi_count; } - copyin(buf, xfer_start, count); + copyin(buf, base + offset, count); } /*====================================================================*/ @@ -1611,8 +1607,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, } ei_status.mem = info->base + offset; + ei_status.priv = req.Size; dev->mem_start = (u_long)ei_status.mem; - dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size; + dev->mem_end = dev->mem_start + req.Size; ei_status.tx_start_page = start_pg; ei_status.rx_start_page = start_pg + TX_PAGES; @@ -1634,13 +1631,218 @@ failed: /*====================================================================*/ +static struct pcmcia_device_id pcnet_ids[] = { + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), + PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), + PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), + PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004), + PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d), + PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075), + PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145), + PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230), + PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530), +/* PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), conflict with axnet_cs */ + PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), + PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), + PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041), + PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452), +/* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), conflict with axnet_cs */ + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), + PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), + PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0), + PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0), + PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82), + PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8), + PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab), + PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11), + PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff), + PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68), + PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997), + PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8), + PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96), + PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96), + PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224), + PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb), + PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247), + PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96), + PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1), + PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd), + PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190), + PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504), + PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a), + PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79), + PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7), + PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a), + PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), + PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), + PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), + PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), + PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2), + PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2), + PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04), + PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d), + PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814), + PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0), + PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf), + PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995), + PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233), + PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e), + PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398), + PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b), + PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec), + PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9), + PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84), + PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9), + PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1), + PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1), + PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb), + PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11), + PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6), + PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c), + PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e), + PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61), + PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517), + PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e), + PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb), + PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327), + PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947), + PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6), + PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494), + PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), + PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), + PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), + PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), + PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), + PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), + PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2), + PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c), + PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40), + PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7), + PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab), + PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78), + PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11), + PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d), + PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389), + PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9), + PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a), + PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737), + PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922), + PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0), + PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578), + PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307), + PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4), + PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8), + PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3), + PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c), + PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6), + PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472), + PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7), + PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9), + PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8), + PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76), + PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e), + PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), + PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f), + PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7), + PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641), + PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1), + PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80), + PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), + PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), + PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), + PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), + PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), + PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388), + PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c), + PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265), + PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e), + PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8), + PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa), + PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f), + PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a), + PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e), + PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0), + PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e), + PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89), + PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360), + PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de), + PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f), + PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6), + PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a), + PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078), + /* too generic! */ + /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */ + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"), + PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "LA-PCM.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); + static struct pcmcia_driver pcnet_driver = { .drv = { .name = "pcnet_cs", }, .attach = pcnet_attach, + .event = pcnet_event, .detach = pcnet_detach, .owner = THIS_MODULE, + .id_table = pcnet_ids, }; static int __init init_pcnet_cs(void) diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 85a152173148..d652e1eddb45 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -41,8 +41,8 @@ #include <linux/ioport.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/jiffies.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -127,6 +127,12 @@ struct smc_private { int rx_ovrn; }; +struct smc_cfg_mem { + tuple_t tuple; + cisparse_t parse; + u_char buf[255]; +}; + /* Special definitions for Megahertz multifunction cards */ #define MEGAHERTZ_ISR 0x0380 @@ -364,10 +370,6 @@ static dev_link_t *smc91c92_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &smc91c92_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -498,14 +500,24 @@ static int mhz_mfc_config(dev_link_t *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); - tuple_t tuple; - cisparse_t parse; - u_char buf[255]; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + cisparse_t *parse; + cistpl_cftable_entry_t *cf; + u_char *buf; win_req_t req; memreq_t mem; int i, k; + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return CS_OUT_OF_RESOURCE; + + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + cf = &parse->cftable_entry; + buf = cfg_mem->buf; + link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; link->irq.Attributes = @@ -514,12 +526,12 @@ static int mhz_mfc_config(dev_link_t *link) link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts2 = 8; - tuple.Attributes = tuple.TupleOffset = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = sizeof(buf); - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple->Attributes = tuple->TupleOffset = 0; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 255; + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(link->handle, &tuple, &parse); + i = first_tuple(link->handle, tuple, parse); /* The Megahertz combo cards have modem-like CIS entries, so we have to explicitly try a bunch of port combinations. */ while (i == CS_SUCCESS) { @@ -532,10 +544,10 @@ static int mhz_mfc_config(dev_link_t *link) if (i == CS_SUCCESS) break; } if (i == CS_SUCCESS) break; - i = next_tuple(link->handle, &tuple, &parse); + i = next_tuple(link->handle, tuple, parse); } if (i != CS_SUCCESS) - return i; + goto free_cfg_mem; dev->base_addr = link->io.BasePort1; /* Allocate a memory window, for accessing the ISR */ @@ -544,7 +556,7 @@ static int mhz_mfc_config(dev_link_t *link) req.AccessSpeed = 0; i = pcmcia_request_window(&link->handle, &req, &link->win); if (i != CS_SUCCESS) - return i; + goto free_cfg_mem; smc->base = ioremap(req.Base, req.Size); mem.CardOffset = mem.Page = 0; if (smc->manfid == MANFID_MOTOROLA) @@ -556,6 +568,8 @@ static int mhz_mfc_config(dev_link_t *link) && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) mhz_3288_power(link); +free_cfg_mem: + kfree(cfg_mem); return i; } @@ -563,39 +577,61 @@ static int mhz_setup(dev_link_t *link) { client_handle_t handle = link->handle; struct net_device *dev = link->priv; - tuple_t tuple; - cisparse_t parse; - u_char buf[255], *station_addr; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + cisparse_t *parse; + u_char *buf, *station_addr; + int rc; + + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return -1; + + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + buf = cfg_mem->buf; - tuple.Attributes = tuple.TupleOffset = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); + tuple->Attributes = tuple->TupleOffset = 0; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 255; /* Read the station address from the CIS. It is stored as the last (fourth) string in the Version 1 Version/ID tuple. */ - tuple.DesiredTuple = CISTPL_VERS_1; - if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) - return -1; + tuple->DesiredTuple = CISTPL_VERS_1; + if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; + } /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ - if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS) - first_tuple(handle, &tuple, &parse); - if (parse.version_1.ns > 3) { - station_addr = parse.version_1.str + parse.version_1.ofs[3]; - if (cvt_ascii_address(dev, station_addr) == 0) - return 0; + if (next_tuple(handle, tuple, parse) != CS_SUCCESS) + first_tuple(handle, tuple, parse); + if (parse->version_1.ns > 3) { + station_addr = parse->version_1.str + parse->version_1.ofs[3]; + if (cvt_ascii_address(dev, station_addr) == 0) { + rc = 0; + goto free_cfg_mem; + } } /* Another possibility: for the EM3288, in a special tuple */ - tuple.DesiredTuple = 0x81; - if (pcmcia_get_first_tuple(handle, &tuple) != CS_SUCCESS) - return -1; - if (pcmcia_get_tuple_data(handle, &tuple) != CS_SUCCESS) - return -1; + tuple->DesiredTuple = 0x81; + if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; + } + if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; + } buf[12] = '\0'; - if (cvt_ascii_address(dev, buf) == 0) - return 0; - - return -1; + if (cvt_ascii_address(dev, buf) == 0) { + rc = 0; + goto free_cfg_mem; + } + rc = -1; +free_cfg_mem: + kfree(cfg_mem); + return rc; } /*====================================================================== @@ -665,19 +701,29 @@ static int mot_setup(dev_link_t *link) static int smc_config(dev_link_t *link) { struct net_device *dev = link->priv; - tuple_t tuple; - cisparse_t parse; - u_char buf[255]; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + cisparse_t *parse; + cistpl_cftable_entry_t *cf; + u_char *buf; int i; - tuple.Attributes = tuple.TupleOffset = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = sizeof(buf); - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return CS_OUT_OF_RESOURCE; + + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + cf = &parse->cftable_entry; + buf = cfg_mem->buf; + + tuple->Attributes = tuple->TupleOffset = 0; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 255; + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; link->io.NumPorts1 = 16; - i = first_tuple(link->handle, &tuple, &parse); + i = first_tuple(link->handle, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if (i == CS_SUCCESS) { link->conf.ConfigIndex = cf->index; @@ -686,10 +732,12 @@ static int smc_config(dev_link_t *link) i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) break; } - i = next_tuple(link->handle, &tuple, &parse); + i = next_tuple(link->handle, tuple, parse); } if (i == CS_SUCCESS) dev->base_addr = link->io.BasePort1; + + kfree(cfg_mem); return i; } @@ -697,41 +745,58 @@ static int smc_setup(dev_link_t *link) { client_handle_t handle = link->handle; struct net_device *dev = link->priv; - tuple_t tuple; - cisparse_t parse; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + cisparse_t *parse; cistpl_lan_node_id_t *node_id; - u_char buf[255], *station_addr; - int i; + u_char *buf, *station_addr; + int i, rc; + + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return CS_OUT_OF_RESOURCE; - tuple.Attributes = tuple.TupleOffset = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + buf = cfg_mem->buf; + + tuple->Attributes = tuple->TupleOffset = 0; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 255; /* Check for a LAN function extension tuple */ - tuple.DesiredTuple = CISTPL_FUNCE; - i = first_tuple(handle, &tuple, &parse); + tuple->DesiredTuple = CISTPL_FUNCE; + i = first_tuple(handle, tuple, parse); while (i == CS_SUCCESS) { - if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID) + if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) break; - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(handle, tuple, parse); } if (i == CS_SUCCESS) { - node_id = (cistpl_lan_node_id_t *)parse.funce.data; + node_id = (cistpl_lan_node_id_t *)parse->funce.data; if (node_id->nb == 6) { for (i = 0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; - return 0; + rc = 0; + goto free_cfg_mem; } } /* Try the third string in the Version 1 Version/ID tuple. */ - tuple.DesiredTuple = CISTPL_VERS_1; - if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) - return -1; - station_addr = parse.version_1.str + parse.version_1.ofs[2]; - if (cvt_ascii_address(dev, station_addr) == 0) - return 0; + tuple->DesiredTuple = CISTPL_VERS_1; + if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; + } + station_addr = parse->version_1.str + parse->version_1.ofs[2]; + if (cvt_ascii_address(dev, station_addr) == 0) { + rc = 0; + goto free_cfg_mem; + } - return -1; + rc = -1; +free_cfg_mem: + kfree(cfg_mem); + return rc; } /*====================================================================*/ @@ -773,26 +838,36 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) { client_handle_t handle = link->handle; struct net_device *dev = link->priv; - tuple_t tuple; - u_char buf[255]; - int i; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + u_char *buf; + int i, rc; + + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return -1; + + tuple = &cfg_mem->tuple; + buf = cfg_mem->buf; - tuple.Attributes = TUPLE_RETURN_COMMON; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; + tuple->Attributes = TUPLE_RETURN_COMMON; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 255; + tuple->TupleOffset = 0; /* Read the station address from tuple 0x90, subtuple 0x04 */ - tuple.DesiredTuple = 0x90; - i = pcmcia_get_first_tuple(handle, &tuple); + tuple->DesiredTuple = 0x90; + i = pcmcia_get_first_tuple(handle, tuple); while (i == CS_SUCCESS) { - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(handle, tuple); if ((i != CS_SUCCESS) || (buf[0] == 0x04)) break; - i = pcmcia_get_next_tuple(handle, &tuple); + i = pcmcia_get_next_tuple(handle, tuple); + } + if (i != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; } - if (i != CS_SUCCESS) - return -1; for (i = 0; i < 6; i++) dev->dev_addr[i] = buf[i+2]; @@ -814,8 +889,10 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) inw(link->io.BasePort1 + OSITECH_AUI_PWR), inw(link->io.BasePort1 + OSITECH_RESET_ISR)); } - - return 0; + rc = 0; +free_cfg_mem: + kfree(cfg_mem); + return rc; } /*====================================================================== @@ -887,9 +964,10 @@ static void smc91c92_config(dev_link_t *link) client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); - tuple_t tuple; - cisparse_t parse; - u_short buf[32]; + struct smc_cfg_mem *cfg_mem; + tuple_t *tuple; + cisparse_t *parse; + u_char *buf; char *name; int i, j, rev; kio_addr_t ioaddr; @@ -897,21 +975,29 @@ static void smc91c92_config(dev_link_t *link) DEBUG(0, "smc91c92_config(0x%p)\n", link); - tuple.Attributes = tuple.TupleOffset = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = sizeof(buf); + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + goto config_failed; - tuple.DesiredTuple = CISTPL_CONFIG; - i = first_tuple(handle, &tuple, &parse); - CS_EXIT_TEST(i, ParseTuple, config_failed); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + buf = cfg_mem->buf; - tuple.DesiredTuple = CISTPL_MANFID; - tuple.Attributes = TUPLE_RETURN_COMMON; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - smc->manfid = parse.manfid.manf; - smc->cardid = parse.manfid.card; + tuple->Attributes = tuple->TupleOffset = 0; + tuple->TupleData = (cisdata_t *)buf; + tuple->TupleDataMax = 64; + + tuple->DesiredTuple = CISTPL_CONFIG; + i = first_tuple(handle, tuple, parse); + CS_EXIT_TEST(i, ParseTuple, config_failed); + link->conf.ConfigBase = parse->config.base; + link->conf.Present = parse->config.rmask[0]; + + tuple->DesiredTuple = CISTPL_MANFID; + tuple->Attributes = TUPLE_RETURN_COMMON; + if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { + smc->manfid = parse->manfid.manf; + smc->cardid = parse->manfid.card; } /* Configure card */ @@ -1046,7 +1132,7 @@ static void smc91c92_config(dev_link_t *link) printk(KERN_NOTICE " No MII transceivers found!\n"); } } - + kfree(cfg_mem); return; config_undo: @@ -1054,6 +1140,7 @@ config_undo: config_failed: /* CS_EXIT_TEST() calls jump to here... */ smc91c92_release(link); link->state &= ~DEV_CONFIG_PENDING; + kfree(cfg_mem); } /* smc91c92_config */ @@ -2006,7 +2093,7 @@ static void media_check(u_long arg) } /* Ignore collisions unless we've had no rx's recently */ - if (jiffies - dev->last_rx > HZ) { + if (time_after(jiffies, dev->last_rx + HZ)) { if (smc->tx_err || (smc->media_status & EPH_16COL)) media |= EPH_16COL; } @@ -2236,13 +2323,47 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) return rc; } +static struct pcmcia_device_id smc91c92_ids[] = { + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a), + PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), + PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), + PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), + PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), + PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020), + PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023), + PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb), + PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc), + PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1), + PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5), + PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9), + PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953), + PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a), + PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Four of Diamonds Ethernet", 0xc2f80cd, 0xb3466314), + PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Seven of Diamonds Ethernet", 0xc2f80cd, 0x194b650a), + PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc), + PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9), + PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d), + /* These conflict with other cards! */ + /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */ + /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */ + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids); + static struct pcmcia_driver smc91c92_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "smc91c92_cs", }, .attach = smc91c92_attach, + .event = smc91c92_event, .detach = smc91c92_detach, + .id_table = smc91c92_ids, }; static int __init init_smc91c92_cs(void) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 58177d67ea12..ce143f08638a 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -81,7 +81,6 @@ #include <linux/ioport.h> #include <linux/bitops.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -619,11 +618,6 @@ xirc2ps_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &xirc2ps_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; if ((err = pcmcia_register_client(&link->handle, &client_reg))) { @@ -1983,13 +1977,42 @@ do_stop(struct net_device *dev) return 0; } +static struct pcmcia_device_id xirc2ps_ids[] = { + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), + PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), + PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), + PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), + PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), + PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), + PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), + PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), + PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), + PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), + PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), + PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), + /* also matches CFE-10 cards! */ + /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); + + static struct pcmcia_driver xirc2ps_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "xirc2ps_cs", }, .attach = xirc2ps_attach, + .event = xirc2ps_event, .detach = xirc2ps_detach, + .id_table = xirc2ps_ids, }; static int __init diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 13f114876965..113b68099216 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -850,7 +850,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - schedule_timeout(data * HZ); + msleep_interruptible(data * 1000); del_timer_sync(&lp->blink_timer); /* Restore the original value of the bcrs */ @@ -1602,7 +1602,7 @@ pcnet32_init_ring(struct net_device *dev) rmb(); if (lp->rx_dma_addr[i] == 0) - lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, + lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); @@ -1983,7 +1983,7 @@ pcnet32_rx(struct net_device *dev) lp->rx_skbuff[entry] = newskb; newskb->dev = dev; lp->rx_dma_addr[entry] = - pci_map_single(lp->pci_dev, newskb->tail, + pci_map_single(lp->pci_dev, newskb->data, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]); rx_in_place = 1; @@ -2020,7 +2020,7 @@ pcnet32_rx(struct net_device *dev) PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, - (unsigned char *)(lp->rx_skbuff[entry]->tail), + (unsigned char *)(lp->rx_skbuff[entry]->data), pkt_len,0); pci_dma_sync_single_for_device(lp->pci_dev, lp->rx_dma_addr[entry], diff --git a/drivers/net/plip.c b/drivers/net/plip.c index f4b62405d2e5..1bd22cd40c75 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -160,7 +160,7 @@ static struct net_device_stats *plip_get_stats(struct net_device *dev); static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int plip_preempt(void *handle); static void plip_wakeup(void *handle); - + enum plip_connection_state { PLIP_CN_NONE=0, PLIP_CN_RECEIVE, @@ -231,8 +231,8 @@ struct net_local { atomic_t kill_timer; struct semaphore killed_timer_sem; }; - -inline static void enable_parport_interrupts (struct net_device *dev) + +static inline void enable_parport_interrupts (struct net_device *dev) { if (dev->irq != -1) { @@ -242,7 +242,7 @@ inline static void enable_parport_interrupts (struct net_device *dev) } } -inline static void disable_parport_interrupts (struct net_device *dev) +static inline void disable_parport_interrupts (struct net_device *dev) { if (dev->irq != -1) { @@ -252,7 +252,7 @@ inline static void disable_parport_interrupts (struct net_device *dev) } } -inline static void write_data (struct net_device *dev, unsigned char data) +static inline void write_data (struct net_device *dev, unsigned char data) { struct parport *port = ((struct net_local *)dev->priv)->pardev->port; @@ -260,14 +260,14 @@ inline static void write_data (struct net_device *dev, unsigned char data) port->ops->write_data (port, data); } -inline static unsigned char read_status (struct net_device *dev) +static inline unsigned char read_status (struct net_device *dev) { struct parport *port = ((struct net_local *)dev->priv)->pardev->port; return port->ops->read_status (port); } - + /* Entry point of PLIP driver. Probe the hardware, and register/initialize the driver. @@ -316,7 +316,7 @@ plip_init_netdev(struct net_device *dev) spin_lock_init(&nl->lock); } - + /* Bottom half handler for the delayed request. This routine is kicked by do_timer(). Request `plip_bh' to be invoked. */ @@ -471,7 +471,7 @@ plip_bh_timeout_error(struct net_device *dev, struct net_local *nl, return TIMEOUT; } - + static int plip_none(struct net_device *dev, struct net_local *nl, struct plip_local *snd, struct plip_local *rcv) @@ -481,7 +481,7 @@ plip_none(struct net_device *dev, struct net_local *nl, /* PLIP_RECEIVE --- receive a byte(two nibbles) Returns OK on success, TIMEOUT on timeout */ -inline static int +static inline int plip_receive(unsigned short nibble_timeout, struct net_device *dev, enum plip_nibble_state *ns_p, unsigned char *data_p) { @@ -540,7 +540,7 @@ plip_receive(unsigned short nibble_timeout, struct net_device *dev, * in far too many old systems not all even running Linux. */ -static unsigned short plip_type_trans(struct sk_buff *skb, struct net_device *dev) +static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; unsigned char *rawp; @@ -582,7 +582,6 @@ static unsigned short plip_type_trans(struct sk_buff *skb, struct net_device *de return htons(ETH_P_802_2); } - /* PLIP_RECEIVE_PACKET --- receive a packet */ static int plip_receive_packet(struct net_device *dev, struct net_local *nl, @@ -702,7 +701,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, /* PLIP_SEND --- send a byte (two nibbles) Returns OK on success, TIMEOUT when timeout */ -inline static int +static inline int plip_send(unsigned short nibble_timeout, struct net_device *dev, enum plip_nibble_state *ns_p, unsigned char data) { @@ -902,7 +901,7 @@ plip_error(struct net_device *dev, struct net_local *nl, return OK; } - + /* Handle the parallel port interrupts. */ static void plip_interrupt(int irq, void *dev_id, struct pt_regs * regs) @@ -957,7 +956,7 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs) spin_unlock_irq(&nl->lock); } - + static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev) { @@ -1238,7 +1237,7 @@ plip_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } return 0; } - + static int parport[PLIP_MAX] = { [0 ... PLIP_MAX-1] = -1 }; static int timid; diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 33b9d79b1aad..59e8183c639e 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -364,7 +364,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, spin_lock_irqsave(&ap->recv_lock, flags); ppp_async_input(ap, buf, cflags, count); spin_unlock_irqrestore(&ap->recv_lock, flags); - if (skb_queue_len(&ap->rqueue)) + if (!skb_queue_empty(&ap->rqueue)) tasklet_schedule(&ap->tsk); ap_put(ap); if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) @@ -1025,7 +1025,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data, static void __exit ppp_async_cleanup(void) { - if (tty_register_ldisc(N_PPP, NULL) != 0) + if (tty_unregister_ldisc(N_PPP) != 0) printk(KERN_ERR "failed to unregister PPP line discipline\n"); } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 3b377f6cd4a0..a32668e88e09 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -273,7 +273,7 @@ static int ppp_connect_channel(struct channel *pch, int unit); static int ppp_disconnect_channel(struct channel *pch); static void ppp_destroy_channel(struct channel *pch); -static struct class_simple *ppp_class; +static struct class *ppp_class; /* Translates a PPP protocol number to a NP index (NP == network protocol) */ static inline int proto_to_npindex(int proto) @@ -858,12 +858,12 @@ static int __init ppp_init(void) printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); if (!err) { - ppp_class = class_simple_create(THIS_MODULE, "ppp"); + ppp_class = class_create(THIS_MODULE, "ppp"); if (IS_ERR(ppp_class)) { err = PTR_ERR(ppp_class); goto out_chrdev; } - class_simple_device_add(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); + class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "ppp"); if (err) @@ -876,8 +876,8 @@ out: return err; out_class: - class_simple_device_remove(MKDEV(PPP_MAJOR,0)); - class_simple_destroy(ppp_class); + class_device_destroy(ppp_class, MKDEV(PPP_MAJOR,0)); + class_destroy(ppp_class); out_chrdev: unregister_chrdev(PPP_MAJOR, "ppp"); goto out; @@ -1217,36 +1217,43 @@ ppp_push(struct ppp *ppp) */ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) { - int nch, len, fragsize; + int len, fragsize; int i, bits, hdrlen, mtu; - int flen, fnb; + int flen; + int navail, nfree; + int nbigger; unsigned char *p, *q; struct list_head *list; struct channel *pch; struct sk_buff *frag; struct ppp_channel *chan; - nch = 0; + nfree = 0; /* # channels which have no packet already queued */ + navail = 0; /* total # of usable channels (not deregistered) */ hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; + i = 0; list = &ppp->channels; while ((list = list->next) != &ppp->channels) { pch = list_entry(list, struct channel, clist); - nch += pch->avail = (skb_queue_len(&pch->file.xq) == 0); - /* - * If a channel hasn't had a fragment yet, it has to get - * one before we send any fragments on later channels. - * If it can't take a fragment now, don't give any - * to subsequent channels. - */ - if (!pch->had_frag && !pch->avail) { - while ((list = list->next) != &ppp->channels) { - pch = list_entry(list, struct channel, clist); - pch->avail = 0; + navail += pch->avail = (pch->chan != NULL); + if (pch->avail) { + if (skb_queue_empty(&pch->file.xq) || + !pch->had_frag) { + pch->avail = 2; + ++nfree; } - break; + if (!pch->had_frag && i < ppp->nxchan) + ppp->nxchan = i; } + ++i; } - if (nch == 0) + + /* + * Don't start sending this packet unless at least half of + * the channels are free. This gives much better TCP + * performance if we have a lot of channels. + */ + if (nfree == 0 || nfree < navail / 2) return 0; /* can't take now, leave it in xmit_pending */ /* Do protocol field compression (XXX this should be optional) */ @@ -1257,14 +1264,19 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) --len; } - /* decide on fragment size */ + /* + * Decide on fragment size. + * We create a fragment for each free channel regardless of + * how small they are (i.e. even 0 length) in order to minimize + * the time that it will take to detect when a channel drops + * a fragment. + */ fragsize = len; - if (nch > 1) { - int maxch = ROUNDUP(len, MIN_FRAG_SIZE); - if (nch > maxch) - nch = maxch; - fragsize = ROUNDUP(fragsize, nch); - } + if (nfree > 1) + fragsize = ROUNDUP(fragsize, nfree); + /* nbigger channels get fragsize bytes, the rest get fragsize-1, + except if nbigger==0, then they all get fragsize. */ + nbigger = len % nfree; /* skip to the channel after the one we last used and start at that one */ @@ -1278,7 +1290,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) /* create a fragment for each channel */ bits = B; - do { + while (nfree > 0 || len > 0) { list = list->next; if (list == &ppp->channels) { i = 0; @@ -1289,61 +1301,92 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) if (!pch->avail) continue; + /* + * Skip this channel if it has a fragment pending already and + * we haven't given a fragment to all of the free channels. + */ + if (pch->avail == 1) { + if (nfree > 0) + continue; + } else { + --nfree; + pch->avail = 1; + } + /* check the channel's mtu and whether it is still attached. */ spin_lock_bh(&pch->downl); - if (pch->chan == 0 || (mtu = pch->chan->mtu) < hdrlen) { - /* can't use this channel */ + if (pch->chan == NULL) { + /* can't use this channel, it's being deregistered */ spin_unlock_bh(&pch->downl); pch->avail = 0; - if (--nch == 0) + if (--navail == 0) break; continue; } /* - * We have to create multiple fragments for this channel - * if fragsize is greater than the channel's mtu. + * Create a fragment for this channel of + * min(max(mtu+2-hdrlen, 4), fragsize, len) bytes. + * If mtu+2-hdrlen < 4, that is a ridiculously small + * MTU, so we use mtu = 2 + hdrlen. */ if (fragsize > len) fragsize = len; - for (flen = fragsize; flen > 0; flen -= fnb) { - fnb = flen; - if (fnb > mtu + 2 - hdrlen) - fnb = mtu + 2 - hdrlen; - if (fnb >= len) - bits |= E; - frag = alloc_skb(fnb + hdrlen, GFP_ATOMIC); - if (frag == 0) - goto noskb; - q = skb_put(frag, fnb + hdrlen); - /* make the MP header */ - q[0] = PPP_MP >> 8; - q[1] = PPP_MP; - if (ppp->flags & SC_MP_XSHORTSEQ) { - q[2] = bits + ((ppp->nxseq >> 8) & 0xf); - q[3] = ppp->nxseq; - } else { - q[2] = bits; - q[3] = ppp->nxseq >> 16; - q[4] = ppp->nxseq >> 8; - q[5] = ppp->nxseq; - } - - /* copy the data in */ - memcpy(q + hdrlen, p, fnb); - - /* try to send it down the channel */ - chan = pch->chan; - if (!chan->ops->start_xmit(chan, frag)) - skb_queue_tail(&pch->file.xq, frag); - pch->had_frag = 1; - p += fnb; - len -= fnb; - ++ppp->nxseq; - bits = 0; + flen = fragsize; + mtu = pch->chan->mtu + 2 - hdrlen; + if (mtu < 4) + mtu = 4; + if (flen > mtu) + flen = mtu; + if (flen == len && nfree == 0) + bits |= E; + frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); + if (frag == 0) + goto noskb; + q = skb_put(frag, flen + hdrlen); + + /* make the MP header */ + q[0] = PPP_MP >> 8; + q[1] = PPP_MP; + if (ppp->flags & SC_MP_XSHORTSEQ) { + q[2] = bits + ((ppp->nxseq >> 8) & 0xf); + q[3] = ppp->nxseq; + } else { + q[2] = bits; + q[3] = ppp->nxseq >> 16; + q[4] = ppp->nxseq >> 8; + q[5] = ppp->nxseq; } + + /* + * Copy the data in. + * Unfortunately there is a bug in older versions of + * the Linux PPP multilink reconstruction code where it + * drops 0-length fragments. Therefore we make sure the + * fragment has at least one byte of data. Any bytes + * we add in this situation will end up as padding on the + * end of the reconstructed packet. + */ + if (flen == 0) + *skb_put(frag, 1) = 0; + else + memcpy(q + hdrlen, p, flen); + + /* try to send it down the channel */ + chan = pch->chan; + if (!skb_queue_empty(&pch->file.xq) || + !chan->ops->start_xmit(chan, frag)) + skb_queue_tail(&pch->file.xq, frag); + pch->had_frag = 1; + p += flen; + len -= flen; + ++ppp->nxseq; + bits = 0; spin_unlock_bh(&pch->downl); - } while (len > 0); + + if (--nbigger == 0 && fragsize > 0) + --fragsize; + } ppp->nxchan = i; return 1; @@ -1369,7 +1412,7 @@ ppp_channel_push(struct channel *pch) spin_lock_bh(&pch->downl); if (pch->chan != 0) { - while (skb_queue_len(&pch->file.xq) > 0) { + while (!skb_queue_empty(&pch->file.xq)) { skb = skb_dequeue(&pch->file.xq); if (!pch->chan->ops->start_xmit(pch->chan, skb)) { /* put the packet back and try again later */ @@ -1383,7 +1426,7 @@ ppp_channel_push(struct channel *pch) } spin_unlock_bh(&pch->downl); /* see if there is anything from the attached unit to be sent */ - if (skb_queue_len(&pch->file.xq) == 0) { + if (skb_queue_empty(&pch->file.xq)) { read_lock_bh(&pch->upl); ppp = pch->ppp; if (ppp != 0) @@ -1422,7 +1465,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) kfree_skb(skb); return; } - + proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) { @@ -1691,7 +1734,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) struct list_head *l; int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0) + if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0) goto err; /* no good, throw it away */ /* Decode sequence number and begin/end bits */ @@ -2611,8 +2654,8 @@ static void __exit ppp_cleanup(void) if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) printk(KERN_ERR "PPP: failed to unregister PPP device\n"); devfs_remove("ppp"); - class_simple_device_remove(MKDEV(PPP_MAJOR, 0)); - class_simple_destroy(ppp_class); + class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); + class_destroy(ppp_class); } /* diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 7d0150b4c629..4d51c0c8023d 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -406,7 +406,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, spin_lock_irqsave(&ap->recv_lock, flags); ppp_sync_input(ap, buf, cflags, count); spin_unlock_irqrestore(&ap->recv_lock, flags); - if (skb_queue_len(&ap->rqueue)) + if (!skb_queue_empty(&ap->rqueue)) tasklet_schedule(&ap->tsk); sp_put(ap); if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) @@ -793,7 +793,7 @@ err: static void __exit ppp_sync_cleanup(void) { - if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0) + if (tty_unregister_ldisc(N_SYNC_PPP) != 0) printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index d6d0e43dab65..d5afe05cd826 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -69,7 +69,13 @@ VERSION 2.2LK <2005/01/25> #include <asm/io.h> #include <asm/irq.h> -#define RTL8169_VERSION "2.2LK" +#ifdef CONFIG_R8169_NAPI +#define NAPI_SUFFIX "-NAPI" +#else +#define NAPI_SUFFIX "" +#endif + +#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX #define MODULENAME "r8169" #define PFX MODULENAME ": " @@ -85,6 +91,10 @@ VERSION 2.2LK <2005/01/25> #define dprintk(fmt, args...) do {} while (0) #endif /* RTL8169_DEBUG */ +#define R8169_MSG_DEFAULT \ + (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \ + NETIF_MSG_IFDOWN) + #define TX_BUFFS_AVAIL(tp) \ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) @@ -174,8 +184,9 @@ const static struct { #undef _R static struct pci_device_id rtl8169_pci_tbl[] = { - {0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), }, + { PCI_DEVICE(0x16ec, 0x0116), }, {0,}, }; @@ -183,10 +194,15 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); static int rx_copybreak = 200; static int use_dac; +static struct { + u32 msg_enable; +} debug = { -1 }; enum RTL8169_registers { MAC0 = 0, /* Ethernet hardware address. */ MAR0 = 8, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, TxDescStartAddrLow = 0x20, TxDescStartAddrHigh = 0x24, TxHDescStartAddrLow = 0x28, @@ -328,6 +344,9 @@ enum RTL8169_register_content { /* _TBICSRBit */ TBILinkOK = 0x02000000, + + /* DumpCounterCommand */ + CounterDump = 0x8, }; enum _DescStatusBit { @@ -385,6 +404,7 @@ struct rtl8169_private { struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ spinlock_t lock; /* spin lock flag */ + u32 msg_enable; int chipset; int mac_version; int phy_version; @@ -418,9 +438,13 @@ struct rtl8169_private { MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); module_param_array(media, int, &num_media, 0); +MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8)."); module_param(rx_copybreak, int, 0); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param(use_dac, int, 0); MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); +module_param_named(debug, debug.msg_enable, int, 0); +MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); MODULE_LICENSE("GPL"); MODULE_VERSION(RTL8169_VERSION); @@ -433,10 +457,10 @@ static void rtl8169_hw_start(struct net_device *dev); static int rtl8169_close(struct net_device *dev); static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); -static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); +static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, void __iomem *); -static int rtl8169_change_mtu(struct net_device *netdev, int new_mtu); +static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); static void rtl8169_down(struct net_device *dev); #ifdef CONFIG_R8169_NAPI @@ -543,9 +567,13 @@ static void rtl8169_check_link_status(struct net_device *dev, spin_lock_irqsave(&tp->lock, flags); if (tp->link_ok(ioaddr)) { netif_carrier_on(dev); - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else + if (netif_msg_ifup(tp)) + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else { + if (netif_msg_ifdown(tp)) + printk(KERN_INFO PFX "%s: link down\n", dev->name); netif_carrier_off(dev); + } spin_unlock_irqrestore(&tp->lock, flags); } @@ -569,7 +597,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; - if ((option != 0xff) && !idx) + if ((option != 0xff) && !idx && netif_msg_drv(&debug)) printk(KERN_WARNING PFX "media option is deprecated.\n"); for (p = link_settings; p->media != 0xff; p++) { @@ -611,9 +639,11 @@ static int rtl8169_set_speed_tbi(struct net_device *dev, } else if (autoneg == AUTONEG_ENABLE) RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); else { - printk(KERN_WARNING PFX - "%s: incorrect speed setting refused in TBI mode\n", - dev->name); + if (netif_msg_link(tp)) { + printk(KERN_WARNING "%s: " + "incorrect speed setting refused in TBI mode\n", + dev->name); + } ret = -EOPNOTSUPP; } @@ -871,12 +901,120 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, spin_unlock_irqrestore(&tp->lock, flags); } +static u32 rtl8169_get_msglevel(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + return tp->msg_enable; +} + +static void rtl8169_set_msglevel(struct net_device *dev, u32 value) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + tp->msg_enable = value; +} + +static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { + "tx_packets", + "rx_packets", + "tx_errors", + "rx_errors", + "rx_missed", + "align_errors", + "tx_single_collisions", + "tx_multi_collisions", + "unicast", + "broadcast", + "multicast", + "tx_aborted", + "tx_underrun", +}; + +struct rtl8169_counters { + u64 tx_packets; + u64 rx_packets; + u64 tx_errors; + u32 rx_errors; + u16 rx_missed; + u16 align_errors; + u32 tx_one_collision; + u32 tx_multi_collision; + u64 rx_unicast; + u64 rx_broadcast; + u32 rx_multicast; + u16 tx_aborted; + u16 tx_underun; +}; + +static int rtl8169_get_stats_count(struct net_device *dev) +{ + return ARRAY_SIZE(rtl8169_gstrings); +} + +static void rtl8169_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct rtl8169_counters *counters; + dma_addr_t paddr; + u32 cmd; + + ASSERT_RTNL(); + + counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); + if (!counters) + return; + + RTL_W32(CounterAddrHigh, (u64)paddr >> 32); + cmd = (u64)paddr & DMA_32BIT_MASK; + RTL_W32(CounterAddrLow, cmd); + RTL_W32(CounterAddrLow, cmd | CounterDump); + + while (RTL_R32(CounterAddrLow) & CounterDump) { + if (msleep_interruptible(1)) + break; + } + + RTL_W32(CounterAddrLow, 0); + RTL_W32(CounterAddrHigh, 0); + + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underun); + + pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); +} + +static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch(stringset) { + case ETH_SS_STATS: + memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); + break; + } +} + + static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, + .get_msglevel = rtl8169_get_msglevel, + .set_msglevel = rtl8169_set_msglevel, .get_rx_csum = rtl8169_get_rx_csum, .set_rx_csum = rtl8169_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, @@ -886,6 +1024,9 @@ static struct ethtool_ops rtl8169_ethtool_ops = { .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, .get_regs = rtl8169_get_regs, + .get_strings = rtl8169_get_strings, + .get_stats_count = rtl8169_get_stats_count, + .get_ethtool_stats = rtl8169_get_ethtool_stats, }; static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum, @@ -1091,7 +1232,8 @@ static void rtl8169_phy_timer(unsigned long __opaque) if (tp->link_ok(ioaddr)) goto out_unlock; - printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name); + if (netif_msg_link(tp)) + printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); tp->phy_reset_enable(ioaddr); @@ -1169,18 +1311,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, /* dev zeroed in alloc_etherdev */ dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { - printk(KERN_ERR PFX "unable to alloc new ethernet\n"); + if (netif_msg_drv(&debug)) + printk(KERN_ERR PFX "unable to alloc new ethernet\n"); goto err_out; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pci_enable_device(pdev); - if (rc) { - printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev)); + if (rc < 0) { + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX "%s: enable failure\n", + pci_name(pdev)); + } goto err_out_free_dev; } @@ -1196,29 +1343,39 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX - "Cannot find PowerManagement capability, aborting.\n"); + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX + "Cannot find PowerManagement capability. " + "Aborting.\n"); + } goto err_out_mwi; } /* make sure PCI base addr 1 is MMIO */ if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX - "region #1 not an MMIO resource, aborting\n"); + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX + "region #1 not an MMIO resource, aborting\n"); + } rc = -ENODEV; goto err_out_mwi; } /* check for weird/broken PCI region reporting */ if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { - printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX + "Invalid PCI region size(s), aborting\n"); + } rc = -ENODEV; goto err_out_mwi; } rc = pci_request_regions(pdev, MODULENAME); - if (rc) { - printk(KERN_ERR PFX "%s: could not request regions.\n", - pci_name(pdev)); + if (rc < 0) { + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX "%s: could not request regions.\n", + pci_name(pdev)); + } goto err_out_mwi; } @@ -1231,7 +1388,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { - printk(KERN_ERR PFX "DMA configuration failed.\n"); + if (netif_msg_probe(tp)) { + printk(KERN_ERR PFX + "DMA configuration failed.\n"); + } goto err_out_free_res; } } @@ -1241,7 +1401,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, /* ioremap MMIO region */ ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE); if (ioaddr == NULL) { - printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); + if (netif_msg_probe(tp)) + printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; goto err_out_free_res; } @@ -1272,9 +1433,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, } if (i < 0) { /* Unknown chip: assume array element #0, original RTL-8169 */ - printk(KERN_DEBUG PFX - "PCI device %s: unknown chip version, assuming %s\n", - pci_name(pdev), rtl_chip_info[0].name); + if (netif_msg_probe(tp)) { + printk(KERN_DEBUG PFX "PCI device %s: " + "unknown chip version, assuming %s\n", + pci_name(pdev), rtl_chip_info[0].name); + } i++; } tp->chipset = i; @@ -1308,7 +1471,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct rtl8169_private *tp; void __iomem *ioaddr = NULL; static int board_idx = -1; - static int printed_version = 0; u8 autoneg, duplex; u16 speed; int i, rc; @@ -1318,10 +1480,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) board_idx++; - if (!printed_version) { + if (netif_msg_drv(&debug)) { printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", MODULENAME, RTL8169_VERSION); - printed_version = 1; } rc = rtl8169_init_board(pdev, &dev, &ioaddr); @@ -1366,7 +1527,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_R8169_NAPI dev->poll = rtl8169_poll; dev->weight = R8169_NAPI_WEIGHT; - printk(KERN_INFO PFX "NAPI enabled\n"); #endif #ifdef CONFIG_R8169_VLAN @@ -1391,20 +1551,24 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; } - printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name, - rtl_chip_info[tp->chipset].name); + if (netif_msg_probe(tp)) { + printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", + dev->name, rtl_chip_info[tp->chipset].name); + } pci_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - rtl_chip_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); + if (netif_msg_probe(tp)) { + printk(KERN_INFO "%s: %s at 0x%lx, " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " + "IRQ %d\n", + dev->name, + rtl_chip_info[ent->driver_data].name, + dev->base_addr, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5], dev->irq); + } rtl8169_hw_phy_config(dev); @@ -1427,7 +1591,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl8169_set_speed(dev, autoneg, speed, duplex); - if (RTL_R8(PHYstatus) & TBI_Enable) + if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); return 0; @@ -1712,7 +1876,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, skb_reserve(skb, NET_IP_ALIGN); *sk_buff = skb; - mapping = pci_map_single(pdev, skb->tail, rx_buf_sz, + mapping = pci_map_single(pdev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); @@ -1860,8 +2024,13 @@ static void rtl8169_reinit_task(void *_data) ret = rtl8169_open(dev); if (unlikely(ret < 0)) { if (net_ratelimit()) { - printk(PFX KERN_ERR "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); + struct rtl8169_private *tp = netdev_priv(dev); + + if (netif_msg_drv(tp)) { + printk(PFX KERN_ERR + "%s: reinit failure (status = %d)." + " Rescheduling.\n", dev->name, ret); + } } rtl8169_schedule_work(dev, rtl8169_reinit_task); } @@ -1886,8 +2055,12 @@ static void rtl8169_reset_task(void *_data) netif_wake_queue(dev); } else { if (net_ratelimit()) { - printk(PFX KERN_EMERG "%s: Rx buffers shortage\n", - dev->name); + struct rtl8169_private *tp = netdev_priv(dev); + + if (netif_msg_intr(tp)) { + printk(PFX KERN_EMERG + "%s: Rx buffers shortage\n", dev->name); + } } rtl8169_schedule_work(dev, rtl8169_reset_task); } @@ -1973,8 +2146,11 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) int ret = 0; if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); + if (netif_msg_drv(tp)) { + printk(KERN_ERR + "%s: BUG! Tx Ring full when queue awake!\n", + dev->name); + } goto err_stop; } @@ -2049,8 +2225,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); pci_read_config_word(pdev, PCI_STATUS, &pci_status); - printk(KERN_ERR PFX "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); + if (netif_msg_intr(tp)) { + printk(KERN_ERR + "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", + dev->name, pci_cmd, pci_status); + } /* * The recovery sequence below admits a very elaborated explanation: @@ -2069,7 +2248,8 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) /* The infamous DAC f*ckup only happens at boot time */ if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name); + if (netif_msg_intr(tp)) + printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); tp->cp_cmd &= ~PCIDAC; RTL_W16(CPlusCmd, tp->cp_cmd); dev->features &= ~NETIF_F_HIGHDMA; @@ -2156,7 +2336,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); if (skb) { skb_reserve(skb, NET_IP_ALIGN); - eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0); + eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); *sk_buff = skb; rtl8169_mark_to_asic(desc, rx_buf_sz); ret = 0; @@ -2180,7 +2360,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); - while (rx_left > 0) { + for (; rx_left > 0; rx_left--, cur_rx++) { unsigned int entry = cur_rx % NUM_RX_DESC; struct RxDesc *desc = tp->RxDescArray + entry; u32 status; @@ -2190,9 +2370,12 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, if (status & DescOwn) break; - if (status & RxRES) { - printk(KERN_INFO "%s: Rx ERROR. status = %08x\n", - dev->name, status); + if (unlikely(status & RxRES)) { + if (netif_msg_rx_err(tp)) { + printk(KERN_INFO + "%s: Rx ERROR. status = %08x\n", + dev->name, status); + } tp->stats.rx_errors++; if (status & (RxRWT | RxRUNT)) tp->stats.rx_length_errors++; @@ -2214,7 +2397,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, tp->stats.rx_dropped++; tp->stats.rx_length_errors++; rtl8169_mark_to_asic(desc, tp->rx_buf_sz); - goto move_on; + continue; } rtl8169_rx_csum(skb, desc); @@ -2243,16 +2426,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, tp->stats.rx_bytes += pkt_size; tp->stats.rx_packets++; } -move_on: - cur_rx++; - rx_left--; } count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count) + if (!delta && count && netif_msg_intr(tp)) printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); tp->dirty_rx += delta; @@ -2263,7 +2443,7 @@ move_on: * after refill ? * - how do others driver handle this condition (Uh oh...). */ - if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) + if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); return count; @@ -2315,7 +2495,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (likely(netif_rx_schedule_prep(dev))) __netif_rx_schedule(dev); - else { + else if (netif_msg_intr(tp)) { printk(KERN_INFO "%s: interrupt %04x taken in poll\n", dev->name, status); } @@ -2334,8 +2514,10 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } while (boguscnt > 0); if (boguscnt <= 0) { - printk(KERN_WARNING "%s: Too much work at interrupt!\n", - dev->name); + if (net_ratelimit() && netif_msg_intr(tp)) { + printk(KERN_WARNING + "%s: Too much work at interrupt!\n", dev->name); + } /* Clear all interrupt sources. */ RTL_W16(IntrStatus, 0xffff); } @@ -2458,8 +2640,10 @@ rtl8169_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); + if (netif_msg_link(tp)) { + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); + } rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 9c224eba057d..ea638b162d3f 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -42,6 +42,7 @@ #include <linux/errno.h> #include <linux/ioport.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -1698,11 +1699,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) #else ba = &nic->ba[ring_no][block_no][off]; skb_reserve(skb, BUF0_LEN); - tmp = (unsigned long) skb->data; - tmp += ALIGN_SIZE; - tmp &= ~ALIGN_SIZE; - skb->data = (void *) tmp; - skb->tail = (void *) tmp; + tmp = ((unsigned long) skb->data & ALIGN_SIZE); + if (tmp) + skb_reserve(skb, (ALIGN_SIZE + 1) - tmp); memset(rxdp, 0, sizeof(RxD_t)); rxdp->Buffer2_ptr = pci_map_single @@ -4593,19 +4592,19 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) return ret; } - if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n"); dma_flag = TRUE; if (pci_set_consistent_dma_mask - (pdev, 0xffffffffffffffffULL)) { + (pdev, DMA_64BIT_MASK)) { DBG_PRINT(ERR_DBG, "Unable to obtain 64bit DMA for \ consistent allocations\n"); pci_disable_device(pdev); return -ENOMEM; } - } else if (!pci_set_dma_mask(pdev, 0xffffffffUL)) { + } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 32bit DMA\n"); } else { pci_disable_device(pdev); diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index e15369c8d165..d6388e1533f0 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -90,7 +90,6 @@ static int sb1000_close(struct net_device *dev); /* SB1000 hardware routines to be used during open/configuration phases */ -static inline void nicedelay(unsigned long usecs); static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name); static inline int card_wait_for_ready(const int ioaddr[], const char* name, @@ -254,13 +253,6 @@ static struct pnp_driver sb1000_driver = { static const int TimeOutJiffies = (875 * HZ) / 100; -static inline void nicedelay(unsigned long usecs) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ); - return; -} - /* Card Wait For Busy Clear (cannot be used during an interrupt) */ static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name) @@ -475,7 +467,7 @@ sb1000_reset(const int ioaddr[], const char* name) udelay(1000); outb(0x0, port); inb(port); - nicedelay(60000); + ssleep(1); outb(0x4, port); inb(port); udelay(1000); @@ -537,7 +529,7 @@ sb1000_activate(const int ioaddr[], const char* name) const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; - nicedelay(50000); + ssleep(1); if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if ((status = card_send_command(ioaddr, name, Command1, st))) @@ -944,7 +936,7 @@ sb1000_open(struct net_device *dev) /* initialize sb1000 */ if ((status = sb1000_reset(ioaddr, name))) return status; - nicedelay(200000); + ssleep(1); if ((status = sb1000_check_CRC(ioaddr, name))) return status; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index fd2e7c374906..7abd55a4fb21 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -963,11 +963,11 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb) /* * Do not interrupt per DMA transfer. */ - dsc->dscr_a = virt_to_phys(sb_new->tail) | + dsc->dscr_a = virt_to_phys(sb_new->data) | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0; #else - dsc->dscr_a = virt_to_phys(sb_new->tail) | + dsc->dscr_a = virt_to_phys(sb_new->data) | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | M_DMA_DSCRA_INTERRUPT; #endif diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index 20edeb345792..3ad0b6751f6f 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -135,10 +135,8 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct shaper *shaper = dev->priv; struct sk_buff *ptr; - - if (down_trylock(&shaper->sem)) - return -1; - + + spin_lock(&shaper->lock); ptr=shaper->sendq.prev; /* @@ -232,7 +230,7 @@ static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) shaper->stats.collisions++; } shaper_kick(shaper); - up(&shaper->sem); + spin_unlock(&shaper->lock); return 0; } @@ -271,11 +269,9 @@ static void shaper_timer(unsigned long data) { struct shaper *shaper = (struct shaper *)data; - if (!down_trylock(&shaper->sem)) { - shaper_kick(shaper); - up(&shaper->sem); - } else - mod_timer(&shaper->timer, jiffies); + spin_lock(&shaper->lock); + shaper_kick(shaper); + spin_unlock(&shaper->lock); } /* @@ -332,21 +328,6 @@ static void shaper_kick(struct shaper *shaper) /* - * Flush the shaper queues on a closedown - */ - -static void shaper_flush(struct shaper *shaper) -{ - struct sk_buff *skb; - - down(&shaper->sem); - while((skb=skb_dequeue(&shaper->sendq))!=NULL) - dev_kfree_skb(skb); - shaper_kick(shaper); - up(&shaper->sem); -} - -/* * Bring the interface up. We just disallow this until a * bind. */ @@ -375,7 +356,15 @@ static int shaper_open(struct net_device *dev) static int shaper_close(struct net_device *dev) { struct shaper *shaper=dev->priv; - shaper_flush(shaper); + struct sk_buff *skb; + + while ((skb = skb_dequeue(&shaper->sendq)) != NULL) + dev_kfree_skb(skb); + + spin_lock_bh(&shaper->lock); + shaper_kick(shaper); + spin_unlock_bh(&shaper->lock); + del_timer_sync(&shaper->timer); return 0; } @@ -576,6 +565,7 @@ static void shaper_init_priv(struct net_device *dev) init_timer(&sh->timer); sh->timer.function=shaper_timer; sh->timer.data=(unsigned long)sh; + spin_lock_init(&sh->lock); } /* diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 3107aed0fb51..23b713c700b3 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -66,6 +66,7 @@ #include <linux/ethtool.h> #include <linux/crc32.h> #include <linux/bitops.h> +#include <linux/dma-mapping.h> #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> @@ -93,8 +94,6 @@ static int sis900_debug = -1; /* Use SIS900_DEF_MSG as value */ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (4*HZ) -/* SiS 900 is capable of 32 bits BM DMA */ -#define SIS900_DMA_MASK 0xffffffff enum { SIS_900 = 0, @@ -414,7 +413,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, ret = pci_enable_device(pci_dev); if(ret) return ret; - i = pci_set_dma_mask(pci_dev, SIS900_DMA_MASK); + i = pci_set_dma_mask(pci_dev, DMA_32BIT_MASK); if(i){ printk(KERN_ERR "sis900.c: architecture does not support" "32bit PCI busmaster DMA\n"); @@ -1155,7 +1154,7 @@ sis900_init_rx_ring(struct net_device *net_dev) sis_priv->rx_skbuff[i] = skb; sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE; sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev, - skb->tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); } sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC); @@ -1777,7 +1776,7 @@ static int sis900_rx(struct net_device *net_dev) sis_priv->rx_skbuff[entry] = skb; sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; sis_priv->rx_ring[entry].bufptr = - pci_map_single(sis_priv->pci_dev, skb->tail, + pci_map_single(sis_priv->pci_dev, skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); sis_priv->dirty_rx++; } @@ -1810,7 +1809,7 @@ static int sis900_rx(struct net_device *net_dev) sis_priv->rx_skbuff[entry] = skb; sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; sis_priv->rx_ring[entry].bufptr = - pci_map_single(sis_priv->pci_dev, skb->tail, + pci_map_single(sis_priv->pci_dev, skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); } } diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 7bfaef9305b2..6ee4771addf1 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -112,6 +112,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/dma-mapping.h> #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -4212,7 +4213,7 @@ SK_BOOL DualNet; Flags); SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); - pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; + netif_carrier_off(pAC->dev[Param.Para32[0]]); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4355,7 +4356,7 @@ SK_BOOL DualNet; } /* Inform the world that link protocol is up. */ - pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING; + netif_carrier_on(pAC->dev[Param.Para32[0]]); break; case SK_DRV_NET_DOWN: /* SK_U32 Reason */ @@ -4368,7 +4369,7 @@ SK_BOOL DualNet; } else { DoPrintInterfaceChange = SK_TRUE; } - pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; + netif_carrier_off(pAC->dev[Param.Para32[1]]); break; case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, @@ -4912,8 +4913,8 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, goto out; /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) && + pci_set_dma_mask(pdev, DMA_32BIT_MASK)) goto out_disable_device; @@ -4961,7 +4962,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &SkGePollController; #endif - dev->flags &= ~IFF_RUNNING; SET_NETDEV_DEV(dev, &pdev->dev); SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); @@ -5035,7 +5035,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, dev->set_mac_address = &SkGeSetMacAddr; dev->do_ioctl = &SkGeIoctl; dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; SET_NETDEV_DEV(dev, &pdev->dev); SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); @@ -5142,17 +5141,18 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) SK_AC *pAC = pNet->pAC; struct net_device *otherdev = pAC->dev[1]; - if (pNet->Up) { - pAC->WasIfUp[0] = SK_TRUE; + if (netif_running(dev)) { + netif_carrier_off(dev); DoPrintInterfaceChange = SK_FALSE; SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + netif_device_detach(dev); } if (otherdev != dev) { - pNet = netdev_priv(otherdev); - if (pNet->Up) { - pAC->WasIfUp[1] = SK_TRUE; + if (netif_running(otherdev)) { + netif_carrier_off(otherdev); DoPrintInterfaceChange = SK_FALSE; SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + netif_device_detach(otherdev); } } @@ -5172,27 +5172,43 @@ static int skge_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); DEV_NET *pNet = netdev_priv(dev); SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + int ret; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_enable_device(pdev); pci_set_master(pdev); if (pAC->GIni.GIMacsFound == 2) - request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); else - request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + if (ret) { + printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); + pAC->AllocFlag &= ~SK_ALLOC_IRQ; + dev->irq = 0; + pci_disable_device(pdev); + return -EBUSY; + } - if (pAC->WasIfUp[0] == SK_TRUE) { + netif_device_attach(dev); + if (netif_running(dev)) { DoPrintInterfaceChange = SK_FALSE; SkDrvInitAdapter(pAC, 0); /* first device */ - } - if (pAC->dev[1] != dev && pAC->WasIfUp[1] == SK_TRUE) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 1); /* first device */ + } + if (otherdev != dev) { + netif_device_attach(otherdev); + if (netif_running(otherdev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* second device */ + } } return 0; } +#else +#define skge_suspend NULL +#define skge_resume NULL #endif static struct pci_device_id skge_pci_tbl[] = { diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c index df4483429a77..6cb49dd02251 100644 --- a/drivers/net/sk98lin/skgeinit.c +++ b/drivers/net/sk98lin/skgeinit.c @@ -2016,7 +2016,7 @@ SK_IOC IoC) /* IO context */ * we set the PHY to coma mode and switch to D3 power state. */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* for all ports switch PHY to coma mode */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c index 94a09deecb32..42d2d963150a 100644 --- a/drivers/net/sk98lin/skxmac2.c +++ b/drivers/net/sk98lin/skxmac2.c @@ -1065,7 +1065,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; @@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c deleted file mode 100644 index 134ae0e6495b..000000000000 --- a/drivers/net/sk_g16.c +++ /dev/null @@ -1,2066 +0,0 @@ -/*- - * Copyright (C) 1994 by PJD Weichmann & SWS Bern, Switzerland - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Module : sk_g16.c - * - * Version : $Revision: 1.1 $ - * - * Author : Patrick J.D. Weichmann - * - * Date Created : 94/05/26 - * Last Updated : $Date: 1994/06/30 16:25:15 $ - * - * Description : Schneider & Koch G16 Ethernet Device Driver for - * Linux Kernel >= 1.1.22 - * Update History : - * Paul Gortmaker, 03/97: Fix for v2.1.x to use read{b,w} - * write{b,w} and memcpy -> memcpy_{to,from}io - * - * Jeff Garzik, 06/2000, Modularize - * --*/ - -static const char rcsid[] = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $"; - -/* - * The Schneider & Koch (SK) G16 Network device driver is based - * on the 'ni6510' driver from Michael Hipp which can be found at - * ftp://sunsite.unc.edu/pub/Linux/system/Network/drivers/nidrivers.tar.gz - * - * Sources: 1) ni6510.c by M. Hipp - * 2) depca.c by D.C. Davies - * 3) skeleton.c by D. Becker - * 4) Am7990 Local Area Network Controller for Ethernet (LANCE), - * AMD, Pub. #05698, June 1989 - * - * Many Thanks for helping me to get things working to: - * - * A. Cox (A.Cox@swansea.ac.uk) - * M. Hipp (mhipp@student.uni-tuebingen.de) - * R. Bolz (Schneider & Koch, Germany) - * - * To Do: - * - Support of SK_G8 and other SK Network Cards. - * - Autoset memory mapped RAM. Check for free memory and then - * configure RAM correctly. - * - SK_close should really set card in to initial state. - * - Test if IRQ 3 is not switched off. Use autoirq() functionality. - * (as in /drivers/net/skeleton.c) - * - Implement Multicast addressing. At minimum something like - * in depca.c. - * - Redo the statistics part. - * - Try to find out if the board is in 8 Bit or 16 Bit slot. - * If in 8 Bit mode don't use IRQ 11. - * - (Try to make it slightly faster.) - * - Power management support - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fcntl.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/io.h> - -#include "sk_g16.h" - -/* - * Schneider & Koch Card Definitions - * ================================= - */ - -#define SK_NAME "SK_G16" - -/* - * SK_G16 Configuration - * -------------------- - */ - -/* - * Abbreviations - * ------------- - * - * RAM - used for the 16KB shared memory - * Boot_ROM, ROM - are used for referencing the BootEPROM - * - * SK_BOOT_ROM and SK_ADDR are symbolic constants used to configure - * the behaviour of the driver and the SK_G16. - * - * ! See sk_g16.install on how to install and configure the driver ! - * - * SK_BOOT_ROM defines if the Boot_ROM should be switched off or not. - * - * SK_ADDR defines the address where the RAM will be mapped into the real - * host memory. - * valid addresses are from 0xa0000 to 0xfc000 in 16Kbyte steps. - */ - -#define SK_BOOT_ROM 1 /* 1=BootROM on 0=off */ - -#define SK_ADDR 0xcc000 - -/* - * In POS3 are bits A14-A19 of the address bus. These bits can be set - * to choose the RAM address. That's why we only can choose the RAM address - * in 16KB steps. - */ - -#define POS_ADDR (rom_addr>>14) /* Do not change this line */ - -/* - * SK_G16 I/O PORT's + IRQ's + Boot_ROM locations - * ---------------------------------------------- - */ - -/* - * As nearly every card has also SK_G16 a specified I/O Port region and - * only a few possible IRQ's. - * In the Installation Guide from Schneider & Koch is listed a possible - * Interrupt IRQ2. IRQ2 is always IRQ9 in boards with two cascaded interrupt - * controllers. So we use in SK_IRQS IRQ9. - */ - -/* Don't touch any of the following #defines. */ - -#define SK_IO_PORTS { 0x100, 0x180, 0x208, 0x220, 0x288, 0x320, 0x328, 0x390, 0 } - -#define SK_IRQS { 3, 5, 9, 11, 0 } - -#define SK_BOOT_ROM_LOCATIONS { 0xc0000, 0xc4000, 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xdc000, 0 } - -#define SK_BOOT_ROM_ID { 0x55, 0xaa, 0x10, 0x50, 0x06, 0x33 } - -/* - * SK_G16 POS REGISTERS - * -------------------- - */ - -/* - * SK_G16 has a Programmable Option Select (POS) Register. - * The POS is composed of 8 separate registers (POS0-7) which - * are I/O mapped on an address set by the W1 switch. - * - */ - -#define SK_POS_SIZE 8 /* 8 I/O Ports are used by SK_G16 */ - -#define SK_POS0 ioaddr /* Card-ID Low (R) */ -#define SK_POS1 ioaddr+1 /* Card-ID High (R) */ -#define SK_POS2 ioaddr+2 /* Card-Enable, Boot-ROM Disable (RW) */ -#define SK_POS3 ioaddr+3 /* Base address of RAM */ -#define SK_POS4 ioaddr+4 /* IRQ */ - -/* POS5 - POS7 are unused */ - -/* - * SK_G16 MAC PREFIX - * ----------------- - */ - -/* - * Scheider & Koch manufacturer code (00:00:a5). - * This must be checked, that we are sure it is a SK card. - */ - -#define SK_MAC0 0x00 -#define SK_MAC1 0x00 -#define SK_MAC2 0x5a - -/* - * SK_G16 ID - * --------- - */ - -/* - * If POS0,POS1 contain the following ID, then we know - * at which I/O Port Address we are. - */ - -#define SK_IDLOW 0xfd -#define SK_IDHIGH 0x6a - - -/* - * LANCE POS Bit definitions - * ------------------------- - */ - -#define SK_ROM_RAM_ON (POS2_CARD) -#define SK_ROM_RAM_OFF (POS2_EPROM) -#define SK_ROM_ON (inb(SK_POS2) & POS2_CARD) -#define SK_ROM_OFF (inb(SK_POS2) | POS2_EPROM) -#define SK_RAM_ON (inb(SK_POS2) | POS2_CARD) -#define SK_RAM_OFF (inb(SK_POS2) & POS2_EPROM) - -#define POS2_CARD 0x0001 /* 1 = SK_G16 on 0 = off */ -#define POS2_EPROM 0x0002 /* 1 = Boot EPROM off 0 = on */ - -/* - * SK_G16 Memory mapped Registers - * ------------------------------ - * - */ - -#define SK_IOREG (&board->ioreg) /* LANCE data registers. */ -#define SK_PORT (&board->port) /* Control, Status register */ -#define SK_IOCOM (&board->iocom) /* I/O Command */ - -/* - * SK_G16 Status/Control Register bits - * ----------------------------------- - * - * (C) Controlreg (S) Statusreg - */ - -/* - * Register transfer: 0 = no transfer - * 1 = transferring data between LANCE and I/O reg - */ -#define SK_IORUN 0x20 - -/* - * LANCE interrupt: 0 = LANCE interrupt occurred - * 1 = no LANCE interrupt occurred - */ -#define SK_IRQ 0x10 - -#define SK_RESET 0x08 /* Reset SK_CARD: 0 = RESET 1 = normal */ -#define SK_RW 0x02 /* 0 = write to 1 = read from */ -#define SK_ADR 0x01 /* 0 = REG DataPort 1 = RAP Reg addr port */ - - -#define SK_RREG SK_RW /* Transferdirection to read from lance */ -#define SK_WREG 0 /* Transferdirection to write to lance */ -#define SK_RAP SK_ADR /* Destination Register RAP */ -#define SK_RDATA 0 /* Destination Register REG DataPort */ - -/* - * SK_G16 I/O Command - * ------------------ - */ - -/* - * Any bitcombination sets the internal I/O bit (transfer will start) - * when written to I/O Command - */ - -#define SK_DOIO 0x80 /* Do Transfer */ - -/* - * LANCE RAP (Register Address Port). - * --------------------------------- - */ - -/* - * The LANCE internal registers are selected through the RAP. - * The Registers are: - * - * CSR0 - Status and Control flags - * CSR1 - Low order bits of initialize block (bits 15:00) - * CSR2 - High order bits of initialize block (bits 07:00, 15:08 are reserved) - * CSR3 - Allows redefinition of the Bus Master Interface. - * This register must be set to 0x0002, which means BSWAP = 0, - * ACON = 1, BCON = 0; - * - */ - -#define CSR0 0x00 -#define CSR1 0x01 -#define CSR2 0x02 -#define CSR3 0x03 - -/* - * General Definitions - * =================== - */ - -/* - * Set the number of Tx and Rx buffers, using Log_2(# buffers). - * We have 16KB RAM which can be accessed by the LANCE. In the - * memory are not only the buffers but also the ring descriptors and - * the initialize block. - * Don't change anything unless you really know what you do. - */ - -#define LC_LOG_TX_BUFFERS 1 /* (2 == 2^^1) 2 Transmit buffers */ -#define LC_LOG_RX_BUFFERS 3 /* (8 == 2^^3) 8 Receive buffers */ - -/* Descriptor ring sizes */ - -#define TMDNUM (1 << (LC_LOG_TX_BUFFERS)) /* 2 Transmit descriptor rings */ -#define RMDNUM (1 << (LC_LOG_RX_BUFFERS)) /* 8 Receive Buffers */ - -/* Define Mask for setting RMD, TMD length in the LANCE init_block */ - -#define TMDNUMMASK (LC_LOG_TX_BUFFERS << 29) -#define RMDNUMMASK (LC_LOG_RX_BUFFERS << 29) - -/* - * Data Buffer size is set to maximum packet length. - */ - -#define PKT_BUF_SZ 1518 - -/* - * The number of low I/O ports used by the ethercard. - */ - -#define ETHERCARD_TOTAL_SIZE SK_POS_SIZE - -/* - * SK_DEBUG - * - * Here you can choose what level of debugging wanted. - * - * If SK_DEBUG and SK_DEBUG2 are undefined, then only the - * necessary messages will be printed. - * - * If SK_DEBUG is defined, there will be many debugging prints - * which can help to find some mistakes in configuration or even - * in the driver code. - * - * If SK_DEBUG2 is defined, many many messages will be printed - * which normally you don't need. I used this to check the interrupt - * routine. - * - * (If you define only SK_DEBUG2 then only the messages for - * checking interrupts will be printed!) - * - * Normal way of live is: - * - * For the whole thing get going let both symbolic constants - * undefined. If you face any problems and you know what's going - * on (you know something about the card and you can interpret some - * hex LANCE register output) then define SK_DEBUG - * - */ - -#undef SK_DEBUG /* debugging */ -#undef SK_DEBUG2 /* debugging with more verbose report */ - -#ifdef SK_DEBUG -#define PRINTK(x) printk x -#else -#define PRINTK(x) /**/ -#endif - -#ifdef SK_DEBUG2 -#define PRINTK2(x) printk x -#else -#define PRINTK2(x) /**/ -#endif - -/* - * SK_G16 RAM - * - * The components are memory mapped and can be set in a region from - * 0x00000 through 0xfc000 in 16KB steps. - * - * The Network components are: dual ported RAM, Prom, I/O Reg, Status-, - * Controlregister and I/O Command. - * - * dual ported RAM: This is the only memory region which the LANCE chip - * has access to. From the Lance it is addressed from 0x0000 to - * 0x3fbf. The host accesses it normally. - * - * PROM: The PROM obtains the ETHERNET-MAC-Address. It is realised as a - * 8-Bit PROM, this means only the 16 even addresses are used of the - * 32 Byte Address region. Access to an odd address results in invalid - * data. - * - * LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write, - * Hi-Byte Write, Low-Byte Read, Hi-Byte Read. - * Transfer from or to the LANCE is always in 16Bit so Low and High - * registers are always relevant. - * - * The Data from the Readregister is not the data in the Writeregister!! - * - * Port: Status- and Controlregister. - * Two different registers which share the same address, Status is - * read-only, Control is write-only. - * - * I/O Command: - * Any bitcombination written in here starts the transmission between - * Host and LANCE. - */ - -typedef struct -{ - unsigned char ram[0x3fc0]; /* 16KB dual ported ram */ - unsigned char rom[0x0020]; /* 32Byte PROM containing 6Byte MAC */ - unsigned char res1[0x0010]; /* reserved */ - unsigned volatile short ioreg;/* LANCE I/O Register */ - unsigned volatile char port; /* Statusregister and Controlregister */ - unsigned char iocom; /* I/O Command Register */ -} SK_RAM; - -/* struct */ - -/* - * This is the structure for the dual ported ram. We - * have exactly 16 320 Bytes. In here there must be: - * - * - Initialize Block (starting at a word boundary) - * - Receive and Transmit Descriptor Rings (quadword boundary) - * - Data Buffers (arbitrary boundary) - * - * This is because LANCE has on SK_G16 only access to the dual ported - * RAM and nowhere else. - */ - -struct SK_ram -{ - struct init_block ib; - struct tmd tmde[TMDNUM]; - struct rmd rmde[RMDNUM]; - char tmdbuf[TMDNUM][PKT_BUF_SZ]; - char rmdbuf[RMDNUM][PKT_BUF_SZ]; -}; - -/* - * Structure where all necessary information is for ring buffer - * management and statistics. - */ - -struct priv -{ - struct SK_ram *ram; /* dual ported ram structure */ - struct rmd *rmdhead; /* start of receive ring descriptors */ - struct tmd *tmdhead; /* start of transmit ring descriptors */ - int rmdnum; /* actual used ring descriptor */ - int tmdnum; /* actual transmit descriptor for transmitting data */ - int tmdlast; /* last sent descriptor used for error handling, etc */ - void *rmdbufs[RMDNUM]; /* pointer to the receive buffers */ - void *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */ - struct net_device_stats stats; /* Device driver statistics */ -}; - -/* global variable declaration */ - -/* IRQ map used to reserve a IRQ (see SK_open()) */ - -/* static variables */ - -static SK_RAM *board; /* pointer to our memory mapped board components */ -static DEFINE_SPINLOCK(SK_lock); - -/* Macros */ - - -/* Function Prototypes */ - -/* - * Device Driver functions - * ----------------------- - * See for short explanation of each function its definitions header. - */ - -static int SK_probe(struct net_device *dev, short ioaddr); - -static void SK_timeout(struct net_device *dev); -static int SK_open(struct net_device *dev); -static int SK_send_packet(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void SK_rxintr(struct net_device *dev); -static void SK_txintr(struct net_device *dev); -static int SK_close(struct net_device *dev); - -static struct net_device_stats *SK_get_stats(struct net_device *dev); - -unsigned int SK_rom_addr(void); - -static void set_multicast_list(struct net_device *dev); - -/* - * LANCE Functions - * --------------- - */ - -static int SK_lance_init(struct net_device *dev, unsigned short mode); -void SK_reset_board(void); -void SK_set_RAP(int reg_number); -int SK_read_reg(int reg_number); -int SK_rread_reg(void); -void SK_write_reg(int reg_number, int value); - -/* - * Debugging functions - * ------------------- - */ - -void SK_print_pos(struct net_device *dev, char *text); -void SK_print_dev(struct net_device *dev, char *text); -void SK_print_ram(struct net_device *dev); - - -/*- - * Function : SK_init - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Check for a SK_G16 network adaptor and initialize it. - * This function gets called by dev_init which initializes - * all Network devices. - * - * Parameters : I : struct net_device *dev - structure preconfigured - * from Space.c - * Return Value : 0 = Driver Found and initialized - * Errors : ENODEV - no device found - * ENXIO - not probed - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -static int io; /* 0 == probe */ - -/* - * Check for a network adaptor of this type, and return '0' if one exists. - * If dev->base_addr == 0, probe all likely locations. - * If dev->base_addr == 1, always return failure. - */ - -struct net_device * __init SK_init(int unit) -{ - int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ - static unsigned version_printed; - struct net_device *dev = alloc_etherdev(sizeof(struct priv)); - int err = -ENODEV; - - if (!dev) - return ERR_PTR(-ENOMEM); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - io = dev->base_addr; - } - - if (version_printed++ == 0) - PRINTK(("%s: %s", SK_NAME, rcsid)); - - if (io > 0xff) { /* Check a single specified address */ - err = -EBUSY; - /* Check if on specified address is a SK_G16 */ - if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) { - err = SK_probe(dev, io); - if (!err) - goto got_it; - release_region(io, ETHERCARD_TOTAL_SIZE); - } - } else if (io > 0) { /* Don't probe at all */ - err = -ENXIO; - } else { - /* Autoprobe base_addr */ - for (port = &ports[0]; *port; port++) { - io = *port; - - /* Check if I/O Port region is used by another board */ - if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) - continue; /* Try next Port address */ - - /* Check if at ioaddr is a SK_G16 */ - if (SK_probe(dev, io) == 0) - goto got_it; - - release_region(io, ETHERCARD_TOTAL_SIZE); - } - } -err_out: - free_netdev(dev); - return ERR_PTR(err); - -got_it: - err = register_netdev(dev); - if (err) { - release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE); - goto err_out; - } - return dev; - -} /* End of SK_init */ - - -MODULE_AUTHOR("Patrick J.D. Weichmann"); -MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board"); - - -#ifdef MODULE - -static struct net_device *SK_dev; - -static int __init SK_init_module (void) -{ - SK_dev = SK_init(-1); - return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0; -} - -static void __exit SK_cleanup_module (void) -{ - unregister_netdev(SK_dev); - release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE); - free_netdev(SK_dev); -} - -module_init(SK_init_module); -module_exit(SK_cleanup_module); -#endif - - -/*- - * Function : SK_probe - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function is called by SK_init and - * does the main part of initialization. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * I : short ioaddr - I/O Port address where POS is. - * Return Value : 0 = Initialization done - * Errors : ENODEV - No SK_G16 found - * -1 - Configuration problem - * Globals : board - pointer to SK_RAM - * Update History : - * YY/MM/DD uid Description - * 94/06/30 pwe SK_ADDR now checked and at the correct place --*/ - -int __init SK_probe(struct net_device *dev, short ioaddr) -{ - int i,j; /* Counters */ - int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ - unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */ - - struct priv *p = netdev_priv(dev); /* SK_G16 private structure */ - - if (inb(SK_POS0) != SK_IDLOW || inb(SK_POS1) != SK_IDHIGH) - return -ENODEV; - dev->base_addr = ioaddr; - - if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000) - { - - sk_addr_flag = 1; - - /* - * Now here we could use a routine which searches for a free - * place in the ram and set SK_ADDR if found. TODO. - */ - } - - if (SK_BOOT_ROM) /* Shall we keep Boot_ROM on ? */ - { - PRINTK(("## %s: SK_BOOT_ROM is set.\n", SK_NAME)); - - rom_addr = SK_rom_addr(); - - if (rom_addr == 0) /* No Boot_ROM found */ - { - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; /* assign predefined address */ - - PRINTK(("## %s: NO Bootrom found \n", SK_NAME)); - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - else if (rom_addr == SK_ADDR) - { - printk("%s: RAM + ROM are set to the same address %#08x\n" - " Check configuration. Now switching off Boot_ROM\n", - SK_NAME, rom_addr); - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off*/ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - else - { - PRINTK(("## %s: Found ROM at %#08x\n", SK_NAME, rom_addr)); - PRINTK(("## %s: Keeping Boot_ROM on\n", SK_NAME)); - - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_ROM_RAM_ON, SK_POS2); /* RAM on, BOOT_ROM on */ - } - } - else /* Don't keep Boot_ROM */ - { - PRINTK(("## %s: SK_BOOT_ROM is not set.\n", SK_NAME)); - - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_rom_addr(); /* Try to find a Boot_ROM */ - - /* IF we find a Boot_ROM disable it */ - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - - /* We found a Boot_ROM and it's gone. Set RAM address on - * Boot_ROM address. - */ - - if (rom_addr) - { - printk("%s: We found Boot_ROM at %#08x. Now setting RAM on" - "that address\n", SK_NAME, rom_addr); - - outb(POS_ADDR, SK_POS3); /* Set RAM on Boot_ROM address */ - } - else /* We did not find a Boot_ROM, use predefined SK_ADDR for ram */ - { - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; - - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - } - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - -#ifdef SK_DEBUG - SK_print_pos(dev, "POS registers after ROM, RAM config"); -#endif - - board = (SK_RAM *) isa_bus_to_virt(rom_addr); - - /* Read in station address */ - for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2) - { - dev->dev_addr[i] = readb(board->rom+j); - } - - /* Check for manufacturer code */ - if (!(dev->dev_addr[0] == SK_MAC0 && - dev->dev_addr[1] == SK_MAC1 && - dev->dev_addr[2] == SK_MAC2) ) - { - PRINTK(("## %s: We did not find SK_G16 at RAM location.\n", - SK_NAME)); - return -ENODEV; /* NO SK_G16 found */ - } - - printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, - "Schneider & Koch Netcard", - (unsigned int) dev->base_addr, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); - - memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ - - /* Assign our Device Driver functions */ - - dev->open = SK_open; - dev->stop = SK_close; - dev->hard_start_xmit = SK_send_packet; - dev->get_stats = SK_get_stats; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = SK_timeout; - dev->watchdog_timeo = HZ/7; - - - dev->flags &= ~IFF_MULTICAST; - - /* Initialize private structure */ - - p->ram = (struct SK_ram *) rom_addr; /* Set dual ported RAM addr */ - p->tmdhead = &(p->ram)->tmde[0]; /* Set TMD head */ - p->rmdhead = &(p->ram)->rmde[0]; /* Set RMD head */ - - /* Initialize buffer pointers */ - - for (i = 0; i < TMDNUM; i++) - { - p->tmdbufs[i] = &(p->ram)->tmdbuf[i]; - } - - for (i = 0; i < RMDNUM; i++) - { - p->rmdbufs[i] = &(p->ram)->rmdbuf[i]; - } - -#ifdef SK_DEBUG - SK_print_pos(dev, "End of SK_probe"); - SK_print_ram(dev); -#endif - return 0; /* Initialization done */ -} /* End of SK_probe() */ - - -/*- - * Function : SK_open - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function is called sometimes after booting - * when ifconfig program is run. - * - * This function requests an IRQ, sets the correct - * IRQ in the card. Then calls SK_lance_init() to - * init and start the LANCE chip. Then if everything is - * ok returns with 0 (OK), which means SK_G16 is now - * opened and operational. - * - * (Called by dev_open() /net/inet/dev.c) - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * Return Value : 0 - Device opened - * Errors : -EAGAIN - Open failed - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static int SK_open(struct net_device *dev) -{ - int i = 0; - int irqval = 0; - int ioaddr = dev->base_addr; - - int irqtab[] = SK_IRQS; - - struct priv *p = netdev_priv(dev); - - PRINTK(("## %s: At beginning of SK_open(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - if (dev->irq == 0) /* Autoirq */ - { - i = 0; - - /* - * Check if one IRQ out of SK_IRQS is free and install - * interrupt handler. - * Most done by request_irq(). - * irqval: 0 - interrupt handler installed for IRQ irqtab[i] - * -EBUSY - interrupt busy - * -EINVAL - irq > 15 or handler = NULL - */ - - do - { - irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16", dev); - i++; - } while (irqval && irqtab[i]); - - if (irqval) /* We tried every possible IRQ but no success */ - { - printk("%s: unable to get an IRQ\n", dev->name); - return -EAGAIN; - } - - dev->irq = irqtab[--i]; - - outb(i<<2, SK_POS4); /* Set Card on probed IRQ */ - - } - else if (dev->irq == 2) /* IRQ2 is always IRQ9 */ - { - if (request_irq(9, &SK_interrupt, 0, "sk_g16", dev)) - { - printk("%s: unable to get IRQ 9\n", dev->name); - return -EAGAIN; - } - dev->irq = 9; - - /* - * Now we set card on IRQ2. - * This can be confusing, but remember that IRQ2 on the network - * card is in reality IRQ9 - */ - outb(0x08, SK_POS4); /* set card to IRQ2 */ - - } - else /* Check IRQ as defined in Space.c */ - { - int i = 0; - - /* check if IRQ free and valid. Then install Interrupt handler */ - - if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16", dev)) - { - printk("%s: unable to get selected IRQ\n", dev->name); - return -EAGAIN; - } - - switch(dev->irq) - { - case 3: i = 0; - break; - case 5: i = 1; - break; - case 2: i = 2; - break; - case 11:i = 3; - break; - default: - printk("%s: Preselected IRQ %d is invalid for %s boards", - dev->name, - dev->irq, - SK_NAME); - return -EAGAIN; - } - - outb(i<<2, SK_POS4); /* Set IRQ on card */ - } - - printk("%s: Schneider & Koch G16 at %#3x, IRQ %d, shared mem at %#08x\n", - dev->name, (unsigned int)dev->base_addr, - (int) dev->irq, (unsigned int) p->ram); - - if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */ - { - netif_start_queue(dev); - -#ifdef SK_DEBUG - - /* - * This debug block tries to stop LANCE, - * reinit LANCE with transmitter and receiver disabled, - * then stop again and reinit with NORMAL_MODE - */ - - printk("## %s: After lance init. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_write_reg(CSR0, CSR0_STOP); - printk("## %s: LANCE stopped. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_lance_init(dev, MODE_DTX | MODE_DRX); - printk("## %s: Reinit with DTX + DRX off. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_write_reg(CSR0, CSR0_STOP); - printk("## %s: LANCE stopped. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_lance_init(dev, MODE_NORMAL); - printk("## %s: LANCE back to normal mode. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_print_pos(dev, "POS regs before returning OK"); - -#endif /* SK_DEBUG */ - - return 0; /* SK_open() is successful */ - } - else /* LANCE init failed */ - { - - PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - return -EAGAIN; - } - -} /* End of SK_open() */ - - -/*- - * Function : SK_lance_init - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Reset LANCE chip, fill RMD, TMD structures with - * start values and Start LANCE. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * I : int mode - put LANCE into "mode" see data-sheet for - * more info. - * Return Value : 0 - Init done - * Errors : -1 - Init failed - * Update History : - * YY/MM/DD uid Description --*/ - -static int SK_lance_init(struct net_device *dev, unsigned short mode) -{ - int i; - unsigned long flags; - struct priv *p = netdev_priv(dev); - struct tmd *tmdp; - struct rmd *rmdp; - - PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - /* Reset LANCE */ - SK_reset_board(); - - /* Initialize TMD's with start values */ - p->tmdnum = 0; /* First descriptor for transmitting */ - p->tmdlast = 0; /* First descriptor for reading stats */ - - for (i = 0; i < TMDNUM; i++) /* Init all TMD's */ - { - tmdp = p->tmdhead + i; - - writel((unsigned long) p->tmdbufs[i], tmdp->u.buffer); /* assign buffer */ - - /* Mark TMD as start and end of packet */ - writeb(TX_STP | TX_ENP, &tmdp->u.s.status); - } - - - /* Initialize RMD's with start values */ - - p->rmdnum = 0; /* First RMD which will be used */ - - for (i = 0; i < RMDNUM; i++) /* Init all RMD's */ - { - rmdp = p->rmdhead + i; - - - writel((unsigned long) p->rmdbufs[i], rmdp->u.buffer); /* assign buffer */ - - /* - * LANCE must be owner at beginning so that he can fill in - * receiving packets, set status and release RMD - */ - - writeb(RX_OWN, &rmdp->u.s.status); - - writew(-PKT_BUF_SZ, &rmdp->blen); /* Buffer Size (two's complement) */ - - writeb(0, &rmdp->mlen); /* init message length */ - - } - - /* Fill LANCE Initialize Block */ - - writew(mode, (&((p->ram)->ib.mode))); /* Set operation mode */ - - for (i = 0; i < ETH_ALEN; i++) /* Set physical address */ - { - writeb(dev->dev_addr[i], (&((p->ram)->ib.paddr[i]))); - } - - for (i = 0; i < 8; i++) /* Set multicast, logical address */ - { - writeb(0, (&((p->ram)->ib.laddr[i]))); /* We do not use logical addressing */ - } - - /* Set ring descriptor pointers and set number of descriptors */ - - writel((int)p->rmdhead | RMDNUMMASK, (&((p->ram)->ib.rdrp))); - writel((int)p->tmdhead | TMDNUMMASK, (&((p->ram)->ib.tdrp))); - - /* Prepare LANCE Control and Status Registers */ - - spin_lock_irqsave(&SK_lock, flags); - - SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */ - - /* - * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to - * PC Memory locations. - * - * In structure SK_ram is defined that the first thing in ram - * is the initialization block. So his address is for LANCE always - * 0x0000 - * - * CSR1 contains low order bits 15:0 of initialization block address - * CSR2 is built of: - * 7:0 High order bits 23:16 of initialization block address - * 15:8 reserved, must be 0 - */ - - /* Set initialization block address (must be on word boundary) */ - SK_write_reg(CSR1, 0); /* Set low order bits 15:0 */ - SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */ - - - PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - /* Initialize LANCE */ - - /* - * INIT = Initialize, when set, causes the LANCE to begin the - * initialization procedure and access the Init Block. - */ - - SK_write_reg(CSR0, CSR0_INIT); - - spin_unlock_irqrestore(&SK_lock, flags); - - /* Wait until LANCE finished initialization */ - - SK_set_RAP(CSR0); /* Register Address Pointer to CSR0 */ - - for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++) - ; /* Wait until init done or go ahead if problems (i>=100) */ - - if (i >= 100) /* Something is wrong ! */ - { - printk("%s: can't init am7990, status: %04x " - "init_block: %#08x\n", - dev->name, (int) SK_read_reg(CSR0), - (unsigned int) &(p->ram)->ib); - -#ifdef SK_DEBUG - SK_print_pos(dev, "LANCE INIT failed"); - SK_print_dev(dev,"Device Structure:"); -#endif - - return -1; /* LANCE init failed */ - } - - PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i)); - - /* Clear Initialize done, enable Interrupts, start LANCE */ - - SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT); - - PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME, - SK_read_reg(CSR0))); - - return 0; /* LANCE is up and running */ - -} /* End of SK_lance_init() */ - - - -/*- - * Function : SK_send_packet - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : Writes an socket buffer into a transmit descriptor - * and starts transmission. - * - * Parameters : I : struct sk_buff *skb - packet to transfer - * I : struct net_device *dev - SK_G16 device structure - * Return Value : 0 - OK - * 1 - Could not transmit (dev_queue_xmit will queue it) - * and try to sent it later - * Globals : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_timeout(struct net_device *dev) -{ - printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name); - SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */ - netif_wake_queue(dev); /* Clear Transmitter flag */ - dev->trans_start = jiffies; /* Mark Start of transmission */ -} - -static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - struct tmd *tmdp; - static char pad[64]; - - PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", - SK_NAME, SK_read_reg(CSR0))); - - - /* - * Block a timer-based transmit from overlapping. - * This means check if we are already in. - */ - - netif_stop_queue (dev); - - { - - /* Evaluate Packet length */ - short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */ - - /* Fill in Transmit Message Descriptor */ - - /* Copy data into dual ported ram */ - - memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len); - if (len != skb->len) - memcpy_toio((tmdp->u.buffer & 0x00ffffff) + skb->len, pad, len-skb->len); - - writew(-len, &tmdp->blen); /* set length to transmit */ - - /* - * Packet start and end is always set because we use the maximum - * packet length as buffer length. - * Relinquish ownership to LANCE - */ - - writeb(TX_OWN | TX_STP | TX_ENP, &tmdp->u.s.status); - - /* Start Demand Transmission */ - SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA); - - dev->trans_start = jiffies; /* Mark start of transmission */ - - /* Set pointer to next transmit buffer */ - p->tmdnum++; - p->tmdnum &= TMDNUM-1; - - /* Do we own the next transmit buffer ? */ - if (! (readb(&((p->tmdhead + p->tmdnum)->u.s.status)) & TX_OWN) ) - { - /* - * We own next buffer and are ready to transmit, so - * clear busy flag - */ - netif_start_queue(dev); - } - - p->stats.tx_bytes += skb->len; - - } - - dev_kfree_skb(skb); - return 0; -} /* End of SK_send_packet */ - - -/*- - * Function : SK_interrupt - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : SK_G16 interrupt handler which checks for LANCE - * Errors, handles transmit and receive interrupts - * - * Parameters : I : int irq, void *dev_id, struct pt_regs * regs - - * Return Value : None - * Errors : None - * Globals : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - int csr0; - struct net_device *dev = dev_id; - struct priv *p = netdev_priv(dev); - - - PRINTK2(("## %s: SK_interrupt(). status: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - if (dev == NULL) - { - printk("SK_interrupt(): IRQ %d for unknown device.\n", irq); - } - - spin_lock (&SK_lock); - - csr0 = SK_read_reg(CSR0); /* store register for checking */ - - /* - * Acknowledge all of the current interrupt sources, disable - * Interrupts (INEA = 0) - */ - - SK_write_reg(CSR0, csr0 & CSR0_CLRALL); - - if (csr0 & CSR0_ERR) /* LANCE Error */ - { - printk("%s: error: %04x\n", dev->name, csr0); - - if (csr0 & CSR0_MISS) /* No place to store packet ? */ - { - p->stats.rx_dropped++; - } - } - - if (csr0 & CSR0_RINT) /* Receive Interrupt (packet arrived) */ - { - SK_rxintr(dev); - } - - if (csr0 & CSR0_TINT) /* Transmit interrupt (packet sent) */ - { - SK_txintr(dev); - } - - SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ - - spin_unlock (&SK_lock); - return IRQ_HANDLED; -} /* End of SK_interrupt() */ - - -/*- - * Function : SK_txintr - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : After sending a packet we check status, update - * statistics and relinquish ownership of transmit - * descriptor ring. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_txintr(struct net_device *dev) -{ - int tmdstat; - struct tmd *tmdp; - struct priv *p = netdev_priv(dev); - - - PRINTK2(("## %s: SK_txintr() status: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - tmdp = p->tmdhead + p->tmdlast; /* Which buffer we sent at last ? */ - - /* Set next buffer */ - p->tmdlast++; - p->tmdlast &= TMDNUM-1; - - tmdstat = readb(&tmdp->u.s.status); - - /* - * We check status of transmitted packet. - * see LANCE data-sheet for error explanation - */ - if (tmdstat & TX_ERR) /* Error occurred */ - { - int stat2 = readw(&tmdp->status2); - - printk("%s: TX error: %04x %04x\n", dev->name, tmdstat, stat2); - - if (stat2 & TX_TDR) /* TDR problems? */ - { - printk("%s: tdr-problems \n", dev->name); - } - - if (stat2 & TX_RTRY) /* Failed in 16 attempts to transmit ? */ - p->stats.tx_aborted_errors++; - if (stat2 & TX_LCOL) /* Late collision ? */ - p->stats.tx_window_errors++; - if (stat2 & TX_LCAR) /* Loss of Carrier ? */ - p->stats.tx_carrier_errors++; - if (stat2 & TX_UFLO) /* Underflow error ? */ - { - p->stats.tx_fifo_errors++; - - /* - * If UFLO error occurs it will turn transmitter of. - * So we must reinit LANCE - */ - - SK_lance_init(dev, MODE_NORMAL); - } - - p->stats.tx_errors++; - - writew(0, &tmdp->status2); /* Clear error flags */ - } - else if (tmdstat & TX_MORE) /* Collisions occurred ? */ - { - /* - * Here I have a problem. - * I only know that there must be one or up to 15 collisions. - * That's why TX_MORE is set, because after 16 attempts TX_RTRY - * will be set which means couldn't send packet aborted transfer. - * - * First I did not have this in but then I thought at minimum - * we see that something was not ok. - * If anyone knows something better than this to handle this - * please report it. - */ - - p->stats.collisions++; - } - else /* Packet sent without any problems */ - { - p->stats.tx_packets++; - } - - /* - * We mark transmitter not busy anymore, because now we have a free - * transmit descriptor which can be filled by SK_send_packet and - * afterwards sent by the LANCE - * - * The function which do handle slow IRQ parts is do_bottom_half() - * which runs at normal kernel priority, that means all interrupt are - * enabled. (see kernel/irq.c) - * - * net_bh does something like this: - * - check if already in net_bh - * - try to transmit something from the send queue - * - if something is in the receive queue send it up to higher - * levels if it is a known protocol - * - try to transmit something from the send queue - */ - - netif_wake_queue(dev); - -} /* End of SK_txintr() */ - - -/*- - * Function : SK_rxintr - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : Buffer sent, check for errors, relinquish ownership - * of the receive message descriptor. - * - * Parameters : I : SK_G16 device structure - * Return Value : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_rxintr(struct net_device *dev) -{ - - struct rmd *rmdp; - int rmdstat; - struct priv *p = netdev_priv(dev); - - PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - rmdp = p->rmdhead + p->rmdnum; - - /* As long as we own the next entry, check status and send - * it up to higher layer - */ - - while (!( (rmdstat = readb(&rmdp->u.s.status)) & RX_OWN)) - { - /* - * Start and end of packet must be set, because we use - * the ethernet maximum packet length (1518) as buffer size. - * - * Because our buffers are at maximum OFLO and BUFF errors are - * not to be concerned (see Data sheet) - */ - - if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP)) - { - /* Start of a frame > 1518 Bytes ? */ - - if (rmdstat & RX_STP) - { - p->stats.rx_errors++; /* bad packet received */ - p->stats.rx_length_errors++; /* packet too long */ - - printk("%s: packet too long\n", dev->name); - } - - /* - * All other packets will be ignored until a new frame with - * start (RX_STP) set follows. - * - * What we do is just give descriptor free for new incoming - * packets. - */ - - writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */ - - } - else if (rmdstat & RX_ERR) /* Receive Error ? */ - { - printk("%s: RX error: %04x\n", dev->name, (int) rmdstat); - - p->stats.rx_errors++; - - if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++; - if (rmdstat & RX_CRC) p->stats.rx_crc_errors++; - - writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */ - - } - else /* We have a packet which can be queued for the upper layers */ - { - - int len = readw(&rmdp->mlen) & 0x0fff; /* extract message length from receive buffer */ - struct sk_buff *skb; - - skb = dev_alloc_skb(len+2); /* allocate socket buffer */ - - if (skb == NULL) /* Could not get mem ? */ - { - - /* - * Couldn't allocate sk_buffer so we give descriptor back - * to Lance, update statistics and go ahead. - */ - - writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */ - printk("%s: Couldn't allocate sk_buff, deferring packet.\n", - dev->name); - p->stats.rx_dropped++; - - break; /* Jump out */ - } - - /* Prepare sk_buff to queue for upper layers */ - - skb->dev = dev; - skb_reserve(skb,2); /* Align IP header on 16 byte boundary */ - - /* - * Copy data out of our receive descriptor into sk_buff. - * - * (rmdp->u.buffer & 0x00ffffff) -> get address of buffer and - * ignore status fields) - */ - - memcpy_fromio(skb_put(skb,len), (rmdp->u.buffer & 0x00ffffff), len); - - - /* - * Notify the upper protocol layers that there is another packet - * to handle - * - * netif_rx() always succeeds. see /net/inet/dev.c for more. - */ - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); /* queue packet and mark it for processing */ - - /* - * Packet is queued and marked for processing so we - * free our descriptor and update statistics - */ - - writeb(RX_OWN, &rmdp->u.s.status); - dev->last_rx = jiffies; - p->stats.rx_packets++; - p->stats.rx_bytes += len; - - - p->rmdnum++; - p->rmdnum %= RMDNUM; - - rmdp = p->rmdhead + p->rmdnum; - } - } -} /* End of SK_rxintr() */ - - -/*- - * Function : SK_close - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : close gets called from dev_close() and should - * deinstall the card (free_irq, mem etc). - * - * Parameters : I : struct net_device *dev - our device structure - * Return Value : 0 - closed device driver - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -/* I have tried to set BOOT_ROM on and RAM off but then, after a 'ifconfig - * down' the system stops. So I don't shut set card to init state. - */ - -static int SK_close(struct net_device *dev) -{ - - PRINTK(("## %s: SK_close(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - netif_stop_queue(dev); /* Transmitter busy */ - - printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME, - (int) SK_read_reg(CSR0)); - - SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */ - - free_irq(dev->irq, dev); /* Free IRQ */ - - return 0; /* always succeed */ - -} /* End of SK_close() */ - - -/*- - * Function : SK_get_stats - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Return current status structure to upper layers. - * It is called by sprintf_stats (dev.c). - * - * Parameters : I : struct net_device *dev - our device structure - * Return Value : struct net_device_stats * - our current statistics - * Errors : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static struct net_device_stats *SK_get_stats(struct net_device *dev) -{ - - struct priv *p = netdev_priv(dev); - - PRINTK(("## %s: SK_get_stats(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - return &p->stats; /* Return Device status */ - -} /* End of SK_get_stats() */ - - -/*- - * Function : set_multicast_list - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function gets called when a program performs - * a SIOCSIFFLAGS call. Ifconfig does this if you call - * 'ifconfig [-]allmulti' which enables or disables the - * Promiscuous mode. - * Promiscuous mode is when the Network card accepts all - * packets, not only the packets which match our MAC - * Address. It is useful for writing a network monitor, - * but it is also a security problem. You have to remember - * that all information on the net is not encrypted. - * - * Parameters : I : struct net_device *dev - SK_G16 device Structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description - * 95/10/18 ACox New multicast calling scheme --*/ - - -/* Set or clear the multicast filter for SK_G16. - */ - -static void set_multicast_list(struct net_device *dev) -{ - - if (dev->flags&IFF_PROMISC) - { - /* Reinitialize LANCE with MODE_PROM set */ - SK_lance_init(dev, MODE_PROM); - } - else if (dev->mc_count==0 && !(dev->flags&IFF_ALLMULTI)) - { - /* Reinitialize LANCE without MODE_PROM */ - SK_lance_init(dev, MODE_NORMAL); - } - else - { - /* Multicast with logical address filter on */ - /* Reinitialize LANCE without MODE_PROM */ - SK_lance_init(dev, MODE_NORMAL); - - /* Not implemented yet. */ - } -} /* End of set_multicast_list() */ - - - -/*- - * Function : SK_rom_addr - * Author : Patrick J.D. Weichmann - * Date Created : 94/06/01 - * - * Description : Try to find a Boot_ROM at all possible locations - * - * Parameters : None - * Return Value : Address where Boot_ROM is - * Errors : 0 - Did not find Boot_ROM - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -unsigned int __init SK_rom_addr(void) -{ - int i,j; - int rom_found = 0; - unsigned int rom_location[] = SK_BOOT_ROM_LOCATIONS; - unsigned char rom_id[] = SK_BOOT_ROM_ID; - unsigned char test_byte; - - /* Autodetect Boot_ROM */ - PRINTK(("## %s: Autodetection of Boot_ROM\n", SK_NAME)); - - for (i = 0; (rom_location[i] != 0) && (rom_found == 0); i++) - { - - PRINTK(("## Trying ROM location %#08x", rom_location[i])); - - rom_found = 1; - for (j = 0; j < 6; j++) - { - test_byte = readb(rom_location[i]+j); - PRINTK((" %02x ", *test_byte)); - - if(test_byte != rom_id[j]) - { - rom_found = 0; - } - } - PRINTK(("\n")); - } - - if (rom_found == 1) - { - PRINTK(("## %s: Boot_ROM found at %#08x\n", - SK_NAME, rom_location[(i-1)])); - - return (rom_location[--i]); - } - else - { - PRINTK(("%s: No Boot_ROM found\n", SK_NAME)); - return 0; - } -} /* End of SK_rom_addr() */ - - - -/* LANCE access functions - * - * ! CSR1-3 can only be accessed when in CSR0 the STOP bit is set ! - */ - - -/*- - * Function : SK_reset_board - * - * Author : Patrick J.D. Weichmann - * - * Date Created : 94/05/25 - * - * Description : This function resets SK_G16 and all components, but - * POS registers are not changed - * - * Parameters : None - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_reset_board(void) -{ - writeb(0x00, SK_PORT); /* Reset active */ - mdelay(5); /* Delay min 5ms */ - writeb(SK_RESET, SK_PORT); /* Set back to normal operation */ - -} /* End of SK_reset_board() */ - - -/*- - * Function : SK_set_RAP - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : Set LANCE Register Address Port to register - * for later data transfer. - * - * Parameters : I : reg_number - which CSR to read/write from/to - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_set_RAP(int reg_number) -{ - writew(reg_number, SK_IOREG); - writeb(SK_RESET | SK_RAP | SK_WREG, SK_PORT); - writeb(SK_DOIO, SK_IOCOM); - - while (readb(SK_PORT) & SK_IORUN) - barrier(); -} /* End of SK_set_RAP() */ - - -/*- - * Function : SK_read_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : Set RAP and read data from a LANCE CSR register - * - * Parameters : I : reg_number - which CSR to read from - * Return Value : Register contents - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -int SK_read_reg(int reg_number) -{ - SK_set_RAP(reg_number); - - writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT); - writeb(SK_DOIO, SK_IOCOM); - - while (readb(SK_PORT) & SK_IORUN) - barrier(); - return (readw(SK_IOREG)); - -} /* End of SK_read_reg() */ - - -/*- - * Function : SK_rread_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/28 - * - * Description : Read data from preseted register. - * This function requires that you know which - * Register is actually set. Be aware that CSR1-3 - * can only be accessed when in CSR0 STOP is set. - * - * Return Value : Register contents - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -int SK_rread_reg(void) -{ - writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT); - - writeb(SK_DOIO, SK_IOCOM); - - while (readb(SK_PORT) & SK_IORUN) - barrier(); - return (readw(SK_IOREG)); - -} /* End of SK_rread_reg() */ - - -/*- - * Function : SK_write_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function sets the RAP then fills in the - * LANCE I/O Reg and starts Transfer to LANCE. - * It waits until transfer has ended which is max. 7 ms - * and then it returns. - * - * Parameters : I : reg_number - which CSR to write to - * I : value - what value to fill into register - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_write_reg(int reg_number, int value) -{ - SK_set_RAP(reg_number); - - writew(value, SK_IOREG); - writeb(SK_RESET | SK_RDATA | SK_WREG, SK_PORT); - writeb(SK_DOIO, SK_IOCOM); - - while (readb(SK_PORT) & SK_IORUN) - barrier(); -} /* End of SK_write_reg */ - - - -/* - * Debugging functions - * ------------------- - */ - -/*- - * Function : SK_print_pos - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function prints out the 4 POS (Programmable - * Option Select) Registers. Used mainly to debug operation. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * I : char * - Text which will be printed as title - * Return Value : None - * Errors : None - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_print_pos(struct net_device *dev, char *text) -{ - int ioaddr = dev->base_addr; - - unsigned char pos0 = inb(SK_POS0), - pos1 = inb(SK_POS1), - pos2 = inb(SK_POS2), - pos3 = inb(SK_POS3), - pos4 = inb(SK_POS4); - - - printk("## %s: %s.\n" - "## pos0=%#4x pos1=%#4x pos2=%#04x pos3=%#08x pos4=%#04x\n", - SK_NAME, text, pos0, pos1, pos2, (pos3<<14), pos4); - -} /* End of SK_print_pos() */ - - - -/*- - * Function : SK_print_dev - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function simply prints out the important fields - * of the device structure. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * I : char *text - Title for printing - * Return Value : None - * Errors : None - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_print_dev(struct net_device *dev, char *text) -{ - if (dev == NULL) - { - printk("## %s: Device Structure. %s\n", SK_NAME, text); - printk("## DEVICE == NULL\n"); - } - else - { - printk("## %s: Device Structure. %s\n", SK_NAME, text); - printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", - dev->name, dev->base_addr, dev->irq); - - printk("## next device: %#08x init function: %#08x\n", - (int) dev->next, (int) dev->init); - } - -} /* End of SK_print_dev() */ - - - -/*- - * Function : SK_print_ram - * Author : Patrick J.D. Weichmann - * Date Created : 94/06/02 - * - * Description : This function is used to check how are things set up - * in the 16KB RAM. Also the pointers to the receive and - * transmit descriptor rings and rx and tx buffers locations. - * It contains a minor bug in printing, but has no effect to the values - * only newlines are not correct. - * - * Parameters : I : struct net_device *dev - SK_G16 device structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -void __init SK_print_ram(struct net_device *dev) -{ - - int i; - struct priv *p = netdev_priv(dev); - - printk("## %s: RAM Details.\n" - "## RAM at %#08x tmdhead: %#08x rmdhead: %#08x initblock: %#08x\n", - SK_NAME, - (unsigned int) p->ram, - (unsigned int) p->tmdhead, - (unsigned int) p->rmdhead, - (unsigned int) &(p->ram)->ib); - - printk("## "); - - for(i = 0; i < TMDNUM; i++) - { - if (!(i % 3)) /* Every third line do a newline */ - { - printk("\n## "); - } - printk("tmdbufs%d: %#08x ", (i+1), (int) p->tmdbufs[i]); - } - printk("## "); - - for(i = 0; i < RMDNUM; i++) - { - if (!(i % 3)) /* Every third line do a newline */ - { - printk("\n## "); - } - printk("rmdbufs%d: %#08x ", (i+1), (int) p->rmdbufs[i]); - } - printk("\n"); - -} /* End of SK_print_ram() */ - diff --git a/drivers/net/sk_g16.h b/drivers/net/sk_g16.h deleted file mode 100644 index 0a5dc0908a04..000000000000 --- a/drivers/net/sk_g16.h +++ /dev/null @@ -1,165 +0,0 @@ -/*- - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Module : sk_g16.h - * Version : $Revision$ - * - * Author : M.Hipp (mhipp@student.uni-tuebingen.de) - * changes by : Patrick J.D. Weichmann - * - * Date Created : 94/05/25 - * - * Description : In here are all necessary definitions of - * the am7990 (LANCE) chip used for writing a - * network device driver which uses this chip - * - * $Log$ --*/ - -#ifndef SK_G16_H - -#define SK_G16_H - - -/* - * Control and Status Register 0 (CSR0) bit definitions - * - * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write) - * - */ - -#define CSR0_ERR 0x8000 /* Error summary (R) */ -#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */ -#define CSR0_CERR 0x2000 /* Collision Error (RC) */ -#define CSR0_MISS 0x1000 /* Missed packet (RC) */ -#define CSR0_MERR 0x0800 /* Memory Error (RC) */ -#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */ -#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */ -#define CSR0_IDON 0x0100 /* Initialization Done (RC) */ -#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */ -#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */ -#define CSR0_RXON 0x0020 /* Receiver on (R) */ -#define CSR0_TXON 0x0010 /* Transmitter on (R) */ -#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */ -#define CSR0_STOP 0x0004 /* Stop (RS) */ -#define CSR0_STRT 0x0002 /* Start (RS) */ -#define CSR0_INIT 0x0001 /* Initialize (RS) */ - -#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */ - -/* - * Control and Status Register 3 (CSR3) bit definitions - * - */ - -#define CSR3_BSWAP 0x0004 /* Byte Swap (RW) */ -#define CSR3_ACON 0x0002 /* ALE Control (RW) */ -#define CSR3_BCON 0x0001 /* Byte Control (RW) */ - -/* - * Initialization Block Mode operation Bit Definitions. - */ - -#define MODE_PROM 0x8000 /* Promiscuous Mode */ -#define MODE_INTL 0x0040 /* Internal Loopback */ -#define MODE_DRTY 0x0020 /* Disable Retry */ -#define MODE_COLL 0x0010 /* Force Collision */ -#define MODE_DTCR 0x0008 /* Disable Transmit CRC) */ -#define MODE_LOOP 0x0004 /* Loopback */ -#define MODE_DTX 0x0002 /* Disable the Transmitter */ -#define MODE_DRX 0x0001 /* Disable the Receiver */ - -#define MODE_NORMAL 0x0000 /* Normal operation mode */ - -/* - * Receive message descriptor status bit definitions. - */ - -#define RX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */ -#define RX_ERR 0x40 /* Error Summary */ -#define RX_FRAM 0x20 /* Framing Error */ -#define RX_OFLO 0x10 /* Overflow Error */ -#define RX_CRC 0x08 /* CRC Error */ -#define RX_BUFF 0x04 /* Buffer Error */ -#define RX_STP 0x02 /* Start of Packet */ -#define RX_ENP 0x01 /* End of Packet */ - - -/* - * Transmit message descriptor status bit definitions. - */ - -#define TX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */ -#define TX_ERR 0x40 /* Error Summary */ -#define TX_MORE 0x10 /* More the 1 retry needed to Xmit */ -#define TX_ONE 0x08 /* One retry needed to Xmit */ -#define TX_DEF 0x04 /* Deferred */ -#define TX_STP 0x02 /* Start of Packet */ -#define TX_ENP 0x01 /* End of Packet */ - -/* - * Transmit status (2) (valid if TX_ERR == 1) - */ - -#define TX_BUFF 0x8000 /* Buffering error (no ENP) */ -#define TX_UFLO 0x4000 /* Underflow (late memory) */ -#define TX_LCOL 0x1000 /* Late collision */ -#define TX_LCAR 0x0400 /* Loss of Carrier */ -#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */ -#define TX_TDR 0x003f /* Time-domain-reflectometer-value */ - - -/* - * Structures used for Communication with the LANCE - */ - -/* LANCE Initialize Block */ - -struct init_block -{ - unsigned short mode; /* Mode Register */ - unsigned char paddr[6]; /* Physical Address (MAC) */ - unsigned char laddr[8]; /* Logical Filter Address (not used) */ - unsigned int rdrp; /* Receive Descriptor Ring pointer */ - unsigned int tdrp; /* Transmit Descriptor Ring pointer */ -}; - - -/* Receive Message Descriptor Entry */ - -struct rmd -{ - union - { - unsigned long buffer; /* Address of buffer */ - struct - { - unsigned char unused[3]; - unsigned volatile char status; /* Status Bits */ - } s; - } u; - volatile short blen; /* Buffer Length (two's complement) */ - unsigned short mlen; /* Message Byte Count */ -}; - - -/* Transmit Message Descriptor Entry */ - -struct tmd -{ - union - { - unsigned long buffer; /* Address of buffer */ - struct - { - unsigned char unused[3]; - unsigned volatile char status; /* Status Bits */ - } s; - } u; - unsigned short blen; /* Buffer Length (two's complement) */ - unsigned volatile short status2; /* Error Status Bits */ -}; - -#endif /* End of SK_G16_H */ diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile index 6cfccfb7889f..cb23580fcffa 100644 --- a/drivers/net/skfp/Makefile +++ b/drivers/net/skfp/Makefile @@ -6,8 +6,8 @@ obj-$(CONFIG_SKFP) += skfp.o skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ ecm.o pcmplc.o pmf.o queue.o rmt.o \ - smtdef.o smtinit.o smttimer.o srf.o lnkstat.o \ - smtparse.o hwt.o drvfbi.o ess.o + smtdef.o smtinit.o smttimer.o srf.o hwt.o \ + drvfbi.o ess.o # NOTE: # Compiling this driver produces some warnings (and some more are diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c index 052e841ba187..5b475833f645 100644 --- a/drivers/net/skfp/drvfbi.c +++ b/drivers/net/skfp/drvfbi.c @@ -105,8 +105,8 @@ extern int AIX_vpdReadByte() ; #endif -/* Prototypes of local functions. */ -void smt_stop_watchdog(struct s_smc *smc); +/* Prototype of a local function. */ +static void smt_stop_watchdog(struct s_smc *smc); #ifdef MCA static int read_card_id() ; @@ -631,7 +631,7 @@ void plc_clear_irq(struct s_smc *smc, int p) * LED_Y_OFF just switch yellow LED off * LED_Y_ON just switch yello LED on */ -void led_indication(struct s_smc *smc, int led_event) +static void led_indication(struct s_smc *smc, int led_event) { /* use smc->hw.mac_ring_is_up == TRUE * as indication for Ring Operational @@ -764,122 +764,6 @@ void llc_recover_tx(struct s_smc *smc) #endif } -/*--------------------------- DMA init ----------------------------*/ -#ifdef ISA - -/* - * init DMA - */ -void init_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - - /* - * set cascade mode, - * clear mask bit (enable DMA cannal) - */ - if (dma > 3) { - outp(0xd6,(dma & 0x03) | 0xc0) ; - outp(0xd4, dma & 0x03) ; - } - else { - outp(0x0b,(dma & 0x03) | 0xc0) ; - outp(0x0a,dma & 0x03) ; - } -} - -/* - * disable DMA - */ -void dis_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - - /* - * set mask bit (disable DMA cannal) - */ - if (dma > 3) { - outp(0xd4,(dma & 0x03) | 0x04) ; - } - else { - outp(0x0a,(dma & 0x03) | 0x04) ; - } -} - -#endif /* ISA */ - -#ifdef EISA - -/*arrays with io addresses of dma controller length and address registers*/ -static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ; -static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ; -static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ; - -void init_dma(struct s_smc *smc, int dma) -{ - /* - * extended mode register - * 32 bit IO - * type c - * TC output - * disable stop - */ - - /* mode read (write) demand */ - smc->hw.dma_rmode = (dma & 3) | 0x08 | 0x0 ; - smc->hw.dma_wmode = (dma & 3) | 0x04 | 0x0 ; - - /* 32 bit IO's, burst DMA mode (type "C") */ - smc->hw.dma_emode = (dma & 3) | 0x08 | 0x30 ; - - outp((dma < 4) ? 0x40b : 0x4d6,smc->hw.dma_emode) ; - - /* disable chaining */ - outp((dma < 4) ? 0x40a : 0x4d4,(dma&3)) ; - - /*load dma controller addresses for fast access during set dma*/ - smc->hw.dma_base_word_count = cntr[smc->hw.dma]; - smc->hw.dma_base_address = base[smc->hw.dma]; - smc->hw.dma_base_address_page = page[smc->hw.dma]; - -} - -void dis_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - - outp((dma < 4) ? 0x0a : 0xd4,(dma&3)|4) ;/* mask bit */ -} -#endif /* EISA */ - -#ifdef MCA -void init_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - SK_UNUSED(dma) ; -} - -void dis_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - SK_UNUSED(dma) ; -} -#endif - -#ifdef PCI -void init_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - SK_UNUSED(dma) ; -} - -void dis_dma(struct s_smc *smc, int dma) -{ - SK_UNUSED(smc) ; - SK_UNUSED(dma) ; -} -#endif - #ifdef MULT_OEM static int is_equal_num(char comp1[], char comp2[], int num) { @@ -1407,7 +1291,7 @@ void smt_start_watchdog(struct s_smc *smc) #endif /* DEBUG */ } -void smt_stop_watchdog(struct s_smc *smc) +static void smt_stop_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ #ifndef DEBUG @@ -1422,104 +1306,6 @@ void smt_stop_watchdog(struct s_smc *smc) } #ifdef PCI -static char get_rom_byte(struct s_smc *smc, u_short addr) -{ - GET_PAGE(addr) ; - return (READ_PROM(ADDR(B2_FDP))) ; -} - -/* - * ROM image defines - */ -#define ROM_SIG_1 0 -#define ROM_SIG_2 1 -#define PCI_DATA_1 0x18 -#define PCI_DATA_2 0x19 - -/* - * PCI data structure defines - */ -#define VPD_DATA_1 0x08 -#define VPD_DATA_2 0x09 -#define IMAGE_LEN_1 0x10 -#define IMAGE_LEN_2 0x11 -#define CODE_TYPE 0x14 -#define INDICATOR 0x15 - -/* - * BEGIN_MANUAL_ENTRY(mac_drv_vpd_read) - * mac_drv_vpd_read(smc,buf,size,image) - * - * function DOWNCALL (FDDIWARE) - * reads the VPD data of the FPROM and writes it into the - * buffer - * - * para buf points to the buffer for the VPD data - * size size of the VPD data buffer - * image boot image; code type of the boot image - * image = 0 Intel x86, PC-AT compatible - * 1 OPENBOOT standard for PCI - * 2-FF reserved - * - * returns len number of VPD data bytes read form the FPROM - * <0 number of read bytes - * >0 error: data invalid - * - * END_MANUAL_ENTRY - */ -int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image) -{ - u_short ibase ; - u_short pci_base ; - u_short vpd ; - int len ; - - len = 0 ; - ibase = 0 ; - /* - * as long images defined - */ - while (get_rom_byte(smc,ibase+ROM_SIG_1) == 0x55 && - (u_char) get_rom_byte(smc,ibase+ROM_SIG_2) == 0xaa) { - /* - * get the pointer to the PCI data structure - */ - pci_base = ibase + get_rom_byte(smc,ibase+PCI_DATA_1) + - (get_rom_byte(smc,ibase+PCI_DATA_2) << 8) ; - - if (image == get_rom_byte(smc,pci_base+CODE_TYPE)) { - /* - * we have the right image, read the VPD data - */ - vpd = ibase + get_rom_byte(smc,pci_base+VPD_DATA_1) + - (get_rom_byte(smc,pci_base+VPD_DATA_2) << 8) ; - if (vpd == ibase) { - break ; /* no VPD data */ - } - for (len = 0; len < size; len++,buf++,vpd++) { - *buf = get_rom_byte(smc,vpd) ; - } - break ; - } - else { - /* - * try the next image - */ - if (get_rom_byte(smc,pci_base+INDICATOR) & 0x80) { - break ; /* this was the last image */ - } - ibase = ibase + get_rom_byte(smc,ibase+IMAGE_LEN_1) + - (get_rom_byte(smc,ibase+IMAGE_LEN_2) << 8) ; - } - } - - return(len) ; -} - -void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value) -{ - smc->hw.pci_fix_value = fix_value ; -} void mac_do_pci_fix(struct s_smc *smc) { diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index fd39b4b2ef7d..62b01328c496 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c @@ -102,7 +102,7 @@ void ess_timer_poll(struct s_smc *smc); void ess_para_change(struct s_smc *smc); int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, int fs); -int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); +static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); /* @@ -375,7 +375,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, * determines the synchronous bandwidth, set the TSYNC register and the * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. */ -int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) +static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) { /* * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index 76e78442fc24..a2ed47f1cc70 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -1117,30 +1117,6 @@ void mac_clear_multicast(struct s_smc *smc) /* BEGIN_MANUAL_ENTRY(if,func;others;2) - int mac_set_func_addr(smc,f_addr) - struct s_smc *smc ; - u_long f_addr ; - -Function DOWNCALL (SMT, fplustm.c) - Set a Token-Ring functional address, the address will - be activated after calling mac_update_multicast() - -Para f_addr functional bits in non-canonical format - -Returns 0: always success - - END_MANUAL_ENTRY() - */ -int mac_set_func_addr(struct s_smc *smc, u_long f_addr) -{ - smc->hw.fp.func_addr = f_addr ; - return(0) ; -} - - -/* - BEGIN_MANUAL_ENTRY(if,func;others;2) - int mac_add_multicast(smc,addr,can) struct s_smc *smc ; struct fddi_addr *addr ; @@ -1203,52 +1179,6 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) } /* - BEGIN_MANUAL_ENTRY(if,func;others;2) - - void mac_del_multicast(smc,addr,can) - struct s_smc *smc ; - struct fddi_addr *addr ; - int can ; - -Function DOWNCALL (SMT, fplustm.c) - Delete an entry from the multicast table - -Para addr pointer to a multicast address - can = 0: the multicast address has the physical format - = 1: the multicast address has the canonical format - | 0x80 permanent - - END_MANUAL_ENTRY() - */ -void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) -{ - SK_LOC_DECL(struct fddi_addr,own) ; - struct s_fpmc *tb ; - - if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80))) - return ; - /* - * permanent addresses must be deleted with perm bit - * and vice versa - */ - if (( tb->perm && (can & 0x80)) || - (!tb->perm && !(can & 0x80))) { - /* - * delete it - */ - if (tb->n) { - tb->n-- ; - if (tb->perm) { - smc->hw.fp.smt_slots_used-- ; - } - else { - smc->hw.fp.os_slots_used-- ; - } - } - } -} - -/* * mode */ diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h index 603982debc71..f2f771d8be76 100644 --- a/drivers/net/skfp/h/cmtdef.h +++ b/drivers/net/skfp/h/cmtdef.h @@ -507,7 +507,6 @@ void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, int *remote, int *mac); void plc_config_mux(struct s_smc *smc, int mux); void sm_lem_evaluate(struct s_smc *smc); -void smt_clear_una_dna(struct s_smc *smc); void mac_update_counter(struct s_smc *smc); void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); void sm_ma_control(struct s_smc *smc, int mode); @@ -541,11 +540,9 @@ void smt_timer_poll(struct s_smc *smc); u_long smt_get_time(void); u_long smt_get_tid(struct s_smc *smc); void smt_timer_done(struct s_smc *smc); -void smt_set_defaults(struct s_smc *smc); void smt_fixup_mib(struct s_smc *smc); void smt_reset_defaults(struct s_smc *smc, int level); void smt_agent_task(struct s_smc *smc); -void smt_please_reconnect(struct s_smc *smc, int reconn_time); int smt_check_para(struct s_smc *smc, struct smt_header *sm, const u_short list[]); void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); @@ -568,7 +565,6 @@ int pcm_get_s_port(struct s_smc *smc); int pcm_rooted_station(struct s_smc *smc); int cfm_get_mac_input(struct s_smc *smc); int cfm_get_mac_output(struct s_smc *smc); -int port_to_mib(struct s_smc *smc, int p); int cem_build_path(struct s_smc *smc, char *to, int path_index); int sm_mac_get_tx_state(struct s_smc *smc); char *get_pcmstate(struct s_smc *smc, int np); @@ -580,8 +576,6 @@ void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local); void smt_set_timestamp(struct s_smc *smc, u_char *p); void mac_set_rx_mode(struct s_smc *smc, int mode); int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); -int mac_set_func_addr(struct s_smc *smc, u_long f_addr); -void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); void mac_update_multicast(struct s_smc *smc); void mac_clear_multicast(struct s_smc *smc); void set_formac_tsync(struct s_smc *smc, long sync_bw); @@ -599,7 +593,6 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd); int smt_set_mac_opvalues(struct s_smc *smc); #ifdef TAG_MODE -void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value); void mac_do_pci_fix(struct s_smc *smc); void mac_drv_clear_tx_queue(struct s_smc *smc); void mac_drv_repair_descr(struct s_smc *smc); diff --git a/drivers/net/skfp/h/hwmtm.h b/drivers/net/skfp/h/hwmtm.h index 4e360af07d77..1a606d4bfe5e 100644 --- a/drivers/net/skfp/h/hwmtm.h +++ b/drivers/net/skfp/h/hwmtm.h @@ -262,31 +262,6 @@ struct os_debug { (smc)->hw.fp.tx_q[queue].tx_curr_put /* - * BEGIN_MANUAL_ENTRY(HWM_TX_CHECK) - * void HWM_TX_CHECK(smc,frame_status,low_water) - * - * function MACRO (hardware module, hwmtm.h) - * This macro is invoked by the OS-specific before it left it's - * driver_send function. This macro calls mac_drv_clear_txd - * if the free TxDs of the current transmit queue is equal or - * lower than the given low water mark. - * - * para frame_status status of the frame, see design description - * low_water low water mark of free TxD's - * - * END_MANUAL_ENTRY - */ -#ifndef HWM_NO_FLOW_CTL -#define HWM_TX_CHECK(smc,frame_status,low_water) {\ - if ((low_water)>=(smc)->hw.fp.tx_q[(frame_status)&QUEUE_A0].tx_free) {\ - mac_drv_clear_txd(smc) ;\ - }\ -} -#else -#define HWM_TX_CHECK(smc,frame_status,low_water) mac_drv_clear_txd(smc) -#endif - -/* * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN) * int HWM_GET_RX_FRAG_LEN(rxd) * diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/skfp/h/osdef1st.h index 5359eb53008d..763ca18cbea8 100644 --- a/drivers/net/skfp/h/osdef1st.h +++ b/drivers/net/skfp/h/osdef1st.h @@ -20,6 +20,8 @@ // HWM (HardWare Module) Definitions // ----------------------- +#include <asm/byteorder.h> + #ifdef __LITTLE_ENDIAN #define LITTLE_ENDIAN #else diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index 18d429021edb..438f424e6361 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c @@ -86,6 +86,7 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); static SMbuf* get_llc_rx(struct s_smc *smc); static SMbuf* get_txd_mb(struct s_smc *smc); +static void mac_drv_clear_txd(struct s_smc *smc); /* ------------------------------------------------------------- @@ -146,7 +147,6 @@ extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, */ void process_receive(struct s_smc *smc); void fddi_isr(struct s_smc *smc); -void mac_drv_clear_txd(struct s_smc *smc); void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); void init_driver_fplus(struct s_smc *smc); void mac_drv_rx_mode(struct s_smc *smc, int mode); @@ -158,7 +158,6 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, int frame_status); -int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len); int mac_drv_init(struct s_smc *smc); int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, int frame_status); @@ -1448,35 +1447,6 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ; } -#ifndef NDIS_OS2 -/* - * BEGIN_MANUAL_ENTRY(mac_drv_rx_frag) - * int mac_drv_rx_frag(smc,virt,len) - * - * function DOWNCALL (hwmtm.c) - * mac_drv_rx_frag fills the fragment with a part of the frame. - * - * para virt the virtual address of the fragment - * len the length in bytes of the fragment - * - * return 0: success code, no errors possible - * - * END_MANUAL_ENTRY - */ -int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len) -{ - NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ; - - DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ; - memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ; - smc->os.hwm.r.mb_pos += len ; - - NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ; - return(0) ; -} -#endif - - /* * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) * @@ -1978,7 +1948,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) * * END_MANUAL_ENTRY */ -void mac_drv_clear_txd(struct s_smc *smc) +static void mac_drv_clear_txd(struct s_smc *smc) { struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t1 ; diff --git a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c deleted file mode 100644 index 00a248044f86..000000000000 --- a/drivers/net/skfp/lnkstat.c +++ /dev/null @@ -1,204 +0,0 @@ -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * See the file "skfddi.c" for further information. - * - * 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. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - IBM FDDI read error log function -*/ - -#include "h/types.h" -#include "h/fddi.h" -#include "h/smc.h" -#include "h/lnkstat.h" - -#ifndef lint -static const char ID_sccs[] = "@(#)lnkstat.c 1.8 97/04/11 (C) SK " ; -#endif - -#ifdef sun -#define _far -#endif - -#define EL_IS_OK(x,l) ((((int)&(((struct s_error_log *)0)->x)) + \ - sizeof(er->x)) <= l) - -/* - BEGIN_MANUAL_ENTRY(if,func;others;11) - - u_long smt_get_error_word(smc) - struct s_smc *smc ; - -Function DOWNCALL (SMT, lnkstat.c) - This functions returns the SMT error work for AIX events. - -Return smt_error_word These bits are supported: - - SMT_ERL_ALC == [PS/PA].fddiPORTLerFlag - SMT_ERL_BLC == [PB].fddiPORTLerFlag - SMT_ERL_NCC == fddiMACNotCopiedFlag - SMT_ERL_FEC == fddiMACFrameErrorFlag - - END_MANUAL_ENTRY() - */ -u_long smt_get_error_word(struct s_smc *smc) -{ - u_long st; - - /* - * smt error word low - */ - st = 0 ; - if (smc->s.sas == SMT_SAS) { - if (smc->mib.p[PS].fddiPORTLerFlag) - st |= SMT_ERL_ALC ; - } - else { - if (smc->mib.p[PA].fddiPORTLerFlag) - st |= SMT_ERL_ALC ; - if (smc->mib.p[PB].fddiPORTLerFlag) - st |= SMT_ERL_BLC ; - } - if (smc->mib.m[MAC0].fddiMACNotCopiedFlag) - st |= SMT_ERL_NCC ; /* not copied condition */ - if (smc->mib.m[MAC0].fddiMACFrameErrorFlag) - st |= SMT_ERL_FEC ; /* frame error condition */ - - return st; -} - -/* - BEGIN_MANUAL_ENTRY(if,func;others;11) - - u_long smt_get_event_word(smc) - struct s_smc *smc ; - -Function DOWNCALL (SMT, lnkstat.c) - This functions returns the SMT event work for AIX events. - -Return smt_event_word always 0 - - END_MANUAL_ENTRY() - */ -u_long smt_get_event_word(struct s_smc *smc) -{ - return (u_long) 0; -} - -/* - BEGIN_MANUAL_ENTRY(if,func;others;11) - - u_long smt_get_port_event_word(smc) - struct s_smc *smc ; - -Function DOWNCALL (SMT, lnkstat.c) - This functions returns the SMT port event work for AIX events. - -Return smt_port_event_word always 0 - - END_MANUAL_ENTRY() - */ -u_long smt_get_port_event_word(struct s_smc *smc) -{ - return (u_long) 0; -} - -/* - BEGIN_MANUAL_ENTRY(if,func;others;11) - - u_long smt_read_errorlog(smc,p,len) - struct s_smc *smc ; - char _far *p ; - int len ; - -Function DOWNCALL (SMT, lnkstat.c) - This functions returns the SMT error log field for AIX events. - -Para p pointer to the error log field - len len of the error log field - -Return len used len of the error log field - - END_MANUAL_ENTRY() - */ -int smt_read_errorlog(struct s_smc *smc, char _far *p, int len) -{ - int i ; - int st ; - struct s_error_log _far *er ; - - er = (struct s_error_log _far *) p ; - if (len > sizeof(struct s_error_log)) - len = sizeof(struct s_error_log) ; - for (i = 0 ; i < len ; i++) - *p++ = 0 ; - /* - * set count - */ - if (EL_IS_OK(set_count_high,len)) { - er->set_count_low = (u_short)smc->mib.fddiSMTSetCount.count ; - er->set_count_high = - (u_short)(smc->mib.fddiSMTSetCount.count >> 16L) ; - } - /* - * aci - */ - if (EL_IS_OK(aci_id_code,len)) { - er->aci_id_code = 0 ; - } - /* - * purge counter is missed frames; 16 bits only - */ - if (EL_IS_OK(purge_frame_counter,len)) { - if (smc->mib.m[MAC0].fddiMACCopied_Ct > 0xffff) - er->purge_frame_counter = 0xffff ; - else - er->purge_frame_counter = - (u_short)smc->mib.m[MAC0].fddiMACCopied_Ct ; - } - /* - * CMT and RMT state machines - */ - if (EL_IS_OK(ecm_state,len)) - er->ecm_state = smc->mib.fddiSMTECMState ; - - if (EL_IS_OK(pcm_b_state,len)) { - if (smc->s.sas == SMT_SAS) { - er->pcm_a_state = smc->y[PS].mib->fddiPORTPCMState ; - er->pcm_b_state = 0 ; - } - else { - er->pcm_a_state = smc->y[PA].mib->fddiPORTPCMState ; - er->pcm_b_state = smc->y[PB].mib->fddiPORTPCMState ; - } - } - if (EL_IS_OK(cfm_state,len)) - er->cfm_state = smc->mib.fddiSMTCF_State ; - if (EL_IS_OK(rmt_state,len)) - er->rmt_state = smc->mib.m[MAC0].fddiMACRMTState ; - - /* - * smt error word low (we only need the low order 16 bits.) - */ - - st = smt_get_error_word(smc) & 0xffff ; - - if (EL_IS_OK(smt_error_low,len)) - er->smt_error_low = st ; - - if (EL_IS_OK(ucode_version_level,len)) - er->ucode_version_level = 0x0101 ; - return(len) ; -} - diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c index 571f055c096b..cd0aa4c151b0 100644 --- a/drivers/net/skfp/pcmplc.c +++ b/drivers/net/skfp/pcmplc.c @@ -1861,13 +1861,6 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd) #endif } -void pcm_set_lct_short(struct s_smc *smc, int n) -{ - if (n <= 0 || n > 1000) - return ; - smc->s.lct_short = n ; -} - #ifdef DEBUG /* * fill state struct diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index f2b446d8b0bf..efc639c013fd 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c @@ -36,12 +36,13 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm); static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); static const struct s_p_tab* smt_get_ptab(u_short para); static int smt_mib_phys(struct s_smc *smc); -int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, - int set); +static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, + int local, int set); void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, int index, int local); static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, int set, int local); +static int port_to_mib(struct s_smc *smc, int p); #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) @@ -1078,8 +1079,8 @@ wrong_error: /* * set parameter */ -int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, - int set) +static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, + int local, int set) { #define IFSET(x) if (set) (x) @@ -1549,7 +1550,7 @@ static int smt_mib_phys(struct s_smc *smc) #endif } -int port_to_mib(struct s_smc *smc, int p) +static int port_to_mib(struct s_smc *smc, int p) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index c88aad6edd74..4b5ed2c63177 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -149,7 +149,6 @@ extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, extern void mac_drv_rx_mode(struct s_smc *smc, int mode); extern void mac_drv_clear_rx_queue(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); -extern void mac_drv_clear_txd(struct s_smc *smc); static struct pci_device_id skfddi_pci_tbl[] = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index 71935eaf9d4e..f17c05cbe44b 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c @@ -86,7 +86,7 @@ static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, u_long tid, int local); #ifdef LITTLE_ENDIAN -static void smt_string_swap(void); +static void smt_string_swap(char *data, const char *format, int len); #endif static void smt_add_frame_len(SMbuf *mb, int len); static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); @@ -110,7 +110,7 @@ static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, int len); -void smt_clear_una_dna(struct s_smc *smc); +static void smt_clear_una_dna(struct s_smc *smc); static void smt_clear_old_una_dna(struct s_smc *smc); #ifdef CONCENTRATOR static int entity_to_index(void); @@ -118,7 +118,7 @@ static int entity_to_index(void); static void update_dac(struct s_smc *smc, int report); static int div_ratio(u_long upper, u_long lower); #ifdef USE_CAN_ADDR -void hwm_conv_can(struct s_smc *smc, char *data, int len); +static void hwm_conv_can(struct s_smc *smc, char *data, int len); #else #define hwm_conv_can(smc,data,len) #endif @@ -216,24 +216,6 @@ void smt_agent_task(struct s_smc *smc) DB_SMT("SMT agent task\n",0,0) ; } -void smt_please_reconnect(struct s_smc *smc, int reconn_time) -/* struct s_smc *smc; Pointer to SMT context */ -/* int reconn_time; Wait for reconnect time in seconds */ -{ - /* - * The please reconnect variable is used as a timer. - * It is decremented each time smt_event is called. - * This happens every second or when smt_force_irq is called. - * Note: smt_force_irq () is called on some packet receives and - * when a multicast address is changed. Since nothing - * is received during the disconnect and the multicast - * address changes can be viewed as not very often and - * the timer runs out close to its given value - * (reconn_time). - */ - smc->sm.please_reconnect = reconn_time ; -} - #ifndef SMT_REAL_TOKEN_CT void smt_emulate_token_ct(struct s_smc *smc, int mac_index) { @@ -1574,7 +1556,7 @@ static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long see * clear DNA and UNA * called from CFM if configuration changes */ -void smt_clear_una_dna(struct s_smc *smc) +static void smt_clear_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; @@ -2058,30 +2040,10 @@ int smt_action(struct s_smc *smc, int class, int code, int index) } /* - * change tneg - * set T_Req in MIB (Path Attribute) - * calculate new values for MAC - * if change required - * disconnect - * set reconnect - * end - */ -void smt_change_t_neg(struct s_smc *smc, u_long tneg) -{ - smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ; - - if (smt_set_mac_opvalues(smc)) { - RS_SET(smc,RS_EVENT) ; - smc->sm.please_reconnect = 1 ; - queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; - } -} - -/* * canonical conversion of <len> bytes beginning form *data */ #ifdef USE_CAN_ADDR -void hwm_conv_can(struct s_smc *smc, char *data, int len) +static void hwm_conv_can(struct s_smc *smc, char *data, int len) { int i ; diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c index 5a0c8db816d8..4e07ff7073f1 100644 --- a/drivers/net/skfp/smtdef.c +++ b/drivers/net/skfp/smtdef.c @@ -76,11 +76,6 @@ void smt_reset_defaults(struct s_smc *smc, int level); static void smt_init_mib(struct s_smc *smc, int level); static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); -void smt_set_defaults(struct s_smc *smc) -{ - smt_reset_defaults(smc,0) ; -} - #define MS2BCLK(x) ((x)*12500L) #define US2BCLK(x) ((x)*1250L) diff --git a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c deleted file mode 100644 index d5779e414dbe..000000000000 --- a/drivers/net/skfp/smtparse.c +++ /dev/null @@ -1,467 +0,0 @@ -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * See the file "skfddi.c" for further information. - * - * 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. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -/* - parser for SMT parameters -*/ - -#include "h/types.h" -#include "h/fddi.h" -#include "h/smc.h" -#include "h/smt_p.h" - -#define KERNEL -#include "h/smtstate.h" - -#ifndef lint -static const char ID_sccs[] = "@(#)smtparse.c 1.12 98/10/06 (C) SK " ; -#endif - -#ifdef sun -#define _far -#endif - -/* - * convert to BCLK units - */ -#define MS2BCLK(x) ((x)*12500L) -#define US2BCLK(x) ((x/10)*125L) - -/* - * parameter table - */ -static struct s_ptab { - char *pt_name ; - u_short pt_num ; - u_short pt_type ; - u_long pt_min ; - u_long pt_max ; -} ptab[] = { - { "PMFPASSWD",0, 0 } , - { "USERDATA",1, 0 } , - { "LERCUTOFFA",2, 1, 4, 15 } , - { "LERCUTOFFB",3, 1, 4, 15 } , - { "LERALARMA",4, 1, 4, 15 } , - { "LERALARMB",5, 1, 4, 15 } , - { "TMAX",6, 1, 5, 165 } , - { "TMIN",7, 1, 5, 165 } , - { "TREQ",8, 1, 5, 165 } , - { "TVX",9, 1, 2500, 10000 } , -#ifdef ESS - { "SBAPAYLOAD",10, 1, 0, 1562 } , - { "SBAOVERHEAD",11, 1, 50, 5000 } , - { "MAXTNEG",12, 1, 5, 165 } , - { "MINSEGMENTSIZE",13, 1, 0, 4478 } , - { "SBACATEGORY",14, 1, 0, 0xffff } , - { "SYNCHTXMODE",15, 0 } , -#endif -#ifdef SBA - { "SBACOMMAND",16, 0 } , - { "SBAAVAILABLE",17, 1, 0, 100 } , -#endif - { NULL } -} ; - -/* Define maximum string size for values and keybuffer */ -#define MAX_VAL 40 - -/* - * local function declarations - */ -static u_long parse_num(int type, char _far *value, char *v, u_long mn, - u_long mx, int scale); -static int parse_word(char *buf, char _far *text); - -#ifdef SIM -#define DB_MAIN(a,b,c) printf(a,b,c) -#else -#define DB_MAIN(a,b,c) -#endif - -/* - * BEGIN_MANUAL_ENTRY() - * - * int smt_parse_arg(struct s_smc *,char _far *keyword,int type, - char _far *value) - * - * parse SMT parameter - * *keyword - * pointer to keyword, must be \0, \n or \r terminated - * *value pointer to value, either char * or u_long * - * if char * - * pointer to value, must be \0, \n or \r terminated - * if u_long * - * contains binary value - * - * type 0: integer - * 1: string - * return - * 0 parameter parsed ok - * != 0 error - * NOTE: - * function can be called with DS != SS - * - * - * END_MANUAL_ENTRY() - */ -int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type, - char _far *value) -{ - char keybuf[MAX_VAL+1]; - char valbuf[MAX_VAL+1]; - char c ; - char *p ; - char *v ; - char *d ; - u_long val = 0 ; - struct s_ptab *pt ; - int st ; - int i ; - - /* - * parse keyword - */ - if ((st = parse_word(keybuf,keyword))) - return(st) ; - /* - * parse value if given as string - */ - if (type == 1) { - if ((st = parse_word(valbuf,value))) - return(st) ; - } - /* - * search in table - */ - st = 0 ; - for (pt = ptab ; (v = pt->pt_name) ; pt++) { - for (p = keybuf ; (c = *p) ; p++,v++) { - if (c != *v) - break ; - } - if (!c && !*v) - break ; - } - if (!v) - return(-1) ; -#if 0 - printf("=>%s<==>%s<=\n",pt->pt_name,valbuf) ; -#endif - /* - * set value in MIB - */ - if (pt->pt_type) - val = parse_num(type,value,valbuf,pt->pt_min,pt->pt_max,1) ; - switch (pt->pt_num) { - case 0 : - v = valbuf ; - d = (char *) smc->mib.fddiPRPMFPasswd ; - for (i = 0 ; i < (signed)sizeof(smc->mib.fddiPRPMFPasswd) ; i++) - *d++ = *v++ ; - DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiPRPMFPasswd) ; - break ; - case 1 : - v = valbuf ; - d = (char *) smc->mib.fddiSMTUserData ; - for (i = 0 ; i < (signed)sizeof(smc->mib.fddiSMTUserData) ; i++) - *d++ = *v++ ; - DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiSMTUserData) ; - break ; - case 2 : - smc->mib.p[PA].fddiPORTLer_Cutoff = (u_char) val ; - DB_MAIN("SET %s = %d\n", - pt->pt_name,smc->mib.p[PA].fddiPORTLer_Cutoff) ; - break ; - case 3 : - smc->mib.p[PB].fddiPORTLer_Cutoff = (u_char) val ; - DB_MAIN("SET %s = %d\n", - pt->pt_name,smc->mib.p[PB].fddiPORTLer_Cutoff) ; - break ; - case 4 : - smc->mib.p[PA].fddiPORTLer_Alarm = (u_char) val ; - DB_MAIN("SET %s = %d\n", - pt->pt_name,smc->mib.p[PA].fddiPORTLer_Alarm) ; - break ; - case 5 : - smc->mib.p[PB].fddiPORTLer_Alarm = (u_char) val ; - DB_MAIN("SET %s = %d\n", - pt->pt_name,smc->mib.p[PB].fddiPORTLer_Alarm) ; - break ; - case 6 : /* TMAX */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.a[PATH0].fddiPATHT_MaxLowerBound = - (u_long) -MS2BCLK((long)val) ; - break ; - case 7 : /* TMIN */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.m[MAC0].fddiMACT_Min = - (u_long) -MS2BCLK((long)val) ; - break ; - case 8 : /* TREQ */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.a[PATH0].fddiPATHMaxT_Req = - (u_long) -MS2BCLK((long)val) ; - break ; - case 9 : /* TVX */ - DB_MAIN("SET %s = %d \n",pt->pt_name,val) ; - smc->mib.a[PATH0].fddiPATHTVXLowerBound = - (u_long) -US2BCLK((long)val) ; - break ; -#ifdef ESS - case 10 : /* SBAPAYLOAD */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - if (smc->mib.fddiESSPayload != val) { - smc->ess.raf_act_timer_poll = TRUE ; - smc->mib.fddiESSPayload = val ; - } - break ; - case 11 : /* SBAOVERHEAD */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.fddiESSOverhead = val ; - break ; - case 12 : /* MAXTNEG */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.fddiESSMaxTNeg = (u_long) -MS2BCLK((long)val) ; - break ; - case 13 : /* MINSEGMENTSIZE */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.fddiESSMinSegmentSize = val ; - break ; - case 14 : /* SBACATEGORY */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.fddiESSCategory = - (smc->mib.fddiESSCategory & 0xffff) | - ((u_long)(val << 16)) ; - break ; - case 15 : /* SYNCHTXMODE */ - /* do not use memcmp(valbuf,"ALL",3) because DS != SS */ - if (valbuf[0] == 'A' && valbuf[1] == 'L' && valbuf[2] == 'L') { - smc->mib.fddiESSSynchTxMode = TRUE ; - DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; - } - /* if (!memcmp(valbuf,"SPLIT",5)) { */ - if (valbuf[0] == 'S' && valbuf[1] == 'P' && valbuf[2] == 'L' && - valbuf[3] == 'I' && valbuf[4] == 'T') { - DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; - smc->mib.fddiESSSynchTxMode = FALSE ; - } - break ; -#endif -#ifdef SBA - case 16 : /* SBACOMMAND */ - /* if (!memcmp(valbuf,"START",5)) { */ - if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'A' && - valbuf[3] == 'R' && valbuf[4] == 'T') { - DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; - smc->mib.fddiSBACommand = SB_START ; - } - /* if (!memcmp(valbuf,"STOP",4)) { */ - if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'O' && - valbuf[3] == 'P') { - DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ; - smc->mib.fddiSBACommand = SB_STOP ; - } - break ; - case 17 : /* SBAAVAILABLE */ - DB_MAIN("SET %s = %d\n",pt->pt_name,val) ; - smc->mib.fddiSBAAvailable = (u_char) val ; - break ; -#endif - } - return(0) ; -} - -static int parse_word(char *buf, char _far *text) -{ - char c ; - char *p ; - int p_len ; - int quote ; - int i ; - int ok ; - - /* - * skip leading white space - */ - p = buf ; - for (i = 0 ; i < MAX_VAL ; i++) - *p++ = 0 ; - p = buf ; - p_len = 0 ; - ok = 0 ; - while ( (c = *text++) && (c != '\n') && (c != '\r')) { - if ((c != ' ') && (c != '\t')) { - ok = 1 ; - break ; - } - } - if (!ok) - return(-1) ; - if (c == '"') { - quote = 1 ; - } - else { - quote = 0 ; - text-- ; - } - /* - * parse valbuf - */ - ok = 0 ; - while (!ok && p_len < MAX_VAL-1 && (c = *text++) && (c != '\n') - && (c != '\r')) { - switch (quote) { - case 0 : - if ((c == ' ') || (c == '\t') || (c == '=')) { - ok = 1 ; - break ; - } - *p++ = c ; - p_len++ ; - break ; - case 2 : - *p++ = c ; - p_len++ ; - quote = 1 ; - break ; - case 1 : - switch (c) { - case '"' : - ok = 1 ; - break ; - case '\\' : - quote = 2 ; - break ; - default : - *p++ = c ; - p_len++ ; - } - } - } - *p++ = 0 ; - for (p = buf ; (c = *p) ; p++) { - if (c >= 'a' && c <= 'z') - *p = c + 'A' - 'a' ; - } - return(0) ; -} - -static u_long parse_num(int type, char _far *value, char *v, u_long mn, - u_long mx, int scale) -{ - u_long x = 0 ; - char c ; - - if (type == 0) { /* integer */ - u_long _far *l ; - u_long u1 ; - - l = (u_long _far *) value ; - u1 = *l ; - /* - * if the value is negative take the lower limit - */ - if ((long)u1 < 0) { - if (- ((long)u1) > (long) mx) { - u1 = 0 ; - } - else { - u1 = (u_long) - ((long)u1) ; - } - } - x = u1 ; - } - else { /* string */ - int sign = 0 ; - - if (*v == '-') { - sign = 1 ; - } - while ((c = *v++) && (c >= '0') && (c <= '9')) { - x = x * 10 + c - '0' ; - } - if (scale == 10) { - x *= 10 ; - if (c == '.') { - if ((c = *v++) && (c >= '0') && (c <= '9')) { - x += c - '0' ; - } - } - } - if (sign) - x = (u_long) - ((long)x) ; - } - /* - * if the value is negative - * and the absolute value is outside the limits - * take the lower limit - * else - * take the absoute value - */ - if ((long)x < 0) { - if (- ((long)x) > (long) mx) { - x = 0 ; - } - else { - x = (u_long) - ((long)x) ; - } - } - if (x < mn) - return(mn) ; - else if (x > mx) - return(mx) ; - return(x) ; -} - -#if 0 -struct s_smc SMC ; -main() -{ - char *p ; - char *v ; - char buf[100] ; - int toggle = 0 ; - - while (gets(buf)) { - p = buf ; - while (*p && ((*p == ' ') || (*p == '\t'))) - p++ ; - - while (*p && ((*p != ' ') && (*p != '\t'))) - p++ ; - - v = p ; - while (*v && ((*v == ' ') || (*v == '\t'))) - v++ ; - if ((*v >= '0') && (*v <= '9')) { - toggle = !toggle ; - if (toggle) { - u_long l ; - l = atol(v) ; - smt_parse_arg(&SMC,buf,0,(char _far *)&l) ; - } - else - smt_parse_arg(&SMC,buf,1,(char _far *)p) ; - } - else { - smt_parse_arg(&SMC,buf,1,(char _far *)p) ; - } - } - exit(0) ; -} -#endif - diff --git a/drivers/net/skge.c b/drivers/net/skge.c new file mode 100644 index 000000000000..f15739481d62 --- /dev/null +++ b/drivers/net/skge.c @@ -0,0 +1,3317 @@ +/* + * New driver for Marvell Yukon chipset and SysKonnect Gigabit + * Ethernet adapters. Based on earlier sk98lin, e100 and + * FreeBSD if_sk drivers. + * + * This driver intentionally does not support all the features + * of the original driver such as link fail-over and link management because + * those should be done at higher levels. + * + * Copyright (C) 2004, 2005 Stephen Hemminger <shemminger@osdl.org> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/pci.h> +#include <linux/if_vlan.h> +#include <linux/ip.h> +#include <linux/delay.h> +#include <linux/crc32.h> +#include <linux/dma-mapping.h> +#include <asm/irq.h> + +#include "skge.h" + +#define DRV_NAME "skge" +#define DRV_VERSION "0.8" +#define PFX DRV_NAME " " + +#define DEFAULT_TX_RING_SIZE 128 +#define DEFAULT_RX_RING_SIZE 512 +#define MAX_TX_RING_SIZE 1024 +#define MAX_RX_RING_SIZE 4096 +#define RX_COPY_THRESHOLD 128 +#define RX_BUF_SIZE 1536 +#define PHY_RETRIES 1000 +#define ETH_JUMBO_MTU 9000 +#define TX_WATCHDOG (5 * HZ) +#define NAPI_WEIGHT 64 +#define BLINK_MS 250 + +MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); +MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +static const u32 default_msg + = NETIF_MSG_DRV| NETIF_MSG_PROBE| NETIF_MSG_LINK + | NETIF_MSG_IFUP| NETIF_MSG_IFDOWN; + +static int debug = -1; /* defaults above */ +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +static const struct pci_device_id skge_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) }, + { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ + { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, + { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) }, + { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, skge_id_table); + +static int skge_up(struct net_device *dev); +static int skge_down(struct net_device *dev); +static void skge_tx_clean(struct skge_port *skge); +static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static void genesis_get_stats(struct skge_port *skge, u64 *data); +static void yukon_get_stats(struct skge_port *skge, u64 *data); +static void yukon_init(struct skge_hw *hw, int port); +static void yukon_reset(struct skge_hw *hw, int port); +static void genesis_mac_init(struct skge_hw *hw, int port); +static void genesis_reset(struct skge_hw *hw, int port); +static void genesis_link_up(struct skge_port *skge); + +/* Avoid conditionals by using array */ +static const int txqaddr[] = { Q_XA1, Q_XA2 }; +static const int rxqaddr[] = { Q_R1, Q_R2 }; +static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; +static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; +static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 }; + +/* Don't need to look at whole 16K. + * last interesting register is descriptor poll timer. + */ +#define SKGE_REGS_LEN (29*128) + +static int skge_get_regs_len(struct net_device *dev) +{ + return SKGE_REGS_LEN; +} + +/* + * Returns copy of control register region + * I/O region is divided into banks and certain regions are unreadable + */ +static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + const struct skge_port *skge = netdev_priv(dev); + unsigned long offs; + const void __iomem *io = skge->hw->regs; + static const unsigned long bankmap + = (1<<0) | (1<<2) | (1<<8) | (1<<9) + | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16) + | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23) + | (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28); + + regs->version = 1; + for (offs = 0; offs < regs->len; offs += 128) { + u32 len = min_t(u32, 128, regs->len - offs); + + if (bankmap & (1<<(offs/128))) + memcpy_fromio(p + offs, io + offs, len); + else + memset(p + offs, 0, len); + } +} + +/* Wake on Lan only supported on Yukon chps with rev 1 or above */ +static int wol_supported(const struct skge_hw *hw) +{ + return !((hw->chip_id == CHIP_ID_GENESIS || + (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0))); +} + +static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct skge_port *skge = netdev_priv(dev); + + wol->supported = wol_supported(skge->hw) ? WAKE_MAGIC : 0; + wol->wolopts = skge->wol ? WAKE_MAGIC : 0; +} + +static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + + if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) + return -EOPNOTSUPP; + + if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw)) + return -EOPNOTSUPP; + + skge->wol = wol->wolopts == WAKE_MAGIC; + + if (skge->wol) { + memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN); + + skge_write16(hw, WOL_CTRL_STAT, + WOL_CTL_ENA_PME_ON_MAGIC_PKT | + WOL_CTL_ENA_MAGIC_PKT_UNIT); + } else + skge_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT); + + return 0; +} + +/* Determine supported/adverised modes based on hardware. + * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx + */ +static u32 skge_supported_modes(const struct skge_hw *hw) +{ + u32 supported; + + if (iscopper(hw)) { + supported = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg| SUPPORTED_TP; + + if (hw->chip_id == CHIP_ID_GENESIS) + supported &= ~(SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full); + + else if (hw->chip_id == CHIP_ID_YUKON) + supported &= ~SUPPORTED_1000baseT_Half; + } else + supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE + | SUPPORTED_Autoneg; + + return supported; +} + +static int skge_get_settings(struct net_device *dev, + struct ethtool_cmd *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + + ecmd->transceiver = XCVR_INTERNAL; + ecmd->supported = skge_supported_modes(hw); + + if (iscopper(hw)) { + ecmd->port = PORT_TP; + ecmd->phy_address = hw->phy_addr; + } else + ecmd->port = PORT_FIBRE; + + ecmd->advertising = skge->advertising; + ecmd->autoneg = skge->autoneg; + ecmd->speed = skge->speed; + ecmd->duplex = skge->duplex; + return 0; +} + +static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + const struct skge_hw *hw = skge->hw; + u32 supported = skge_supported_modes(hw); + + if (ecmd->autoneg == AUTONEG_ENABLE) { + ecmd->advertising = supported; + skge->duplex = -1; + skge->speed = -1; + } else { + u32 setting; + + switch (ecmd->speed) { + case SPEED_1000: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_1000baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_1000baseT_Half; + else + return -EINVAL; + break; + case SPEED_100: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_100baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_100baseT_Half; + else + return -EINVAL; + break; + + case SPEED_10: + if (ecmd->duplex == DUPLEX_FULL) + setting = SUPPORTED_10baseT_Full; + else if (ecmd->duplex == DUPLEX_HALF) + setting = SUPPORTED_10baseT_Half; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + if ((setting & supported) == 0) + return -EINVAL; + + skge->speed = ecmd->speed; + skge->duplex = ecmd->duplex; + } + + skge->autoneg = ecmd->autoneg; + skge->advertising = ecmd->advertising; + + if (netif_running(dev)) { + skge_down(dev); + skge_up(dev); + } + return (0); +} + +static void skge_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct skge_port *skge = netdev_priv(dev); + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, pci_name(skge->hw->pdev)); +} + +static const struct skge_stat { + char name[ETH_GSTRING_LEN]; + u16 xmac_offset; + u16 gma_offset; +} skge_stats[] = { + { "tx_bytes", XM_TXO_OK_HI, GM_TXO_OK_HI }, + { "rx_bytes", XM_RXO_OK_HI, GM_RXO_OK_HI }, + + { "tx_broadcast", XM_TXF_BC_OK, GM_TXF_BC_OK }, + { "rx_broadcast", XM_RXF_BC_OK, GM_RXF_BC_OK }, + { "tx_multicast", XM_TXF_MC_OK, GM_TXF_MC_OK }, + { "rx_multicast", XM_RXF_MC_OK, GM_RXF_MC_OK }, + { "tx_unicast", XM_TXF_UC_OK, GM_TXF_UC_OK }, + { "rx_unicast", XM_RXF_UC_OK, GM_RXF_UC_OK }, + { "tx_mac_pause", XM_TXF_MPAUSE, GM_TXF_MPAUSE }, + { "rx_mac_pause", XM_RXF_MPAUSE, GM_RXF_MPAUSE }, + + { "collisions", XM_TXF_SNG_COL, GM_TXF_SNG_COL }, + { "multi_collisions", XM_TXF_MUL_COL, GM_TXF_MUL_COL }, + { "aborted", XM_TXF_ABO_COL, GM_TXF_ABO_COL }, + { "late_collision", XM_TXF_LAT_COL, GM_TXF_LAT_COL }, + { "fifo_underrun", XM_TXE_FIFO_UR, GM_TXE_FIFO_UR }, + { "fifo_overflow", XM_RXE_FIFO_OV, GM_RXE_FIFO_OV }, + + { "rx_toolong", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, + { "rx_jabber", XM_RXF_JAB_PKT, GM_RXF_JAB_PKT }, + { "rx_runt", XM_RXE_RUNT, GM_RXE_FRAG }, + { "rx_too_long", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, + { "rx_fcs_error", XM_RXF_FCS_ERR, GM_RXF_FCS_ERR }, +}; + +static int skge_get_stats_count(struct net_device *dev) +{ + return ARRAY_SIZE(skge_stats); +} + +static void skge_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct skge_port *skge = netdev_priv(dev); + + if (skge->hw->chip_id == CHIP_ID_GENESIS) + genesis_get_stats(skge, data); + else + yukon_get_stats(skge, data); +} + +/* Use hardware MIB variables for critical path statistics and + * transmit feedback not reported at interrupt. + * Other errors are accounted for in interrupt handler. + */ +static struct net_device_stats *skge_get_stats(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + u64 data[ARRAY_SIZE(skge_stats)]; + + if (skge->hw->chip_id == CHIP_ID_GENESIS) + genesis_get_stats(skge, data); + else + yukon_get_stats(skge, data); + + skge->net_stats.tx_bytes = data[0]; + skge->net_stats.rx_bytes = data[1]; + skge->net_stats.tx_packets = data[2] + data[4] + data[6]; + skge->net_stats.rx_packets = data[3] + data[5] + data[7]; + skge->net_stats.multicast = data[5] + data[7]; + skge->net_stats.collisions = data[10]; + skge->net_stats.tx_aborted_errors = data[12]; + + return &skge->net_stats; +} + +static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(skge_stats); i++) + memcpy(data + i * ETH_GSTRING_LEN, + skge_stats[i].name, ETH_GSTRING_LEN); + break; + } +} + +static void skge_get_ring_param(struct net_device *dev, + struct ethtool_ringparam *p) +{ + struct skge_port *skge = netdev_priv(dev); + + p->rx_max_pending = MAX_RX_RING_SIZE; + p->tx_max_pending = MAX_TX_RING_SIZE; + p->rx_mini_max_pending = 0; + p->rx_jumbo_max_pending = 0; + + p->rx_pending = skge->rx_ring.count; + p->tx_pending = skge->tx_ring.count; + p->rx_mini_pending = 0; + p->rx_jumbo_pending = 0; +} + +static int skge_set_ring_param(struct net_device *dev, + struct ethtool_ringparam *p) +{ + struct skge_port *skge = netdev_priv(dev); + + if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || + p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE) + return -EINVAL; + + skge->rx_ring.count = p->rx_pending; + skge->tx_ring.count = p->tx_pending; + + if (netif_running(dev)) { + skge_down(dev); + skge_up(dev); + } + + return 0; +} + +static u32 skge_get_msglevel(struct net_device *netdev) +{ + struct skge_port *skge = netdev_priv(netdev); + return skge->msg_enable; +} + +static void skge_set_msglevel(struct net_device *netdev, u32 value) +{ + struct skge_port *skge = netdev_priv(netdev); + skge->msg_enable = value; +} + +static int skge_nway_reset(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + + if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev)) + return -EINVAL; + + spin_lock_bh(&hw->phy_lock); + if (hw->chip_id == CHIP_ID_GENESIS) { + genesis_reset(hw, port); + genesis_mac_init(hw, port); + } else { + yukon_reset(hw, port); + yukon_init(hw, port); + } + spin_unlock_bh(&hw->phy_lock); + return 0; +} + +static int skge_set_sg(struct net_device *dev, u32 data) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + + if (hw->chip_id == CHIP_ID_GENESIS && data) + return -EOPNOTSUPP; + return ethtool_op_set_sg(dev, data); +} + +static int skge_set_tx_csum(struct net_device *dev, u32 data) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + + if (hw->chip_id == CHIP_ID_GENESIS && data) + return -EOPNOTSUPP; + + return ethtool_op_set_tx_csum(dev, data); +} + +static u32 skge_get_rx_csum(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + + return skge->rx_csum; +} + +/* Only Yukon supports checksum offload. */ +static int skge_set_rx_csum(struct net_device *dev, u32 data) +{ + struct skge_port *skge = netdev_priv(dev); + + if (skge->hw->chip_id == CHIP_ID_GENESIS && data) + return -EOPNOTSUPP; + + skge->rx_csum = data; + return 0; +} + +static void skge_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + + ecmd->tx_pause = (skge->flow_control == FLOW_MODE_LOC_SEND) + || (skge->flow_control == FLOW_MODE_SYMMETRIC); + ecmd->rx_pause = (skge->flow_control == FLOW_MODE_REM_SEND) + || (skge->flow_control == FLOW_MODE_SYMMETRIC); + + ecmd->autoneg = skge->autoneg; +} + +static int skge_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + + skge->autoneg = ecmd->autoneg; + if (ecmd->rx_pause && ecmd->tx_pause) + skge->flow_control = FLOW_MODE_SYMMETRIC; + else if (ecmd->rx_pause && !ecmd->tx_pause) + skge->flow_control = FLOW_MODE_REM_SEND; + else if (!ecmd->rx_pause && ecmd->tx_pause) + skge->flow_control = FLOW_MODE_LOC_SEND; + else + skge->flow_control = FLOW_MODE_NONE; + + if (netif_running(dev)) { + skge_down(dev); + skge_up(dev); + } + return 0; +} + +/* Chip internal frequency for clock calculations */ +static inline u32 hwkhz(const struct skge_hw *hw) +{ + if (hw->chip_id == CHIP_ID_GENESIS) + return 53215; /* or: 53.125 MHz */ + else + return 78215; /* or: 78.125 MHz */ +} + +/* Chip hz to microseconds */ +static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks) +{ + return (ticks * 1000) / hwkhz(hw); +} + +/* Microseconds to chip hz */ +static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec) +{ + return hwkhz(hw) * usec / 1000; +} + +static int skge_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + + ecmd->rx_coalesce_usecs = 0; + ecmd->tx_coalesce_usecs = 0; + + if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) { + u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI)); + u32 msk = skge_read32(hw, B2_IRQM_MSK); + + if (msk & rxirqmask[port]) + ecmd->rx_coalesce_usecs = delay; + if (msk & txirqmask[port]) + ecmd->tx_coalesce_usecs = delay; + } + + return 0; +} + +/* Note: interrupt timer is per board, but can turn on/off per port */ +static int skge_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ecmd) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + u32 msk = skge_read32(hw, B2_IRQM_MSK); + u32 delay = 25; + + if (ecmd->rx_coalesce_usecs == 0) + msk &= ~rxirqmask[port]; + else if (ecmd->rx_coalesce_usecs < 25 || + ecmd->rx_coalesce_usecs > 33333) + return -EINVAL; + else { + msk |= rxirqmask[port]; + delay = ecmd->rx_coalesce_usecs; + } + + if (ecmd->tx_coalesce_usecs == 0) + msk &= ~txirqmask[port]; + else if (ecmd->tx_coalesce_usecs < 25 || + ecmd->tx_coalesce_usecs > 33333) + return -EINVAL; + else { + msk |= txirqmask[port]; + delay = min(delay, ecmd->rx_coalesce_usecs); + } + + skge_write32(hw, B2_IRQM_MSK, msk); + if (msk == 0) + skge_write32(hw, B2_IRQM_CTRL, TIM_STOP); + else { + skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay)); + skge_write32(hw, B2_IRQM_CTRL, TIM_START); + } + return 0; +} + +enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; +static void skge_led(struct skge_port *skge, enum led_mode mode) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + + spin_lock_bh(&hw->phy_lock); + if (hw->chip_id == CHIP_ID_GENESIS) { + switch (mode) { + case LED_MODE_OFF: + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + break; + + case LED_MODE_ON: + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); + + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); + + break; + + case LED_MODE_TST: + skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); + break; + } + } else { + switch (mode) { + case LED_MODE_OFF: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_OFF) | + PHY_M_LED_MO_10(MO_LED_OFF) | + PHY_M_LED_MO_100(MO_LED_OFF) | + PHY_M_LED_MO_1000(MO_LED_OFF) | + PHY_M_LED_MO_RX(MO_LED_OFF)); + break; + case LED_MODE_ON: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, + PHY_M_LED_PULS_DUR(PULS_170MS) | + PHY_M_LED_BLINK_RT(BLINK_84MS) | + PHY_M_LEDC_TX_CTRL | + PHY_M_LEDC_DP_CTRL); + + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_RX(MO_LED_OFF) | + (skge->speed == SPEED_100 ? + PHY_M_LED_MO_100(MO_LED_ON) : 0)); + break; + case LED_MODE_TST: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_ON) | + PHY_M_LED_MO_10(MO_LED_ON) | + PHY_M_LED_MO_100(MO_LED_ON) | + PHY_M_LED_MO_1000(MO_LED_ON) | + PHY_M_LED_MO_RX(MO_LED_ON)); + } + } + spin_unlock_bh(&hw->phy_lock); +} + +/* blink LED's for finding board */ +static int skge_phys_id(struct net_device *dev, u32 data) +{ + struct skge_port *skge = netdev_priv(dev); + unsigned long ms; + enum led_mode mode = LED_MODE_TST; + + if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; + else + ms = data * 1000; + + while (ms > 0) { + skge_led(skge, mode); + mode ^= LED_MODE_TST; + + if (msleep_interruptible(BLINK_MS)) + break; + ms -= BLINK_MS; + } + + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); + + return 0; +} + +static struct ethtool_ops skge_ethtool_ops = { + .get_settings = skge_get_settings, + .set_settings = skge_set_settings, + .get_drvinfo = skge_get_drvinfo, + .get_regs_len = skge_get_regs_len, + .get_regs = skge_get_regs, + .get_wol = skge_get_wol, + .set_wol = skge_set_wol, + .get_msglevel = skge_get_msglevel, + .set_msglevel = skge_set_msglevel, + .nway_reset = skge_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = skge_get_ring_param, + .set_ringparam = skge_set_ring_param, + .get_pauseparam = skge_get_pauseparam, + .set_pauseparam = skge_set_pauseparam, + .get_coalesce = skge_get_coalesce, + .set_coalesce = skge_set_coalesce, + .get_sg = ethtool_op_get_sg, + .set_sg = skge_set_sg, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = skge_set_tx_csum, + .get_rx_csum = skge_get_rx_csum, + .set_rx_csum = skge_set_rx_csum, + .get_strings = skge_get_strings, + .phys_id = skge_phys_id, + .get_stats_count = skge_get_stats_count, + .get_ethtool_stats = skge_get_ethtool_stats, +}; + +/* + * Allocate ring elements and chain them together + * One-to-one association of board descriptors with ring elements + */ +static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base) +{ + struct skge_tx_desc *d; + struct skge_element *e; + int i; + + ring->start = kmalloc(sizeof(*e)*ring->count, GFP_KERNEL); + if (!ring->start) + return -ENOMEM; + + for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) { + e->desc = d; + e->skb = NULL; + if (i == ring->count - 1) { + e->next = ring->start; + d->next_offset = base; + } else { + e->next = e + 1; + d->next_offset = base + (i+1) * sizeof(*d); + } + } + ring->to_use = ring->to_clean = ring->start; + + return 0; +} + +static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size) +{ + struct sk_buff *skb = dev_alloc_skb(size); + + if (likely(skb)) { + skb->dev = dev; + skb_reserve(skb, NET_IP_ALIGN); + } + return skb; +} + +/* Allocate and setup a new buffer for receiving */ +static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, + struct sk_buff *skb, unsigned int bufsize) +{ + struct skge_rx_desc *rd = e->desc; + u64 map; + + map = pci_map_single(skge->hw->pdev, skb->data, bufsize, + PCI_DMA_FROMDEVICE); + + rd->dma_lo = map; + rd->dma_hi = map >> 32; + e->skb = skb; + rd->csum1_start = ETH_HLEN; + rd->csum2_start = ETH_HLEN; + rd->csum1 = 0; + rd->csum2 = 0; + + wmb(); + + rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; + pci_unmap_addr_set(e, mapaddr, map); + pci_unmap_len_set(e, maplen, bufsize); +} + +/* Resume receiving using existing skb, + * Note: DMA address is not changed by chip. + * MTU not changed while receiver active. + */ +static void skge_rx_reuse(struct skge_element *e, unsigned int size) +{ + struct skge_rx_desc *rd = e->desc; + + rd->csum2 = 0; + rd->csum2_start = ETH_HLEN; + + wmb(); + + rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size; +} + + +/* Free all buffers in receive ring, assumes receiver stopped */ +static void skge_rx_clean(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + struct skge_ring *ring = &skge->rx_ring; + struct skge_element *e; + + e = ring->start; + do { + struct skge_rx_desc *rd = e->desc; + rd->control = 0; + if (e->skb) { + pci_unmap_single(hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_FROMDEVICE); + dev_kfree_skb(e->skb); + e->skb = NULL; + } + } while ((e = e->next) != ring->start); +} + + +/* Allocate buffers for receive ring + * For receive: to_clean is next received frame. + */ +static int skge_rx_fill(struct skge_port *skge) +{ + struct skge_ring *ring = &skge->rx_ring; + struct skge_element *e; + unsigned int bufsize = skge->rx_buf_size; + + e = ring->start; + do { + struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize); + + if (!skb) + return -ENOMEM; + + skge_rx_setup(skge, e, skb, bufsize); + } while ( (e = e->next) != ring->start); + + ring->to_clean = ring->start; + return 0; +} + +static void skge_link_up(struct skge_port *skge) +{ + netif_carrier_on(skge->netdev); + if (skge->tx_avail > MAX_SKB_FRAGS + 1) + netif_wake_queue(skge->netdev); + + if (netif_msg_link(skge)) + printk(KERN_INFO PFX + "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", + skge->netdev->name, skge->speed, + skge->duplex == DUPLEX_FULL ? "full" : "half", + (skge->flow_control == FLOW_MODE_NONE) ? "none" : + (skge->flow_control == FLOW_MODE_LOC_SEND) ? "tx only" : + (skge->flow_control == FLOW_MODE_REM_SEND) ? "rx only" : + (skge->flow_control == FLOW_MODE_SYMMETRIC) ? "tx and rx" : + "unknown"); +} + +static void skge_link_down(struct skge_port *skge) +{ + netif_carrier_off(skge->netdev); + netif_stop_queue(skge->netdev); + + if (netif_msg_link(skge)) + printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); +} + +static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) +{ + int i; + u16 v; + + xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); + v = xm_read16(hw, port, XM_PHY_DATA); + + /* Need to wait for external PHY */ + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + if (xm_read16(hw, port, XM_MMU_CMD) + & XM_MMU_PHY_RDY) + goto ready; + } + + printk(KERN_WARNING PFX "%s: phy read timed out\n", + hw->dev[port]->name); + return 0; + ready: + v = xm_read16(hw, port, XM_PHY_DATA); + + return v; +} + +static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +{ + int i; + + xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); + for (i = 0; i < PHY_RETRIES; i++) { + if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) + goto ready; + udelay(1); + } + printk(KERN_WARNING PFX "%s: phy write failed to come ready\n", + hw->dev[port]->name); + + + ready: + xm_write16(hw, port, XM_PHY_DATA, val); + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) + return; + } + printk(KERN_WARNING PFX "%s: phy write timed out\n", + hw->dev[port]->name); +} + +static void genesis_init(struct skge_hw *hw) +{ + /* set blink source counter */ + skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100); + skge_write8(hw, B2_BSC_CTRL, BSC_START); + + /* configure mac arbiter */ + skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); + + /* configure mac arbiter timeout values */ + skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53); + skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53); + skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53); + skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53); + + skge_write8(hw, B3_MA_RCINI_RX1, 0); + skge_write8(hw, B3_MA_RCINI_RX2, 0); + skge_write8(hw, B3_MA_RCINI_TX1, 0); + skge_write8(hw, B3_MA_RCINI_TX2, 0); + + /* configure packet arbiter timeout */ + skge_write16(hw, B3_PA_CTRL, PA_RST_CLR); + skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); + skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); + skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); + skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); +} + +static void genesis_reset(struct skge_hw *hw, int port) +{ + const u8 zero[8] = { 0 }; + + /* reset the statistics module */ + xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); + xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ + xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ + xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ + xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ + + /* disable Broadcom PHY IRQ */ + xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); + + xm_outhash(hw, port, XM_HSM, zero); +} + + +/* Convert mode to MII values */ +static const u16 phy_pause_map[] = { + [FLOW_MODE_NONE] = 0, + [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, + [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, + [FLOW_MODE_REM_SEND] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, +}; + + +/* Check status of Broadcom phy link */ +static void bcom_check_link(struct skge_hw *hw, int port) +{ + struct net_device *dev = hw->dev[port]; + struct skge_port *skge = netdev_priv(dev); + u16 status; + + /* read twice because of latch */ + (void) xm_phy_read(hw, port, PHY_BCOM_STAT); + status = xm_phy_read(hw, port, PHY_BCOM_STAT); + + pr_debug("bcom_check_link status=0x%x\n", status); + + if ((status & PHY_ST_LSYNC) == 0) { + u16 cmd = xm_read16(hw, port, XM_MMU_CMD); + cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); + xm_write16(hw, port, XM_MMU_CMD, cmd); + /* dummy read to ensure writing */ + (void) xm_read16(hw, port, XM_MMU_CMD); + + if (netif_carrier_ok(dev)) + skge_link_down(skge); + } else { + if (skge->autoneg == AUTONEG_ENABLE && + (status & PHY_ST_AN_OVER)) { + u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP); + u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); + + if (lpa & PHY_B_AN_RF) { + printk(KERN_NOTICE PFX "%s: remote fault\n", + dev->name); + return; + } + + /* Check Duplex mismatch */ + switch (aux & PHY_B_AS_AN_RES_MSK) { + case PHY_B_RES_1000FD: + skge->duplex = DUPLEX_FULL; + break; + case PHY_B_RES_1000HD: + skge->duplex = DUPLEX_HALF; + break; + default: + printk(KERN_NOTICE PFX "%s: duplex mismatch\n", + dev->name); + return; + } + + + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + switch (aux & PHY_B_AS_PAUSE_MSK) { + case PHY_B_AS_PAUSE_MSK: + skge->flow_control = FLOW_MODE_SYMMETRIC; + break; + case PHY_B_AS_PRR: + skge->flow_control = FLOW_MODE_REM_SEND; + break; + case PHY_B_AS_PRT: + skge->flow_control = FLOW_MODE_LOC_SEND; + break; + default: + skge->flow_control = FLOW_MODE_NONE; + } + + skge->speed = SPEED_1000; + } + + if (!netif_carrier_ok(dev)) + genesis_link_up(skge); + } +} + +/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional + * Phy on for 100 or 10Mbit operation + */ +static void bcom_phy_init(struct skge_port *skge, int jumbo) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + int i; + u16 id1, r, ext, ctl; + + /* magic workaround patterns for Broadcom */ + static const struct { + u16 reg; + u16 val; + } A1hack[] = { + { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, + { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 }, + { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 }, + { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, + }, C0hack[] = { + { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, + { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, + }; + + pr_debug("bcom_phy_init\n"); + + /* read Id from external PHY (all have the same address) */ + id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); + + /* Optimize MDIO transfer by suppressing preamble. */ + r = xm_read16(hw, port, XM_MMU_CMD); + r |= XM_MMU_NO_PRE; + xm_write16(hw, port, XM_MMU_CMD,r); + + switch (id1) { + case PHY_BCOM_ID1_C0: + /* + * Workaround BCOM Errata for the C0 type. + * Write magic patterns to reserved registers. + */ + for (i = 0; i < ARRAY_SIZE(C0hack); i++) + xm_phy_write(hw, port, + C0hack[i].reg, C0hack[i].val); + + break; + case PHY_BCOM_ID1_A1: + /* + * Workaround BCOM Errata for the A1 type. + * Write magic patterns to reserved registers. + */ + for (i = 0; i < ARRAY_SIZE(A1hack); i++) + xm_phy_write(hw, port, + A1hack[i].reg, A1hack[i].val); + break; + } + + /* + * Workaround BCOM Errata (#10523) for all BCom PHYs. + * Disable Power Management after reset. + */ + r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); + r |= PHY_B_AC_DIS_PM; + xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r); + + /* Dummy read */ + xm_read16(hw, port, XM_ISRC); + + ext = PHY_B_PEC_EN_LTR; /* enable tx led */ + ctl = PHY_CT_SP1000; /* always 1000mbit */ + + if (skge->autoneg == AUTONEG_ENABLE) { + /* + * Workaround BCOM Errata #1 for the C5 type. + * 1000Base-T Link Acquisition Failure in Slave Mode + * Set Repeater/DTE bit 10 of the 1000Base-T Control Register + */ + u16 adv = PHY_B_1000C_RD; + if (skge->advertising & ADVERTISED_1000baseT_Half) + adv |= PHY_B_1000C_AHD; + if (skge->advertising & ADVERTISED_1000baseT_Full) + adv |= PHY_B_1000C_AFD; + xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv); + + ctl |= PHY_CT_ANE | PHY_CT_RE_CFG; + } else { + if (skge->duplex == DUPLEX_FULL) + ctl |= PHY_CT_DUP_MD; + /* Force to slave */ + xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE); + } + + /* Set autonegotiation pause parameters */ + xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, + phy_pause_map[skge->flow_control] | PHY_AN_CSMA); + + /* Handle Jumbo frames */ + if (jumbo) { + xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, + PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); + + ext |= PHY_B_PEC_HIGH_LA; + + } + + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); + xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); + + /* Use link status change interrrupt */ + xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); + + bcom_check_link(hw, port); +} + +static void genesis_mac_init(struct skge_hw *hw, int port) +{ + struct net_device *dev = hw->dev[port]; + struct skge_port *skge = netdev_priv(dev); + int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; + int i; + u32 r; + const u8 zero[6] = { 0 }; + + /* Clear MIB counters */ + xm_write16(hw, port, XM_STAT_CMD, + XM_SC_CLR_RXC | XM_SC_CLR_TXC); + /* Clear two times according to Errata #3 */ + xm_write16(hw, port, XM_STAT_CMD, + XM_SC_CLR_RXC | XM_SC_CLR_TXC); + + /* Unreset the XMAC. */ + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + + /* + * Perform additional initialization for external PHYs, + * namely for the 1000baseTX cards that use the XMAC's + * GMII mode. + */ + /* Take external Phy out of reset */ + r = skge_read32(hw, B2_GP_IO); + if (port == 0) + r |= GP_DIR_0|GP_IO_0; + else + r |= GP_DIR_2|GP_IO_2; + + skge_write32(hw, B2_GP_IO, r); + skge_read32(hw, B2_GP_IO); + + /* Enable GMII interfac */ + xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); + + bcom_phy_init(skge, jumbo); + + /* Set Station Address */ + xm_outaddr(hw, port, XM_SA, dev->dev_addr); + + /* We don't use match addresses so clear */ + for (i = 1; i < 16; i++) + xm_outaddr(hw, port, XM_EXM(i), zero); + + /* configure Rx High Water Mark (XM_RX_HI_WM) */ + xm_write16(hw, port, XM_RX_HI_WM, 1450); + + /* We don't need the FCS appended to the packet. */ + r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS; + if (jumbo) + r |= XM_RX_BIG_PK_OK; + + if (skge->duplex == DUPLEX_HALF) { + /* + * If in manual half duplex mode the other side might be in + * full duplex mode, so ignore if a carrier extension is not seen + * on frames received + */ + r |= XM_RX_DIS_CEXT; + } + xm_write16(hw, port, XM_RX_CMD, r); + + + /* We want short frames padded to 60 bytes. */ + xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); + + /* + * Bump up the transmit threshold. This helps hold off transmit + * underruns when we're blasting traffic from both ports at once. + */ + xm_write16(hw, port, XM_TX_THR, 512); + + /* + * Enable the reception of all error frames. This is is + * a necessary evil due to the design of the XMAC. The + * XMAC's receive FIFO is only 8K in size, however jumbo + * frames can be up to 9000 bytes in length. When bad + * frame filtering is enabled, the XMAC's RX FIFO operates + * in 'store and forward' mode. For this to work, the + * entire frame has to fit into the FIFO, but that means + * that jumbo frames larger than 8192 bytes will be + * truncated. Disabling all bad frame filtering causes + * the RX FIFO to operate in streaming mode, in which + * case the XMAC will start transfering frames out of the + * RX FIFO as soon as the FIFO threshold is reached. + */ + xm_write32(hw, port, XM_MODE, XM_DEF_MODE); + + + /* + * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) + * - Enable all bits excepting 'Octets Rx OK Low CntOv' + * and 'Octets Rx OK Hi Cnt Ov'. + */ + xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK); + + /* + * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) + * - Enable all bits excepting 'Octets Tx OK Low CntOv' + * and 'Octets Tx OK Hi Cnt Ov'. + */ + xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK); + + /* Configure MAC arbiter */ + skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); + + /* configure timeout values */ + skge_write8(hw, B3_MA_TOINI_RX1, 72); + skge_write8(hw, B3_MA_TOINI_RX2, 72); + skge_write8(hw, B3_MA_TOINI_TX1, 72); + skge_write8(hw, B3_MA_TOINI_TX2, 72); + + skge_write8(hw, B3_MA_RCINI_RX1, 0); + skge_write8(hw, B3_MA_RCINI_RX2, 0); + skge_write8(hw, B3_MA_RCINI_TX1, 0); + skge_write8(hw, B3_MA_RCINI_TX2, 0); + + /* Configure Rx MAC FIFO */ + skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR); + skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT); + skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD); + + /* Configure Tx MAC FIFO */ + skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR); + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); + skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); + + if (jumbo) { + /* Enable frame flushing if jumbo frames used */ + skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); + } else { + /* enable timeout timers if normal frames */ + skge_write16(hw, B3_PA_CTRL, + (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); + } +} + +static void genesis_stop(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + u32 reg; + + /* Clear Tx packet arbiter timeout IRQ */ + skge_write16(hw, B3_PA_CTRL, + port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); + + /* + * If the transfer stucks at the MAC the STOP command will not + * terminate if we don't flush the XMAC's transmit FIFO ! + */ + xm_write32(hw, port, XM_MODE, + xm_read32(hw, port, XM_MODE)|XM_MD_FTF); + + + /* Reset the MAC */ + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + + /* For external PHYs there must be special handling */ + reg = skge_read32(hw, B2_GP_IO); + if (port == 0) { + reg |= GP_DIR_0; + reg &= ~GP_IO_0; + } else { + reg |= GP_DIR_2; + reg &= ~GP_IO_2; + } + skge_write32(hw, B2_GP_IO, reg); + skge_read32(hw, B2_GP_IO); + + xm_write16(hw, port, XM_MMU_CMD, + xm_read16(hw, port, XM_MMU_CMD) + & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); + + xm_read16(hw, port, XM_MMU_CMD); +} + + +static void genesis_get_stats(struct skge_port *skge, u64 *data) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + int i; + unsigned long timeout = jiffies + HZ; + + xm_write16(hw, port, + XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); + + /* wait for update to complete */ + while (xm_read16(hw, port, XM_STAT_CMD) + & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) { + if (time_after(jiffies, timeout)) + break; + udelay(10); + } + + /* special case for 64 bit octet counter */ + data[0] = (u64) xm_read32(hw, port, XM_TXO_OK_HI) << 32 + | xm_read32(hw, port, XM_TXO_OK_LO); + data[1] = (u64) xm_read32(hw, port, XM_RXO_OK_HI) << 32 + | xm_read32(hw, port, XM_RXO_OK_LO); + + for (i = 2; i < ARRAY_SIZE(skge_stats); i++) + data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset); +} + +static void genesis_mac_intr(struct skge_hw *hw, int port) +{ + struct skge_port *skge = netdev_priv(hw->dev[port]); + u16 status = xm_read16(hw, port, XM_ISRC); + + if (netif_msg_intr(skge)) + printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", + skge->netdev->name, status); + + if (status & XM_IS_TXF_UR) { + xm_write32(hw, port, XM_MODE, XM_MD_FTF); + ++skge->net_stats.tx_fifo_errors; + } + if (status & XM_IS_RXF_OV) { + xm_write32(hw, port, XM_MODE, XM_MD_FRF); + ++skge->net_stats.rx_fifo_errors; + } +} + +static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +{ + int i; + + gma_write16(hw, port, GM_SMI_DATA, val); + gma_write16(hw, port, GM_SMI_CTRL, + GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + + if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) + break; + } +} + +static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) +{ + int i; + + gma_write16(hw, port, GM_SMI_CTRL, + GM_SMI_CT_PHY_AD(hw->phy_addr) + | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); + + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) + goto ready; + } + + printk(KERN_WARNING PFX "%s: phy read timeout\n", + hw->dev[port]->name); + return 0; + ready: + return gma_read16(hw, port, GM_SMI_DATA); +} + +static void genesis_link_up(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + u16 cmd; + u32 mode, msk; + + pr_debug("genesis_link_up\n"); + cmd = xm_read16(hw, port, XM_MMU_CMD); + + /* + * enabling pause frame reception is required for 1000BT + * because the XMAC is not reset if the link is going down + */ + if (skge->flow_control == FLOW_MODE_NONE || + skge->flow_control == FLOW_MODE_LOC_SEND) + /* Disable Pause Frame Reception */ + cmd |= XM_MMU_IGN_PF; + else + /* Enable Pause Frame Reception */ + cmd &= ~XM_MMU_IGN_PF; + + xm_write16(hw, port, XM_MMU_CMD, cmd); + + mode = xm_read32(hw, port, XM_MODE); + if (skge->flow_control == FLOW_MODE_SYMMETRIC || + skge->flow_control == FLOW_MODE_LOC_SEND) { + /* + * Configure Pause Frame Generation + * Use internal and external Pause Frame Generation. + * Sending pause frames is edge triggered. + * Send a Pause frame with the maximum pause time if + * internal oder external FIFO full condition occurs. + * Send a zero pause time frame to re-start transmission. + */ + /* XM_PAUSE_DA = '010000C28001' (default) */ + /* XM_MAC_PTIME = 0xffff (maximum) */ + /* remember this value is defined in big endian (!) */ + xm_write16(hw, port, XM_MAC_PTIME, 0xffff); + + mode |= XM_PAUSE_MODE; + skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE); + } else { + /* + * disable pause frame generation is required for 1000BT + * because the XMAC is not reset if the link is going down + */ + /* Disable Pause Mode in Mode Register */ + mode &= ~XM_PAUSE_MODE; + + skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE); + } + + xm_write32(hw, port, XM_MODE, mode); + + msk = XM_DEF_MSK; + /* disable GP0 interrupt bit for external Phy */ + msk |= XM_IS_INP_ASS; + + xm_write16(hw, port, XM_IMSK, msk); + xm_read16(hw, port, XM_ISRC); + + /* get MMU Command Reg. */ + cmd = xm_read16(hw, port, XM_MMU_CMD); + if (skge->duplex == DUPLEX_FULL) + cmd |= XM_MMU_GMII_FD; + + /* + * Workaround BCOM Errata (#10523) for all BCom Phys + * Enable Power Management after link up + */ + xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, + xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) + & ~PHY_B_AC_DIS_PM); + xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); + + /* enable Rx/Tx */ + xm_write16(hw, port, XM_MMU_CMD, + cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX); + skge_link_up(skge); +} + + +static inline void bcom_phy_intr(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + u16 isrc; + + isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); + if (netif_msg_intr(skge)) + printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x\n", + skge->netdev->name, isrc); + + if (isrc & PHY_B_IS_PSE) + printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n", + hw->dev[port]->name); + + /* Workaround BCom Errata: + * enable and disable loopback mode if "NO HCD" occurs. + */ + if (isrc & PHY_B_IS_NO_HDCL) { + u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); + xm_phy_write(hw, port, PHY_BCOM_CTRL, + ctrl | PHY_CT_LOOP); + xm_phy_write(hw, port, PHY_BCOM_CTRL, + ctrl & ~PHY_CT_LOOP); + } + + if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) + bcom_check_link(hw, port); + +} + +/* Marvell Phy Initailization */ +static void yukon_init(struct skge_hw *hw, int port) +{ + struct skge_port *skge = netdev_priv(hw->dev[port]); + u16 ctrl, ct1000, adv; + + pr_debug("yukon_init\n"); + if (skge->autoneg == AUTONEG_ENABLE) { + u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); + + ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | + PHY_M_EC_MAC_S_MSK); + ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); + + ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); + + gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); + } + + ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); + if (skge->autoneg == AUTONEG_DISABLE) + ctrl &= ~PHY_CT_ANE; + + ctrl |= PHY_CT_RESET; + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + + ctrl = 0; + ct1000 = 0; + adv = PHY_AN_CSMA; + + if (skge->autoneg == AUTONEG_ENABLE) { + if (iscopper(hw)) { + if (skge->advertising & ADVERTISED_1000baseT_Full) + ct1000 |= PHY_M_1000C_AFD; + if (skge->advertising & ADVERTISED_1000baseT_Half) + ct1000 |= PHY_M_1000C_AHD; + if (skge->advertising & ADVERTISED_100baseT_Full) + adv |= PHY_M_AN_100_FD; + if (skge->advertising & ADVERTISED_100baseT_Half) + adv |= PHY_M_AN_100_HD; + if (skge->advertising & ADVERTISED_10baseT_Full) + adv |= PHY_M_AN_10_FD; + if (skge->advertising & ADVERTISED_10baseT_Half) + adv |= PHY_M_AN_10_HD; + } else /* special defines for FIBER (88E1011S only) */ + adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; + + /* Set Flow-control capabilities */ + adv |= phy_pause_map[skge->flow_control]; + + /* Restart Auto-negotiation */ + ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; + } else { + /* forced speed/duplex settings */ + ct1000 = PHY_M_1000C_MSE; + + if (skge->duplex == DUPLEX_FULL) + ctrl |= PHY_CT_DUP_MD; + + switch (skge->speed) { + case SPEED_1000: + ctrl |= PHY_CT_SP1000; + break; + case SPEED_100: + ctrl |= PHY_CT_SP100; + break; + } + + ctrl |= PHY_CT_RESET; + } + + gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); + + gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + + /* Enable phy interrupt on autonegotiation complete (or link up) */ + if (skge->autoneg == AUTONEG_ENABLE) + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); + else + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); +} + +static void yukon_reset(struct skge_hw *hw, int port) +{ + gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */ + gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ + gma_write16(hw, port, GM_MC_ADDR_H2, 0); + gma_write16(hw, port, GM_MC_ADDR_H3, 0); + gma_write16(hw, port, GM_MC_ADDR_H4, 0); + + gma_write16(hw, port, GM_RX_CTRL, + gma_read16(hw, port, GM_RX_CTRL) + | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); +} + +static void yukon_mac_init(struct skge_hw *hw, int port) +{ + struct skge_port *skge = netdev_priv(hw->dev[port]); + int i; + u32 reg; + const u8 *addr = hw->dev[port]->dev_addr; + + /* WA code for COMA mode -- set PHY reset */ + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) + skge_write32(hw, B2_GP_IO, + (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); + + /* hard reset */ + skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); + + /* WA code for COMA mode -- clear PHY reset */ + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) + skge_write32(hw, B2_GP_IO, + (skge_read32(hw, B2_GP_IO) | GP_DIR_9) + & ~GP_IO_9); + + /* Set hardware config mode */ + reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | + GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE; + reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB; + + /* Clear GMC reset */ + skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET); + skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + if (skge->autoneg == AUTONEG_DISABLE) { + reg = GM_GPCR_AU_ALL_DIS; + gma_write16(hw, port, GM_GP_CTRL, + gma_read16(hw, port, GM_GP_CTRL) | reg); + + switch (skge->speed) { + case SPEED_1000: + reg |= GM_GPCR_SPEED_1000; + /* fallthru */ + case SPEED_100: + reg |= GM_GPCR_SPEED_100; + } + + if (skge->duplex == DUPLEX_FULL) + reg |= GM_GPCR_DUP_FULL; + } else + reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; + switch (skge->flow_control) { + case FLOW_MODE_NONE: + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; + break; + case FLOW_MODE_LOC_SEND: + /* disable Rx flow-control */ + reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; + } + + gma_write16(hw, port, GM_GP_CTRL, reg); + skge_read16(hw, GMAC_IRQ_SRC); + + yukon_init(hw, port); + + /* MIB clear */ + reg = gma_read16(hw, port, GM_PHY_ADDR); + gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); + + for (i = 0; i < GM_MIB_CNT_SIZE; i++) + gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i); + gma_write16(hw, port, GM_PHY_ADDR, reg); + + /* transmit control */ + gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); + + /* receive control reg: unicast + multicast + no FCS */ + gma_write16(hw, port, GM_RX_CTRL, + GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); + + /* transmit flow control */ + gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); + + /* transmit parameter */ + gma_write16(hw, port, GM_TX_PARAM, + TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | + TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | + TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); + + /* serial mode register */ + reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); + if (hw->dev[port]->mtu > 1500) + reg |= GM_SMOD_JUMBO_ENA; + + gma_write16(hw, port, GM_SERIAL_MODE, reg); + + /* physical address: used for pause frames */ + gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); + /* virtual address for data */ + gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); + + /* enable interrupt mask for counter overflows */ + gma_write16(hw, port, GM_TX_IRQ_MSK, 0); + gma_write16(hw, port, GM_RX_IRQ_MSK, 0); + gma_write16(hw, port, GM_TR_IRQ_MSK, 0); + + /* Initialize Mac Fifo */ + + /* Configure Rx MAC FIFO */ + skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); + reg = GMF_OPER_ON | GMF_RX_F_FL_ON; + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) + reg &= ~GMF_RX_F_FL_ON; + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); + skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); + skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); + + /* Configure Tx MAC FIFO */ + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); + skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); +} + +static void yukon_stop(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { + skge_write32(hw, B2_GP_IO, + skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); + } + + gma_write16(hw, port, GM_GP_CTRL, + gma_read16(hw, port, GM_GP_CTRL) + & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); + gma_read16(hw, port, GM_GP_CTRL); + + /* set GPHY Control reset */ + skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); +} + +static void yukon_get_stats(struct skge_port *skge, u64 *data) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + int i; + + data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 + | gma_read32(hw, port, GM_TXO_OK_LO); + data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32 + | gma_read32(hw, port, GM_RXO_OK_LO); + + for (i = 2; i < ARRAY_SIZE(skge_stats); i++) + data[i] = gma_read32(hw, port, + skge_stats[i].gma_offset); +} + +static void yukon_mac_intr(struct skge_hw *hw, int port) +{ + struct net_device *dev = hw->dev[port]; + struct skge_port *skge = netdev_priv(dev); + u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); + + if (netif_msg_intr(skge)) + printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", + dev->name, status); + + if (status & GM_IS_RX_FF_OR) { + ++skge->net_stats.rx_fifo_errors; + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); + } + + if (status & GM_IS_TX_FF_UR) { + ++skge->net_stats.tx_fifo_errors; + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); + } + +} + +static u16 yukon_speed(const struct skge_hw *hw, u16 aux) +{ + switch (aux & PHY_M_PS_SPEED_MSK) { + case PHY_M_PS_SPEED_1000: + return SPEED_1000; + case PHY_M_PS_SPEED_100: + return SPEED_100; + default: + return SPEED_10; + } +} + +static void yukon_link_up(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + u16 reg; + + pr_debug("yukon_link_up\n"); + + /* Enable Transmit FIFO Underrun */ + skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK); + + reg = gma_read16(hw, port, GM_GP_CTRL); + if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) + reg |= GM_GPCR_DUP_FULL; + + /* enable Rx/Tx */ + reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; + gma_write16(hw, port, GM_GP_CTRL, reg); + + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); + skge_link_up(skge); +} + +static void yukon_link_down(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + u16 ctrl; + + pr_debug("yukon_link_down\n"); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); + + ctrl = gma_read16(hw, port, GM_GP_CTRL); + ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + gma_write16(hw, port, GM_GP_CTRL, ctrl); + + if (skge->flow_control == FLOW_MODE_REM_SEND) { + /* restore Asymmetric Pause bit */ + gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, + gm_phy_read(hw, port, + PHY_MARV_AUNE_ADV) + | PHY_M_AN_ASP); + + } + + yukon_reset(hw, port); + skge_link_down(skge); + + yukon_init(hw, port); +} + +static void yukon_phy_intr(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + const char *reason = NULL; + u16 istatus, phystat; + + istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); + phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); + + if (netif_msg_intr(skge)) + printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x 0x%x\n", + skge->netdev->name, istatus, phystat); + + if (istatus & PHY_M_IS_AN_COMPL) { + if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP) + & PHY_M_AN_RF) { + reason = "remote fault"; + goto failed; + } + + if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) { + reason = "master/slave fault"; + goto failed; + } + + if (!(phystat & PHY_M_PS_SPDUP_RES)) { + reason = "speed/duplex"; + goto failed; + } + + skge->duplex = (phystat & PHY_M_PS_FULL_DUP) + ? DUPLEX_FULL : DUPLEX_HALF; + skge->speed = yukon_speed(hw, phystat); + + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + switch (phystat & PHY_M_PS_PAUSE_MSK) { + case PHY_M_PS_PAUSE_MSK: + skge->flow_control = FLOW_MODE_SYMMETRIC; + break; + case PHY_M_PS_RX_P_EN: + skge->flow_control = FLOW_MODE_REM_SEND; + break; + case PHY_M_PS_TX_P_EN: + skge->flow_control = FLOW_MODE_LOC_SEND; + break; + default: + skge->flow_control = FLOW_MODE_NONE; + } + + if (skge->flow_control == FLOW_MODE_NONE || + (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) + skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + else + skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); + yukon_link_up(skge); + return; + } + + if (istatus & PHY_M_IS_LSP_CHANGE) + skge->speed = yukon_speed(hw, phystat); + + if (istatus & PHY_M_IS_DUP_CHANGE) + skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; + if (istatus & PHY_M_IS_LST_CHANGE) { + if (phystat & PHY_M_PS_LINK_UP) + yukon_link_up(skge); + else + yukon_link_down(skge); + } + return; + failed: + printk(KERN_ERR PFX "%s: autonegotiation failed (%s)\n", + skge->netdev->name, reason); + + /* XXX restart autonegotiation? */ +} + +static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) +{ + u32 end; + + start /= 8; + len /= 8; + end = start + len - 1; + + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); + skge_write32(hw, RB_ADDR(q, RB_START), start); + skge_write32(hw, RB_ADDR(q, RB_WP), start); + skge_write32(hw, RB_ADDR(q, RB_RP), start); + skge_write32(hw, RB_ADDR(q, RB_END), end); + + if (q == Q_R1 || q == Q_R2) { + /* Set thresholds on receive queue's */ + skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), + start + (2*len)/3); + skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), + start + (len/3)); + } else { + /* Enable store & forward on Tx queue's because + * Tx FIFO is only 4K on Genesis and 1K on Yukon + */ + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); + } + + skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); +} + +/* Setup Bus Memory Interface */ +static void skge_qset(struct skge_port *skge, u16 q, + const struct skge_element *e) +{ + struct skge_hw *hw = skge->hw; + u32 watermark = 0x600; + u64 base = skge->dma + (e->desc - skge->mem); + + /* optimization to reduce window on 32bit/33mhz */ + if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0) + watermark /= 2; + + skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET); + skge_write32(hw, Q_ADDR(q, Q_F), watermark); + skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32)); + skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base); +} + +static int skge_up(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + u32 chunk, ram_addr; + size_t rx_size, tx_size; + int err; + + if (netif_msg_ifup(skge)) + printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + + if (dev->mtu > RX_BUF_SIZE) + skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; + else + skge->rx_buf_size = RX_BUF_SIZE; + + + rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc); + tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc); + skge->mem_size = tx_size + rx_size; + skge->mem = pci_alloc_consistent(hw->pdev, skge->mem_size, &skge->dma); + if (!skge->mem) + return -ENOMEM; + + memset(skge->mem, 0, skge->mem_size); + + if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma))) + goto free_pci_mem; + + err = skge_rx_fill(skge); + if (err) + goto free_rx_ring; + + if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, + skge->dma + rx_size))) + goto free_rx_ring; + + skge->tx_avail = skge->tx_ring.count - 1; + + /* Enable IRQ from port */ + hw->intr_mask |= portirqmask[port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + + /* Initialze MAC */ + spin_lock_bh(&hw->phy_lock); + if (hw->chip_id == CHIP_ID_GENESIS) + genesis_mac_init(hw, port); + else + yukon_mac_init(hw, port); + spin_unlock_bh(&hw->phy_lock); + + /* Configure RAMbuffers */ + chunk = hw->ram_size / ((hw->ports + 1)*2); + ram_addr = hw->ram_offset + 2 * chunk * port; + + skge_ramset(hw, rxqaddr[port], ram_addr, chunk); + skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); + + BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); + skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); + skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); + + /* Start receiver BMU */ + wmb(); + skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); + skge_led(skge, LED_MODE_ON); + + pr_debug("skge_up completed\n"); + return 0; + + free_rx_ring: + skge_rx_clean(skge); + kfree(skge->rx_ring.start); + free_pci_mem: + pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); + + return err; +} + +static int skge_down(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + + if (netif_msg_ifdown(skge)) + printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + + netif_stop_queue(dev); + + /* Stop transmitter */ + skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); + skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), + RB_RST_SET|RB_DIS_OP_MD); + + if (hw->chip_id == CHIP_ID_GENESIS) + genesis_stop(skge); + else + yukon_stop(skge); + + /* Disable Force Sync bit and Enable Alloc bit */ + skge_write8(hw, SK_REG(port, TXA_CTRL), + TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); + + /* Stop Interval Timer and Limit Counter of Tx Arbiter */ + skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); + skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); + + /* Reset PCI FIFO */ + skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET); + skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); + + /* Reset the RAM Buffer async Tx queue */ + skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET); + /* stop receiver */ + skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); + skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), + RB_RST_SET|RB_DIS_OP_MD); + skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); + + if (hw->chip_id == CHIP_ID_GENESIS) { + skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); + skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); + } else { + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); + } + + skge_led(skge, LED_MODE_OFF); + + skge_tx_clean(skge); + skge_rx_clean(skge); + + kfree(skge->rx_ring.start); + kfree(skge->tx_ring.start); + pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); + return 0; +} + +static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + struct skge_ring *ring = &skge->tx_ring; + struct skge_element *e; + struct skge_tx_desc *td; + int i; + u32 control, len; + u64 map; + unsigned long flags; + + skb = skb_padto(skb, ETH_ZLEN); + if (!skb) + return NETDEV_TX_OK; + + local_irq_save(flags); + if (!spin_trylock(&skge->tx_lock)) { + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } + + if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { + netif_stop_queue(dev); + spin_unlock_irqrestore(&skge->tx_lock, flags); + + printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", + dev->name); + return NETDEV_TX_BUSY; + } + + e = ring->to_use; + td = e->desc; + e->skb = skb; + len = skb_headlen(skb); + map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(e, mapaddr, map); + pci_unmap_len_set(e, maplen, len); + + td->dma_lo = map; + td->dma_hi = map >> 32; + + if (skb->ip_summed == CHECKSUM_HW) { + const struct iphdr *ip + = (const struct iphdr *) (skb->data + ETH_HLEN); + int offset = skb->h.raw - skb->data; + + /* This seems backwards, but it is what the sk98lin + * does. Looks like hardware is wrong? + */ + if (ip->protocol == IPPROTO_UDP + && hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) + control = BMU_TCP_CHECK; + else + control = BMU_UDP_CHECK; + + td->csum_offs = 0; + td->csum_start = offset; + td->csum_write = offset + skb->csum; + } else + control = BMU_CHECK; + + if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */ + control |= BMU_EOF| BMU_IRQ_EOF; + else { + struct skge_tx_desc *tf = td; + + control |= BMU_STFWD; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + map = pci_map_page(hw->pdev, frag->page, frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + + e = e->next; + e->skb = NULL; + tf = e->desc; + tf->dma_lo = map; + tf->dma_hi = (u64) map >> 32; + pci_unmap_addr_set(e, mapaddr, map); + pci_unmap_len_set(e, maplen, frag->size); + + tf->control = BMU_OWN | BMU_SW | control | frag->size; + } + tf->control |= BMU_EOF | BMU_IRQ_EOF; + } + /* Make sure all the descriptors written */ + wmb(); + td->control = BMU_OWN | BMU_SW | BMU_STF | control | len; + wmb(); + + skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); + + if (netif_msg_tx_queued(skge)) + printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n", + dev->name, e - ring->start, skb->len); + + ring->to_use = e->next; + skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1; + if (skge->tx_avail <= MAX_SKB_FRAGS + 1) { + pr_debug("%s: transmit queue full\n", dev->name); + netif_stop_queue(dev); + } + + dev->trans_start = jiffies; + spin_unlock_irqrestore(&skge->tx_lock, flags); + + return NETDEV_TX_OK; +} + +static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) +{ + /* This ring element can be skb or fragment */ + if (e->skb) { + pci_unmap_single(hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_TODEVICE); + dev_kfree_skb_any(e->skb); + e->skb = NULL; + } else { + pci_unmap_page(hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_TODEVICE); + } +} + +static void skge_tx_clean(struct skge_port *skge) +{ + struct skge_ring *ring = &skge->tx_ring; + struct skge_element *e; + unsigned long flags; + + spin_lock_irqsave(&skge->tx_lock, flags); + for (e = ring->to_clean; e != ring->to_use; e = e->next) { + ++skge->tx_avail; + skge_tx_free(skge->hw, e); + } + ring->to_clean = e; + spin_unlock_irqrestore(&skge->tx_lock, flags); +} + +static void skge_tx_timeout(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + + if (netif_msg_timer(skge)) + printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name); + + skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP); + skge_tx_clean(skge); +} + +static int skge_change_mtu(struct net_device *dev, int new_mtu) +{ + int err = 0; + int running = netif_running(dev); + + if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) + return -EINVAL; + + + if (running) + skge_down(dev); + dev->mtu = new_mtu; + if (running) + skge_up(dev); + + return err; +} + +static void genesis_set_multicast(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + int i, count = dev->mc_count; + struct dev_mc_list *list = dev->mc_list; + u32 mode; + u8 filter[8]; + + pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count); + + mode = xm_read32(hw, port, XM_MODE); + mode |= XM_MD_ENA_HASH; + if (dev->flags & IFF_PROMISC) + mode |= XM_MD_ENA_PROM; + else + mode &= ~XM_MD_ENA_PROM; + + if (dev->flags & IFF_ALLMULTI) + memset(filter, 0xff, sizeof(filter)); + else { + memset(filter, 0, sizeof(filter)); + for (i = 0; list && i < count; i++, list = list->next) { + u32 crc, bit; + crc = ether_crc_le(ETH_ALEN, list->dmi_addr); + bit = ~crc & 0x3f; + filter[bit/8] |= 1 << (bit%8); + } + } + + xm_write32(hw, port, XM_MODE, mode); + xm_outhash(hw, port, XM_HSM, filter); +} + +static void yukon_set_multicast(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int port = skge->port; + struct dev_mc_list *list = dev->mc_list; + u16 reg; + u8 filter[8]; + + memset(filter, 0, sizeof(filter)); + + reg = gma_read16(hw, port, GM_RX_CTRL); + reg |= GM_RXCR_UCF_ENA; + + if (dev->flags & IFF_PROMISC) /* promiscious */ + reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + else if (dev->flags & IFF_ALLMULTI) /* all multicast */ + memset(filter, 0xff, sizeof(filter)); + else if (dev->mc_count == 0) /* no multicast */ + reg &= ~GM_RXCR_MCF_ENA; + else { + int i; + reg |= GM_RXCR_MCF_ENA; + + for (i = 0; list && i < dev->mc_count; i++, list = list->next) { + u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; + filter[bit/8] |= 1 << (bit%8); + } + } + + + gma_write16(hw, port, GM_MC_ADDR_H1, + (u16)filter[0] | ((u16)filter[1] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H2, + (u16)filter[2] | ((u16)filter[3] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H3, + (u16)filter[4] | ((u16)filter[5] << 8)); + gma_write16(hw, port, GM_MC_ADDR_H4, + (u16)filter[6] | ((u16)filter[7] << 8)); + + gma_write16(hw, port, GM_RX_CTRL, reg); +} + +static inline int bad_phy_status(const struct skge_hw *hw, u32 status) +{ + if (hw->chip_id == CHIP_ID_GENESIS) + return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0; + else + return (status & GMR_FS_ANY_ERR) || + (status & GMR_FS_RX_OK) == 0; +} + +static void skge_rx_error(struct skge_port *skge, int slot, + u32 control, u32 status) +{ + if (netif_msg_rx_err(skge)) + printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n", + skge->netdev->name, slot, control, status); + + if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) + skge->net_stats.rx_length_errors++; + else if (skge->hw->chip_id == CHIP_ID_GENESIS) { + if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) + skge->net_stats.rx_length_errors++; + if (status & XMR_FS_FRA_ERR) + skge->net_stats.rx_frame_errors++; + if (status & XMR_FS_FCS_ERR) + skge->net_stats.rx_crc_errors++; + } else { + if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) + skge->net_stats.rx_length_errors++; + if (status & GMR_FS_FRAGMENT) + skge->net_stats.rx_frame_errors++; + if (status & GMR_FS_CRC_ERR) + skge->net_stats.rx_crc_errors++; + } +} + +/* Get receive buffer from descriptor. + * Handles copy of small buffers and reallocation failures + */ +static inline struct sk_buff *skge_rx_get(struct skge_port *skge, + struct skge_element *e, + unsigned int len) +{ + struct sk_buff *nskb, *skb; + + if (len < RX_COPY_THRESHOLD) { + nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN); + if (unlikely(!nskb)) + return NULL; + + pci_dma_sync_single_for_cpu(skge->hw->pdev, + pci_unmap_addr(e, mapaddr), + len, PCI_DMA_FROMDEVICE); + memcpy(nskb->data, e->skb->data, len); + pci_dma_sync_single_for_device(skge->hw->pdev, + pci_unmap_addr(e, mapaddr), + len, PCI_DMA_FROMDEVICE); + + if (skge->rx_csum) { + struct skge_rx_desc *rd = e->desc; + nskb->csum = le16_to_cpu(rd->csum2); + nskb->ip_summed = CHECKSUM_HW; + } + skge_rx_reuse(e, skge->rx_buf_size); + return nskb; + } else { + nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size); + if (unlikely(!nskb)) + return NULL; + + pci_unmap_single(skge->hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_FROMDEVICE); + skb = e->skb; + if (skge->rx_csum) { + struct skge_rx_desc *rd = e->desc; + skb->csum = le16_to_cpu(rd->csum2); + skb->ip_summed = CHECKSUM_HW; + } + + skge_rx_setup(skge, e, nskb, skge->rx_buf_size); + return skb; + } +} + + +static int skge_poll(struct net_device *dev, int *budget) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + struct skge_ring *ring = &skge->rx_ring; + struct skge_element *e; + unsigned int to_do = min(dev->quota, *budget); + unsigned int work_done = 0; + + pr_debug("skge_poll\n"); + + for (e = ring->to_clean; work_done < to_do; e = e->next) { + struct skge_rx_desc *rd = e->desc; + struct sk_buff *skb; + u32 control, len, status; + + rmb(); + control = rd->control; + if (control & BMU_OWN) + break; + + len = control & BMU_BBC; + status = rd->status; + + if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF) + || bad_phy_status(hw, status))) { + skge_rx_error(skge, e - ring->start, control, status); + skge_rx_reuse(e, skge->rx_buf_size); + continue; + } + + if (netif_msg_rx_status(skge)) + printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n", + dev->name, e - ring->start, rd->status, len); + + skb = skge_rx_get(skge, e, len); + if (likely(skb)) { + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, dev); + + dev->last_rx = jiffies; + netif_receive_skb(skb); + + ++work_done; + } else + skge_rx_reuse(e, skge->rx_buf_size); + } + ring->to_clean = e; + + /* restart receiver */ + wmb(); + skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), + CSR_START | CSR_IRQ_CL_F); + + *budget -= work_done; + dev->quota -= work_done; + + if (work_done >= to_do) + return 1; /* not done */ + + local_irq_disable(); + __netif_rx_complete(dev); + hw->intr_mask |= portirqmask[skge->port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + local_irq_enable(); + return 0; +} + +static inline void skge_tx_intr(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + struct skge_ring *ring = &skge->tx_ring; + struct skge_element *e; + + spin_lock(&skge->tx_lock); + for (e = ring->to_clean; e != ring->to_use; e = e->next) { + struct skge_tx_desc *td = e->desc; + u32 control; + + rmb(); + control = td->control; + if (control & BMU_OWN) + break; + + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n", + dev->name, e - ring->start, td->status); + + skge_tx_free(hw, e); + e->skb = NULL; + ++skge->tx_avail; + } + ring->to_clean = e; + skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); + + if (skge->tx_avail > MAX_SKB_FRAGS + 1) + netif_wake_queue(dev); + + spin_unlock(&skge->tx_lock); +} + +/* Parity errors seem to happen when Genesis is connected to a switch + * with no other ports present. Heartbeat error?? + */ +static void skge_mac_parity(struct skge_hw *hw, int port) +{ + struct net_device *dev = hw->dev[port]; + + if (dev) { + struct skge_port *skge = netdev_priv(dev); + ++skge->net_stats.tx_heartbeat_errors; + } + + if (hw->chip_id == CHIP_ID_GENESIS) + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), + MFF_CLR_PERR); + else + /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), + (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) + ? GMF_CLI_TX_FC : GMF_CLI_TX_PE); +} + +static void skge_pci_clear(struct skge_hw *hw) +{ + u16 status; + + pci_read_config_word(hw->pdev, PCI_STATUS, &status); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + pci_write_config_word(hw->pdev, PCI_STATUS, + status | PCI_STATUS_ERROR_BITS); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); +} + +static void skge_mac_intr(struct skge_hw *hw, int port) +{ + if (hw->chip_id == CHIP_ID_GENESIS) + genesis_mac_intr(hw, port); + else + yukon_mac_intr(hw, port); +} + +/* Handle device specific framing and timeout interrupts */ +static void skge_error_irq(struct skge_hw *hw) +{ + u32 hwstatus = skge_read32(hw, B0_HWE_ISRC); + + if (hw->chip_id == CHIP_ID_GENESIS) { + /* clear xmac errors */ + if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) + skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT); + if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) + skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT); + } else { + /* Timestamp (unused) overflow */ + if (hwstatus & IS_IRQ_TIST_OV) + skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); + + if (hwstatus & IS_IRQ_SENSOR) { + /* no sensors on 32-bit Yukon */ + if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) { + printk(KERN_ERR PFX "ignoring bogus sensor interrups\n"); + skge_write32(hw, B0_HWE_IMSK, + IS_ERR_MSK & ~IS_IRQ_SENSOR); + } else + printk(KERN_WARNING PFX "sensor interrupt\n"); + } + + + } + + if (hwstatus & IS_RAM_RD_PAR) { + printk(KERN_ERR PFX "Ram read data parity error\n"); + skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR); + } + + if (hwstatus & IS_RAM_WR_PAR) { + printk(KERN_ERR PFX "Ram write data parity error\n"); + skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR); + } + + if (hwstatus & IS_M1_PAR_ERR) + skge_mac_parity(hw, 0); + + if (hwstatus & IS_M2_PAR_ERR) + skge_mac_parity(hw, 1); + + if (hwstatus & IS_R1_PAR_ERR) + skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P); + + if (hwstatus & IS_R2_PAR_ERR) + skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P); + + if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) { + printk(KERN_ERR PFX "hardware error detected (status 0x%x)\n", + hwstatus); + + skge_pci_clear(hw); + + hwstatus = skge_read32(hw, B0_HWE_ISRC); + if (hwstatus & IS_IRQ_STAT) { + printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n", + hwstatus); + hw->intr_mask &= ~IS_HW_ERR; + } + } +} + +/* + * Interrrupt from PHY are handled in tasklet (soft irq) + * because accessing phy registers requires spin wait which might + * cause excess interrupt latency. + */ +static void skge_extirq(unsigned long data) +{ + struct skge_hw *hw = (struct skge_hw *) data; + int port; + + spin_lock(&hw->phy_lock); + for (port = 0; port < 2; port++) { + struct net_device *dev = hw->dev[port]; + + if (dev && netif_running(dev)) { + struct skge_port *skge = netdev_priv(dev); + + if (hw->chip_id != CHIP_ID_GENESIS) + yukon_phy_intr(skge); + else + bcom_phy_intr(skge); + } + } + spin_unlock(&hw->phy_lock); + + local_irq_disable(); + hw->intr_mask |= IS_EXT_REG; + skge_write32(hw, B0_IMSK, hw->intr_mask); + local_irq_enable(); +} + +static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct skge_hw *hw = dev_id; + u32 status = skge_read32(hw, B0_SP_ISRC); + + if (status == 0 || status == ~0) /* hotplug or shared irq */ + return IRQ_NONE; + + status &= hw->intr_mask; + if (status & IS_R1_F) { + hw->intr_mask &= ~IS_R1_F; + netif_rx_schedule(hw->dev[0]); + } + + if (status & IS_R2_F) { + hw->intr_mask &= ~IS_R2_F; + netif_rx_schedule(hw->dev[1]); + } + + if (status & IS_XA1_F) + skge_tx_intr(hw->dev[0]); + + if (status & IS_XA2_F) + skge_tx_intr(hw->dev[1]); + + if (status & IS_PA_TO_RX1) { + struct skge_port *skge = netdev_priv(hw->dev[0]); + ++skge->net_stats.rx_over_errors; + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); + } + + if (status & IS_PA_TO_RX2) { + struct skge_port *skge = netdev_priv(hw->dev[1]); + ++skge->net_stats.rx_over_errors; + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); + } + + if (status & IS_PA_TO_TX1) + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); + + if (status & IS_PA_TO_TX2) + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); + + if (status & IS_MAC1) + skge_mac_intr(hw, 0); + + if (status & IS_MAC2) + skge_mac_intr(hw, 1); + + if (status & IS_HW_ERR) + skge_error_irq(hw); + + if (status & IS_EXT_REG) { + hw->intr_mask &= ~IS_EXT_REG; + tasklet_schedule(&hw->ext_tasklet); + } + + skge_write32(hw, B0_IMSK, hw->intr_mask); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void skge_netpoll(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + + disable_irq(dev->irq); + skge_intr(dev->irq, skge->hw, NULL); + enable_irq(dev->irq); +} +#endif + +static int skge_set_mac_address(struct net_device *dev, void *p) +{ + struct skge_port *skge = netdev_priv(dev); + struct sockaddr *addr = p; + int err = 0; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + skge_down(dev); + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8, + dev->dev_addr, ETH_ALEN); + memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8, + dev->dev_addr, ETH_ALEN); + if (dev->flags & IFF_UP) + err = skge_up(dev); + return err; +} + +static const struct { + u8 id; + const char *name; +} skge_chips[] = { + { CHIP_ID_GENESIS, "Genesis" }, + { CHIP_ID_YUKON, "Yukon" }, + { CHIP_ID_YUKON_LITE, "Yukon-Lite"}, + { CHIP_ID_YUKON_LP, "Yukon-LP"}, +}; + +static const char *skge_board_name(const struct skge_hw *hw) +{ + int i; + static char buf[16]; + + for (i = 0; i < ARRAY_SIZE(skge_chips); i++) + if (skge_chips[i].id == hw->chip_id) + return skge_chips[i].name; + + snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id); + return buf; +} + + +/* + * Setup the board data structure, but don't bring up + * the port(s) + */ +static int skge_reset(struct skge_hw *hw) +{ + u16 ctst; + u8 t8, mac_cfg; + int i; + + ctst = skge_read16(hw, B0_CTST); + + /* do a SW reset */ + skge_write8(hw, B0_CTST, CS_RST_SET); + skge_write8(hw, B0_CTST, CS_RST_CLR); + + /* clear PCI errors, if any */ + skge_pci_clear(hw); + + skge_write8(hw, B0_CTST, CS_MRST_CLR); + + /* restore CLK_RUN bits (for Yukon-Lite) */ + skge_write16(hw, B0_CTST, + ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA)); + + hw->chip_id = skge_read8(hw, B2_CHIP_ID); + hw->phy_type = skge_read8(hw, B2_E_1) & 0xf; + hw->pmd_type = skge_read8(hw, B2_PMD_TYP); + + switch (hw->chip_id) { + case CHIP_ID_GENESIS: + switch (hw->phy_type) { + case SK_PHY_BCOM: + hw->phy_addr = PHY_ADDR_BCOM; + break; + default: + printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n", + pci_name(hw->pdev), hw->phy_type); + return -EOPNOTSUPP; + } + break; + + case CHIP_ID_YUKON: + case CHIP_ID_YUKON_LITE: + case CHIP_ID_YUKON_LP: + if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S') + hw->phy_type = SK_PHY_MARV_COPPER; + + hw->phy_addr = PHY_ADDR_MARV; + if (!iscopper(hw)) + hw->phy_type = SK_PHY_MARV_FIBER; + + break; + + default: + printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", + pci_name(hw->pdev), hw->chip_id); + return -EOPNOTSUPP; + } + + mac_cfg = skge_read8(hw, B2_MAC_CFG); + hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2; + hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4; + + /* read the adapters RAM size */ + t8 = skge_read8(hw, B2_E_0); + if (hw->chip_id == CHIP_ID_GENESIS) { + if (t8 == 3) { + /* special case: 4 x 64k x 36, offset = 0x80000 */ + hw->ram_size = 0x100000; + hw->ram_offset = 0x80000; + } else + hw->ram_size = t8 * 512; + } + else if (t8 == 0) + hw->ram_size = 0x20000; + else + hw->ram_size = t8 * 4096; + + if (hw->chip_id == CHIP_ID_GENESIS) + genesis_init(hw); + else { + /* switch power to VCC (WA for VAUX problem) */ + skge_write8(hw, B0_POWER_CTRL, + PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); + for (i = 0; i < hw->ports; i++) { + skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); + skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + } + } + + /* turn off hardware timer (unused) */ + skge_write8(hw, B2_TI_CTRL, TIM_STOP); + skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ); + skge_write8(hw, B0_LED, LED_STAT_ON); + + /* enable the Tx Arbiters */ + for (i = 0; i < hw->ports; i++) + skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); + + /* Initialize ram interface */ + skge_write16(hw, B3_RI_CTRL, RI_RST_CLR); + + skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53); + skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53); + skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53); + skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53); + skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53); + skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53); + skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53); + + skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK); + + /* Set interrupt moderation for Transmit only + * Receive interrupts avoided by NAPI + */ + skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F); + skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); + skge_write32(hw, B2_IRQM_CTRL, TIM_START); + + hw->intr_mask = IS_HW_ERR | IS_EXT_REG; + skge_write32(hw, B0_IMSK, hw->intr_mask); + + if (hw->chip_id != CHIP_ID_GENESIS) + skge_write8(hw, GMAC_IRQ_MSK, 0); + + spin_lock_bh(&hw->phy_lock); + for (i = 0; i < hw->ports; i++) { + if (hw->chip_id == CHIP_ID_GENESIS) + genesis_reset(hw, i); + else + yukon_reset(hw, i); + } + spin_unlock_bh(&hw->phy_lock); + + return 0; +} + +/* Initialize network device */ +static struct net_device *skge_devinit(struct skge_hw *hw, int port, + int highmem) +{ + struct skge_port *skge; + struct net_device *dev = alloc_etherdev(sizeof(*skge)); + + if (!dev) { + printk(KERN_ERR "skge etherdev alloc failed"); + return NULL; + } + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &hw->pdev->dev); + dev->open = skge_up; + dev->stop = skge_down; + dev->hard_start_xmit = skge_xmit_frame; + dev->get_stats = skge_get_stats; + if (hw->chip_id == CHIP_ID_GENESIS) + dev->set_multicast_list = genesis_set_multicast; + else + dev->set_multicast_list = yukon_set_multicast; + + dev->set_mac_address = skge_set_mac_address; + dev->change_mtu = skge_change_mtu; + SET_ETHTOOL_OPS(dev, &skge_ethtool_ops); + dev->tx_timeout = skge_tx_timeout; + dev->watchdog_timeo = TX_WATCHDOG; + dev->poll = skge_poll; + dev->weight = NAPI_WEIGHT; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = skge_netpoll; +#endif + dev->irq = hw->pdev->irq; + dev->features = NETIF_F_LLTX; + if (highmem) + dev->features |= NETIF_F_HIGHDMA; + + skge = netdev_priv(dev); + skge->netdev = dev; + skge->hw = hw; + skge->msg_enable = netif_msg_init(debug, default_msg); + skge->tx_ring.count = DEFAULT_TX_RING_SIZE; + skge->rx_ring.count = DEFAULT_RX_RING_SIZE; + + /* Auto speed and flow control */ + skge->autoneg = AUTONEG_ENABLE; + skge->flow_control = FLOW_MODE_SYMMETRIC; + skge->duplex = -1; + skge->speed = -1; + skge->advertising = skge_supported_modes(hw); + + hw->dev[port] = dev; + + skge->port = port; + + spin_lock_init(&skge->tx_lock); + + if (hw->chip_id != CHIP_ID_GENESIS) { + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + skge->rx_csum = 1; + } + + /* read the mac address */ + memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); + + /* device is off until link detection */ + netif_carrier_off(dev); + netif_stop_queue(dev); + + return dev; +} + +static void __devinit skge_show_addr(struct net_device *dev) +{ + const struct skge_port *skge = netdev_priv(dev); + + if (netif_msg_probe(skge)) + printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); +} + +static int __devinit skge_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev, *dev1; + struct skge_hw *hw; + int err, using_dac = 0; + + if ((err = pci_enable_device(pdev))) { + printk(KERN_ERR PFX "%s cannot enable PCI device\n", + pci_name(pdev)); + goto err_out; + } + + if ((err = pci_request_regions(pdev, DRV_NAME))) { + printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", + pci_name(pdev)); + goto err_out_disable_pdev; + } + + pci_set_master(pdev); + + if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) + using_dac = 1; + else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { + printk(KERN_ERR PFX "%s no usable DMA configuration\n", + pci_name(pdev)); + goto err_out_free_regions; + } + +#ifdef __BIG_ENDIAN + /* byte swap decriptors in hardware */ + { + u32 reg; + + pci_read_config_dword(pdev, PCI_DEV_REG2, ®); + reg |= PCI_REV_DESC; + pci_write_config_dword(pdev, PCI_DEV_REG2, reg); + } +#endif + + err = -ENOMEM; + hw = kmalloc(sizeof(*hw), GFP_KERNEL); + if (!hw) { + printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", + pci_name(pdev)); + goto err_out_free_regions; + } + + memset(hw, 0, sizeof(*hw)); + hw->pdev = pdev; + spin_lock_init(&hw->phy_lock); + tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); + + hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); + if (!hw->regs) { + printk(KERN_ERR PFX "%s: cannot map device registers\n", + pci_name(pdev)); + goto err_out_free_hw; + } + + if ((err = request_irq(pdev->irq, skge_intr, SA_SHIRQ, DRV_NAME, hw))) { + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", + pci_name(pdev), pdev->irq); + goto err_out_iounmap; + } + pci_set_drvdata(pdev, hw); + + err = skge_reset(hw); + if (err) + goto err_out_free_irq; + + printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n", + pci_resource_start(pdev, 0), pdev->irq, + skge_board_name(hw), hw->chip_rev); + + if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) + goto err_out_led_off; + + if ((err = register_netdev(dev))) { + printk(KERN_ERR PFX "%s: cannot register net device\n", + pci_name(pdev)); + goto err_out_free_netdev; + } + + skge_show_addr(dev); + + if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) { + if (register_netdev(dev1) == 0) + skge_show_addr(dev1); + else { + /* Failure to register second port need not be fatal */ + printk(KERN_WARNING PFX "register of second port failed\n"); + hw->dev[1] = NULL; + free_netdev(dev1); + } + } + + return 0; + +err_out_free_netdev: + free_netdev(dev); +err_out_led_off: + skge_write16(hw, B0_LED, LED_STAT_OFF); +err_out_free_irq: + free_irq(pdev->irq, hw); +err_out_iounmap: + iounmap(hw->regs); +err_out_free_hw: + kfree(hw); +err_out_free_regions: + pci_release_regions(pdev); +err_out_disable_pdev: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +err_out: + return err; +} + +static void __devexit skge_remove(struct pci_dev *pdev) +{ + struct skge_hw *hw = pci_get_drvdata(pdev); + struct net_device *dev0, *dev1; + + if (!hw) + return; + + if ((dev1 = hw->dev[1])) + unregister_netdev(dev1); + dev0 = hw->dev[0]; + unregister_netdev(dev0); + + tasklet_kill(&hw->ext_tasklet); + + free_irq(pdev->irq, hw); + pci_release_regions(pdev); + pci_disable_device(pdev); + if (dev1) + free_netdev(dev1); + free_netdev(dev0); + skge_write16(hw, B0_LED, LED_STAT_OFF); + iounmap(hw->regs); + kfree(hw); + pci_set_drvdata(pdev, NULL); +} + +#ifdef CONFIG_PM +static int skge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct skge_hw *hw = pci_get_drvdata(pdev); + int i, wol = 0; + + for (i = 0; i < 2; i++) { + struct net_device *dev = hw->dev[i]; + + if (dev) { + struct skge_port *skge = netdev_priv(dev); + if (netif_running(dev)) { + netif_carrier_off(dev); + skge_down(dev); + } + netif_device_detach(dev); + wol |= skge->wol; + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int skge_resume(struct pci_dev *pdev) +{ + struct skge_hw *hw = pci_get_drvdata(pdev); + int i; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + + skge_reset(hw); + + for (i = 0; i < 2; i++) { + struct net_device *dev = hw->dev[i]; + if (dev) { + netif_device_attach(dev); + if (netif_running(dev)) + skge_up(dev); + } + } + return 0; +} +#endif + +static struct pci_driver skge_driver = { + .name = DRV_NAME, + .id_table = skge_id_table, + .probe = skge_probe, + .remove = __devexit_p(skge_remove), +#ifdef CONFIG_PM + .suspend = skge_suspend, + .resume = skge_resume, +#endif +}; + +static int __init skge_init_module(void) +{ + return pci_module_init(&skge_driver); +} + +static void __exit skge_cleanup_module(void) +{ + pci_unregister_driver(&skge_driver); +} + +module_init(skge_init_module); +module_exit(skge_cleanup_module); diff --git a/drivers/net/skge.h b/drivers/net/skge.h new file mode 100644 index 000000000000..b432f1bb8168 --- /dev/null +++ b/drivers/net/skge.h @@ -0,0 +1,2617 @@ +/* + * Definitions for the new Marvell Yukon / SysKonenct driver. + */ +#ifndef _SKGE_H +#define _SKGE_H + +/* PCI config registers */ +#define PCI_DEV_REG1 0x40 +#define PCI_DEV_REG2 0x44 +#define PCI_REV_DESC 0x4 + +#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ + PCI_STATUS_SIG_SYSTEM_ERROR | \ + PCI_STATUS_REC_MASTER_ABORT | \ + PCI_STATUS_REC_TARGET_ABORT | \ + PCI_STATUS_PARITY) + +enum csr_regs { + B0_RAP = 0x0000, + B0_CTST = 0x0004, + B0_LED = 0x0006, + B0_POWER_CTRL = 0x0007, + B0_ISRC = 0x0008, + B0_IMSK = 0x000c, + B0_HWE_ISRC = 0x0010, + B0_HWE_IMSK = 0x0014, + B0_SP_ISRC = 0x0018, + B0_XM1_IMSK = 0x0020, + B0_XM1_ISRC = 0x0028, + B0_XM1_PHY_ADDR = 0x0030, + B0_XM1_PHY_DATA = 0x0034, + B0_XM2_IMSK = 0x0040, + B0_XM2_ISRC = 0x0048, + B0_XM2_PHY_ADDR = 0x0050, + B0_XM2_PHY_DATA = 0x0054, + B0_R1_CSR = 0x0060, + B0_R2_CSR = 0x0064, + B0_XS1_CSR = 0x0068, + B0_XA1_CSR = 0x006c, + B0_XS2_CSR = 0x0070, + B0_XA2_CSR = 0x0074, + + B2_MAC_1 = 0x0100, + B2_MAC_2 = 0x0108, + B2_MAC_3 = 0x0110, + B2_CONN_TYP = 0x0118, + B2_PMD_TYP = 0x0119, + B2_MAC_CFG = 0x011a, + B2_CHIP_ID = 0x011b, + B2_E_0 = 0x011c, + B2_E_1 = 0x011d, + B2_E_2 = 0x011e, + B2_E_3 = 0x011f, + B2_FAR = 0x0120, + B2_FDP = 0x0124, + B2_LD_CTRL = 0x0128, + B2_LD_TEST = 0x0129, + B2_TI_INI = 0x0130, + B2_TI_VAL = 0x0134, + B2_TI_CTRL = 0x0138, + B2_TI_TEST = 0x0139, + B2_IRQM_INI = 0x0140, + B2_IRQM_VAL = 0x0144, + B2_IRQM_CTRL = 0x0148, + B2_IRQM_TEST = 0x0149, + B2_IRQM_MSK = 0x014c, + B2_IRQM_HWE_MSK = 0x0150, + B2_TST_CTRL1 = 0x0158, + B2_TST_CTRL2 = 0x0159, + B2_GP_IO = 0x015c, + B2_I2C_CTRL = 0x0160, + B2_I2C_DATA = 0x0164, + B2_I2C_IRQ = 0x0168, + B2_I2C_SW = 0x016c, + B2_BSC_INI = 0x0170, + B2_BSC_VAL = 0x0174, + B2_BSC_CTRL = 0x0178, + B2_BSC_STAT = 0x0179, + B2_BSC_TST = 0x017a, + + B3_RAM_ADDR = 0x0180, + B3_RAM_DATA_LO = 0x0184, + B3_RAM_DATA_HI = 0x0188, + B3_RI_WTO_R1 = 0x0190, + B3_RI_WTO_XA1 = 0x0191, + B3_RI_WTO_XS1 = 0x0192, + B3_RI_RTO_R1 = 0x0193, + B3_RI_RTO_XA1 = 0x0194, + B3_RI_RTO_XS1 = 0x0195, + B3_RI_WTO_R2 = 0x0196, + B3_RI_WTO_XA2 = 0x0197, + B3_RI_WTO_XS2 = 0x0198, + B3_RI_RTO_R2 = 0x0199, + B3_RI_RTO_XA2 = 0x019a, + B3_RI_RTO_XS2 = 0x019b, + B3_RI_TO_VAL = 0x019c, + B3_RI_CTRL = 0x01a0, + B3_RI_TEST = 0x01a2, + B3_MA_TOINI_RX1 = 0x01b0, + B3_MA_TOINI_RX2 = 0x01b1, + B3_MA_TOINI_TX1 = 0x01b2, + B3_MA_TOINI_TX2 = 0x01b3, + B3_MA_TOVAL_RX1 = 0x01b4, + B3_MA_TOVAL_RX2 = 0x01b5, + B3_MA_TOVAL_TX1 = 0x01b6, + B3_MA_TOVAL_TX2 = 0x01b7, + B3_MA_TO_CTRL = 0x01b8, + B3_MA_TO_TEST = 0x01ba, + B3_MA_RCINI_RX1 = 0x01c0, + B3_MA_RCINI_RX2 = 0x01c1, + B3_MA_RCINI_TX1 = 0x01c2, + B3_MA_RCINI_TX2 = 0x01c3, + B3_MA_RCVAL_RX1 = 0x01c4, + B3_MA_RCVAL_RX2 = 0x01c5, + B3_MA_RCVAL_TX1 = 0x01c6, + B3_MA_RCVAL_TX2 = 0x01c7, + B3_MA_RC_CTRL = 0x01c8, + B3_MA_RC_TEST = 0x01ca, + B3_PA_TOINI_RX1 = 0x01d0, + B3_PA_TOINI_RX2 = 0x01d4, + B3_PA_TOINI_TX1 = 0x01d8, + B3_PA_TOINI_TX2 = 0x01dc, + B3_PA_TOVAL_RX1 = 0x01e0, + B3_PA_TOVAL_RX2 = 0x01e4, + B3_PA_TOVAL_TX1 = 0x01e8, + B3_PA_TOVAL_TX2 = 0x01ec, + B3_PA_CTRL = 0x01f0, + B3_PA_TEST = 0x01f2, +}; + +/* B0_CTST 16 bit Control/Status register */ +enum { + CS_CLK_RUN_HOT = 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */ + CS_CLK_RUN_RST = 1<<12,/* CLK_RUN reset (YUKON-Lite only) */ + CS_CLK_RUN_ENA = 1<<11,/* CLK_RUN enable (YUKON-Lite only) */ + CS_VAUX_AVAIL = 1<<10,/* VAUX available (YUKON only) */ + CS_BUS_CLOCK = 1<<9, /* Bus Clock 0/1 = 33/66 MHz */ + CS_BUS_SLOT_SZ = 1<<8, /* Slot Size 0/1 = 32/64 bit slot */ + CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */ + CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */ + CS_STOP_DONE = 1<<5, /* Stop Master is finished */ + CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */ + CS_MRST_CLR = 1<<3, /* Clear Master reset */ + CS_MRST_SET = 1<<2, /* Set Master reset */ + CS_RST_CLR = 1<<1, /* Clear Software reset */ + CS_RST_SET = 1, /* Set Software reset */ + +/* B0_LED 8 Bit LED register */ +/* Bit 7.. 2: reserved */ + LED_STAT_ON = 1<<1, /* Status LED on */ + LED_STAT_OFF = 1, /* Status LED off */ + +/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ + PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */ + PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */ + PC_VCC_ENA = 1<<5, /* Switch VCC Enable */ + PC_VCC_DIS = 1<<4, /* Switch VCC Disable */ + PC_VAUX_ON = 1<<3, /* Switch VAUX On */ + PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */ + PC_VCC_ON = 1<<1, /* Switch VCC On */ + PC_VCC_OFF = 1<<0, /* Switch VCC Off */ +}; + +/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ +enum { + IS_ALL_MSK = 0xbffffffful, /* All Interrupt bits */ + IS_HW_ERR = 1<<31, /* Interrupt HW Error */ + /* Bit 30: reserved */ + IS_PA_TO_RX1 = 1<<29, /* Packet Arb Timeout Rx1 */ + IS_PA_TO_RX2 = 1<<28, /* Packet Arb Timeout Rx2 */ + IS_PA_TO_TX1 = 1<<27, /* Packet Arb Timeout Tx1 */ + IS_PA_TO_TX2 = 1<<26, /* Packet Arb Timeout Tx2 */ + IS_I2C_READY = 1<<25, /* IRQ on end of I2C Tx */ + IS_IRQ_SW = 1<<24, /* SW forced IRQ */ + IS_EXT_REG = 1<<23, /* IRQ from LM80 or PHY (GENESIS only) */ + /* IRQ from PHY (YUKON only) */ + IS_TIMINT = 1<<22, /* IRQ from Timer */ + IS_MAC1 = 1<<21, /* IRQ from MAC 1 */ + IS_LNK_SYNC_M1 = 1<<20, /* Link Sync Cnt wrap MAC 1 */ + IS_MAC2 = 1<<19, /* IRQ from MAC 2 */ + IS_LNK_SYNC_M2 = 1<<18, /* Link Sync Cnt wrap MAC 2 */ +/* Receive Queue 1 */ + IS_R1_B = 1<<17, /* Q_R1 End of Buffer */ + IS_R1_F = 1<<16, /* Q_R1 End of Frame */ + IS_R1_C = 1<<15, /* Q_R1 Encoding Error */ +/* Receive Queue 2 */ + IS_R2_B = 1<<14, /* Q_R2 End of Buffer */ + IS_R2_F = 1<<13, /* Q_R2 End of Frame */ + IS_R2_C = 1<<12, /* Q_R2 Encoding Error */ +/* Synchronous Transmit Queue 1 */ + IS_XS1_B = 1<<11, /* Q_XS1 End of Buffer */ + IS_XS1_F = 1<<10, /* Q_XS1 End of Frame */ + IS_XS1_C = 1<<9, /* Q_XS1 Encoding Error */ +/* Asynchronous Transmit Queue 1 */ + IS_XA1_B = 1<<8, /* Q_XA1 End of Buffer */ + IS_XA1_F = 1<<7, /* Q_XA1 End of Frame */ + IS_XA1_C = 1<<6, /* Q_XA1 Encoding Error */ +/* Synchronous Transmit Queue 2 */ + IS_XS2_B = 1<<5, /* Q_XS2 End of Buffer */ + IS_XS2_F = 1<<4, /* Q_XS2 End of Frame */ + IS_XS2_C = 1<<3, /* Q_XS2 Encoding Error */ +/* Asynchronous Transmit Queue 2 */ + IS_XA2_B = 1<<2, /* Q_XA2 End of Buffer */ + IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */ + IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */ + + IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1, + IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2, + + IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1, + IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2, +}; + + +/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ +enum { + IS_ERR_MSK = 0x00003fff,/* All Error bits */ + + IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */ + IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */ + IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */ + IS_IRQ_STAT = 1<<10, /* IRQ status exception */ + IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */ + IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */ + IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */ + IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */ + IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */ + IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */ + IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */ + IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */ + IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */ + IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */ +}; + +/* B2_TST_CTRL1 8 bit Test Control Register 1 */ +enum { + TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */ + TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */ + TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */ + TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */ + TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */ + TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */ + TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */ + TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ +}; + +/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ +enum { + CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ + /* Bit 3.. 2: reserved */ + CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */ + CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/ +}; + +/* B2_CHIP_ID 8 bit Chip Identification Number */ +enum { + CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */ + CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */ + CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */ + CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */ + CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */ + CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ + CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ + + CHIP_REV_YU_LITE_A1 = 3, /* Chip Rev. for YUKON-Lite A1,A2 */ + CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */ +}; + +/* B2_TI_CTRL 8 bit Timer control */ +/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ +enum { + TIM_START = 1<<2, /* Start Timer */ + TIM_STOP = 1<<1, /* Stop Timer */ + TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */ +}; + +/* B2_TI_TEST 8 Bit Timer Test */ +/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ +/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ +enum { + TIM_T_ON = 1<<2, /* Test mode on */ + TIM_T_OFF = 1<<1, /* Test mode off */ + TIM_T_STEP = 1<<0, /* Test step */ +}; + +/* B2_GP_IO 32 bit General Purpose I/O Register */ +enum { + GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */ + GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */ + GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */ + GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */ + GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */ + GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */ + GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */ + GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */ + GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */ + GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */ + + GP_IO_9 = 1<<9, /* IO_9 pin */ + GP_IO_8 = 1<<8, /* IO_8 pin */ + GP_IO_7 = 1<<7, /* IO_7 pin */ + GP_IO_6 = 1<<6, /* IO_6 pin */ + GP_IO_5 = 1<<5, /* IO_5 pin */ + GP_IO_4 = 1<<4, /* IO_4 pin */ + GP_IO_3 = 1<<3, /* IO_3 pin */ + GP_IO_2 = 1<<2, /* IO_2 pin */ + GP_IO_1 = 1<<1, /* IO_1 pin */ + GP_IO_0 = 1<<0, /* IO_0 pin */ +}; + +/* Descriptor Bit Definition */ +/* TxCtrl Transmit Buffer Control Field */ +/* RxCtrl Receive Buffer Control Field */ +enum { + BMU_OWN = 1<<31, /* OWN bit: 0=host/1=BMU */ + BMU_STF = 1<<30, /* Start of Frame */ + BMU_EOF = 1<<29, /* End of Frame */ + BMU_IRQ_EOB = 1<<28, /* Req "End of Buffer" IRQ */ + BMU_IRQ_EOF = 1<<27, /* Req "End of Frame" IRQ */ + /* TxCtrl specific bits */ + BMU_STFWD = 1<<26, /* (Tx) Store & Forward Frame */ + BMU_NO_FCS = 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */ + BMU_SW = 1<<24, /* (Tx) 1 bit res. for SW use */ + /* RxCtrl specific bits */ + BMU_DEV_0 = 1<<26, /* (Rx) Transfer data to Dev0 */ + BMU_STAT_VAL = 1<<25, /* (Rx) Rx Status Valid */ + BMU_TIST_VAL = 1<<24, /* (Rx) Rx TimeStamp Valid */ + /* Bit 23..16: BMU Check Opcodes */ + BMU_CHECK = 0x55<<16, /* Default BMU check */ + BMU_TCP_CHECK = 0x56<<16, /* Descr with TCP ext */ + BMU_UDP_CHECK = 0x57<<16, /* Descr with UDP ext (YUKON only) */ + BMU_BBC = 0xffffL, /* Bit 15.. 0: Buffer Byte Counter */ +}; + +/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ +enum { + BSC_START = 1<<1, /* Start Blink Source Counter */ + BSC_STOP = 1<<0, /* Stop Blink Source Counter */ +}; + +/* B2_BSC_STAT 8 bit Blink Source Counter Status */ +enum { + BSC_SRC = 1<<0, /* Blink Source, 0=Off / 1=On */ +}; + +/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ +enum { + BSC_T_ON = 1<<2, /* Test mode on */ + BSC_T_OFF = 1<<1, /* Test mode off */ + BSC_T_STEP = 1<<0, /* Test step */ +}; + +/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ + /* Bit 31..19: reserved */ +#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ +/* RAM Interface Registers */ + +/* B3_RI_CTRL 16 bit RAM Iface Control Register */ +enum { + RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */ + RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/ + + RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */ + RI_RST_SET = 1<<0, /* Set RAM Interface Reset */ +}; + +/* MAC Arbiter Registers */ +/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ +enum { + MA_FOE_ON = 1<<3, /* XMAC Fast Output Enable ON */ + MA_FOE_OFF = 1<<2, /* XMAC Fast Output Enable OFF */ + MA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ + MA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ + +}; + +/* Timeout values */ +#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ +#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ +#define SK_PKT_TO_MAX 0xffff /* Maximum value */ +#define SK_RI_TO_53 36 /* RAM interface timeout */ + +/* Packet Arbiter Registers */ +/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ +enum { + PA_CLR_TO_TX2 = 1<<13, /* Clear IRQ Packet Timeout TX2 */ + PA_CLR_TO_TX1 = 1<<12, /* Clear IRQ Packet Timeout TX1 */ + PA_CLR_TO_RX2 = 1<<11, /* Clear IRQ Packet Timeout RX2 */ + PA_CLR_TO_RX1 = 1<<10, /* Clear IRQ Packet Timeout RX1 */ + PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */ + PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */ + PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */ + PA_DIS_TO_TX1 = 1<<6, /* Disable Timeout Timer TX1 */ + PA_ENA_TO_RX2 = 1<<5, /* Enable Timeout Timer RX2 */ + PA_DIS_TO_RX2 = 1<<4, /* Disable Timeout Timer RX2 */ + PA_ENA_TO_RX1 = 1<<3, /* Enable Timeout Timer RX1 */ + PA_DIS_TO_RX1 = 1<<2, /* Disable Timeout Timer RX1 */ + PA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ + PA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ +}; + +#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ + PA_ENA_TO_TX1 | PA_ENA_TO_TX2) + + +/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ +/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ +/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ +/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ +/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ + +#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ + +/* TXA_CTRL 8 bit Tx Arbiter Control Register */ +enum { + TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */ + TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */ + TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */ + TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */ + TXA_START_RC = 1<<3, /* Start sync Rate Control */ + TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */ + TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */ + TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */ +}; + +/* + * Bank 4 - 5 + */ +/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ +enum { + TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/ + TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */ + TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */ + TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */ + TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ + TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ + TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */ +}; + + +enum { + B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ + B7_CFG_SPC = 0x0380,/* copy of the Configuration register */ + B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */ + B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */ + B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */ + B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */ + B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */ + B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */ + B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */ +}; + +/* Queue Register Offsets, use Q_ADDR() to access */ +enum { + B8_Q_REGS = 0x0400, /* base of Queue registers */ + Q_D = 0x00, /* 8*32 bit Current Descriptor */ + Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ + Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ + Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ + Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ + Q_BC = 0x30, /* 32 bit Current Byte Counter */ + Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ + Q_F = 0x38, /* 32 bit Flag Register */ + Q_T1 = 0x3c, /* 32 bit Test Register 1 */ + Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ + Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ + Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ + Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ + Q_T2 = 0x40, /* 32 bit Test Register 2 */ + Q_T3 = 0x44, /* 32 bit Test Register 3 */ + +/* Yukon-2 */ + Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */ + Q_WM = 0x40, /* 16 bit FIFO Watermark */ + Q_AL = 0x42, /* 8 bit FIFO Alignment */ + Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */ + Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */ + Q_RP = 0x48, /* 8 bit FIFO Read Pointer */ + Q_RL = 0x4a, /* 8 bit FIFO Read Level */ + Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */ + Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */ + Q_WL = 0x4e, /* 8 bit FIFO Write Level */ + Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */ +}; +#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) + +/* RAM Buffer Register Offsets */ +enum { + + RB_START = 0x00,/* 32 bit RAM Buffer Start Address */ + RB_END = 0x04,/* 32 bit RAM Buffer End Address */ + RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */ + RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */ + RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ + RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ + RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */ + RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ + /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ + RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */ + RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */ + RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */ + RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */ + RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */ +}; + +/* Receive and Transmit Queues */ +enum { + Q_R1 = 0x0000, /* Receive Queue 1 */ + Q_R2 = 0x0080, /* Receive Queue 2 */ + Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */ + Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */ + Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */ + Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */ +}; + +/* Different MAC Types */ +enum { + SK_MAC_XMAC = 0, /* Xaqti XMAC II */ + SK_MAC_GMAC = 1, /* Marvell GMAC */ +}; + +/* Different PHY Types */ +enum { + SK_PHY_XMAC = 0,/* integrated in XMAC II */ + SK_PHY_BCOM = 1,/* Broadcom BCM5400 */ + SK_PHY_LONE = 2,/* Level One LXT1000 [not supported]*/ + SK_PHY_NAT = 3,/* National DP83891 [not supported] */ + SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */ + SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */ +}; + +/* PHY addresses (bits 12..8 of PHY address reg) */ +enum { + PHY_ADDR_XMAC = 0<<8, + PHY_ADDR_BCOM = 1<<8, + +/* GPHY address (bits 15..11 of SMI control reg) */ + PHY_ADDR_MARV = 0, +}; + +#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs)) + +/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */ +enum { + RX_MFF_EA = 0x0c00,/* 32 bit Receive MAC FIFO End Address */ + RX_MFF_WP = 0x0c04,/* 32 bit Receive MAC FIFO Write Pointer */ + + RX_MFF_RP = 0x0c0c,/* 32 bit Receive MAC FIFO Read Pointer */ + RX_MFF_PC = 0x0c10,/* 32 bit Receive MAC FIFO Packet Cnt */ + RX_MFF_LEV = 0x0c14,/* 32 bit Receive MAC FIFO Level */ + RX_MFF_CTRL1 = 0x0c18,/* 16 bit Receive MAC FIFO Control Reg 1*/ + RX_MFF_STAT_TO = 0x0c1a,/* 8 bit Receive MAC Status Timeout */ + RX_MFF_TIST_TO = 0x0c1b,/* 8 bit Receive MAC Time Stamp Timeout */ + RX_MFF_CTRL2 = 0x0c1c,/* 8 bit Receive MAC FIFO Control Reg 2*/ + RX_MFF_TST1 = 0x0c1d,/* 8 bit Receive MAC FIFO Test Reg 1 */ + RX_MFF_TST2 = 0x0c1e,/* 8 bit Receive MAC FIFO Test Reg 2 */ + + RX_LED_INI = 0x0c20,/* 32 bit Receive LED Cnt Init Value */ + RX_LED_VAL = 0x0c24,/* 32 bit Receive LED Cnt Current Value */ + RX_LED_CTRL = 0x0c28,/* 8 bit Receive LED Cnt Control Reg */ + RX_LED_TST = 0x0c29,/* 8 bit Receive LED Cnt Test Register */ + + LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */ + LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */ + LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */ + LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */ + LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */ +}; + +/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ +/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ +enum { + MFF_ENA_RDY_PAT = 1<<13, /* Enable Ready Patch */ + MFF_DIS_RDY_PAT = 1<<12, /* Disable Ready Patch */ + MFF_ENA_TIM_PAT = 1<<11, /* Enable Timing Patch */ + MFF_DIS_TIM_PAT = 1<<10, /* Disable Timing Patch */ + MFF_ENA_ALM_FUL = 1<<9, /* Enable AlmostFull Sign */ + MFF_DIS_ALM_FUL = 1<<8, /* Disable AlmostFull Sign */ + MFF_ENA_PAUSE = 1<<7, /* Enable Pause Signaling */ + MFF_DIS_PAUSE = 1<<6, /* Disable Pause Signaling */ + MFF_ENA_FLUSH = 1<<5, /* Enable Frame Flushing */ + MFF_DIS_FLUSH = 1<<4, /* Disable Frame Flushing */ + MFF_ENA_TIST = 1<<3, /* Enable Time Stamp Gener */ + MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */ + MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */ + MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */ +#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT +}; + +/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ +enum { + MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */ + /* Bit 14: reserved */ + MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */ + MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */ + + MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */ + MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */ + + MFF_ENA_LOOPB = 1<<3, /* Enable Loopback */ + MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */ + MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */ + MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */ +}; + +#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) + +/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ +/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ +enum { + MFF_WSP_T_ON = 1<<6, /* Tx: Write Shadow Ptr TestOn */ + MFF_WSP_T_OFF = 1<<5, /* Tx: Write Shadow Ptr TstOff */ + MFF_WSP_INC = 1<<4, /* Tx: Write Shadow Ptr Increment */ + MFF_PC_DEC = 1<<3, /* Packet Counter Decrement */ + MFF_PC_T_ON = 1<<2, /* Packet Counter Test On */ + MFF_PC_T_OFF = 1<<1, /* Packet Counter Test Off */ + MFF_PC_INC = 1<<0, /* Packet Counter Increment */ +}; + +/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ +/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ +enum { + MFF_WP_T_ON = 1<<6, /* Write Pointer Test On */ + MFF_WP_T_OFF = 1<<5, /* Write Pointer Test Off */ + MFF_WP_INC = 1<<4, /* Write Pointer Increm */ + + MFF_RP_T_ON = 1<<2, /* Read Pointer Test On */ + MFF_RP_T_OFF = 1<<1, /* Read Pointer Test Off */ + MFF_RP_DEC = 1<<0, /* Read Pointer Decrement */ +}; + +/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ +/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ +enum { + MFF_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ + MFF_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ + MFF_RST_CLR = 1<<1, /* Clear MAC FIFO Reset */ + MFF_RST_SET = 1<<0, /* Set MAC FIFO Reset */ +}; + + +/* Link LED Counter Registers (GENESIS only) */ + +/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ +/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ +/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ +enum { + LED_START = 1<<2, /* Start Timer */ + LED_STOP = 1<<1, /* Stop Timer */ + LED_STATE = 1<<0, /* Rx/Tx: LED State, 1=LED on */ +}; + +/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ +/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ +/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ +enum { + LED_T_ON = 1<<2, /* LED Counter Test mode On */ + LED_T_OFF = 1<<1, /* LED Counter Test mode Off */ + LED_T_STEP = 1<<0, /* LED Counter Step */ +}; + +/* LNK_LED_REG 8 bit Link LED Register */ +enum { + LED_BLK_ON = 1<<5, /* Link LED Blinking On */ + LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */ + LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */ + LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */ + LED_ON = 1<<1, /* switch LED on */ + LED_OFF = 1<<0, /* switch LED off */ +}; + +/* Receive GMAC FIFO (YUKON and Yukon-2) */ +enum { + RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */ + RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */ + RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */ + RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */ + RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */ + RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */ + + RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */ + RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */ + + RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */ + + RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */ + + RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */ +}; + + +/* TXA_TEST 8 bit Tx Arbiter Test Register */ +enum { + TXA_INT_T_ON = 1<<5, /* Tx Arb Interval Timer Test On */ + TXA_INT_T_OFF = 1<<4, /* Tx Arb Interval Timer Test Off */ + TXA_INT_T_STEP = 1<<3, /* Tx Arb Interval Timer Step */ + TXA_LIM_T_ON = 1<<2, /* Tx Arb Limit Timer Test On */ + TXA_LIM_T_OFF = 1<<1, /* Tx Arb Limit Timer Test Off */ + TXA_LIM_T_STEP = 1<<0, /* Tx Arb Limit Timer Step */ +}; + +/* TXA_STAT 8 bit Tx Arbiter Status Register */ +enum { + TXA_PRIO_XS = 1<<0, /* sync queue has prio to send */ +}; + + +/* Q_BC 32 bit Current Byte Counter */ + +/* BMU Control Status Registers */ +/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ +/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ +/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ +/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ +/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ +/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ +/* Q_CSR 32 bit BMU Control/Status Register */ + +enum { + CSR_SV_IDLE = 1<<24, /* BMU SM Idle */ + + CSR_DESC_CLR = 1<<21, /* Clear Reset for Descr */ + CSR_DESC_SET = 1<<20, /* Set Reset for Descr */ + CSR_FIFO_CLR = 1<<19, /* Clear Reset for FIFO */ + CSR_FIFO_SET = 1<<18, /* Set Reset for FIFO */ + CSR_HPI_RUN = 1<<17, /* Release HPI SM */ + CSR_HPI_RST = 1<<16, /* Reset HPI SM to Idle */ + CSR_SV_RUN = 1<<15, /* Release Supervisor SM */ + CSR_SV_RST = 1<<14, /* Reset Supervisor SM */ + CSR_DREAD_RUN = 1<<13, /* Release Descr Read SM */ + CSR_DREAD_RST = 1<<12, /* Reset Descr Read SM */ + CSR_DWRITE_RUN = 1<<11, /* Release Descr Write SM */ + CSR_DWRITE_RST = 1<<10, /* Reset Descr Write SM */ + CSR_TRANS_RUN = 1<<9, /* Release Transfer SM */ + CSR_TRANS_RST = 1<<8, /* Reset Transfer SM */ + CSR_ENA_POL = 1<<7, /* Enable Descr Polling */ + CSR_DIS_POL = 1<<6, /* Disable Descr Polling */ + CSR_STOP = 1<<5, /* Stop Rx/Tx Queue */ + CSR_START = 1<<4, /* Start Rx/Tx Queue */ + CSR_IRQ_CL_P = 1<<3, /* (Rx) Clear Parity IRQ */ + CSR_IRQ_CL_B = 1<<2, /* Clear EOB IRQ */ + CSR_IRQ_CL_F = 1<<1, /* Clear EOF IRQ */ + CSR_IRQ_CL_C = 1<<0, /* Clear ERR IRQ */ +}; + +#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ + CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ + CSR_TRANS_RST) +#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ + CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ + CSR_TRANS_RUN) + +/* Q_F 32 bit Flag Register */ +enum { + F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */ + F_EMPTY = 1<<27, /* Tx FIFO: empty flag */ + F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */ + F_WM_REACHED = 1<<25, /* Watermark reached */ + + F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */ + F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */ +}; + +/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ +/* RB_START 32 bit RAM Buffer Start Address */ +/* RB_END 32 bit RAM Buffer End Address */ +/* RB_WP 32 bit RAM Buffer Write Pointer */ +/* RB_RP 32 bit RAM Buffer Read Pointer */ +/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ +/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ +/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ +/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ +/* RB_PC 32 bit RAM Buffer Packet Counter */ +/* RB_LEV 32 bit RAM Buffer Level Register */ + +#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ +/* RB_TST2 8 bit RAM Buffer Test Register 2 */ +/* RB_TST1 8 bit RAM Buffer Test Register 1 */ + +/* RB_CTRL 8 bit RAM Buffer Control Register */ +enum { + RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */ + RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */ + RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ + RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ + RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */ + RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */ +}; + +/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */ +enum { + TX_MFF_EA = 0x0d00,/* 32 bit Transmit MAC FIFO End Address */ + TX_MFF_WP = 0x0d04,/* 32 bit Transmit MAC FIFO WR Pointer */ + TX_MFF_WSP = 0x0d08,/* 32 bit Transmit MAC FIFO WR Shadow Ptr */ + TX_MFF_RP = 0x0d0c,/* 32 bit Transmit MAC FIFO RD Pointer */ + TX_MFF_PC = 0x0d10,/* 32 bit Transmit MAC FIFO Packet Cnt */ + TX_MFF_LEV = 0x0d14,/* 32 bit Transmit MAC FIFO Level */ + TX_MFF_CTRL1 = 0x0d18,/* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ + TX_MFF_WAF = 0x0d1a,/* 8 bit Transmit MAC Wait after flush */ + + TX_MFF_CTRL2 = 0x0d1c,/* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ + TX_MFF_TST1 = 0x0d1d,/* 8 bit Transmit MAC FIFO Test Reg 1 */ + TX_MFF_TST2 = 0x0d1e,/* 8 bit Transmit MAC FIFO Test Reg 2 */ + + TX_LED_INI = 0x0d20,/* 32 bit Transmit LED Cnt Init Value */ + TX_LED_VAL = 0x0d24,/* 32 bit Transmit LED Cnt Current Val */ + TX_LED_CTRL = 0x0d28,/* 8 bit Transmit LED Cnt Control Reg */ + TX_LED_TST = 0x0d29,/* 8 bit Transmit LED Cnt Test Reg */ +}; + +/* Counter and Timer constants, for a host clock of 62.5 MHz */ +#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ +#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ + +#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */ + +#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ + /* 215 ms at 78.12 MHz */ + +#define SK_FACT_62 100 /* is given in percent */ +#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ +#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ + + +/* Transmit GMAC FIFO (YUKON only) */ +enum { + TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */ + TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ + TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */ + + TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */ + TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ + TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */ + + TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ + TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ + TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ + + /* Descriptor Poll Timer Registers */ + B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */ + B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */ + B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */ + + B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */ + + /* Time Stamp Timer Registers (YUKON only) */ + GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */ + GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */ + GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */ +}; + +/* Status BMU Registers (Yukon-2 only)*/ +enum { + STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */ + STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */ + /* 0x0e85 - 0x0e86: reserved */ + STAT_LIST_ADDR_LO = 0x0e88,/* 32 bit Status List Start Addr (low) */ + STAT_LIST_ADDR_HI = 0x0e8c,/* 32 bit Status List Start Addr (high) */ + STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */ + STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */ + STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */ + STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */ + STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */ + STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */ + +/* FIFO Control/Status Registers (Yukon-2 only)*/ + STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */ + STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */ + STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */ + STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */ + STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */ + STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */ + STAT_FIFO_ISR_WM = 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */ + +/* Level and ISR Timer Registers (Yukon-2 only)*/ + STAT_LEV_TIMER_INI = 0x0eb0,/* 32 bit Level Timer Init. Value Reg */ + STAT_LEV_TIMER_CNT = 0x0eb4,/* 32 bit Level Timer Counter Reg */ + STAT_LEV_TIMER_CTRL = 0x0eb8,/* 8 bit Level Timer Control Reg */ + STAT_LEV_TIMER_TEST = 0x0eb9,/* 8 bit Level Timer Test Reg */ + STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */ + STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */ + STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */ + STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */ + STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */ + STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */ + STAT_ISR_TIMER_CTRL = 0x0ed8,/* 8 bit ISR Timer Control Reg */ + STAT_ISR_TIMER_TEST = 0x0ed9,/* 8 bit ISR Timer Test Reg */ + + ST_LAST_IDX_MASK = 0x007f,/* Last Index Mask */ + ST_TXRP_IDX_MASK = 0x0fff,/* Tx Report Index Mask */ + ST_TXTH_IDX_MASK = 0x0fff,/* Tx Threshold Index Mask */ + ST_WM_IDX_MASK = 0x3f,/* FIFO Watermark Index Mask */ +}; + +enum { + LINKLED_OFF = 0x01, + LINKLED_ON = 0x02, + LINKLED_LINKSYNC_OFF = 0x04, + LINKLED_LINKSYNC_ON = 0x08, + LINKLED_BLINK_OFF = 0x10, + LINKLED_BLINK_ON = 0x20, +}; + +/* GMAC and GPHY Control Registers (YUKON only) */ +enum { + GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */ + GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */ + GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */ + GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */ + GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */ + +/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ + + WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */ + + WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */ + WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */ + WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */ + WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */ + WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */ + WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */ + WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */ + +/* WOL Pattern Length Registers (YUKON only) */ + + WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */ + WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */ + +/* WOL Pattern Counter Registers (YUKON only) */ + + WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ + WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ +}; + +enum { + WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ + WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ +}; + +enum { + BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */ + BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */ + BASE_XMAC_2 = 0x3000,/* XMAC 2 registers */ + BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */ +}; + +/* + * Receive Frame Status Encoding + */ +enum { + XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */ + XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/ + XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/ + XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */ + XMR_FS_MC = 1<<14, /* Bit 14: Multicast Frame */ + XMR_FS_UC = 1<<13, /* Bit 13: Unicast Frame */ + + XMR_FS_BURST = 1<<11, /* Bit 11: Burst Mode */ + XMR_FS_CEX_ERR = 1<<10, /* Bit 10: Carrier Ext. Error */ + XMR_FS_802_3 = 1<<9, /* Bit 9: 802.3 Frame */ + XMR_FS_COL_ERR = 1<<8, /* Bit 8: Collision Error */ + XMR_FS_CAR_ERR = 1<<7, /* Bit 7: Carrier Event Error */ + XMR_FS_LEN_ERR = 1<<6, /* Bit 6: In-Range Length Error */ + XMR_FS_FRA_ERR = 1<<5, /* Bit 5: Framing Error */ + XMR_FS_RUNT = 1<<4, /* Bit 4: Runt Frame */ + XMR_FS_LNG_ERR = 1<<3, /* Bit 3: Giant (Jumbo) Frame */ + XMR_FS_FCS_ERR = 1<<2, /* Bit 2: Frame Check Sequ Err */ + XMR_FS_ERR = 1<<1, /* Bit 1: Frame Error */ + XMR_FS_MCTRL = 1<<0, /* Bit 0: MAC Control Packet */ + +/* + * XMR_FS_ERR will be set if + * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, + * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR + * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue + * XMR_FS_ERR unless the corresponding bit in the Receive Command + * Register is set. + */ +}; + +/* +,* XMAC-PHY Registers, indirect addressed over the XMAC + */ +enum { + PHY_XMAC_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ + PHY_XMAC_STAT = 0x01,/* 16 bit r/w PHY Status Register */ + PHY_XMAC_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ + PHY_XMAC_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ + PHY_XMAC_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ + PHY_XMAC_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Abi Reg */ + PHY_XMAC_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ + PHY_XMAC_NEPG = 0x07,/* 16 bit r/w Next Page Register */ + PHY_XMAC_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ + + PHY_XMAC_EXT_STAT = 0x0f,/* 16 bit r/o Ext Status Register */ + PHY_XMAC_RES_ABI = 0x10,/* 16 bit r/o PHY Resolved Ability */ +}; +/* + * Broadcom-PHY Registers, indirect addressed over XMAC + */ +enum { + PHY_BCOM_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ + PHY_BCOM_STAT = 0x01,/* 16 bit r/o PHY Status Register */ + PHY_BCOM_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ + PHY_BCOM_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ + PHY_BCOM_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ + PHY_BCOM_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ + PHY_BCOM_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ + PHY_BCOM_NEPG = 0x07,/* 16 bit r/w Next Page Register */ + PHY_BCOM_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ + /* Broadcom-specific registers */ + PHY_BCOM_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ + PHY_BCOM_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ + PHY_BCOM_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ + PHY_BCOM_P_EXT_CTRL = 0x10,/* 16 bit r/w PHY Extended Ctrl Reg */ + PHY_BCOM_P_EXT_STAT = 0x11,/* 16 bit r/o PHY Extended Stat Reg */ + PHY_BCOM_RE_CTR = 0x12,/* 16 bit r/w Receive Error Counter */ + PHY_BCOM_FC_CTR = 0x13,/* 16 bit r/w False Carrier Sense Cnt */ + PHY_BCOM_RNO_CTR = 0x14,/* 16 bit r/w Receiver NOT_OK Cnt */ + + PHY_BCOM_AUX_CTRL = 0x18,/* 16 bit r/w Auxiliary Control Reg */ + PHY_BCOM_AUX_STAT = 0x19,/* 16 bit r/o Auxiliary Stat Summary */ + PHY_BCOM_INT_STAT = 0x1a,/* 16 bit r/o Interrupt Status Reg */ + PHY_BCOM_INT_MASK = 0x1b,/* 16 bit r/w Interrupt Mask Reg */ +}; + +/* + * Marvel-PHY Registers, indirect addressed over GMAC + */ +enum { + PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ + PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */ + PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ + PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ + PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ + PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ + PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ + PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */ + PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ + /* Marvel-specific registers */ + PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ + PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ + PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ + PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */ + PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */ + PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */ + PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */ + PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */ + PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */ + PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */ + PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */ + PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */ + PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */ + PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */ + PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */ + PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */ + PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */ + PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */ + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ + PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */ + PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */ + PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */ + PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */ + PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */ +}; + +enum { + PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */ + PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */ + PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */ + PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */ + PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */ + PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */ + PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */ + PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */ + PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */ + PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */ +}; + +enum { + PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */ + PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */ + PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */ +}; + +enum { + PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */ + + PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ + PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ + PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ + PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ + PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ + PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ + PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */ +}; + +enum { + PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */ + PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */ + PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */ +}; + +/* different Broadcom PHY Ids */ +enum { + PHY_BCOM_ID1_A1 = 0x6041, + PHY_BCOM_ID1_B2 = 0x6043, + PHY_BCOM_ID1_C0 = 0x6044, + PHY_BCOM_ID1_C5 = 0x6047, +}; + +/* different Marvell PHY Ids */ +enum { + PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */ + PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */ + PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */ + PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */ + PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ +}; + +/* Advertisement register bits */ +enum { + PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ + PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ + PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */ + + PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */ + PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */ + PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */ + PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */ + PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */ + PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */ + PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */ + PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */ + PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ + PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA, + PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL | + PHY_AN_100HALF | PHY_AN_100FULL, +}; + +/* Xmac Specific */ +enum { + PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ + PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ + PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */ + + PHY_X_AN_PAUSE = 3<<7,/* Bit 8.. 7: Pause Bits */ + PHY_X_AN_HD = 1<<6, /* Bit 6: Half Duplex */ + PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */ +}; + +/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */ +enum { + PHY_X_P_NO_PAUSE = 0<<7,/* Bit 8..7: no Pause Mode */ + PHY_X_P_SYM_MD = 1<<7, /* Bit 8..7: symmetric Pause Mode */ + PHY_X_P_ASYM_MD = 2<<7,/* Bit 8..7: asymmetric Pause Mode */ + PHY_X_P_BOTH_MD = 3<<7,/* Bit 8..7: both Pause Mode */ +}; + + +/* Broadcom-Specific */ +/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +enum { + PHY_B_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ + PHY_B_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */ + PHY_B_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */ + PHY_B_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */ + PHY_B_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */ + PHY_B_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */ +}; + +/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +enum { + PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ + PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ + PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ + PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */ + PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */ + PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */ + /* Bit 9..8: reserved */ + PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ +}; + +/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ +enum { + PHY_B_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */ + PHY_B_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */ + PHY_B_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */ + PHY_B_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */ +}; + +/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ +enum { + PHY_B_PEC_MAC_PHY = 1<<15, /* Bit 15: 10BIT/GMI-Interface */ + PHY_B_PEC_DIS_CROSS = 1<<14, /* Bit 14: Disable MDI Crossover */ + PHY_B_PEC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */ + PHY_B_PEC_INT_DIS = 1<<12, /* Bit 12: Interrupts Disabled */ + PHY_B_PEC_F_INT = 1<<11, /* Bit 11: Force Interrupt */ + PHY_B_PEC_BY_45 = 1<<10, /* Bit 10: Bypass 4B5B-Decoder */ + PHY_B_PEC_BY_SCR = 1<<9, /* Bit 9: Bypass Scrambler */ + PHY_B_PEC_BY_MLT3 = 1<<8, /* Bit 8: Bypass MLT3 Encoder */ + PHY_B_PEC_BY_RXA = 1<<7, /* Bit 7: Bypass Rx Alignm. */ + PHY_B_PEC_RES_SCR = 1<<6, /* Bit 6: Reset Scrambler */ + PHY_B_PEC_EN_LTR = 1<<5, /* Bit 5: Ena LED Traffic Mode */ + PHY_B_PEC_LED_ON = 1<<4, /* Bit 4: Force LED's on */ + PHY_B_PEC_LED_OFF = 1<<3, /* Bit 3: Force LED's off */ + PHY_B_PEC_EX_IPG = 1<<2, /* Bit 2: Extend Tx IPG Mode */ + PHY_B_PEC_3_LED = 1<<1, /* Bit 1: Three Link LED mode */ + PHY_B_PEC_HIGH_LA = 1<<0, /* Bit 0: GMII FIFO Elasticy */ +}; + +/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ +enum { + PHY_B_PES_CROSS_STAT = 1<<13, /* Bit 13: MDI Crossover Status */ + PHY_B_PES_INT_STAT = 1<<12, /* Bit 12: Interrupt Status */ + PHY_B_PES_RRS = 1<<11, /* Bit 11: Remote Receiver Stat. */ + PHY_B_PES_LRS = 1<<10, /* Bit 10: Local Receiver Stat. */ + PHY_B_PES_LOCKED = 1<<9, /* Bit 9: Locked */ + PHY_B_PES_LS = 1<<8, /* Bit 8: Link Status */ + PHY_B_PES_RF = 1<<7, /* Bit 7: Remote Fault */ + PHY_B_PES_CE_ER = 1<<6, /* Bit 6: Carrier Ext Error */ + PHY_B_PES_BAD_SSD = 1<<5, /* Bit 5: Bad SSD */ + PHY_B_PES_BAD_ESD = 1<<4, /* Bit 4: Bad ESD */ + PHY_B_PES_RX_ER = 1<<3, /* Bit 3: Receive Error */ + PHY_B_PES_TX_ER = 1<<2, /* Bit 2: Transmit Error */ + PHY_B_PES_LOCK_ER = 1<<1, /* Bit 1: Lock Error */ + PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ +}; + +/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +enum { + PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ + + PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ + PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ +}; + + +/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ +enum { + PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ + +/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ + PHY_B_RC_LOC_MSK = 0xff00, /* Bit 15..8: Local Rx NOT_OK cnt */ + PHY_B_RC_REM_MSK = 0x00ff, /* Bit 7..0: Remote Rx NOT_OK cnt */ + +/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ + PHY_B_AC_L_SQE = 1<<15, /* Bit 15: Low Squelch */ + PHY_B_AC_LONG_PACK = 1<<14, /* Bit 14: Rx Long Packets */ + PHY_B_AC_ER_CTRL = 3<<12,/* Bit 13..12: Edgerate Control */ + /* Bit 11: reserved */ + PHY_B_AC_TX_TST = 1<<10, /* Bit 10: Tx test bit, always 1 */ + /* Bit 9.. 8: reserved */ + PHY_B_AC_DIS_PRF = 1<<7, /* Bit 7: dis part resp filter */ + /* Bit 6: reserved */ + PHY_B_AC_DIS_PM = 1<<5, /* Bit 5: dis power management */ + /* Bit 4: reserved */ + PHY_B_AC_DIAG = 1<<3, /* Bit 3: Diagnostic Mode */ +}; + +/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ +enum { + PHY_B_AS_AN_C = 1<<15, /* Bit 15: AutoNeg complete */ + PHY_B_AS_AN_CA = 1<<14, /* Bit 14: AN Complete Ack */ + PHY_B_AS_ANACK_D = 1<<13, /* Bit 13: AN Ack Detect */ + PHY_B_AS_ANAB_D = 1<<12, /* Bit 12: AN Ability Detect */ + PHY_B_AS_NPW = 1<<11, /* Bit 11: AN Next Page Wait */ + PHY_B_AS_AN_RES_MSK = 7<<8,/* Bit 10..8: AN HDC */ + PHY_B_AS_PDF = 1<<7, /* Bit 7: Parallel Detect. Fault */ + PHY_B_AS_RF = 1<<6, /* Bit 6: Remote Fault */ + PHY_B_AS_ANP_R = 1<<5, /* Bit 5: AN Page Received */ + PHY_B_AS_LP_ANAB = 1<<4, /* Bit 4: LP AN Ability */ + PHY_B_AS_LP_NPAB = 1<<3, /* Bit 3: LP Next Page Ability */ + PHY_B_AS_LS = 1<<2, /* Bit 2: Link Status */ + PHY_B_AS_PRR = 1<<1, /* Bit 1: Pause Resolution-Rx */ + PHY_B_AS_PRT = 1<<0, /* Bit 0: Pause Resolution-Tx */ +}; +#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) + +/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ +/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ +enum { + PHY_B_IS_PSE = 1<<14, /* Bit 14: Pair Swap Error */ + PHY_B_IS_MDXI_SC = 1<<13, /* Bit 13: MDIX Status Change */ + PHY_B_IS_HCT = 1<<12, /* Bit 12: counter above 32k */ + PHY_B_IS_LCT = 1<<11, /* Bit 11: counter above 128 */ + PHY_B_IS_AN_PR = 1<<10, /* Bit 10: Page Received */ + PHY_B_IS_NO_HDCL = 1<<9, /* Bit 9: No HCD Link */ + PHY_B_IS_NO_HDC = 1<<8, /* Bit 8: No HCD */ + PHY_B_IS_NEG_USHDC = 1<<7, /* Bit 7: Negotiated Unsup. HCD */ + PHY_B_IS_SCR_S_ER = 1<<6, /* Bit 6: Scrambler Sync Error */ + PHY_B_IS_RRS_CHANGE = 1<<5, /* Bit 5: Remote Rx Stat Change */ + PHY_B_IS_LRS_CHANGE = 1<<4, /* Bit 4: Local Rx Stat Change */ + PHY_B_IS_DUP_CHANGE = 1<<3, /* Bit 3: Duplex Mode Change */ + PHY_B_IS_LSP_CHANGE = 1<<2, /* Bit 2: Link Speed Change */ + PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ + PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ +}; +#define PHY_B_DEF_MSK \ + (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \ + PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE)) + +/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ +enum { + PHY_B_P_NO_PAUSE = 0<<10,/* Bit 11..10: no Pause Mode */ + PHY_B_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */ + PHY_B_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */ + PHY_B_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */ +}; +/* + * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) + */ +enum { + PHY_B_RES_1000FD = 7<<8,/* Bit 10..8: 1000Base-T Full Dup. */ + PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */ +}; + +/** Marvell-Specific */ +enum { + PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */ + PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */ + PHY_M_AN_RF = 1<<13, /* Remote Fault */ + + PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */ + PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */ + PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */ + PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */ + PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */ + PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */ + PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */ + PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */ +}; + +/* special defines for FIBER (88E1011S only) */ +enum { + PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ + PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ + PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */ + PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */ +}; + +/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ +enum { + PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */ + PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */ + PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */ + PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */ +}; + +/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +enum { + PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ + PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */ + PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */ + PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */ + PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */ + PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */ +}; + +/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ +enum { + PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */ + PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */ + PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */ + PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */ + PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */ + PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */ + PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */ + PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */ + PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */ + PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */ + PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */ + PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */ +}; + +enum { + PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */ + PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ +}; + +#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) + +enum { + PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ + PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */ + PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */ +}; + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +enum { + PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */ + PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */ + PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */ + PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */ + PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */ + + PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */ + PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */ + + PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */ + PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */ +}; + +/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ +enum { + PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */ + PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */ + PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */ + PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */ + PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */ + PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */ + PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */ + PHY_M_PS_LINK_UP = 1<<10, /* Link Up */ + PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */ + PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */ + PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */ + PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */ + PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */ + PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */ + PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */ + PHY_M_PS_JABBER = 1<<0, /* Jabber */ +}; + +#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +enum { + PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */ + PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */ +}; + +enum { + PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */ + PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */ + PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */ + PHY_M_IS_AN_PR = 1<<12, /* Page Received */ + PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */ + PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */ + PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */ + PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */ + PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */ + PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */ + PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */ + PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */ + + PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ + PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ + PHY_M_IS_JABBER = 1<<0, /* Jabber */ + + PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, + + PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, +}; + +/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ +enum { + PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */ + PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */ + + PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */ + PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */ + /* (88E1011 only) */ + PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */ + /* (88E1011 only) */ + PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */ + /* (88E1111 only) */ + PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ + /* !!! Errata in spec. (1 = disable) */ + PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ + PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */ + PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ + PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ + PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ + PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; + +#define PHY_M_EC_M_DSC(x) ((x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */ +#define PHY_M_EC_S_DSC(x) ((x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */ +#define PHY_M_EC_MAC_S(x) ((x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */ + +#define PHY_M_EC_M_DSC_2(x) ((x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */ + /* 100=5x; 101=6x; 110=7x; 111=8x */ +enum { + MAC_TX_CLK_0_MHZ = 2, + MAC_TX_CLK_2_5_MHZ = 6, + MAC_TX_CLK_25_MHZ = 7, +}; + +/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ +enum { + PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */ + PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */ + PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */ + PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */ + PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */ + PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */ + PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */ + /* (88E1111 only) */ +}; + +enum { + PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */ + /* (88E1011 only) */ + PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */ + PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */ + PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */ + PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */ + PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ +}; + +#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) + +enum { + PULS_NO_STR = 0,/* no pulse stretching */ + PULS_21MS = 1,/* 21 ms to 42 ms */ + PULS_42MS = 2,/* 42 ms to 84 ms */ + PULS_84MS = 3,/* 84 ms to 170 ms */ + PULS_170MS = 4,/* 170 ms to 340 ms */ + PULS_340MS = 5,/* 340 ms to 670 ms */ + PULS_670MS = 6,/* 670 ms to 1.3 s */ + PULS_1300MS = 7,/* 1.3 s to 2.7 s */ +}; + +#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) + +enum { + BLINK_42MS = 0,/* 42 ms */ + BLINK_84MS = 1,/* 84 ms */ + BLINK_170MS = 2,/* 170 ms */ + BLINK_340MS = 3,/* 340 ms */ + BLINK_670MS = 4,/* 670 ms */ +}; + +/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ +#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ + /* Bit 13..12: reserved */ +#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ +#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ +#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ +#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ +#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ +#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ + +enum { + MO_LED_NORM = 0, + MO_LED_BLINK = 1, + MO_LED_OFF = 2, + MO_LED_ON = 3, +}; + +/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ +enum { + PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */ + PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */ + PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */ + PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */ + PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */ +}; + +/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ +enum { + PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */ + PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */ + PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */ + PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */ + PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */ + PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */ + PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */ + /* (88E1111 only) */ + /* Bit 9.. 4: reserved (88E1011 only) */ + PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */ + PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */ + PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */ +}; + +/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ +enum { + PHY_M_CABD_ENA_TEST = 1<<15, /* Enable Test (Page 0) */ + PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */ + /* (88E1111 only) */ + PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */ + PHY_M_CABD_AMPL_MSK = 0x1f<<8,/* Bit 12.. 8: Amplitude Mask */ + /* (88E1111 only) */ + PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */ +}; + +/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ +enum { + CABD_STAT_NORMAL= 0, + CABD_STAT_SHORT = 1, + CABD_STAT_OPEN = 2, + CABD_STAT_FAIL = 3, +}; + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/ + /* Bit 15..12: reserved (used internally) */ +enum { + PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */ + PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */ + PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ +}; + +#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) + +enum { + LED_PAR_CTRL_COLX = 0x00, + LED_PAR_CTRL_ERROR = 0x01, + LED_PAR_CTRL_DUPLEX = 0x02, + LED_PAR_CTRL_DP_COL = 0x03, + LED_PAR_CTRL_SPEED = 0x04, + LED_PAR_CTRL_LINK = 0x05, + LED_PAR_CTRL_TX = 0x06, + LED_PAR_CTRL_RX = 0x07, + LED_PAR_CTRL_ACT = 0x08, + LED_PAR_CTRL_LNK_RX = 0x09, + LED_PAR_CTRL_LNK_AC = 0x0a, + LED_PAR_CTRL_ACT_BL = 0x0b, + LED_PAR_CTRL_TX_BL = 0x0c, + LED_PAR_CTRL_RX_BL = 0x0d, + LED_PAR_CTRL_COL_BL = 0x0e, + LED_PAR_CTRL_INACT = 0x0f +}; + +/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/ +enum { + PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */ + PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */ + PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */ +}; + +/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ +/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ +enum { + PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */ + PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */ + PHY_M_MAC_MD_COPPER = 5,/* Copper only */ + PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ +}; +#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) + +/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ +enum { + PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */ + PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */ + PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */ + PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ +}; + +#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) +#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) +#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) +#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) + +/* GMAC registers */ +/* Port Registers */ +enum { + GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */ + GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */ + GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */ + GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */ + GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */ + GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */ + GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */ +/* Source Address Registers */ + GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */ + GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */ + GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */ + GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */ + GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */ + GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */ + +/* Multicast Address Hash Registers */ + GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */ + GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */ + GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */ + GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */ + +/* Interrupt Source Registers */ + GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */ + GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */ + GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */ + +/* Interrupt Mask Registers */ + GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */ + GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */ + GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */ + +/* Serial Management Interface (SMI) Registers */ + GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ + GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ + GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ +}; + +/* MIB Counters */ +#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ +#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ + +/* + * MIB Counters base address definitions (low word) - + * use offset 4 for access to high word (32 bit r/o) + */ +enum { + GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ + GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ + GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ + GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ + GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ + /* GM_MIB_CNT_BASE + 40: reserved */ + GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ + GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ + GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ + GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */ + GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ + GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ + GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ + GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ + GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ + GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ + GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ + GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ + GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ + GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ + GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ + /* GM_MIB_CNT_BASE + 168: reserved */ + GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ + /* GM_MIB_CNT_BASE + 184: reserved */ + GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ + GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ + GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ + GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ + GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ + GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ + GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ + GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ + GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ + GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ + GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ + GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ + GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ + + GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ + GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ + GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ + GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ + GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ + GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ +}; + +/* GMAC Bit Definitions */ +/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ +enum { + GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */ + GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */ + GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */ + GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ + GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ + GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ + GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ + + GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ + GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ + GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */ + GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */ + GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */ +}; + +/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ +enum { + GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */ + GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */ + GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */ + GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */ + GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */ + GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */ + GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */ + GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */ + GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */ + GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */ + GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */ + GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */ + GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */ + GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */ + GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */ +}; + +#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) +#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS) + +/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ +enum { + GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */ + GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */ + GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */ + GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */ +}; + +#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK) +#define TX_COL_DEF 0x04 + +/* GM_RX_CTRL 16 bit r/w Receive Control Register */ +enum { + GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */ + GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */ + GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */ + GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */ +}; + +/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ +enum { + GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */ + GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */ + GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */ + + TX_JAM_LEN_DEF = 0x03, + TX_JAM_IPG_DEF = 0x0b, + TX_IPG_JAM_DEF = 0x1c, +}; + +#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK) +#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK) +#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK) + + +/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ +enum { + GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */ + GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */ + GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */ + GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */ + GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ +}; + +#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK) +#define DATA_BLIND_DEF 0x04 + +#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) +#define IPG_DATA_DEF 0x1e + +/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ +enum { + GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */ + GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */ + GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/ + GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ + GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ +}; + +#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) +#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) + +/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ +enum { + GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */ + GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */ +}; + +/* Receive Frame Status Encoding */ +enum { + GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ + GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */ + GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */ + GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */ + GMR_FS_MC = 1<<10, /* Bit 10: Multicast Packet */ + GMR_FS_BC = 1<<9, /* Bit 9: Broadcast Packet */ + GMR_FS_RX_OK = 1<<8, /* Bit 8: Receive OK (Good Packet) */ + GMR_FS_GOOD_FC = 1<<7, /* Bit 7: Good Flow-Control Packet */ + GMR_FS_BAD_FC = 1<<6, /* Bit 6: Bad Flow-Control Packet */ + GMR_FS_MII_ERR = 1<<5, /* Bit 5: MII Error */ + GMR_FS_LONG_ERR = 1<<4, /* Bit 4: Too Long Packet */ + GMR_FS_FRAGMENT = 1<<3, /* Bit 3: Fragment */ + + GMR_FS_CRC_ERR = 1<<1, /* Bit 1: CRC Error */ + GMR_FS_RX_FF_OV = 1<<0, /* Bit 0: Rx FIFO Overflow */ + +/* + * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) + */ + GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | + GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | + GMR_FS_JABBER, +/* Rx GMAC FIFO Flush Mask (default) */ + RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR | + GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE | + GMR_FS_JABBER, +}; + +/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ +enum { + GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ + GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ + GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ + + GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */ + GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */ + GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */ + GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */ + GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */ + GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */ + GMF_CLI_RX_FC = 1<<4, /* Clear IRQ Rx Frame Complete */ + GMF_OPER_ON = 1<<3, /* Operational Mode On */ + GMF_OPER_OFF = 1<<2, /* Operational Mode Off */ + GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */ + GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */ + + RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */ +}; + + +/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ +enum { + GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ + GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ + GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */ + + GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */ + GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */ + GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */ +}; + +/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ +enum { + GMT_ST_START = 1<<2, /* Start Time Stamp Timer */ + GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */ + GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */ +}; + +/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ +enum { + GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ + GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ + GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ + GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */ + GMC_PAUSE_ON = 1<<3, /* Pause On */ + GMC_PAUSE_OFF = 1<<2, /* Pause Off */ + GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */ + GMC_RST_SET = 1<<0, /* Set GMAC Reset */ +}; + +/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ +enum { + GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */ + GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */ + GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */ + GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */ + GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */ + GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */ + GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */ + GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */ + GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */ + GPC_ANEG_0 = 1<<19, /* ANEG[0] */ + GPC_ENA_XC = 1<<18, /* Enable MDI crossover */ + GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */ + GPC_ANEG_3 = 1<<16, /* ANEG[3] */ + GPC_ANEG_2 = 1<<15, /* ANEG[2] */ + GPC_ANEG_1 = 1<<14, /* ANEG[1] */ + GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */ + GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */ + GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */ + GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */ + GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */ + GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */ + /* Bits 7..2: reserved */ + GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */ + GPC_RST_SET = 1<<0, /* Set GPHY Reset */ +}; + +#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) +#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) +#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0) + +/* forced speed and duplex mode (don't mix with other ANEG bits) */ +#define GPC_FRC10MBIT_HALF 0 +#define GPC_FRC10MBIT_FULL GPC_ANEG_0 +#define GPC_FRC100MBIT_HALF GPC_ANEG_1 +#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) + +/* auto-negotiation with limited advertised speeds */ +/* mix only with master/slave settings (for copper) */ +#define GPC_ADV_1000_HALF GPC_ANEG_2 +#define GPC_ADV_1000_FULL GPC_ANEG_3 +#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) + +/* master/slave settings */ +/* only for copper with 1000 Mbps */ +#define GPC_FORCE_MASTER 0 +#define GPC_FORCE_SLAVE GPC_ANEG_0 +#define GPC_PREF_MASTER GPC_ANEG_1 +#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) + +/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ +/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ +enum { + GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */ + GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */ + GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */ + GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */ + GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ + GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ + +#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR) + +/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ + /* Bits 15.. 2: reserved */ + GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */ + GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */ + + +/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ + WOL_CTL_LINK_CHG_OCC = 1<<15, + WOL_CTL_MAGIC_PKT_OCC = 1<<14, + WOL_CTL_PATTERN_OCC = 1<<13, + WOL_CTL_CLEAR_RESULT = 1<<12, + WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11, + WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10, + WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9, + WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8, + WOL_CTL_ENA_PME_ON_PATTERN = 1<<7, + WOL_CTL_DIS_PME_ON_PATTERN = 1<<6, + WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5, + WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4, + WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3, + WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2, + WOL_CTL_ENA_PATTERN_UNIT = 1<<1, + WOL_CTL_DIS_PATTERN_UNIT = 1<<0, +}; + +#define WOL_CTL_DEFAULT \ + (WOL_CTL_DIS_PME_ON_LINK_CHG | \ + WOL_CTL_DIS_PME_ON_PATTERN | \ + WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ + WOL_CTL_DIS_LINK_CHG_UNIT | \ + WOL_CTL_DIS_PATTERN_UNIT | \ + WOL_CTL_DIS_MAGIC_PKT_UNIT) + +/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ +#define WOL_CTL_PATT_ENA(x) (1 << (x)) + + +/* XMAC II registers */ +enum { + XM_MMU_CMD = 0x0000, /* 16 bit r/w MMU Command Register */ + XM_POFF = 0x0008, /* 32 bit r/w Packet Offset Register */ + XM_BURST = 0x000c, /* 32 bit r/w Burst Register for half duplex*/ + XM_1L_VLAN_TAG = 0x0010, /* 16 bit r/w One Level VLAN Tag ID */ + XM_2L_VLAN_TAG = 0x0014, /* 16 bit r/w Two Level VLAN Tag ID */ + XM_TX_CMD = 0x0020, /* 16 bit r/w Transmit Command Register */ + XM_TX_RT_LIM = 0x0024, /* 16 bit r/w Transmit Retry Limit Register */ + XM_TX_STIME = 0x0028, /* 16 bit r/w Transmit Slottime Register */ + XM_TX_IPG = 0x002c, /* 16 bit r/w Transmit Inter Packet Gap */ + XM_RX_CMD = 0x0030, /* 16 bit r/w Receive Command Register */ + XM_PHY_ADDR = 0x0034, /* 16 bit r/w PHY Address Register */ + XM_PHY_DATA = 0x0038, /* 16 bit r/w PHY Data Register */ + XM_GP_PORT = 0x0040, /* 32 bit r/w General Purpose Port Register */ + XM_IMSK = 0x0044, /* 16 bit r/w Interrupt Mask Register */ + XM_ISRC = 0x0048, /* 16 bit r/o Interrupt Status Register */ + XM_HW_CFG = 0x004c, /* 16 bit r/w Hardware Config Register */ + XM_TX_LO_WM = 0x0060, /* 16 bit r/w Tx FIFO Low Water Mark */ + XM_TX_HI_WM = 0x0062, /* 16 bit r/w Tx FIFO High Water Mark */ + XM_TX_THR = 0x0064, /* 16 bit r/w Tx Request Threshold */ + XM_HT_THR = 0x0066, /* 16 bit r/w Host Request Threshold */ + XM_PAUSE_DA = 0x0068, /* NA reg r/w Pause Destination Address */ + XM_CTL_PARA = 0x0070, /* 32 bit r/w Control Parameter Register */ + XM_MAC_OPCODE = 0x0074, /* 16 bit r/w Opcode for MAC control frames */ + XM_MAC_PTIME = 0x0076, /* 16 bit r/w Pause time for MAC ctrl frames*/ + XM_TX_STAT = 0x0078, /* 32 bit r/o Tx Status LIFO Register */ + + XM_EXM_START = 0x0080, /* r/w Start Address of the EXM Regs */ +#define XM_EXM(reg) (XM_EXM_START + ((reg) << 3)) +}; + +enum { + XM_SRC_CHK = 0x0100, /* NA reg r/w Source Check Address Register */ + XM_SA = 0x0108, /* NA reg r/w Station Address Register */ + XM_HSM = 0x0110, /* 64 bit r/w Hash Match Address Registers */ + XM_RX_LO_WM = 0x0118, /* 16 bit r/w Receive Low Water Mark */ + XM_RX_HI_WM = 0x011a, /* 16 bit r/w Receive High Water Mark */ + XM_RX_THR = 0x011c, /* 32 bit r/w Receive Request Threshold */ + XM_DEV_ID = 0x0120, /* 32 bit r/o Device ID Register */ + XM_MODE = 0x0124, /* 32 bit r/w Mode Register */ + XM_LSA = 0x0128, /* NA reg r/o Last Source Register */ + XM_TS_READ = 0x0130, /* 32 bit r/o Time Stamp Read Register */ + XM_TS_LOAD = 0x0134, /* 32 bit r/o Time Stamp Load Value */ + XM_STAT_CMD = 0x0200, /* 16 bit r/w Statistics Command Register */ + XM_RX_CNT_EV = 0x0204, /* 32 bit r/o Rx Counter Event Register */ + XM_TX_CNT_EV = 0x0208, /* 32 bit r/o Tx Counter Event Register */ + XM_RX_EV_MSK = 0x020c, /* 32 bit r/w Rx Counter Event Mask */ + XM_TX_EV_MSK = 0x0210, /* 32 bit r/w Tx Counter Event Mask */ + XM_TXF_OK = 0x0280, /* 32 bit r/o Frames Transmitted OK Conuter */ + XM_TXO_OK_HI = 0x0284, /* 32 bit r/o Octets Transmitted OK High Cnt*/ + XM_TXO_OK_LO = 0x0288, /* 32 bit r/o Octets Transmitted OK Low Cnt */ + XM_TXF_BC_OK = 0x028c, /* 32 bit r/o Broadcast Frames Xmitted OK */ + XM_TXF_MC_OK = 0x0290, /* 32 bit r/o Multicast Frames Xmitted OK */ + XM_TXF_UC_OK = 0x0294, /* 32 bit r/o Unicast Frames Xmitted OK */ + XM_TXF_LONG = 0x0298, /* 32 bit r/o Tx Long Frame Counter */ + XM_TXE_BURST = 0x029c, /* 32 bit r/o Tx Burst Event Counter */ + XM_TXF_MPAUSE = 0x02a0, /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ + XM_TXF_MCTRL = 0x02a4, /* 32 bit r/o Tx MAC Ctrl Frame Counter */ + XM_TXF_SNG_COL = 0x02a8, /* 32 bit r/o Tx Single Collision Counter */ + XM_TXF_MUL_COL = 0x02ac, /* 32 bit r/o Tx Multiple Collision Counter */ + XM_TXF_ABO_COL = 0x02b0, /* 32 bit r/o Tx aborted due to Exces. Col. */ + XM_TXF_LAT_COL = 0x02b4, /* 32 bit r/o Tx Late Collision Counter */ + XM_TXF_DEF = 0x02b8, /* 32 bit r/o Tx Deferred Frame Counter */ + XM_TXF_EX_DEF = 0x02bc, /* 32 bit r/o Tx Excessive Deferall Counter */ + XM_TXE_FIFO_UR = 0x02c0, /* 32 bit r/o Tx FIFO Underrun Event Cnt */ + XM_TXE_CS_ERR = 0x02c4, /* 32 bit r/o Tx Carrier Sense Error Cnt */ + XM_TXP_UTIL = 0x02c8, /* 32 bit r/o Tx Utilization in % */ + XM_TXF_64B = 0x02d0, /* 32 bit r/o 64 Byte Tx Frame Counter */ + XM_TXF_127B = 0x02d4, /* 32 bit r/o 65-127 Byte Tx Frame Counter */ + XM_TXF_255B = 0x02d8, /* 32 bit r/o 128-255 Byte Tx Frame Counter */ + XM_TXF_511B = 0x02dc, /* 32 bit r/o 256-511 Byte Tx Frame Counter */ + XM_TXF_1023B = 0x02e0, /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ + XM_TXF_MAX_SZ = 0x02e4, /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ + XM_RXF_OK = 0x0300, /* 32 bit r/o Frames Received OK */ + XM_RXO_OK_HI = 0x0304, /* 32 bit r/o Octets Received OK High Cnt */ + XM_RXO_OK_LO = 0x0308, /* 32 bit r/o Octets Received OK Low Counter*/ + XM_RXF_BC_OK = 0x030c, /* 32 bit r/o Broadcast Frames Received OK */ + XM_RXF_MC_OK = 0x0310, /* 32 bit r/o Multicast Frames Received OK */ + XM_RXF_UC_OK = 0x0314, /* 32 bit r/o Unicast Frames Received OK */ + XM_RXF_MPAUSE = 0x0318, /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ + XM_RXF_MCTRL = 0x031c, /* 32 bit r/o Rx MAC Ctrl Frame Counter */ + XM_RXF_INV_MP = 0x0320, /* 32 bit r/o Rx invalid Pause Frame Cnt */ + XM_RXF_INV_MOC = 0x0324, /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ + XM_RXE_BURST = 0x0328, /* 32 bit r/o Rx Burst Event Counter */ + XM_RXE_FMISS = 0x032c, /* 32 bit r/o Rx Missed Frames Event Cnt */ + XM_RXF_FRA_ERR = 0x0330, /* 32 bit r/o Rx Framing Error Counter */ + XM_RXE_FIFO_OV = 0x0334, /* 32 bit r/o Rx FIFO overflow Event Cnt */ + XM_RXF_JAB_PKT = 0x0338, /* 32 bit r/o Rx Jabber Packet Frame Cnt */ + XM_RXE_CAR_ERR = 0x033c, /* 32 bit r/o Rx Carrier Event Error Cnt */ + XM_RXF_LEN_ERR = 0x0340, /* 32 bit r/o Rx in Range Length Error */ + XM_RXE_SYM_ERR = 0x0344, /* 32 bit r/o Rx Symbol Error Counter */ + XM_RXE_SHT_ERR = 0x0348, /* 32 bit r/o Rx Short Event Error Cnt */ + XM_RXE_RUNT = 0x034c, /* 32 bit r/o Rx Runt Event Counter */ + XM_RXF_LNG_ERR = 0x0350, /* 32 bit r/o Rx Frame too Long Error Cnt */ + XM_RXF_FCS_ERR = 0x0354, /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ + XM_RXF_CEX_ERR = 0x035c, /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ + XM_RXP_UTIL = 0x0360, /* 32 bit r/o Rx Utilization in % */ + XM_RXF_64B = 0x0368, /* 32 bit r/o 64 Byte Rx Frame Counter */ + XM_RXF_127B = 0x036c, /* 32 bit r/o 65-127 Byte Rx Frame Counter */ + XM_RXF_255B = 0x0370, /* 32 bit r/o 128-255 Byte Rx Frame Counter */ + XM_RXF_511B = 0x0374, /* 32 bit r/o 256-511 Byte Rx Frame Counter */ + XM_RXF_1023B = 0x0378, /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ + XM_RXF_MAX_SZ = 0x037c, /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ +}; + +/* XM_MMU_CMD 16 bit r/w MMU Command Register */ +enum { + XM_MMU_PHY_RDY = 1<<12,/* Bit 12: PHY Read Ready */ + XM_MMU_PHY_BUSY = 1<<11,/* Bit 11: PHY Busy */ + XM_MMU_IGN_PF = 1<<10,/* Bit 10: Ignore Pause Frame */ + XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */ + XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */ + XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */ + XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */ + XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */ + XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */ + XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */ + XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */ + XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */ +}; + + +/* XM_TX_CMD 16 bit r/w Transmit Command Register */ +enum { + XM_TX_BK2BK = 1<<6, /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ + XM_TX_ENC_BYP = 1<<5, /* Bit 5: Set Encoder in Bypass Mode */ + XM_TX_SAM_LINE = 1<<4, /* Bit 4: (sc) Start utilization calculation */ + XM_TX_NO_GIG_MD = 1<<3, /* Bit 3: Disable Carrier Extension */ + XM_TX_NO_PRE = 1<<2, /* Bit 2: Disable Preamble Generation */ + XM_TX_NO_CRC = 1<<1, /* Bit 1: Disable CRC Generation */ + XM_TX_AUTO_PAD = 1<<0, /* Bit 0: Enable Automatic Padding */ +}; + +/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ +#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ + + +/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ +#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ + + +/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ +#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ + + +/* XM_RX_CMD 16 bit r/w Receive Command Register */ +enum { + XM_RX_LENERR_OK = 1<<8, /* Bit 8 don't set Rx Err bit for */ + /* inrange error packets */ + XM_RX_BIG_PK_OK = 1<<7, /* Bit 7 don't set Rx Err bit for */ + /* jumbo packets */ + XM_RX_IPG_CAP = 1<<6, /* Bit 6 repl. type field with IPG */ + XM_RX_TP_MD = 1<<5, /* Bit 5: Enable transparent Mode */ + XM_RX_STRIP_FCS = 1<<4, /* Bit 4: Enable FCS Stripping */ + XM_RX_SELF_RX = 1<<3, /* Bit 3: Enable Rx of own packets */ + XM_RX_SAM_LINE = 1<<2, /* Bit 2: (sc) Start utilization calculation */ + XM_RX_STRIP_PAD = 1<<1, /* Bit 1: Strip pad bytes of Rx frames */ + XM_RX_DIS_CEXT = 1<<0, /* Bit 0: Disable carrier ext. check */ +}; + + +/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ +enum { + XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */ + XM_GP_FRC_INT = 1<<5, /* Bit 5: (sc) Force Interrupt */ + XM_GP_RES_MAC = 1<<3, /* Bit 3: (sc) Reset MAC and FIFOs */ + XM_GP_RES_STAT = 1<<2, /* Bit 2: (sc) Reset the statistics module */ + XM_GP_INP_ASS = 1<<0, /* Bit 0: (ro) GP Input Pin asserted */ +}; + + +/* XM_IMSK 16 bit r/w Interrupt Mask Register */ +/* XM_ISRC 16 bit r/o Interrupt Status Register */ +enum { + XM_IS_LNK_AE = 1<<14, /* Bit 14: Link Asynchronous Event */ + XM_IS_TX_ABORT = 1<<13, /* Bit 13: Transmit Abort, late Col. etc */ + XM_IS_FRC_INT = 1<<12, /* Bit 12: Force INT bit set in GP */ + XM_IS_INP_ASS = 1<<11, /* Bit 11: Input Asserted, GP bit 0 set */ + XM_IS_LIPA_RC = 1<<10, /* Bit 10: Link Partner requests config */ + XM_IS_RX_PAGE = 1<<9, /* Bit 9: Page Received */ + XM_IS_TX_PAGE = 1<<8, /* Bit 8: Next Page Loaded for Transmit */ + XM_IS_AND = 1<<7, /* Bit 7: Auto-Negotiation Done */ + XM_IS_TSC_OV = 1<<6, /* Bit 6: Time Stamp Counter Overflow */ + XM_IS_RXC_OV = 1<<5, /* Bit 5: Rx Counter Event Overflow */ + XM_IS_TXC_OV = 1<<4, /* Bit 4: Tx Counter Event Overflow */ + XM_IS_RXF_OV = 1<<3, /* Bit 3: Receive FIFO Overflow */ + XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */ + XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */ + XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ +}; + +#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \ + XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \ + XM_IS_RXF_OV | XM_IS_TXF_UR)) + + +/* XM_HW_CFG 16 bit r/w Hardware Config Register */ +enum { + XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */ + XM_HW_COM4SIG = 1<<2, /* Bit 2: use Comma Detect for Sig. Det.*/ + XM_HW_GMII_MD = 1<<0, /* Bit 0: GMII Interface selected */ +}; + + +/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ +/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ +#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ + +/* XM_TX_THR 16 bit r/w Tx Request Threshold */ +/* XM_HT_THR 16 bit r/w Host Request Threshold */ +/* XM_RX_THR 16 bit r/w Rx Request Threshold */ +#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ + + +/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ +enum { + XM_ST_VALID = (1UL<<31), /* Bit 31: Status Valid */ + XM_ST_BYTE_CNT = (0x3fffL<<17), /* Bit 30..17: Tx frame Length */ + XM_ST_RETRY_CNT = (0x1fL<<12), /* Bit 16..12: Retry Count */ + XM_ST_EX_COL = 1<<11, /* Bit 11: Excessive Collisions */ + XM_ST_EX_DEF = 1<<10, /* Bit 10: Excessive Deferral */ + XM_ST_BURST = 1<<9, /* Bit 9: p. xmitted in burst md*/ + XM_ST_DEFER = 1<<8, /* Bit 8: packet was defered */ + XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */ + XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */ + XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */ + XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occured */ + XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */ + XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */ + XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */ + XM_ST_SGN_COL = 1<<0, /* Bit 0: Single Collision */ +}; + +/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ +/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ +#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ + + +/* XM_DEV_ID 32 bit r/o Device ID Register */ +#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ +#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ + + +/* XM_MODE 32 bit r/w Mode Register */ +enum { + XM_MD_ENA_REJ = 1<<26, /* Bit 26: Enable Frame Reject */ + XM_MD_SPOE_E = 1<<25, /* Bit 25: Send Pause on Edge */ + /* extern generated */ + XM_MD_TX_REP = 1<<24, /* Bit 24: Transmit Repeater Mode */ + XM_MD_SPOFF_I = 1<<23, /* Bit 23: Send Pause on FIFO full */ + /* intern generated */ + XM_MD_LE_STW = 1<<22, /* Bit 22: Rx Stat Word in Little Endian */ + XM_MD_TX_CONT = 1<<21, /* Bit 21: Send Continuous */ + XM_MD_TX_PAUSE = 1<<20, /* Bit 20: (sc) Send Pause Frame */ + XM_MD_ATS = 1<<19, /* Bit 19: Append Time Stamp */ + XM_MD_SPOL_I = 1<<18, /* Bit 18: Send Pause on Low */ + /* intern generated */ + XM_MD_SPOH_I = 1<<17, /* Bit 17: Send Pause on High */ + /* intern generated */ + XM_MD_CAP = 1<<16, /* Bit 16: Check Address Pair */ + XM_MD_ENA_HASH = 1<<15, /* Bit 15: Enable Hashing */ + XM_MD_CSA = 1<<14, /* Bit 14: Check Station Address */ + XM_MD_CAA = 1<<13, /* Bit 13: Check Address Array */ + XM_MD_RX_MCTRL = 1<<12, /* Bit 12: Rx MAC Control Frame */ + XM_MD_RX_RUNT = 1<<11, /* Bit 11: Rx Runt Frames */ + XM_MD_RX_IRLE = 1<<10, /* Bit 10: Rx in Range Len Err Frame */ + XM_MD_RX_LONG = 1<<9, /* Bit 9: Rx Long Frame */ + XM_MD_RX_CRCE = 1<<8, /* Bit 8: Rx CRC Error Frame */ + XM_MD_RX_ERR = 1<<7, /* Bit 7: Rx Error Frame */ + XM_MD_DIS_UC = 1<<6, /* Bit 6: Disable Rx Unicast */ + XM_MD_DIS_MC = 1<<5, /* Bit 5: Disable Rx Multicast */ + XM_MD_DIS_BC = 1<<4, /* Bit 4: Disable Rx Broadcast */ + XM_MD_ENA_PROM = 1<<3, /* Bit 3: Enable Promiscuous */ + XM_MD_ENA_BE = 1<<2, /* Bit 2: Enable Big Endian */ + XM_MD_FTF = 1<<1, /* Bit 1: (sc) Flush Tx FIFO */ + XM_MD_FRF = 1<<0, /* Bit 0: (sc) Flush Rx FIFO */ +}; + +#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) +#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ + XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA) + +/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ +enum { + XM_SC_SNP_RXC = 1<<5, /* Bit 5: (sc) Snap Rx Counters */ + XM_SC_SNP_TXC = 1<<4, /* Bit 4: (sc) Snap Tx Counters */ + XM_SC_CP_RXC = 1<<3, /* Bit 3: Copy Rx Counters Continuously */ + XM_SC_CP_TXC = 1<<2, /* Bit 2: Copy Tx Counters Continuously */ + XM_SC_CLR_RXC = 1<<1, /* Bit 1: (sc) Clear Rx Counters */ + XM_SC_CLR_TXC = 1<<0, /* Bit 0: (sc) Clear Tx Counters */ +}; + + +/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ +/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ +enum { + XMR_MAX_SZ_OV = 1<<31, /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ + XMR_1023B_OV = 1<<30, /* Bit 30: 512-1023Byte Rx Cnt Ov*/ + XMR_511B_OV = 1<<29, /* Bit 29: 256-511 Byte Rx Cnt Ov*/ + XMR_255B_OV = 1<<28, /* Bit 28: 128-255 Byte Rx Cnt Ov*/ + XMR_127B_OV = 1<<27, /* Bit 27: 65-127 Byte Rx Cnt Ov */ + XMR_64B_OV = 1<<26, /* Bit 26: 64 Byte Rx Cnt Ov */ + XMR_UTIL_OV = 1<<25, /* Bit 25: Rx Util Cnt Overflow */ + XMR_UTIL_UR = 1<<24, /* Bit 24: Rx Util Cnt Underrun */ + XMR_CEX_ERR_OV = 1<<23, /* Bit 23: CEXT Err Cnt Ov */ + XMR_FCS_ERR_OV = 1<<21, /* Bit 21: Rx FCS Error Cnt Ov */ + XMR_LNG_ERR_OV = 1<<20, /* Bit 20: Rx too Long Err Cnt Ov*/ + XMR_RUNT_OV = 1<<19, /* Bit 19: Runt Event Cnt Ov */ + XMR_SHT_ERR_OV = 1<<18, /* Bit 18: Rx Short Ev Err Cnt Ov*/ + XMR_SYM_ERR_OV = 1<<17, /* Bit 17: Rx Sym Err Cnt Ov */ + XMR_CAR_ERR_OV = 1<<15, /* Bit 15: Rx Carr Ev Err Cnt Ov */ + XMR_JAB_PKT_OV = 1<<14, /* Bit 14: Rx Jabb Packet Cnt Ov */ + XMR_FIFO_OV = 1<<13, /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ + XMR_FRA_ERR_OV = 1<<12, /* Bit 12: Rx Framing Err Cnt Ov */ + XMR_FMISS_OV = 1<<11, /* Bit 11: Rx Missed Ev Cnt Ov */ + XMR_BURST = 1<<10, /* Bit 10: Rx Burst Event Cnt Ov */ + XMR_INV_MOC = 1<<9, /* Bit 9: Rx with inv. MAC OC Ov*/ + XMR_INV_MP = 1<<8, /* Bit 8: Rx inv Pause Frame Ov */ + XMR_MCTRL_OV = 1<<7, /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ + XMR_MPAUSE_OV = 1<<6, /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ + XMR_UC_OK_OV = 1<<5, /* Bit 5: Rx Unicast Frame CntOv*/ + XMR_MC_OK_OV = 1<<4, /* Bit 4: Rx Multicast Cnt Ov */ + XMR_BC_OK_OV = 1<<3, /* Bit 3: Rx Broadcast Cnt Ov */ + XMR_OK_LO_OV = 1<<2, /* Bit 2: Octets Rx OK Low CntOv*/ + XMR_OK_HI_OV = 1<<1, /* Bit 1: Octets Rx OK Hi Cnt Ov*/ + XMR_OK_OV = 1<<0, /* Bit 0: Frames Received Ok Ov */ +}; + +#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) + +/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ +/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ +enum { + XMT_MAX_SZ_OV = 1<<25, /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ + XMT_1023B_OV = 1<<24, /* Bit 24: 512-1023Byte Tx Cnt Ov*/ + XMT_511B_OV = 1<<23, /* Bit 23: 256-511 Byte Tx Cnt Ov*/ + XMT_255B_OV = 1<<22, /* Bit 22: 128-255 Byte Tx Cnt Ov*/ + XMT_127B_OV = 1<<21, /* Bit 21: 65-127 Byte Tx Cnt Ov */ + XMT_64B_OV = 1<<20, /* Bit 20: 64 Byte Tx Cnt Ov */ + XMT_UTIL_OV = 1<<19, /* Bit 19: Tx Util Cnt Overflow */ + XMT_UTIL_UR = 1<<18, /* Bit 18: Tx Util Cnt Underrun */ + XMT_CS_ERR_OV = 1<<17, /* Bit 17: Tx Carr Sen Err Cnt Ov*/ + XMT_FIFO_UR_OV = 1<<16, /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ + XMT_EX_DEF_OV = 1<<15, /* Bit 15: Tx Ex Deferall Cnt Ov */ + XMT_DEF = 1<<14, /* Bit 14: Tx Deferred Cnt Ov */ + XMT_LAT_COL_OV = 1<<13, /* Bit 13: Tx Late Col Cnt Ov */ + XMT_ABO_COL_OV = 1<<12, /* Bit 12: Tx abo dueto Ex Col Ov*/ + XMT_MUL_COL_OV = 1<<11, /* Bit 11: Tx Mult Col Cnt Ov */ + XMT_SNG_COL = 1<<10, /* Bit 10: Tx Single Col Cnt Ov */ + XMT_MCTRL_OV = 1<<9, /* Bit 9: Tx MAC Ctrl Counter Ov*/ + XMT_MPAUSE = 1<<8, /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ + XMT_BURST = 1<<7, /* Bit 7: Tx Burst Event Cnt Ov */ + XMT_LONG = 1<<6, /* Bit 6: Tx Long Frame Cnt Ov */ + XMT_UC_OK_OV = 1<<5, /* Bit 5: Tx Unicast Cnt Ov */ + XMT_MC_OK_OV = 1<<4, /* Bit 4: Tx Multicast Cnt Ov */ + XMT_BC_OK_OV = 1<<3, /* Bit 3: Tx Broadcast Cnt Ov */ + XMT_OK_LO_OV = 1<<2, /* Bit 2: Octets Tx OK Low CntOv*/ + XMT_OK_HI_OV = 1<<1, /* Bit 1: Octets Tx OK Hi Cnt Ov*/ + XMT_OK_OV = 1<<0, /* Bit 0: Frames Tx Ok Ov */ +}; + +#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) + +struct skge_rx_desc { + u32 control; + u32 next_offset; + u32 dma_lo; + u32 dma_hi; + u32 status; + u32 timestamp; + u16 csum2; + u16 csum1; + u16 csum2_start; + u16 csum1_start; +}; + +struct skge_tx_desc { + u32 control; + u32 next_offset; + u32 dma_lo; + u32 dma_hi; + u32 status; + u32 csum_offs; + u16 csum_write; + u16 csum_start; + u32 rsvd; +}; + +struct skge_element { + struct skge_element *next; + void *desc; + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(mapaddr); + DECLARE_PCI_UNMAP_LEN(maplen); +}; + +struct skge_ring { + struct skge_element *to_clean; + struct skge_element *to_use; + struct skge_element *start; + unsigned long count; +}; + + +struct skge_hw { + void __iomem *regs; + struct pci_dev *pdev; + u32 intr_mask; + struct net_device *dev[2]; + + u8 chip_id; + u8 chip_rev; + u8 phy_type; + u8 pmd_type; + u16 phy_addr; + u8 ports; + + u32 ram_size; + u32 ram_offset; + + struct tasklet_struct ext_tasklet; + spinlock_t phy_lock; +}; + + +static inline int iscopper(const struct skge_hw *hw) +{ + return (hw->pmd_type == 'T'); +} + +enum { + FLOW_MODE_NONE = 0, /* No Flow-Control */ + FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */ + FLOW_MODE_REM_SEND = 2, /* Symmetric or just remote */ + FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */ +}; + +struct skge_port { + u32 msg_enable; + struct skge_hw *hw; + struct net_device *netdev; + int port; + + spinlock_t tx_lock; + u32 tx_avail; + struct skge_ring tx_ring; + struct skge_ring rx_ring; + + struct net_device_stats net_stats; + + u8 rx_csum; + u8 blink_on; + u8 flow_control; + u8 wol; + u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ + u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ + u16 speed; /* SPEED_1000, SPEED_100, ... */ + u32 advertising; + + void *mem; /* PCI memory for rings */ + dma_addr_t dma; + unsigned long mem_size; + unsigned int rx_buf_size; +}; + + +/* Register accessor for memory mapped device */ +static inline u32 skge_read32(const struct skge_hw *hw, int reg) +{ + return readl(hw->regs + reg); +} + +static inline u16 skge_read16(const struct skge_hw *hw, int reg) +{ + return readw(hw->regs + reg); +} + +static inline u8 skge_read8(const struct skge_hw *hw, int reg) +{ + return readb(hw->regs + reg); +} + +static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val) +{ + writel(val, hw->regs + reg); +} + +static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val) +{ + writew(val, hw->regs + reg); +} + +static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val) +{ + writeb(val, hw->regs + reg); +} + +/* MAC Related Registers inside the device. */ +#define SK_REG(port,reg) (((port)<<7)+(reg)) +#define SK_XMAC_REG(port, reg) \ + ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1) + +static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg) +{ + u32 v; + v = skge_read16(hw, SK_XMAC_REG(port, reg)); + v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16; + return v; +} + +static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg) +{ + return skge_read16(hw, SK_XMAC_REG(port,reg)); +} + +static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v) +{ + skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff); + skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16); +} + +static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v) +{ + skge_write16(hw, SK_XMAC_REG(port,r), v); +} + +static inline void xm_outhash(const struct skge_hw *hw, int port, int reg, + const u8 *hash) +{ + xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8)); + xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8)); + xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8)); + xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8)); +} + +static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg, + const u8 *addr) +{ + xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8)); + xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8)); + xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8)); +} + +#define SK_GMAC_REG(port,reg) \ + (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg)) + +static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg) +{ + return skge_read16(hw, SK_GMAC_REG(port,reg)); +} + +static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg) +{ + return (u32) skge_read16(hw, SK_GMAC_REG(port,reg)) + | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16); +} + +static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) +{ + skge_write16(hw, SK_GMAC_REG(port,r), v); +} + +static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, + const u8 *addr) +{ + gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8)); + gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); + gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); +} + +#endif diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 8f7841c0374d..404ea4297e32 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -74,6 +74,7 @@ #include <linux/rtnetlink.h> #include <linux/if_arp.h> #include <linux/if_slip.h> +#include <linux/delay.h> #include <linux/init.h> #include "slip.h" #ifdef CONFIG_INET @@ -198,18 +199,12 @@ err_exit: static void sl_free_bufs(struct slip *sl) { - void * tmp; - /* Free all SLIP frame buffers. */ - tmp = xchg(&sl->rbuff, NULL); - kfree(tmp); - tmp = xchg(&sl->xbuff, NULL); - kfree(tmp); + kfree(xchg(&sl->rbuff, NULL)); + kfree(xchg(&sl->xbuff, NULL)); #ifdef SL_INCLUDE_CSLIP - tmp = xchg(&sl->cbuff, NULL); - kfree(tmp); - if ((tmp = xchg(&sl->slcomp, NULL)) != NULL) - slhc_free(tmp); + kfree(xchg(&sl->cbuff, NULL)); + slhc_free(xchg(&sl->slcomp, NULL)); #endif } @@ -1389,10 +1384,8 @@ static void __exit slip_exit(void) /* First of all: check for active disciplines and hangup them. */ do { - if (busy) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); - } + if (busy) + msleep_interruptible(100); busy = 0; for (i = 0; i < slip_maxdev; i++) { @@ -1430,7 +1423,7 @@ static void __exit slip_exit(void) kfree(slip_devs); slip_devs = NULL; - if ((i = tty_register_ldisc(N_SLIP, NULL))) + if ((i = tty_unregister_ldisc(N_SLIP))) { printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); } diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 990201f42ba0..f00c476064f0 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -49,7 +49,6 @@ #include <asm/system.h> #include "8390.h" -#include "smc-mca.h" #define DRV_NAME "smc-mca" @@ -100,6 +99,63 @@ module_param_array(ultra_irq, int, NULL, 0); MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)"); MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)"); +static const struct { + unsigned int base_addr; +} addr_table[] = { + { 0x0800 }, + { 0x1800 }, + { 0x2800 }, + { 0x3800 }, + { 0x4800 }, + { 0x5800 }, + { 0x6800 }, + { 0x7800 }, + { 0x8800 }, + { 0x9800 }, + { 0xa800 }, + { 0xb800 }, + { 0xc800 }, + { 0xd800 }, + { 0xe800 }, + { 0xf800 } +}; + +#define MEM_MASK 64 + +static const struct { + unsigned char mem_index; + unsigned long mem_start; + unsigned char num_pages; +} mem_table[] = { + { 16, 0x0c0000, 40 }, + { 18, 0x0c4000, 40 }, + { 20, 0x0c8000, 40 }, + { 22, 0x0cc000, 40 }, + { 24, 0x0d0000, 40 }, + { 26, 0x0d4000, 40 }, + { 28, 0x0d8000, 40 }, + { 30, 0x0dc000, 40 }, + {144, 0xfc0000, 40 }, + {148, 0xfc8000, 40 }, + {154, 0xfd0000, 40 }, + {156, 0xfd8000, 40 }, + { 0, 0x0c0000, 20 }, + { 1, 0x0c2000, 20 }, + { 2, 0x0c4000, 20 }, + { 3, 0x0c6000, 20 } +}; + +#define IRQ_MASK 243 +static const struct { + unsigned char new_irq; + unsigned char old_irq; +} irq_table[] = { + { 3, 3 }, + { 4, 4 }, + { 10, 10 }, + { 14, 15 } +}; + static short smc_mca_adapter_ids[] __initdata = { 0x61c8, 0x61c9, @@ -126,7 +182,7 @@ static char *smc_mca_adapter_names[] __initdata = { static int ultra_found = 0; -int __init ultramca_probe(struct device *gen_dev) +static int __init ultramca_probe(struct device *gen_dev) { unsigned short ioaddr; struct net_device *dev; diff --git a/drivers/net/smc-mca.h b/drivers/net/smc-mca.h deleted file mode 100644 index ac50117a7e84..000000000000 --- a/drivers/net/smc-mca.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * djweis weisd3458@uni.edu - * most of this file was taken from ps2esdi.h - */ - -struct { - unsigned int base_addr; -} addr_table[] = { - { 0x0800 }, - { 0x1800 }, - { 0x2800 }, - { 0x3800 }, - { 0x4800 }, - { 0x5800 }, - { 0x6800 }, - { 0x7800 }, - { 0x8800 }, - { 0x9800 }, - { 0xa800 }, - { 0xb800 }, - { 0xc800 }, - { 0xd800 }, - { 0xe800 }, - { 0xf800 } -}; - -#define MEM_MASK 64 - -struct { - unsigned char mem_index; - unsigned long mem_start; - unsigned char num_pages; -} mem_table[] = { - { 16, 0x0c0000, 40 }, - { 18, 0x0c4000, 40 }, - { 20, 0x0c8000, 40 }, - { 22, 0x0cc000, 40 }, - { 24, 0x0d0000, 40 }, - { 26, 0x0d4000, 40 }, - { 28, 0x0d8000, 40 }, - { 30, 0x0dc000, 40 }, - {144, 0xfc0000, 40 }, - {148, 0xfc8000, 40 }, - {154, 0xfd0000, 40 }, - {156, 0xfd8000, 40 }, - { 0, 0x0c0000, 20 }, - { 1, 0x0c2000, 20 }, - { 2, 0x0c4000, 20 }, - { 3, 0x0c6000, 20 } -}; - -#define IRQ_MASK 243 -struct { - unsigned char new_irq; - unsigned char old_irq; -} irq_table[] = { - { 3, 3 }, - { 4, 4 }, - { 10, 10 }, - { 14, 15 } -}; diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index b564c677c6d2..6d9dae60a697 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -194,12 +194,7 @@ struct net_device * __init ultra_probe(int unit) err = do_ultra_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -325,6 +320,9 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr) #endif NS8390_init(dev, 0); + retval = register_netdev(dev); + if (retval) + goto out; return 0; out: release_region(ioaddr, ULTRA_IO_EXTENT); @@ -583,11 +581,8 @@ init_module(void) dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; if (do_ultra_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ultra[found++] = dev; - continue; - } - cleanup_card(dev); + dev_ultra[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 5e561ba44333..1438fdd20826 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -129,7 +129,7 @@ MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); /* * Transmit timeout, default 5 seconds. */ -static int watchdog = 5000; +static int watchdog = 1000; module_param(watchdog, int, 0400); MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); @@ -315,15 +315,25 @@ static void smc_reset(struct net_device *dev) struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int ctl, cfg; + struct sk_buff *pending_skb; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); - /* Disable all interrupts */ + /* Disable all interrupts, block TX tasklet */ spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); + pending_skb = lp->pending_tx_skb; + lp->pending_tx_skb = NULL; spin_unlock(&lp->lock); + /* free any pending tx skb */ + if (pending_skb) { + dev_kfree_skb(pending_skb); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } + /* * This resets the registers mostly to defaults, but doesn't * affect EEPROM. That seems unnecessary @@ -389,14 +399,6 @@ static void smc_reset(struct net_device *dev) SMC_SELECT_BANK(2); SMC_SET_MMU_CMD(MC_RESET); SMC_WAIT_MMU_BUSY(); - - /* clear anything saved */ - if (lp->pending_tx_skb != NULL) { - dev_kfree_skb (lp->pending_tx_skb); - lp->pending_tx_skb = NULL; - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - } } /* @@ -440,6 +442,7 @@ static void smc_shutdown(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; + struct sk_buff *pending_skb; DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); @@ -447,7 +450,11 @@ static void smc_shutdown(struct net_device *dev) spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); + pending_skb = lp->pending_tx_skb; + lp->pending_tx_skb = NULL; spin_unlock(&lp->lock); + if (pending_skb) + dev_kfree_skb(pending_skb); /* and tell the card to stay away from that nasty outside world */ SMC_SELECT_BANK(0); @@ -627,7 +634,12 @@ static void smc_hardware_send_pkt(unsigned long data) } skb = lp->pending_tx_skb; + if (unlikely(!skb)) { + smc_special_unlock(&lp->lock); + return; + } lp->pending_tx_skb = NULL; + packet_no = SMC_GET_AR(); if (unlikely(packet_no & AR_FAILED)) { printk("%s: Memory allocation failed.\n", dev->name); @@ -660,15 +672,14 @@ static void smc_hardware_send_pkt(unsigned long data) SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG); /* - * If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag - * before queueing this packet for TX, and if it's clear then - * we stop the queue here. This will have the effect of - * having at most 2 packets queued for TX in the chip's memory - * at all time. If THROTTLE_TX_PKTS is not set then the queue - * is stopped only when memory allocation (MC_ALLOC) does not - * succeed right away. + * If THROTTLE_TX_PKTS is set, we stop the queue here. This will + * have the effect of having at most one packet queued for TX + * in the chip's memory at all time. + * + * If THROTTLE_TX_PKTS is not set then the queue is stopped only + * when memory allocation (MC_ALLOC) does not succeed right away. */ - if (THROTTLE_TX_PKTS && !(SMC_GET_INT() & IM_TX_EMPTY_INT)) + if (THROTTLE_TX_PKTS) netif_stop_queue(dev); /* queue the packet for TX */ @@ -703,7 +714,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) DBG(3, "%s: %s\n", dev->name, __FUNCTION__); BUG_ON(lp->pending_tx_skb != NULL); - lp->pending_tx_skb = skb; /* * The MMU wants the number of pages to be the number of 256 bytes @@ -719,7 +729,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) numPages = ((skb->len & ~1) + (6 - 1)) >> 8; if (unlikely(numPages > 7)) { printk("%s: Far too big packet error.\n", dev->name); - lp->pending_tx_skb = NULL; lp->stats.tx_errors++; lp->stats.tx_dropped++; dev_kfree_skb(skb); @@ -746,6 +755,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) smc_special_unlock(&lp->lock); + lp->pending_tx_skb = skb; if (!poll_count) { /* oh well, wait until the chip finds memory later */ netif_stop_queue(dev); @@ -792,17 +802,20 @@ static void smc_tx(struct net_device *dev) DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n", dev->name, tx_status, packet_no); - if (!(tx_status & TS_SUCCESS)) + if (!(tx_status & ES_TX_SUC)) lp->stats.tx_errors++; - if (tx_status & TS_LOSTCAR) + + if (tx_status & ES_LOSTCARR) lp->stats.tx_carrier_errors++; - if (tx_status & TS_LATCOL) { - PRINTK("%s: late collision occurred on last xmit\n", dev->name); + if (tx_status & (ES_LATCOL | ES_16COL)) { + PRINTK("%s: %s occurred on last xmit\n", dev->name, + (tx_status & ES_LATCOL) ? + "late collision" : "too many collisions"); lp->stats.tx_window_errors++; if (!(lp->stats.tx_window_errors & 63) && net_ratelimit()) { - printk(KERN_INFO "%s: unexpectedly large numbers of " - "late collisions. Please check duplex " + printk(KERN_INFO "%s: unexpectedly large number of " + "bad collisions. Please check duplex " "setting.\n", dev->name); } } @@ -1060,7 +1073,7 @@ static void smc_phy_powerdown(struct net_device *dev) above). linkwatch_event() also wants the netlink semaphore. */ while(lp->work_pending) - schedule(); + yield(); bmcr = smc_phy_read(dev, phy, MII_BMCR); smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); @@ -1236,7 +1249,7 @@ static void smc_10bt_check_media(struct net_device *dev, int init) old_carrier = netif_carrier_ok(dev) ? 1 : 0; SMC_SELECT_BANK(0); - new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0; + new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0; SMC_SELECT_BANK(2); if (init || (old_carrier != new_carrier)) { @@ -1308,15 +1321,16 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!status) break; - if (status & IM_RCV_INT) { - DBG(3, "%s: RX irq\n", dev->name); - smc_rcv(dev); - } else if (status & IM_TX_INT) { + if (status & IM_TX_INT) { + /* do this before RX as it will free memory quickly */ DBG(3, "%s: TX int\n", dev->name); smc_tx(dev); SMC_ACK_INT(IM_TX_INT); if (THROTTLE_TX_PKTS) netif_wake_queue(dev); + } else if (status & IM_RCV_INT) { + DBG(3, "%s: RX irq\n", dev->name); + smc_rcv(dev); } else if (status & IM_ALLOC_INT) { DBG(3, "%s: Allocation irq\n", dev->name); tasklet_hi_schedule(&lp->tx_task); @@ -1337,7 +1351,10 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* multiple collisions */ lp->stats.collisions += card_stats & 0xF; } else if (status & IM_RX_OVRN_INT) { - DBG(1, "%s: RX overrun\n", dev->name); + DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name, + ({ int eph_st; SMC_SELECT_BANK(0); + eph_st = SMC_GET_EPH_STATUS(); + SMC_SELECT_BANK(2); eph_st; }) ); SMC_ACK_INT(IM_RX_OVRN_INT); lp->stats.rx_errors++; lp->stats.rx_fifo_errors++; @@ -1389,7 +1406,7 @@ static void smc_timeout(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - int status, mask, meminfo, fifo; + int status, mask, eph_st, meminfo, fifo; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); @@ -1398,11 +1415,13 @@ static void smc_timeout(struct net_device *dev) mask = SMC_GET_INT_MASK(); fifo = SMC_GET_FIFO(); SMC_SELECT_BANK(0); + eph_st = SMC_GET_EPH_STATUS(); meminfo = SMC_GET_MIR(); SMC_SELECT_BANK(2); spin_unlock_irq(&lp->lock); - PRINTK( "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", - dev->name, status, mask, meminfo, fifo ); + PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x " + "MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n", + dev->name, status, mask, meminfo, fifo, eph_st ); smc_reset(dev); smc_enable(dev); @@ -1598,14 +1617,8 @@ static int smc_close(struct net_device *dev) /* clear everything */ smc_shutdown(dev); - + tasklet_kill(&lp->tx_task); smc_phy_powerdown(dev); - - if (lp->pending_tx_skb) { - dev_kfree_skb(lp->pending_tx_skb); - lp->pending_tx_skb = NULL; - } - return 0; } @@ -1863,7 +1876,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) SMC_SELECT_BANK(1); val = SMC_GET_BASE(); val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT; - if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */ + if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) { printk("%s: IOADDR %p doesn't match configuration (%x).\n", CARDNAME, ioaddr, val); } @@ -1985,7 +1998,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) if (retval) goto err_out; - set_irq_type(dev->irq, IRQT_RISING); + set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); #ifdef SMC_USE_PXA_DMA { diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index ddd2688e7d33..a9b06b8d8e3f 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -151,7 +151,7 @@ /* We actually can't write halfwords properly if not word aligned */ static inline void -SMC_outw(u16 val, unsigned long ioaddr, int reg) +SMC_outw(u16 val, void __iomem *ioaddr, int reg) { if (reg & 2) { unsigned int v = val << 16; @@ -182,6 +182,16 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg) #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) +#include <asm/mach-types.h> +#include <asm/arch/cpu.h> + +#define SMC_IRQ_TRIGGER_TYPE (( \ + machine_is_omap_h2() \ + || machine_is_omap_h3() \ + || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ + ) ? IRQT_FALLING : IRQT_RISING) + + #elif defined(CONFIG_SH_SH4202_MICRODEV) #define SMC_CAN_USE_8BIT 0 @@ -300,6 +310,9 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #endif +#ifndef SMC_IRQ_TRIGGER_TYPE +#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING +#endif #ifdef SMC_USE_PXA_DMA /* @@ -317,7 +330,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #define SMC_insl(a, r, p, l) \ smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l) static inline void -smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma, +smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma, u_char *buf, int len) { dma_addr_t dmabuf; @@ -355,7 +368,7 @@ smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma, #define SMC_insw(a, r, p, l) \ smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l) static inline void -smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma, +smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma, u_char *buf, int len) { dma_addr_t dmabuf; @@ -681,14 +694,6 @@ static const char * chip_ids[ 16 ] = { /* - . Transmit status bits -*/ -#define TS_SUCCESS 0x0001 -#define TS_LOSTCAR 0x0400 -#define TS_LATCOL 0x0200 -#define TS_16COL 0x0010 - -/* . Receive status bits */ #define RS_ALGNERR 0x8000 @@ -845,6 +850,7 @@ static const char * chip_ids[ 16 ] = { #define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG ) #define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG ) #define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG ) +#define SMC_GET_EPH_STATUS() SMC_inw( ioaddr, EPH_STATUS_REG ) #define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG ) #define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG ) #define SMC_GET_REV() SMC_inw( ioaddr, REV_REG ) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 236bdd3f6ba0..88b89dc95c77 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -2,7 +2,7 @@ /* Written 1998-2000 by Donald Becker. - Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please + Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please send all bug reports to me, and not to Donald Becker, as this code has been heavily modified from Donald's original version. @@ -129,12 +129,18 @@ - put the chip to a D3 slumber on driver unload - added config option to enable/disable NAPI -TODO: bugfixes (no bugs known as of right now) + LK1.4.2 (Ion Badulescu) + - finally added firmware (GPL'ed by Adaptec) + - removed compatibility code for 2.2.x + +TODO: - fix forced speed/duplexing code (broken a long time ago, when + somebody converted the driver to use the generic MII code) + - fix VLAN support */ #define DRV_NAME "starfire" -#define DRV_VERSION "1.03+LK1.4.1" -#define DRV_RELDATE "February 10, 2002" +#define DRV_VERSION "1.03+LK1.4.2" +#define DRV_RELDATE "January 19, 2005" #include <linux/config.h> #include <linux/version.h> @@ -145,25 +151,15 @@ TODO: bugfixes (no bugs known as of right now) #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/crc32.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/if_vlan.h> #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/uaccess.h> #include <asm/io.h> -/* - * Adaptec's license for their drivers (which is where I got the - * firmware files) does not allow one to redistribute them. Thus, we can't - * include the firmware with this driver. - * - * However, should a legal-to-distribute firmware become available, - * the driver developer would need only to obtain the firmware in the - * form of a C header file. - * Once that's done, the #undef below must be changed into a #define - * for this driver to really use the firmware. Note that Rx/Tx - * hardware TCP checksumming is not possible without the firmware. - * - * WANTED: legal firmware to include with this GPL'd driver. - */ -#undef HAS_FIRMWARE +#include "starfire_firmware.h" /* * The current frame processor firmware fails to checksum a fragment * of length 1. If and when this is fixed, the #define below can be removed. @@ -172,13 +168,7 @@ TODO: bugfixes (no bugs known as of right now) /* * Define this if using the driver with the zero-copy patch */ -#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS) #define ZEROCOPY -#endif - -#ifdef HAS_FIRMWARE -#include "starfire_firmware.h" -#endif /* HAS_FIRMWARE */ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define VLAN_SUPPORT @@ -202,11 +192,7 @@ static int mtu; The Starfire has a 512 element hash table based on the Ethernet CRC. */ static int multicast_filter_limit = 512; /* Whether to do TCP/UDP checksums in hardware */ -#ifdef HAS_FIRMWARE static int enable_hw_cksum = 1; -#else -static int enable_hw_cksum = 0; -#endif #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ /* @@ -291,43 +277,15 @@ static int full_duplex[MAX_UNITS] = {0, }; #define RX_DESC_ADDR_SIZE RxDescAddr32bit #endif -#ifdef MAX_SKB_FRAGS #define skb_first_frag_len(skb) skb_headlen(skb) #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1) -#else /* not MAX_SKB_FRAGS */ -#define skb_first_frag_len(skb) (skb->len) -#define skb_num_frags(skb) 1 -#endif /* not MAX_SKB_FRAGS */ - -/* 2.2.x compatibility code */ -#if LINUX_VERSION_CODE < 0x20300 - -#include "starfire-kcomp22.h" - -#else /* LINUX_VERSION_CODE > 0x20300 */ - -#include <linux/crc32.h> -#include <linux/ethtool.h> -#include <linux/mii.h> - -#include <linux/if_vlan.h> - -#define init_tx_timer(dev, func, timeout) \ - dev->tx_timeout = func; \ - dev->watchdog_timeo = timeout; -#define kick_tx_timer(dev, func, timeout) - -#define netif_start_if(dev) -#define netif_stop_if(dev) - -#define PCI_SLOT_NAME(pci_dev) pci_name(pci_dev) - -#endif /* LINUX_VERSION_CODE > 0x20300 */ #ifdef HAVE_NETDEV_POLL #define init_poll(dev) \ +do { \ dev->poll = &netdev_poll; \ - dev->weight = max_interrupt_work; + dev->weight = max_interrupt_work; \ +} while (0) #define netdev_rx(dev, ioaddr) \ do { \ u32 intr_enable; \ @@ -341,7 +299,7 @@ do { \ /* Paranoia check */ \ intr_enable = readl(ioaddr + IntrEnable); \ if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \ - printk("%s: interrupt while in polling mode!\n", dev->name); \ + printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \ intr_enable &= ~(IntrRxDone | IntrRxEmpty); \ writel(intr_enable, ioaddr + IntrEnable); \ } \ @@ -371,6 +329,7 @@ KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELD MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); module_param(max_interrupt_work, int, 0); module_param(mtu, int, 0); @@ -425,7 +384,7 @@ on the 32/64 bitness of the architecture), and relies on automatic minimum-length padding. It does not use the completion queue consumer index, but instead checks for non-zero status entries. -For receive this driver uses type 0/1/2/3 receive descriptors. The driver +For receive this driver uses type 2/3 receive descriptors. The driver allocates full frame size skbuffs for the Rx ring buffers, so all frames should fit in a single descriptor. The driver does not use the completion queue consumer index, but instead checks for non-zero status entries. @@ -476,7 +435,7 @@ IVc. Errata */ - + enum chip_capability_flags {CanHaveMII=1, }; @@ -670,7 +629,6 @@ struct full_rx_done_desc { u32 timestamp; }; /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */ -#ifdef HAS_FIRMWARE #ifdef VLAN_SUPPORT typedef struct full_rx_done_desc rx_done_desc; #define RxComplType RxComplType3 @@ -678,15 +636,6 @@ typedef struct full_rx_done_desc rx_done_desc; typedef struct csum_rx_done_desc rx_done_desc; #define RxComplType RxComplType2 #endif /* not VLAN_SUPPORT */ -#else /* not HAS_FIRMWARE */ -#ifdef VLAN_SUPPORT -typedef struct basic_rx_done_desc rx_done_desc; -#define RxComplType RxComplType1 -#else /* not VLAN_SUPPORT */ -typedef struct short_rx_done_desc rx_done_desc; -#define RxComplType RxComplType0 -#endif /* not VLAN_SUPPORT */ -#endif /* not HAS_FIRMWARE */ enum rx_done_bits { RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000, @@ -898,13 +847,10 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, /* enable MWI -- it vastly improves Rx performance on sparc64 */ pci_set_mwi(pdev); -#ifdef MAX_SKB_FRAGS - dev->features |= NETIF_F_SG; -#endif /* MAX_SKB_FRAGS */ #ifdef ZEROCOPY /* Starfire can do TCP/UDP checksumming */ if (enable_hw_cksum) - dev->features |= NETIF_F_IP_CSUM; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; #endif /* ZEROCOPY */ #ifdef VLAN_SUPPORT dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; @@ -1008,7 +954,8 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, /* The chip-specific entries in the device structure. */ dev->open = &netdev_open; dev->hard_start_xmit = &start_tx; - init_tx_timer(dev, tx_timeout, TX_TIMEOUT); + dev->tx_timeout = tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; init_poll(dev); dev->stop = &netdev_close; dev->get_stats = &get_stats; @@ -1039,7 +986,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0) break; if (boguscnt == 0) { - printk("%s: PHY reset never completed!\n", dev->name); + printk("%s: PHY#%d reset never completed!\n", dev->name, phy); continue; } mii_status = mdio_read(dev, phy, MII_BMSR); @@ -1110,6 +1057,7 @@ static int netdev_open(struct net_device *dev) size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; /* Do we ever need to reset the chip??? */ + retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); if (retval) return retval; @@ -1211,7 +1159,6 @@ static int netdev_open(struct net_device *dev) writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl); - netif_start_if(dev); netif_start_queue(dev); if (debug > 1) @@ -1238,13 +1185,11 @@ static int netdev_open(struct net_device *dev) writel(ETH_P_8021Q, ioaddr + VlanType); #endif /* VLAN_SUPPORT */ -#ifdef HAS_FIRMWARE /* Load Rx/Tx firmware into the frame processors */ for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4); for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4); -#endif /* HAS_FIRMWARE */ if (enable_hw_cksum) /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl); @@ -1341,7 +1286,7 @@ static void init_ring(struct net_device *dev) np->rx_info[i].skb = skb; if (skb == NULL) break; - np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb->dev = dev; /* Mark as being used by this device. */ /* Grrr, we cannot offset to correctly align the IP header. */ np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); @@ -1378,8 +1323,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) u32 status; int i; - kick_tx_timer(dev, tx_timeout, TX_TIMEOUT); - /* * be cautious here, wrapping the queue has weird semantics * and we may not have enough slots even when it seems we do. @@ -1404,7 +1347,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) } if (has_bad_length) - skb_checksum_help(skb); + skb_checksum_help(skb, 0); } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ @@ -1433,12 +1376,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_info[entry].mapping = pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE); } else { -#ifdef MAX_SKB_FRAGS skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1]; status |= this_frag->size; np->tx_info[entry].mapping = pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE); -#endif /* MAX_SKB_FRAGS */ } np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping); @@ -1531,7 +1472,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs np->tx_info[entry].mapping = 0; np->dirty_tx += np->tx_info[entry].used_slots; entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE; -#ifdef MAX_SKB_FRAGS { int i; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { @@ -1543,7 +1483,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs entry++; } } -#endif /* MAX_SKB_FRAGS */ + dev_kfree_skb_irq(skb); } np->tx_done_q[np->tx_done].status = 0; @@ -1603,7 +1543,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) if (debug > 4) printk(KERN_DEBUG " netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status); if (!(desc_status & RxOK)) { - /* There was a error. */ + /* There was an error. */ if (debug > 2) printk(KERN_DEBUG " netdev_rx() Rx error was %#8.8x.\n", desc_status); np->stats.rx_errors++; @@ -1632,7 +1572,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) pci_dma_sync_single_for_cpu(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0); + eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0); pci_dma_sync_single_for_device(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); @@ -1656,11 +1596,10 @@ static int __netdev_rx(struct net_device *dev, int *quota) #endif skb->protocol = eth_type_trans(skb, dev); -#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT) +#ifdef VLAN_SUPPORT if (debug > 4) printk(KERN_DEBUG " netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2)); #endif -#ifdef HAS_FIRMWARE if (le16_to_cpu(desc->status2) & 0x0100) { skb->ip_summed = CHECKSUM_UNNECESSARY; np->stats.rx_compressed++; @@ -1679,7 +1618,6 @@ static int __netdev_rx(struct net_device *dev, int *quota) skb->csum = le16_to_cpu(desc->csum); printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2)); } -#endif /* HAS_FIRMWARE */ #ifdef VLAN_SUPPORT if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) { if (debug > 4) @@ -1758,7 +1696,7 @@ static void refill_rx_ring(struct net_device *dev) if (skb == NULL) break; /* Better luck next round. */ np->rx_info[entry].mapping = - pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[entry].rxaddr = cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); @@ -1900,9 +1838,6 @@ static struct net_device_stats *get_stats(struct net_device *dev) } -/* Chips may use the upper or lower CRC bits, and may reverse and/or invert - them. Select the endian-ness that results in minimal calculations. -*/ static void set_rx_mode(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); @@ -1969,6 +1904,8 @@ static void set_rx_mode(struct net_device *dev) memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { + /* The chip uses the upper 9 CRC bits + as index into the hash table */ int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23; __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1]; @@ -2001,7 +1938,7 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) struct netdev_private *np = netdev_priv(dev); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev)); + strcpy(info->bus_info, pci_name(np->pci_dev)); } static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -2083,7 +2020,6 @@ static int netdev_close(struct net_device *dev) int i; netif_stop_queue(dev); - netif_stop_if(dev); if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n", @@ -2184,7 +2120,13 @@ static int __init starfire_init (void) /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE printk(version); +#ifdef HAVE_NETDEV_POLL + printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n"); +#else + printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n"); #endif +#endif + #ifndef ADDR_64BITS /* we can do this test only at run-time... sigh */ if (sizeof(dma_addr_t) == sizeof(u64)) { @@ -2192,10 +2134,6 @@ static int __init starfire_init (void) return -ENODEV; } #endif /* not ADDR_64BITS */ -#ifndef HAS_FIRMWARE - /* unconditionally disable hw cksums if firmware is not present */ - enable_hw_cksum = 0; -#endif /* not HAS_FIRMWARE */ return pci_module_init (&starfire_driver); } diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h new file mode 100644 index 000000000000..0a668528955d --- /dev/null +++ b/drivers/net/starfire_firmware.h @@ -0,0 +1,346 @@ +/* + * Copyright 2003 Adaptec, Inc. + * + * Please read the following license before using the Adaptec Software + * ("Program"). If you do not agree to the license terms, do not use the + * Program: + * + * You agree to be bound by version 2 of the General Public License ("GPL") + * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html. + * If the link is broken, write to Free Software Foundation, 59 Temple Place, + * Boston, Massachusetts 02111-1307. + * + * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND + * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE + * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE + * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR + * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR + * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM. + * + */ + +static const u32 firmware_rx[] = { + 0x010003dc, 0x00000000, + 0x04000421, 0x00000086, + 0x80000015, 0x0000180e, + 0x81000015, 0x00006664, + 0x1a0040ab, 0x00000b06, + 0x14200011, 0x00000000, + 0x14204022, 0x0000aaaa, + 0x14204022, 0x00000300, + 0x14204022, 0x00000000, + 0x1a0040ab, 0x00000b14, + 0x14200011, 0x00000000, + 0x83000015, 0x00000002, + 0x04000021, 0x00000000, + 0x00000010, 0x00000000, + 0x04000421, 0x00000087, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00008015, 0x00000000, + 0x0000003e, 0x00000000, + 0x00000010, 0x00000000, + 0x82000015, 0x00004000, + 0x009e8050, 0x00000000, + 0x03008015, 0x00000000, + 0x86008015, 0x00000000, + 0x82000015, 0x00008000, + 0x0100001c, 0x00000000, + 0x000050a0, 0x0000010c, + 0x4e20d011, 0x00006008, + 0x1420d012, 0x00004008, + 0x0000f090, 0x00007000, + 0x0000c8b0, 0x00003000, + 0x00004040, 0x00000000, + 0x00108015, 0x00000000, + 0x00a2c150, 0x00004000, + 0x00a400b0, 0x00000014, + 0x00000020, 0x00000000, + 0x2500400d, 0x00002525, + 0x00047220, 0x00003100, + 0x00934070, 0x00000000, + 0x00000020, 0x00000000, + 0x00924460, 0x00000184, + 0x2b20c011, 0x00000000, + 0x0000c420, 0x00000540, + 0x36014018, 0x0000422d, + 0x14200011, 0x00000000, + 0x00924460, 0x00000183, + 0x3200001f, 0x00000034, + 0x02ac0015, 0x00000002, + 0x00a60110, 0x00000008, + 0x42200011, 0x00000000, + 0x00924060, 0x00000103, + 0x0000001e, 0x00000000, + 0x00000020, 0x00000100, + 0x0000001e, 0x00000000, + 0x00924460, 0x00000086, + 0x00004080, 0x00000000, + 0x0092c070, 0x00000000, + 0x00924060, 0x00000100, + 0x0000c890, 0x00005000, + 0x00a6c110, 0x00000000, + 0x00b0c090, 0x00000012, + 0x021c0015, 0x00000000, + 0x3200001f, 0x00000034, + 0x00924460, 0x00000510, + 0x44210011, 0x00000000, + 0x42000011, 0x00000000, + 0x83000015, 0x00000040, + 0x00924460, 0x00000508, + 0x45014018, 0x00004545, + 0x00808050, 0x00000000, + 0x62208012, 0x00000000, + 0x82000015, 0x00000800, + 0x15200011, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x80000015, 0x0000eea4, + 0x81000015, 0x0000005f, + 0x00000060, 0x00000000, + 0x00004120, 0x00000000, + 0x00004a00, 0x00004000, + 0x00924460, 0x00000190, + 0x5601401a, 0x00005956, + 0x14000011, 0x00000000, + 0x00934050, 0x00000018, + 0x00930050, 0x00000018, + 0x3601403a, 0x0000002d, + 0x000643a9, 0x00000000, + 0x0000c420, 0x00000140, + 0x5601401a, 0x00005956, + 0x14000011, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x000642a9, 0x00000000, + 0x00024420, 0x00000183, + 0x5601401a, 0x00005956, + 0x82000015, 0x00002000, + 0x15200011, 0x00000000, + 0x82000015, 0x00000010, + 0x15200011, 0x00000000, + 0x82000015, 0x00000010, + 0x15200011, 0x00000000, +}; /* 104 Rx instructions */ +#define FIRMWARE_RX_SIZE 104 + +static const u32 firmware_tx[] = { + 0x010003dc, 0x00000000, + 0x04000421, 0x00000086, + 0x80000015, 0x0000180e, + 0x81000015, 0x00006664, + 0x1a0040ab, 0x00000b06, + 0x14200011, 0x00000000, + 0x14204022, 0x0000aaaa, + 0x14204022, 0x00000300, + 0x14204022, 0x00000000, + 0x1a0040ab, 0x00000b14, + 0x14200011, 0x00000000, + 0x83000015, 0x00000002, + 0x04000021, 0x00000000, + 0x00000010, 0x00000000, + 0x04000421, 0x00000087, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00008015, 0x00000000, + 0x0000003e, 0x00000000, + 0x00000010, 0x00000000, + 0x82000015, 0x00004000, + 0x009e8050, 0x00000000, + 0x03008015, 0x00000000, + 0x86008015, 0x00000000, + 0x82000015, 0x00008000, + 0x0100001c, 0x00000000, + 0x000050a0, 0x0000010c, + 0x4e20d011, 0x00006008, + 0x1420d012, 0x00004008, + 0x0000f090, 0x00007000, + 0x0000c8b0, 0x00003000, + 0x00004040, 0x00000000, + 0x00108015, 0x00000000, + 0x00a2c150, 0x00004000, + 0x00a400b0, 0x00000014, + 0x00000020, 0x00000000, + 0x2500400d, 0x00002525, + 0x00047220, 0x00003100, + 0x00934070, 0x00000000, + 0x00000020, 0x00000000, + 0x00924460, 0x00000184, + 0x2b20c011, 0x00000000, + 0x0000c420, 0x00000540, + 0x36014018, 0x0000422d, + 0x14200011, 0x00000000, + 0x00924460, 0x00000183, + 0x3200001f, 0x00000034, + 0x02ac0015, 0x00000002, + 0x00a60110, 0x00000008, + 0x42200011, 0x00000000, + 0x00924060, 0x00000103, + 0x0000001e, 0x00000000, + 0x00000020, 0x00000100, + 0x0000001e, 0x00000000, + 0x00924460, 0x00000086, + 0x00004080, 0x00000000, + 0x0092c070, 0x00000000, + 0x00924060, 0x00000100, + 0x0000c890, 0x00005000, + 0x00a6c110, 0x00000000, + 0x00b0c090, 0x00000012, + 0x021c0015, 0x00000000, + 0x3200001f, 0x00000034, + 0x00924460, 0x00000510, + 0x44210011, 0x00000000, + 0x42000011, 0x00000000, + 0x83000015, 0x00000040, + 0x00924460, 0x00000508, + 0x45014018, 0x00004545, + 0x00808050, 0x00000000, + 0x62208012, 0x00000000, + 0x82000015, 0x00000800, + 0x15200011, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x80000015, 0x0000eea4, + 0x81000015, 0x0000005f, + 0x00000060, 0x00000000, + 0x00004120, 0x00000000, + 0x00004a00, 0x00004000, + 0x00924460, 0x00000190, + 0x5601401a, 0x00005956, + 0x14000011, 0x00000000, + 0x00934050, 0x00000018, + 0x00930050, 0x00000018, + 0x3601403a, 0x0000002d, + 0x000643a9, 0x00000000, + 0x0000c420, 0x00000140, + 0x5601401a, 0x00005956, + 0x14000011, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x000642a9, 0x00000000, + 0x00024420, 0x00000183, + 0x5601401a, 0x00005956, + 0x82000015, 0x00002000, + 0x15200011, 0x00000000, + 0x82000015, 0x00000010, + 0x15200011, 0x00000000, + 0x82000015, 0x00000010, + 0x15200011, 0x00000000, +}; /* 104 Tx instructions */ +#define FIRMWARE_TX_SIZE 104 +#if 0 +static const u32 firmware_wol[] = { + 0x010003dc, 0x00000000, + 0x19000421, 0x00000087, + 0x80000015, 0x00001a1a, + 0x81000015, 0x00001a1a, + 0x1a0040ab, 0x00000b06, + 0x15200011, 0x00000000, + 0x15204022, 0x0000aaaa, + 0x15204022, 0x00000300, + 0x15204022, 0x00000000, + 0x1a0040ab, 0x00000b15, + 0x15200011, 0x00000000, + 0x83000015, 0x00000002, + 0x04000021, 0x00000000, + 0x00000010, 0x00000000, + 0x04000421, 0x00000087, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00008015, 0x00000000, + 0x0000003e, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x82000015, 0x00004000, + 0x82000015, 0x00008000, + 0x0000000c, 0x00000000, + 0x00000010, 0x00000000, + 0x00004080, 0x00000100, + 0x1f20c011, 0x00001122, + 0x2720f011, 0x00003011, + 0x19200071, 0x00000000, + 0x1a200051, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x1d2040a4, 0x00003344, + 0x1d2040a2, 0x00005566, + 0x000040a0, 0x00000100, + 0x00108050, 0x00000001, + 0x1a208012, 0x00000006, + 0x82000015, 0x00008080, + 0x010003dc, 0x00000000, + 0x1d2040a4, 0x00002233, + 0x1d2040a4, 0x00004455, + 0x2d208011, 0x00000005, + 0x1d2040a4, 0x00006611, + 0x00108050, 0x00000001, + 0x27200011, 0x00000000, + 0x1d2050a4, 0x00006600, + 0x82000015, 0x00008080, + 0x010003dc, 0x00000000, + 0x00000050, 0x00000000, + 0x1b200031, 0x00000000, + 0x0000001e, 0x00000000, + 0x0000001e, 0x00000000, + 0x0000001e, 0x00000000, + 0x0000001e, 0x00000000, + 0x00924460, 0x00000086, + 0x00004080, 0x00000000, + 0x0092c070, 0x00000000, + 0x00924060, 0x00000100, + 0x0000c890, 0x00005000, + 0x00a6c110, 0x00000000, + 0x00b0c090, 0x00000012, + 0x021c0015, 0x00000000, + 0x3200001f, 0x00000034, + 0x00924460, 0x00000510, + 0x44210011, 0x00000000, + 0x42000011, 0x00000000, + 0x83000015, 0x00000040, + 0x00924460, 0x00000508, + 0x476a0012, 0x00000100, + 0x83000015, 0x00000008, + 0x16200011, 0x00000000, + 0x001e8050, 0x00000000, + 0x001e8050, 0x00000000, + 0x00808050, 0x00000000, + 0x03008015, 0x00000000, + 0x62208012, 0x00000000, + 0x82000015, 0x00000800, + 0x16200011, 0x00000000, + 0x80000015, 0x0000eea4, + 0x81000015, 0x0000005f, + 0x00000020, 0x00000000, + 0x00004120, 0x00000000, + 0x00004a00, 0x00004000, + 0x00924460, 0x00000190, + 0x5c01401a, 0x0000595c, + 0x15000011, 0x00000000, + 0x00934050, 0x00000018, + 0x00930050, 0x00000018, + 0x3601403a, 0x0000002d, + 0x00064029, 0x00000000, + 0x0000c420, 0x00000140, + 0x5c01401a, 0x0000595c, + 0x15000011, 0x00000000, + 0x00000010, 0x00000000, + 0x00000010, 0x00000000, + 0x00064029, 0x00000000, + 0x00024420, 0x00000183, + 0x5c01401a, 0x0000595c, + 0x82000015, 0x00002000, + 0x16200011, 0x00000000, + 0x82000015, 0x00000010, + 0x16200011, 0x00000000, + 0x82000015, 0x00000010, + 0x16200011, 0x00000000, +}; /* 104 WoL instructions */ +#define FIRMWARE_WOL_SIZE 104 +#endif diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 08cb7177a175..d500a5771dbc 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1028,7 +1028,7 @@ static void init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ np->rx_ring[i].frag[0].addr = cpu_to_le32( - pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, + pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag); } @@ -1341,7 +1341,7 @@ static void rx_poll(unsigned long data) np->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); + eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); pci_dma_sync_single_for_device(np->pci_dev, desc->frag[0].addr, np->rx_buf_sz, @@ -1400,7 +1400,7 @@ static void refill_rx (struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ np->rx_ring[entry].frag[0].addr = cpu_to_le32( - pci_map_single(np->pci_dev, skb->tail, + pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } /* Perhaps we need not reset this field. */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 5cd50fd53c12..2608e7a3d214 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -44,6 +44,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> @@ -2989,10 +2990,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev, */ if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_GEM && - !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) { + !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { pci_using_dac = 1; } else { - err = pci_set_dma_mask(pdev, (u64) 0xffffffff); + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); @@ -3078,7 +3079,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->phy_mii.dev = dev; gp->phy_mii.mdio_read = _phy_read; gp->phy_mii.mdio_write = _phy_write; - +#ifdef CONFIG_PPC_PMAC + gp->phy_mii.platform_data = gp->of_node; +#endif /* By default, we start with autoneg */ gp->want_autoneg = 1; diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index 0fca414d3657..d3ddb41d6e5c 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c @@ -32,6 +32,10 @@ #include <linux/ethtool.h> #include <linux/delay.h> +#ifdef CONFIG_PPC_PMAC +#include <asm/prom.h> +#endif + #include "sungem_phy.h" /* Link modes of the BCM5400 PHY */ @@ -281,10 +285,12 @@ static int bcm5411_suspend(struct mii_phy* phy) static int bcm5421_init(struct mii_phy* phy) { u16 data; - int rev; + unsigned int id; - rev = phy_read(phy, MII_PHYSID2) & 0x000f; - if (rev == 0) { + id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2)); + + /* Revision 0 of 5421 needs some fixups */ + if (id == 0x002060e0) { /* This is borrowed from MacOS */ phy_write(phy, 0x18, 0x1007); @@ -297,21 +303,28 @@ static int bcm5421_init(struct mii_phy* phy) data = phy_read(phy, 0x15); phy_write(phy, 0x15, data | 0x0200); } -#if 0 - /* This has to be verified before I enable it */ - /* Enable automatic low-power */ - phy_write(phy, 0x1c, 0x9002); - phy_write(phy, 0x1c, 0xa821); - phy_write(phy, 0x1c, 0x941d); -#endif - return 0; -} -static int bcm5421k2_init(struct mii_phy* phy) -{ - /* Init code borrowed from OF */ - phy_write(phy, 4, 0x01e1); - phy_write(phy, 9, 0x0300); + /* Pick up some init code from OF for K2 version */ + if ((id & 0xfffffff0) == 0x002062e0) { + phy_write(phy, 4, 0x01e1); + phy_write(phy, 9, 0x0300); + } + + /* Check if we can enable automatic low power */ +#ifdef CONFIG_PPC_PMAC + if (phy->platform_data) { + struct device_node *np = of_get_parent(phy->platform_data); + int can_low_power = 1; + if (np == NULL || get_property(np, "no-autolowpower", NULL)) + can_low_power = 0; + if (can_low_power) { + /* Enable automatic low-power */ + phy_write(phy, 0x1c, 0x9002); + phy_write(phy, 0x1c, 0xa821); + phy_write(phy, 0x1c, 0x941d); + } + } +#endif /* CONFIG_PPC_PMAC */ return 0; } @@ -762,7 +775,7 @@ static struct mii_phy_def bcm5421_phy_def = { /* Broadcom BCM 5421 built-in K2 */ static struct mii_phy_ops bcm5421k2_phy_ops = { - .init = bcm5421k2_init, + .init = bcm5421_init, .suspend = bcm5411_suspend, .setup_aneg = bcm54xx_setup_aneg, .setup_forced = bcm54xx_setup_forced, @@ -779,6 +792,25 @@ static struct mii_phy_def bcm5421k2_phy_def = { .ops = &bcm5421k2_phy_ops }; +/* Broadcom BCM 5462 built-in Vesta */ +static struct mii_phy_ops bcm5462V_phy_ops = { + .init = bcm5421_init, + .suspend = bcm5411_suspend, + .setup_aneg = bcm54xx_setup_aneg, + .setup_forced = bcm54xx_setup_forced, + .poll_link = genmii_poll_link, + .read_link = bcm54xx_read_link, +}; + +static struct mii_phy_def bcm5462V_phy_def = { + .phy_id = 0x002060d0, + .phy_id_mask = 0xfffffff0, + .name = "BCM5462-Vesta", + .features = MII_GBIT_FEATURES, + .magic_aneg = 1, + .ops = &bcm5462V_phy_ops +}; + /* Marvell 88E1101 (Apple seem to deal with 2 different revs, * I masked out the 8 last bits to get both, but some specs * would be useful here) --BenH. @@ -824,6 +856,7 @@ static struct mii_phy_def* mii_phy_table[] = { &bcm5411_phy_def, &bcm5421_phy_def, &bcm5421k2_phy_def, + &bcm5462V_phy_def, &marvell_phy_def, &genmii_phy_def, NULL diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h index 822cb58174ea..430544496c52 100644 --- a/drivers/net/sungem_phy.h +++ b/drivers/net/sungem_phy.h @@ -43,9 +43,10 @@ struct mii_phy int pause; /* Provided by host chip */ - struct net_device* dev; + struct net_device *dev; int (*mdio_read) (struct net_device *dev, int mii_id, int reg); void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val); + void *platform_data; }; /* Pass in a struct mii_phy with dev, mdio_read and mdio_write diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a0b8848049c9..201a550f0bcc 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.31" -#define DRV_MODULE_RELDATE "June 8, 2005" +#define DRV_MODULE_VERSION "3.34" +#define DRV_MODULE_RELDATE "July 25, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -90,7 +90,7 @@ /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 #define TG3_MAX_MTU(tp) \ - (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 9000 : 1500) + ((tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place @@ -221,6 +221,10 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, @@ -337,12 +341,10 @@ static struct { static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) { if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); + spin_lock_bh(&tp->indirect_lock); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); - spin_unlock_irqrestore(&tp->indirect_lock, flags); + spin_unlock_bh(&tp->indirect_lock); } else { writel(val, tp->regs + off); if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0) @@ -353,12 +355,10 @@ static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) { if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); + spin_lock_bh(&tp->indirect_lock); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); - spin_unlock_irqrestore(&tp->indirect_lock, flags); + spin_unlock_bh(&tp->indirect_lock); } else { void __iomem *dest = tp->regs + off; writel(val, dest); @@ -398,28 +398,24 @@ static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val) static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); + spin_lock_bh(&tp->indirect_lock); pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); /* Always leave this as zero. */ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); + spin_unlock_bh(&tp->indirect_lock); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { - unsigned long flags; - - spin_lock_irqsave(&tp->indirect_lock, flags); + spin_lock_bh(&tp->indirect_lock); pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); /* Always leave this as zero. */ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); + spin_unlock_bh(&tp->indirect_lock); } static void tg3_disable_ints(struct tg3 *tp) @@ -438,12 +434,14 @@ static inline void tg3_cond_int(struct tg3 *tp) static void tg3_enable_ints(struct tg3 *tp) { + tp->irq_sync = 0; + wmb(); + tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, (tp->last_tag << 24)); tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - tg3_cond_int(tp); } @@ -492,6 +490,7 @@ static void tg3_restart_ints(struct tg3 *tp) static inline void tg3_netif_stop(struct tg3 *tp) { + tp->dev->trans_start = jiffies; /* prevent tx timeout */ netif_poll_disable(tp->dev); netif_tx_disable(tp->dev); } @@ -504,7 +503,8 @@ static inline void tg3_netif_start(struct tg3 *tp) * (such as after tg3_init_hw) */ netif_poll_enable(tp->dev); - tg3_cond_int(tp); + tp->hw_status->status |= SD_STATUS_UPDATED; + tg3_enable_ints(tp); } static void tg3_switch_clocks(struct tg3 *tp) @@ -512,6 +512,9 @@ static void tg3_switch_clocks(struct tg3 *tp) u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL); u32 orig_clock_ctrl; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + return; + orig_clock_ctrl = clock_ctrl; clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | @@ -911,7 +914,7 @@ out: if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); - } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + } else if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { u32 phy_reg; /* Set bit 14 with read-modify-write to preserve other bits */ @@ -923,7 +926,7 @@ out: /* Set phy register 0x10 bit 0 to high fifo elasticity to support * jumbo frames transmission. */ - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + if (tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) { u32 phy_reg; if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg)) @@ -1097,7 +1100,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) tp->link_config.orig_autoneg = tp->link_config.autoneg; } - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) { tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; @@ -1149,6 +1152,8 @@ static int tg3_set_power_state(struct tg3 *tp, int state) CLOCK_CTRL_ALTCLK | CLOCK_CTRL_PWRDOWN_PLL133); udelay(40); + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { + /* do nothing */ } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) { u32 newbits1, newbits2; @@ -1242,6 +1247,25 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv u32 old_tx_mode = tp->tx_mode; if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { + + /* Convert 1000BaseX flow control bits to 1000BaseT + * bits before resolving flow control. + */ + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + local_adv &= ~(ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM); + + if (local_adv & ADVERTISE_1000XPAUSE) + local_adv |= ADVERTISE_PAUSE_CAP; + if (local_adv & ADVERTISE_1000XPSE_ASYM) + local_adv |= ADVERTISE_PAUSE_ASYM; + if (remote_adv & LPA_1000XPAUSE) + remote_adv |= LPA_PAUSE_CAP; + if (remote_adv & LPA_1000XPAUSE_ASYM) + remote_adv |= LPA_PAUSE_ASYM; + } + if (local_adv & ADVERTISE_PAUSE_CAP) { if (local_adv & ADVERTISE_PAUSE_ASYM) { if (remote_adv & LPA_PAUSE_CAP) @@ -2502,12 +2526,226 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) return 0; } +static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) +{ + int current_link_up, err = 0; + u32 bmsr, bmcr; + u16 current_speed; + u8 current_duplex; + + tp->mac_mode |= MAC_MODE_PORT_MODE_GMII; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + + tw32(MAC_EVENT, 0); + + tw32_f(MAC_STATUS, + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_MI_COMPLETION | + MAC_STATUS_LNKSTATE_CHANGED)); + udelay(40); + + if (force_reset) + tg3_phy_reset(tp); + + current_link_up = 0; + current_speed = SPEED_INVALID; + current_duplex = DUPLEX_INVALID; + + err |= tg3_readphy(tp, MII_BMSR, &bmsr); + err |= tg3_readphy(tp, MII_BMSR, &bmsr); + + err |= tg3_readphy(tp, MII_BMCR, &bmcr); + + if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset && + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { + /* do nothing, just check for link up at the end */ + } else if (tp->link_config.autoneg == AUTONEG_ENABLE) { + u32 adv, new_adv; + + err |= tg3_readphy(tp, MII_ADVERTISE, &adv); + new_adv = adv & ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF | + ADVERTISE_1000XPAUSE | + ADVERTISE_1000XPSE_ASYM | + ADVERTISE_SLCT); + + /* Always advertise symmetric PAUSE just like copper */ + new_adv |= ADVERTISE_1000XPAUSE; + + if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) + new_adv |= ADVERTISE_1000XHALF; + if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) + new_adv |= ADVERTISE_1000XFULL; + + if ((new_adv != adv) || !(bmcr & BMCR_ANENABLE)) { + tg3_writephy(tp, MII_ADVERTISE, new_adv); + bmcr |= BMCR_ANENABLE | BMCR_ANRESTART; + tg3_writephy(tp, MII_BMCR, bmcr); + + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + + return err; + } + } else { + u32 new_bmcr; + + bmcr &= ~BMCR_SPEED1000; + new_bmcr = bmcr & ~(BMCR_ANENABLE | BMCR_FULLDPLX); + + if (tp->link_config.duplex == DUPLEX_FULL) + new_bmcr |= BMCR_FULLDPLX; + + if (new_bmcr != bmcr) { + /* BMCR_SPEED1000 is a reserved bit that needs + * to be set on write. + */ + new_bmcr |= BMCR_SPEED1000; + + /* Force a linkdown */ + if (netif_carrier_ok(tp->dev)) { + u32 adv; + + err |= tg3_readphy(tp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | + ADVERTISE_1000XHALF | + ADVERTISE_SLCT); + tg3_writephy(tp, MII_ADVERTISE, adv); + tg3_writephy(tp, MII_BMCR, bmcr | + BMCR_ANRESTART | + BMCR_ANENABLE); + udelay(10); + netif_carrier_off(tp->dev); + } + tg3_writephy(tp, MII_BMCR, new_bmcr); + bmcr = new_bmcr; + err |= tg3_readphy(tp, MII_BMSR, &bmsr); + err |= tg3_readphy(tp, MII_BMSR, &bmsr); + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + } + } + + if (bmsr & BMSR_LSTATUS) { + current_speed = SPEED_1000; + current_link_up = 1; + if (bmcr & BMCR_FULLDPLX) + current_duplex = DUPLEX_FULL; + else + current_duplex = DUPLEX_HALF; + + if (bmcr & BMCR_ANENABLE) { + u32 local_adv, remote_adv, common; + + err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv); + err |= tg3_readphy(tp, MII_LPA, &remote_adv); + common = local_adv & remote_adv; + if (common & (ADVERTISE_1000XHALF | + ADVERTISE_1000XFULL)) { + if (common & ADVERTISE_1000XFULL) + current_duplex = DUPLEX_FULL; + else + current_duplex = DUPLEX_HALF; + + tg3_setup_flow_control(tp, local_adv, + remote_adv); + } + else + current_link_up = 0; + } + } + + tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX; + if (tp->link_config.active_duplex == DUPLEX_HALF) + tp->mac_mode |= MAC_MODE_HALF_DUPLEX; + + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + + tp->link_config.active_speed = current_speed; + tp->link_config.active_duplex = current_duplex; + + if (current_link_up != netif_carrier_ok(tp->dev)) { + if (current_link_up) + netif_carrier_on(tp->dev); + else { + netif_carrier_off(tp->dev); + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + } + tg3_link_report(tp); + } + return err; +} + +static void tg3_serdes_parallel_detect(struct tg3 *tp) +{ + if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) { + /* Give autoneg time to complete. */ + tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + return; + } + if (!netif_carrier_ok(tp->dev) && + (tp->link_config.autoneg == AUTONEG_ENABLE)) { + u32 bmcr; + + tg3_readphy(tp, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { + u32 phy1, phy2; + + /* Select shadow register 0x1f */ + tg3_writephy(tp, 0x1c, 0x7c00); + tg3_readphy(tp, 0x1c, &phy1); + + /* Select expansion interrupt status register */ + tg3_writephy(tp, 0x17, 0x0f01); + tg3_readphy(tp, 0x15, &phy2); + tg3_readphy(tp, 0x15, &phy2); + + if ((phy1 & 0x10) && !(phy2 & 0x20)) { + /* We have signal detect and not receiving + * config code words, link is up by parallel + * detection. + */ + + bmcr &= ~BMCR_ANENABLE; + bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; + tg3_writephy(tp, MII_BMCR, bmcr); + tp->tg3_flags2 |= TG3_FLG2_PARALLEL_DETECT; + } + } + } + else if (netif_carrier_ok(tp->dev) && + (tp->link_config.autoneg == AUTONEG_ENABLE) && + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { + u32 phy2; + + /* Select expansion interrupt status register */ + tg3_writephy(tp, 0x17, 0x0f01); + tg3_readphy(tp, 0x15, &phy2); + if (phy2 & 0x20) { + u32 bmcr; + + /* Config code words received, turn on autoneg. */ + tg3_readphy(tp, MII_BMCR, &bmcr); + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANENABLE); + + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + + } + } +} + static int tg3_setup_phy(struct tg3 *tp, int force_reset) { int err; if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { err = tg3_setup_fiber_phy(tp, force_reset); + } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + err = tg3_setup_fiber_mii_phy(tp, force_reset); } else { err = tg3_setup_copper_phy(tp, force_reset); } @@ -2578,7 +2816,7 @@ static void tg3_tx(struct tg3 *tp) sw_idx = NEXT_TX(sw_idx); } - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); } tp->tx_cons = sw_idx; @@ -2616,7 +2854,7 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, map = &tp->rx_std_buffers[dest_idx]; if (src_idx >= 0) src_map = &tp->rx_std_buffers[src_idx]; - skb_size = RX_PKT_BUF_SZ; + skb_size = tp->rx_pkt_buf_sz; break; case RXD_OPAQUE_RING_JUMBO: @@ -2884,11 +3122,8 @@ static int tg3_poll(struct net_device *netdev, int *budget) { struct tg3 *tp = netdev_priv(netdev); struct tg3_hw_status *sblk = tp->hw_status; - unsigned long flags; int done; - spin_lock_irqsave(&tp->lock, flags); - /* handle link change and other phy events */ if (!(tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | @@ -2896,7 +3131,9 @@ static int tg3_poll(struct net_device *netdev, int *budget) if (sblk->status & SD_STATUS_LINK_CHG) { sblk->status = SD_STATUS_UPDATED | (sblk->status & ~SD_STATUS_LINK_CHG); + spin_lock(&tp->lock); tg3_setup_phy(tp, 0); + spin_unlock(&tp->lock); } } @@ -2907,8 +3144,6 @@ static int tg3_poll(struct net_device *netdev, int *budget) spin_unlock(&tp->tx_lock); } - spin_unlock_irqrestore(&tp->lock, flags); - /* run RX thread, within the bounds set by NAPI. * All RX "locking" is done by ensuring outside * code synchronizes with dev->poll() @@ -2929,19 +3164,54 @@ static int tg3_poll(struct net_device *netdev, int *budget) if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) tp->last_tag = sblk->status_tag; rmb(); + sblk->status &= ~SD_STATUS_UPDATED; /* if no more work, tell net stack and NIC we're done */ done = !tg3_has_work(tp); if (done) { - spin_lock_irqsave(&tp->lock, flags); - __netif_rx_complete(netdev); + spin_lock(&tp->lock); + netif_rx_complete(netdev); tg3_restart_ints(tp); - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock(&tp->lock); } return (done ? 0 : 1); } +static void tg3_irq_quiesce(struct tg3 *tp) +{ + BUG_ON(tp->irq_sync); + + tp->irq_sync = 1; + smp_mb(); + + synchronize_irq(tp->pdev->irq); +} + +static inline int tg3_irq_sync(struct tg3 *tp) +{ + return tp->irq_sync; +} + +/* Fully shutdown all tg3 driver activity elsewhere in the system. + * If irq_sync is non-zero, then the IRQ handler must be synchronized + * with as well. Most of the time, this is not necessary except when + * shutting down the device. + */ +static inline void tg3_full_lock(struct tg3 *tp, int irq_sync) +{ + if (irq_sync) + tg3_irq_quiesce(tp); + spin_lock_bh(&tp->lock); + spin_lock(&tp->tx_lock); +} + +static inline void tg3_full_unlock(struct tg3 *tp) +{ + spin_unlock(&tp->tx_lock); + spin_unlock_bh(&tp->lock); +} + /* MSI ISR - No need to check for interrupt sharing and no need to * flush status block and interrupt mailbox. PCI ordering rules * guarantee that MSI will arrive after the status block. @@ -2951,9 +3221,6 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); /* * Writing any value to intr-mbox-0 clears PCI INTA# and @@ -2964,6 +3231,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); tp->last_tag = sblk->status_tag; + rmb(); + if (tg3_irq_sync(tp)) + goto out; sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) netif_rx_schedule(dev); /* schedule NAPI poll */ @@ -2972,9 +3242,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, tp->last_tag << 24); } - - spin_unlock_irqrestore(&tp->lock, flags); - +out: return IRQ_RETVAL(1); } @@ -2983,11 +3251,8 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; - unsigned long flags; unsigned int handled = 1; - spin_lock_irqsave(&tp->lock, flags); - /* In INTx mode, it is possible for the interrupt to arrive at * the CPU before the status block posted prior to the interrupt. * Reading the PCI State register will confirm whether the @@ -3004,6 +3269,8 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + if (tg3_irq_sync(tp)) + goto out; sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) netif_rx_schedule(dev); /* schedule NAPI poll */ @@ -3018,9 +3285,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) } else { /* shared interrupt */ handled = 0; } - - spin_unlock_irqrestore(&tp->lock, flags); - +out: return IRQ_RETVAL(handled); } @@ -3029,11 +3294,8 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r struct net_device *dev = dev_id; struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; - unsigned long flags; unsigned int handled = 1; - spin_lock_irqsave(&tp->lock, flags); - /* In INTx mode, it is possible for the interrupt to arrive at * the CPU before the status block posted prior to the interrupt. * Reading the PCI State register will confirm whether the @@ -3051,6 +3313,9 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); tp->last_tag = sblk->status_tag; + rmb(); + if (tg3_irq_sync(tp)) + goto out; sblk->status &= ~SD_STATUS_UPDATED; if (likely(tg3_has_work(tp))) netif_rx_schedule(dev); /* schedule NAPI poll */ @@ -3065,9 +3330,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r } else { /* shared interrupt */ handled = 0; } - - spin_unlock_irqrestore(&tp->lock, flags); - +out: return IRQ_RETVAL(handled); } @@ -3106,8 +3369,7 @@ static void tg3_reset_task(void *_data) tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 1); restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; @@ -3117,8 +3379,7 @@ static void tg3_reset_task(void *_data) tg3_netif_start(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); if (restart_timer) mod_timer(&tp->timer, jiffies + 1); @@ -3224,39 +3485,21 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int i; u32 len, entry, base_flags, mss; int would_hit_hwbug; - unsigned long flags; len = skb_headlen(skb); /* No BH disabling for tx_lock here. We are running in BH disabled * context and TX reclaim runs via tp->poll inside of a software - * interrupt. Rejoice! - * - * Actually, things are not so simple. If we are to take a hw - * IRQ here, we can deadlock, consider: - * - * CPU1 CPU2 - * tg3_start_xmit - * take tp->tx_lock - * tg3_timer - * take tp->lock - * tg3_interrupt - * spin on tp->lock - * spin on tp->tx_lock - * - * So we really do need to disable interrupts when taking - * tx_lock here. + * interrupt. Furthermore, IRQ processing runs lockless so we have + * no IRQ context deadlocks to worry about either. Rejoice! */ - local_irq_save(flags); - if (!spin_trylock(&tp->tx_lock)) { - local_irq_restore(flags); + if (!spin_trylock(&tp->tx_lock)) return NETDEV_TX_LOCKED; - } /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { netif_stop_queue(dev); - spin_unlock_irqrestore(&tp->tx_lock, flags); + spin_unlock(&tp->tx_lock); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); return NETDEV_TX_BUSY; @@ -3421,7 +3664,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) out_unlock: mmiowb(); - spin_unlock_irqrestore(&tp->tx_lock, flags); + spin_unlock(&tp->tx_lock); dev->trans_start = jiffies; @@ -3433,10 +3676,18 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, { dev->mtu = new_mtu; - if (new_mtu > ETH_DATA_LEN) - tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE; - else - tp->tg3_flags &= ~TG3_FLAG_JUMBO_ENABLE; + if (new_mtu > ETH_DATA_LEN) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + ethtool_op_set_tso(dev, 0); + } + else + tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; + } else { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE; + } } static int tg3_change_mtu(struct net_device *dev, int new_mtu) @@ -3455,8 +3706,8 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) } tg3_netif_stop(tp); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + + tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); @@ -3466,8 +3717,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_netif_start(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); return 0; } @@ -3491,7 +3741,7 @@ static void tg3_free_rings(struct tg3 *tp) continue; pci_unmap_single(tp->pdev, pci_unmap_addr(rxp, mapping), - RX_PKT_BUF_SZ - tp->rx_offset, + tp->rx_pkt_buf_sz - tp->rx_offset, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(rxp->skb); rxp->skb = NULL; @@ -3564,6 +3814,11 @@ static void tg3_init_rings(struct tg3 *tp) memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); + tp->rx_pkt_buf_sz = RX_PKT_BUF_SZ; + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) && + (tp->dev->mtu > ETH_DATA_LEN)) + tp->rx_pkt_buf_sz = RX_JUMBO_PKT_BUF_SZ; + /* Initialize invariants of the rings, we only set this * stuff once. This works because the card does not * write into the rx buffer posting rings. @@ -3572,14 +3827,14 @@ static void tg3_init_rings(struct tg3 *tp) struct tg3_rx_buffer_desc *rxd; rxd = &tp->rx_std[i]; - rxd->idx_len = (RX_PKT_BUF_SZ - tp->rx_offset - 64) + rxd->idx_len = (tp->rx_pkt_buf_sz - tp->rx_offset - 64) << RXD_LEN_SHIFT; rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT)); } - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { struct tg3_rx_buffer_desc *rxd; @@ -3600,7 +3855,7 @@ static void tg3_init_rings(struct tg3 *tp) break; } - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { for (i = 0; i < tp->rx_jumbo_pending; i++) { if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO, -1, i) < 0) @@ -4056,7 +4311,30 @@ static int tg3_chip_reset(struct tg3 *tp) val &= ~PCIX_CAPS_RELAXED_ORDERING; pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); - tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { + u32 val; + + /* Chip reset on 5780 will reset MSI enable bit, + * so need to restore it. + */ + if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { + u16 ctrl; + + pci_read_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + &ctrl); + pci_write_config_word(tp->pdev, + tp->msi_cap + PCI_MSI_FLAGS, + ctrl | PCI_MSI_FLAGS_ENABLE); + val = tr32(MSGINT_MODE); + tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); + } + + val = tr32(MEMARB_MODE); + tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); + + } else + tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { tg3_stop_fw(tp); @@ -4082,6 +4360,9 @@ static int tg3_chip_reset(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tw32_f(MAC_MODE, tp->mac_mode); + } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + tp->mac_mode = MAC_MODE_PORT_MODE_GMII; + tw32_f(MAC_MODE, tp->mac_mode); } else tw32_f(MAC_MODE, 0); udelay(40); @@ -5088,9 +5369,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); __tg3_set_mac_addr(tp); - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); return 0; } @@ -5117,7 +5398,7 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, } static void __tg3_set_rx_mode(struct net_device *); -static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) +static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) { tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); @@ -5245,7 +5526,7 @@ static int tg3_reset_hw(struct tg3 *tp) } #endif - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) { + if (tp->dev->mtu <= ETH_DATA_LEN) { tw32(BUFMGR_MB_RDMA_LOW_WATER, tp->bufmgr_config.mbuf_read_dma_low_water); tw32(BUFMGR_MB_MACRX_LOW_WATER, @@ -5320,7 +5601,7 @@ static int tg3_reset_hw(struct tg3 *tp) /* Setup replenish threshold. */ tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8); - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) { + if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, ((u64) tp->rx_jumbo_mapping >> 32)); tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, @@ -5381,7 +5662,7 @@ static int tg3_reset_hw(struct tg3 *tp) tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_std_ptr); - tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ? + tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ? tp->rx_jumbo_pending : 0; tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_jumbo_ptr); @@ -5460,7 +5741,7 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(10); } - tg3_set_coalesce(tp, &tp->coal); + __tg3_set_coalesce(tp, &tp->coal); /* set status block DMA address */ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, @@ -5683,7 +5964,8 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK); tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK); - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780)) limit = 8; else limit = 16; @@ -5727,9 +6009,6 @@ static int tg3_reset_hw(struct tg3 *tp) tg3_write_sig_post_reset(tp, RESET_KIND_INIT); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) - tg3_enable_ints(tp); - return 0; } @@ -5802,10 +6081,8 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; - unsigned long flags; - spin_lock_irqsave(&tp->lock, flags); - spin_lock(&tp->tx_lock); + spin_lock(&tp->lock); if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { /* All of this garbage is because when using non-tagged @@ -5822,8 +6099,7 @@ static void tg3_timer(unsigned long __opaque) if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER; - spin_unlock(&tp->tx_lock); - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock(&tp->lock); schedule_work(&tp->reset_task); return; } @@ -5871,7 +6147,8 @@ static void tg3_timer(unsigned long __opaque) udelay(40); tg3_setup_phy(tp, 0); } - } + } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) + tg3_serdes_parallel_detect(tp); tp->timer_counter = tp->timer_multiplier; } @@ -5891,8 +6168,7 @@ static void tg3_timer(unsigned long __opaque) tp->asf_counter = tp->asf_multiplier; } - spin_unlock(&tp->tx_lock); - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock(&tp->lock); tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); @@ -6007,14 +6283,12 @@ static int tg3_test_msi(struct tg3 *tp) /* Need to reset the chip because the MSI cycle may have terminated * with Master Abort. */ - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 1); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); err = tg3_init_hw(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); if (err) free_irq(tp->pdev->irq, dev); @@ -6027,14 +6301,12 @@ static int tg3_open(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); int err; - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tg3_disable_ints(tp); tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); /* The placement of this call is tied * to the setup and use of Host TX descriptors. @@ -6081,8 +6353,7 @@ static int tg3_open(struct net_device *dev) return err; } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); err = tg3_init_hw(tp); if (err) { @@ -6106,8 +6377,7 @@ static int tg3_open(struct net_device *dev) tp->timer.function = tg3_timer; } - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); if (err) { free_irq(tp->pdev->irq, dev); @@ -6123,8 +6393,7 @@ static int tg3_open(struct net_device *dev) err = tg3_test_msi(tp); if (err) { - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { pci_disable_msi(tp->pdev); @@ -6134,22 +6403,19 @@ static int tg3_open(struct net_device *dev) tg3_free_rings(tp); tg3_free_consistent(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); return err; } } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); add_timer(&tp->timer); tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; tg3_enable_ints(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); netif_start_queue(dev); @@ -6395,8 +6661,7 @@ static int tg3_close(struct net_device *dev) del_timer_sync(&tp->timer); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 1); #if 0 tg3_dump_state(tp); #endif @@ -6410,8 +6675,7 @@ static int tg3_close(struct net_device *dev) TG3_FLAG_GOT_SERDES_FLOWCTL); netif_carrier_off(tp->dev); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); free_irq(tp->pdev->irq, dev); if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { @@ -6448,16 +6712,15 @@ static unsigned long calc_crc_errors(struct tg3 *tp) if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { - unsigned long flags; u32 val; - spin_lock_irqsave(&tp->lock, flags); + spin_lock_bh(&tp->lock); if (!tg3_readphy(tp, 0x1e, &val)) { tg3_writephy(tp, 0x1e, val | 0x8000); tg3_readphy(tp, 0x14, &val); } else val = 0; - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock_bh(&tp->lock); tp->phy_crc_errors += val; @@ -6719,11 +6982,9 @@ static void tg3_set_rx_mode(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); __tg3_set_rx_mode(dev); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); } #define TG3_REGDUMP_LEN (32 * 1024) @@ -6745,8 +7006,7 @@ static void tg3_get_regs(struct net_device *dev, memset(p, 0, TG3_REGDUMP_LEN); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); #define __GET_REG32(reg) (*(p)++ = tr32(reg)) #define GET_REG32_LOOP(base,len) \ @@ -6796,8 +7056,7 @@ do { p = (u32 *)(orig_p + (reg)); \ #undef GET_REG32_LOOP #undef GET_REG32_1 - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); } static int tg3_get_eeprom_len(struct net_device *dev) @@ -6973,8 +7232,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EINVAL; } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tp->link_config.autoneg = cmd->autoneg; if (cmd->autoneg == AUTONEG_ENABLE) { @@ -6990,8 +7248,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (netif_running(dev)) tg3_setup_phy(tp, 1); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); return 0; } @@ -7027,12 +7284,12 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) return -EINVAL; - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); if (wol->wolopts & WAKE_MAGIC) tp->tg3_flags |= TG3_FLAG_WOL_ENABLE; else tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE; - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); return 0; } @@ -7072,7 +7329,7 @@ static int tg3_nway_reset(struct net_device *dev) if (!netif_running(dev)) return -EAGAIN; - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); r = -EINVAL; tg3_readphy(tp, MII_BMCR, &bmcr); if (!tg3_readphy(tp, MII_BMCR, &bmcr) && @@ -7080,7 +7337,7 @@ static int tg3_nway_reset(struct net_device *dev) tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); r = 0; } - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); return r; } @@ -7102,17 +7359,19 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam * static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct tg3 *tp = netdev_priv(dev); + int irq_sync = 0; if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || (ering->tx_pending > TG3_TX_RING_SIZE - 1)) return -EINVAL; - if (netif_running(dev)) + if (netif_running(dev)) { tg3_netif_stop(tp); + irq_sync = 1; + } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, irq_sync); tp->rx_pending = ering->rx_pending; @@ -7128,8 +7387,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tg3_netif_start(tp); } - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); return 0; } @@ -7146,12 +7404,15 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct tg3 *tp = netdev_priv(dev); + int irq_sync = 0; - if (netif_running(dev)) + if (netif_running(dev)) { tg3_netif_stop(tp); + irq_sync = 1; + } + + tg3_full_lock(tp, irq_sync); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); if (epause->autoneg) tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; else @@ -7170,8 +7431,8 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam tg3_init_hw(tp); tg3_netif_start(tp); } - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + + tg3_full_unlock(tp); return 0; } @@ -7192,12 +7453,12 @@ static int tg3_set_rx_csum(struct net_device *dev, u32 data) return 0; } - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); if (data) tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); return 0; } @@ -7606,8 +7867,6 @@ static int tg3_test_loopback(struct tg3 *tp) tg3_abort_hw(tp, 1); - /* Clearing this flag to keep interrupts disabled */ - tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; tg3_reset_hw(tp); mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | @@ -7716,11 +7975,14 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, data[1] = 1; } if (etest->flags & ETH_TEST_FL_OFFLINE) { - if (netif_running(dev)) + int irq_sync = 0; + + if (netif_running(dev)) { tg3_netif_stop(tp); + irq_sync = 1; + } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, irq_sync); tg3_halt(tp, RESET_KIND_SUSPEND, 1); tg3_nvram_lock(tp); @@ -7742,14 +8004,14 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, data[4] = 1; } - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); + if (tg3_test_interrupt(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; data[5] = 1; } - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + + tg3_full_lock(tp, 0); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { @@ -7757,8 +8019,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_init_hw(tp); tg3_netif_start(tp); } - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + + tg3_full_unlock(tp); } } @@ -7779,9 +8041,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval); - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); data->val_out = mii_regval; @@ -7795,9 +8057,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irq(&tp->lock); + spin_lock_bh(&tp->lock); err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in); - spin_unlock_irq(&tp->lock); + spin_unlock_bh(&tp->lock); return err; @@ -7813,28 +8075,24 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { struct tg3 *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tp->vlgrp = grp; /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */ __tg3_set_rx_mode(dev); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); } static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct tg3 *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); if (tp->vlgrp) tp->vlgrp->vlan_devices[vid] = NULL; - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); } #endif @@ -7846,6 +8104,60 @@ static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } +static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) +{ + struct tg3 *tp = netdev_priv(dev); + u32 max_rxcoal_tick_int = 0, max_txcoal_tick_int = 0; + u32 max_stat_coal_ticks = 0, min_stat_coal_ticks = 0; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + max_rxcoal_tick_int = MAX_RXCOAL_TICK_INT; + max_txcoal_tick_int = MAX_TXCOAL_TICK_INT; + max_stat_coal_ticks = MAX_STAT_COAL_TICKS; + min_stat_coal_ticks = MIN_STAT_COAL_TICKS; + } + + if ((ec->rx_coalesce_usecs > MAX_RXCOL_TICKS) || + (ec->tx_coalesce_usecs > MAX_TXCOL_TICKS) || + (ec->rx_max_coalesced_frames > MAX_RXMAX_FRAMES) || + (ec->tx_max_coalesced_frames > MAX_TXMAX_FRAMES) || + (ec->rx_coalesce_usecs_irq > max_rxcoal_tick_int) || + (ec->tx_coalesce_usecs_irq > max_txcoal_tick_int) || + (ec->rx_max_coalesced_frames_irq > MAX_RXCOAL_MAXF_INT) || + (ec->tx_max_coalesced_frames_irq > MAX_TXCOAL_MAXF_INT) || + (ec->stats_block_coalesce_usecs > max_stat_coal_ticks) || + (ec->stats_block_coalesce_usecs < min_stat_coal_ticks)) + return -EINVAL; + + /* No rx interrupts will be generated if both are zero */ + if ((ec->rx_coalesce_usecs == 0) && + (ec->rx_max_coalesced_frames == 0)) + return -EINVAL; + + /* No tx interrupts will be generated if both are zero */ + if ((ec->tx_coalesce_usecs == 0) && + (ec->tx_max_coalesced_frames == 0)) + return -EINVAL; + + /* Only copy relevant parameters, ignore all others. */ + tp->coal.rx_coalesce_usecs = ec->rx_coalesce_usecs; + tp->coal.tx_coalesce_usecs = ec->tx_coalesce_usecs; + tp->coal.rx_max_coalesced_frames = ec->rx_max_coalesced_frames; + tp->coal.tx_max_coalesced_frames = ec->tx_max_coalesced_frames; + tp->coal.rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq; + tp->coal.tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq; + tp->coal.rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq; + tp->coal.tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq; + tp->coal.stats_block_coalesce_usecs = ec->stats_block_coalesce_usecs; + + if (netif_running(dev)) { + tg3_full_lock(tp, 0); + __tg3_set_coalesce(tp, &tp->coal); + tg3_full_unlock(tp); + } + return 0; +} + static struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, @@ -7881,6 +8193,7 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, + .set_coalesce = tg3_set_coalesce, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) @@ -8539,8 +8852,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) eeprom_phy_id = 0; tp->phy_id = eeprom_phy_id; - if (eeprom_phy_serdes) - tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + if (eeprom_phy_serdes) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; + else + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + } if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | @@ -8675,7 +8992,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } } - if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl; @@ -8728,7 +9045,7 @@ skip_phy_reset: err = tg3_init_5401phy_dsp(tp); } - if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) tp->link_config.advertising = (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | @@ -8898,6 +9215,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; + /* Find msi capability. */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI); + /* Initialize misc host control in PCI block. */ tp->misc_host_ctrl |= (misc_ctrl_reg & MISC_HOST_CTRL_CHIPREV); @@ -8913,7 +9234,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) tp->tg3_flags2 |= TG3_FLG2_5750_PLUS; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) || @@ -8923,6 +9245,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_HW_TSO; + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) + tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; + if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; @@ -9049,8 +9376,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Derive initial jumbo mode from MTU assigned in * ether_setup() via the alloc_etherdev() call */ - if (tp->dev->mtu > ETH_DATA_LEN) - tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE; + if (tp->dev->mtu > ETH_DATA_LEN && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780) + tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE; /* Determine WakeOnLan speed to use. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || @@ -9066,7 +9394,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) || ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) && - (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) + (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) || + (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX || @@ -9275,8 +9604,9 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) #endif mac_offset = 0x7c; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - !(tp->tg3_flags & TG3_FLG2_SUN_570X)) { + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && + !(tp->tg3_flags & TG3_FLG2_SUN_570X)) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; if (tg3_nvram_lock(tp)) @@ -9590,6 +9920,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp) /* Set bit 23 to enable PCIX hw bug fix */ tp->dma_rwctrl |= 0x009f0000; + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) { + /* 5780 always in PCIX mode */ + tp->dma_rwctrl |= 0x00144000; } else { tp->dma_rwctrl |= 0x001b000f; } @@ -9743,19 +10076,35 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - tp->bufmgr_config.mbuf_read_dma_low_water = - DEFAULT_MB_RDMA_LOW_WATER; - tp->bufmgr_config.mbuf_mac_rx_low_water = - DEFAULT_MB_MACRX_LOW_WATER; - tp->bufmgr_config.mbuf_high_water = - DEFAULT_MB_HIGH_WATER; + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_5705; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_5705; + + tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = + DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780; + tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = + DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780; + tp->bufmgr_config.mbuf_high_water_jumbo = + DEFAULT_MB_HIGH_WATER_JUMBO_5780; + } else { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER; + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER; - tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = - DEFAULT_MB_RDMA_LOW_WATER_JUMBO; - tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = - DEFAULT_MB_MACRX_LOW_WATER_JUMBO; - tp->bufmgr_config.mbuf_high_water_jumbo = - DEFAULT_MB_HIGH_WATER_JUMBO; + tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = + DEFAULT_MB_RDMA_LOW_WATER_JUMBO; + tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = + DEFAULT_MB_MACRX_LOW_WATER_JUMBO; + tp->bufmgr_config.mbuf_high_water_jumbo = + DEFAULT_MB_HIGH_WATER_JUMBO; + } tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER; tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER; @@ -9773,6 +10122,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5750: return "5750"; case PHY_ID_BCM5752: return "5752"; + case PHY_ID_BCM5780: return "5780"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; @@ -9825,6 +10175,12 @@ static void __devinit tg3_init_coal(struct tg3 *tp) ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS; ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS; } + + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { + ec->rx_coalesce_usecs_irq = 0; + ec->tx_coalesce_usecs_irq = 0; + ec->stats_block_coalesce_usecs = 0; + } } static int __devinit tg3_init_one(struct pci_dev *pdev, @@ -9962,8 +10318,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_link_config(tp); - tg3_init_bufmgr_config(tp); - tp->rx_pending = TG3_DEF_RX_RING_PENDING; tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING; tp->tx_pending = TG3_DEF_TX_RING_PENDING; @@ -9992,14 +10346,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { - tp->bufmgr_config.mbuf_read_dma_low_water = - DEFAULT_MB_RDMA_LOW_WATER_5705; - tp->bufmgr_config.mbuf_mac_rx_low_water = - DEFAULT_MB_MACRX_LOW_WATER_5705; - tp->bufmgr_config.mbuf_high_water = - DEFAULT_MB_HIGH_WATER_5705; - } + tg3_init_bufmgr_config(tp); #if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { @@ -10165,24 +10512,19 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) del_timer_sync(&tp->timer); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 1); tg3_disable_ints(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); netif_device_detach(dev); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); err = tg3_set_power_state(tp, pci_choose_state(pdev, state)); if (err) { - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tg3_init_hw(tp); @@ -10192,8 +10534,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_attach(dev); tg3_netif_start(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); } return err; @@ -10216,20 +10557,16 @@ static int tg3_resume(struct pci_dev *pdev) netif_device_attach(dev); - spin_lock_irq(&tp->lock); - spin_lock(&tp->tx_lock); + tg3_full_lock(tp, 0); tg3_init_hw(tp); tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); - tg3_enable_ints(tp); - tg3_netif_start(tp); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); + tg3_full_unlock(tp); return 0; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 993f84c93dc4..5c4433c147fa 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -136,6 +136,7 @@ #define ASIC_REV_5705 0x03 #define ASIC_REV_5750 0x04 #define ASIC_REV_5752 0x06 +#define ASIC_REV_5780 0x08 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -879,31 +880,41 @@ #define LOW_RXCOL_TICKS_CLRTCKS 0x00000014 #define DEFAULT_RXCOL_TICKS 0x00000048 #define HIGH_RXCOL_TICKS 0x00000096 +#define MAX_RXCOL_TICKS 0x000003ff #define HOSTCC_TXCOL_TICKS 0x00003c0c #define LOW_TXCOL_TICKS 0x00000096 #define LOW_TXCOL_TICKS_CLRTCKS 0x00000048 #define DEFAULT_TXCOL_TICKS 0x0000012c #define HIGH_TXCOL_TICKS 0x00000145 +#define MAX_TXCOL_TICKS 0x000003ff #define HOSTCC_RXMAX_FRAMES 0x00003c10 #define LOW_RXMAX_FRAMES 0x00000005 #define DEFAULT_RXMAX_FRAMES 0x00000008 #define HIGH_RXMAX_FRAMES 0x00000012 +#define MAX_RXMAX_FRAMES 0x000000ff #define HOSTCC_TXMAX_FRAMES 0x00003c14 #define LOW_TXMAX_FRAMES 0x00000035 #define DEFAULT_TXMAX_FRAMES 0x0000004b #define HIGH_TXMAX_FRAMES 0x00000052 +#define MAX_TXMAX_FRAMES 0x000000ff #define HOSTCC_RXCOAL_TICK_INT 0x00003c18 #define DEFAULT_RXCOAL_TICK_INT 0x00000019 #define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014 +#define MAX_RXCOAL_TICK_INT 0x000003ff #define HOSTCC_TXCOAL_TICK_INT 0x00003c1c #define DEFAULT_TXCOAL_TICK_INT 0x00000019 #define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014 +#define MAX_TXCOAL_TICK_INT 0x000003ff #define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 #define DEFAULT_RXCOAL_MAXF_INT 0x00000005 +#define MAX_RXCOAL_MAXF_INT 0x000000ff #define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 #define DEFAULT_TXCOAL_MAXF_INT 0x00000005 +#define MAX_TXCOAL_MAXF_INT 0x000000ff #define HOSTCC_STAT_COAL_TICKS 0x00003c28 #define DEFAULT_STAT_COAL_TICKS 0x000f4240 +#define MAX_STAT_COAL_TICKS 0xd693d400 +#define MIN_STAT_COAL_TICKS 0x00000064 /* 0x3c2c --> 0x3c30 unused */ #define HOSTCC_STATS_BLK_HOST_ADDR 0x00003c30 /* 64-bit */ #define HOSTCC_STATUS_BLK_HOST_ADDR 0x00003c38 /* 64-bit */ @@ -974,14 +985,17 @@ #define DEFAULT_MB_RDMA_LOW_WATER 0x00000050 #define DEFAULT_MB_RDMA_LOW_WATER_5705 0x00000000 #define DEFAULT_MB_RDMA_LOW_WATER_JUMBO 0x00000130 +#define DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780 0x00000000 #define BUFMGR_MB_MACRX_LOW_WATER 0x00004414 #define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 #define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 +#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b #define BUFMGR_MB_HIGH_WATER 0x00004418 #define DEFAULT_MB_HIGH_WATER 0x00000060 #define DEFAULT_MB_HIGH_WATER_5705 0x00000060 #define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c +#define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096 #define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c #define BUFMGR_MB_ALLOC_BIT 0x10000000 #define BUFMGR_RX_MB_ALLOC_RESP 0x00004420 @@ -2006,17 +2020,31 @@ struct tg3_ethtool_stats { struct tg3 { /* begin "general, frequently-used members" cacheline section */ + /* If the IRQ handler (which runs lockless) needs to be + * quiesced, the following bitmask state is used. The + * SYNC flag is set by non-IRQ context code to initiate + * the quiescence. + * + * When the IRQ handler notices that SYNC is set, it + * disables interrupts and returns. + * + * When all outstanding IRQ handlers have returned after + * the SYNC flag has been set, the setter can be assured + * that interrupts will no longer get run. + * + * In this way all SMP driver locks are never acquired + * in hw IRQ context, only sw IRQ context or lower. + */ + unsigned int irq_sync; + /* SMP locking strategy: * * lock: Held during all operations except TX packet * processing. * - * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx + * tx_lock: Held during tg3_start_xmit and tg3_tx * - * If you want to shut up all asynchronous processing you must - * acquire both locks, 'lock' taken before 'tx_lock'. IRQs must - * be disabled to take 'lock' but only softirq disabling is - * necessary for acquisition of 'tx_lock'. + * Both of these locks are to be held with BH safety. */ spinlock_t lock; spinlock_t indirect_lock; @@ -2063,6 +2091,8 @@ struct tg3 { struct tg3_rx_buffer_desc *rx_rcb; dma_addr_t rx_rcb_mapping; + u32 rx_pkt_buf_sz; + /* begin "everything else" cacheline(s) section */ struct net_device_stats net_stats; struct net_device_stats net_stats_prev; @@ -2100,7 +2130,7 @@ struct tg3 { #define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 #define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 -#define TG3_FLAG_JUMBO_ENABLE 0x00800000 +#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 @@ -2130,6 +2160,11 @@ struct tg3 { #define TG3_FLG2_5750_PLUS 0x00080000 #define TG3_FLG2_PROTECTED_NVRAM 0x00100000 #define TG3_FLG2_USING_MSI 0x00200000 +#define TG3_FLG2_JUMBO_CAPABLE 0x00400000 +#define TG3_FLG2_MII_SERDES 0x00800000 +#define TG3_FLG2_ANY_SERDES (TG3_FLG2_PHY_SERDES | \ + TG3_FLG2_MII_SERDES) +#define TG3_FLG2_PARALLEL_DETECT 0x01000000 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 @@ -2163,6 +2198,7 @@ struct tg3 { u8 pci_bist; int pm_cap; + int msi_cap; /* PHY info */ u32 phy_id; @@ -2176,6 +2212,7 @@ struct tg3 { #define PHY_ID_BCM5705 0x600081a0 #define PHY_ID_BCM5750 0x60008180 #define PHY_ID_BCM5752 0x60008100 +#define PHY_ID_BCM5780 0x60008350 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 9680a308c62b..942fae0f2130 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -171,6 +171,7 @@ #include <linux/ioport.h> #include <linux/eisa.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/delay.h> @@ -566,7 +567,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, priv->adapter = &board_info[ent->driver_data]; - rc = pci_set_dma_mask(pdev, 0xFFFFFFFF); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n"); goto err_out_free_dev; @@ -2819,7 +2820,7 @@ void TLan_PhyMonitor( struct net_device *dev ) if (priv->link) { priv->link = 0; printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name); - dev->flags &= ~IFF_RUNNING; + netif_carrier_off(dev); TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); return; } @@ -2829,7 +2830,7 @@ void TLan_PhyMonitor( struct net_device *dev ) if ((phy_status & MII_GS_LINK) && !priv->link) { priv->link = 1; printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name); - dev->flags |= IFF_RUNNING; + netif_carrier_on(dev); } /* Setup a new monitor */ diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index 0d1dcf421771..41e0cd8f4786 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -276,7 +276,8 @@ static void xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value) return ; } -int __devinit xl_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit xl_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev ; struct xl_private *xl_priv ; diff --git a/drivers/net/tokenring/3c359_microcode.h b/drivers/net/tokenring/3c359_microcode.h index 81354afa3d34..0400c029c077 100644 --- a/drivers/net/tokenring/3c359_microcode.h +++ b/drivers/net/tokenring/3c359_microcode.h @@ -22,7 +22,7 @@ static int mc_size = 24880 ; -u8 microcode[] = { +static const u8 microcode[] = { 0xfe,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index bd4a2bccf867..87103c400999 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c @@ -468,14 +468,3 @@ static void __exit abyss_rmmod (void) module_init(abyss_init); module_exit(abyss_rmmod); - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index c098863bdd9d..e7b001017b9a 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -151,7 +151,7 @@ static char version[] __initdata = /* this allows displaying full adapter information */ -char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" }; +static char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" }; static char pcchannelid[] __devinitdata = { 0x05, 0x00, 0x04, 0x09, @@ -171,7 +171,7 @@ static char mcchannelid[] __devinitdata = { 0x03, 0x08, 0x02, 0x00 }; -char __devinit *adapter_def(char type) +static char __devinit *adapter_def(char type) { switch (type) { case 0xF: return "PC Adapter | PC Adapter II | Adapter/A"; @@ -184,7 +184,7 @@ char __devinit *adapter_def(char type) #define TRC_INIT 0x01 /* Trace initialization & PROBEs */ #define TRC_INITV 0x02 /* verbose init trace points */ -unsigned char ibmtr_debug_trace = 0; +static unsigned char ibmtr_debug_trace = 0; static int ibmtr_probe(struct net_device *dev); static int ibmtr_probe1(struct net_device *dev, int ioaddr); @@ -192,20 +192,20 @@ static unsigned char get_sram_size(struct tok_info *adapt_info); static int trdev_init(struct net_device *dev); static int tok_open(struct net_device *dev); static int tok_init_card(struct net_device *dev); -void tok_open_adapter(unsigned long dev_addr); +static void tok_open_adapter(unsigned long dev_addr); static void open_sap(unsigned char type, struct net_device *dev); static void tok_set_multicast_list(struct net_device *dev); static int tok_send_packet(struct sk_buff *skb, struct net_device *dev); static int tok_close(struct net_device *dev); -irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void initial_tok_int(struct net_device *dev); static void tr_tx(struct net_device *dev); static void tr_rx(struct net_device *dev); -void ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev); +static void ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev); static void tok_rerun(unsigned long dev_addr); -void ibmtr_readlog(struct net_device *dev); +static void ibmtr_readlog(struct net_device *dev); static struct net_device_stats *tok_get_stats(struct net_device *dev); -int ibmtr_change_mtu(struct net_device *dev, int mtu); +static int ibmtr_change_mtu(struct net_device *dev, int mtu); static void find_turbo_adapters(int *iolist); static int ibmtr_portlist[IBMTR_MAX_ADAPTERS+1] __devinitdata = { @@ -888,11 +888,6 @@ static int tok_open(struct net_device *dev) ti->sap_status = CLOSED; /* CLOSED or OPEN */ ti->open_failure = NO; /* NO or YES */ ti->open_mode = MANUAL; /* MANUAL or AUTOMATIC */ - /* 12/2000 not typical Linux, but we can use RUNNING to let us know when - the network has crapped out or cables are disconnected. Useful because - the IFF_UP flag stays up the whole time, until ifconfig tr0 down. - */ - dev->flags &= ~IFF_RUNNING; ti->sram_phys &= ~1; /* to reverse what we do in tok_close */ /* init the spinlock */ @@ -933,7 +928,7 @@ static int tok_open(struct net_device *dev) #define DLC_MAX_SAP_OFST 32 #define DLC_MAX_STA_OFST 33 -void tok_open_adapter(unsigned long dev_addr) +static void tok_open_adapter(unsigned long dev_addr) { struct net_device *dev = (struct net_device *) dev_addr; struct tok_info *ti; @@ -1104,7 +1099,7 @@ static void __iomem *map_address(struct tok_info *ti, unsigned index, __u8 *page return ti->sram_virt + index; } -void dir_open_adapter (struct net_device *dev) +static void dir_open_adapter (struct net_device *dev) { struct tok_info *ti = (struct tok_info *) dev->priv; unsigned char ret_code; @@ -1177,7 +1172,7 @@ void dir_open_adapter (struct net_device *dev) /******************************************************************************/ -irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned char status; /* unsigned char status_even ; */ @@ -1242,7 +1237,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) ti->open_status = CLOSED; ti->sap_status = CLOSED; ti->open_mode = AUTOMATIC; - dev->flags &= ~IFF_RUNNING; + netif_carrier_off(dev); netif_stop_queue(dev); ti->open_action = RESTART; outb(0, dev->base_addr + ADAPTRESET); @@ -1323,7 +1318,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) break; } netif_wake_queue(dev); - dev->flags |= IFF_RUNNING;/*BMS 12/2000*/ + netif_carrier_on(dev); break; case DIR_INTERRUPT: case DIR_MOD_OPEN_PARAMS: @@ -1427,7 +1422,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) ring_status); if(ring_status& (REMOVE_RECV|AUTO_REMOVAL|LOBE_FAULT)){ netif_stop_queue(dev); - dev->flags &= ~IFF_RUNNING;/*not typical Linux*/ + netif_carrier_off(dev); DPRINTK("Remove received, or Auto-removal error" ", or Lobe fault\n"); DPRINTK("We'll try to reopen the closed adapter" @@ -1845,7 +1840,7 @@ static void tr_rx(struct net_device *dev) /*****************************************************************************/ -void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev) +static void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev) { tmr->expires = jiffies + TR_RETRY_INTERVAL; tmr->data = (unsigned long) dev; @@ -1877,7 +1872,7 @@ void tok_rerun(unsigned long dev_addr){ /*****************************************************************************/ -void ibmtr_readlog(struct net_device *dev) +static void ibmtr_readlog(struct net_device *dev) { struct tok_info *ti; @@ -1910,7 +1905,7 @@ static struct net_device_stats *tok_get_stats(struct net_device *dev) /*****************************************************************************/ -int ibmtr_change_mtu(struct net_device *dev, int mtu) +static int ibmtr_change_mtu(struct net_device *dev, int mtu) { struct tok_info *ti = (struct tok_info *) dev->priv; diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 99e0b03b69a8..97712c3c4e07 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -118,6 +118,7 @@ #include <linux/stddef.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/spinlock.h> #include <linux/version.h> #include <linux/bitops.h> @@ -257,7 +258,7 @@ static int __devinit streamer_init_one(struct pci_dev *pdev, #endif #endif - rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR "%s: No suitable PCI mapping available.\n", dev->name); @@ -454,8 +455,7 @@ static int streamer_reset(struct net_device *dev) writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL); t = jiffies; /* Hold soft reset bit for a while */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); + ssleep(1); writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET, streamer_mmio + BCTL); @@ -511,8 +511,7 @@ static int streamer_reset(struct net_device *dev) writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + msleep_interruptible(100); if (jiffies - t > 40 * HZ) { printk(KERN_ERR "IBM PCI tokenring card not responding\n"); diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index cfae2bbf2167..659cbdbef7f3 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -625,7 +625,7 @@ static int madgemc_chipset_init(struct net_device *dev) /* * Disable the board, and put back into power-up state. */ -void madgemc_chipset_close(struct net_device *dev) +static void madgemc_chipset_close(struct net_device *dev) { /* disable interrupts */ madgemc_setint(dev, 0); @@ -786,15 +786,3 @@ module_exit(madgemc_exit); MODULE_LICENSE("GPL"); - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ - diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c index 675b063508e3..40ad0fde28af 100644 --- a/drivers/net/tokenring/proteon.c +++ b/drivers/net/tokenring/proteon.c @@ -419,14 +419,3 @@ void cleanup_module(void) } #endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c index 3fab54a26466..f26796e2d0e5 100644 --- a/drivers/net/tokenring/skisa.c +++ b/drivers/net/tokenring/skisa.c @@ -429,14 +429,3 @@ void cleanup_module(void) } #endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 5c8aeacb8318..67d2b596ce22 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -77,7 +77,7 @@ static int ringspeed; /* SMC Name of the Adapter. */ static char smctr_name[] = "SMC TokenCard"; -char *smctr_model = "Unknown"; +static char *smctr_model = "Unknown"; /* Use 0 for production, 1 for verification, 2 for debug, and * 3 for very verbose debug. diff --git a/drivers/net/tokenring/smctr_firmware.h b/drivers/net/tokenring/smctr_firmware.h index 53f2cbc817c9..48994b043b7c 100644 --- a/drivers/net/tokenring/smctr_firmware.h +++ b/drivers/net/tokenring/smctr_firmware.h @@ -21,7 +21,7 @@ #if defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE) -unsigned char smctr_code[] = { +static const unsigned char smctr_code[] = { 0x0BC, 0x01D, 0x012, 0x03B, 0x063, 0x0B4, 0x0E9, 0x000, 0x000, 0x01F, 0x000, 0x001, 0x001, 0x000, 0x002, 0x005, 0x001, 0x000, 0x006, 0x003, 0x001, 0x000, 0x004, 0x009, diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index df43b449e429..5e0b0ce98ed7 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -2379,7 +2379,7 @@ EXPORT_SYMBOL(tmsdev_init); EXPORT_SYMBOL(tmsdev_term); EXPORT_SYMBOL(tms380tr_wait); -struct module *TMS380_module = NULL; +static struct module *TMS380_module = NULL; int init_module(void) { @@ -2397,14 +2397,3 @@ void cleanup_module(void) MODULE_LICENSE("GPL"); - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index 37ddb5c2bec3..2e18c0a46482 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -254,14 +254,3 @@ static void __exit tms_pci_rmmod (void) module_init(tms_pci_init); module_exit(tms_pci_rmmod); - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c" - * c-set-style "K&R" - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index dd357dd8c370..fc353e348f9a 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -446,13 +446,13 @@ static void de_rx (struct de_private *de) mapping = de->rx_skb[rx_tail].mapping = - pci_map_single(de->pdev, copy_skb->tail, + pci_map_single(de->pdev, copy_skb->data, buflen, PCI_DMA_FROMDEVICE); de->rx_skb[rx_tail].skb = copy_skb; } else { pci_dma_sync_single_for_cpu(de->pdev, mapping, len, PCI_DMA_FROMDEVICE); skb_reserve(copy_skb, RX_OFFSET); - memcpy(skb_put(copy_skb, len), skb->tail, len); + memcpy(skb_put(copy_skb, len), skb->data, len); pci_dma_sync_single_for_device(de->pdev, mapping, len, PCI_DMA_FROMDEVICE); @@ -1269,7 +1269,7 @@ static int de_refill_rx (struct de_private *de) skb->dev = de->dev; de->rx_skb[i].mapping = pci_map_single(de->pdev, - skb->tail, de->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE); de->rx_skb[i].skb = skb; de->rx_ring[i].opts1 = cpu_to_le32(DescOwn); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index e25f33df223e..74e9075d9c48 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -78,6 +78,7 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -354,7 +355,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_set_dma_mask(pdev, 0xffffffff)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n"); err = -ENODEV; goto err_out_free; @@ -743,11 +744,6 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs) DMFE_DBUG(0, "dmfe_interrupt()", 0); - if (!dev) { - DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0); - return IRQ_NONE; - } - spin_lock_irqsave(&db->lock, flags); /* Got DM910X status */ @@ -949,8 +945,8 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) /* Received Packet CRC check need or not */ if ( (db->dm910x_chk_mode & 1) && - (cal_CRC(skb->tail, rxlen, 1) != - (*(u32 *) (skb->tail+rxlen) ))) { /* FIXME (?) */ + (cal_CRC(skb->data, rxlen, 1) != + (*(u32 *) (skb->data+rxlen) ))) { /* FIXME (?) */ /* Found a error received packet */ dmfe_reuse_skb(db, rxptr->rx_skb_ptr); db->dm910x_chk_mode = 3; @@ -963,7 +959,7 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) /* size less than COPY_SIZE, allocate a rxlen SKB */ skb->dev = dev; skb_reserve(skb, 2); /* 16byte align */ - memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen); + memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->data, rxlen); dmfe_reuse_skb(db, rxptr->rx_skb_ptr); } else { skb->dev = dev; @@ -1256,7 +1252,7 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb) if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) { rxptr->rx_skb_ptr = skb; - rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); + rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); wmb(); rxptr->rdes0 = cpu_to_le32(0x80000000); db->rx_avail_cnt++; @@ -1467,7 +1463,7 @@ static void allocate_rx_buffer(struct dmfe_board_info *db) if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL ) break; rxptr->rx_skb_ptr = skb; /* FIXME (?) */ - rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); + rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); wmb(); rxptr->rdes0 = cpu_to_le32(0x80000000); rxptr = rxptr->next_rx_desc; @@ -1806,7 +1802,7 @@ static void dmfe_parse_srom(struct dmfe_board_info * db) if ( ( (int) srom[18] & 0xff) == SROM_V41_CODE) { /* SROM V4.01 */ /* Get NIC support media mode */ - db->NIC_capability = le16_to_cpup(srom + 34); + db->NIC_capability = le16_to_cpup((__le16 *)srom + 34/2); db->PHY_reg4 = 0; for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) { switch( db->NIC_capability & tmp_reg ) { @@ -1818,7 +1814,8 @@ static void dmfe_parse_srom(struct dmfe_board_info * db) } /* Media Mode Force or not check */ - dmfe_mode = le32_to_cpup(srom + 34) & le32_to_cpup(srom + 36); + dmfe_mode = le32_to_cpup((__le32 *)srom + 34/4) & + le32_to_cpup((__le32 *)srom + 36/4); switch(dmfe_mode) { case 0x4: dmfe_media_mode = DMFE_100MHF; break; /* 100MHF */ case 0x2: dmfe_media_mode = DMFE_10MFD; break; /* 10MFD */ diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index ac5bf49ff60f..fbd9ab60b052 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -63,6 +63,22 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = { */ { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 } }, + {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset */ + 0x0000, /* 0 == high offset, 0 == gap */ + 0x0800, /* Default Autoselect */ + 0x8001, /* 1 leaf, extended type, bogus len */ + 0x0003, /* Type 3 (MII), PHY #0 */ + 0x0400, /* 0 init instr, 4 reset instr */ + 0x0801, /* Set control mode, GP0 output */ + 0x0000, /* Drive GP0 Low (RST is active low) */ + 0x0800, /* control mode, GP0 input (undriven) */ + 0x0000, /* clear control mode */ + 0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX */ + 0x01e0, /* Advertise all above */ + 0x5000, /* FDX all above */ + 0x1800, /* Set fast TTM in 100bt modes */ + 0x0000, /* PHY cannot be unplugged */ + }}, {NULL}}; diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index afb5cda9d8e1..bb3558164a5b 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -78,7 +78,7 @@ int tulip_refill_rx(struct net_device *dev) if (skb == NULL) break; - mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ, + mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); tp->rx_buffers[entry].mapping = mapping; @@ -199,12 +199,12 @@ int tulip_poll(struct net_device *dev, int *budget) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail, + eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, pkt_len, 0); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), - tp->rx_buffers[entry].skb->tail, + tp->rx_buffers[entry].skb->data, pkt_len); #endif pci_dma_sync_single_for_device(tp->pdev, @@ -423,12 +423,12 @@ static int tulip_rx(struct net_device *dev) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail, + eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, pkt_len, 0); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), - tp->rx_buffers[entry].skb->tail, + tp->rx_buffers[entry].skb->data, pkt_len); #endif pci_dma_sync_single_for_device(tp->pdev, diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index 919c40cd635c..e26c31f944bf 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -400,6 +400,9 @@ void tulip_select_media(struct net_device *dev, int startup) } tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); + + mdelay(1); + return; } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index e0ae3ed6e578..d45d8f56e5b4 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -242,6 +242,7 @@ static struct pci_device_id tulip_pci_tbl[] = { { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ { 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */ { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ + { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); @@ -624,7 +625,7 @@ static void tulip_init_ring(struct net_device *dev) tp->rx_buffers[i].skb = skb; if (skb == NULL) break; - mapping = pci_map_single(tp->pdev, skb->tail, + mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); tp->rx_buffers[i].mapping = mapping; skb->dev = dev; /* Mark as being used by this device. */ @@ -1514,8 +1515,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, (PCI_SLOT(pdev->devfn) == 12))) { /* Cobalt MAC address in first EEPROM locations. */ sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; + /* Ensure our media table fixup get's applied */ + memcpy(ee_data + 16, ee_data, 8); } #endif #ifdef CONFIG_GSC @@ -1756,11 +1757,19 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); - if (dev && netif_running (dev) && netif_device_present (dev)) { - netif_device_detach (dev); - tulip_down (dev); - /* pci_power_off(pdev, -1); */ - } + if (!dev) + return -EINVAL; + + if (netif_running(dev)) + tulip_down(dev); + + netif_device_detach(dev); + free_irq(dev->irq, dev); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; } @@ -1768,15 +1777,26 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state) static int tulip_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + int retval; - if (dev && netif_running (dev) && !netif_device_present (dev)) { -#if 1 - pci_enable_device (pdev); -#endif - /* pci_power_on(pdev); */ - tulip_up (dev); - netif_device_attach (dev); + if (!dev) + return -EINVAL; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + pci_enable_device(pdev); + + if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) { + printk (KERN_ERR "tulip: request_irq failed in resume\n"); + return retval; } + + netif_device_attach(dev); + + if (netif_running(dev)) + tulip_up(dev); + return 0; } diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index caff2f590165..5b1af3986abf 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -121,6 +121,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> @@ -394,7 +395,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, irq = pdev->irq; - if (pci_set_dma_mask(pdev,0xFFFFffff)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "Winbond-840: Device %s disabled due to DMA limitations.\n", pci_name(pdev)); return -EIO; @@ -848,7 +849,7 @@ static void init_rxtx_rings(struct net_device *dev) if (skb == NULL) break; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_addr[i] = pci_map_single(np->pci_dev,skb->tail, + np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data, skb->len,PCI_DMA_FROMDEVICE); np->rx_ring[i].buffer1 = np->rx_addr[i]; @@ -1268,7 +1269,7 @@ static int netdev_rx(struct net_device *dev) pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); + eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, @@ -1314,7 +1315,7 @@ static int netdev_rx(struct net_device *dev) break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ np->rx_addr[entry] = pci_map_single(np->pci_dev, - skb->tail, + skb->data, skb->len, PCI_DMA_FROMDEVICE); np->rx_ring[entry].buffer1 = np->rx_addr[entry]; } diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index b8a9b395c5ea..887d7245fe7b 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -899,7 +899,7 @@ static void xircom_init_ring(struct net_device *dev) break; skb->dev = dev; /* Mark as being used by this device. */ tp->rx_ring[i].status = Rx0DescOwned; /* Owned by Xircom chip */ - tp->rx_ring[i].buffer1 = virt_to_bus(skb->tail); + tp->rx_ring[i].buffer1 = virt_to_bus(skb->data); } tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -1291,7 +1291,7 @@ xircom_rx(struct net_device *dev) if (skb == NULL) break; skb->dev = dev; /* Mark as being used by this device. */ - tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail); + tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data); work_done++; } tp->rx_ring[entry].status = Rx0DescOwned; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7bfee366297b..effab0b9adca 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -215,7 +215,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) poll_wait(file, &tun->read_wait, wait); - if (skb_queue_len(&tun->readq)) + if (!skb_queue_empty(&tun->readq)) mask |= POLLIN | POLLRDNORM; return mask; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 8f3392989a06..ecfa6f8805ce 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1661,7 +1661,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx) #endif skb->dev = tp->dev; - dma_addr = pci_map_single(tp->pdev, skb->tail, + dma_addr = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); /* Since no card does 64 bit DAC, the high bits will never @@ -1721,7 +1721,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready, pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(new_skb, skb->tail, pkt_len, 0); + eth_copy_and_sum(new_skb, skb->data, pkt_len, 0); pci_dma_sync_single_for_device(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); @@ -1906,9 +1906,9 @@ typhoon_sleep(struct typhoon *tp, pci_power_t state, u16 events) */ netif_carrier_off(tp->dev); - pci_enable_wake(tp->pdev, pci_choose_state(pdev, state), 1); + pci_enable_wake(tp->pdev, state, 1); pci_disable_device(pdev); - return pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return pci_set_power_state(pdev, state); } static int @@ -2274,7 +2274,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) goto need_resume; } - if(typhoon_sleep(tp, state, tp->wol_events) < 0) { + if(typhoon_sleep(tp, pci_choose_state(pdev, state), tp->wol_events) < 0) { printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name); goto need_resume; } diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 7b57d552094a..fc7738ffbfff 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -186,6 +186,7 @@ static const int multicast_filter_limit = 32; #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> @@ -506,7 +507,7 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; static int rhine_close(struct net_device *dev); -static void rhine_shutdown (struct device *gdev); +static void rhine_shutdown (struct pci_dev *pdev); #define RHINE_WAIT_FOR(condition) do { \ int i=1024; \ @@ -740,7 +741,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, goto err_out; /* this should always be supported */ - rc = pci_set_dma_mask(pdev, 0xffffffff); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR "32-bit PCI DMA addresses not supported by " "the card!?\n"); @@ -989,7 +990,7 @@ static void alloc_rbufs(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ rp->rx_skbuff_dma[i] = - pci_map_single(rp->pdev, skb->tail, rp->rx_buf_sz, + pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, PCI_DMA_FROMDEVICE); rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]); @@ -1397,7 +1398,7 @@ static void rhine_tx(struct net_device *dev) while (rp->dirty_tx != rp->cur_tx) { txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); if (debug > 6) - printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n", + printk(KERN_DEBUG "Tx scavenge %d status %8.8x.\n", entry, txstatus); if (txstatus & DescOwn) break; @@ -1468,7 +1469,7 @@ static void rhine_rx(struct net_device *dev) int data_size = desc_status >> 16; if (debug > 4) - printk(KERN_DEBUG " rhine_rx() status is %8.8x.\n", + printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", desc_status); if (--boguscnt < 0) break; @@ -1486,7 +1487,7 @@ static void rhine_rx(struct net_device *dev) } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG " rhine_rx() Rx " + printk(KERN_DEBUG "rhine_rx() Rx " "error was %8.8x.\n", desc_status); rp->stats.rx_errors++; @@ -1517,7 +1518,7 @@ static void rhine_rx(struct net_device *dev) PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, - rp->rx_skbuff[entry]->tail, + rp->rx_skbuff[entry]->data, pkt_len, 0); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(rp->pdev, @@ -1560,7 +1561,7 @@ static void rhine_rx(struct net_device *dev) break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ rp->rx_skbuff_dma[entry] = - pci_map_single(rp->pdev, skb->tail, + pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, PCI_DMA_FROMDEVICE); rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]); @@ -1894,9 +1895,8 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -static void rhine_shutdown (struct device *gendev) +static void rhine_shutdown (struct pci_dev *pdev) { - struct pci_dev *pdev = to_pci_dev(gendev); struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; @@ -1955,7 +1955,7 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state) pci_save_state(pdev); spin_lock_irqsave(&rp->lock, flags); - rhine_shutdown(&pdev->dev); + rhine_shutdown(pdev); spin_unlock_irqrestore(&rp->lock, flags); free_irq(dev->irq, dev); @@ -2009,9 +2009,7 @@ static struct pci_driver rhine_driver = { .suspend = rhine_suspend, .resume = rhine_resume, #endif /* CONFIG_PM */ - .driver = { - .shutdown = rhine_shutdown, - } + .shutdown = rhine_shutdown, }; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 15e710283493..abc5cee6eedc 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1335,7 +1335,7 @@ static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size, if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) skb_reserve(new_skb, 2); - memcpy(new_skb->data, rx_skb[0]->tail, pkt_size); + memcpy(new_skb->data, rx_skb[0]->data, pkt_size); *rx_skb = new_skb; ret = 0; } @@ -1456,9 +1456,9 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx) * Do the gymnastics to get the buffer head for data at * 64byte alignment. */ - skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->tail & 63); + skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->data & 63); rd_info->skb->dev = vptr->dev; - rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->tail, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE); + rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE); /* * Fill in the descriptor to match diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index 1b70b7c97580..d9a774b91ddc 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1414,7 +1414,7 @@ static inline void mac_get_cam(struct mac_regs __iomem * regs, int idx, u8 *addr * the rest of the logic from the result of sleep/wakeup */ -inline static void mac_wol_reset(struct mac_regs __iomem * regs) +static inline void mac_wol_reset(struct mac_regs __iomem * regs) { /* Turn off SWPTAG right after leaving power mode */ @@ -1811,7 +1811,7 @@ struct velocity_info { * CHECK ME: locking */ -inline static int velocity_get_ip(struct velocity_info *vptr) +static inline int velocity_get_ip(struct velocity_info *vptr) { struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr; struct in_ifaddr *ifa; diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 66b94668ddd8..18c27e1e7884 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -435,7 +435,7 @@ config VENDOR_SANGOMA the driver to support. If you have one or more of these cards, say M to this option; - and read <file:Documentation/networking/wanpipe.txt>. + and read <file:Documentation/networking/wan-router.txt>. To compile this driver as a module, choose M here: the module will be called wanpipe. diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 921a573372e9..7ff814fd65d0 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -235,7 +235,7 @@ static int dma[MAX_CARDS+1]; static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, }; /* for class stuff*/ -static struct class_simple *cosa_class; +static struct class *cosa_class; #ifdef MODULE module_param_array(io, int, NULL, 0); @@ -394,19 +394,19 @@ static int __init cosa_init(void) goto out; } devfs_mk_dir("cosa"); - cosa_class = class_simple_create(THIS_MODULE, "cosa"); + cosa_class = class_create(THIS_MODULE, "cosa"); if (IS_ERR(cosa_class)) { err = PTR_ERR(cosa_class); goto out_chrdev; } for (i=0; i<nr_cards; i++) { - class_simple_device_add(cosa_class, MKDEV(cosa_major, i), + class_device_create(cosa_class, MKDEV(cosa_major, i), NULL, "cosa%d", i); err = devfs_mk_cdev(MKDEV(cosa_major, i), S_IFCHR|S_IRUSR|S_IWUSR, "cosa/%d", i); if (err) { - class_simple_device_remove(MKDEV(cosa_major, i)); + class_device_destroy(cosa_class, MKDEV(cosa_major, i)); goto out_chrdev; } } @@ -427,10 +427,10 @@ static void __exit cosa_exit(void) printk(KERN_INFO "Unloading the cosa module\n"); for (i=0; i<nr_cards; i++) { - class_simple_device_remove(MKDEV(cosa_major, i)); + class_device_destroy(cosa_class, MKDEV(cosa_major, i)); devfs_remove("cosa/%d", i); } - class_simple_destroy(cosa_class); + class_destroy(cosa_class); devfs_remove("cosa"); for (cosa=cosa_cards; nr_cards--; cosa++) { /* Clean up the per-channel data */ diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 7575b799ce53..2c83cca34b86 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -861,8 +861,7 @@ fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, /* * Mark it for our own raw sockets interface */ -static unsigned short farsync_type_trans(struct sk_buff *skb, - struct net_device *dev) +static __be16 farsync_type_trans(struct sk_buff *skb, struct net_device *dev) { skb->dev = dev; skb->mac.raw = skb->data; @@ -981,6 +980,7 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd) /* Wait for any previous command to complete */ while (mbval > NAK) { spin_unlock_irqrestore(&card->card_lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_lock_irqsave(&card->card_lock, flags); diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index c1b6896d7007..48c03c11cd9a 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, } skb_reserve(skb, 4); cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); - data = (cisco_packet*)skb->tail; + data = (cisco_packet*)skb->data; data->type = htonl(type); data->par1 = htonl(par1); @@ -91,8 +91,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, -static unsigned short cisco_type_trans(struct sk_buff *skb, - struct net_device *dev) +static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) { hdlc_header *data = (hdlc_header*)skb->data; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 7f450b51a6cb..a5d6891c9d4c 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -2,7 +2,7 @@ * Generic HDLC support routines for Linux * Frame Relay support * - * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -27,6 +27,10 @@ active = open and "link reliable" exist = new = not used + CCITT LMI: ITU-T Q.933 Annex A + ANSI LMI: ANSI T1.617 Annex D + CISCO LMI: the original, aka "Gang of Four" LMI + */ #include <linux/module.h> @@ -49,45 +53,41 @@ #undef DEBUG_ECN #undef DEBUG_LINK -#define MAXLEN_LMISTAT 20 /* max size of status enquiry frame */ - -#define PVC_STATE_NEW 0x01 -#define PVC_STATE_ACTIVE 0x02 -#define PVC_STATE_FECN 0x08 /* FECN condition */ -#define PVC_STATE_BECN 0x10 /* BECN condition */ - - -#define FR_UI 0x03 -#define FR_PAD 0x00 - -#define NLPID_IP 0xCC -#define NLPID_IPV6 0x8E -#define NLPID_SNAP 0x80 -#define NLPID_PAD 0x00 -#define NLPID_Q933 0x08 - - -#define LMI_DLCI 0 /* LMI DLCI */ -#define LMI_PROTO 0x08 -#define LMI_CALLREF 0x00 /* Call Reference */ -#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI lockshift */ -#define LMI_REPTYPE 1 /* report type */ -#define LMI_CCITT_REPTYPE 0x51 -#define LMI_ALIVE 3 /* keep alive */ -#define LMI_CCITT_ALIVE 0x53 -#define LMI_PVCSTAT 7 /* pvc status */ -#define LMI_CCITT_PVCSTAT 0x57 -#define LMI_FULLREP 0 /* full report */ -#define LMI_INTEGRITY 1 /* link integrity report */ -#define LMI_SINGLE 2 /* single pvc report */ +#define FR_UI 0x03 +#define FR_PAD 0x00 + +#define NLPID_IP 0xCC +#define NLPID_IPV6 0x8E +#define NLPID_SNAP 0x80 +#define NLPID_PAD 0x00 +#define NLPID_CCITT_ANSI_LMI 0x08 +#define NLPID_CISCO_LMI 0x09 + + +#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */ +#define LMI_CISCO_DLCI 1023 + +#define LMI_CALLREF 0x00 /* Call Reference */ +#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */ +#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */ +#define LMI_CCITT_REPTYPE 0x51 +#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */ +#define LMI_CCITT_ALIVE 0x53 +#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */ +#define LMI_CCITT_PVCSTAT 0x57 + +#define LMI_FULLREP 0x00 /* full report */ +#define LMI_INTEGRITY 0x01 /* link integrity report */ +#define LMI_SINGLE 0x02 /* single PVC report */ + #define LMI_STATUS_ENQUIRY 0x75 #define LMI_STATUS 0x7D /* reply */ #define LMI_REPT_LEN 1 /* report type element length */ #define LMI_INTEG_LEN 2 /* link integrity element length */ -#define LMI_LENGTH 13 /* standard LMI frame length */ -#define LMI_ANSI_LENGTH 14 +#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */ +#define LMI_ANSI_LENGTH 14 typedef struct { @@ -223,51 +223,34 @@ static inline struct net_device** get_dev_p(pvc_device *pvc, int type) } -static inline u16 status_to_dlci(u8 *status, int *active, int *new) -{ - *new = (status[2] & 0x08) ? 1 : 0; - *active = (status[2] & 0x02) ? 1 : 0; - - return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3); -} - - -static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new) -{ - status[0] = (dlci >> 4) & 0x3F; - status[1] = ((dlci << 3) & 0x78) | 0x80; - status[2] = 0x80; - - if (new) - status[2] |= 0x08; - else if (active) - status[2] |= 0x02; -} - - - static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) { u16 head_len; struct sk_buff *skb = *skb_p; switch (skb->protocol) { - case __constant_ntohs(ETH_P_IP): + case __constant_ntohs(NLPID_CCITT_ANSI_LMI): head_len = 4; skb_push(skb, head_len); - skb->data[3] = NLPID_IP; + skb->data[3] = NLPID_CCITT_ANSI_LMI; break; - case __constant_ntohs(ETH_P_IPV6): + case __constant_ntohs(NLPID_CISCO_LMI): head_len = 4; skb_push(skb, head_len); - skb->data[3] = NLPID_IPV6; + skb->data[3] = NLPID_CISCO_LMI; break; - case __constant_ntohs(LMI_PROTO): + case __constant_ntohs(ETH_P_IP): + head_len = 4; + skb_push(skb, head_len); + skb->data[3] = NLPID_IP; + break; + + case __constant_ntohs(ETH_P_IPV6): head_len = 4; skb_push(skb, head_len); - skb->data[3] = LMI_PROTO; + skb->data[3] = NLPID_IPV6; break; case __constant_ntohs(ETH_P_802_3): @@ -461,13 +444,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) hdlc_device *hdlc = dev_to_hdlc(dev); struct sk_buff *skb; pvc_device *pvc = hdlc->state.fr.first_pvc; - int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH - : LMI_LENGTH; - int stat_len = 3; + int lmi = hdlc->state.fr.settings.lmi; + int dce = hdlc->state.fr.settings.dce; + int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; + int stat_len = (lmi == LMI_CISCO) ? 6 : 3; u8 *data; int i = 0; - if (hdlc->state.fr.settings.dce && fullrep) { + if (dce && fullrep) { len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); if (len > HDLC_MAX_MRU) { printk(KERN_WARNING "%s: Too many PVCs while sending " @@ -484,29 +468,31 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) } memset(skb->data, 0, len); skb_reserve(skb, 4); - skb->protocol = __constant_htons(LMI_PROTO); - fr_hard_header(&skb, LMI_DLCI); + if (lmi == LMI_CISCO) { + skb->protocol = __constant_htons(NLPID_CISCO_LMI); + fr_hard_header(&skb, LMI_CISCO_DLCI); + } else { + skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); + fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); + } data = skb->tail; data[i++] = LMI_CALLREF; - data[i++] = hdlc->state.fr.settings.dce - ? LMI_STATUS : LMI_STATUS_ENQUIRY; - if (hdlc->state.fr.settings.lmi == LMI_ANSI) + data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY; + if (lmi == LMI_ANSI) data[i++] = LMI_ANSI_LOCKSHIFT; - data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_REPTYPE : LMI_REPTYPE; + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : + LMI_ANSI_CISCO_REPTYPE; data[i++] = LMI_REPT_LEN; data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; - - data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_ALIVE : LMI_ALIVE; + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; data[i++] = LMI_INTEG_LEN; data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); data[i++] = hdlc->state.fr.rxseq; - if (hdlc->state.fr.settings.dce && fullrep) { + if (dce && fullrep) { while (pvc) { - data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT; + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : + LMI_ANSI_CISCO_PVCSTAT; data[i++] = stat_len; /* LMI start/restart */ @@ -523,8 +509,20 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) fr_log_dlci_active(pvc); } - dlci_to_status(pvc->dlci, data + i, - pvc->state.active, pvc->state.new); + if (lmi == LMI_CISCO) { + data[i] = pvc->dlci >> 8; + data[i + 1] = pvc->dlci & 0xFF; + } else { + data[i] = (pvc->dlci >> 4) & 0x3F; + data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80; + data[i + 2] = 0x80; + } + + if (pvc->state.new) + data[i + 2] |= 0x08; + else if (pvc->state.active) + data[i + 2] |= 0x02; + i += stat_len; pvc = pvc->next; } @@ -569,6 +567,8 @@ static void fr_set_link_state(int reliable, struct net_device *dev) pvc_carrier(0, pvc); pvc->state.exist = pvc->state.active = 0; pvc->state.new = 0; + if (!hdlc->state.fr.settings.dce) + pvc->state.bandwidth = 0; pvc = pvc->next; } } @@ -583,11 +583,12 @@ static void fr_timer(unsigned long arg) int i, cnt = 0, reliable; u32 list; - if (hdlc->state.fr.settings.dce) + if (hdlc->state.fr.settings.dce) { reliable = hdlc->state.fr.request && time_before(jiffies, hdlc->state.fr.last_poll + hdlc->state.fr.settings.t392 * HZ); - else { + hdlc->state.fr.request = 0; + } else { hdlc->state.fr.last_errors <<= 1; /* Shift the list */ if (hdlc->state.fr.request) { if (hdlc->state.fr.reliable) @@ -634,65 +635,88 @@ static void fr_timer(unsigned long arg) static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) { hdlc_device *hdlc = dev_to_hdlc(dev); - int stat_len; pvc_device *pvc; - int reptype = -1, error, no_ram; u8 rxseq, txseq; - int i; + int lmi = hdlc->state.fr.settings.lmi; + int dce = hdlc->state.fr.settings.dce; + int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; - if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI) - ? LMI_ANSI_LENGTH : LMI_LENGTH)) { + if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : + LMI_CCITT_CISCO_LENGTH)) { printk(KERN_INFO "%s: Short LMI frame\n", dev->name); return 1; } - if (skb->data[5] != (!hdlc->state.fr.settings.dce ? - LMI_STATUS : LMI_STATUS_ENQUIRY)) { - printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n", - dev->name, skb->data[2], - hdlc->state.fr.settings.dce ? "enquiry" : "reply"); + if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : + NLPID_CCITT_ANSI_LMI)) { + printk(KERN_INFO "%s: Received non-LMI frame with LMI" + " DLCI\n", dev->name); + return 1; + } + + if (skb->data[4] != LMI_CALLREF) { + printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", + dev->name, skb->data[4]); + return 1; + } + + if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { + printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", + dev->name, skb->data[5]); return 1; } - i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6; + if (lmi == LMI_ANSI) { + if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { + printk(KERN_INFO "%s: Not ANSI locking shift in LMI" + " message (0x%02X)\n", dev->name, skb->data[6]); + return 1; + } + i = 7; + } else + i = 6; - if (skb->data[i] != - ((hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) { - printk(KERN_INFO "%s: Not a report type=%x\n", + if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : + LMI_ANSI_CISCO_REPTYPE)) { + printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", dev->name, skb->data[i]); return 1; } - i++; - i++; /* Skip length field */ + if (skb->data[++i] != LMI_REPT_LEN) { + printk(KERN_INFO "%s: Invalid LMI Report type IE length" + " (%u)\n", dev->name, skb->data[i]); + return 1; + } - reptype = skb->data[i++]; + reptype = skb->data[++i]; + if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { + printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", + dev->name, reptype); + return 1; + } - if (skb->data[i]!= - ((hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_ALIVE : LMI_ALIVE)) { - printk(KERN_INFO "%s: Unsupported status element=%x\n", - dev->name, skb->data[i]); + if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : + LMI_ANSI_CISCO_ALIVE)) { + printk(KERN_INFO "%s: Not an LMI Link integrity verification" + " IE (0x%02X)\n", dev->name, skb->data[i]); return 1; } - i++; - i++; /* Skip length field */ + if (skb->data[++i] != LMI_INTEG_LEN) { + printk(KERN_INFO "%s: Invalid LMI Link integrity verification" + " IE length (%u)\n", dev->name, skb->data[i]); + return 1; + } + i++; hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ rxseq = skb->data[i++]; /* Should confirm our sequence */ txseq = hdlc->state.fr.txseq; - if (hdlc->state.fr.settings.dce) { - if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) { - printk(KERN_INFO "%s: Unsupported report type=%x\n", - dev->name, reptype); - return 1; - } + if (dce) hdlc->state.fr.last_poll = jiffies; - } error = 0; if (!hdlc->state.fr.reliable) @@ -703,7 +727,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) error = 1; } - if (hdlc->state.fr.settings.dce) { + if (dce) { if (hdlc->state.fr.fullrep_sent && !error) { /* Stop sending full report - the last one has been confirmed by DTE */ hdlc->state.fr.fullrep_sent = 0; @@ -725,6 +749,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) hdlc->state.fr.dce_changed = 0; } + hdlc->state.fr.request = 1; /* got request */ fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); return 0; } @@ -739,7 +764,6 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (reptype != LMI_FULLREP) return 0; - stat_len = 3; pvc = hdlc->state.fr.first_pvc; while (pvc) { @@ -750,24 +774,35 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) no_ram = 0; while (skb->len >= i + 2 + stat_len) { u16 dlci; + u32 bw; unsigned int active, new; - if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT) - ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) { - printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n", - dev->name, skb->data[i]); + if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : + LMI_ANSI_CISCO_PVCSTAT)) { + printk(KERN_INFO "%s: Not an LMI PVC status IE" + " (0x%02X)\n", dev->name, skb->data[i]); return 1; } - i++; - if (skb->data[i] != stat_len) { - printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n", - dev->name, skb->data[i]); + if (skb->data[++i] != stat_len) { + printk(KERN_INFO "%s: Invalid LMI PVC status IE length" + " (%u)\n", dev->name, skb->data[i]); return 1; } i++; - dlci = status_to_dlci(skb->data + i, &active, &new); + new = !! (skb->data[i + 2] & 0x08); + active = !! (skb->data[i + 2] & 0x02); + if (lmi == LMI_CISCO) { + dlci = (skb->data[i] << 8) | skb->data[i + 1]; + bw = (skb->data[i + 3] << 16) | + (skb->data[i + 4] << 8) | + (skb->data[i + 5]); + } else { + dlci = ((skb->data[i] & 0x3F) << 4) | + ((skb->data[i + 1] & 0x78) >> 3); + bw = 0; + } pvc = add_pvc(dev, dlci); @@ -783,9 +818,11 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) pvc->state.deleted = 0; if (active != pvc->state.active || new != pvc->state.new || + bw != pvc->state.bandwidth || !pvc->state.exist) { pvc->state.new = new; pvc->state.active = active; + pvc->state.bandwidth = bw; pvc_carrier(active, pvc); fr_log_dlci_active(pvc); } @@ -801,6 +838,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) pvc_carrier(0, pvc); pvc->state.active = pvc->state.new = 0; pvc->state.exist = 0; + pvc->state.bandwidth = 0; fr_log_dlci_active(pvc); } pvc = pvc->next; @@ -829,22 +867,15 @@ static int fr_rx(struct sk_buff *skb) dlci = q922_to_dlci(skb->data); - if (dlci == LMI_DLCI) { - if (hdlc->state.fr.settings.lmi == LMI_NONE) - goto rx_error; /* LMI packet with no LMI? */ - - if (data[3] == LMI_PROTO) { - if (fr_lmi_recv(ndev, skb)) - goto rx_error; - else { - dev_kfree_skb_any(skb); - return NET_RX_SUCCESS; - } - } - - printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n", - ndev->name); - goto rx_error; + if ((dlci == LMI_CCITT_ANSI_DLCI && + (hdlc->state.fr.settings.lmi == LMI_ANSI || + hdlc->state.fr.settings.lmi == LMI_CCITT)) || + (dlci == LMI_CISCO_DLCI && + hdlc->state.fr.settings.lmi == LMI_CISCO)) { + if (fr_lmi_recv(ndev, skb)) + goto rx_error; + dev_kfree_skb_any(skb); + return NET_RX_SUCCESS; } pvc = find_pvc(hdlc, dlci); @@ -1170,7 +1201,8 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) if ((new_settings.lmi != LMI_NONE && new_settings.lmi != LMI_ANSI && - new_settings.lmi != LMI_CCITT) || + new_settings.lmi != LMI_CCITT && + new_settings.lmi != LMI_CISCO) || new_settings.t391 < 1 || new_settings.t392 < 2 || new_settings.n391 < 1 || diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c index 6ed064cb4469..a63f6a2cc4f7 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc_generic.c @@ -1,7 +1,7 @@ /* * Generic HDLC support routines for Linux * - * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> + * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl> * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -38,7 +38,7 @@ #include <linux/hdlc.h> -static const char* version = "HDLC support module revision 1.17"; +static const char* version = "HDLC support module revision 1.18"; #undef DEBUG_LINK @@ -126,10 +126,13 @@ void hdlc_set_carrier(int on, struct net_device *dev) if (!hdlc->open) goto carrier_exit; - if (hdlc->carrier) + if (hdlc->carrier) { + printk(KERN_INFO "%s: Carrier detected\n", dev->name); __hdlc_set_carrier_on(dev); - else + } else { + printk(KERN_INFO "%s: Carrier lost\n", dev->name); __hdlc_set_carrier_off(dev); + } carrier_exit: spin_unlock_irqrestore(&hdlc->state_lock, flags); @@ -157,8 +160,11 @@ int hdlc_open(struct net_device *dev) spin_lock_irq(&hdlc->state_lock); - if (hdlc->carrier) + if (hdlc->carrier) { + printk(KERN_INFO "%s: Carrier detected\n", dev->name); __hdlc_set_carrier_on(dev); + } else + printk(KERN_INFO "%s: No carrier\n", dev->name); hdlc->open = 1; diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 7cd6195a2e46..b81263eaede0 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -66,8 +66,7 @@ static void ppp_close(struct net_device *dev) -static unsigned short ppp_type_trans(struct sk_buff *skb, - struct net_device *dev) +static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) { return __constant_htons(ETH_P_WAN_PPP); } diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index c41fb70b6929..9456d31cb1c1 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c @@ -24,8 +24,7 @@ #include <linux/hdlc.h> -static unsigned short raw_type_trans(struct sk_buff *skb, - struct net_device *dev) +static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) { return __constant_htons(ETH_P_IP); } diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 15e545f66cd7..2b948ea397d5 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -723,7 +723,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ /* lmc_reset (sc); Why reset??? The link can go down ok */ /* Inform the world that link has been lost */ - dev->flags &= ~IFF_RUNNING; + netif_carrier_off(dev); } /* @@ -736,7 +736,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ /* lmc_reset (sc); Again why reset??? */ /* Inform the world that link protocol is back up. */ - dev->flags |= IFF_RUNNING; + netif_carrier_on(dev); /* Now we have to tell the syncppp that we had an outage * and that it should deal. Calling sppp_reopen here @@ -1168,8 +1168,6 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/ sc->lmc_media->set_link_status (sc, 1); sc->lmc_media->set_status (sc, NULL); - //dev->flags |= IFF_RUNNING; - netif_wake_queue(dev); sc->lmc_txfull = 0; @@ -1233,8 +1231,6 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */ LMC_CSR_WRITE (sc, csr_command, csr6); - dev->flags &= ~IFF_RUNNING; - sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c index 2efccb0554c0..c5f5e62aab8b 100644 --- a/drivers/net/wan/sdla_fr.c +++ b/drivers/net/wan/sdla_fr.c @@ -152,6 +152,7 @@ #include <asm/io.h> /* for inb(), outb(), etc. */ #include <linux/time.h> /* for do_gettimeofday */ #include <linux/in.h> /* sockaddr_in */ +#include <linux/jiffies.h> /* time_after() macro */ #include <asm/errno.h> #include <linux/ip.h> @@ -773,7 +774,7 @@ static int update(struct wan_device* wandev) for(;;) { if(card->u.f.update_comms_stats == 0) break; - if ((jiffies - timeout) > (1 * HZ)){ + if (time_after(jiffies, timeout + 1 * HZ)){ card->u.f.update_comms_stats = 0; return -EAGAIN; } @@ -4799,7 +4800,7 @@ static void trigger_unconfig_fr(struct net_device *dev) { fr_channel_t *chan = dev->priv; volatile sdla_t *card = chan->card; - u32 timeout; + unsigned long timeout; fr508_flags_t* flags = card->flags; int reset_critical=0; @@ -4821,7 +4822,7 @@ static void trigger_unconfig_fr(struct net_device *dev) if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG)) break; - if ((jiffies - timeout) > (1 * HZ)){ + if (time_after(jiffies, timeout + 1 * HZ)){ card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG; printk(KERN_INFO "%s: Failed to delete DLCI %i\n", card->devname,chan->dlci); diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c index 5e3124856eb0..9d6528a50f7b 100644 --- a/drivers/net/wan/sdla_ft1.c +++ b/drivers/net/wan/sdla_ft1.c @@ -29,6 +29,7 @@ #include <linux/wanrouter.h> /* WAN router definitions */ #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ #include <linux/if_arp.h> /* ARPHRD_* defines */ +#include <linux/jiffies.h> /* time_after() macro */ #include <linux/inetdevice.h> #include <asm/uaccess.h> @@ -164,7 +165,7 @@ int wpft1_init (sdla_t* card, wandev_conf_t* conf) timeout = jiffies; while (mb->return_code != 'I') /* Wait 1s for board to initialize */ - if ((jiffies - timeout) > 1*HZ) break; + if (time_after(jiffies, timeout + 1*HZ)) break; if (mb->return_code != 'I') { printk(KERN_INFO diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c index 1761cb68ab48..a4b489cccbbf 100644 --- a/drivers/net/wan/sdla_ppp.c +++ b/drivers/net/wan/sdla_ppp.c @@ -101,6 +101,7 @@ #include <linux/if_arp.h> /* ARPHRD_* defines */ #include <asm/byteorder.h> /* htons(), etc. */ #include <linux/in.h> /* sockaddr_in */ +#include <linux/jiffies.h> /* time_after() macro */ #include <asm/uaccess.h> @@ -482,7 +483,7 @@ static int update(struct wan_device *wandev) if(ppp_priv_area->update_comms_stats == 0){ break; } - if ((jiffies - timeout) > (1 * HZ)){ + if (time_after(jiffies, timeout + 1 * HZ)){ ppp_priv_area->update_comms_stats = 0; ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c index 3a93d2fd4fbf..8a95d61a2f8f 100644 --- a/drivers/net/wan/sdla_x25.c +++ b/drivers/net/wan/sdla_x25.c @@ -91,6 +91,7 @@ #include <linux/wanrouter.h> /* WAN router definitions */ #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ #include <linux/workqueue.h> +#include <linux/jiffies.h> /* time_after() macro */ #include <asm/byteorder.h> /* htons(), etc. */ #include <asm/atomic.h> #include <linux/delay.h> /* Experimental delay */ @@ -867,7 +868,7 @@ static int update(struct wan_device* wandev) if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){ break; } - if ((jiffies-timeout) > 1*HZ){ + if (time_after(jiffies, timeout + 1*HZ)){ card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; return -EAGAIN; } diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c index 6aa6987d96cb..812a1183c502 100644 --- a/drivers/net/wan/wanpipe_multppp.c +++ b/drivers/net/wan/wanpipe_multppp.c @@ -26,6 +26,7 @@ #include <linux/wanrouter.h> /* WAN router definitions */ #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ #include <linux/if_arp.h> /* ARPHRD_* defines */ +#include <linux/jiffies.h> /* time_after() macro */ #include <linux/in.h> /* sockaddr_in */ #include <linux/inet.h> @@ -270,9 +271,9 @@ int wsppp_init (sdla_t* card, wandev_conf_t* conf) ready to accept commands. We expect this to be completed in less than 1 second. */ - timeout = jiffies; + timeout = jiffies + 1 * HZ; while (mb->return_code != 'I') /* Wait 1s for board to initialize */ - if ((jiffies - timeout) > 1*HZ) break; + if (time_after(jiffies, timeout)) break; if (mb->return_code != 'I') { printk(KERN_INFO @@ -493,11 +494,11 @@ static int update(struct wan_device* wandev) chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE; /* wait a maximum of 1 second for the statistics to be updated */ - timeout = jiffies; + timeout = jiffies + 1 * HZ; for(;;) { if(chdlc_priv_area->update_comms_stats == 0) break; - if ((jiffies - timeout) > (1 * HZ)){ + if (time_after(jiffies, timeout)){ chdlc_priv_area->update_comms_stats = 0; chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 1e7b47704ad9..9c1e10602f2b 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -26,6 +26,7 @@ #include <linux/netdevice.h> #include <linux/hdlc.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/delay.h> @@ -624,8 +625,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, /* FIXME when PCI/DMA subsystems are fixed. We set both dma_mask and consistent_dma_mask back to 32 bits to indicate the card can do 32-bit DMA addressing */ - if (pci_set_consistent_dma_mask(pdev, 0xFFFFFFFF) || - pci_set_dma_mask(pdev, 0xFFFFFFFF)) { + if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) || + pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_ERR "wanXL: No usable DMA configuration\n"); wanxl_pci_remove_one(pdev); return -EIO; diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 1c540d825551..bdf672c48182 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -829,7 +829,7 @@ static void __exit exit_x25_asy(void) } kfree(x25_asy_devs); - tty_register_ldisc(N_X25, NULL); + tty_unregister_ldisc(N_X25); } module_init(init_x25_asy); diff --git a/drivers/net/wd.c b/drivers/net/wd.c index 1f05d9bd05e4..b03feae459fc 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -149,12 +149,7 @@ struct net_device * __init wd_probe(int unit) err = do_wd_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -164,6 +159,7 @@ out: static int __init wd_probe1(struct net_device *dev, int ioaddr) { int i; + int err; int checksum = 0; int ancient = 0; /* An old card without config registers. */ int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */ @@ -356,7 +352,10 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) outb(inb(ioaddr+4)|0x80, ioaddr+4); #endif - return 0; + err = register_netdev(dev); + if (err) + free_irq(dev->irq, dev); + return err; } static int @@ -527,11 +526,8 @@ init_module(void) dev->mem_start = mem[this_dev]; dev->mem_end = mem_end[this_dev]; if (do_wd_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_wd[found++] = dev; - continue; - } - cleanup_card(dev); + dev_wd[found++] = dev; + continue; } free_netdev(dev); printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]); diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index fb10a2db63ad..df20adcd0730 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -900,7 +900,7 @@ typedef struct aironet_ioctl { unsigned char __user *data; // d-data } aironet_ioctl; -static char *swversion = "2.1"; +static char swversion[] = "2.1"; #endif /* CISCO_EXT */ #define NUM_MODULES 2 @@ -1209,7 +1209,7 @@ struct airo_info { unsigned char __iomem *pciaux; unsigned char *shared; dma_addr_t shared_dma; - int power; + pm_message_t power; SsidRid *SSID; APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE @@ -2374,7 +2374,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) /* * Clean out tx queue */ - if (test_bit(FLAG_MPI, &ai->flags) && skb_queue_len (&ai->txq) > 0) { + if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) { struct sk_buff *skb = NULL; for (;(skb = skb_dequeue(&ai->txq));) dev_kfree_skb(skb); @@ -2918,7 +2918,7 @@ static int airo_thread(void *data) { flush_signals(current); /* make swsusp happy with our thread */ - try_to_freeze(PF_FREEZE); + try_to_freeze(); if (test_bit(JOB_DIE, &ai->flags)) break; @@ -3287,7 +3287,7 @@ exitrx: if (status & EV_TXEXC) get_tx_error(apriv, -1); spin_lock_irqsave(&apriv->aux_lock, flags); - if (skb_queue_len (&apriv->txq)) { + if (!skb_queue_empty(&apriv->txq)) { spin_unlock_irqrestore(&apriv->aux_lock,flags); mpi_send_packet (dev); } else { @@ -5013,7 +5013,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) { enable_MAC(ai, &rsp, 1); } -inline static u8 hexVal(char c) { +static inline u8 hexVal(char c) { if (c>='0' && c<='9') return c -= '0'; if (c>='a' && c<='f') return c -= 'a'-10; if (c>='A' && c<='F') return c -= 'A'-10; @@ -5499,9 +5499,9 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) cmd.cmd=HOSTSLEEP; issuecommand(ai, &cmd, &rsp); - pci_enable_wake(pdev, state, 1); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); pci_save_state(pdev); - return pci_set_power_state(pdev, state); + return pci_set_power_state(pdev, pci_choose_state(pdev, state)); } static int airo_pci_resume(struct pci_dev *pdev) @@ -5512,7 +5512,7 @@ static int airo_pci_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); - pci_enable_wake(pdev, ai->power, 0); + pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0); if (ai->power > 1) { reset_card(dev, 0); @@ -5541,7 +5541,7 @@ static int airo_pci_resume(struct pci_dev *pdev) } writeConfigRid(ai, 0); enable_MAC(ai, &rsp, 0); - ai->power = 0; + ai->power = PMSG_ON; netif_device_attach(dev); netif_wake_queue(dev); enable_interrupts(ai); diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index fbf53af6cda4..bf25584d68d3 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -33,7 +33,6 @@ #include <linux/timer.h> #include <linux/netdevice.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -210,11 +209,6 @@ static dev_link_t *airo_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &airo_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -559,13 +553,24 @@ static int airo_event(event_t event, int priority, return 0; } /* airo_event */ +static struct pcmcia_device_id airo_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), + PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005), + PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007), + PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, airo_ids); + static struct pcmcia_driver airo_driver = { .owner = THIS_MODULE, .drv = { .name = "airo_cs", }, .attach = airo_attach, + .event = airo_event, .detach = airo_detach, + .id_table = airo_ids, }; static int airo_cs_init(void) diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c index b4f4bd7956a2..9d496703c465 100644 --- a/drivers/net/wireless/airport.c +++ b/drivers/net/wireless/airport.c @@ -184,7 +184,7 @@ static int airport_hard_reset(struct orinoco_private *priv) } static int -airport_attach(struct macio_dev *mdev, const struct of_match *match) +airport_attach(struct macio_dev *mdev, const struct of_device_id *match) { struct orinoco_private *priv; struct net_device *dev; @@ -266,16 +266,16 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); -static struct of_match airport_match[] = +static struct of_device_id airport_match[] = { { .name = "radio", - .type = OF_ANY_MATCH, - .compatible = OF_ANY_MATCH }, {}, }; +MODULE_DEVICE_TABLE (of, airport_match); + static struct macio_driver airport_driver = { .name = DRIVER_NAME, diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c index 4f304c6e693a..0e1ac338cac1 100644 --- a/drivers/net/wireless/arlan-main.c +++ b/drivers/net/wireless/arlan-main.c @@ -33,8 +33,6 @@ static int arlan_EEPROM_bad; #ifdef ARLAN_DEBUGGING -static int arlan_entry_debug; -static int arlan_exit_debug; static int testMemory = testMemoryUNKNOWN; static int irq = irqUNKNOWN; static int txScrambled = 1; @@ -43,15 +41,13 @@ static int mdebug; module_param(irq, int, 0); module_param(mdebug, int, 0); module_param(testMemory, int, 0); -module_param(arlan_entry_debug, int, 0); -module_param(arlan_exit_debug, int, 0); module_param(txScrambled, int, 0); MODULE_PARM_DESC(irq, "(unused)"); MODULE_PARM_DESC(testMemory, "(unused)"); MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)"); #endif -module_param(arlan_debug, int, 0); +module_param_named(debug, arlan_debug, int, 0); module_param(spreadingCode, int, 0); module_param(channelNumber, int, 0); module_param(channelSet, int, 0); @@ -63,17 +59,19 @@ module_param(keyStart, int, 0); module_param(tx_delay_ms, int, 0); module_param(retries, int, 0); module_param(tx_queue_len, int, 0); -module_param(arlan_EEPROM_bad, int, 0); -MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)"); +module_param_named(EEPROM_bad, arlan_EEPROM_bad, int, 0); +MODULE_PARM_DESC(debug, "Arlan debug enable (0-1)"); MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions"); #ifdef ARLAN_ENTRY_EXIT_DEBUGGING -MODULE_PARM_DESC(arlan_entry_debug, "Arlan driver function entry debugging"); -MODULE_PARM_DESC(arlan_exit_debug, "Arlan driver function exit debugging"); -MODULE_PARM_DESC(arlan_entry_and_exit_debug, "Arlan driver function entry and exit debugging"); -#else -MODULE_PARM_DESC(arlan_entry_debug, "(ignored)"); -MODULE_PARM_DESC(arlan_exit_debug, "(ignored)"); -MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)"); +static int arlan_entry_debug; +static int arlan_exit_debug; +static int arlan_entry_and_exit_debug; +module_param_named(entry_debug, arlan_entry_debug, int, 0); +module_param_named(exit_debug, arlan_exit_debug, int, 0); +module_param_named(entry_and_exit_debug, arlan_entry_and_exit_debug, int, 0); +MODULE_PARM_DESC(entry_debug, "Arlan driver function entry debugging"); +MODULE_PARM_DESC(exit_debug, "Arlan driver function exit debugging"); +MODULE_PARM_DESC(entry_and_exit_debug, "Arlan driver function entry and exit debugging"); #endif struct arlan_conf_stru arlan_conf[MAX_ARLANS]; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index a4ed28d9c783..ff031a3985b3 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -43,7 +43,6 @@ #include <linux/moduleparam.h> #include <linux/device.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -218,11 +217,6 @@ static dev_link_t *atmel_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &atmel_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -646,13 +640,36 @@ static int atmel_event(event_t event, int priority, } /* atmel_event */ /*====================================================================*/ +static struct pcmcia_device_id atmel_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620), + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696), + PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302), + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007), + PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9), + PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f), + PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a), + PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f), + PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5), + PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b), + PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6), + PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68), + PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774), + PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377), + PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e), + PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, atmel_ids); + static struct pcmcia_driver atmel_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "atmel_cs", + .owner = THIS_MODULE, + .drv = { + .name = "atmel_cs", }, - .attach = atmel_attach, - .detach = atmel_detach, + .attach = atmel_attach, + .event = atmel_event, + .detach = atmel_detach, + .id_table = atmel_ids, }; static int atmel_cs_init(void) diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 382241e7edbb..5f507c49907b 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -62,7 +62,6 @@ #endif /* WIRELESS_EXT > 12 */ #endif -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -491,11 +490,6 @@ static dev_link_t *netwave_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &netwave_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -1668,13 +1662,21 @@ static int netwave_close(struct net_device *dev) { return 0; } +static struct pcmcia_device_id netwave_ids[] = { + PCMCIA_DEVICE_PROD_ID12("Xircom", "CreditCard Netwave", 0x2e3ee845, 0x54e28a28), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, netwave_ids); + static struct pcmcia_driver netwave_driver = { .owner = THIS_MODULE, .drv = { .name = "netwave_cs", }, .attach = netwave_attach, + .event = netwave_event, .detach = netwave_detach, + .id_table = netwave_ids, }; static int __init init_netwave_cs(void) diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index a3a32430ae9d..aabcdc2be05e 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -46,382 +46,9 @@ * under either the MPL or the GPL. */ /* - * v0.01 -> v0.02 - 21/3/2001 - Jean II - * o Allow to use regular ethX device name instead of dldwdX - * o Warning on IBSS with ESSID=any for firmware 6.06 - * o Put proper range.throughput values (optimistic) - * o IWSPY support (IOCTL and stat gather in Rx path) - * o Allow setting frequency in Ad-Hoc mode - * o Disable WEP setting if !has_wep to work on old firmware - * o Fix txpower range - * o Start adding support for Samsung/Compaq firmware - * - * v0.02 -> v0.03 - 23/3/2001 - Jean II - * o Start adding Symbol support - need to check all that - * o Fix Prism2/Symbol WEP to accept 128 bits keys - * o Add Symbol WEP (add authentication type) - * o Add Prism2/Symbol rate - * o Add PM timeout (holdover duration) - * o Enable "iwconfig eth0 key off" and friends (toggle flags) - * o Enable "iwconfig eth0 power unicast/all" (toggle flags) - * o Try with an Intel card. It report firmware 1.01, behave like - * an antiquated firmware, however on windows it says 2.00. Yuck ! - * o Workaround firmware bug in allocate buffer (Intel 1.01) - * o Finish external renaming to orinoco... - * o Testing with various Wavelan firmwares - * - * v0.03 -> v0.04 - 30/3/2001 - Jean II - * o Update to Wireless 11 -> add retry limit/lifetime support - * o Tested with a D-Link DWL 650 card, fill in firmware support - * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) - * o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-( - * It works on D-Link *only* after a tcpdump. Weird... - * And still doesn't work on Intel card. Grrrr... - * o Update the mode after a setport3 - * o Add preamble setting for Symbol cards (not yet enabled) - * o Don't complain as much about Symbol cards... - * - * v0.04 -> v0.04b - 22/4/2001 - David Gibson - * o Removed the 'eth' parameter - always use ethXX as the - * interface name instead of dldwdXX. The other was racy - * anyway. - * o Clean up RID definitions in hermes.h, other cleanups - * - * v0.04b -> v0.04c - 24/4/2001 - Jean II - * o Tim Hurley <timster AT seiki.bliztech.com> reported a D-Link card - * with vendor 02 and firmware 0.08. Added in the capabilities... - * o Tested Lucent firmware 7.28, everything works... - * - * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt - * o Spin-off Pcmcia code. This file is renamed orinoco.c, - * and orinoco_cs.c now contains only the Pcmcia specific stuff - * o Add Airport driver support on top of orinoco.c (see airport.c) - * - * v0.05 -> v0.05a - 4/5/2001 - Jean II - * o Revert to old Pcmcia code to fix breakage of Ben's changes... - * - * v0.05a -> v0.05b - 4/5/2001 - Jean II - * o add module parameter 'ignore_cis_vcc' for D-Link @ 5V - * o D-Link firmware doesn't support multicast. We just print a few - * error messages, but otherwise everything works... - * o For David : set/getport3 works fine, just upgrade iwpriv... - * - * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt - * o Adapt airport.c to latest changes in orinoco.c - * o Remove deferred power enabling code - * - * v0.05c -> v0.05d - 5/5/2001 - Jean II - * o Workaround to SNAP decapsulate frame from Linksys AP - * original patch from : Dong Liu <dliu AT research.bell-labs.com> - * (note : the memcmp bug was mine - fixed) - * o Remove set_retry stuff, no firmware support it (bloat--). - * - * v0.05d -> v0.06 - 25/5/2001 - Jean II - * Original patch from "Hong Lin" <alin AT redhat.com>, - * "Ian Kinner" <ikinner AT redhat.com> - * and "David Smith" <dsmith AT redhat.com> - * o Init of priv->tx_rate_ctrl in firmware specific section. - * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! - * o Spectrum card always need cor_reset (for every reset) - * o Fix cor_reset to not lose bit 7 in the register - * o flush_stale_links to remove zombie Pcmcia instances - * o Ack previous hermes event before reset - * Me (with my little hands) - * o Allow orinoco.c to call cor_reset via priv->card_reset_handler - * o Add priv->need_card_reset to toggle this feature - * o Fix various buglets when setting WEP in Symbol firmware - * Now, encryption is fully functional on Symbol cards. Youpi ! - * - * v0.06 -> v0.06b - 25/5/2001 - Jean II - * o IBSS on Symbol use port_mode = 4. Please don't ask... - * - * v0.06b -> v0.06c - 29/5/2001 - Jean II - * o Show first spy address in /proc/net/wireless for IBSS mode as well - * - * v0.06c -> v0.06d - 6/7/2001 - David Gibson - * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus' - * wishes to reduce the number of unnecessary messages. - * o Removed bogus message on CRC error. - * o Merged fixes for v0.08 Prism 2 firmware from William Waghorn - * <willwaghorn AT yahoo.co.uk> - * o Slight cleanup/re-arrangement of firmware detection code. - * - * v0.06d -> v0.06e - 1/8/2001 - David Gibson - * o Removed some redundant global initializers (orinoco_cs.c). - * o Added some module metadata - * - * v0.06e -> v0.06f - 14/8/2001 - David Gibson - * o Wording fix to license - * o Added a 'use_alternate_encaps' module parameter for APs which need an - * oui of 00:00:00. We really need a better way of handling this, but - * the module flag is better than nothing for now. - * - * v0.06f -> v0.07 - 20/8/2001 - David Gibson - * o Removed BAP error retries from hermes_bap_seek(). For Tx we now - * let the upper layers handle the retry, we retry explicitly in the - * Rx path, but don't make as much noise about it. - * o Firmware detection cleanups. - * - * v0.07 -> v0.07a - 1/10/3001 - Jean II - * o Add code to read Symbol firmware revision, inspired by latest code - * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee ! - * o Thanks to Jared Valentine <hidden AT xmission.com> for "providing" me - * a 3Com card with a recent firmware, fill out Symbol firmware - * capabilities of latest rev (2.20), as well as older Symbol cards. - * o Disable Power Management in newer Symbol firmware, the API - * has changed (documentation needed). - * - * v0.07a -> v0.08 - 3/10/2001 - David Gibson - * o Fixed a possible buffer overrun found by the Stanford checker (in - * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not - * a big problem. - * o Turned has_big_wep on for Intersil cards. That's not true for all of - * them but we should at least let the capable ones try. - * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I - * realized that my assumption that the driver's serialization - * would prevent the BAP being busy on entry was possibly false, because - * things other than seeks may make the BAP busy. - * o Use "alternate" (oui 00:00:00) encapsulation by default. - * Setting use_old_encaps will mimic the old behaviour, but I think we - * will be able to eliminate this. - * o Don't try to make __initdata const (the version string). This can't - * work because of the way the __initdata sectioning works. - * o Added MODULE_LICENSE tags. - * o Support for PLX (transparent PCMCIA->PCI bridge) cards. - * o Changed to using the new type-fascist min/max. - * - * v0.08 -> v0.08a - 9/10/2001 - David Gibson - * o Inserted some missing acknowledgements/info into the Changelog. - * o Fixed some bugs in the normalization of signal level reporting. - * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware, - * which led to an instant crash on big-endian machines. - * - * v0.08a -> v0.08b - 20/11/2001 - David Gibson - * o Lots of cleanup and bugfixes in orinoco_plx.c - * o Cleanup to handling of Tx rate setting. - * o Removed support for old encapsulation method. - * o Removed old "dldwd" names. - * o Split RID constants into a new file hermes_rid.h - * o Renamed RID constants to match linux-wlan-ng and prism2.o - * o Bugfixes in hermes.c - * o Poke the PLX's INTCSR register, so it actually starts - * generating interrupts. These cards might actually work now. - * o Update to wireless extensions v12 (Jean II) - * o Support for tallies and inquire command (Jean II) - * o Airport updates for newer PPC kernels (BenH) - * - * v0.08b -> v0.09 - 21/12/2001 - David Gibson - * o Some new PCI IDs for PLX cards. - * o Removed broken attempt to do ALLMULTI reception. Just use - * promiscuous mode instead - * o Preliminary work for list-AP (Jean II) - * o Airport updates from (BenH) - * o Eliminated racy hw_ready stuff - * o Fixed generation of fake events in irq handler. This should - * finally kill the EIO problems (Jean II & dgibson) - * o Fixed breakage of bitrate set/get on Agere firmware (Jean II) - * - * v0.09 -> v0.09a - 2/1/2002 - David Gibson - * o Fixed stupid mistake in multicast list handling, triggering - * a BUG() - * - * v0.09a -> v0.09b - 16/1/2002 - David Gibson - * o Fixed even stupider mistake in new interrupt handling, which - * seriously broke things on big-endian machines. - * o Removed a bunch of redundant includes and exports. - * o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c - * o Don't attempt to do hardware level multicast reception on - * Intersil firmware, just go promisc instead. - * o Typo fixed in hermes_issue_cmd() - * o Eliminated WIRELESS_SPY #ifdefs - * o Status code reported on Tx exceptions - * o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC - * interrupts, which should fix the timeouts we're seeing. - * - * v0.09b -> v0.10 - 25 Feb 2002 - David Gibson - * o Removed nested structures used for header parsing, so the - * driver should now work without hackery on ARM - * o Fix for WEP handling on Intersil (Hawk Newton) - * o Eliminated the /proc/hermes/ethXX/regs debugging file. It - * was never very useful. - * o Make Rx errors less noisy. - * - * v0.10 -> v0.11 - 5 Apr 2002 - David Gibson - * o Laid the groundwork in hermes.[ch] for devices which map - * into PCI memory space rather than IO space. - * o Fixed bug in multicast handling (cleared multicast list when - * leaving promiscuous mode). - * o Relegated Tx error messages to debug. - * o Cleaned up / corrected handling of allocation lengths. - * o Set OWNSSID in IBSS mode for WinXP interoperability (jimc). - * o Change to using alloc_etherdev() for structure allocations. - * o Check for and drop undersized packets. - * o Fixed a race in stopping/waking the queue. This should fix - * the timeout problems (Pavel Roskin) - * o Reverted to netif_wake_queue() on the ALLOC event. - * o Fixes for recent Symbol firmwares which lack AP density - * (Pavel Roskin). - * - * v0.11 -> v0.11a - 29 Apr 2002 - David Gibson - * o Handle different register spacing, necessary for Prism 2.5 - * PCI adaptors (Steve Hill). - * o Cleaned up initialization of card structures in orinoco_cs - * and airport. Removed card->priv field. - * o Make response structure optional for hermes_docmd_wait() - * Pavel Roskin) - * o Added PCI id for Nortel emobility to orinoco_plx.c. - * o Cleanup to handling of Symbol's allocation bug. (Pavel Roskin) - * o Cleanups to firmware capability detection. - * o Arrange for orinoco_pci.c to override firmware detection. - * We should be able to support the PCI Intersil cards now. - * o Cleanup handling of reset_cor and hard_reset (Pavel Roskin). - * o Remove erroneous use of USER_BAP in the TxExc handler (Jouni - * Malinen). - * o Makefile changes for better integration into David Hinds - * pcmcia-cs package. - * - * v0.11a -> v0.11b - 1 May 2002 - David Gibson - * o Better error reporting in orinoco_plx_init_one() - * o Fixed multiple bad kfree() bugs introduced by the - * alloc_orinocodev() changes. - * - * v0.11b -> v0.12 - 19 Jun 2002 - David Gibson - * o Support changing the MAC address. - * o Correct display of Intersil firmware revision numbers. - * o Entirely revised locking scheme. Should be both simpler and - * better. - * o Merged some common code in orinoco_plx, orinoco_pci and - * airport by creating orinoco_default_{open,stop,reset}() - * which are used as the dev->open, dev->stop, priv->reset - * callbacks if none are specified when alloc_orinocodev() is - * called. - * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt(). - * They didn't do anything. - * - * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson - * o Some rearrangement of code. - * o Numerous fixups to locking and rest handling, particularly - * for PCMCIA. - * o This allows open and stop net_device methods to be in - * orinoco.c now, rather than in the init modules. - * o In orinoco_cs.c link->priv now points to the struct - * net_device not to the struct orinoco_private. - * o Added a check for undersized SNAP frames, which could cause - * crashes. - * - * v0.12a -> v0.12b - 11 Jul 2002 - David Gibson - * o Fix hw->num_init testing code, so num_init is actually - * incremented. - * o Fix very stupid bug in orinoco_cs which broke compile with - * CONFIG_SMP. - * o Squashed a warning. - * - * v0.12b -> v0.12c - 26 Jul 2002 - David Gibson - * o Change to C9X style designated initializers. - * o Add support for 3Com AirConnect PCI. - * o No longer ignore the hard_reset argument to - * alloc_orinocodev(). Oops. - * - * v0.12c -> v0.13beta1 - 13 Sep 2002 - David Gibson - * o Revert the broken 0.12* locking scheme and go to a new yet - * simpler scheme. - * o Do firmware resets only in orinoco_init() and when waking - * the card from hard sleep. - * - * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson - * o Re-introduced full resets (via schedule_task()) on Tx - * timeout. - * - * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson - * o Minor cleanups to info frame handling. Add basic support - * for linkstatus info frames. - * o Include required kernel headers in orinoco.h, to avoid - * compile problems. - * - * v0.13a -> v0.13b - 10 Feb 2003 - David Gibson - * o Implemented hard reset for Airport cards - * o Experimental suspend/resume implementation for orinoco_pci - * o Abolished /proc debugging support, replaced with a debugging - * iwpriv. Now it's ugly and simple instead of ugly and complex. - * o Bugfix in hermes.c if the firmware returned a record length - * of 0, we could go clobbering memory. - * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable - * was set, which was usually true on PCMCIA hot removes. - * o Track LINKSTATUS messages, silently drop Tx packets before - * we are connected (avoids confusing the firmware), and only - * give LINKSTATUS printk()s if the status has changed. - * - * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson - * o Cleanup: use dev instead of priv in various places. - * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event - * if we're in the middle of a (driver initiated) hard reset. - * o Bug fix: ETH_ZLEN is supposed to include the header - * (Dionysus Blazakis & Manish Karir) - * o Convert to using workqueues instead of taskqueues (and - * backwards compatibility macros for pre 2.5.41 kernels). - * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in - * airport.c - * o New orinoco_tmd.c init module from Joerg Dorchain for - * TMD7160 based PCI to PCMCIA bridges (similar to - * orinoco_plx.c). - * - * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson - * o Make hw_unavailable a counter, rather than just a flag, this - * is necessary to avoid some races (such as a card being - * removed in the middle of orinoco_reset(). - * o Restore Release/RequestConfiguration in the PCMCIA event handler - * when dealing with a driver initiated hard reset. This is - * necessary to prevent hangs due to a spurious interrupt while - * the reset is in progress. - * o Clear the 802.11 header when transmitting, even though we - * don't use it. This fixes a long standing bug on some - * firmwares, which seem to get confused if that isn't done. - * o Be less eager to de-encapsulate SNAP frames, only do so if - * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old - * behaviour broke CDP (Cisco Discovery Protocol). - * o Use dev instead of priv for free_irq() as well as - * request_irq() (oops). - * o Attempt to reset rather than giving up if we get too many - * IRQs. - * o Changed semantics of __orinoco_down() so it can be called - * safely with hw_unavailable set. It also now clears the - * linkstatus (since we're going to have to reassociate). - * - * v0.13d -> v0.13e - 12 May 2003 - David Gibson - * o Support for post-2.5.68 return values from irq handler. - * o Fixed bug where underlength packets would be double counted - * in the rx_dropped statistics. - * o Provided a module parameter to suppress linkstatus messages. - * - * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson - * o Replaced priv->connected logic with netif_carrier_on/off() - * calls. - * o Remove has_ibss_any and never set the CREATEIBSS RID when - * the ESSID is empty. Too many firmwares break if we do. - * o 2.6 merges: Replace pdev->slot_name with pci_name(), remove - * __devinitdata from PCI ID tables, use free_netdev(). - * o Enabled shared-key authentication for Agere firmware (from - * Robert J. Moore <Robert.J.Moore AT allanbank.com> - * o Move netif_wake_queue() (back) to the Tx completion from the - * ALLOC event. This seems to prevent/mitigate the rolling - * error -110 problems at least on some Intersil firmwares. - * Theoretically reduces performance, but I can't measure it. - * Patch from Andrew Tridgell <tridge AT samba.org> - * - * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson - * o Correctly turn off shared-key authentication when requested - * (bugfix from Robert J. Moore). - * o Correct airport sleep interfaces for current 2.6 kernels. - * o Add code for key change without disabling/enabling the MAC - * port. This is supposed to allow 802.1x to work sanely, but - * doesn't seem to yet. - * * TODO - * o New wireless extensions API (patch from Moustafa - * Youssef, updated by Jim Carter and Pavel Roskin). * o Handle de-encapsulation within network layer, provide 802.11 * headers (patch from Thomas 'Dent' Mirlacher) - * o RF monitor mode support * o Fix possible races in SPY handling. * o Disconnect wireless extensions from fundamental configuration. * o (maybe) Software WEP support (patch from Stano Meduna). @@ -462,7 +89,10 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/etherdevice.h> +#include <linux/ethtool.h> #include <linux/wireless.h> +#include <net/iw_handler.h> +#include <net/ieee80211.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -492,6 +122,13 @@ EXPORT_SYMBOL(orinoco_debug); static int suppress_linkstatus; /* = 0 */ module_param(suppress_linkstatus, bool, 0644); MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes"); +static int ignore_disconnect; /* = 0 */ +module_param(ignore_disconnect, int, 0644); +MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); + +static int force_monitor; /* = 0 */ +module_param(force_monitor, int, 0644); +MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); /********************************************************************/ /* Compile time configuration and compatibility stuff */ @@ -508,6 +145,10 @@ MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes"); /* Internal constants */ /********************************************************************/ +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ +static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) + #define ORINOCO_MIN_MTU 256 #define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD) @@ -534,6 +175,11 @@ MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes"); | HERMES_EV_WTERR | HERMES_EV_INFO \ | HERMES_EV_INFDROP ) +#define MAX_RID_LEN 1024 + +static const struct iw_handler_def orinoco_handler_def; +static struct ethtool_ops orinoco_ethtool_ops; + /********************************************************************/ /* Data tables */ /********************************************************************/ @@ -568,26 +214,45 @@ static struct { /* Data types */ /********************************************************************/ -struct header_struct { - /* 802.3 */ - u8 dest[ETH_ALEN]; - u8 src[ETH_ALEN]; - u16 len; - /* 802.2 */ +/* Used in Event handling. + * We avoid nested structres as they break on ARM -- Moustafa */ +struct hermes_tx_descriptor_802_11 { + /* hermes_tx_descriptor */ + u16 status; + u16 reserved1; + u16 reserved2; + u32 sw_support; + u8 retry_count; + u8 tx_rate; + u16 tx_control; + + /* ieee802_11_hdr */ + u16 frame_ctl; + u16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + u16 seq_ctl; + u8 addr4[ETH_ALEN]; + u16 data_len; + + /* ethhdr */ + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short h_proto; /* packet type ID field */ + + /* p8022_hdr */ u8 dsap; u8 ssap; u8 ctrl; - /* SNAP */ u8 oui[3]; + u16 ethertype; } __attribute__ ((packed)); -/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ -u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; - -#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) - +/* Rx frame header except compatibility 802.3 header */ struct hermes_rx_descriptor { + /* Control */ u16 status; u32 time; u8 silence; @@ -595,16 +260,26 @@ struct hermes_rx_descriptor { u8 rate; u8 rxflow; u32 reserved; + + /* 802.11 header */ + u16 frame_ctl; + u16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + u16 seq_ctl; + u8 addr4[ETH_ALEN]; + + /* Data length */ + u16 data_len; } __attribute__ ((packed)); /********************************************************************/ /* Function prototypes */ /********************************************************************/ -static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int __orinoco_program_rids(struct net_device *dev); static void __orinoco_set_multicast_list(struct net_device *dev); -static int orinoco_debug_dump_recs(struct net_device *dev); /********************************************************************/ /* Internal helper functions */ @@ -626,6 +301,10 @@ static inline void set_port_type(struct orinoco_private *priv) priv->createibss = 1; } break; + case IW_MODE_MONITOR: + priv->port_type = 3; + priv->createibss = 0; + break; default: printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", priv->ndev->name); @@ -655,7 +334,7 @@ static int orinoco_open(struct net_device *dev) return err; } -int orinoco_stop(struct net_device *dev) +static int orinoco_stop(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); int err = 0; @@ -686,7 +365,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; struct iw_statistics *wstats = &priv->wstats; - int err = 0; + int err; unsigned long flags; if (! netif_device_present(dev)) { @@ -695,9 +374,21 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) return NULL; /* FIXME: Can we do better than this? */ } + /* If busy, return the old stats. Returning NULL may cause + * the interface to disappear from /proc/net/wireless */ if (orinoco_lock(priv, &flags) != 0) - return NULL; /* FIXME: Erg, we've been signalled, how - * do we propagate this back up? */ + return wstats; + + /* We can't really wait for the tallies inquiry command to + * complete, so we just use the previous results and trigger + * a new tallies inquiry command for next time - Jean II */ + /* FIXME: Really we should wait for the inquiry to come back - + * as it is the stats we give don't make a whole lot of sense. + * Unfortunately, it's not clear how to do that within the + * wireless extensions framework: I think we're in user + * context, but a lock seems to be held by the time we get in + * here so we're not safe to sleep here. */ + hermes_inquire(hw, HERMES_INQ_TALLIES); if (priv->iw_mode == IW_MODE_ADHOC) { memset(&wstats->qual, 0, sizeof(wstats->qual)); @@ -716,25 +407,16 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_COMMSQUALITY, &cq); - - wstats->qual.qual = (int)le16_to_cpu(cq.qual); - wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; - wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; - wstats->qual.updated = 7; + + if (!err) { + wstats->qual.qual = (int)le16_to_cpu(cq.qual); + wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; + wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; + wstats->qual.updated = 7; + } } - /* We can't really wait for the tallies inquiry command to - * complete, so we just use the previous results and trigger - * a new tallies inquiry command for next time - Jean II */ - /* FIXME: We're in user context (I think?), so we should just - wait for the tallies to come through */ - err = hermes_inquire(hw, HERMES_INQ_TALLIES); - orinoco_unlock(priv, &flags); - - if (err) - return NULL; - return wstats; } @@ -809,7 +491,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) return 1; } - if (! netif_carrier_ok(dev)) { + if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ @@ -946,26 +628,55 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); - struct hermes_tx_descriptor desc; + struct hermes_tx_descriptor_802_11 hdr; int err = 0; if (fid == DUMMY_FID) return; /* Nothing's really happened */ - err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); + /* Read the frame header */ + err = hermes_bap_pread(hw, IRQ_BAP, &hdr, + sizeof(struct hermes_tx_descriptor) + + sizeof(struct ieee80211_hdr), + fid, 0); + + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); + stats->tx_errors++; + if (err) { printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " "(FID=%04X error %d)\n", dev->name, fid, err); - } else { - DEBUG(1, "%s: Tx error, status %d\n", - dev->name, le16_to_cpu(desc.status)); + return; } - stats->tx_errors++; + DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, + err, fid); + + /* We produce a TXDROP event only for retry or lifetime + * exceeded, because that's the only status that really mean + * that this particular node went away. + * Other errors means that *we* screwed up. - Jean II */ + hdr.status = le16_to_cpu(hdr.status); + if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { + union iwreq_data wrqu; + + /* Copy 802.11 dest address. + * We use the 802.11 header because the frame may + * not be 802.3 or may be mangled... + * In Ad-Hoc mode, it will be the node address. + * In managed mode, it will be most likely the AP addr + * User space will figure out how to convert it to + * whatever it needs (IP address or else). + * - Jean II */ + memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); + } netif_wake_queue(dev); - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } static void orinoco_tx_timeout(struct net_device *dev) @@ -1042,18 +753,127 @@ static void orinoco_stat_gather(struct net_device *dev, } } +/* + * orinoco_rx_monitor - handle received monitor frames. + * + * Arguments: + * dev network device + * rxfid received FID + * desc rx descriptor of the frame + * + * Call context: interrupt + */ +static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, + struct hermes_rx_descriptor *desc) +{ + u32 hdrlen = 30; /* return full header by default */ + u32 datalen = 0; + u16 fc; + int err; + int len; + struct sk_buff *skb; + struct orinoco_private *priv = netdev_priv(dev); + struct net_device_stats *stats = &priv->stats; + hermes_t *hw = &priv->hw; + + len = le16_to_cpu(desc->data_len); + + /* Determine the size of the header and the data */ + fc = le16_to_cpu(desc->frame_ctl); + switch (fc & IEEE80211_FCTL_FTYPE) { + case IEEE80211_FTYPE_DATA: + if ((fc & IEEE80211_FCTL_TODS) + && (fc & IEEE80211_FCTL_FROMDS)) + hdrlen = 30; + else + hdrlen = 24; + datalen = len; + break; + case IEEE80211_FTYPE_MGMT: + hdrlen = 24; + datalen = len; + break; + case IEEE80211_FTYPE_CTL: + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_PSPOLL: + case IEEE80211_STYPE_RTS: + case IEEE80211_STYPE_CFEND: + case IEEE80211_STYPE_CFENDACK: + hdrlen = 16; + break; + case IEEE80211_STYPE_CTS: + case IEEE80211_STYPE_ACK: + hdrlen = 10; + break; + } + break; + default: + /* Unknown frame type */ + break; + } + + /* sanity check the length */ + if (datalen > IEEE80211_DATA_LEN + 12) { + printk(KERN_DEBUG "%s: oversized monitor frame, " + "data length = %d\n", dev->name, datalen); + err = -EIO; + stats->rx_length_errors++; + goto update_stats; + } + + skb = dev_alloc_skb(hdrlen + datalen); + if (!skb) { + printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", + dev->name); + err = -ENOMEM; + goto drop; + } + + /* Copy the 802.11 header to the skb */ + memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); + skb->mac.raw = skb->data; + + /* If any, copy the data from the card to the skb */ + if (datalen > 0) { + err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), + ALIGN(datalen, 2), rxfid, + HERMES_802_2_OFFSET); + if (err) { + printk(KERN_ERR "%s: error %d reading monitor frame\n", + dev->name, err); + goto drop; + } + } + + skb->dev = dev; + skb->ip_summed = CHECKSUM_NONE; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_802_2); + + dev->last_rx = jiffies; + stats->rx_packets++; + stats->rx_bytes += skb->len; + + netif_rx(skb); + return; + + drop: + dev_kfree_skb_irq(skb); + update_stats: + stats->rx_errors++; + stats->rx_dropped++; +} + static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; - u16 rxfid, status; - int length, data_len, data_off; - char *p; + u16 rxfid, status, fc; + int length; struct hermes_rx_descriptor desc; - struct header_struct hdr; - struct ethhdr *eh; + struct ethhdr *hdr; int err; rxfid = hermes_read_regn(hw, RXFID); @@ -1063,53 +883,46 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + goto update_stats; } status = le16_to_cpu(desc.status); - if (status & HERMES_RXSTAT_ERR) { - if (status & HERMES_RXSTAT_UNDECRYPTABLE) { - wstats->discard.code++; - DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", - dev->name); - } else { - stats->rx_crc_errors++; - DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); - } - stats->rx_errors++; - goto drop; + if (status & HERMES_RXSTAT_BADCRC) { + DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", + dev->name); + stats->rx_crc_errors++; + goto update_stats; } - /* For now we ignore the 802.11 header completely, assuming - that the card's firmware has handled anything vital */ + /* Handle frames in monitor mode */ + if (priv->iw_mode == IW_MODE_MONITOR) { + orinoco_rx_monitor(dev, rxfid, &desc); + return; + } - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), - rxfid, HERMES_802_3_OFFSET); - if (err) { - printk(KERN_ERR "%s: error %d reading frame header. " - "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + if (status & HERMES_RXSTAT_UNDECRYPTABLE) { + DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", + dev->name); + wstats->discard.code++; + goto update_stats; } - length = ntohs(hdr.len); - + length = le16_to_cpu(desc.data_len); + fc = le16_to_cpu(desc.frame_ctl); + /* Sanity checks */ if (length < 3) { /* No for even an 802.2 LLC header */ /* At least on Symbol firmware with PCF we get quite a lot of these legitimately - Poll frames with no data. */ - stats->rx_dropped++; - goto drop; + return; } if (length > IEEE802_11_DATA_LEN) { printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", dev->name, length); stats->rx_length_errors++; - stats->rx_errors++; - goto drop; + goto update_stats; } /* We need space for the packet data itself, plus an ethernet @@ -1121,60 +934,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) if (!skb) { printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", dev->name); - goto drop; + goto update_stats; } - skb_reserve(skb, 2); /* This way the IP header is aligned */ + /* We'll prepend the header, so reserve space for it. The worst + case is no decapsulation, when 802.3 header is prepended and + nothing is removed. 2 is for aligning the IP header. */ + skb_reserve(skb, ETH_HLEN + 2); + + err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), + ALIGN(length, 2), rxfid, + HERMES_802_2_OFFSET); + if (err) { + printk(KERN_ERR "%s: error %d reading frame. " + "Frame dropped.\n", dev->name, err); + goto drop; + } /* Handle decapsulation * In most cases, the firmware tell us about SNAP frames. * For some reason, the SNAP frames sent by LinkSys APs * are not properly recognised by most firmwares. * So, check ourselves */ - if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || - ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || - is_ethersnap(&hdr)) { + if (length >= ENCAPS_OVERHEAD && + (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || + ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || + is_ethersnap(skb->data))) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to the original EthernetII frame. */ - - if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ - stats->rx_length_errors++; - goto drop; - } - - /* Remove SNAP header, reconstruct EthernetII frame */ - data_len = length - ENCAPS_OVERHEAD; - data_off = HERMES_802_3_OFFSET + sizeof(hdr); - - eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); - - memcpy(eh, &hdr, 2 * ETH_ALEN); - eh->h_proto = hdr.ethertype; + hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD); } else { - /* All other cases indicate a genuine 802.3 frame. No - decapsulation needed. We just throw the whole - thing in, and hope the protocol layer can deal with - it as 802.3 */ - data_len = length; - data_off = HERMES_802_3_OFFSET; - /* FIXME: we re-read from the card data we already read here */ - } - - p = skb_put(skb, data_len); - err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2), - rxfid, data_off); - if (err) { - printk(KERN_ERR "%s: error %d reading frame. " - "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + /* 802.3 frame - prepend 802.3 header as is */ + hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); + hdr->h_proto = htons(length); } + memcpy(hdr->h_dest, desc.addr1, ETH_ALEN); + if (fc & IEEE80211_FCTL_FROMDS) + memcpy(hdr->h_source, desc.addr3, ETH_ALEN); + else + memcpy(hdr->h_source, desc.addr2, ETH_ALEN); dev->last_rx = jiffies; skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; + if (fc & IEEE80211_FCTL_TODS) + skb->pkt_type = PACKET_OTHERHOST; /* Process the wireless stats if needed */ orinoco_stat_gather(dev, skb, &desc); @@ -1187,11 +993,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) return; drop: + dev_kfree_skb_irq(skb); + update_stats: + stats->rx_errors++; stats->rx_dropped++; - - if (skb) - dev_kfree_skb_irq(skb); - return; } /********************************************************************/ @@ -1235,6 +1040,99 @@ static void print_linkstatus(struct net_device *dev, u16 status) dev->name, s, status); } +/* Search scan results for requested BSSID, join it if found */ +static void orinoco_join_ap(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + int err; + unsigned long flags; + struct join_req { + u8 bssid[ETH_ALEN]; + u16 channel; + } __attribute__ ((packed)) req; + const int atom_len = offsetof(struct prism2_scan_apinfo, atim); + struct prism2_scan_apinfo *atom; + int offset = 4; + u8 *buf; + u16 len; + + /* Allocate buffer for scan results */ + buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL); + if (! buf) + return; + + if (orinoco_lock(priv, &flags) != 0) + goto out; + + /* Sanity checks in case user changed something in the meantime */ + if (! priv->bssid_fixed) + goto out; + + if (strlen(priv->desired_essid) == 0) + goto out; + + /* Read scan results from the firmware */ + err = hermes_read_ltv(hw, USER_BAP, + HERMES_RID_SCANRESULTSTABLE, + MAX_SCAN_LEN, &len, buf); + if (err) { + printk(KERN_ERR "%s: Cannot read scan results\n", + dev->name); + goto out; + } + + len = HERMES_RECLEN_TO_BYTES(len); + + /* Go through the scan results looking for the channel of the AP + * we were requested to join */ + for (; offset + atom_len <= len; offset += atom_len) { + atom = (struct prism2_scan_apinfo *) (buf + offset); + if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) + goto found; + } + + DEBUG(1, "%s: Requested AP not found in scan results\n", + dev->name); + goto out; + + found: + memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); + req.channel = atom->channel; /* both are little-endian */ + err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, + &req); + if (err) + printk(KERN_ERR "%s: Error issuing join request\n", dev->name); + + out: + kfree(buf); + orinoco_unlock(priv, &flags); +} + +/* Send new BSSID to userspace */ +static void orinoco_send_wevents(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + union iwreq_data wrqu; + int err; + unsigned long flags; + + if (orinoco_lock(priv, &flags) != 0) + return; + + err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, wrqu.ap_addr.sa_data); + if (err != 0) + return; + + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + orinoco_unlock(priv, &flags); +} + static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = netdev_priv(dev); @@ -1275,9 +1173,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) len = sizeof(tallies); } - /* Read directly the data (no seek) */ - hermes_read_words(hw, HERMES_DATA1, (void *) &tallies, - len / 2); /* FIXME: blech! */ + err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len, + infofid, sizeof(info)); + if (err) + break; /* Increment our various counters */ /* wstats->discard.nwid - no wrong BSSID stuff */ @@ -1301,31 +1200,122 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) u16 newstatus; int connected; + if (priv->iw_mode == IW_MODE_MONITOR) + break; + if (len != sizeof(linkstatus)) { printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", dev->name, len); break; } - hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus, - len / 2); + err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, + infofid, sizeof(info)); + if (err) + break; newstatus = le16_to_cpu(linkstatus.linkstatus); + /* Symbol firmware uses "out of range" to signal that + * the hostscan frame can be requested. */ + if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && + priv->firmware_type == FIRMWARE_TYPE_SYMBOL && + priv->has_hostscan && priv->scan_inprogress) { + hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); + break; + } + connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); if (connected) netif_carrier_on(dev); - else + else if (!ignore_disconnect) netif_carrier_off(dev); - if (newstatus != priv->last_linkstatus) + if (newstatus != priv->last_linkstatus) { + priv->last_linkstatus = newstatus; print_linkstatus(dev, newstatus); + /* The info frame contains only one word which is the + * status (see hermes.h). The status is pretty boring + * in itself, that's why we export the new BSSID... + * Jean II */ + schedule_work(&priv->wevent_work); + } + } + break; + case HERMES_INQ_SCAN: + if (!priv->scan_inprogress && priv->bssid_fixed && + priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { + schedule_work(&priv->join_work); + break; + } + /* fall through */ + case HERMES_INQ_HOSTSCAN: + case HERMES_INQ_HOSTSCAN_SYMBOL: { + /* Result of a scanning. Contains information about + * cells in the vicinity - Jean II */ + union iwreq_data wrqu; + unsigned char *buf; + + /* Sanity check */ + if (len > 4096) { + printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", + dev->name, len); + break; + } + + /* We are a strict producer. If the previous scan results + * have not been consumed, we just have to drop this + * frame. We can't remove the previous results ourselves, + * that would be *very* racy... Jean II */ + if (priv->scan_result != NULL) { + printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name); + break; + } + + /* Allocate buffer for results */ + buf = kmalloc(len, GFP_ATOMIC); + if (buf == NULL) + /* No memory, so can't printk()... */ + break; + + /* Read scan data */ + err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, + infofid, sizeof(info)); + if (err) + break; - priv->last_linkstatus = newstatus; +#ifdef ORINOCO_DEBUG + { + int i; + printk(KERN_DEBUG "Scan result [%02X", buf[0]); + for(i = 1; i < (len * 2); i++) + printk(":%02X", buf[i]); + printk("]\n"); + } +#endif /* ORINOCO_DEBUG */ + + /* Allow the clients to access the results */ + priv->scan_len = len; + priv->scan_result = buf; + + /* Send an empty event to user space. + * We don't send the received data on the event because + * it would require us to do complex transcoding, and + * we want to minimise the work done in the irq handler + * Use a request to extract the data - Jean II */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); } break; + case HERMES_INQ_SEC_STAT_AGERE: + /* Security status (Agere specific) */ + /* Ignore this frame for now */ + if (priv->firmware_type == FIRMWARE_TYPE_AGERE) + break; + /* fall through */ default: printk(KERN_DEBUG "%s: Unknown information frame received: " "type 0x%04x, length %d\n", dev->name, type, len); @@ -1350,6 +1340,8 @@ int __orinoco_up(struct net_device *dev) struct hermes *hw = &priv->hw; int err; + netif_carrier_off(dev); /* just to make sure */ + err = __orinoco_program_rids(dev); if (err) { printk(KERN_ERR "%s: Error %d configuring card\n", @@ -1413,7 +1405,7 @@ int orinoco_reinit_firmware(struct net_device *dev) return err; err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err == -EIO) { + if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { /* Try workaround for old Symbol firmware bug */ printk(KERN_WARNING "%s: firmware ALLOC bug detected " "(old Symbol firmware?). Trying to work around... ", @@ -1460,6 +1452,36 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) return err; } +/* Set fixed AP address */ +static int __orinoco_hw_set_wap(struct orinoco_private *priv) +{ + int roaming_flag; + int err = 0; + hermes_t *hw = &priv->hw; + + switch (priv->firmware_type) { + case FIRMWARE_TYPE_AGERE: + /* not supported */ + break; + case FIRMWARE_TYPE_INTERSIL: + if (priv->bssid_fixed) + roaming_flag = 2; + else + roaming_flag = 1; + + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFROAMINGMODE, + roaming_flag); + break; + case FIRMWARE_TYPE_SYMBOL: + err = HERMES_WRITE_RECORD(hw, USER_BAP, + HERMES_RID_CNFMANDATORYBSSID_SYMBOL, + &priv->desired_bssid); + break; + } + return err; +} + /* Change the WEP keys and/or the current keys. Can be called * either from __orinoco_hw_setup_wep() or directly from * orinoco_ioctl_setiwencode(). In the later case the association @@ -1610,17 +1632,15 @@ static int __orinoco_program_rids(struct net_device *dev) return err; } /* Set the channel/frequency */ - if (priv->channel == 0) { - printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name); - if (priv->createibss) - priv->channel = 10; - } - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, - priv->channel); - if (err) { - printk(KERN_ERR "%s: Error %d setting channel\n", - dev->name, err); - return err; + if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFOWNCHANNEL, + priv->channel); + if (err) { + printk(KERN_ERR "%s: Error %d setting channel %d\n", + dev->name, err, priv->channel); + return err; + } } if (priv->has_ibss) { @@ -1647,6 +1667,13 @@ static int __orinoco_program_rids(struct net_device *dev) } } + /* Set the desired BSSID */ + err = __orinoco_hw_set_wap(priv); + if (err) { + printk(KERN_ERR "%s: Error %d setting AP address\n", + dev->name, err); + return err; + } /* Set the desired ESSID */ idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); @@ -1785,6 +1812,20 @@ static int __orinoco_program_rids(struct net_device *dev) } } + if (priv->iw_mode == IW_MODE_MONITOR) { + /* Enable monitor mode */ + dev->type = ARPHRD_IEEE80211; + err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + HERMES_TEST_MONITOR, 0, NULL); + } else { + /* Disable monitor mode */ + dev->type = ARPHRD_ETHER; + err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + HERMES_TEST_STOP, 0, NULL); + } + if (err) + return err; + /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->mc_count = 0; @@ -1861,62 +1902,13 @@ __orinoco_set_multicast_list(struct net_device *dev) dev->flags &= ~IFF_PROMISC; } -static int orinoco_reconfigure(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - unsigned long flags; - int err = 0; - - if (priv->broken_disableport) { - schedule_work(&priv->reset_work); - return 0; - } - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_disable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", - dev->name); - priv->broken_disableport = 1; - goto out; - } - - err = __orinoco_program_rids(dev); - if (err) { - printk(KERN_WARNING "%s: Unable to reconfigure card\n", - dev->name); - goto out; - } - - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", - dev->name); - goto out; - } - - out: - if (err) { - printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); - schedule_work(&priv->reset_work); - err = 0; - } - - orinoco_unlock(priv, &flags); - return err; - -} - /* This must be called from user context, without locks held - use * schedule_work() */ static void orinoco_reset(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; - int err = 0; + int err; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -1938,20 +1930,25 @@ static void orinoco_reset(struct net_device *dev) orinoco_unlock(priv, &flags); - if (priv->hard_reset) + /* Scanning support: Cleanup of driver struct */ + kfree(priv->scan_result); + priv->scan_result = NULL; + priv->scan_inprogress = 0; + + if (priv->hard_reset) { err = (*priv->hard_reset)(priv); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d " - "performing hard reset\n", dev->name, err); - /* FIXME: shutdown of some sort */ - return; + if (err) { + printk(KERN_ERR "%s: orinoco_reset: Error %d " + "performing hard reset\n", dev->name, err); + goto disable; + } } err = orinoco_reinit_firmware(dev); if (err) { printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n", dev->name, err); - return; + goto disable; } spin_lock_irq(&priv->lock); /* This has to be called from user context */ @@ -1972,6 +1969,10 @@ static void orinoco_reset(struct net_device *dev) spin_unlock_irq(&priv->lock); return; + disable: + hermes_set_irqmask(hw, 0); + netif_device_detach(dev); + printk(KERN_ERR "%s: Device has been disabled!\n", dev->name); } /********************************************************************/ @@ -2056,7 +2057,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (events & HERMES_EV_ALLOC) __orinoco_ev_alloc(dev, hw); - hermes_write_regn(hw, EVACK, events); + hermes_write_regn(hw, EVACK, evstat); evstat = hermes_read_regn(hw, EVSTAT); events = evstat & hw->inten; @@ -2172,6 +2173,8 @@ static int determine_firmware(struct net_device *dev) priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ priv->ibss_port = 1; + priv->has_hostscan = (firmver >= 0x8000a); + priv->broken_monitor = (firmver >= 0x80000); /* Tested with Agere firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II @@ -2215,6 +2218,10 @@ static int determine_firmware(struct net_device *dev) firmver >= 0x31000; priv->has_preamble = (firmver >= 0x20000); priv->ibss_port = 4; + priv->broken_disableport = (firmver == 0x25013) || + (firmver >= 0x30000 && firmver <= 0x31000); + priv->has_hostscan = (firmver >= 0x31001) || + (firmver >= 0x29057 && firmver < 0x30000); /* Tested with Intel firmware : 0x20015 => Jean II */ /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ break; @@ -2234,6 +2241,7 @@ static int determine_firmware(struct net_device *dev) priv->has_ibss = (firmver >= 0x000700); /* FIXME */ priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); priv->has_pm = (firmver >= 0x000700); + priv->has_hostscan = (firmver >= 0x010301); if (firmver >= 0x000800) priv->ibss_port = 0; @@ -2267,7 +2275,7 @@ static int orinoco_init(struct net_device *dev) priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN; /* Initialize the firmware */ - err = hermes_init(hw); + err = orinoco_reinit_firmware(dev); if (err != 0) { printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n", dev->name, err); @@ -2400,31 +2408,12 @@ static int orinoco_init(struct net_device *dev) /* By default use IEEE/IBSS ad-hoc mode if we have it */ priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss); set_port_type(priv); - priv->channel = 10; /* default channel, more-or-less arbitrary */ + priv->channel = 0; /* use firmware default */ priv->promiscuous = 0; priv->wep_on = 0; priv->tx_key = 0; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err == -EIO) { - /* Try workaround for old Symbol firmware bug */ - printk(KERN_WARNING "%s: firmware ALLOC bug detected " - "(old Symbol firmware?). Trying to work around... ", - dev->name); - - priv->nicbuf_size = TX_NICBUF_SIZE_BUG; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err) - printk("failed!\n"); - else - printk("ok.\n"); - } - if (err) { - printk("%s: Error %d allocating Tx buffer\n", dev->name, err); - goto out; - } - /* Make the hardware available, as long as it hasn't been * removed elsewhere (e.g. by PCMCIA hot unplug) */ spin_lock_irq(&priv->lock); @@ -2450,7 +2439,7 @@ struct net_device *alloc_orinocodev(int sizeof_card, priv = netdev_priv(dev); priv->ndev = dev; if (sizeof_card) - priv->card = (void *)((unsigned long)netdev_priv(dev) + priv->card = (void *)((unsigned long)priv + sizeof(struct orinoco_private)); else priv->card = NULL; @@ -2461,8 +2450,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, dev->tx_timeout = orinoco_tx_timeout; dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->get_stats = orinoco_get_stats; + dev->ethtool_ops = &orinoco_ethtool_ops; dev->get_wireless_stats = orinoco_get_wireless_stats; - dev->do_ioctl = orinoco_ioctl; + dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; dev->change_mtu = orinoco_change_mtu; dev->set_multicast_list = orinoco_set_multicast_list; /* we use the default eth_mac_addr for setting the MAC addr */ @@ -2478,6 +2468,8 @@ struct net_device *alloc_orinocodev(int sizeof_card, * before anything else touches the * hardware */ INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); + INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); + INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); netif_carrier_off(dev); priv->last_linkstatus = 0xffff; @@ -2488,6 +2480,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, void free_orinocodev(struct net_device *dev) { + struct orinoco_private *priv = netdev_priv(dev); + + kfree(priv->scan_result); free_netdev(dev); } @@ -2495,24 +2490,6 @@ void free_orinocodev(struct net_device *dev) /* Wireless extensions */ /********************************************************************/ -static int orinoco_hw_get_bssid(struct orinoco_private *priv, - char buf[ETH_ALEN]) -{ - hermes_t *hw = &priv->hw; - int err = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, buf); - - orinoco_unlock(priv, &flags); - - return err; -} - static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]) { @@ -2555,6 +2532,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, } len = le16_to_cpu(essidbuf.len); + BUG_ON(len > IW_ESSID_MAX_SIZE); memset(buf, 0, IW_ESSID_MAX_SIZE+1); memcpy(buf, p, len); @@ -2637,140 +2615,271 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, return 0; } -static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) +static int orinoco_ioctl_getname(struct net_device *dev, + struct iw_request_info *info, + char *name, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int err = 0; - int mode; - struct iw_range range; int numrates; - int i, k; + int err; + + err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); + + if (!err && (numrates > 2)) + strcpy(name, "IEEE 802.11b"); + else + strcpy(name, "IEEE 802.11-DS"); + + return 0; +} + +static int orinoco_ioctl_setwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; + static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - TRACE_ENTER(dev->name); + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + /* Enable automatic roaming - no sanity checks are needed */ + if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || + memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { + priv->bssid_fixed = 0; + memset(priv->desired_bssid, 0, ETH_ALEN); + + /* "off" means keep existing connection */ + if (ap_addr->sa_data[0] == 0) { + __orinoco_hw_set_wap(priv); + err = 0; + } + goto out; + } + + if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { + printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " + "support manual roaming\n", + dev->name); + err = -EOPNOTSUPP; + goto out; + } + + if (priv->iw_mode != IW_MODE_INFRA) { + printk(KERN_WARNING "%s: Manual roaming supported only in " + "managed mode\n", dev->name); + err = -EOPNOTSUPP; + goto out; + } + + /* Intersil firmware hangs without Desired ESSID */ + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && + strlen(priv->desired_essid) == 0) { + printk(KERN_WARNING "%s: Desired ESSID must be set for " + "manual roaming\n", dev->name); + err = -EOPNOTSUPP; + goto out; + } + + /* Finally, enable manual roaming */ + priv->bssid_fixed = 1; + memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); + + out: + orinoco_unlock(priv, &flags); + return err; +} - if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) - return -EFAULT; +static int orinoco_ioctl_getwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); - rrq->length = sizeof(range); + hermes_t *hw = &priv->hw; + int err = 0; + unsigned long flags; if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - mode = priv->iw_mode; + ap_addr->sa_family = ARPHRD_ETHER; + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, ap_addr->sa_data); + orinoco_unlock(priv, &flags); - memset(&range, 0, sizeof(range)); + return err; +} - /* Much of this shamelessly taken from wvlan_cs.c. No idea - * what it all means -dgibson */ - range.we_version_compiled = WIRELESS_EXT; - range.we_version_source = 11; +static int orinoco_ioctl_setmode(struct net_device *dev, + struct iw_request_info *info, + u32 *mode, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int err = -EINPROGRESS; /* Call commit handler */ + unsigned long flags; - range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ + if (priv->iw_mode == *mode) + return 0; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + switch (*mode) { + case IW_MODE_ADHOC: + if (!priv->has_ibss && !priv->has_port3) + err = -EOPNOTSUPP; + break; + + case IW_MODE_INFRA: + break; + + case IW_MODE_MONITOR: + if (priv->broken_monitor && !force_monitor) { + printk(KERN_WARNING "%s: Monitor mode support is " + "buggy in this firmware, not enabling\n", + dev->name); + err = -EOPNOTSUPP; + } + break; + + default: + err = -EOPNOTSUPP; + break; + } + + if (err == -EINPROGRESS) { + priv->iw_mode = *mode; + set_port_type(priv); + } + + orinoco_unlock(priv, &flags); + + return err; +} + +static int orinoco_ioctl_getmode(struct net_device *dev, + struct iw_request_info *info, + u32 *mode, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + + *mode = priv->iw_mode; + return 0; +} + +static int orinoco_ioctl_getiwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *rrq, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int err = 0; + struct iw_range *range = (struct iw_range *) extra; + int numrates; + int i, k; + + TRACE_ENTER(dev->name); + + rrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 14; /* Set available channels/frequencies */ - range.num_channels = NUM_CHANNELS; + range->num_channels = NUM_CHANNELS; k = 0; for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { - range.freq[k].i = i + 1; - range.freq[k].m = channel_frequency[i] * 100000; - range.freq[k].e = 1; + range->freq[k].i = i + 1; + range->freq[k].m = channel_frequency[i] * 100000; + range->freq[k].e = 1; k++; } if (k >= IW_MAX_FREQUENCIES) break; } - range.num_frequency = k; + range->num_frequency = k; + range->sensitivity = 3; - range.sensitivity = 3; + if (priv->has_wep) { + range->max_encoding_tokens = ORINOCO_MAX_KEYS; + range->encoding_size[0] = SMALL_KEY_SIZE; + range->num_encoding_sizes = 1; + + if (priv->has_big_wep) { + range->encoding_size[1] = LARGE_KEY_SIZE; + range->num_encoding_sizes = 2; + } + } - if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ + if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ /* Quality stats meaningless in ad-hoc mode */ - range.max_qual.qual = 0; - range.max_qual.level = 0; - range.max_qual.noise = 0; - range.avg_qual.qual = 0; - range.avg_qual.level = 0; - range.avg_qual.noise = 0; } else { - range.max_qual.qual = 0x8b - 0x2f; - range.max_qual.level = 0x2f - 0x95 - 1; - range.max_qual.noise = 0x2f - 0x95 - 1; + range->max_qual.qual = 0x8b - 0x2f; + range->max_qual.level = 0x2f - 0x95 - 1; + range->max_qual.noise = 0x2f - 0x95 - 1; /* Need to get better values */ - range.avg_qual.qual = 0x24; - range.avg_qual.level = 0xC2; - range.avg_qual.noise = 0x9E; + range->avg_qual.qual = 0x24; + range->avg_qual.level = 0xC2; + range->avg_qual.noise = 0x9E; } err = orinoco_hw_get_bitratelist(priv, &numrates, - range.bitrate, IW_MAX_BITRATES); + range->bitrate, IW_MAX_BITRATES); if (err) return err; - range.num_bitrates = numrates; - + range->num_bitrates = numrates; + /* Set an indication of the max TCP throughput in bit/s that we can * expect using this interface. May be use for QoS stuff... * Jean II */ - if(numrates > 2) - range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ + if (numrates > 2) + range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ else - range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ - - range.min_rts = 0; - range.max_rts = 2347; - range.min_frag = 256; - range.max_frag = 2346; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - if (priv->has_wep) { - range.max_encoding_tokens = ORINOCO_MAX_KEYS; - - range.encoding_size[0] = SMALL_KEY_SIZE; - range.num_encoding_sizes = 1; - - if (priv->has_big_wep) { - range.encoding_size[1] = LARGE_KEY_SIZE; - range.num_encoding_sizes = 2; - } - } else { - range.num_encoding_sizes = 0; - range.max_encoding_tokens = 0; - } - orinoco_unlock(priv, &flags); - - range.min_pmp = 0; - range.max_pmp = 65535000; - range.min_pmt = 0; - range.max_pmt = 65535 * 1000; /* ??? */ - range.pmp_flags = IW_POWER_PERIOD; - range.pmt_flags = IW_POWER_TIMEOUT; - range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; - - range.num_txpower = 1; - range.txpower[0] = 15; /* 15dBm */ - range.txpower_capa = IW_TXPOW_DBM; - - range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; - range.retry_flags = IW_RETRY_LIMIT; - range.r_time_flags = IW_RETRY_LIFETIME; - range.min_retry = 0; - range.max_retry = 65535; /* ??? */ - range.min_r_time = 0; - range.max_r_time = 65535 * 1000; /* ??? */ - - if (copy_to_user(rrq->pointer, &range, sizeof(range))) - return -EFAULT; + range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + range->min_pmp = 0; + range->max_pmp = 65535000; + range->min_pmt = 0; + range->max_pmt = 65535 * 1000; /* ??? */ + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; + + range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = IW_RETRY_LIFETIME; + range->min_retry = 0; + range->max_retry = 65535; /* ??? */ + range->min_r_time = 0; + range->max_r_time = 65535 * 1000; /* ??? */ TRACE_EXIT(dev->name); return 0; } -static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) +static int orinoco_ioctl_setiwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, + char *keybuf) { struct orinoco_private *priv = netdev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; @@ -2778,8 +2887,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er int enable = priv->wep_on; int restricted = priv->wep_restrict; u16 xlen = 0; - int err = 0; - char keybuf[ORINOCO_MAX_KEY_SIZE]; + int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; if (! priv->has_wep) @@ -2792,9 +2900,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) return -E2BIG; - - if (copy_from_user(keybuf, erq->pointer, erq->length)) - return -EFAULT; } if (orinoco_lock(priv, &flags) != 0) @@ -2868,12 +2973,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er return err; } -static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) +static int orinoco_ioctl_getiwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, + char *keybuf) { struct orinoco_private *priv = netdev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; u16 xlen = 0; - char keybuf[ORINOCO_MAX_KEY_SIZE]; unsigned long flags; if (! priv->has_wep) @@ -2902,50 +3009,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); orinoco_unlock(priv, &flags); - - if (erq->pointer) { - if (copy_to_user(erq->pointer, keybuf, xlen)) - return -EFAULT; - } - return 0; } -static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) +static int orinoco_ioctl_setessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, + char *essidbuf) { struct orinoco_private *priv = netdev_priv(dev); - char essidbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it * anyway... - Jean II */ - memset(&essidbuf, 0, sizeof(essidbuf)); - - if (erq->flags) { - if (erq->length > IW_ESSID_MAX_SIZE) - return -E2BIG; - - if (copy_from_user(&essidbuf, erq->pointer, erq->length)) - return -EFAULT; - - essidbuf[erq->length] = '\0'; - } + /* Hum... Should not use Wireless Extension constant (may change), + * should use our own... - Jean II */ + if (erq->length > IW_ESSID_MAX_SIZE) + return -E2BIG; if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); + /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ + memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); + + /* If not ANY, get the new ESSID */ + if (erq->flags) { + memcpy(priv->desired_essid, essidbuf, erq->length); + } orinoco_unlock(priv, &flags); - return 0; + return -EINPROGRESS; /* Call commit handler */ } -static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) +static int orinoco_ioctl_getessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, + char *essidbuf) { struct orinoco_private *priv = netdev_priv(dev); - char essidbuf[IW_ESSID_MAX_SIZE+1]; int active; int err = 0; unsigned long flags; @@ -2959,51 +3063,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) } else { if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); + memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); orinoco_unlock(priv, &flags); } erq->flags = 1; erq->length = strlen(essidbuf) + 1; - if (erq->pointer) - if (copy_to_user(erq->pointer, essidbuf, erq->length)) - return -EFAULT; TRACE_EXIT(dev->name); return 0; } -static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) +static int orinoco_ioctl_setnick(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *nrq, + char *nickbuf) { struct orinoco_private *priv = netdev_priv(dev); - char nickbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; if (nrq->length > IW_ESSID_MAX_SIZE) return -E2BIG; - memset(nickbuf, 0, sizeof(nickbuf)); - - if (copy_from_user(nickbuf, nrq->pointer, nrq->length)) - return -EFAULT; - - nickbuf[nrq->length] = '\0'; - if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(priv->nick, nickbuf, sizeof(priv->nick)); + memset(priv->nick, 0, sizeof(priv->nick)); + memcpy(priv->nick, nickbuf, nrq->length); orinoco_unlock(priv, &flags); - return 0; + return -EINPROGRESS; /* Call commit handler */ } -static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) +static int orinoco_ioctl_getnick(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *nrq, + char *nickbuf) { struct orinoco_private *priv = netdev_priv(dev); - char nickbuf[IW_ESSID_MAX_SIZE+1]; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3014,23 +3113,22 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) nrq->length = strlen(nickbuf)+1; - if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf))) - return -EFAULT; - return 0; } -static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) +static int orinoco_ioctl_setfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *frq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); int chan = -1; unsigned long flags; + int err = -EINPROGRESS; /* Call commit handler */ - /* We can only use this in Ad-Hoc demo mode to set the operating - * frequency, or in IBSS mode to set the frequency where the IBSS - * will be created - Jean II */ - if (priv->iw_mode != IW_MODE_ADHOC) - return -EOPNOTSUPP; + /* In infrastructure mode the AP sets the channel */ + if (priv->iw_mode == IW_MODE_INFRA) + return -EBUSY; if ( (frq->e == 0) && (frq->m <= 1000) ) { /* Setting by channel number */ @@ -3054,13 +3152,44 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) if (orinoco_lock(priv, &flags) != 0) return -EBUSY; + priv->channel = chan; + if (priv->iw_mode == IW_MODE_MONITOR) { + /* Fast channel change - no commit if successful */ + hermes_t *hw = &priv->hw; + err = hermes_docmd_wait(hw, HERMES_CMD_TEST | + HERMES_TEST_SET_CHANNEL, + chan, NULL); + } orinoco_unlock(priv, &flags); + return err; +} + +static int orinoco_ioctl_getfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *frq, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int tmp; + + /* Locking done in there */ + tmp = orinoco_hw_get_freq(priv); + if (tmp < 0) { + return tmp; + } + + frq->m = tmp; + frq->e = 1; + return 0; } -static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) +static int orinoco_ioctl_getsens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *srq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3086,7 +3215,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) return 0; } -static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) +static int orinoco_ioctl_setsens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *srq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); int val = srq->value; @@ -3103,10 +3235,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) priv->ap_density = val; orinoco_unlock(priv, &flags); - return 0; + return -EINPROGRESS; /* Call commit handler */ } -static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) +static int orinoco_ioctl_setrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rrq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); int val = rrq->value; @@ -3124,13 +3259,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) priv->rts_thresh = val; orinoco_unlock(priv, &flags); + return -EINPROGRESS; /* Call commit handler */ +} + +static int orinoco_ioctl_getrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rrq, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + + rrq->value = priv->rts_thresh; + rrq->disabled = (rrq->value == 2347); + rrq->fixed = 1; + return 0; } -static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) +static int orinoco_ioctl_setfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int err = 0; + int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3162,11 +3314,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) return err; } -static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) +static int orinoco_ioctl_getfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; - int err = 0; + int err; u16 val; unsigned long flags; @@ -3199,10 +3354,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) return err; } -static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) +static int orinoco_ioctl_setrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rrq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int err = 0; int ratemode = -1; int bitrate; /* 100s of kilobits */ int i; @@ -3238,10 +3395,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) priv->bitratemode = ratemode; orinoco_unlock(priv, &flags); - return err; + return -EINPROGRESS; } -static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) +static int orinoco_ioctl_getrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rrq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3306,10 +3466,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) return err; } -static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) +static int orinoco_ioctl_setpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *prq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int err = 0; + int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3358,7 +3521,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) return err; } -static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) +static int orinoco_ioctl_getpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *prq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3406,7 +3572,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) return err; } -static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) +static int orinoco_ioctl_getretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rrq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -3457,10 +3626,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) return err; } -static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) +static int orinoco_ioctl_reset(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + + if (! capable(CAP_NET_ADMIN)) + return -EPERM; + + if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { + printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); + + /* Firmware reset */ + orinoco_reset(dev); + } else { + printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); + + schedule_work(&priv->reset_work); + } + + return 0; +} + +static int orinoco_ioctl_setibssport(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) + { struct orinoco_private *priv = netdev_priv(dev); - int val = *( (int *) wrq->u.name ); + int val = *( (int *) extra ); unsigned long flags; if (orinoco_lock(priv, &flags) != 0) @@ -3472,28 +3669,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) set_port_type(priv); orinoco_unlock(priv, &flags); - return 0; + return -EINPROGRESS; /* Call commit handler */ } -static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) +static int orinoco_ioctl_getibssport(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int *val = (int *)wrq->u.name; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; + int *val = (int *) extra; *val = priv->ibss_port; - orinoco_unlock(priv, &flags); - return 0; } -static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) +static int orinoco_ioctl_setport3(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int val = *( (int *) wrq->u.name ); + int val = *( (int *) extra ); int err = 0; unsigned long flags; @@ -3522,51 +3719,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) err = -EINVAL; } - if (! err) + if (! err) { /* Actually update the mode we are using */ set_port_type(priv); + err = -EINPROGRESS; + } orinoco_unlock(priv, &flags); return err; } -static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) +static int orinoco_ioctl_getport3(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int *val = (int *) extra; + + *val = priv->prefer_port3; + return 0; +} + +static int orinoco_ioctl_setpreamble(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - int *val = (int *)wrq->u.name; unsigned long flags; + int val; + + if (! priv->has_preamble) + return -EOPNOTSUPP; + + /* 802.11b has recently defined some short preamble. + * Basically, the Phy header has been reduced in size. + * This increase performance, especially at high rates + * (the preamble is transmitted at 1Mb/s), unfortunately + * this give compatibility troubles... - Jean II */ + val = *( (int *) extra ); if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - *val = priv->prefer_port3; + if (val) + priv->preamble = 1; + else + priv->preamble = 0; + orinoco_unlock(priv, &flags); + + return -EINPROGRESS; /* Call commit handler */ +} + +static int orinoco_ioctl_getpreamble(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int *val = (int *) extra; + + if (! priv->has_preamble) + return -EOPNOTSUPP; + + *val = priv->preamble; return 0; } +/* ioctl interface to hermes_read_ltv() + * To use with iwpriv, pass the RID as the token argument, e.g. + * iwpriv get_rid [0xfc00] + * At least Wireless Tools 25 is required to use iwpriv. + * For Wireless Tools 25 and 26 append "dummy" are the end. */ +static int orinoco_ioctl_getrid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + hermes_t *hw = &priv->hw; + int rid = data->flags; + u16 length; + int err; + unsigned long flags; + + /* It's a "get" function, but we don't want users to access the + * WEP key and other raw firmware data */ + if (! capable(CAP_NET_ADMIN)) + return -EPERM; + + if (rid < 0xfc00 || rid > 0xffff) + return -EINVAL; + + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; + + err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, + extra); + if (err) + goto out; + + data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), + MAX_RID_LEN); + + out: + orinoco_unlock(priv, &flags); + return err; +} + /* Spy is used for link quality/strength measurements in Ad-Hoc mode * Jean II */ -static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) +static int orinoco_ioctl_setspy(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *srq, + char *extra) + { struct orinoco_private *priv = netdev_priv(dev); - struct sockaddr address[IW_MAX_SPY]; + struct sockaddr *address = (struct sockaddr *) extra; int number = srq->length; int i; - int err = 0; unsigned long flags; - /* Check the number of addresses */ - if (number > IW_MAX_SPY) - return -E2BIG; - - /* Get the data in the driver */ - if (srq->pointer) { - if (copy_from_user(address, srq->pointer, - sizeof(struct sockaddr) * number)) - return -EFAULT; - } - /* Make sure nobody mess with the structure while we do */ if (orinoco_lock(priv, &flags) != 0) return -EBUSY; @@ -3590,14 +3867,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) /* Now, let the others play */ orinoco_unlock(priv, &flags); - return err; + /* Do NOT call commit handler */ + return 0; } -static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) +static int orinoco_ioctl_getspy(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *srq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - struct sockaddr address[IW_MAX_SPY]; - struct iw_quality spy_stat[IW_MAX_SPY]; + struct sockaddr *address = (struct sockaddr *) extra; int number; int i; unsigned long flags; @@ -3606,7 +3886,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) return -EBUSY; number = priv->spy_number; - if ((number > 0) && (srq->pointer)) { + /* Create address struct */ + for (i = 0; i < number; i++) { + memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); + address[i].sa_family = AF_UNIX; + } + if (number > 0) { /* Create address struct */ for (i = 0; i < number; i++) { memcpy(address[i].sa_data, priv->spy_address[i], @@ -3617,535 +3902,504 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) /* In theory, we should disable irqs while copying the stats * because the rx path might update it in the middle... * Bah, who care ? - Jean II */ - memcpy(&spy_stat, priv->spy_stat, - sizeof(struct iw_quality) * IW_MAX_SPY); - for (i=0; i < number; i++) - priv->spy_stat[i].updated = 0; + memcpy(extra + (sizeof(struct sockaddr) * number), + priv->spy_stat, sizeof(struct iw_quality) * number); } + /* Reset updated flags. */ + for (i = 0; i < number; i++) + priv->spy_stat[i].updated = 0; orinoco_unlock(priv, &flags); - /* Push stuff to user space */ srq->length = number; - if(copy_to_user(srq->pointer, address, - sizeof(struct sockaddr) * number)) - return -EFAULT; - if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number), - &spy_stat, sizeof(struct iw_quality) * number)) - return -EFAULT; return 0; } -static int -orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +/* Trigger a scan (look for other cells in the vicinity */ +static int orinoco_ioctl_setscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *srq, + char *extra) { struct orinoco_private *priv = netdev_priv(dev); - struct iwreq *wrq = (struct iwreq *)rq; + hermes_t *hw = &priv->hw; int err = 0; - int tmp; - int changed = 0; unsigned long flags; - TRACE_ENTER(dev->name); - - /* In theory, we could allow most of the the SET stuff to be - * done. In practice, the lapse of time at startup when the - * card is not ready is very short, so why bother... Note - * that netif_device_present is different from up/down - * (ifconfig), when the device is not yet up, it is usually - * already ready... Jean II */ - if (! netif_device_present(dev)) - return -ENODEV; + /* Note : you may have realised that, as this is a SET operation, + * this is priviledged and therefore a normal user can't + * perform scanning. + * This is not an error, while the device perform scanning, + * traffic doesn't flow, so it's a perfect DoS... + * Jean II */ - switch (cmd) { - case SIOCGIWNAME: - strcpy(wrq->u.name, "IEEE 802.11-DS"); - break; - - case SIOCGIWAP: - wrq->u.ap_addr.sa_family = ARPHRD_ETHER; - err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data); - break; + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; - case SIOCGIWRANGE: - err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); - break; + /* Scanning with port 0 disabled would fail */ + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } - case SIOCSIWMODE: - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - switch (wrq->u.mode) { - case IW_MODE_ADHOC: - if (! (priv->has_ibss || priv->has_port3) ) - err = -EINVAL; - else { - priv->iw_mode = IW_MODE_ADHOC; - changed = 1; - } - break; + /* In monitor mode, the scan results are always empty. + * Probe responses are passed to the driver as received + * frames and could be processed in software. */ + if (priv->iw_mode == IW_MODE_MONITOR) { + err = -EOPNOTSUPP; + goto out; + } - case IW_MODE_INFRA: - priv->iw_mode = IW_MODE_INFRA; - changed = 1; - break; + /* Note : because we don't lock out the irq handler, the way + * we access scan variables in priv is critical. + * o scan_inprogress : not touched by irq handler + * o scan_mode : not touched by irq handler + * o scan_result : irq is strict producer, non-irq is strict + * consumer. + * o scan_len : synchronised with scan_result + * Before modifying anything on those variables, please think hard ! + * Jean II */ - default: - err = -EINVAL; - break; - } - set_port_type(priv); - orinoco_unlock(priv, &flags); - break; + /* If there is still some left-over scan results, get rid of it */ + if (priv->scan_result != NULL) { + /* What's likely is that a client did crash or was killed + * between triggering the scan request and reading the + * results, so we need to reset everything. + * Some clients that are too slow may suffer from that... + * Jean II */ + kfree(priv->scan_result); + priv->scan_result = NULL; + } - case SIOCGIWMODE: - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - wrq->u.mode = priv->iw_mode; - orinoco_unlock(priv, &flags); - break; + /* Save flags */ + priv->scan_mode = srq->flags; - case SIOCSIWENCODE: - err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); - if (! err) - changed = 1; - break; + /* Always trigger scanning, even if it's in progress. + * This way, if the info frame get lost, we will recover somewhat + * gracefully - Jean II */ - case SIOCGIWENCODE: - if (! capable(CAP_NET_ADMIN)) { - err = -EPERM; + if (priv->has_hostscan) { + switch (priv->firmware_type) { + case FIRMWARE_TYPE_SYMBOL: + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFHOSTSCAN_SYMBOL, + HERMES_HOSTSCAN_SYMBOL_ONCE | + HERMES_HOSTSCAN_SYMBOL_BCAST); break; + case FIRMWARE_TYPE_INTERSIL: { + u16 req[3]; + + req[0] = cpu_to_le16(0x3fff); /* All channels */ + req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ + req[2] = 0; /* Any ESSID */ + err = HERMES_WRITE_RECORD(hw, USER_BAP, + HERMES_RID_CNFHOSTSCAN, &req); } - - err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); - break; - - case SIOCSIWESSID: - err = orinoco_ioctl_setessid(dev, &wrq->u.essid); - if (! err) - changed = 1; - break; - - case SIOCGIWESSID: - err = orinoco_ioctl_getessid(dev, &wrq->u.essid); - break; - - case SIOCSIWNICKN: - err = orinoco_ioctl_setnick(dev, &wrq->u.data); - if (! err) - changed = 1; - break; - - case SIOCGIWNICKN: - err = orinoco_ioctl_getnick(dev, &wrq->u.data); break; + case FIRMWARE_TYPE_AGERE: + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFSCANSSID_AGERE, + 0); /* Any ESSID */ + if (err) + break; - case SIOCGIWFREQ: - tmp = orinoco_hw_get_freq(priv); - if (tmp < 0) { - err = tmp; - } else { - wrq->u.freq.m = tmp; - wrq->u.freq.e = 1; + err = hermes_inquire(hw, HERMES_INQ_SCAN); + break; } - break; - - case SIOCSIWFREQ: - err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); - if (! err) - changed = 1; - break; - - case SIOCGIWSENS: - err = orinoco_ioctl_getsens(dev, &wrq->u.sens); - break; - - case SIOCSIWSENS: - err = orinoco_ioctl_setsens(dev, &wrq->u.sens); - if (! err) - changed = 1; - break; - - case SIOCGIWRTS: - wrq->u.rts.value = priv->rts_thresh; - wrq->u.rts.disabled = (wrq->u.rts.value == 2347); - wrq->u.rts.fixed = 1; - break; - - case SIOCSIWRTS: - err = orinoco_ioctl_setrts(dev, &wrq->u.rts); - if (! err) - changed = 1; - break; - - case SIOCSIWFRAG: - err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); - if (! err) - changed = 1; - break; - - case SIOCGIWFRAG: - err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); - break; + } else + err = hermes_inquire(hw, HERMES_INQ_SCAN); - case SIOCSIWRATE: - err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); - if (! err) - changed = 1; - break; - - case SIOCGIWRATE: - err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); - break; - - case SIOCSIWPOWER: - err = orinoco_ioctl_setpower(dev, &wrq->u.power); - if (! err) - changed = 1; - break; + /* One more client */ + if (! err) + priv->scan_inprogress = 1; - case SIOCGIWPOWER: - err = orinoco_ioctl_getpower(dev, &wrq->u.power); - break; + out: + orinoco_unlock(priv, &flags); + return err; +} - case SIOCGIWTXPOW: - /* The card only supports one tx power, so this is easy */ - wrq->u.txpower.value = 15; /* dBm */ - wrq->u.txpower.fixed = 1; - wrq->u.txpower.disabled = 0; - wrq->u.txpower.flags = IW_TXPOW_DBM; - break; +/* Translate scan data returned from the card to a card independant + * format that the Wireless Tools will understand - Jean II */ +static inline int orinoco_translate_scan(struct net_device *dev, + char *buffer, + char *scan, + int scan_len) +{ + struct orinoco_private *priv = netdev_priv(dev); + int offset; /* In the scan data */ + union hermes_scan_info *atom; + int atom_len; + u16 capabilities; + u16 channel; + struct iw_event iwe; /* Temporary buffer */ + char * current_ev = buffer; + char * end_buf = buffer + IW_SCAN_MAX_DATA; - case SIOCSIWRETRY: - err = -EOPNOTSUPP; + switch (priv->firmware_type) { + case FIRMWARE_TYPE_AGERE: + atom_len = sizeof(struct agere_scan_apinfo); + offset = 0; break; - - case SIOCGIWRETRY: - err = orinoco_ioctl_getretry(dev, &wrq->u.retry); + case FIRMWARE_TYPE_SYMBOL: + /* Lack of documentation necessitates this hack. + * Different firmwares have 68 or 76 byte long atoms. + * We try modulo first. If the length divides by both, + * we check what would be the channel in the second + * frame for a 68-byte atom. 76-byte atoms have 0 there. + * Valid channel cannot be 0. */ + if (scan_len % 76) + atom_len = 68; + else if (scan_len % 68) + atom_len = 76; + else if (scan_len >= 1292 && scan[68] == 0) + atom_len = 76; + else + atom_len = 68; + offset = 0; break; - - case SIOCSIWSPY: - err = orinoco_ioctl_setspy(dev, &wrq->u.data); + case FIRMWARE_TYPE_INTERSIL: + offset = 4; + if (priv->has_hostscan) + atom_len = scan[0] + (scan[1] << 8); + else + atom_len = offsetof(struct prism2_scan_apinfo, atim); break; + default: + return 0; + } - case SIOCGIWSPY: - err = orinoco_ioctl_getspy(dev, &wrq->u.data); - break; + /* Check that we got an whole number of atoms */ + if ((scan_len - offset) % atom_len) { + printk(KERN_ERR "%s: Unexpected scan data length %d, " + "atom_len %d, offset %d\n", dev->name, scan_len, + atom_len, offset); + return 0; + } - case SIOCGIWPRIV: - if (wrq->u.data.pointer) { - struct iw_priv_args privtab[] = { - { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, - { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, - { SIOCIWFIRSTPRIV + 0x2, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_port3" }, - { SIOCIWFIRSTPRIV + 0x3, 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_port3" }, - { SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_preamble" }, - { SIOCIWFIRSTPRIV + 0x5, 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_preamble" }, - { SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_ibssport" }, - { SIOCIWFIRSTPRIV + 0x7, 0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_ibssport" }, - { SIOCIWLASTPRIV, 0, 0, "dump_recs" }, - }; - - wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); - if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) - err = -EFAULT; + /* Read the entries one by one */ + for (; offset + atom_len <= scan_len; offset += atom_len) { + /* Get next atom */ + atom = (union hermes_scan_info *) (scan + offset); + + /* First entry *MUST* be the AP MAC address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* Other entries will be displayed in the order we give them */ + + /* Add the ESSID */ + iwe.u.data.length = le16_to_cpu(atom->a.essid_len); + if (iwe.u.data.length > 32) + iwe.u.data.length = 32; + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); + + /* Add mode */ + iwe.cmd = SIOCGIWMODE; + capabilities = le16_to_cpu(atom->a.capabilities); + if (capabilities & 0x3) { + if (capabilities & 0x1) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); } - break; - - case SIOCIWFIRSTPRIV + 0x0: /* force_reset */ - case SIOCIWFIRSTPRIV + 0x1: /* card_reset */ - if (! capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; + + channel = atom->s.channel; + if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) { + /* Add frequency */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = channel_frequency[channel-1] * 100000; + iwe.u.freq.e = 1; + current_ev = iwe_stream_add_event(current_ev, end_buf, + &iwe, IW_EV_FREQ_LEN); } - - printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - schedule_work(&priv->reset_work); - break; + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.updated = 0x10; /* no link quality */ + iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95; + iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95; + /* Wireless tools prior to 27.pre22 will show link quality + * anyway, so we provide a reasonable value. */ + if (iwe.u.qual.level > iwe.u.qual.noise) + iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; + else + iwe.u.qual.qual = 0; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); - case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ - if (! capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if (capabilities & 0x10) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid); + + /* Bit rate is not available in Lucent/Agere firmwares */ + if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { + char * current_val = current_ev + IW_EV_LCP_LEN; + int i; + int step; + + if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) + step = 2; + else + step = 1; + + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + /* Max 10 values */ + for (i = 0; i < 10; i += step) { + /* NULL terminated */ + if (atom->p.rates[i] == 0x0) + break; + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000); + current_val = iwe_stream_add_value(current_ev, current_val, + end_buf, &iwe, + IW_EV_PARAM_LEN); + } + /* Check if we added any event */ + if ((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; } - err = orinoco_ioctl_setport3(dev, wrq); - if (! err) - changed = 1; - break; + /* The other data in the scan result are not really + * interesting, so for now drop it - Jean II */ + } + return current_ev - buffer; +} - case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ - err = orinoco_ioctl_getport3(dev, wrq); - break; +/* Return results of a scan */ +static int orinoco_ioctl_getscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *srq, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + int err = 0; + unsigned long flags; - case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ - if (! capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; - } + if (orinoco_lock(priv, &flags) != 0) + return -EBUSY; - /* 802.11b has recently defined some short preamble. - * Basically, the Phy header has been reduced in size. - * This increase performance, especially at high rates - * (the preamble is transmitted at 1Mb/s), unfortunately - * this give compatibility troubles... - Jean II */ - if(priv->has_preamble) { - int val = *( (int *) wrq->u.name ); - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - if (val) - priv->preamble = 1; - else - priv->preamble = 0; - orinoco_unlock(priv, &flags); - changed = 1; - } else - err = -EOPNOTSUPP; - break; + /* If no results yet, ask to try again later */ + if (priv->scan_result == NULL) { + if (priv->scan_inprogress) + /* Important note : we don't want to block the caller + * until results are ready for various reasons. + * First, managing wait queues is complex and racy. + * Second, we grab some rtnetlink lock before comming + * here (in dev_ioctl()). + * Third, we generate an Wireless Event, so the + * caller can wait itself on that - Jean II */ + err = -EAGAIN; + else + /* Client error, no scan results... + * The caller need to restart the scan. */ + err = -ENODATA; + } else { + /* We have some results to push back to user space */ + + /* Translate to WE format */ + srq->length = orinoco_translate_scan(dev, extra, + priv->scan_result, + priv->scan_len); + + /* Return flags */ + srq->flags = (__u16) priv->scan_mode; + + /* Results are here, so scan no longer in progress */ + priv->scan_inprogress = 0; + + /* In any case, Scan results will be cleaned up in the + * reset function and when exiting the driver. + * The person triggering the scanning may never come to + * pick the results, so we need to do it in those places. + * Jean II */ + +#ifdef SCAN_SINGLE_READ + /* If you enable this option, only one client (the first + * one) will be able to read the result (and only one + * time). If there is multiple concurent clients that + * want to read scan results, this behavior is not + * advisable - Jean II */ + kfree(priv->scan_result); + priv->scan_result = NULL; +#endif /* SCAN_SINGLE_READ */ + /* Here, if too much time has elapsed since last scan, + * we may want to clean up scan results... - Jean II */ + } + + orinoco_unlock(priv, &flags); + return err; +} - case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ - if(priv->has_preamble) { - int *val = (int *)wrq->u.name; +/* Commit handler, called after set operations */ +static int orinoco_ioctl_commit(struct net_device *dev, + struct iw_request_info *info, + void *wrqu, + char *extra) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + unsigned long flags; + int err = 0; - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - *val = priv->preamble; - orinoco_unlock(priv, &flags); - } else - err = -EOPNOTSUPP; - break; - case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ - if (! capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; - } + if (!priv->open) + return 0; - err = orinoco_ioctl_setibssport(dev, wrq); - if (! err) - changed = 1; - break; + if (priv->broken_disableport) { + orinoco_reset(dev); + return 0; + } - case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ - err = orinoco_ioctl_getibssport(dev, wrq); - break; + if (orinoco_lock(priv, &flags) != 0) + return err; - case SIOCIWLASTPRIV: - err = orinoco_debug_dump_recs(dev); - if (err) - printk(KERN_ERR "%s: Unable to dump records (%d)\n", - dev->name, err); - break; + err = hermes_disable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to disable port " + "while reconfiguring card\n", dev->name); + priv->broken_disableport = 1; + goto out; + } + err = __orinoco_program_rids(dev); + if (err) { + printk(KERN_WARNING "%s: Unable to reconfigure card\n", + dev->name); + goto out; + } - default: - err = -EOPNOTSUPP; + err = hermes_enable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", + dev->name); + goto out; } - - if (! err && changed && netif_running(dev)) { - err = orinoco_reconfigure(dev); - } - TRACE_EXIT(dev->name); + out: + if (err) { + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); + schedule_work(&priv->reset_work); + err = 0; + } + orinoco_unlock(priv, &flags); return err; } -struct { - u16 rid; - char *name; - int displaytype; -#define DISPLAY_WORDS 0 -#define DISPLAY_BYTES 1 -#define DISPLAY_STRING 2 -#define DISPLAY_XSTRING 3 -} record_table[] = { -#define DEBUG_REC(name,type) { HERMES_RID_##name, #name, DISPLAY_##type } - DEBUG_REC(CNFPORTTYPE,WORDS), - DEBUG_REC(CNFOWNMACADDR,BYTES), - DEBUG_REC(CNFDESIREDSSID,STRING), - DEBUG_REC(CNFOWNCHANNEL,WORDS), - DEBUG_REC(CNFOWNSSID,STRING), - DEBUG_REC(CNFOWNATIMWINDOW,WORDS), - DEBUG_REC(CNFSYSTEMSCALE,WORDS), - DEBUG_REC(CNFMAXDATALEN,WORDS), - DEBUG_REC(CNFPMENABLED,WORDS), - DEBUG_REC(CNFPMEPS,WORDS), - DEBUG_REC(CNFMULTICASTRECEIVE,WORDS), - DEBUG_REC(CNFMAXSLEEPDURATION,WORDS), - DEBUG_REC(CNFPMHOLDOVERDURATION,WORDS), - DEBUG_REC(CNFOWNNAME,STRING), - DEBUG_REC(CNFOWNDTIMPERIOD,WORDS), - DEBUG_REC(CNFMULTICASTPMBUFFERING,WORDS), - DEBUG_REC(CNFWEPENABLED_AGERE,WORDS), - DEBUG_REC(CNFMANDATORYBSSID_SYMBOL,WORDS), - DEBUG_REC(CNFWEPDEFAULTKEYID,WORDS), - DEBUG_REC(CNFDEFAULTKEY0,BYTES), - DEBUG_REC(CNFDEFAULTKEY1,BYTES), - DEBUG_REC(CNFMWOROBUST_AGERE,WORDS), - DEBUG_REC(CNFDEFAULTKEY2,BYTES), - DEBUG_REC(CNFDEFAULTKEY3,BYTES), - DEBUG_REC(CNFWEPFLAGS_INTERSIL,WORDS), - DEBUG_REC(CNFWEPKEYMAPPINGTABLE,WORDS), - DEBUG_REC(CNFAUTHENTICATION,WORDS), - DEBUG_REC(CNFMAXASSOCSTA,WORDS), - DEBUG_REC(CNFKEYLENGTH_SYMBOL,WORDS), - DEBUG_REC(CNFTXCONTROL,WORDS), - DEBUG_REC(CNFROAMINGMODE,WORDS), - DEBUG_REC(CNFHOSTAUTHENTICATION,WORDS), - DEBUG_REC(CNFRCVCRCERROR,WORDS), - DEBUG_REC(CNFMMLIFE,WORDS), - DEBUG_REC(CNFALTRETRYCOUNT,WORDS), - DEBUG_REC(CNFBEACONINT,WORDS), - DEBUG_REC(CNFAPPCFINFO,WORDS), - DEBUG_REC(CNFSTAPCFINFO,WORDS), - DEBUG_REC(CNFPRIORITYQUSAGE,WORDS), - DEBUG_REC(CNFTIMCTRL,WORDS), - DEBUG_REC(CNFTHIRTY2TALLY,WORDS), - DEBUG_REC(CNFENHSECURITY,WORDS), - DEBUG_REC(CNFGROUPADDRESSES,BYTES), - DEBUG_REC(CNFCREATEIBSS,WORDS), - DEBUG_REC(CNFFRAGMENTATIONTHRESHOLD,WORDS), - DEBUG_REC(CNFRTSTHRESHOLD,WORDS), - DEBUG_REC(CNFTXRATECONTROL,WORDS), - DEBUG_REC(CNFPROMISCUOUSMODE,WORDS), - DEBUG_REC(CNFBASICRATES_SYMBOL,WORDS), - DEBUG_REC(CNFPREAMBLE_SYMBOL,WORDS), - DEBUG_REC(CNFSHORTPREAMBLE,WORDS), - DEBUG_REC(CNFWEPKEYS_AGERE,BYTES), - DEBUG_REC(CNFEXCLUDELONGPREAMBLE,WORDS), - DEBUG_REC(CNFTXKEY_AGERE,WORDS), - DEBUG_REC(CNFAUTHENTICATIONRSPTO,WORDS), - DEBUG_REC(CNFBASICRATES,WORDS), - DEBUG_REC(CNFSUPPORTEDRATES,WORDS), - DEBUG_REC(CNFTICKTIME,WORDS), - DEBUG_REC(CNFSCANREQUEST,WORDS), - DEBUG_REC(CNFJOINREQUEST,WORDS), - DEBUG_REC(CNFAUTHENTICATESTATION,WORDS), - DEBUG_REC(CNFCHANNELINFOREQUEST,WORDS), - DEBUG_REC(MAXLOADTIME,WORDS), - DEBUG_REC(DOWNLOADBUFFER,WORDS), - DEBUG_REC(PRIID,WORDS), - DEBUG_REC(PRISUPRANGE,WORDS), - DEBUG_REC(CFIACTRANGES,WORDS), - DEBUG_REC(NICSERNUM,XSTRING), - DEBUG_REC(NICID,WORDS), - DEBUG_REC(MFISUPRANGE,WORDS), - DEBUG_REC(CFISUPRANGE,WORDS), - DEBUG_REC(CHANNELLIST,WORDS), - DEBUG_REC(REGULATORYDOMAINS,WORDS), - DEBUG_REC(TEMPTYPE,WORDS), -/* DEBUG_REC(CIS,BYTES), */ - DEBUG_REC(STAID,WORDS), - DEBUG_REC(CURRENTSSID,STRING), - DEBUG_REC(CURRENTBSSID,BYTES), - DEBUG_REC(COMMSQUALITY,WORDS), - DEBUG_REC(CURRENTTXRATE,WORDS), - DEBUG_REC(CURRENTBEACONINTERVAL,WORDS), - DEBUG_REC(CURRENTSCALETHRESHOLDS,WORDS), - DEBUG_REC(PROTOCOLRSPTIME,WORDS), - DEBUG_REC(SHORTRETRYLIMIT,WORDS), - DEBUG_REC(LONGRETRYLIMIT,WORDS), - DEBUG_REC(MAXTRANSMITLIFETIME,WORDS), - DEBUG_REC(MAXRECEIVELIFETIME,WORDS), - DEBUG_REC(CFPOLLABLE,WORDS), - DEBUG_REC(AUTHENTICATIONALGORITHMS,WORDS), - DEBUG_REC(PRIVACYOPTIONIMPLEMENTED,WORDS), - DEBUG_REC(OWNMACADDR,BYTES), - DEBUG_REC(SCANRESULTSTABLE,WORDS), - DEBUG_REC(PHYTYPE,WORDS), - DEBUG_REC(CURRENTCHANNEL,WORDS), - DEBUG_REC(CURRENTPOWERSTATE,WORDS), - DEBUG_REC(CCAMODE,WORDS), - DEBUG_REC(SUPPORTEDDATARATES,WORDS), - DEBUG_REC(BUILDSEQ,BYTES), - DEBUG_REC(FWID,XSTRING) -#undef DEBUG_REC +static const struct iw_priv_args orinoco_privtab[] = { + { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, + { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, + { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_port3" }, + { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_port3" }, + { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_preamble" }, + { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_preamble" }, + { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_ibssport" }, + { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_ibssport" }, + { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, + "get_rid" }, }; -#define DEBUG_LTV_SIZE 128 - -static int orinoco_debug_dump_recs(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - u8 *val8; - u16 *val16; - int i,j; - u16 length; - int err; - - /* I'm not sure: we might have a lock here, so we'd better go - atomic, just in case. */ - val8 = kmalloc(DEBUG_LTV_SIZE + 2, GFP_ATOMIC); - if (! val8) - return -ENOMEM; - val16 = (u16 *)val8; - - for (i = 0; i < ARRAY_SIZE(record_table); i++) { - u16 rid = record_table[i].rid; - int len; - memset(val8, 0, DEBUG_LTV_SIZE + 2); - - err = hermes_read_ltv(hw, USER_BAP, rid, DEBUG_LTV_SIZE, - &length, val8); - if (err) { - DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid); - continue; - } - val16 = (u16 *)val8; - if (length == 0) - continue; - - printk(KERN_DEBUG "%-15s (0x%04x): length=%d (%d bytes)\tvalue=", - record_table[i].name, - rid, length, (length-1)*2); - len = min(((int)length-1)*2, DEBUG_LTV_SIZE); - - switch (record_table[i].displaytype) { - case DISPLAY_WORDS: - for (j = 0; j < len / 2; j++) - printk("%04X-", le16_to_cpu(val16[j])); - break; +/* + * Structures to export the Wireless Handlers + */ - case DISPLAY_BYTES: - default: - for (j = 0; j < len; j++) - printk("%02X:", val8[j]); - break; +static const iw_handler orinoco_handler[] = { + [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit, + [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname, + [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq, + [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq, + [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode, + [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode, + [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens, + [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens, + [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange, + [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy, + [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy, + [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap, + [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap, + [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan, + [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan, + [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid, + [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid, + [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick, + [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick, + [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate, + [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate, + [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts, + [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts, + [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag, + [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag, + [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry, + [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode, + [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode, + [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower, + [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower, +}; - case DISPLAY_STRING: - len = min(len, le16_to_cpu(val16[0])+2); - val8[len] = '\0'; - printk("\"%s\"", (char *)&val16[1]); - break; - case DISPLAY_XSTRING: - printk("'%s'", (char *)val8); - } +/* + Added typecasting since we no longer use iwreq_data -- Moustafa + */ +static const iw_handler orinoco_private_handler[] = { + [0] (iw_handler) orinoco_ioctl_reset, + [1] (iw_handler) orinoco_ioctl_reset, + [2] (iw_handler) orinoco_ioctl_setport3, + [3] (iw_handler) orinoco_ioctl_getport3, + [4] (iw_handler) orinoco_ioctl_setpreamble, + [5] (iw_handler) orinoco_ioctl_getpreamble, + [6] (iw_handler) orinoco_ioctl_setibssport, + [7] (iw_handler) orinoco_ioctl_getibssport, + [9] (iw_handler) orinoco_ioctl_getrid, +}; - printk("\n"); - } +static const struct iw_handler_def orinoco_handler_def = { + .num_standard = ARRAY_SIZE(orinoco_handler), + .num_private = ARRAY_SIZE(orinoco_private_handler), + .num_private_args = ARRAY_SIZE(orinoco_privtab), + .standard = orinoco_handler, + .private = orinoco_private_handler, + .private_args = orinoco_privtab, +}; - kfree(val8); +static void orinoco_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct orinoco_private *priv = netdev_priv(dev); - return 0; + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); + strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); + strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); + if (dev->class_dev.dev) + strncpy(info->bus_info, dev->class_dev.dev->bus_id, + sizeof(info->bus_info) - 1); + else + snprintf(info->bus_info, sizeof(info->bus_info) - 1, + "PCMCIA %p", priv->hw.iobase); } +static struct ethtool_ops orinoco_ethtool_ops = { + .get_drvinfo = orinoco_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + /********************************************************************/ /* Debugging */ /********************************************************************/ @@ -4218,7 +4472,6 @@ EXPORT_SYMBOL(free_orinocodev); EXPORT_SYMBOL(__orinoco_up); EXPORT_SYMBOL(__orinoco_down); -EXPORT_SYMBOL(orinoco_stop); EXPORT_SYMBOL(orinoco_reinit_firmware); EXPORT_SYMBOL(orinoco_interrupt); diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 13e42c2afb27..2f213a7103fe 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -7,7 +7,7 @@ #ifndef _ORINOCO_H #define _ORINOCO_H -#define DRIVER_VERSION "0.14alpha2" +#define DRIVER_VERSION "0.15rc2" #include <linux/types.h> #include <linux/spinlock.h> @@ -22,6 +22,8 @@ #define WIRELESS_SPY // enable iwspy support +#define MAX_SCAN_LEN 4096 + #define ORINOCO_MAX_KEY_SIZE 14 #define ORINOCO_MAX_KEYS 4 @@ -30,6 +32,20 @@ struct orinoco_key { char data[ORINOCO_MAX_KEY_SIZE]; } __attribute__ ((packed)); +struct header_struct { + /* 802.3 */ + u8 dest[ETH_ALEN]; + u8 src[ETH_ALEN]; + u16 len; + /* 802.2 */ + u8 dsap; + u8 ssap; + u8 ctrl; + /* SNAP */ + u8 oui[3]; + u16 ethertype; +} __attribute__ ((packed)); + typedef enum { FIRMWARE_TYPE_AGERE, FIRMWARE_TYPE_INTERSIL, @@ -48,6 +64,8 @@ struct orinoco_private { /* driver state */ int open; u16 last_linkstatus; + struct work_struct join_work; + struct work_struct wevent_work; /* Net device stuff */ struct net_device *ndev; @@ -74,7 +92,9 @@ struct orinoco_private { unsigned int has_pm:1; unsigned int has_preamble:1; unsigned int has_sensitivity:1; + unsigned int has_hostscan:1; unsigned int broken_disableport:1; + unsigned int broken_monitor:1; /* Configuration paramaters */ u32 iw_mode; @@ -84,6 +104,8 @@ struct orinoco_private { int bitratemode; char nick[IW_ESSID_MAX_SIZE+1]; char desired_essid[IW_ESSID_MAX_SIZE+1]; + char desired_bssid[ETH_ALEN]; + int bssid_fixed; u16 frag_thresh, mwo_robust; u16 channel; u16 ap_density, rts_thresh; @@ -98,6 +120,12 @@ struct orinoco_private { /* Configuration dependent variables */ int port_type, createibss; int promiscuous, mc_count; + + /* Scanning support */ + int scan_inprogress; /* Scan pending... */ + u32 scan_mode; /* Type of scan done */ + char * scan_result; /* Result of previous scan */ + int scan_len; /* Lenght of result */ }; #ifdef ORINOCO_DEBUG @@ -119,7 +147,6 @@ extern struct net_device *alloc_orinocodev(int sizeof_card, extern void free_orinocodev(struct net_device *dev); extern int __orinoco_up(struct net_device *dev); extern int __orinoco_down(struct net_device *dev); -extern int orinoco_stop(struct net_device *dev); extern int orinoco_reinit_firmware(struct net_device *dev); extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs); diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 74a8227256aa..1cc1492083c9 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -31,7 +31,6 @@ #include <linux/etherdevice.h> #include <linux/wireless.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -186,11 +185,6 @@ orinoco_cs_attach(void) dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &orinoco_cs_event; client_reg.Version = 0x0210; /* FIXME: what does this mean? */ client_reg.event_callback_args.client_data = link; @@ -608,13 +602,63 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION " (David Gibson <hermes@gibson.dropbear.id.au>, " "Pavel Roskin <proski@gnu.org>, et al)"; +static struct pcmcia_device_id orinoco_cs_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), + PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), + PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), + PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), + PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), + PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), + PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), + PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), + PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), + PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), + PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), + PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), + PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), + PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), + PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), + PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), + PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), + PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); + static struct pcmcia_driver orinoco_driver = { .owner = THIS_MODULE, .drv = { .name = DRIVER_NAME, }, .attach = orinoco_cs_attach, + .event = orinoco_cs_event, .detach = orinoco_cs_detach, + .id_table = orinoco_cs_ids, }; static int __init diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 4481ec18c5a0..adc7499136dc 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -112,10 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block, void isl38xx_trigger_device(int asleep, void __iomem *device_base) { - struct timeval current_time; u32 reg, counter = 0; #if VERBOSE > SHOW_ERROR_MESSAGES + struct timeval current_time; DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); #endif @@ -126,11 +126,11 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", current_time.tv_sec, (long)current_time.tv_usec); -#endif DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); +#endif udelay(ISL38XX_WRITEIO_DELAY); reg = readl(device_base + ISL38XX_INT_IDENT_REG); @@ -148,10 +148,12 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) counter++; } +#if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); +#endif udelay(ISL38XX_WRITEIO_DELAY); #if VERBOSE > SHOW_ERROR_MESSAGES diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 6e5bda56b8f8..0e0ba614259a 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -46,7 +46,6 @@ #include <linux/skbuff.h> #include <linux/ethtool.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -393,11 +392,6 @@ static dev_link_t *ray_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ray_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -2904,13 +2898,21 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long } #endif +static struct pcmcia_device_id ray_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, ray_ids); + static struct pcmcia_driver ray_driver = { .owner = THIS_MODULE, .drv = { .name = "ray_cs", }, .attach = ray_attach, + .event = ray_event, .detach = ray_detach, + .id_table = ray_ids, }; static int __init init_ray_cs(void) diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index ec8cf29ffced..6c42b573a95a 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -2828,7 +2828,7 @@ static void __exit strip_exit_driver(void) /* Unregister with the /proc/net file here. */ proc_net_remove("strip"); - if ((i = tty_register_ldisc(N_STRIP, NULL))) + if ((i = tty_unregister_ldisc(N_STRIP))) printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); printk(signoff); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index ec8329788e49..f6130a53b796 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4684,12 +4684,6 @@ wavelan_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.EventMask = - CS_EVENT_REGISTRATION_COMPLETE | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &wavelan_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; @@ -4889,13 +4883,24 @@ wavelan_event(event_t event, /* The event received */ return 0; } +static struct pcmcia_device_id wavelan_ids[] = { + PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), + PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), + PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/PCMCIA", 0x23eb9949, 0x1bc50975), + PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/PCMCIA", 0x24358cd4, 0x1bc50975), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, wavelan_ids); + static struct pcmcia_driver wavelan_driver = { .owner = THIS_MODULE, .drv = { .name = "wavelan_cs", }, .attach = wavelan_attach, + .event = wavelan_event, .detach = wavelan_detach, + .id_table = wavelan_ids, }; static int __init diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index ea2ef8dddb92..677ff71883cb 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -452,7 +452,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <pcmcia/version.h> /* Wavelan declarations */ #include "i82593.h" /* Definitions for the Intel chip */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 1433e5aaf1b4..dd902126d018 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -49,7 +49,6 @@ #include <net/iw_handler.h> -#include <pcmcia/version.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> @@ -2005,13 +2004,6 @@ static dev_link_t *wl3501_attach(void) link->next = wl3501_dev_list; wl3501_dev_list = link; client_reg.dev_info = &wl3501_dev_info; - client_reg.EventMask = CS_EVENT_CARD_INSERTION | - CS_EVENT_RESET_PHYSICAL | - CS_EVENT_CARD_RESET | - CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | - CS_EVENT_PM_RESUME; - client_reg.event_handler = wl3501_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = pcmcia_register_client(&link->handle, &client_reg); @@ -2239,13 +2231,21 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) return 0; } +static struct pcmcia_device_id wl3501_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); + static struct pcmcia_driver wl3501_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "wl3501_cs", + .owner = THIS_MODULE, + .drv = { + .name = "wl3501_cs", }, - .attach = wl3501_attach, - .detach = wl3501_detach, + .attach = wl3501_attach, + .event = wl3501_event, + .detach = wl3501_detach, + .id_table = wl3501_ids, }; static int __init wl3501_init_module(void) diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 9da925430109..1c2506535f7e 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -786,7 +786,7 @@ static void yellowfin_init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev, - skb->tail, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); + skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); } yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -1111,7 +1111,7 @@ static int yellowfin_rx(struct net_device *dev) pci_dma_sync_single_for_cpu(yp->pci_dev, desc->addr, yp->rx_buf_sz, PCI_DMA_FROMDEVICE); desc_status = le32_to_cpu(desc->result_status) >> 16; - buf_addr = rx_skb->tail; + buf_addr = rx_skb->data; data_size = (le32_to_cpu(desc->dbdma_cmd) - le32_to_cpu(desc->result_status)) & 0xffff; frame_status = le16_to_cpu(get_unaligned((s16*)&(buf_addr[data_size - 2]))); @@ -1185,7 +1185,7 @@ static int yellowfin_rx(struct net_device *dev) break; skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ - eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0); + eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, @@ -1211,7 +1211,7 @@ static int yellowfin_rx(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ yp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev, - skb->tail, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); + skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); } yp->rx_ring[entry].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->rx_ring[entry].result_status = 0; /* Clear complete bit. */ |