Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

629 lines
15 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.

;*****************************************************
;*
;* Terminal Message Processor
;*
;* The TMP determines the user interface to CCP/M.
;* Much of the interface is available though
;* system calls. This TMP takes advantage of
;* as much as possible for simplicity. The TMP
;* could, for instance, be easily modified to
;* force logins and have non-standard defaults.
;*
;* With a little more work, the TMP could do all
;* command parsing and File Loading instead of
;* using the CLI COMMAND FUNCTION.
;* Suggestions are given in the CCP/M-86 SYSTEM'S GUIDE.
;*
;*****************************************************
title 'Terminal Message Processor - CCP/M-86 2.0'
; Some common equates
true equ 0ffh
false equ 0
cr equ 13 ; carraige return
lf equ 10 ; linefeed
tab equ 9 ; tab char
; CCP/M-86 system functions used by the TMP
osint equ 224 ; interrupt number for CCP/M
; system calls
c_write equ 2 ; console functions
c_writebuf equ 9
c_readbuf equ 10
c_attachc equ 146
c_detachc equ 147
c_setnum equ 148
l_setnum equ 160 ; list device functions
l_getnum equ 164
f_open equ 15 ; file functions
f_close equ 16
f_read equ 20
f_setdma equ 26
f_parse equ 152
drv_set equ 14 ; drive functions
drv_get equ 25
drv_free equ 39
dir_usernum equ 32 ; directory functions
p_cli equ 150 ; process control functions
; Process descriptor flags
ps_run equ 00 ; on ready list root
pf_sys equ 001h ; system process
pf_keep equ 002h ; do not terminate
; Some locations in the system data segment
s_ccpmseg equ word ptr 40H ;begin CCPM segment
s_sysdisk equ byte ptr 04bh ;system disk
s_ncns equ byte ptr 47H ;sys. consoles
s_version equ word ptr 78h ;ofst ver. str in SUP
; Some RSP format equates
rsp_top equ 0
rsp_md equ 008h
rsp_pd equ 010h
rsp_uda equ 040h
rsp_bottom equ 140h
; Error codes returned by the CLI
e_no_memory equ 3 ; cant find memory
e_no_pd equ 12 ; no free pd's
e_q_full equ 15 ; full queue
e_illdisk equ 23 ; illegal disk #
e_badfname equ 24 ; illegal filename
e_badftype equ 25 ; illegal filetype
e_bad_load equ 28 ; bad ret. from BDOS load
e_bad_read equ 29 ; bad ret. from BDOS read
e_bad_open equ 30 ; bad ret. from BDOS open
e_nullcmd equ 31 ; null command sent
e_ill_lst equ 37 ; illegal list device
e_ill_passwd equ 38 ; illegal password
e_abort equ 40 ; aborted in CLI
;*****************************************************
;*
;* TMP Shared Code and Constant Area
;*
;*****************************************************
cseg
org 0
jmps tmp
db 'COPYRIGHT (c) 1983, DIGITAL RESEARCH 3/28/83. '
;===
tmp: ; PROGRAM MAIN - INITIALIZATION
;===
; Set default console # = TMP#
mov dl,defconsole ! call setconsolenum
; Set default disk = system drive
push ds ! mov ds,sysdatseg
mov dl,.s_sysdisk ! pop ds ;get system drive from
call setdisk ;system data segment
xor dl,dl ;all TMPs come up user 0
call setuser
call attach ;print version
push ds ! mov ds,sysdatseg
mov dx,.s_version
mov ds,.s_ccpmseg
call print_ds_string ! pop ds
call detach
push ds ! pop es
mov si,offset pd_ascii_num
mov di,offset startupnum
mov cx,3
rep movsb
mov dx,offset fcb
mov cl,f_open ;try to open the startup file
call ccpm ;on default drive which is
cmp al,0ffh ;the system drive
je nostartup
mov dx,offset clicb_cmd ;use the CLI buffer for this
mov cl,f_setdma ;one time one sector read
call ccpm
mov dx,offset fcb
mov cl,f_read
call ccpm
push ax
mov dx,offset fcb
mov cl,f_close
call ccpm
pop ax
test al,al
jnz nostartup
mov ax,ds
mov es,ax
mov al,cr
mov cx,128
mov di,offset clicb_cmd
repne scasb
jne nostartup ;didn't find a carriage return
inc di ;include cr lf in line
mov byte ptr [di],'$'
sub di,offset clicb_cmd
mov ax,di
sub ax, 2
mov read_blen, al
mov dx,offset supmsg
call printstring
mov dx,offset clicb_cmd
call print_ds_string
jmps startup
nostartup:
; THIS IS WHERE A LOGIN ROUTINE MIGHT
; BE IMPLEMENTED. THE DATA FILE THAT
; CONTAINS THE USER NAME AND PASSWORD
; MIGHT ALSO CONTAIN AN INITIAL DEFAULT
; DISK AND USER NUMBER FOR THAT USER.
;===========
nextcommand: ; LOOP FOREVER
;===========
; free drive
mov dx,0ffffh ! call drive_free
; attach console
call attach
; print CR,LF if we just sent command
cmp cmdsent,false ! je noclearline
mov cmdsent,false
call crlf
noclearline:
; set up and print user prompt
; get current default user # and disk
; this call should be made on every
; loop in case the last command
; has changed the default.
mov dl,cr ! call prchar
call getuser
test bl,bl ! jz nozero ;don't print user 0 prompt
mov dl,bl ! call prnum
nozero:
call getdisk
mov dl,'A' ! add dl,bl
call prchar
mov dx,offset prompt
call print_string
; Read Command from Console
mov dx,offset read_buf ! call conreadbuf
startup:
; echo newline
mov dl,lf ! call prchar
; make sure not a null command
lea bx,clicb_cmd
cmp read_blen,0 ! je gonextcmd
deblank:
cmp byte ptr [bx],' ' ! je zapblank
cmp byte ptr [bx],tab ! jne noblanks
zapblank:
inc bx ! dec read_blen ! jmps deblank
noblanks:
lea ax,clicb_cmd ! cmp ax,bx ! je chksemi
; remove leading blanks
push ds ! pop es ! xor ch,ch ! mov cl,read_blen
mov di,ax ! mov si,bx ! cld ! rep movsb
mov bx,ax
chksemi: ; see if line starts with semicolon
cmp byte ptr [bx],';' ! je gonextcmd
; see if disk change
; if 'X:' change def disk to X
cmp read_blen,2 ! jne clicall
cmp byte ptr 1[bx],':'
jne clicall
; change default disk
mov dl,[bx] ;get disk name
and dl,5fh ;Upper Case
sub dl,'A' ;disk number
; check bounds
cmp dl,0 ! jb baddrive
cmp dl,15 ! ja baddrive
; select default disk
call setdisk ! jmp gonextcmd
baddrive: mov dx,offset errstr ! call printstring
mov dx,offset drverr ! call printstring ! call crlf
gonextcmd: jmp nextcommand
;=======
clicall: ; SEND CLI COMMAND
;=======
; put null at end of input
mov bx,offset clicb_cmd
mov al,read_blen ! mov ah,0
add bx,ax ! mov byte ptr [bx],0
; copy command string for error
; reporting later and to check
; for built in commands...
mov cx,64
mov si,offset clicb_cmd
mov di,offset savebuf
push ds ! pop es
rep movsw
; parse front to see if
; built in command
mov si,offset fcb
mov di,offset savebuf
call parsefilename
jcxz goodparse
sub bx,bx ! mov bl,read_blen
add bx,offset savebuf
mov byte ptr [bx],'$'
jmp clierror
goodparse: mov parseret,bx
cmp bx,0 ! jne haveatail
mov bl,read_blen
add bx,offset savebuf
haveatail: mov byte ptr [bx],'$' ! inc bx
cmp fcb,0 ! je try_builtin
jmp not_builtin
; is it USER command?
try_builtin: mov si,offset fcb ! inc si
mov di,offset usercmd
push cs ! pop es
mov cx,4 ! repz cmpsw
jnz notuser
mov si,offset fcb
mov di,parseret
cmp di,0 ! je pruser
inc di
call parsefilename
cmp cx,0 ! jne pruser
mov si,offset fcb
inc si
mov dx,[si]
call a_to_b
cmp bl,15 ! ja usererr
mov dl,bl
call setuser
jmp pruser
usererr: mov dx,offset usererrmsg
call printstring
pruser: mov dx,offset usermsg
call printstring
call getuser
mov dl,bl ! call prnum
call crlf
jmp nextcommand
notuser:
mov si,offset fcb ! inc si
mov di,offset printercmd
push cs ! pop es
mov cx,4 ! repz cmpsw
jnz notprinter
mov si,offset fcb
mov di,parseret
cmp di,0 ! je prprinter
inc di
call parsefilename
cmp cx,0 ! jne prprinter
mov si,offset fcb
inc si
mov dx,[si]
call a_to_b
cmp bl,0ffh
je printererr
mov dl,bl
call setlist
jcxz prprinter
printererr: mov dx,offset printemsg
call printstring
prprinter: mov dx,offset printermsg
call printstring
call getlist
mov dl,bl ! call prnum
call crlf
jmp nextcommand
notprinter:
not_builtin:
; initialize Cli Control Block
mov clicb_net,0
; make cli call
mov cmdsent,true
lea dx,clicb ! mov cl,p_cli
call ccpm
cmp bx,0 ! jne clierror
jmp nextcommand
;========
clierror:
;========
; Cli call unsuccesful, analyze and display err msg
; input: CX = ERROR CODE
mov si,(offset clierrtab)-4
nexterr:
add si,4
cmp cs:word ptr [si],0ffffh ! je unknownerr
cmp cx,cs:[si] ! jne nexterr
unknownerr:
mov dx,cs:2[si]
; jmps showerr
showerr: ; Print Error String
;------- ; input: DX = address of Error
; string in CSEG
; if DX=0 then NULL COMMAND
cmp dx,0 ! jne perr
mov cmdsent,false ! jmp nextcommand
perr: push dx ! call crlf
mov dx,offset errstr ! call printstring
pop dx ! call printstring ! call crlf
mov dx,offset cmdstr ! call printstring
mov dx,offset savebuf ! call print_ds_string ! call crlf
jmp nextcommand
parsefilename: ; SI = fcb DI = string
mov cx,f_parse
mov bx,offset pcb
mov [bx],di ! mov 2[bx],si
mov dx,bx ! jmp ccpm
a_to_b: ;dl = 1st char, dh = 2nd char
cmp dh,' ' ! jne atob2char
mov dh,dl ! mov dl,'0'
atob2char: cmp dh,'0' ! jb atoberr
cmp dh,'9' ! ja atoberr
cmp dl,'0' ! jb atoberr
cmp dl,'9' ! ja atoberr
sub dh,'0' ! sub dl,'0'
mov ax,0 ! mov al,dl
push dx ! mov cl,10
mul cl ! pop dx
mov dl,dh ! mov dh,0
add ax,dx
mov bx,ax ! ret
atoberr: mov bl,0ffh ! ret
prnum: ; dl = num (0-15)
cmp dl,10 ! jb prnum_one
push dx
mov dl,'1' ! call prchar
pop dx ! sub dl,10
prnum_one: add dl,'0'
; jmp prchar
prchar: mov cl,c_write ! jmp ccpm
getuser: mov dl,0ffh
setuser: mov cl,dir_usernum ! jmp ccpm
crlf: mov dx,offset crlfstr
;jmps printstring
printstring: push ds ! mov ax,cs ! mov ds,ax
call print_ds_string ! pop ds ! ret
print_ds_string:mov cl,c_writebuf ! jmps ccpm
setconsolenum: mov cl,c_setnum ! jmps ccpm
setdisk: mov cl,drv_set ! jmps ccpm
getdisk: mov cl,drv_get ! jmps ccpm
setlist: mov cl,l_setnum ! jmps ccpm
getlist: mov cl,l_getnum ! jmps ccpm
attach: mov cl,c_attachc ! jmps ccpm
detach: mov cl,c_detachc ! jmps ccpm
con_readbuf: mov cl,c_readbuf ! jmps ccpm
drivefree: mov cl,drv_free !; jmps ccpm
;====
ccpm: ; INTERFACE ROUTINE FOR SYSTEM ENTRY POINTS
;====
int osint ! ret
;*****************************************************
;*
;* CONSTANTS (IN SHARED CODE SEGMENT)
;*
;*****************************************************
clierrtab dw e_nullcmd, 0 ;null command
dw e_no_memory, memerr ;No memory
dw e_no_pd, pderr ;No unused PD
dw e_badfname, fnameerr;Ill. command
dw e_illdisk, fnameerr;Ill. disk
dw e_ill_passwd, fnameerr;Ill. password
dw e_badftype, fnameerr;Ill. type
dw e_bad_load, loaderr ;
dw e_bad_read, loaderr ;
dw e_bad_open, openerr ;
dw e_q_full, qfullerr;
dw e_abort, aborterr;
; a few extra entries for future errors
dw 0ffffh, catcherr;
dw 0ffffh, catcherr;
dw 0ffffh, catcherr;
dw 0ffffh, catcherr;
prompt db '>$'
crlfstr db 13,10,'$'
errstr db 'CP/M Error: $'
memerr db 'Not Enough Memory$'
pderr db 'PD Table Full$'
fnameerr db 'Bad File Spec$'
catcherr rb 0 ;Unknown Errs give
loaderr db 'Load Error$' ; Load Error Msg
openerr db 'Can''t Find Command$'
qfullerr db 'RSP Command Que Full$'
aborterr db 'CLI Abort$'
drverr db 'Invalid Drive$'
cmdstr db 'Command = $'
usererrmsg db 13,10,'Invalid User Number,'
db ' IGNORED',13,10,'$'
usermsg db 13,10,'User Number = $'
printemsg db 13,10,'Invalid Printer Number,'
db ' IGNORED',13,10,'$'
printermsg db 13,10,'Printer Number = $'
usercmd db 'USER '
printercmd db 'PRINTER '
supmsg db 'Start up command: $'
;*****************************************************
;*
;* TMP Data Area - this area is copied once for
;* each system console. The 'defconsole'
;* field is unique for each copy
;* - Each Data Area is run by a common
;* shared code segment.
;*
;*****************************************************
DSEG
org rsp_top
sysdatseg dw 0
sdatvar dw s_ncns
defconsole db 0,0
dw 0,0,0,0,0
org rsp_pd
pd dw 0,0 ; link fields
db ps_run ; status
db 198 ; priority
dw pf_sys+pf_keep ; flags
db 'Tmp' ; Name
pd_ascii_num db ' ' ; Ascii number field set by GENSYS
dw offset uda/10h ; uda seg
db 0,0 ; disk,user
db 0,0 ; ldisk,luser
dw 0ffffh ; mem
dw 0,0 ; dvract,wait
db 0,0 ; org,net
dw 0 ; parent
db 0,0 ; cns,abort
db 0,0 ; cin,cout
db 0,0 ; lst,sf3
db 0,0 ; sf4,sf5
dw 0,0 ; reserved
dw 0,0 ; pret,scratch
org rsp_uda
uda dw 0,0,0,0 ;0-7 note: no default DMA
dw 0,0,0,0 ;8-fh
dw 0,0,0,0 ;10-17
dw 0,0,0,0 ;18-1f
dw 0,0,0,0 ;20-27
dw 0,0,0,0 ;28-2f
dw 0,0,offset stack_top,0 ;30-37
dw 0,0,0,0 ;38-3f
dw 0,0,0,0 ;40-47
dw 0,0,0,0 ;48-4f
dw 0,0,0,0 ;50-57
dw 0,0,0,0 ;58-5f
db 1 ;60 INSYS <> 0
;don't switch from
;from UDA stack
;on entry to SUP
db 0 ;61
dw 0,0 ;62-64
db 0 ;66
dw 0 ;67-68
db 0 ;69
dw 0cccch,0cccch,0cccch ;6A-6F
dw 0cccch,0cccch,0cccch,0cccch ;70
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;80
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;90
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;A0
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;B0
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;C0
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;D0
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;E0
dw 0cccch,0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch,0cccch ;F0
dw 0cccch
stack_top dw offset tmp ; code starting point
dw 0 ; code seg - set by GENSYS
dw 0 ; init. flags - set by GENSYS
; UDA is 100H bytes long
maxcmdlen equ 128
; the Read Console Buffer and the
; Cli Control Block share the same memory
read_buf rb 0
read_maxcmd db 128
clicb rb 0
clicb_net rb 0
read_blen rb 1
clicb_cmd rb maxcmdlen + 1
cmdsent db false
parseret dw 0
pcb dw offset savebuf
dw offset fcb
fcb db 0, 'STARTUP '
startupnum db ' '
rb 20
db 0 ;current record
savebuf rb 128
db 0 ;ensure hex is formed
end