/Ethernet monitor station firmware for CSD142 boards
/Colin McRoberts CS4 project 1983 - 84

/There is one big data buffer, used cyclically.
/This is filled by the ether receiver with everything
/it hears.
/The group layout is as follows:
/  Ether status &16_c, +1 for fifo overflow, +2 for dma overrun
/  Dest station
/  Dest port
/  Source station
/  Source port
/  Packet type
/  Packet sequence number
/  Packet size (DMA) Low
/    "      "    "   High
/  Packet size (packet) Low
/    "      "     "     High
/  The first 5 characters in the packet

  area ix
  loc 0
var status,dest,,missd,,unused,,source,,sized,,sizep,,type,,data

/Device addresses
dmaer=0
dmaet=2
dmalr=4
dmalt=6
dma=8
tc=16_10   /read-only (clears DMA TC interrupt)
int=16_10  /write-only interrupt enable (ltbe.lrdr.lrcr.dmatc)
lkc=16_20  /link control (read/write)
lkd=16_30  /link data
er=16_40   /read: data/control, write: filter/reset
ls=16_50   /(link status) read-only (rbf.rdr.rcr.0.0.0.0.tbe)
etd=16_50  /write-only: data into fifo
es=16_60   /read-only: (tcol.ta.tdone.rctrl.crce.rcol.ra.over)
et=16_60   /write-only: hold-off counter, reset

/Interrupt enable bits
tcintbit=8
rcintbit=4
rdintbit=2
teintbit=1

/DMA enable bits
erdmabit=1
etdmabit=2
lrdmabit=4
ltdmabit=8
tcbit=16_40

/Miscellaneous constants
header=14;datamax=512+20;stksiz=512
databits=1
pktsiz=header+1+databits
/Variables
  area ram
  loc 16_1800
  loc stksiz+.
stktop:
var get,,dbstart,,newstart,,misses,,dmasiz,,tflag,ints,fststs
dbufftop: loc 400*pktsiz+.
dbuffbot:

/Initial entry
  area rom
  loc 16_1000

  jr begin
w dbufftop
w dbuffbot
w stktop
begin:
  di
  ld hl,#dbufftop+pktsiz
  ld newstart,hl
  ld de,16_4000+header+datamax+5-1
  ld c,dmaer
  exx; ex af,af
  ld sp,#stktop

/Initialise hardware
  in a,(tc)               /reset DMA interrupt
  xor a; out (et),a       /reset transmitter
  ld a,16_80; out (er),a  /reset receiver (sets overrun)
  in a,(er)               /(clears overrun)

/Set up ER DMA
  ld hl,#dbufftop
  ld dbstart,hl
  ld de,16_4000+header+datamax+5-1 /5=size(2)+crc(2)+pad(1)
  ld c,dmaer
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit
  out (dma),a

/Set up variables
  ld ix,dbstart
  dec ix
  xor a;ld tflag,a
  ld ints,a
  ld hl,#dbufftop-1
  ld get,hl
  ld hl,0
  ld misses,hl

/Set up interrupts
  ld a,tcintbit+rcintbit
  out (int),a
  ld a,inttab>>8
  ld i,a
  im2

/Idle loop
  ei
idle:
  ld hl,dbstart
  dec hl
  ld de,get
  or a; sbc hl,de
  jr z,idle
  ld hl,get
  ld a,(hl); inc hl
  out (lkc),a
lcrwait:
  in a,(ls)
  rra
  jr nc,lcrwait
donectrl:
  ld b,header+databits
send:
  ld a,(hl); inc hl
  out (lkd),a
ldrwait:
  in a,(ls)
  rra
  jr nc,ldrwait
  djnz send
  ld get,hl
  ld de,#dbuffbot-1
  ld a,l; xor e
  jp nz,idle
  ld a,h; xor d
  jp nz,idle
  ld hl,#dbufftop-1
  ld get,hl
  jp idle


/   I N T E R R U P T   P R O C E S S I N G

