patch-1.3.44 linux/drivers/net/ewrk3.c
Next file: linux/drivers/net/hp100.c
Previous file: linux/drivers/net/eth16i.c
Back to the patch index
Back to the overall index
- Lines: 281
- Date:
Fri Nov 24 16:39:53 1995
- Orig file:
v1.3.43/linux/drivers/net/ewrk3.c
- Orig date:
Thu Nov 9 11:23:49 1995
diff -u --recursive --new-file v1.3.43/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
@@ -290,7 +290,7 @@
static void ewrk3_interrupt(int irq, struct pt_regs *regs);
static int ewrk3_close(struct device *dev);
static struct enet_statistics *ewrk3_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd);
/*
@@ -303,7 +303,7 @@
static void EthwrkSignature(char * name, char *eeprom_image);
static int DevicePresent(short iobase);
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table);
+static void SetMulticastFilter(struct device *dev, int num_addr, char *multicast_table);
static int Read_EEPROM(short iobase, unsigned char eaddr);
static int Write_EEPROM(short data, short iobase, unsigned char eaddr);
@@ -723,11 +723,15 @@
struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
char csr, page;
short iobase = dev->base_addr;
+ int flags=dev->flags;
/*
** Enable all multicasts
*/
- set_multicast_list(dev, HASH_TABLE_LEN, NULL);
+
+ dev->flags|=IFF_ALLMULTI;
+ set_multicast_list(dev);
+ dev->flags=flags;
/*
** Clean out any remaining entries in all the queues here
@@ -1207,7 +1211,7 @@
** best-effort filtering.
*/
static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
{
struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
int iobase = dev->base_addr;
@@ -1216,21 +1220,24 @@
csr = inb(EWRK3_CSR);
- if (lp->shmem_length == IO_ONLY) {
+ if (lp->shmem_length == IO_ONLY)
+ {
multicast_table = (char *) PAGE0_HTE;
} else {
multicast_table = (char *)(lp->shmem_base + PAGE0_HTE);
}
- if (num_addrs >= 0) {
- SetMulticastFilter(dev, num_addrs, (char *)addrs, multicast_table);
- csr &= ~PME;
- csr |= MCE;
- outb(csr, EWRK3_CSR);
- } else { /* set promiscuous mode */
+ if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+ {
csr |= PME;
csr &= ~MCE;
outb(csr, EWRK3_CSR);
+ dev->flags|=IFF_PROMISC;
+ } else { /* set promiscuous mode */
+ SetMulticastFilter(dev, dev->mc_count, multicast_table);
+ csr &= ~PME;
+ csr |= MCE;
+ outb(csr, EWRK3_CSR);
}
}
@@ -1242,83 +1249,110 @@
** Note that when clearing the table, the broadcast bit must remain asserted
** to receive broadcast messages.
*/
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table)
+static void SetMulticastFilter(struct device *dev, int num_addrs, char *multicast_table)
{
- struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
- int i, iobase = dev->base_addr;
- char j, bit, byte;
- short *p = (short *) multicast_table;
- u_short hashcode;
- u_long crc, poly = CRC_POLYNOMIAL_LE;
-
- while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
-
- if (lp->shmem_length == IO_ONLY) {
- outb(0, EWRK3_IOPR);
- outw((short)((long)multicast_table), EWRK3_PIR1);
- } else {
- outb(0, EWRK3_MPR);
- }
+ struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
+ char *addrs;
+ struct dev_mc_list *dmi=dev->mc_list;
+ int i, iobase = dev->base_addr;
+ char j, bit, byte;
+ short *p = (short *) multicast_table;
+ u_short hashcode;
+ u_long crc, poly = CRC_POLYNOMIAL_LE;
- if (num_addrs == HASH_TABLE_LEN) {
- for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
- if (lp->shmem_length == IO_ONLY) {
- outb(0xff, EWRK3_DATA);
- } else { /* memset didn't work here */
- *p++ = 0xffff;
- i++;
- }
- }
- } else {
- /* Clear table except for broadcast bit */
- if (lp->shmem_length == IO_ONLY) {
- for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) {
- outb(0x00, EWRK3_DATA);
- }
- outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */
- for (; i<(HASH_TABLE_LEN >> 3); i++) {
- outb(0x00, EWRK3_DATA);
- }
- } else {
- memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
- *(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
- }
+ while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
- /* Update table */
- for (i=0;i<num_addrs;i++) { /* for each address in the list */
- if ((*addrs & 0x01) == 1) { /* multicast address? */
- crc = 0xffffffff; /* init CRC for each address */
- for (byte=0;byte<ETH_ALEN;byte++) { /* for each address byte */
- /* process each address bit */
- for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
- crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
- }
+ if (lp->shmem_length == IO_ONLY)
+ {
+ outb(0, EWRK3_IOPR);
+ outw((short)((long)multicast_table), EWRK3_PIR1);
+ }
+ else
+ {
+ outb(0, EWRK3_MPR);
}
- hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
- byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
- bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
+ if (num_addrs >= HASH_TABLE_LEN)
+ {
+ for (i=0; i<(HASH_TABLE_LEN >> 3); i++)
+ {
+ if (lp->shmem_length == IO_ONLY)
+ {
+ outb(0xff, EWRK3_DATA);
+ }
+ else
+ { /* memset didn't work here */
+ *p++ = 0xffff;
+ i++;
+ }
+ }
+ }
+ else
+ {
+ /* Clear table except for broadcast bit */
+ if (lp->shmem_length == IO_ONLY)
+ {
+ for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++)
+ {
+ outb(0x00, EWRK3_DATA);
+ }
+ outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */
+ for (; i<(HASH_TABLE_LEN >> 3); i++)
+ {
+ outb(0x00, EWRK3_DATA);
+ }
+ }
+ else
+ {
+ memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
+ *(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
+ }
- if (lp->shmem_length == IO_ONLY) {
- unsigned char tmp;
+ /* Update table */
- outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
- tmp = inb(EWRK3_DATA);
- tmp |= bit;
- outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
- outb(tmp, EWRK3_DATA);
- } else {
- multicast_table[byte] |= bit;
+ for (i=0;i<dev->mc_count;i++)
+ {
+ /* for each address in the list */
+ addrs=dmi->dmi_addr;
+ dmi=dmi->next;
+
+ if ((*addrs & 0x01) == 1)
+ { /* multicast address? */
+ crc = 0xffffffff; /* init CRC for each address */
+ for (byte=0;byte<ETH_ALEN;byte++)
+ { /* for each address byte */
+ /* process each address bit */
+ for (bit = *addrs++,j=0;j<8;j++, bit>>=1)
+ {
+ crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
+ }
+ }
+ hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */
+
+ byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
+ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
+
+ if (lp->shmem_length == IO_ONLY)
+ {
+ unsigned char tmp;
+
+ outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
+ tmp = inb(EWRK3_DATA);
+ tmp |= bit;
+ outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
+ outb(tmp, EWRK3_DATA);
+ }
+ else
+ {
+ multicast_table[byte] |= bit;
+ }
+ }
+ }
}
- } else { /* skip this address */
- addrs += ETH_ALEN;
- }
- }
- }
- lp->lock = 0; /* Unlock the page register */
+ lp->lock = 0; /* Unlock the page register */
- return;
+ return;
}
#ifndef MODULE
@@ -1669,7 +1703,8 @@
break;
case EWRK3_SAY_BOO: /* Say "Boo!" to the kernel log file */
- printk("%s: Boo!\n", dev->name);
+ if(suser())
+ printk("%s: Boo!\n", dev->name);
break;
case EWRK3_GET_MCA: /* Get the multicast address table */
@@ -1692,6 +1727,8 @@
lp->lock = 0; /* Unlock the page register */
break;
+
+#if 0
case EWRK3_SET_MCA: /* Set a multicast address */
if (suser()) {
err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len);
@@ -1725,6 +1762,7 @@
}
break;
+#endif
case EWRK3_GET_STATS: /* Get the driver statistics */
err = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats));
if (err) return err;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this