Updated Zorro-LAN-IDE Driver to 2.15

- Multicast fixes
- new Microchip OUIs added to verification table
This commit is contained in:
Henryk Richter
2026-03-02 10:41:17 +01:00
parent 0f18ce181d
commit 52ba722800
26 changed files with 1284 additions and 93 deletions
+378 -5
View File
@@ -23,11 +23,13 @@
DEBUG EQU 0
GLOBALINT_BOARD EQU 0 ;if 1, then toggle board interrupt, else ENC624 INTIE
OPT_AVOID_DEFAULT_RESETS EQU 1 ;if 1, then check valid Microchip MAC OUI and don't reset the whole chip if the MAC address is ok
OPT_Z2_WORDREAD EQU 1 ;read words instead of Longs on Z2 (specifically, 68030)
incdir src:baxnet/trunk/source/
;Temp:Amiga/src/Zorro-LAN-IDE.git/Driver/enc624j6net/
include "enc624j6net/registers.i"
include "enc624j6net/macros.i"
include "hw.i"
ifnd DEBUG
DEBUG EQU 0
@@ -129,6 +131,9 @@ ENC_BOARDID EQU 123 ;ZII-IDE-LAN-CP
XDEF _enc624j6l_ReadPHY
XDEF _enc624j6l_WritePHY
ifne OPT_Z2_WORDREAD
XDEF _enc624j6l_Z2Mode
endc
;
; System includes
@@ -457,7 +462,16 @@ a
dc.b $04,$91,$62,0
dc.b $54,$10,$EC,0
dc.b $80,$1F,$12,0
dc.b $D8,$80,$39,0
dc.b $D8,$80,$39,0
;new registrations by Microchip
dc.b $e8,$eb,$1b,0 ; 23-Jun-2020
dc.b $80,$34,$28,0 ; 22-Dec-2020
dc.b $60,$8a,$10,0 ; 30-Mar-2021
dc.b $fc,$0f,$e7,0 ; 10-Sep-2021
dc.b $9c,$95,$6e,0 ; 21-Apr-2022
dc.b $44,$b7,$d0,0 ; 02-Aug-2022
dc.b $D8,$47,$8f,0 ; 13-Jan-2023
dc.b $40,$84,$32,0 ; 30-Mar-2023
dc.b 0,0,0,0
.dorst:
@@ -657,7 +671,7 @@ _enc624j6l_Init:
move #RXSTOP_INIT&$fffe,d0
WRITEREG ERXTAIL,a0,d0 ;tail pointer in buffer = rx-2, wraparound
; ifne _OPT_FLOWCONTROL
; ifne _OPT_FLOWCONTROL ;this is now a runtime option
moveq #PIO_INIT_FLOW_CONTROL,d0
and d1,d0
beq.s .init_noflow
@@ -809,7 +823,50 @@ _enc624j6l_SetOnline:
moveq #0,d0
WRITEREG PLinkChange,a0,d0 ;no detected/acknowledged link right now, i.e. LNK and DPX bits = 0
ifne 1
moveq #48,d0 ;was: 12
move.l d0,-(sp)
.an_wait_loop:
moveq #100,d0 ;
lsl.l #5,d0 ;wait 3.2ms (0.1*32)
bsr _enc624j6l_UMinDelay ;
moveq #PHSTAT1,d0 ;AUTONEG DONE, forced speeds/duplex
bsr _enc624j6l_ReadPHY
and.w #PHSTAT1_ANDONE,d0 ;autoneg success?
beq.s .an_not_finished
bsr _enc624j6l_CheckLinkChange ;
bra.s .an_finished
.an_not_finished:
subq.l #1,(sp)
bgt.s .an_wait_loop
.an_finished:
addq.l #4,sp
endc
ifne 0
;---------------- until HW comes upe ----------------------------------
;
;wait 256 us
;
moveq #40,d1 ;
.txwait:
READREG ECON1,a0,d0
and.w #ECON1_TXRTS,d0
beq.s .txrdy
;100 MBit/s frame time is max. 0.12 ms (without inter-frame spacing)
;WRITEDEBUG TXWait_MSG
;wait 5 us via CIA
moveq #5,d0
bsr _enc624j6l_UMinDelay
dbf d1,.txwait ;approx. 1ms max. wait
.txrdy:
endc
;moveq #1,d0 ;already set, see above
.err
rts
@@ -1073,6 +1130,7 @@ _enc624j6l_IntServer_List:
; In: A0 = board base address
;
; Out: D0 <0 error
;
; =0 ok, no link change handled
; >0 ok, link change handled
;
@@ -1080,7 +1138,7 @@ _enc624j6l_IntServer_List:
;
_enc624j6l_CheckLinkChange:
move.l a0,d0
beq.s .rts
beq.s .err ;error: we don't have a board
; link change events are captured with Interrupts and stored
; in the (custom) PLinkChange location (per board) by init and
@@ -1145,7 +1203,8 @@ _enc624j6l_CheckLinkChange:
moveq #0,d0
.rts:
rts
.err: moveq #HW_MAC_INVALID,d0 ;-1
rts
;---------------------------------------------------------------------------------------
;
@@ -1272,6 +1331,305 @@ _enc624j6l_HaveRecv:
bra.s .rts
ifne OPT_Z2_WORDREAD
;---------------------------------------------------------------------------------------
;
; receive single frame from HW into supplied memory buffer (Z2 Only)
;
; input: A0 - APTR mmapped board base address
; A1 - APTR buffer for received frame
; D0 - SHORT maximum size in buffer
;
; output: D0 <0 - error (i.e. frame too large)
; 0 - no pending frames
; >0 - size of received frame in buffer
;
; trash: -
;
; notes:
;
_enc624j6l_RecvFrameZ2:
;WORD READS ONLY
movem.l d2-d7/a1-a3,-(sp)
move.l a0,d1
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
;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
;lea (a0,d7.w),a2 ;read ptr for next packet address
;READREG 0,a2,d0 ;next packet pointer
READSRAM a0,d7,d0 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP
rol.w #8,d0 ;swap pointer to Big Endian
endc
;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
cmp d0,d7
bgt.s .maybewrap
;unwrapped next packet
move d0,d1
bra.s .ptrcheck
.maybewrap:
;wrapped next packet ?
move #RXSTOP_INIT+1-RXSTART_INIT,d1 ;unwrap distance
add.w d0,d1 ;next pkt + unwrap distance
.ptrcheck:
sub.w d7,d1 ;length of pkt
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...)
;------------------ check receive status vector -----------------------------
addq.w #2,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer
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
addq.w #4,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer
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
subq #6+2,d1 ;STATUS VECTOR, Pointer
move d1,d0 ;
subq #4,d0 ;subtract CRC length
addq.w #2,d7 ;increment pointer (skip status vector length field)
WRAPINDEX d7 ;wrap D7 if beyond buffer
;d0.w: length (without crc)
;d7.w: read position (beginning of frame, dest MAC)
;a0: board I/O
;a1: dest pointer
move.l a1,a3
ifne _OPT_RECV
move.l d7,d1 ;start
;and.l #$FFFF,d1 ;keep only lower address
add.w d0,d1 ;start+bytes
bvs.s .nooptrecv ;what? beyond 16 Bit ? -> we really should consider this an error, really :-)
cmp.w #RXSTOP_INIT,d1 ;
bgt.s .nooptrecv ;sadly, we cannot use faster routine atm, because we have a wrap around in the SRAM buffer
ifne _OPT_ADR_QUIRK
eor.w #$6000,d7
endc ;_OPT_ADR_QUIRK
lea (a0,d7.w),a2 ;read pointer
ifeq _OPT_BUFFER_SWAP
btst #1,d7 ;do we have a read address that`s not long aligned?
beq.s .no_impair
move.w (a2)+,(a1)+ ;long-align address
subq #2,d0
ble.w .end_read ;should not happen (>14 per valid frame)
moveq #15,d1 ;
move.l d0,d2 ;total bytes
and.l d0,d1 ;remainder: max 15 bytes
lsr.w #4,d2 ;total/16
addq #2,d0
bra.s .impair
.no_impair:
move.l d0,d2 ;total bytes
moveq #15,d1 ;
lsr.w #4,d2 ;total/16
and.l d0,d1 ;remainder: max 15 bytes
.impair:
addq #3,d1 ;remainder, rounded up to +3 bytes
subq #1,d2 ;dbf
blt.s .nopt16_read ;less than 16 bytes -> bail out
bra.s .opt16_read
.opt16_loop:
move.w d3,(a1)+
.opt16_read:
rept 3
move.w (a2)+,(a1)+
move.w (a2)+,(a1)+
endr
move.w (a2)+,(a1)+
move.w (a2)+,d3
dbf d2,.opt16_loop
move.w d3,(a1)+
.nopt16_read:
else ;_OPT_BUFFER_SWAP
moveq #3,d1 ;round bytes up
add d0,d1 ;byte count + 3
endc ;_OPT_BUFFER_SWAP
lsr #2,d1 ;converted to dword count = ceil(bytes/4)
subq #1,d1 ;longwords - 1
blt.s .end_read
.opt_read:
ifne _OPT_BUFFER_SWAP
move.w (a2)+,d2 ;get current word
rol.w #8,d2 ;swap buffer to Big Endian
move.w d2,(a1)+
move.w (a2)+,d2
rol.w #8,d2 ;swap buffer to Big Endian
move.w d2,(a1)+
else ;_OPT_BUFFER_SWAP
move.w (a2)+,(a1)+
move.w (a2)+,(a1)+
endc ;_OPT_BUFFER_SWAP
dbf d1,.opt_read
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
;
move.w #RXSTOP_INIT+1,d1 ;end address $6000
lea (a0,d7.w),a2 ;read pointer
sub.w d7,d1 ;minus start pointer = number of bytes until wrap
cmp.w d0,d1 ;
bhi.s .emergency_slow ;don`t trust anyone: if d1<0 or >total_length, then branch to slow routine
move d1,d2
lsr #2,d2 ;we copy long words
subq #1,d2 ;dbf
blt.s .nowords_beforewrap ;
.loop_beforewrap:
move.w (a2)+,(a1)+
move.w (a2)+,(a1)+
dbf d2,.loop_beforewrap
.nowords_beforewrap: ;
btst #1,d7 ;uneven longword address before wraparound ?
beq.s .copy_afterwrap
move.w (a2)+,(a1)+ ;copy word from uneven address
.copy_afterwrap:
move #RXSTART_INIT,d7 ;wrap
lea (a0,d7.w),a2 ;read pointer
move d0,d2 ;total bytes to read
sub.w d1,d2 ;remaining=total-copied (D1=RXSTOP_INIT+1-D7)
ble.s .end_read ;done, if zero
move d2,d1 ;
lsr #2,d2 ;we copy long words
bra.s .enter_afterwrap
.loop_afterwrap:
move.w (a2)+,(a1)+
move.w (a2)+,(a1)+
.enter_afterwrap:
dbf d2,.loop_afterwrap
and.b #3,d1 ;btst #1,d1 ;1 byte or short remaining ?
beq.s .end_read
move.w (a2)+,(a1)+
bra.s .end_read
.emergency_slow:
endc ;_OPT_BUFFER_SWAP
endc ;_OPT_RECV
;generic loop: check for position overflows with each word
;
;CAUTION: DWORD loop doesn`t apply here since buffer is organized
; in multiples of two bytes, same for frame lengths and
; possible wraparounds
;
moveq #1,d2 ;mask for lower bit
move d0,d1 ;byte count
lsr #1,d1 ;converted to word count
and.l d0,d2 ;if lower bits are set ->
bne.s .generic_read ;read 1 word more if impair byte/word count
subq #1,d1 ;words - 1
.generic_read:
move.w (a0,d7.w),d2 ;get current word
ifne _OPT_BUFFER_SWAP
rol.w #8,d2 ;swap buffer to Big Endian
endc
move.w d2,(a1)+ ; store currend word
addq #2,d7 ;increment position
WRAPINDEX d7 ;wrap D7 if beyond buffer
dbf d1,.generic_read
.end_read:
;frame copied, now advance HW pointer
READREG PNextPacket,a0,d1 ;write pointer for next packet
cmp #RXSTART_INIT,d1
bne.s .tail_nowrap
move #(RXSTOP_INIT&$fffe)+2,d1
.tail_nowrap:
subq #2,d1
WRITEREG ERXTAIL,a0,d1 ;tail pointer in buffer = rx-2, wraparound
move #ECON1_PKTDEC,d1
SETREG ECON1,a0,d1 ;set packet decrement ("frame", actually)
ext.l d0
ifne ADD_4RX
addq.l #4,d0 ;+4 (fake CRC) for Shapeshifter, also see server.c plain copy mode
endc
cmp.w #14,d0
bge.s .rts
moveq #0,d0
.rts:
movem.l (sp)+,d2-d7/a1-a3
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
moveq #ECON1_RXEN,d0 ;re-enable reception
SETREG ECON1,a0,d0
moveq #0,d0
bra.s .rts
endc
;---------------------------------------------------------------------------------------
;
; receive single frame from HW into supplied memory buffer
@@ -1289,10 +1647,17 @@ _enc624j6l_HaveRecv:
; notes:
;
_enc624j6l_RecvFrame: ;
ifne OPT_Z2_WORDREAD
tst.l Z2Mode
bne.w _enc624j6l_RecvFrameZ2
endc
movem.l d2-d7/a1-a3,-(sp)
move.l a0,d1
beq .err
moveq #0,d0
READREG ESTAT,a0,d2 ;number of pending frames
move.b d2,d0 ;clear out count (ESTAT_PKTCNT7...ESTAT_PKTCNT0)
@@ -1899,4 +2264,12 @@ _enc624j6l_UMinDelay:
;recvcount: dc.l 0
;recvlist: ds.w 65536
;separate section necessary with SAS/C
section data,data
Z2Mode:
_enc624j6l_Z2Mode:
dc.l 0
END