--- hp100-1.52/hp100.c Mon Apr 21 14:20:47 1997 +++ hp100-1.53/hp100.c Fri Jun 6 10:31:44 1997 @@ -2,7 +2,7 @@ ** hp100.c ** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters ** -** $Id: hp100.c,v 1.52 1997/04/21 14:20:20 perex Exp perex $ +** $Id: hp100.c,v 1.53 1997/06/06 10:31:35 perex Exp perex $ ** ** Based on the HP100 driver written by Jaroslav Kysela ** Extended for new busmaster capable chipsets by @@ -34,6 +34,10 @@ ** Free Software Foundation) either version two of this License, or any ** later version. ** +** +** 1.52 -> 1.53 +** - fixed bug in multicast support +** */ #define HP100_DEFAULT_PRIORITY_TX 0 @@ -78,6 +82,12 @@ typedef struct net_device_stats hp100_stats_t; #endif +#ifndef __initfunc +#define __initfunc(__initarg) __initarg +#else +#include +#endif + #include "hp100.h" /* @@ -141,6 +151,7 @@ int hub_status; /* was login to hub successful? */ u_char mac1_mode; u_char mac2_mode; + u_char hash_bytes[ 8 ]; hp100_stats_t stats; /* Rings for busmaster mode: */ @@ -254,7 +265,7 @@ * since this could cause problems when the card is not installed. */ -int hp100_probe( struct device *dev ) +__initfunc(int hp100_probe( struct device *dev )) { int base_addr = dev ? dev -> base_addr : 0; int ioaddr = 0; @@ -354,7 +365,7 @@ } -static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ) +__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn )) { int i; @@ -593,6 +604,7 @@ lp->soft_model = hp100_inb( SOFT_MODEL ); lp->mac1_mode = HP100_MAC1MODE3; lp->mac2_mode = HP100_MAC2MODE3; + memset( &lp->hash_bytes, 0x00, 8 ); dev->base_addr = ioaddr; @@ -1039,6 +1051,7 @@ lp->lan_type = hp100_sense_lan( dev ); lp->mac1_mode = HP100_MAC1MODE3; lp->mac2_mode = HP100_MAC2MODE3; + memset( &lp->hash_bytes, 0x00, 8 ); hp100_stop_interface( dev ); @@ -1463,7 +1476,6 @@ { hp100_ints_off(); i = hp100_sense_lan( dev ); - hp100_page( PERFORMANCE ); hp100_ints_on(); if ( i == HP100_LAN_ERR ) printk( "%s: link down detected\n", dev->name ); @@ -1630,7 +1642,6 @@ { hp100_ints_off(); i = hp100_sense_lan( dev ); - hp100_page( PERFORMANCE ); hp100_ints_on(); if ( i == HP100_LAN_ERR ) printk( "%s: link down detected\n", dev->name ); @@ -2060,32 +2071,70 @@ { lp->mac2_mode = HP100_MAC2MODE6; /* promiscuous mode = get all good */ lp->mac1_mode = HP100_MAC1MODE6; /* packets on the net */ + memset( &lp->hash_bytes, 0xff, 8 ); } else if ( dev->mc_count || (dev->flags&IFF_ALLMULTI) ) { lp->mac2_mode = HP100_MAC2MODE5; /* multicast mode = get packets for */ lp->mac1_mode = HP100_MAC1MODE5; /* me, broadcasts and all multicasts */ + memset( &lp->hash_bytes, 0xff, 8 ); } else { lp->mac2_mode = HP100_MAC2MODE3; /* normal mode = get packets for me */ lp->mac1_mode = HP100_MAC1MODE3; /* and broadcasts */ + memset( &lp->hash_bytes, 0x00, 8 ); } if ( ( (hp100_inb(MAC_CFG_1) & 0x0f)!=lp->mac1_mode ) || - ( hp100_inb(MAC_CFG_2)!=lp->mac2_mode ) ) { - hp100_outb( lp->mac2_mode, MAC_CFG_2 ); - hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 ); /* clear mac1 mode bits */ - hp100_orb( lp->mac1_mode, MAC_CFG_1 ); /* and set the new mode */ + ( hp100_inb(MAC_CFG_2)!=lp->mac2_mode ) ) + { + int i; + + hp100_outb( lp->mac2_mode, MAC_CFG_2 ); + hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 ); /* clear mac1 mode bits */ + hp100_orb( lp->mac1_mode, MAC_CFG_1 ); /* and set the new mode */ + + hp100_page( MAC_ADDRESS ); + for ( i = 0; i < 8; i++ ) + hp100_outb( lp->hash_bytes[ i ], HASH_BYTE0 + i ); +#ifdef HP100_DEBUG + printk("hp100: mac1 = 0x%x, mac2 = 0x%x, multicast hash = 0x%x\n", lp->mac1_mode, lp->mac2_mode, lp->hash_bytes[ 0 ]); +#endif - if(lp->lan_type==HP100_LAN_100) - { + if(lp->lan_type==HP100_LAN_100) + { #ifdef HP100_DEBUG - printk("hp100: 100VG MAC settings have changed - relogin.\n"); -#endif - lp->hub_status=hp100_login_to_vg_hub( dev, TRUE ); /* force a relogin to the hub */ - } - } + printk("hp100: 100VG MAC settings have changed - relogin.\n"); +#endif + lp->hub_status=hp100_login_to_vg_hub( dev, TRUE ); /* force a relogin to the hub */ + } + } + else + { + int i; + u_char old_hash_bytes[ 8 ]; + + hp100_page( MAC_ADDRESS ); + for ( i = 0; i < 8; i++ ) + old_hash_bytes[ i ] = hp100_inb( HASH_BYTE0 + i ); + if ( memcmp( old_hash_bytes, &lp->hash_bytes, 8 ) ) + { + for ( i = 0; i < 8; i++ ) + hp100_outb( lp->hash_bytes[ i ], HASH_BYTE0 + i ); +#ifdef HP100_DEBUG + printk("hp100: multicast hash = 0x%x\n", lp->hash_bytes[ 0 ]); +#endif + + if(lp->lan_type==HP100_LAN_100) + { +#ifdef HP100_DEBUG + printk("hp100: 100VG MAC settings have changed - relogin.\n"); +#endif + lp->hub_status=hp100_login_to_vg_hub( dev, TRUE ); /* force a relogin to the hub */ + } + } + } hp100_page( MAC_CTRL ); hp100_orb( HP100_RX_EN | HP100_RX_IDLE | /* enable rx */ @@ -2387,7 +2436,11 @@ #ifdef HP100_DEBUG printk( "hp100_sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", val_VG, val_10 ); #endif - if ( val_10 & HP100_LINK_BEAT_ST ) return HP100_LAN_10; + if ( val_10 & (HP100_LINK_BEAT_ST|HP100_AUI_ST) ) + { + hp100_page(PERFORMANCE); + return HP100_LAN_10; + } if ( (lp->id->id == 0x02019F022) || (lp->id->id == 0x01042103c) || (lp->id->id == 0x01040103c) )