Browse Source

add ethernet (sana-ii) driver sources

pull/1/head
mntmn 1 year ago
parent
commit
aba0a3cca9
13 changed files with 1613 additions and 0 deletions
  1. +199
    -0
      net/Common.mk
  2. +51
    -0
      net/Makefile
  3. +5
    -0
      net/build.sh
  4. +65
    -0
      net/compiler.h
  5. +25
    -0
      net/debug.h
  6. +187
    -0
      net/debug.i
  7. +691
    -0
      net/device.c
  8. +147
    -0
      net/device.h
  9. +53
    -0
      net/deviceheader.c
  10. +76
    -0
      net/deviceinit.c
  11. +45
    -0
      net/kprintf.asm
  12. +52
    -0
      net/macros.h
  13. +17
    -0
      net/version.h

+ 199
- 0
net/Common.mk View File

@@ -0,0 +1,199 @@
###############################################################################
#
# Common.mk
#
# author: Henryk Richter <henryk.richter@gmx.net>
#
# note: when switching between different hardware targets, don`t forget
# "make clean" in between
#
# tools required:
# GNU Make, either VBCC or GCC for AmigaOS/68k, VASM
# recent sana2.h , e.g. from RoadShow SDK
#
# porting:
# you might need to adapt the paths (prefix for Compiler/Includes)
# Some installations have ADE: instead of GG: on Amigaos
# Recent work on AmigaOS cross toolchains suggest /opt/m68k-amigaos/sys-include
# instead of the traditional os-include
#
###############################################################################
# debug = 1 will include string debugging for terminal/sushi/sashimi
debug = 1
# compiler_vcc = 1 will trigger VBCC, else GCC
compiler_vcc = 1

###############################################################################
# prefix for system includes (ASM)
# native AmigaOS compilation: set PREFX=GG: or PREFX=ADE:, depending on toolchain
###############################################################################
PREFX = /home/mntmn/code/vbcc/targets/m68k-amigaos
#PREFX = gg:
SYSINC = "-I$(PREFX)/include -I$(PREFX)/include2"

###############################################################################
#
# compiler executables (choice of gcc or vbcc)
#
###############################################################################
ifeq ($(compiler_vcc),1)

# VBCC (use explicit vlink line for LINK= if complaints about R_PC happen)
CCX = vc +aos68k $(SYSINC)
LINK = vlink -bamigahunk -x -s -mrel -Cvbcc -Bstatic -nostdlib #-Rshort
#LINKEXE = vlink -bamigahunk -x -s -mrel -Cvbcc -Bstatic
LINKEXE = vc +aos68k
#LINK = $(CCX) -nostdlib
CFLAGS = -Os -+ -sc -c99 -cpu=$(CPU)
CFLAGS2 = -Os -+ -sc -c99 -cpu=$(CPU2)

else

# GCC
CCX = m68k-amigaos-gcc
LINK = $(CCX) -nostartfiles -s
LINKEXE = $(CCX) -s -noixemul
CFLAGS = -O3 -s -m$(CPU) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul
CFLAGS2 = -O3 -s -m$(CPU2) -Wall -noixemul -mregparm=4 -fomit-frame-pointer -msoft-float -noixemul

endif

VASM = vasmm68k_mot
VASMFORMAT = -m$(CPU) -Fhunk -nowarn=2064 -quiet $(SYSINC)
VASMFORMAT2 = -m$(CPU2) -Fhunk -nowarn=2064 -quiet $(SYSINC)

# unused here
#HOST = $(shell uname)

###############################################################################
#
# paths to the local includes
#
###############################################################################

IPATH =

###############################################################################
#
# compile-level feature definitions
#
###############################################################################
ifeq ($(compiler_vcc),1)
# skip quotes with VCC, the AmigaOS native version doesn't like them
#DEFINES += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#DEFINES += -DDEVICEDATE=$(DEVICEDATE)
#DEFINES += -DDEVICEEXTRA=$(DEVICEEXTRA)
DEFINES += -DDEVICENAME="$(DEVICEID)"
DEFINES += -DHAVE_VERSION_H=1
#DEFINES += -DNEWSTYLE
#ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID)

#DEFINES2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#DEFINES2 += -DDEVICEDATE=$(DEVICEDATE)
#DEFINES2 += -DDEVICEEXTRA=$(DEVICEEXTRA)
DEFINES2 += -DDEVICENAME="$(DEVICEID2)"
DEFINES2 += -DHAVE_VERSION_H=1
#DEFINES2 += -DNEWSTYLE
#ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)

else

#DEFINES += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)"
#DEFINES += -D"DEVICEDATE=$(DEVICEDATE)"
#DEFINES += -D"DEVICEEXTRA=$(DEVICEEXTRA)"
DEFINES += -D"DEVICENAME="$(DEVICEID)""
DEFINES += -DHAVE_VERSION_H=1
DEFINES += -DNEWSTYLE
#ASMDEFS += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)
#ASMDEFS += -DDEVICEDATE=$(DEVICEDATE) -DDEVICENAME=$(DEVICEID)

#DEFINES2 += -D"DEVICEVERSION=$(DEVICEVERSION)" -D"DEVICEREVISION=$(DEVICEREVISION)"
#DEFINES2 += -D"DEVICEDATE=$(DEVICEDATE)" -D"DEVICENAME="$(DEVICEID2)""
#DEFINES2 += -D"DEVICEEXTRA=$(DEVICEEXTRA)"
DEFINES2 += -D"DEVICENAME="$(DEVICEID2)""
DEFINES2 += -DHAVE_VERSION_H=1
DEFINES2 += -DNEWSTYLE
#ASMDEFS2 += -DDEVICEVERSION=$(DEVICEVERSION) -DDEVICEREVISION=$(DEVICEREVISION)

