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:
HenrykRichter
2018-01-09 21:40:50 +01:00
parent dde9bf1d4e
commit 13c4b7f8e6
8 changed files with 129 additions and 31 deletions
+2 -4
View File
@@ -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.
+55
View File
@@ -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;
+43 -10
View File
@@ -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:
+9 -3
View File
@@ -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 */
+7 -4
View File
@@ -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
+4 -4
View File
@@ -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;
+3
View File
@@ -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