Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 3.1 SOURCE/D5/SEROUT.A86
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

359 lines
11 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'Interrupt Serial Output'
;****************************************************************
;* *
;* This module is the invariant part of an interrupt *
;* driven serial output system. *
;* Last Update: 2/14/84 *
;* *
;****************************************************************
include flags.equ
include system.lib
include chrcomm.equ
include serdata.equ
dseg
public dsr_check
public dsr_vec
extrn bit_mask_tbl:byte
extrn ocdesctbl:word
extrn icdesctbl:word
extrn vrtl_phy:byte
cseg
public serial_out
public intco
public dsr_start
extrn supif:near
extrn usart_on:near
extrn usart_off:near
extrn usart_select:near
;;=====
intco: ;; called from ssint.a86,i3int.a86
;;=====
;;
;; ENTRY: bx -> Xmit Q ctl structure
;;
;; OFLAG: 01h - process flag waiting (buf empty)
;; 02h - status ready
;; 10h - Xoff pending
;; 20H - Xon/Xoff mode
;; 80H - RTS protocol support
;;
;; EXIT : AX,BX used.
;; All other registers preserved.
;;
;; Handles the interrupt side of writing a char to the console.
;; It runs in an interrupt context.
push dx ;; port select register
xor dh,dh ;; clear the high byte
mov al, OUSART[bx] ;; get the usart number
cmp al, NO_SELECT ;; does it need a select ?
je no_sel
call usart_select
no_sel:
test OFLAG[bx], XON_XOFF_MODE ;; Is this USART supporting Xon/Xoff protocol ?
jz intco1
test OFLAG[bx], XOFF_PENDING ;; Have we received a stop request?
jnz icoexit ;; yes
intco1:
test OFLAG[bx], RTS_PROT ;; Is this USART supporting RTS protocol
jz intco2
xor dh, dh ;; yes,...
mov dl, OSTPORT[bx] ;; get the status port
in al, dx ;; get the status
mov ah, DSR_BIT[bx] ;; get the DSR bit
test al, ah ;; test the DSR bit of the USART
jnz intco2 ;; bit(7) = 1 if DSR* = 0 volts
call dsr_stop ;; we've gotten a request to stop
jmp icoexit
intco2:
mov dl, OSTPORT[bx] ;; get the status port addr
in al,dx ;; get the USARTS status
mov ah, XMIT_MASK[bx] ;; get the Xmit empty mask
test al, ah ;; is the Xmit buffer empty ?
jz icoexit
;; yes, are there any characters to send ?
push cx ;; save the regs we're going to use
push si
mov cx, OMSGCNT[bx]
cmp cx,0 ;; is there a char to send ?
je icodone
mov si, OMSGOUT[bx] ;; yes, get the output index
mov al, OBUFFER[bx+si] ;; al = char to send
mov dl, OIOPORT[bx] ;; get the USARTS data port
out dx, al ;; send the char
inc si ;; inc the output index
and si, ONMSGS - 1 ;; mod the Queue size
mov OMSGOUT[bx], si ;; save the output index
dec cx ;; dec the chars-to-send count
mov OMSGCNT[bx], cx ;; If there is a proccess waiting for
;; room in this Q, do a flag set for
;; the process when the Q is half empty.
cmp cx, ( ONMSGS / 2 ) ;; is the Q at least half empty ?
ja icodone
test OFLAG[bx], PROC_WAITING ;; yes, is there a process waiting?
jz icodone ;; no,...
push bx ;; save the remaining environment
push bp ;; for the flag set call
push di
push es
intco3:
mov dl, OFLAGN[bx] ;; Get the flag for this Q
mov cl, F_FLAGSET ;; do the flag set
push bx ;; save the Q ptr in case of a retry
call supif
pop bx
cmp ax, ERROR ;; was there an error ?
jne intco4
cmp cx, FLAG_IGNORE ;; yes, was the flag ignored ?
je intco3 ;; yes, try again
intco4:
pop es ;; restore the environment
pop di ;; that was saved for the flag set
pop bp
pop bx
and OFLAG[bx], not PROC_WAITING ;; clear the proc waiting flag
icodone:
pop si ;; restore the context
pop cx
cmp OMSGCNT[bx], 0 ;; More char's to send ?
jne icoexit ;; yes, just return
mov al, OUSART[bx] ;; no, get the usart number
call usart_off ;; turn off usart's transmit system
icoexit:
pop dx
ret
eject
;===========
serial_out:
;===========
;
; ENTRY: cl = character to send out
; bx -> Queue control struct
;
; EXIT: the character is :
; 1] either sent to the USART,
; 2] or put in the output buffer,
; 3] or, the process is flagwaited until there is room
; in the output buffer .
pushf
push bx
cli
push cx ;; save the character
mov cx, OMSGCNT[bx] ;; cx = number of chars in the Q
cmp cx, ONMSGS ;; is there room in the Q ?
jb con1
or OFLAG[bx], PROC_WAITING ;; no, set a local process-waiting flag
pop cx
pop bx
popf ;; turn interrupts back on
push cx ;; save the character
push bx ;; save the Q ctl structure
mov dl,OFLAGN[bx] ;; do the global flagwait
mov cl,F_FLAGWAIT
call supif
cmp ax, ERROR ;; was there an error ?
jne con0
;; It might have been a flag overrun.
mov cl, P_DISPATCH ;; Dispatch the process, and try again.
call supif
con0:
pop bx ;; BX -> Q ctl structure
pop cx ;; restore the char
jmps serial_out
con1: ;; There's room in the Xmit Q.
cmp OESC_CNT[bx], 0 ;; Check the esc count
jz not_esc
push bx
cmp OESC_CNT[bx], 1 ;; Are we at the end of the sequence?
je check_switch ;; Yes, see if PIN is waiting.
check_xy:
cmp OESC_CNT[bx], 3 ;; See if this is a 4-char sequence.
jne dec_esc ;; We're at first or third char.
pop bx ! pop ax
push ax ! push bx ;; AX -> char , BX -> Output Q ctl
cmp ax, 'Y' ;; ESC Y is only 4-char sequence.
je dec_esc
check_switch:
pop bx ! pop ax
mov OESC_CNT[bx], 0 ;; Clear escape count.
call con2 ;; Send the last char in the sequence
xor ah,ah ;; before doing the flag set, if any.
mov al, CUR_VCON[bx]
mov bx,ax
mov bl, vrtl_phy[bx] ;; get the physical console #
xor bh,bh
shl bx, 1
mov bx, icdesctbl[bx] ;; get the Input Q control structure
test Q_STATE[bx],SWITCH_PEND ;; Is PIN waiting for an escape
jz exit ;; sequence to end ?
flag_set:
push bx ! push cx ! push si
xor dh, dh
mov dl, P_CON[bx]
add dl, SWITCH_BIAS ;; Flag # = virtual console + bias
mov cl, f_flagset ;; Wake up the PIN waiting to do
call supif ;; a screen switch.
pop si ! pop cx ! pop bx
and Q_STATE[bx], not SWITCH_PEND
jmps exit
not_esc:
pop ax
call con2
jmps exit
dec_esc:
pop bx ! pop ax
dec OESC_CNT[bx]
call con2
exit:
pop bx
popf
ret
con2: ;; put the character in the Xmit 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],al ;; put it in the Q
inc cx ;; inc Q char count
mov OMSGCNT[bx],cx
;; if 1st char in Q, start USART Xmit
dec cx ;; cx = chars in Q -1
jnz con4
test OFLAG[bx], XON_XOFF_MODE ;; Is it supporting Xon/Xoff protocol ?
jz con3
test OFLAG[bx], XOFF_PENDING ;; Is there an Xoff pending ?
jnz con4
;; The character is in the buffer and
con3: ;; the usart int system is turned off.
call usart_on ;; Start the Usart's Xmitter.
con4:
ret
eject
;===========
dsr_stop:
;===========
; This routine is called when the USART is set to acknowledge the DSR pin
; and the DSR line is high (i.e.,stop sending data).
;
; ENTRY: bx -> Output Q control structure for the USART
; EXIT: The dsr_vec has a bit set for this usart.
; The usart transmitter interrupt system is shut down.
; The dsr_check flag is posted for the tick routine.
; To post this usart in the dsr_vec
mov al, O_BIT_MASK[bx] ; get the bit corresponding to this USART
or dsr_vec, al ; OR it into the DSR vector
mov al, OUSART[bx] ; get the usart number
call usart_off ; and stop the transmitter
mov dsr_check, TRUE ; signal the tick routine to check the
; state of the DSR pin for this usart
ret
;=========
dsr_start:
;=========
; Called by the tick routine when the dsr_check flag = true.
; It looks at the dsr vector to figure out which usart has had its
; transmitter turned off (due to the DSR pin). It then reads the usart's
; status and tests the state of the DSR bit in the status word (bit(7)).
; When this bit is on ,the port we're sending to wants more data. We
; start the transmitter and remove its bit from the dsr_vector. If the
; dsr vector has all its bits cleared, we clear the dsr check flag.
push ax ;; save the environment
push bx
push cx
push dx
dsr_test_lp:
mov al, 0
call usart_select ;; select the usart
mov ah, dsr_vec ;; bit vector of the off Xmitters
dsr_lp_0:
mov bx, offset bit_mask_tbl ;; byte mask for each Xmit interrupt
mov cx, 8 ;; length of bit mask table
dsr_lp:
test ah, [bx]
jz dsr_lp_2
mov al, [bx] ;; found the usart, AND off the bit in
not al ;; dsr_vec
and ah, al
;; CX = USART
mov bx, offset ocdesctbl ;; get base of Xmit Q table
shl cx, 1 ;; times 2 ( word table )
add bx, cx ;; index into the table
mov bx, [bx] ;; bx -> Xmit Q ctl Structure
mov al, OUSART[bx] ;; select the USART
call usart_select
xor dh, dh
mov dl, OSTPORT[bx] ;; get USART's status port
in al, dx ;; read the status
test al, DSR_BIT[bx] ;; check DSR pin - should we turn on
jz dsr_lp_1 ;; the transmitter ?
call usart_on ;; yes, turn on the Usart
mov al, O_BIT_MASK[bx] ;; get the bit
not al ;; make it an AND mask
and dsr_vec, al ;; remove from bit vector
dsr_lp_1:
jmps dsr_lp_0 ;; in case another usart has it's
;; xmitter turned off
dsr_lp_2:
inc bx ;; point to the next mask
loop dsr_lp ;; check all the USARTS
cmp dsr_vec, 0 ;; if dsr_vec is empty, clear dsr_check
jne dsr_st1 ;; flag
mov dsr_check, FALSE
dsr_st1:
pop dx ;; restore the environment
pop cx
pop bx
pop ax
ret
dseg
dsr_check db 0 ; This flag = true when a USART has had its
; transmitter shut down due to the state of
; the dsr pin.
dsr_vec db 0 ; This is a bit vector of the usarts that
; have had their transmitter(s) shut down by
; a reqest from the port they're sending data
; to.
end