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:
Henryk Richter
2019-04-13 21:13:28 +02:00
parent 5c8a5c12ed
commit 7c19cf2fd1
14 changed files with 285 additions and 62 deletions
+37 -11
View File
@@ -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:
+3 -2
View File
@@ -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));
/*
+166 -9
View File
@@ -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 );
}