aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pcmcia/axnet_cs.c
diff options
context:
space:
mode:
authorKomuro <komurojun-mbn@nifty.com>2006-03-25 17:31:55 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-29 17:26:05 -0500
commitb8ab2dc3e1a7c525ca73ba0af3518ec0b7654b3b (patch)
tree468a1ed9815a0f4cef1d2aef57d9e071f2b0d321 /drivers/net/pcmcia/axnet_cs.c
parent5c5131297db57b501f371ab53c40343eac6f2af7 (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.c61
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
1691static 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
1693static void do_set_multicast_list(struct net_device *dev) 1715static 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);