updated ENC624j6net driver
- fixes to gcc native and cross compilation settings
- implemented hardware based multicast filtering hashes, resulting
in less unwanted traffic to our Amigas (especially Bonjour, UPNP and such)
- MULTICAST option in envarc:sana2/enc624j6net.config will now
allow all multicast traffic as opposed to the default fine grained
filtering behaviour
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
; ------------------------------------------------------------------------------
|
||||
; | Lowlevel Access to memory mapped ENC624J600 in PSP mode |
|
||||
; | Henryk Richter <henryk.richter@gmx.net> |
|
||||
@@ -19,19 +20,25 @@
|
||||
; - _enc624j6l_RXReset -> won't recover from totally unresponsive chip (but exits gracefully)
|
||||
;
|
||||
; enable debugging code block (comment/uncomment, see below)
|
||||
DEBUG EQU 1
|
||||
DEBUG EQU 0
|
||||
GLOBALINT_BOARD EQU 1 ;if 1, then toggle board interrupt, else ENC624 INTIE
|
||||
|
||||
incdir src:baxnet/trunk/source/
|
||||
;Temp:Amiga/src/Zorro-LAN-IDE.git/Driver/enc624j6net/
|
||||
include "enc624j6net/registers.i"
|
||||
include "enc624j6net/macros.i"
|
||||
include "debug.i"
|
||||
|
||||
ifnd DEBUG
|
||||
DEBUG EQU 0
|
||||
endc
|
||||
|
||||
ifne 1
|
||||
include "debug.i"
|
||||
else
|
||||
WRITEDEBUG macro
|
||||
nop
|
||||
endm
|
||||
endc
|
||||
;
|
||||
ADD_4RX EQU 1 ;add 4 to valid RX size (fake CRC), fixes shapeshifter RAW treatment
|
||||
_OPT_LONGRESET EQU 0 ;in testing, don't enable
|
||||
@@ -134,12 +141,6 @@ _LVOSignal EQU -324
|
||||
|
||||
section code,code
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; | |
|
||||
; | Test/Debug code |
|
||||
@@ -277,7 +278,13 @@ regtests:
|
||||
READREG ESTAT,a0,d0
|
||||
READREG ECON1,a0,d1
|
||||
READREG MACON2,a0,d2
|
||||
READREG MABBIPG,a0,d3
|
||||
; READREG MABBIPG,a0,d3
|
||||
|
||||
READREG ERXFCON,a0,d3
|
||||
READREG EHT1,a0,d4
|
||||
READREG EHT2,a0,d5
|
||||
READREG EHT3,a0,d6
|
||||
READREG EHT4,a0,d7
|
||||
rts
|
||||
|
||||
|
||||
@@ -587,6 +594,7 @@ _enc624j6l_Init:
|
||||
WRITEREG ERXST,a0,d0 ;set RX start pointer (end will be $5fff)
|
||||
WRITEREG PNextPacket,a0,d0 ;set user read pointer
|
||||
|
||||
suba.l a1,a1 ;no multicast hash table (yet)
|
||||
bsr _enc624j6l_bc_mc_filter ;in: A0/D1, out: D0
|
||||
|
||||
move #RXSTOP_INIT&$fffe,d0
|
||||
@@ -644,6 +652,7 @@ _enc624j6l_Init:
|
||||
;
|
||||
; in: A0 - board base
|
||||
; D1 - init flags
|
||||
; A1 - multicast hash table (4x USHORT)
|
||||
;out: D0 >0 = OK
|
||||
; <=0 = FAIL
|
||||
_enc624j6l_bc_mc_filter:
|
||||
@@ -658,15 +667,32 @@ _enc624j6l_bc_mc_filter:
|
||||
move #ERXFCON_NOTMEEN|ERXFCON_MCEN|ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
|
||||
bra.s .setfilter
|
||||
.no_promisc:
|
||||
moveq #PIO_INIT_MULTI_CAST,d0
|
||||
moveq #PIO_INIT_MULTI_CAST,d0 ;all multicast ?
|
||||
and d1,d0
|
||||
beq.s .no_multicast
|
||||
move #ERXFCON_MCEN|ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
|
||||
bra.s .setfilter
|
||||
.no_multicast:
|
||||
move #ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
|
||||
|
||||
; did we get a multicast hash table ?
|
||||
move.l a1,d1
|
||||
beq.s .nohashes
|
||||
AND #$ffff-ERXFCON_MCEN,d0 ;don't accept ALL multicast
|
||||
OR #ERXFCON_HTEN,d0 ;enable multicast hash table filter
|
||||
|
||||
move (a1),d1
|
||||
WRITEREG EHT1,a0,d1
|
||||
move 2(a1),d1
|
||||
WRITEREG EHT2,a0,d1
|
||||
move 4(a1),d1
|
||||
WRITEREG EHT3,a0,d1
|
||||
move 6(a1),d1
|
||||
WRITEREG EHT4,a0,d1
|
||||
.nohashes:
|
||||
|
||||
.setfilter:
|
||||
WRITEREG ERXFCON,a0,d0 ;set filter TODO: pattern matching stuff
|
||||
WRITEREG ERXFCON,a0,d0 ;set filter
|
||||
|
||||
moveq #1,d0
|
||||
.rts:
|
||||
|
||||
@@ -239,8 +239,9 @@ ASM SAVEDS int enc624j6l_SetOnline( ASMR(a0) void *board ASMREG(a0) );
|
||||
>=0 - OK
|
||||
*/
|
||||
ASM SAVEDS int enc624j6l_bc_mc_filter(
|
||||
ASMR(a0) void *board ASMREG(a0),
|
||||
ASMR(d1) unsigned long flags ASMREG(d1) );
|
||||
ASMR(a0) void *board ASMREG(a0),
|
||||
ASMR(d1) unsigned long flags ASMREG(d1),
|
||||
ASMR(a1) unsigned short *mc_hashes ASMREG(a1));
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -30,6 +30,7 @@ extern const BYTE DeviceName[];
|
||||
/* use generic board fields in current unit */
|
||||
#define duh_online du_hwl0
|
||||
#define duh_BASE du_hwp0
|
||||
#define duh_RefCount du_hwl1
|
||||
|
||||
#define HW_INTERVALDEF 100000L
|
||||
|
||||
@@ -105,7 +106,7 @@ ASM SAVEDS LONG hw_Find_Boards( ASMR(a0) DEVBASEP ASMREG(a0) )
|
||||
|
||||
/* bring board to sane state (i.e. perform soft reset) */
|
||||
/* if( boardbase < (APTR)0x40000000 ) */ /* debug only */
|
||||
enc624j6l_CheckBoard( boardbase );
|
||||
enc624j6l_CheckBoard( boardbase );
|
||||
}
|
||||
ret = i;
|
||||
D(("%ld boards found\n",ret));
|
||||
@@ -119,7 +120,33 @@ ASM SAVEDS LONG hw_Find_Boards( ASMR(a0) DEVBASEP ASMREG(a0) )
|
||||
ASM SAVEDS LONG hw_AllocBoard( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0) )
|
||||
{
|
||||
/* is there a way to lock a ZII Board ? */
|
||||
#if 0
|
||||
LONG i;
|
||||
struct ConfigDev *cfg = (0);
|
||||
|
||||
if( unit > db->db_NBoards )
|
||||
return 0;
|
||||
|
||||
for( i=0 ; i < db->db_NBoards ; i++ )
|
||||
{
|
||||
cfg = FindConfigDev( cfg, ENC_MANUFACTURER, ENC_BOARD );
|
||||
if( !cfg )
|
||||
return 0;
|
||||
if( (APTR)cfg->cd_BoardAddr == db->db_Units[unit].duh_BASE )
|
||||
break;
|
||||
}
|
||||
|
||||
if( (APTR)cfg->cd_BoardAddr != db->db_Units[unit].duh_BASE )
|
||||
return 0;
|
||||
|
||||
if( db->db_Units[unit].duh_RefCount == 0 )
|
||||
{
|
||||
ObtainConfigBinding();
|
||||
|
||||
ReleaseConfigBinding();
|
||||
}
|
||||
db->db_Units[unit].duh_RefCount++;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -127,6 +154,20 @@ ASM SAVEDS LONG hw_AllocBoard( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASM SAVEDS LONG hw_ReleaseBoard( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0) )
|
||||
{
|
||||
#if 0
|
||||
if( unit > db->db_NBoards )
|
||||
return 0;
|
||||
|
||||
for( i=0 ; i < db->db_NBoards ; i++ )
|
||||
{
|
||||
cfg = FindConfigDev( cfg, ENC_MANUFACTURER, ENC_BOARD );
|
||||
if( !cfg )
|
||||
return 0;
|
||||
if( (APTR)cfg->cd_BoardAddr == db->db_Units[unit].duh_BASE )
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -427,27 +468,143 @@ ASM SAVEDS LONG hw_write_phy( ASMR(a0) DEVBASEP ASMREG(
|
||||
return enc624j6l_WritePHY( boardbase, reg, value );
|
||||
}
|
||||
|
||||
/*
|
||||
calculate CRC32 for MAC address hashing
|
||||
slow but relatively short (and can be adapted to other
|
||||
polynoms easily)
|
||||
*/
|
||||
ASM ULONG myhw_CRC32( ASMR(a0) UBYTE *buffer ASMREG(a0),
|
||||
ASMR(d0) ULONG nbytes ASMREG(d0) )
|
||||
{
|
||||
UWORD i,j;
|
||||
ULONG t,crc = 0xffffffff;
|
||||
ULONG poly = 0x04c11db7;
|
||||
|
||||
for( j = 0 ; j < nbytes ; j++ )
|
||||
{
|
||||
for( i = 0 ; i < 8 ; i++ )
|
||||
{
|
||||
t = crc>>31;
|
||||
crc <<= 1;
|
||||
if( ( t ^ ( buffer[j] >> i ) ) & 0x01 )
|
||||
crc ^= poly;
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ASM ULONG CMPgeMAC( ASMR(a0) UBYTE *cur ASMREG(a0),
|
||||
ASMR(a1) UBYTE *cmp ASMREG(a1) )
|
||||
{
|
||||
USHORT i;
|
||||
ULONG res = 1;
|
||||
|
||||
for( i = 0 ; i < 6 ; i++ )
|
||||
{
|
||||
if( cur[i] > cmp[i] )
|
||||
break;
|
||||
if( cur[i] < cmp[i] )
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
ASM ULONG CMPleMAC( ASMR(a0) UBYTE *cur ASMREG(a0),
|
||||
ASMR(a1) UBYTE *cmp ASMREG(a1) )
|
||||
{
|
||||
USHORT i;
|
||||
ULONG res = 1;
|
||||
|
||||
for( i = 0 ; i < 6 ; i++ )
|
||||
{
|
||||
if( cur[i] < cmp[i] )
|
||||
break;
|
||||
if( cur[i] > cmp[i] )
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ASM void INCMAC( ASMR(a0) UBYTE *curmc ASMREG(a0) )
|
||||
{
|
||||
SHORT i;
|
||||
for( i=5 ; i >= 0 ; i-- )
|
||||
{
|
||||
curmc[i]++;
|
||||
if( curmc[i] != 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: implement Multicast hashing */
|
||||
ASM SAVEDS LONG hw_change_multicast( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(a1) struct List *mcastlist ASMREG(a1) )
|
||||
{
|
||||
/* TODO: implement Multicast hashing */
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
ULONG flags;
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
struct HWData *hwd = &db->db_hwdat;
|
||||
ULONG flags;
|
||||
ULONG crc,curhash;
|
||||
USHORT mc_hashes[4] = {0,0,0,0}; /* EHT1, EHT2, EHT3, EHT4 */
|
||||
USHORT *hash_tab;
|
||||
struct MCastEntry *mc;
|
||||
UBYTE *curmc;
|
||||
|
||||
flags = PIO_INIT_BROAD_CAST;
|
||||
|
||||
if( db->db_Units[0].du_Flags & DUF_PROMISC )
|
||||
flags |= PIO_INIT_PROMISC;
|
||||
|
||||
/* list non-empty ? (kludge right now, can be done more fine grained) */
|
||||
if( mcastlist->lh_Head->ln_Succ )
|
||||
if( hwd->multicast ) /* accept ALL multicast ? (config option) */
|
||||
flags |= PIO_INIT_MULTI_CAST;
|
||||
|
||||
enc624j6l_bc_mc_filter(boardbase, flags );/* flags & (PIO_INIT_BROAD_CAST|PIO_INIT_MULTI_CAST) ); */
|
||||
/* list non-empty ? */
|
||||
hash_tab = NULL;
|
||||
if( mcastlist->lh_Head->ln_Succ )
|
||||
{
|
||||
/* flags |= PIO_INIT_MULTI_CAST; */ /* see above */
|
||||
hash_tab = mc_hashes;
|
||||
|
||||
for( mc = (struct MCastEntry *)mcastlist->lh_Head;
|
||||
mc->mce_Node.mln_Succ ;
|
||||
mc=(struct MCastEntry*)mc->mce_Node.mln_Succ )
|
||||
{
|
||||
curmc = mc->mce_start;
|
||||
while( CMPleMAC( curmc, mc->mce_stop ) )
|
||||
{
|
||||
D(("CMPleMAC %ld %02lx%02lx%02lx%02lx%02lx%02lx - %02lx%02lx%02lx%02lx%02lx%02lx\n",\
|
||||
CMPleMAC( curmc, mc->mce_stop ),\
|
||||
(ULONG)curmc[0],(ULONG)curmc[1],\
|
||||
(ULONG)curmc[2],(ULONG)curmc[3],\
|
||||
(ULONG)curmc[4],(ULONG)curmc[5],\
|
||||
(ULONG)mc->mce_stop[0],(ULONG)mc->mce_stop[1],\
|
||||
(ULONG)mc->mce_stop[2],(ULONG)mc->mce_stop[3],\
|
||||
(ULONG)mc->mce_stop[4],(ULONG)mc->mce_stop[5] \
|
||||
));
|
||||
|
||||
crc = myhw_CRC32( mc->mce_start, 6 );
|
||||
curhash = (crc & 0x1f800000)>>23; /* 2 bit reg, 4 bit hash pos in reg */
|
||||
mc_hashes[ ((curhash >> 4)&3) ] |= 1<<(curhash&0xf);
|
||||
INCMAC( curmc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D(("hw_change_multicast board %lx flags %lx hashtab %lx\n",(ULONG)boardbase,(ULONG)flags,(ULONG)hash_tab));
|
||||
|
||||
enc624j6l_bc_mc_filter(boardbase, flags, hash_tab );/* flags & (PIO_INIT_BROAD_CAST|PIO_INIT_MULTI_CAST) ); */
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -494,7 +651,7 @@ void myhw_ControlInterrupts( DEVBASEP )
|
||||
hwd->hwd_Interrupt.is_Code = (void(*)())enc624j6l_IntServer_List;
|
||||
hwd->hwd_Interrupt.is_Data = &hwd->hwd_act_boards[0];
|
||||
hwd->hwd_Interrupt.is_Node.ln_Type = NT_INTERRUPT;
|
||||
hwd->hwd_Interrupt.is_Node.ln_Pri = 51;
|
||||
hwd->hwd_Interrupt.is_Node.ln_Pri = 126; /* 51; */
|
||||
hwd->hwd_Interrupt.is_Node.ln_Name = (char*)intname;
|
||||
AddIntServer( HW_INTSOURCE, &hwd->hwd_Interrupt );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user