CP and LAN working! Clockport needed to be stopped if FCS='1'
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
MIITool
|
||||
-------
|
||||
|
||||
This utility allows to observe and change the physical parameters
|
||||
of Ethernet NICs on AmigaOS. The parameters include autonegotiation
|
||||
settings and forced speed/duplex combinations. While it is expected
|
||||
that autonegotiation "just works" with modern equipment, there still
|
||||
are people with some interest in retro-computing who might or might
|
||||
not experience link-related problems or are just curious about some
|
||||
inner workings of everyday hardware.
|
||||
|
||||
A modern switch ("link partner") should advertise it`s capabilities
|
||||
properly such that the Ethernet hardware can select the optimal mode
|
||||
out of the supported set. If that is not the case, you can narrow down
|
||||
the list of advertised modes such that the link partners come to a
|
||||
working agreement. The last resort is to set a fixed speed/duplex
|
||||
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.
|
||||
|
||||
None of the settings this tool applies is permanent. Changed parameters
|
||||
are only valid until a reboot of the NIC.
|
||||
|
||||
Examples for usage are given at the end of this text.
|
||||
|
||||
|
||||
Prerequisites:
|
||||
- AmigaOS 2.04 on 68k
|
||||
- active Ethernet SANA-II driver, i.e. after starting the IP-Stack
|
||||
|
||||
|
||||
Invocation:
|
||||
- MIITool is supposed to be run from CLI/Shell.
|
||||
|
||||
|
||||
Arguments template:
|
||||
DEVICE/K,UNIT/K/N,V/S,FORCEMEDIA/K,ADVERTISE/K,RENEG/S,RESET/S,VV/S
|
||||
|
||||
|
||||
Detailed description of arguments:
|
||||
|
||||
keyword - description
|
||||
------------------------
|
||||
DEVICE/K - device name corresponding to active ethernet interface
|
||||
DEV/K example: DEVICE=enc624j6net.device
|
||||
|
||||
UNIT/K/N - unit number of device to be opened (default: 0)
|
||||
example: UNIT=0
|
||||
|
||||
FORCEMEDIA - speed/duplex combination to set unconditionally,
|
||||
see below for a list of valid speed or duplex modes
|
||||
|
||||
ADVERTISE - speed/duplex combinations to announce by autonegotiation,
|
||||
implicitly restart autonegotiation,
|
||||
see below for a list of valid speed or duplex modes
|
||||
|
||||
RENEG - restart autonegotiation, please allow a couple of seconds
|
||||
RESTART until the negotiation is finished
|
||||
|
||||
RESET - reset PHY to power-on state
|
||||
|
||||
VERBOSE - more detailed outputs
|
||||
V
|
||||
|
||||
VERYVERBOSE- even more detailed outputs
|
||||
VV
|
||||
|
||||
|
||||
Valid Speed/Duplex combinations (not case sensitive):
|
||||
|
||||
10baseT-HD - 10 Mbit/s half duplex
|
||||
10baseT-FD - 10 Mbit/s full duplex
|
||||
100baseTx-HD - 100 Mbit/s half duplex over two wire pairs
|
||||
100baseTx-FD - 100 Mbit/s full duplex over two wire pairs (common)
|
||||
100baseT4 - 100 Mbit/s full duplex over 4 wire pairs (rare)
|
||||
10baseT - 10 Mbit/s half or full duplex
|
||||
10bT - 10 Mbit/s half or full duplex
|
||||
100baseTx - 100 Mbit/s half or full duplex
|
||||
100bTx - 100 Mbit/s half or full duplex
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
current status (detailed):
|
||||
miitool DEV=enc624j6net.device v
|
||||
|
||||
negotiate 10 Mbit/s only
|
||||
miitool DEV=enc624j6net.device ADVERTISE=10bT
|
||||
|
||||
negotiate 100baseTx and 10baseT half duplex only:
|
||||
miitool DEV=enc624j6net.device ADVERTISE=100bTx,10baseT-HD
|
||||
|
||||
force 100 Mbit/s full duplex
|
||||
miitool DEV=enc624j6net.device FORCEMEDIA=100baseTx-FD
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -23,7 +23,7 @@
|
||||
#DEVICEREVISION=95
|
||||
#DEVICEDATE=08.09.2018
|
||||
SUBDIR=enc624j6net
|
||||
ASMOBJECTS = $(SUBDIR)/enc624j6l.o $(SUBDIR)/intervaltimer.o
|
||||
ASMOBJECTS = $(SUBDIR)/enc624j6l.o $(SUBDIR)/intervaltimer.o kprintf.o
|
||||
|
||||
###############################################################################
|
||||
# Devices to build (1 or 2, keep DEVICEID2 empty if only one build is desired)
|
||||
@@ -31,7 +31,7 @@ ASMOBJECTS = $(SUBDIR)/enc624j6l.o $(SUBDIR)/intervaltimer.o
|
||||
###############################################################################
|
||||
|
||||
DEVICEID=enc624j6net.device
|
||||
DEFINES = # -DPROTO_V2EXPNET
|
||||
DEFINES = -DHW_DMA_TX # -DPROTO_V2EXPNET
|
||||
ASMDEFS = # -DPROTO_V2EXPNET
|
||||
CPU = 68020
|
||||
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
; ifd DEBUG
|
||||
; XDEF _AbsExecBase
|
||||
; XDEF _LVORawDoFmt
|
||||
; XDEF _LVORawPutChar
|
||||
; XDEF _LVORawMayGetChar
|
||||
; XDEF _AbsExecBase
|
||||
; endif
|
||||
|
||||
ifnd _LVORawDoFmt
|
||||
_LVORawDoFmt equ -$20a
|
||||
endc
|
||||
ifnd _LVORawPutChar
|
||||
_LVORawPutChar equ -$204
|
||||
_LVORawIOInit equ -$1f8
|
||||
_LVORawMayGetChar equ -$1fe
|
||||
endc
|
||||
|
||||
;
|
||||
;
|
||||
;
|
||||
ifd DEBUG
|
||||
|
||||
XREF _KPrintF
|
||||
|
||||
WRITEDEBUG macro
|
||||
movem.l d0/d1/a0/a1,-(sp)
|
||||
ifnb \9
|
||||
move.l \9,-(sp)
|
||||
endif
|
||||
ifnb \8
|
||||
move.l \8,-(sp)
|
||||
endif
|
||||
ifnb \7
|
||||
move.l \7,-(sp)
|
||||
endif
|
||||
ifnb \6
|
||||
move.l \6,-(sp)
|
||||
endif
|
||||
ifnb \5
|
||||
move.l \5,-(sp)
|
||||
endif
|
||||
ifnb \4
|
||||
move.l \4,-(sp)
|
||||
endif
|
||||
ifnb \3
|
||||
move.l \3,-(sp)
|
||||
endif
|
||||
ifnb \2
|
||||
move.l \2,-(sp)
|
||||
endif
|
||||
lea.l (\1),a0
|
||||
move.l sp,a1
|
||||
jsr _KPrintF
|
||||
ifnb \2
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \3
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \4
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \5
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \6
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \7
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \8
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \9
|
||||
add.l #4,sp
|
||||
endif
|
||||
movem.l (sp)+,d0/d1/a0/a1
|
||||
endm
|
||||
else
|
||||
WRITEDEBUG macro
|
||||
nop
|
||||
endm
|
||||
endc
|
||||
|
||||
|
||||
;
|
||||
;
|
||||
;
|
||||
WRITEOUT macro
|
||||
movem.l d0/d1/d2/a0/a1/a6,-(sp)
|
||||
ifnb \9
|
||||
move.l \9,-(sp)
|
||||
endif
|
||||
ifnb \8
|
||||
move.l \8,-(sp)
|
||||
endif
|
||||
ifnb \7
|
||||
move.l \7,-(sp)
|
||||
endif
|
||||
ifnb \6
|
||||
move.l \6,-(sp)
|
||||
endif
|
||||
ifnb \5
|
||||
move.l \5,-(sp)
|
||||
endif
|
||||
ifnb \4
|
||||
move.l \4,-(sp)
|
||||
endif
|
||||
ifnb \3
|
||||
move.l \3,-(sp)
|
||||
endif
|
||||
ifnb \2
|
||||
move.l \2,-(sp)
|
||||
endif
|
||||
ifd DEBUG
|
||||
move.l \1,a0
|
||||
move.l sp,a1
|
||||
jsr _KPrintF
|
||||
endif
|
||||
move.l \1,d1
|
||||
move.l sp,d2
|
||||
movea.l DOSBase,a6
|
||||
jsr _LVOVPrintf(a6)
|
||||
ifnb \2
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \3
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \4
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \5
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \6
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \7
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \8
|
||||
add.l #4,sp
|
||||
endif
|
||||
ifnb \9
|
||||
add.l #4,sp
|
||||
endif
|
||||
movem.l (sp)+,d0/d1/d2/a0/a1/a6
|
||||
endm
|
||||
|
||||
;COUNTERS only when DEBUG is on
|
||||
ifd DEBUG
|
||||
ifne DEBUG
|
||||
DEBUG_COUNTERS EQU 1
|
||||
endc
|
||||
endc
|
||||
|
||||
ifd DEBUG_COUNTERS
|
||||
COUNTER_INC macro
|
||||
addq.l #1,\1
|
||||
endm
|
||||
else
|
||||
COUNTER_INC macro
|
||||
nop
|
||||
endm
|
||||
endc
|
||||
|
||||
; write usage of all emulated instructions if DEBUG is 1 to RAWIO (sushi/sashimi/serial)
|
||||
ifd DEBUG
|
||||
ifne DEBUG
|
||||
HAVE_DEBUGINSTR EQU 1
|
||||
DEBUGINSTR macro
|
||||
ifnb \3
|
||||
WRITEDEBUG \1,\2,\3
|
||||
else
|
||||
WRITEDEBUG \1,\2
|
||||
endc
|
||||
endm
|
||||
endc
|
||||
endc
|
||||
ifnd HAVE_DEBUGINSTR
|
||||
DEBUGINSTR macro
|
||||
endm
|
||||
endc
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
in server.c as a separate process. Interrupts are forwarded
|
||||
as signals to server.c as well (depending on target hardware).
|
||||
|
||||
S2_CONFIGINTERFACE worked more than once, it *must* only work once.
|
||||
|
||||
*/
|
||||
#define DEVICE_MAIN
|
||||
|
||||
@@ -200,6 +202,12 @@ ASM SAVEDS LONG DevOpen( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
|
||||
dbm->dbm_PacketFilter = (APTR)( GetTagData(S2_PacketFilter,0,
|
||||
(struct TagItem *)ioreq->ios2_BufferManagement));
|
||||
|
||||
dbm->dbm_CopyFromBufferDMA = (BMCALL)((void (*)())(GetTagData(S2_DMACopyFromBuff32, 0,
|
||||
(struct TagItem *)ioreq->ios2_BufferManagement)));
|
||||
dbm->dbm_CopyToBufferDMA = (BMCALL)((void (*)())(GetTagData(S2_DMACopyToBuff32, 0,
|
||||
(struct TagItem *)ioreq->ios2_BufferManagement)));
|
||||
|
||||
|
||||
/* v1.95: disabled CopyToBuffer32 due to problems with MiamiDX */
|
||||
/* v1.99: try identifying Miami */
|
||||
/* MiamiDX requires byte count to be a multiple of 4 */
|
||||
@@ -215,7 +223,7 @@ ASM SAVEDS LONG DevOpen( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
|
||||
dbm->dbm_CopyFromBuffer32 = (BMCALL)((void (*)())(GetTagData(S2_CopyFromBuff32, 0,
|
||||
(struct TagItem *)ioreq->ios2_BufferManagement)));
|
||||
}
|
||||
|
||||
|
||||
D(("BufferMgmt CBuf32 %lx PF %lx CBuf %lx\n",(ULONG)dbm->dbm_CopyFromBuffer32,(ULONG)dbm->dbm_PacketFilter,(ULONG)dbm->dbm_CopyFromBuffer));
|
||||
|
||||
if( !dbm->dbm_CopyToBuffer32 )
|
||||
@@ -265,6 +273,8 @@ ASM SAVEDS LONG DevOpen( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
|
||||
}
|
||||
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
|
||||
|
||||
D(("DevOpen return code %ld\n",ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -588,6 +598,8 @@ ASM SAVEDS VOID DevBeginIO( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
|
||||
{
|
||||
struct IOStdReq *stdrq = (struct IOStdReq *)ioreq;
|
||||
|
||||
D(("NSCMD_DEVICEQUERY size %ld\n",(ULONG)stdrq->io_Length));
|
||||
|
||||
if( (!stdrq->io_Data) || (stdrq->io_Length < sizeof( NSDQueryAnswer ) ) )
|
||||
{
|
||||
ioreq->ios2_Req.io_Error = IOERR_BADLENGTH;
|
||||
@@ -598,6 +610,7 @@ ASM SAVEDS VOID DevBeginIO( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
|
||||
stdrq->io_Actual = sizeof( NSDQueryAnswer );
|
||||
ioreq->ios2_Req.io_Error = 0;
|
||||
}
|
||||
D(("NSCMD_DEVICEQUERY return %ld\n",(ULONG)ioreq->ios2_Req.io_Error));
|
||||
}
|
||||
break;
|
||||
/* query contents may ask for live data: handle in server.c */
|
||||
|
||||
@@ -123,7 +123,7 @@ struct devbase {
|
||||
};
|
||||
|
||||
|
||||
typedef BOOL (* ASM BMCALL)( ASMR(a0) void * ASMREG(a0), ASMR(a1) void * ASMREG(a1), ASMR(d0) LONG ASMREG(d0) );
|
||||
typedef LONG (* ASM BMCALL)( ASMR(a0) void * ASMREG(a0), ASMR(a1) void * ASMREG(a1), ASMR(d0) LONG ASMREG(d0) );
|
||||
|
||||
struct db_BufferManagement {
|
||||
struct MinNode dbm_n;
|
||||
@@ -131,6 +131,8 @@ struct db_BufferManagement {
|
||||
BMCALL dbm_CopyToBuffer32;
|
||||
BMCALL dbm_CopyFromBuffer;
|
||||
BMCALL dbm_CopyToBuffer;
|
||||
BMCALL dbm_CopyFromBufferDMA; /* this buffering method requires additional support from lowlevel HW implementation */
|
||||
BMCALL dbm_CopyToBufferDMA; /* usage of this pointer requires additional checks */
|
||||
APTR dbm_PacketFilter; /* this is actually a Hook */
|
||||
ULONG dbm_ID;
|
||||
};
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,4 @@
|
||||
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
; ------------------------------------------------------------------------------
|
||||
; | Lowlevel Access to memory mapped ENC624J600 in PSP mode |
|
||||
; | Henryk Richter <henryk.richter@gmx.net> |
|
||||
@@ -15,18 +16,23 @@
|
||||
;
|
||||
;
|
||||
;TODO:
|
||||
; - Pattern Matching, MC/MC filtering: Multicast,Broadcast,Unicast(self),MagicPacket,correct CRC,"not me" Unicast
|
||||
; - Pattern Matching, MC filtering: Multicast,Broadcast,Unicast(self),MagicPacket,correct CRC,"not me" Unicast
|
||||
; - _enc624j6l_RXReset -> won't recover from totally unresponsive chip (but exits gracefully)
|
||||
; - RXSTART_INIT = $0c00 -> currently $2000 due to previous location bug
|
||||
;
|
||||
; enable debugging code block (comment/uncomment, see below)
|
||||
;DEBUG EQU 1
|
||||
|
||||
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"
|
||||
|
||||
; enable debugging code block
|
||||
ifnd DEBUG
|
||||
DEBUG EQU 0
|
||||
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
|
||||
@@ -116,6 +122,9 @@ ENC_BOARDID EQU 123 ;ZII-IDE-LAN-CP
|
||||
XDEF _enc624j6l_bc_mc_filter
|
||||
|
||||
XDEF _enc624j6l_ReadPHY
|
||||
XDEF _enc624j6l_WritePHY
|
||||
|
||||
|
||||
;
|
||||
; System includes
|
||||
;
|
||||
@@ -250,9 +259,9 @@ opendos:
|
||||
beq .noframe ;nothing received
|
||||
|
||||
;debug: disable recv
|
||||
move.l _boardbase(pc),a0
|
||||
moveq #ECON1_RXEN,d0
|
||||
CLRREG ECON1,a0,d0
|
||||
;move.l _boardbase(pc),a0
|
||||
;moveq #ECON1_RXEN,d0
|
||||
;CLRREG ECON1,a0,d0
|
||||
|
||||
move.l _boardbase(pc),a0
|
||||
lea readframe,a1
|
||||
@@ -791,7 +800,7 @@ _enc624j6l_EnableInterrupt:
|
||||
move.w d0,($4000,a0)
|
||||
lea -$4000(a0),a0
|
||||
|
||||
move #EIE_PKTIE|EIE_INTIE,d0
|
||||
move #EIE_PKTIE|EIE_PCFULIE|EIE_INTIE,d0
|
||||
SETREG EIE,a0,d0
|
||||
|
||||
moveq #1,d0
|
||||
@@ -814,7 +823,7 @@ _enc624j6l_EnableInterrupt:
|
||||
; Notes: assumes that init() was called before
|
||||
;
|
||||
_enc624j6l_EnableGlobalInterrupt:
|
||||
move #EIE_INTIE,d0
|
||||
move #EIE_PKTIE|EIE_PCFULIE|EIE_INTIE,d0 ; move #EIE_INTIE,d0
|
||||
SETREG EIE,a0,d0
|
||||
moveq #1,d0
|
||||
.rts
|
||||
@@ -896,35 +905,32 @@ _enc624j6l_DisableInterrupt:
|
||||
; ULONG sigbit
|
||||
;
|
||||
_enc624j6l_IntServer_List:
|
||||
move.l a6,-(sp)
|
||||
|
||||
move.l a1,d0 ;no pointer supplied ? -> return
|
||||
beq.s .rts
|
||||
beq.s .end
|
||||
movem.l d1/A1/a6,-(sp)
|
||||
|
||||
move.l a1,a6
|
||||
|
||||
moveq #0,d1
|
||||
.boardloop:
|
||||
move.l (a1)+,d0 ;next entry from list
|
||||
beq.s .done ;
|
||||
move.l d0,a0 ;current board
|
||||
move.l (A6)+,d0 ;read magic word
|
||||
cmp.l #HW_MAGIC_WORD,D0 ; are we in the right structure?
|
||||
bne.s .done
|
||||
|
||||
READREG EIR,a0,d0 ;get interrupt status reg
|
||||
and #EIR_PKTIF,d0
|
||||
or.l d0,d1
|
||||
bra.s .boardloop
|
||||
.boardloop:
|
||||
move.l (A6)+,d0 ;next entry from list
|
||||
beq.s .done ;
|
||||
move.l d0,a1 ;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
|
||||
.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
|
||||
move #EIE_INTIE,D0 ;disable board interrupt until someone enables it again
|
||||
CLRREG EIE,A1,d0
|
||||
bra.s .intdis_loop
|
||||
.boardsdone:
|
||||
|
||||
;faster: get from extended Driver board list instead from ZII/ZIII card
|
||||
ifne 1
|
||||
@@ -960,7 +966,8 @@ _enc624j6l_IntServer_List:
|
||||
jsr _LVOSignal(a6)
|
||||
|
||||
.rts
|
||||
move.l (sp)+,a6
|
||||
movem.l (sp)+,D1/A1/A6
|
||||
.end
|
||||
moveq #0,d0 ;set Z flag
|
||||
rts
|
||||
|
||||
@@ -1062,8 +1069,45 @@ _enc624j6l_CheckLinkChange:
|
||||
; Notes: - Doesn't check for Board Pointer (!)
|
||||
; - doesn't re-enable RX (!)
|
||||
;
|
||||
|
||||
ifne DEBUG
|
||||
RXReset_MSG: dc.b "RXReset Head %04lx Tail %04lx NextPacket %04lx ReadPTR %04lx Bytes %04lx",10,0
|
||||
endc
|
||||
|
||||
_enc624j6l_RXReset:
|
||||
|
||||
ifne DEBUG
|
||||
;print current HW registers to serial
|
||||
movem.l d2-d7,-(sp)
|
||||
|
||||
moveq #0,d0
|
||||
moveq #0,d1
|
||||
moveq #0,d2
|
||||
moveq #0,d3
|
||||
READREG ERXHEAD,A0,d0
|
||||
READREG ERXTAIL,A0,d1
|
||||
READREG PNextPacket,a0,d2
|
||||
READSRAM a0,d2,d3 ;move (a0,d7.w),d0
|
||||
ifeq _OPT_BUFFER_SWAP
|
||||
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
|
||||
WRAPINDEX d5 ;wrap D4 if beyond buffer
|
||||
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
|
||||
|
||||
movem.l (sp)+,d2-d7
|
||||
endc
|
||||
|
||||
moveq #ECON2_RXRST,d0 ;RX Reset, clears RXEN
|
||||
SETREG ECON2,a0,d0 ;
|
||||
;moveq #ECON1_RXEN,d0 ;done by RX reset
|
||||
@@ -1171,6 +1215,15 @@ _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
|
||||
@@ -1259,10 +1312,23 @@ _enc624j6l_RecvFrame: ;
|
||||
|
||||
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
|
||||
@@ -1424,7 +1490,7 @@ _enc624j6l_RecvFrame: ;
|
||||
; notes:
|
||||
;
|
||||
_enc624j6l_TransmitFrame:
|
||||
movem.l d2-d5/a2,-(sp)
|
||||
movem.l d2-d5/a3,-(sp)
|
||||
|
||||
;---------------- parameter check -------------------------------------
|
||||
|
||||
@@ -1455,33 +1521,60 @@ _enc624j6l_TransmitFrame:
|
||||
eor.w #PSwapTX,d2 ;swap buffer
|
||||
WRITEREG PNextTX,a0,d2 ;remember pointer (d2 also for ETXST later)
|
||||
|
||||
lea (a0,d2.w),a2 ;write pointer for frame
|
||||
lea (a0,d2.w),a3 ;write pointer for frame
|
||||
|
||||
ifeq _OPT_BUFFER_SWAP
|
||||
|
||||
ifd HW_DMA_TX
|
||||
move.l a2,d3
|
||||
beq.s .no_separate_header
|
||||
ifne 1
|
||||
move.l -2(a2),(a3)+ ;garbage (2), DstMAC,SrcMAC,Type/Len = 16 Bytes
|
||||
move.l 2(a2),(a3)+
|
||||
move.l 6(a2),(a3)+
|
||||
move.l 10(a2),(a3)+
|
||||
moveq #14,d3
|
||||
addq #2,d2 ;start pointer behind garbage (2)
|
||||
else
|
||||
move.l (a2),(a3)+ ;copy DstMAC,SrcMAC,Type/Len = 14 Bytes
|
||||
move.l 4(a2),(a3)+
|
||||
move.l 8(a2),(a3)+
|
||||
move.w 12(a2),(a3)+
|
||||
moveq #14,d3
|
||||
endc
|
||||
.no_separate_header
|
||||
endc
|
||||
|
||||
;faster TX when buffer swapping is not necessary
|
||||
move.l d0,d4 ;remember length
|
||||
moveq #63,d5 ;
|
||||
and.l d5,d0 ;remainder of 64 byte copy loop
|
||||
move.l d4,d5 ;length in bytes
|
||||
ifd HW_DMA_TX
|
||||
add.l d3,d4 ;length+header (either 0 or 14)
|
||||
endc
|
||||
asr.w #6,d5 ;64 byte blocks
|
||||
subq.w #1,d5 ;dbf
|
||||
blt.s .smallcopy
|
||||
bra.s .largecopy_start
|
||||
|
||||
.largecopy:
|
||||
move.l d1,(a2)+
|
||||
move.l d1,(a3)+
|
||||
.largecopy_start:
|
||||
rept 15
|
||||
move.l (a1)+,(a2)+ ;save to SRAM
|
||||
move.l (a1)+,(a3)+ ;save to SRAM
|
||||
endr
|
||||
move.l (a1)+,d1
|
||||
dbf d5,.largecopy
|
||||
|
||||
move.l d1,(a2)+
|
||||
move.l d1,(a3)+
|
||||
|
||||
else ;_OPT_BUFFER_SWAP
|
||||
|
||||
ifd HW_DMA_TX
|
||||
error "HW_DMA_TX not supported for _OPT_BUFFER_SWAP configuration, disable!"
|
||||
endc
|
||||
|
||||
move.w d0,d4 ;still need length later
|
||||
|
||||
endc ;_OPT_BUFFER_SWAP
|
||||
@@ -1507,11 +1600,11 @@ _enc624j6l_TransmitFrame:
|
||||
rol.w d4,d3
|
||||
swap d1
|
||||
swap d3
|
||||
move.l d1,(a2)+ ;save to SRAM
|
||||
move.l d3,(a2)+ ;save to SRAM
|
||||
move.l d1,(a3)+ ;save to SRAM
|
||||
move.l d3,(a3)+ ;save to SRAM
|
||||
else ;_OPT_BUFFER_SWAP
|
||||
move.l (a1)+,(a2)+ ;save to SRAM
|
||||
move.l (a1)+,(a2)+ ;save to SRAM
|
||||
move.l (a1)+,(a3)+ ;save to SRAM
|
||||
move.l (a1)+,(a3)+ ;save to SRAM
|
||||
endc ;_OPT_BUFFER_SWAP
|
||||
|
||||
dbf d0,.txcopy
|
||||
@@ -1546,7 +1639,7 @@ _enc624j6l_TransmitFrame:
|
||||
SETREG ECON1,a0,d1 ;
|
||||
|
||||
.err:
|
||||
movem.l (sp)+,d2-d5/a2
|
||||
movem.l (sp)+,d2-d5/a3
|
||||
rts
|
||||
|
||||
ifne _OPT_CHECKLINK_TX
|
||||
@@ -1559,6 +1652,7 @@ _enc624j6l_TransmitFrame:
|
||||
|
||||
endc
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------------------
|
||||
;
|
||||
; read PHY register (16 Bit)
|
||||
@@ -1613,6 +1707,60 @@ _enc624j6l_ReadPHY:
|
||||
.err:
|
||||
moveq #-1,d0
|
||||
rts
|
||||
|
||||
;---------------------------------------------------------------------------------------
|
||||
;
|
||||
; write PHY register (16 Bit)
|
||||
;
|
||||
; input: A0 - APTR mmapped board base address
|
||||
; D0 - LONG Phy register (5 valid bits)
|
||||
; D1 - SHORT value written into PHY reg
|
||||
;
|
||||
; output: LONG D0 <0 - error (bad register index)
|
||||
; - 16 Bit PHY reg contents
|
||||
;
|
||||
; trash: -
|
||||
;
|
||||
; notes:
|
||||
;
|
||||
;
|
||||
_enc624j6l_WritePHY:
|
||||
cmp.w #31,d0
|
||||
bhi.w .err
|
||||
|
||||
bset #8,d0 ;$100 + PHY_REG
|
||||
WRITEREG MIREGADR,a0,d0 ;set PHY register address
|
||||
WRITEREG MIWR,a0,d1 ;set desired content
|
||||
|
||||
moveq #25,d0 ;25 us delay (at least)
|
||||
bsr _enc624j6l_UMinDelay ;
|
||||
|
||||
moveq #100,d1
|
||||
.waitloop:
|
||||
READREG MISTAT,a0,d0
|
||||
btst #0,d0
|
||||
beq.s .notbusy
|
||||
|
||||
tst.b $BFE301 ;1 CIA access = 1.4 us
|
||||
subq.w #1,d1 ;>165 us exceeded ? -> something is wrong, SPEC says 25.6 us
|
||||
blt.s .notbusy ;error
|
||||
|
||||
bra.s .waitloop
|
||||
.notbusy
|
||||
; moveq #0,d0
|
||||
; WRITEREG MICMD,a0,d0 ;cancel write command
|
||||
|
||||
moveq #0,d0
|
||||
.ret:
|
||||
rts
|
||||
.err:
|
||||
moveq #-1,d0
|
||||
bra.s .ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------------------------
|
||||
;------------------------------------------------------------------------------------------------
|
||||
;
|
||||
|
||||
@@ -196,17 +196,23 @@ ASM SAVEDS int enc624j6l_RecvFrame( ASMR(a0) void *board ASMREG(a0),
|
||||
input: board - mmapped board base address
|
||||
buffer - output buffer (should have >=1514 bytes)
|
||||
sendsize - size of buffer in bytes ( no CRC appended (!) )
|
||||
header - 14 Bytes Ethernet header
|
||||
(total frame transmit size = sendsize+14)
|
||||
|
||||
output: <0 - error
|
||||
0 - nothing in receive buffer
|
||||
>0 - size of received frame
|
||||
|
||||
notes:
|
||||
|
||||
"header" argument valid only when "HW_DMA_TX" is defined (Makefile)
|
||||
*/
|
||||
ASM SAVEDS int enc624j6l_TransmitFrame( ASMR(a0) void *board ASMREG(a0),
|
||||
ASMR(a1) unsigned char* buffer ASMREG(a1),
|
||||
ASMR(d0) short sendsize ASMREG(d0) );
|
||||
ASMR(d0) short sendsize ASMREG(d0)
|
||||
#ifdef HW_DMA_TX
|
||||
,ASMR(a2) unsigned char* header ASMREG(a2)
|
||||
#endif
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
@@ -330,7 +336,7 @@ ASM SAVEDS int enc624j6l_CheckLinkChange( ASMR(a0) void *board ASMREG(a0) );
|
||||
Purpose: read PHY register
|
||||
|
||||
input: board - mmapped board base address
|
||||
flags - broadcast,promiscous, multicast
|
||||
phyreg - PHY register to read
|
||||
|
||||
output: <0 - error
|
||||
>=0 - OK
|
||||
@@ -340,5 +346,20 @@ ASM SAVEDS int enc624j6l_ReadPHY(
|
||||
ASMR(d0) unsigned long phyreg ASMREG(d0) );
|
||||
|
||||
|
||||
/*
|
||||
Purpose: write PHY register
|
||||
|
||||
input: board - mmapped board base address
|
||||
phyreg - PHY register to read
|
||||
value - value written into PHY reg
|
||||
|
||||
output: <0 - error
|
||||
>=0 - OK
|
||||
*/
|
||||
ASM SAVEDS int enc624j6l_WritePHY(
|
||||
ASMR(a0) void *board ASMREG(a0),
|
||||
ASMR(d0) unsigned long phyreg ASMREG(d0),
|
||||
ASMR(d1) unsigned short data ASMREG(d1) );
|
||||
|
||||
|
||||
#endif /* _INC_ENC624J6L_H */
|
||||
|
||||
@@ -51,18 +51,18 @@ void myhw_ControlIntervalTimer( DEVBASEP );
|
||||
|
||||
/* these calls might not run within the context of a process and
|
||||
will be called from varying tasks and without prior init:
|
||||
hw_Find_Boards()
|
||||
hw_Find_Boards() - this one just identifies available HW and returns #boards
|
||||
hw_AllocBoard()
|
||||
hw_ReleaseBoard()
|
||||
hw_GetMacAddress()
|
||||
hw_GetMacAddress() - get default MAC address from board
|
||||
|
||||
these calls are in the context of the server task:
|
||||
hw_Setup() - general init (board allocated already)
|
||||
hw_Shutdown() - general shutdown (board still allocated)
|
||||
hw_Attach() - make hardware ready for action (online)
|
||||
hw_Detach() - put hardware into sleep mode (offline)
|
||||
hw_Setup() - general init (board allocated already)
|
||||
hw_Shutdown() - general shutdown (board still allocated)
|
||||
hw_Attach() - make hardware ready for action (online)
|
||||
hw_Detach() - put hardware into sleep mode (offline)
|
||||
|
||||
hw_recv_sigmask() - get signals for hardware (if any)
|
||||
hw_recv_sigmask() - get signals for hardware (if any, i.e. signal on interrupt)
|
||||
hw_recv_pending() - check for pending receive frames
|
||||
|
||||
hw_recv_frame() - receive one frame
|
||||
@@ -71,10 +71,11 @@ void myhw_ControlIntervalTimer( DEVBASEP );
|
||||
and apply them (called only when no RX/TX
|
||||
in progress)
|
||||
|
||||
hw_config_init() - set defaults for HW
|
||||
hw_config_update() - update config of HW
|
||||
hw_ConfigInit() - set defaults for HW
|
||||
hw_ConfigUpdate() - update config of HW
|
||||
|
||||
hw_get_mac_status() - running parameters
|
||||
hw_change_multicast - re-initialize multicast filter for new address list
|
||||
hw_get_mac_status() - running parameters (optional), S2_DEVICEQUERYEXT
|
||||
*/
|
||||
|
||||
const BYTE exp_name[] = "expansion.library";
|
||||
@@ -274,13 +275,31 @@ ASM SAVEDS void hw_ConfigUpdate( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
hwd->multicast = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
send a single frame to the hardware:
|
||||
- either fully assembled frame (14 bytes DMAC,SMAC,TYPE followed by payload
|
||||
- or payload in "frame" and 14 byte header in "header"
|
||||
- provide Makefile-level definition of HW_DMA_TX in the latter case
|
||||
|
||||
- note: if you pass "header==NULL" with active HW_DMA_TX definition,
|
||||
the hw_send_frame assumes the header to be present (SANA-II RAW frames) and
|
||||
is handling "frame" as fully assembled frame
|
||||
*/
|
||||
ASM SAVEDS LONG hw_send_frame( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(a1) UBYTE *frame ASMREG(a1),
|
||||
ASMR(d1) ULONG framesize ASMREG(d1) )
|
||||
ASMR(d1) ULONG framesize ASMREG(d1)
|
||||
#ifdef HW_DMA_TX
|
||||
,ASMR(a2) UBYTE *header ASMREG(a2)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
enc624j6l_TransmitFrame( db->db_Units[unit].duh_BASE, frame, framesize );
|
||||
/* TX with separate header support ? (optional) */
|
||||
enc624j6l_TransmitFrame( db->db_Units[unit].duh_BASE, frame, framesize
|
||||
#ifdef HW_DMA_TX
|
||||
,header
|
||||
#endif
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -329,14 +348,16 @@ ASM SAVEDS LONG hw_check_link_change( ASMR(a0) DEVBASEP ASMREG(
|
||||
return 1; /* don't signal panic to the outside, everything is under control */
|
||||
}
|
||||
|
||||
/* obtain running parameters of Ethernet MAC: link up/down, Speed, Duplex */
|
||||
/* obtain running parameters of Ethernet MAC: link up/down, Speed, Duplex for
|
||||
SANA-II DeviceQueryExtension (general parameters)
|
||||
*/
|
||||
ASM SAVEDS LONG hw_get_mac_status( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0) )
|
||||
{
|
||||
struct HWData *hwd = &db->db_hwdat;
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
struct HWData *hwd = &db->db_hwdat;
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
|
||||
LONG ret;
|
||||
LONG ret;
|
||||
LONG phstat3;
|
||||
LONG phstat1;
|
||||
LONG phcon1;
|
||||
@@ -345,8 +366,8 @@ ASM SAVEDS LONG hw_get_mac_status( ASMR(a0) DEVBASEP ASMREG(
|
||||
phstat3 = enc624j6l_ReadPHY( boardbase, PHSTAT3 );
|
||||
phcon1 = enc624j6l_ReadPHY( boardbase, PHCON1 );
|
||||
phstat1 = enc624j6l_ReadPHY( boardbase, PHSTAT1 ); /* read again to see whether link is established */
|
||||
if( ( phstat1 < 0 ) || ( phstat3 < 0 ) )
|
||||
return HW_MAC_INVALID; /* no valid data found */
|
||||
if( ( phstat1 < 0 ) || ( phstat3 < 0 ) )
|
||||
return HW_MAC_INVALID; /* no valid data found */
|
||||
|
||||
/* a) check Link */
|
||||
ret = 0;
|
||||
@@ -358,7 +379,7 @@ ASM SAVEDS LONG hw_get_mac_status( ASMR(a0) DEVBASEP ASMREG(
|
||||
if( phcon1 & PHCON1_ANEN ) /* autonegotiation enabled */
|
||||
ret |= HW_MAC_AUTONEGOTIATION;
|
||||
|
||||
phstat3 = (phstat3>>2)&7; /* get active Speed/Duplex */
|
||||
phstat3 = (phstat3>>2)&7; /* get active Speed/Duplex */
|
||||
switch( phstat3 )
|
||||
{
|
||||
case 6:
|
||||
@@ -385,6 +406,30 @@ ASM SAVEDS LONG hw_get_mac_status( ASMR(a0) DEVBASEP ASMREG(
|
||||
|
||||
}
|
||||
|
||||
/* read PHY register */
|
||||
ASM SAVEDS LONG hw_read_phy( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(d1) ULONG reg ASMREG(d1) )
|
||||
{
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
|
||||
return enc624j6l_ReadPHY( boardbase, reg );
|
||||
}
|
||||
|
||||
/* write PHY register (return -1 in case of error) */
|
||||
ASM SAVEDS LONG hw_write_phy( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(d1) ULONG reg ASMREG(d1),
|
||||
ASMR(d2) ULONG value ASMREG(d2) )
|
||||
{
|
||||
APTR boardbase = db->db_Units[unit].duh_BASE;
|
||||
|
||||
return enc624j6l_WritePHY( boardbase, reg, value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ASM SAVEDS LONG hw_change_multicast( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(a1) struct List *mcastlist ASMREG(a1) )
|
||||
@@ -404,8 +449,6 @@ ASM SAVEDS LONG hw_change_multicast( ASMR(a0) DEVBASEP ASMREG(
|
||||
|
||||
enc624j6l_bc_mc_filter(boardbase, flags );/* flags & (PIO_INIT_BROAD_CAST|PIO_INIT_MULTI_CAST) ); */
|
||||
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -417,7 +460,9 @@ void myhw_ControlInterrupts( DEVBASEP )
|
||||
|
||||
ObtainSemaphore( &hwd->hwd_Sem ); /* redundant here: server is a single task -> but it looks good :-) */
|
||||
|
||||
flag = 0;
|
||||
hwd->hwd_act_boards[0] = HW_MAGIC_WORD;
|
||||
|
||||
flag = 1;
|
||||
for( i=0 ; i < db->db_NBoards ; i++ )
|
||||
{
|
||||
if( db->db_Units[i].duh_online )
|
||||
@@ -431,7 +476,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 ) /* determine on/off switch */
|
||||
if( flag>1 ) /* determine on/off switch */
|
||||
{
|
||||
/* at least 1 board is online */
|
||||
if( hwd->hwd_Interrupt.is_Data )
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
struct HWData {
|
||||
struct Interrupt hwd_Interrupt; /* keep the interrupt at top of HWData !! */
|
||||
struct SignalSemaphore hwd_Sem; /* list locking (global per unit) */
|
||||
APTR hwd_act_boards[MAX_UNITS+1+3]; /* poll all active boards by ptr in interrupt, NULL terminated, followed by SigTask,Sigbit,ExecBase */
|
||||
APTR hwd_act_boards[MAX_UNITS+1+3+1]; /* poll all active boards by ptr in interrupt, MAGIC_WORD INIT, NULL terminated, followed by SigTask,Sigbit,ExecBase */
|
||||
|
||||
ULONG hwd_SigMask; /* signal mask to wait for in server main instance */
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ struct devbase;
|
||||
#define HW_MACB_SPEEDS_END 18 /* this is the next free bit */
|
||||
#define HW_MAC_SPEEDSMASK ((1<<HW_MACB_SPEEDS_END)-4)
|
||||
#define HW_MAC_NEXTSPEED(_a_) ( (_a_)+2 )
|
||||
|
||||
#define HW_MAGIC_WORD 0xB00BDEED
|
||||
|
||||
|
||||
|
||||
@@ -94,10 +94,24 @@ ASM SAVEDS void hw_ConfigInit( ASMR(a0) DEVBASEP ASMREG(a0) )
|
||||
ASM SAVEDS void hw_ConfigUpdate( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(a1) void * ASMREG(a1) );
|
||||
|
||||
/*
|
||||
send a single frame to the hardware:
|
||||
- either fully assembled frame (14 bytes DMAC,SMAC,TYPE followed by payload
|
||||
- or payload in "frame" and 14 byte header in "header"
|
||||
- provide Makefile-level definition of HW_DMA_TX in the latter case
|
||||
|
||||
- note: if you pass "header==NULL" with active HW_DMA_TX definition,
|
||||
the hw_send_frame assumes the header to be present (SANA-II RAW frames) and
|
||||
is handling "frame" as fully assembled frame
|
||||
*/
|
||||
ASM SAVEDS LONG hw_send_frame( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(a1) UBYTE *frame ASMREG(a1),
|
||||
ASMR(d1) ULONG framesize ASMREG(d1) );
|
||||
ASMR(d1) ULONG framesize ASMREG(d1)
|
||||
#ifdef HW_DMA_TX
|
||||
,ASMR(a2) UBYTE *header ASMREG(a2)
|
||||
#endif
|
||||
);
|
||||
|
||||
ASM SAVEDS LONG hw_recv_frame( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
@@ -116,6 +130,18 @@ ASM SAVEDS LONG hw_change_multicast( ASMR(a0) DEVBASEP ASMREG(
|
||||
ASM SAVEDS LONG hw_get_mac_status( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0) );
|
||||
|
||||
/* read PHY register (return -1 in case of error) */
|
||||
ASM SAVEDS LONG hw_read_phy( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(d1) ULONG reg ASMREG(d1) );
|
||||
|
||||
/* write PHY register (return -1 in case of error) */
|
||||
ASM SAVEDS LONG hw_write_phy( ASMR(a0) DEVBASEP ASMREG(a0),
|
||||
ASMR(d0) ULONG unit ASMREG(d0),
|
||||
ASMR(d1) ULONG reg ASMREG(d1),
|
||||
ASMR(d2) ULONG value ASMREG(d2) );
|
||||
|
||||
|
||||
/* kept this global for now: Z-II/Z-III boards share the same interrupt */
|
||||
ASM SAVEDS ULONG hw_recv_sigmask( ASMR(a0) DEVBASEP ASMREG(a0) );
|
||||
|
||||
|
||||
@@ -39,5 +39,5 @@ HW_MACB_SPEED5000 EQU 10
|
||||
HW_MACB_SPEED10000 EQU 12 ; Am I optimistic ?
|
||||
HW_MACB_SPEEDS_END EQU 14 ; this is the next free bit
|
||||
HW_MAC_SPEEDSMASK EQU ((1<<HW_MACB_SPEEDS_END)-4)
|
||||
|
||||
HW_MAGIC_WORD EQU $B00BDEED
|
||||
endc ;_INC_HW_I
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
incdir include:
|
||||
ifnd _LVOSupervisor
|
||||
include exec/exec_lib.i
|
||||
endc
|
||||
include exec/execbase.i
|
||||
|
||||
ifnd _LVORawDoFmt
|
||||
_LVORawDoFmt equ -$20a
|
||||
endc
|
||||
ifnd _LVORawPutChar
|
||||
_LVORawPutChar equ -$204
|
||||
_LVORawIOInit equ -$1f8
|
||||
_LVORawMayGetChar equ -$1fe
|
||||
endc
|
||||
|
||||
XDEF _KPrintF
|
||||
|
||||
;A0 = format
|
||||
;A1 = arguments
|
||||
_KPrintF:
|
||||
ifd DEBUG
|
||||
|
||||
movem.l d0-d2/a0-a3/a6,-(sp)
|
||||
|
||||
move.l 4.w,a6
|
||||
jsr _LVORawIOInit(a6) ;better safe than sorry
|
||||
|
||||
lea .kprintfproc(pc),a2
|
||||
suba.l a3,a3 ;data pointer (0 here)
|
||||
jsr _LVORawDoFmt(a6)
|
||||
|
||||
movem.l (sp)+,d0-d2/a0-a3/a6
|
||||
rts
|
||||
.kprintfproc:
|
||||
movem.l d0/d1/a0/a1/a6,-(sp)
|
||||
move.l 4.w,a6
|
||||
jsr _LVORawPutChar(a6) ; move.b d0,(a3)+
|
||||
movem.l (sp)+,d0/d1/a0/a1/a6
|
||||
|
||||
endc ;DEBUG
|
||||
|
||||
rts
|
||||
|
||||
|
||||
@@ -0,0 +1,661 @@
|
||||
/*******************************************************************************************/
|
||||
/** **/
|
||||
/** miitool.c **/
|
||||
/** SANA-II extension for access to Ethernet PHY registers over MII interface **/
|
||||
/** **/
|
||||
/** Copyright (c) 2019, Henryk Richter, Timm S. Müller **/
|
||||
/** All rights reserved. **/
|
||||
/** **/
|
||||
/** Redistribution and use in source and binary forms, with or without **/
|
||||
/** modification, are permitted provided that the following conditions are met: **/
|
||||
/** 1. Redistributions of source code must retain the above copyright **/
|
||||
/** notice, this list of conditions and the following disclaimer. **/
|
||||
/** 2. Redistributions in binary form must reproduce the above copyright **/
|
||||
/** notice, this list of conditions and the following disclaimer in the **/
|
||||
/** documentation and/or other materials provided with the distribution. **/
|
||||
/** 3. All advertising materials mentioning features or use of this software **/
|
||||
/** must display the following acknowledgement: **/
|
||||
/** 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 **/
|
||||
/** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED **/
|
||||
/** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE **/
|
||||
/** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY **/
|
||||
/** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES **/
|
||||
/** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; **/
|
||||
/** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND **/
|
||||
/** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT **/
|
||||
/** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS **/
|
||||
/** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/
|
||||
/** **/
|
||||
/*******************************************************************************************/
|
||||
/*
|
||||
Notes:
|
||||
- make sure you have an up-to-date devices/sana2devqueryext.h
|
||||
- make sure you have devices/newstyle.h
|
||||
- compilation
|
||||
sc miitool.c link
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <proto/utility.h>
|
||||
#include <devices/newstyle.h>
|
||||
#include <devices/sana2.h>
|
||||
#include <devices/sana2devqueryext.h>
|
||||
#include "miitool.h"
|
||||
|
||||
|
||||
#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;
|
||||
struct progopts {
|
||||
BYTE *devname;
|
||||
LONG *unit; /* unit to open */
|
||||
ULONG verbose; /* verbose mode enabled */
|
||||
BYTE *force; /* force media type */
|
||||
BYTE *advertise; /* advertise specific types */
|
||||
ULONG renegotiate; /* restart autonegotiation */
|
||||
ULONG reset; /* reset MII */
|
||||
ULONG vverbose; /* higher verbosity level */
|
||||
};
|
||||
|
||||
struct prgdata {
|
||||
struct MsgPort *sana2devport;
|
||||
struct IOSana2Req *sana2devio;
|
||||
struct Device *sana2dev;
|
||||
UBYTE devvalid;
|
||||
struct progopts opts;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void end_prog( struct prgdata *prg )
|
||||
{
|
||||
if( prg->sana2devio )
|
||||
{
|
||||
if( prg->devvalid )
|
||||
CloseDevice( (struct IORequest *)prg->sana2devio );
|
||||
DeleteIORequest( (struct IORequest *)prg->sana2devio );
|
||||
}
|
||||
if( prg->sana2devport )
|
||||
DeleteMsgPort( prg->sana2devport );
|
||||
}
|
||||
|
||||
/*
|
||||
note: call this only once at program startup
|
||||
*/
|
||||
LONG start_prog( struct prgdata *prg )
|
||||
{
|
||||
SHORT i;
|
||||
UBYTE *t = (UBYTE*)prg;
|
||||
for( i=0 ; i < sizeof( struct prgdata ) ; i++ )
|
||||
*t++ = 0;
|
||||
|
||||
prg->sana2devport = CreateMsgPort();
|
||||
if( !prg->sana2devport )
|
||||
goto err;
|
||||
|
||||
prg->sana2devio = (struct IOSana2Req *) CreateIORequest(
|
||||
prg->sana2devport, sizeof(struct IOSana2Req));
|
||||
if( !prg->sana2devio )
|
||||
goto err;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
end_prog( prg );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void clr_device( struct prgdata *prg )
|
||||
{
|
||||
if( !prg->devvalid )
|
||||
return;
|
||||
prg->devvalid = 0;
|
||||
CloseDevice( (struct IORequest *)prg->sana2devio );
|
||||
}
|
||||
|
||||
|
||||
LONG get_device(struct prgdata *prg, BYTE *name, LONG unit )
|
||||
{
|
||||
if( !name )
|
||||
return 0;
|
||||
if( prg->devvalid ) /* close previously opened device */
|
||||
clr_device( prg );
|
||||
|
||||
prg->devvalid = OpenDevice(name,unit,(struct IORequest *)prg->sana2devio,0) == 0;
|
||||
if( !prg->devvalid )
|
||||
{
|
||||
Printf( "Cannot open %s unit %ld\n",(ULONG)name,unit );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL findcmd(struct NSDeviceQueryResult *nsdqr, UWORD cmd)
|
||||
{
|
||||
UWORD *p;
|
||||
for (p = nsdqr->SupportedCommands; (*p); ++p)
|
||||
if (*p == cmd)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
verify NSD support, SANA-II type, Device Query extension on previously opened device
|
||||
*/
|
||||
LONG probe_device( struct prgdata *prg )
|
||||
{
|
||||
struct IOStdReq *stdreq;
|
||||
struct NSDeviceQueryResult nsdqr;
|
||||
|
||||
if( !prg )
|
||||
return 0;
|
||||
if( !prg->devvalid )
|
||||
return 0;
|
||||
|
||||
stdreq = (struct IOStdReq *)prg->sana2devio;
|
||||
stdreq->io_Command = NSCMD_DEVICEQUERY;
|
||||
stdreq->io_Flags = 0;
|
||||
stdreq->io_Data = &nsdqr;
|
||||
stdreq->io_Length = sizeof nsdqr;
|
||||
if (DoIO((struct IORequest *) stdreq) != 0)
|
||||
{
|
||||
Printf("I/O error: no NewStyleDevice.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nsdqr.DeviceType != NSDEVTYPE_SANA2)
|
||||
{
|
||||
Printf("Device is not a SANA-II device (type %ld, needed %ld\n).", (LONG)nsdqr.DeviceType, (LONG) NSDEVTYPE_SANA2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!findcmd(&nsdqr, S2_DEVICEQUERYEXT))
|
||||
{
|
||||
Printf("Device does not support S2_DEVICEQUERYEXT.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct {
|
||||
BYTE *name;
|
||||
UWORD namelen;
|
||||
UWORD value;
|
||||
} media[] = {
|
||||
/* The order through 100baseT4 matches bits in the BMSR */
|
||||
{ "10baseT-HD", 10,MII_AN_10BASET_HD },
|
||||
{ "10baseT-FD", 10,MII_AN_10BASET_FD },
|
||||
{ "100baseTx-HD", 12,MII_AN_100BASETX_HD },
|
||||
{ "100baseTx-FD", 12,MII_AN_100BASETX_FD },
|
||||
{ "100baseT4", 9,MII_AN_100BASET4 },
|
||||
{ "100baseTx", 9,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
|
||||
{ "10baseT", 7,MII_AN_10BASET_FD | MII_AN_10BASET_HD },
|
||||
{ "100bTx", 6,MII_AN_100BASETX_FD | MII_AN_100BASETX_HD },
|
||||
{ "10bT", 4,MII_AN_10BASET_FD | MII_AN_10BASET_HD },
|
||||
};
|
||||
#define NMEDIA (sizeof(media)/sizeof(media[0]))
|
||||
|
||||
void dump_mii_media( USHORT par, BOOL bestonly )
|
||||
{
|
||||
LONG i;
|
||||
|
||||
par >>= 5; /* get upper bits */
|
||||
for( i=4 ; i >= 0 ; i-- )
|
||||
{
|
||||
if( par & (1<<i) )
|
||||
{
|
||||
Printf(" ");
|
||||
Printf("%s",(ULONG)media[i].name);
|
||||
if( bestonly )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( par & (1<<5) )
|
||||
Printf(" flow-control");
|
||||
}
|
||||
|
||||
LONG parse_speedduplex( BYTE *parameters )
|
||||
{
|
||||
LONG i,res = 0;
|
||||
BYTE *s;
|
||||
|
||||
if( !parameters )
|
||||
return 0;
|
||||
|
||||
s = parameters;
|
||||
while( *s != 0 )
|
||||
{
|
||||
for( i=0 ; i < NMEDIA ; i++ )
|
||||
if( Strnicmp( media[i].name, s, media[i].namelen ) == 0 )
|
||||
break;
|
||||
if( i==NMEDIA )
|
||||
goto err;
|
||||
|
||||
s += media[i].namelen;
|
||||
res |= media[i].value;
|
||||
|
||||
/* skip " " and/or "," */
|
||||
while( *s != 0 )
|
||||
{
|
||||
if( (*s==' ') || (*s==',') )
|
||||
s++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
err:
|
||||
Printf("Invalid media specification %s\n",parameters);
|
||||
Printf("Valid Arguments:\n");
|
||||
for( i=0 ; i < NMEDIA ; i++ )
|
||||
Printf("%s\n",media[i].name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
note: this code assumes that "mii" has the register contents in natural
|
||||
byte ordering. Also, the registers themselves shall be consecutive
|
||||
in memory.
|
||||
*/
|
||||
int dump_mii( struct S2DevQueryMIIParam *mii, LONG length, LONG verbose )
|
||||
{
|
||||
USHORT bmcr,bmsr,advert,curlink;
|
||||
LONG i;
|
||||
|
||||
bmcr = mii[MII_BMCR].Content;
|
||||
bmsr = mii[MII_BMSR].Content;
|
||||
advert = mii[MII_ANAR].Content;
|
||||
curlink = mii[MII_ANLPAR].Content;
|
||||
|
||||
if( bmcr == 0xffff )
|
||||
{
|
||||
Printf("No MII transceiver found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( bmcr & MII_BMCR_AN_ENA)
|
||||
{
|
||||
if( bmsr & MII_BMSR_AN_COMPLETE)
|
||||
{
|
||||
if( advert & curlink )
|
||||
{
|
||||
if( curlink & MII_AN_ACK )
|
||||
Printf("negotiated ");
|
||||
else Printf("no autonegotiation,");
|
||||
dump_mii_media( advert & curlink, 1 );
|
||||
Printf(", ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("autonegotiation failed, ");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (bmcr & MII_BMCR_RESTART)
|
||||
{
|
||||
Printf("autonegotiation restarted, ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("%s Mbit, %s duplex, ",
|
||||
(bmcr & MII_BMCR_100MBIT) ? "100" : "10",
|
||||
(bmcr & MII_BMCR_DUPLEX) ? "full" : "half" );
|
||||
}
|
||||
if( bmsr & MII_BMSR_LINK_VALID )
|
||||
Printf("link ok");
|
||||
else Printf("no link");
|
||||
Printf("\n");
|
||||
|
||||
if( verbose > 1 )
|
||||
{
|
||||
Printf("PHY Registers:");
|
||||
for( i=0 ; i < length/sizeof( struct S2DevQueryMIIParam ) ; i++ )
|
||||
{
|
||||
if(!(i%8))
|
||||
Printf("\n");
|
||||
if( mii[i].ID == S2_DEVQUERYEXT_MII_INVALID )
|
||||
Printf("N/A ");
|
||||
else
|
||||
Printf("%04lx ",(LONG)(mii[i].Content));
|
||||
}
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
if( verbose )
|
||||
{
|
||||
Printf(" vendor %02lx:%02lx:%02lx, model %ld rev %ld\n",
|
||||
(LONG)mii[2].Content>>10,
|
||||
(LONG)(mii[2].Content>>2)&0xff,
|
||||
(LONG)((mii[2].Content<<6)|(mii[3].Content>>10))&0xff,
|
||||
(LONG)(mii[3].Content>>4)&0x3f,
|
||||
(LONG)(mii[3].Content&0x0f)
|
||||
);
|
||||
Printf(" basic mode: ");
|
||||
if( bmcr & MII_BMCR_RESET )
|
||||
Printf("software reset, ");
|
||||
if( bmcr & MII_BMCR_LOOPBACK )
|
||||
Printf("loopback, ");
|
||||
if( bmcr & MII_BMCR_ISOLATE )
|
||||
Printf("isolate, ");
|
||||
if( bmcr & MII_BMCR_COLTEST )
|
||||
Printf("collision test, ");
|
||||
if( bmcr & MII_BMCR_AN_ENA )
|
||||
Printf("autonegotiation enabled\n");
|
||||
else
|
||||
Printf("%s Mbit, %s duplex\n",
|
||||
(bmcr & MII_BMCR_100MBIT) ? "100" : "10",
|
||||
(bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
|
||||
Printf(" basic status: ");
|
||||
if( bmsr & MII_BMSR_AN_COMPLETE )
|
||||
Printf("autonegotiation complete, ");
|
||||
else if( bmcr & MII_BMCR_RESTART )
|
||||
Printf("autonegotiation restarted, ");
|
||||
if( bmsr & MII_BMSR_REMOTE_FAULT )
|
||||
Printf(" remote fault, ");
|
||||
Printf( (bmsr & MII_BMSR_LINK_VALID) ? "link ok" : "no link");
|
||||
Printf("\n capabilities:");
|
||||
dump_mii_media( bmsr >> 6, 0 );
|
||||
Printf("\n advertising: ");
|
||||
dump_mii_media( advert, 0 );
|
||||
if( curlink & MII_AN_ABILITY_MASK )
|
||||
{
|
||||
Printf("\n link partner:");
|
||||
dump_mii_media( curlink, 0 );
|
||||
}
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Query consecutive set of MII registers from start to end (inclusive)
|
||||
*/
|
||||
LONG query_mii( struct prgdata *prg, struct S2DevQueryMIIParam *mii, LONG start, LONG end )
|
||||
{
|
||||
struct S2DevQueryMIIParam *miitmp;
|
||||
struct S2DevQueryExtParam parm_mii;
|
||||
struct TagItem tags[2];
|
||||
LONG i;
|
||||
|
||||
/* MII specific */
|
||||
parm_mii.Data = (APTR)mii;
|
||||
parm_mii.Length = (end-start+1)*sizeof(struct S2DevQueryMIIParam);
|
||||
parm_mii.Actual = 0;
|
||||
|
||||
for( i=start,miitmp=mii ; i <= end ; i++,miitmp++ ) /* MII standard register set: 8 */
|
||||
{
|
||||
miitmp->ID = i;
|
||||
}
|
||||
|
||||
tags[i=0].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 )
|
||||
return 0;
|
||||
else
|
||||
return parm_mii.Actual;
|
||||
}
|
||||
|
||||
LONG write_mii( struct prgdata *prg, struct S2DevQueryMIIParam *mii, LONG num )
|
||||
{
|
||||
struct S2DevQueryExtParam parm_mii;
|
||||
struct TagItem tags[2];
|
||||
LONG i;
|
||||
|
||||
/* MII specific */
|
||||
parm_mii.Data = (APTR)mii;
|
||||
parm_mii.Length = (num)*sizeof(struct S2DevQueryMIIParam);
|
||||
parm_mii.Actual = 0;
|
||||
|
||||
tags[i=0].ti_Tag = S2_DevQueryExtSetMII;
|
||||
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 )
|
||||
return 0;
|
||||
else
|
||||
return parm_mii.Actual;
|
||||
}
|
||||
|
||||
/* 8 basic registers, we poll 16 out of curiosity */
|
||||
#define MII_REGNUM 16
|
||||
/* two spare registers for write mode */
|
||||
#define MII_SPARE 2
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct prgdata _prg,*prg=&_prg;
|
||||
int res = RETURN_FAIL;
|
||||
char vendorname[128], productname[128];
|
||||
struct S2DevQueryExtParam parm_productname;
|
||||
struct S2DevQueryExtParam parm_vendorname;
|
||||
struct S2DevQueryExtParam parm_mii;
|
||||
struct S2DevQueryMIIParam mii[MII_REGNUM+MII_SPARE];
|
||||
struct TagItem tags[3];
|
||||
int i;
|
||||
struct RDArgs *rdargs;
|
||||
BYTE *name;
|
||||
LONG unit,autoneg,force;
|
||||
|
||||
if( !start_prog(prg) )
|
||||
return res;
|
||||
|
||||
if( !(rdargs = ReadArgs( (char*)opt_template,(LONG*)&prg->opts,NULL) ) )
|
||||
{
|
||||
Printf("Argument error\n");
|
||||
end_prog(prg);
|
||||
return res;
|
||||
}
|
||||
|
||||
if( !prg->opts.devname )
|
||||
{
|
||||
name = "enc624j6net.device";
|
||||
Printf("TODO: auto-detect, now trying default %s\n",name);
|
||||
/* end_prog(prg);
|
||||
return res; */
|
||||
}
|
||||
else
|
||||
name = prg->opts.devname;
|
||||
|
||||
unit = (prg->opts.unit) ? *prg->opts.unit : 0;
|
||||
if( prg->opts.vverbose )
|
||||
prg->opts.verbose = 2;
|
||||
else
|
||||
if( prg->opts.verbose )
|
||||
prg->opts.verbose = 1;
|
||||
|
||||
/* parameter check */
|
||||
if( ( (prg->opts.force) && (prg->opts.renegotiate) ) ||
|
||||
( (prg->opts.force) && (prg->opts.advertise) )
|
||||
)
|
||||
{
|
||||
Printf("Error: Forced and Autonegotiation parameter mismatch\n");
|
||||
end_prog(prg);
|
||||
return RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* convert text to binary mask */
|
||||
autoneg = parse_speedduplex( prg->opts.advertise );
|
||||
force = parse_speedduplex( prg->opts.force );
|
||||
if( (autoneg|force) < 0 )
|
||||
{
|
||||
end_prog(prg);
|
||||
return RETURN_FAIL;
|
||||
}
|
||||
|
||||
if( get_device( prg, name , unit ) )
|
||||
{
|
||||
if( probe_device( prg ) )
|
||||
res = RETURN_OK;
|
||||
}
|
||||
if( res != RETURN_OK )
|
||||
{
|
||||
end_prog(prg);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* device open, query extension present, now query it */
|
||||
{
|
||||
/* general information */
|
||||
parm_vendorname.Data = vendorname;
|
||||
parm_vendorname.Length = sizeof(vendorname);
|
||||
parm_vendorname.Actual = 0;
|
||||
parm_productname.Data = productname;
|
||||
parm_productname.Length = sizeof(productname);
|
||||
parm_productname.Actual = 0;
|
||||
#if 1
|
||||
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 = TAG_DONE;
|
||||
|
||||
prg->sana2devio->ios2_Req.io_Command = S2_DEVICEQUERYEXT;
|
||||
prg->sana2devio->ios2_Data = tags;
|
||||
prg->sana2devio->ios2_DataLength = sizeof(tags);
|
||||
|
||||
DoIO( (struct IORequest *)prg->sana2devio );
|
||||
|
||||
/* separate query subroutine in here for MII, though not
|
||||
absolutely necessary (MII is queried more than once) */
|
||||
parm_mii.Actual = query_mii( prg, mii, 0, 15 );
|
||||
if( parm_mii.Actual )
|
||||
{
|
||||
/* read BMSR twice */
|
||||
query_mii( prg, mii+MII_BMSR, MII_BMSR, MII_BMSR );
|
||||
res = RETURN_OK;
|
||||
}
|
||||
else
|
||||
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);
|
||||
/* general info */
|
||||
if( parm_vendorname.Actual != 0 )
|
||||
{
|
||||
vendorname[parm_vendorname.Actual-1] = 0;
|
||||
Printf("Vendor: %s\n",vendorname);
|
||||
}
|
||||
if( parm_productname.Actual != 0 )
|
||||
{
|
||||
productname[parm_productname.Actual-1] = 0;
|
||||
Printf("Product: %s\n",productname);
|
||||
}
|
||||
|
||||
/* after query, see what we've got */
|
||||
if( res == RETURN_OK )
|
||||
{
|
||||
/* MII data */
|
||||
if( parm_mii.Actual == 0 )
|
||||
{
|
||||
Printf("Unable to query MII data.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !(prg->opts.renegotiate) && !(prg->opts.reset)
|
||||
&& !(prg->opts.advertise) && !(prg->opts.force)
|
||||
)
|
||||
{
|
||||
Printf("Active Parameters:\n");
|
||||
dump_mii( mii, parm_mii.Actual, prg->opts.verbose );
|
||||
}
|
||||
}
|
||||
|
||||
if( prg->opts.reset )
|
||||
{
|
||||
Printf("resetting the transceiver...\n");
|
||||
mii[MII_REGNUM].ID = MII_BMCR;
|
||||
mii[MII_REGNUM].Content = MII_BMCR_RESET;
|
||||
write_mii( prg, &mii[MII_REGNUM], 1 );
|
||||
}
|
||||
|
||||
if( prg->opts.advertise )
|
||||
{
|
||||
mii[MII_REGNUM].ID = MII_ANAR;
|
||||
mii[MII_REGNUM].Content = autoneg|1;
|
||||
write_mii( prg, &mii[MII_REGNUM], 1 );
|
||||
prg->opts.renegotiate = 1;
|
||||
}
|
||||
|
||||
if( prg->opts.renegotiate )
|
||||
{
|
||||
Printf("restarting autonegotiation...\n");
|
||||
|
||||
mii[MII_REGNUM].ID = MII_BMCR;
|
||||
mii[MII_REGNUM].Content = 0x0000;
|
||||
write_mii( prg, &mii[MII_REGNUM], 1 );
|
||||
|
||||
mii[MII_REGNUM].ID = MII_BMCR;
|
||||
mii[MII_REGNUM].Content = MII_BMCR_AN_ENA|MII_BMCR_RESTART;
|
||||
write_mii( prg, &mii[MII_REGNUM], 1 );
|
||||
}
|
||||
|
||||
if( prg->opts.force )
|
||||
{
|
||||
UWORD bmcr = 0;
|
||||
if( force & (MII_AN_100BASETX_FD|MII_AN_100BASETX_HD))
|
||||
bmcr |= MII_BMCR_100MBIT;
|
||||
if( force & (MII_AN_100BASETX_FD|MII_AN_10BASET_FD))
|
||||
bmcr |= MII_BMCR_DUPLEX;
|
||||
|
||||
mii[MII_REGNUM].ID = MII_BMCR;
|
||||
mii[MII_REGNUM].Content = bmcr;
|
||||
write_mii( prg, &mii[MII_REGNUM], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
end_prog(prg);
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*******************************************************************************************/
|
||||
/** **/
|
||||
/** miitool.h **/
|
||||
/** definitions for PHY registers **/
|
||||
/** **/
|
||||
/** Copyright (C) 2000 David A. Hinds -- dhinds@pcmcia.sourceforge.org **/
|
||||
/** **/
|
||||
/** origin: mii.h in net-tools-1.60 **/
|
||||
/** **/
|
||||
/*******************************************************************************************/
|
||||
#ifndef _INC_MIITOOL_H
|
||||
#define _INC_MIITOOL_H
|
||||
|
||||
/* Basic Mode Control Register */
|
||||
#define MII_BMCR 0x00
|
||||
#define MII_BMCR_RESET 0x8000
|
||||
#define MII_BMCR_LOOPBACK 0x4000
|
||||
#define MII_BMCR_100MBIT 0x2000
|
||||
#define MII_BMCR_AN_ENA 0x1000
|
||||
#define MII_BMCR_ISOLATE 0x0400
|
||||
#define MII_BMCR_RESTART 0x0200
|
||||
#define MII_BMCR_DUPLEX 0x0100
|
||||
#define MII_BMCR_COLTEST 0x0080
|
||||
|
||||
/* Basic Mode Status Register */
|
||||
#define MII_BMSR 0x01
|
||||
#define MII_BMSR_CAP_MASK 0xf800
|
||||
#define MII_BMSR_100BASET4 0x8000
|
||||
#define MII_BMSR_100BASETX_FD 0x4000
|
||||
#define MII_BMSR_100BASETX_HD 0x2000
|
||||
#define MII_BMSR_10BASET_FD 0x1000
|
||||
#define MII_BMSR_10BASET_HD 0x0800
|
||||
#define MII_BMSR_NO_PREAMBLE 0x0040
|
||||
#define MII_BMSR_AN_COMPLETE 0x0020
|
||||
#define MII_BMSR_REMOTE_FAULT 0x0010
|
||||
#define MII_BMSR_AN_ABLE 0x0008
|
||||
#define MII_BMSR_LINK_VALID 0x0004
|
||||
#define MII_BMSR_JABBER 0x0002
|
||||
#define MII_BMSR_EXT_CAP 0x0001
|
||||
|
||||
#define MII_PHY_ID1 0x02
|
||||
#define MII_PHY_ID2 0x03
|
||||
|
||||
/* Auto-Negotiation Advertisement Register */
|
||||
#define MII_ANAR 0x04
|
||||
/* Auto-Negotiation Link Partner Ability Register */
|
||||
#define MII_ANLPAR 0x05
|
||||
#define MII_AN_NEXT_PAGE 0x8000
|
||||
#define MII_AN_ACK 0x4000
|
||||
#define MII_AN_REMOTE_FAULT 0x2000
|
||||
#define MII_AN_ABILITY_MASK 0x07e0
|
||||
#define MII_AN_FLOW_CONTROL 0x0400
|
||||
#define MII_AN_100BASET4 0x0200
|
||||
#define MII_AN_100BASETX_FD 0x0100
|
||||
#define MII_AN_100BASETX_HD 0x0080
|
||||
#define MII_AN_10BASET_FD 0x0040
|
||||
#define MII_AN_10BASET_HD 0x0020
|
||||
#define MII_AN_PROT_MASK 0x001f
|
||||
#define MII_AN_PROT_802_3 0x0001
|
||||
|
||||
/* Auto-Negotiation Expansion Register */
|
||||
#define MII_ANER 0x06
|
||||
#define MII_ANER_MULT_FAULT 0x0010
|
||||
#define MII_ANER_LP_NP_ABLE 0x0008
|
||||
#define MII_ANER_NP_ABLE 0x0004
|
||||
#define MII_ANER_PAGE_RX 0x0002
|
||||
#define MII_ANER_LP_AN_ABLE 0x0001
|
||||
|
||||
|
||||
#endif /* _INC_MIITOOL_H */
|
||||
@@ -36,21 +36,20 @@ extern const BYTE DeviceName[];
|
||||
#define HW_INTERVALDEF 10000
|
||||
#define HW_DEFSPI 2
|
||||
|
||||
|
||||
/* these calls might not run within the context of a process and
|
||||
will be called from varying tasks and without prior init:
|
||||
hw_Find_Boards()
|
||||
hw_Find_Boards() - this one just identifies available HW and returns #boards
|
||||
hw_AllocBoard()
|
||||
hw_ReleaseBoard()
|
||||
hw_GetMacAddress()
|
||||
hw_GetMacAddress() - get default MAC address from board
|
||||
|
||||
these calls are in the context of the server task:
|
||||
hw_Setup() - general init (board allocated already)
|
||||
hw_Shutdown() - general shutdown (board still allocated)
|
||||
hw_Attach() - make hardware ready for action (online)
|
||||
hw_Detach() - put hardware into sleep mode (offline)
|
||||
hw_Setup() - general init (board allocated already)
|
||||
hw_Shutdown() - general shutdown (board still allocated)
|
||||
hw_Attach() - make hardware ready for action (online)
|
||||
hw_Detach() - put hardware into sleep mode (offline)
|
||||
|
||||
hw_recv_sigmask() - get signals for hardware (if any)
|
||||
hw_recv_sigmask() - get signals for hardware (if any, i.e. signal on interrupt)
|
||||
hw_recv_pending() - check for pending receive frames
|
||||
|
||||
hw_recv_frame() - receive one frame
|
||||
@@ -59,10 +58,14 @@ extern const BYTE DeviceName[];
|
||||
and apply them (called only when no RX/TX
|
||||
in progress)
|
||||
|
||||
hw_config_init() - set defaults for HW
|
||||
hw_config_update() - update config of HW
|
||||
hw_ConfigInit() - set defaults for HW
|
||||
hw_ConfigUpdate() - update config of HW
|
||||
|
||||
hw_change_multicast - re-initialize multicast filter for new address list
|
||||
hw_get_mac_status() - running parameters (optional), S2_DEVICEQUERYEXT
|
||||
*/
|
||||
|
||||
|
||||
#ifdef PROTO_V2EXPNET
|
||||
#define USE_INTERRUPT
|
||||
|
||||
|
||||
+143
-12
@@ -35,9 +35,12 @@ static LONG server_queryext( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq );
|
||||
*/
|
||||
#define S2QUERYEXT_NOLENGTHCHECK
|
||||
|
||||
/* this limits the number of write requests per run, also improves
|
||||
Roadshow performance when active */
|
||||
#define ONE_WRITE_REQ
|
||||
/* tunables: number of one-call read and write requests */
|
||||
/* this limits the number of processed write requests per run when enabled */
|
||||
#define ONE_WRITE_REQ 2
|
||||
/* this limits the number of processed read requests per run when enabled */
|
||||
#define ONE_READ_REQ 2
|
||||
|
||||
|
||||
|
||||
/* (avoid external link libraries) this call is not time critical */
|
||||
@@ -570,6 +573,67 @@ static LONG server_queryext( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef S2_DevQueryExtGetMII
|
||||
tval = GetTagData( S2_DevQueryExtGetMII, 0, tlist );
|
||||
if( tval )
|
||||
{
|
||||
struct S2DevQueryMIIParam *miip;
|
||||
LONG res;
|
||||
LONG curidx=0,lastidx = 0;
|
||||
|
||||
D(("MII Register Query"));
|
||||
|
||||
s2qep = (struct S2DevQueryExtParam *)tval;
|
||||
len = s2qep->Length; /* in Bytes */
|
||||
miip = (struct S2DevQueryMIIParam *)s2qep->Data;
|
||||
|
||||
while( curidx <= len-sizeof( struct S2DevQueryMIIParam ) )
|
||||
{
|
||||
if( (res = hw_read_phy( db, unit, miip->ID )) >= 0 )
|
||||
{
|
||||
miip->Content = res;
|
||||
lastidx = curidx;
|
||||
}
|
||||
else
|
||||
{ /* can't read register ID, invalidate */
|
||||
miip->ID = S2_DEVQUERYEXT_MII_INVALID;
|
||||
miip->Content = 0;
|
||||
}
|
||||
|
||||
miip++;
|
||||
curidx += sizeof( struct S2DevQueryMIIParam );
|
||||
}
|
||||
s2qep->Actual = lastidx;
|
||||
}
|
||||
#endif
|
||||
#ifdef S2_DevQueryExtSetMII
|
||||
tval = GetTagData( S2_DevQueryExtSetMII, 0, tlist );
|
||||
if( tval )
|
||||
{
|
||||
struct S2DevQueryMIIParam *miip;
|
||||
LONG res;
|
||||
LONG curidx=0,lastidx = 0;
|
||||
|
||||
D(("MII Register Write"));
|
||||
|
||||
s2qep = (struct S2DevQueryExtParam *)tval;
|
||||
len = s2qep->Length; /* in Bytes */
|
||||
miip = (struct S2DevQueryMIIParam *)s2qep->Data;
|
||||
|
||||
while( curidx <= len-sizeof( struct S2DevQueryMIIParam ) )
|
||||
{
|
||||
if( miip->ID != S2_DEVQUERYEXT_MII_INVALID )
|
||||
{
|
||||
if( (res = hw_write_phy( db, unit, miip->ID, miip->Content )) >= 0 )
|
||||
lastidx = curidx;
|
||||
|
||||
miip++;
|
||||
curidx += sizeof( struct S2DevQueryMIIParam );
|
||||
}
|
||||
}
|
||||
s2qep->Actual = lastidx;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -632,20 +696,34 @@ LONG server_writeerror( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq, LONG cod
|
||||
|
||||
|
||||
#ifndef EXTERNAL_WRITE_FRAME
|
||||
/* note: entering here with locked semaphore */
|
||||
/*
|
||||
note: entering here with locked semaphore
|
||||
note(2): HW_DMA_TX is maybe a little misleading in it's actual use here.
|
||||
This implementation will use that SANA-II capability in the following
|
||||
way: Obtain a pointer to either the whole frame (RAW) or the Payload
|
||||
and send either a complete frame or two chunks down to the hardware.
|
||||
HW_DMA_TX is defined by the Makefile. One of the chunks
|
||||
is the constant-size header (14 Bytes) and the other is the payload.
|
||||
*/
|
||||
static LONG write_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq )
|
||||
{
|
||||
LONG ret;/* = SERR_OK;*/
|
||||
UBYTE *copy_ptr,*frame;
|
||||
ULONG framesize;
|
||||
struct db_BufferManagement *dbm;
|
||||
#ifdef HW_DMA_TX
|
||||
UBYTE *header_ptr;
|
||||
#endif
|
||||
|
||||
D(("write: type %08lx, size %ld\n",ioreq->ios2_PacketType,
|
||||
ioreq->ios2_DataLength));
|
||||
|
||||
frame = db->db_svdat.sv_frame;
|
||||
framesize = ioreq->ios2_DataLength;
|
||||
copy_ptr = frame;
|
||||
copy_ptr = frame;
|
||||
#ifdef HW_DMA_TX
|
||||
header_ptr= NULL;
|
||||
#endif
|
||||
|
||||
/* copy raw frame: simply overwrite ethernet frame part of plip packet */
|
||||
if( !(ioreq->ios2_Req.io_Flags & SANA2IOF_RAW) )
|
||||
@@ -653,18 +731,46 @@ static LONG write_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq )
|
||||
COPYMAC( frame, ioreq->ios2_DstAddr ); /* macro in server.h */
|
||||
COPYMAC( frame+6, db->db_Units[unit].du_CFGAddr );
|
||||
*( (USHORT*)(frame+12)) = ioreq->ios2_PacketType;
|
||||
copy_ptr += 14;
|
||||
#ifdef HW_DMA_TX
|
||||
header_ptr = frame;
|
||||
copy_ptr += 16; /* aligned behind header with a gap of 2 */
|
||||
#else
|
||||
copy_ptr += 14;
|
||||
framesize += 14;
|
||||
#endif
|
||||
}
|
||||
|
||||
dbm = (struct db_BufferManagement *)ioreq->ios2_BufferManagement;
|
||||
|
||||
/* copy32 is valid ptr, even if the stack offers only regular CopyFromBuffer */
|
||||
/* #if 0 */
|
||||
#ifdef HW_DMA_TX
|
||||
/* hw implementation supports it, now check if we can use DMA copy buffer */
|
||||
if( dbm->dbm_CopyFromBufferDMA )
|
||||
{
|
||||
UBYTE *dma_ptr;
|
||||
|
||||
dma_ptr = (UBYTE*)(*dbm->dbm_CopyFromBufferDMA)( ioreq->ios2_Data, NULL, 0 );
|
||||
if( dma_ptr )
|
||||
{
|
||||
/* pass extra header if not raw */
|
||||
hw_send_frame(db, unit, dma_ptr,framesize, header_ptr );
|
||||
|
||||
ret = SERR_OK; /* FIXME: error code */
|
||||
goto dmasend_done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* copy32 is a valid ptr, even if the stack offers only regular CopyFromBuffer */
|
||||
if( (*dbm->dbm_CopyFromBuffer32)(copy_ptr,ioreq->ios2_Data, ioreq->ios2_DataLength) )
|
||||
{
|
||||
send:
|
||||
D(("+hw_send\n"));
|
||||
ret = hw_send_frame(db, unit, frame, framesize) ? SERR_OK : SERR_ERROR;
|
||||
#ifdef HW_DMA_TX
|
||||
ret = hw_send_frame(db, unit, copy_ptr, framesize, header_ptr ) ? SERR_OK:SERR_ERROR;
|
||||
#else
|
||||
ret = hw_send_frame(db, unit, frame, framesize ) ? SERR_OK : SERR_ERROR;
|
||||
#endif
|
||||
D(("-hw_send\n"));
|
||||
}
|
||||
else
|
||||
@@ -676,6 +782,10 @@ send:
|
||||
ret = SERR_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HW_DMA_TX
|
||||
dmasend_done:
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -684,17 +794,20 @@ send:
|
||||
static LONG server_writequeue( DEVBASEP, ULONG unit )
|
||||
{
|
||||
LONG code;
|
||||
#ifdef ONE_WRITE_REQ
|
||||
LONG t = 0;
|
||||
#endif
|
||||
struct IOSana2Req *ioreq,*nextio;
|
||||
|
||||
ObtainSemaphore( &db->db_Units[unit].du_Sem );
|
||||
|
||||
#if 1 /* #ifdef ONE_WRITE_REQ */
|
||||
#if 1
|
||||
/* whole queue per call */
|
||||
for( ioreq = (struct IOSana2Req *)db->db_Units[unit].du_WriteQueue.lh_Head;
|
||||
(nextio= (struct IOSana2Req *)ioreq->ios2_Req.io_Message.mn_Node.ln_Succ);
|
||||
ioreq = nextio )
|
||||
#else
|
||||
/* single write per call */
|
||||
/* single write per call (deprecated in favor of ONE_WRITE_REQ) */
|
||||
ioreq = (struct IOSana2Req *)db->db_Units[unit].du_WriteQueue.lh_Head;
|
||||
if( ioreq->ios2_Req.io_Message.mn_Node.ln_Succ )
|
||||
#endif
|
||||
@@ -731,8 +844,13 @@ static LONG server_writequeue( DEVBASEP, ULONG unit )
|
||||
server_writeerror( db, unit, ioreq, code );
|
||||
}
|
||||
#ifdef ONE_WRITE_REQ
|
||||
if( hw_recv_pending(db,unit) )
|
||||
t++;
|
||||
if( t >= ONE_WRITE_REQ ) /* this somewhat balances hardware polling overhead vs. IP-stack timing */
|
||||
{
|
||||
t = 0;
|
||||
if( hw_recv_pending(db,unit) )
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -817,6 +935,9 @@ static LONG server_readqueue( DEVBASEP, ULONG unit )
|
||||
LONG framesize;
|
||||
LONG frametype;
|
||||
LONG dropflag;
|
||||
#ifdef ONE_READ_REQ
|
||||
LONG t=0;
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
{
|
||||
@@ -895,7 +1016,17 @@ nextframe:
|
||||
/* TODO: check for error, send S2EVENT_HARDWARE|S2EVENT_ERROR|S2EVENT_RX along with stats db_DevStats.BadData */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#ifdef ONE_READ_REQ
|
||||
t++;
|
||||
if( t>= ONE_READ_REQ )
|
||||
{
|
||||
struct IOSana2Req *wr = (struct IOSana2Req *)db->db_Units[unit].du_WriteQueue.lh_Head;
|
||||
/* t=0; */
|
||||
if( wr->ios2_Req.io_Message.mn_Node.ln_Succ )
|
||||
goto end; /* pending writes ? -> leave after ONE_READ_REQ requests */
|
||||
}
|
||||
#endif
|
||||
} /* while(1) */
|
||||
end:
|
||||
return SERR_OK;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ ASMOBJECTS = $(SUBDIR)/enc624j6l.o$(TYPE) $(SUBDIR)/intervaltimer.o$(TYPE)
|
||||
# more than one flavour of the same code base may be build with this setup
|
||||
# arguments passed down recursively (example):
|
||||
#DEVICEID=v2expeth.device
|
||||
#DEFINES1 = -DPROTO_V2EXPNET
|
||||
#ASMDEFS = -DPROTO_V2EXPNET
|
||||
DEFINES1 = DEFINE HW_DMA_TX=1
|
||||
ASMDEFS1 = -DHW_DMA_TX=1
|
||||
#CPU = 68020
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ DEFINES = $(DEFINES) DEFINE DEVICENAME=$(DEVICEID)
|
||||
ASMDEFS = $(ASMDEFS1)
|
||||
#-DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# debug
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#define _INC_VERSION_H
|
||||
|
||||
#define DEVICEVERSION 2
|
||||
#define DEVICEREVISION 0
|
||||
#define DEVICEREVISION 1
|
||||
#define DEVICEEXTRA
|
||||
/* #define DEVICEEXTRA Beta */
|
||||
#define DEVICEDATE 13.01.2019
|
||||
#define DEVICEDATE 21.02.2019
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user