/Ethernet monitor station firmware for CSD142 boards
/RWT May 1982

/There is one big data buffer, used cyclically.
/This is filled by the ether receiver with everything
/it hears.
/There is a smaller circular buffer containing 16 bytes
/per packet heard.  This is filled by the ether receiver
/interrupt handler, and drained by the idle process
/sending it off to the boot processor.  The boot processor
/is given groups of 16 bytes, the first byte in each group
/is sent as a control character to guarantee phase
/synchronisation.
/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,,source,,type,,sized,,sizep,,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

  area rom
  loc 16_1000

/Variables
  area ram
  loc 16_1800
var get,,put,,dbstart,,dbtemp,
cbufftop: loc 16*128+.
cbuffbot:
dbufftop: loc 7000+.
dbuffbot:

/Initial entry
  area rom
  jr begin
w cbufftop
w dbufftop
w dbuffbot
begin:
  di
  ld sp,16_4000

/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 hl,#cbufftop
  ld get,hl
  ld put,hl

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

/Idle loop
  ei
  ld bc,0
idle:
  ld hl,put
  ld de,get
  or a; sbc hl,de
  jr nz,idl0           /Something interesting ->
  dec c
  jr nz,idle
  dec b
  jr nz,idle
  xor a; out (lkd),a
  call ltwait
  jr idle
idl0:
  ld hl,get
  ld a,(hl); inc hl
  out (lkc),a
  call ltwait
  ld b,15
idl1:
  ld a,(hl); inc hl
  out (lkd),a
  call ltwait
  djnz idl1
  ld bc,0
  ld get,hl
  ld de,#cbuffbot
  ld a,l; xor e
  jp nz,idle
  ld a,h; xor d
  jp nz,idle
  ld hl,#cbufftop
  ld get,hl
  jp idle

/Routine to wait for link TBE
ltwait:
  in a,(ls)
  rra; ret cy
  jp ltwait

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

/DMA Completion (Ether receiver ONLY)
/The ether receiver has delivered an outsize packet
/Clobber and re-initialise it
intdtc:
  exx; ex af,af
  in a,(tc)           /Clear interrupt
  ld a,16_80            /freeze receiver
  out (er),a
  ld hl,dbstart
  ld de,16_4000+header+datamax+5-1
  ld c,dmaer
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit /prepare to reactivate DMA
  out (dma),a
  in a,(er)             /unfreeze receiver (clear OVR)
  ld hl,put
  ld (hl),2
  jp wrap

/Ether Receiver Fifo Overflow
intovf:
  exx; ex af,af
  ld a,16_80            /freeze receiver
  out (er),a
  ld hl,dbstart
  ld de,16_4000+header+datamax+5-1
  ld c,dmaer
  out (c),hl
  inc c
  out (c),de
  ld a,erdmabit+tcbit /prepare to reactivate DMA
  out (dma),a
  in a,(er)             /unfreeze receiver (clear OVR)
  ld hl,put
  ld (hl),1
  jp wrap

/Ether Receiver Done
interd:
  exx; ex af,af
  ld hl,dbstart
  ld dbtemp,hl
  ld c,dmaer
  in de,(c)          /read end address
  ld hl,de
  ld bc,#dbuffbot-header-datamax-6
  sbc hl,bc
  ld hl,de
  jp n,int1
  ld hl,#dbufftop
int1:
  ld dbstart,hl
  ld c,dmaer
  out (c),hl         /set new start address
  inc c
  ld hl,16_4000+header+datamax+5-1 /and new size
  out (c),hl
  ld a,erdmabit+tcbit
  ld ix,put
  out (dma),a
  in a,(es)
  ld status,a        /Note ether status
  in a,(er)          /Read control character
  ex de,hl           /(ER now active) HL=endad
  dec hl; dec hl       /back past CRC bytes
  dec hl; ld b,(hl)
  dec hl; ld c,(hl)    /BC = packet size (from packet)
  ld sizep,bc
  ld de,dbtemp
  or a; sbc hl,de      /HL = packet size (from DMA)
  ld sized,hl
  ld iy,dbtemp
  ld hl,(iy)
  ld dest,hl
  ld hl,(iy+6)
  ld source,hl
  ld hl,(iy+12)
  ld type,hl
  ld hl,(iy+14)
  ld data,hl
  ld hl,(iy+16)
  ld data(2),hl
  ld a,(iy+18)
  ld data(4),a
  ld hl,put
wrap: ld de,16
  add hl,de
  ld put,hl
  ld de,#cbuffbot
  ld a,l; xor e; jr z,wr1
intret: exx; ex af,af; ei; ret
wr1: ld a,h; xor d
  jp nz,intret
  ld hl,#cbufftop
  ld put,hl
  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 intspu     /rcr
  w intspu     /rdr
  w intspu     /tbe
  w intspu     /spu

  end
