ENC624J6Net
- changed interrupt usage for Int2 instead of Int6
(after discussion with Matze about "best" approach)
- see HW_INTSOURCE in hw.c for the active interrupt source
- this build reflects changed word handling in CPLD code,
now all addresses below $6000 are presented as Big Endian
words, such that copies of the frames can be done with
fast instructions like movem
This commit is contained in:
@@ -8,10 +8,10 @@ author: Henryk Richter <henryk.richter@gmx.net>
|
||||
Release Notes:
|
||||
--------------
|
||||
|
||||
- goes along with 21 December 2017 CPLD build, where interrupts are extended
|
||||
- goes along with 27 December 2017 CPLD build, where interrupts are extended
|
||||
- older CPLD builds will lock up Amiga at first interrupt
|
||||
- provisions for swapped address lines 12/13 are in the code
|
||||
- board requires Int6 to be soldered (NOT Int2)
|
||||
- board requires Int2 to be soldered (NOT Int6)
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
@@ -32,8 +32,6 @@ as argument will then activate the driver for RoadShow.
|
||||
Technical notes:
|
||||
----------------
|
||||
|
||||
(IMPORTANT: not _yet_ true for current CPLD build)
|
||||
|
||||
Matze's card does selective byte swapping for different areas of the chip within
|
||||
the CPLD. This step enables Big Endian reads/writes to the hardware registers. Since
|
||||
the SRAM would be byte-swapped as well, the latest (WIP) version of the CPLD presents
|
||||
|
||||
Binary file not shown.
@@ -79,6 +79,15 @@
|
||||
#include "enc624j6l.h" /* for MAC retrieval */
|
||||
#endif
|
||||
|
||||
#ifdef DIRECT_WRITE
|
||||
typedef enum { AW_OK, AW_BUFFER_ERROR, AW_ERROR } AW_RESULT;
|
||||
PUBLIC REGARGS VOID DoEvent(BASEPTR, long event);
|
||||
PUBLIC REGARGS AW_RESULT write_frame(BASEPTR, struct IOSana2Req *ios2);
|
||||
#ifndef __HW_H
|
||||
#include "hw.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define INVALID_SDNET_UNIT 0x33 /* used by both sdnet and encnet */
|
||||
|
||||
/*E*/
|
||||
@@ -723,9 +732,55 @@ PRIVATE APTR pb_AllocExpansion( ULONG portid, BASEPTR )
|
||||
ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
|
||||
ios2->ios2_Req.io_Error = 0;
|
||||
ObtainSemaphore(&pb->pb_WriteListSem);
|
||||
#ifdef DIRECT_WRITE
|
||||
{
|
||||
AW_RESULT code;
|
||||
struct IOSana2Req *currentwrite = (struct IOSana2Req*)ios2;
|
||||
|
||||
code = write_frame(pb, ios2);
|
||||
if (code == AW_BUFFER_ERROR) /* BufferManagement callback error */
|
||||
{
|
||||
d(("buffer error\n"));
|
||||
DoEvent(pb, S2EVENT_ERROR | S2EVENT_BUFF | S2EVENT_SOFTWARE);
|
||||
pb->pb_SpecialStats[S2SS_TXERRORS].Count++;
|
||||
d(("pb->pb_SpecialStats[S2SS_TXERRORS].Count = %ld\n",pb->pb_SpecialStats[S2SS_TXERRORS].Count));
|
||||
currentwrite->ios2_Req.io_Error = S2ERR_SOFTWARE;
|
||||
currentwrite->ios2_WireError = S2WERR_BUFF_ERROR;
|
||||
Remove((struct Node*)currentwrite);
|
||||
DevTermIO(pb, currentwrite);
|
||||
}
|
||||
else if (code == AW_ERROR)
|
||||
{
|
||||
/*
|
||||
** this is a real line error, upper levels (e.g. Internet TCP) have
|
||||
** to care for reliability!
|
||||
*/
|
||||
d(("error while transmitting packet\n"));
|
||||
DoEvent(pb, S2EVENT_ERROR | S2EVENT_TX | S2EVENT_HARDWARE);
|
||||
pb->pb_SpecialStats[S2SS_TXERRORS].Count++;
|
||||
d(("pb->pb_SpecialStats[S2SS_TXERRORS].Count = %ld\n",pb->pb_SpecialStats[S2SS_TXERRORS].Count));
|
||||
currentwrite->ios2_Req.io_Error = S2ERR_TX_FAILURE;
|
||||
currentwrite->ios2_WireError = S2WERR_GENERIC_ERROR;
|
||||
Remove((struct Node*)currentwrite);
|
||||
DevTermIO(pb, currentwrite);
|
||||
}
|
||||
else /*if (code == AW_OK)*/ /* well done! */
|
||||
{
|
||||
d(("packet transmitted successfully\n"));
|
||||
pb->pb_DevStats.PacketsSent++;
|
||||
dotracktype(pb, (ULONG) pb->pb_Frame->hwf_Type, 1, 0, currentwrite->ios2_DataLength, 0, 0);
|
||||
currentwrite->ios2_Req.io_Error = S2ERR_NO_ERROR;
|
||||
currentwrite->ios2_WireError = S2WERR_GENERIC_ERROR;
|
||||
Remove((struct Node*)currentwrite);
|
||||
DevTermIO(pb, currentwrite);
|
||||
}
|
||||
}
|
||||
ReleaseSemaphore(&pb->pb_WriteListSem);
|
||||
#else
|
||||
AddTail((struct List*)&pb->pb_WriteList, (struct Node*)ios2);
|
||||
ReleaseSemaphore(&pb->pb_WriteListSem);
|
||||
Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_F);
|
||||
#endif
|
||||
ios2 = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -30,10 +30,10 @@ DEBUG EQU 1
|
||||
;
|
||||
|
||||
;------------------ options, some depend on hardware (CPLD) configuration -------------------------
|
||||
_OPT_BUFFER_SWAP EQU 1 ;perform byte swap on buffer ops (1) or assume native endian (0)
|
||||
_OPT_BUFFER_SWAP EQU 0 ;perform byte swap on buffer ops (1) or assume native endian (0)
|
||||
_OPT_REG_SWAP EQU 0 ;perform byte swap on register ops (1) or assume native endian (0)
|
||||
_OPT_ADR_QUIRK EQU 1 ;address lines 12/13 are swapped (1) or linear addressing (0)
|
||||
_OPT_FLOWCONTROL EQU 1 ;perform flow control on RX (1) or not (0)
|
||||
_OPT_FLOWCONTROL EQU 0 ;perform flow control on RX (1) or not (0)
|
||||
_OPT_RECV EQU 1 ;faster recv (1) or generic (0)
|
||||
|
||||
;
|
||||
@@ -65,6 +65,15 @@ PSwapTX EQU $600 ;swap between two TX buffers (one active, one activated after
|
||||
;
|
||||
;
|
||||
|
||||
;------------- driver init flags -----------------------------------
|
||||
PIO_INIT_FULL_DUPLEX EQU 1
|
||||
PIO_INIT_LOOP_BACK EQU 2
|
||||
PIO_INIT_BROAD_CAST EQU 4
|
||||
PIO_INIT_FLOW_CONTROL EQU 8
|
||||
PIO_INIT_MULTI_CAST EQU 16
|
||||
PIO_INIT_PROMISC EQU 32
|
||||
|
||||
|
||||
|
||||
ifne DEBUG
|
||||
;
|
||||
@@ -1179,6 +1188,7 @@ _enc624j6l_SetMAC: ;set user defined MAC address
|
||||
; testing with low turnaround time.
|
||||
;
|
||||
; In: A0 - Board base address
|
||||
; D1 - flags
|
||||
;
|
||||
; Out:
|
||||
; D0 <= 0 - failure
|
||||
@@ -1205,9 +1215,9 @@ _enc624j6l_Init:
|
||||
|
||||
;33.333Mhz clock out frequency (see defines above)
|
||||
move.w #CLOCK_DEF_CLR,d0 ;clr mask
|
||||
move.w #CLOCK_DEF_SET,d1 ;set mask
|
||||
CLRREG ECON2,a0,d0
|
||||
SETREG ECON2,a0,d1
|
||||
move.w #CLOCK_DEF_SET,d0 ;set mask
|
||||
SETREG ECON2,a0,d0
|
||||
|
||||
; disable crypto engine and all interrupts
|
||||
move #EIR_CRYPTEN|EIR_MODEXIF|EIR_HASHIF|EIR_AESIF|EIR_LINKIF|EIR_PRDYIF|EIR_PKTIF|EIR_DMAIF|EIR_TXIF|EIR_TXABTIF|EIR_RXABTIF|EIR_PCFULIF,d0
|
||||
@@ -1225,17 +1235,24 @@ _enc624j6l_Init:
|
||||
move #RXSTOP_INIT&$fffe,d0
|
||||
WRITEREG ERXTAIL,a0,d0 ;tail pointer in buffer = rx-2, wraparound
|
||||
|
||||
ifne _OPT_FLOWCONTROL
|
||||
; ifne _OPT_FLOWCONTROL
|
||||
moveq #PIO_INIT_FLOW_CONTROL,d0
|
||||
and d1,d0
|
||||
beq.s .init_noflow
|
||||
|
||||
move #(128<<8)|(32),d0 ;128*96=12288 high water mark, 32*96=3072 low water mark
|
||||
WRITEREG ERXWM,a0,d0
|
||||
moveq #MACON1_RXPAUS,d0
|
||||
SETREG MACON1,a0,d0
|
||||
move #ECON2_AUTOFC,d0
|
||||
SETREG ECON2,a0,d0
|
||||
else
|
||||
bra.s .init_flowdone
|
||||
; else
|
||||
.init_noflow:
|
||||
move #ECON2_AUTOFC,d0
|
||||
CLRREG ECON2,a0,d0 ;disable automatic flow control
|
||||
endc
|
||||
.init_flowdone:
|
||||
; endc
|
||||
|
||||
|
||||
;--------------- TX configuration -----------------------
|
||||
@@ -1595,7 +1612,12 @@ _enc624j6l_RecvFrame: ;
|
||||
READREG PNextPacket,a0,d7 ;get user read pointer from private space
|
||||
;lea (a0,d7.w),a2 ;read ptr for next packet address
|
||||
;READREG 0,a2,d0 ;next packet pointer
|
||||
|
||||
READSRAM a0,d7,d0 ;move (a0,d7.w),d0
|
||||
ifeq _OPT_BUFFER_SWAP
|
||||
rol.w #8,d0 ;swap pointer to Big Endian
|
||||
endc
|
||||
|
||||
;verify next packet pointer, re-initialize recv if this is invalid
|
||||
cmp #RXSTOP_INIT,d0 ;bad pointer (<0 or >end of memory)
|
||||
bhi.w .recv_err
|
||||
@@ -1629,6 +1651,9 @@ _enc624j6l_RecvFrame: ;
|
||||
;lea (a0,d7.w),a2 ;read ptr for first control word
|
||||
;READREG 0,a2,d0 ;last control word = length (byte count)
|
||||
READSRAM a0,d7,d0 ;move (a0,d7.w),d0
|
||||
ifeq _OPT_BUFFER_SWAP
|
||||
rol.w #8,d0 ;swap pointer to Big Endian
|
||||
endc
|
||||
|
||||
and.w #$f800,d0 ;verify (should be all zeros in upper 9 bits)
|
||||
bne .recv_err ;receive buffer is wrong -> re-initialize
|
||||
@@ -1638,6 +1663,9 @@ _enc624j6l_RecvFrame: ;
|
||||
;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
|
||||
;D1 is the distance to the next frame = stored length + recv vevtor
|
||||
@@ -1676,15 +1704,20 @@ _enc624j6l_RecvFrame: ;
|
||||
endc
|
||||
lea (a0,d7.w),a2 ;read pointer
|
||||
move d0,d1 ;byte count
|
||||
lsr #1,d1 ;converted to word count
|
||||
lsr #2,d1 ;converted to dword count
|
||||
bcs.s .opt_read ;read 1 byte more if impair byte count
|
||||
subq #1,d1 ;words - 1
|
||||
.opt_read:
|
||||
move (a2)+,d2 ;get current word
|
||||
ifne _OPT_BUFFER_SWAP
|
||||
move.w (a2)+,d2 ;get current word
|
||||
rol.w #8,d2 ;swap buffer to Big Endian
|
||||
move.w d2,(a1)+
|
||||
move.w (a2)+,d2 ;get current word
|
||||
rol.w #8,d2 ;swap buffer to Big Endian
|
||||
move.w d2,(a1)+
|
||||
else
|
||||
move.l (a2)+,(a1)+
|
||||
endc
|
||||
move d2,(a1)+
|
||||
dbf d1,.opt_read
|
||||
bra.s .end_read
|
||||
.nooptrecv:
|
||||
|
||||
@@ -90,8 +90,8 @@
|
||||
#define BOARD hwb->hwb_boards[0]
|
||||
|
||||
/* interrupt (choice here is INTB_EXTER or INTB_PORTS, depending on solder blob */
|
||||
#define HW_INTSOURCE INTB_EXTER
|
||||
/*#define HW_INTSOURCE INTB_PORTS*/
|
||||
/*#define HW_INTSOURCE INTB_EXTER */ /* Int 6 */
|
||||
#define HW_INTSOURCE INTB_PORTS /* Int 2 */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -193,6 +193,7 @@ GLOBAL REGARGS void hw_config_init(struct PLIPBase *pb)
|
||||
hwb->hwb_fullduplex = 0;
|
||||
hwb->hwb_spispeed = 1; /* optimistic default */
|
||||
hwb->hwb_multicast = 0;
|
||||
hwb->hwb_flowcontrol= 0; /* no flow control by default */
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +217,10 @@ GLOBAL REGARGS void hw_config_update(struct PLIPBase *pb, struct TemplateConfig
|
||||
{
|
||||
hwb->hwb_multicast = 1;
|
||||
}
|
||||
if( args->flowcontrol )
|
||||
{
|
||||
hwb->hwb_flowcontrol = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -355,9 +360,10 @@ GLOBAL REGARGS BOOL hw_attach(struct PLIPBase *pb)
|
||||
flags = PIO_INIT_BROAD_CAST;
|
||||
if( hwb->hwb_multicast )
|
||||
flags |= PIO_INIT_MULTI_CAST;
|
||||
|
||||
if( hwb->hwb_fullduplex )
|
||||
flags |= PIO_INIT_FULL_DUPLEX;
|
||||
if( hwb->hwb_flowcontrol )
|
||||
flags |= PIO_INIT_FLOW_CONTROL;
|
||||
#ifdef PROTO_ENC624NET
|
||||
if( enc624j6l_Init( BOARD, (unsigned long)flags ) <= 0 )
|
||||
rc = FALSE; /* ERROR IN CASE OF DEVICE NOT FOUND */
|
||||
|
||||
@@ -39,9 +39,11 @@ struct HWBase
|
||||
|
||||
/* config options */
|
||||
ULONG hwb_timervalue; /* timer speed */
|
||||
ULONG hwb_fullduplex; /* full duplex */
|
||||
UBYTE hwb_fullduplex; /* full duplex */
|
||||
UBYTE hwb_flowcontrol; /* flow control enable (1/0) */
|
||||
UBYTE hwb_multicast; /* multicast enable */
|
||||
UBYTE hwb_free_unused1;
|
||||
ULONG hwb_spispeed; /* SPI speed */
|
||||
ULONG hwb_multicast; /* multicast enable */
|
||||
};
|
||||
|
||||
#define HWB_RECV_PENDING 0
|
||||
@@ -57,8 +59,8 @@ struct HWBase
|
||||
|
||||
/* ----- config ----- */
|
||||
|
||||
#define CONFIGFILE "ENV:SANA2/sdnet.config"
|
||||
#define TEMPLATE "TIMER/K/N,FULLDUPLEX/S,SPISPEED/K/N,MULTICAST/S"
|
||||
#define CONFIGFILE "ENV:SANA2/enc624j6net.config"
|
||||
#define TEMPLATE "TIMER/K/N,FULLDUPLEX/S,SPISPEED/K/N,MULTICAST/S,FLOWCONTROL/S"
|
||||
|
||||
/* structure to be filled by ReadArgs template */
|
||||
struct TemplateConfig
|
||||
@@ -68,6 +70,7 @@ struct TemplateConfig
|
||||
ULONG fullduplex;
|
||||
ULONG *spispeed;
|
||||
ULONG multicast;
|
||||
ULONG flowcontrol;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,12 +65,12 @@ PUBLIC VOID SAVEDS ServerTask(void);
|
||||
/*E*/
|
||||
/*F*/ /* private */
|
||||
PRIVATE struct PLIPBase *startup(void);
|
||||
PRIVATE REGARGS VOID DoEvent(BASEPTR, long event);
|
||||
PUBLIC REGARGS VOID DoEvent(BASEPTR, long event);
|
||||
PRIVATE VOID readargs(BASEPTR);
|
||||
PRIVATE BOOL init(BASEPTR);
|
||||
PRIVATE REGARGS BOOL goonline(BASEPTR);
|
||||
PRIVATE REGARGS VOID gooffline(BASEPTR);
|
||||
PRIVATE REGARGS AW_RESULT write_frame(BASEPTR, struct IOSana2Req *ios2);
|
||||
PUBLIC REGARGS AW_RESULT write_frame(BASEPTR, struct IOSana2Req *ios2);
|
||||
PRIVATE REGARGS VOID dowritereqs(BASEPTR);
|
||||
PRIVATE REGARGS VOID doreadreqs(BASEPTR);
|
||||
PRIVATE REGARGS VOID dos2reqs(BASEPTR);
|
||||
@@ -161,7 +161,7 @@ PRIVATE REGARGS VOID dos2reqs(BASEPTR);
|
||||
/*
|
||||
** SANA-2 Event management
|
||||
*/
|
||||
/*F*/ PRIVATE REGARGS VOID DoEvent(BASEPTR, long event)
|
||||
/*F*/ PUBLIC REGARGS VOID DoEvent(BASEPTR, long event)
|
||||
{
|
||||
struct IOSana2Req *ior, *ior2;
|
||||
|
||||
@@ -187,7 +187,7 @@ PRIVATE REGARGS VOID dos2reqs(BASEPTR);
|
||||
/*
|
||||
** writing packets
|
||||
*/
|
||||
/*F*/ PRIVATE REGARGS AW_RESULT write_frame(BASEPTR, struct IOSana2Req *ios2)
|
||||
/*F*/ PUBLIC REGARGS AW_RESULT write_frame(BASEPTR, struct IOSana2Req *ios2)
|
||||
{
|
||||
AW_RESULT rc;
|
||||
struct HWFrame *frame = pb->pb_Frame;
|
||||
|
||||
@@ -17,6 +17,9 @@ HWSRCDIR = enc624j6net
|
||||
DEVICE_NAME = enc624j6net
|
||||
DEFS = DEFINE PROTO_ENC624NET=1
|
||||
|
||||
# quick hack/test to write directly - didn't work out for me
|
||||
#DEFINE DIRECT_WRITE=1
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
# I keep various include trees, so for this project I directly reference
|
||||
|
||||
Reference in New Issue
Block a user