endif


###############################################################################
#
# debug
#
###############################################################################
ifeq ($(debug),1)
CFLAGS += -DDEBUG -g
CFLAGS2 += -DDEBUG -g
LINKLIBS = -L$(PREFX)/lib -ldebug -lamiga
endif

###############################################################################
#
# compiler flags and optimization levels
#
###############################################################################

CFLAGS += -I. -I$(SUBDIR)
CFLAGS2 += -I. -I$(SUBDIR)
LDFLAGS =

###############################################################################
#
# objects to build
#
###############################################################################
# ASM based alternative to deviceheader.o would be romtag.o

OBJECTS = deviceheader.o deviceinit.o device.o
OBJECTS += $(ASMOBJECTS)

# used for secondary build
OBJECTS2 = $(patsubst %.o,%.2o,$(OBJECTS))

###############################################################################
#
# rules and commands
#
###############################################################################

all: $(DEVICEID) $(DEVICEID2) $(TESTTOOL) $(TESTTOOL2)

clean:
rm -f $(OBJECTS) $(OBJECTS2)
rm -f $(DEVICEID) $(DEVICEID2) $(EXTRACLEAN)

# not for cross compile :-)
install: $(DEVICEID) $(DEVICEID2)
copy $(DEVICEID) $(DEVICEID2) DEVS:


#sdnet: $(DEVICEID)
#expnet: $(DEVICEID2)

$(DEVICEID) : $(OBJECTS)
$(LINK) $(LDFLAGS) -o $@ $(OBJECTS) $(LINKLIBS) $(LINKOPTS)


# separate ruleset for each subdirectory, ./src overrides all other paths for priority
# of platform-optimized routines
%.o : %.c
$(CCX) -c $(CFLAGS) $(DEFINES) $(IPATH) $< -o $@

%.o : %.asm
${VASM} $(VASMFORMAT) $(ASMDEFS) -o $@ $<


# secondary ruleset (used for expnet, will be ignored if DEVICEID2 is empty)
$(DEVICEID2) : $(OBJECTS2)
$(LINK) $(LDFLAGS) -o $@ $(OBJECTS2) $(LINKLIBS)

%.2o : %.c
$(CCX) -c $(CFLAGS2) $(DEFINES2) $(IPATH) $< -o $@

%.2o : %.asm
${VASM} $(VASMFORMAT2) $(ASMDEFS2) -o $@ $<



+ 51
- 0
net/Makefile View File

@@ -0,0 +1,51 @@
###############################################################################
#
# makefile for vbcc or gcc
#
# author: Henryk Richter <henryk.richter@gmx.net>
#
# concept:
#
# tools required:
# - vbcc, defaulting to m68k-amigaos
# - vlink
# (- vasm)
#
# porting:
#
# see Common.mk
#
###############################################################################

###############################################################################
# Date, version, extra objects to build
#
###############################################################################
DEVICEVERSION=1
DEVICEREVISION=0
DEVICEDATE=31.07.2019
#ASMOBJECTS = $(SUBDIR)/enc624j6l.o $(SUBDIR)/intervaltimer.o kprintf.o

###############################################################################
# Devices to build (1 or 2, keep DEVICEID2 empty if only one build is desired)
#
###############################################################################

DEVICEID=ZZ9000Net.device
DEFINES = #
ASMDEFS = #
CPU = 68020

DEVICEID2= #test.device_68000
DEFINES2 = # -DPROTO_V2EXPNET
ASMDEFS2 = # -DPROTO_V2EXPNET
CPU2 = #68000

###############################################################################
# import generic ruleset
#
###############################################################################
include Common.mk




+ 5
- 0
net/build.sh View File

@@ -0,0 +1,5 @@
export VBCC=../../vbcc
export PATH=$PATH:$VBCC/bin
export SDK="-I$VBCC/targets/m68k-amigaos/include -I$VBCC/targets/m68k-amigaos/include2"

make

+ 65
- 0
net/compiler.h View File

@@ -0,0 +1,65 @@
/*
compiler.h

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

Interface macros for ASM subroutines for VBCC, GCC and SAS/C

syntax:
ASM SAVEDS int some_asm_subroutine(
ASMR(d3) unsigned int some_data ASMREG(d3),
ASMR(a0) unsigned char *some_address ASMREG(a0)
);

Reason for the double spec of An/Dn: some compilers (SAS) require the register
on the left hand side, gcc on the right hand side. I wanted to avoid a big macro
for the whole argument and moved the stuff into two macros per argument.

*/
#ifndef _INC_ASMINTERFACE_H
#define _INC_ASMINTERFACE_H

#ifdef __SASC

#define ASM __asm
#define ASMR(x) register __ ## x
#define ASMREG(x)
#define SAVEDS __saveds
#define STRUCTOFFSET OFFSET /* exec/initializers.h */
#define INLINE __inline static

#else /* __SASC */

#ifdef __GNUC__

#define ASM
#define ASMR(x) register
#define ASMREG(x) __asm("" #x "")
//#define SAVEDS __saveds
#define SAVEDS
#define STRUCTOFFSET OFFSET /* exec/initializers.h */
#define INLINE static inline

#else /* __GNUC__ */

#ifdef __VBCC__

#define ASM
#define ASMR(x) __reg("" #x "")
#define ASMREG(x)
#define SAVEDS __saveds
#define STRUCTOFFSET(_a_,_b_) offsetof(struct _a_, _b_) /* stddef.h */
#include <stddef.h>
/* sorry, I ran into some issues inlining stuff with VBCC, disabling it */
#define INLINE

