mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 18:04:07 +00:00
Upload
Digital Research
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user