Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,359 @@
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