#else /* __VBCC__ */

#error "Compiler not supported yet in compiler.h"

#endif /* __VBCC__ */
#endif /* __GNUC__ */
#endif /* __SASC */


#endif /* _INC_ASMINTERFACE_H */

+ 25
- 0
net/debug.h View File

@@ -0,0 +1,25 @@
/*
debug.h

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

Debugging Macros


*/
#ifndef _INC_DEBUG_H
#define _INC_DEBUG_H

#ifdef DEBUG
extern void KPrintF(char *, ...), KGetChar(void);

#define D(_x_) do { KPrintF("%s:%ld:",__FILE__,__LINE__); KPrintF _x_; } while(0)

#else /* DEBUG */

#define D(x)

#endif /* DEBUG */


#endif /* _INC_DEBUG_H */

+ 187
- 0
net/debug.i View File

@@ -0,0 +1,187 @@
; 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

;
;
;
ifne 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
;
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



+ 691
- 0
net/device.c View File

@@ -0,0 +1,691 @@
/*
* MNT ZZ9000 Network Driver (ZZ9000Net.device)
* Copyright (C) 2016-2019, Lukas F. Hartmann <lukas@mntre.com>
* MNT Research GmbH, Berlin
* https://mntre.com
*
* Based on code copyright (C) 2018 Henryk Richter <henryk.richter@gmx.net>
* Released under GPLv3+ with permission.
*
* More Info: https://mntre.com/zz9000
*
* SPDX-License-Identifier: GPL-3.0-or-later
* GNU General Public License v3.0 or later
*
* https://spdx.org/licenses/GPL-3.0-or-later.html
*/

#define DEVICE_MAIN

#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/dos.h>
#include <proto/expansion.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <exec/lists.h>
#include <exec/errors.h>
#include <exec/interrupts.h>
#include <exec/tasks.h>
#include <string.h>

#ifdef HAVE_VERSION_H
#include "version.h"
#endif
/* NSD support is optional */
#ifdef NEWSTYLE
#include <devices/newstyle.h>
#endif /* NEWSTYLE */
#ifdef DEVICES_NEWSTYLE_H

const UWORD dev_supportedcmds[] = {
NSCMD_DEVICEQUERY,
CMD_READ,
CMD_WRITE,
/* ... add all cmds here that are supported by BeginIO */
0
};

const struct NSDeviceQueryResult NSDQueryAnswer = {
0,
16, /* up to SupportedCommands (inclusive) TODO: correct number */
NSDEVTYPE_SANA2, /* TODO: proper device type */
0, /* subtype */
(UWORD*)dev_supportedcmds
};
#endif /* DEVICES_NEWSTYLE_H */

#include "device.h"
#include "macros.h"

static ULONG ZZ9K_REGS = 0;
#define ZZ9K_RX 0x2000
#define ZZ9K_TX 0x8000

__saveds void frame_proc();
char *frame_proc_name = "ZZ9000NetFramer";

// ZZ9000 Interrupt Handler (INT6)
__saveds void dev_isr(__reg("a1") struct devbase* db) {
// signal main process that a packet is available
if (db->db_Proc) {
Signal((struct Task*)db->db_Proc, SIGBREAKF_CTRL_F);
}
}

static UBYTE HW_MAC[] = {0x00,0x00,0x00,0x00,0x00,0x00};

void set_mac_from_string(UBYTE* buf) {
int k=0;
for (int i=0; i<6; i++) {
int c = buf[k];
int v = 0;
if (c>='0' && c<='9') c-='0';
else if (c>='a' && c<='f') c=c+10-'a';
else if (c>='A' && c<='F') c=c+10-'A';

v = c<<4;
c = buf[k+1];
if (c>='0' && c<='9') c-='0';
else if (c>='a' && c<='f') c=c+10-'a';
else if (c>='A' && c<='F') c=c+10-'A';

HW_MAC[i] = v+c;
k+=3;
}
}

struct ProcInit
{
struct Message msg;
struct devbase *db;
BOOL error;
UBYTE pad[2];
};

