Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 2.0 SOURCE/kern/chario.cio
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

774 lines
16 KiB
Plaintext

;*****************************************************
;*
;* 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],ctlc
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 ;AL, BL = 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],bl
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 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 bl,c_nchar[si]
mov al,bl
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)
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