include "i:fs.inc"
include "i:util.inc"
begin ; !Ethernet monitor station (Aug 83)
bytespec (16_7fffc)status
bytespec (16_7fffd)data
bytespec (16_7ffff)control
constinteger tbe=8,rd=4,rc=2,rbf=1
integer sym,fileend,i
integer phase=0,count=0
constinteger filebeg=16_1000
recordformat intf(integer top,bot,put,get)
record (intf)intbuf
constinteger bufsize=16384
bytearray buffer(0:bufsize-1)
constinteger cr=13,esc=27,nopage=8
integer crc=0,col=0,dov=0,fov=0,pak=0,ack=0,ret=0,qqq=0
routine preload; !Read Z80 object file into an array
integer sym
onevent 9 start
closeinput; selectinput(0); return
finish
selectinput(1)
fileend = filebeg
cycle
readsymbol(sym); buffer(fileend) = sym; fileend = fileend+1
repeat
end
routine load; !Load Station's Z80 (cutting filestore umbilical)
integer sym,ad
sym = 0; status = sym; ! Disable station interrupts
control = 16_03
cycle
repeatuntil status&tbe#0
ad = 16_1000
while ad<fileend cycle
sym = buffer(ad)
data = sym
cycle
repeatuntil status&tbe#0
ad = ad+1
repeat
control = 16_0b
cycle
repeatuntil status&tbe#0
end
routine ether interrupt handler(record (*)name r)
*=16_43FA;*=16_000C; ! lea int,a1
*=16_21C9;*=16_1070; ! move.l a1,$1070
*=16_2348;*=16_0006; ! move.l a0,6(a1)
*=16_4E75; ! rts
*=16_48E7;*=16_C0C0; ! int movem.l d0/d1/a0/a1,-(sp)
*=16_207C;*=16_0006;*=16_00A1;! move.l #$000600a1,a0; !Overwriten with A0
*=16_1039;*=16_0007;*=16_FFFC;! move.b $7fffc,d0
*=16_0800;*=16_0001; ! btst #1,d0
*=16_6734; ! beq.s data
*=16_2268;*=16_0008; ! move.l 8(a0),a1
*=16_720E; ! moveq #14,d1
*=16_12F9;*=16_0007;*=16_FFFF;! move.b $7ffff,(a1)+
*=16_1039;*=16_0007;*=16_FFFC;! loop move.b $7fffc,d0
*=16_0800;*=16_0002; ! btst #2,d0
*=16_67F4; ! beq loop
*=16_12F9;*=16_0007;*=16_FFFD;! move.b $7fffd,(a1)+
*=16_51C9;*=16_FFEC; ! dbra d1,loop
*=16_B3E8;*=16_0004; ! cmp.l 4(a0),a1
*=16_6602; ! bne.s x1
*=16_2250; ! move.l (a0),a1
*=16_2149;*=16_0008; ! x1 move.l a1,8(a0)
*=16_4CDF;*=16_0303; ! intret movem.l (sp)+,d0/d1/a0/a1
*=16_4E73; ! rte
*=16_1039;*=16_0007;*=16_FFFD;! data move.b $7fffd,d0
*=16_60F2; ! bra intret
end
routine date time
string (31)s
length(s) = fcommr('G'<<8,"",charno(s,1),31)
printstring(s)
end
routine at(integer line,col)
printsymbol(esc); printsymbol('Y')
printsymbol(line+' '); printsymbol(col+' ')
end
routine log(integername err)
err = err+1
if err=1 start
if err==pak then at(1,40) and printstring("Pak=") c
elseif err==ack then at(1,50) and printstring("Ack=") c
elseif err==crc then at(1, 0) and printstring("CRC=") c
elseif err==col then at(1,10) and printstring("COL=") c
elseif err==dov then at(1,20) and printstring("DOV=") c
elseif err==fov then at(1,30) and printstring("FOV=") c
elseif err==ret then at(1,60) and printstring("Ret=") c
else at(1,70) and printstring("???=")
finish
if err==pak then at(1,44) c
elseif err==ack then at(1,54) c
elseif err==crc then at(1, 4) c
elseif err==col then at(1,14) c
elseif err==dov then at(1,24) c
elseif err==fov then at(1,34) c
elseif err==ret then at(1,64) c
else at(1,74)
phex4(err)
end
recordformat rawf(byte st,ds,dp,ss,sp,ty,sq,dsl,dsh,psl,psh,d1,d2,d3,d4,d5)
record (rawf)name raw
recordformat xf(short row,col,from,to, c
data,redata,dsq,size,string (5)content, c
short acks,reacks,asq)
constinteger maxx=40
record (xf)array x(1:maxx)
record (xf)name xx
routine idle
integer n = intbuf_put-intbuf_get
n = n+intbuf_bot-intbuf_top if n<0
at(0,35); phex4(n>>4)
end
routine process packet
owninteger nextslot=0
integer i,j,from,to,slot
idle
if raw_st&2#0 start
log(dov); return
finish
if raw_st&1#0 start
log(fov); return
finish
log(crc) if raw_st&8#0
log(col) if raw_st&4#0
from = raw_ss<<8+raw_sp
to = raw_ds<<8+raw_dp
! Decide which slot to use.
if from&16_7f00=16_7000 and to&16_7000=16_1000 start
slot = (from&15)<<1
elseif from&16_7000=16_1000 and to&16_7f00=16_7000 start
slot = (from>>8&15)<<1-1
elsestart
log(qqq)
nextslot = rem(nextslot+1,maxx-30)
slot = maxx-nextslot
finish
xx == x(slot)
!found:
xx_from = from; xx_to = to
if raw_ty&128=0 start
log(pak)
if raw_sq=0 or raw_sq#xx_dsq start
xx_dsq = raw_sq; xx_data = xx_data+1
else
xx_redata = xx_redata+1; log(ret)
finish
xx_size = raw_psl+raw_psh<<8
i = raw_dsl+raw_dsh<<8; xx_size = ¬i unless i=xx_size
! length(xx_content) = 5
! %for i=1,1,5 %cycle
! j = byteinteger(addr(raw_d1)+i-1)
! j = '_' %unless ' '<=j<=126
! charno(xx_content,i) = j
! %repeat
at(xx_row,xx_col); phex4(xx_from); phex4(xx_to)
space; phex4(xx_data); space; phex4(xx_redata); space
phex2(xx_dsq); space; phex4(xx_size-14)
! space; printstring(xx_content)
else
log(ack)
if raw_sq=0 or raw_sq#xx_asq start
xx_asq = raw_sq; xx_acks = xx_acks+1
else
xx_reacks = xx_reacks+1; log(ret)
finish
at(xx_row,xx_col); phex4(xx_from); phex4(xx_to)
at(xx_row,xx_col+27)
phex4(xx_acks); space; phex4(xx_reacks); space; phex2(xx_asq)
finish
end
!* I N I T I A L I S E
set terminal mode(nopage)
intbuf_top = addr(buffer(0))
intbuf_bot = intbuf_top+bufsize
intbuf_put = intbuf_top; intbuf_get = intbuf_top
openinput(1,"ether:monitor.bin"); preload
printsymbol(esc); printsymbol('v')
printstring("Ethernet Monitor Station")
printstring(" Up since ")
date time; newline
load
ether interrupt handler(intbuf)
status = 6; ! Re-enable station interrupts (receive-only)
at(2,0); printstring("From To Data (re) No Size Acks (re) No")
at(2,40); printstring("From To Data (re) No Size Acks (re) No")
for i = 1,1,maxx cycle
xx == x(i); xx = 0
if i<=maxx>>1 start
xx_row = i+2; xx_col = 0
else
xx_row = i+2-maxx>>1; xx_col = 40
at(xx_row,39); printsymbol('|')
finish
repeat
!** Main Program Loop
cycle
while intbuf_get#intbuf_put cycle ; ! Update Loop
raw == record(intbuf_get)
intbuf_get = intbuf_get+16
intbuf_get = intbuf_top if intbuf_get=intbuf_bot
process packet
repeat
idle while intbuf_get=intbuf_put
repeat
endofprogram