__saveds struct Device *DevInit( ASMR(d0) DEVBASEP ASMREG(d0),
ASMR(a0) BPTR seglist ASMREG(a0),
ASMR(a6) struct Library *_SysBase ASMREG(a6) )
{
UBYTE*p;
ULONG i;
LONG ok;

p = ((UBYTE*)db) + sizeof(struct Library);
i = sizeof(DEVBASETYPE)-sizeof(struct Library);
while( i-- )
*p++ = 0;

db->db_SysBase = _SysBase;
db->db_SegList = seglist;
db->db_Flags = 0;

ok = 0;
if( (DOSBase = OpenLibrary("dos.library", 36)) ) {
if( (UtilityBase = OpenLibrary("utility.library", 37)) ) {
ok = 0;

struct ConfigDev* cd = NULL;
USHORT fwrev = 0;

if ((ExpansionBase = OpenLibrary("expansion.library", 0)) ) {
// Find Z2 or Z3 model of MNT ZZ9000
if ((cd = (struct ConfigDev*)FindConfigDev(cd,0x6d6e,0x4)) || (cd = (struct ConfigDev*)FindConfigDev(cd,0x6d6e,0x3))) {
BPTR fh;
D(("ZZ9000Net: MNT ZZ9000 found.\n"));
ZZ9K_REGS = (ULONG)cd->cd_BoardAddr;

// Thanks to https://grandcentrix.team
HW_MAC[0]=0x68;
HW_MAC[1]=0x82;
HW_MAC[2]=0xF2;
HW_MAC[3]=0x00;
HW_MAC[4]=0x01;
HW_MAC[5]=0x00;
if ((fh=Open("ENV:ZZ9K_MAC",MODE_OLDFILE))) {
UBYTE char_buf[32];
char* res = FGets(fh,char_buf,18);
if (!res || strlen(char_buf)<17) {
D(("ZZ9000Net: MAC address in ENV:ZZ9K_MAC has invalid syntax.\n"));
} else {
D(("ZZ9000Net: Setting MAC address from ENV:ZZ9K_MAC.\n"));
set_mac_from_string(char_buf);
}
Close(fh);
}

// FIXME
*(USHORT*)(ZZ9K_REGS+0x84) = (HW_MAC[0]<<8)|HW_MAC[1];
*(USHORT*)(ZZ9K_REGS+0x84) = (HW_MAC[0]<<8)|HW_MAC[1];
*(USHORT*)(ZZ9K_REGS+0x86) = (HW_MAC[2]<<8)|HW_MAC[3];
*(USHORT*)(ZZ9K_REGS+0x86) = (HW_MAC[2]<<8)|HW_MAC[3];
*(USHORT*)(ZZ9K_REGS+0x88) = (HW_MAC[4]<<8)|HW_MAC[5];

ok = 1;

} else {
D(("ZZ9000Net: MNT ZZ9000 not found!\n"));
}
CloseLibrary(ExpansionBase);
} else {
D(("ZZ9000Net: failed to open expansion.library!\n"));
}
if (!ok) {
CloseLibrary(DOSBase);
CloseLibrary(UtilityBase);
}
}
else {
D(("ZZ9000Net: Could not open utility.library.\n"));
CloseLibrary(DOSBase);
}
}
else {
D(("ZZ9000Net: Could not open dos.library.\n"));
}

/* no hardware found, reject init */
return (ok > 0) ? (struct Device*)db : (0);
}

__saveds LONG DevOpen( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
ASMR(d0) ULONG unit ASMREG(d0),
ASMR(d1) ULONG flags ASMREG(d1),
ASMR(a6) DEVBASEP ASMREG(a6) )
{
LONG ok = 0,ret = IOERR_OPENFAIL;
struct BufferManagement *bm;

D(("ZZ9000Net: DevOpen for %ld\n",unit));

db->db_Lib.lib_OpenCnt++; /* avoid Expunge, see below for separate "unit" open count */
if (unit==0 && db->db_Lib.lib_OpenCnt==1) {
if ((bm = (struct BufferManagement*)AllocVec(sizeof(struct BufferManagement), MEMF_CLEAR|MEMF_PUBLIC))) {
bm->bm_CopyToBuffer = (BMFunc)GetTagData(S2_CopyToBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
bm->bm_CopyFromBuffer = (BMFunc)GetTagData(S2_CopyFromBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);

ioreq->ios2_BufferManagement = (VOID *)bm;
ioreq->ios2_Req.io_Error = 0;
ioreq->ios2_Req.io_Unit = (struct Unit *)unit; // not a real pointer, but id integer
ioreq->ios2_Req.io_Device = (struct Device *)db;

NewList(&db->db_ReadList);
InitSemaphore(&db->db_ReadListSem);

struct ProcInit init;
struct MsgPort *port;

if (port = CreateMsgPort()) {
D(("ZZ9000Net: Starting Process\n"));
if (db->db_Proc = CreateNewProcTags(NP_Entry, frame_proc, NP_Name,
frame_proc_name, TAG_DONE)) {
init.error = 1;
init.db = db;
init.msg.mn_Length = sizeof(init);
init.msg.mn_ReplyPort = port;

Delay(50);
D(("ZZ9000Net: handover db: %lx\n",init.db));
PutMsg(&db->db_Proc->pr_MsgPort, (struct Message*)&init);
WaitPort(port);

if (!init.error) {
ok = 1;
// Register Interrupt (INT6) server
if (db->db_int6 = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR)) {
db->db_int6->is_Node.ln_Type = NT_INTERRUPT;
db->db_int6->is_Node.ln_Pri = -60;
db->db_int6->is_Node.ln_Name = "ZZ9000Net";
db->db_int6->is_Data = (APTR)db;
db->db_int6->is_Code = dev_isr;

// 13 = INTB_EXTER
Disable();
AddIntServer(13, db->db_int6);
Enable();
D(("ZZ9000Net: INT6 server registered\n"));
ret = 0;
ok = 1;
} else {
D(("ZZ9000Net: failed to alloc INT6 struct\n"));
ret = IOERR_OPENFAIL;
ok = 0;
// FIXME end process
}
} else {
D(("ZZ9000Net:process startup error\n"));
ret = IOERR_OPENFAIL;
ok = 0;
}
} else {
D(("ZZ9000Net:couldn't create process\n"));
ret = IOERR_OPENFAIL;
ok = 0;
}
DeleteMsgPort(port);
}
}
} else {
ret = IOERR_OPENFAIL;
ok = 0;
}

if (ok) {
ret = 0;
db->db_Lib.lib_Flags &= ~LIBF_DELEXP;
}

if (ret == IOERR_OPENFAIL) {
ioreq->ios2_Req.io_Unit = (0);
ioreq->ios2_Req.io_Device = (0);
ioreq->ios2_Req.io_Error = ret;
db->db_Lib.lib_OpenCnt--;
}
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;

D(("ZZ9000Net: DevOpen return code %ld\n",ret));

return ret;
}