/ Timing interrupt from the MC6800 so insert a dummy packet
/ into the buffer.
intrcr:
  exx; ex af,af
  in a,(es)
  and 2
  jp nz,setflg
  xor a; out (dma),a
  ld de,dbstart
  in hl,(c)
  or a; sbc hl,de
  jp nz,retqck
  ld hl,newstart
  out (c),hl
  inc c
  ld de,16_4000+header+datamax+5-1
  out (c),de
  ld a,erdmabit+tcbit
  out (dma),a
  in a,(lkc)
  ld a,32
  ld status,a
  ld type,a
  jp wrap
retqck:
  ld a,erdmabit+tcbit
  out (dma),a
setflg:
  in a,(lkc)
  ld a,32
  ld tflag,a
  exx; ex af,af; ei; ret

/DMA Completion (Ether receiver ONLY)
/The ether receiver has delivered an outsize packet
intdtc:
  exx; ex af,af
  in a,(tc)           /Clear interrupt
  xor a; out (dma),a
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit /prepare to reactivate DMA
  out (dma),a
  ld a,1
  ld ints,a
  ld a,tflag
  or 2
  ld status,a
  jp wrap

/Ether Receiver Fifo Overflow
intovf:
  exx; ex af,af
  xor a; out (dma),a
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit /prepare to reactivate DMA
  out (dma),a
  ld a,1
  ld ints,a
  ld a,tflag
  or 1
  ld status,a
  jp wrap

/Ether Receiver Done
interd:
  exx; ex af,af
  ld a,ints
  and 1
  jp z,valid
  ld hl,dbstart
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit
  out (dma),a
  xor a; ld ints,a
  dec c
  ld hl,newstart
  exx; ex af,af; ei; ret
valid:
  ld de,newstart
  in hl,(c)          /read end address
  out (c),de         /set new start address
  inc c
  ld de,16_4000+header+datamax+5-1 /and new size
  out (c),de
  ld a,erdmabit+tcbit
  out (dma),a
  in a,(es)
  and 12
  ld c,a
  ld a,tflag
  or c
  ld status,a        /Note ether status
  dec hl; dec hl     /back past CRC bytes
  dec hl; ld b,(hl)
  dec hl; ld c,(hl)  /BC = packet size (from packet)
  in a,(er)          /Read control character
  ld dmasiz,hl
  ld de,0
  ld hl,missd
  sbc hl,de
  jp nz,badpkt
  ld hl,unused
  sbc hl,de
  jp nz,badpkt
  ld hl,sizep
  sbc hl,de
  jp nz,badpkt
  ld hl,sized
  sbc hl,de
  jp z,okpkt
badpkt:
  ld a,tflag
  or 16
  ld status,a
  ld hl,dmasiz
  ld de,dbstart
  or a; sbc hl,de      /HL = packet size (from DMA)
  ld sized,hl
  ld hl,misses
  ld missd,hl
  jp wrap
okpkt:
  ld hl,dmasiz
  ld de,dbstart
  or a; sbc hl,de      /HL = packet size (from DMA)
  ld sized,hl
  ld sizep,bc
  ld hl,misses
  ld missd,hl
wrap:
  ld hl,newstart
  ld de,header+1+databits
  add hl,de
  ld de,#dbuffbot
  ld a,l; xor e; jr z,wrprnd
intret:
  ld bc,hl
  ld de,get
  or a; sbc hl,de
  ld hl,newstart
  jp p,retok
  ld hl,header+datamax+5-1
  add hl,bc
  or a; sbc hl,de
  ld hl,newstart
  jp n,retok
  ld hl,misses
  inc hl
  ld misses,hl
  ld hl,dbstart
retok:
  ld dbstart,hl
  ld newstart,bc
  ld hl,bc
  ld de,16_4000+header+datamax+5-1
  ld c,dmaer
  ld ix,dbstart
  dec ix
  xor a;ld tflag,a   /zero tflag
  exx; ex af,af; ei; ret
wrprnd:
  ld a,h; xor d
  jp nz,intret
  ld hl,#dbufftop
  jp intret

/Unsolicited interrupts
intspu:
  halt

/(256-byte-aligned) interrupt table
  block 256-.&255
inttab:
  w intovf     /ovf
  w interd     /erd
  w intspu     /etd
  w intdtc     /dtc
  w intrcr     /rcr
  w intspu     /rdr
  w intspu     /tbe
  w intspu     /spu

  end
