home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
vol238
/
level1.aqm
/
LEVEL1.ASM
Wrap
Assembly Source File
|
1986-02-10
|
20KB
|
832 lines
title 'LEVEL1.ASM'
;************************************************
;* *
;* LEVEL1.ASM *
;* *
;* Hardware level initialization and interrupt *
;* service routines for X.25 protocol. *
;* Implemented for Digital Research Computers *
;* 'Big Board' single board computer. *
;* (Z80+SIO+CTC using mode 2 interrupts) *
;* *
;* rev 1.39 08/21/84 E. Elizondo *
;* *
;* (c) 1984 E. Elizondo - all rights reserved. *
;* *
;* This program may be used freely for non- *
;* commercial applications. It may not be sold *
;* or used for commercial applications without *
;* written permission of the author. *
;* *
;************************************************
;
maclib Z80 ;DR Z80 macro library
; design parameters
; timer periods (seconds)
t1: equ 10 ;level 2 timer T1
t20: equ 180 ;level 3 timer T20
t21: equ 200 ;level 3 timer T21
t22: equ 180 ;level 3 timer T22
t23: equ 180 ;level 3 timer T23
; BIG BOARD equates
; I/O port assignments
BAUDA: equ 00h ;channel A baud generator
SIO: equ 04h ;dual serial I/O
SIODPA: equ SIO+0 ;SIO data port A
SIOCPA: equ SIO+2 ;SIO control/status port A
CTC: equ 18h ;quad counter/timer circuit
CTC0: equ CTC+0 ;CTC channel 0
CTC1: equ CTC+1 ;CTC channel 1
; interrupt vector locations
SIOV4: equ 0FF08h ;SIO port A xmit buffer empty int vector
SIOV5: equ 0FF0Ah ;SIO port A external status change
SIOV6: equ 0FF0Ch ;SIO port A receive data available
SIOV7: equ 0FF0Eh ;SIO port A special receive condition
CTCV1: equ 0FF12h ;CTC channel 1 interrupt
; SIO commands
srcres equ 0011$0000b ;reset special rx cond errors
eomres equ 1100$0000b ;reset tx eom latch
crcres equ 1000$0000b ;reset tx crc
escres equ 0001$0000b ;reset external status interrupt
intpres equ 0010$1000b ;reset tx interupt pending
abort equ 0000$1000b ;HDLC abort command
; special Level 2 frame identifiers
cmdrfid equ 1000$0111b ;X.25 CMDR frame identifier
; hooks for main program
; subroutine entry points
public inisio ;initialize SIO channel A
public sbaud ;set baud rate
public txwake ;start frame transmission
public txabo ;transmit immediate abort
public t1on ;start level 2 timer T1
public t1off ;stop level 2 timer T1
public t20on ;start level 3 timer T20
public t20off ;stop level 3 timer T20
public t21on ;start level 3 timer T21
public t21off ;stop level 3 timer T21
public t22on ;start level 3 timer T22
public t22off ;stop level 3 timer T22
public t23on ;start level 3 timer T23
public t23off ;stop level 3 timer T23
; addresses
public baudop ;default baud rate option
public rxgfct ;count of good received frames
public rxbfct ;count of bad received frames
public rxbbct ;count of buffer busy
public rxboct ;count of buffer overrun
public rxcect ;count of crc errors
public rxoect ;count of received frame overruns
public rxabct ;count of received aborts
public txefct ;count of tx end of frames
public txuect ;count of tx underrun errors
public txabct ;count of transmitted aborts
public txaddr ;tx address byte
public txctrl ;tx control byte
public rxstat ;receive status flags
public txstat ;transmit status flags
public tistat ;timer status flags
; definition of rxstat flag byte:
; bit set condition
; 0 rx active
; 1 undefined
; 2 undefined
; 3 undefined
; 4 undefined
; 5 receiver buffers unavailable
; 6 undefined
; 7 undefined
; definition of txstat flag byte:
; bit set condition
; 0 tx active
; 1 tx message complete
; 2 tx frame underrun
; 3 next tx character is control
; 4 undefined
; 5 undefined
; 6 undefined
; 7 undefined
; definition of tistat flag byte:
; bit set condition
; 0 level 2 timer t1 timed out
; 1 level 3 timer t20 timed out
; 2 level 3 timer t21 timed out
; 3 level 3 timer T22 timed out
; 4 level 3 timer T23 timed out
; 5 undefined
; 6 undefined
; 7 undefined
; external suboutines
extrn ilprt ;in line print routine
extrn putbuf ;write char to buffer
extrn getbuf ;read char from buffer
extrn bpoint ;point to bcb address
extrn newrxb ;get new rx buffer
extrn clrbuf ;clear buffer for new use
extrn resbcb ;restore bcb pointers
extrn delay ;wait a bit
; external addresses
extrn rxbact ;active rx buffer #
extrn rxbtab ;table of rx bcb pointers
extrn rxfree ;bcb for list of free rx buffers
extrn rxflst ;bcb for list of complete rx buffers
extrn rxbcbp ;active rx bcb
extrn txbtab ;table of tx bcb pointers
extrn txbcbp ;active tx bcb
extrn txubcb ;bcb for CMDR/FRMR I data
; miscellaneous equates
cr equ 0Dh ;carriage ret
lf equ 0Ah ;line feed
cseg ;code segment
; *********************************
; * initialization section *
; *********************************
; initialize SIO port A
; (externally called)
; on entry: no paramters
; on exit: flags, regs clobbered
inisio:
; initialize interrupt vectors
lxi h,siotbe ;tx interrupt service
shld siov4
lxi h,sioesc ;ext status change service
shld siov5
lxi h,siorca ;rx interrupt service
shld siov6
lxi h,siosrc ;special rx condition service
shld siov7
lxi h,tick ;1 second timer interrupt
shld ctcv1
; initialize baud rate
lda baudop ;get initial baud rate option
call sbaud ;set rate
; initialize programmable I/O devices
lxi h,intab ;point to SIO parameter table
inilp: mov b,m ;b= loop bytecount
inx h
mov c,m ;c= device control port #
inx h
outir ;output byte string
mov a,m ;test for end of table
inr a ; /
jnz inilp ;loop again if not at end
; initialize program status flags
xra a
sta rxstat ;clear receive flags
sta txstat ;clear transmit flags
; clear sio rx buffer
in siodpa ;clear out SIO data buffer
in siodpa ;again for luck
ret
; *********************************
; * interrupt service routines *
; *********************************
; receive character interupt service routine
; (externally called)
; on entry: no parameters
; on exit: all flags, registers unchanged
siorca:
call save ;save registers
in siodpa ;get received char
mov b,a ;save char in <b>
lxi h,rxstat ;point to rx status flag
setb 0,m ;set rx active
bit 5,m ;rx buffer available?
jnz erxbusy ;no, handle error
;
mov a,b ;get byte
lhld rxbcbp ;<hl>=active bcb pointer
call putbuf ;store in buffer
rnc ;exit if no buffer overflow
;
lhld rxboct ;else increment buffer overflow
inx h ;..error counter
shld rxboct ; /
ret
; handle no buffer available error
erxbusy:
lhld rxbbct ;get buffer busy error count
inx h ;increment it
shld rxbbct ;and save updated count
ret
; special receive condition interrupt service routine
; (externally called)
; on entry: no parameters
; on exit: all flags, regs unchanged
siosrc:
call save ;save registers
mvi a,1 ;select rr1
out siocpa ; /
in siocpa ;read rr1
mov b,a ;save status in <b>
mvi a,srcres ;reset error command
out siocpa ; /
in siodpa ;clear data byte
lxi h,rxstat ;clear rx active
res 0,m
bit 7,b ;check end of frame bit
jnz eof ;yes, service it
;
; process error conditions
lhld rxbfct ;update bad frame count
inx h ; /
shld rxbfct ; /
bit 6,b ;crc error?
cnz crcerr ;yes, service it
;
bit 5,b ;overrun error?
cnz orerr ;yes, service it
;
call flush ;clear rx buffer
ret
;
; process end of frame
eof:
lda rxbact ;get active buffer #
lxi h,rxflst ;point to list of rx frames
call putbuf ;hand over frame
call newrxb ;get new rx buffer if avail
lhld rxgfct ;update good frame count
inx h ; /
shld rxgfct ; /
ret
;
;
crcerr: lhld rxcect ;update crc error counter
inx h ; /
shld rxcect ; /
ret
;
orerr: lhld rxoect ;update overrun error counter
inx h ; /
shld rxoect ; /
ret
; tx wake routine (starts transmission of frame)
; (externally called)
; on entry: no paramters
; on exit: flags, regs clobbered
txwake:
lxi h,txstat ;point to tx status flag
setb 0,m ;signal tx active
setb 3,m ;signal next char is control
mvi a,crcres ;reset tx crc
out siocpa ; /
lda txaddr ;get address byte
out siodpa ;transmit it
mvi a,eomres ;reset tx eom latch
out siocpa ; /
ret
; tx buffer empty interrrupt service routine
; (externally called)
; on entry: no parameters
; on exit: all flags, regs unchanged
siotbe:
call save ;save registers
lxi h,txstat ;point to tx status flag
bit 1,m ;message complete?
jnz txeof ;yes, process end of frame
;
lda txctrl ;get control byte
bit 3,m ;next char is control?
jz txnext ;no, process remainder of frame
;
res 3,m ;yes, reset flag
out siodpa ;transmit control byte
ret
;
; process remainder of frame
txnext: bit 0,a ;I frame?
jz txinfo ;yes, process it
;
ani 1110$1111b ;CMDR frame?
cpi cmdrfid ; /
jnz txeom ;no, process end of message
;
lxi h,txubcb ;yes, point to CMDR bcb
call getbuf ;byte available?
jc txeom ;no, process end of message
;
out siodpa ;else output byte
ret
; process I frame
txinfo: lhld txbcbp ;point to active bcb
call getbuf ;end of buffer?
cc resbcb ;yes, restore bcb pointers
jc txeom ;and process end of message
;
out siodpa ;else output byte
ret
;
; process end of transmitted message
txeom: lxi h,txstat ;point to tx status flag
setb 1,m ;set message complete semaphore
lhld txefct ;increment end of frame count
inx h ; /
shld txefct ; /
jmp txexi
; process end of transmitted frame
txeof: res 1,m ;clear tx mc flag
res 0,m ;set tx inactive
txexi: mvi a,intpres ;reset tbe int pending
out siocpa ; /
ret
; service external status change interrupt
; (externally called)
; on entry: no parameters
; on exit: all flags, regs unchanged
sioesc:
call save ;save registers
in siocpa ;read rr0
mov b,a ;save status in <b>
bit 6,b ;tx buffer underrun?
jnz txurun ;yes, process it
;
bit 7,b ;abort received?
jnz rxabo ;yes, process it
;
; else it's only a sync detect
in siodpa ;clear extraneous char
jmp escexi ;and exit
;
; process rx abort
rxabo:
mvi a,3 ;wr3
out siocpa ; /
mvi a,1101$0001b ;enter hunt phase
out siocpa
in siodpa ;clear any extraneous char
lhld rxabct ;increment rx abort count
inx h ; /
shld rxabct ; /
call flush ;clear rx buffer
call delay ;wait a little bit
jmp escexi ;and exit
;
; process tx buffer underrun
txurun: mvi a,eomres ;reset eom/underrun latch
out siocpa ; /
lxi h,txstat ;point to tx status flag
bit 1,m ;tx message complete?
jnz escexi ;yes, it's normal termination
;
; process real tx buffer underrun error
res 0,m ;clear tx busy flag
lhld txuect ;increment underrun error count
inx h ; /
shld txuect ; /
call txabo ;and abort transmission
lda txctrl ;get control byte
bit 0,a ;I frame?
jnz escexi ;no, exit
;
lhld txbcbp ;yes, point to active tx bcb
call resbcb ;and reset pointers
;
; common exit
escexi: mvi a,escres ;reset esc condition
out siocpa ; /
ret
; clear active rx buffer
; (internally called)
flush: lhld rxbcbp ;point to active rx bcb
call clrbuf ;clear buffer
ret
; service 1 second timer interrupt from CTC-1
; (externally called)
; on entry: no parameters
; on exit: all flags, regs unchanged
tick:
call save ;save registers
lxi d,tistat ;<de>=A(timer status word)
lxi h,t1ct ;point to first counter
xra a ;clear <a>
cmp m ;count=0?
jz tick1 ;yes, keep going
dcr m ;else decrement count
jnz tick1 ;keep going if not 0
xchg ;else set timeout flag
setb 0,m ; /
xchg ; /
tick1: inx h ;point to next counter
cmp m ;count=0?
jz tick2 ;yes, keep going
dcr m ;else decrement count
jnz tick2 ;keep going if not 0
xchg ;else set timeout flag
setb 1,m ; /
xchg ; /
tick2: inx h ;point to next counter
cmp m ;count=0?
jz tick3 ;yes, keep going
dcr m ;else decrement count
jnz tick3 ;keep going if not 0
xchg ;else set timeout flag
setb 2,m ; /
xchg ; /
tick3: inx h ;point to next counter
cmp m ;count=0?
jz tick4 ;yes, keep going
dcr m ;else decrement count
jnz tick4 ;keep going if not 0
xchg ;else set timeout flag
setb 3,m ; /
xchg ; /
tick4: inx h ;point to next counter
cmp m ;count=0?
jz tick5 ;yes, keep going
dcr m ;else decrement count
jnz tick5 ;keep going if not 0
xchg ;else set timeout flag
setb 4,m ; /
xchg ; /
tick5: ;room for expansion
ret
; save register routine for interrrupt service
save: xthl ;save <hl> & point to service routine
push d ;save the other regs
push b ; /
push psw ; /
call go ;go and return here from service routine
pop psw ;restore registers
pop b ; /
pop d ; /
pop h ;and get <hl> back from stack
ei ;enable interupts
reti ;restore interrupt chain
;
go: pchl ;dispatch to <hl>
; *********************************
; * level 1 control subroutines *
; *********************************
; transmit abort signal
; (externally and internally called)
; on entry: no parameters
; on exit: flags, regs clobbered
txabo:
mvi a,abort ;send immediate abort
out siocpa ; /
lhld txabct ;increment transmitted abort count
inx h ; /
shld txabct ; /
ret
; stop level 2 timer T1
; (externally and internally called)
; on entry: no paramters
; on exit: all flas, regs unchanged
t1off:
push psw ;save regs and flags
push h ; /
xra a ;set count to 0
sta t1ct ; /
lxi h,tistat ;reset timeout flag
res 0,m ; /
pop h ;restore regs and flags
pop psw ; /
ret
; stop level 3 timer T20
; (externally and internally called)
; on entry: no paramters
; on exit: all flas, regs unchanged
t20off:
push psw ;save regs and flags
push h ; /
xra a ;set count to 0
sta t20ct ; /
lxi h,tistat ;reset timeout flag
res 1,m ; /
pop h ;restore regs and flags
pop psw ; /
ret
; stop level 3 timer T21
; (externally and internally called)
; on entry: no paramters
; on exit: all flas, regs unchanged
t21off:
push psw ;save regs and flags
push h ; /
xra a ;set count to 0
sta t21ct ; /
lxi h,tistat ;reset timeout flag
res 2,m ; /
pop h ;restore regs and flags
pop psw ; /
ret
; stop level 3 timer T22
; (externally and internally called)
; on entry: no paramters
; on exit: all flas, regs unchanged
t22off:
push psw ;save regs and flags
push h ; /
xra a ;set count to 0
sta t22ct ; /
lxi h,tistat ;reset timeout flag
res 3,m ; /
pop h ;restore regs and flags
pop psw ; /
ret
; stop level 3 timer T23
; (externally and internally called)
; on entry: no paramters
; on exit: all flas, regs unchanged
t23off:
push psw ;save regs and flags
push h ; /
xra a ;set count to 0
sta t23ct ; /
lxi h,tistat ;reset timeout flag
res 4,m ; /
pop h ;restore regs and flags
pop psw ; /
ret
; start level 2 timer T1
; (externally called)
; on entry: no parameters
; on exit: all regs, flags unchanged
t1on:
push psw ;save regs and flags
push h ; /
mvi a,t1 ;intitialize count
sta t1ct ; /
lxi h,tistat ;reset timeout flag
res 0,m ; /
pop h ;restore flags, regs
pop psw ; /
ret
; start level 3 timer T20
; (externally called)
; on entry: no parameters
; on exit: all regs, flags unchanged
t20on:
push psw ;save regs and flags
push h ; /
mvi a,t20 ;intitialize count
sta t20ct ; /
lxi h,tistat ;reset timeout flag
res 1,m ; /
pop h ;restore flags, regs
pop psw ; /
ret
; start level 3 timer T21
; (externally called)
; on entry: no parameters
; on exit: all regs, flags unchanged
t21on:
push psw ;save regs and flags
push h ; /
mvi a,t21 ;intitialize count
sta t21ct ; /
lxi h,tistat ;reset timeout flag
res 2,m ; /
pop h ;restore flags, regs
pop psw ; /
ret
; start level 3 timer T22
; (externally called)
; on entry: no parameters
; on exit: all regs, flags unchanged
t22on:
push psw ;save regs and flags
push h ; /
mvi a,t22 ;intitialize count
sta t22ct ; /
lxi h,tistat ;reset timeout flag
res 3,m ; /
pop h ;restore flags, regs
pop psw ; /
ret
; start level 3 timer T23
; (externally called)
; on entry: no parameters
; on exit: all regs, flags unchanged
t23on:
push psw ;save regs and flags
push h ; /
mvi a,t23 ;intitialize count
sta t23ct ; /
lxi h,tistat ;reset timeout flag
res 4,m ; /
pop h ;restore flags, regs
pop psw ; /
ret
; set baud rate
; (externally and internally called)
; on entry: <a>=baud option (0-7)
; on exit: <a>=upper 4 bits=0
; all other regs unchanged
sbaud:
ani 07h ;extract lower 3 bits
sta baudop ;save option
push h ;save registers
push d ; /
lxi h,baudtab ;point to baud table
mov e,a ;option to <de>
mvi d,0
dad d ;point to desired baud
mov a,m ;get baud rate byte
sta baudtab ;save it
out bauda ;program the 8116
pop d ;restore registers
pop h
ret
; *****************
; * data tables *
; *****************
dseg ;data segment
baudop db 1 ;default baud rate option
; table of constants for 8116 baud rate generator
baudtab db 0000$0000b ;0= current baud rate
db 0000$0101b ;1= 300 baud
db 0000$0110b ;2= 600 baud
db 0000$0111b ;3= 1200 baud
db 0000$1010b ;4= 2400 baud
db 0000$1100b ;5= 4800 baud
db 0000$1110b ;6= 9600 baud
db 0000$1111b ;7= 19200 baud
; SIO initialization table
intab: db t1end-$-2 ;byte count
db siocpa ;SIO channel a control port
db 0 ;WR0 for sure
db 0001$1000b ;reset channel a
db 4 ;WR4
db 0010$0000b ;HDLC mode
db 7 ;WR7
db 0111$1110b ;HDLC flag
db 1 ;WR1
db 0001$1111b ;interrupt control
db 5 ;WR5
db 1110$1011b ;tx parameters + tx enable
t1end: equ $
; initialize CTC0
db t2end-$-2 ;byte count
db CTC0 ;CTC0 control port
db 00100111b ;put CTC0 in timer mode
db 105 ;with period=105*256*0.4 us
t2end: equ $ ;(=10752 us)
; initialize CTC1
db t3end-$-2 ;byte count
db CTC1 ;CTC1 control port
db 11000111b ;put CTC1 in counter mode
db 93 ;with period=93*10752 us
t3end: equ $ ;(=1sec) & interrupt enabled
; initialize SIO receive section
; (separated to facilitate initialization in self test mode)
db t4end-$-2 ;byte count
db siocpa ;SIO-A control port
db 3 ;WR3
db 1101$0001b ;rx parameters + rx enable
t4end: equ $
db -1 ;end of table marker
; *************************
; * global variables *
; *************************
rxstat db 0 ;rx status flags
txstat db 0 ;tx status flags
tistat db 0 ;timer status flags
txaddr db 0 ;tx address byte
txctrl db 0FFh ;tx control byte
; system timers (must be contiguous)
t1ct: db 0 ;level 2 timer T1 count
t20ct: db 0 ;level 3 timer T20 count
t21ct: db 0 ;level 3 timer T21 count
t22ct: db 0 ;level 3 timer T22 count
t23ct: db 0 ;level 3 timer T23 count
; level 1 diagnostic counters
rxbfct dw 0000h ;bad received frames
rxgfct dw 0000h ;good received frames
rxbbct dw 0000h ;chars lost due to buffers not avail
rxboct dw 0000h ;chars lost due to buffer overrrun
rxcect dw 0000h ;received crc errors
rxoect dw 0000h ;receive overrun errors
rxabct dw 0000h ;received aborts
txefct dw 0000h ;tx end of frame count
txuect dw 0000h ;tx underrun errors
txabct dw 0000h ;transmitted aborts