diff options
author | Komuro <komurojun-mbn@nifty.com> | 2006-03-25 17:31:55 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-29 17:26:05 -0500 |
commit | b8ab2dc3e1a7c525ca73ba0af3518ec0b7654b3b (patch) | |
tree | 468a1ed9815a0f4cef1d2aef57d9e071f2b0d321 /drivers/net/pcmcia/axnet_cs.c | |
parent | 5c5131297db57b501f371ab53c40343eac6f2af7 (diff) |
[PATCH] axnet_cs.c : add hardware multicast support
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/pcmcia/axnet_cs.c')
-rw-r--r-- | drivers/net/pcmcia/axnet_cs.c | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index aa5581369399..1cc94b2d76c1 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
36 | #include <linux/ethtool.h> | 36 | #include <linux/ethtool.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/crc32.h> | ||
38 | #include "../8390.h" | 39 | #include "../8390.h" |
39 | 40 | ||
40 | #include <pcmcia/cs_types.h> | 41 | #include <pcmcia/cs_types.h> |
@@ -1682,17 +1683,67 @@ static struct net_device_stats *get_stats(struct net_device *dev) | |||
1682 | return &ei_local->stat; | 1683 | return &ei_local->stat; |
1683 | } | 1684 | } |
1684 | 1685 | ||
1686 | /* | ||
1687 | * Form the 64 bit 8390 multicast table from the linked list of addresses | ||
1688 | * associated with this dev structure. | ||
1689 | */ | ||
1690 | |||
1691 | static inline void make_mc_bits(u8 *bits, struct net_device *dev) | ||
1692 | { | ||
1693 | struct dev_mc_list *dmi; | ||
1694 | u32 crc; | ||
1695 | |||
1696 | for (dmi=dev->mc_list; dmi; dmi=dmi->next) { | ||
1697 | |||
1698 | crc = ether_crc(ETH_ALEN, dmi->dmi_addr); | ||
1699 | /* | ||
1700 | * The 8390 uses the 6 most significant bits of the | ||
1701 | * CRC to index the multicast table. | ||
1702 | */ | ||
1703 | bits[crc>>29] |= (1<<((crc>>26)&7)); | ||
1704 | } | ||
1705 | } | ||
1706 | |||
1685 | /** | 1707 | /** |
1686 | * do_set_multicast_list - set/clear multicast filter | 1708 | * do_set_multicast_list - set/clear multicast filter |
1687 | * @dev: net device for which multicast filter is adjusted | 1709 | * @dev: net device for which multicast filter is adjusted |
1688 | * | 1710 | * |
1689 | * Set or clear the multicast filter for this adaptor. May be called | 1711 | * Set or clear the multicast filter for this adaptor. |
1690 | * from a BH in 2.1.x. Must be called with lock held. | 1712 | * Must be called with lock held. |
1691 | */ | 1713 | */ |
1692 | 1714 | ||
1693 | static void do_set_multicast_list(struct net_device *dev) | 1715 | static void do_set_multicast_list(struct net_device *dev) |
1694 | { | 1716 | { |
1695 | long e8390_base = dev->base_addr; | 1717 | long e8390_base = dev->base_addr; |
1718 | int i; | ||
1719 | struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); | ||
1720 | |||
1721 | if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { | ||
1722 | memset(ei_local->mcfilter, 0, 8); | ||
1723 | if (dev->mc_list) | ||
1724 | make_mc_bits(ei_local->mcfilter, dev); | ||
1725 | } else { | ||
1726 | /* set to accept-all */ | ||
1727 | memset(ei_local->mcfilter, 0xFF, 8); | ||
1728 | } | ||
1729 | |||
1730 | /* | ||
1731 | * DP8390 manuals don't specify any magic sequence for altering | ||
1732 | * the multicast regs on an already running card. To be safe, we | ||
1733 | * ensure multicast mode is off prior to loading up the new hash | ||
1734 | * table. If this proves to be not enough, we can always resort | ||
1735 | * to stopping the NIC, loading the table and then restarting. | ||
1736 | */ | ||
1737 | |||
1738 | if (netif_running(dev)) | ||
1739 | outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); | ||
1740 | |||
1741 | outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); | ||
1742 | for(i = 0; i < 8; i++) | ||
1743 | { | ||
1744 | outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); | ||
1745 | } | ||
1746 | outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); | ||
1696 | 1747 | ||
1697 | if(dev->flags&IFF_PROMISC) | 1748 | if(dev->flags&IFF_PROMISC) |
1698 | outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); | 1749 | outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); |
@@ -1794,12 +1845,6 @@ static void AX88190_init(struct net_device *dev, int startp) | |||
1794 | if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) | 1845 | if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) |
1795 | printk(KERN_ERR "Hw. address read/write mismap %d\n",i); | 1846 | printk(KERN_ERR "Hw. address read/write mismap %d\n",i); |
1796 | } | 1847 | } |
1797 | /* | ||
1798 | * Initialize the multicast list to accept-all. If we enable multicast | ||
1799 | * the higher levels can do the filtering. | ||
1800 | */ | ||
1801 | for (i = 0; i < 8; i++) | ||
1802 | outb_p(0xff, e8390_base + EN1_MULT + i); | ||
1803 | 1848 | ||
1804 | outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); | 1849 | outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); |
1805 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); | 1850 | outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); |