/New Checking Program for CSD142 Ether Boards /RWT Feb 1986 /This test works WITHOUT interrupts. /It begins with a host link echo test, in which /certain characters are intercepted and treated as /instructions to executed a number of specific tests: / 'M' Memory Test / 'T' Ether transmit test / 'R' Ether Receive test /The echo and memory tests do not assume the presence /of working RAM, and hence hold their entire context /in registers. To achieve this, it has been necessary /to exploit an unpublished feature of the Z80, namely /that most instructions which access H or L will, if /prefixed with the special instruction prefix 16_FD, /which normally causes IY to be used instead of HL, /will cause the appropriate half of IY to be used /instead of H or L. /Frig withiy=16_fd /Memory /$if rom base=0 low=16_1000 /$else /base=16_1000 /low=16_2000 /$finish size=low delay=low+2 pointer=low+4 packet=low+8 high=16_4000 /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 /NB: Interrupt vectors (for interest only) /2 ltbe /4 lrdr /6 lrcr /8 dmatc /a etdone /c erdone /e overflow /IO-package entry points pdata=base+8 pctrl=base+16 rdata=base+16_18 rctrl=base+16_20 rsym=base+16_28 loc base+16_00; ld sp,high jp begin loc base+16_08; jp xpdata loc base+16_10; jp xpctrl loc base+16_18; jp xrdata loc base+16_20; jp xrctrl loc base+16_28; jp xrsym loc base+16_30; jp *+16_1000 loc base+16_38; jp *+16_1000 loc base+16_66; jp *+16_1000 / I N I T I A L E N T R Y begin: ld a,halt ld (16_1030),a ld (16_1038),a ld (16_1066),a di jp rwait / E C H O T E S T twait: in a,ls /Wait for LTBE rra jp nc,twait rwait: in a,ls /Wait for LRBF add a,a jp nc,rwait jp n,data /LRDR=0: -> in a,lkc out lkc,a jp twait data: in a,lkd cp 'T' jp z,transtest cp 'R' jp z,rectest cp 'M' jp z,memtest out lkd,a jp twait / M E M O R Y T E S T / B Old pattern / C New pattern / D Long-term error count / E Short-term e c / IYH Picks *NAUGHTY* / IYL Drops *NAUGHTY* / IX Pointer / HL Counter message: text "Memory test" 0 memtest: ld hl,message hello: in a,ls rra; jr nc,hello ld a,(hl); inc hl or a; jr z,startm out (lkd),a jr hello startm: ld ix,low /Clear store ld hl,high-low clearloop: ld (ix),0 inc ix; dec hl ld a,h; or l jp nz,clearloop ld c,0 /Set Oldpat=0 (later) ld de,0 /Clear error counts ld iy,0 /Clear pick/drop mainloop: ld b,c ld a,b; rlca /Work out new pattern xor 1; ld c,a ld ix,low ld hl,high-low testloop: ld a,b xor (ix) /Check old pattern jp z,longok /OK -> and b withiy; or l /Record picks withiy; ld l,a ld a,b; cpl; ld b,a cpl; xor (ix) /Re-read (!) and b withiy; or h /Record drops withiy; ld h,a ld a,b; cpl; ld b,a inc d /Bump error count jp nz,longok /But not past 255 ld d,255 longok: ld a,c ld (ix),a /Write and xor (ix) /check new pattern jp z,shortok /OK -> and c withiy; or l withiy; ld l,a ld a,c; cpl; ld c,a cpl; xor (ix) and c withiy; or h withiy; ld h,a ld a,c; cpl; ld c,a inc e jp nz,longok ld e,255 shortok: inc ix /Bump pointer dec hl /Count down ld a,h; or l /Done? jp nz,testloop /No -> wtre: in a,ls /write results to link rra; jr nc,wtre ld a,b /First Oldpat out lkc,a wtb: in a,ls rra; jr nc,wtb ld a,c /Then Newpat out lkd,a wtc: in a,ls rra; jr nc,wtc ld a,d /Then Long errcount out lkd,a wtd: in a,ls rra; jr nc,wtd ld a,e /Then Short errcount out lkd,a wte: in a,ls rra; jr nc,wte withiy; ld a,h /Then Picks out lkd,a wth: in a,ls rra; jr nc,wth withiy; ld a,l /Then Drops out lkd,a wtl: in a,ls rra; jr nc,wtl jp mainloop / T R A N S M I T T E S T /Any data characters received are appended to the packet. /On receipt of a control character, its low-order 2 bits /are inspected, and the following action is taken: /0: Reset data character packet buffer pointer /1: Set packet size (next 2 data characters) /2: Send one packet /3: Loop packet transmission (next char specifies delay) transtest: ld hl,16 ld (size),hl ld hl,16_6666 ld (packet),hl ld hl,16_9999 ld (packet+12),hl ld hl,'I'<<8+'H' ld (packet+14),hl ld hl,0 ld (delay),hl ld (packet+2),hl ld (packet+4),hl ld (packet+8),hl ld (packet+10),hl txreset: ld hl,packet ld (pointer),hl txidle: call rsym jr cy,txctrl ld hl,(pointer) ld (hl),a inc hl ld (pointer),hl jr txidle txctrl: and 3 jr z,txreset cp 1 jr z,txsize cp 2 jr nz,txloop call txone jr txidle txsize: call rsym ld (size+1),a call rsym ld (size),a txloop: call txone ld hl,(delay) txdelay: dec hl ld a,h or l jr nz,txdelay jr txloop txone: ld c,dmaet ld hl,packet out (c),hl inc c ld hl,(size) ld de,16_7fff add hl,de out (c),hl ld a,tcbit+etdmabit out (dma),a txwait: in a,(es) ld b,a and 16_a0 jr z,txwait xor a out (dma),a out (et),a ld c,dmaet in hl,(c) ld de,-packet add hl,de ld a,b call pctrl ld a,h call pdata ld a,l call pdata ret / R E C E I V E T E S T /On receipt of a control character, the /station address filter is set to that value. /On receipt of a data character '*', a receive loop /is entered, in which all received packets are fully /displayed. /On receipt of a data character '*', a receive loop /is entered in which all received packets are only /partially displayed. /On receipt of any other data character, one packet /is received and displayed. rectest: ld a,16_80 /Default: promiscuous mode ssa: out (er),a /set station address, freeze rx in a,(er) /unfreeze rx, reset overflow rxidle: call rsym jr cy,ssa /control char -> cp '?' jr z,partloop cp '*' jr z,fullloop call fullone jr rxidle fullloop: call fullone jr fullloop partloop: call partone jr partloop /Partial receipt displays: /One control char denoting ether status, /followed by a number of data characters: /dma packet length (2 chars), /first two and last two packet chars. /Full receipt displays: /Ctrl char: ether status, data chars: /DMA length (2 chars), /Entire packet. partone: call getone ld a,d call pctrl ld a,h call pdata ld a,l call pdata ld a,(packet) call pdata ld a,(packet+1) call pdata ld de,packet-4 add hl,de ld a,(hl) call pdata inc hl ld a,(hl) call pdata inc hl ld a,(hl) call pdata inc hl ld a,(hl) call pdata ret fullone: call getone ld a,d call pctrl ld a,h call pdata ld a,l call pdata ld bc,hl ld hl,packet-1 showloop: ld a,b or c ret z dec bc inc hl ld a,(hl) call pdata jr showloop /Get one packet. /Return with D = ether status, / HL = packet length (as indicated by DMA) getone: ld c,dmaer /set up DMA channel ld hl,packet /packet buffer start address out (c),hl inc c ld hl,16_47ff /input mode, 2048 bytes out (c),hl ld a,tcbit+erdmabit out (dma),a /enable dma rxwait: in a,(es) ld d,a and 16_11 /wait for done or overflow jr z,rxwait xor a out (dma),a /stop dma in a,(er) /read ether control char ld e,a ld c,dmaer in hl,(c) /read dma address ld bc,-packet add hl,bc ld a,h or l ret nz /non-empty packet => ld a,d cp 16_10 ret nz /error status => jr getone /try again -> / I / O P A C K A G E /Send one data character from A xpdata: out lkd,a push af xpwait: in a,ls rra; jp nc,xpwait pop af ret /Send one control character from A xpctrl: out lkc,a push af jp xpwait /Read one data or control char into A xrsym: in a,ls add a,a; jp nc,xrsym add a,a; ccf jp nc,gotd jp gotc /Read one control character into A xrc0: in a,lkd xrctrl: in a,ls add a,a; jp nc,xrctrl jp n,xrc0 /Skip data -> gotc: in a,lkc ret /Read one data character into A xrd0: in a,lkc xrdata: in a,ls add a,a; jp nc,xrdata jp p,xrd0 /Skip control -> gotd: in a,lkd ret end