Updated baxnet-driver ansd Z3-Interface

This commit is contained in:
MHeinrichs
2019-11-15 00:40:34 +01:00
parent 906d8a902f
commit d125d49fa6
58 changed files with 27198 additions and 18831 deletions
+3 -3
View File
@@ -19,7 +19,7 @@
#
###############################################################################
# debug = 1 will include string debugging for terminal/sushi/sashimi
debug = 0
debug = 1
# compiler_vcc = 1 will trigger VBCC, else GCC
compiler_vcc = 0
@@ -27,8 +27,8 @@ compiler_vcc = 0
# prefix for system includes (ASM)
# native AmigaOS compilation: set PREFX=GG: or PREFX=ADE:, depending on toolchain
###############################################################################
#PREFX = /opt/amigaos-68k/
PREFX = gg:
PREFX = /opt/amigaos-68k/
#PREFX = gg:
SYSINC = $(PREFX)os-include
###############################################################################
+1 -1
View File
@@ -32,7 +32,7 @@ ASMOBJECTS = $(SUBDIR)/enc624j6l.o $(SUBDIR)/intervaltimer.o kprintf.o
DEVICEID=enc624j6net.device
DEFINES = -DHW_DMA_TX # -DPROTO_V2EXPNET
ASMDEFS = -DHW_DMA_TX # -DPROTO_V2EXPNET
ASMDEFS = # -DPROTO_V2EXPNET
CPU = 68020
DEVICEID2=enc624j6net.device_68000
+5 -6
View File
@@ -19,10 +19,9 @@ _LVORawMayGetChar equ -$1fe
;
;
;
ifne DEBUG
ifd DEBUG
; XREF _KPrintFa0a1
; XREF _KPrintF
XREF _KPrintF
WRITEDEBUG macro
movem.l d0/d1/a0/a1,-(sp)
@@ -52,7 +51,7 @@ WRITEDEBUG macro
endif
lea.l (\1),a0
move.l sp,a1
jsr _KPrintFa0a1
jsr _KPrintF
ifnb \2
add.l #4,sp
endif
@@ -81,7 +80,7 @@ WRITEDEBUG macro
endm
else
WRITEDEBUG macro
;
nop
endm
endc
@@ -118,7 +117,7 @@ WRITEOUT macro
ifd DEBUG
move.l \1,a0
move.l sp,a1
jsr _KPrintFa0a1
jsr _KPrintF
endif
move.l \1,d1
move.l sp,d2
+1 -8
View File
@@ -75,12 +75,6 @@ const struct NSDeviceQueryResult NSDQueryAnswer = {
#include "hw.h"
#include "macros.h"
/* enable heavy debug (D2=beginIO) */
#define D2(x)
#define D4(x)
/* #define D2(x) D(x) */
/* #define D4(x) D(x) */
@@ -388,8 +382,7 @@ ASM SAVEDS VOID DevBeginIO( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
/*ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;*/
/* heavy debug on beginIO */
D2(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
switch( ioreq->ios2_Req.io_Command )
{
+11 -37
View File
@@ -1,4 +1,3 @@
;APS00000000000000000000000000000000000000000000000000000000000000000000000000000000
; ------------------------------------------------------------------------------
; | Lowlevel Access to memory mapped ENC624J600 in PSP mode |
; | Henryk Richter <henryk.richter@gmx.net> |
@@ -20,25 +19,19 @@
; - _enc624j6l_RXReset -> won't recover from totally unresponsive chip (but exits gracefully)
;
; enable debugging code block (comment/uncomment, see below)
DEBUG EQU 0
DEBUG EQU 1
GLOBALINT_BOARD EQU 1 ;if 1, then toggle board interrupt, else ENC624 INTIE
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"
ifnd DEBUG
DEBUG EQU 0
endc
ifne 1
include "debug.i"
else
WRITEDEBUG macro
nop
endm
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
@@ -141,6 +134,12 @@ _LVOSignal EQU -324
section code,code
; -----------------------------------------------------------------------------
; | |
; | Test/Debug code |
@@ -278,13 +277,7 @@ regtests:
READREG ESTAT,a0,d0
READREG ECON1,a0,d1
READREG MACON2,a0,d2
; READREG MABBIPG,a0,d3
READREG ERXFCON,a0,d3
READREG EHT1,a0,d4
READREG EHT2,a0,d5
READREG EHT3,a0,d6
READREG EHT4,a0,d7
READREG MABBIPG,a0,d3
rts
@@ -594,7 +587,6 @@ _enc624j6l_Init:
WRITEREG ERXST,a0,d0 ;set RX start pointer (end will be $5fff)
WRITEREG PNextPacket,a0,d0 ;set user read pointer
suba.l a1,a1 ;no multicast hash table (yet)
bsr _enc624j6l_bc_mc_filter ;in: A0/D1, out: D0
move #RXSTOP_INIT&$fffe,d0
@@ -652,7 +644,6 @@ _enc624j6l_Init:
;
; in: A0 - board base
; D1 - init flags
; A1 - multicast hash table (4x USHORT)
;out: D0 >0 = OK
; <=0 = FAIL
_enc624j6l_bc_mc_filter:
@@ -667,32 +658,15 @@ _enc624j6l_bc_mc_filter:
move #ERXFCON_NOTMEEN|ERXFCON_MCEN|ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
bra.s .setfilter
.no_promisc:
moveq #PIO_INIT_MULTI_CAST,d0 ;all multicast ?
moveq #PIO_INIT_MULTI_CAST,d0
and d1,d0
beq.s .no_multicast
move #ERXFCON_MCEN|ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
bra.s .setfilter
.no_multicast:
move #ERXFCON_BCEN|ERXFCON_UCEN|ERXFCON_MPEN|ERXFCON_CRCEN|ERXFCON_RUNTEN,d0
; did we get a multicast hash table ?
move.l a1,d1
beq.s .nohashes
AND #$ffff-ERXFCON_MCEN,d0 ;don't accept ALL multicast
OR #ERXFCON_HTEN,d0 ;enable multicast hash table filter
move (a1),d1
WRITEREG EHT1,a0,d1
move 2(a1),d1
WRITEREG EHT2,a0,d1
move 4(a1),d1
WRITEREG EHT3,a0,d1
move 6(a1),d1
WRITEREG EHT4,a0,d1
.nohashes:
.setfilter:
WRITEREG ERXFCON,a0,d0 ;set filter
WRITEREG ERXFCON,a0,d0 ;set filter TODO: pattern matching stuff
moveq #1,d0
.rts:
+2 -3
View File
@@ -239,9 +239,8 @@ ASM SAVEDS int enc624j6l_SetOnline( ASMR(a0) void *board ASMREG(a0) );
>=0 - OK
*/
ASM SAVEDS int enc624j6l_bc_mc_filter(
ASMR(a0) void *board ASMREG(a0),
ASMR(d1) unsigned long flags ASMREG(d1),
ASMR(a1) unsigned short *mc_hashes ASMREG(a1));
ASMR(a0) void *board ASMREG(a0),
ASMR(d1) unsigned long flags ASMREG(d1) );
/*
+9 -166
View File
@@ -30,7 +30,6 @@ extern const BYTE DeviceName[];
/* use generic board fields in current unit */
#define duh_online du_hwl0
#define duh_BASE du_hwp0
#define duh_RefCount du_hwl1
#define HW_INTERVALDEF 100000L
@@ -106,7 +105,7 @@ ASM SAVEDS LONG hw_Find_Boards( ASMR(a0) DEVBASEP ASMREG(a0) )
/* bring board to sane state (i.e. perform soft reset) */
/* if( boardbase < (APTR)0x40000000 ) */ /* debug only */
enc624j6l_CheckBoard( boardbase );
enc624j6l_CheckBoard( boardbase );
}
ret = i;
D(("%ld boards found\n",ret));
@@ -120,33 +119,7 @@ ASM SAVEDS LONG hw_Find_Boards( ASMR(a0) DEVBASEP ASMREG(a0) )
ASM SAVEDS LONG hw_AllocBoard( ASMR(a0) DEVBASEP ASMREG(a0),
ASMR(d0) ULONG unit ASMREG(d0) )
{
#if 0
LONG i;
struct ConfigDev *cfg = (0);
if( unit > db->db_NBoards )
return 0;
for( i=0 ; i < db->db_NBoards ; i++ )
{
cfg = FindConfigDev( cfg, ENC_MANUFACTURER, ENC_BOARD );
if( !cfg )
return 0;
if( (APTR)cfg->cd_BoardAddr == db->db_Units[unit].duh_BASE )
break;
}
if( (APTR)cfg->cd_BoardAddr != db->db_Units[unit].duh_BASE )
return 0;
if( db->db_Units[unit].duh_RefCount == 0 )
{
ObtainConfigBinding();
ReleaseConfigBinding();
}
db->db_Units[unit].duh_RefCount++;
#endif
/* is there a way to lock a ZII Board ? */
return 1;
}
@@ -154,20 +127,6 @@ ASM SAVEDS LONG hw_AllocBoard( ASMR(a0) DEVBASEP ASMREG(a0),
ASM SAVEDS LONG hw_ReleaseBoard( ASMR(a0) DEVBASEP ASMREG(a0),
ASMR(d0) ULONG unit ASMREG(d0) )
{
#if 0
if( unit > db->db_NBoards )
return 0;
for( i=0 ; i < db->db_NBoards ; i++ )
{
cfg = FindConfigDev( cfg, ENC_MANUFACTURER, ENC_BOARD );
if( !cfg )
return 0;
if( (APTR)cfg->cd_BoardAddr == db->db_Units[unit].duh_BASE )
break;
}
#endif
return 1;
}
@@ -468,143 +427,27 @@ ASM SAVEDS LONG hw_write_phy( ASMR(a0) DEVBASEP ASMREG(
return enc624j6l_WritePHY( boardbase, reg, value );
}
/*
calculate CRC32 for MAC address hashing
slow but relatively short (and can be adapted to other
polynoms easily)
*/
ASM ULONG myhw_CRC32( ASMR(a0) UBYTE *buffer ASMREG(a0),
ASMR(d0) ULONG nbytes ASMREG(d0) )
{
UWORD i,j;
ULONG t,crc = 0xffffffff;
ULONG poly = 0x04c11db7;
for( j = 0 ; j < nbytes ; j++ )
{
for( i = 0 ; i < 8 ; i++ )
{
t = crc>>31;
crc <<= 1;
if( ( t ^ ( buffer[j] >> i ) ) & 0x01 )
crc ^= poly;
}
}
return crc;
}
#if 0
ASM ULONG CMPgeMAC( ASMR(a0) UBYTE *cur ASMREG(a0),
ASMR(a1) UBYTE *cmp ASMREG(a1) )
{
USHORT i;
ULONG res = 1;
for( i = 0 ; i < 6 ; i++ )
{
if( cur[i] > cmp[i] )
break;
if( cur[i] < cmp[i] )
{
res = 0;
break;
}
}
return res;
}
#endif
ASM ULONG CMPleMAC( ASMR(a0) UBYTE *cur ASMREG(a0),
ASMR(a1) UBYTE *cmp ASMREG(a1) )
{
USHORT i;
ULONG res = 1;
for( i = 0 ; i < 6 ; i++ )
{
if( cur[i] < cmp[i] )
break;
if( cur[i] > cmp[i] )
{
res = 0;
break;
}
}
return res;
}
ASM void INCMAC( ASMR(a0) UBYTE *curmc ASMREG(a0) )
{
SHORT i;
for( i=5 ; i >= 0 ; i-- )
{
curmc[i]++;
if( curmc[i] != 0 )
{
break;
}
}
}
/* TODO: implement Multicast hashing */
ASM SAVEDS LONG hw_change_multicast( ASMR(a0) DEVBASEP ASMREG(a0),
ASMR(d0) ULONG unit ASMREG(d0),
ASMR(a1) struct List *mcastlist ASMREG(a1) )
{
APTR boardbase = db->db_Units[unit].duh_BASE;
struct HWData *hwd = &db->db_hwdat;
ULONG flags;
ULONG crc,curhash;
USHORT mc_hashes[4] = {0,0,0,0}; /* EHT1, EHT2, EHT3, EHT4 */
USHORT *hash_tab;
struct MCastEntry *mc;
UBYTE *curmc;
/* TODO: implement Multicast hashing */
APTR boardbase = db->db_Units[unit].duh_BASE;
ULONG flags;
flags = PIO_INIT_BROAD_CAST;
if( db->db_Units[0].du_Flags & DUF_PROMISC )
flags |= PIO_INIT_PROMISC;
if( hwd->multicast ) /* accept ALL multicast ? (config option) */
/* list non-empty ? (kludge right now, can be done more fine grained) */
if( mcastlist->lh_Head->ln_Succ )
flags |= PIO_INIT_MULTI_CAST;
/* list non-empty ? */
hash_tab = NULL;
if( mcastlist->lh_Head->ln_Succ )
{
/* flags |= PIO_INIT_MULTI_CAST; */ /* see above */
hash_tab = mc_hashes;
for( mc = (struct MCastEntry *)mcastlist->lh_Head;
mc->mce_Node.mln_Succ ;
mc=(struct MCastEntry*)mc->mce_Node.mln_Succ )
{
curmc = mc->mce_start;
while( CMPleMAC( curmc, mc->mce_stop ) )
{
D(("CMPleMAC %ld %02lx%02lx%02lx%02lx%02lx%02lx - %02lx%02lx%02lx%02lx%02lx%02lx\n",\
CMPleMAC( curmc, mc->mce_stop ),\
(ULONG)curmc[0],(ULONG)curmc[1],\
(ULONG)curmc[2],(ULONG)curmc[3],\
(ULONG)curmc[4],(ULONG)curmc[5],\
(ULONG)mc->mce_stop[0],(ULONG)mc->mce_stop[1],\
(ULONG)mc->mce_stop[2],(ULONG)mc->mce_stop[3],\
(ULONG)mc->mce_stop[4],(ULONG)mc->mce_stop[5] \
));
crc = myhw_CRC32( mc->mce_start, 6 );
curhash = (crc & 0x1f800000)>>23; /* 2 bit reg, 4 bit hash pos in reg */
mc_hashes[ ((curhash >> 4)&3) ] |= 1<<(curhash&0xf);
INCMAC( curmc );
}
}
}
D(("hw_change_multicast board %lx flags %lx hashtab %lx\n",(ULONG)boardbase,(ULONG)flags,(ULONG)hash_tab));
enc624j6l_bc_mc_filter(boardbase, flags, hash_tab );/* flags & (PIO_INIT_BROAD_CAST|PIO_INIT_MULTI_CAST) ); */
enc624j6l_bc_mc_filter(boardbase, flags );/* flags & (PIO_INIT_BROAD_CAST|PIO_INIT_MULTI_CAST) ); */
return 1;
}
@@ -651,7 +494,7 @@ void myhw_ControlInterrupts( DEVBASEP )
hwd->hwd_Interrupt.is_Code = (void(*)())enc624j6l_IntServer_List;
hwd->hwd_Interrupt.is_Data = &hwd->hwd_act_boards[0];
hwd->hwd_Interrupt.is_Node.ln_Type = NT_INTERRUPT;
hwd->hwd_Interrupt.is_Node.ln_Pri = 126; /* 51; */
hwd->hwd_Interrupt.is_Node.ln_Pri = 51;
hwd->hwd_Interrupt.is_Node.ln_Name = (char*)intname;
AddIntServer( HW_INTSOURCE, &hwd->hwd_Interrupt );
}
+1 -1
View File
@@ -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+1]; /* poll all active boards by ptr in interrupt, MAGIC_WORD INIT, NULL terminated, followed by SigTask,Sigbit,ExecBase */
APTR hwd_act_boards[MAX_UNITS+1+3]; /* poll all active boards by ptr in interrupt, NULL terminated, followed by SigTask,Sigbit,ExecBase */
ULONG hwd_SigMask; /* signal mask to wait for in server main instance */
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -9
View File
@@ -14,18 +14,11 @@ _LVORawIOInit equ -$1f8
_LVORawMayGetChar equ -$1fe
endc
; XDEF _KPrintF
XDEF _KPrintFa0a1
;_KPrintF:
rts
move.l 4(sp),a0
lea 8(sp),a1
; fall through
XDEF _KPrintF
;A0 = format
;A1 = arguments
_KPrintFa0a1:
_KPrintF:
; ifd DEBUG
movem.l d0-d2/a0-a3/a6,-(sp)
+12 -27
View File
@@ -41,12 +41,6 @@ static LONG server_queryext( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq );
/* this limits the number of processed read requests per run when enabled */
#define ONE_READ_REQ 2
/* heavy debug on read/write */
#define D2(x)
#define D4(x)
/* #define D2(x) D(x) */
/* #define D4(x) D(x) */
/* (avoid external link libraries) this call is not time critical */
@@ -390,15 +384,6 @@ static LONG server_changeMulticast( DEVBASEP, ULONG unit, struct IOSana2Req *ior
COPYMAC( entry->mce_start, ioreq->ios2_SrcAddr );
COPYMAC( entry->mce_stop, ioreq->ios2_SrcAddr );
D(("ADD Multicast MAC %02lx%02lx%02lx%02lx%02lx%02lx - %02lx%02lx%02lx%02lx%02lx%02lx\n",\
(ULONG)entry->mce_start[0],(ULONG)entry->mce_start[1],\
(ULONG)entry->mce_start[2],(ULONG)entry->mce_start[3],\
(ULONG)entry->mce_start[4],(ULONG)entry->mce_start[5],\
(ULONG)entry->mce_stop[0],(ULONG)entry->mce_stop[1],\
(ULONG)entry->mce_stop[2],(ULONG)entry->mce_stop[3],\
(ULONG)entry->mce_stop[4],(ULONG)entry->mce_stop[5] \
));
ADDTAIL( &db->db_svdat.sv_mclist, entry );
apply:
@@ -730,7 +715,7 @@ static LONG write_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq )
UBYTE *header_ptr;
#endif
D2(("write: type %08lx, size %ld\n",ioreq->ios2_PacketType,
D(("write: type %08lx, size %ld\n",ioreq->ios2_PacketType,
ioreq->ios2_DataLength));
frame = db->db_svdat.sv_frame;
@@ -780,13 +765,13 @@ static LONG write_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq )
if( (*dbm->dbm_CopyFromBuffer32)(copy_ptr,ioreq->ios2_Data, ioreq->ios2_DataLength) )
{
send:
D2(("+hw_send\n"));
D(("+hw_send\n"));
#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
D2(("-hw_send\n"));
D(("-hw_send\n"));
}
else
{
@@ -907,14 +892,14 @@ static void server_read_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq, U
{
frame += 14; /* skip DST,SRC,Type */
framesize -= 18; /* also remove CRC */
D4(("plain mode: frame flags %ld\n",bcflag));
D(("plain mode: frame flags %ld\n",bcflag));
}
ioreq->ios2_Req.io_Flags &= SANA2IOF_RAW; /* ignore all other flags */
ioreq->ios2_Req.io_Flags |= bcflag;
ioreq->ios2_Req.io_Error = 0;
ioreq->ios2_WireError = 0;
D4(("ReadFrm IO %lx, DBM %lx frm %lx frmsz %ld\n",(ULONG)ioreq,(ULONG)dbm,(ULONG)frame,framesize));
D(("ReadFrm IO %lx, DBM %lx frm %lx frmsz %ld\n",(ULONG)ioreq,(ULONG)dbm,(ULONG)frame,framesize));
if( dbm->dbm_PacketFilter ) /* Filter Packets ? */
{
@@ -933,7 +918,7 @@ static void server_read_frame( DEVBASEP, ULONG unit, struct IOSana2Req *ioreq, U
ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
}
}
D4(("Copied io_Error %ld\n",(LONG)ioreq->ios2_Req.io_Error));
D(("Copied io_Error %ld\n",(LONG)ioreq->ios2_Req.io_Error));
Remove( (struct Node*)ioreq );
svTermIO( db, ioreq );
@@ -961,7 +946,7 @@ static LONG server_readqueue( DEVBASEP, ULONG unit )
/* TODO: devstats */
frametype = *( (USHORT*)(frame+12) );
D4(("Have Frame size %ld type %ld\n",framesize,frametype));
D(("Have Frame size %ld type %ld\n",framesize,frametype));
ObtainSemaphore( &db->db_Units[unit].du_Sem );
@@ -979,14 +964,14 @@ orphan:
ioreq = (struct IOSana2Req *)GetHead( (struct List*)&db->db_Units[unit].du_ReadOrphans );
if( ioreq )
{
D4(("Orphaned Frame\n"));
D(("Orphaned Frame\n"));
ioreq->ios2_PacketType = frametype;
server_read_frame( db, unit, ioreq, frame, framesize );
}
else
{
D4(("No ioreq for orphaned frame\n"));
D(("No ioreq for orphaned frame\n"));
}
goto nextframe;
@@ -1020,7 +1005,7 @@ havetype:
{
db->db_Units[unit].du_DevStats.Overruns++;
type->srt_Sana2PacketTypeStats.PacketsDropped++;
D4(("No Reader for frame\n"));
D(("No Reader for frame\n"));
goto orphan; /* does it help if we give the frame to the orphan list? */
}
nextframe:
@@ -1109,9 +1094,9 @@ VOID SAVEDS ServerTask(void)
}
if( hw_recv_pending(db,i) )
{
D4(("Read on unit %ld start\n",i));
D(("Read on unit %ld start\n",i));
server_readqueue( db, i );
D4(("Read on unit %ld stop\n",i));
D(("Read on unit %ld stop\n",i));
action = 1;
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ ASMDEFS1 = -DHW_DMA_TX=1
###############################################################################
# debug = 1 will include string debugging for terminal/sushi/sashimi
# not enabled yet in SAS/C makefile
#debug = 0
debug = 0
###############################################################################
# prefix for system includes (ASM)
+2 -2
View File
@@ -9,9 +9,9 @@
#define _INC_VERSION_H
#define DEVICEVERSION 2
#define DEVICEREVISION 3
#define DEVICEREVISION 2
#define DEVICEEXTRA
/* #define DEVICEEXTRA Beta */
#define DEVICEDATE 04.04.2019
#define DEVICEDATE 10.03.2019
#endif