__saveds BPTR DevClose( ASMR(a1) struct IORequest *ioreq ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) )
{
/* ULONG unit; */
BPTR ret = (0);

D(("ZZ9000Net: DevClose open count %ld\n",db->db_Lib.lib_OpenCnt));

if( !ioreq )
return ret;

db->db_Lib.lib_OpenCnt--;

if (db->db_Lib.lib_OpenCnt == 0) {
Forbid();
if (db->db_int6) {
D(("ZZ9000Net: Remove IntServer...\n"));
RemIntServer(13, db->db_int6);
db->db_int6 = 0;
}
if (db->db_Proc) {
D(("ZZ9000Net: End Proc...\n"));
Signal((struct Task*)db->db_Proc, SIGBREAKF_CTRL_C);
db->db_Proc = 0;
}
Permit();
}

ioreq->io_Device = (0);
ioreq->io_Unit = (struct Unit *)(-1);

if (db->db_Lib.lib_Flags & LIBF_DELEXP)
ret = DevExpunge(db);

return ret;
}

__saveds BPTR DevExpunge( ASMR(a6) DEVBASEP ASMREG(a6) )
{
BPTR seglist = db->db_SegList;

if( db->db_Lib.lib_OpenCnt )
{
db->db_Lib.lib_Flags |= LIBF_DELEXP;
return (0);
}
D(("ZZ9000Net: Remove Device Node...\n"));
Remove((struct Node*)db);

CloseLibrary(DOSBase);
CloseLibrary(UtilityBase);
FreeMem( ((BYTE*)db)-db->db_Lib.lib_NegSize,(ULONG)(db->db_Lib.lib_PosSize + db->db_Lib.lib_NegSize));

return seglist;
}

ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame);
ULONG write_frame(struct IOSana2Req *req, UBYTE *frame);

__saveds VOID DevBeginIO( ASMR(a1) struct IOSana2Req *ioreq ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) )
{
ULONG unit = (ULONG)ioreq->ios2_Req.io_Unit;
int mtu;
ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;

//D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));

switch( ioreq->ios2_Req.io_Command ) {
case CMD_READ:
if (ioreq->ios2_BufferManagement == NULL) {
ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
}
else {
// not quick, add request to reader list
// will be handled on interrupts by frame_proc
ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
ObtainSemaphore(&db->db_ReadListSem);
AddHead((struct List*)&db->db_ReadList, (struct Node*)ioreq);
ReleaseSemaphore(&db->db_ReadListSem);
ioreq = NULL;
}
break;
case S2_BROADCAST:
/* set broadcast addr: ff:ff:ff:ff:ff:ff */
if (ioreq->ios2_DstAddr) {
memset(ioreq->ios2_DstAddr, 0xff, HW_ADDRFIELDSIZE);
} else {
D(("bcast: invalid dst addr\n"));
}
/* fall through */
case CMD_WRITE: {
ULONG res = write_frame(ioreq, (UBYTE*)(ZZ9K_REGS+ZZ9K_TX));
if (res!=0) {
ioreq->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
} else {
ioreq->ios2_Req.io_Error = 0;
}
break;
}
case S2_READORPHAN:
if( !ioreq->ios2_BufferManagement )
{
ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
}
else
{
ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
// FIXME do we need this list?
//ObtainSemaphore(&db->db_Units[unit].du_Sem);
//AddHead((struct List*)&db->db_ReadOrphans,(struct Node*)ioreq);
//ReleaseSemaphore(&db->db_Units[unit].du_Sem);
ioreq = NULL;
}
break;
case S2_ONLINE:
case S2_OFFLINE:
case S2_CONFIGINTERFACE: /* forward request */
break;

case S2_GETSTATIONADDRESS:
memcpy(ioreq->ios2_SrcAddr, HW_MAC, HW_ADDRFIELDSIZE); /* current */
memcpy(ioreq->ios2_DstAddr, HW_MAC, HW_ADDRFIELDSIZE); /* default */
break;
case S2_DEVICEQUERY:
{
struct Sana2DeviceQuery *devquery;

devquery = ioreq->ios2_StatData;
devquery->DevQueryFormat = 0; /* "this is format 0" */
devquery->DeviceLevel = 0; /* "this spec defines level 0" */
if (devquery->SizeAvailable >= 18) devquery->AddrFieldSize = HW_ADDRFIELDSIZE * 8; /* Bits! */
if (devquery->SizeAvailable >= 22) devquery->MTU = 1500;
if (devquery->SizeAvailable >= 26) devquery->BPS = 1000*1000*100;
if (devquery->SizeAvailable >= 30) devquery->HardwareType = S2WireType_Ethernet;

devquery->SizeSupplied = (devquery->SizeAvailable<30?devquery->SizeAvailable:30);
}
break;
case S2_GETSPECIALSTATS:
{
struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
s2ssh->RecordCountSupplied = 0;
}
break;
default:
{
ioreq->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
break;
}
}

if (ioreq) {
DevTermIO(db, (struct IORequest*)ioreq);
}
}

__saveds LONG DevAbortIO( ASMR(a1) struct IORequest *ioreq ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) )
{
LONG ret = 0;
struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;

D(("ZZ9000Net: AbortIO on %lx\n",(ULONG)ioreq));
Remove((struct Node*)ioreq);
ioreq->io_Error = IOERR_ABORTED;
ios2->ios2_WireError = 0;

ReplyMsg((struct Message*)ioreq);
return ret;
}

void DevTermIO( DEVBASEP, struct IORequest *ioreq )
{
struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
if (!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
ReplyMsg((struct Message *)ioreq);
} else {
ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
}
}

