;***************************************************** ;* ;* 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