mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
359 lines
11 KiB
Plaintext
359 lines
11 KiB
Plaintext
|
||
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
|
||
|
||
|
||
|