ULONG get_frame_serial(UBYTE* frame) {
UBYTE* frm = (UBYTE*)frame;
ULONG ser = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
return ser;
}

ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame)
{
ULONG datasize;
BYTE *frame_ptr;
BOOL broadcast;
ULONG err = 0;
struct BufferManagement *bm;

UBYTE* frm = (UBYTE*)frame;
ULONG sz = ((ULONG)frm[0]<<8)|((ULONG)frm[1]);
ULONG ser = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
USHORT tp = ((USHORT)frm[16]<<8)|((USHORT)frm[17]);
if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
frame_ptr = frm+4;
datasize = sz;
req->ios2_Req.io_Flags = SANA2IOF_RAW;
}
else {
frame_ptr = frm+4+HW_ETH_HDR_SIZE;
datasize = sz-HW_ETH_HDR_SIZE;
req->ios2_Req.io_Flags = 0;
}

req->ios2_DataLength = datasize;

//D(("datasize: %lx\n",datasize));
//D(("frame_ptr: %lx\n",frame_ptr));
//D(("ios2_Data: %lx\n",req->ios2_Data));
//D(("bufmgmt: %lx\n",req->ios2_BufferManagement));

// copy frame to device user (probably tcp/ip system)
bm = (struct BufferManagement *)req->ios2_BufferManagement;
if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
//D(("rx copybuf error\n"));
req->ios2_Req.io_Error = S2ERR_SOFTWARE;
req->ios2_WireError = S2WERR_BUFF_ERROR;
err = 1;
}
else {
req->ios2_Req.io_Error = req->ios2_WireError = 0;
err = 0;
}
memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
//D(("RXSZ %ld\n",(LONG)sz));
//D(("RXPT %ld\n",(LONG)tp));

//D(("RXSER %ld\n",(LONG)ser));
//D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
//D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));

broadcast = TRUE;
for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
if (frame[i+4] != 0xff) {
broadcast = FALSE;
break;
}
}
if (broadcast) {
req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
}
req->ios2_PacketType = tp;

return err;
}

ULONG write_frame(struct IOSana2Req *req, UBYTE *frame)
{
ULONG rc=0;
struct BufferManagement *bm;
USHORT sz=0;
if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
sz = req->ios2_DataLength;
} else {
sz = req->ios2_DataLength + HW_ETH_HDR_SIZE;
*((USHORT*)(frame+6+6)) = (USHORT)req->ios2_PacketType;
memcpy(frame, req->ios2_DstAddr, HW_ADDRFIELDSIZE);
memcpy(frame+6, HW_MAC, HW_ADDRFIELDSIZE);
frame+=HW_ETH_HDR_SIZE;
}

if (sz>0) {
bm = (struct BufferManagement *)req->ios2_BufferManagement;

if (!(*bm->bm_CopyFromBuffer)(frame, req->ios2_Data, req->ios2_DataLength)) {
rc = 1; // FIXME error code
//D(("tx copybuf err\n"));
}
else {
// buffer was copied to zz9000, send it
volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x80); // FIXME send_frame reg
*reg = sz;

// get feedback
rc = *reg;
if (rc!=0) {
D(("tx err: %d\n",rc));
}
}
}

return rc;
}

__saveds void frame_proc() {
ULONG wmask;
D(("ZZ9000Net: frame_proc()\n"));
struct Process* proc;
struct ProcInit* init;

{
struct { void *db_SysBase; } *db = (void*)0x4;

proc = (struct Process*)FindTask(NULL);
WaitPort(&proc->pr_MsgPort);
init = (struct ProcInit*)GetMsg(&proc->pr_MsgPort);
init->error = 0;
ReplyMsg((struct Message*)init);
}
struct devbase* db = init->db;
wmask = SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_C;

ULONG old_serial = 0;
while (1) {
struct IOSana2Req *ior;
BOOL receiver_found = 0;
// wait for signal from our interrupt handler
// remove this to use polled-IO
ULONG recv = Wait(wmask);

if (recv & SIGBREAKF_CTRL_C) {
D(("ZZ9000Net: process end\n"));
break;
}

volatile UBYTE* frm = (volatile UBYTE*)(ZZ9K_REGS+ZZ9K_RX);
ULONG serial = get_frame_serial(frm);

//D(("FTI %ld\n", serial));
if (serial != old_serial) {
int processed = 0;
USHORT packet_type = ((USHORT)frm[16]<<8)|((USHORT)frm[17]);
old_serial = serial;

ObtainSemaphore(&db->db_ReadListSem);
for (ior = (struct IOSana2Req *)db->db_ReadList.lh_Head;
ior->ios2_Req.io_Message.mn_Node.ln_Succ;
ior = (struct IOSana2Req *)ior->ios2_Req.io_Message.mn_Node.ln_Succ) {
if (ior->ios2_PacketType == packet_type) {
ULONG res = read_frame(ior, frm);
if (res==0) {
Remove((struct Node*)ior);
ReplyMsg((struct Message *)ior);
processed = 1;
} else {
D(("RERR %ld\n",res));
}
break;
}
}
ReleaseSemaphore(&db->db_ReadListSem);

if (!processed) {
D(("UNPR %ld\n",(LONG)packet_type));
}
// mark this frame as accepted
volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x82); // FIXME receive_frame reg
*reg = 1;
}
}
}


+ 147
- 0
net/device.h View File

@@ -0,0 +1,147 @@
/*
* MNT ZZ9000 Network Driver (ZZ9000Net.device)
* Copyright (C) 2016-2019, Lukas F. Hartmann <lukas@mntre.com>
* MNT Research GmbH, Berlin
* https://mntre.com
* Copyright (C) 2018 Henryk Richter <henryk.richter@gmx.net>
*
* More Info: https://mntre.com/zz9000
*
* SPDX-License-Identifier: GPL-3.0-or-later
* GNU General Public License v3.0 or later
*
* https://spdx.org/licenses/GPL-3.0-or-later.html
*/

