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

767 lines
16 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.

;*****************************************************
;*
;* Character I/0 Routines
;*
;*****************************************************
;===========
cmode_entry: ;Get/Set Console Mode
;===========
;
; entry: DX = 0FFFFH if returning current value
; else DX = new console mode word
; return: BX = console mode if DX = 0FFFFH on entry
;
mov bx,rlr
inc dx ! jz cm_get
dec dx
mov p_conmode[bx],dx
xor bx,bx
ret
cm_get:
mov bx,p_conmode[bx]
ret
;===========
conin_entry: ;Function 1:console input
;===========
call coninit
call coninf ;char in AL and BL
mov dl,al ;PIN handles control chars
co_notp:
call echoc ! jb ciexit ;check nonprint char
call tabout ;echo character - if printable
ciexit:
mov bl,dl ! ret
;============
conout_entry: ;Function 2:console output - DL = char
;============
call coninit
test p_conmode[bx],pcm_rout ;BX=RLR PD
jz co_tab
jmp conoutf
co_tab:
jmp tabout
;============ ;internal only under CCP/M
rconin_entry: ; raw console input
;============
call rawinit
jmp coninf ;returns char in AL and BL
;============= ;internal only under CCP/M
rconout_entry: ; raw console output - DL = char
;=============
call rawinit
rconout:
jmp conoutf
;=============
listout_entry: ; write to list device - DL = char
;=============
mov bx,rlr ! mov dh,p_lst[bx]
mov si,u_lstccb
push dx ! call lstattach_entry ! pop dx
jmp listf
;=============
constat_entry: ;check console status
;=============
call coninit ;console mode is made "cooked"
call cse_cl
test bl,bl ! jz co_r ;BL=1 if char ready
mov di,rlr
test p_conmode[di],pcm_11
jz co_r
call coninf ;read the char
cmp al,ctlc ! jne co_nc ;want only control C
mov c_nchar[si],bx ;all 16 bits
mov bl,1
co_r:
ret ;return BL=0 or 1
co_nc:
xor bl,bl ! ret ;char not a ^C
;=======
ciostat: ; check status w/out changing pf_raw
;=======
mov bx,rlr
mov dh,p_cns[bx]
mov si,u_conccb
test si,si ;U_CONCCB=0 if no attach yet
jz cse_no
cmp bx,c_attach[si]
je cse_cl
cse_no:
mov cl,f_dispatch ! call osif
mov bl,0 ! ret
cse_cl:
call constf
test bl,bl ! jz cse_c2
mov bl,1
cse_c2:
mov al,bl ! ret
;===========
dirio_entry: ;function 6
;===========
; direct console i/o - read if 0ffh
; entry: DL = 0ffh if readif (ret=0 on not ready, else char)
; = 0feh if status (ret=0 not read or 0ffh if ready)
; = 0fdh if input (wait there is a character)
; = char to output
; exit: BL = 0, 0ffh or character if status or input
call rawinit
cmp dl,0fdh
jb rconout ;output DL
ja diosts
jmp coninf ;DL=0FDh, get char
diosts: ;some type of status
call constf
cmp dl,0feh ! jne diocin ;DL=0FEh, return status
dio1:
ret ;BL=0FFh or 0h
diocin:
test bl,bl ! jz dio1 ;DL=0FFh, if char,conin
jmp coninf
;==============
conwrite_entry: ;write line until delimiter in UDA encountered
;============== ;user function 9, delimiter set by function 110
;
; input: DX = buffer addr in u_wrkseg
push dx
call coninit
pop bx
cwr1: push ds ! mov ds,u_wrkseg
mov dl,[bx] ! pop ds
cmp dl, u_delim ! je cwr_e
push bx
mov bx,rlr
test p_conmode[bx],pcm_rout ! jz cw_tab
call conoutf ! jmps cw_notab
cw_tab:
call tabout
cw_notab:
pop bx
inc bx ! jmps cwr1
cwr_e: ret
;===========
delim_entry: ;get/set output delimiter, user function 110
;===========
;
; entry: DX = 0FFFFH if returning current delimiter
; else DL = new delimiter
; return: BL = delimiter if DX = 0FFFFH on entry
cmp dx,0FFFFH ! jz d_get
mov u_delim,dl
ret
d_get:
mov bl,u_delim
ret
;=============
p_block_entry:
;=============
; entry: DX = CB addr where 1st word is offset,
; 2nd word is segment, 3rd word
; is length
; return: None
push dx
call coninit ;BX=PD address
pop di
xor ax,ax
mov bp,p_conmode[bx]
jmps block_out
;=============
l_block_entry:
;=============
; return: None
; entry: DX = CB addr where 1st word is offset,
; 2nd word is segment, 3rd word
; is length
push dx
call lstattach_entry
pop di
mov bx,rlr ! mov dh,p_lst[bx]
mov ax,0ffffh
;jmps block_out
;SI -> CCB or LCB (in XIOS)
block_out: ;u_wrkseg:DI -> user's parameter block
;DH=list or console device number
;AX = 0 if console, 0FFFFH if list
push ds ! mov ds,u_wrkseg
mov cx,cb_len[di] ;CX = string length
mov bx,cb_seg[di]
mov di,cb_off[di] ;BX:DI = string start
pop ds
test cx,cx ! jz b_ret ;test for zero length
b_loop: ;BX:DI -> string to print or list
;AX = 0 if to console = 0FFFFH if to list
;BP = p_conmode if going to console
push ds ! mov ds,bx
mov dl,[di]
pop ds
push bp ! push di ! push cx ! push bx ! push ax
test ax,ax ! jz b_con
call listf ! jmps nb_nxt
b_con:
test bp,pcm_rout ! jnz nb_nt ;raw output mode ?
call tabout ! jmps nb_nxt ;test for ctrlP ?
nb_nt:
call conoutf
nb_nxt:
pop ax ! pop bx ! pop cx ! pop di ! pop bp
inc di
loop b_loop
b_ret:
ret
;==============
conprint_entry: ;write line until delimiter or max
;============== ;mask parity, do not check for ctrl chars
;
; input: DX = address of buffer in u_wrkseg
; BH = max characters (0=no max)
; BL = delimiter character
push bx ! push dx
call coninit
pop bx ! pop ax
xor cx,cx
and al,07fh
; AH=max, AL=delimiter, BX->buffer
; CX = count = 0
cpr1: cmp ah,0 ! je cpr2
cmp ah,cl ! je cpr_e
cpr2: push ds ! mov ds,u_wrkseg
mov dl,[bx] ! pop ds
and dl,07fh
cpr3: cmp dl,al ! je cpr_e
push ax ! push cx ! push bx
call conoutf
call chk_ctrlP
pop bx ! pop cx ! pop ax
inc cl ! inc bx
jmps cpr1
cpr_e: ret
;=============
conread_entry: ;read a buffered console line
;=============
; buffer=(max length, current length, buffer)
push dx
call coninit
pop bx
read: push bx ;[SP] = buffer offset
mov al,c_column[si]
mov c_strtcol[si],al ;start column = current column
xor bx,bx ;BX = character count
;read next character, CX, BX active
readnx: push bx
readn0: call coninf ;AX, BX = 16 bit char just read
mov dl,al
pop bx
; Carriage Return
cmp dl,cr ! jnz notcr
eofre: jmp readen
notcr:
; Line Feed
cmp dl,lf ! jz eofre
tryh: ; Backspace
cmp dl,ctlh ! jnz noth
or bl,bl ! jz readnx ;if not 1st char
dec bl ! mov al,c_column[si] ;decrement char count
mov c_btmp[si],al ;temporary hold
or c_flag[si],cf_compc ! jmp linelen
noth:
; Rubout
cmp dl,rubout ! jnz notrub
or bl,bl ! jz readnxx ;only if not 1st char
pop di ! push di
push ds ! mov ds,u_wrkseg
mov dl,1[di+bx] ! pop ds ;make char=last char
dec bx ;dec char count
jmp rdech1 ;echo, read next
readnxx: jmp readnx
notrub:
; Control E
cmp dl,ctle ! jnz note
push bx
mov dl,cr ! call conoutf
mov dl,lf ! call conoutf
mov c_column[si],0
mov c_strtcol[si],0
jmp readn0
note:
; Control X
cmp dl,ctlx ! jnz notx
backx: mov al,c_strtcol[si]
cmp al,c_column[si] ! jb backxxx
xor bx,bx ! jmps readnxx
backxxx: mov dl,ctlh ! call conoutf
mov dl,' ' ! call conoutf
mov dl,ctlh ! call conoutf
dec c_column[si]
jmps backx
notx:
; Control U
cmp dl,ctlu ! jnz notu
call crlfp
pop bx ! jmp read
notu:
; CONTROL R - redraw line
cmp dl,ctlr ! jnz notr
linelen: push bx ! call crlfp
;print buffer on screen
pop cx ! xor bx,bx
rep0: or cl,cl ! jz rep1
pop di ! push di
push ds ! mov ds,u_wrkseg
inc bx ! dec cl
mov dl,1[di+bx] ! pop ds ;DL = nxt char
mov ch,bl ! push cx
call ctlout
pop cx ! mov bh,0 ! mov bl,ch
jmps rep0
rep1: test c_flag[si],cf_compc
push bx ! jz l_22
and c_flag[si],not cf_compc
mov ah,c_btmp[si] ! mov al,ah
backsp: cmp al,c_column[si]
jb l_22
sub al,c_column[si]
or al,al ! jz l_22
push ax
mov dl,ctlh ! call conoutf
mov dl,' ' ! call conoutf
mov dl,ctlh ! call conoutf
pop ax ! dec ah ! mov al,ah
jmps backsp
l_22: jmp readn0
notr:
; All other characters
rdecho: inc bx
pop di ! push di
push ds ! mov ds,u_wrkseg
mov 1[di+bx],dl ! pop ds
rdech1: push bx ! call ctlout ! pop bx
pop di ! push di
push ds ! mov ds,u_wrkseg
cmp bl,[di] ! pop ds ! jae readen
push bx ! jmps l_22
; End of Console String
readen: pop di
push ds ! mov ds,u_wrkseg
mov 1[di],bl ! pop ds
mov dl,cr ! call conoutf
mov c_column[si],0
ret
rawinit:
;-------
mov bx,rlr ;turn on raw flag
or p_flag[bx],pf_raw
jmps ninit
coninit:
;-------
; entry: DL = char if called by output routine
; exit: DH = console device number
; BX = RLR PD - raw flag turned off
; SI = CCB owned by calling PD
mov bx,rlr ;turn off raw flag
and p_flag[bx],not pf_raw
ninit:
mov dh,p_cns[bx]
mov si,u_conccb
test si,si ! jz attach
cmp c_attach[si],bx
jne attach
ret
attach:
; exit: SI=CCB
; BX,DX preserved
push bx ! push dx
call conattach_entry
pop dx ! pop bx
ret
echoc:
;-----
; check if character is graphic
; input: DL = character
; DH = console #
; SI = CCB address
; output: carry set if not graphic
; DL,DH,SI pass through
cmp dl,cr ! je ret0
cmp dl,lf ! je ret0
cmp dl,tab ! je ret0
cmp dl,ctlh ! je ret0
cmp dl,' '
ret0: ret
prcsmsg:
;-------
; print string in Code Segment
; input: DX->null terminated string in CS
xor bx,bx ! mov ax,cs
prstr: push u_wrkseg
mov u_wrkseg,ax
call conprint_entry
pop u_wrkseg ! ret
prname:
;------
; print name
; input: DX->8 char name in DS
mov bh,8 ! mov bl,' '
mov ax,ds ! jmps prstr
conout:
;------
; compute character position/write console
; input: DL = character
; DH = console #
; SI = ccb address
; output: DL = character
; DH = console #
; SI = ccb address
;check if only calculating column position
test c_flag[si],cf_compc ! jnz compout
;write the character, then compute column.
call conoutf
mov bx,rlr
test p_conmode[bx],pcm_rout
jnz co_np
call chk_ctrlP ;printer echo handling
co_np:
;compute column position
compout:
mov al,c_column[si]
cmp dl,rubout ! je ccret
inc al
cmp dl,' ' ! jae ccret
dec al
or al,al ! jz ccret
cmp dl,ctlh ! jnz notbs
dec al ! jmps ccret
notbs: cmp dl,cr ! jne ccret
mov al,0
ccret: mov c_column[si],al
ret
chk_ctrlP:
;---------
; Entry: SI=CCB address
; DH=console device number
; DL=character just sent to console
; Exit: SI,DX preserved
; Echo the character to the printer if the ctrlP flag is set
; in the CCB, and the ctrlO flag is off, and the cf_bufp
; flag is off. Cf_bufp is set when we send a character
; to a VOUT process when we are a background buffered
; console. The VOUT process decides whether to send the
; character to the screen when it purges the buffered output.
mov ax,c_state[si]
test ax,csm_ctrlP
jz cp_ret
test ax,csm_ctrlO
jnz cp_ret
mov al,c_flag[si]
test al,cf_bufp
jz cp_listit
and c_flag[si],not cf_bufp ;turn off the flag
jmps cp_ret
cp_listit:
push dx ! push si
mov dh,c_mimic[si]
cmp dh,0ffh ;mimic = 0ffh if
je cp_no ;PIN turned off ^P
call listf
cp_no:
pop si ! pop dx
cp_ret:
ret
ctlout:
;------
; send CTRL character with possible preceding up-arrow
; input: DL = character
; DH = console #
; SI = ccb address
; output: DL,DH = character,console
; SI = ccb address
call echoc ! jae tabout
push dx ! mov dl,ctl ! call conout
pop dx ! or dl,40h
; jmp tabout
tabout:
;------
; expand tabs to console
; input: DL = character
; DH = console
; SI = ccb address
; output: DL,DH = char,console
; SI = ccb address
cmp dl,tab ! je tab1
jmp conout
tab1:
mov dl,' '
tab0: call conout
mov al,c_column[si]
and al,111b ! jnz tab0
mov dl,tab
ret2: ret
crlf:
;----
push dx ! mov dl,cr ! call conout
mov dl,lf ! call conout ! pop dx
ret
crlfp:
;-----
; print #, cr, lf for ctlx, ctlu, ctlr functions
; then print ' ' until we are at strtcol (starting column)
; input: DH = console
; SI = ccb address
; output: DH = console
; SI = ccb address
mov dl,'#' ! call conout
call crlf
mov dl,' '
crlfp0: mov al,c_column[si]
cmp al,c_strtcol[si] ! jae crlfp1
call conout ! jmps crlfp0
crlfp1: ret
;
; XIOS CHARACTER I/O INTERFACE
;
; XIOS CONSTAT CALL
;
; entry: DH = console #
; SI = ccb address
; returns:DH = console #
; SI = ccb address
; AX = BX = 0 if no char, = 0FFH if char ready
constf:
cmp dh,ncns ;if not VC goto XIOS
jb cst_vc
mov al,io_const
jmp goxios
cst_vc:
xor bx,bx
cmp c_nchar[si],bx
jne cst_true
mov di,c_vinq[si]
cmp q_msgcnt[di],bx ;number of chars in type ahead
je cst_ret ;queue
cst_true:
mov bl,0ffh ;char ready
cst_ret:
mov al,bl
ret
; XIOS CONIN CALL
;
; entry: DH = console #
; SI = ccb address
; returns:DH = console #
; AL = BL = character
; SI = ccb address
;
coninf:
cmp dh,ncns ;if not VC goto XIOS
jb ci_vc
mov dl,c_pc[si] ;io_conin needs physical console #
mov al,io_conin
jmp goxios
ci_vc:
cmp c_nchar[si],0
jne ci_gotc
mov cx,f_qread
call csi_readq
ci_gotc:
mov bx,c_nchar[si]
mov ax,bx
mov c_nchar[si],0
ret
csi_readq:
push dx ! push si
mov ax,c_vinq[si]
mov c_qpbqaddr[si],ax
lea ax,c_nchar[si]
mov c_qpbbuffptr[si],ax
lea dx,c_qpbflags[si]
call osif
pop si ! pop dx
ret
; XIOS CONOUT CALL
;
; entry: DH = console #
; DL = character
; SI = ccb address
; exit: DH = console #
; SI = ccb address
conoutf:
cmp dh,ncns ;if not VC goto XIOS
jb co_vc
mov al,io_conout ;console number
jmp goxios ;control C could hang up this
co_vc: ;hardware, should handle similar
pushf ! cli ;to virtual screens
mov ax,c_state[si]
mov bx,ax
and ax,not(csm_ctrlP + csm_ctrlO + csm_noswitch + csm_suspend)
cmp ax,2 ;0=foreground&dynamic, 1=foreground&
jbe co_getconout ;buffered, 2=background&dynamic
cmp ax,csm_buffered + csm_background
je co_buffer
;sleep on all other states
push dx ! push si ;and wait for the PIN or
lea dx, c_usleep[si] ;VOUT to wake us up
mov bl, ps_ciowait
mov cx, f_sleep
call osif
pop si ! pop dx
popf
jmps co_vc ;start over, state could
;have changed
co_buffer: ;Virtual Console is in some type of buffered state
popf ;allow interrupts
or c_flag[si],cf_vout+cf_bufp ;VOUT we are writing a msg.
;If we switch screens, and VOUT
;just finishes purging, VOUT
;will wait for this message.
;Turn on cf_bufp so we don't
;echo to the printer if ctrlP is on
mov ax,c_voutq[si]
mov c_qpbqaddr[si],ax
lea ax,c_qbuff[si] ;points to 2-byte message
mov c_qpbbuffptr[si],ax
push dx ! push si
xor dh,dh ;DL = data, DH = data msg type (0)
mov c_qbuff[si],dx
lea dx,c_qpbflags[si]
mov cx, f_qwrite
call osif
pop si ! pop dx
and c_flag[si],not cf_vout ;tell VOUT we're done writing
ret ;message
co_getconout:
test bx,csm_ctrlO ;BX = ccb.state
jz co_cbitsget ;famous racehorse
popf ! ret ;ctrl O byte bucket
co_cbitsget: ;output is going to XIOS,
;ensure no other process
test c_flag[si],cf_conout ;is in XIOS console output code
jz co_gotconout ;for this screen
co_conoutsleep:
push dx ! push si
lea dx, c_cosleep[si]
mov bl, ps_ciowait
mov cx, f_sleep
call osif
pop si ! pop dx
popf
jmp co_vc ;start over, state
;could have changed
co_gotconout:
or c_flag[si], cf_conout ;set XIOS conout "ownership" flag
popf ;allow interrupts
mov bx,rlr
push p_flag[bx] ;save flags
or p_flag[bx],pf_tempkeep ;don't allow abort
push bx
mov ax,io_conout ;XIOS function number
call goxios
and c_flag[si], not cf_conout ;wake any process wanting XIOS
cmp c_cosleep[si],0 ;test here for faster output
je co_nowake
push dx ! push si
mov cx,f_wakeup
mov bl,ps_ciowait
lea dx,c_cosleep[si]
call osif
pop si ! pop dx
co_nowake:
pop bx ;process address
test p_flag[bx],pf_ctlc ;was ^C typed ?
pop p_flag[bx] ;restore PD flags
jz co_xret
or p_flag[bx],pf_ctlc
push dx ! push si
xor dx,dx
mov cx,f_terminate
call osif ;returns here if keep flg is on
pop si ! pop dx
co_xret:
ret
; XIOS LIST OUT CALL
;
; entry: DH = console #
; DL = character
; SI = ccb address
; exit: DH = console #
; SI = ccb address
listf:
mov ax,io_list
;jmps goxios
goxios:
push dx ! push si
mov cl,dl ! mov dl,dh ;CL = char, DL = device
call xiosif
pop si ! pop dx
ret