.ENABL LC .title PRMDRV, prom programmer driver, version 1 .sbttl constant definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ** constants ** ; ;REC standard DLV-11J configuration, line printer port, SLU 1 ARCSR=176560 ;addrs of receiver CSR ARVEC=360 ;address of receiver interrupt vector ;VA minc, to channel (slu) 0, 9600 baud ; ARCSR=176500 ;addrs of receiver CSR ; ARVEC=300 ;address of receiver interrupt vector RCSR=ARCSR ;addrs of receive control status register RBUF=ARCSR+2 ;addrs of receive buffer RVEC=ARVEC ;receive ISR vector XCSR=ARCSR+4 ;addrs of transmit control status register XBUF=ARCSR+6 ;addrs of transmit buffer XVEC=ARVEC+4 ;transmit ISR vector ENAINT=100 ;interrupt enable code ; RBSIZ=100. ;receiver buffer size MAXR=90. ;maximum # of nibbles in input buffer ;after which ^S xmitted MINR=10. ;minimum # of nibbles in input buffer ;after which ^Q sent, i.e. if a ^S ;was sent previously (this is determined ;by the STOP flag being true) ; XBSIZ=100. ;xmit buffer size CTRLS='S-100 ;control S CTRLQ='Q-100 ;control Q TRUE=1 ;value if flag is true FALSE=0 ;value if flag is false ; ;codes returned by PPIN RCVERR=-1 ;UART receiver framing or overrun error ;or input buffer data overrun NODATA=0 ;no data received from PP SUCCES=1 ;one byte returned successfully ;----------------------------------------------------------- ; To test for framing, parity and overrun errors on the ;host UART, leave the following line uncommented, else if ;commented, these errors will not be tested for. TRERR=TRUE ;uncomment to test for HOST ;UART receiver errors ;----------------------------------------------------------- ; To transmit data slowly to PP leave defined. ;To xmit at maximum rate, leave undefined. ;SLOW=32000 ;range 0<=SLOW<=64K ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; to allow use of 'CALL X' in place of 'JSR PC,X' ; .macro call subr ; jsr pc,subr ; .endm ; .page .sbttl data section .psect ppcode stop: .word ;=TRUE if host sent ^S to stop xmission ;from programmer, else =FALSE to indicate that ;xmission is enabled. rhead: .word ;pointer to head of input circular buffer rtail: .word ;pointer to tail of input circular buffer rcount: .word 0 ;# of bytes currently on input circ bufr rcbuf: .blkb RBSIZ ;input circular buffer rerr: .word ;=RCVERR if receiver parity or framing error occured, ;else =0 if no error occured. ; xhead: .word ;pointer to head of output circular buffer xtail: .word ;pointer to tail of output circular buffer xcount: .word 0 ;# of bytes currently on output circ bufr xcbuf: .blkb XBSIZ ;output circular buffer xiena: .word .page .sbttl PPMINI initialization code ; ; subroutine ppmini ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PPMINI is an initialization subroutine that may be called to reset ;the status of communications between the PP and the HOST computer. ;This routine must be called before any other commands are transmitted ;and may be called from a FORTRAN program to reset the ;host software. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ppmini:: ;transmitter initialization clr @#XCSR ;disable interrupts clr xiena ;transmit interrupts not enabled mov #xisr,@#XVEC ;load xmit vector ISR addrs mov #140,@#XVEC+2 ;load xmit vector priority mov #xcbuf,xhead ;reset output circ bufr pointer mov #xcbuf,xtail ; " clr xcount ;clear char count ;receiver initialization clr stop ;receiver not halted mov #risr,@#RVEC ;load recv vector ISR addrs mov #140,@#RVEC+2 ;load recv vector priority mov #rcbuf,rhead ;reset input circ bufr pointer mov #rcbuf,rtail ; " clr rcount ;clear char count tstb @#RBUF ;remove any waiting input character movb #ENAINT,@#RCSR ;enable receiver interrupts if no errors return ; .page .sbttl XISR - transmitter interrupt service routine ; ; XISR - transmitter interrupt service routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The transmit interrupt service routine takes bytes to be ;sent to the PP off of the transmit circular buffer and stores them ;in the output buffer of the DLV-11J for serial transmission. ; 1) If the transmit output data buffer becomes empty ; data cannot be sent (obviously) and transmit ; interrupts will not be reenabled. ; 2) When a byte is transmitted, if there is no more ; data remaining to be transmitted, the routine will ; NOT reenable interrupts. ; 3) The flag XIENA is set to true when transmit interrupts ; are enabled, else it is set to false. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xisr: clr @#XCSR ;disable xmit interrupts tst xcount ;any data left to send? beq 20$ ;no ;yes, send next byte. movb @xtail,@#XBUF ;load next byte from out Q into output ;of transmitter register inc xtail ;inc in bufr pointer cmp xtail,#xcbuf+XBSIZ ;bufr pointer overflow? blo 10$ ;no mov #xcbuf,xtail ;yes, reset out circ bufr pointr 10$: dec xcount ;dec count of # of bytes on output Q beq 20$ ;no more to xmit, don't interrupt again mov #TRUE,xiena ;indicate xmit interrupts ARE enabled movb #ENAINT,@#XCSR ;enable interrupts rti ; 20$: clr xiena ;indicate xmit interrupts NOT enabled rti ;return w/o reenabling interrupts .page .sbttl PPX FORTRAN callable byte transmit subroutine ; ; subroutine PPX(outdat,outsiz) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Transmits an arbitrary length byte string to the PP. The string ;is passed in the byte vector OUTDAT and is assumed to store ;OUTSIZ # of characters. OUTSIZ is a 16 bit integer. ; The primary purpose of this routine is to load data ;to be transmitted onto the output circular buffer, and to try ;to keep interrupts enabled as much as possible. ; NOTE-The first operation should be to initialize the PP. ; This routine uses and modifies registers r0 and r1. ;The subroutine PPXI is the MACRO entry point and the registers ;are defined as follows: ; r0 = # of bytes to xmit ; r1 = addrs of first byte to xmit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ppx:: mov @4(r5),r0 ;# of bytes to xmit in r0 mov 2(r5),r1 ;addrs of first byte to xmit ppxi: ;MACRO entry point tst r0 ;any more characters to xmit? beq 30$ ;no ;----------------------------------------------------------- ; If want to transmit data slowly, define ;SLOW, and the value defines the number of loop iterations in the ;time wasting loop below. .IF DF SLOW ;conditional assembly of this code mov r4,-(sp) ;preserve counter register mov #SLOW,r4 ;store loop count in reg 7$: dec r4 ;decrement count bpl 7$ ;wait till 0 mov (sp)+,r4 ;then restore register, continue .ENDC ;end of conditional assembly block ;----------------------------------------------------------- cmp xcount,#XBSIZ ;is output buffer full? bge 20$ ;yes, try to re-enable interrupts and ;do not add to output bufr ;else movb (r1)+,@xhead ;mov byte from in list to in bufr inc xhead ;inc bufr pointer cmp xhead,#xcbuf+XBSIZ ;bufr pointer overflow? blo 10$ ;no mov #xcbuf,xhead ;yes, reset in circ bufr pointr 10$: inc xcount ;inc count of # of bytes on out bufr dec r0 ;dec count of bytes to xmit ; 20$: cmpb xiena,#TRUE ;waiting on previous tranmit request? beq ppxi ;xmit interrupts enabled, try to add ;to output bufr mov #TRUE,xiena ;indicate xmit interrupts enabled movb #ENAINT,@#XCSR ;set int's on xmit CSR br ppxi ; ; 30$: return ;exit from this point when no more ;data to be sent .page .sbttl RISR - receiver interrupt service routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; The DLV-11J receiver register is defined as follows: ; ; bits description ; --------------------------------------------------- ; 0-8 data byte from PP ; 9-11 not used ; 12 parity error ; 13 framing error ; 14 overrun error ; 15 error ; ; All lines data sent from the PP is buffered be lines and ;each line is terminated with a carriage return and a line feed. ;The receiver interrupt service routine buffers input data without ;regards to what is being xmited, and further transmits either ;CTRLS or CTRLQ as needed in order to regulate data xmit from the PP ; ; If the host input buffer has more than MAXR characters, ;then a ^S is sent to the PP to halt transmission, and ;this is done within the Receiver interrupt service routine. ;When a ^S is sent to the PP, the flag is set to true. ;Thereafter it is the responsibility of other routines to send ;a ^Q to the PP so that more data can be received. The ^Q ;is sent to the PP when MINR bytes being used on the input ;buffer. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; risr: clr @#rcsr ;disable interrupts mov r0,-(sp) ;save r0 .if ndf TRERR ;if NO test for receiver errors movb @#rbuf,r0 ;store input byte in r0 .endc ; .if df TRERR ;test for host UART receiver errors mov @#rbuf,r0 ;store receiver word in temp bit #170000,r0 ;data receiver error? ;test all condition codes in recv reg beq 10$ ;no error mov #RCVERR,rerr ;set error flag to indicate a receiver error ;has occured. Flag will be tested by PPIN ;subroutine .endc ; 10$: inc rcount ;inc receive buffer count cmpb #MAXR,rcount ;is input bufr getting too full? bgt 20$ ;no movb #CTRLS,@#XBUF ;send ^S to AWG to stop xmission mov #TRUE,stop ;indicate xmit from AWG is halted cmp #RBSIZ,rcount ;test for input buffer overflow error bge 20$ ;no overflow error mov #RCVERR,rerr ;overflow error!! 20$: movb r0,@rhead ;load byte onto the intput queue inc rhead ; cmp rhead,#rcbuf+RBSIZ ;pointer overflow? blo 30$ ;no mov #rcbuf,rhead ;yes, reset queue pointer 30$: mov (sp)+,r0 ;restore r0 movb #ENAINT,@#RCSR ;enable receiver interrupts rti ; .page .sbttl PPIN FORTRAN or MACRO callable byte receive subroutine ; ; integer function ppin(nxtbyt) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PPIN reads the next byte of data from the circular ;input buffer and returns the byte in the byte variable NXTBYT. ;The function also returns a status in r0 as follows: ; ; code return PPIN | description ; -------------------|------------------------------------- ; RCVERR=-1 | UART receiver framing or overrun error ; | or input buffer data overrun ; NODATA=0 | no data received from PP ; SUCCES=1 | one byte returned successfully ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ppin:: clr @2(r5) ;if status not equal to 1, then fix ;value of variable NXTBYT returned to caller tst rerr ;a recent receiver error? beq 10$ ;no receive error clr rerr ;reset error flag till next error clr rcount ;flush receiver input buffer mov rhead,rtail ;reset circ bufr pointers mov #RCVERR,r0 ;indicate receive error return ;return to caller ; 10$: tst rcount ;test if byte received from PP bne 15$ ;word received, get it, else mov #NODATA,r0 ;no data received yet br 30$ ;see if xmit from PP halted 15$: movb @rtail,@2(r5) ;get byte off of input queue inc rtail ;bump queue pointer cmp rtail,#rcbuf+RBSIZ ;input buf pointer overflow? blo 20$ ;no mov #rcbuf,rtail ;reset input buf pointer 20$: dec rcount ;dec count of nibbles on input queue mov #SUCCES,r0 ;indicate data returned by routine 30$: tst stop ;is xmit from PP halted? beq 40$ ;no cmpb #MINR,rcount ;input buffer still too full? blt 40$ ;yes, wait before enabling data send clr stop ;indicate xmit from PP not stopped movb #CTRLQ,@#XBUF ;send ^Q to reenable data transmission from PP 40$: return ; .page .sbttl PPSTP - FORTRAN callable exit routine ; ; subroutine ppstp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This subroutine waits for I/O operations to complete ;and then disconnects the interrupt vectors, and sets the ;initialization flag so to force initialization if any of ;the routines are called again. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ppstp:: 10$: tst xcount ;is transmit queue empty? bne 10$ ;if not wait clr @#RCSR ;disable receiver interrupts ;xmit interrupts already disabled return ; .end