updated LAN driver

This commit is contained in:
HenrykRichter
2019-03-20 09:02:11 +01:00
parent ec9088d70d
commit f97e75d972
20 changed files with 450 additions and 331 deletions
+127 -121
View File
@@ -1,4 +1,3 @@
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
; ------------------------------------------------------------------------------
; | Lowlevel Access to memory mapped ENC624J600 in PSP mode |
; | Henryk Richter <henryk.richter@gmx.net> |
@@ -20,14 +19,14 @@
; - _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 1
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"
include "hw.i"
ifnd DEBUG
DEBUG EQU 0
@@ -41,7 +40,7 @@ _OPT_LONGRESET EQU 0 ;in testing, don't enable
;
; options for buffer memory configuration, please reserve some space for private variables
;
PSTART_INIT EQU $0BF0 ; 16 Bytes private storage for driver
PSTART_INIT EQU $0BF8 ; 8 Bytes private storage for driver
PSTOP_INIT EQU $0BFF ; (see below for definitions)
RXSTART_INIT EQU $0C00 ; start of RX buffer, room for 14 packets
@@ -57,10 +56,8 @@ MAX_FRAMELEN EQU 1518
;------------ driver private storage ------------------------------
PNextPacket EQU PSTART_INIT ;2 Bytes - private "next packet" pointer for RX
PNextTX EQU PSTART_INIT+2 ;2 Bytes - private "next packet" pointer for TX (init as 0)
PSigBit EQU PSTART_INIT+4 ;2 Bytes interrupt bit
PSigTask EQU PSTART_INIT+6 ;4 Bytes signaled task
PLinkChange EQU PSTART_INIT+10 ;2 Bytes Link Change (copy of PHYDPX,PHYLNK bits)
Punused EQU PSTART_INIT+12 ;
PLinkChange EQU PSTART_INIT+4 ;2 Bytes Link Change (copy of PHYDPX,PHYLNK bits)
Punused EQU PSTART_INIT+6 ;
;------------- TX: double buffering --------------------------------
PSwapTX EQU $600 ;swap between two TX buffers (one active, one activated after last TX done)
@@ -560,6 +557,8 @@ _enc624j6l_Init:
move.l a0,d0
beq .err
WRITEDEBUG Init_MSG,a0
READREG ESTAT,a0,d0
and #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0
cmp #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0
@@ -787,20 +786,13 @@ _enc624j6l_EnableInterrupt:
move.l a0,d1
beq.s .err
WRITEREG PSigBit,a0,d0 ;save signal bit
move.l a1,d0
WRITEREG PSigTask+2,a0,d0 ;lower two bytes
swap d0 ;
WRITEREG PSigTask,a0,d0 ;upper two bytes
; enable interrupt for incoming packet
moveq #-1,d0 ;magic trick: the board enables Interrupts
lea $4000(a0),a0
move.w d0,($4000,a0)
lea -$4000(a0),a0
move #EIE_PKTIE|EIE_PCFULIE|EIE_INTIE,d0
move #EIE_PKTIE|EIE_INTIE|EIE_PCFULIE,d0
SETREG EIE,a0,d0
moveq #1,d0
@@ -823,8 +815,20 @@ _enc624j6l_EnableInterrupt:
; Notes: assumes that init() was called before
;
_enc624j6l_EnableGlobalInterrupt:
move #EIE_PKTIE|EIE_PCFULIE|EIE_INTIE,d0 ; move #EIE_INTIE,d0
SETREG EIE,a0,d0
ifne GLOBALINT_BOARD
moveq #-1,d0 ;magic trick: the board enables Interrupts
lea $4000(a0),a0
move.w d0,($4000,a0)
lea -$4000(a0),a0
else ;GLOBALINT_BOARD
move #EIE_PKTIE|EIE_INTIE|EIE_PCFULIE,d0
SETREG EIE,a0,d0
endc ;GLOBALINT_BOARD
moveq #1,d0
.rts
rts
@@ -842,8 +846,21 @@ _enc624j6l_EnableGlobalInterrupt:
; Notes: assumes that init() was called before
;
_enc624j6l_DisableGlobalInterrupt:
move #EIE_INTIE,d0
CLRREG EIE,a0,d0
ifne GLOBALINT_BOARD
moveq #0,d0 ;magic trick: the board enables Interrupts
lea $4000(a0),a0
move.w d0,($4000,a0)
lea -$4000(a0),a0
else ;GLOBALINT_BOARD
move #EIE_INTIE,d0
CLRREG EIE,a0,d0
endc ;GLOBALINT_BOARD
moveq #1,d0
.rts
rts
@@ -878,10 +895,6 @@ _enc624j6l_DisableInterrupt:
move #EIE_INTIE|EIE_PKTIE|EIE_LINKIE|EIE_AESIE|EIE_MODEXIE|EIE_HASHIE|EIE_PRDYIE|EIE_DMAIE|EIE_TXIE|EIE_TXABTIE|EIE_RXABTIE|EIE_PCFULIE,d0
CLRREG EIE,a0,d0
moveq #0,d0
WRITEREG PSigTask+2,a0,d0 ;lower two bytes
WRITEREG PSigTask,a0,d0 ;upper two bytes
moveq #1,d0
.err:
rts
@@ -905,35 +918,50 @@ _enc624j6l_DisableInterrupt:
; ULONG sigbit
;
_enc624j6l_IntServer_List:
move.l a6,-(sp)
move.l a1,d0 ;no pointer supplied ? -> return
beq.s .end
movem.l d1/A1/a6,-(sp)
beq.s .rts
move.l a1,a6
moveq #0,d1
move.l (A6)+,d0 ;read magic word
cmp.l #HW_MAGIC_WORD,D0 ; are we in the right structure?
bne.s .done
.boardloop:
move.l (A6)+,d0 ;next entry from list
move.l (a1)+,d0 ;next entry from list
beq.s .done ;
move.l d0,a1 ;current board
move.l d0,a0 ;current board
READREG EIR,A1,d0 ;get interrupt status reg
and #EIR_PKTIF|EIR_PCFULIF,D0
beq.s .boardloop ;no interrupt here
or.l d0,D1 ; save if at least one one board has interrupted
move #EIE_INTIE,D0 ;disable board interrupt until someone enables it again
CLRREG EIE,A1,d0
BRA.s .boardloop
READREG EIR,a0,d0 ;get interrupt status reg
and #EIR_PKTIF|EIR_PCFULIF|EIR_RXABTIF|EIR_PKTIF|EIR_TXABTIF,d0
or.l d0,d1
bra.s .boardloop
.done:
tst.w d1
beq.s .rts
; clear EIE_INTIE in all active boards directly from here
.intdis_loop:
move.l (a6)+,d0
beq.s .boardsdone
move.l d0,a1
ifne GLOBALINT_BOARD
moveq #0,d0 ;magic trick: the board enables Interrupts
lea $4000(a1),a1
move.w d0,($4000,a1)
else ;GLOBALINT_BOARD
move #EIE_INTIE,D0 ;disable board interrupt until someone enables it again
CLRREG EIE,A1,d0
endc ;GLOBALINT_BOARD
bra.s .intdis_loop
.boardsdone:
;faster: get from extended Driver board list instead from ZII/ZIII card
ifne 1
move.l (a6)+,d0 ;SigTask
beq.s .rts
@@ -941,33 +969,16 @@ _enc624j6l_IntServer_List:
move.l (a6)+,d1 ;SigBit
move.l d0,a1 ;SigTask
move.l (a6)+,a6 ;ExecBase
move.l (a6)+,a6 ;ExecBase (from FastRAM)
;move.l 4.w,a6
moveq #0,d0
bset d1,d0
else
READREG PSigTask,a0,d0 ;upper two bytes
swap d0 ;
READREG PSigTask+2,a0,d0 ;lower two bytes
tst.l d0 ; no task ?
beq.s .rts
move.l d0,a1 ; signaled task
moveq #0,d0
READREG PSigBit,a0,d1 ;get signal bit
bset d1,d0 ;signal mask
move.l 4.w,a6
endc
jsr _LVOSignal(a6)
.rts
movem.l (sp)+,D1/A1/A6
.end
move.l (sp)+,a6
moveq #0,d0 ;set Z flag
rts
@@ -1071,7 +1082,11 @@ _enc624j6l_CheckLinkChange:
;
ifne DEBUG
RXReset_MSG: dc.b "RXReset Head %04lx Tail %04lx NextPacket %04lx ReadPTR %04lx Bytes %04lx",10,0
RXReset_MSG: dc.b "RXReset Head %04lx Tail %04lx NextPacket %04lx NextReadPTR %04lx Bytes(maybe) %04lx ESTAT %04lx",13,10,0
Init_MSG: dc.b "ENC624j6net init (debug build) board address %lx",13,10,0
TXWait_MSG: dc.b "TransmitFrame: waiting",13,10,0
TXAbort_MSG: dc.b "TransmitFrame: abort",13,10,0
cnop 0,4
endc
_enc624j6l_RXReset:
@@ -1084,6 +1099,8 @@ _enc624j6l_RXReset:
moveq #0,d1
moveq #0,d2
moveq #0,d3
moveq #0,d7
READREG ESTAT,a0,d7
READREG ERXHEAD,A0,d0
READREG ERXTAIL,A0,d1
READREG PNextPacket,a0,d2
@@ -1092,19 +1109,16 @@ _enc624j6l_RXReset:
rol.w #8,d3 ;swap pointer to Big Endian
endc ;d3=next Packet (from receive status vector)
moveq #2,d5
add d2,d5 ;increment pointer by one word
moveq #2,d5
add d2,d5 ;increment pointer by one word
WRAPINDEX d5 ;wrap D4 if beyond buffer
READSRAM a0,d5,d4 ;receive byte count
READSRAM a0,d5,d4 ;receive byte count
ifeq _OPT_BUFFER_SWAP
rol.w #8,d4 ;swap pointer to Big Endian
endc
WRITEDEBUG RXReset_MSG,d0,d1,d2,d3,d4
WRITEDEBUG RXReset_MSG,d0,d1,d2,d3,d4,d7
movem.l (sp)+,d2-d7
endc
@@ -1194,16 +1208,18 @@ _enc624j6l_HaveRecv:
_enc624j6l_RecvFrame: ;
movem.l d2-d7/a1-a3,-(sp)
move.l a0,d1
beq .err
beq .err
moveq #0,d0
READREG ESTAT,a0,d2 ;number of pending frames
move.b d2,d0 ;clear out count (ESTAT_PKTCNT7...ESTAT_PKTCNT0)
beq .rts ;nothing in buffer, return sheer emptiness
beq .rts ;nothing in buffer, return sheer emptiness
;at least one frame in buffer
ifne DEBUG
READREG ERXHEAD,A0,d4
READREG ERXTAIL,A0,d5
endc
;----------- check next packet pointer and verify expected state -----------
READREG PNextPacket,a0,d7 ;get user read pointer from private space
@@ -1215,15 +1231,6 @@ _enc624j6l_RecvFrame: ;
rol.w #8,d0 ;swap pointer to Big Endian
endc
; btst #0,d0
; beq.s .nozerobit
; nop
;.nozerobit
; btst #0,d7
; beq.s .nozerobit2
; nop
;.nozerobit2
;verify next packet pointer, re-initialize recv if this is invalid
cmp #RXSTOP_INIT,d0 ;bad pointer (<0 or >end of memory)
bhi.w .recv_err
@@ -1238,55 +1245,40 @@ _enc624j6l_RecvFrame: ;
add.w d0,d1 ;next pkt + unwrap distance
.ptrcheck:
sub.w d7,d1 ;length of pkt
cmp #MAX_FRAMELEN+2+6,d1 ;must be smaller than max framelen + ptr + status vector
cmp #MAX_FRAMELEN+2+6+2,d1 ;must be smaller than max framelen + ptr + status vector + alignment
bhi .recv_err ;-> reinit recv (am I paranoid ? -> try ENC28J60, then you know why...)
;debug: collect packet positions
;move.l recvptr,a2
;move d0,(a2)+
;move.l a2,recvptr
;addq.l #1,recvcount
;cmp.l #65536,recvcount
;bgt .recv_err
WRITEREG PNextPacket,a0,d0 ;write pointer for next packet
;------------------ check receive status vector -----------------------------
addq.w #2,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer
;lea (a0,d7.w),a2 ;read ptr for first control word
;READREG 0,a2,d0 ;last control word = length (byte count)
READSRAM a0,d7,d0 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP
rol.w #8,d0 ;swap pointer to Big Endian
ifne 0
READSRAM a0,d7,d2 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP
rol.w #8,d2 ;swap pointer to Big Endian
endc
and.w #$f800,d2 ;verify (should be all zeros in upper 9 bits)
bne .recv_err ;receive buffer is wrong -> re-initialize
endc
and.w #$f800,d0 ;verify (should be all zeros in upper 9 bits)
bne .recv_err ;receive buffer is wrong -> re-initialize
addq.w #4,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer
;lea (a0,d7.w),a2 ;new read pointer for length
;READREG 0,a2,d0 ;last control word = length (byte count)
READSRAM a0,d7,d0 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP
rol.w #8,d0 ;swap pointer to Big Endian
endc
ifne 1
WRITEREG PNextPacket,a0,d0 ;write pointer for next packet
ifne 0
;lea (a0,d7.w),a2 ;new read pointer for length
;READREG 0,a2,d0 ;last control word = length (byte count)
READSRAM a0,d7,d2 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP
rol.w #8,d2 ;swap pointer to Big Endian
endc ;_OPT_BUFFER_SWAP
endc ;0
;D1 is the distance to the next frame = stored length + recv vevtor
sub #6+2,d1 ;STATUS VECTOR, Pointer
subq #6+2,d1 ;STATUS VECTOR, Pointer
move d1,d0 ;
else
cmp #2,d0
blt .recv_err ;can't be: SRC MAC 6 DST MAC 6 LEN/TYPE 2 CRC 4 (discounting variable data)
cmp #MAX_FRAMELEN,d0
bgt .recv_err
endc
subq #4,d0 ;subtract CRC length
addq.w #2,d7 ;increment pointer (skip status vector length field)
@@ -1365,6 +1357,10 @@ _enc624j6l_RecvFrame: ;
bra.s .end_read
.nooptrecv:
;DEBUG ONLY
;bra.s .emergency_slow
;DEBUG ONLY
ifeq _OPT_BUFFER_SWAP ;1
;
;wraparound aware loop for big endian buffer
@@ -1462,7 +1458,13 @@ _enc624j6l_RecvFrame: ;
rts
.err: moveq #-1,d0 ;receive error
bra.s .rts
.recv_err:
moveq #0,d0
READREG ESTAT,a0,d2 ;number of pending frames
move.b d2,d0 ;clear out count (ESTAT_PKTCNT7...ESTAT_PKTCNT0)
beq.s .rts ;nothing in buffer, return sheer emptiness
;serious problem: we need to re-initialize the recv buffer here
bsr _enc624j6l_RXReset
@@ -1613,18 +1615,22 @@ _enc624j6l_TransmitFrame:
.copydone
;---------------- wait on last frame ----------------------------------
move #200,d3
move #600,d3 ;
.txwait:
READREG ECON1,a0,d1
and.w #ECON1_TXRTS,d1
beq.s .txrdy
;100 MBit/s frame time is max. 0.12 ms (without inter-frame spacing)
;wait 20 us via CIA
moveq #20,d0
;WRITEDEBUG TXWait_MSG
;wait 5 us via CIA
moveq #5,d0
bsr _enc624j6l_UMinDelay
dbf d3,.txwait ;approx. 4ms max. wait
WRITEDEBUG TXAbort_MSG
;hmpf. abort last transmission
move #ECON1_TXRTS,d1 ;
CLRREG ECON1,a0,d1 ;
+2 -4
View File
@@ -460,9 +460,7 @@ void myhw_ControlInterrupts( DEVBASEP )
ObtainSemaphore( &hwd->hwd_Sem ); /* redundant here: server is a single task -> but it looks good :-) */
hwd->hwd_act_boards[0] = HW_MAGIC_WORD;
flag = 1;
flag = 0;
for( i=0 ; i < db->db_NBoards ; i++ )
{
if( db->db_Units[i].duh_online )
@@ -476,7 +474,7 @@ void myhw_ControlInterrupts( DEVBASEP )
hwd->hwd_act_boards[flag+2] = (APTR)hwd->hwd_IntSig; /* append sigbit */
hwd->hwd_act_boards[flag+3] = (APTR)db->db_SysBase; /* append ExecBase *((APTR*)0x4); */
if( flag>1 ) /* determine on/off switch */
if( flag ) /* determine on/off switch */
{
/* at least 1 board is online */
if( hwd->hwd_Interrupt.is_Data )