mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 01:14:21 +00:00
335 lines
9.7 KiB
Plaintext
335 lines
9.7 KiB
Plaintext
|
||
title 'Serial Input module'
|
||
|
||
;*****************************************
|
||
; *
|
||
; SERIAL INPUT MODULE *
|
||
; Last change : 2/13/84 *
|
||
; *
|
||
;*****************************************
|
||
|
||
include system.lib
|
||
include chrcomm.equ
|
||
include serdata.equ
|
||
|
||
cseg
|
||
|
||
public serial_in
|
||
public store_char
|
||
|
||
extrn supif:near ;; headentr.a86
|
||
extrn ocdesctbl:word ;; serdata.a86
|
||
extrn usart_on:near
|
||
extrn xmit_on:near ;; servar.a86
|
||
extrn xmit_off:near ;; servar.a86
|
||
extrn set_bit:near ;; servar.a86
|
||
extrn clear_bit:near ;; servar.a86
|
||
|
||
serial_in:
|
||
;-----
|
||
; ENTRY: bx = addr of the input Q control block
|
||
;
|
||
; EXIT: al = data from the usart's Q
|
||
; ah = the usarts status byte
|
||
|
||
pushf ! cli
|
||
|
||
cin2: ;; if char is available, get it
|
||
test Q_STATE[bx], CHAR_AVAIL ;; else flagwait until it's available
|
||
jnz cin1
|
||
or Q_STATE[bx], IPROC_WAITING ;; set a loacal proc waiting flag
|
||
push bx ;; save the address of Q control struc
|
||
mov dl, SYS_FLAG[bx] ;; do the flag wait
|
||
mov cl, F_FLAGWAIT
|
||
call supif
|
||
cmp ax, 0ffffh ! jne cin3 ;; was there an error ?
|
||
mov cl, P_DISPATCH ;; dispatch the process, let it try
|
||
call supif ;; again later
|
||
cin3:
|
||
pop bx ;; get back the Q control structure
|
||
jmps cin2 ;; just in case the flagset shouldn't
|
||
;; have happened.
|
||
cin1:
|
||
push bx ;; save the Q control structure
|
||
call conin_fc ;; call the console read routine
|
||
pop bx ;; restore the Q control addr
|
||
mov al, LAST_CHAR[bx] ;; al = char from Q
|
||
mov ah, LAST_STAT[bx] ;; ah = status from Q
|
||
popf ;; turn the interrupts back on
|
||
ret
|
||
|
||
|
||
|
||
conin_fc:
|
||
;;--------
|
||
;; This routine reads a character from the console input Q
|
||
;;
|
||
;; ENTRY: bx -> the Q control structure
|
||
;;
|
||
;; EXIT: LAST_CHAR[bx] = the character that was read in
|
||
;; LAST_STAT[bx] = the usart's status that corresponded to the
|
||
;; char in LAST_CHAR[bx]
|
||
|
||
push si ;; we need an index register
|
||
mov si, PROC_OUT[bx] ;; get the Q's output index
|
||
mov al, D_BUFF[bx+si] ;; get the character
|
||
mov LAST_CHAR[bx], al
|
||
mov al, S_BUFF[bx+si] ;; get the status byte
|
||
mov LAST_STAT[bx], al
|
||
inc si ;; inc the processes output index
|
||
and si, (INMSGS -1) ;; mod the size of the Q
|
||
mov PROC_OUT[bx], si ;; restore the index register
|
||
pop si ;; restore the extra index register
|
||
dec UN_PC[bx] ;; dec un-processed char count
|
||
cmp UN_PC[bx], 0 ;; was this the last char in the Q ?
|
||
jne cinf2 ;; no ...
|
||
cinf1:
|
||
and Q_STATE[bx], not CHAR_AVAIL
|
||
cinf2: ;; if sender was stopped check the receive buffer
|
||
;; for being half empty. When the receive buffer is half
|
||
test Q_STATE[bx], SENDER_STOPPED ;; empty restart the sender
|
||
jz cinf3
|
||
cmp UN_PC[bx], ( INMSGS / 2 )
|
||
ja cinf3
|
||
call start_sender ;; the Q is half empty
|
||
cinf3:
|
||
ret
|
||
|
||
|
||
store_char:
|
||
;;----------
|
||
;;
|
||
;; This routine stores the status and data bytes from a usart in their Q's.
|
||
;; It also handles the interrupt level Xon Xoff protocol.
|
||
;; If an error is detected in the status byte returned from the USART
|
||
;; a reset error command is sent to the usart.
|
||
;;
|
||
;; ENTRY: bx -> receive Q control structure
|
||
;; al = the data read from the USART
|
||
;; ah = the status read from the USART
|
||
;;
|
||
;; EXIT: the status and data are put in the status and data Q's.
|
||
;;
|
||
|
||
test Q_STATE[bx], BIT8_MASK ;; are we masking off the 8th bit
|
||
jz try_xon
|
||
and al, 7FH
|
||
try_xon:
|
||
test Q_STATE[bx], XX_MODE ;; is this Q in Xon Xoff mode ?
|
||
jz store_now
|
||
cmp al, XON ! jne try_xoff ;; is the char an Xon
|
||
call xmit_on ;; char was an Xon, start transmitter
|
||
ret
|
||
try_xoff:
|
||
cmp al, XOFF ! jne store_now
|
||
call xmit_off ;; char was an Xoff, stop transmitter
|
||
ret
|
||
store_now:
|
||
push si ;; use SI as an index register
|
||
mov si, INT_IN[bx]
|
||
mov D_BUFF[bx+si], al ;; store the data
|
||
mov S_BUFF[bx+si], ah ;; store the status
|
||
inc si
|
||
and si, (INMSGS - 1)
|
||
mov INT_IN[bx], si
|
||
pop si
|
||
|
||
or Q_STATE[bx], CHAR_AVAIL ;; set char avail flag
|
||
test ah, PARITY_ERR or OVERRUN_ERR or FRAME_ERR;; check for usart errs
|
||
jz no_err ;; if err, send error reset to usart
|
||
inc ERR_CNT[bx] ;; inc the error reset counter
|
||
mov ah, ERROR_RESET ;; set up the error reset bit
|
||
call set_bit ;; now set it in the usarts command register
|
||
and CMD_REG[bx], not ERROR_RESET ;; this is one time command
|
||
;; we have to reset the command
|
||
;; register image, so we don't
|
||
;; keep doing an error reset
|
||
no_err:
|
||
inc UN_PC[bx]
|
||
cmp UN_PC[bx], UPPER_LIM ;; is # chars in buff >= limit ?
|
||
jb check_proc_waiting ;; no
|
||
call stop_sender ;; yes, stop transmitter
|
||
check_proc_waiting:
|
||
test Q_STATE[bx], IPROC_WAITING ;; only do flagset if proc is waiting
|
||
jz no_proc_waiting ;; for a character
|
||
and Q_STATE[bx], not IPROC_WAITING ;; clear the process waiting flag
|
||
push ax ! push bx ! push cx ;; this is an interrupt context
|
||
push dx ! push bp ! push si ;; save the environment
|
||
push di ! push es ! push ds
|
||
sc2:
|
||
mov dl, SYS_FLAG[bx] ;; get the flag number
|
||
mov cl, F_FLAGSET ;; set the system function
|
||
push bx ;; save the Q ptr in case of a retry
|
||
call supif
|
||
pop bx ;; restore the Q ptr
|
||
cmp ax, 0ffffh ;; check for an error
|
||
jne sc3
|
||
cmp cx, 2aH ;; was it a flag ignore ?
|
||
jne sc3 ;; if it was not an ignore just exit
|
||
jmps sc2 ;; else, try again
|
||
|
||
sc3:
|
||
pop ds ! pop es ! pop di ;; restore environment
|
||
pop si ! pop bp ! pop dx
|
||
pop cx ! pop bx ! pop ax
|
||
no_proc_waiting:
|
||
ret
|
||
|
||
|
||
start_sender:
|
||
;;------------
|
||
;;
|
||
;; This routine tries to restart the sender.
|
||
;;
|
||
;; ENTRY: bx = addr Q control structure
|
||
;;
|
||
;; EXIT: none
|
||
;;
|
||
;; NOTE: I have assumed + 12 volts on the DSR or RTS lines means
|
||
;; send data. Conversely - 12 volts means stop
|
||
;; sending data.
|
||
;; The DTR* pin (#24) on the 2651 is wired
|
||
;; to the DSR pin on the DB-25 connector ( pin 6 ),
|
||
;; through an inverting driver. This requires setting
|
||
;; the DTR bit in the command register to start the sender.
|
||
;;
|
||
;; For the RTS protocol, the RTS* pin (23) on the 2651
|
||
;; is wired to the Ready for Send pin on the DB-25
|
||
;; connector ( pin 5 ) through an inverting driver. This
|
||
;; requires setting the RTS bit in the command register
|
||
;; to start the sender.
|
||
|
||
test Q_STATE[bx], DTR_MODE ;; check dtr protocol
|
||
jz try_rts1
|
||
mov ah, DTR ;; force DTR* (dtr not) pin low
|
||
call set_bit
|
||
and Q_STATE[bx], not SENDER_STOPPED
|
||
try_rts1:
|
||
test Q_STATE[bx], RTS_MODE ;; check for RTS protocol,
|
||
jz try_xx1
|
||
mov ah, RTS ;; force the RTS* (rts not) pin low
|
||
call set_bit
|
||
and Q_STATE[bx], not SENDER_STOPPED
|
||
try_xx1:
|
||
test Q_STATE[bx], XX_MODE ;; check for Xon/Xoff protocol
|
||
jz no_prot
|
||
call send_xon
|
||
and Q_STATE[bx], not SENDER_STOPPED
|
||
no_prot:
|
||
ret
|
||
|
||
|
||
|
||
stop_sender:
|
||
;;-----------
|
||
;; This routine tries to stop the transmitter.
|
||
;;
|
||
;; ENTRY: bx = addr( Q control )
|
||
;;
|
||
;; EXIT: none
|
||
;;
|
||
|
||
test Q_STATE[bx], DTR_MODE
|
||
jz try_rts
|
||
mov ah, DTR ;; force DTR* (dtr not) pin high
|
||
call clear_bit
|
||
or Q_STATE[bx], SENDER_STOPPED
|
||
try_rts:
|
||
test Q_STATE[bx], RTS_MODE ;; check for RTS protocol,
|
||
jz try_xx
|
||
mov ah, RTS ;; force the RTS* (rts not) pin high
|
||
call clear_bit
|
||
or Q_STATE[bx], SENDER_STOPPED
|
||
try_xx:
|
||
test Q_STATE[bx], XX_MODE ;; check for Xon/Xoff protocol
|
||
jz no_protocol
|
||
call send_xoff
|
||
or Q_STATE[bx], SENDER_STOPPED
|
||
no_protocol:
|
||
cmp UN_PC[bx], INMSGS ;; If at lim of buffer, adjust char
|
||
jb ss_2
|
||
ss_0:
|
||
dec UN_PC[bx]
|
||
cmp INT_IN[bx], 0
|
||
je ss_1
|
||
dec INT_IN[bx]
|
||
jmps ss_2
|
||
ss_1:
|
||
mov INT_IN[bx], (INMSGS - 1) ;; force index to end of buffer
|
||
ss_2:
|
||
ret
|
||
|
||
send_xon:
|
||
;;--------
|
||
;; This routine sends an Xon to the sender
|
||
;;
|
||
;; ENTRY: bx = addr of Q control sturcture
|
||
;;
|
||
;; EXIT: An Xon ( ctl q ) is sent to the sender
|
||
;;
|
||
test XINT_MASK[bx], SS_U ;; is this the system support board?
|
||
je sxn
|
||
mov ah, XON ;; it's interfacer 3 board
|
||
call send_char
|
||
sxn:
|
||
ret
|
||
|
||
|
||
send_xoff:
|
||
;;---------
|
||
;; This routine sends an Xoff to the sender.
|
||
;;
|
||
;; ENTRY: bx = addr of Q control sturcture
|
||
;;
|
||
;; EXIT: An Xoff ( ctl s ) is sent to the sender
|
||
;;
|
||
test XINT_MASK[bx], SS_U ;; is this the system support board?
|
||
je sxf
|
||
mov ah, XOFF ;; it's the interfacer 3 board
|
||
call send_char
|
||
sxf:
|
||
ret
|
||
|
||
|
||
send_char:
|
||
;;---------
|
||
;; This routine sends a single character to the USART in the Q ctl struct.
|
||
;;
|
||
;; ENTRY: bx = addr Q control structure
|
||
;; ah = char to send
|
||
;;
|
||
;; EXIT: none
|
||
|
||
push bx ;; save the input Q control addr
|
||
mov bl, U_NUMB[bx] ;; get the usart's i3 number
|
||
xor bh, bh ;; clear the upper byte
|
||
inc bx ;; index above the SS usart
|
||
shl bx, 1 ;; indexing into a word table
|
||
mov bx, ocdesctbl[bx] ;; bx -> Output Q control
|
||
|
||
push cx
|
||
push si
|
||
|
||
mov cx, OMSGCNT[bx] ;; get the number of chars in Q
|
||
mov si, omsgout[bx] ;; get the output index
|
||
add si, cx ;; add to it the number of chars
|
||
and si,onmsgs-1 ;; in the buffer, mod( buff size )
|
||
|
||
mov obuffer[bx+si],ah ;; put the char in the Q
|
||
inc cx ;; inc the chars in Q count
|
||
mov omsgcnt[bx],cx ;; update
|
||
|
||
dec cx ;; if 1st char in Q, start Xmit int's
|
||
jnz sc1 ;; cx = chars in Q - 1
|
||
call usart_on ;; start the Xmitter
|
||
sc1:
|
||
pop si
|
||
pop cx
|
||
|
||
pop bx ;; restore the input Q control addr
|
||
|
||
ret
|
||
|
||
end
|
||
|
||
|