/*
device.h

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

Device Functions and Definitions


*/
#ifndef _INC_DEVICE_H
#define _INC_DEVICE_H

/* defaults */
#define MAX_UNITS 4

/* includes */
#include "compiler.h"
#include <dos/dos.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/semaphores.h>
#include "debug.h"
#include "sana2.h"

/* reassign Library bases from global definitions to own struct */
#define SysBase db->db_SysBase
#define DOSBase db->db_DOSBase
#define UtilityBase db->db_UtilityBase
#define ExpansionBase db->db_ExpansionBase

struct DevUnit {
/* HW Data (generic for now) (example only, unused in construct)*/
ULONG du_hwl0;
ULONG du_hwl1;
ULONG du_hwl2;
APTR du_hwp0;
APTR du_hwp1;
APTR du_hwp2;
};


struct devbase {
struct Library db_Lib;
BPTR db_SegList; /* from Device Init */

ULONG db_Flags; /* misc */
struct Library *db_SysBase; /* Exec Base */
struct Library *db_DOSBase;
struct Library *db_UtilityBase;
struct Library *db_ExpansionBase;
struct Interrupt *db_int6;

struct List db_ReadList;
struct SignalSemaphore db_ReadListSem;
struct Process* db_Proc;

struct DevUnit db_Units[MAX_UNITS]; /* unused in construct */
};

#ifndef DEVBASETYPE
#define DEVBASETYPE struct devbase
#endif
#ifndef DEVBASEP
#define DEVBASEP DEVBASETYPE *db
#endif

/* PROTOS */

ASM LONG LibNull( void );

ASM SAVEDS struct Device *DevInit(ASMR(d0) DEVBASEP ASMREG(d0),
ASMR(a0) BPTR seglist ASMREG(a0),
ASMR(a6) struct Library *_SysBase ASMREG(a6) );

ASM SAVEDS LONG DevOpen( ASMR(a1) struct IOSana2Req *ios2 ASMREG(a1),
ASMR(d0) ULONG unit ASMREG(d0),
ASMR(d1) ULONG flags ASMREG(d1),
ASMR(a6) DEVBASEP ASMREG(a6) );

ASM SAVEDS BPTR DevClose( ASMR(a1) struct IORequest *ios2 ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) );

ASM SAVEDS BPTR DevExpunge( ASMR(a6) DEVBASEP ASMREG(a6) );

ASM SAVEDS VOID DevBeginIO( ASMR(a1) struct IOSana2Req *ios2 ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) );

ASM SAVEDS LONG DevAbortIO( ASMR(a1) struct IORequest *ios2 ASMREG(a1),
ASMR(a6) DEVBASEP ASMREG(a6) );

void DevTermIO( DEVBASETYPE*, struct IORequest * );

/* private functions */
#ifdef DEVICE_MAIN

//static void dbNewList( struct List * );
//static LONG dbIsInList( struct List *, struct Node * );

#endif /* DEVICE_MAIN */

#define HW_ADDRFIELDSIZE 6
#define HW_ETH_HDR_SIZE 14 /* ethernet header: dst, src, type */
#define HW_ETH_MTU 1500

typedef BOOL (*BMFunc)(__reg("a0") void* a, __reg("a1") void* b, __reg("d0") long c);

typedef struct BufferManagement
{
struct MinNode bm_Node;
BMFunc bm_CopyFromBuffer;
BMFunc bm_CopyToBuffer;
} BufferManagement;

struct HWFrame {
USHORT hwf_Size;
/* use layout of ethernet header here */
UBYTE hwf_DstAddr[HW_ADDRFIELDSIZE];
UBYTE hwf_SrcAddr[HW_ADDRFIELDSIZE];
USHORT hwf_Type;
/*UBYTE hwf_Data[MTU];*/
};

const struct InitTable
{
ULONG LibBaseSize;
APTR FunctionTable;
APTR DataTable;
APTR InitLibTable;
};

#endif /* _INC_DEVICE_H */

+ 53
- 0
net/deviceheader.c View File

@@ -0,0 +1,53 @@
/*
Device Header - ROMTAG

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

taken from commandline (compiler options)
-DDEVICENAME=blah.device
-DDEVICEVERSION=45
-DDEVICEREVISION=36
-DDEVICEDATE=2.12.2012

*/

#include <exec/resident.h>
#include <exec/nodes.h>
#include <exec/initializers.h>
#include <exec/libraries.h>
#ifdef HAVE_VERSION_H
#include "version.h"
#endif
#include "compiler.h"
#include "device.h"

/* Enable this if you want pure C for the device. (disable compilation of romtag.asm in that case)
I personally prefer the small ASM blob to steer away from linking challenges.
*/
#if 1

ASM LONG LibNull( void )
{
return 0;
}

extern const char DeviceName[];
extern const char DeviceVersionString[];
extern const APTR DeviceInitTab[];

static const struct Resident _00RomTag = {
RTC_MATCHWORD,
( struct Resident* ) &_00RomTag,
( struct Resident* ) &_00RomTag + 1,
RTF_AUTOINIT,
DEVICEVERSION,
NT_DEVICE,
0,
(char*)DeviceName,
(char*)DeviceVersionString+6,
(APTR)DeviceInitTab
};
#endif




+ 76
- 0
net/deviceinit.c View File

@@ -0,0 +1,76 @@
/*
devinit.c

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

initialization structures and data

*/
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/dos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <exec/lists.h>

#ifdef HAVE_VERSION_H
#include "version.h"
#endif
#include "device.h"
#include "macros.h"
#include <exec/initializers.h>

