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
+12
View File
@@ -64,6 +64,18 @@ PRIORITY=PRI/K/N,BPS/K/N,MTU/K/N,FULLDUPLEX/S,FLOWCONTROL/S,TIMER/K/N,MULTICAST/
Changelog: Changelog:
---------- ----------
2.2 - some more tuning to RX/TX scheduling
- added optional debug code to lowlevel routines
- removed some obsolete bus transfers
- uses DMACopyFromBuffer for IP-stacks supporting
this capability
- explicit 32 bit alignment for RX/TX to speed up
ZIII transfers
- added experimental support for MII interface to
poll and modify speed and duplex settings on the
fly
- miitool added (see README.miitool)
2.00 - improved RX speed for buffer wraparound cases 2.00 - improved RX speed for buffer wraparound cases
- some more safety checks for boards with unresponsive - some more safety checks for boards with unresponsive
ENC chips (explicit card bus clear before verification of ENC chips (explicit card bus clear before verification of
+8 -1
View File
@@ -18,7 +18,11 @@ combination. Please note that fixed parameters must be set at both
ends of the link. Otherwise the link will work slowly or not at all. ends of the link. Otherwise the link will work slowly or not at all.
None of the settings this tool applies is permanent. Changed parameters None of the settings this tool applies is permanent. Changed parameters
are only valid until a reboot of the NIC. are only valid until the next reset of the NIC.
This utility is able to detect an active Ethernet interface in case that
the RoadShow TCP/IP stack is active. Otherwise, the device needs to be
passed as commandline option explicitly.
Examples for usage are given at the end of this text. Examples for usage are given at the end of this text.
@@ -80,6 +84,9 @@ Valid Speed/Duplex combinations (not case sensitive):
Examples: Examples:
current status (detailed, autodetect)
miitool v
current status (detailed): current status (detailed):
miitool DEV=enc624j6net.device v miitool DEV=enc624j6net.device v
-102
View File
@@ -1,102 +0,0 @@
VWiznet - A SANA-II driver for W5500 10/100 ethernet modules
Copyright (C) 2018-2019 Henryk Richter <henryk.richter@gmx.net>
This driver is supposed to support W5500 modules hooked up to the expansion
port of Vampire 500V2+ cards.
Installation:
-------------
Installation of the driver is straightforward.
Just copy vwiznet500ex.device from the bin subdirectory to devs:networks
and enable the interface in your favorite TCP/IP stack as usual. So far,
successful tests have been done with the free AmiTCP/IP 3.0b2, AmiTCP4.0-4.2,
Genesis, MiamiDX and RoadShow.
The minimum system requirement is the Gold 2.10 release of Apollo Core
for Vampire 500V2+.
Vampire500 Expansion port Hardware
-----------------------------------
Please see http://wiki.apollo-accelerators.com/doku.php/expansionport for
guidance on pinout of the expansion port.
The W5500 can be clocked way higher than the ENC28J60 that was used for
SDNet. As a consequence of clocks beyond 25 MHz, signal integrity is of
some concern. Therefore it is suggested to connect the module is as close
as possible to the expansion port and use an Ethernet expansion cable
in order to reach the edge of the computer case.
An adapter PCB is in the making. That PCB plugs directly into the Vampire
expansion port, connects readily available W5500 modules on the other
side and contains some components to keep signal integrity in a good shape.
Options
-------
Below you find the options accepted by the driver. Please note that no special
configuration is necessary for normal operation. What you find documented below
is available for tuning purposes.
The options template for the config files
ENVARC:SANA2/vwiznet500ex.config
is as follows:
PRIORITY=PRI/K/N,BPS/K/N,MTU/K/N,SPISPEED/K/N,TIMER/K/N,NOINTERRUPT/S
SPISPEED - SPI clock divider (1-10, default 1), controls maximum
clock of SPI bus. Actual I/O clock is Core_Clock/(3+SPISPEED).
PRIORITY - server task priority (default 1)
BPS - bit per seconds for statistics purposes
MTU - maximum transmission unit (default 1500)
NOINTERRUPT - disable hardware interrupt and use polling instead
(default: interrupt enabled)
TIMER - when disabling interrupt you also need to specify
a timer interval in microseconds
(default: 0, i.e. no timer)
example1 (useful for DSL via PPPoE,
higher priority for server task = more speed with AmiTCP
at the expense of multitasking friendliness):
echo "MTU=1492 SPISPEED=1 PRIORITY=6" >ENVARC:sana2/vwiznet500ex.config
Changelog:
----------
1.99 - re-enabled 32 Bit Buffer copies (unless Miami is active)
- default server task priority for AmiTCP=6 (otherwise 0)
- tuned RX/TX balancing to make RoadShow happy
- added Packet Filter hook processing (needs testing)
1.98 - preparations for V2 of the adapter PCB: hardware based reset
1.97 - added New style device commands
- implemented SANA-II Device Query Extension
1.96 - tuned defaults
1.95 - initial build, aligned with sdnet/v2expeth version
Copyrights / License:
---------------------
Copyright (C) 2018-2019 Henryk Richter <henryk.richter@gmx.net>, all rights reserved.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+42 -23
View File
@@ -25,11 +25,15 @@ compiler_vcc = 1
############################################################################### ###############################################################################
# prefix for system includes (ASM) # prefix for system includes (ASM)
# # native AmigaOS compilation: set PREFX=GG: or PREFX=ADE:, depending on toolchain
############################################################################### ###############################################################################
PREFX = c:/Users/Matze/Amiga/development/VBCC/
PREFX = /opt/amigaos-68k/
#PREFX = gg: #PREFX = gg:
SYSINC = $(PREFX)NDK39/Include/include_i #PREFX = c:/Users/Matze/Amiga/development/VBCC/
SYSINC = $(PREFX)os-include
#SYSINC = $(PREFX)NDK39/Include/include_i
############################################################################### ###############################################################################
# #
@@ -41,6 +45,7 @@ ifeq ($(compiler_vcc),1)
# VBCC (use explicit vlink line for LINK= if complaints about R_PC happen) # VBCC (use explicit vlink line for LINK= if complaints about R_PC happen)
CCX = vc CCX = vc
LINK = vlink -bamigahunk -x -s -mrel -Cvbcc -Bstatic -nostdlib #-Rshort LINK = vlink -bamigahunk -x -s -mrel -Cvbcc -Bstatic -nostdlib #-Rshort
LINKEXE = vlink -bamigahunk -x -s -mrel -Cvbcc -Bstatic
#LINK = $(CCX) -nostdlib #LINK = $(CCX) -nostdlib
CFLAGS = -Os -+ -sc -c99 -cpu=$(CPU) CFLAGS = -Os -+ -sc -c99 -cpu=$(CPU)
CFLAGS2 = -Os -+ -sc -c99 -cpu=$(CPU2) CFLAGS2 = -Os -+ -sc -c99 -cpu=$(CPU2)
@@ -50,6 +55,7 @@ else
# GCC # GCC
CCX = m68k-amigaos-gcc CCX = m68k-amigaos-gcc
LINK = $(CCX) -nostartfiles -s LINK = $(CCX) -nostartfiles -s
LINKEXE = $(CCX) -s -noixemul
CFLAGS = -O3 -s -m$(CPU) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul CFLAGS = -O3 -s -m$(CPU) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul
CFLAGS2 = -O3 -s -m$(CPU2) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul CFLAGS2 = -O3 -s -m$(CPU2) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul
@@ -68,7 +74,7 @@ VASMFORMAT2 = -m$(CPU2) -Fhunk -nowarn=2064 -quiet -I$(SYSINC)
# #
############################################################################### ###############################################################################
IPATH = IPATH =
############################################################################### ###############################################################################
# #
@@ -77,29 +83,41 @@ IPATH =
############################################################################### ###############################################################################
ifeq ($(compiler_vcc),1) ifeq ($(compiler_vcc),1)
# skip quotes with VCC, the AmigaOS native version doesn't like them # skip quotes with VCC, the AmigaOS native version doesn't like them
DEFINES += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) #DEFINES += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
DEFINES += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME="$(DEVICEID)" #DEFINES += -DDEVICEDATE=$(DEVICEDATE)
DEFINES += -DDEVICEEXTRA=$(DEVICEEXTRA) #DEFINES += -DDEVICEEXTRA=$(DEVICEEXTRA)
ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) DEFINES += -DDEVICENAME="$(DEVICEID)"
DEFINES += -DHAVE_VERSION_H=1
DEFINES += -DNEWSTYLE
#ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID) #ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID)
DEFINES2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) #DEFINES2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
DEFINES2 += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME="$(DEVICEID2)" #DEFINES2 += -DDEVICEDATE=$(DEVICEDATE)
DEFINES2 += -DDEVICEEXTRA=$(DEVICEEXTRA) #DEFINES2 += -DDEVICEEXTRA=$(DEVICEEXTRA)
ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) DEFINES2 += -DDEVICENAME="$(DEVICEID2)"
DEFINES2 += -DHAVE_VERSION_H=1
DEFINES2 += -DNEWSTYLE
#ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
else else
DEFINES += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)" #DEFINES += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)"
DEFINES += -D"DEVICEDATE=$(DEVICEDATE)" -D"DEVICENAME="$(DEVICEID)"" #DEFINES += -D"DEVICEDATE=$(DEVICEDATE)"
DEFINES += -D"DEVICEEXTRA=$(DEVICEEXTRA)" #DEFINES += -D"DEVICEEXTRA=$(DEVICEEXTRA)"
ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) DEFINES += -D"DEVICENAME="$(DEVICEID)""
DEFINES += -DHAVE_VERSION_H=1
DEFINES += -DNEWSTYLE
#ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID) #ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID)
DEFINES2 += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)" #DEFINES2 += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)"
DEFINES2 += -D"DEVICEDATE=$(DEVICEDATE)" -D"DEVICENAME="$(DEVICEID2)"" #DEFINES2 += -D"DEVICEDATE=$(DEVICEDATE)" -D"DEVICENAME="$(DEVICEID2)""
DEFINES2 += -D"DEVICEEXTRA=$(DEVICEEXTRA)" #DEFINES2 += -D"DEVICEEXTRA=$(DEVICEEXTRA)"
ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION) DEFINES2 += -D"DEVICENAME="$(DEVICEID2)""
DEFINES2 += -DHAVE_VERSION_H=1
DEFINES2 += -DNEWSTYLE
#ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
endif endif
@@ -112,7 +130,8 @@ endif
ifeq ($(debug),1) ifeq ($(debug),1)
CFLAGS += -DDEBUG -g CFLAGS += -DDEBUG -g
CFLAGS2 += -DDEBUG -g CFLAGS2 += -DDEBUG -g
LINKLIBS = -L$(PREFX)targets/m68k-amigaos/lib -ldebug LINKLIBS = -L$(PREFX)/lib -L$(PREFX)targets/m68k-amigaos/lib -ldebug
#LINKLIBS = -L$(PREFX)targets/m68k-amigaos/lib -ldebug
endif endif
############################################################################### ###############################################################################
@@ -144,11 +163,11 @@ OBJECTS2 = $(patsubst %.o,%.2o,$(OBJECTS))
# #
############################################################################### ###############################################################################
all: $(DEVICEID) $(DEVICEID2) all: $(DEVICEID) $(DEVICEID2) $(TESTTOOL) $(TESTTOOL2)
clean: clean:
rm -f $(OBJECTS) $(OBJECTS2) rm -f $(OBJECTS) $(OBJECTS2)
rm -f $(DEVICEID) $(DEVICEID2) rm -f $(DEVICEID) $(DEVICEID2) $(EXTRACLEAN)
# not for cross compile :-) # not for cross compile :-)
install: $(DEVICEID) $(DEVICEID2) install: $(DEVICEID) $(DEVICEID2)
Binary file not shown.
Binary file not shown.
+127 -121
View File
@@ -1,4 +1,3 @@
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
; ------------------------------------------------------------------------------ ; ------------------------------------------------------------------------------
; | Lowlevel Access to memory mapped ENC624J600 in PSP mode | ; | Lowlevel Access to memory mapped ENC624J600 in PSP mode |
; | Henryk Richter <henryk.richter@gmx.net> | ; | Henryk Richter <henryk.richter@gmx.net> |
@@ -20,14 +19,14 @@
; - _enc624j6l_RXReset -> won't recover from totally unresponsive chip (but exits gracefully) ; - _enc624j6l_RXReset -> won't recover from totally unresponsive chip (but exits gracefully)
; ;
; enable debugging code block (comment/uncomment, see below) ; 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/ incdir src:baxnet/trunk/source/
;Temp:Amiga/src/Zorro-LAN-IDE.git/Driver/enc624j6net/ ;Temp:Amiga/src/Zorro-LAN-IDE.git/Driver/enc624j6net/
include "enc624j6net/registers.i" include "enc624j6net/registers.i"
include "enc624j6net/macros.i" include "enc624j6net/macros.i"
include "debug.i" include "debug.i"
include "hw.i"
ifnd DEBUG ifnd DEBUG
DEBUG EQU 0 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 ; 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) PSTOP_INIT EQU $0BFF ; (see below for definitions)
RXSTART_INIT EQU $0C00 ; start of RX buffer, room for 14 packets RXSTART_INIT EQU $0C00 ; start of RX buffer, room for 14 packets
@@ -57,10 +56,8 @@ MAX_FRAMELEN EQU 1518
;------------ driver private storage ------------------------------ ;------------ driver private storage ------------------------------
PNextPacket EQU PSTART_INIT ;2 Bytes - private "next packet" pointer for RX 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) 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 PLinkChange EQU PSTART_INIT+4 ;2 Bytes Link Change (copy of PHYDPX,PHYLNK bits)
PSigTask EQU PSTART_INIT+6 ;4 Bytes signaled task Punused EQU PSTART_INIT+6 ;
PLinkChange EQU PSTART_INIT+10 ;2 Bytes Link Change (copy of PHYDPX,PHYLNK bits)
Punused EQU PSTART_INIT+12 ;
;------------- TX: double buffering -------------------------------- ;------------- TX: double buffering --------------------------------
PSwapTX EQU $600 ;swap between two TX buffers (one active, one activated after last TX done) 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 move.l a0,d0
beq .err beq .err
WRITEDEBUG Init_MSG,a0
READREG ESTAT,a0,d0 READREG ESTAT,a0,d0
and #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0 and #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0
cmp #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0 cmp #(ESTAT_CLKRDY|ESTAT_PHYRDY),d0
@@ -787,20 +786,13 @@ _enc624j6l_EnableInterrupt:
move.l a0,d1 move.l a0,d1
beq.s .err 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 ; enable interrupt for incoming packet
moveq #-1,d0 ;magic trick: the board enables Interrupts moveq #-1,d0 ;magic trick: the board enables Interrupts
lea $4000(a0),a0 lea $4000(a0),a0
move.w d0,($4000,a0) move.w d0,($4000,a0)
lea -$4000(a0),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 SETREG EIE,a0,d0
moveq #1,d0 moveq #1,d0
@@ -823,8 +815,20 @@ _enc624j6l_EnableInterrupt:
; Notes: assumes that init() was called before ; Notes: assumes that init() was called before
; ;
_enc624j6l_EnableGlobalInterrupt: _enc624j6l_EnableGlobalInterrupt:
move #EIE_PKTIE|EIE_PCFULIE|EIE_INTIE,d0 ; move #EIE_INTIE,d0 ifne GLOBALINT_BOARD
SETREG EIE,a0,d0
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 moveq #1,d0
.rts .rts
rts rts
@@ -842,8 +846,21 @@ _enc624j6l_EnableGlobalInterrupt:
; Notes: assumes that init() was called before ; Notes: assumes that init() was called before
; ;
_enc624j6l_DisableGlobalInterrupt: _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 moveq #1,d0
.rts .rts
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 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 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 moveq #1,d0
.err: .err:
rts rts
@@ -905,35 +918,50 @@ _enc624j6l_DisableInterrupt:
; ULONG sigbit ; ULONG sigbit
; ;
_enc624j6l_IntServer_List: _enc624j6l_IntServer_List:
move.l a6,-(sp)
move.l a1,d0 ;no pointer supplied ? -> return move.l a1,d0 ;no pointer supplied ? -> return
beq.s .end beq.s .rts
movem.l d1/A1/a6,-(sp)
move.l a1,a6 move.l a1,a6
moveq #0,d1 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: .boardloop:
move.l (A6)+,d0 ;next entry from list move.l (a1)+,d0 ;next entry from list
beq.s .done ; beq.s .done ;
move.l d0,a1 ;current board move.l d0,a0 ;current board
READREG EIR,A1,d0 ;get interrupt status reg READREG EIR,a0,d0 ;get interrupt status reg
and #EIR_PKTIF|EIR_PCFULIF,D0 and #EIR_PKTIF|EIR_PCFULIF|EIR_RXABTIF|EIR_PKTIF|EIR_TXABTIF,d0
beq.s .boardloop ;no interrupt here
or.l d0,D1 ; save if at least one one board has interrupted or.l d0,d1
move #EIE_INTIE,D0 ;disable board interrupt until someone enables it again bra.s .boardloop
CLRREG EIE,A1,d0
BRA.s .boardloop
.done: .done:
tst.w d1 tst.w d1
beq.s .rts 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 ;faster: get from extended Driver board list instead from ZII/ZIII card
ifne 1
move.l (a6)+,d0 ;SigTask move.l (a6)+,d0 ;SigTask
beq.s .rts beq.s .rts
@@ -941,33 +969,16 @@ _enc624j6l_IntServer_List:
move.l (a6)+,d1 ;SigBit move.l (a6)+,d1 ;SigBit
move.l d0,a1 ;SigTask 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 moveq #0,d0
bset d1,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) jsr _LVOSignal(a6)
.rts .rts
movem.l (sp)+,D1/A1/A6 move.l (sp)+,a6
.end
moveq #0,d0 ;set Z flag moveq #0,d0 ;set Z flag
rts rts
@@ -1071,7 +1082,11 @@ _enc624j6l_CheckLinkChange:
; ;
ifne DEBUG 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 endc
_enc624j6l_RXReset: _enc624j6l_RXReset:
@@ -1084,6 +1099,8 @@ _enc624j6l_RXReset:
moveq #0,d1 moveq #0,d1
moveq #0,d2 moveq #0,d2
moveq #0,d3 moveq #0,d3
moveq #0,d7
READREG ESTAT,a0,d7
READREG ERXHEAD,A0,d0 READREG ERXHEAD,A0,d0
READREG ERXTAIL,A0,d1 READREG ERXTAIL,A0,d1
READREG PNextPacket,a0,d2 READREG PNextPacket,a0,d2
@@ -1092,19 +1109,16 @@ _enc624j6l_RXReset:
rol.w #8,d3 ;swap pointer to Big Endian rol.w #8,d3 ;swap pointer to Big Endian
endc ;d3=next Packet (from receive status vector) endc ;d3=next Packet (from receive status vector)
moveq #2,d5 moveq #2,d5
add d2,d5 ;increment pointer by one word add d2,d5 ;increment pointer by one word
WRAPINDEX d5 ;wrap D4 if beyond buffer 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 ifeq _OPT_BUFFER_SWAP
rol.w #8,d4 ;swap pointer to Big Endian rol.w #8,d4 ;swap pointer to Big Endian
endc endc
WRITEDEBUG RXReset_MSG,d0,d1,d2,d3,d4,d7
WRITEDEBUG RXReset_MSG,d0,d1,d2,d3,d4
movem.l (sp)+,d2-d7 movem.l (sp)+,d2-d7
endc endc
@@ -1194,16 +1208,18 @@ _enc624j6l_HaveRecv:
_enc624j6l_RecvFrame: ; _enc624j6l_RecvFrame: ;
movem.l d2-d7/a1-a3,-(sp) movem.l d2-d7/a1-a3,-(sp)
move.l a0,d1 move.l a0,d1
beq .err beq .err
moveq #0,d0 moveq #0,d0
READREG ESTAT,a0,d2 ;number of pending frames READREG ESTAT,a0,d2 ;number of pending frames
move.b d2,d0 ;clear out count (ESTAT_PKTCNT7...ESTAT_PKTCNT0) 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 ;at least one frame in buffer
ifne DEBUG
READREG ERXHEAD,A0,d4 READREG ERXHEAD,A0,d4
READREG ERXTAIL,A0,d5 READREG ERXTAIL,A0,d5
endc
;----------- check next packet pointer and verify expected state ----------- ;----------- check next packet pointer and verify expected state -----------
READREG PNextPacket,a0,d7 ;get user read pointer from private space 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 rol.w #8,d0 ;swap pointer to Big Endian
endc 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 ;verify next packet pointer, re-initialize recv if this is invalid
cmp #RXSTOP_INIT,d0 ;bad pointer (<0 or >end of memory) cmp #RXSTOP_INIT,d0 ;bad pointer (<0 or >end of memory)
bhi.w .recv_err bhi.w .recv_err
@@ -1238,55 +1245,40 @@ _enc624j6l_RecvFrame: ;
add.w d0,d1 ;next pkt + unwrap distance add.w d0,d1 ;next pkt + unwrap distance
.ptrcheck: .ptrcheck:
sub.w d7,d1 ;length of pkt 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...) 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 ----------------------------- ;------------------ check receive status vector -----------------------------
addq.w #2,d7 ;increment pointer addq.w #2,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer 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) ifne 0
READSRAM a0,d7,d0 ;move (a0,d7.w),d0 READSRAM a0,d7,d2 ;move (a0,d7.w),d0
ifeq _OPT_BUFFER_SWAP ifeq _OPT_BUFFER_SWAP
rol.w #8,d0 ;swap pointer to Big Endian 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 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 addq.w #4,d7 ;increment pointer
WRAPINDEX d7 ;wrap D7 if beyond buffer 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 ;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 ; 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 subq #4,d0 ;subtract CRC length
addq.w #2,d7 ;increment pointer (skip status vector length field) addq.w #2,d7 ;increment pointer (skip status vector length field)
@@ -1365,6 +1357,10 @@ _enc624j6l_RecvFrame: ;
bra.s .end_read bra.s .end_read
.nooptrecv: .nooptrecv:
;DEBUG ONLY
;bra.s .emergency_slow
;DEBUG ONLY
ifeq _OPT_BUFFER_SWAP ;1 ifeq _OPT_BUFFER_SWAP ;1
; ;
;wraparound aware loop for big endian buffer ;wraparound aware loop for big endian buffer
@@ -1462,7 +1458,13 @@ _enc624j6l_RecvFrame: ;
rts rts
.err: moveq #-1,d0 ;receive error .err: moveq #-1,d0 ;receive error
bra.s .rts bra.s .rts
.recv_err: .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 ;serious problem: we need to re-initialize the recv buffer here
bsr _enc624j6l_RXReset bsr _enc624j6l_RXReset
@@ -1613,18 +1615,22 @@ _enc624j6l_TransmitFrame:
.copydone .copydone
;---------------- wait on last frame ---------------------------------- ;---------------- wait on last frame ----------------------------------
move #200,d3 move #600,d3 ;
.txwait: .txwait:
READREG ECON1,a0,d1 READREG ECON1,a0,d1
and.w #ECON1_TXRTS,d1 and.w #ECON1_TXRTS,d1
beq.s .txrdy beq.s .txrdy
;100 MBit/s frame time is max. 0.12 ms (without inter-frame spacing) ;100 MBit/s frame time is max. 0.12 ms (without inter-frame spacing)
;wait 20 us via CIA ;WRITEDEBUG TXWait_MSG
moveq #20,d0
;wait 5 us via CIA
moveq #5,d0
bsr _enc624j6l_UMinDelay bsr _enc624j6l_UMinDelay
dbf d3,.txwait ;approx. 4ms max. wait dbf d3,.txwait ;approx. 4ms max. wait
WRITEDEBUG TXAbort_MSG
;hmpf. abort last transmission ;hmpf. abort last transmission
move #ECON1_TXRTS,d1 ; move #ECON1_TXRTS,d1 ;
CLRREG ECON1,a0,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 :-) */ ObtainSemaphore( &hwd->hwd_Sem ); /* redundant here: server is a single task -> but it looks good :-) */
hwd->hwd_act_boards[0] = HW_MAGIC_WORD; flag = 0;
flag = 1;
for( i=0 ; i < db->db_NBoards ; i++ ) for( i=0 ; i < db->db_NBoards ; i++ )
{ {
if( db->db_Units[i].duh_online ) 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+2] = (APTR)hwd->hwd_IntSig; /* append sigbit */
hwd->hwd_act_boards[flag+3] = (APTR)db->db_SysBase; /* append ExecBase *((APTR*)0x4); */ 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 */ /* at least 1 board is online */
if( hwd->hwd_Interrupt.is_Data ) if( hwd->hwd_Interrupt.is_Data )
+4 -3
View File
@@ -1,6 +1,7 @@
incdir include: incdir include:
ifnd _LVOSupervisor ifnd _LVOSupervisor
include exec/exec_lib.i include lvo/exec_lib.i
;include exec/exec_lib.i
endc endc
include exec/execbase.i include exec/execbase.i
@@ -18,7 +19,7 @@ _LVORawMayGetChar equ -$1fe
;A0 = format ;A0 = format
;A1 = arguments ;A1 = arguments
_KPrintF: _KPrintF:
ifd DEBUG ; ifd DEBUG
movem.l d0-d2/a0-a3/a6,-(sp) movem.l d0-d2/a0-a3/a6,-(sp)
@@ -37,7 +38,7 @@ _KPrintF:
jsr _LVORawPutChar(a6) ; move.b d0,(a3)+ jsr _LVORawPutChar(a6) ; move.b d0,(a3)+
movem.l (sp)+,d0/d1/a0/a1/a6 movem.l (sp)+,d0/d1/a0/a1/a6
endc ;DEBUG ; endc ;DEBUG
rts rts
+205 -73
View File
@@ -4,7 +4,6 @@
/** SANA-II extension for access to Ethernet PHY registers over MII interface **/ /** SANA-II extension for access to Ethernet PHY registers over MII interface **/
/** **/ /** **/
/** Copyright (c) 2019, Henryk Richter, Timm S. Müller **/ /** Copyright (c) 2019, Henryk Richter, Timm S. Müller **/
/** All rights reserved. **/
/** **/ /** **/
/** Redistribution and use in source and binary forms, with or without **/ /** Redistribution and use in source and binary forms, with or without **/
/** modification, are permitted provided that the following conditions are met: **/ /** modification, are permitted provided that the following conditions are met: **/
@@ -16,9 +15,6 @@
/** 3. All advertising materials mentioning features or use of this software **/ /** 3. All advertising materials mentioning features or use of this software **/
/** must display the following acknowledgement: **/ /** must display the following acknowledgement: **/
/** This product includes software developed by Henryk Richter. **/ /** This product includes software developed by Henryk Richter. **/
/** 4. Neither the name of the Henryk Richter nor the **/
/** names of its contributors may be used to endorse or promote products **/
/** derived from this software without specific prior written permission. **/
/** **/ /** **/
/** THIS SOFTWARE IS PROVIDED BY Henryk Richter ''AS IS'' AND ANY **/ /** THIS SOFTWARE IS PROVIDED BY Henryk Richter ''AS IS'' AND ANY **/
/** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED **/ /** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED **/
@@ -32,15 +28,22 @@
/** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ /** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/
/** **/ /** **/
/*******************************************************************************************/ /*******************************************************************************************/
/** Acknowledgements: **/
/** text and definitions in "media" table and "miitool.h" file originate from mii-tool.c **/
/** written/copyright 1997-2000 by Donald Becker **/
/*******************************************************************************************/
/* /*
Notes: Notes:
- make sure you have an up-to-date devices/sana2devqueryext.h - make sure you have an up-to-date devices/sana2devqueryext.h
- make sure you have devices/newstyle.h - make sure you have devices/newstyle.h
- compilation - compilation
sc miitool.c link sc miitool.c link INCLUDEDIR=sc:netinclude
gcc miitool.c -Igg:netinclude -o miitool
- if you don`t have the Roadshow SDK installed, just comment "RSHOW" out to build
without auto-detection code
*/ */
#define RSHOW
#include <proto/exec.h> #include <proto/exec.h>
#include <proto/dos.h> #include <proto/dos.h>
@@ -49,8 +52,17 @@
#include <devices/sana2.h> #include <devices/sana2.h>
#include <devices/sana2devqueryext.h> #include <devices/sana2devqueryext.h>
#include "miitool.h" #include "miitool.h"
#ifdef RSHOW
#include <libraries/bsdsocket.h>
#include <proto/bsdsocket.h>
#endif
#ifdef __GNUC__
struct UtilityBase *UtilityBase;
static USHORT Utility_MY = 0;
#endif
#define OPT_TEMPLATE "DEVICE=DEV/K,UNIT/K/N,VERBOSE=V/S,FORCEMEDIA/K,ADVERTISE/K,RENEG=RESTART/S,RESET/S,VERYVERBOSE=VV/S" #define OPT_TEMPLATE "DEVICE=DEV/K,UNIT/K/N,VERBOSE=V/S,FORCEMEDIA/K,ADVERTISE/K,RENEG=RESTART/S,RESET/S,VERYVERBOSE=VV/S"
const char opt_template[] = OPT_TEMPLATE; const char opt_template[] = OPT_TEMPLATE;
struct progopts { struct progopts {
@@ -70,12 +82,17 @@ struct prgdata {
struct Device *sana2dev; struct Device *sana2dev;
UBYTE devvalid; UBYTE devvalid;
struct progopts opts; struct progopts opts;
BYTE *auto_devname; /* device name, if auto-detected */
}; };
void end_prog( struct prgdata *prg ) void end_prog( struct prgdata *prg )
{ {
if( prg->auto_devname )
FreeVec( prg->auto_devname );
if( prg->sana2devio ) if( prg->sana2devio )
{ {
if( prg->devvalid ) if( prg->devvalid )
@@ -84,6 +101,16 @@ void end_prog( struct prgdata *prg )
} }
if( prg->sana2devport ) if( prg->sana2devport )
DeleteMsgPort( prg->sana2devport ); DeleteMsgPort( prg->sana2devport );
#ifdef __GNUC__
if( (UtilityBase) && (Utility_MY) )
{
CloseLibrary( (struct Library*)UtilityBase );
Utility_MY = 0;
UtilityBase = NULL;
}
#endif /* __GNUC__ */
} }
/* /*
@@ -105,6 +132,13 @@ LONG start_prog( struct prgdata *prg )
if( !prg->sana2devio ) if( !prg->sana2devio )
goto err; goto err;
#ifdef __GNUC__
if( !UtilityBase )
{
UtilityBase = (struct UtilityBase*)OpenLibrary("utility.library",37);
Utility_MY = 1;
}
#endif /* __GNUC__ */
return 1; return 1;
err: err:
end_prog( prg ); end_prog( prg );
@@ -189,36 +223,37 @@ const struct {
BYTE *name; BYTE *name;
UWORD namelen; UWORD namelen;
UWORD value; UWORD value;
} media[] = { } mediatypes[] = {
/* The order through 100baseT4 matches bits in the BMSR */ /* these are kept in this order for the dump loop decision about best mode */
{ "10baseT-HD", 10,MII_AN_10BASET_HD }, { "10baseT-HD", 10,MII_AN_10BASET_HD },
{ "10baseT-FD", 10,MII_AN_10BASET_FD }, { "10baseT-FD", 10,MII_AN_10BASET_FD },
{ "100baseTx-HD", 12,MII_AN_100BASETX_HD }, { "100baseTx-HD", 12,MII_AN_100BASETX_HD },
{ "100baseTx-FD", 12,MII_AN_100BASETX_FD }, { "100baseTx-FD", 12,MII_AN_100BASETX_FD },
{ "100baseT4", 9,MII_AN_100BASET4 }, { "100baseT4", 9,MII_AN_100BASET4 },
/* generic mode names where only the speed matters */
{ "100baseTx", 9,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD }, { "100baseTx", 9,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
{ "10baseT", 7,MII_AN_10BASET_FD | MII_AN_10BASET_HD }, { "10baseT", 7,MII_AN_10BASET_FD | MII_AN_10BASET_HD },
{ "100bTx", 6,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD }, { "100bTx", 6,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
{ "10bT", 4,MII_AN_10BASET_FD | MII_AN_10BASET_HD }, { "10bT", 4,MII_AN_10BASET_FD | MII_AN_10BASET_HD },
}; };
#define NMEDIA (sizeof(media)/sizeof(media[0])) #define NMEDIA (sizeof(mediatypes)/sizeof(mediatypes[0]))
void dump_mii_media( USHORT par, BOOL bestonly )
void dump_mii_media( USHORT parms, BOOL bestonly )
{ {
LONG i; LONG i;
par >>= 5; /* get upper bits */ for( i=9 ; i >= 5 ; i-- )
for( i=4 ; i >= 0 ; i-- )
{ {
if( par & (1<<i) ) if( parms & (1<<i) )
{ {
Printf(" "); Printf(" %s",(ULONG)mediatypes[i-5].name);
Printf("%s",(ULONG)media[i].name);
if( bestonly ) if( bestonly )
break; break;
} }
} }
if( par & (1<<5) )
if( parms & (1<<10) )
Printf(" flow-control"); Printf(" flow-control");
} }
@@ -234,13 +269,13 @@ LONG parse_speedduplex( BYTE *parameters )
while( *s != 0 ) while( *s != 0 )
{ {
for( i=0 ; i < NMEDIA ; i++ ) for( i=0 ; i < NMEDIA ; i++ )
if( Strnicmp( media[i].name, s, media[i].namelen ) == 0 ) if( Strnicmp( mediatypes[i].name, s, mediatypes[i].namelen ) == 0 )
break; break;
if( i==NMEDIA ) if( i==NMEDIA )
goto err; goto err;
s += media[i].namelen; s += mediatypes[i].namelen;
res |= media[i].value; res |= mediatypes[i].value;
/* skip " " and/or "," */ /* skip " " and/or "," */
while( *s != 0 ) while( *s != 0 )
@@ -254,26 +289,26 @@ LONG parse_speedduplex( BYTE *parameters )
return res; return res;
err: err:
Printf("Invalid media specification %s\n",parameters); Printf("Invalid media specification %s\n",(ULONG)parameters);
Printf("Valid Arguments:\n"); Printf("Valid Arguments:\n");
for( i=0 ; i < NMEDIA ; i++ ) for( i=0 ; i < NMEDIA ; i++ )
Printf("%s\n",media[i].name); Printf("%s\n",(ULONG)mediatypes[i].name);
return -1; return -1;
} }
/* /*
note: this code assumes that "mii" has the register contents in natural note: this code assumes that "mii" has the register contents in network
byte ordering. Also, the registers themselves shall be consecutive byte ordering. Also, the registers themselves shall be consecutive
in memory. in memory.
*/ */
int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose ) int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
{ {
USHORT bmcr,bmsr,advert,curlink; USHORT bmcr,bmsr,selfad,curlink;
LONG i; LONG i;
bmcr = mii[MII_BMCR].Content; bmcr = mii[MII_BMCR].Content;
bmsr = mii[MII_BMSR].Content; bmsr = mii[MII_BMSR].Content;
advert = mii[MII_ANAR].Content; selfad = mii[MII_ANAR].Content;
curlink = mii[MII_ANLPAR].Content; curlink = mii[MII_ANLPAR].Content;
if( bmcr == 0xffff ) if( bmcr == 0xffff )
@@ -286,19 +321,19 @@ int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
{ {
if( bmsr & MII_BMSR_AN_COMPLETE) if( bmsr & MII_BMSR_AN_COMPLETE)
{ {
if( advert & curlink ) if( selfad & curlink )
{ {
if( curlink & MII_AN_ACK ) /* if( curlink & MII_AN_ACK ) */
Printf("negotiated "); Printf("negotiated ");
else Printf("no autonegotiation,"); /* else Printf("no autonegotiation,"); */
dump_mii_media( advert & curlink, 1 ); dump_mii_media( selfad & curlink, 1 );
Printf(", "); Printf(", ");
} }
else else
{ {
Printf("autonegotiation failed, "); Printf("autonegotiation failed, ");
}
} }
}
else else
if (bmcr & MII_BMCR_RESTART) if (bmcr & MII_BMCR_RESTART)
{ {
@@ -308,8 +343,8 @@ int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
else else
{ {
Printf("%s Mbit, %s duplex, ", Printf("%s Mbit, %s duplex, ",
(bmcr & MII_BMCR_100MBIT) ? "100" : "10", (bmcr & MII_BMCR_100MBIT) ? (ULONG)"100" : (ULONG)"10",
(bmcr & MII_BMCR_DUPLEX) ? "full" : "half" ); (bmcr & MII_BMCR_DUPLEX) ? (ULONG)"full" : (ULONG)"half" );
} }
if( bmsr & MII_BMSR_LINK_VALID ) if( bmsr & MII_BMSR_LINK_VALID )
Printf("link ok"); Printf("link ok");
@@ -353,8 +388,8 @@ int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
Printf("autonegotiation enabled\n"); Printf("autonegotiation enabled\n");
else else
Printf("%s Mbit, %s duplex\n", Printf("%s Mbit, %s duplex\n",
(bmcr & MII_BMCR_100MBIT) ? "100" : "10", (bmcr & MII_BMCR_100MBIT) ? (ULONG)"100" : (ULONG)"10",
(bmcr & MII_BMCR_DUPLEX) ? "full" : "half"); (bmcr & MII_BMCR_DUPLEX) ? (ULONG)"full" : (ULONG)"half");
Printf(" basic status: "); Printf(" basic status: ");
if( bmsr & MII_BMSR_AN_COMPLETE ) if( bmsr & MII_BMSR_AN_COMPLETE )
Printf("autonegotiation complete, "); Printf("autonegotiation complete, ");
@@ -366,7 +401,7 @@ int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
Printf("\n capabilities:"); Printf("\n capabilities:");
dump_mii_media( bmsr >> 6, 0 ); dump_mii_media( bmsr >> 6, 0 );
Printf("\n advertising: "); Printf("\n advertising: ");
dump_mii_media( advert, 0 ); dump_mii_media( selfad, 0 );
if( curlink & MII_AN_ABILITY_MASK ) if( curlink & MII_AN_ABILITY_MASK )
{ {
Printf("\n link partner:"); Printf("\n link partner:");
@@ -438,6 +473,111 @@ LONG write_mii( struct prgdata *prg, struct S2DevQueryMIIParam *mii, LONG num )
return parm_mii.Actual; return parm_mii.Actual;
} }
#ifdef RSHOW
/* return string length without closing 0 */
LONG myStrLen( BYTE *str )
{
LONG ret = 0;
if( str )
{
while( *str++ )
ret++;
}
return ret;
}
/* copy string, append 0 */
void myStrNCpy( BYTE *dst, BYTE*src, LONG bytes )
{
if( !dst )
return;
if( src )
{
while( (bytes--) && (*src != 0) )
{
*dst++ = *src++;
}
}
*dst = 0;
}
/* find active interface and its device in RoadShow (optional) */
/* "which" index of Ethernet adapter 0,1,2,... */
/* "unit" is the output unit */
BYTE *find_active_interface(LONG which, LONG *unit )
{
struct Library *SocketBase;
BYTE *ret = NULL;
struct List * interface_list = NULL;
struct Node *n;
BYTE *dev = NULL;
LONG hw = -1;
SocketBase = OpenLibrary("bsdsocket.library",4);
if( !SocketBase )
{
Printf("Cannot open bsdsocket.library version 4 for device auto-detection\n");
return NULL;
}
do
{
LONG have_iface = 0;
if( !(SocketBaseTags(SBTM_GETREF(SBTC_HAVE_INTERFACE_API), &have_iface, TAG_DONE) == 0)
||(!have_iface) )
{
Printf("RoadShow-style interface API not available in IP stack\n");
break;
}
interface_list = ObtainInterfaceList();
if( !interface_list )
{
break;
}
for( n=interface_list->lh_Head ; n->ln_Succ != NULL ; n=n->ln_Succ )
{
/* Printf("Interface %s\n",n->ln_Name); */
/* find Ethernet interface */
if(!QueryInterfaceTags( n->ln_Name, IFQ_HardwareType, &hw,
IFQ_DeviceName, &dev,
IFQ_DeviceUnit, unit ) )
continue;
/* Printf("device %s hwtype %ld\n",dev,hw); */
if( hw == S2WireType_Ethernet )
break;
}
if( hw == S2WireType_Ethernet )
{
if( dev )
{
ret = AllocVec( myStrLen( dev ), 0 );
if( ret )
myStrNCpy( ret, dev, myStrLen(dev) );
}
}
}
while(0);
if( interface_list )
ReleaseInterfaceList(interface_list);
CloseLibrary(SocketBase);
return ret;
}
#endif
/* 8 basic registers, we poll 16 out of curiosity */ /* 8 basic registers, we poll 16 out of curiosity */
#define MII_REGNUM 16 #define MII_REGNUM 16
/* two spare registers for write mode */ /* two spare registers for write mode */
@@ -468,17 +608,34 @@ int main(int argc, char **argv)
return res; return res;
} }
unit = (prg->opts.unit) ? *prg->opts.unit : 0;
if( !prg->opts.devname ) if( !prg->opts.devname )
{ {
#ifdef RSHOW
LONG _unit;
prg->auto_devname = find_active_interface( 0, &_unit );
if( prg->auto_devname )
{
unit = _unit;
name = prg->auto_devname;
}
else
{
Printf("cannot auto-determine device, please use DEVICE=... as argument\n");
end_prog(prg);
return res;
}
#else
name = "enc624j6net.device"; name = "enc624j6net.device";
Printf("TODO: auto-detect, now trying default %s\n",name); Printf("device auto-detect not compiled in, now trying default %s\n",name);
#endif
/* end_prog(prg); /* end_prog(prg);
return res; */ return res; */
} }
else else
name = prg->opts.devname; name = prg->opts.devname;
unit = (prg->opts.unit) ? *prg->opts.unit : 0;
if( prg->opts.vverbose ) if( prg->opts.vverbose )
prg->opts.verbose = 2; prg->opts.verbose = 2;
else else
@@ -524,7 +681,7 @@ int main(int argc, char **argv)
parm_productname.Data = productname; parm_productname.Data = productname;
parm_productname.Length = sizeof(productname); parm_productname.Length = sizeof(productname);
parm_productname.Actual = 0; parm_productname.Actual = 0;
#if 1
tags[i=0].ti_Tag = S2_DevQueryExtVendorName; tags[i=0].ti_Tag = S2_DevQueryExtVendorName;
tags[i++].ti_Data = (ULONG) &parm_vendorname; tags[i++].ti_Data = (ULONG) &parm_vendorname;
tags[i ].ti_Tag = S2_DevQueryExtProductName; tags[i ].ti_Tag = S2_DevQueryExtProductName;
@@ -542,55 +699,28 @@ int main(int argc, char **argv)
parm_mii.Actual = query_mii( prg, mii, 0, 15 ); parm_mii.Actual = query_mii( prg, mii, 0, 15 );
if( parm_mii.Actual ) if( parm_mii.Actual )
{ {
/* read BMSR twice */ /* read BMSR a second time */
query_mii( prg, mii+MII_BMSR, MII_BMSR, MII_BMSR ); query_mii( prg, mii+MII_BMSR, MII_BMSR, MII_BMSR );
res = RETURN_OK; res = RETURN_OK;
} }
else else
{
Printf("Sana2DeviceQueryExtension for MII access not present\n");
res = RETURN_WARN; res = RETURN_WARN;
#else }
/* MII specific */
parm_mii.Data = (APTR)mii;
parm_mii.Length = sizeof(mii);
parm_mii.Actual = 0;
for( i=0 ; i < 16 ; i++ ) /* MII standard register set: 8 */
{
mii[i].ID = i; /* mii[i].Content = 0; */
}
mii[16].ID = MII_BMSR; /* read BMSR twice */
tags[i=0].ti_Tag = S2_DevQueryExtVendorName;
tags[i++].ti_Data = (ULONG) &parm_vendorname;
tags[i ].ti_Tag = S2_DevQueryExtProductName;
tags[i++].ti_Data = (ULONG) &parm_productname;
tags[i ].ti_Tag = S2_DevQueryExtGetMII;
tags[i++].ti_Data = (ULONG) &parm_mii;
tags[i ].ti_Tag = TAG_DONE;
prg->sana2devio->ios2_Req.io_Command = S2_DEVICEQUERYEXT;
prg->sana2devio->ios2_Data = tags;
prg->sana2devio->ios2_DataLength = sizeof tags;
if( DoIO((struct IORequest *) prg->sana2devio ) != 0 )
res = RETURN_WARN;
else res = RETURN_OK;
mii[MII_BMSR].Content = mii[16].Content; /* read BMSR twice */
#endif
} }
Printf("Device: %s\n",name); Printf("Device: %s\n",(ULONG)name);
/* general info */ /* general info */
if( parm_vendorname.Actual != 0 ) if( parm_vendorname.Actual != 0 )
{ {
vendorname[parm_vendorname.Actual-1] = 0; vendorname[parm_vendorname.Actual-1] = 0;
Printf("Vendor: %s\n",vendorname); Printf("Vendor: %s\n",(ULONG)vendorname);
} }
if( parm_productname.Actual != 0 ) if( parm_productname.Actual != 0 )
{ {
productname[parm_productname.Actual-1] = 0; productname[parm_productname.Actual-1] = 0;
Printf("Product: %s\n",productname); Printf("Product: %s\n",(ULONG)productname);
} }
/* after query, see what we've got */ /* after query, see what we've got */
@@ -603,6 +733,7 @@ int main(int argc, char **argv)
} }
else else
{ {
/* command or query ? */
if( !(prg->opts.renegotiate) && !(prg->opts.reset) if( !(prg->opts.renegotiate) && !(prg->opts.reset)
&& !(prg->opts.advertise) && !(prg->opts.force) && !(prg->opts.advertise) && !(prg->opts.force)
) )
@@ -659,3 +790,4 @@ int main(int argc, char **argv)
end_prog(prg); end_prog(prg);
return res; return res;
} }
+45
View File
@@ -66,6 +66,51 @@ struct S2DevQueryExtParam
/* Current physical link speed, see definitions below: */ /* Current physical link speed, see definitions below: */
#define S2_DevQueryExtLinkSpeed (S2_DevQueryExtTagBase + 4) #define S2_DevQueryExtLinkSpeed (S2_DevQueryExtTagBase + 4)
/* proposal added by Henryk Richter: access to MII */
/* MII is the standardized ethernet interface to the
PHY registers. It allows to read and modify autonegotiation
settings and status, as well as manual reconfiguration of
link parameters. In order to ease the burden on the
SANA-II driver, this interface is transparent in the sense
that no processing of MII registers is necessary.
Please note that MII read/write is slow. Use with discretion.
The format of the Data APTR is per entry as follows:
UWORD ID
UWORD Content
S2_DevQueryExtGetMII
Please pass a writable Data array of Length=2*NumIDs to the call and
initialize the IDs you are interested in. The driver will initialize
the Content of the IDs it knows about. Should a requested ID be
unsupported by the driver or underlying chipset, the driver will
overwrite the respective IDs with S2_DEVQUERYEXT_MII_INVALID and
clear the associated Content field.
In case of fatal error, the "Actual" field of S2DevQueryExtParam
will be 0. Otherwise, the last successfully updated location + 2
will be returned.
S2_DevQueryExtSetMII
Please pass a Data array of Length=2*NumIDs to the call and initialize
the IDs to write along with their content. The driver will write the
MII registers corresponding with the IDs in the given order.
In case of fatal error, the "Actual" field of S2DevQueryExtParam
will be 0. Otherwise, the last successfully updated location + 2
will be returned.
*/
#define S2_DevQueryExtGetMII (S2_DevQueryExtTagBase + 0x20)
#define S2_DevQueryExtSetMII (S2_DevQueryExtTagBase + 0x21)
struct S2DevQueryMIIParam
{
UWORD ID;
UWORD Content;
};
#define S2_DEVQUERYEXT_MII_INVALID 0xfe
#define S2_DEVQUERYEXT_LINK_UNDEFINED 0xffffffff #define S2_DEVQUERYEXT_LINK_UNDEFINED 0xffffffff
#define S2_DEVQUERYEXT_LINK_DOWN 0 #define S2_DEVQUERYEXT_LINK_DOWN 0
#define S2_DEVQUERYEXT_LINK_UP 1 #define S2_DEVQUERYEXT_LINK_UP 1
+2 -1
View File
@@ -37,7 +37,7 @@ static LONG server_queryext( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq );
/* tunables: number of one-call read and write requests */ /* tunables: number of one-call read and write requests */
/* this limits the number of processed write requests per run when enabled */ /* this limits the number of processed write requests per run when enabled */
#define ONE_WRITE_REQ 2 #define ONE_WRITE_REQ 1
/* this limits the number of processed read requests per run when enabled */ /* this limits the number of processed read requests per run when enabled */
#define ONE_READ_REQ 2 #define ONE_READ_REQ 2
@@ -1071,6 +1071,7 @@ VOID SAVEDS ServerTask(void)
{ {
if( !action ) /* queues quiet ? -> sleep */ if( !action ) /* queues quiet ? -> sleep */
{ {
Disable();
i=0;BOARDLOOP( ( ; i < db->db_NBoards ; i++ ) ) i=0;BOARDLOOP( ( ; i < db->db_NBoards ; i++ ) )
{ /* housekeeping -> check for link change on idle, re-enable interrupts etc. */ { /* housekeeping -> check for link change on idle, re-enable interrupts etc. */
hw_check_link_change(db,i); hw_check_link_change(db,i);
+1 -1
View File
@@ -127,7 +127,7 @@ CFLAGS = $(CFLAGS) INCLUDEDIR="" INCLUDEDIR=$(SUBDIR) $(DEFINES)
# ASM based alternative to deviceheader.o would be romtag.o # ASM based alternative to deviceheader.o would be romtag.o
OBJECTS = deviceheader.o$(TYPE) deviceinit.o$(TYPE) device.o$(TYPE) \ OBJECTS = deviceheader.o$(TYPE) deviceinit.o$(TYPE) device.o$(TYPE) \
server.o$(TYPE) $(SUBDIR)/hw.o$(TYPE) server.o$(TYPE) $(SUBDIR)/hw.o$(TYPE) kprintf.o$(TYPE)
OBJECTS = $(OBJECTS) $(ASMOBJECTS) OBJECTS = $(OBJECTS) $(ASMOBJECTS)
+2 -2
View File
@@ -9,9 +9,9 @@
#define _INC_VERSION_H #define _INC_VERSION_H
#define DEVICEVERSION 2 #define DEVICEVERSION 2
#define DEVICEREVISION 1 #define DEVICEREVISION 2
#define DEVICEEXTRA #define DEVICEEXTRA
/* #define DEVICEEXTRA Beta */ /* #define DEVICEEXTRA Beta */
#define DEVICEDATE 21.02.2019 #define DEVICEDATE 10.03.2019
#endif #endif