#define xstr(a) str(a)
#define str(a) #a

#ifndef DEVICEEXTRA
#define DEVICEEXTRA
#endif

static const char _DeviceVersionString[] = "$VER: " xstr(DEVICENAME) " " xstr(DEVICEVERSION) "." xstr(DEVICEREVISION) xstr(DEVICEEXTRA) " (" xstr(DEVICEDATE) ")";
const char *DeviceVersionString = (const char *)_DeviceVersionString;
const char DeviceName[] = xstr(DEVICENAME);


const APTR DeviceFunctions[] = {
(APTR) DevOpen,
(APTR) DevClose,
(APTR) DevExpunge,
(APTR) LibNull,
(APTR) DevBeginIO,
(APTR) DevAbortIO,
(APTR) -1
};


#define WORDINIT(_a_) UWORD _a_ ##W1; UWORD _a_ ##W2; UWORD _a_ ##ARG;
#define LONGINIT(_a_) UBYTE _a_ ##A1; UBYTE _a_ ##A2; ULONG _a_ ##ARG;
struct DeviceInitData
{
WORDINIT(w1)
LONGINIT(l1)
WORDINIT(w2)
WORDINIT(w3)
WORDINIT(w4)
LONGINIT(l2)
ULONG end_initlist;
} DeviceInitializers =
{
INITBYTE( STRUCTOFFSET( Node, ln_Type), NT_DEVICE),
0x80, (UBYTE) ((LONG)STRUCTOFFSET( Node, ln_Name)), (ULONG) &DeviceName[0],
INITBYTE( STRUCTOFFSET(Library,lib_Flags), LIBF_SUMUSED|LIBF_CHANGED ),
INITWORD( STRUCTOFFSET(Library,lib_Version), DEVICEVERSION ),
INITWORD( STRUCTOFFSET(Library,lib_Revision), DEVICEREVISION ),
0x80, (UBYTE) ((LONG)STRUCTOFFSET(Library,lib_IdString)), (ULONG) &_DeviceVersionString[6],
(ULONG) 0
};


const APTR DeviceInitTab[] = {
(APTR) sizeof( DEVBASETYPE ),
(APTR) &DeviceFunctions,
(APTR) &DeviceInitializers,
(APTR) DevInit
};



+ 45
- 0
net/kprintf.asm View File

@@ -0,0 +1,45 @@
incdir include:
ifnd _LVOSupervisor
include lvo/exec_lib.i
;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



+ 52
- 0
net/macros.h View File

@@ -0,0 +1,52 @@
/*
macros.h

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

useful macros

*/
#ifndef _INC_MACROS_H
#define _INC_MACROS_H

#define GetHead(l) (void *)(((struct List *)l)->lh_Head->ln_Succ \
? ((struct List *)l)->lh_Head \
: (struct Node *)0)
#define GetTail(l) (void *)(((struct List *)l)->lh_TailPred->ln_Pred \
? ((struct List *)l)->lh_TailPred \
: (struct Node *)0)
#define GetSucc(n) (void *)(((struct Node *)n)->ln_Succ->ln_Succ \
? ((struct Node *)n)->ln_Succ \
: (struct Node *)0)
#define GetPred(n) (void *)(((struct Node *)n)->ln_Pred->ln_Pred \
? ((struct Node *)n)->ln_Pred \
: (struct Node *)0)

#define REMOVE(n) ((void)(\
((struct Node *)n)->ln_Pred->ln_Succ = ((struct Node *)n)->ln_Succ,\
((struct Node *)n)->ln_Succ->ln_Pred = ((struct Node *)n)->ln_Pred ))

#define ADDHEAD(l,n) ((void)(\
((struct Node *)n)->ln_Succ = ((struct List *)l)->lh_Head, \
((struct Node *)n)->ln_Pred = (struct Node *)&((struct List *)l)->lh_Head, \
((struct List *)l)->lh_Head->ln_Pred = ((struct Node *)n), \
((struct List *)l)->lh_Head = ((struct Node *)n)))

#define ADDTAIL(l,n) ((void)(\
((struct Node *)n)->ln_Succ = (struct Node *)&((struct List *)l)->lh_Tail, \
((struct Node *)n)->ln_Pred = ((struct List *)l)->lh_TailPred, \
((struct List *)l)->lh_TailPred->ln_Succ = ((struct Node *)n), \
((struct List *)l)->lh_TailPred = ((struct Node *)n) ))

#define NEWLIST(l) (((struct List *)l)->lh_TailPred = (struct Node *)(l), \
((struct List *)l)->lh_Tail = 0, \
((struct List *)l)->lh_Head = (struct Node *)&(((struct List *)l)->lh_Tail))


#define min(_a_,_b_) ( (_a_) > (_b_) ) ? _b_ : _a_
#define max(_a_,_b_) ( (_a_) < (_b_) ) ? _b_ : _a_
#define BOUNDS(_val_,_min_,_max_) ( (_val_) < (_min_) ) ? _min_ : ( (_val_) > (_max_) ) ? _max_ : _val_


#endif /* _INC_MACROS_H */


+ 17
- 0
net/version.h View File

@@ -0,0 +1,17 @@
/*
version.h

(C) 2018 Henryk Richter <henryk.richter@gmx.net>

version and date handling
*/
#ifndef _INC_VERSION_H
#define _INC_VERSION_H

#define DEVICEVERSION 1
#define DEVICEREVISION 1
#define DEVICEEXTRA
/* #define DEVICEEXTRA Beta */
#define DEVICEDATE 19.08.2019

#endif

Loading…
Cancel
Save