mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 09:54:20 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
Herein lie all sources to following CCP/M-86 2.0 modules:
|
||||
|
||||
SUP.CON
|
||||
CIO.CON
|
||||
MEM.CON
|
||||
RTM.CON
|
||||
SYSDAT.CON
|
||||
|
||||
WARNING! There are several .DEF files in this group with the same name
|
||||
as the .DEF files compiled with the BDOS. THESE FILES ARE NOT NECESSARILY
|
||||
THE SAME, AND SHOULD BE KEPT SEPARATE!!!!
|
||||
|
||||
These modules are assembled using ASM86 running under CP/M or CP/M-86.
|
||||
|
||||
@@ -0,0 +1,521 @@
|
||||
;*************************************************************
|
||||
;*
|
||||
;* Terminate and Abort Specify Process Entry Points
|
||||
;*
|
||||
;*************************************************************
|
||||
|
||||
;============== ==============
|
||||
sysreset_entry: ; System Reset
|
||||
;============== ==============
|
||||
xor dx,dx
|
||||
mov cx,f_terminate
|
||||
jmp osif
|
||||
|
||||
;=============== ===============================
|
||||
terminate_entry: ; Terminate - DX=terminate code
|
||||
;=============== ===============================
|
||||
; This entry point is used for a process to terminate itself. The
|
||||
; code from the label 'TERMINATE:' on, is also used by a process to be
|
||||
; terminated when it comes back into context, as set up by
|
||||
; abort specified process.
|
||||
|
||||
mov bx,rlr
|
||||
call abt_chk
|
||||
jcxz terminate
|
||||
jmp term_err
|
||||
|
||||
terminate: ;process terminated by abort
|
||||
mov bx,rlr ;spec resumes execution here
|
||||
cli ;interrupts off during stack switch
|
||||
mov ss,p_uda[bx] ;reset the stack to top of UDA
|
||||
mov sp,ulen
|
||||
sti
|
||||
|
||||
mov p_prior[bx],abt_prior ;finish termination quickly
|
||||
;abort spec can't force us
|
||||
;to reenter terminate when
|
||||
;we have best priority
|
||||
|
||||
mov bx,offset thrd_spb ;get ownership of thread
|
||||
call sync_entry ;list before searching
|
||||
|
||||
xor dx,dx
|
||||
mov bx,(offset thrdrt)-p_thread
|
||||
mov ax,rlr
|
||||
nxtchld:
|
||||
mov bx,p_thread[bx] ;set all child process's p_parent
|
||||
test bx,bx ! jz nochld ;field to 0
|
||||
cmp p_parent[bx],ax
|
||||
jne nxtchld
|
||||
mov p_parent[bx],dx ;found a child, 0 its parent field
|
||||
jmps nxtchld
|
||||
nochld:
|
||||
mov bx,offset thrd_spb
|
||||
call unsync_entry
|
||||
;set parent's child abort flag
|
||||
mov bx,rlr ;if terminating process's
|
||||
|
||||
test p_flag[bx],pf_ctlc ;CTL_C flag is on, ie, we are
|
||||
jz term_r1 ;terminating from an abort spec
|
||||
and p_flag[bx],not pf_ctlc ;or control C
|
||||
mov bx,p_parent[bx]
|
||||
test bx,bx ! jz term_r1
|
||||
or p_flag[bx],pf_childabort
|
||||
term_r1:
|
||||
mov u_error_mode,0feh ;call BDOS termination
|
||||
mov cx,f_bdosterm
|
||||
call osif
|
||||
|
||||
mov bx,offset q_spb
|
||||
call sync_entry
|
||||
call rlsmx ;release all MXqueues
|
||||
mov bx,offset q_spb
|
||||
call unsync_entry
|
||||
|
||||
mov bx,offset mem_spb ;get ownership of MEM
|
||||
call sync_entry
|
||||
mov mem_cnt,1 ;keep MEM from freeing
|
||||
;the MEM_SPB
|
||||
|
||||
mov bx,offset thrd_spb ;get the MEM sync BEFORE
|
||||
call sync_entry ;the THRD sync to avoid
|
||||
;deadlock
|
||||
|
||||
mov cx,f_freeall ;free all memory except
|
||||
call osif ;load stack and UDA
|
||||
mov bx,rlr ;dispatcher does rest of
|
||||
mov p_stat[bx],ps_term ;termination
|
||||
jmp dsptch
|
||||
|
||||
term_err:
|
||||
;--------
|
||||
; entry: CX=1 then can't terminate because KEEP or SYS flag
|
||||
; CX=0ffffh TEMPKEEP on, CTLC turned on
|
||||
|
||||
; called from TERMINATE_ENTRY and ABORT_SPEC_ENTRY
|
||||
; after call to ABT_CHK:
|
||||
|
||||
dec cx ! jz term_err1
|
||||
;TEMPKEEP and CTLC flag on
|
||||
xor bx,bx ! mov cx,bx ;and process will terminate
|
||||
ret ;itself, or needs CTLC information
|
||||
|
||||
term_err1:
|
||||
mov cx,e_pd_noterm ;couldn't term because of
|
||||
mov bx,0ffffh ! ret ;SYS or KEEP flags,
|
||||
;CTLC is off
|
||||
|
||||
;================
|
||||
abort_spec_entry: ;Abort the specified process
|
||||
;================
|
||||
; entry: DX = address of APB in the caller's U_WRKSEG
|
||||
; exit: BX = 0 if success, 0FFFFH if failure
|
||||
; CX = 0 " " , error code if failure
|
||||
|
||||
; Set up the specified PD for termination when it is next in context.
|
||||
; If the running PD is the same as the PD to abort, we can just use
|
||||
; the terminate entry point. Otherwise we use the Abort Parameter Block
|
||||
; to find it. If it cannot be found, name and console must both match,
|
||||
; the abort fails. If the TEMPKEEP flag is on, set the CTLC flag
|
||||
; and return. If the KEEP flag is on and not the TEMPKEEP flag,
|
||||
; then fail.
|
||||
; If the terminate code in DL on entry, is not 0ffh
|
||||
; and the SYS flag is on in the PD to be aborted, then fail.
|
||||
; The PD is taken off the list it is attached to via its link field.
|
||||
; The terminating PD's priority is set to ABT_PRIOR,
|
||||
; and the address of TERMINATE: is put on top of its UDA stack.
|
||||
; This forces the terminating process to run next (it has the
|
||||
; best priority in the system) and for it to resume execution
|
||||
; at TERMINATE: on returning from the dispatcher.
|
||||
|
||||
push dx
|
||||
mov bx,offset thrd_spb ; get ownership of thread
|
||||
call sync_entry ; while searching
|
||||
pop si ; U_WRKSEG:SI->APB
|
||||
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov bx,apb_pd[si] ; get PD adr to abort
|
||||
mov cx,apb_term[si] ; get termination/memfree code
|
||||
mov ah,apb_cns[si] ; console from APB
|
||||
pop ds
|
||||
push cx ; save termination code
|
||||
test bx,bx ! jz abt_findit ; got a PD ID, but not verified
|
||||
call find_pdthrd ; find it on thread
|
||||
push cx ; save return code
|
||||
jmps abt_unsync
|
||||
|
||||
abt_findit:
|
||||
add dx,offset apb_pdname ; get adr of named PD
|
||||
mov bx,offset thrdrt - p_thread ; find it on thread
|
||||
call findpdnc ; look for PD name and console match
|
||||
push cx ; save return code
|
||||
abt_unsync:
|
||||
push bx ; BX=PD if found
|
||||
mov bx,offset thrd_spb
|
||||
call unsync_entry
|
||||
pop bx
|
||||
pop cx ; CX=0 if no PD found
|
||||
jcxz abt_err1
|
||||
; successfully found PD
|
||||
pop dx ; DX = terminate code
|
||||
mov ax,rlr ; we are aborting ourselves
|
||||
cmp ax,bx ; jump to TERMINATE_ENTRY
|
||||
jne abt_notus
|
||||
jmp terminate_entry
|
||||
|
||||
abt_notus:
|
||||
mov indisp,true ; stop dispatching
|
||||
;pushf ! cli ; do not let process or another
|
||||
; process (NO_ABORT_SPEC) change the
|
||||
or p_flag[bx],pf_ctlc ; flags while testing and acting on them.
|
||||
call abt_chk ; ok to abort this PD ?
|
||||
jcxz abt_ok
|
||||
;popf ; can't abort it - return
|
||||
call ok_disp
|
||||
jmps term_err
|
||||
|
||||
; The interrupt window above may be lessened if the TERMINATE_ENTRY
|
||||
; code is moved to the dispatcher and the status is set to PS_TERM.
|
||||
; Turning interrupts back on, the aborting process could come
|
||||
; back into context. Before turning on TEMPKEEP it would check
|
||||
; its status, if it is PS_TERM, then it goes to the dispatcher
|
||||
; to terminate.
|
||||
|
||||
abt_ok: ; this process will be aborted
|
||||
mov dl,p_stat[bx] ; call abort function based on status
|
||||
mov dh,0 ! mov di,dx
|
||||
|
||||
add di,di
|
||||
call cs:abort_tab[di] ; find via p_link and take PD off its list
|
||||
;popf
|
||||
call ok_disp ; process can't come back into context
|
||||
; so interrupts are ok
|
||||
jcxz abt_err2 ; couldn't find PD on list by indicated
|
||||
mov indisp,false ; by P_STAT
|
||||
mov p_prior[bx],abt_prior
|
||||
; set to low priority
|
||||
push es ; save calling process' UDA
|
||||
mov es,p_uda[bx] ; UDA of PD being aborted
|
||||
mov si,(ulen-2) ; reset stack to top of UDA
|
||||
mov u_sp,si
|
||||
mov u_ss,es
|
||||
mov es:[si],offset terminate
|
||||
; TERMINATE: will be executed when
|
||||
; terminating process comes back into
|
||||
; context
|
||||
xor ax,ax ; on exit from dispatcher interrupts
|
||||
mov u_flag_sav,ax ; will be off
|
||||
mov u_inint,false ; return into context with a RET and
|
||||
; not an IRET
|
||||
pop es ; ES=calling PD's UDA
|
||||
call abt_putdrl
|
||||
xor bx,bx ; indicate sucess
|
||||
jmp pdisp ; force abort to happen before we return
|
||||
; since terminating process has better
|
||||
; priority
|
||||
|
||||
abt_err1:
|
||||
pop dx ; throw out termination code
|
||||
abt_err2:
|
||||
mov cx,e_no_pdname ; set TERM_ERR for other returns
|
||||
mov bx,0ffffh
|
||||
ret
|
||||
|
||||
; The folowing are the abort handlers for a specific PD status.
|
||||
; These labels are entered in the abort_tab(le) in the RTM data area.
|
||||
; Interrupts assumed off.
|
||||
; For all of the following:
|
||||
; entry: BX = PD addr to be aborted
|
||||
; AH = cons
|
||||
; exit: CX=0 if error
|
||||
; BX preserved
|
||||
;
|
||||
; abort_specified process jump table
|
||||
;
|
||||
; Status
|
||||
abort_tab dw abtrun ; 0 = ready list root
|
||||
dw abtslp ; 1 = poll
|
||||
dw abtdly ; 2 = delay
|
||||
dw abtslp ; 3 = swap
|
||||
dw abttrm ; 4 = term
|
||||
dw abtrun ; 5 = sleep
|
||||
dw abtslp ; 6 = dq
|
||||
dw abtslp ; 7 = nq
|
||||
dw abtflg ; 8 = flagwait
|
||||
dw abtslp ; 9 = ciowait
|
||||
dw abtslp ; 10 = sync
|
||||
abt_tablen equ offset $ - offset abort_tab
|
||||
|
||||
abtrun:
|
||||
;-------
|
||||
; On ready list root or dispatcher ready list
|
||||
|
||||
mov di,(offset rlr) - p_link
|
||||
call find_pd
|
||||
jcxz abtr_drl
|
||||
jmps snip_it
|
||||
abtr_drl: ; wasn't on rlr, try drl
|
||||
mov di,(offset drl) - plink
|
||||
jmps abt_common
|
||||
|
||||
abtslp:
|
||||
;------
|
||||
; On list indicated by u_dparam
|
||||
; Note: a PD in the SY_NEXT field will not be found
|
||||
; and cannot be terminated. Usually the PD has TEMPKEEP on
|
||||
; so it never gets this far.
|
||||
|
||||
push es ! mov es,p_uda[bx]
|
||||
mov di,u_dparam
|
||||
pop es ! jmps abt_common
|
||||
|
||||
abtdly:
|
||||
;------
|
||||
mov di,offset dlr - p_link
|
||||
call find_pd
|
||||
jcxz abt_tab_err
|
||||
mov si,p_link[si] ; Fix wait field in next PD on dlr
|
||||
test si,si
|
||||
jz ad_nofix ; Are there more PDs after the one
|
||||
mov dx,p_wait[si] ; being aborted on the DLR ?
|
||||
add dx,p_wait[bx] ; Add wait of aborting PD
|
||||
mov p_wait[si],dx ; New value in next PD on dlr
|
||||
ad_nofix:
|
||||
jmps snip_it
|
||||
|
||||
abttrm:
|
||||
;------
|
||||
mov indisp,false
|
||||
call pdisp ; we are terminating already
|
||||
xor cx,cx ; make sure termination completes
|
||||
jmps abt_tab_err ; before returning error
|
||||
|
||||
abtflg:
|
||||
;------
|
||||
xor cx,cx
|
||||
mov di,u_dparam ; flag PD field asleep on
|
||||
cmp bx,[di] ; if interrupts are allowed
|
||||
jne aflg_err ; in this code, check DRL
|
||||
inc flg_ignore[di] ; and RLR if not in flags
|
||||
mov flg_pd[di],flag_off
|
||||
inc cx
|
||||
aflg_err:
|
||||
ret
|
||||
|
||||
abt_common:
|
||||
;----------
|
||||
call find_pd ! jcxz abt_tab_err
|
||||
;jmps snip_it
|
||||
|
||||
snip_it:
|
||||
;-------
|
||||
; Take PD out of linked list of PDs
|
||||
; entry: BX = PD being sniped out
|
||||
; DI = offset of previous PD or offset of root - p_link.
|
||||
|
||||
mov dx,p_link[bx] ; DX = next link
|
||||
mov p_link[di],dx
|
||||
ret ; CX<>0
|
||||
|
||||
abt_tab_err:
|
||||
;-----------
|
||||
ret ; CX = 0
|
||||
|
||||
;
|
||||
; End of abort_tab(le) functions
|
||||
;
|
||||
|
||||
|
||||
abt_putdrl:
|
||||
;-------
|
||||
; Puts PD on DRL
|
||||
; entry: BX = PD to insert
|
||||
; exit: BX preserved
|
||||
|
||||
pushf ! cli
|
||||
mov dx,drl
|
||||
mov p_link[bx],dx
|
||||
mov drl,bx
|
||||
popf ! ret
|
||||
|
||||
; Utility routines for abort entry point
|
||||
|
||||
findpdnc:
|
||||
;--------
|
||||
; Find PD by name and console, via thread list.
|
||||
; entry: BX = offset of thread list root - p_thread
|
||||
; DX = adr of name in u_wrkseg
|
||||
; AH = console number
|
||||
; ownership of thread sync
|
||||
; exit: BX = PD
|
||||
; CX = 0 failure
|
||||
|
||||
xor cx,cx
|
||||
nxt_pdname:
|
||||
push ax ; save console number
|
||||
call findpdname_entry
|
||||
pop ax
|
||||
jcxz fnc_found_one ; CX = 0 is success from findpdname
|
||||
xor cx,cx
|
||||
ret ; CX = 0 is failure from this routine
|
||||
fnc_found_one: ; found PD w/ same name
|
||||
cmp p_cns[bx],ah ; chk for same console #
|
||||
jnz nxt_pdname
|
||||
inc cx ! ret ; success
|
||||
|
||||
find_pdthrd:
|
||||
;-----------
|
||||
; Find PD on thread list
|
||||
; entry: BX = PD address we want
|
||||
; ownership of thread sync
|
||||
; exit: CX = 0 if not found
|
||||
; BX prserved
|
||||
|
||||
xor cx,cx
|
||||
mov di,offset thrdrt - p_thread
|
||||
fp_next:
|
||||
mov di,p_thread[di]
|
||||
test di,di
|
||||
jz fp_err
|
||||
cmp bx,di
|
||||
jne fp_next
|
||||
inc cx
|
||||
fp_err:
|
||||
ret
|
||||
|
||||
|
||||
find_pd:
|
||||
;-------
|
||||
; Find PD through link field, interrupts assumed off
|
||||
; entry: BX = PD address
|
||||
; DI = offset of list root - p_link
|
||||
; exit: BX = SI = PD address
|
||||
; DI = Previous PD
|
||||
; CX = 0 if failure
|
||||
|
||||
mov si,p_link[di]
|
||||
xor cx,cx
|
||||
fpd_nxt_pd:
|
||||
test si,si ; SI could be zero to start
|
||||
jz fpd_not_found
|
||||
cmp si,bx ; Are addresses the same ?
|
||||
jz fpd_found
|
||||
fpd_nxt_lnk:
|
||||
mov di,si ; Save previous link
|
||||
mov si,p_link[si]
|
||||
jmps fpd_nxt_pd
|
||||
fpd_found:
|
||||
inc cx
|
||||
fpd_not_found:
|
||||
ret
|
||||
|
||||
fflgpd:
|
||||
;-----
|
||||
; Find offset into flag table of flag waiting PD
|
||||
; entry: BX = PD
|
||||
; exit: DI = offset in RTM data of flag
|
||||
; CX = 0 if failure
|
||||
; BX preserved
|
||||
|
||||
mov cl,nflags
|
||||
xor ch,ch
|
||||
mov di,flags
|
||||
ffp_nxt_flg:
|
||||
cmp bx,flg_pd[di] ; assume legal flag
|
||||
jz ffp_pdfound
|
||||
add di,flglen
|
||||
loop ffp_nxt_flg
|
||||
ffp_pdfound:
|
||||
ret ; CX is 0 at end of loop instr
|
||||
; CX <> 0 if found
|
||||
|
||||
|
||||
ok_disp:
|
||||
;-------
|
||||
mov indisp,false
|
||||
cmp drl,0
|
||||
jz od_ret
|
||||
call pdisp
|
||||
od_ret:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
abt_chk:
|
||||
;-------
|
||||
; Check different PD flags for terminate or abort
|
||||
; CTLC flag is on if called from ABORT_SPEC
|
||||
; entry: BX = PD to possibly abort
|
||||
; DL = termination code
|
||||
; interrupts off if called from ABORT_SPEC
|
||||
; exit: CX = 00000H if ok to abort
|
||||
; 00001H IF NOT OK TO ABORT
|
||||
; 0FFFFH IF TEMPKEEP
|
||||
; BX = PD as on entry
|
||||
; interrupts unchanged
|
||||
|
||||
xor cx,cx
|
||||
mov ax,p_flag[bx] ;AX = PD flags
|
||||
|
||||
;test TEMPKEEP first
|
||||
;for signaling KEEP process
|
||||
;to terminate i.e., the TMP
|
||||
;while in the CLI
|
||||
test ax,pf_tempkeep ! jz ac_keep
|
||||
or ax,pf_ctlc ;signal control C
|
||||
dec cx ;temp keep return
|
||||
jmps ac_ret
|
||||
ac_keep:
|
||||
test ax,pf_keep ! jnz ac_no
|
||||
;not KEEP, test SYS
|
||||
inc dl ! jz ac_ok ;if DL = 0ffh -> ok to terminate
|
||||
test ax,pf_sys ! jz ac_ok ;DL<>0ffh & not sys-> ok to terminate
|
||||
ac_no:
|
||||
and ax,not pf_ctlc ;turn off ctlc
|
||||
inc cx ;CX=1, can't terminate
|
||||
|
||||
ac_ret:
|
||||
mov p_flag[bx],ax ;new flags if no termination
|
||||
ac_ok:
|
||||
ret
|
||||
|
||||
rlsmx:
|
||||
;-----
|
||||
; Release all MX queues owned by the terminating process
|
||||
; called only from TERMINATE_ENTRY
|
||||
; entry: we own the Queue SYNC
|
||||
; exit: none
|
||||
|
||||
; To guard against queue deletes, and to make interrupt
|
||||
; windows are smaller, we start over from the beginning of
|
||||
; QLR after we write to an MXqueue that we own.
|
||||
|
||||
mov bx,rlr ;BX=running process
|
||||
; pushf ! cli
|
||||
mov si,(offset qlr)-q_link
|
||||
rm_nxt:
|
||||
mov si,q_link[si] ;SI=QD currently checking
|
||||
test si,si ;end of list ?
|
||||
jz rm_done
|
||||
test q_flags[si],qf_mx ;is it an MX queue ?
|
||||
jz rm_nxt
|
||||
cmp bx,q_buf[si] ;do we own it ?
|
||||
jne rm_nxt
|
||||
; popf ;allow interrupts
|
||||
push si ;put 2-word QPB on stack
|
||||
xor ax,ax
|
||||
push ax
|
||||
mov dx,sp
|
||||
mov cx,f_qwrite
|
||||
push ds ;save DS
|
||||
push ss ! pop ds ;DS=SS
|
||||
call osif
|
||||
pop ds ;restore DS
|
||||
pop ax ! pop ax ;throw out 2-word QPB
|
||||
jmps rlsmx ;start over from
|
||||
;top of queue list
|
||||
;a queue could have been
|
||||
;deleted while we were writing
|
||||
rm_done:
|
||||
; popf
|
||||
ret
|
||||
@@ -0,0 +1,11 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Assign Console Control Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
acb_cns equ byte ptr 0
|
||||
acb_match equ byte ptr acb_cns + byte
|
||||
acb_pd equ word ptr acb_match + byte
|
||||
acb_name equ byte ptr acb_pd + word
|
||||
acblen equ acb_name + pnamsiz
|
||||
@@ -0,0 +1,16 @@
|
||||
;*************************************************************
|
||||
;*
|
||||
;* Abort Parameter Block
|
||||
;*
|
||||
;*************************************************************
|
||||
|
||||
apb_pd equ word ptr 0
|
||||
apb_term equ word ptr apb_pd + word
|
||||
apb_cns equ byte ptr apb_term + word
|
||||
apb_net equ byte ptr apb_cns + byte
|
||||
apb_pdname equ byte ptr apb_net + byte
|
||||
apb_len equ apb_pdname + pnamsiz
|
||||
|
||||
; Priority processes are set to when aborting
|
||||
|
||||
abt_prior equ 32
|
||||
@@ -0,0 +1,48 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Base Page Format
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
DSEG
|
||||
org 0
|
||||
|
||||
bpg_clen rb 3
|
||||
bpg_cseg rw 1
|
||||
bpg_8080 rb 1
|
||||
|
||||
bpg_dlen rb 3
|
||||
bpg_dseg rw 1
|
||||
bpg_dxxx rb 1
|
||||
|
||||
bpg_elen rb 3
|
||||
bpg_eseg rw 1
|
||||
bpg_exxx rb 1
|
||||
|
||||
bpg_slen rb 3
|
||||
bpg_sseg rw 1
|
||||
bpg_sxxx rb 1
|
||||
|
||||
org 050h
|
||||
|
||||
bpg_lddsk rb 1
|
||||
bpg_pw1ptr rw 1
|
||||
bpg_pw1len rb 1
|
||||
bpg_pw2ptr rw 1
|
||||
bpg_pw2len rb 1
|
||||
|
||||
org 05ch
|
||||
|
||||
bpg_fcb0 rb 0
|
||||
|
||||
org 06ch
|
||||
|
||||
bpg_fcb1 rb 0
|
||||
|
||||
org 80h
|
||||
|
||||
bpg_dma rb 0
|
||||
|
||||
org 100h
|
||||
|
||||
bpg_udata rb 0
|
||||
@@ -0,0 +1,24 @@
|
||||
;
|
||||
;
|
||||
; GENERATE CONCURRENT CP/M-86 MODULES
|
||||
;
|
||||
;
|
||||
vax $$a#home#
|
||||
vax $$a#set def [.ccpm.micro.kern]#
|
||||
;
|
||||
ren system.def=system.ccc
|
||||
ren cpyright.def=cpyright.ccc
|
||||
;
|
||||
; GENERATE BDOS.CON
|
||||
;
|
||||
;a86 bdos
|
||||
;gencmd bdos
|
||||
;era bdos.con
|
||||
;ren bdos.con=bdos.cmd
|
||||
;xref86 bdos
|
||||
;ren cbdos.xrf=bdos.xrf
|
||||
;vax cbdos.xrf $$satn
|
||||
;era bdos.lst
|
||||
;era cbdos.xrf
|
||||
;era bdos.sym
|
||||
;era bdos.h86
|
||||
@@ -0,0 +1,7 @@
|
||||
;
|
||||
; Character Block (CP/M 3.0 Character Control Block)
|
||||
;
|
||||
cb_off equ word ptr 0
|
||||
cb_seg equ word ptr cb_off + word
|
||||
cb_len equ word ptr cb_seg + word
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Console Control Block Definition
|
||||
;*
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 00 | attach | queue |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 04 | flag | startcol| column | nchar |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 08 | mimic | msource | type | btmp |
|
||||
;* +---------+---------+---------+---------+
|
||||
;*
|
||||
;* attach - current owner of device
|
||||
;* if 0, no owner
|
||||
;* if 0ffffh, a mimic device
|
||||
;* queue - linked list of PDs waiting to attach
|
||||
;* flag - run-time flags
|
||||
;* startcol - used for line editing
|
||||
;* column - used for line editing
|
||||
;* nchar - 1 character read ahead for CTRL chars.
|
||||
;* mimic - cio dev that mimics us.
|
||||
;* 0ffh means no mimic device
|
||||
;* msource - if attach = 0ffffh, we are a
|
||||
;* mimic device and msource is the
|
||||
;* device we are mimicing.
|
||||
;* type - type of device
|
||||
;* btmp - Temporary console variable
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
c_attach equ word ptr 0
|
||||
c_queue equ word ptr c_attach + word
|
||||
c_flag equ byte ptr c_queue + word
|
||||
c_strtcol equ byte ptr c_flag + byte
|
||||
c_column equ byte ptr c_strtcol + byte
|
||||
c_nchar equ byte ptr c_column + byte
|
||||
c_mimic equ byte ptr c_nchar + byte
|
||||
c_msource equ byte ptr c_mimic + byte
|
||||
c_type equ byte ptr c_msource + byte
|
||||
c_btmp equ byte ptr c_type + byte
|
||||
ccblen equ byte ptr c_btmp + byte
|
||||
|
||||
; Flags for c_flag
|
||||
|
||||
cf_listcp equ 001h ;control P toggle
|
||||
cf_compc equ 002h ;suppress output
|
||||
@@ -0,0 +1,114 @@
|
||||
;
|
||||
;
|
||||
; GENERATE CONCURRENT CP/M-86 MODULES
|
||||
;
|
||||
; This .SUB file also transfers XRF files to vax.
|
||||
; 'CVAX' is the 'VAX' program modified to use '#' as a command delimiter
|
||||
; (rather than backslant).
|
||||
;
|
||||
;
|
||||
; You MUST login to vax first!
|
||||
;
|
||||
cvax $$a#home#
|
||||
cvax $$a#set def [.kern]#
|
||||
;
|
||||
ren system.def=system.ccc
|
||||
ren cpyright.def=cpyright.ccc
|
||||
;
|
||||
; GENERATE BDOS.CON
|
||||
;
|
||||
; this is done elsewhere
|
||||
;
|
||||
; GENERATE SUP.CON
|
||||
;
|
||||
asm86 sup
|
||||
gencmd sup
|
||||
era sup.con
|
||||
ren sup.con=sup.cmd
|
||||
xref86 sup
|
||||
era csup.xrf
|
||||
ren csup.xrf=sup.xrf
|
||||
cvax csup.xrf $$satn
|
||||
era csup.sym
|
||||
ren csup.sym=sup.sym
|
||||
cvax csup.sym $$tans
|
||||
era sup.lst
|
||||
era sup.h86
|
||||
era csup.xrf
|
||||
;
|
||||
; GENERATE RTM.CON
|
||||
;
|
||||
asm86 rtm
|
||||
gencmd rtm
|
||||
era rtm.con
|
||||
ren rtm.con=rtm.cmd
|
||||
xref86 rtm
|
||||
era crtm.xrf
|
||||
|
||||
ren crtm.xrf=rtm.xrf
|
||||
cvax crtm.xrf $$satn
|
||||
era crtm.sym
|
||||
ren crtm.sym=rtm.sym
|
||||
cvax crtm.sym $$tans
|
||||
era rtm.lst
|
||||
era rtm.h86
|
||||
|
||||
era crtm.xrf
|
||||
;
|
||||
; GENERATE MEM.CON
|
||||
;
|
||||
asm86 mem
|
||||
gencmd mem
|
||||
era mem.con
|
||||
ren mem.con=mem.cmd
|
||||
xref86 mem
|
||||
era cmem.xrf
|
||||
ren cmem.xrf=mem.xrf
|
||||
cvax cmem.xrf $$satn
|
||||
era cmem.sym
|
||||
ren cmem.sym=mem.sym
|
||||
cvax cmem.sym $$tans
|
||||
era mem.lst
|
||||
era cmem.xrf
|
||||
era mem.h86
|
||||
;
|
||||
; GENERATE CIO.CON
|
||||
;
|
||||
asm86 cio
|
||||
gencmd cio
|
||||
era cio.con
|
||||
ren cio.con=cio.cmd
|
||||
xref86 cio
|
||||
era ccio.xrf
|
||||
ren ccio.xrf=cio.xrf
|
||||
cvax ccio.xrf $$satn
|
||||
era ccio.sym
|
||||
ren ccio.sym=cio.sym
|
||||
cvax ccio.sym $$tans
|
||||
era cio.lst
|
||||
era ccio.xrf
|
||||
era cio.h86
|
||||
;
|
||||
;
|
||||
; GENERATE SYSDAT.CON
|
||||
;
|
||||
asm86 sysdat
|
||||
gencmd sysdat
|
||||
era sysdat.con
|
||||
ren sysdat.con=sysdat.cmd
|
||||
xref86 sysdat
|
||||
era csysdat.xrf
|
||||
ren csysdat.xrf=sysdat.xrf
|
||||
cvax csysdat.xrf $$satn
|
||||
era sysdat.lst
|
||||
era sysdat.sym
|
||||
era csysdat.xrf
|
||||
era sysdat.h86
|
||||
;
|
||||
ren system.ccc=system.def
|
||||
ren cpyright.ccc=cpyright.def
|
||||
;
|
||||
;
|
||||
;
|
||||
; KERNEL GENERATION COMPLETED!
|
||||
;
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Character Definitions
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
ctlc equ 003h
|
||||
ctld equ 004h
|
||||
ctle equ 005h
|
||||
bell equ 007h
|
||||
ctlh equ 008h
|
||||
tab equ 009h
|
||||
lf equ 00ah
|
||||
cr equ 00dh
|
||||
ctlp equ 010h
|
||||
ctlq equ 011h
|
||||
ctlr equ 012h
|
||||
ctls equ 013h
|
||||
ctlu equ 015h
|
||||
ctlx equ 018h
|
||||
ctlz equ 01ah
|
||||
ctl equ 05eh
|
||||
rubout equ 07fh
|
||||
@@ -0,0 +1,773 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* 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
|
||||
@@ -0,0 +1,32 @@
|
||||
include cpyright.def
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MP/M-86 and Concurrent CP/M-86
|
||||
;* Character I/O Module
|
||||
;*
|
||||
;*****************************************************
|
||||
eject ! include system.def
|
||||
eject ! include modfunc.def
|
||||
eject ! include xioscb.def
|
||||
eject ! include pd.def
|
||||
eject ! include err.def
|
||||
eject ! include qd.def
|
||||
eject ! include acb.def
|
||||
if mpm
|
||||
eject ! include ccb.def
|
||||
endif
|
||||
if ccpm
|
||||
eject ! include vccb.def
|
||||
endif
|
||||
eject ! include char.def
|
||||
eject ! include cmode.def
|
||||
eject ! include cb.def
|
||||
eject ! include cioif.cio
|
||||
eject ! include console.cio
|
||||
eject ! include chario.cio
|
||||
eject ! include patch.cod
|
||||
eject ! include uda.fmt
|
||||
eject ! include sysdat.dat
|
||||
eject ! include data.bdo
|
||||
eject ! end
|
||||
@@ -0,0 +1,92 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Character I/O Interface
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
CSEG
|
||||
org 0
|
||||
|
||||
jmp init
|
||||
jmp entry
|
||||
|
||||
;3 variables set by GENSYS
|
||||
sysdat dw 0
|
||||
supervisor equ (offset $)
|
||||
rw 2
|
||||
|
||||
org 0ch
|
||||
dev_ver db 6 ;development system data version
|
||||
;set in sysdat.fmt
|
||||
|
||||
db 'COPYRIGHT (C) 1982,'
|
||||
db ' DIGITAL RESEARCH '
|
||||
db 'XXXX-0000-'
|
||||
serial db '654321'
|
||||
|
||||
;====
|
||||
init:
|
||||
;====
|
||||
retf
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* CIO function table
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
functab dw conin_entry ; 0 - Console Input
|
||||
dw conout_entry ; 1 - Console Output
|
||||
dw rconin_entry ; 2 - raw console input
|
||||
dw rconout_entry ; 3 - raw console output
|
||||
dw listout_entry ; 4 - list output
|
||||
dw dirio_entry ; 5 - direct console I/O
|
||||
dw conwrite_entry ; 6 - print string
|
||||
dw conread_entry ; 7 - read buffer
|
||||
dw constat_entry ; 8 - console status
|
||||
dw conattach_entry ; 9 - attach console
|
||||
dw condetach_entry ; 10- detach console
|
||||
dw setdefcon_entry ; 11- set default console
|
||||
dw conassign_entry ; 12- assign console
|
||||
dw getdefcon_entry ; 13- get default console
|
||||
dw conprint_entry ; 14- print string (internal)
|
||||
dw lstattach_entry ; 15- attach list
|
||||
dw lstdetach_entry ; 16- detach list
|
||||
dw setdeflst_entry ; 17- set default list
|
||||
dw clstattch_entry ; 18- cond list attach
|
||||
dw cconattch_entry ; 19- cond list detach
|
||||
dw getdeflst_entry ; 20- get default list
|
||||
dw notimp ; 21
|
||||
|
||||
dw notimp ; 22
|
||||
dw cioterm ; 23- cleanup for term.
|
||||
dw ciostat ; 24- check status w/out
|
||||
; changing raw/cooked flag
|
||||
dw cmode_entry ; 25- get/set console mode word -
|
||||
; user func 109
|
||||
dw delim_entry ; 26- get/set delimiter - user func 110
|
||||
|
||||
dw pblock_entry ; 27- print block - user func 111
|
||||
dw lblock_entry ; 28- list block - user func 112
|
||||
|
||||
;===== =================
|
||||
entry: ; CIO entry point
|
||||
;===== =================
|
||||
shl cx,1 ! mov si,cx
|
||||
call cs:functab[si] ! retf
|
||||
|
||||
;==== ==============
|
||||
osif: ; OS interface
|
||||
;==== ==============
|
||||
callf cs:dword ptr .supervisor ! ret
|
||||
|
||||
;====== ================
|
||||
xiosif: ; XIOS interface
|
||||
;====== ================
|
||||
callf dword ptr .xiosmod ! ret
|
||||
|
||||
;======
|
||||
notimp:
|
||||
;======
|
||||
mov bx,0ffffh
|
||||
ret
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Cli Command Control Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
clicb_net equ byte ptr 0
|
||||
clicb_cmd equ byte ptr clicb_net + byte
|
||||
|
||||
clicblen equ clicb_cmd + 129*byte
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Command Header Format and Load Fixup Records
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;group descriptor format
|
||||
ch_form equ byte ptr 0
|
||||
ch_length equ word ptr (ch_form + byte)
|
||||
ch_base equ word ptr (ch_length + word)
|
||||
ch_min equ word ptr (ch_base + word)
|
||||
ch_max equ word ptr (ch_min + word)
|
||||
chlen equ ch_max + word
|
||||
|
||||
ch_entmax equ 8 ;max number of group
|
||||
;descriptors
|
||||
|
||||
ch_lbyte equ byte ptr 07fh ;MSB bit in CH_LBYTE
|
||||
ch_fixrec equ word ptr 07dh ;signals fixup records
|
||||
;start at record number
|
||||
;in CH_FIXREC
|
||||
|
||||
fix_grp equ byte ptr 0 ;format of fixup record
|
||||
fix_para equ word ptr fix_grp + byte
|
||||
fix_offs equ byte ptr fix_para + word
|
||||
fixlen equ fix_offs + byte
|
||||
@@ -0,0 +1,9 @@
|
||||
;
|
||||
; Bit masks for the console mode word
|
||||
;
|
||||
cm_ctlc equ 0001H
|
||||
cm_ctls equ 0002H
|
||||
cm_rawo equ 0004H
|
||||
cm_rsx1 equ 0100H
|
||||
cm_rsx2 equ 0200H
|
||||
|
||||
@@ -0,0 +1,717 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Command Line Interpreter, Program Chain
|
||||
;*
|
||||
;*****************************************************
|
||||
;=========
|
||||
chain_ent:
|
||||
;=========
|
||||
|
||||
xor dx,dx
|
||||
|
||||
;=======
|
||||
cli_ent:
|
||||
;=======
|
||||
; Create a process based on an Ascii Command Line.
|
||||
; The command Line is first parsed and an FCB is
|
||||
; initialized as a result.
|
||||
; An attempt is made to open a queue with the filename
|
||||
; of the FCB, and with the RSP flag on.
|
||||
; The command tail is written to the queue if it is found.
|
||||
; If the queue cannot be opened or is not and RSP type then
|
||||
; we try and load the command from disk.
|
||||
; If the write queue fails we return e_q_full error code and
|
||||
; do not look on the disk.
|
||||
; After the queue write, an console assign call attempted to
|
||||
; a process with the same name and the PF_DSKLD flag off.
|
||||
; Irregardless of the success of the assign we then return.
|
||||
;
|
||||
; If the RSP queue cannot be opened, or is not an RSP type queue then
|
||||
; we make the name type in the
|
||||
; FCB to be 'CMD' and attempt to open the file. If this fails,
|
||||
; so do we.
|
||||
; We then obtain a Process Descriptor from the
|
||||
; PD table. Again we fail if it does.
|
||||
; On a successful open, we call the BDOS load function.
|
||||
; If the load fails, so do we. The PD is
|
||||
; initialized, the default console is assigned to the
|
||||
; PD, the PF_DSKLD flag turned on,
|
||||
; and a create process call is made.
|
||||
|
||||
;
|
||||
; input: DX -> command buffer in u_wrkseg
|
||||
; It is assumed that the calling process
|
||||
; is attached to its default console
|
||||
|
||||
; and is willing to lose it since it
|
||||
; will be handed to the newly created
|
||||
; process.
|
||||
; if DX = 0, assume chain w/command in DMA
|
||||
;
|
||||
; output: BX = 0 if successful
|
||||
; = 0ffffh if failure has occured
|
||||
; CX = error code
|
||||
|
||||
mov bx,rlr ! mov ax,p_flag[bx]
|
||||
push ax ;save flags on stack
|
||||
or ax,pf_tempkeep + pf_noctls
|
||||
mov p_flag[bx],ax
|
||||
push dx ;save parameter
|
||||
call cli_sync ;rentrancy stops with sync call
|
||||
pop dx ;we can save the flags
|
||||
pop cli_pflag ;and other variables in the CLI
|
||||
;data area
|
||||
; we have CLI SYNC
|
||||
; Check for Chain
|
||||
|
||||
mov cli_chain,false
|
||||
cmp dx,0 ! jne cli_cli
|
||||
mov cli_chain,true
|
||||
mov cli_term,false
|
||||
cli_cli:
|
||||
; initialize defaults from parent PD
|
||||
|
||||
mov cli_dfil,false
|
||||
cmp dayfile,0ffh ! jne nodf
|
||||
push dx ! mov cx,f_cconattch
|
||||
call osif ! pop dx
|
||||
cmp cx,0 ! jne nodf
|
||||
mov cli_dfil,true
|
||||
push dx
|
||||
|
||||
call prtime
|
||||
pop dx
|
||||
nodf: mov bx,rlr
|
||||
mov cli_ppd,bx
|
||||
mov cl,p_dsk[bx]
|
||||
mov cli_dsk,cl
|
||||
mov cl,p_user[bx]
|
||||
mov cli_user,cl
|
||||
mov cl,p_cns[bx]
|
||||
mov cli_cns,cl
|
||||
mov cl,u_error_mode
|
||||
mov cli_err_mode,cl
|
||||
mov cx,u_dma_ofst
|
||||
mov cli_dma_ofst,cx
|
||||
|
||||
mov cx,u_dma_seg
|
||||
mov cli_dma_seg,cx
|
||||
mov clierr,0
|
||||
|
||||
; copy command into local area
|
||||
|
||||
cmp cli_chain,true ! jne cli_cpy
|
||||
|
||||
push es ! push ds
|
||||
mov es,sysdat
|
||||
mov si,cli_dma_ofst
|
||||
mov di,offset cli_cmdtail
|
||||
mov ds,cli_dma_seg
|
||||
mov cx,040H
|
||||
rep movsw
|
||||
pop ds ! pop es
|
||||
jmp cli_parse
|
||||
|
||||
cli_cpy:
|
||||
push es ! push ds
|
||||
mov ds,u_wrkseg ! pop es
|
||||
; DS=Wrkseg, ES=Sysdat, SP->UDA
|
||||
; copy clicb_net
|
||||
mov si,dx ! mov di,offset cli_net
|
||||
movsb
|
||||
; copy command
|
||||
mov si,dx ! add si,clicb_cmd
|
||||
mov di,offset cli_cmdtail
|
||||
mov cx,clicblen-clicb_cmd
|
||||
rep movsb
|
||||
push es ! pop ds ! pop es
|
||||
|
||||
;parse the command
|
||||
cli_parse:
|
||||
call pfn ! jcxz cli_gprs
|
||||
mov clierr,cx
|
||||
jmp cli_exit
|
||||
cli_gprs:
|
||||
|
||||
call shtal
|
||||
|
||||
;fcb has parsed filename
|
||||
;if not explicit disk then
|
||||
; if not RSP try CMD
|
||||
;else try CMD
|
||||
|
||||
cmp cli_fcb,0 ! jne cli_ffload
|
||||
mov bx,(offset cli_fcb)
|
||||
cmp fcb_plen[bx],0 ! jne cli_ffload
|
||||
call cli_checkque ! jnz cli_ffload
|
||||
;successful RSP access
|
||||
cli_qful:
|
||||
cmp cli_chain,true ! jne cli_exit2
|
||||
mov cli_term,true
|
||||
cli_exit2: jmp cli_exit
|
||||
cli_ffload:
|
||||
cmp cx,e_q_full ! jne cli_fload
|
||||
mov clierr,cx ! jmps cli_qful
|
||||
|
||||
cli_checkque:
|
||||
;------------
|
||||
; output: z flag on if successful
|
||||
|
||||
;copy fcb.name to qpb.name
|
||||
|
||||
mov si,(offset cli_fcb)+fcb_name
|
||||
mov di,(offset cli_cuspqpb)+qpb_name
|
||||
mov cx,qnamsiz/2 ! push es ! push ds ! pop es
|
||||
push si ! rep movsw
|
||||
|
||||
;copy fcb.name to acb.name
|
||||
|
||||
pop si ! mov cx,qnamsiz/2
|
||||
mov di,(offset cli_acb)+acb_name
|
||||
rep movsw ! pop es
|
||||
|
||||
;open queue
|
||||
|
||||
mov cx,f_qopen ! mov dx,(offset cli_cuspqpb)
|
||||
call osif ! jcxz cli_goodq
|
||||
retcli1: cmp cx,0 ! ret ;CX = 0ffffh on error
|
||||
|
||||
;we successfully opened the queue
|
||||
;now check RSP flag
|
||||
cli_goodq:
|
||||
mov bx,offset cli_cuspqpb
|
||||
mov bx,qpb_qaddr[bx]
|
||||
test q_flags[bx],qf_rsp ! jnz cli_gq
|
||||
mov cx,e_no_queue ! jmps retcli1
|
||||
|
||||
;write command tail to queue
|
||||
|
||||
cli_gq: mov cx,f_cqwrite ! mov dx,offset cli_cuspqpb
|
||||
call osif ! jcxz cli_qw
|
||||
mov cx,e_q_full ! jmps retcli1
|
||||
|
||||
;successful queue write, assign console
|
||||
|
||||
cli_qw: cmp cli_dfil,true ! jne noqm
|
||||
call prcusp
|
||||
noqm: mov bx,offset cli_acb
|
||||
mov al,cli_cns ! mov acb_cns[bx],al
|
||||
mov acb_match[bx],false
|
||||
mov acb_pd[bx],1 ;match on PD with DSKLD flag off
|
||||
call conasn ! xor cx,cx ! ret
|
||||
|
||||
cli_fload:
|
||||
;---------
|
||||
; Try to Load a file for execution
|
||||
; The Command Line Parsed correctly and we have an FCB
|
||||
; set up. We already know there isn't a queue and a
|
||||
; process by the same name as the command.
|
||||
|
||||
; Obtain a Process Descriptor
|
||||
|
||||
pushf ! cli ! mov bx,pul
|
||||
cmp bx,0 ! jne cli_gpd
|
||||
popf ! mov clierr,e_no_pd
|
||||
jmp cli_exit
|
||||
cli_gpd:
|
||||
mov si,p_link[bx] ! mov pul,si
|
||||
popf ! mov cli_pd,bx
|
||||
; zero PD
|
||||
push es ! push ds ! pop es
|
||||
mov di,bx ! mov cx,pdlen/2
|
||||
xor ax,ax ! rep stosw
|
||||
pop es
|
||||
|
||||
; Initialize the PD for Load
|
||||
|
||||
mov bx,cli_pd
|
||||
mov p_flag[bx],pf_table
|
||||
mov di,bx ! add di,p_name
|
||||
mov si,offset cli_fcb ! add si,fcb_name
|
||||
push es ! mov ax,ds ! mov es,ax
|
||||
mov cx,pnamsiz/2 ! rep movsw
|
||||
pop es
|
||||
mov si,rlr
|
||||
mov al,cli_dsk ! mov p_dsk[bx],al ;inherit parents drive/user
|
||||
mov al,cli_user ! mov p_user[bx],al ;even if we load off another
|
||||
;drive or user
|
||||
|
||||
;this should be in
|
||||
;process create ?
|
||||
|
||||
mov al,cli_cns ! mov p_cns[bx],al
|
||||
mov al,p_lst[si]
|
||||
if mpm
|
||||
sub al,ncondev
|
||||
endif
|
||||
mov p_lst[bx],al
|
||||
|
||||
; 3. Open the file
|
||||
|
||||
mov si,(offset cli_fcb)+fcb_pwd
|
||||
mov di,offset cli_dma
|
||||
push es ! mov es,sysdat
|
||||
mov cx,4 ! rep movsw
|
||||
pop es
|
||||
mov u_dma_ofst,offset cli_dma
|
||||
mov u_dma_seg,ds
|
||||
|
||||
mov si,offset cli_fcb
|
||||
mov byte ptr fcb_type[si],'C'
|
||||
mov byte ptr fcb_type+1[si],'M'
|
||||
mov byte ptr fcb_type+2[si],'D'
|
||||
|
||||
; Open the CMD file
|
||||
|
||||
mov u_error_mode,0feh
|
||||
call flopn
|
||||
cmp bl,0ffh ! jne cli_gopen
|
||||
|
||||
; on failure,
|
||||
; if default is not system disk
|
||||
; and not an explicit disk then
|
||||
; try CMD file on System disk
|
||||
|
||||
cmp bh,0 ! jne cli_bo ;extended error
|
||||
mov cl,srchdisk
|
||||
cmp cl,cli_dsk ! je cli_bo ;already on system disk
|
||||
cmp cli_fcb,0 ! jne cli_bo ;check for explicit
|
||||
;select
|
||||
; try system disk
|
||||
|
||||
; mov bx,rlr
|
||||
|
||||
; mov p_dsk[bx],cl
|
||||
inc cl
|
||||
mov cli_fcb,cl ;set drive byte to
|
||||
call flopn ;system disk
|
||||
cmp bl,0ffh ! je cli_bo
|
||||
|
||||
|
||||
;make sure SYS attribute is on...
|
||||
|
||||
mov bx,offset cli_fcb
|
||||
test byte ptr fcb_type+1[bx],080h ! jnz cli_gopen
|
||||
|
||||
|
||||
;We opened a NON-SYS file. Do explicit open
|
||||
;on user zero if not already
|
||||
|
||||
call flclse
|
||||
mov bx,rlr
|
||||
cmp p_user[bx],0 ! je cli_boe
|
||||
mov p_user[bx],0
|
||||
call flopn
|
||||
cmp bl,0ffh ! je cli_bo
|
||||
mov bx,offset cli_fcb
|
||||
test byte ptr fcb_type+1[bx],080h
|
||||
jnz cli_gopen
|
||||
call flclse
|
||||
jmps cli_boe
|
||||
|
||||
;could not find CMD file
|
||||
|
||||
|
||||
cli_bo: cmp bh,0 ! jne cli_rmpd2
|
||||
cli_boe: mov clierr,e_bad_open
|
||||
cli_rmpd2: jmp cli_rmpd
|
||||
cli_gopen:
|
||||
|
||||
; 8. Call the load function
|
||||
|
||||
mov bx,rlr
|
||||
test p_flag[bx],pf_ctlc ! jz cli_ld1
|
||||
mov bx,0ffffh ! mov cx,e_abort
|
||||
jmp cli_cl
|
||||
|
||||
cli_ld1:
|
||||
cmp cmod,true ! jne not_cmod
|
||||
mov bx,cli_pd
|
||||
mov si,offset cli_fcb
|
||||
|
||||
;test F1 bit
|
||||
mov p_cmod[bx],0
|
||||
test byte ptr fcb_name[si],080h ! jz not_f1
|
||||
or p_cmod[bx],080h
|
||||
|
||||
;test F2 bit
|
||||
not_f1: test byte ptr fcb_name+1[si],080h ! jz not_f2
|
||||
or p_cmod[bx],040h
|
||||
|
||||
;test F3 bit
|
||||
not_f2:
|
||||
|
||||
;if mpm dave brown test
|
||||
test byte ptr fcb_name+2[si],080h
|
||||
jz not_f3
|
||||
;endif
|
||||
|
||||
or p_cmod[bx],020h
|
||||
|
||||
;test F4 bit
|
||||
not_f3: test byte ptr fcb_name+3[si],80h ! jz not_cmod
|
||||
or p_cmod[bx],070h
|
||||
not_cmod:
|
||||
|
||||
cmp cli_chain,true ! jne cli_kuda
|
||||
mov bx,cli_pd
|
||||
mov p_uda[bx],es
|
||||
mov ax,offset inituda
|
||||
mov cl,4 ! shr ax,cl
|
||||
add ax,sysdat
|
||||
mov bx,es ! mov es,ax ! mov di,0
|
||||
mov ds,bx ! mov si,di
|
||||
mov cx,ulen/2
|
||||
rep movsw
|
||||
pushf ! cli ! pop dx
|
||||
mov ax,es
|
||||
mov ds,sysdat
|
||||
mov ss,ax
|
||||
mov bx,rlr
|
||||
mov p_uda[bx],ax
|
||||
push dx ! popf
|
||||
cli_kuda:
|
||||
cmp cli_dfil,true ! jne noprfil
|
||||
call prfilnam
|
||||
call crlf
|
||||
|
||||
noprfil:mov bx,cli_pd
|
||||
mov dx,offset cli_fcb
|
||||
mov cx,f_load
|
||||
cmp cli_chain,true ! jne cli_ld
|
||||
mov cli_term,true
|
||||
cli_ld: call osif
|
||||
cli_cl: push bx ! push cx
|
||||
mov u_error_mode,0
|
||||
call flclse
|
||||
pop cx ! pop bx
|
||||
jcxz cli_gload
|
||||
cmp cx,e_abort ! jne cli_lnab
|
||||
jmp cli_rmpd
|
||||
cli_lnab: mov clierr,cx
|
||||
jmp cli_rmpd
|
||||
cli_gload:
|
||||
mov cli_bpage,bx
|
||||
|
||||
; 9a. Parse Command Tail
|
||||
|
||||
; copy cmdtail to user DMA buffer
|
||||
|
||||
push es ! mov es,cli_bpage
|
||||
mov di,offset bpg_dma+1
|
||||
|
||||
mov si,offset cli_cmdtail
|
||||
mov cx,127
|
||||
rep movsb ! pop es
|
||||
|
||||
; count cmd length and convert
|
||||
; to upper case
|
||||
|
||||
push ds ! mov ds,cli_bpage
|
||||
mov cl,0 ! mov di,offset bpg_dma+1
|
||||
ncmdchar:
|
||||
cmp byte ptr [di],0 ! je endtail
|
||||
|
||||
; convert CMD tail to UPPER CASE
|
||||
|
||||
cmp byte ptr [di],'a' ! jb nlow
|
||||
cmp byte ptr [di],'z' ! ja nlow
|
||||
and byte ptr [di],05fh
|
||||
nlow:
|
||||
|
||||
|
||||
|
||||
inc di ! inc cl ! jmps ncmdchar
|
||||
endtail:
|
||||
mov bpg_dma,cl ! pop ds
|
||||
|
||||
; load disk init, location 50H
|
||||
; of base page is done in LOAD
|
||||
|
||||
push es ! mov es,cli_bpage
|
||||
|
||||
; init default fcb
|
||||
|
||||
mov di,offset bpg_fcb0
|
||||
xor ax,ax ! stosb ;default disk
|
||||
mov al,' '
|
||||
mov cx,11 ! rep stosb ;name,type
|
||||
xor ax,ax
|
||||
mov cx,2 ! rep stosw ;other
|
||||
push ds ! push es ! pop ds
|
||||
mov si,offset bpg_fcb0
|
||||
mov cx,8 ! rep movsw
|
||||
pop ds ! pop es
|
||||
|
||||
; if cmdtail, parse
|
||||
|
||||
cmp cli_cmdtail,0 ! je ctdone
|
||||
call pfn
|
||||
cmp bx,0ffffh ! je ctdone
|
||||
|
||||
; copy fcb to user fcb front
|
||||
|
||||
push es ! mov es,cli_bpage
|
||||
mov di,offset bpg_fcb0
|
||||
mov si,offset cli_fcb
|
||||
mov ax,fcb_pptr[si]
|
||||
; AX->password in CLI_CMDTAIL
|
||||
sub ax,offset cli_cmdtail
|
||||
add ax,offset bpg_dma + 1
|
||||
; AX->password in Base Page
|
||||
mov es:bpg_pw1ptr,ax
|
||||
mov al,fcb_plen[si]
|
||||
mov es:bpg_pw1len,al
|
||||
mov cx,8 ! rep movsw ! pop es
|
||||
|
||||
; if more cmdtail, parse
|
||||
|
||||
cmp bx,0 ! je ctdone
|
||||
push cli_pcb ! inc bx
|
||||
mov cli_pcb,bx
|
||||
call pfn
|
||||
pop cli_pcb
|
||||
cmp bx,0ffffh ! je ctdone
|
||||
|
||||
; copy 2nd fcb front
|
||||
|
||||
push es ! mov es,cli_bpage
|
||||
mov di,offset bpg_fcb1
|
||||
mov si,offset cli_fcb
|
||||
mov ax,fcb_pptr[si]
|
||||
; AX->password in CLI_CMDTAIL
|
||||
sub ax,offset cli_cmdtail
|
||||
add ax,offset bpg_dma + 1
|
||||
; AX->password in Base Page
|
||||
mov es:bpg_pw2ptr,ax
|
||||
mov al,fcb_plen[si]
|
||||
mov es:bpg_pw2len,al
|
||||
mov cx,8
|
||||
rep movsw
|
||||
pop es
|
||||
ctdone:
|
||||
|
||||
; 10. Create the process
|
||||
|
||||
cmp cli_chain,true ! jne nprior
|
||||
mov cx,f_setprior
|
||||
mov dx,1 ! call osif
|
||||
nprior:
|
||||
mov si,cli_pd ! or p_flag[si],pf_dskld ;from disk, to differ
|
||||
mov dx,si ! mov cx,f_createproc ;from RSP with same name
|
||||
call osif
|
||||
|
||||
; 11. Assign Console to new process
|
||||
|
||||
mov bx,rlr
|
||||
and p_flag[bx],not pf_ctlc
|
||||
|
||||
; Check to see if user hit CTRL D
|
||||
test p_flag[bx],pf_ctld ! jz asgn
|
||||
and p_flag[bx],not pf_ctld
|
||||
mov bx,cli_pd
|
||||
or p_flag[bx],pf_ctld
|
||||
jmp cli_exit
|
||||
asgn: mov bx,offset cli_acb
|
||||
mov al,cli_cns ! mov acb_cns[bx],al
|
||||
mov ax,cli_pd ! mov acb_pd[bx],ax
|
||||
mov acb_match[bx],true
|
||||
call conasn
|
||||
mov clierr,cx
|
||||
|
||||
jmps cli_exit
|
||||
|
||||
; 12. All Done
|
||||
|
||||
cli_rmpd: ; release PD
|
||||
|
||||
mov si,cli_pd
|
||||
|
||||
; Release any memory that might still be
|
||||
; associated with the PD. This could
|
||||
; happen from a CTRL C.
|
||||
|
||||
cmp p_mem[si],0 ! je rmpd1
|
||||
push ds ! push es
|
||||
push si
|
||||
mov si,p_mem[si]
|
||||
push ms_start[si]
|
||||
mov cx,f_memfree
|
||||
mov dx,sp
|
||||
mov ax,ss ! mov ds,ax
|
||||
call osif
|
||||
pop ax ! pop si
|
||||
pop es ! pop ds
|
||||
jmps cli_rmpd
|
||||
|
||||
; Place empty PD on PUL.
|
||||
|
||||
rmpd1: pushf ! cli
|
||||
mov bx,pul
|
||||
mov p_link[si],bx ! mov pul,si
|
||||
popf
|
||||
|
||||
; Normal EXIT
|
||||
|
||||
cli_exit: ; close file and release CLI SYNC
|
||||
mov bx,rlr
|
||||
mov cl,cli_dsk ! mov p_dsk[bx],cl
|
||||
mov cl,cli_user ! mov p_user[bx],cl
|
||||
mov cl,cli_err_mode ! mov u_error_mode,cl
|
||||
mov cx,cli_dma_ofst ! mov u_dma_ofst,cx
|
||||
mov cx,cli_dma_seg ! mov u_dma_seg,cx
|
||||
cmp cli_chain,true ! jne clirls
|
||||
mov bx,rlr ! mov si,cli_pd ;inherit calling PD's
|
||||
mov ax,p_parent[bx] ;parent if chaining
|
||||
mov p_parent[si],ax
|
||||
cmp cli_term,true ! jne clirls
|
||||
and p_flag[bx],not (pf_keep+pf_sys+pf_tempkeep+pf_ctlc)
|
||||
mov cx,f_terminate ;TERM_ACT in dispatcher
|
||||
jmp osif ;releases CLI_SYNC
|
||||
clirls:
|
||||
push cli_pflag
|
||||
push cli_err
|
||||
call cli_unsync
|
||||
pop dx
|
||||
pop ax ! and ax,pf_tempkeep+pf_noctls
|
||||
mov bx,rlr ! mov cx,p_flag[bx]
|
||||
and cx,not pf_tempkeep+pf_noctls
|
||||
or cx,ax ! mov p_flag[bx],cx
|
||||
test p_flag[bx],pf_ctlc ! jz cli_nctl
|
||||
mov cx,f_terminate ! xor dx,dx
|
||||
call osif
|
||||
and p_flag[bx],not pf_ctlc
|
||||
mov dx,e_abort
|
||||
|
||||
; setup error return if needed
|
||||
cli_nctl:
|
||||
|
||||
mov cx,dx
|
||||
xor bx,bx
|
||||
jcxz cli_gexit
|
||||
mov bx,0ffffh
|
||||
|
||||
cli_gexit:
|
||||
ret
|
||||
|
||||
shtal:
|
||||
;---------
|
||||
; setup command tail to be parsed
|
||||
; input: AX = output of previous parsefilename
|
||||
|
||||
cmp ax,0 ! je ntail
|
||||
|
||||
;shift command tail to beginning
|
||||
;of command buffer
|
||||
|
||||
push ax ! sub ax,offset cli_cmdtail
|
||||
mov cx,128 ! sub cx,ax ! shr cx,1
|
||||
pop si ! mov di,offset cli_cmdtail
|
||||
push es ! push ds ! pop es
|
||||
rep movsw ! pop es
|
||||
ret
|
||||
ntail:
|
||||
mov cli_cmdtail,0
|
||||
ret
|
||||
|
||||
;============================
|
||||
; Various string subroutines
|
||||
|
||||
crlf: mov dl,13 ! call prchar
|
||||
mov dl,10
|
||||
;jmps prchar
|
||||
|
||||
prchar:
|
||||
mov si,u_conccb
|
||||
mov di,rlr
|
||||
cmp [si],di ! jne prr
|
||||
mov cx,f_conout ! jmp osif
|
||||
prr: ret
|
||||
|
||||
prtime: mov dl,tod_hr ! call prnum
|
||||
mov dl,':' ! call prchar
|
||||
mov dl,tod_min ! call prnum
|
||||
mov dl,':' ! call prchar
|
||||
mov dl,tod_sec ! call prnum
|
||||
mov dl,' ' ! jmps prchar
|
||||
|
||||
prnum: push dx ! mov cl,4
|
||||
shr dl,cl ! add dl,'0'
|
||||
call prchar
|
||||
pop dx ! and dl,0fh
|
||||
add dl,'0' ! jmps prchar
|
||||
|
||||
prfilnam:
|
||||
call prdisk
|
||||
mov dx,(offset cli_fcb)+fcb_name
|
||||
call prnam
|
||||
mov dl,'.' ! call prchar
|
||||
mov dx,(offset cli_fcb) + fcb_type
|
||||
call prtyp
|
||||
mov dl,' ' ! call prchar
|
||||
mov bx,offset cli_fcb
|
||||
test byte ptr fcb_name+7[bx],080h ! jnz pruser
|
||||
cmp cli_user,0 ! je pret
|
||||
mov bx,rlr
|
||||
cmp p_user[bx],0 ! je pruser
|
||||
pret: ret
|
||||
|
||||
pruser: mov dx,offset userstr
|
||||
jmps prcsm
|
||||
|
||||
prdisk: mov dl,cli_fcb
|
||||
cmp dl,0 ! je prpddsk
|
||||
dec dl ! jmps prdsk1
|
||||
|
||||
prpddsk:
|
||||
mov bx,rlr
|
||||
mov dl,p_dsk[bx]
|
||||
prdsk1: add dl,'A' ! call prchar
|
||||
mov dl,':' ! jmp prchar
|
||||
|
||||
prcusp: mov dx,(offset cli_cuspqpb) + qpb_name
|
||||
call prnam ! mov dx,offset questr
|
||||
call prcsm ! jmp crlf
|
||||
|
||||
prcsm: mov si,u_conccb
|
||||
mov di,rlr
|
||||
cmp [si],di ! jne prr1
|
||||
xor bx,bx ! push ds
|
||||
mov ax,cs ! mov ds,ax
|
||||
call cprnt1 ! pop ds
|
||||
prr1: ret
|
||||
|
||||
prtyp: mov bh,3 ! jmps prn1
|
||||
prnam: mov bh,8
|
||||
prn1: mov bl,' '
|
||||
mov si,u_conccb
|
||||
mov di,rlr
|
||||
cmp [si],di ! jne prr1
|
||||
cprnt1: mov cx,f_conprint ! jmps jos
|
||||
|
||||
flclse:
|
||||
mov cx,f_fclose ! mov dx,offset cli_fcb
|
||||
jmps fo1
|
||||
flopn:
|
||||
mov cx,f_fopen
|
||||
mov si,offset cli_fcb
|
||||
or byte ptr fcb_name+5[si],080h ;f6`=open read-only
|
||||
mov dx,si
|
||||
fo1: push es ! call osif ! pop es ! ret
|
||||
|
||||
cli_sync:mov cx,f_sync
|
||||
jmps mx1
|
||||
|
||||
cli_unsync: mov cx,f_unsync
|
||||
mx1: mov bx,offset cli_spb
|
||||
jos: jmp osif
|
||||
|
||||
pfn: mov dx,offset cli_pcb ! mov cx,f_parsefilename
|
||||
jmps jos
|
||||
|
||||
conasn: mov cx,f_conassign ! mov dx,offset cli_acb
|
||||
jmps jos
|
||||
|
||||
questr db ' Msg Qued',0
|
||||
|
||||
userstr db '(User 0)',0
|
||||
@@ -0,0 +1,428 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Character I/O ownership routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;===============
|
||||
lstattach_entry:
|
||||
;===============
|
||||
xor cx,cx ;unconditional attach code
|
||||
jmps lcb_verify
|
||||
|
||||
;===============
|
||||
clstattch_entry:
|
||||
;===============
|
||||
mov cx,0ffffh ;conditional attach code
|
||||
|
||||
lcb_verify:
|
||||
;----------
|
||||
push cx
|
||||
mov si,u_lstccb ;U_LSTCCB=0 if not yet initialized
|
||||
test si,si ! jnz lcb_ok
|
||||
call getlcbadr
|
||||
mov u_lstccb,si
|
||||
lcb_ok:
|
||||
pop cx ;restore attach code
|
||||
jmps cioattach
|
||||
|
||||
;===============
|
||||
conattach_entry:
|
||||
;===============
|
||||
xor cx,cx ;unconditional attach code
|
||||
jmps ccb_verify
|
||||
|
||||
;===============
|
||||
cconattch_entry:
|
||||
;===============
|
||||
mov cx,0ffffh ;conditional attach code
|
||||
ccb_verify:
|
||||
push cx
|
||||
mov si,u_conccb
|
||||
test si,si ! jnz ccb_ok
|
||||
call getccbadr
|
||||
mov u_conccb,si
|
||||
ccb_ok:
|
||||
pop cx ;conditional attach if 0ffffh
|
||||
;jmps cioattach
|
||||
|
||||
;=========
|
||||
cioattach: ;NOTE: PIN does attaches also for ^P
|
||||
;=========
|
||||
; Attach calling process to default ciodev.
|
||||
; if ciodev is being used, sleep on c_queue
|
||||
; until another process detaches from device
|
||||
; and calling process is next in queue.
|
||||
; input: SI = CCB address of device
|
||||
; DI = offset of dev number in PD
|
||||
; CX = 0ffffh if conditional
|
||||
|
||||
mov ax,rlr ! mov bx,ax
|
||||
; BX = PD addr
|
||||
; SI = CCB addr
|
||||
; CX = Condition Flag
|
||||
pushf ! cli
|
||||
cmp bx,c_attach[si] ! je ca_ret ;we already own it
|
||||
cmp c_attach[si],0 ! je ca_atch ;nobody owns it, we'll take it
|
||||
jcxz ca_sleep ;somebody else owns it
|
||||
popf ! mov bx,0ffffh ;or it is a mimic list (0ffffh)
|
||||
mov cx,e_no_attach ! ret ;- no attach in either case
|
||||
ca_sleep:
|
||||
push dx ;save DH=cons #
|
||||
lea dx,c_queue[si] ;unconditional if CX=0
|
||||
mov bl,ps_ciowait
|
||||
push si
|
||||
mov cx,f_sleep ! call osif
|
||||
pop si ! pop dx ! popf ! xor cx,cx
|
||||
jmps cioattach
|
||||
ca_atch: mov c_attach[si],bx
|
||||
ca_ret: popf ! xor bx,bx ! ret
|
||||
|
||||
;===============
|
||||
lstdetach_entry:
|
||||
;===============
|
||||
call lcb_verify ;ensure U_LSTCCB is non zero
|
||||
jmps ciodetach
|
||||
|
||||
;===============
|
||||
condetach_entry:
|
||||
;===============
|
||||
call ccb_verify ;ensure U_CONCCB is non zero
|
||||
;jmps ciodetach
|
||||
|
||||
;=========
|
||||
ciodetach: ;NOTE PIN also does detaching for ^P
|
||||
;=========
|
||||
; Detach Calling process from default ciodev.
|
||||
; If current owner of ciodev then zero c_attach
|
||||
; and wakeup the c_queue list to give another
|
||||
; process the ciodev.
|
||||
; input: SI = CCB addr of device
|
||||
|
||||
mov bx,rlr
|
||||
; SI = CCB address
|
||||
; BX = PD address
|
||||
pushf ! cli
|
||||
cmp c_attach[si],0 ! je cd_ret
|
||||
cmp c_attach[si],bx ! je cd_detach
|
||||
popf ! mov bx,0ffffh
|
||||
mov cx,e_not_owner ! ret
|
||||
cd_detach:
|
||||
mov ax,c_queue[si]
|
||||
mov c_attach[si],ax
|
||||
mov cx,f_wakeup
|
||||
lea dx,c_queue[si]
|
||||
call osif
|
||||
cd_ret:
|
||||
popf
|
||||
xor bx,bx ! ret
|
||||
|
||||
|
||||
;===============
|
||||
conassign_entry:
|
||||
;===============
|
||||
; Attach specified console to specified process
|
||||
;
|
||||
; entry: U_WRKSEG:DX -> ACB
|
||||
;
|
||||
; +-----+-----+-----+-----+
|
||||
; | CNS |Match| PD Addr |
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; | Name |
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;
|
||||
; CNS - console to assign
|
||||
; Match - if not 0,
|
||||
; PD's default console must match acb_cns
|
||||
; PD Addr - PD address to assign to
|
||||
; Name - use PD name to assign, if PD addr=0
|
||||
; Name - use PD name to assign, if PD addr=1,
|
||||
; but also ensure DSKLD flag is off
|
||||
; (DiSK LoaD is set when PD was created
|
||||
; from disk transient, RSPs have DSKLD=0)
|
||||
; Should check for DSKLD=1 if PD addr = 0
|
||||
; but we may have compatibility issues
|
||||
;
|
||||
; exit: BX = 0 if success, 0ffffh if failure
|
||||
; CX = Error Code
|
||||
|
||||
push dx ;save ACB
|
||||
mov bx,offset thrd_spb ;get ownership of thread
|
||||
mov cx,f_sync
|
||||
call osif
|
||||
pop di ;U_WRKSEG:DI->ACB
|
||||
mov indisp,true ;stop dispatching
|
||||
|
||||
push ds ;save SYSDAT
|
||||
mov ds,u_wrkseg
|
||||
cmp acb_pd[di],1 ;name or address match ?
|
||||
jbe as_name
|
||||
|
||||
mov bx,acb_pd[di] ;find by PD address
|
||||
pop ds ;DS=SYSDAT
|
||||
mov si,(offset thrdrt)-p_thread
|
||||
as_next1: ;verify PD is on thread
|
||||
mov si,p_thread[si]
|
||||
test si,si ! jz as_nom ;no match if end of thread
|
||||
cmp bx,si ! je as_found_id
|
||||
jmps as_next1
|
||||
as_found_id:
|
||||
call as_chk ;check console match
|
||||
jcxz as_mok ;match ok
|
||||
jmps as_nom ;no match
|
||||
|
||||
as_name: ;look for PD by name on thread
|
||||
pop ds ;DS=SYSDAT
|
||||
mov bx,(offset thrdrt)-p_thread
|
||||
as_next2: ;look for PD by name on thread
|
||||
push di ;save ACB
|
||||
lea dx,acb_name[di] ;U_WRKSEG:DI->ACB
|
||||
mov ds,u_wrkseg ;DS:DX->ASCII name
|
||||
mov cx,f_findpdname
|
||||
call osif
|
||||
mov ds,sysdat
|
||||
pop di ;ACB
|
||||
jcxz as_okname ;CX<>0 if no match
|
||||
|
||||
as_nom:
|
||||
mov cx,e_no_pdname ;couldn't find PD specified
|
||||
jmps as_err ;by ACB on thread list
|
||||
as_okname:
|
||||
;matched PD by name check by ACB
|
||||
call as_chk ;BX->PD matched by name
|
||||
jcxz as_mok
|
||||
;console or DSKLD didn't match
|
||||
jmps as_next2 ;search for another PD
|
||||
|
||||
as_mok: ;match OK, found the PD
|
||||
push bx ! push di ;BX=matched PD, DI=ACB
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
pop di ! pop ax ;DI=ACB, AX=matched PD
|
||||
|
||||
mov ds,u_wrkseg
|
||||
push ax ;save matched PD
|
||||
mov al,acb_cns[di]
|
||||
mov ds,sysdat
|
||||
call getccbadr_spec ;SI=CCB on return
|
||||
mov bx,rlr ;BX=running process
|
||||
pop ax ;AX=matched PD
|
||||
|
||||
cmp c_attach[si],0 ;and change CCB
|
||||
je as_ok ;CCB must be unused (0) or
|
||||
cmp c_attach[si],bx ;running process must own it
|
||||
je as_ok
|
||||
mov cx,e_not_owner
|
||||
as_err:
|
||||
push cx ;save error code
|
||||
call as_ok_disp
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
pop cx
|
||||
mov bx,0ffffh
|
||||
ret
|
||||
as_ok:
|
||||
mov c_attach[si],ax ;new owner
|
||||
push ax ! push si ;save owner and CCB
|
||||
call as_ok_disp ;allow dispatches
|
||||
pop si ! pop ax
|
||||
mov bx,ax ;AX=BX=new owner
|
||||
add si,c_queue-p_link ;go down CCB queue for PD
|
||||
mov di,si ;DI=SI=address of CCB.QUEUE
|
||||
as_nqpd:
|
||||
cmp p_link[si],0 ;look on C_QUEUE for PD being
|
||||
jz as_gexit ;assigned the console
|
||||
cmp p_link[si],bx
|
||||
je as_qfix
|
||||
mov si,p_link[si]
|
||||
jmps as_nqpd ;next PD
|
||||
as_qfix:
|
||||
mov ax,p_link[bx] ;take PD out of C_QUEUE
|
||||
mov p_link[si],ax
|
||||
mov si,p_link[di] ;SI = first PD on C_QUEUE
|
||||
mov p_link[di],bx ;put PD in front of C_QUEUE
|
||||
mov p_link[bx],si ;attach rest of list
|
||||
mov dx,di ;pass C_QUEUE address to wakeup
|
||||
mov cx,f_wakeup
|
||||
call osif
|
||||
as_gexit:
|
||||
xor bx,bx
|
||||
ret
|
||||
|
||||
as_ok_disp:
|
||||
;----------
|
||||
; entry: none
|
||||
; exit: none
|
||||
; Allow dispatching
|
||||
|
||||
mov indisp,false
|
||||
pushf ! cli
|
||||
cmp drl,0 ! je as_nwake
|
||||
mov cx,f_dispatch
|
||||
call osif
|
||||
as_nwake:
|
||||
popf ! ret
|
||||
|
||||
as_chk:
|
||||
;------
|
||||
; check PD against Assign Control Block parameters
|
||||
; entry: BX = PD to check
|
||||
; U_WRKSEG:DI = ACB
|
||||
; exit: CX = 0 if assign match
|
||||
; CX <> 0 if no match
|
||||
; CX,AX used
|
||||
|
||||
xor cx,cx
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg
|
||||
mov ax,es:acb_pd[di]
|
||||
cmp ax,1 ;if >1 then matching on PD address
|
||||
ja asc_cns
|
||||
dec ax
|
||||
jnz asc_cns
|
||||
test p_flag[bx],pf_dskld ;RSP, DSKLD must be off
|
||||
jnz asc_no
|
||||
asc_cns:
|
||||
cmp es:acb_match[di],0 ;console match requested ?
|
||||
je asc_ok
|
||||
mov al,es:acb_cns[di] ;must match on console
|
||||
cmp al,p_cns[bx]
|
||||
je asc_ok
|
||||
asc_no:
|
||||
inc cx
|
||||
asc_ok:
|
||||
pop es ;ES=UDA
|
||||
ret
|
||||
|
||||
;=============== =====================
|
||||
getdefcon_entry: ; Get Default Console
|
||||
;=============== =====================
|
||||
|
||||
mov si,rlr
|
||||
xor bh,bh ! mov bl,p_cns[si]
|
||||
ret
|
||||
|
||||
;=============== ==================
|
||||
getdeflst_entry: ; Get Default List
|
||||
;=============== ==================
|
||||
|
||||
mov si,rlr
|
||||
xor bh,bh ! mov bl,p_lst[si]
|
||||
ret
|
||||
|
||||
;=============== =====================
|
||||
setdefcon_entry: ; Set Default Console
|
||||
;=============== =====================
|
||||
|
||||
cmp dl,ncondev
|
||||
jb sd_good
|
||||
mov cx,e_ill_cns
|
||||
mov bx,0ffffh ! ret
|
||||
sd_good:
|
||||
mov si,rlr
|
||||
mov p_cns[si],dl
|
||||
call getccbadr
|
||||
mov u_conccb,si
|
||||
xor bx,bx
|
||||
ret
|
||||
|
||||
;=============== ==================
|
||||
setdeflst_entry: ; Set Default List
|
||||
;=============== ==================
|
||||
|
||||
cmp dl,nlstdev
|
||||
jb sdl_good
|
||||
mov cx,e_ill_lst
|
||||
mov bx,0ffffh ! ret
|
||||
sdl_good:
|
||||
mov si,rlr
|
||||
mov p_lst[si],dl
|
||||
call getlcbadr
|
||||
mov u_lstccb,si
|
||||
xor bx,bx
|
||||
ret
|
||||
|
||||
|
||||
getccbadr:
|
||||
;---------
|
||||
; get CCB for calling process' console device
|
||||
; input: None
|
||||
; output: SI = address of CCB
|
||||
; BX = running PD address
|
||||
|
||||
mov bx,rlr
|
||||
mov al,p_cns[bx]
|
||||
|
||||
getccbadr_spec: ;AL is console number
|
||||
xor ah,ah ;when called from ASSIGN
|
||||
mov si,ccb
|
||||
mov cl,2
|
||||
shl ax,cl
|
||||
add si,ax ;+4
|
||||
add si,ax ;+4 = 8
|
||||
add si,ax ;+4 =12
|
||||
mov cl,3
|
||||
shl ax,cl
|
||||
add si,ax ;+32 =44
|
||||
ret
|
||||
|
||||
getlcbadr:
|
||||
;---------
|
||||
; Get LCB for calling process list device
|
||||
; entry: None
|
||||
; output: SI = address of LCB
|
||||
; BX = PD address
|
||||
|
||||
mov bx,rlr
|
||||
xor ah,ah
|
||||
mov al,p_lst[bx]
|
||||
mov si,lcb
|
||||
push ax ;lcb#
|
||||
shl ax,1 ;2*lcb#
|
||||
add si,ax ;lcbadr + 2*lcb#
|
||||
pop ax ;lcb#
|
||||
mov cl,3
|
||||
shl ax,cl ;8*lcb#
|
||||
add si,ax ;lcbadr + 2*lcb# + 8*lcb#
|
||||
ret
|
||||
|
||||
|
||||
;=======
|
||||
cioterm:
|
||||
;=======
|
||||
; Detach Calling process from all character devices.
|
||||
; Called only from the dispatcher
|
||||
|
||||
mov al,ncondev
|
||||
mov si,ccb
|
||||
nxtccb: cmp al,0 ! je ct_dlcb
|
||||
cmp si,u_conccb ! jne ct_dccb
|
||||
and c_flag[si],not (cf_conout + cf_vout + cf_bufp)
|
||||
mov cx,f_wakeup ;release proc waiting for XIOS conout
|
||||
lea dx,c_cosleep[si]
|
||||
push ax ! push si
|
||||
call osif
|
||||
pop si ! pop ax
|
||||
ct_dccb:
|
||||
push ax ! push si
|
||||
call ciodetach
|
||||
pop si ! pop ax
|
||||
dec al
|
||||
add si,ccblen
|
||||
jmps nxtccb
|
||||
|
||||
ct_dlcb:
|
||||
mov al,nlstdev
|
||||
mov si,lcb
|
||||
ct_nlcb:
|
||||
cmp al,0 ! je ct_ret
|
||||
push ax ! push si
|
||||
call ciodetach
|
||||
pop si ! pop ax
|
||||
dec al
|
||||
add si,lcblen
|
||||
jmps ct_nlcb
|
||||
|
||||
ct_ret: xor bx,bx ! ret
|
||||
@@ -0,0 +1,237 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MEM Entry Points
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
; Format of Memory Control Block used
|
||||
; in CP/M-86 Memory Calls (53 - 58)
|
||||
;
|
||||
; +-----------+-----------+-----+
|
||||
; MCB | Base | Length | ext |
|
||||
; +-----------+-----------+-----+
|
||||
;
|
||||
|
||||
mcb_base equ word ptr 0
|
||||
mcb_length equ word ptr mcb_base + word
|
||||
mcb_ext equ byte ptr mcb_length + word
|
||||
mcblen equ mcb_ext + byte
|
||||
|
||||
|
||||
;============ =====================
|
||||
maxmem_entry: ; 53 - Get Max Memory
|
||||
;============ =====================
|
||||
; input: DX = address of MCB in u_wrkseg
|
||||
; output: BX = 0ffffh if failure
|
||||
; 0h if success
|
||||
; CX = Error Code
|
||||
; mcb_ext = 0 if no additional mem
|
||||
; 1 if more available
|
||||
|
||||
mov si,dx
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov dx,mcb_length[si] ! pop ds
|
||||
sub ax,ax ! mov bx,ax
|
||||
call getmemory ! jcxz mm_gm
|
||||
mov bx,0ffffh ! ret
|
||||
mm_gm: push ds ! mov ds,u_wrkseg
|
||||
mov mcb_length[si],dx
|
||||
mov mcb_base[si],ax
|
||||
mov mcb_ext[si],1
|
||||
pop ds ! sub bx,bx ! ret
|
||||
|
||||
;============
|
||||
absmax_entry: ; 54 - Get Abs Max Mem
|
||||
;============
|
||||
; Allocate the largest absolute memory region which
|
||||
; is less than or equal mcb_length
|
||||
; input: DX = address of MCB in u_wrkseg
|
||||
; output: BX = 0ffffh if failure
|
||||
; 0h if success
|
||||
; CX = Error Code
|
||||
|
||||
mov si,dx
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov ax,mcb_base[si]
|
||||
mov dx,mcb_length[si] ! pop ds
|
||||
sub bx,bx
|
||||
call getmemory ! jcxz am_gm
|
||||
mov bx,0ffffh ! ret
|
||||
am_gm: push ds ! mov ds,u_wrkseg
|
||||
mov mcb_length[si],dx
|
||||
mov mcb_base[si],ax
|
||||
pop ds ! sub bx,bx ! ret
|
||||
|
||||
;==============
|
||||
cpmalloc_entry: ; 55 - Alloc Mem
|
||||
;==============
|
||||
; Allocate a memory region which is equal to mcb_length
|
||||
;
|
||||
; input: DX = address of MCB in u_wrkseg
|
||||
; output: BX = 0ffffh if failure
|
||||
; 0h if success
|
||||
; CX = Error Code
|
||||
|
||||
mov si,dx
|
||||
push ds ! mov ds,u_wrkseg
|
||||
sub ax,ax ! mov bx,mcb_length[si]
|
||||
mov dx,bx ! pop ds
|
||||
call getmemory ! jcxz ca_gm
|
||||
mov bx,0ffffh ! ret
|
||||
ca_gm: push ds ! mov ds,u_wrkseg
|
||||
mov mcb_length[si],dx
|
||||
mov mcb_base[si],ax
|
||||
pop ds ! sub bx,bx ! ret
|
||||
|
||||
|
||||
;=============
|
||||
cpmabsa_entry: ; 56 - Alloc Abs Mem
|
||||
;=============
|
||||
; Allocate an absolut memory region which is
|
||||
; equal to mcb_length. Note: For CP/M-86
|
||||
; compatibility, this function must return success
|
||||
; if the memory is already allocated because
|
||||
; the GET MAX functions allocate memory in MP/M, CCP/M
|
||||
; and not in CP/M.
|
||||
;
|
||||
; input: DX = address of MCB in u_wrkseg
|
||||
; output: BX = 0ffffh if failure
|
||||
; 0h if success
|
||||
; CX = Error Code
|
||||
|
||||
mov si,dx
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov ax,mcb_base[si]
|
||||
mov bx,mcb_length[si]
|
||||
mov dx,bx ! pop ds
|
||||
|
||||
|
||||
; See if We already own this memory
|
||||
; SI -> MCB in U_WRKSEG
|
||||
; AX=Base, BX=Length, DX=Length
|
||||
|
||||
xor cx,cx
|
||||
mov di,rlr
|
||||
add di,p_mem-ms_link
|
||||
caa_n: mov di,ms_link[di]
|
||||
cmp di,0 ! je caa_g
|
||||
cmp ms_start[di],ax ! jne caa_n
|
||||
cmp ms_length[di],bx ! jbe caa_gm
|
||||
mov cx,e_no_memory
|
||||
mov bx,0ffffh ! ret
|
||||
|
||||
; SI -> MCB in U_WRKSEG
|
||||
; AX=Base, BX=Length, DX=Length
|
||||
caa_g: call getmemory ! jcxz caa_gm
|
||||
mov bx,0ffffh ! ret
|
||||
|
||||
; Successful allocation
|
||||
caa_gm: push ds ! mov ds,u_wrkseg
|
||||
mov mcb_length[si],dx
|
||||
mov mcb_base[si],ax
|
||||
pop ds ! sub bx,bx ! ret
|
||||
|
||||
getmemory:
|
||||
;---------
|
||||
; input: AX = start
|
||||
; BX = min
|
||||
; DX = max
|
||||
; output: AX = start
|
||||
; DX = length
|
||||
; CX = error code
|
||||
; preserve SI
|
||||
|
||||
push si
|
||||
sub cx,cx ! push cx ! push cx ! push dx ! push bx
|
||||
push ax ! mov dx,sp
|
||||
push ds ! mov cx,ss ! mov ds,cx
|
||||
mov cx,f_malloc ! call osif
|
||||
pop ds ! pop ax ! pop dx ! pop bx ! pop bx ! pop bx
|
||||
pop si ! ret
|
||||
|
||||
;=============
|
||||
cpmfree_entry: ; 57 - Free Mem
|
||||
;=============
|
||||
; Free memory as specified in MCB
|
||||
; input: DX = offset of MCB in u_wrkseg
|
||||
; mcb_ext = 0ffh = free all but load mem
|
||||
; else as specified by mcb_base.
|
||||
; mcb_base = seg addr of memory segment
|
||||
; to free. IF in middle of
|
||||
; existing segment then just free
|
||||
; the end of the segment.
|
||||
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov si,dx
|
||||
mov al,mcb_ext[si]
|
||||
mov dx,mcb_base[si] ! pop ds
|
||||
cmp al,0ffh ! jne free_memory
|
||||
cpmf_root: mov bx,rlr
|
||||
add bx,p_mem-ms_link
|
||||
cpmf_next: mov si,ms_link[bx]
|
||||
cmp si,0 ! jne try_seg
|
||||
sub bx,bx ! mov cx,bx ! ret
|
||||
try_seg: test ms_flags[si],mf_load ! jz free_seg
|
||||
mov bx,si ! jmps cpmf_next
|
||||
free_seg: mov dx,ms_start[si]
|
||||
push si ! call free_memory ! pop si
|
||||
jcxz cpmf_root
|
||||
jmps cpmf_next
|
||||
|
||||
free_memory:
|
||||
;-----------
|
||||
; input: DX = start
|
||||
; output: BX = 0,0ffffh (success,fail)
|
||||
; CX = Error Code
|
||||
|
||||
push ds ! push ss ! pop ds
|
||||
sub cx,cx ! push cx ! push dx
|
||||
mov dx,sp
|
||||
mov cx,f_memfree ! call osif
|
||||
pop dx ! pop dx ! pop ds
|
||||
ret
|
||||
|
||||
;=============
|
||||
freeall_entry: ; 58 - Free All Mem
|
||||
;=============
|
||||
; Free all memory except LOAD UDA and LDSTK
|
||||
; If a transient program calls this, it must free up the
|
||||
; all of the perceived memory. The UDA and LDSTK is not
|
||||
; perceived by CPM compatible programs. The UDA cannot be
|
||||
; freed, since it is part of the process descriptor, until
|
||||
; termination in the dispatcher.
|
||||
|
||||
mov si,rlr
|
||||
mov ax,p_uda[si]
|
||||
add si,p_mem-ms_link
|
||||
fam_n: mov si,ms_link[si]
|
||||
|
||||
; See if anymore memory to free
|
||||
cmp si,0 ! je fam_e
|
||||
mov bx,ms_start[si]
|
||||
|
||||
; See if UDA above start
|
||||
cmp bx,ax ! ja fam_a ;AX=UDA Segment
|
||||
mov cx,bx
|
||||
add cx,ms_length[si]
|
||||
|
||||
; See if below start+len
|
||||
cmp cx,ax ! jb fam_a
|
||||
|
||||
; WE HAVE A UDA !!!
|
||||
; see if we already trimmed it
|
||||
|
||||
test ms_flags[si],mf_udaonly
|
||||
jnz fam_n
|
||||
or ms_flags[si],mf_udaonly
|
||||
|
||||
; trim the memory above the UDA
|
||||
|
||||
add ax,(lstklen+ulen)/16 ;CX=# paragraphs
|
||||
mov bx,ax
|
||||
|
||||
; Free the segment or after the UDA+LDSTK
|
||||
fam_a: mov dx,bx
|
||||
call free_memory
|
||||
jmps freeall_entry
|
||||
fam_e: xor bx,bx ! mov cx,bx ! ret
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Concurrent CP/M-86 V2.1
|
||||
;* =======================
|
||||
;*
|
||||
;* Copyright (c) 1982
|
||||
;*
|
||||
;* Digital Research
|
||||
;* P.O.Box 579
|
||||
;* Pacific Grove, California 93950
|
||||
;*
|
||||
;* (408) 649-3896
|
||||
;* TWX 9103605001
|
||||
;*
|
||||
;* All Information contained in this source listing is
|
||||
;*
|
||||
;* PROPRIETORY
|
||||
;* ===========
|
||||
;*
|
||||
;* All rights reserved. No part of this document
|
||||
;* may be reproduced, transmitted, stored in a
|
||||
;* retrieval system, or translated into any language
|
||||
;* or computer language, in any form or by any means
|
||||
;* without the prior written permission of Digital
|
||||
;* Research, P.O Box 579, Pacific Grove, California.
|
||||
;*
|
||||
;*****************************************************
|
||||
@@ -0,0 +1,474 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* bdos data area
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
CCPMOFF equ true
|
||||
|
||||
if BCPM
|
||||
|
||||
;
|
||||
; 8086 variables that must reside in code segment
|
||||
;
|
||||
cseg $
|
||||
;
|
||||
axsave dw 0 ; register saves
|
||||
ss_save dw 0
|
||||
sp_save dw 0
|
||||
stack_begin dw endstack
|
||||
;
|
||||
; variables in data segment:
|
||||
;
|
||||
dseg cpmsegment
|
||||
org bdosoffset+bdoscodesize
|
||||
|
||||
header rs 128
|
||||
rs 72
|
||||
|
||||
pag0 dw 0 ;address of user's page zero
|
||||
ip0 db 0 ;initial page value for ip register
|
||||
;
|
||||
; memory control block
|
||||
;
|
||||
umembase dw 0 ;user'sbase for memory request
|
||||
umemlg dw 0 ;length of memory req
|
||||
contf db 0 ;flag indicates added memory is avail
|
||||
;
|
||||
;
|
||||
hold_info dw 0 ;save info
|
||||
hold_spsave dw 0 ;save user sp during program load
|
||||
hold_sssave dw 0 ;save user ss during program load
|
||||
|
||||
mod8080 db 0
|
||||
;
|
||||
; byte i/o variables:
|
||||
;
|
||||
compcol db 0 ;true if computing column position
|
||||
strtcol db 0 ;starting column position after read
|
||||
column db 0 ;column position
|
||||
listcp db 0 ;listing toggle
|
||||
kbchar db 0 ;initial key char = 00
|
||||
|
||||
endif
|
||||
|
||||
dseg
|
||||
if BMPM
|
||||
org 0c00h ;org for MP/M system
|
||||
endif
|
||||
|
||||
if BMPM and CCPMOFF
|
||||
org 0800h ;org for CCP/M system
|
||||
endif
|
||||
|
||||
if BMPM
|
||||
rlog dw 0 ;removeable logged-in disks
|
||||
tlog dw 0 ;removeable disk test login vector
|
||||
ntlog dw 0 ;new tlog vector
|
||||
|
||||
endif
|
||||
|
||||
rodsk dw 0 ;read only disk vector
|
||||
dlog dw 0 ;logged-in disks
|
||||
|
||||
open_fnd db 0 ;open file found in srch_olist
|
||||
|
||||
;the following variables are set to zero upon entry to file system
|
||||
|
||||
fcbdsk db 0 ;disk named in fcb
|
||||
parlg db 0 ;length of parameter block copied
|
||||
aret dw 0 ;adr value to return
|
||||
lret equ byte ptr aret ;low(aret)
|
||||
resel db 0 ;reselection flag
|
||||
rd_dir_flag db 0 ;must read/locate directory record
|
||||
comp_fcb_cks db 0 ;compute fcb checksum flag
|
||||
search_user0 db 0 ;search user 0 for file (open)
|
||||
make_xfcb db 0 ;make & search xfcb flag
|
||||
find_xfcb db 0 ;search find xfcb flag
|
||||
xdcnt dw 0 ;empty directory dcnt
|
||||
DIR_CNT DB 0 ;DIRECT I/O COUNT
|
||||
MULT_NUM DB 0 ;MULTI-SECTOR COUNT used in bdos
|
||||
olap_type db 0 ;record lock overlap type
|
||||
ff_flag db 0 ;0ffh xios error return flag
|
||||
err_type db 0 ;type of error to print if not zero
|
||||
rb 4 ;reserved bytes
|
||||
zerolength equ (offset $)-(offset fcbdsk)
|
||||
mult_sec db 1 ;multi sector count passed to xios
|
||||
RELOG DB 0 ;AUTOMATIC RELOG SWITCH
|
||||
|
||||
BLK_OFF DB 0 ;RECORD OFFSET WITHIN BLOCK
|
||||
blk_num dw 0 ;block number
|
||||
;
|
||||
ua_lroot dw offset ua0 ;unallocated block list root
|
||||
;
|
||||
ua0 dw offset ua1,0
|
||||
db 0ffh,0
|
||||
ua1 dw offset ua2,0
|
||||
db 0ffh,0
|
||||
ua2 dw offset ua3,0
|
||||
db 0ffh,0
|
||||
ua3 dw offset ua4,0
|
||||
db 0ffh,0
|
||||
ua4 dw offset ua5,0
|
||||
db 0ffh,0
|
||||
ua5 dw 0,0
|
||||
db 0ffh,0
|
||||
|
||||
HASH RB 4 ;HASH CODE WORK AREA
|
||||
HASHL DB 0 ;HASH SEARCH LENGTH
|
||||
|
||||
LOG_FXS db 11 ;number of log_fxs entrys
|
||||
; fxi15,fxi17,fxi19,fxi22,fxi23
|
||||
db 02h ,04h ,06h ,09h ,0ah
|
||||
; fxi30,fxi35,fxi99,fxi100,fxi102,fxi103
|
||||
db 11h ,16h ,25h ,26h ,28h ,29h
|
||||
db 0,0,0,0 ;reserved
|
||||
rw_fxs db 7 ;number of rw_fxs entrys
|
||||
; fxi20,fxi21,fxi33,fxi34,fxi40,fxi42,fxi43
|
||||
db 07h ,08h ,14h ,15h ,1bh ,1ch ,1dh
|
||||
db 0,0 ;reserved
|
||||
sc_fxs db 2 ;number of sc_fxs entrys
|
||||
; fxi16,fxi18
|
||||
db 03h ,05h
|
||||
db 0,0 ;reserved
|
||||
|
||||
DEBLOCK_FX DB 0 ;DEBLOCK FUNCTION #
|
||||
PHY_OFF DB 0 ;RECORD OFFSET WITHIN PHYSICAL RECORD
|
||||
CUR_BCBA DW 0 ;CURRENT BCB OFFSET
|
||||
ROOT_BCBA DW 0 ;ROOT BCB OFFSET
|
||||
EMPTY_BCBA DW 0 ;EMPTY BCB OFFSET
|
||||
|
||||
if BMPM
|
||||
|
||||
P_LAST_BCBA DW 0 ;PROCESS'S LAST BCB OFFSET
|
||||
P_BCB_CNT DB 0 ;PROCESS BCB COUNT IN BCB LIST
|
||||
|
||||
endif
|
||||
|
||||
fx_intrn db 0 ;internal BDOS function number
|
||||
|
||||
TRACK DW 0 ;BCB RECORD'S TRACK
|
||||
SECTOR DW 0 ;BCB RECORD'S SECTOR
|
||||
|
||||
; seldsk,usrcode are initialized as a pair
|
||||
seldsk db 0 ;selected disk num
|
||||
usrcode db 0 ;curr user num
|
||||
|
||||
info dw 0 ;info adr
|
||||
searcha dw 0 ;search adr
|
||||
|
||||
;the following variable order is critical
|
||||
|
||||
;variables copied from uda for mp/m x
|
||||
|
||||
;variables included in fcb checksum for mp/m and cp/m x
|
||||
|
||||
;variables used to access system lock list for mp/m x
|
||||
|
||||
dma_ofst dw 0 ;dma offset 1
|
||||
dma_seg dw 0 ;dma segment 2
|
||||
func db 0 ;bdos function # 3
|
||||
searchl db 0 ;search len 4
|
||||
|
||||
if BMPM
|
||||
|
||||
searchaofst dw 0 ;search adr ofst 5
|
||||
searchabase dw 0 ;search adr base 6
|
||||
|
||||
endif
|
||||
|
||||
dcnt dw 0 ;directory counter 7
|
||||
dblk dw 0 ;directory block 8 ?? - not used - ??
|
||||
error_mode db 0 ;bdos error mode 9
|
||||
mult_cnt db 0 ;bdos multi-sector cnt 10
|
||||
df_password rb 8 ;process default pw 11
|
||||
|
||||
if BMPM
|
||||
|
||||
pd_cnt db 0 ;bdos process cnt 12 1
|
||||
|
||||
endif
|
||||
|
||||
high_ext db 0 ;fcb high extent bits 2
|
||||
xfcb_read_only db 0 ;xfcb read only flag 3
|
||||
curdsk db 0ffh ;current disk 4 1
|
||||
|
||||
if BMPM
|
||||
|
||||
packed_dcnt db 0 ;packed dblk+dcnt 2
|
||||
db 0
|
||||
db 0
|
||||
pdaddr dw 0 ;process descriptor addr 3
|
||||
|
||||
endif
|
||||
|
||||
org ((offset $) + 1) and 0fffeh
|
||||
|
||||
; curtrka - alloca are set upon disk select
|
||||
|
||||
; (data must be adjacent)
|
||||
|
||||
cdrmaxa dw 0 ;ptr to cur dir max val
|
||||
drvlbla dw 0 ;drive label data byte addr
|
||||
buffa dw 0 ;ptr to dir dma addr
|
||||
dpbaddr dw 0 ;curr disk param block addr
|
||||
checka dw 0 ;curr checksum vector addr
|
||||
alloca dw 0 ;curr alloc vector addr
|
||||
DIR_BCBA DW 0 ;DIRECTORY BUFFER CONTROL BLOCK ADDR
|
||||
DAT_BCBA dw 0 ;DATA BUFFER CONTROL BLOCK ADDR
|
||||
HASH_SEG dw 0 ;HASH TABLE SEGMENT
|
||||
addlist equ 12 ;"$-buffa" = addr list size
|
||||
|
||||
; sectpt - offset obtained from disk parm block at dpbaddr
|
||||
; (data must be adjacent)
|
||||
|
||||
sectpt dw 0 ;sectors per track
|
||||
blkshf db 0 ;block shift factor
|
||||
blkmsk db 0 ;block mask
|
||||
extmsk db 0 ;extent mask
|
||||
maxall dw 0 ;max alloc num
|
||||
dirmax dw 0 ;max dir num
|
||||
dirblk dw 0 ;reserved alloc bits for dir
|
||||
chksiz dw 0 ;size of checksum vector
|
||||
offsetv dw 0 ;offset tracks at beginning
|
||||
PHYSHF DB 0 ;PHYSICAL RECORD SHIFT FACTOR
|
||||
PHYMSK DB 0 ;PHYSICAL RECORD MASK
|
||||
endlist rs 0 ;end of list
|
||||
dpblist equ (offset endlist)-(offset sectpt)
|
||||
;size
|
||||
|
||||
; local variables
|
||||
|
||||
common_dma rb 16 ;copy of user's dma 1st 16 bytes
|
||||
make_flag db 0 ;make function flag
|
||||
actual_rc db 0 ;directory ext record count
|
||||
save_xfcb db 0 ;search xfcb save flag
|
||||
save_mod db 0 ;open_reel module save field
|
||||
pw_mode db 0 ;password mode
|
||||
attributes db 0 ;fcb interface attributes hold byte
|
||||
|
||||
if BMPM
|
||||
|
||||
; number of lock list items required for lock operation
|
||||
required_table db 1,0,2,2,1,1,2,2,1,1,2,2,1,1,2,2
|
||||
|
||||
chk_olist_flag db 0 ;check | test olist flag
|
||||
lock_sp dw 0 ;lock stack ptr
|
||||
lock_shell db 0 ;lock shell flag
|
||||
check_fcb_ret db 0 ;check_fcb return switch
|
||||
lock_unlock db 0 ;lock | unlock function flag
|
||||
incr_pdcnt db 0 ;increment process_cnt flag ??
|
||||
free_mode db 0 ;free lock list entries flag ??
|
||||
;1=free entries for curdsk
|
||||
;0=free all entries
|
||||
cur_pos dw 0 ;current position in lock list
|
||||
prv_pos dw 0 ;previous position in lock list
|
||||
|
||||
dont_close db 0 ;inhibit actual close flag
|
||||
open_cnt db 0 ;process open file count
|
||||
lock_cnt db 0 ;process locked record count
|
||||
file_id dw 0 ;address of file' lock list entry
|
||||
set_ro_flag db 0 ;set drive r/o flag
|
||||
check_disk db 0 ;disk reset open file check flag
|
||||
flushed db 0 ;lock list open file flush flag
|
||||
|
||||
;free_root, lock_max, open_max initialized by sysgen
|
||||
|
||||
dw offset free_root
|
||||
open_root dw 0 ;lock list open file list root
|
||||
lock_root dw 0 ;lock list locked record list root
|
||||
|
||||
endif
|
||||
|
||||
sdcnt dw 0 ;saved dcnt of file's 1st fcb
|
||||
sdcnt0 dw 0 ;saved dcnt (user 0 pass)
|
||||
|
||||
if BCPM
|
||||
|
||||
chain_flag db 0 ;chain flag ??
|
||||
tod db 0ffh,0ffh,0ffh,0ffh ??
|
||||
|
||||
|
||||
endif
|
||||
|
||||
|
||||
rmf db 0 ;read mode flag for open$reel
|
||||
wflag db 0 ;xios/bios write flag
|
||||
dirloc db 0 ;directory flag in rename, etc.
|
||||
linfo db 0 ;low(info)
|
||||
dminx db 0 ;local for diskwrite
|
||||
single db 0 ;set true if single byte
|
||||
;alloc map
|
||||
rcount db 0 ;record count in curr fcb
|
||||
extval db 0 ;extent num and extmsk
|
||||
vrecord db 0 ;curr virtual record
|
||||
ADRIVE DB 0 ;CURRENT DISK - must preceed arecord
|
||||
arecord dw 0 ;curr actual record
|
||||
db 0 ;curr actual record high byte
|
||||
ARECORD1 dw 0 ;curr actual block# * blkmsk
|
||||
drec dw 0 ;curr actual directory record
|
||||
CUR_dma_seg DW 0
|
||||
CUR_DMA DW 0
|
||||
|
||||
; local variables for directory access
|
||||
|
||||
dptr db 0 ;directory pointer 0,1,2,3
|
||||
ldcnt equ byte ptr dcnt ;low(dcnt)
|
||||
user_zero_pass db 0 ;search user zero flag
|
||||
|
||||
|
||||
; shell variables
|
||||
|
||||
shell_si dw 0 ;bdos command offset
|
||||
shell_rr db 0,0,0 ;r0,r1,r2 save area
|
||||
|
||||
; special 8086 variables:
|
||||
|
||||
uda_save dw 0 ;user data area saved value
|
||||
parametersegment dw 0 ;user parameter segment
|
||||
returnseg dw 0 ;user return segment
|
||||
|
||||
|
||||
; error messages
|
||||
|
||||
err_drv db 0
|
||||
err_pd_addr dw 0
|
||||
|
||||
dskmsg db 13,10,'CP/M Error On '
|
||||
dskerr db ' : ',0
|
||||
|
||||
xerr_list dw 0,permsg,rodmsg,rofmsg,selmsg
|
||||
dw xe5,xe6,xe7,xe8,xe9,xe10,xe11,xe3
|
||||
|
||||
permsg db 'Disk I/O',0
|
||||
rodmsg db 'Read/Only Disk',0
|
||||
|
||||
rofmsg db 'Read/Only File',0
|
||||
selmsg db 'Invalid Drive',0
|
||||
|
||||
xe3 db 'File Opened in Read/Only Mode',0
|
||||
|
||||
xe5 db 'File Currently Open',0
|
||||
xe6 db 'Close Checksum Error',0
|
||||
xe7 db 'Password Error',0
|
||||
xe8 db 'File Already Exists',0
|
||||
xe9 db 'Illegal ? in FCB',0
|
||||
xe10 db 'Open File Limit Exceeded',0
|
||||
xe11 db 'No Room in System Lock List',0
|
||||
|
||||
crlf_str db 13,10,0
|
||||
pr_fx db 13,10,'Bdos Function = '
|
||||
pr_fx1 db ' '
|
||||
pr_fcb db ' File = '
|
||||
pr_fcb1 rs 12
|
||||
db 0
|
||||
|
||||
deniedmsg db 13,10,'Disk reset denied, Drive '
|
||||
denieddrv db 0,':'
|
||||
db ' Console '
|
||||
deniedcns db 0
|
||||
db ' Program '
|
||||
deniedprc db '12345678',0
|
||||
|
||||
if BMPM
|
||||
|
||||
; bdos stack switch variables and stack
|
||||
; used for all bdos disk functions
|
||||
|
||||
org ((offset $) + 1) and 0fffeh
|
||||
|
||||
; 69 word bdos stack
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
bdosstack rw 0
|
||||
|
||||
save_sp rw 1
|
||||
ss_save rw 1
|
||||
sp_save rw 1
|
||||
|
||||
; local buffer area:
|
||||
|
||||
info_fcb rb 40 ;local user FCB
|
||||
save_fcb rb 16 ;fcb save area for xfcb search
|
||||
|
||||
mxdiskqd dw 0 ;link
|
||||
db 0,0 ;net,org
|
||||
dw qf_keep+qf_mx ;flags (MX queue)
|
||||
db 'MXdisk '
|
||||
dw 0,1 ;msglen,nmsgs
|
||||
dw 0,0 ;nq,dq
|
||||
dw 1,0 ;msgcnt,out
|
||||
dw 0 ;buffer ptr
|
||||
|
||||
mxdiskqpb db 0 ;flgs
|
||||
db 0 ;net
|
||||
dw mxdiskqd ;qaddr
|
||||
dw 1 ;nmsgs
|
||||
dw 0 ;buffer
|
||||
db 'MXdisk '
|
||||
|
||||
; Error Message sync param block for mutual exclusion
|
||||
|
||||
msg_spb dw 0 ;link Error Message sync parameter block
|
||||
dw 0 ;owner
|
||||
dw 0 ;wait
|
||||
dw 0 ;next
|
||||
endif
|
||||
|
||||
if BCPM
|
||||
|
||||
;
|
||||
; special 8086 variables:
|
||||
;
|
||||
ioloc db 0 ;iobyte
|
||||
user_parm_seg dw 0 ;holds user parameter seg during load
|
||||
nallocmem db 0 ;no. of allocated memory segments
|
||||
ncrmem db 0 ;no. of available memory segments
|
||||
crmem dw 0,0 ;memory table (16 elements)
|
||||
dw 0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
dw 0,0,0,0,0,0,0,0
|
||||
;
|
||||
mem_stack_length equ 40
|
||||
memstack rs mem_stack_length
|
||||
;8 possible allocations
|
||||
stbase equ word ptr 0
|
||||
stlen equ word ptr 2
|
||||
ccpflag equ byte ptr 4
|
||||
nccpalloc db 0 ;number of current ccp allocations
|
||||
mem_stk_ptr dw 0 ;current memory stack location
|
||||
|
||||
stackarea rw ssize ;stack size
|
||||
endstack rb 0 ;top of stack
|
||||
;
|
||||
endif
|
||||
org 0fffh
|
||||
if CCPMOFF
|
||||
org 0bffh
|
||||
endif
|
||||
db 0
|
||||
@@ -0,0 +1,604 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Dispatch Routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;=====
|
||||
fdisp:
|
||||
;=====
|
||||
; This entry point used by interrupt routines in XIOS
|
||||
; Note: if the XIOS is performing memory protection interrupt
|
||||
; handlers must enable O.S. memory before calling the O.S.
|
||||
|
||||
cli
|
||||
push ds ! mov ds,sysdat
|
||||
cmp indisp,true ! je nodisp ;if indisp=true then we are
|
||||
mov ax_sav,ax ;in the dispatcher and
|
||||
mov al,true ! mov indisp,al ;this code is skipped
|
||||
mov ax,es ! mov es_sav,ax
|
||||
mov ax,rlr ! xchg ax,bx ! mov bx_sav,ax
|
||||
mov es,p_uda[bx]
|
||||
mov al,true ! mov u_in_int,al
|
||||
pop ax ! mov u_ds_sav,ax
|
||||
mov al,p_stat[bx]
|
||||
mov u_stat_sav,al
|
||||
mov p_stat[bx],ps_run
|
||||
mov ax,es_sav
|
||||
mov u_es_sav,ax
|
||||
|
||||
; AX in AX_SAV
|
||||
; BX in BX_SAV
|
||||
; ES in U_ES_SAV
|
||||
; DS in U_DS_SAV
|
||||
; p_stat in U_STAT_SAV
|
||||
jmp intdisp
|
||||
;dispatcher will jump to here if
|
||||
; u_in_int = true.
|
||||
|
||||
int_disp_exit: ;interrupts are off
|
||||
|
||||
; AX in AX
|
||||
; BX in BX
|
||||
; ES in U_ES_SAV
|
||||
; DS in U_DS_SAV
|
||||
; p_stat in U_STAT_SAV
|
||||
|
||||
mov ax_sav,ax
|
||||
mov ax,bx ! mov bx_sav,ax
|
||||
;check for
|
||||
cmp drl,0 ! jnz intdisp ;interrupt occurence
|
||||
;on dispatcher exit
|
||||
|
||||
mov al,false ! mov u_in_int,al
|
||||
mov ax,rlr ! mov bx,ax
|
||||
mov al,u_stat_sav
|
||||
mov p_stat[bx],al
|
||||
mov ax,bx_sav ! mov bx,ax
|
||||
mov ax,ax_sav
|
||||
mov indisp,false
|
||||
mov ds,u_ds_sav
|
||||
mov es,u_es_sav
|
||||
iret
|
||||
|
||||
nodisp: pop ds
|
||||
iret
|
||||
|
||||
|
||||
;========
|
||||
farpdisp:
|
||||
;========
|
||||
; Intermodule pdisp (non-interrupt)
|
||||
|
||||
call pdisp ! retf
|
||||
|
||||
;=====
|
||||
pdisp:
|
||||
;=====
|
||||
; Call dispatcher with no special action
|
||||
|
||||
push bx ! mov bx,rlr
|
||||
mov p_stat[bx],ps_run ! pop bx
|
||||
;jmp dsptch
|
||||
|
||||
;======
|
||||
dsptch:
|
||||
;======
|
||||
; The dispatch function looks like a noop to the
|
||||
; caller. All flags and registers are maintained.
|
||||
; No levels of user stack is used.
|
||||
; (jmp dispatch = ret)
|
||||
; Interrupt routines enter through fdisp.
|
||||
;
|
||||
; Dispatch has two (2) arguments:
|
||||
; 1. the p_stat field of the process descriptor
|
||||
; determines the type of action to perform
|
||||
; for this process.
|
||||
; 2. the dparam field of the uda is an argument
|
||||
; to the action.
|
||||
; The main part of the dispatch routine takes the
|
||||
; currently running process off the Ready list
|
||||
; and jmps to a routine which will put it on some
|
||||
; other list depending on the p_stat argument.
|
||||
; The subsequent routine will then jump to the
|
||||
; scheduler which will do polling of devices and
|
||||
; move processes off the dispatch ready list onto
|
||||
; the Ready list. The Ready List is maintained
|
||||
; in priority order with round-robin scheduling
|
||||
; of processes with equivalent priorities. The
|
||||
; first process on the ready list will then be
|
||||
; switched in.
|
||||
|
||||
; set indisp flag
|
||||
pushf ! cli
|
||||
cmp indisp,true ! jne dispin
|
||||
popf ! ret
|
||||
dispin: mov indisp,true
|
||||
pop u_flag_sav
|
||||
|
||||
; assumming bx=RLR:
|
||||
; if PLR=0 and DRL=0 then
|
||||
; if p_stat[bx]=PS_RUN then
|
||||
; if p_link[bx]=0 or
|
||||
; p_prior[p_link[bx]]<>p_prior[bx] then
|
||||
; don't do dispatch
|
||||
|
||||
mov ax_sav,ax
|
||||
mov ax,bx ! mov bx_sav,bx
|
||||
intdisp:
|
||||
cmp plr,0 ! jne dcont ;if Poll list = 0 and
|
||||
cmp drl,0 ! jne dcont ;Dsptch Ready list = 0 and
|
||||
mov ax,rlr ! mov bx,ax ;(RLR can never be 0 here)
|
||||
cmp p_stat[bx],ps_run ! jne dcont ;our status is run and
|
||||
cmp p_link[bx],0 ! je no_disp2 ;other PD to ready to run
|
||||
mov al,p_prior[bx] ;with an equal priority
|
||||
mov bx,p_link[bx] ;THEN skip the dispatch
|
||||
cmp al,p_prior[bx] ! je dcont
|
||||
no_disp2:
|
||||
mov ax,bx_sav ! mov bx,ax
|
||||
mov ax,ax_sav
|
||||
jmp dext
|
||||
|
||||
dcont:
|
||||
mov u_ss,ss ! mov u_sp,sp
|
||||
mov ss,sysdat ! mov sp,offset dsptchtos
|
||||
mov ax,bx_sav ! mov bx,ax
|
||||
mov ax,ax_sav
|
||||
sti
|
||||
cld
|
||||
; save registers
|
||||
; NOTE: We will use DS instead of ES
|
||||
; No segment overrides...
|
||||
|
||||
push es ! pop ds
|
||||
mov ds:u_ax,ax
|
||||
mov ax,bx ! mov ds:u_bx,ax
|
||||
mov ax,cx ! mov ds:u_cx,ax
|
||||
mov ax,dx ! mov ds:u_dx,ax
|
||||
mov ax,di ! mov ds:u_di,ax
|
||||
mov ax,si ! mov ds:u_si,ax
|
||||
mov ax,bp ! mov ds:u_bp,ax
|
||||
|
||||
; Save interrupt vectors 0,1,3,4 not INT 2 which is NMI
|
||||
; MP/M-86, CCP/M-86 1.0 on the IBM PC saved NMI
|
||||
; Block move first 2
|
||||
|
||||
xor bx,bx ! mov ds,bx
|
||||
mov si,bx ! mov di,offset u_ivectors
|
||||
mov dx,4
|
||||
mov cx,dx ! rep movsw
|
||||
mov cx,dx ! add si,dx ;get next 2
|
||||
add di,dx ;skip INT 2 location documented
|
||||
rep movsw ;now as reserved word in UDA
|
||||
; block move osint,debugint
|
||||
|
||||
mov si,offset i_os_ip ! mov di,offset u_os_ip
|
||||
mov cx,dx ! rep movsw
|
||||
|
||||
; take current process off RLR.
|
||||
mov ds,sysdat
|
||||
; ;disable memory for the process
|
||||
; ;we are taking out of context
|
||||
;turn off interrupts ?
|
||||
; mov bx,rlr !; lea si,p_mem-ms_link[bx]
|
||||
;dsp_dnxt:
|
||||
; mov si,ms_link[si]
|
||||
; test si,si !; jz dsp_disabled
|
||||
; mov cx,ms_start[si] !; mov dx,ms_length[si]
|
||||
; push si
|
||||
; mov ax,io_disable !; call xiosif
|
||||
; pop si
|
||||
|
||||
; jmps dsp_dnxt
|
||||
;
|
||||
;dsp_disabled:
|
||||
|
||||
nop
|
||||
mov ax,rlr ! mov si,ax
|
||||
mov ax,p_link[si] ! mov rlr,ax
|
||||
mov p_link[si],0
|
||||
; We are now in NO-MAN's land
|
||||
; From now until the end of the
|
||||
; switch routine, There is no
|
||||
; process in context.
|
||||
; SI -> PD just taken out of context.
|
||||
; jump to routine for given status
|
||||
xor bh,bh ! mov bl,p_stat[si] ! shl bx,1
|
||||
jmp cs:dsp_table[bx]
|
||||
|
||||
org ((offset $)+1) AND 0fffeh
|
||||
|
||||
dsp_table dw disp_act ;00 - run
|
||||
dw disp_act ;01 - (nop)-poll device
|
||||
dw delay_act ;02 - delay
|
||||
dw disp_act ;03 - (nop)-swap
|
||||
dw term_act ;04 - terminate
|
||||
dw sleep_act ;05 - sleep
|
||||
dw disp_act ;06 - (nop)-dq
|
||||
dw disp_act ;07 - (nop)-nq
|
||||
dw flag_act ;08 - flag wait
|
||||
dw disp_act ;09 - (nop)-ciowait
|
||||
dw disp_act ;10 - (nop)-sync
|
||||
|
||||
sleep_act:
|
||||
;---------
|
||||
; insert running process into list specified by
|
||||
; u_dparam and set p_stat from p_scratch
|
||||
; Note: we cannot sleep on the DLR since interrupts are on
|
||||
; here, and flag_set can change the DLR
|
||||
|
||||
mov ax,u_dparam
|
||||
mov bx,ax
|
||||
push si ! call insert_process
|
||||
pop si ! or p_flag[si],pf_resource
|
||||
mov al,p_scratch[si] ! mov p_stat[si],al
|
||||
jmp schedule
|
||||
|
||||
delay_act:
|
||||
;---------
|
||||
; Put the running process on the Delay List. The
|
||||
; delay list is built such that any process's
|
||||
; remaining delay time is the additive of the delay
|
||||
; times of all processes ahead of it plus the # of
|
||||
; ticks in it's own p_wait field. At each clock tick
|
||||
; the p_wait field of the top process in the list
|
||||
; is decremented. If it reaches zero (0), all
|
||||
; processes with a zero in the p_wait field are
|
||||
; placed on the dispatch ready list.
|
||||
; input: SI=pd address
|
||||
|
||||
cli ;keep flag set from changing
|
||||
if mpm ;TICK, and changing DLR
|
||||
push si ! mov al,io_strtclk
|
||||
call xiosif ! pop si
|
||||
endif
|
||||
|
||||
if ccpm
|
||||
mov tick,true
|
||||
endif
|
||||
|
||||
mov bx,(offset dlr)-p_link
|
||||
mov cx,u_dparam ! inc cx
|
||||
cmp cx,0 ! jne del_lp
|
||||
dec cx
|
||||
del_lp: mov di,p_link[bx]
|
||||
cmp di,0 ! je del_o
|
||||
mov ax,p_wait[di]
|
||||
cmp ax,cx ! ja del_o
|
||||
sub cx,ax ! mov bx,di ! jmps del_lp
|
||||
del_o: mov p_link[si],di ! mov p_link[bx],si
|
||||
mov p_wait[si],cx
|
||||
cmp di,0 ! je del_e
|
||||
sub p_wait[di],cx
|
||||
del_e: jmp schedule
|
||||
|
||||
flag_act:
|
||||
;--------
|
||||
; place running process in flag table to wait
|
||||
; for next flag. Note, flag may have been set...
|
||||
; input: SI=pd address
|
||||
; U_DPARAM=address of Flag entry
|
||||
|
||||
mov ax,u_dparam ! mov bx,ax
|
||||
cli ;protect from flag set
|
||||
cmp flg_pd[bx],flag_on ! je gflagon
|
||||
mov flg_pd[bx],si ! mov p_link[si],0
|
||||
jmp schedule
|
||||
gflagon: ; Flag set since wait check
|
||||
mov flg_pd[bx],flag_off
|
||||
sti
|
||||
jmps disp_act
|
||||
|
||||
term_act:
|
||||
;--------
|
||||
; Terminate the running process, free memory, free pd, free sync
|
||||
; structures. Can only be called by TERMINATE_ENTRY.
|
||||
|
||||
; input: SI=pd address
|
||||
; MEM_SYNC owned by calling process
|
||||
|
||||
; place PD on rlr for now.
|
||||
mov ax,rlr
|
||||
mov p_link[si],ax
|
||||
mov rlr,si
|
||||
|
||||
; clean up consoles
|
||||
mov cx,f_cioterm ! call osif
|
||||
|
||||
; clean up memory
|
||||
; (we own the MXmemory queue)
|
||||
free_nxt:
|
||||
mov ax,rlr ! mov si,ax
|
||||
mov si,p_mem[si]
|
||||
test si,si ! jz end_free
|
||||
push ds ! xor cx,cx ! push cx
|
||||
push ms_start[si]
|
||||
mov ax,ss ! mov ds,ax ! mov dx,sp
|
||||
mov cx,f_memfree ! call osif
|
||||
pop bx ! pop cx ! pop ds
|
||||
jmps free_nxt
|
||||
end_free:
|
||||
|
||||
;release any sync structures
|
||||
;after releasing memory
|
||||
mov mem_cnt,0 ;and MEM_CNT=1
|
||||
;on entry, also own THRD_SYNC
|
||||
;so it is safe to call
|
||||
;FREEPD below,
|
||||
;ASSIGN_SYNC cannot be called
|
||||
;with the THRD_SPB
|
||||
;SI=terminating process
|
||||
mov bx,offset slr - sy_link ;release any sync structures
|
||||
t_nsync: ;owned by terminating PD
|
||||
mov bx,sy_link[bx]
|
||||
test bx,bx ;end of syncs?
|
||||
jz t_sync_done
|
||||
push bx ;PD cannot be allowed to
|
||||
call unsync_entry ;abort if in SY.NEXT
|
||||
pop bx
|
||||
jmps t_nsync
|
||||
|
||||
t_sync_done:
|
||||
|
||||
; take off RLR
|
||||
mov si,rlr
|
||||
mov ax,p_link[si]
|
||||
mov rlr,ax
|
||||
mov p_link[si],0
|
||||
|
||||
; cmp si,owner_8087 ;release 8087 if we owned it
|
||||
; jne t_end ! mov owner_8087,0
|
||||
;t_end:
|
||||
; free up PD
|
||||
call freepd ! jmp schedule
|
||||
|
||||
|
||||
disp_act:
|
||||
;--------
|
||||
; place process on RLR
|
||||
; input: SI=pd address
|
||||
|
||||
mov p_stat[si],ps_run
|
||||
mov bx,(offset rlr)-p_link
|
||||
call insert_process ! jmp schedule
|
||||
|
||||
;==============
|
||||
insert_process:
|
||||
;==============
|
||||
;
|
||||
; put PD# in list ordered by priority
|
||||
;
|
||||
; entry: BX = list root
|
||||
; SI = pd number
|
||||
; exit: SI is preserved
|
||||
; interrupt state as on entry
|
||||
|
||||
mov cx,pflag[si] ! and cx,pf_resource
|
||||
;if a process was waiting
|
||||
ins_npd: mov di,p_link[bx] ;on a resource, insert
|
||||
test di,di ! jz ins_out ;it ahead of equal priority
|
||||
mov al,p_prior[di] ;process
|
||||
cmp al,p_prior[si]
|
||||
ja ins_out ;lowest priority first
|
||||
jb ins_nxt ;higher - keep going down list
|
||||
jcxz ins_nxt ;equal and not resource
|
||||
jmps ins_out ;equal & resource
|
||||
ins_nxt: mov bx,di ! jmp ins_npd
|
||||
ins_out: jcxz ins_exit
|
||||
and p_flag[si],not pf_resource
|
||||
ins_exit:
|
||||
mov p_link[si],di ! mov p_link[bx],si ! ret
|
||||
|
||||
;========
|
||||
schedule:
|
||||
;========
|
||||
; poll all required devices and place any ready
|
||||
; processes on the Ready List
|
||||
|
||||
;we can enable interrupts now.
|
||||
;there MUST be a process on the RLR
|
||||
;at this point, ie. IDLE...
|
||||
sti
|
||||
;go through the Poll List
|
||||
mov di,(offset plr)-p_link
|
||||
;get the next PD on list.
|
||||
;DI is the last one which
|
||||
;has already been checked.
|
||||
polld_another:
|
||||
mov si,p_link[di]
|
||||
;SI is the next PD to check
|
||||
test si,si ! jz drltorlr
|
||||
;SI is valid PD, poll it.
|
||||
|
||||
;If top PD on the PLR has a worse
|
||||
;priority compared to top PD on the RLR,
|
||||
;there is no reason to call the XIOS
|
||||
;and poll the device, this time through
|
||||
;the dispatcher. We must poll on equal
|
||||
;priority to keep a compute bound
|
||||
;process and the CLOCK from locking
|
||||
;out a polling process.
|
||||
;Note, we stop polling after
|
||||
;the first process that has polled
|
||||
;successfully, or we get to the end of
|
||||
;the PLR. The process is placed on
|
||||
;the RLR.
|
||||
|
||||
mov bx,rlr ! test bx,bx ;if RLR=0: poll
|
||||
jz poll_it
|
||||
mov al,p_prior[si] ;priority of 1st poll PD
|
||||
cmp al,p_prior[bx] ! jbe poll_it ;poll if equal or better
|
||||
jmps drltorlr ;priority than head of RLR
|
||||
poll_it:
|
||||
push di
|
||||
if mpm
|
||||
mov cx,p_wait[si]
|
||||
endif
|
||||
if ccpm
|
||||
mov dx,p_wait[si]
|
||||
endif
|
||||
mov al,io_polldev ! call xiosif
|
||||
pop di ! mov si,p_link[di]
|
||||
;if AL=0, device not ready.
|
||||
cmp al,0 ! je polld_next
|
||||
;device ready,
|
||||
;move SI from PLR to RLR
|
||||
mov ax,p_link[si] ! mov p_link[di],ax
|
||||
mov bx,(offset rlr)-p_link
|
||||
mov p_stat[si],ps_run
|
||||
call insert_process ;got one ready to run:
|
||||
jmps drltorlr ;stop polling
|
||||
;p_link[SI]=next PD to check
|
||||
polld_next: ;SI has been checked
|
||||
mov di,si ! jmps polld_another
|
||||
|
||||
drltorlr:
|
||||
;--------
|
||||
; Pull all processes on the dispatch ready list and
|
||||
; place them on the Ready List.
|
||||
|
||||
;We must disable interrupts while
|
||||
;playing with DRL since interrupts
|
||||
;doing a Flag_set may also.
|
||||
;We must competely drain the DRL since
|
||||
;it is in no particular order.
|
||||
|
||||
cli ! mov si,drl ;protect DRL from flag set
|
||||
test si,si ! jz switch
|
||||
mov ax,p_link[si] ! mov drl,ax
|
||||
; test ax,ax ;is this the last PD on DRL?
|
||||
; jnz drl_noi ;yes - don't turn on interrupts
|
||||
sti ;interrupts off guarentees
|
||||
;drl_noi: ;the last DRL PD with the
|
||||
mov p_stat[si],ps_run ;best priority will run
|
||||
mov bx,(offset rlr)-p_link ;next and at least until
|
||||
call insert_process ;it turns on interrupts
|
||||
jmps drltorlr
|
||||
|
||||
switch:
|
||||
;------
|
||||
; switch to the first process on the Ready List
|
||||
|
||||
sti
|
||||
mov bx,rlr
|
||||
; if no next process, go back ;
|
||||
; to schedule. Gives more immediate ;
|
||||
; response to polled and interrupt ;
|
||||
; driven devices ;
|
||||
test bx,bx ! jnz switch1 ;
|
||||
jmp schedule ;
|
||||
switch1: ;
|
||||
|
||||
; ;enable memory for this process
|
||||
; ;turn on interrupts ?
|
||||
; mov bx,rlr !; lea si,p_mem-ms_link[bx]
|
||||
;dsp_enxt:
|
||||
; mov si,ms_link[si]
|
||||
; test si,si !; jz dsp_enabled
|
||||
; mov cx,ms_start[si] !; mov dx,ms_length[si]
|
||||
; push si
|
||||
; mov ax,io_enable !; call xiosif
|
||||
; pop si
|
||||
; jmps dsp_enxt
|
||||
;
|
||||
;dsp_enabled:
|
||||
;
|
||||
; ;Save and restore the 8087 environment if process to run
|
||||
; ;uses the 8087 and is not the owner. Interrupts
|
||||
; ;must be on. Code from Intel Ap. Note. 113 page 29
|
||||
;
|
||||
; ;This code shouldn't be added unless interrupt windows in
|
||||
; ;switch are allowed or the 8087 restore is separated
|
||||
; ;from the 8086/8088 restore. The switch code without this
|
||||
; ;commented out 8087 code,
|
||||
; ;creates an interrupt window approx. 100 to 200 micro
|
||||
; ;secs on 5 to 4 meg CPU.
|
||||
|
||||
; ;Allowing interrupt windows in switch
|
||||
; ;means we must check on leaving the dispatcher
|
||||
; ;for an interrupt awakened process (DRL again <> 0)
|
||||
; ;and call the
|
||||
; ;dispatcher again to prevent a 16 milli second wakeup time
|
||||
; ;for a PD doing a flagwait after the interrupt service routine.
|
||||
|
||||
; ;Calling the dispatcher at the end of the dispatch
|
||||
; ;(see commented out code at end of dispatcher and at
|
||||
; ;INT_DISP_EXIT:)
|
||||
; ;creates contention problems between PDs waiting for a resource
|
||||
; ;and PDs waking up from interrupts. It cannot be guarenteed
|
||||
; ;who will run next. An interrupt awakened process can
|
||||
; ;get a just freed resource is should have waited for.
|
||||
; ;The RTM ASSIGN_SYNC_ENTRY is an untested solution
|
||||
; ;for allowing interrupts in the dispatcher switch code.
|
||||
|
||||
; ;BX=PD to run next
|
||||
; test p_flag[bx],pf_8087 ;does this process use the NPX ?
|
||||
; jz done8087
|
||||
; cmp bx,owner_8087 ;do we already own it
|
||||
; je done8087
|
||||
; xchg bx,owner_8087 ;new owner, also set by terminate
|
||||
; test bx,bx ! jz get8087 ;no one owns it if BX=0
|
||||
; mov dx,ds ;save sysdat in DX
|
||||
; mov ds,p_uda[bx] ;old owner's UDA
|
||||
; fnstcw ds:u_8087 ;save IEM bit status
|
||||
; nop ;delay while 8087 busy saves control reg
|
||||
; fndisi ;disable 8087 busy signal
|
||||
; mov ax,ds:u_8087 ;get original control word
|
||||
;
|
||||
; fsave ds:u_8087 ;save NPX context
|
||||
; fwait ;IEM=1.wait for save to finish
|
||||
; mov ds:u_8087,ax ;save original control word
|
||||
;get8087:
|
||||
; mov ds,dx ;DS=sysdat
|
||||
; mov bx,rlr
|
||||
; mov ds,p_uda[bx] ;PD to run next
|
||||
; frstor ds:u_8087 ;get its 8087 environment
|
||||
; push ds ;DS=UDA
|
||||
; jmps restore ;UDA on stack
|
||||
;
|
||||
;done8087: ;BX=PD to run next
|
||||
|
||||
mov dx,p_uda[bx] ! mov ds,dx ;DS=UDA
|
||||
push dx ;UDA on stack
|
||||
|
||||
;Restore interrupt vectors
|
||||
|
||||
restore:
|
||||
xor ax,ax ! mov es,ax ! mov di,ax
|
||||
mov si,offset u_ivectors
|
||||
mov dx,4
|
||||
mov cx,dx ! rep movsw ;restore interrupt vectors 0,1
|
||||
mov cx,dx ! add di,dx ;don't touch NMI
|
||||
add si,dx ;skip what was NMI
|
||||
rep movsw ;restore interupt vectors 3,4
|
||||
|
||||
mov si,offset u_os_ip ;DS=UDA
|
||||
mov di,offset i_os_ip
|
||||
mov cx,dx ! rep movsw
|
||||
|
||||
; restore registers
|
||||
mov ax,ds:u_bx ! mov bx,ax
|
||||
mov ax,ds:u_cx ! mov cx,ax
|
||||
mov ax,ds:u_dx ! mov dx,ax
|
||||
mov ax,ds:u_si ! mov si,ax
|
||||
mov ax,ds:u_di ! mov di,ax
|
||||
mov ax,ds:u_bp ! mov bp,ax
|
||||
mov ax,ds:u_ax
|
||||
; restore DS and ES and stack
|
||||
pop es ;ES=UDA
|
||||
cli ;turn interrupts off for rest
|
||||
mov ss,u_ss ;of exit
|
||||
mov sp,u_sp
|
||||
mov ds,sysdat
|
||||
dext:
|
||||
cmp u_in_int,true ! jne dret
|
||||
jmp int_disp_exit
|
||||
dret:
|
||||
push u_flag_sav
|
||||
mov indisp,false
|
||||
cmp drl,0 ! je dd_ret
|
||||
popf ; someone is on DRL from interrupt during
|
||||
jmp pdisp ; switch, dispatch now, no 16ms wait
|
||||
dd_ret:
|
||||
popf
|
||||
ret
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* System Entry Table entry format
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
enttab_entry equ word ptr 0
|
||||
entlen equ enttab_entry + word
|
||||
|
||||
; Flags Values in ent_flag
|
||||
|
||||
ef_network equ 0f0h ; network intercept
|
||||
|
||||
; see SYSTEM.DEF for ent_tab definition
|
||||
@@ -0,0 +1,47 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Error definitions
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
e_not_implemented equ 1 ; not implemented
|
||||
e_bad_entry equ 2 ; illegal func. #
|
||||
e_no_memory equ 3 ; cant find memory
|
||||
e_ill_flag equ 4 ; illegal flag #
|
||||
e_flag_ovrrun equ 5 ; flag over run in
|
||||
e_flag_underrun equ 6 ; flag underrun in
|
||||
e_no_qd equ 7 ; no unused qd's
|
||||
e_no_qbuf equ 8 ; no free qbuffer
|
||||
e_no_queue equ 9 ; cant find que on qlr
|
||||
e_q_inuse equ 10 ; queue in use
|
||||
; equ 11 ;
|
||||
e_no_pd equ 12 ; no free pd's
|
||||
e_q_protected equ 13 ; no que access
|
||||
e_q_empty equ 14 ; empty queue
|
||||
e_q_full equ 15 ; full queue
|
||||
e_ncliq equ 16 ; Cli queue missing
|
||||
; equ 17 ;
|
||||
e_no_umd equ 18 ; no unused MD's
|
||||
e_ill_cns equ 19 ; illegal cns num.
|
||||
e_no_pdname equ 20 ; no PD match
|
||||
e_no_cnsmatch equ 21 ; no cns match
|
||||
e_nclip equ 22 ; no cli process
|
||||
e_illdisk equ 23 ; illegal disk #
|
||||
e_badfname equ 24 ; illegal filename
|
||||
e_badftype equ 25 ; illegal filetype
|
||||
e_nochar equ 26 ; char not ready
|
||||
e_ill_md equ 27 ; illegal mem descriptor
|
||||
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
|
||||
e_not_owner equ 32 ; not owner of resource
|
||||
e_no_cseg equ 33 ; no CSEG in load file
|
||||
e_active_pd equ 34 ; PD exists on Thread Root
|
||||
e_pd_noterm equ 35 ; could not terminate process
|
||||
e_no_attach equ 36 ; could not attach to ciodev
|
||||
e_ill_lst equ 37 ; illegal list device
|
||||
e_ill_passwd equ 38 ; illegal password specified
|
||||
e_no_mimic equ 39 ; can't mimic or unmimic
|
||||
e_abort equ 40 ; external termination occured
|
||||
e_fixuprec equ 41 ; fixup error
|
||||
@@ -0,0 +1,16 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* File Control Block Format
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
fcb_dr equ byte ptr 00h
|
||||
fcb_name equ byte ptr 01h
|
||||
fcb_type equ byte ptr 09h
|
||||
|
||||
fcb_pwd equ byte ptr 010h
|
||||
fcb_pptr equ word ptr 018h
|
||||
fcb_plen equ byte ptr 01ah
|
||||
|
||||
fcb_cr equ byte ptr 020h
|
||||
fcb_r0 equ word ptr 021h
|
||||
@@ -0,0 +1,39 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Find Process Descriptor
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;================ =================================
|
||||
findpdname_entry: ; Find Process Descriptor by Name
|
||||
;================ =================================
|
||||
; Find process by name in thread list
|
||||
; Before calling this routine, calling process must
|
||||
; own the THRD_SPB (Thread Sync Parameter Block) as
|
||||
; interrupts are not turned off.
|
||||
;
|
||||
; input: DX->name in u_wrkseg
|
||||
; BX->thread list root - p_thread
|
||||
; output: BX=pd if found
|
||||
; =0ffffh if not found
|
||||
; CX=0 if found
|
||||
; =e_no_pdname if not found
|
||||
|
||||
push es ! mov es,u_wrkseg
|
||||
fpn_cmpname:
|
||||
mov si,dx
|
||||
mov bx,p_thread[bx]
|
||||
cmp bx,0 ! je fpn_nomatch
|
||||
mov cl,0
|
||||
lea di,p_name[bx]
|
||||
fpn_cmplet:
|
||||
cmp cl,8 ! je fpn_found
|
||||
mov al,es:[si] ! sub al,[di]
|
||||
shl al,1 ! jnz fpn_cmpname
|
||||
inc cl ! inc si ! inc di
|
||||
jmps fpn_cmplet
|
||||
fpn_found: mov cx,0 ! jmps fpn_exit
|
||||
fpn_nomatch:
|
||||
mov cx,e_no_pdname ! mov bx,0ffffh
|
||||
fpn_exit:
|
||||
pop es ! ret
|
||||
@@ -0,0 +1,185 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Flag Management
|
||||
;*
|
||||
;* FLAGS-flag table offset NFLAGS-number of flags
|
||||
;*
|
||||
;* Format of Flag Table Entry:
|
||||
;* +-------------+------+
|
||||
;* | flag |ignore|
|
||||
;* +-------------+------+
|
||||
;* flag - 00000h, flag can be allocated
|
||||
;* flag - 0ffffh, flag is off but is allocated to some
|
||||
;* function.
|
||||
;* 0fffeh, flag is set
|
||||
;* 0xxxxh, PD that is waiting
|
||||
;* ignore- 0ffh, normal case
|
||||
;* 0xxh, number of flags to ignore-1
|
||||
;*
|
||||
;* GENSYS initializes the flags reserved by the system
|
||||
;* and the XIOS header to 0ffh's. The rest of the
|
||||
;* flags are initialized to 0 by GENSYS.
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;============
|
||||
;getfree_flag:
|
||||
;============
|
||||
|
||||
; input: DX = 0 then allocate a flag
|
||||
; else
|
||||
; if DH = 0FFH then release flag number
|
||||
; DL (0 relative)
|
||||
; output:
|
||||
; BX = flag allocated if getting a flag
|
||||
; or 0FFFFH if no flag is available
|
||||
; BX = 0FFFFH if attempting to release a
|
||||
; no existent flag
|
||||
; CX = 0 no error
|
||||
; CX = 4 if illegal flag number
|
||||
; CX = 27H if no more flags to allocate
|
||||
;
|
||||
; Flags reserved by CCP/M or MP/M and the XIOS
|
||||
; header, cannot be released.
|
||||
;
|
||||
;turn off interrupts
|
||||
;
|
||||
; test dx,dx ! jz rf_alloc
|
||||
; inc dh ! jnz rf_enum
|
||||
; cmp dl,nrsv_flags ! jbe rf_enum
|
||||
; cmp dl,nflags ! jae rf_enum
|
||||
; xor ax,ax ! mov bx,ax ! mov cx,ax
|
||||
; mov al,dl
|
||||
; add al,dl ! add al,dl
|
||||
; mov si,ax ! mov word ptr flags[si],0
|
||||
; mov byte ptr flags 2[si],0
|
||||
; ret
|
||||
|
||||
;rf_alloc:
|
||||
|
||||
; mov si,flags ! xor ax,ax
|
||||
; mov bx,ax ! mov cx,nflags
|
||||
;rf_nxt:
|
||||
; cmp ax,[si] ! je rf_foundone ;got one
|
||||
; add si,3 ! inc bx
|
||||
; loop rf_nxt
|
||||
; mov cx,e_noflags ! jmps rf_err
|
||||
;rf_foundone:
|
||||
; mov cx,ax ;0 CX
|
||||
; dec ax
|
||||
; mov [si],ax ;set the 3 bytes to 0ffh
|
||||
; mov 2[si],al
|
||||
; ret
|
||||
;rf_enum:
|
||||
; mov cx,e_illflag
|
||||
;rf_err:
|
||||
; mov bx,0ffffh
|
||||
; ret
|
||||
|
||||
;============== ==========================
|
||||
flag_set_entry: ; Set Logical Interrupt Flag
|
||||
;============== ==========================
|
||||
; NOTE: the flagset routine can (must?) be called from outside
|
||||
; the operating system through an interrupt
|
||||
; routine. UDA variables cannot be used. This
|
||||
; is the only function an interrupt routine can
|
||||
; call.
|
||||
;
|
||||
; input: DL = flag number
|
||||
; output: BX = 0 if okay,0ffffh if error
|
||||
; CX = if error: e_flag_ovrrun
|
||||
|
||||
call flag_valid
|
||||
cmp cl,flag_tick ! jne notick
|
||||
mov bx,dlr
|
||||
test bx,bx ! jz dlr_null ;no process waiting
|
||||
dec p_wait[bx] ! jnz nxt_tick
|
||||
nxt_tpd:
|
||||
mov si,p_link[bx] ! mov dlr,si ;SI,DLR=next waiting PD
|
||||
mov p_stat[bx],ps_run ;put PD done waiting
|
||||
mov ax,drl ! mov p_link[bx],ax ;on DRL
|
||||
mov drl,bx
|
||||
test si,si ! jz dlr_null ;SI=next waiting PD
|
||||
cmp p_wait[si],0 ! jnz nxt_tick
|
||||
mov bx,si ! jmps nxt_tpd;another process was waiting
|
||||
;the same number of ticks
|
||||
nxt_tick: jmp flag_exit ;wait for next tick
|
||||
|
||||
dlr_null: ;DLR is empty turn off
|
||||
mov tick,false ! jmp flag_exit ;XIOS tick flag
|
||||
|
||||
no_tick:
|
||||
cmp flg_ignore[si],flag_zig ! je fs_set
|
||||
dec flg_ignore[si] ! jmp flag_exit
|
||||
|
||||
fs_set: cmp bx,flag_on ! jne fs_non
|
||||
mov cx,e_flag_ovrrun ! jmp flag_bexit
|
||||
|
||||
fs_non: cmp bx,flag_off ! jne fs_noff
|
||||
mov flg_pd[si],flag_on
|
||||
jmp flag_exit
|
||||
|
||||
fs_noff:mov ax,drl ! mov p_link[bx],ax
|
||||
mov drl,bx ! mov p_stat[bx],ps_run
|
||||
or p_flag[bx],pf_resource ;12/4/83
|
||||
mov flg_pd[si],flag_off
|
||||
jmp flag_exit
|
||||
|
||||
;=============== ===============================
|
||||
flag_wait_entry: ; Wait for Logical Interrupt Flag
|
||||
;=============== ===============================
|
||||
; input: DL = flag number
|
||||
; output: BX = 0 if everything okay
|
||||
; BX = 0ffffh if Error
|
||||
; CX = Error Code:0,e_flag_underrun
|
||||
|
||||
|
||||
call flag_valid
|
||||
cmp bx,flag_on ! jne fw_non
|
||||
mov flg_pd[si],flag_off
|
||||
jmp flag_exit
|
||||
fw_non: cmp bx,flag_off ! jne fw_noff
|
||||
mov bx,rlr
|
||||
mov p_stat[bx],ps_flagwait
|
||||
mov u_dparam,si
|
||||
call dsptch ! jmp flag_exit
|
||||
fw_noff:mov cx,e_flag_underrun ! jmp flag_bexit
|
||||
|
||||
flag_valid: ; Check validity of flag number
|
||||
;---------- -----------------------------
|
||||
; entry: DL = flag number
|
||||
; output: SI = ptr to flag entry
|
||||
; BX = contents of flag entry
|
||||
; CL = flag number
|
||||
; clear interrupt flag - Flags on stack
|
||||
|
||||
pop ax ! pushf ;AX=return address
|
||||
cmp dl,nflags ! jb flag_good
|
||||
flag_bad:
|
||||
mov cx,e_ill_flag ! jmp flag_bexit ;flags and next return
|
||||
flag_good: ;address on stack
|
||||
mov cl,dl ;save flag number
|
||||
xor dh,dh ! push ax ! cli ;return to fset/fwait on stack
|
||||
mov ax,dx ;multiply flag number
|
||||
mov bx,ax ;times 3
|
||||
add ax,ax ;*2
|
||||
add ax,bx ;*3
|
||||
mov si,flags ! add si,ax
|
||||
mov bx,[si]
|
||||
;test bx,bx ;FLAG field cannot be 0
|
||||
;jz flag_bad
|
||||
ret
|
||||
|
||||
flag_exit: ; Successful Exit
|
||||
;--------- ---------------
|
||||
; entry: flags and return from flagset or flagwait on stack
|
||||
|
||||
xor bx,bx ! popf ! ret
|
||||
|
||||
|
||||
flag_bexit: ; Exit with Error
|
||||
;---------- ---------------
|
||||
; entry: flags and return from flagset or flagwait on stack
|
||||
|
||||
xor bx,bx ! dec bx
|
||||
popf ! ret
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Format of Flag Table Entry
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
flg_pd equ word ptr 0
|
||||
flg_ignore equ byte ptr (flg_pd + word)
|
||||
flglen equ flg_ignore + byte
|
||||
|
||||
flag_off equ 0ffffh ;flag not set
|
||||
flag_on equ 0fffeh ;flag set
|
||||
flag_zig equ 0ffh ;normal value
|
||||
@@ -0,0 +1,28 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Idle Process
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;====
|
||||
idle: ;Idle Process
|
||||
;====
|
||||
; Jump to the XIOS idle routine
|
||||
|
||||
if mpm
|
||||
mov ds,sysdat
|
||||
mov bx,rlr
|
||||
mov es,p_uda[bx]
|
||||
mov ax,io_idle
|
||||
jmp xiosif
|
||||
endif
|
||||
|
||||
if ccpm ;we could move idle to the RTM
|
||||
mov ds,sysdat ;and initialize its IP:CS to
|
||||
mov bx,rlr
|
||||
mov ax,p_uda[bx] ;point to the dispatcher
|
||||
mov es,ax ;and get rid of this
|
||||
mov cx,f_dispatch ;code since idle will never
|
||||
call osif ;come out of the dispatcher
|
||||
jmps idle
|
||||
endif
|
||||
@@ -0,0 +1,118 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MP/M-86 Supervisor Initialization
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
cseg
|
||||
org 0
|
||||
|
||||
jmp init ;system initialization
|
||||
jmp entry ;intermodule entry pt.
|
||||
|
||||
;next 3 words are set by GENSYS
|
||||
sysdat dw 0 ;segment
|
||||
supervisor dw entry ;offset
|
||||
dw 0 ;segment
|
||||
|
||||
org 0ch
|
||||
dev_ver db 6 ;development system data version
|
||||
;set in sysdat.dat
|
||||
|
||||
db 'COPYRIGHT (C) 1982,'
|
||||
db ' DIGITAL RESEARCH '
|
||||
db 'XXXX-0000-'
|
||||
serial db '654321'
|
||||
|
||||
;====
|
||||
init:
|
||||
;====
|
||||
; system initialization
|
||||
; DS set to Sysdat Segment by loader
|
||||
|
||||
;make INIT a process:
|
||||
;set up init stack
|
||||
|
||||
cli ! cld ;Loader enters here
|
||||
mov ax,ds ;with interrupts
|
||||
mov ss,ax ! mov sp,offset (init_tos) ;possibly on
|
||||
|
||||
;initialize init uda
|
||||
|
||||
mov bx,offset initpd
|
||||
mov ax,offset inituda
|
||||
mov cl,4 ! shr ax,cl
|
||||
add ax,sysdat ! mov p_uda[bx],ax
|
||||
mov es,ax
|
||||
mov u_wrkseg,ds
|
||||
|
||||
;we now look like we are in the O.S. as usual:
|
||||
;DS=SYSDAT seg, ES=UDA, U_WRKSEG=PD's DS.
|
||||
|
||||
; set up mpm entry point
|
||||
|
||||
push ds
|
||||
xor ax,ax ! mov ds,ax
|
||||
mov i_os_ip,offset user_entry
|
||||
|
||||
mov i_os_cs,cs
|
||||
pop ds
|
||||
|
||||
;initialize modules
|
||||
|
||||
mov bx,mod_init
|
||||
push bx ! callf dword ptr rtmmod[bx] ! pop bx ; init RTM
|
||||
push bx ! callf dword ptr memmod[bx] ! pop bx ; init MEM
|
||||
test module_map,bdosmod_bit ! jz nbdo
|
||||
push bx ! callf dword ptr bdosmod[bx] ! pop bx ; init BDOS
|
||||
|
||||
nbdo: test module_map,ciomod_bit ! jz ncio
|
||||
push bx ! callf dword ptr ciomod[bx] ! pop bx ; init CIO
|
||||
|
||||
ncio: test module_map,xiosmod_bit ! jz nxio
|
||||
push ds ! push es
|
||||
callf dword ptr xiosmod[bx] ! pop es ! pop ds ; init XIOS
|
||||
|
||||
nxio:
|
||||
; reset interrupt vectors after XIOS INIT
|
||||
|
||||
mov ax,ds ! sub bx,bx ! mov ds,bx
|
||||
mov i_os_ip,offset user_entry
|
||||
mov i_os_cs,cs
|
||||
mov ds,ax
|
||||
|
||||
; get Character Dev Info from XIOS
|
||||
|
||||
if mpm
|
||||
mov ax,io_maxconsole ! call xiosif
|
||||
mov ncondev,bl ! mov nciodev,bl
|
||||
mov ax,io_maxlist ! call xiosif
|
||||
mov nlstdev,bl ! add nciodev,bl
|
||||
mov bx,offset initpd
|
||||
mov al,ncondev
|
||||
mov p_lst[bx],al
|
||||
endif
|
||||
; Init CCB and LCB adr in INIT UDA so
|
||||
; child processes will inherit them
|
||||
|
||||
mov cl,f_conattach ! int osint
|
||||
mov cl,f_lstattach ! int osint
|
||||
|
||||
; Start RSPs
|
||||
nrsp: ;loop til done
|
||||
mov ds,sysdat ;reset DS
|
||||
mov cx,rspseg ! jcxz rsp_o ;?all done?
|
||||
mov es,cx ;ES->RSP
|
||||
mov ax,es:.rsp_link ;save next RSP
|
||||
mov rspseg,ax
|
||||
mov es:.rsp_link,ds ;give Sysdat to RSP
|
||||
mov si,rsp_pd ;get PD
|
||||
mov ds,cx ;DS = RSP Data Seg
|
||||
mov p_mem[si],0
|
||||
mov cl,f_createproc ;Create RSP Process(s)
|
||||
mov dx,si ! int osint
|
||||
jmps nrsp ;Do another...
|
||||
rsp_o:
|
||||
; terminate init process
|
||||
mov cl,f_terminate
|
||||
mov dl,0ffh ! int osint
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Format of Load Table Used by Load Program
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
ldt_start equ word ptr 0
|
||||
ldt_min equ word ptr ldt_start + word
|
||||
ldt_max equ word ptr ldt_min + word
|
||||
ldt_pd equ word ptr ldt_max + word
|
||||
ldt_atr equ word ptr ldt_pd + word
|
||||
ldt_fstrt equ word ptr ldt_atr + word
|
||||
ldt_flen equ word ptr ldt_fstrt + word
|
||||
ldt_type equ byte ptr ldt_flen + word
|
||||
ldt_id equ word ptr ldt_type + byte
|
||||
ldtlen equ ldt_id + word
|
||||
@@ -0,0 +1,902 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Program Load
|
||||
;*
|
||||
;*****************************************************
|
||||
;
|
||||
; LDTAB Entry Format:
|
||||
; 0 2 4 6 8
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; | START | MIN | MAX | PD |
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;
|
||||
; 8 10(A) 12(C) 14(E) 16(10) 17(11)
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; | ATR | FSTRT | FLEN | TYPE| ID |
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;
|
||||
;
|
||||
; start Absolute Address requested
|
||||
; min Min memory wanted
|
||||
; max Max memory wanted
|
||||
; pd PD to allocate to
|
||||
; atr Attributes, Memory Flags
|
||||
; fstrt Starting paragraph in File
|
||||
; flen # of paragraphs in file
|
||||
; type Group type
|
||||
; id Segment Address of this group
|
||||
;
|
||||
; The Load Table contains 9 entries, One for each
|
||||
; potential Group in Command File and One extra
|
||||
; for Independent Memory Allocations.
|
||||
|
||||
ldt_start equ word ptr 0
|
||||
ldt_min equ word ptr ldt_start + word
|
||||
ldt_max equ word ptr ldt_min + word
|
||||
ldt_pd equ word ptr ldt_max + word
|
||||
ldt_atr equ word ptr ldt_pd + word
|
||||
ldt_fstrt equ word ptr ldt_atr + word
|
||||
ldt_flen equ word ptr ldt_fstrt + word
|
||||
ldt_type equ byte ptr ldt_flen + word
|
||||
ldt_id equ word ptr ldt_type + byte
|
||||
ldtlen equ ldt_id + word
|
||||
|
||||
|
||||
|
||||
;=========
|
||||
cload_ent: ; entry point to load for a chain command
|
||||
;=========
|
||||
; Assumes UDA is set in passed PD.
|
||||
|
||||
push bx ! mov bx,1
|
||||
jmps load
|
||||
|
||||
;========
|
||||
load_ent: ; User entry point to load .CMD file for execution
|
||||
;========
|
||||
; input: DX = address of open FCB in u_wrkseg
|
||||
; output: BX = segment addr of Base Page
|
||||
; = 0ffffh if error
|
||||
; CX = Error Code
|
||||
|
||||
sub bx,bx
|
||||
;jmp load
|
||||
;====
|
||||
load: ; Intermodule entry point to load .CMD file
|
||||
;====
|
||||
; input: DX = addr of open FCB in u_wrkseg
|
||||
; BX = addr of unused PD to initialize
|
||||
; 0 - do not init PD
|
||||
; 1 - chain load (PD addr on stack)
|
||||
; output: BX = seg addr of Base Page
|
||||
; = 0ffffh if error
|
||||
; CX = Error Code
|
||||
|
||||
; Get MXLoad Queue
|
||||
|
||||
push dx ! push bx
|
||||
mov cx,f_qread ! mov dx,offset mxloadqpb
|
||||
call osif
|
||||
mov lod_chain,false
|
||||
pop lod_pd ! pop si
|
||||
cmp lod_pd,1 ! jne ld_cf
|
||||
pop lod_pd ! mov lod_chain,true
|
||||
|
||||
; Copy FCB into lod_fcb
|
||||
; SI-> user FCB in u_wrkseg
|
||||
|
||||
ld_cf: mov cx,fcblen/2 ! mov di,offset lod_fcb
|
||||
push es ! push ds ! push ds
|
||||
mov ds,u_wrkseg ! pop es
|
||||
rep movsw
|
||||
pop ds ! pop es
|
||||
|
||||
|
||||
; Read the Header
|
||||
|
||||
mov bx,offset lod_fcb
|
||||
mov byte ptr fcb_r0+2[bx],0
|
||||
mov ax,0 ;record #
|
||||
mov bx,1 ;# of sectors
|
||||
mov dx,offset lod_dma ;DMA offset
|
||||
mov cx,sysdat ;DMA segment
|
||||
call drd ! jcxz h_hdr
|
||||
jmp lod_exit
|
||||
h_hdr:
|
||||
mov lod_indma,0
|
||||
|
||||
; initialize Load Disk and User
|
||||
; from FCB
|
||||
|
||||
mov bx,rlr
|
||||
mov al,p_user[bx]
|
||||
mov lod_user,al
|
||||
mov al,p_dsk[bx] ;default disk of calling PD
|
||||
mov lod_disk,al ;1-15 -> A-P
|
||||
mov bx,offset lod_fcb
|
||||
mov al,fcb_dr[bx]
|
||||
mov lod_fifty,al ;base page address 50H, 0=default
|
||||
test al,al ! jz use_ddsk
|
||||
dec al ;1-15 -> A-P
|
||||
mov lod_disk,al
|
||||
use_ddsk:
|
||||
test byte ptr fcb_name+7[bx],080h ! jz use_dusr
|
||||
|
||||
mov lod_user,0
|
||||
use_dusr:
|
||||
|
||||
; Initialize ldtab
|
||||
|
||||
; Zero ldtab
|
||||
mov cx,ldtabsiz/2 ! sub ax,ax
|
||||
mov di,offset ldtab
|
||||
push es ! mov es,sysdat
|
||||
rep stos ax ! pop es
|
||||
|
||||
; 1st ldtab entry is UDA and LSTK
|
||||
; if a PD was specified...
|
||||
|
||||
mov lod_nldt,0
|
||||
mov si,offset ldtab
|
||||
cmp lod_pd,0 ! jne form_uda
|
||||
jmp gc_ifo
|
||||
form_uda: mov ldt_min[si],(lstklen+ulen)/16 ;min=max=UDA+STK paragraphs
|
||||
mov ldt_max[si],(lstklen+ulen)/16
|
||||
mov ax,lod_pd ! mov ldt_pd[si],ax
|
||||
mov ldt_atr[si],mf_load
|
||||
add si,ldtlen
|
||||
inc lod_nldt
|
||||
cmp lod_chain,true ! jne gc_ifo
|
||||
|
||||
;We are CHAINING. Free all memory
|
||||
; except UDA area and LDSTK. This will keep
|
||||
; the first partition for the chain
|
||||
; as well as not crash the system.
|
||||
|
||||
push si
|
||||
mov cx,f_freeall ! call osif
|
||||
|
||||
;transfer memory to new pd
|
||||
|
||||
mov bx,rlr
|
||||
mov ax,p_mem[bx] ! mov p_mem[bx],0
|
||||
mov bx,lod_pd ! mov p_mem[bx],ax
|
||||
pop si
|
||||
|
||||
gc_ifo:
|
||||
;go through CMD header and init
|
||||
;a ldtab entry per header entry.
|
||||
;alloc abs mem
|
||||
|
||||
mov bx,offset lod_dma
|
||||
mov al,ch_lbyte[bx] ; save fixup flag
|
||||
mov lod_lbyte,al
|
||||
mov ax,ch_fixrec[bx] ; save record # of fixups, if any
|
||||
mov lod_fixrec,ax
|
||||
mov lod_fixrec1,ax
|
||||
|
||||
mov cx,ch_entmax ; BX = offset LOD_DMA
|
||||
mov dx,8 ; DX = position in file
|
||||
ch_more:cmp ch_form[bx],0 ! jne ch_doit
|
||||
jmp ch_next
|
||||
ch_doit: mov al,ch_form[bx] ! mov ldt_type[si],al ;type of seg
|
||||
mov ax,ch_length[bx] ! mov ldt_flen[si],ax ;length
|
||||
mov ldt_fstrt[si],dx ! add dx,ax ;pos in file
|
||||
mov ax,ch_base[bx] ! mov ldt_start[si],ax ;abs seg
|
||||
mov ax,ch_min[bx] ! mov ldt_min[si],ax ;min needed
|
||||
mov ax,ch_max[bx]
|
||||
cmp ax,0 ! jne setmax
|
||||
mov ax,ch_min[bx]
|
||||
setmax: mov ldt_max[si],ax ;max wanted
|
||||
mov ax,lod_pd ! mov ldt_pd[si],ax ;pd to alloc to
|
||||
cmp ax,0 ! je not_load
|
||||
mov ax,mf_load
|
||||
|
||||
jmps not_load
|
||||
skipjmp:jmps ch_more
|
||||
|
||||
if mpm
|
||||
|
||||
not_load: cmp ch_form[bx],1 ! jne try_sh
|
||||
add ax,mf_code ! jmps s_atr
|
||||
try_sh: cmp ch_form[bx],9 ! jne s_atr
|
||||
add ax,mf_code+mf_share
|
||||
s_atr: mov ldt_atr[si],ax ;memory flags
|
||||
|
||||
;if abs, allocate memory
|
||||
cmp ldt_start[si],0 ! je ch_nabs ;see if abs mem
|
||||
jmps ch_al
|
||||
ch_nabs: cmp ldt_type[si],9
|
||||
jne ch_nxt ;see if shared code
|
||||
push cx
|
||||
push bx ! push dx ;save load DMA and position in file
|
||||
call get_sh
|
||||
|
||||
pop dx ! pop bx
|
||||
cmp cx,0 ! pop cx
|
||||
je ch_nxt
|
||||
jmp ld_out
|
||||
ch_al: push bx ! push dx ! push cx ! push si
|
||||
mov cx,f_malloc ! mov dx,si
|
||||
call osif ! pop si
|
||||
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
||||
cmp cx,0 ! pop cx ! pop dx ! pop bx
|
||||
je ch_nxt
|
||||
;couldn't find memory
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
jmp ld_out
|
||||
|
||||
endif
|
||||
|
||||
if ccpm
|
||||
|
||||
not_load: cmp ch_form[bx],9 ! jne try_code
|
||||
mov ch_form[bx],1
|
||||
mov ldt_type[si],1
|
||||
try_code: cmp ch_form[bx],1 ! jne s_atr
|
||||
add ax,mf_code
|
||||
s_atr: mov ldt_atr[si],ax ;memory flags
|
||||
|
||||
;if abs, allocate memory
|
||||
cmp ldt_start[si],0 ! je ch_nxt ;see if abs mem
|
||||
ch_al: push bx ! push dx ! push cx ! push si
|
||||
mov cx,f_malloc ! mov dx,si
|
||||
call osif ! pop si
|
||||
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
||||
cmp cx,0 ! pop cx ! pop dx ! pop bx
|
||||
je ch_nxt
|
||||
;couldn't find memory
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
jmp ld_out
|
||||
|
||||
endif
|
||||
|
||||
ch_nxt: add si,ldtlen
|
||||
inc lod_nldt
|
||||
ch_next:add bx,chlen
|
||||
loop skipjmp
|
||||
|
||||
; alloc all other memory
|
||||
; SI -> mpb for non_abs mem req.
|
||||
;add all parts together for a single malloc
|
||||
mov bx,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
mov lod_nrels,0
|
||||
lt_more:cmp ldt_min[bx],0 ! je lt_next
|
||||
cmp ldt_start[bx],0 ! jne lt_next
|
||||
mov ax,ldt_min[bx]
|
||||
mov dx,ax
|
||||
add ldt_min[si],ax
|
||||
cmp dx,ldt_min[si] ! jbe lt_m ; check for ovrflw
|
||||
mov ldt_min[si],0ffffh
|
||||
lt_m: mov ax,ldt_max[bx]
|
||||
mov dx,ax
|
||||
add ldt_max[si],ax
|
||||
cmp dx,ldt_max[si] ! jbe lt_m1 ; check for ovrflw
|
||||
mov ldt_max[si],0ffffh
|
||||
lt_m1: inc lod_nrels
|
||||
lt_next:add bx,ldtlen ! loop lt_more
|
||||
|
||||
;malloc
|
||||
cmp lod_pd,0 ! je noloadf
|
||||
mov ldt_atr[si],mf_load
|
||||
noloadf:mov ax,lod_pd ! mov ldt_pd[si],ax
|
||||
push si ! mov dx,si ! mov cx,f_malloc
|
||||
call osif ! pop si
|
||||
mov ax,ldt_start[si] ! mov ldt_id[si],ax
|
||||
cmp bx,0ffffh ! jne lt_sprd
|
||||
|
||||
;Not Enough Memory - release any
|
||||
; memory already allocated
|
||||
ld_out: push cx
|
||||
mov bx,offset ldtab
|
||||
mov cx,lod_nldt ! inc cx
|
||||
lg_more: cmp ldt_id[bx],0 ! je lg_next
|
||||
push cx ! push bx ! push ds
|
||||
;push MFPB on stack
|
||||
push ldt_pd[bx]
|
||||
push ldt_id[bx]
|
||||
mov dx,sp ! push ss ! pop ds
|
||||
mov cx,f_memfree
|
||||
call osif
|
||||
pop cx ! pop cx
|
||||
|
||||
pop ds ! pop bx ! pop cx
|
||||
lg_next: add bx,ldtlen ! loop lg_more
|
||||
mov bx,0ffffh ! pop cx ! jmp lod_exit
|
||||
|
||||
lt_sprd:
|
||||
;spread the memory allocated
|
||||
;amongst the nrels
|
||||
;1st give everyone the minimum
|
||||
mov bx,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
ls_more:cmp ldt_start[bx],0 ! jne ls_next
|
||||
mov ax,ldt_min[bx]
|
||||
sub ldt_min[si],ax
|
||||
cmp ax,ldt_max[bx] ! jne ls_next
|
||||
mov dx,ldt_start[si] ! mov ldt_start[bx],dx
|
||||
add ldt_start[si],ax
|
||||
dec lod_nrels
|
||||
ls_next:add bx,ldtlen ! loop ls_more
|
||||
|
||||
;spread whats left amongst those that need more
|
||||
mov bx,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
lsl_mre:cmp ldt_start[bx],0 ! jne lsl_nxt
|
||||
mov ax,ldt_start[si] ! mov ldt_start[bx],ax
|
||||
mov ax,ldt_min[si]
|
||||
cmp ax,0 ! je adj_start
|
||||
push cx ! sub cx,cx
|
||||
mov dx,cx ! mov cl,lod_nrels
|
||||
div cx ! pop cx
|
||||
cmp dx,0 ! je evendiv
|
||||
inc ax
|
||||
evendiv: mov dx,ldt_max[bx] ! sub dx,ldt_min[bx]
|
||||
cmp ax,dx ! jbe nottoomuch
|
||||
mov ax,dx
|
||||
nottoomuch: add ldt_min[bx],ax ! sub ldt_min[si],ax
|
||||
adj_start: mov ax,ldt_min[bx] ! add ldt_start[si],ax
|
||||
dec lod_nrels
|
||||
lsl_nxt:add bx,ldtlen ! loop lsl_mre
|
||||
|
||||
; fill memory from file
|
||||
|
||||
mov si,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
lf_mre: cmp ldt_flen[si],0 ! je lf_nxt
|
||||
push cx ! push ldt_start[si] ! push si
|
||||
call lod_group
|
||||
pop si ! pop ldt_start[si]
|
||||
cmp cx,0 ! pop cx
|
||||
je lf_nxt
|
||||
|
||||
if ccpm
|
||||
|
||||
jmp ld_out
|
||||
endif
|
||||
|
||||
if mpm
|
||||
|
||||
; error in lod_group
|
||||
; if loading shared code we also
|
||||
; have to release Shared Code from SCL.
|
||||
; It will be the top item in the list.
|
||||
|
||||
cmp ldt_atr[si],mf_load+mf_code+mf_share
|
||||
je rm_sh
|
||||
jmp ld_out
|
||||
rm_sh: push cx ; remember Err Code
|
||||
|
||||
; Remove PD from SCL
|
||||
pushf ! cli
|
||||
mov bx,scl
|
||||
mov ax,p_thread[bx]
|
||||
mov scl,ax
|
||||
popf
|
||||
|
||||
; Release the memory
|
||||
|
||||
push ds ! push bx
|
||||
mov bx,p_mem[bx] ! push ms_start[bx]
|
||||
mov ax,ss ! mov ds,ax
|
||||
mov dx,sp ! mov cx,f_memfree
|
||||
call osif
|
||||
pop ax ! pop bx ! pop ds
|
||||
|
||||
; Place PD on PUL
|
||||
|
||||
pushf ! cli
|
||||
mov ax,pul
|
||||
mov pul,bx
|
||||
mov p_link[bx],ax
|
||||
popf
|
||||
|
||||
pop cx
|
||||
jmp ld_out
|
||||
endif
|
||||
|
||||
lf_nxt: add si,ldtlen ! loop lf_mre
|
||||
|
||||
|
||||
; Check for fixup records and do fixups
|
||||
|
||||
test lod_lbyte,80h ; hi bit of last byte in cmd header
|
||||
jz init_base ; is set if fixups
|
||||
fx_read:
|
||||
mov ax,lod_fixrec ; get record # of fixups in file
|
||||
mov bx,1 ; read one record
|
||||
mov cx,ds
|
||||
mov dx, offset lod_dma
|
||||
call drd ; do random read
|
||||
jcxz fx_read_ok ; 0=ok,CL=0ff if EOF
|
||||
inc cl ; EOF ?
|
||||
jnz fx_err ; some read error, not EOF
|
||||
mov ax,lod_fixrec1 ; make sure one fixup
|
||||
cmp ax,lod_fixrec ; record was read since cmd header
|
||||
je fx_err ; said we needed them
|
||||
jmps init_base
|
||||
|
||||
fx_read_ok: ; go look for fixup records
|
||||
mov bx,offset lod_dma ; BX-> at fixup records
|
||||
fx_chk:
|
||||
mov al,fix_grp[bx] ; any more fixups?
|
||||
test al,al
|
||||
jz init_base
|
||||
and al,0fh ; low nibble is target group
|
||||
call tblsrch ; find target group in load table
|
||||
mov dx,ldt_start[di] ; DX = target segment, this is
|
||||
; what we add to the load image
|
||||
mov al,fix_grp[bx] ; location group is high nibble
|
||||
mov cl,4 ; put in low nibble of AL
|
||||
shr al,cl
|
||||
call tblsrch ; DI = location load table entry
|
||||
mov ax,ldt_start[di] ; AX = base segment of location
|
||||
add ax,fix_para[bx] ; add paragraph offset
|
||||
|
||||
push es ; absolute paragraph in memory
|
||||
mov es,ax
|
||||
xor ax,ax
|
||||
mov al,fix_offs[bx] ; get offset of fixup location
|
||||
mov di,ax
|
||||
add es:[di],dx ; make the fixup (finally)
|
||||
pop es
|
||||
|
||||
add bx,fixlen ; do next fixup
|
||||
cmp bx,offset lod_dma + dskrecl ; end of this record ?
|
||||
jne fx_chk
|
||||
inc lod_fixrec ; read another record
|
||||
jmps fx_read ; of fixups
|
||||
|
||||
tblsrch:
|
||||
;-------
|
||||
; Search for group in load table
|
||||
; entry: AL = group # to match on
|
||||
; exit: DI = load group entry that matches or
|
||||
; pop return and exit loader
|
||||
; BX,DX preserved
|
||||
|
||||
mov cx,lod_nldt ; # entries in table
|
||||
mov di,offset ldtab
|
||||
srchloop:
|
||||
cmp al,ldt_type[di]
|
||||
je srchdn ; found group's entry
|
||||
add di,ldtlen
|
||||
loop srchloop
|
||||
pop ax
|
||||
jmps fx_err
|
||||
srchdn:
|
||||
ret
|
||||
|
||||
fx_err:
|
||||
mov cx,e_fixuprec
|
||||
jmp ld_out
|
||||
|
||||
|
||||
|
||||
; init Base Page
|
||||
; 1st Data Group has Base Page
|
||||
; if none then first nonshared
|
||||
; Code Group (8080 model)
|
||||
init_base:
|
||||
mov lod_8080,0
|
||||
mov si,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
lb_more:cmp ldt_type[si],2 ! je lb_fnd
|
||||
add si,ldtlen ! loop lb_more
|
||||
mov si,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
lbc_mre: cmp ldt_type[si],1 ! je lb_fnd80
|
||||
add si,ldtlen ! loop lbc_mre
|
||||
mov cx,e_no_cseg ! jmp ld_out
|
||||
lb_fnd80: mov lod_8080,1
|
||||
lb_fnd:
|
||||
push es ! mov es,ldt_start[si]
|
||||
mov lod_basep,es
|
||||
sub ax,ax ! mov di,ax
|
||||
mov cx,05bh/2 ! rep stos ax
|
||||
mov al,lod_8080 ! mov es:.5,al
|
||||
mov si,offset ldtab
|
||||
mov cx,lod_nldt
|
||||
lbb_mre:cmp ldt_type[si],0 ! je lbb_nxt
|
||||
mov ax,6 ! mov bl,ldt_type[si]
|
||||
cmp bl,9 ! jne lbb_nsh
|
||||
mov bl,1
|
||||
lbb_nsh: dec bl ! mul bl ! mov bx,ax
|
||||
|
||||
;calculate last byte (3 byte value)
|
||||
; =(paragraphs*16)-1
|
||||
push cx ! mov dx,ldt_min[si]
|
||||
push dx ! mov cl,4 ! shl dx,cl
|
||||
push dx ! dec dx ! mov es:[bx],dx
|
||||
pop cx ! pop dx ! push cx
|
||||
mov cl,12 ! shr dx,cl ! pop cx
|
||||
cmp cx,0 ! jne lbb_nzer
|
||||
cmp dx,0 ! je lbb_zer
|
||||
dec dl ! jmps lbb_nzer
|
||||
lbb_zer: mov es:word ptr [bx],0
|
||||
lbb_nzer: mov es:2[bx],dl ! pop cx
|
||||
|
||||
;put starting paragraph in place
|
||||
mov ax,ldt_start[si] ! mov es:3[bx],ax
|
||||
|
||||
lbb_nxt:add si,ldtlen ! loop lbb_mre
|
||||
|
||||
;if 8080 model, copy CS info into DS info
|
||||
|
||||
cmp lod_8080,1 ! jne lnot80
|
||||
push ds ! push es ! pop ds ! mov si,0
|
||||
mov di,6 ! mov cx,3
|
||||
rep movsw ! pop ds
|
||||
lnot80:
|
||||
mov al,lod_fifty ;initialize base page load disk
|
||||
mov es:.50H,al
|
||||
pop es
|
||||
|
||||
; init PD ,UDA and LDSTK
|
||||
|
||||
mov bx,lod_basep
|
||||
cmp lod_pd,0 ! jne lip_1
|
||||
jmp lod_exit
|
||||
lip_1: mov si,offset ldtab
|
||||
mov bx,lod_pd
|
||||
mov ax,ldt_start[si]
|
||||
mov p_uda[bx],ax
|
||||
; remember where lstk,uda are
|
||||
mov lod_uda,ax
|
||||
push es ! mov es,ax
|
||||
add ax,(ulen/16) ! mov lod_lstk,ax
|
||||
; initialize UDA,LDSTK with zeros
|
||||
xor di,di ! mov ax,di
|
||||
mov cx,(ulen + lstklen)/2
|
||||
rep stos ax ! pop es
|
||||
|
||||
; setup p_uda for creat_proc
|
||||
|
||||
mov ax,sysdat
|
||||
sub p_uda[bx],ax
|
||||
mov p_stat[bx],ps_run
|
||||
mov p_prior[bx],200
|
||||
|
||||
; init load disk/user
|
||||
|
||||
mov al,lod_user ! mov p_luser[bx],al
|
||||
mov al,lod_disk ! mov p_ldsk[bx],al
|
||||
|
||||
; init UDA
|
||||
|
||||
push es ! mov es,lod_uda
|
||||
mov u_dma_ofst,(offset bpg_dma)
|
||||
mov bx,lod_basep
|
||||
|
||||
mov u_dma_seg,bx
|
||||
mov ax,lod_lstk
|
||||
push ds ! mov ds,bx
|
||||
mov u_initds,bx
|
||||
mov u_inites,bx
|
||||
mov u_initss,ax
|
||||
mov ax,bpg_cseg
|
||||
cmp ax,0 ! jne h_cs
|
||||
pop ds ! pop es ! mov cx,e_no_cseg
|
||||
jmp ld_out
|
||||
h_cs: mov u_initcs,ax
|
||||
mov ax,bpg_eseg
|
||||
cmp ax,0 ! je noes
|
||||
mov u_inites,ax
|
||||
noes: mov u_stack_sp,(offset ls_sp)
|
||||
sub dx,dx ! mov al,bpg_8080
|
||||
cmp al,0 ! je n80m
|
||||
mov dx,0100h
|
||||
n80m:
|
||||
mov ds,u_initss
|
||||
mov ls_offset,dx ;set up initial stack
|
||||
mov ls_flags,0200h ;for a RETF from user
|
||||
mov ls_roffset,offset user_retf ;process, see SUPIF.SUP
|
||||
mov ls_rcseg,cs ;module for USER_RETF:
|
||||
pop ds ! pop es ;code
|
||||
|
||||
mov bx,lod_basep
|
||||
sub cx,cx
|
||||
lod_exit:
|
||||
push cx ! push bx
|
||||
mov cx,f_qwrite ! mov dx,offset mxloadqpb
|
||||
call osif ! pop bx ! pop cx ! ret
|
||||
|
||||
|
||||
lod_group: ;load a group described in ldtab
|
||||
;----------
|
||||
; input: SI = addr of ldtab entry
|
||||
; output: CX = Error Code
|
||||
|
||||
; see if first part already in DMA
|
||||
mov bx,si
|
||||
mov ax,lod_indma ;starting paragraph in dma
|
||||
mov cx,ldt_fstrt[bx]
|
||||
;AX = starting paragraph in local DMA
|
||||
;CX = starting paragraph to transfer
|
||||
;BX -> ldtab entry
|
||||
cmp cx,ax ! jb rd_first
|
||||
;starts at or after the pp. in dma
|
||||
sub cx,ax
|
||||
cmp cx,8 ! jae rd_first
|
||||
;starts in the dma
|
||||
mov dx,8 ! sub dx,cx
|
||||
;CX = # of pp. to skip
|
||||
;DX = length of remaining buffer
|
||||
cmp dx,ldt_flen[bx] ! jbe xfer
|
||||
mov dx,ldt_flen[bx]
|
||||
xfer: mov si,offset lod_dma
|
||||
mov ax,cx ! mov cl,4 ! shl ax,cl
|
||||
add si,ax
|
||||
;SI -> beginning of transfer area
|
||||
; in lod_dma
|
||||
mov ax,dx ! mov cl,3 ! shl ax,cl
|
||||
mov cx,ax
|
||||
;CX = number of words to transfer
|
||||
xor di,di
|
||||
push es ! mov es,ldt_start[bx]
|
||||
rep movsw ! pop es
|
||||
add ldt_start[bx],dx
|
||||
sub ldt_flen[bx],dx ! add ldt_fstrt[bx],dx
|
||||
rd_first:
|
||||
cmp ldt_flen[bx],0 ! jne rd_1st
|
||||
sub cx,cx ! ret
|
||||
rd_1st:
|
||||
test ldt_fstrt[bx],07h ! jnz rd_indma
|
||||
cmp ldt_flen[bx],8 ! jae xf_d
|
||||
rd_indma:
|
||||
push bx
|
||||
mov ax,ldt_fstrt[bx]
|
||||
shr ax,1 ! shr ax,1 ! shr ax,1 ; Record #
|
||||
mov bx,1 ; read 1 record
|
||||
mov dx,offset lod_dma ; DMA offset
|
||||
mov cx,sysdat ; DMA segment
|
||||
call drd
|
||||
pop bx
|
||||
jcxz rd_agn
|
||||
cmp cx,0ffh ! jne rd_r3
|
||||
mov cx,0
|
||||
rd_r3: ret
|
||||
rd_agn: mov ax,ldt_fstrt[bx]
|
||||
and ax,0fff8h ; note starting paragraph
|
||||
mov lod_indma,ax ; in DMA
|
||||
mov si,bx ! jmp lod_group
|
||||
|
||||
; We are at a Sector Boundary with at least
|
||||
; a sector to place into the user area
|
||||
xf_d:
|
||||
push bx
|
||||
sub dx,dx ; DMA offset
|
||||
mov cx,ldt_start[bx] ; DMA segment
|
||||
|
||||
mov ax,ldt_fstrt[bx]
|
||||
shr ax,1 ! shr ax,1 ! shr ax,1 ; Record #
|
||||
mov bx,ldt_flen[bx]
|
||||
shr bx,1 ! shr bx,1 ! shr bx,1 ; # of records
|
||||
push bx
|
||||
call drd
|
||||
pop ax ! pop bx
|
||||
jcxz xfer_n
|
||||
cmp cx,0ffh ! jne rd_r4
|
||||
xor cx,cx
|
||||
rd_r4: ret
|
||||
xfer_n: shl ax,1 ! shl ax,1 ! shl ax,1
|
||||
add ldt_start[bx],ax
|
||||
add ldt_fstrt[bx],ax
|
||||
sub ldt_flen[bx],ax
|
||||
jmp rd_first
|
||||
|
||||
drd:
|
||||
; input: AX = Record Number
|
||||
; BX = Number of Sectors
|
||||
; CX = dma segment
|
||||
; DX = dma offset
|
||||
; output: CX = 0 if okay
|
||||
; CX = 0FFH if End of File
|
||||
; else Error Code
|
||||
|
||||
mov u_dma_ofst,dx
|
||||
mov u_dma_seg,cx
|
||||
|
||||
; read BX sectors starting at Record AX
|
||||
drd_lp:
|
||||
push bx ;old # sectors
|
||||
push ax ;old record #
|
||||
cmp bx,128 ! jbe drd_r
|
||||
mov bx,128
|
||||
|
||||
; Max Mulit-sector count is 128
|
||||
|
||||
drd_r: mov cl,u_mult_cnt
|
||||
push cx
|
||||
mov u_mult_cnt,bl
|
||||
push bx
|
||||
mov si,offset lod_fcb
|
||||
mov fcb_r0[si],ax
|
||||
mov cx,f_freadrdm ! mov dx,si
|
||||
push es ! call osif ! pop es
|
||||
pop dx ;multi_cnt used
|
||||
pop cx ! mov u_mult_cnt,cl
|
||||
cmp bl,1 ! jbe dr_r2
|
||||
mov cx,e_bad_read ! mov bx,0ffffh
|
||||
pop ax ! pop ax ! ret
|
||||
dr_r2: mov cl,bl
|
||||
pop ax ! add ax,dx ;adjust record #
|
||||
pop bx ! sub bx,dx ;adjust # sectors
|
||||
shl dx,1 ! shl dx,1 ! shl dx,1
|
||||
add u_dma_seg,dx
|
||||
|
||||
; check for CTRL C. If hit while loading
|
||||
; last set of characters, this is the place to
|
||||
; clean things up...
|
||||
|
||||
push cx ! push ax ! push bx
|
||||
mov cx,f_ciostat ! call osif
|
||||
pop bx ! pop ax ! pop cx
|
||||
|
||||
; Now see if CTRL C was hit during the
|
||||
; the load.
|
||||
|
||||
mov si,rlr
|
||||
test p_flag[si],pf_ctlc ! jz dr_r1
|
||||
mov cx,e_abort ! mov bx,0ffffh
|
||||
ret
|
||||
dr_r1: cmp cl,0 ! je dr_r5
|
||||
mov cx,0ffh ! ret
|
||||
dr_r5: cmp bx,0 ! jne drd_lp
|
||||
xor cx,cx
|
||||
ret
|
||||
|
||||
if mpm
|
||||
|
||||
get_sh:
|
||||
;------
|
||||
; Allocate memory for shared code. If memory already
|
||||
; exists then mark LDTAB entry with FLEN=0 for no load.
|
||||
; START must be non-zero on success.
|
||||
;
|
||||
|
||||
; input: SI = LDTAB Entry for shared code
|
||||
; output: CX = 0 on success
|
||||
; = 0ffffh on failure
|
||||
; SI is unchanged
|
||||
;
|
||||
|
||||
; 1. Look for PD Name on SCL, making sure
|
||||
; LDSK and LUSER are the same.
|
||||
|
||||
mov bx,(offset scl)-p_thread
|
||||
gs_nxt: push si
|
||||
mov dx,offset lod_fcb ! add dx,fcb_name
|
||||
mov cx,f_findpdname ! call osif
|
||||
; BX=pd found or 0ffffh
|
||||
pop si
|
||||
cmp bx,0ffffh ! je no_sh
|
||||
mov al,lod_disk
|
||||
cmp p_ldsk[bx],al ! jne gs_nxt
|
||||
mov al,lod_user
|
||||
cmp p_luser[bx],al ! jne gs_nxt
|
||||
|
||||
; 2. if (1.) then Share the Memory.
|
||||
; 2.1 Set FLEN=0
|
||||
|
||||
push bx ! push si
|
||||
call shmem
|
||||
pop si ! pop bx
|
||||
cmp cx,0ffffh ! je no_sh
|
||||
mov ldt_flen[si],0
|
||||
|
||||
; Put SHARE PD on end of SCL
|
||||
; BX = SHARE PD
|
||||
|
||||
pushf ! cli
|
||||
mov di,(offset SCL)-p_thread
|
||||
sh_nin1: cmp p_thread[di],bx ! je sh_rm ;look for share PD
|
||||
mov di,p_thread[di] ! jmps sh_nin1
|
||||
sh_rm: mov ax,p_thread[bx] ;take it off the list
|
||||
mov p_thread[di],ax
|
||||
sh_in: cmp p_thread[di],0 ! je sh_end ;look for the end
|
||||
mov di,p_thread[di] ! jmps sh_in
|
||||
sh_end: mov p_thread[di],bx ;insert share PD on end
|
||||
xor cx,cx
|
||||
mov p_thread[bx],cx
|
||||
popf ! ret ;success
|
||||
|
||||
; 3. if (NOT 1.) allocate memory to NEW PD
|
||||
no_sh:
|
||||
|
||||
; get new PD
|
||||
|
||||
pushf ! cli
|
||||
mov bx,pul
|
||||
cmp bx,0 ! je sherr
|
||||
mov ax,p_link[bx] ! mov pul,ax
|
||||
popf
|
||||
|
||||
; alloc memory for code segment
|
||||
|
||||
push bx ! push si
|
||||
mov cx,f_malloc
|
||||
mov dx,si
|
||||
call osif
|
||||
pop si ! pop bx
|
||||
cmp cx,0 ! jne merr
|
||||
|
||||
; initialize new PD name
|
||||
; BX = New PD
|
||||
push si
|
||||
mov si,ldt_pd[si] ;SI=old pd
|
||||
push si
|
||||
mov di,bx
|
||||
add si,p_name ! add di,p_name
|
||||
mov cx,4
|
||||
push es ! mov ax,ds ! mov es,ax
|
||||
rep movsw
|
||||
pop es ! pop di ! pop si
|
||||
|
||||
; DI = old PD, BX=New PD
|
||||
|
||||
mov al,lod_user ! mov p_luser[bx],al
|
||||
mov al,lod_disk ! mov p_ldsk[bx],al
|
||||
|
||||
; share w/new PD
|
||||
|
||||
mov ax,ldt_start[si]
|
||||
push bx ! push si ! push ds
|
||||
push ax ! push bx ! push di
|
||||
mov ax,ss ! mov ds,ax
|
||||
mov dx,sp ! mov cx,f_share
|
||||
call osif
|
||||
add sp,6
|
||||
pop ds ! pop si ! pop bx
|
||||
|
||||
; put new PD on SCL
|
||||
|
||||
pushf ! cli
|
||||
mov di,(offset SCL)-p_thread
|
||||
sh_nin: cmp p_thread[di],0 ! je sh_doit
|
||||
mov di,p_thread[di] ! jmps sh_nin
|
||||
sh_doit: mov p_thread[di],bx ;insert new share PD
|
||||
xor cx,cx
|
||||
mov p_thread[bx],cx
|
||||
popf ! ret ;success
|
||||
merr: pushf ! cli
|
||||
mov ax,pul
|
||||
mov p_link[bx],ax
|
||||
mov pul,bx
|
||||
sherr: popf
|
||||
mov cx,0ffffh ! ret
|
||||
|
||||
shmem:
|
||||
;-----
|
||||
;input: SI = LDTAB
|
||||
; BX = Owner PD
|
||||
; Load_pd = Requestor
|
||||
; Have to set LDT_START
|
||||
;
|
||||
|
||||
lea di,(p_mem-ms_link)[bx]
|
||||
sm_nxt:
|
||||
mov di,ms_link[di]
|
||||
cmp di,0 ! je sm_no
|
||||
mov ax,ms_flags[di]
|
||||
and ax,mf_share+mf_code+mf_load
|
||||
cmp ax,mf_share+mf_code+mf_load ! jne sm_nxt
|
||||
push si ! push ds
|
||||
push ms_start[di]
|
||||
push ms_start[di]
|
||||
push lod_pd
|
||||
push bx
|
||||
mov ax,ss ! mov ds,ax
|
||||
mov dx,sp ! mov cx,f_share
|
||||
call osif
|
||||
|
||||
; This will always work.
|
||||
|
||||
pop ax ! pop ax ! pop ax
|
||||
pop dx ! pop ds ! pop si
|
||||
mov ldt_start[si],dx
|
||||
ret
|
||||
sm_no: mov cx,0ffffh ! ret
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Partition Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
mpb_segadr equ word ptr 0
|
||||
mpb_min equ word ptr mp_segadr + word
|
||||
mpb_max equ word ptr mp_min + word
|
||||
mpb_pdadr equ word ptr mp_max + word
|
||||
mpb_attrib equ word ptr mp_pdadr + word
|
||||
|
||||
mpblen equ mp_attrib + word
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Load Memory Segment Format
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
mp_stacksize equ 96*byte
|
||||
|
||||
mp_uda equ 0
|
||||
mp_stack equ mp_uda+ulen
|
||||
mp_segstart equ mp_stack+mp_stacksize
|
||||
|
||||
mp_udapar equ mp_uda/16
|
||||
mp_stkpar equ mp_stack/16
|
||||
mp_nparag equ mp_segstart/16
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Load Stack Format
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
lstklen equ 96 * byte
|
||||
|
||||
DSEG
|
||||
org lstklen - 10
|
||||
|
||||
ls_sp rw 0
|
||||
ls_offset rw 1
|
||||
ls_cseg rw 1
|
||||
ls_flags rw 1
|
||||
ls_roffset rw 1
|
||||
ls_rcseg rw 1
|
||||
@@ -0,0 +1,306 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Allocation Unit Routines
|
||||
;*
|
||||
;* Memory Allocation Unit
|
||||
;* A Memory Allocation Unit is a contiguous
|
||||
;* area of memory that is described by a MD.
|
||||
;* At the beginning of this area is a Suballocation
|
||||
;* table that describes areas within it that are
|
||||
;* allocated or free
|
||||
;*
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* MD | Link | Start | Length | Plist |
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;*
|
||||
;* Link - Link field for placing MAUs on Linked
|
||||
;* lists
|
||||
;* Start - Segment Address of the area covered
|
||||
;* Length - Length of area
|
||||
|
||||
;* Plist - used for a linked list of partitions
|
||||
;* that are included in this area.
|
||||
;*
|
||||
;* Suballocation Table
|
||||
;* The m_start field is the segment
|
||||
;* address of the suballocation table (offset 0).
|
||||
;* The first entry of the table is special and
|
||||
;* has the following format.
|
||||
;*
|
||||
;* +----+----+----+----+----+
|
||||
;* SAT0 |ents| reserved |
|
||||
;* +----+----+----+----+----+
|
||||
;*
|
||||
;* sat1_ents - number of SAT entries
|
||||
;* not including SAT0
|
||||
;* Subsequent entries have the following format
|
||||
;*
|
||||
;* +----+----+----+----+----+
|
||||
;* SAT | Start | Length |nall|
|
||||
;* +----+----+----+----+----+
|
||||
;*
|
||||
;* start - start address of this contiguous
|
||||
;* piece of memory
|
||||
;* length - of this piece of memory
|
||||
;* nall - number of times allocated
|
||||
;* 0 = free 2 = share
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
sat_start equ word ptr 0
|
||||
sat_length equ word ptr sat_start + word
|
||||
sat_nall equ byte ptr sat_length + word
|
||||
satlen equ sat_nall + byte
|
||||
|
||||
;==============
|
||||
maualloc_entry: ; Alloc from MAU
|
||||
;==============
|
||||
; Allocate a piece of memory from an MAU
|
||||
;
|
||||
; input: BX = address of MAU
|
||||
; DX = MPB in u_wrkseg
|
||||
; mpb_start = abs addr (0 = any)
|
||||
; mpb_min = minimum necessary
|
||||
; mpb_max = maximum wanted
|
||||
;
|
||||
; output: BX = 0h if success
|
||||
; 0ffffh if failure
|
||||
; CX = Error Code
|
||||
; mpb_start = start address
|
||||
; mpb_min = mcb_max = length
|
||||
|
||||
|
||||
push es ! mov es,u_wrkseg
|
||||
|
||||
; if absolute, see if within MAU
|
||||
mov si,dx ! mov cx,es:mpb_start[si]
|
||||
cmp cx,0 ! je maua_rel
|
||||
mov ax,m_start[bx]
|
||||
cmp cx,ax ! jb maua_err
|
||||
add ax,m_length[bx]
|
||||
cmp cx,ax ! jae maua_err
|
||||
maua_rel:
|
||||
mov ds,m_start[bx]
|
||||
maua_start:
|
||||
sub bx,bx ! mov dl,bl ;BX->SAT entry
|
||||
;DL = SAT number
|
||||
maua_nsat:
|
||||
inc dl ! add bx,satlen
|
||||
|
||||
cmp dl,.0 ! ja maua_err ;?out of table entries?
|
||||
cmp sat_start[bx],0 ! je maua_err ;?end of used table?
|
||||
cmp sat_nall[bx],0 ! jne maua_nsat ;?already allocated?
|
||||
mov cx,es:mpb_start[si]
|
||||
cmp cx,0 ! je maua_nabs ;?abs req?
|
||||
mov ax,sat_start[bx]
|
||||
cmp cx,ax ! jb maua_nsat ;?in this area?
|
||||
add ax,sat_length[bx]
|
||||
cmp cx,ax ! jae maua_nsat
|
||||
cmp cx,sat_start[bx] ! je maua_nabs ;?exact?
|
||||
sub cx,sat_start[bx]
|
||||
push si
|
||||
call mau_split ;make exact
|
||||
pop si
|
||||
jmps maua_start
|
||||
maua_err:
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
jmps maua_out
|
||||
maua_nabs:
|
||||
mov cx,es:mpb_min[si]
|
||||
mov ax,sat_length[bx]
|
||||
cmp cx,ax ! ja maua_nsat
|
||||
mov cx,es:mpb_max[si]
|
||||
cmp cx,ax ! jae maua_alloc
|
||||
cmp sat_nall[bx],0 ! je maua_splitit
|
||||
mov ax,es:mpb_flags[si]
|
||||
and ax,mf_share ! jz maua_nsat
|
||||
jmps maua_alloc
|
||||
maua_splitit: push si ! call mau_split ! pop si
|
||||
maua_alloc: mov ax,sat_length[bx]
|
||||
mov es:mpb_min[si],ax
|
||||
mov es:mpb_max[si],ax
|
||||
mov ax,sat_start[bx]
|
||||
mov es:mpb_start[si],ax
|
||||
inc sat_nall[bx]
|
||||
call mau_collapse
|
||||
sub bx,bx ! mov cx,bx
|
||||
jmps maua_out
|
||||
maua_out:
|
||||
mov ds,sysdat
|
||||
pop es ! ret
|
||||
|
||||
;=============
|
||||
maufree_entry: ; Free from MAU
|
||||
;=============
|
||||
; free SAT in given MAU
|
||||
; input: DX = address of MAF in u_wrkseg
|
||||
; output: CX = 0 if successful
|
||||
; CX = 0ffffh on failure
|
||||
; if CX = 0,
|
||||
; BX = 0 if MAU still in use
|
||||
; BX = 0ffffh if MAU is empty
|
||||
; if CX = 0ffffh
|
||||
; BX = 0ffffh
|
||||
|
||||
push es ! mov es,u_wrkseg
|
||||
mov si,dx
|
||||
mov bx,es:maf_mau[si]
|
||||
mov ds,m_start[bx]
|
||||
|
||||
; ES:SI -> MAF
|
||||
; DS: 0 -> SAT table
|
||||
|
||||
sub bx,bx ! mov cx,bx
|
||||
mov dx,es:maf_sat[si]
|
||||
|
||||
; DS:BX -> current SAT
|
||||
; CX = SAT entry number
|
||||
; DX = MAF_SAT start
|
||||
|
||||
mauf_nsat:
|
||||
add bx,satlen ! inc cx
|
||||
cmp cx,.0 ! ja mauf_err
|
||||
cmp dx,sat_start[bx] ; This SAT?
|
||||
jne mauf_nsat
|
||||
cmp dx,es:maf_start[si] ; Freeing all of it?
|
||||
je mauf_free
|
||||
cmp sat_nall[bx],1 ; Is it shared?
|
||||
je mauf_nsha
|
||||
jmps mauf_out ; Can't split it
|
||||
; since its shared.
|
||||
; But, no error
|
||||
|
||||
mauf_nsha: mov cx,es:maf_start[si] ; Not shared,
|
||||
mov ax,sat_start[bx]
|
||||
add ax,sat_length[bx]
|
||||
cmp ax,cx ! jb mauf_err ; Within range?
|
||||
|
||||
; must split this SAT
|
||||
; this can only be done if not shared
|
||||
|
||||
sub cx,dx ! call mau_split
|
||||
sub cx,cx ! mov bx,cx ! jmps mauf_c
|
||||
mauf_free: dec sat_nall[bx]
|
||||
mauf_c: call mau_collapse ! jmps mauf_out
|
||||
mauf_err:
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
mauf_out:
|
||||
pop es ! mov ds,sysdat
|
||||
ret
|
||||
|
||||
mau_split: ;split SAT into 2
|
||||
;--------- -----------------
|
||||
; new SAT element starting at split boundary
|
||||
; with nall=0, old has same nall.
|
||||
; input: BX = address of SAT element
|
||||
; CX = length to split at
|
||||
; output: BX = address of original SAT element
|
||||
|
||||
push bx ! push cx
|
||||
add bx,satlen ! call mau_insert
|
||||
cmp cx,0 ! pop cx
|
||||
pop bx ! jne maus_err ;create hole if error
|
||||
lea di,satlen[bx] ! mov dx,sat_length[bx]
|
||||
sub dx,cx ! mov sat_length[di],dx
|
||||
mov dx,cx ! add dx,sat_start[bx]
|
||||
mov sat_start[di],dx ! mov sat_nall[di],0
|
||||
maus_err:
|
||||
mov sat_length[bx],cx
|
||||
ret
|
||||
|
||||
mau_collapse: ;collapse adjacent unallocated SATs
|
||||
;------------ -----------------------------------
|
||||
; collapse adjacent unallocated SATs and holes in table
|
||||
; if possible
|
||||
; return: BX = 0 if not empty
|
||||
; = 0ffffh if empty
|
||||
; CX = 0
|
||||
|
||||
sub bx,bx ! mov cx,bx
|
||||
mauc_nsat:
|
||||
inc cx
|
||||
cmp cx,.0 ! je mauc_mtchk
|
||||
add bx,satlen ! lea di,satlen[bx]
|
||||
cmp sat_start[bx],0 ! je mauc_mtchk
|
||||
cmp sat_start[di],0 ! je mauc_mtchk
|
||||
cmp sat_nall[bx],0 ! jne mauc_notfree
|
||||
;this SAT is free
|
||||
mov ax,sat_start[bx] ! add ax,sat_length[bx]
|
||||
cmp ax,sat_start[di] ! je mauc_fnohole
|
||||
;followed by a hole
|
||||
mov ax,sat_start[di] ! sub ax,sat_start[bx]
|
||||
mov sat_length[bx],ax
|
||||
mauc_fnohole:
|
||||
;free SAT., no hole
|
||||
cmp sat_nall[di],0 ! jne mauc_nsat
|
||||
;followed by free SAT
|
||||
mov ax,sat_length[di]
|
||||
add sat_length[bx],ax
|
||||
push bx ! push cx
|
||||
mov bx,di ! call mau_release
|
||||
pop cx ! pop bx
|
||||
sub bx,satlen ! dec cx
|
||||
jmp mauc_nsat
|
||||
mauc_notfree:
|
||||
;allocated SAT
|
||||
mov ax,sat_start[bx] ! add ax,sat_length[bx]
|
||||
cmp ax,sat_start[di] ! je mauc_nsat
|
||||
;followed by a hole
|
||||
cmp sat_nall[di],0 ! je mauc_nfhole
|
||||
;next SAT is allocated
|
||||
|
||||
push bx ! push cx
|
||||
mov di,bx ! call mau_insert
|
||||
pop cx ! pop bx
|
||||
jmp mauc_nsat
|
||||
mauc_nfhole: ;Alloc SAT, followed by hole
|
||||
;next SAT is free
|
||||
mov ax,sat_start[di] ! sub ax,sat_start[bx]
|
||||
sub sat_start[di],ax ! add sat_length[di],ax
|
||||
jmp mauc_nsat
|
||||
|
||||
mauc_mtchk:
|
||||
mov bp,0ffffh
|
||||
xor cx,cx ! xor bx,bx
|
||||
mauc_mtn:
|
||||
inc cx
|
||||
cmp cx,.0 ! je mauc_out
|
||||
add bx,satlen
|
||||
cmp sat_start[bx],0 ! je mauc_out
|
||||
cmp sat_nall[bx],0 ! je mauc_mtn
|
||||
mov bp,0
|
||||
mauc_out:
|
||||
mov bx,bp ! xor cx,cx ! ret
|
||||
|
||||
mau_release:
|
||||
;-----------
|
||||
; input: BX = SAT to release
|
||||
|
||||
push es ! mov ax,ds ! mov es,ax
|
||||
mov ax,satlen
|
||||
mul byte ptr .0
|
||||
push ax ! mov cx,ax ! sub cx,bx
|
||||
mov di,bx ! add bx,satlen
|
||||
mov si,bx ! rep movs al,al
|
||||
pop bx ! mov sat_length[bx],0
|
||||
mov sat_start[bx],0
|
||||
mov sat_nall[bx],0
|
||||
pop es ! ret
|
||||
|
||||
mau_insert:
|
||||
;----------
|
||||
; input: BX = SAT to place new SAT in front
|
||||
; output: CX = 0 if successful
|
||||
|
||||
mov ax,satlen ! mul byte ptr .0
|
||||
mov si,ax ! mov cx,0ffffh
|
||||
cmp sat_start[si],0 ! jne maui_r
|
||||
mov cx,si ! sub cx,bx
|
||||
dec si ! lea di,satlen[si]
|
||||
push es ! push ds ! pop es
|
||||
std ! rep movsb ! cld
|
||||
pop es ! sub cx,cx
|
||||
mov sat_start[bx],cx
|
||||
mov sat_length[bx],cx
|
||||
mov sat_nall[bx],cl
|
||||
maui_r: ret
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
include cpyright.def
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MP/M-86 Memory Management Module
|
||||
;*
|
||||
;*****************************************************
|
||||
eject ! include system.def
|
||||
eject ! include modfunc.def
|
||||
eject ! include pd.def
|
||||
eject ! include qd.def
|
||||
eject ! include err.def
|
||||
eject ! include mem.def
|
||||
eject ! include mpb.def
|
||||
eject ! include memif.mem
|
||||
eject ! include cpmmem.mem
|
||||
eject ! include memory.mem
|
||||
eject ! include share.mem
|
||||
eject ! include mau.mem
|
||||
eject ! include ml.mem
|
||||
eject ! include util.mem
|
||||
eject ! include patch.cod
|
||||
eject ! include uda.fmt
|
||||
eject ! include lstk.fmt
|
||||
eject ! include sysdat.dat
|
||||
eject ! include data.bdo
|
||||
eject ! end
|
||||
@@ -0,0 +1,30 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Descriptor Formats
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
; format while on MFL or MAL
|
||||
|
||||
m_link equ word ptr 0
|
||||
m_start equ word ptr m_link+word
|
||||
m_length equ word ptr m_start+word
|
||||
m_plist equ word ptr m_length+word
|
||||
m_unused equ word ptr m_plist+word
|
||||
mdlen equ m_unused+word
|
||||
|
||||
; format while on PD as memory segment
|
||||
; ms_flags uses same definitions as
|
||||
; mpb_flags
|
||||
|
||||
ms_link equ word ptr m_link
|
||||
ms_start equ word ptr m_start
|
||||
ms_length equ word ptr m_length
|
||||
ms_flags equ word ptr m_plist
|
||||
ms_mau equ word ptr m_unused
|
||||
|
||||
; format of spb (share parameter block)
|
||||
|
||||
spb_opd equ word ptr 0
|
||||
spb_rpd equ word ptr spb_opd + word
|
||||
spb_start equ word ptr spb_rpd + word
|
||||
@@ -0,0 +1,117 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Management Module Interface
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
CSEG
|
||||
org 0
|
||||
|
||||
jmp init
|
||||
jmp entry
|
||||
|
||||
;3 variables set by GENSYS
|
||||
sysdat dw 0
|
||||
supervisor equ (offset $)
|
||||
rw 2
|
||||
|
||||
org 0ch
|
||||
dev_ver db 6 ;development system data version
|
||||
;set in sysdat.fmt
|
||||
|
||||
db 'COPYRIGHT (C) 1983,'
|
||||
db ' DIGITAL RESEARCH '
|
||||
db 'XXXX-0000-'
|
||||
serial db '654321'
|
||||
|
||||
;====
|
||||
init:
|
||||
;====
|
||||
retf
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MEM function table
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
functab dw maxmem_entry ; 53 - Get Max Memory
|
||||
dw absmax_entry ; 54 - Get Abs Max Mem
|
||||
dw cpmalloc_entry ; 55 - Alloc Mem
|
||||
dw cpmabsa_entry ; 56 - Alloc Abs Mem
|
||||
dw cpmfree_entry ; 57 - Free Mem
|
||||
dw freeall_entry ; 58 - Free All Mem
|
||||
dw malloc_entry ; 129 - Rel Mem Rqst
|
||||
dw mfree_entry ; 130 - Memory Free
|
||||
dw share_entry ; share memory
|
||||
dw maualloc_entry ; Alloc from MAU
|
||||
dw maufree_entry ; Free from MAU
|
||||
dw mlalloc_entry ; Alloc from Mem List
|
||||
dw mlfree_entry ; Free from Mem List
|
||||
|
||||
;===== =================
|
||||
entry: ; MEM entry point
|
||||
;===== =================
|
||||
; entry: CX = memory function number
|
||||
; DX,BX parameters
|
||||
; exit: AX=BX=return code
|
||||
; CX=error code if BX=0ffffh
|
||||
|
||||
; The memory manager is a mutually exclusive code
|
||||
; section, only one process may be in the memory code
|
||||
; at one time. However, a process already in the memory manager
|
||||
; can call the memory manager ENTRY: point again.
|
||||
; Once a process gets into the memory code it cannot
|
||||
; be terminated.
|
||||
|
||||
call m_sync ;obtain memory system
|
||||
mov ch,0 ! shl cx,1 ;and make sure TEMPKEEP is on
|
||||
mov si,cx
|
||||
call cs:functab[si]
|
||||
call m_unsync
|
||||
mov ax,bx ;last time out, BX,CX preserved
|
||||
retf
|
||||
|
||||
m_sync:
|
||||
;------
|
||||
|
||||
push bx ! push cx ! push dx ;save entry parameters
|
||||
mov bx,offset mem_spb
|
||||
mov cx,f_sync ;obtain memory system
|
||||
call osif ;reetrancy stops here ...
|
||||
inc mem_cnt ;keep track how many
|
||||
;times through memory entry
|
||||
cmp mem_cnt,1 ! jne ms1
|
||||
mov cx,f_no_abort ;cannot abort while in
|
||||
call osif ;MEM, call NO_ABORT_ENTRY
|
||||
ms1: ;on 1st time through only
|
||||
pop dx ! pop cx ! pop bx
|
||||
ret
|
||||
|
||||
; Note: the MEM_CNT variable is set to 1 by TERMINATE in the RTM
|
||||
; and back to 0 by the TERM_ACT in the dispatcher.
|
||||
|
||||
m_unsync:
|
||||
;--------
|
||||
dec mem_cnt ;only release when last time
|
||||
jnz mu_ret ;out of memory system
|
||||
push bx ! push cx
|
||||
mov bx,offset mem_spb
|
||||
mov cx,f_unsync
|
||||
call osif ;reentrancy starts here ...
|
||||
mov cx,f_ok_abort
|
||||
call osif ;exit no_abort region
|
||||
pop cx ! pop bx
|
||||
mu_ret:
|
||||
ret
|
||||
|
||||
;==== ================
|
||||
osif: ; O.S. interface
|
||||
;==== ================
|
||||
callf cs:dword ptr .supervisor ! ret
|
||||
|
||||
;====== ================
|
||||
xiosif: ; XIOS interface
|
||||
;====== ================
|
||||
callf dword ptr .xiosmod ! ret
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MEM Entry Points
|
||||
;*
|
||||
;* Each process descriptor points to a linked
|
||||
;* list of MDs that describe memory segments that
|
||||
;* it owns. The MDs note the starting paragraph
|
||||
;* and a MAU that the Memory Segment is in.
|
||||
;*
|
||||
;* Format of MDs on p_mem lists:
|
||||
;*
|
||||
;* +----+----+----+----+----+----+----+----+----+----+
|
||||
;* | link | start | length | flags | mau |
|
||||
;* +----+----+----+----+----+----+----+----+----+----+
|
||||
;*
|
||||
;* link link field for p_mem list
|
||||
;* start starting paragraph of memory segment
|
||||
;* length length in paragraphs of memory segment
|
||||
;* flags load,code,and share as in MPB
|
||||
;* mau offset of MAU in SYSDAT that segment is
|
||||
;* allocated from
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;============
|
||||
malloc_entry:
|
||||
;============
|
||||
; Allocate Memory - memory is allocated from MAUs.
|
||||
; First we try to allocate memory from MAUs that has
|
||||
; memory segments already allocated by this process.
|
||||
; If that fails, we try to create a new MAU from the
|
||||
; Memory Free List (MFL). If both fails, an error is
|
||||
; is returned to the user.
|
||||
;
|
||||
; input: DX = MPB in u_wrkseg
|
||||
; output: BX = 0 if successful (unused memory)
|
||||
; = 1 if successful (shared code)
|
||||
; = 0ffffh if failure
|
||||
; CX = error code
|
||||
;
|
||||
; Format of MPB:
|
||||
;
|
||||
; +----+----+----+----+----+----+----+----+----+----+
|
||||
; | start | min | max | pdadr | flags |
|
||||
; +----+----+----+----+----+----+----+----+----+----+
|
||||
;
|
||||
; start - if non-zero, an absolute request
|
||||
; min - minimum length that will satisfy the request
|
||||
; max - maximum length wanted
|
||||
; We will try to allocate the maximum
|
||||
; but will be satisfied with as little as the
|
||||
; minimum.
|
||||
; pdadr - Process Descriptor to allocate memory to.
|
||||
; Note - PD can not be a current process unless
|
||||
; it is the calling process.
|
||||
; The Calling process must explicitly release
|
||||
; the memory if the PD never becomes a process.
|
||||
; Otherwise, memory is released upon termination.
|
||||
; If pdadr is 0, then calling process allocates
|
||||
; the memory.
|
||||
; flags - 00001h Load This segment initialized from
|
||||
; a disk file
|
||||
; 00002h Shared This is a sharable segment
|
||||
; 00004h Code This is a Code segment
|
||||
|
||||
; Get a MD for use in the p_mem list
|
||||
|
||||
; DX -> MPB (u_wrkseg)
|
||||
push dx ! call getmd ! pop dx ; BX -> MD
|
||||
jcxz mall_gmd
|
||||
mov bx,0ffffh ! ret
|
||||
mall_gmd:
|
||||
; fill PDADR field in case its zero
|
||||
|
||||
push es ! mov es,u_wrkseg ;save UDA
|
||||
mov di,dx ! mov ax,es:mpb_pdadr[di]
|
||||
cmp ax,0 ! jne mall_gpd
|
||||
mov ax,rlr
|
||||
mov es:mpb_pdadr[di],ax
|
||||
mall_gpd:
|
||||
pop es ;ES=UDA
|
||||
cmp ax,rlr ! je mall_pdv1
|
||||
|
||||
push ax ! push bx
|
||||
push dx ! push di
|
||||
mov bx,offset thrd_spb ;ok to call sync on
|
||||
mov cx,f_sync ;thread after sync-ing
|
||||
call osif ;on memory
|
||||
pop di ! pop dx
|
||||
pop bx ! pop ax
|
||||
mov si,(offset thrdrt)-p_thread
|
||||
|
||||
mall_pdnxt: mov si,p_thread[si]
|
||||
|
||||
cmp si,0 ! je mall_pdver
|
||||
cmp si,ax ! jne mall_pdnxt
|
||||
cmp si,rlr ! je mall_pdver
|
||||
mov cx,e_active_pd
|
||||
push bx ; save MD addr
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
pop bx ; restore MD addr
|
||||
jmp mall_err
|
||||
mall_pdver:
|
||||
push ax ! push bx
|
||||
push dx ! push di
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
pop di ! pop dx
|
||||
pop bx ! pop ax
|
||||
|
||||
; verify MIN <= MAX
|
||||
|
||||
mall_pdv1:
|
||||
push es ! mov es,u_wrkseg
|
||||
mov cx,es:mpb_min[di]
|
||||
cmp cx,es:mpb_max[di]
|
||||
jbe mpb_ok
|
||||
mov es:mpb_max[di],cx
|
||||
mpb_ok:
|
||||
|
||||
; Make sure total allocation <= MMP
|
||||
|
||||
mov si,ax ! add si,(p_mem - ms_link)
|
||||
sub cx,cx ! push si
|
||||
max_chk_nxt:
|
||||
mov si,ms_link[si]
|
||||
cmp si,0 ! je max_chk_done
|
||||
add cx,ms_length[si]
|
||||
jmps max_chk_nxt
|
||||
max_chk_done:
|
||||
pop si ! mov ax,mmp
|
||||
sub ax,cx
|
||||
cmp ax,0 ! jne not_zero
|
||||
no_min: pop es
|
||||
mall_nomem: mov cx,e_no_memory
|
||||
mall_err: call freemd ; Free the Memory Descriptor
|
||||
mov bx,0ffffh ! ret ; CX=Error Code set previously
|
||||
not_zero:
|
||||
cmp ax,es:mpb_min[di] ! jb no_min
|
||||
cmp ax,es:mpb_max[di] ! jae max_ok
|
||||
mov es:mpb_max[di],ax
|
||||
max_ok:
|
||||
|
||||
; initialize local variables
|
||||
|
||||
push di ! mov di,offset beststart
|
||||
mov cx,11 ! sub ax,ax
|
||||
mov es,sysdat
|
||||
rep stosw ! pop di
|
||||
|
||||
sub cx,cx
|
||||
pop es
|
||||
; try to allocate memory
|
||||
|
||||
mall_next:
|
||||
mov si,ms_link[si]
|
||||
cmp si,0 ! je mall_ml
|
||||
cmp cx,ms_mau[si] ! je mall_next
|
||||
; here's a MAU we haven't tried...
|
||||
; CX=last MAU tried
|
||||
; DX=MPB adr in u_wrkseg
|
||||
; BX=New MD
|
||||
; SI=current MD
|
||||
push cx ! push dx ! push bx ! push si
|
||||
mov bx,ms_mau[si]
|
||||
call mall_try_mau
|
||||
pop si ! pop bx ! pop dx
|
||||
; Plus DI=MAU address
|
||||
cmp cx,0 ! pop cx ! jne mall_next
|
||||
; exact allocation
|
||||
; succesful allocation
|
||||
jmp mall_linkit
|
||||
|
||||
mall_ml: ; We must create a new MAU from MFL
|
||||
push bx ! push dx
|
||||
mov ds,u_wrkseg
|
||||
mov bx,offset mfl ! mov cx,f_mlalloc
|
||||
call osif
|
||||
mov ds,sysdat
|
||||
;BX=MAU, (New MD,MPB on stack)
|
||||
jcxz mall_ml0
|
||||
pop dx ! pop bx
|
||||
jmp mall_linkit
|
||||
mall_ml0: ; We have a new MAU
|
||||
;place MAU on MAL
|
||||
mov si,mal
|
||||
mov m_link[bx],si
|
||||
mov mal,bx
|
||||
;allocate memory
|
||||
pop dx ! push dx
|
||||
sub si,si
|
||||
call mall_try_mau
|
||||
pop dx ! pop bx
|
||||
;DI=MAU, BX=New MD, DX=MPB in u_wrkseg
|
||||
|
||||
mall_linkit:
|
||||
;BX -> MD
|
||||
;DX -> MPB in u_wrkseg
|
||||
|
||||
cmp beststart,0 ! jne yesmem
|
||||
|
||||
if ccpm
|
||||
jmp mall_nomem
|
||||
endif
|
||||
|
||||
if mpm
|
||||
|
||||
; We couldn't find any memory ...
|
||||
; lets take something off the SCL
|
||||
|
||||
pushf ! cli
|
||||
mov di,scl
|
||||
cmp di,0 ! jne take_one_off
|
||||
|
||||
; No where else to try, giveup.
|
||||
popf ! jmp mall_nomem
|
||||
|
||||
; take first SHARE PD off SCL
|
||||
take_one_off:
|
||||
mov ax,p_thread[di]
|
||||
mov scl,ax
|
||||
popf
|
||||
|
||||
; Free its memory
|
||||
; We can assume only one memory segment
|
||||
|
||||
push bx ! push dx
|
||||
mov bx,p_mem[di]
|
||||
push di ! push ds
|
||||
push di ! push ms_start[bx]
|
||||
push ss ! pop ds
|
||||
mov dx,sp ! mov cx,f_memfree
|
||||
call osif
|
||||
pop ax ! pop ax
|
||||
pop ds ! pop di
|
||||
|
||||
; There should be no error.
|
||||
; Put SHARE PD on PUL
|
||||
pushf ! cli
|
||||
mov ax,pul
|
||||
mov p_link[di],ax
|
||||
mov pul,di
|
||||
popf
|
||||
|
||||
|
||||
; Let's assume we just released a partition
|
||||
; and try the ML Alloc again.
|
||||
|
||||
pop dx ! pop bx
|
||||
jmp mall_ml
|
||||
endif
|
||||
|
||||
; We have memory ...
|
||||
yesmem:
|
||||
push es ! mov es,u_wrkseg
|
||||
mov di,dx
|
||||
mov ax,beststart
|
||||
mov es:mpb_start[di],ax
|
||||
mov ms_start[bx],ax
|
||||
mov ax,bestlen
|
||||
mov es:mpb_min[di],ax
|
||||
mov es:mpb_max[di],ax
|
||||
mov ms_length[bx],ax
|
||||
mov ax,es:mpb_flags[di]
|
||||
mov ms_flags[bx],ax
|
||||
mov si,bestsi
|
||||
cmp si,0 ! jne mall_l0
|
||||
mov si,es:mpb_pdadr[di]
|
||||
add si,(p_mem-ms_link)
|
||||
mall_l0:mov ax,ms_link[si] ! mov ms_link[bx],ax
|
||||
mov ms_link[si],bx
|
||||
mov di,bestmau
|
||||
mov ms_mau[bx],di
|
||||
pop es ! sub cx,cx ! mov bx,cx ! ret
|
||||
|
||||
mall_try_mau:
|
||||
;------------
|
||||
; input: BX -> MAU
|
||||
; DX -> MPB in u_wrkseg
|
||||
; SI = MS Root that MAU came from
|
||||
; output: CX = 0, found exact allocation
|
||||
; else, exact not found
|
||||
|
||||
; save root,mau
|
||||
mov currsi,si
|
||||
mov currmau,bx
|
||||
|
||||
|
||||
; copy user's MPB into local MPB
|
||||
push dx ! push ds ! push es
|
||||
mov ds,u_wrkseg
|
||||
mov es,sysdat
|
||||
mov si,dx ! mov di,offset currmpb
|
||||
mov cx,5 ! rep movsw
|
||||
pop es ! pop ds
|
||||
|
||||
mov dx,offset currmpb
|
||||
mov cx,f_maualloc ! call osif
|
||||
|
||||
pop di
|
||||
jcxz chkbest
|
||||
ret
|
||||
chkbest:
|
||||
push es ! mov es,u_wrkseg
|
||||
mov si,offset currmpb
|
||||
mov ax,mpb_max[si]
|
||||
sub cx,cx
|
||||
cmp ax,es:mpb_max[di]
|
||||
pop es
|
||||
jz replacebest
|
||||
mov cx,3 ! mov bx,currmau
|
||||
mov di,si
|
||||
cmp ax,bestlen ! jbe freeworst
|
||||
replacebest:
|
||||
mov di,offset beststart
|
||||
mov bx,bestmau
|
||||
call freeworst
|
||||
mov si,offset currmpb
|
||||
mov ax,mpb_start[si] ! mov beststart,ax
|
||||
mov ax,mpb_max[si] ! mov bestlen,ax
|
||||
mov ax,currmau ! mov bestmau,ax
|
||||
mov ax,currsi ! mov bestsi,ax
|
||||
savret: ret
|
||||
freeworst: ; DI->Start, CX=Return Code, BX=MAU
|
||||
cmp word ptr [di],0 ! je savret
|
||||
|
||||
; free worst memory
|
||||
push cx ! push ds
|
||||
push word ptr [di] ! push word ptr [di]
|
||||
push bx ! push ss ! pop ds
|
||||
mov dx,sp ! mov cx,f_maufree
|
||||
call osif
|
||||
|
||||
|
||||
; if MAU empty, free MAU
|
||||
cmp cx,0 ! jne mflret
|
||||
cmp bx,0ffffh ! jne mflret
|
||||
pop bx ! pop ax ! pop ax ! pop ds
|
||||
|
||||
|
||||
; take off MAL
|
||||
; BX = MAU address
|
||||
mov ax,bx ! mov bx,(offset mal)-m_link
|
||||
mfl1: mov si,bx ! mov bx,m_link[si]
|
||||
cmp bx,ax ! jne mfl1
|
||||
push ax
|
||||
mov ax,m_link[bx] ! mov m_link[si],ax
|
||||
pop bx
|
||||
; Replace into MFL
|
||||
mov cx,f_mlfree
|
||||
mov dx,bx ! mov bx,offset mfl
|
||||
call osif ! pop cx ! ret
|
||||
|
||||
mflret: pop bx ! pop ax ! pop ax
|
||||
pop ds ! pop cx ! ret
|
||||
|
||||
;===========
|
||||
mfree_entry: ; 130 - Memory Free
|
||||
;===========
|
||||
; Free the memory segment with the given segment addr.
|
||||
; input: DX = MFPB in u_wrkseg
|
||||
; output: BX = 0 if successful
|
||||
; = 0ffffh on failure
|
||||
; CX = error code
|
||||
;
|
||||
; Memory Free Parameter Block (MFPB)
|
||||
;
|
||||
; +----+----+----+----+
|
||||
; | start | pdadr |
|
||||
; +----+----+----+----+
|
||||
;
|
||||
; start - starting paragraph of area to be freed.
|
||||
; pdadr - PD to free memory from. If 0, then calling
|
||||
; process. If non-zero, the PD must not be
|
||||
; a current process.
|
||||
|
||||
push es ! mov es,u_wrkseg
|
||||
mov si,dx
|
||||
mov bx,es:mfpb_pd[si]
|
||||
mov dx,es:mfpb_start[si]
|
||||
pop es
|
||||
; BX = pdadr
|
||||
; DX = start paragraph
|
||||
cmp bx,0 ! jne mfree_chkpd
|
||||
mov bx,rlr
|
||||
jmps mfree_g1
|
||||
mfree_chkpd:
|
||||
|
||||
push bx ! push dx
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_sync
|
||||
call osif
|
||||
pop dx ! pop bx
|
||||
|
||||
mov si,(offset thrdrt)-p_thread
|
||||
mfree_nxtpd:
|
||||
mov si,p_thread[si]
|
||||
cmp si,0 ! je mfree_gotpd
|
||||
cmp si,bx ! jne mfree_nxtpd
|
||||
cmp si,rlr ! je mfree_gotpd
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
mov bx,0ffffh
|
||||
mov cx,e_active_pd
|
||||
ret
|
||||
mfree_gotpd:
|
||||
push bx ! push dx
|
||||
mov bx,offset thrd_spb
|
||||
mov cx,f_unsync
|
||||
call osif
|
||||
pop dx ! pop bx
|
||||
|
||||
mfree_g1:
|
||||
lea si,p_mem[bx]
|
||||
mfree_next:
|
||||
mov bx,si ! mov si,ms_link[bx]
|
||||
cmp si,0 ! je mfree_err
|
||||
cmp ms_start[si],dx ! je mfree_it
|
||||
ja mfree_next
|
||||
mov ax,ms_start[si]
|
||||
add ax,ms_length[si]
|
||||
cmp ax,dx ! jbe mfree_next
|
||||
push dx ! push si
|
||||
call mfree_it
|
||||
pop si ! pop dx
|
||||
cmp cx,0 ! jne mfree_next
|
||||
mfree_exit:
|
||||
sub bx,bx ! mov cx,bx ! ret
|
||||
mfree_err:
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
ret
|
||||
|
||||
mfree_it:
|
||||
;--------
|
||||
; input: BX = root
|
||||
; SI = MD ([bx])
|
||||
; DX = segment to free
|
||||
; output: BX = 0,0ffffh (success,failure)
|
||||
; CX = Error Code
|
||||
|
||||
push bx ! push si ! push dx
|
||||
;push MAF structure
|
||||
push dx ! push ms_start[si]
|
||||
push ms_mau[si]
|
||||
mov dx,sp ! push ss ! pop ds
|
||||
mov cx,f_maufree ! call osif
|
||||
mov bp,bx ;if bp=0,MAU not empty
|
||||
mov ds,sysdat
|
||||
;pop MAF structure
|
||||
pop ax ! pop ax ! pop ax
|
||||
pop dx ! pop si ! pop bx
|
||||
;DX=segment to free
|
||||
;BX=root
|
||||
;SI=MD ( [BX] )
|
||||
cmp cx,0
|
||||
jne mfree_err
|
||||
cmp dx,ms_start[si] ! je mfree_off
|
||||
;decrease length
|
||||
sub dx,ms_start[si]
|
||||
mov ms_length[si],dx
|
||||
mfree_r:
|
||||
jmps mfree_exit
|
||||
;take off p_mem list
|
||||
mfree_off: mov ax,ms_link[si] ! mov ms_link[bx],ax
|
||||
;free MD
|
||||
push ms_mau[si] ! push bp
|
||||
mov bx,si ! call freemd
|
||||
pop bp ! pop dx
|
||||
;free MAU if empty
|
||||
cmp bp,0 ! je mfree_exit
|
||||
;find it on MAL
|
||||
mov di,(offset mal)-m_link
|
||||
mfree_nmal: mov si,di ! mov di,m_link[si]
|
||||
cmp di,dx ! jne mfree_nmal
|
||||
;release from MAL
|
||||
mov ax,m_link[di] ! mov m_link[si],ax
|
||||
mov m_link[di],0
|
||||
;release to MFL
|
||||
mov bx,offset mfl ! mov cx,f_mlfree
|
||||
jmp osif
|
||||
@@ -0,0 +1,212 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory List Functions
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;=============
|
||||
mlalloc_entry: ; Alloc from Mem List
|
||||
;=============
|
||||
; Create a MAU from a Memory List. Memory List is a
|
||||
; linked list of MDs in memory order (low first). It
|
||||
; is assumed that units in the Memory List are paragraphs
|
||||
; input: DX = address of MPB in u_wrkseg
|
||||
; BX = ML root in SYSDAT
|
||||
; output: BX = address of MAU
|
||||
; = 0ffffh if error
|
||||
|
||||
; CX = Error Code
|
||||
|
||||
mov si,dx
|
||||
sub ax,ax ! mov cx,ax ! mov dx,0ffffh
|
||||
; AX = MD w/best score
|
||||
; DX = best score
|
||||
; CX = # partitions used
|
||||
; SI -> MPB in u_wrkseg
|
||||
push ax ! push cx
|
||||
mla_nmd:cmp m_link[bx],0 ! je mla_found
|
||||
push bx ! push dx ! push si
|
||||
call mla_value
|
||||
pop si ! pop dx ! pop bx
|
||||
cmp cx,dx ! jae mla_next
|
||||
mov dx,cx ! pop cx ! mov cx,ax
|
||||
pop ax ! mov ax,bx
|
||||
push ax ! push cx
|
||||
cmp dx,0 ! je mla_found
|
||||
mla_next: mov bx,m_link[bx]
|
||||
jmps mla_nmd
|
||||
mla_found:
|
||||
pop cx ! pop ax
|
||||
cmp ax,0 ! je mla_err
|
||||
mov bx,ax ! mov ax,cx
|
||||
jmp mla_makemau
|
||||
mla_err:
|
||||
mov bx,0ffffh ! mov cx,e_no_memory
|
||||
mla_out:ret
|
||||
|
||||
mla_value:
|
||||
;---------
|
||||
; input: BX = ML element Root
|
||||
; SI = MPB in u_wrkseg
|
||||
; output: CX = value (0=perfect,0ffffh=no fit)
|
||||
; AX = # of elements
|
||||
|
||||
push es ! mov es,u_wrkseg
|
||||
sub ax,ax ! mov dx,0
|
||||
; AX = # of partitions
|
||||
; DX = total length so far
|
||||
mov di,m_link[bx]
|
||||
cmp di,0 ! je mlav_err
|
||||
; we have a list
|
||||
cmp es:mpb_start[si],0 ! je mlav_next
|
||||
;an absolute request
|
||||
mov cx,m_start[di] ! add cx,(2*satlen)
|
||||
cmp es:mpb_start[si],cx ! jb mlav_err
|
||||
;it starts after our start
|
||||
add cx,m_length[di] ! sub cx,(2*satlen)
|
||||
cmp es:mpb_start[si],cx ! jae mlav_err
|
||||
|
||||
;this list satisfies ABS requirement
|
||||
mlav_next: mov cx,es:mpb_max[si]
|
||||
cmp cx,dx ! jb mlav_chk
|
||||
mlav_add: cmp ax,0 ! je mlav_ad1
|
||||
push ax
|
||||
mov ax,m_start[bx]
|
||||
add ax,m_length[bx]
|
||||
cmp ax,m_start[di] ! pop ax ! je mlav_ad1
|
||||
jmps mlav_chkmin
|
||||
mlav_ad1: inc ax ! add dx,m_length[di]
|
||||
mov bx,di ! mov di,m_link[bx]
|
||||
cmp di,0 ! jne mlav_next
|
||||
mlav_chkmin: mov cx,es:mpb_min[si]
|
||||
add cx,(2*satlen)
|
||||
cmp cx,dx ! jbe mlav_calc
|
||||
mlav_err: mov cx,0ffffh ! sub ax,ax
|
||||
|
||||
pop es ! ret
|
||||
mlav_chk: add cx,(2*satlen)
|
||||
cmp cx,dx ! ja mlav_add
|
||||
|
||||
mlav_calc: ; HERE IS WHERE WE GIVE THIS SET A VALUE.
|
||||
; IT CAN SATIFY THE REQUEST.
|
||||
|
||||
; ALGORITHM:
|
||||
; #partitions = #partitions + 1 if next
|
||||
; to contiquous memory
|
||||
|
||||
; value = (abs(max-length) SHR 4) +
|
||||
; ((#partitions-1) SHL 2)
|
||||
; idea is that 1K = 1 paritition to avoid
|
||||
; gobbling all of our small partitions.
|
||||
; we deal with 256 byte memory units so we
|
||||
; won't overflow a word.
|
||||
|
||||
; AX = # partitions
|
||||
|
||||
; DX = memory size
|
||||
|
||||
push ax ! dec ax
|
||||
mov cl,2
|
||||
shl ax,cl
|
||||
mov cx,es:mpb_max[si]
|
||||
add cx,(2*satlen)
|
||||
|
||||
; If MAX memory is FFFF, SAT adjustment
|
||||
; wraps around so force FFFF.
|
||||
|
||||
cmp cx,(2*satlen) ! jae mlav_added
|
||||
mov cx,0ffffH
|
||||
mlav_added:
|
||||
|
||||
cmp cx,dx ! jbe mlav_ab
|
||||
xchg dx,cx
|
||||
mlav_ab: sub dx,cx ! mov cl,4 ! shr dx,cl
|
||||
add dx,ax ! mov cx,dx
|
||||
pop ax ! pop es ! ret
|
||||
|
||||
mla_makemau:
|
||||
;-----------
|
||||
; input: BX = address of ML element Root
|
||||
; AX = number of elements
|
||||
; output: BX = MAU address
|
||||
|
||||
cmp ax,1 ! jg mlam_getmd
|
||||
mov si,m_link[bx] ! mov cx,m_link[si]
|
||||
mov m_link[bx],cx ! mov bx,si
|
||||
sub cx,cx ! mov m_plist[bx],cx
|
||||
mov m_link[bx],cx
|
||||
jmp mla_initmau
|
||||
mlam_getmd:
|
||||
push ax ! push bx
|
||||
call getmd
|
||||
mov di,bx ! pop bx ! pop ax
|
||||
jcxz mlam_gotmd
|
||||
sub bx,bx ! ret
|
||||
mlam_gotmd:
|
||||
mov m_link[di],0 ! mov m_length[di],0
|
||||
mov si,m_link[bx] ! mov m_plist[di],si
|
||||
mov cx,m_start[si] ! mov m_start[di],cx
|
||||
mlam_next:
|
||||
mov cx,m_length[si] ! add m_length[di],cx
|
||||
dec ax ! cmp ax,0 ! je mlam_nomore
|
||||
mov si,m_link[si] ! jmps mlam_next
|
||||
mlam_nomore:
|
||||
push bx
|
||||
mov bx,m_link[si]
|
||||
mov m_link[si],0
|
||||
pop si ! mov m_link[si],bx
|
||||
mov bx,di ! sub cx,cx ! ;jmp mla_initmau
|
||||
|
||||
mla_initmau:
|
||||
;----------
|
||||
; input: BX = address of MAU
|
||||
; output: BX = address of MAU
|
||||
; CX = 0
|
||||
|
||||
mov dx,m_start[bx] ! mov cx,m_length[bx]
|
||||
push cx ! push es ! mov es,dx ! sub ax,ax
|
||||
mov di,ax ! mov cx,((32*satlen)/2)
|
||||
rep stos ax ! pop es
|
||||
pop cx ! mov ds,dx
|
||||
mov byte ptr .0,31
|
||||
sub cx,(2*satlen) ! add dx,(2*satlen)
|
||||
mov si,satlen ! mov sat_start[si],dx
|
||||
mov sat_length[si],cx ! mov sat_nall[si],0
|
||||
mov ds,sysdat
|
||||
sub cx,cx ! ret
|
||||
|
||||
;============
|
||||
mlfree_entry: ; Free from Mem List
|
||||
;============
|
||||
; input: DX = MAU address
|
||||
; BX = ML Root
|
||||
|
||||
mov si,dx
|
||||
cmp m_plist[si],0 ! je mlf_freeone
|
||||
mov di,si
|
||||
mov si,m_plist[si]
|
||||
mlf_nmd: cmp si,0 ! je mlf_endfree
|
||||
push m_link[si] ! push bx ! push di
|
||||
call ml_insert
|
||||
pop di ! pop bx ! pop si ! jmps mlf_nmd
|
||||
mlf_endfree:
|
||||
mov bx,di ! call freemd
|
||||
jmps mlf_exit
|
||||
mlf_freeone:
|
||||
call ml_insert
|
||||
mlf_exit:
|
||||
sub bx,bx ! mov cx,bx ! ret
|
||||
|
||||
ml_insert:
|
||||
;---------
|
||||
; input: SI = address of MD to insert
|
||||
; BX = ML Root
|
||||
|
||||
mov di,m_link[bx]
|
||||
cmp di,0 ! je mli_ins
|
||||
mov ax,m_start[di]
|
||||
cmp ax,m_start[si] ! ja mli_ins
|
||||
mov bx,di ! jmps ml_insert
|
||||
mli_ins:mov ax,m_link[bx] ! mov m_link[bx],si
|
||||
mov m_link[si],ax
|
||||
ret
|
||||
@@ -0,0 +1,159 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* CCP/M-86, MP/M-86 Inter-Module Function Definitions
|
||||
;*
|
||||
;* Same calling conventions as User programs
|
||||
;* except CX = function instead of CL
|
||||
;* BX = 2nd parameter on entry
|
||||
;* (CH=module, CL=function # in module)
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
; Module definitions
|
||||
user equ 0
|
||||
sup equ 1
|
||||
rtm equ 2
|
||||
mem equ 3
|
||||
cio equ 4
|
||||
bdos equ 5
|
||||
xios equ 6
|
||||
net equ 7
|
||||
|
||||
; Bits that represent present modules
|
||||
; in module_map
|
||||
supmod_bit equ 001h
|
||||
rtmmod_bit equ 002h
|
||||
memmod_bit equ 004h
|
||||
bdosmod_bit equ 008h
|
||||
ciomod_bit equ 010h
|
||||
xiosmod_bit equ 020h
|
||||
netmod_bit equ 040h
|
||||
|
||||
; Supervisor Functions
|
||||
;f_sysreset equ (user * 0100h) + 0
|
||||
;f_conin equ (user * 0100h) + 1
|
||||
f_conout equ (user * 0100h) + 2
|
||||
;f_rconin equ (user * 0100h) + 3 ;supported internally
|
||||
;f_rconout equ (user * 0100h) + 4 ;under CCP/M
|
||||
f_lstout equ (user * 0100h) + 5
|
||||
;f_rawconio equ (user * 0100h) + 6
|
||||
;f_getiobyte equ (user * 0100h) + 7
|
||||
;f_setiobyte equ (user * 0100h) + 8
|
||||
f_conwrite equ (user * 0100h) + 9
|
||||
f_conread equ (user * 0100h) + 10
|
||||
;f_constat equ (user * 0100h) + 11
|
||||
;f_bdosversion equ (user * 0100h) + 12
|
||||
;f_diskreset equ (user * 0100h) + 13
|
||||
;f_diskselect equ (user * 0100h) + 14
|
||||
f_fopen equ (user * 0100h) + 15
|
||||
f_fclose equ (user * 0100h) + 16
|
||||
;f_searchfirst equ (user * 0100h) + 17
|
||||
;f_searchnext equ (user * 0100h) + 18
|
||||
;f_fdelete equ (user * 0100h) + 19
|
||||
f_freadseq equ (user * 0100h) + 20
|
||||
;f_fwriteseq equ (user * 0100h) + 21
|
||||
;f_fmake equ (user * 0100h) + 22
|
||||
;f_frename equ (user * 0100h) + 23
|
||||
;f_loginvector equ (user * 0100h) + 24
|
||||
f_getdefdisk equ (user * 0100h) + 25
|
||||
f_setdma equ (user * 0100h) + 26
|
||||
;f_getallocvec equ (user * 0100h) + 27
|
||||
;f_writeprotect equ (user * 0100h) + 28
|
||||
;f_getrovector equ (user * 0100h) + 29
|
||||
;f_setfileattr equ (user * 0100h) + 30
|
||||
;f_getdpb equ (user * 0100h) + 31
|
||||
f_usercode equ (user * 0100h) + 32
|
||||
f_freadrdm equ (user * 0100h) + 33
|
||||
;f_fwriterdm equ (user * 0100h) + 34
|
||||
;f_filesize equ (user * 0100h) + 35
|
||||
f_setrndrec equ (user * 0100h) + 36
|
||||
;f_resetdrive equ (user * 0100h) + 37
|
||||
;f_accessdrive equ (user * 0100h) + 38
|
||||
;f_freedrive equ (user * 0100h) + 39
|
||||
;f_writerndzero equ (user * 0100h) + 40
|
||||
;f_chain equ (user * 0100h) + 47
|
||||
f_callbios equ (user * 0100h) + 50
|
||||
f_setdmab equ (user * 0100h) + 51
|
||||
;f_getdma equ (user * 0100h) + 52
|
||||
;f_getmaxmem equ (user * 0100h) + 53
|
||||
;f_getabsmaxmem equ (user * 0100h) + 54
|
||||
;f_allocmem equ (user * 0100h) + 55
|
||||
;f_allocabsmem equ (user * 0100h) + 56
|
||||
f_freemem equ (user * 0100h) + 57
|
||||
f_freeall equ (user * 0100h) + 58
|
||||
;f_userload equ (user * 0100h) + 59
|
||||
f_delim equ (user * 0100h) + 110
|
||||
f_malloc equ (user * 0100h) + 128
|
||||
f_memfree equ (user * 0100h) + 130
|
||||
;f_polldev equ (user * 0100h) + 131
|
||||
f_flagwait equ (user * 0100h) + 132
|
||||
f_flagset equ (user * 0100h) + 133
|
||||
f_qmake equ (user * 0100h) + 134
|
||||
f_qopen equ (user * 0100h) + 135
|
||||
;f_qdelete equ (user * 0100h) + 136
|
||||
f_qread equ (user * 0100h) + 137
|
||||
f_cqread equ (user * 0100h) + 138
|
||||
f_qwrite equ (user * 0100h) + 139
|
||||
f_cqwrite equ (user * 0100h) + 140
|
||||
;f_delay equ (user * 0100h) + 141
|
||||
f_dispatch equ (user * 0100h) + 142
|
||||
f_terminate equ (user * 0100h) + 143
|
||||
f_createproc equ (user * 0100h) + 144
|
||||
f_setprior equ (user * 0100h) + 145
|
||||
f_conattach equ (user * 0100h) + 146
|
||||
f_condetach equ (user * 0100h) + 147
|
||||
;f_setdefcon equ (user * 0100h) + 148
|
||||
f_conassign equ (user * 0100h) + 149
|
||||
;f_clicmd equ (user * 0100h) + 150
|
||||
;f_callrsp equ (user * 0100h) + 151
|
||||
f_parsefilename equ (user * 0100h) + 152
|
||||
;f_getdefcon equ (user * 0100h) + 153
|
||||
;f_sdataddr equ (user * 0100h) + 154
|
||||
;f_timeofday equ (user * 0100h) + 155
|
||||
;f_pdaddress equ (user * 0100h) + 156
|
||||
;f_abortprocess equ (user * 0100h) + 157
|
||||
f_lstattach equ (user * 0100h) + 158
|
||||
f_lstdetach equ (user * 0100h) + 159
|
||||
;f_setdeflst equ (user * 0100h) + 160
|
||||
;f_clstattch equ (user * 0100h) + 161
|
||||
f_cconattch equ (user * 0100h) + 162
|
||||
;f_osvernum equ (user * 0100h) + 163
|
||||
;f_getdeflst equ (user * 0100h) + 164
|
||||
|
||||
|
||||
; Internal SUP functions
|
||||
f_load equ (sup * 0100h) + 10
|
||||
f_cload equ (sup * 0100h) + 14
|
||||
|
||||
|
||||
; Internal RTM functions
|
||||
f_inflagset equ (rtm * 0100h) + 3
|
||||
f_sleep equ (rtm * 0100h) + 18
|
||||
f_wakeup equ (rtm * 0100h) + 19
|
||||
f_findpdname equ (rtm * 0100h) + 20
|
||||
f_sync equ (rtm * 0100h) + 21
|
||||
f_unsync equ (rtm * 0100h) + 22
|
||||
f_no_abort equ (rtm * 0100h) + 23
|
||||
f_ok_abort equ (rtm * 0100h) + 24
|
||||
f_no_abort_spec equ (rtm * 0100h) + 25
|
||||
|
||||
|
||||
|
||||
; Internal MEM functions
|
||||
f_share equ (mem * 0100h) + 8
|
||||
f_maualloc equ (mem * 0100h) + 9
|
||||
f_maufree equ (mem * 0100h) + 10
|
||||
f_mlalloc equ (mem * 0100h) + 11
|
||||
f_mlfree equ (mem * 0100h) + 12
|
||||
|
||||
|
||||
; Internal CIO functions
|
||||
f_conprint equ (cio * 0100h) + 14
|
||||
f_cioterm equ (cio * 0100h) + 23
|
||||
f_ciostat equ (cio * 0100h) + 24
|
||||
f_rconin equ (cio * 0100h) + 2
|
||||
f_rconout equ (cio * 0100h) + 3
|
||||
|
||||
|
||||
; Internal BDOS functions
|
||||
f_bdosterm equ (bdos * 0100h) + 45
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Definition of Module Table Entry
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
mod_entry equ 0
|
||||
mod_init equ mod_entry + dword
|
||||
modlen equ mod_init + dword
|
||||
@@ -0,0 +1,49 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Parameter Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
mpb_start equ word ptr 0
|
||||
mpb_min equ word ptr mpb_start + word
|
||||
mpb_max equ word ptr mpb_min + word
|
||||
mpb_pdadr equ word ptr mpb_max + word
|
||||
mpb_flags equ word ptr mpb_pdadr + word
|
||||
|
||||
mpblen equ mpb_flags + word
|
||||
|
||||
|
||||
; mpb_flags definition (also ms_flags)
|
||||
|
||||
mf_load equ 00001h
|
||||
mf_share equ 00002h
|
||||
mf_code equ 00004h
|
||||
; mf_data equ 00008h
|
||||
; mf_extra equ 00010h
|
||||
; mf_stack equ 00020h
|
||||
mf_udaonly equ 00040h
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Memory Free Parameter Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
mfpb_start equ word ptr 0
|
||||
mfpb_pd equ word ptr mfpb_start + word
|
||||
mfpblen equ mfpb_pd + word
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MAU Free Request
|
||||
;*
|
||||
;* +----+----+----+----+----+----+
|
||||
;* | mau | sat | start |
|
||||
;* +----+----+----+----+----+----+
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
maf_mau equ word ptr 0
|
||||
maf_sat equ word ptr maf_mau + word
|
||||
maf_start equ word ptr maf_sat + word
|
||||
maflen equ maf_start + word
|
||||
Binary file not shown.
@@ -0,0 +1,155 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Parse Filename Function
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;========= =========================
|
||||
parse_ent: ; Parse filename into FCB
|
||||
;========= =========================
|
||||
; input: DX -> PCB in u_wrkseg
|
||||
; output: BX = 0ffffh on error
|
||||
; = 0 on last name in string
|
||||
; = offset of delimiter following name
|
||||
; CX = Error Code
|
||||
;
|
||||
; PCB: +----+----+----+----+
|
||||
; | NAMEADR | FCBADR |
|
||||
; +----+----+----+----+
|
||||
;
|
||||
; NAMEADR = offset of String to parse
|
||||
; FCBADR = offset of FCB in u_wrkseg
|
||||
;
|
||||
; Parsed FCB:
|
||||
; 0 => drive, 0=default, 1=A, 2=B, ...
|
||||
; 1- 8 => name, converted to upper case,
|
||||
; padded w/blanks
|
||||
; 9-11 => type, converted to upper case,
|
||||
; padded w/blanks
|
||||
; 12-15 => set to zero
|
||||
; 16-23 => password, convered to upper case,
|
||||
; padded w/blanks
|
||||
; 24-25 => address of password field in 'filename',
|
||||
; set to zero if password length=0
|
||||
; 26 => length of password (0-8)
|
||||
; 27-31 => left as is
|
||||
|
||||
mov ax,u_wrkseg
|
||||
push ds ! mov ds,ax ;DS->u_wrkseg
|
||||
push es ! mov es,ax ;ES->u_wrkseg for string ops
|
||||
mov bx,dx ! mov si,pcb_flnmptr[bx] ;SI->nxt char in parse string
|
||||
mov bx,pcb_fcbptr[bx] ;BX -> FCB
|
||||
call fcbi ! call debl ;init FCB, deblank parse str
|
||||
mov bp,e_badfname ;BAD FILENAME
|
||||
;BP=error code if error
|
||||
call delim ! jnz prs1 ;chk 1st char
|
||||
jmp pfn_endp
|
||||
prs1: mov ch,al ! inc si ! mov al,[si] ;see if Disk spec
|
||||
cmp al,':' ! jne prs2
|
||||
mov bp,e_illdisk ;drive specified
|
||||
mov al,ch ! sub al,'A' ! jc pfn_err ;see if legal
|
||||
cmp al,16 ! jge pfn_err
|
||||
inc al ! mov fcb_dr[bx],al ;good drv, set fcb_dr field
|
||||
mov bp,e_badfname
|
||||
inc si ! call delim ! jnz prs3 ;check nxt char
|
||||
cmp al,'.' ! je pfn_err ;hit delim
|
||||
cmp al,':' ! je pfn_err ; see if legal
|
||||
cmp al,';' ! je pfn_err
|
||||
jmp prs3
|
||||
prs2: dec si ;use default disk
|
||||
|
||||
prs3: ;parse filename
|
||||
mov di,bx ! lea bx,fcb_name[di]
|
||||
mov ch,8 ! call setfld ;fill in FCB
|
||||
cmp ch,0 ! jne prs4
|
||||
call delim ! jz prs4 ;see if more than 8 chars
|
||||
pfn_err: mov cx,bp
|
||||
mov bx,0ffffh ! pop es ! pop ds ! ret
|
||||
prs4: cmp al,'.' ! jnz prs5 ;see if filetype
|
||||
mov bp,e_badftype
|
||||
mov ch,3 ! lea bx,fcb_type[di]
|
||||
inc si ! call setfld ;fill in FCB
|
||||
cmp ch,0 ! jne prs5
|
||||
call delim ! jz prs5
|
||||
jmp pfn_err
|
||||
|
||||
;parse passwd
|
||||
prs5:
|
||||
cmp al,';' ! jnz prs8 ;see if password delim
|
||||
mov bp,e_ill_passwd
|
||||
mov ch,8 ! lea bx,fcb_pwd[di]
|
||||
inc si
|
||||
mov fcb_pptr[di],si ;pointer to password if any
|
||||
call setfld ;yes
|
||||
mov cl,8 ! sub cl,ch
|
||||
mov fcb_plen[di],cl
|
||||
cmp cl,0 ! jne prs51
|
||||
mov fcb_pptr[di],0 ;no password
|
||||
prs51: cmp ch,0 ! jne prs8
|
||||
call delim ! jz prs8
|
||||
jmp pfn_err
|
||||
|
||||
|
||||
prs8: mov bx,si ! call debl ;see if more to parse
|
||||
call delim ! jnz pfn_out ;if yes,exit
|
||||
mov bx,si
|
||||
cmp al,0 ! je pfn_endp
|
||||
cmp al,cr ! jne pfn_out
|
||||
pfn_endp: mov bx,0 ;NOPE
|
||||
pfn_out:sub cx,cx ! pop es ! pop ds ! ret ;exit
|
||||
|
||||
setfld: ; fill in a field until end of field or delim
|
||||
;------
|
||||
pop dx ! call delim ! push dx
|
||||
jz setret
|
||||
cmp al,'*' ! jnz setfld1
|
||||
mov byte ptr [bx],'?'
|
||||
inc bx ! dec ch ! jnz setfld
|
||||
jmp setfld2
|
||||
setfld1: mov [bx],al ! inc bx ! dec ch
|
||||
setfld2: inc si ! cmp ch,0 ! jne setfld
|
||||
setret: ret
|
||||
|
||||
delim: ; see if char is delim, if not UPPER it, err if illegal
|
||||
;-----
|
||||
; input: SI -> next char in parse string
|
||||
; output: 'z' flag on if delimiter found
|
||||
; character converted to UPPER if 'a'-'z'
|
||||
; AL = converted char
|
||||
|
||||
mov cl,ndelims ! mov al,[si] ;See if Delimiter
|
||||
push di ! mov di,offset delims ;look at delim string
|
||||
delnxt: cmp cl,0 ! je no_del ;if end of delims,not delim
|
||||
cmp cs:[di],al ! je delret ;if delim, ret w/ z set
|
||||
dec cl ! inc di ! jmps delnxt ;try next delim
|
||||
no_del: cmp al,' ' ! ja del_up ;not delim, check graphic
|
||||
pop di ! pop bx ! mov cx,e_badfname ;not graphic, err
|
||||
jmp pfn_err ;go directly out, bypass ret
|
||||
del_up: cmp al,'a' ! jb delret ;if below 'a', no high bit,ret
|
||||
cmp al,'z' ! ja del_noup ;if above 'z',
|
||||
and al,05fh ;make 'a'-'z' UPPER CASE
|
||||
del_noup: and al,07fh ;strip high bit
|
||||
delret: pop di ! ret
|
||||
|
||||
delims db 0,tab,cr,'.:;=,/[]<> '
|
||||
ndelims equ (offset $)-(offset delims)
|
||||
|
||||
debl: ;strip leading blanks
|
||||
;-------
|
||||
; input: SI -> parse string
|
||||
; output: SI -> first non-blank or tab char
|
||||
|
||||
cmp byte ptr [si],' ' ! je blnk
|
||||
cmp byte ptr [si],tab ! je blnk
|
||||
ret
|
||||
blnk: inc si ! jmps debl
|
||||
|
||||
fcbi: ; Initialize FCB
|
||||
;-------
|
||||
mov di,bx ! sub ax,ax
|
||||
sub cx,cx ! stosb ; 0 =0
|
||||
mov al,' ' ! mov cl,11 ! rep stosb ; 1-11=' '
|
||||
mov al,0 ! mov cl,2 ! rep stosw ;12-15=0
|
||||
mov al,' ' ! mov cl,8 ! rep stosb ;16-23=' '
|
||||
mov al,0 ! mov cl,3 ! rep stosb ;24-26=0
|
||||
ret
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* PATCH AREA -- 128 bytes long
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
patch:
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;00-0f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;10-1f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;20-2f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;30-3f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;40-4f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;50-5f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;60-6f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
nop ! nop ! nop ! nop ! nop ! nop ;70-7f
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Parse Control Block
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
pcb_flnmptr equ word ptr 0 ; name ptr
|
||||
pcb_fcbptr equ word ptr pcb_flnmptr + word ; fcb ptr
|
||||
pcblen equ pcb_fcbptr + word
|
||||
@@ -0,0 +1,123 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Process Descriptor - with the UDA associated
|
||||
;* with the PD, describes the current
|
||||
;* state of a Process under MP/M-CCP/M
|
||||
;*
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 00| link | thread |stat |prior| flag |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 08| Name |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 10| uda | dsk | user| ldsk|luser| mem |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 18| cmod|tkcnt| wait | reserved | parent |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 20| cns |abort| conmode | lst | reserved |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;* 28| reserved | pret | scratch |
|
||||
;* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
;*
|
||||
;* link - Used for placement into System Lists
|
||||
;* thread - link field for Thread List
|
||||
;* stat - Current Process activity
|
||||
;* prior - priority
|
||||
;* flag - process state flags
|
||||
;* name - name of process
|
||||
;* uda - Segment Adress of User Data Area
|
||||
;* dsk - Current default disk
|
||||
;* user - Current default user number
|
||||
;* ldsk - Disk program loaded from
|
||||
;* luser - User number loaded from
|
||||
;* mem - pointer to MD list of memory owned
|
||||
;* by this process
|
||||
;* cmod - compatibility mode bits.
|
||||
;* 80 -> F1 bit
|
||||
;* 40 -> F2 bit
|
||||
;* 20 -> F3 bit
|
||||
;* 10 -> F4 bit
|
||||
;* tkcnt - temp keep count, # times tempkeep has been
|
||||
;* turned on
|
||||
;* wait - parameter field while on System Lists
|
||||
;* org - Network node that originated this process
|
||||
;* net - Network node running this process
|
||||
;* parent - process that created this process
|
||||
;* cns - default console #
|
||||
;* abort - abort code
|
||||
;* lst - default list #
|
||||
;* conmode - console mode for function 109
|
||||
;* reserved- not currently used
|
||||
;* pret - return code at termination
|
||||
;* scratch - scratch word
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
p_link equ word ptr 0
|
||||
p_thread equ word ptr p_link + word
|
||||
p_stat equ byte ptr p_thread + word
|
||||
p_prior equ byte ptr p_stat + byte
|
||||
p_flag equ word ptr p_prior + byte
|
||||
p_name equ byte ptr p_flag + word
|
||||
p_uda equ word ptr p_name + pnamsiz
|
||||
p_dsk equ byte ptr p_uda + word
|
||||
p_user equ byte ptr p_dsk + byte
|
||||
p_ldsk equ byte ptr p_user + byte
|
||||
p_luser equ byte ptr p_ldsk + byte
|
||||
p_mem equ word ptr p_luser + byte
|
||||
p_cmod equ byte ptr p_mem + word
|
||||
p_tkcnt equ byte ptr p_cmod + byte
|
||||
p_wait equ word ptr p_tkcnt + byte
|
||||
p_parent equ word ptr p_wait + 4
|
||||
p_cns equ byte ptr p_parent + word
|
||||
p_abort equ byte ptr p_cns + byte
|
||||
p_conmode equ word ptr p_abort + byte
|
||||
p_lst equ byte ptr p_conmode + word
|
||||
p_pret equ word ptr p_lst + 8
|
||||
p_scratch equ byte ptr p_pret + word
|
||||
p_wscrtch equ word ptr p_scratch
|
||||
|
||||
;
|
||||
; Process descriptor pd_status values
|
||||
;
|
||||
|
||||
ps_run equ 0 ; in ready list root
|
||||
ps_poll equ 1 ; in poll list
|
||||
ps_delay equ 2 ; in delay list
|
||||
ps_swap equ 3 ; in swap list
|
||||
ps_term equ 4 ; terminating
|
||||
ps_sleep equ 5 ; sleep processing
|
||||
ps_dq equ 6 ; in dq list
|
||||
ps_nq equ 7 ; in nq list
|
||||
ps_flagwait equ 8 ; in flag table
|
||||
ps_ciowait equ 9 ; waiting for character
|
||||
ps_sync equ 10 ; waiting for sync structure
|
||||
;
|
||||
; Process descriptor pd_flag bit values
|
||||
;
|
||||
pf_sys equ 00001h ; system process
|
||||
pf_keep equ 00002h ; do not terminate
|
||||
pf_kernal equ 00004h ; resident in kernal
|
||||
pf_pure equ 00008h ; pure memory descibed
|
||||
pf_table equ 00010h ; from pd table
|
||||
pf_resource equ 00020h ; waiting for resource
|
||||
pf_raw equ 00040h ; raw console i/o
|
||||
pf_ctlc equ 00080h ; abort pending
|
||||
pf_active equ 00100h ; active tty
|
||||
pf_tempkeep equ 00200h ; don't terminate yet...
|
||||
pf_ctld equ 00400h ; explicit detach occured
|
||||
pf_childabort equ 00800h ; child terminated abnormally
|
||||
pf_noctls equ 01000h ; control S not allowed
|
||||
pf_dskld equ 02000h ; process was loaded from disk
|
||||
pf_nokbd equ 04000h ; ignore keyboard
|
||||
pf_8087 equ 08000h ; process uses 8087
|
||||
;
|
||||
; Process descriptor pcm_flag bit values
|
||||
; (console mode set by function 109)
|
||||
;
|
||||
pcm_11 equ 00001h ; control C status for function 11
|
||||
pcm_ctls equ 00002h ; disable control S-Q
|
||||
pcm_rout equ 00004h ; raw output, no tabs or control P
|
||||
pcm_ctlc equ 00008h ; disable control C
|
||||
;pcm_rsrv equ 00040h ; used by CP/M 3.0
|
||||
pcm_ctlo equ 00080h ; disable control O
|
||||
pcm_rsx equ 00300h ; 2 bits used by RSX for status
|
||||
@@ -0,0 +1,245 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Process Routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;====== =========================
|
||||
freepd: ; Free Process Descriptor
|
||||
;====== =========================
|
||||
; entry: SI = PD address
|
||||
|
||||
; Assumes no memory and on no list except thread.
|
||||
; Called only from TERM_ACT in the dispatcher
|
||||
|
||||
mov di,(offset thrdrt)-p_thread
|
||||
freepd_npd:
|
||||
mov bx,p_thread[di] ;find pd on thread
|
||||
cmp bx,si ! je freepd_trd
|
||||
mov di,bx ! jmps freepd_npd
|
||||
freepd_trd:
|
||||
mov ax,p_thread[si] ! mov p_thread[di],ax
|
||||
mov ax,p_flag[si] ! and ax,pf_table
|
||||
cmp ax,0 ! jz freepd_exit
|
||||
mov bx,pul ! mov p_link[si],bx
|
||||
mov pul,si
|
||||
freepd_exit:
|
||||
ret
|
||||
|
||||
;========== ================
|
||||
proc_creat: ; Create Process
|
||||
;========== ================
|
||||
; DX = pd address in u_wrkseg
|
||||
|
||||
cmp dx,0 ! jne cp_doit
|
||||
sub bx,bx ! ret
|
||||
cp_doit:
|
||||
call getpdadr ;si->pdaddr in rtm
|
||||
jcxz cp_gpd
|
||||
mov bx,0ffffh ! ret
|
||||
cp_gpd:
|
||||
mov dx,p_link[si]
|
||||
push dx ! push si
|
||||
; init uda fields
|
||||
cp_uda:
|
||||
;set Parent
|
||||
|
||||
mov bx,rlr
|
||||
mov p_parent[si],bx
|
||||
mov p_conmode[si],0 ;console mode - not inherited
|
||||
;unless RSX which aren't yet
|
||||
;implemented
|
||||
mov p_tkcnt[si],0 ;temp keep count
|
||||
and p_flag[bx],not (pf_childabort + pf_resource)
|
||||
mov al,p_lst[si]
|
||||
cmp al,nlstdev ! jb cp_slst
|
||||
mov al,0 ;make sure its a legal list device
|
||||
cp_slst:
|
||||
if mpm
|
||||
add al,ncondev
|
||||
endif
|
||||
mov p_lst[si],al ;list device is relative to 0 in
|
||||
;CCP/M
|
||||
|
||||
;share memory
|
||||
|
||||
cmp p_mem[bx],0 ! je cp_nm
|
||||
cmp p_mem[si],0 ! jne cp_nm
|
||||
lea di,p_mem[bx]
|
||||
cp_mnxt: mov di,ms_link[di]
|
||||
cmp di,0 ! je cp_nm
|
||||
push di
|
||||
push ms_start[di] ! push si ! push bx
|
||||
mov cx,f_share ! mov dx,sp
|
||||
push ds ! mov ax,ss ! mov ds,ax
|
||||
call osif ! pop ds
|
||||
pop bx ! pop si ! pop ax ! pop di
|
||||
jmps cp_mnxt
|
||||
cp_nm:
|
||||
;set physical UDA segment
|
||||
|
||||
mov ax,u_wrkseg
|
||||
mov dx,p_uda[si] ! add dx,ax
|
||||
mov p_uda[si],dx
|
||||
|
||||
;inherit password
|
||||
|
||||
push es ! push ds
|
||||
mov cx,es ! mov es,dx ! mov ds,cx
|
||||
mov si,offset u_df_password ! mov di,si
|
||||
mov cx,4 ! rep movsw
|
||||
|
||||
;set initial segment values
|
||||
|
||||
mov ds,dx ! xor dx,dx
|
||||
cmp ds:u_initcs,dx ! jne cp_uda1
|
||||
mov ds:u_initcs,ax
|
||||
cp_uda1:cmp ds:u_initds,dx ! jne cp_uda2 ;DX=0
|
||||
mov ds:u_initds,ax
|
||||
cp_uda2:cmp ds:u_initss,dx ! jne cp_uda3 ;DX=0
|
||||
mov ds:u_initss,ax
|
||||
cp_uda3:cmp ds:u_inites,dx ! jne cp_uda4 ;DX=0
|
||||
mov ds:u_inites,ax
|
||||
cp_uda4:
|
||||
|
||||
;Interrupt vector save areas:
|
||||
;Get parent's interrupt vectors 0,1,3,4,224,225
|
||||
;into child's UDA, if the
|
||||
;interrupt vector is not initialized in the
|
||||
;child's UDA.
|
||||
|
||||
mov ds,dx ;DX,DS=0,ES=child's UDA
|
||||
mov si,dx ;divide error vector, #0
|
||||
mov di,offset u_ivectors
|
||||
call cp_icopy
|
||||
call cp_icopy ;single step, #1
|
||||
add si,4 ! add di,4 ;skip NMI, #2
|
||||
call cp_icopy ;1-byte, #3
|
||||
call cp_icopy ;overflow, #4
|
||||
mov si,offset i_os_ip
|
||||
mov di,offset u_os_ip
|
||||
call cp_icopy ;O.S. entry, #224
|
||||
call cp_icopy ;debugger entry, #225
|
||||
|
||||
; set user's stack
|
||||
|
||||
push es ! pop ds
|
||||
mov ax,ds:u_initss
|
||||
mov ds:u_ss,ax
|
||||
mov ax,ds:u_stack_sp
|
||||
mov ds:u_sp,ax
|
||||
|
||||
; set other uda values
|
||||
|
||||
xor dx,dx
|
||||
mov ds:u_delim,'$' ;console mode init
|
||||
mov ds:u_error_mode,dl
|
||||
mov ds:u_pd_cnt,dl
|
||||
mov ds:u_mult_cnt,1
|
||||
mov ds:u_in_int,true
|
||||
;mov ds:u_insys,dl ;don't set insys
|
||||
mov bx,ds:u_initds
|
||||
mov ds:u_ds_sav,bx
|
||||
mov ds:u_dma_seg,bx
|
||||
mov ax,ds:u_inites
|
||||
mov ds:u_es_sav,ax
|
||||
mov ds:u_dparam,dx
|
||||
mov ds:u_flag_sav,dx
|
||||
mov ds:u_conccb,dx
|
||||
mov ds:u_lstccb,dx
|
||||
|
||||
; setup user stack for iret
|
||||
|
||||
mov ds,ds:u_ss
|
||||
mov di,u_sp ;sp->offset
|
||||
mov ax,u_initcs
|
||||
mov 2[di],ax ; ->segment
|
||||
mov word ptr 4[di],0200h ; ->flags, interrupts on
|
||||
pop ds ! pop es ; DS=SYSDAT, ES=UDA
|
||||
|
||||
; put on thread list
|
||||
|
||||
pop si ! pushf ! cli ; don't need SYNC here
|
||||
mov dx,thrdrt ; but this code cannot
|
||||
mov p_thread[si],dx ; be reentrant
|
||||
mov thrdrt,si
|
||||
|
||||
; put on dispatcher ready list
|
||||
|
||||
mov dx,drl ! mov p_link[si],dx
|
||||
mov drl,si ! popf
|
||||
|
||||
; do the next process
|
||||
|
||||
pop dx ! jmp proc_creat
|
||||
|
||||
|
||||
|
||||
cp_icopy:
|
||||
;--------
|
||||
; Entry: ES:DI = UDA ivector location to store
|
||||
; DS:SI = ivector to copy
|
||||
; DX = 0
|
||||
; Exit:
|
||||
; DI,SI = incremented by 4
|
||||
|
||||
cmp es:word ptr 0[di],dx ;DX=0, DI=UDA ivector to copy
|
||||
jne cp_nocopy ;don't copy interrupt vector
|
||||
cmp es:word ptr 2[di],dx ;if it is <> 0 in the UDA
|
||||
jne cp_nocopy
|
||||
mov cx,2 ;move two words
|
||||
rep movsw ;copy to UDA
|
||||
ret
|
||||
cp_nocopy:
|
||||
add si,4 ! add di,4
|
||||
ret
|
||||
|
||||
|
||||
getpdadr:
|
||||
;--------
|
||||
; entry: DX = PD address in U_WRKSEG
|
||||
; exit: CX = 0 successful
|
||||
; SI = PD address in SYSDAT if success
|
||||
; CX =
|
||||
; Make sure PD address is in SYSDAT. If not, copy into
|
||||
; one in PD table. Make address relative to SYSDAT
|
||||
|
||||
push dx ;save PD in U_WRKSEG
|
||||
mov bx,pdlen
|
||||
call sysdat_chk
|
||||
jcxz gpd_bad
|
||||
mov ax,u_wrkseg ;PD is within SYSDAT
|
||||
mov bx,ds
|
||||
sub ax,bx ;U_WRKSEG-SYSDAT
|
||||
mov cl,4 ! shl ax,cl ;make into bytes
|
||||
pop si ;SI relative to U_WRKSEG
|
||||
add si,ax ;SI->PD relative to SYSDAT
|
||||
jmps gpd_done
|
||||
|
||||
gpd_bad:
|
||||
pop si ;U_WRKSEG:SI->PD to copy
|
||||
pushf ! cli ;turn off interrupts while
|
||||
mov di,pul ;changing the PUL
|
||||
test di,di
|
||||
jnz gpd_have
|
||||
mov cx,e_no_pd ;no free PDs left
|
||||
popf ! ret
|
||||
gpd_have: ;DI->PD in SYSDAT
|
||||
mov ax,p_link[di]
|
||||
mov pul,ax ;update PUL
|
||||
popf ;allow interrupts
|
||||
push di ;save address of PD in SYSDAT
|
||||
push es ;save UDA
|
||||
push ds ;SYSDAT
|
||||
mov ds,u_wrkseg ;DS=U_WRKSEG
|
||||
pop es ;ES=SYSDAT
|
||||
mov cx,pdlen/2
|
||||
rep movsw ;copy PD into SYSDAT PD
|
||||
push es ! pop ds ;DS=SYSDAT
|
||||
pop es ;ES=UDA
|
||||
pop si ;SI=PD in SYSDAT
|
||||
or p_flag[si],pf_table ;got it from PD table
|
||||
|
||||
gpd_done:
|
||||
xor cx,cx
|
||||
ret
|
||||
@@ -0,0 +1,82 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Queue Descriptor - This is structure is used
|
||||
;* to create a queue. One is maintained
|
||||
;* in the system data area for each queue
|
||||
;*
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 00 | link |net |org | flags | name...
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 08 ...name | msglen |
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 10 | nmsgs | dq | nq | msgcnt |
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 18 | msgout | buffer |
|
||||
;* +----+----+----+----+
|
||||
;*
|
||||
;* link - used to link QDs is system lists
|
||||
;* net - which machine in the network
|
||||
;* org - origin machine in the network
|
||||
;* flags - Queue Flags
|
||||
;* name - Name of Queue
|
||||
;* msglen - # of bytes in one message
|
||||
;* nmsgs - maximum # of messages in queue
|
||||
;* dq - Root of PDs waiting to read
|
||||
;* nq - Root of PDs list waiting to write
|
||||
;* msgcnt - # of messages currently in queue
|
||||
;* msgout - next message # to read
|
||||
;* buf - pointer to queue message buffer
|
||||
;* (for MX queues, owner of queue)
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
q_link equ word ptr 0
|
||||
q_net equ byte ptr q_link + word
|
||||
q_org equ byte ptr q_net + byte
|
||||
q_flags equ word ptr q_org + byte
|
||||
q_name equ byte ptr q_flags + word
|
||||
q_msglen equ word ptr q_name + qnamsiz
|
||||
q_nmsgs equ word ptr q_msglen + word
|
||||
q_dq equ word ptr q_nmsgs + word
|
||||
q_nq equ word ptr q_dq + word
|
||||
q_msgcnt equ word ptr q_nq + word
|
||||
q_msgout equ word ptr q_msgcnt + word
|
||||
q_buf equ word ptr q_msgout + word
|
||||
qdlen equ q_buf + word
|
||||
;
|
||||
; Q_FLAGS values
|
||||
;
|
||||
qf_mx equ 001h ; Mutual Exclusion
|
||||
qf_keep equ 002h ; NO DELETE
|
||||
qf_hide equ 004h ; Not User writable
|
||||
qf_rsp equ 008h ; rsp queue
|
||||
qf_table equ 010h ; from qd table
|
||||
qf_rpl equ 020h ; rpl queue
|
||||
qf_dev equ 040h ; device queue
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* QPB - Queue Parameter Block
|
||||
;*
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 00 |flgs|net | qaddr | nmsgs | buffptr |
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;* 08 | name |
|
||||
;* +----+----+----+----+----+----+----+----+
|
||||
;*
|
||||
;* flgs - unused
|
||||
;* net - unused (which machine to use)
|
||||
;* qaddr - Queue ID, address of QD
|
||||
;* nmsgs - number of messages to read/write
|
||||
;* buffptr - address to read/write into/from
|
||||
;* name - name of queue (for open only)
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
qpb_flgs equ byte ptr 0
|
||||
qpb_net equ byte ptr qpb_flgs + byte
|
||||
qpb_qaddr equ word ptr qpb_net + byte
|
||||
qpb_nmsgs equ word ptr qpb_qaddr + word
|
||||
qpb_buffptr equ word ptr qpb_nmsgs + word
|
||||
qpb_name equ byte ptr qpb_buffptr + word
|
||||
qpblen equ qpb_name + qnamsiz
|
||||
@@ -0,0 +1,458 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Queue Routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
; Each queue system entry point is mutually exclusive
|
||||
; of the other queue system entry points.
|
||||
; All the routines called in QUE2.RTM are
|
||||
; subroutines of the entry points in QUE1.RTM and
|
||||
; thus are called only when the process has ownership
|
||||
; of the q system.
|
||||
|
||||
; If a process is already in the queue system another process
|
||||
; will wait until the first process calls Q_UNSYNC.
|
||||
; This allows us to keep interrupts on while using shared variables.
|
||||
|
||||
; To protect against terminating and potentially losing a QD,
|
||||
; a message or neglecting to wake up a DQing or NQing
|
||||
; process; a "no abort region" is entered whenever
|
||||
; we obtain the queue system. In addition if we assign
|
||||
; the queue system to a DQing or NQing process, the new owner
|
||||
; of the q system is forced into a "no abort region". This
|
||||
; makes the environment of the waking NQing or DQing process appear
|
||||
; as if it never went to sleep.
|
||||
|
||||
; A note for the uninitiated: DQing is short for "Decoding from a Queue"
|
||||
; or reading from a queue. NQing is short for "eNcoding to a Queue"
|
||||
; or writing to a queue.
|
||||
|
||||
|
||||
;=========== =======================
|
||||
makeq_entry: ; Create a System Queue
|
||||
;=========== =======================
|
||||
; input : U_WRKSEG:DX = address of QD to create
|
||||
; output: BX = 0 if okay , 0ffffh if error
|
||||
; CX = error Code
|
||||
|
||||
call q_sync ;obtain q system, BX,DX preserved
|
||||
|
||||
call getqdaddr ;get QD and q buffer
|
||||
jcxz qm_gotqd
|
||||
jmp qm_err
|
||||
qm_gotqd: ;DI->QD in SYSDAT
|
||||
;make sure this queue doesn't
|
||||
;already exist
|
||||
qm_chk:
|
||||
push es ;save UDA
|
||||
mov es,sysdat
|
||||
mov si,(offset qlr)-q_link
|
||||
qm_nxt:
|
||||
mov si,q_link[si] ;go down QLR to see if QD already
|
||||
test si,si ! jz qm_go ;exists
|
||||
push di ! push si ;save new QD and QLR ptr
|
||||
mov cx,qnamsiz/2
|
||||
add di,q_name ;ES:DI->QPB.NAME
|
||||
add si,q_name ;DS:SI->QPB.NAME
|
||||
repe cmpsw
|
||||
pop si ! pop di ;restore QLR ptr and new QD
|
||||
jne qm_nxt ;no match try next QD
|
||||
|
||||
pop es ;names match, restore UDA
|
||||
call remqd ;QD pointed to by DS:DI
|
||||
|
||||
mov cx,e_q_inuse
|
||||
jmps qm_err
|
||||
|
||||
qm_go: ;no match - alright to make this q
|
||||
pop es ;ES=UDA
|
||||
xor dx,dx ;initialize the QD
|
||||
mov q_dq[di],dx
|
||||
mov q_nq[di],dx
|
||||
mov q_msgcnt[di],dx
|
||||
mov q_msgout[di],dx
|
||||
mov ax,qlr ;put QD on QLR
|
||||
mov q_link[di],ax
|
||||
mov qlr,di
|
||||
xor bx,bx ;return success
|
||||
jmps qm_ret
|
||||
qm_err:
|
||||
mov bx,0ffffh
|
||||
qm_ret:
|
||||
jmp q_unsync ;release q system; BX,CX preserved
|
||||
|
||||
;=========== ======================
|
||||
openq_entry: ; Find an active Queue
|
||||
;=========== ======================
|
||||
; input: U_WRKSEG:DX = address of QPB
|
||||
;
|
||||
; output: sets QPB.QADDR to QD offset in SYSDAT
|
||||
; BX = 0 if okay, 0ffffh if not
|
||||
; CX = error Code
|
||||
|
||||
call q_sync ;obtain q system; BX,DX preserved
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg
|
||||
mov si,(offset qlr)-q_link
|
||||
mov di,dx ;ES:DI->QPB
|
||||
qo_nqd:
|
||||
mov si,q_link[si] ;go down QLR until QD name
|
||||
test si,si ! jnz qo_cmp ;matches QPB name or end of QLR
|
||||
pop es ;ES=UDA
|
||||
mov cx,e_no_queue ;found end of QLR - can't open
|
||||
jmps qo_err
|
||||
qo_cmp:
|
||||
push di ! push si ;compare names
|
||||
mov cx,qnamsiz/2
|
||||
add si,q_name ;DS:SI->QD.NAME
|
||||
add di,qpb_name ;ES:DI->QPB.NAME
|
||||
repe cmpsw
|
||||
pop si ! pop di ;restore QD,QPB
|
||||
jne qo_nqd ;try next QD if no match
|
||||
|
||||
test q_flags[si],qf_hide ;names match
|
||||
jz noprot ;check for protection:
|
||||
mov bx,rlr ;must be system process to
|
||||
test p_flag[bx],pf_sys ;open q with QF_HIDE set
|
||||
jnz noprot
|
||||
pop es ;ES=UDA
|
||||
mov cx,e_q_protected ;QF_HIDE and not SYS PD
|
||||
jmps qo_err
|
||||
noprot:
|
||||
mov es:qpb_qaddr[di],si ;write the QD offset into
|
||||
pop es ;ES=UDA
|
||||
xor bx,bx ;the QPB_QADDR field
|
||||
jmps qo_ret ;to open the q
|
||||
|
||||
qo_err: ;CX=error code
|
||||
mov bx,0ffffh
|
||||
qo_ret:
|
||||
call q_unsync ;release q system; BX,CX preserved
|
||||
ret
|
||||
|
||||
|
||||
;============= =======================
|
||||
deleteq_entry: ; Delete a System Queue
|
||||
;============= =======================
|
||||
; Takes QD off the QLR and place it in the QUL
|
||||
; input: U_WRKSEG:DX = offset of QPB
|
||||
; output: BX = 0 if ok, 0ffffh if error
|
||||
; CX = error code
|
||||
|
||||
mov ax,es ;save UDA
|
||||
mov es,u_wrkseg ;get QD address from user's
|
||||
mov di,dx ;QPB
|
||||
mov di,es:qpb_qaddr[di] ;DS:DI->QD (unverified)
|
||||
mov es,ax ;ES=UDA
|
||||
|
||||
;Check for KEEP, SYS Flags
|
||||
;DS:DI->QD
|
||||
test q_flags[di],qf_keep
|
||||
jnz qd_err1
|
||||
test q_flags[di],qf_hide
|
||||
jz qd_ok1
|
||||
mov bx,rlr ;if hide flag then
|
||||
test p_flag[bx],pf_sys ;SYS flag must be on in PD
|
||||
jnz qd_ok1
|
||||
|
||||
qd_err1: mov cx,e_q_protected
|
||||
mov bx,0ffffh
|
||||
ret
|
||||
qd_ok1:
|
||||
push di ;DI->QD
|
||||
call q_sync ;obtain q system; BX,DX preserved
|
||||
pop di
|
||||
mov ax,q_dq[di] ;if any process is NQing or
|
||||
mov dx,q_nq[di] ;DQing we can't delete
|
||||
or dx,ax ! mov cx,e_q_inuse
|
||||
jnz qd_err2
|
||||
|
||||
mov bx,(offset qlr)-q_link
|
||||
qd_nqd: ;look for QD on QLR
|
||||
mov si,q_link[bx] ;DI=QD to delete
|
||||
test si,si ! jz qd_noq
|
||||
cmp si,di ! je qd_found
|
||||
mov bx,si ! jmps qd_nqd ;try next queue
|
||||
qd_found:
|
||||
mov ax,q_link[di] ;found the queue, remove
|
||||
mov q_link[bx],ax ;it from QLR
|
||||
call remqd
|
||||
xor bx,bx ;return success
|
||||
jmps qd_ret
|
||||
|
||||
qd_noq:
|
||||
mov cx,e_no_queue
|
||||
qd_err2:
|
||||
mov bx,0ffffh
|
||||
qd_ret:
|
||||
jmp q_unsync ;release q system
|
||||
;ret ;BX,CX preserved
|
||||
|
||||
;=========== ============
|
||||
readq_entry: ; Read Queue
|
||||
;=========== ============
|
||||
xor al,al ! jmps readq
|
||||
|
||||
;============
|
||||
creadq_entry: ; Conditional Read Queue
|
||||
;============
|
||||
mov al,0ffh
|
||||
; jmps readq
|
||||
|
||||
readq: ; Read message from queue
|
||||
;----- -------------------------
|
||||
; If no buffer is available the process
|
||||
; making an unconditional READQ is placed into the DQ list.
|
||||
;
|
||||
; input: U_WRKSEG:DX = QPB
|
||||
; AL = 0 if unconditional
|
||||
; <> 0 if not
|
||||
; output: BX = 0 if okay
|
||||
; 0ffffh if error
|
||||
; CX = Error Code
|
||||
|
||||
push ax ;save cond code
|
||||
call q_sync ;get q system; BX,DX preserved
|
||||
call queverify ;is the QPB valid ?
|
||||
pop ax ;AL=cond code
|
||||
mov si,dx ;U_WRKSEG:SI->QPB
|
||||
jcxz qr_ver ;CX=0 QPB is ok
|
||||
jmp qr_err ;CX=error code from
|
||||
qr_ver: ;queverify
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg ;ES:SI->QPB
|
||||
mov bx,es:qpb_qaddr[si] ;BX->QD
|
||||
cmp q_msgcnt[bx],0 ;is there a msg to read ?
|
||||
jne qr_readit
|
||||
|
||||
qr_wait:
|
||||
pop es ;ES=UDA
|
||||
test al,al ! jz qr_wait1 ;conditional read if AL <> 0
|
||||
mov cx,e_q_empty
|
||||
jmps qr_err
|
||||
qr_wait1: ;ES=UDA
|
||||
push bx ! push si ;QD, QPB
|
||||
lea dx,q_dq[bx] ;DX=addr of DQ List
|
||||
mov bl,ps_dq ;sleep status=DQ
|
||||
call q_wait ;wait for a DQ
|
||||
;we now own the q system
|
||||
;and cannot be aborted
|
||||
pop si ! pop bx ;QPB, QD
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg
|
||||
qr_readit:
|
||||
mov di,es:qpb_buffptr[si] ;ES:[DI]->user's queue buffer
|
||||
mov cx,q_msglen[bx] ;ES=U_WRKSEG
|
||||
test cx,cx ! jnz qr_lmsg ;check message length
|
||||
xor ax,ax
|
||||
test q_flags[bx],qf_mx ;msglen=0, check for MX q
|
||||
jz qr_end
|
||||
mov ax,rlr ;its a MX queue
|
||||
mov q_buf[bx],ax ;BUF = PD addr of owner
|
||||
xor ax,ax
|
||||
jmps qr_end
|
||||
qr_lmsg: ;msglen > 0
|
||||
mov ax,q_msgout[bx] ! push ax ;MSGOUT is # of message to read
|
||||
mul cx ! add ax,q_buf[bx] ;compute its start in buffer
|
||||
mov si,ax
|
||||
rep movsb ;move to QPB buffer
|
||||
pop ax ! inc ax ;set MSGOUT to next message
|
||||
cmp ax,q_nmsgs[bx] ;circular buffers, so
|
||||
jne qr_end ;check for wrap around
|
||||
xor ax,ax
|
||||
qr_end:
|
||||
pop es ;ES=UDA
|
||||
mov q_msgout[bx],ax
|
||||
dec q_msgcnt[bx]
|
||||
lea dx,q_nq[bx]
|
||||
call q_assign_sync ;give the queue system to
|
||||
;first NQing process if any,
|
||||
call q_unsync ;release q system if we still
|
||||
;own it, exit no abort region
|
||||
xor bx,bx ;indicate success
|
||||
ret
|
||||
|
||||
qr_err:
|
||||
call q_unsync ;release q system, exit no abort
|
||||
;region, BX,CX preserved
|
||||
mov bx,0ffffh ;indicate error
|
||||
ret
|
||||
|
||||
;============ =============
|
||||
writeq_entry: ; Write Queue
|
||||
;============ =============
|
||||
xor al,al ! jmps writeq
|
||||
|
||||
;============= =========================
|
||||
cwriteq_entry: ; conditional Write Queue
|
||||
;============= =========================
|
||||
mov al,0ffh
|
||||
;jmps writeq
|
||||
|
||||
writeq: ; Write message to queue
|
||||
;------ ------------------------
|
||||
; If no buffer is available when making an unconditional
|
||||
; WRITEQ call, the calling process is placed into the NQ list.
|
||||
;
|
||||
; input: U_WRKSEG:DX = QPB
|
||||
; AL = 0 if unconditional
|
||||
; <> 0 if not
|
||||
; output: BX = 0 if okay
|
||||
; 0ffffh if error
|
||||
; CX = Error Code
|
||||
|
||||
push ax ;save cond code
|
||||
call q_sync ;get queue system
|
||||
;BX,DX preserved
|
||||
call queverify ;is the QPB valid ?
|
||||
pop ax ;AL = cond code
|
||||
mov di,dx ;U_WRKSEG:DI->QPB
|
||||
jcxz qw_ver ;CX=0 QPB is ok
|
||||
jmp qw_err ;CX=error code from
|
||||
qw_ver: ;queverify
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg ;ES:DI->QPB
|
||||
mov bx,es:qpb_qaddr[di] ;BX->QD
|
||||
mov cx,q_msgcnt[bx]
|
||||
cmp cx,q_nmsgs[bx] ;is there a buffer to write ?
|
||||
jne qw_writeit
|
||||
|
||||
qw_wait:
|
||||
pop es ;ES=UDA
|
||||
test al,al ! jz qw_wait1 ;conditional read if AL <> 0
|
||||
mov cx,e_q_full
|
||||
jmps qw_err
|
||||
qw_wait1: ;ES=UDA
|
||||
push bx ! push di ;save QD, QPB
|
||||
lea dx,q_nq[bx] ;DX=addr of NQ List
|
||||
mov bl,ps_nq ;sleep status=NQ
|
||||
call q_wait ;sleep on NQ List
|
||||
;q system is assigned to us,
|
||||
;we are in no abort region
|
||||
;by DQing process that woke us
|
||||
pop di ! pop bx ;QPB,QD
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg
|
||||
qw_writeit:
|
||||
mov si,es:qpb_buffptr[di] ;U_WRKSEG:[SI]->user's queue buffer
|
||||
mov cx,q_msglen[bx] ;ES=U_WRKSEG
|
||||
test cx,cx ! jnz qw_lmsg ;check message length
|
||||
test q_flags[bx],qf_mx ;msglen=0, check for MX q
|
||||
jz qw_end
|
||||
xor ax,ax
|
||||
mov q_buf[bx],ax ;its a MX queue
|
||||
jmps qw_end ;BUF = 0
|
||||
|
||||
qw_lmsg: ;msglen > 0
|
||||
mov ax,q_msgout[bx]
|
||||
add ax,q_msgcnt[bx] ;AX = # of message to write
|
||||
cmp ax,q_nmsgs[bx] ;check for wrap around
|
||||
jb qw_move
|
||||
sub ax,q_nmsgs[bx]
|
||||
qw_move:
|
||||
mul cx ! add ax,q_buf[bx] ;compute its start in buffer
|
||||
mov di,ax ;DI offset of new msg in buffer
|
||||
mov ax,ds ! mov dx,es
|
||||
mov es,ax ! mov ds,dx ;ES=SYSDAT, DS=U_WRKSEG
|
||||
rep movsb ;move to QPB buffer
|
||||
mov ax,es ! mov ds,ax ;DS=SYSDAT
|
||||
qw_end:
|
||||
pop es ;ES=UDA
|
||||
inc q_msgcnt[bx] ;one more message in the queue
|
||||
lea dx,q_dq[bx] ;wake DQing process if any
|
||||
call q_assign_sync
|
||||
call q_unsync ;release q system if we still
|
||||
xor bx,bx ;own it, exit no abort region
|
||||
ret ;BX=0: success
|
||||
|
||||
qw_err:
|
||||
call q_unsync ;release q system; exit no abort
|
||||
;region BX,CX preserved
|
||||
mov bx,0ffffh ;indicate error
|
||||
ret
|
||||
|
||||
|
||||
q_wait: ;wait on DQ or NQ list
|
||||
;------
|
||||
; entry: DX = list to wait on
|
||||
; BL = sleep status
|
||||
; calling process owns queue system through
|
||||
; a call to q_sync
|
||||
|
||||
; Queue message or buffer space is not available.
|
||||
; Give up queue system and sleep on DQ or NQ list, but
|
||||
; do not allow any other process to read or write to a queue
|
||||
; until we get on the sleep list.
|
||||
|
||||
|
||||
pushf ! cli ;keep abort spec from running ...
|
||||
push bx ! push dx ;save sleep status, list address
|
||||
call q_unsync ;does not go to dispatcher, we can be
|
||||
pop dx ! pop bx ;aborted once on sleep list
|
||||
call sleep_entry ;go to dispatcher
|
||||
popf ;come back after q_assign call
|
||||
ret ;Q_ASSIGN: wakes us up when resource
|
||||
;is ready
|
||||
|
||||
q_sync: ;obtain ownership of q system
|
||||
;------
|
||||
; entry: interrupts should be on
|
||||
; ES=UDA
|
||||
; exit: we own the queue system for make,open,read,write,delete
|
||||
; queue operations, interrupts unchanged
|
||||
; BX,DX preserved - usually entry parameters
|
||||
|
||||
push bx ! push dx
|
||||
call no_abort_entry ;we cannot abort while in the queue system
|
||||
mov bx,offset q_spb
|
||||
call sync_entry
|
||||
pop dx ! pop bx
|
||||
ret
|
||||
|
||||
|
||||
q_unsync: ;release the queue system
|
||||
;-------- ;to other processes
|
||||
; entry: interrupts can be or off
|
||||
; exit: interrupts unchanged,
|
||||
; have not gone to dispatcher,
|
||||
; BX,CX preserved - usually return codes
|
||||
|
||||
push bx ! push cx
|
||||
mov bx,offset q_spb
|
||||
call unsync_entry ;wait for queue system
|
||||
call ok_abort_entry ;allow calling PD to be terminated
|
||||
pop cx ! pop bx
|
||||
ret
|
||||
|
||||
|
||||
q_assign_sync:
|
||||
;-------------
|
||||
; entry: DX = address of DQ or NQ list to give the queue
|
||||
; exit: none
|
||||
|
||||
; Assign is used so a process is forced to read or write
|
||||
; after DQing or NQing. Otherwise an awakening DQing or NQing
|
||||
; process could be deleted, leaving a message or buffer space
|
||||
; available with other processes still DQing or NQing.
|
||||
; This message or buffer space would never be reclaimed.
|
||||
; To prevent this situation, the waking DQing or NQing process
|
||||
; is kept from aborting and assigned the QSPB. Note
|
||||
; it is ok for a process to be aborted while it is on the NQ or
|
||||
; DQ list before this routine is called.
|
||||
|
||||
pushf ! cli ;keep abort spec from terminating
|
||||
mov bx,dx ;waking process
|
||||
mov dx,[bx] ;first process on list
|
||||
test dx,dx ;is there a process to wake?
|
||||
jz qa_ret
|
||||
push bx ;save list root
|
||||
call no_abort_spec_entry ;can not abort while in queue
|
||||
pop dx ;system
|
||||
popf ;interrupts are ok now -
|
||||
mov bx,offset q_spb ;present owner and next owner
|
||||
jmp assign_sync_entry ;have TEMPKEEP on
|
||||
|
||||
qa_ret:
|
||||
popf
|
||||
ret
|
||||
@@ -0,0 +1,224 @@
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* Queue system subroutines: Q System must be owned *
|
||||
;* before calling any of the following routines *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
queverify: ; check QLR for existence of QD address
|
||||
;--------- ---------------------------------------
|
||||
; entry: U_WRKSEG:DX = offset of QPB
|
||||
; exit: CX = 0 if queue is found
|
||||
; CX = E_NO_QUEUE error code, if not
|
||||
; BX=SI=QD offset
|
||||
; ES,DX preserved
|
||||
|
||||
push es ;save UDA
|
||||
mov es,u_wrkseg
|
||||
mov bx,dx ;ES:BX->QPB
|
||||
mov bx,es:qpb_qaddr[bx] ;get QD from user's QPB
|
||||
pop es ;restore UDA
|
||||
lea si,qlr-q_link
|
||||
qv_nxt:
|
||||
mov si,q_link[si] ;SI addresses of valid QDs
|
||||
test si,si ! jz qv_nqf
|
||||
cmp bx,si ! jne qv_nxt
|
||||
xor cx,cx ! ret ;BX=SI=QD offset, return success
|
||||
qv_nqf:
|
||||
mov cx,e_no_queue ;couldn't find the queue
|
||||
ret
|
||||
|
||||
getqdaddr:
|
||||
;----------
|
||||
; entry: DX = offset of QD in U_WRKSEG
|
||||
; exit: DI = offset of QD in SYSDAT
|
||||
;
|
||||
; If QD address is within SYSDAT use it.
|
||||
; Else get a QD from QDUL and set QF_TABLE flag.
|
||||
; If Q_NMSGS=0 in QD then return error.
|
||||
; If 0 length buffer needed, zero the Q_BUF field.
|
||||
; If buffer space is within SYSDAT use it. Else get buffer
|
||||
; from QMAU. Return the QD address within SYSDAT.
|
||||
|
||||
push dx ;save QD offset
|
||||
mov bx,qdlen
|
||||
call sysdat_chk
|
||||
jcxz g_qul ;CX=0 if not within SYSDAT
|
||||
mov ax,u_wrkseg ;# of paragraphs to U_WRKSEG
|
||||
mov bx,ds
|
||||
sub ax,bx ;from SYSDAT
|
||||
mov cl,4 ! shl ax,cl ;make into # of bytes
|
||||
pop di ;DI=QD in U_WRKSEG
|
||||
add di,ax ;make QD relative to SYSDAT
|
||||
jmps g_qd
|
||||
g_qul:
|
||||
mov di,qul ;get QD from QUL
|
||||
test di,di ;DI=unused QD
|
||||
jnz g_gotqd
|
||||
pop dx
|
||||
mov cx,e_no_qd ;no QD available
|
||||
ret
|
||||
g_gotqd:
|
||||
mov ax,q_link[di]
|
||||
mov qul,ax
|
||||
pop si ;SI=QD in U_WRKSEG
|
||||
push di ;save SYSDAT QD
|
||||
mov cx,qdlen/2
|
||||
; ES=UDA, DS=SYSDAT
|
||||
mov ax,ds
|
||||
mov ds,u_wrkseg ; DS:SI = QD in U_WRKSEG
|
||||
push es ! mov es,ax ; ES:DI = QD in SYSDAT
|
||||
rep movsw ; copy QD into QD in SYSDAT
|
||||
mov ax,es ! mov ds,ax
|
||||
pop es ; ES=UDA, DS=SYSDAT
|
||||
pop di ; SYSDAT:DI -> New QD
|
||||
or q_flags[di],qf_table ; Set "from table" flag
|
||||
|
||||
g_qd: ;DI=QD in SYSDAT
|
||||
xor cx,cx ;CX=0
|
||||
cmp q_nmsgs[di],cx ;must have one or more msgs
|
||||
jne g_buflen ;or illegal queue
|
||||
mov cx,e_no_qbuf
|
||||
jmps g_qdfree
|
||||
g_buflen: ;if MX or buffer length is zero
|
||||
test q_flags[di],qf_mx ;0 Q_BUF field and return
|
||||
jnz g_mx ;CX=0 to indicate success
|
||||
cmp q_msglen[di],cx
|
||||
jne g_getbuf
|
||||
g_mx:
|
||||
mov q_buf[di],cx
|
||||
ret
|
||||
g_getbuf: ;non 0 length buffer needed
|
||||
cmp q_buf[di],0 ;is there a buffer specified?
|
||||
je g_buf
|
||||
mov ax,q_msglen[di] ;yes make sure it fits in SYSDAT
|
||||
mul q_nmsgs[di] ;AX=needed buffer space
|
||||
mov bx,ax
|
||||
mov dx,q_buf[di]
|
||||
call sysdat_chk
|
||||
jcxz g_buf ;CX=0 not within SYSDAT
|
||||
mov ax,u_wrkseg ;# of paragraphs to U_WRKSEG
|
||||
mov bx,ds
|
||||
sub ax,bx ;from SYSDAT
|
||||
mov cl,4 ! shl ax,cl ;make into # of bytes
|
||||
add q_buf[di],ax ;make buffer relative to SYSDAT
|
||||
xor cx,cx ;indicate success
|
||||
ret
|
||||
|
||||
g_buf: ;allocate buffer space to queue
|
||||
call qspace
|
||||
jcxz g_ret
|
||||
mov cx,e_no_qbuf ;no buffer space
|
||||
g_qdfree:
|
||||
mov ax,qul ;error return QD to QUL
|
||||
mov q_link[di],ax
|
||||
mov qul,di ;CX = error code
|
||||
g_ret:
|
||||
ret
|
||||
|
||||
|
||||
sysdat_chk:
|
||||
;----------
|
||||
; entry: DX = offset of data structure to check
|
||||
; relative to U_WRKSEG
|
||||
; BX = length of data structure
|
||||
; exit: CX <> 0 if within SYSDAT
|
||||
; or wrap around
|
||||
; CX = 0 if not within SYSDAT
|
||||
; SI,DI preserved
|
||||
|
||||
; Check data structure for being within SYSDAT
|
||||
; Also check that data structure doesn't wrap
|
||||
; around at 64K, or 1 megabyte.
|
||||
|
||||
add dx,bx ;find end of data structure
|
||||
jc sc_no ;check for 64K wrap around
|
||||
add dx,0fh
|
||||
mov cl,4 ;round up to next paragraph
|
||||
shr dx,cl ;1st paragraph after struct relative
|
||||
add dx,u_wrkseg ;to U_WRKSEG
|
||||
jc sc_no ;next paragraph after struct
|
||||
;check for 1 MB wrap around
|
||||
mov ax,sysdat
|
||||
cmp dx,ax ;check for below SYSDAT
|
||||
jb sc_no
|
||||
add ax,1000h ;check for above SYSDAT
|
||||
cmp ax,endseg ;must be within 64k and ENDSEG
|
||||
jb sc_end ;(use the smaller of the 2)
|
||||
mov ax,endseg
|
||||
sc_end:
|
||||
cmp dx,ax ;DX=next paragraph,
|
||||
ja sc_no
|
||||
mov cl,1 ;indicate within SYSDAT
|
||||
ret
|
||||
sc_no:
|
||||
xor cx,cx
|
||||
ret
|
||||
|
||||
qspace:
|
||||
;------
|
||||
; entry: DI = QD address
|
||||
; exit: CX = 0 if ok else error code
|
||||
; DI preserved
|
||||
; Allocate buffer space for QD
|
||||
; The QMAU describes the Memory Allocation Unit
|
||||
; for the queues. QMAU is set up by GENCCPM or GENSYS.
|
||||
|
||||
mov ax,q_msglen[di] ;compute size of buffer
|
||||
mul q_nmsgs[di] ;AX=size of request
|
||||
xor cx,cx
|
||||
push cx ! push cx ! push ax ;call MALLOC
|
||||
push ax ! push cx ;with MPB on stack
|
||||
mov dx,sp ! mov ax,ss
|
||||
mov ds,ax
|
||||
mov bx,offset qmau
|
||||
push di ;save QD
|
||||
mov cx,f_maualloc ;go through OSIF to
|
||||
call osif ;get U_WRKSEG=SS
|
||||
pop di ;DI=QD
|
||||
mov ds,sysdat
|
||||
cmp cx,0 ! jne qspace_ret
|
||||
mov bp,sp
|
||||
mov ax,mpb_start[bp]
|
||||
mov q_buf[di],ax ;address of buffer
|
||||
|
||||
qspace_ret:
|
||||
add sp,10 ;pop MPB from stack
|
||||
ret
|
||||
|
||||
remqd:
|
||||
;-----
|
||||
; Place QD on queue unused list
|
||||
; entry: DS:DI = QD address
|
||||
; exit: none
|
||||
|
||||
mov ax,q_flags[di]
|
||||
and ax,qf_table ! jz rqd_exit
|
||||
mov ax,qul ! mov q_link[di],ax
|
||||
mov qul,di
|
||||
jmps qrelease
|
||||
rqd_exit:
|
||||
ret
|
||||
|
||||
|
||||
qrelease:
|
||||
;--------
|
||||
; entry: DI = QD address
|
||||
; exit : none
|
||||
;
|
||||
; Release buffer space for QD.
|
||||
; If the released space is ajacent to another
|
||||
; free area, they are joined in the SAT table.
|
||||
; The QMAU describes the Memory Allocation Unit
|
||||
; for the queues. QMAU is set up by GENCCPM or GENSYS.
|
||||
|
||||
|
||||
mov ax,q_buf[di]
|
||||
mov cx,offset qmau
|
||||
push ax ! push ax ! push cx ;MFPB on stack
|
||||
mov cx,f_maufree
|
||||
mov dx,sp ! mov ax,ss ! mov ds,ax
|
||||
call osif
|
||||
add sp,6 ;pop MFPB from stack
|
||||
mov ds,cs:sysdat ;DS=SYSDAT
|
||||
ret
|
||||
@@ -0,0 +1,79 @@
|
||||
;**********************************************************
|
||||
;*
|
||||
;* Call Resident System Procedure
|
||||
;*
|
||||
;**********************************************************
|
||||
|
||||
cpb_name equ word ptr 0
|
||||
cpb_param equ word ptr cpb_name + qnamsiz
|
||||
|
||||
;=======
|
||||
rpl_ent: ; Call Resident Procedure Library
|
||||
;=======
|
||||
; input: DX = CPB address in u_wrkseg
|
||||
; output: BX = return from RPL (also u_retseg)
|
||||
; 1 if error
|
||||
; CX = error code
|
||||
;
|
||||
; The stack is used like this:
|
||||
;
|
||||
; stack bottom ------------------------- higher memory
|
||||
; 26 | starting DS (sysdat)|
|
||||
; 24 | starting ES (uda) |
|
||||
; 22 | seg of rpl_ret: |
|
||||
; 20 | offset of rpl_ret: |
|
||||
; 18 | seg of the RPL |
|
||||
; 16 | offset or RPL |<-------
|
||||
; 14 | Q /\ | |
|
||||
; 12 | P || | |
|
||||
; 10 | | || | |
|
||||
; 8 | B qname | |
|
||||
; 6 | L buffptr |------>|
|
||||
; 4 | O nmsgs |
|
||||
; 2 | C qaddr |
|
||||
; 0 | K flgs & net |<------SP
|
||||
; stack top ------------------------- lower memory
|
||||
|
||||
|
||||
push ds ! push es
|
||||
mov ds,u_wrkseg ; save ds
|
||||
mov si,dx
|
||||
push cs ; rpl_ret segment
|
||||
mov ax,offset rpl_ret ! push ax ; rpl_ret offset
|
||||
sub ax,ax ! push ax ! push ax ; QPB buffer
|
||||
mov di,sp ; DI -> buffer
|
||||
push (cpb_name+6)[si] ; qpb_name
|
||||
push (cpb_name+4)[si]
|
||||
push (cpb_name+2)[si]
|
||||
push cpb_name[si]
|
||||
mov si,cpb_param[si] ; SI=param
|
||||
push di ; qpb_buffer address
|
||||
inc ax ! push ax ; qpb_nmsgs
|
||||
dec ax ! push ax ! push ax ; qpb_addr,flg,net
|
||||
mov dx,sp ! mov di,dx
|
||||
mov ax,ss ! mov ds,ax
|
||||
mov cx,f_qopen
|
||||
push si ! push di ! call osif
|
||||
pop di ! pop si
|
||||
cmp cx,0 ! jne rpl_err
|
||||
mov bx,qpb_qaddr[di]
|
||||
push ds ! mov ds,sysdat
|
||||
test q_flags[bx],qf_rpl ! pop ds
|
||||
jz rpl_err
|
||||
mov cx,f_qread ! mov dx,di
|
||||
push si ! call osif ! pop si
|
||||
cmp cx,0 ! jne rpl_err
|
||||
add sp,16
|
||||
mov dx,si
|
||||
mov ds,u_wrkseg
|
||||
mov es,u_retseg
|
||||
retf
|
||||
rpl_ret: mov ax,es
|
||||
pop es ! pop ds
|
||||
mov u_retseg,ax
|
||||
ret
|
||||
rpl_err:
|
||||
add sp,24
|
||||
pop es ! pop ds
|
||||
mov bx,1 ! mov cx,e_no_queue
|
||||
ret
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* RSP.DEF - Describes the relative offsets of
|
||||
;* data items in the Data Segment of a
|
||||
;* Resident System Process. GENSYS
|
||||
;* links all RSP's together through the
|
||||
;* rsp_link field (segment address ptrs).
|
||||
;* Each RSP is started up as System
|
||||
;* Initialization.
|
||||
;*
|
||||
;* Format: +---+---+---+---+---+---+---+---+
|
||||
;* 00 | link |sdatvar|ncp| reserved |
|
||||
;* +---+---+---+---+---+---+---+---+
|
||||
;* 08 | reserved | CS |reserve|
|
||||
;* +---+---+---+---+---+---+---+---+
|
||||
;* 10 | Process Descriptor |
|
||||
;* +---+---+---+---+---+---+---+---+
|
||||
;* 40 | User Data Area |
|
||||
;* +---+---+---+---+---+---+---+---+
|
||||
;* E0 | RSP data area |
|
||||
;* +---+---+---+---+---+---+---+---+
|
||||
;*
|
||||
;* link - GENSYS links all RSP's through this.
|
||||
;* At system init, this value is filled
|
||||
;* with the SYSDAT segment address
|
||||
;* sdatvar - if non-zero, this is a variable address
|
||||
;* in the SYSDAT area which indicates the
|
||||
;* a value to put into ncopies (ncp).
|
||||
;* ncp - Number of copies - Used by GENSYS to determine
|
||||
;* how many copies of this RSP to generate.
|
||||
;* This number is modified to be the specific
|
||||
;* copy that was generated.
|
||||
;* CS - Used by GENSYS to determine where a shared
|
||||
;* code segment may exist in multiple copy
|
||||
;* RSPs.
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
rsp_top equ 0
|
||||
rsp_link equ word ptr rsp_top
|
||||
rsp_sysdat equ rsp_link
|
||||
rsp_sdatvar equ word ptr rsp_link + word
|
||||
rsp_ncopies equ byte ptr rsp_sdatvar + word
|
||||
rsp_reserved equ rsp_ncopies + byte
|
||||
rsp_md equ 08h
|
||||
rsp_pd equ 10h
|
||||
rsp_uda equ ((rsp_pd+pdlen+0fh)/10h)*10h
|
||||
rsp_bottom equ rsp_uda + ulen
|
||||
@@ -0,0 +1,43 @@
|
||||
include cpyright.def
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* RTM - MP/M-86 or CCP/M Real Time Monitor
|
||||
;*
|
||||
;*****************************************************
|
||||
eject ! include system.def
|
||||
eject ! include modfunc.def
|
||||
eject ! include modtab.def
|
||||
eject ! include xioscb.def
|
||||
eject ! include flg.def
|
||||
eject ! include mem.def
|
||||
eject ! include mpb.def
|
||||
|
||||
eject ! include pd.def
|
||||
eject ! include err.def
|
||||
eject ! include qd.def
|
||||
eject ! include sync.def
|
||||
eject ! include cmdh.def
|
||||
eject ! include apb.def
|
||||
if mpm
|
||||
eject ! include ccb.def
|
||||
endif
|
||||
if ccpm
|
||||
eject ! include vccb.def
|
||||
endif
|
||||
eject ! include rtmif.rtm
|
||||
eject ! include sysent.rtm
|
||||
eject ! include proc.rtm
|
||||
eject ! include dsptch.rtm
|
||||
eject ! include flag.rtm
|
||||
eject ! include que1.rtm
|
||||
eject ! include que2.rtm
|
||||
eject ! include findpd.rtm
|
||||
eject ! include abort.rtm
|
||||
eject ! include patch.cod
|
||||
eject ! include vec.fmt
|
||||
eject ! include uda.fmt
|
||||
eject ! include sysdat.dat
|
||||
eject ! include data.bdo
|
||||
eject ! include xiosdat.fmt ;SUP 5 - DH - 14APR82
|
||||
eject ! end
|
||||
@@ -0,0 +1,90 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* RTM Interface Routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
cseg
|
||||
org 0
|
||||
|
||||
jmp init ;RTM initialization
|
||||
jmp entry ;RTM entry point
|
||||
|
||||
sysdat dw 0 ;SYSDAT segment
|
||||
supervisor equ offset $
|
||||
rw 2 ;SUP entry point
|
||||
|
||||
org 0ch
|
||||
dev_ver db 6 ;development system data version
|
||||
;set in sysdat.fmt
|
||||
|
||||
db 'COPYRIGHT (C) 1982,'
|
||||
db ' DIGITAL RESEARCH '
|
||||
db 'XXXX-0000-'
|
||||
serial db '654321'
|
||||
|
||||
;==== ===========================
|
||||
init: ; RTM module Initialization
|
||||
;==== ===========================
|
||||
|
||||
mov bx,(offset dispatcher) ;init interrupt pdisp
|
||||
mov word ptr [bx],offset fdisp
|
||||
mov word ptr 2[bx],cs
|
||||
mov bx,(offset rtm_pdisp) ;init intermodule pdisp
|
||||
mov word ptr [bx],offset farpdisp
|
||||
mov word ptr 2[bx],cs
|
||||
retf
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* RTM Function Table
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
org ((offset $)+1) AND 0fffeh ;Word Boundary
|
||||
|
||||
function dw sysreset_entry ;0
|
||||
dw poll_entry ;1
|
||||
dw flag_wait_entry ;2
|
||||
dw flag_set_entry ;3
|
||||
dw makeq_entry ;4
|
||||
dw openq_entry ;5
|
||||
dw deleteq_entry ;6
|
||||
dw readq_entry ;7
|
||||
dw creadq_entry ;8-conditional readq
|
||||
dw writeq_entry ;9
|
||||
dw cwriteq_entry ;10-conditional writeq
|
||||
dw delay_entry ;11
|
||||
dw dispatch_entry ;12
|
||||
dw terminate_entry ;13
|
||||
dw creat_proc_entry;14
|
||||
dw set_prior_entry ;15
|
||||
dw pd_entry ;16-get PD address
|
||||
dw abort_spec_entry;17-abort process
|
||||
dw sleep_entry ;18
|
||||
dw wakeup_entry ;19
|
||||
dw findpdname_entry;20
|
||||
dw sync_entry ;21
|
||||
dw unsync_entry ;22
|
||||
dw no_abort_entry ;23
|
||||
dw ok_abort_entry ;24
|
||||
dw no_abort_spec_entry ;25
|
||||
; dw flagalloc ;26
|
||||
|
||||
;===== =================
|
||||
entry: ; RTM Entry Point
|
||||
;===== =================
|
||||
xor ch,ch ! shl cx,1 ! mov si,cx
|
||||
call cs:function[si]
|
||||
rtm_ret:retf
|
||||
|
||||
;==== ================
|
||||
osif: ; O.S. Interface
|
||||
;==== ================
|
||||
callf cs:dword ptr .supervisor ! ret
|
||||
|
||||
;====== ================
|
||||
xiosif: ; XIOS Interface
|
||||
;====== ================
|
||||
mov si,mod_entry
|
||||
callf dword ptr xiosmod[si] ! ret
|
||||
@@ -0,0 +1,71 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Shared Memory Routines
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;===========
|
||||
share_entry: ; share memory
|
||||
;===========
|
||||
; input: DX->SPB in u_wrkseg
|
||||
;
|
||||
; +-----+-----+-----+-----+-----+-----+
|
||||
; SPB | OPD | RPD | START |
|
||||
; +-----+-----+-----+-----+-----+-----+
|
||||
;
|
||||
|
||||
; Obtain new MD
|
||||
|
||||
push dx ! call getmd ! pop dx
|
||||
jcxz se_c
|
||||
jmp se_err2
|
||||
se_c: mov bp,bx ; BP = New MD
|
||||
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov di,dx ! mov bx,spb_opd[di] ; BX = Owner PD
|
||||
mov si,spb_rpd[di] ; SI = Requestor PD
|
||||
mov dx,spb_start[di] ; DX = start paragraph
|
||||
pop ds
|
||||
|
||||
cmp bx,0 ! jne se_r
|
||||
mov bx,rlr
|
||||
se_r: cmp si,0 ! jne se_s
|
||||
mov si,rlr
|
||||
se_s: cmp si,bx ! je se_ge
|
||||
|
||||
lea di,(p_mem-ms_link)[bx]
|
||||
se_go: mov di,ms_link[di]
|
||||
cmp di,0 ! je se_err
|
||||
cmp ms_start[di],dx ! jne se_go
|
||||
|
||||
; DI = Owner MS to share
|
||||
; SI = Requestor PD
|
||||
; DX = Start
|
||||
; BP = New MD
|
||||
mov bx,bp
|
||||
mov ms_start[bx],dx
|
||||
mov ax,ms_length[di] ! mov ms_length[bx],ax
|
||||
mov ax,ms_flags[di] ! mov ms_flags[bx],ax
|
||||
mov ax,ms_mau[di] ! mov ms_mau[bx],ax
|
||||
mov di,bx ! mov bx,ax
|
||||
push ds ! mov ds,m_start[bx]
|
||||
sub bx,bx ! mov cl,.0
|
||||
se_n: cmp cl,0 ! je se_err1
|
||||
add bx,satlen ! dec cl
|
||||
cmp sat_start[bx],dx ! jne se_n
|
||||
inc sat_nall[bx]
|
||||
; place new MS on RPD p_mem
|
||||
pop ds ! lea bx,p_mem[si]
|
||||
mov dx,ms_mau[di]
|
||||
se_m: mov si,ms_link[bx]
|
||||
cmp si,0 ! je se_link
|
||||
cmp dx,ms_mau[si] ! je se_link
|
||||
mov bx,si ! jmps se_m
|
||||
se_link: mov ms_link[di],si
|
||||
|
||||
mov ms_link[bx],di
|
||||
jmps se_ge
|
||||
se_err1: pop ds ! mov bx,bp ! call freemd
|
||||
se_err: mov cx,e_no_memory
|
||||
se_err2: mov bx,0ffffh ! ret
|
||||
se_ge: sub bx,bx ! mov cx,bx ! ret
|
||||
@@ -0,0 +1,47 @@
|
||||
include cpyright.def
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MP/M or CCP/M Supervisor Module
|
||||
;*
|
||||
;*****************************************************
|
||||
eject ! include system.def
|
||||
eject ! include modfunc.def
|
||||
eject ! include modtab.def
|
||||
eject ! include xioscb.def
|
||||
eject ! include pd.def
|
||||
eject ! include err.def
|
||||
eject ! include qd.def
|
||||
eject ! include fcb.def
|
||||
eject ! include acb.def
|
||||
eject ! include enttab.def
|
||||
eject ! include mem.def
|
||||
eject ! include mpb.def
|
||||
eject ! include clicb.def
|
||||
eject ! include rsp.def
|
||||
eject ! include pcb.def
|
||||
eject ! include cmdh.def
|
||||
eject ! include char.def
|
||||
|
||||
if ccpm
|
||||
eject ! include vccb.def
|
||||
endif
|
||||
eject ! include init.sup
|
||||
eject ! include supif.sup
|
||||
eject ! include sysfunc.sup
|
||||
|
||||
eject ! include command.sup
|
||||
eject ! include load.sup
|
||||
eject ! include parse.sup
|
||||
eject ! include rpl.sup
|
||||
eject ! include patch.cod
|
||||
eject ! include basep.fmt
|
||||
eject ! include lstk.fmt
|
||||
eject ! include vec.fmt
|
||||
eject ! include uda.fmt
|
||||
eject ! include sysdat.dat
|
||||
eject ! include data.bdo
|
||||
if ccpm
|
||||
eject ! include xiosdat.fmt
|
||||
endif
|
||||
eject ! end
|
||||
@@ -0,0 +1,292 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* SUPERVISOR INTERFACE ROUTINES
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;=========
|
||||
user_entry:
|
||||
;=========
|
||||
; User Entry Point - enter here from a INT 224
|
||||
;
|
||||
; REGISTER USAGE
|
||||
; ENTRY EXIT
|
||||
; ----- ----
|
||||
; CL - Function Code AX - Copy of BX
|
||||
; DX - Param BX - Return
|
||||
; DS - Seg Addr CX - Error Code
|
||||
; ES - Segment Return
|
||||
;
|
||||
; DS,SI,DI,BP preserved through call
|
||||
;
|
||||
; SETUP FOR MPM ENVIRONMENT
|
||||
; -------------------------
|
||||
; contents of users stack
|
||||
; Flags
|
||||
; CS
|
||||
; IP <- u_stack_ss,_sp
|
||||
; DS = Sysdat Segment
|
||||
; ES -> user_data_area (UDA)
|
||||
; DX -> function parameter
|
||||
; u_wrkseg == user's DS
|
||||
; u_retseg == user's ES
|
||||
;interrupts are off
|
||||
|
||||
;set up MPM,CCPM environment
|
||||
cld ! mov ax,ds ;AX = user's DS
|
||||
mov ds,sysdat
|
||||
mov bx,rlr
|
||||
mov ds,p_uda[bx] ;DS = UDA segment
|
||||
mov ds:u_retseg,es ;save user's ES
|
||||
|
||||
;U_INSYS is count of times
|
||||
;through this entry point
|
||||
cmp ds:u_insys,0 ! jne noswt ;change stacks to UDA stack
|
||||
;if U_INSYS = 0
|
||||
;otherwise leave stack alone
|
||||
|
||||
;U_WRKSEG where is user's entry DS
|
||||
;is saved
|
||||
mov ds:u_wrkseg,ax ;wipe out earlier u_wrkseg
|
||||
mov ds:u_stack_ss,ss
|
||||
mov ds:u_stack_sp,sp
|
||||
mov ax,ds
|
||||
mov ss,ax ! mov sp,ulen ;stack starts at end of UDA
|
||||
jmps uecont
|
||||
noswt:
|
||||
push ds:u_wrkseg ;save current u_wrkseg on UDA stack
|
||||
mov ds:u_wrkseg,ax
|
||||
|
||||
uecont:
|
||||
sti
|
||||
inc ds:u_insys
|
||||
mov ax,ds ! mov es,ax ;register moves are faster than
|
||||
mov ds,sysdat ;push and pop, DS=SYSDAT,ES=UDA
|
||||
push si ! push di ! push bp
|
||||
|
||||
mov u_func,cl ;record function number in UDA
|
||||
xor ch,ch ;call function and do
|
||||
call netchk ;netwrk chk, returns BX, ES, CX
|
||||
|
||||
coret:
|
||||
pop bp ! pop di ! pop si
|
||||
mov ax,es ;setup user's environment and return
|
||||
mov ds,ax ;DS = UDA segment
|
||||
mov es,ds:u_retseg ;restore ES from entry unless
|
||||
;function returns a segment value
|
||||
mov ax,ds:u_wrkseg ;AX = user's entry DS
|
||||
dec ds:u_insys ! jnz nstk ;switch back to user's stack
|
||||
;if U_INSYS = 0
|
||||
cli
|
||||
mov ss,ds:u_stack_ss
|
||||
mov sp,ds:u_stack_sp
|
||||
jmps ueout
|
||||
nstk:
|
||||
pop ds:u_wrkseg ;restore previous U_WRKSEG if not
|
||||
;going back to user's stack
|
||||
ueout: mov ds,ax ;DS = user's entry DS
|
||||
mov ax,bx ;parameter return BX = AX
|
||||
inc ax
|
||||
jz u_err1 ;CX=error code if AX,BX=0FFFFH
|
||||
xor cx,cx ;CX always 0 if no error
|
||||
u_err1:
|
||||
dec ax
|
||||
iret ;back to user ...
|
||||
;restore interrupts as they
|
||||
;were on entry
|
||||
|
||||
sysfunc: ; call system function
|
||||
;------- -----------------------
|
||||
; entry: if CH <> 0 then CH is module number
|
||||
; (usually 1:SUP, 2:RTM, 3:MEM, 4:CIO, 5:BDOS)
|
||||
; network check is bypassed
|
||||
; if CH = 0 then network check is done
|
||||
; CL = function #
|
||||
; DX = arg
|
||||
; BX = arg
|
||||
; exit: BX = return value
|
||||
; ES = segment return value
|
||||
; CX = error code if BX = 0FFFFH
|
||||
|
||||
test ch,ch ! jz netchk ;network or local
|
||||
mov ax,cx ! jmps localfunc ;in local module
|
||||
|
||||
|
||||
illfunc: ;illegal function number
|
||||
|
||||
jmp i_ent
|
||||
|
||||
netchk:
|
||||
; enter here for network check
|
||||
; check for function numbers represented in function table,
|
||||
; ENTTAB_TABLE. Table space is saved by making the functions
|
||||
; contiguous as we check the range.
|
||||
; The table has entries for functions 0-69, 98-112, 128-164.
|
||||
; Numbers 70-97, 112-127, 165-255 are not in the table.
|
||||
; Illegal functions in this table return the error codes
|
||||
; not implemented (1) or illegal function number (2).
|
||||
; Function not in the table return the illegal function number
|
||||
|
||||
; code.
|
||||
; To add a new user function modify the files SYSDAT.DAT and
|
||||
; MODFUNC.DEF as well as the ranges immediately
|
||||
; below. All of the modules SUP,RTM,MEM,CIO,BDOS,SYSDAT must
|
||||
; then be reassembled.
|
||||
|
||||
cmp cl,69 ! jbe okfunc
|
||||
sub cl,28 ! cmp cl,70 ! jb illfunc ;98-112 are now 70-84
|
||||
cmp cl,84 ! jbe okfunc ;128-164 are now 100-136
|
||||
sub cl,15 ;128-164 are now 85-121
|
||||
cmp cl,121 ! ja illfunc
|
||||
|
||||
okfunc: ;CL is now 0 - num entries
|
||||
;- 1 in entry table
|
||||
mov si,cx ! shl si,1 ;times 2 for entry table
|
||||
add si,offset sysent ;AH high nibble flags
|
||||
mov ax,enttab_entry[si] ;AH low nibble module
|
||||
;AL function number
|
||||
;within module
|
||||
test ah,ef_network ! jz localfunc ;not a network function
|
||||
and ah,not ef_network ;turn off network bit
|
||||
mov al,module_map
|
||||
test al,netmod_bit ! je localfunc ;network module is not there
|
||||
push ax
|
||||
callf dword ptr .netmod ;call network CL = func
|
||||
cmp al,true ;if AL=0FFH do func locally
|
||||
pop ax ;in addition over network
|
||||
jne localfunc
|
||||
mov ax,bx ! ret
|
||||
|
||||
|
||||
localfunc: ;not over the network
|
||||
cmp ah,sup ! je insup ;AH=module, AL=function
|
||||
mov cl,ah
|
||||
mov ch,module_map ! shr ch,cl ;does module exist ?
|
||||
jnc badmod
|
||||
xor ch,ch ! dec cx ;make module 0 relative
|
||||
shl cx,1 ! shl cx,1 ! shl cx,1 ;* 8
|
||||
mov si,cx ! mov cl,al ;func # in CL
|
||||
callf dword ptr module_table[si]
|
||||
ret
|
||||
badmod:
|
||||
jmp n_imp
|
||||
insup:
|
||||
xor ah,ah
|
||||
shl ax,1 ! mov si,ax ; mov cx,ax
|
||||
jmp cs:supfunc[si]
|
||||
|
||||
|
||||
;=====
|
||||
entry: ; Supervisor module entry point
|
||||
;===== -------------------------------
|
||||
;
|
||||
; Arrive here usually on a CALLF using address
|
||||
; at SYSDAT:4. Note: flag set is handled specially.
|
||||
;
|
||||
; entry: if CH <> 0 then CH is module number
|
||||
; (usually 1:SUP, 2:RTM, 3:MEM, 4:CIO, 5:BDOS)
|
||||
; network check is bypassed
|
||||
; if CH = 0 then network check is done;
|
||||
; CL = function #. If CH = 0 then CL is treated
|
||||
; as a function number used with an INT 224:
|
||||
; it is a USER function.
|
||||
; If CH is not 0 then CL is the function number
|
||||
; within the module specified by CH.
|
||||
; The file MODFUNC.DEF contains the equates
|
||||
; used for accessing functions from within the O.S.
|
||||
; These functions are INTERNAL functions.
|
||||
; Note the INTERNAL functions are a superset of
|
||||
; the USER functions. The equates for USER
|
||||
; functions in MODFUNC.DEF have a 0 for the high byte
|
||||
; forcing network checking from this entry point.
|
||||
; An example: if f_conin (from MODFUNC.DEF) is
|
||||
; equal to 0001H. A Console output call to this
|
||||
; entry point thus result in CH = 0, CL = 1.
|
||||
; DX = arg
|
||||
; BX = arg
|
||||
;
|
||||
; exit: BX = return value
|
||||
; ES = segment return value
|
||||
; CX = error code if BX = 0FFFFH
|
||||
|
||||
|
||||
|
||||
cmp cx,f_flagset ! jne notfs ;flag set is exception:
|
||||
mov cx,f_inflagset ;do not go over network,
|
||||
call sysfunc ;make path shorter,
|
||||
mov ax,bx ;parameter return BX = AX
|
||||
inc ax ;AX=0FFFFH if error
|
||||
jz u_err2 ;CX= error code if AX,BX=0FFFFH
|
||||
xor cx,cx ;CX=0 if no error
|
||||
u_err2:
|
||||
dec ax ;set AX back to 0 or 0FFFFH
|
||||
retf ;DS must equal system
|
||||
notfs: ;data segment
|
||||
|
||||
mov u_unused,cx ;save 16 bit function number
|
||||
call osif ! retf
|
||||
|
||||
osif: ;point SUP uses to get
|
||||
;to other modules
|
||||
push u_wrkseg ;save current u_wrkseg
|
||||
mov ax,ds
|
||||
mov u_wrkseg,ax
|
||||
mov ax,sysdat
|
||||
mov ds,ax
|
||||
call sysfunc
|
||||
mov ax,u_wrkseg
|
||||
mov ds,ax
|
||||
pop u_wrkseg
|
||||
mov ax,bx ;BX,CX are return codes
|
||||
inc ax ;AX=0FFFFH if error
|
||||
jz u_err3 ;CX= error code if AX,BX=0FFFFH
|
||||
xor cx,cx ;CX=0 if no error
|
||||
u_err3:
|
||||
dec ax ;set AX back to 0 or 0FFFFH
|
||||
ret
|
||||
|
||||
|
||||
;=========
|
||||
user_retf:
|
||||
;=========
|
||||
; If a user process does a RETF to terminate,
|
||||
; the process ends here. The Load function sets up
|
||||
; the default stack to point here.
|
||||
|
||||
mov bx,rlr
|
||||
and p_flag[bx],not pf_keep+pf_tempkeep+pf_ctlc+pf_sys
|
||||
mov cx,f_terminate
|
||||
xor dx,dx
|
||||
int osint ;make sure the terminate
|
||||
;succeed by reseting the
|
||||
;the keep,tempkeep,ctlc,sys flags
|
||||
|
||||
;======
|
||||
xiosif:
|
||||
;======
|
||||
callf dword ptr .xiosmod ! ret
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Supervisor function table
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
org ((offset $)+1) AND 0fffeh ;Word Boundary
|
||||
|
||||
supfunc dw n_imp ; 0-not implemented
|
||||
dw i_ent ; 1-illegal function number
|
||||
dw bver_ent ; 2-(12)get BDOS version
|
||||
dw cbios_ent ; 3-(50)call bios
|
||||
dw load_ent ; 4-(59)user load function
|
||||
dw cli_ent ; 5-(150)CLI
|
||||
dw rpl_ent ; 6-(151)Call RPL
|
||||
dw parse_ent ; 7-(152)parse filename
|
||||
dw sdat_ent ; 8-(154)get sysdat addr
|
||||
dw tod_ent ; 9-(155)get tod addr
|
||||
dw load ; 10-load function
|
||||
dw over_ent ; 11-O.S. version number
|
||||
dw chain_ent ; 12-(47)Program Chain
|
||||
dw ser_ent ; 13-(107)return serial
|
||||
dw cload_ent ; 14-chain load function
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
;********************************************************
|
||||
; *
|
||||
; Sync Parameter Block *
|
||||
; *
|
||||
;********************************************************
|
||||
|
||||
sy_link equ word ptr 0
|
||||
sy_owner equ word ptr sy_link + 2
|
||||
sy_wait equ word ptr sy_owner + 2
|
||||
sy_next equ word ptr sy_wait + 2
|
||||
synclen equ sy_next + 2
|
||||
@@ -0,0 +1,14 @@
|
||||
eject ! include cpyright.def
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* System Data Area - Initialized Data
|
||||
;*
|
||||
;*****************************************************
|
||||
eject ! include system.def
|
||||
eject ! include pd.def
|
||||
eject ! include uda.def
|
||||
eject ! include qd.def
|
||||
eject ! include modfunc.def
|
||||
eject ! include sysdat.dat
|
||||
eject ! include data.bdo
|
||||
@@ -0,0 +1,540 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* System Data Area
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
CSEG
|
||||
org 0ch
|
||||
;dev_ver
|
||||
db 6 ;development system data version
|
||||
;SYSDAT.CON has 16 byte code segment
|
||||
|
||||
DSEG
|
||||
org 0
|
||||
|
||||
;
|
||||
;This data is initialized by GENCCPM
|
||||
;
|
||||
|
||||
;Module Table - contains the FAR CALL addresses
|
||||
; of each module for their initialization
|
||||
; and entry routines.
|
||||
;
|
||||
; +---+---+---+---+---+---+---+---+
|
||||
; | entry | initialize |
|
||||
; +---+---+---+---+---+---+---+---+
|
||||
;
|
||||
; entry init
|
||||
; ----- ----
|
||||
|
||||
module_table equ dword ptr (offset $)
|
||||
supmod equ (offset $)
|
||||
dw 3,0, 0,0 ;SUP
|
||||
|
||||
rtmmod equ (offset $)
|
||||
dw 3,0, 0,0 ;RTM
|
||||
|
||||
memmod equ (offset $)
|
||||
|
||||
dw 3,0, 0,0 ;MEM
|
||||
|
||||
ciomod equ (offset $)
|
||||
dw 3,0, 0,0 ;CIO
|
||||
|
||||
bdosmod equ (offset $)
|
||||
dw 3,0, 0,0 ;BDOS
|
||||
|
||||
xiosmod equ (offset $)
|
||||
dw 0C03H,0, 0C00H,0 ;XIOS
|
||||
|
||||
netmod equ (offset $)
|
||||
dw 3,0, 0,0 ;NET
|
||||
|
||||
dispatcher equ (offset $)
|
||||
dw 0,0 ;far dispatcher (does IRET)
|
||||
|
||||
rtm_pdisp equ (offset $)
|
||||
dw 0,0 ;far dispatcher (does RETF)
|
||||
|
||||
; location in memory of MP/M-86 or CCP/M-86
|
||||
|
||||
osseg dw 1008h ;1st parag. of MP/M-86 or CCP/M
|
||||
rspseg dw 0 ;segment of first RSP
|
||||
endseg dw 0 ;1st parag. outside of MP/M or CCP/M
|
||||
|
||||
module_map db 03fh ;bit map of modules that exist
|
||||
; in this system. low order bit
|
||||
; corresponds to 1st module in
|
||||
; module table. If bit is on,then
|
||||
; module exists.
|
||||
|
||||
; some answers to GENCCPM questions
|
||||
|
||||
ncns db 4 ;# system console devices
|
||||
nlst db 1 ;# system list devices
|
||||
nccb db 5 ;# character control blocks
|
||||
nflags db 20h ;# flags
|
||||
srchdisk db 1 ;system disk
|
||||
mmp dw 04000h ;Max Memory per process
|
||||
nslaves db 0 ;Number of network requestors
|
||||
dayfile db 0 ;if 0ffh,display command info
|
||||
tempdisk db 1 ;Temporary disk
|
||||
tickspersec db 60 ;Number of ticks per second
|
||||
|
||||
; data lists created by GENCCPM
|
||||
|
||||
free_root dw 0 ;locked unused list
|
||||
ccb dw 0 ;addr. Console Ctrl Blk Table
|
||||
flags dw 0 ;addr. Flag Table
|
||||
mdul dw 020h ;Mem descr. Unused List
|
||||
mfl dw 0 ;Memory Free List
|
||||
pul dw 014h ;Proc. descr. Unused List
|
||||
qul dw 020h ;QCB Unused List
|
||||
;MAU for queue buffer info
|
||||
qmau dw 0 ;link
|
||||
dw 0 ;start segment
|
||||
dw 400h ;length
|
||||
dw 0 ;plist
|
||||
|
||||
;
|
||||
;This data is initialized at Assembly time
|
||||
;
|
||||
|
||||
rlr dw initpd ;Ready List Root
|
||||
dlr dw 0 ;Delay List Root
|
||||
drl dw 0 ;Dispatcher Ready List
|
||||
plr dw 0 ;Poll List Root
|
||||
scl dw 0 ;Shared Code List
|
||||
thrdrt dw initpd ;Process Thread Root
|
||||
qlr dw mxloadqd;Queue List Root
|
||||
mal dw 0 ;Memory Alloc List
|
||||
|
||||
; Version Information
|
||||
|
||||
version dw unknown ;addr. version str in SUP code segment
|
||||
;set by GENCCPM if CCP/M
|
||||
if mpm
|
||||
bvernum dw 01130h ;MPM-86 w/BDOS v3.0
|
||||
osvernum dw 01121h ;MPM-86 V2.1
|
||||
endif
|
||||
|
||||
if ccpm
|
||||
bvernum dw 01431h ;CCP/M w/BDOS 3.1
|
||||
osvernum dw 01420h ;CCP/M V2.0
|
||||
endif
|
||||
|
||||
; Time of Day Structure
|
||||
|
||||
tod rw 0
|
||||
tod_day dw 067EH ;day since 1/1/78 (09 Jul 82)
|
||||
tod_hr db 12h ;hour of day
|
||||
tod_min db 00h ;minute of hour
|
||||
tod_sec db 00h ;second of minute
|
||||
|
||||
; info from XIOS
|
||||
|
||||
ncondev db 0 ;# console devs in XIOS
|
||||
nlstdev db 0 ;# character devs in XIOS
|
||||
nciodev db 0 ;# character i/o devices
|
||||
; supported by XIOS.
|
||||
lcb dw 0 ; list control block address
|
||||
openvec dw 0 ; open file vector
|
||||
lock_max db 20h ; Max Locked Records/process
|
||||
open_max db 20h ; Max Open Files/process
|
||||
owner8087 dw 0 ; no one owns it initially
|
||||
rw 1 ; RESERVED
|
||||
cmod db 0ffh ; BDOS Compatibility
|
||||
ndp8087 db false ; true 8087 exits
|
||||
; (Numeric Data Processor)
|
||||
err_intercept dw 0,0 ; BDOS does a callf here
|
||||
; to print error msgs,
|
||||
; if second word is <> 0
|
||||
slr dw offset mem_spb ; Sync List Root
|
||||
dw 0,0,0,0 ; RESERVED
|
||||
|
||||
|
||||
; SYSENT Table - MP/M-86, CCP/M-86 system function information
|
||||
; The supervisor calls the appropriate module
|
||||
; through this table.
|
||||
;
|
||||
; Low Byte High Byte
|
||||
; +----+----+--------+
|
||||
; |function |flgs|mod|
|
||||
; +----+----+--------+
|
||||
;
|
||||
; flgs - 001h - network intercept
|
||||
; if on, the network module is called
|
||||
; first, on return, either the function
|
||||
; is called or it is considered complete
|
||||
; depending on the return.
|
||||
; mod - module number (0-15)
|
||||
; function- function to call within module
|
||||
|
||||
; note: sup function 0 returns not the
|
||||
; implemented error code to the caller,
|
||||
; and sup function 1 returns the illegal
|
||||
; function error code.
|
||||
|
||||
; standard CPM-2 functions
|
||||
|
||||
; func, module
|
||||
|
||||
org ((offset $) + 1) and 0fffeh
|
||||
|
||||
sysent db 0, rtm ; 0-system reset
|
||||
db 0, cio ; 1-conin
|
||||
db 1, cio ; 2-conout
|
||||
db 0, sup ; 3-raw conin/aux in
|
||||
db 0, sup ; 4-raw conout/aux out
|
||||
db 4, cio ; 5-list out
|
||||
db 5, cio ; 6-raw conio
|
||||
db 0, sup ; 7-getiobyte
|
||||
db 0, sup ; 8-setiobyte
|
||||
db 6, cio ; 9-conwrite
|
||||
db 7, cio ; 10-conread
|
||||
db 8, cio ; 11-constat
|
||||
db 2, sup ; 12-get version
|
||||
db 0, bdos ; 13-diskreset
|
||||
db 1, bdos ; 14-diskselect
|
||||
db 2, bdos ; 15-file open
|
||||
db 3, bdos ; 16-file close
|
||||
db 4, bdos ; 17-search first
|
||||
db 5, bdos ; 18-search next
|
||||
db 6, bdos ; 19-file delete
|
||||
db 7, bdos ; 20-file read seq
|
||||
db 8, bdos ; 21-file write seq
|
||||
db 9, bdos ; 22-file make
|
||||
db 10, bdos ; 23-file rename
|
||||
db 11, bdos ; 24-login vector
|
||||
db 12, bdos ; 25-get def disk
|
||||
db 13, bdos ; 26-set dma
|
||||
db 14, bdos ; 27-get alloc vector
|
||||
db 15, bdos ; 28-write protect
|
||||
db 16, bdos ; 29-get r/0 vector
|
||||
db 17, bdos ; 30-set file attr.
|
||||
db 18, bdos ; 31-get disk parm block
|
||||
db 19, bdos ; 32-user code
|
||||
db 20, bdos ; 33-file read random
|
||||
db 21, bdos ; 34-file write random
|
||||
db 22, bdos ; 35-file size
|
||||
db 23, bdos ; 36-set random record
|
||||
db 24, bdos ; 37-reset drive
|
||||
db 25, bdos ; 38-access drive
|
||||
db 26, bdos ; 39-free drive
|
||||
db 27, bdos ; 40-file write random w/zero fill
|
||||
|
||||
;CPM-3 extensions
|
||||
|
||||
db 0, sup ; 41-Test and Write (NOT IMPLEMENTED)
|
||||
; Would be BDOS func # 28
|
||||
db 28, bdos ; 42-Lock Record
|
||||
db 29, bdos ; 43-Unlock Record
|
||||
db 30, bdos ; 44-Set Multi-sector
|
||||
db 31, bdos ; 45-Set Bdos Error Mode
|
||||
db 32, bdos ; 46-Get Disk Free Space
|
||||
db 12, sup ; 47-Chain to Program
|
||||
; In CP/M-86 BDOS func # 34
|
||||
db 33, bdos ; 48-Flush Buffers
|
||||
db 1, sup ; 49-
|
||||
|
||||
;CPM-86 extensions
|
||||
|
||||
db 3, sup ; 50-call xios
|
||||
db 34, bdos ; 51-set dma base
|
||||
db 35, bdos ; 52-get dma
|
||||
db 0, mem ; 53-get max mem
|
||||
db 1, mem ; 54-get abs max mem
|
||||
db 2, mem ; 55-alloc mem
|
||||
db 3, mem ; 56-alloc abs mem
|
||||
db 4, mem ; 57-free mem
|
||||
db 5, mem ; 58-free all mem
|
||||
db 4, sup ; 59-load
|
||||
db 1, sup ; 60-
|
||||
db 1, sup ; 61-
|
||||
db 1, sup ; 62-
|
||||
db 1, sup ; 63-
|
||||
|
||||
;CP/NET functions
|
||||
|
||||
db 64, net ; 64-network login
|
||||
db 65, net ; 65-network logoff
|
||||
db 66, net ; 66-network send msg
|
||||
db 67, net ; 67-network rcv msg
|
||||
db 68, net ; 68-network status
|
||||
db 69, net ; 69-get network config addr
|
||||
|
||||
;CP/M-3 extensions
|
||||
|
||||
db 36, bdos ; 98-Reset Alloc Vector
|
||||
db 37, bdos ; 99-Truncate File
|
||||
db 38, bdos ;100-Set Dir Label
|
||||
db 39, bdos ;101-Return Dir Label
|
||||
db 40, bdos ;102-Read File XFCB
|
||||
db 41, bdos ;103-Write File XFCB
|
||||
db 42, bdos ;104-Set Date and Time
|
||||
db 43, bdos ;105-Get Date and Time
|
||||
db 44, bdos ;106-Set Default Password
|
||||
db 13, sup ;107-Return Serial Number
|
||||
db 0, sup ;108-(not implemented)
|
||||
db 25, cio ;109-Get/Set Console Mode
|
||||
db 26, cio ;110-Get/Set Output Delimiter
|
||||
db 27, cio ;111-Print Block
|
||||
db 28, cio ;112-List Block
|
||||
|
||||
; MP/M functions
|
||||
|
||||
db 6, mem ;128-mem req
|
||||
db 6, mem ;129-(same function as 128)
|
||||
db 7, mem ;130-mem free
|
||||
db 1, rtm ;131-poll device
|
||||
db 2, rtm ;132-flag wait
|
||||
db 3, rtm ;133-flag set
|
||||
db 4, rtm ;134-queue make
|
||||
db 5, rtm ;135-queue open
|
||||
db 6, rtm ;136-queue delete
|
||||
db 7, rtm ;137-queue read
|
||||
db 8, rtm ;138-cond. queue read
|
||||
db 9, rtm ;139-queue write
|
||||
db 10, rtm ;140-cond. queue write
|
||||
db 11, rtm ;141-delay
|
||||
db 12, rtm ;142-dispatch
|
||||
db 13, rtm ;143-terminate
|
||||
db 14, rtm ;144-create process
|
||||
db 15, rtm ;145-set priority
|
||||
db 9, cio ;146-console attach
|
||||
db 10, cio ;147-console detach
|
||||
db 11, cio ;148-set def console
|
||||
db 12, cio ;149-console assign
|
||||
db 5, sup ;150-CLI
|
||||
db 6, sup ;151-call RPL
|
||||
db 7, sup ;152-parse filename
|
||||
db 13, cio ;153-get def console
|
||||
db 8, sup ;154-sysdat addr
|
||||
db 9, sup ;155-time of day
|
||||
db 16, rtm ;156-get PD addr
|
||||
db 17, rtm ;157-abort process
|
||||
|
||||
; MPM II extensions
|
||||
|
||||
db 15, cio ;158-attach list
|
||||
db 16, cio ;159-detach list
|
||||
db 17, cio ;160-set list dev
|
||||
db 18, cio ;161-Cond. Attach list
|
||||
db 19, cio ;162-Cond. Attach Console
|
||||
db 11, sup ;163-MP/M Version Number
|
||||
db 20, cio ;164-get list dev
|
||||
|
||||
|
||||
; Initialized Queues
|
||||
|
||||
org ((offset $) + 1) and 0fffeh
|
||||
|
||||
mxloadqd dw mxdiskqd
|
||||
db 0,0
|
||||
dw qf_keep+qf_mx
|
||||
db 'MXLoad '
|
||||
dw 0,1,0,0,1,0,0
|
||||
mxloadqpb db 0,0
|
||||
dw mxloadqd,1,0
|
||||
; db 'MXLoad '
|
||||
|
||||
; Data Used by Load Program
|
||||
|
||||
org ((offset $) + 1) and 0fffeh
|
||||
|
||||
lod_uda dw 0
|
||||
lod_lstk dw 0
|
||||
lod_basep dw 0
|
||||
lod_nldt dw 0
|
||||
lod_pd dw 0
|
||||
lod_fcb rs 36
|
||||
lod_indma dw 0
|
||||
lod_nrels db 0
|
||||
lod_chain db 0
|
||||
lod_user db 0
|
||||
lod_disk db 0
|
||||
lod_fifty db 0
|
||||
lod_8080 db 0
|
||||
lod_lbyte db 0
|
||||
lod_fixrec dw 0
|
||||
lod_fixrec1 dw 0
|
||||
lod_dma rb dskrecl
|
||||
ldtab rb ldtabsiz
|
||||
|
||||
cli_dma_ofst rw 1
|
||||
cli_dma_seg rw 1
|
||||
cli_pflag rw 1
|
||||
cli_chain rb 1
|
||||
cli_term rb 1
|
||||
cli_dma rb dskrecl ;dma buffer
|
||||
|
||||
;copy of user's clicb
|
||||
cli_net rb 1 ;net
|
||||
cli_ppd rw 1 ;parent PD
|
||||
cli_cmdtail rb 129 ;command sent
|
||||
rb 1
|
||||
|
||||
cli_fcb rb fcblen+1 ;internal FCB
|
||||
|
||||
cli_cuspqpb db 0,0 ;QPB of command
|
||||
dw 0,0
|
||||
dw offset cli_ppd
|
||||
db '$$$$$$$$'
|
||||
|
||||
cli_acb db 0,0 ;cns,match
|
||||
dw 0 ;pd
|
||||
db '$$$$$$$$' ;name
|
||||
|
||||
cli_pcb dw offset cli_cmdtail ;parse
|
||||
dw offset cli_fcb ;ctl bk
|
||||
|
||||
cli_pd dw 0 ;pd of load prog
|
||||
cli_err dw 0 ;error return
|
||||
cli_bpage dw 0 ;base page
|
||||
cli_lddsk db 1 ;load disk
|
||||
|
||||
;parent information
|
||||
|
||||
cli_cns db 0 ;pd.p_cns save
|
||||
cli_user db 0 ;pd.p_dsk save
|
||||
cli_dsk db 0 ;pd.p_user save
|
||||
cli_err_mode db 0 ;u_error_mode save
|
||||
cli_dfil db 0 ;dayfile flag
|
||||
|
||||
;
|
||||
;System Initialization Variables
|
||||
;
|
||||
|
||||
initpd dw 0 ;link
|
||||
dw 0 ;thread
|
||||
db ps_run ;stat
|
||||
db 1 ;prior
|
||||
dw pf_sys+pf_kernal;flag
|
||||
db 'Init ' ;name
|
||||
dw unknown ;uda segment
|
||||
db 0 ;disk
|
||||
db 0 ;user
|
||||
db 0,0 ;ldsk,luser
|
||||
dw 0 ;mem
|
||||
dw 0 ;dvract
|
||||
dw 0 ;wait
|
||||
db 0,0 ;org,net
|
||||
dw 0 ;parent
|
||||
db 0 ;cns
|
||||
db 0 ;abort
|
||||
db 0,0 ;cin,cout
|
||||
db 0 ;lst
|
||||
db 0,0,0 ;sf3,4,5
|
||||
rb 4 ;reserved
|
||||
dw 0,0 ;pret,scratch
|
||||
|
||||
|
||||
;User Data Area of Init process
|
||||
;paragraph aligned
|
||||
|
||||
org ((offset $)+0fh) AND 0fff0h
|
||||
inituda rb ulen
|
||||
init_tos rw 0
|
||||
org offset inituda + ud_insys
|
||||
db 1 ;keep the SUP from doing stack
|
||||
|
||||
org offset init_tos ;switches
|
||||
|
||||
|
||||
; RTM data
|
||||
; is word aligned from init uda
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
dsptchtos rw 0
|
||||
|
||||
indisp db false ;?currently in dispatch?
|
||||
intflag db 0 ;if 0, interrupts not enabled -
|
||||
;not implemented
|
||||
es_sav dw 0 ;(staying word aligned)
|
||||
bx_sav dw 0
|
||||
ax_sav dw 0
|
||||
|
||||
; MEM Data
|
||||
|
||||
beststart dw 0
|
||||
bestlen dw 0
|
||||
bestsi dw 0
|
||||
bestmau dw 0
|
||||
currmau dw 0
|
||||
currsi dw 0
|
||||
currmpb dw 0,0,0,0,0
|
||||
|
||||
|
||||
; SYNC Parameter Blocks
|
||||
|
||||
; The MEM ENTRY: point uses the following for
|
||||
; mutual exclusion and recursion.
|
||||
|
||||
mem_cnt db 0 ;how many times a process has recursivly
|
||||
;called the memory manager
|
||||
|
||||
mem_spb dw q_spb ;link Mem Sync Parameter Block
|
||||
dw 0 ;owner
|
||||
dw 0 ;wait
|
||||
dw 0 ;next
|
||||
|
||||
; The queue sub-system in the RTM uses the following
|
||||
; structure for mutual exclusion
|
||||
|
||||
q_spb dw cli_spb ;link Queue Sync Parameter Block
|
||||
dw 0 ;owner
|
||||
dw 0 ;wait
|
||||
|
||||
dw 0 ;next
|
||||
|
||||
|
||||
; The CLI uses the CLI_SPB for mutual exclusion
|
||||
|
||||
cli_spb dw thrd_spb;link CLI Sync Parameter Block
|
||||
dw 0 ;owner
|
||||
dw 0 ;wait
|
||||
dw 0 ;next
|
||||
|
||||
; When the thread is accessed, the THRD_SPB must be owned
|
||||
; first.
|
||||
|
||||
thrd_spb dw msg_spb ;link Thread Sync Parameter Block
|
||||
dw 0 ;owner
|
||||
dw 0 ;wait
|
||||
dw 0 ;next
|
||||
|
||||
; Currently the order in which the SYNCs must be obtained if
|
||||
; more than one is needed is:
|
||||
|
||||
; CLI
|
||||
; QUEUE ;called by CLI for RSPs
|
||||
; MEM ;called by make queue
|
||||
; THREAD ;used from the MEM module
|
||||
|
||||
; The SYNCs must be released in reverse order
|
||||
; MSG_SPB is used by the BDOS to protect the BDOS error message
|
||||
; buffer. MSG_SPB is in DATA.BDO
|
||||
@@ -0,0 +1,297 @@
|
||||
;********************************************************
|
||||
;* *
|
||||
;* SYSTEM ENTRY FUNCTIONS *
|
||||
;* *
|
||||
;********************************************************
|
||||
|
||||
;========== =========================
|
||||
poll_entry: ; Poll device - DL=device
|
||||
;========== =========================
|
||||
|
||||
mov ax,rlr
|
||||
mov bx,ax
|
||||
mov p_wait[bx],dx
|
||||
mov dx,offset plr
|
||||
mov bl,ps_poll
|
||||
jmp sleep_entry
|
||||
|
||||
;=========== ===================
|
||||
delay_entry: ;Delay - DX = ticks
|
||||
;=========== ===================
|
||||
|
||||
mov bx,rlr
|
||||
mov p_stat[bx],ps_delay
|
||||
mov u_dparam,dx
|
||||
xor bx,bx ;return success after coming back into
|
||||
jmp dsptch ;context from the dispatcher
|
||||
|
||||
;=============== ==============
|
||||
dispatch_entry: ;Call dispatch
|
||||
;=============== ==============
|
||||
|
||||
xor bx,bx ;return success ala DELAY_ENTRY:
|
||||
jmp pdisp
|
||||
|
||||
;=============== ===========================
|
||||
set_prior_entry: ;Set Priority - DX=priority
|
||||
;=============== ===========================
|
||||
|
||||
mov bx,rlr
|
||||
mov p_prior[bx],dl
|
||||
xor bx,bx ;return success ala DELAY_ENTRY:
|
||||
jmp pdisp
|
||||
|
||||
;======== ==================
|
||||
pd_entry: ;Return addr of PD
|
||||
;======== ==================
|
||||
|
||||
mov u_retseg,ds
|
||||
mov bx,rlr
|
||||
ret
|
||||
|
||||
;================ ============================
|
||||
creat_proc_entry: ;Create Process - DX->new PD
|
||||
;================ ============================
|
||||
|
||||
call proc_creat ! jmp pdisp
|
||||
|
||||
;=========== ==============================
|
||||
sleep_entry: ;Put Calling PD on System List
|
||||
;=========== ==============================
|
||||
; entry: DX = list root to sleep on
|
||||
; BL = sleep status passed to the dispatcher in
|
||||
; the PD.P_WAIT field and becomes the PD.STATUS
|
||||
; when sleeping
|
||||
; interrupts are typically off to ensure
|
||||
; the PD sleeps on the specified list
|
||||
; before another process runs.
|
||||
; exit: BX = 0 to indicate success after return from dispatcher
|
||||
; if entered with interrupts off the process will return
|
||||
; from the dispatcher with them still off
|
||||
|
||||
mov ax,rlr ! mov si,ax
|
||||
mov ax,dx ! mov u_dparam,ax
|
||||
mov p_scratch[si],bl
|
||||
mov p_stat[si],ps_sleep
|
||||
xor bx,bx
|
||||
jmp dsptch
|
||||
|
||||
;============ ==============================
|
||||
wakeup_entry: ;wakeup top PD in System List
|
||||
;============ ==============================
|
||||
; entry: DX = List Root Address
|
||||
; exit: first PD on list is the last entry on the DRL
|
||||
|
||||
|
||||
; Puting the process on the end of the DRL allows the
|
||||
; process to run before equal priority processes waking up
|
||||
; from flag sets, i.e., interrupts.
|
||||
; To work, the dispatcher must disable interrupts
|
||||
; from when the last process on the DRL is placed on the
|
||||
; RLR to when the process is back in context and
|
||||
; turns on the interrupt flag.
|
||||
|
||||
pushf ! cli
|
||||
mov bx,dx ! mov si,[bx] ;SI=PD to wake
|
||||
test si,si ! jz wke_out ;check for a process to wake up
|
||||
mov ax,p_link[si] ;take PD off list
|
||||
mov [bx],ax ;set list root to next PD
|
||||
mov di,offset drl - p_link ;go to the end of DRL
|
||||
xor ax,ax ;AX=0
|
||||
wu_drl:
|
||||
cmp p_link[di],ax
|
||||
je wu_drlend
|
||||
mov di,p_link[di] ! jmps wu_drl
|
||||
wu_drlend:
|
||||
mov p_link[di],si ;make waking PD last on DRL
|
||||
mov p_link[si],ax ;0 the end of the DRL
|
||||
mov p_stat[si],ps_run ;new status
|
||||
call pdisp
|
||||
wke_out:
|
||||
popf ! ret
|
||||
|
||||
;========== ========================
|
||||
sync_entry: ;Obtain mutual exclusion
|
||||
;========== ========================
|
||||
; entry: interrupts on or off
|
||||
; BX = Sync Parameter Block
|
||||
; exit: ownership of Sync Parameter Block,
|
||||
; interrupt state unchanged
|
||||
|
||||
; Obtain ownership of mutually exclusive section of code
|
||||
; without using MXqueues. A process only sleeps temporarily
|
||||
; on a SYNC structure. A process that obtains the
|
||||
; SYNC must call UNSYNC when finished with the
|
||||
; protected data structure and before sleeping or
|
||||
; calling SYNC with on a different SYNC structure.
|
||||
|
||||
mov ax,rlr
|
||||
mov si,ax ;AX=SI calling process
|
||||
pushf ! cli
|
||||
xchg ax,sy_owner[bx] ;AX=owner
|
||||
test ax,ax ;0 nobody owns it
|
||||
jz s_got_it
|
||||
cmp ax,si ;do we already own it ?
|
||||
je s_got_it
|
||||
mov sy_owner[bx],ax ;restore owner
|
||||
lea dx,sy_wait[bx] ;list to sleep on
|
||||
mov bl,ps_sync ;sleep with sync status
|
||||
call sleep_entry
|
||||
;awaken with sync ownership
|
||||
s_got_it:
|
||||
popf ! ret ;we own the SPB
|
||||
|
||||
|
||||
;============ ==========================
|
||||
unsync_entry: ;release mutual exlclusion
|
||||
;============ ==========================
|
||||
;
|
||||
; entry: BX = Sync Parameter Block
|
||||
; exit: SYNC_OWNER changed to the PD in the SY_NEXT
|
||||
; field if SY_NEXT is non 0. The PD in the SY_NEXT
|
||||
; must have a 0 P_LINK. If SY_NEXT=0, the SY_OWNER
|
||||
; field is changed to the first PD on the SY_WAIT
|
||||
; list. If SY_WAIT is 0, SY_OWNER becomes 0.
|
||||
|
||||
mov ax,rlr
|
||||
cmp ax,sy_owner[bx] ;do we own it ?
|
||||
jne us_ret
|
||||
xor ax,ax
|
||||
pushf ! cli ;no other process can change SYNC or DRL
|
||||
xchg ax,sy_next[bx] ;0 SY_NEXT field
|
||||
test ax,ax ;assigned next process ?
|
||||
jz us_wait
|
||||
mov si,ax
|
||||
jmps us_own
|
||||
us_wait:
|
||||
mov si,sy_wait[bx] ;give the sync to first waiting process
|
||||
test si,si ;no waiting PD ?
|
||||
jz us_zero
|
||||
mov ax,p_link[si]
|
||||
mov sy_wait[bx],ax
|
||||
mov p_link[si],0
|
||||
us_own:
|
||||
mov p_stat[si],ps_run
|
||||
mov ax,drl
|
||||
mov p_link[si],ax ;put process on DRL
|
||||
mov drl,si
|
||||
us_zero:
|
||||
mov sy_owner[bx],si ;SI=0 or process to now own sync
|
||||
popf ;allow interrupts
|
||||
us_ret: ;wait for next dispatch
|
||||
ret
|
||||
|
||||
;================= ============================
|
||||
assign_sync_entry: ;give away mutual exlclusion
|
||||
;================= ============================
|
||||
; interrupts on
|
||||
; entry:
|
||||
; BX = Sync Parameter Block
|
||||
; DX = address of list root, assign
|
||||
; SPB to first PD on list
|
||||
; exit: none
|
||||
;
|
||||
mov ax,rlr
|
||||
cmp sy_owner[bx],ax ;check that we own the resource
|
||||
jne as_ret
|
||||
mov si,dx ;SI=list root
|
||||
pushf ! cli ;no other process can run
|
||||
mov di,[si] ;get first PD from list
|
||||
test di,di ;test for 0 list
|
||||
jz as_done
|
||||
mov ax,p_link[di] ;take PD off list
|
||||
mov [si],ax
|
||||
mov p_link[di],0 ;0 link of NEXT PD
|
||||
;status is still PS_SLEEP.
|
||||
;if TEMPKEEP is on ABORT_SPEC
|
||||
;will just turn on CTLC flag.
|
||||
;if no TEMPKEEP, ABORT_SPEC
|
||||
;will not find PD on the U_DPARAM
|
||||
;list and will fail.
|
||||
|
||||
mov sy_next[bx],di ;see UN_SYNC_ENTRY
|
||||
;for use of SYNC_NEXT field
|
||||
as_done:
|
||||
popf
|
||||
as_ret:
|
||||
ret
|
||||
|
||||
;==============
|
||||
no_abort_entry:
|
||||
;==============
|
||||
; Keep the calling process from being aborted by
|
||||
; using the PF_TEMPKEEP flag.
|
||||
; Turn on the PF_TEMPKEEP flag and
|
||||
; increment the P_TKEEPCNT.
|
||||
|
||||
; entry: none
|
||||
; exit: PD fields altered
|
||||
; interrupt state unaltered
|
||||
|
||||
; This code must be exclusive of ABORT_SPEC's testing
|
||||
; and acting on the PD flags.
|
||||
|
||||
|
||||
mov ax,rlr
|
||||
mov si,ax
|
||||
na_spec:
|
||||
cmp p_tkcnt[si],0
|
||||
jne na_saved
|
||||
test p_flag[si],pf_tempkeep
|
||||
jz na_saved
|
||||
or p_tkcnt[si],80h ;save orignal TEMPKEEP in MSB
|
||||
na_saved: ;until rest of O.S. is fixed
|
||||
or p_flag[si],pf_tempkeep
|
||||
inc p_tkcnt[si]
|
||||
ret
|
||||
|
||||
;===================
|
||||
no_abort_spec_entry:
|
||||
;===================
|
||||
; Keep the specified process from being aborted by setting
|
||||
; its TEMPKEEP flag.
|
||||
|
||||
; entry: DX=PD address, interrupts off
|
||||
; exit: PD TEMPKEEP turned on, TKCNT incremented
|
||||
|
||||
mov si,dx
|
||||
jmps na_spec
|
||||
|
||||
;==============
|
||||
ok_abort_entry:
|
||||
;==============
|
||||
; Allow the calling process to be aborted if
|
||||
; the PF_TEMPKEEP flag is keeping it from being aborted.
|
||||
; P_TKCNT is decremented in the PD, if P_TKCNT
|
||||
; is = 0 then PF_TEMPKEEP is turned off and PF_CTLC
|
||||
; flag is tested.
|
||||
|
||||
; Interrupts should be turned off if an NO_ABORT_SPEC
|
||||
; can be performed on a process running this code.
|
||||
|
||||
; entry: none
|
||||
; exit: PD fields altered
|
||||
|
||||
mov ax,rlr
|
||||
mov si,ax
|
||||
mov al,p_tkcnt[si]
|
||||
and al,07FH ;high bit is original TEMPKEEP
|
||||
dec al
|
||||
jz oa_restore ;assume
|
||||
dec p_tkcnt[si] ;no borrow from MSB
|
||||
ret
|
||||
oa_restore:
|
||||
test p_tkcnt[si],80H ;was TEMPKEEP on originally ?
|
||||
jnz oa_ret ;if it was don't chk CTLC here
|
||||
;turn off TEMPKEEP
|
||||
and p_flag[si],not pf_tempkeep
|
||||
test p_flag[si],pf_ctlc
|
||||
jz oa_ret
|
||||
mov dx,0ffffh ;if PF_CTLC is set ok to
|
||||
call terminate_entry ;terminate even if SYS PD,
|
||||
;see ABT_CHK in ABORT.RTM
|
||||
;terminate may fail if
|
||||
;KEEP was set while
|
||||
oa_ret: ;TEMPKEEP was also set.
|
||||
mov p_tkcnt[si],0
|
||||
ret
|
||||
@@ -0,0 +1,176 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* SYSTEM ENTRY FUNCTIONS
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;===== ==========================
|
||||
n_imp: ; Function not implemented
|
||||
;===== ==========================
|
||||
|
||||
mov cx,e_not_implemented
|
||||
mov bx,0ffffh ! ret
|
||||
|
||||
;==== =========================
|
||||
i_ent: ; Illegal System Function
|
||||
;==== =========================
|
||||
mov cx,e_bad_entry
|
||||
mov bx,0ffffh ! ret
|
||||
|
||||
;======= ====================
|
||||
bver_ent: ; Get BDOS Version #
|
||||
;======= ====================
|
||||
mov bx,bvernum ! xor cx,cx ! ret
|
||||
|
||||
;======= ====================
|
||||
over_ent: ; Get O.S. Version #
|
||||
;======= ====================
|
||||
mov bx,osvernum ! xor cx,cx ! ret
|
||||
|
||||
if mpm
|
||||
|
||||
;========= ================== ============
|
||||
cbios_ent: ; Direct BIOS call MPM 2.x ONLY
|
||||
;========= ================== ============
|
||||
|
||||
mov si,dx
|
||||
push ds ! mov ds,u_wrkseg
|
||||
mov al,[si] ! mov cx,1[si]
|
||||
mov dx,3[si] ! pop ds
|
||||
cmp al,1 ! ja goxios ;if BOOT,WBOOT; terminate
|
||||
mov cx,f_terminate
|
||||
mov dx,0 ! jmp osif
|
||||
goxios:
|
||||
cmp al,7 ! jbe gx1 ;7=reader input
|
||||
cmp al,15 ! je gx1 ;15=list status
|
||||
mov bx,0ffffh ! mov cx,e_bad_entry
|
||||
ret
|
||||
gx1: mov bx,rlr
|
||||
cmp al,4 ! ja xlst ;4=console output
|
||||
mov dl,p_cns[bx]
|
||||
cmp al,4 ! je jxio
|
||||
mov cl,dl ! jmps jxio
|
||||
|
||||
xlst: cmp al,6 ! je jxio
|
||||
cmp al,7 ! je jxio
|
||||
mov dl,p_lst[bx]
|
||||
cmp al,15 ! jne jxio
|
||||
mov cl,dl
|
||||
jxio: sub al,2 ! mov ah,0
|
||||
jmp xiosif
|
||||
endif ;end of MP/M direct BIOS call
|
||||
|
||||
if ccpm ;CCP/M direct BIOS call
|
||||
|
||||
;========= ================== =============
|
||||
cbios_ent: ; Direct BIOS call CCPM 2.x ONLY
|
||||
;========= ================== =============
|
||||
|
||||
; DI = 0 if last call was also func 50.
|
||||
; DI = 0ffffh if it wasn't
|
||||
|
||||
; xor di,di
|
||||
; cmp u_func,50
|
||||
; je c_next50
|
||||
; dec di
|
||||
c_next50:
|
||||
; mov u_func,50
|
||||
mov si,dx
|
||||
mov bp,ds ;user register for speed
|
||||
mov ds,u_wrkseg
|
||||
mov al,[si] ! mov cx,1[si]
|
||||
mov dx,3[si]
|
||||
mov ds,bp ;DS=SYSDAT
|
||||
|
||||
cmp al,2 ! jne not_consts ;optimize constat
|
||||
; test di,di ;DI=0 if last call was func 50
|
||||
; jnz go_cio
|
||||
; mov si,rlr
|
||||
; mov bl,ncns ;is it a virtual console ?
|
||||
; cmp bl,p_cns[si]
|
||||
; jae go_cio
|
||||
;get_status:
|
||||
; mov si,u_conccb ;if it was U_CCB is valid
|
||||
; xor bx,bx
|
||||
; cmp c_nchar[si],0
|
||||
; jnz s_gotchar
|
||||
; mov bl,c_numchars[si] ;number of chars in VINQ
|
||||
|
||||
; jmps s_quick
|
||||
go_cio:
|
||||
mov cx,f_ciostat ;doesn't change console mode
|
||||
call osif
|
||||
;s_quick:
|
||||
test bl,bl ! jz x_cs ;returns 1 or 0 (or char count)
|
||||
;s_gotchar:
|
||||
mov bx,0ffh ;BIOS returns 0ffh or 0
|
||||
x_cs:
|
||||
ret
|
||||
|
||||
not_consts:
|
||||
cmp al,4 ! jne not_conout ;console output
|
||||
mov dl,cl ;character to send
|
||||
mov cx,f_rconout
|
||||
jmp osif
|
||||
|
||||
not_conout:
|
||||
cmp al,1 ! ja goxios
|
||||
mov cx,f_terminate ;cold or warm boot
|
||||
mov dx,0 ! jmp osif
|
||||
goxios:
|
||||
cmp al,7 ! jbe gx1 ;BIOS 2-7 and 15 are ok
|
||||
cmp al,15 ! je gx1
|
||||
mov bx,0ffffh ! mov cx,e_bad_entry
|
||||
ret
|
||||
gx1:
|
||||
cmp al,3 ! jne not_conin ;console input
|
||||
mov cx,f_rconin
|
||||
jmp osif ;BIOS return in AL and BL
|
||||
not_conin:
|
||||
cmp al,5 ! jne not_listout
|
||||
mov dl,cl
|
||||
mov cx,f_lstout
|
||||
jmp osif
|
||||
not_listout:
|
||||
cmp al,6 ! jne not_auxout
|
||||
mov ax,io_auxout
|
||||
jmp xiosif
|
||||
|
||||
not_auxout:
|
||||
cmp al,7 ! jne not_auxin
|
||||
mov ax,io_auxin
|
||||
jmp xiosif
|
||||
not_auxin:
|
||||
mov ax,io_listst ;when we move this to CIO
|
||||
jmp xiosif ;check for ownership
|
||||
endif ;end of CCP/M direct BIOS
|
||||
|
||||
|
||||
;======== ==============================
|
||||
|
||||
sdat_ent: ; Ret Addr of System Data Area
|
||||
;======== ==============================
|
||||
|
||||
mov u_retseg,ds
|
||||
xor bx,bx ! mov cx,bx ! ret
|
||||
|
||||
;======= ============================
|
||||
tod_ent: ; Return current Time of Day
|
||||
;======= ============================
|
||||
; copy tod struct into user area
|
||||
push es ! mov es,u_wrkseg
|
||||
mov di,dx
|
||||
mov si,offset tod ! mov cx,todlen
|
||||
rep movsb
|
||||
pop es ! xor cx,cx ! mov bx,cx ! ret
|
||||
|
||||
;======= ======================
|
||||
ser_ent: ; Return Serial Number
|
||||
;======= ======================
|
||||
; copy serial field into user area
|
||||
push es ! mov es,u_wrkseg
|
||||
mov di,dx ! mov si,offset serial
|
||||
push ds ! mov ax,cs ! mov ds,ax
|
||||
mov cx,3 ! rep movsw
|
||||
pop ds ! pop es
|
||||
xor cx,cx ! mov bx,cx ! ret
|
||||
@@ -0,0 +1,31 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* SYSTEM DEFINITIONS
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
true equ 0ffffh ; value of TRUE
|
||||
false equ 0 ; value of FALSE
|
||||
unknown equ 0 ; value to be filled in
|
||||
dskrecl equ 128 ; log. disk record len
|
||||
fcblen equ 32 ; size of file control block
|
||||
pnamsiz equ 8 ; size of process name
|
||||
qnamsiz equ pnamsiz ; size of queue name
|
||||
fnamsiz equ pnamsiz ; size of file name
|
||||
ftypsiz equ 3 ; size of file type
|
||||
osint equ 224 ; int vec for O.S. entry
|
||||
debugint equ osint+1 ; int vec for debuggers
|
||||
ulen equ 0100h ; size of uda
|
||||
u8087len equ ulen + 94 ; size of uda when process uses 8087
|
||||
pdlen equ 030h ; size of Process Descriptor
|
||||
todlen equ 5 ; size of Time of Day struct
|
||||
flag_tick equ 1 ; flag 0 = tick flag
|
||||
flag_sec equ 2 ; flag 1 = second flag
|
||||
flag_min equ 3 ; flag 2 = minute flag
|
||||
ldtabsiz equ 0aah ; ldtablen=11, 10 entries
|
||||
|
||||
mpm equ false ; MP/M-86 or
|
||||
ccpm equ not mpm ; CCP/M-86
|
||||
|
||||
BCPM equ false ; CP/M-86 BDOS
|
||||
BMPM equ not BCPM ; multi-process BDOS
|
||||
@@ -0,0 +1,49 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* TICK Process
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;======
|
||||
notick: ;NO ONE ON DELAY LIST
|
||||
;======
|
||||
mov bx,rlr ! mov es,p_uda[bx]
|
||||
mov u_wrkseg,ds
|
||||
|
||||
if mpm ;FIX 6 - DH - 14APR82
|
||||
mov al,io_stopclk ! call xiosif
|
||||
endif ;FIX 6 - DH - 14APR82
|
||||
|
||||
if ccpm ;FIX 6 - DH - 14APR82
|
||||
|
||||
mov tick,false ;FIX 6 - DH - 14APR82
|
||||
endif ;FIX 6 - DH - 14APR82
|
||||
|
||||
tick_l: ;SOMEONE MAY BE ON DELAY LIST
|
||||
;------
|
||||
; flag wait on the TICK flag
|
||||
mov dx,flag_tick ! mov cx,f_flagwait
|
||||
int osint
|
||||
|
||||
; see if anyone delaying
|
||||
pushf ! cli
|
||||
|
||||
mov bx,dlr
|
||||
cmp bx,0 ! jz drl_e
|
||||
|
||||
; decrement # of ticks to wait
|
||||
; see if done waiting
|
||||
dec p_wait[bx] ! jnz n_tck
|
||||
|
||||
; our process is done waiting
|
||||
ede: mov si,p_link[bx] ! mov dlr,si
|
||||
mov p_stat[bx],ps_run
|
||||
mov ax,drl ! mov p_link[bx],ax
|
||||
mov drl,bx
|
||||
|
||||
cmp si,0 ! je drl_e
|
||||
cmp p_wait[si],0 ! jne n_tck
|
||||
mov bx,si ! jmps ede
|
||||
n_tck: popf ! jmps tick_l
|
||||
drl_e:
|
||||
popf ! jmps notick
|
||||
@@ -0,0 +1,4 @@
|
||||
;
|
||||
; UDA offsets
|
||||
;
|
||||
ud_insys equ 60H
|
||||
@@ -0,0 +1,76 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* User Data Area - The User Data Area is an
|
||||
;* extension of the process descriptor but it
|
||||
;* travels with the user. It contains info
|
||||
;* that is needed only while in context.
|
||||
;*
|
||||
;* While in the operating system, The Extra
|
||||
;* Segment register points to the beginning
|
||||
;* of the User Data Area.
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
ud_insys equ 60h
|
||||
|
||||
eseg
|
||||
org 0
|
||||
|
||||
u_dparam rw 1 ; arg to dispatch
|
||||
|
||||
; this area overlays part of BDOS
|
||||
u_dma_ofst rw 1 ; BDOS dma offset
|
||||
u_dma_seg rw 1 ; BDOS dma segment
|
||||
u_func rb 1 ; actual function number
|
||||
u_searchl rb 1 ; BDOS search length
|
||||
u_searcha rw 1 ; BDOS search FCB offset
|
||||
u_searchabase rw 1 ; BDOS search user's segment
|
||||
u_dcnt rw 1 ; BDOS directory count
|
||||
u_dblk rw 1 ; BDOS directory block #
|
||||
u_error_mode rb 1 ; BDOS error mode
|
||||
u_mult_cnt rb 1 ; BDOS multi-sector count
|
||||
u_df_password rb 8 ; BDOS default password
|
||||
u_pd_cnt rb 1 ; BDOS process count
|
||||
uda_ovl_len equ (offset $)-(offset u_dma_ofst)
|
||||
; end of overlay area
|
||||
|
||||
|
||||
u_in_int rb 1
|
||||
u_sp rw 1 ; save register area
|
||||
u_ss rw 1
|
||||
u_ax rw 1
|
||||
|
||||
u_bx rw 1
|
||||
u_cx rw 1
|
||||
u_dx rw 1
|
||||
u_di rw 1
|
||||
u_si rw 1
|
||||
u_bp rw 1
|
||||
u_wrkseg rw 1 ; curr seg addr of buf
|
||||
u_retseg rw 1 ; usr ES return
|
||||
u_ds_sav rw 1 ;\
|
||||
u_stack_sp rw 1 ; usr stack segment
|
||||
u_stack_ss rw 1 ; usr stack pointer
|
||||
u_ivectors rw 4 ; save int 0,1
|
||||
u_unused rw 2 ;
|
||||
u_ivectors2 rw 4 ; save int 3,4
|
||||
u_es_sav rw 1 ; > Used during interrupts
|
||||
u_flag_sav rw 1 ;/
|
||||
|
||||
u_initcs rw 1
|
||||
u_initds rw 1
|
||||
u_inites rw 1
|
||||
u_initss rw 1
|
||||
u_os_ip rw 1 ; O.S. vec save
|
||||
u_os_cs rw 1
|
||||
u_debug_ip rw 1 ; RTS,Debug Vector Save
|
||||
u_debug_cs rw 1
|
||||
u_insys rb 1 ; # times through user_entry
|
||||
u_stat_sav rb 1 ; used during interrupts
|
||||
u_conccb rw 1 ; default console's CCB addr
|
||||
u_lstccb rw 1 ; default list devices CCB addr
|
||||
u_delim rb 1 ; delimiter for user function 9
|
||||
|
||||
; org ulen
|
||||
;u_8087 rw 47 ; 8087 save area
|
||||
; ; see dispatcher, loader and terminate
|
||||
@@ -0,0 +1,31 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* MEM Common Functions
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
|
||||
getmd: ; get MD from MDUL
|
||||
;----- ------------------
|
||||
; output: BX = MD address
|
||||
; 0 if none found
|
||||
|
||||
; CX = Error Code
|
||||
|
||||
pushf ! cli
|
||||
mov cx,e_no_umd ! mov bx,mdul
|
||||
cmp bx,0 ! je gmd_ret
|
||||
xor cx,cx
|
||||
mov si,m_link[bx] ! mov mdul,si
|
||||
mov m_link[bx],cx ! mov m_start[bx],cx
|
||||
mov m_length[bx],cx ! mov m_plist[bx],cx
|
||||
gmd_ret:popf ! ret
|
||||
|
||||
|
||||
freemd: ; put MD on MDUL
|
||||
;------ ----------------
|
||||
; input: BX = MD address
|
||||
|
||||
pushf ! cli
|
||||
mov si,mdul ! mov mdul,bx
|
||||
mov m_link[bx],si ! popf ! ret
|
||||
@@ -0,0 +1,116 @@
|
||||
;************************************************
|
||||
;*
|
||||
;* Virtual Console Control Block Definition
|
||||
;*
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 00 | attach | queue |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 04 | flag | startcol| column | nchar |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 08 | mimic | msource | pc | vc |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 0C | btmp | rsvd | state |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 10 | maxbufsiz | vinq |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 14 | voutq | vcmxq |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 18 | qpbflags| qpbfill | qpbqaddr |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 1C | qpbnmsgs | qpbbuffptr |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 20 | qbuff | cosleep |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 24 | usleep | vsleep |
|
||||
;* +---------+---------+---------+---------+
|
||||
;* 28 | Reserved |
|
||||
;* +---------+---------+---------+---------+
|
||||
;*
|
||||
;*
|
||||
;*
|
||||
;* attach - current owner of device
|
||||
;* if 0, no owner
|
||||
;* if 0ffffh, a mimic device
|
||||
;* queue - linked list of PDs waiting to attach
|
||||
;* flag - run-time flags
|
||||
;* startcol- used for line editing
|
||||
;* column - used for line editing
|
||||
;* nchar - 1 character read ahead for CTRL chars.
|
||||
;* mimic - cio dev that mimics us.
|
||||
;* 0ffh means no mimic device
|
||||
;* msource - if attach = 0ffffh, we are a
|
||||
;* mimic device and msource is the
|
||||
;* device we are mimicing.
|
||||
;* pc - physical console number
|
||||
;* vc - virtual console number
|
||||
;* btmp - temporary line editing variable
|
||||
;* rsvd - unused
|
||||
;* state - current state of virtual console
|
||||
;* maxbufsiz - maximum file size for buffered mode
|
||||
;* vinq - address of QPB for this virtual console's
|
||||
;* input. written by PIN, created by the VOUT
|
||||
;* process associated with this virtual console
|
||||
;* voutq - address of QPB for this virtual console's
|
||||
|
||||
;* output. written and created by the assoc. VOUT
|
||||
;* vcmxq - MX queue for changing of virtual console state
|
||||
;* qpbflags- the 1st 8 bytes of a Queue Parameter Block, for
|
||||
;* queue reads and writes, used only by reentrant
|
||||
;* intercept code
|
||||
;* qbuff - buffer for queue writes
|
||||
;* cosleep - temporary list for processes waiting for XIOS console output
|
||||
;* usleep - user process sleeps here
|
||||
;* vsleep - vout process sleeps here
|
||||
;*
|
||||
c_attach equ word ptr 0
|
||||
c_queue equ word ptr c_attach + word
|
||||
c_flag equ byte ptr c_queue + word
|
||||
c_strtcol equ byte ptr c_flag + byte
|
||||
c_column equ byte ptr c_strtcol + byte
|
||||
c_nchar equ byte ptr c_column + byte
|
||||
c_mimic equ byte ptr c_nchar + byte
|
||||
c_msource equ byte ptr c_mimic + byte
|
||||
c_pc equ byte ptr c_msource + byte
|
||||
c_vc equ byte ptr c_pc + byte
|
||||
c_btmp equ byte ptr c_vc + byte
|
||||
c_rsvd equ byte ptr c_btmp + byte
|
||||
c_state equ word ptr c_rsvd + byte
|
||||
c_maxbufsiz equ word ptr c_state + word
|
||||
c_vinq equ word ptr c_maxbufsiz + word
|
||||
c_voutq equ word ptr c_vinq + word
|
||||
c_vcmxq equ word ptr c_voutq + word
|
||||
c_qpbflags equ byte ptr c_vcmxq + word
|
||||
c_qpbfill equ byte ptr c_qpbflags + byte
|
||||
c_qpbqaddr equ word ptr c_qpbfill + byte
|
||||
c_qpbnmsgs equ word ptr c_qpbqaddr + word
|
||||
c_qpbbuffptr equ word ptr c_qpbnmsgs + word
|
||||
c_qbuff equ word ptr c_qpbbuffptr + word
|
||||
c_cosleep equ word ptr c_qbuff + word
|
||||
c_usleep equ word ptr c_cosleep + word
|
||||
c_vsleep equ word ptr c_usleep + word
|
||||
ccblen equ c_vsleep + word + 4
|
||||
|
||||
; Flags for c_flag
|
||||
|
||||
cf_listcp equ 001h ;control P toggle
|
||||
cf_compc equ 002h ;suppress output
|
||||
cf_switchs equ 004h ;XIOS supports switch screening
|
||||
cf_conout equ 008h ;ownership flag of console output
|
||||
cf_vout equ 010h ;process writing to VOUTQ
|
||||
cf_bufp equ 020h ;just sent a char to a VOUTQ, don't
|
||||
;echo to list if csm_ctrlP is set.
|
||||
;CCB state flags
|
||||
|
||||
csm_buffered equ 00001h
|
||||
csm_background equ 00002h
|
||||
csm_purging equ 00004h
|
||||
csm_noswitch equ 00008h
|
||||
csm_suspend equ 00010h
|
||||
csm_abort equ 00020h
|
||||
csm_filefull equ 00040h
|
||||
csm_ctrlS equ 00080h
|
||||
csm_ctrlO equ 00100h
|
||||
csm_ctrlP equ 00200h
|
||||
|
||||
;LCB - list control block is first ten bytes of VCCB
|
||||
lcblen equ 10
|
||||
@@ -0,0 +1,25 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Interrupt Vectors - to fiddle with the interrupt
|
||||
;* vectors, set the Data Segment Register to 0
|
||||
;* and use the following variables.
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
DSEG
|
||||
|
||||
i_divide_ip rw 1 ; int 0
|
||||
i_divide_cs rw 1
|
||||
i_trace_ip rw 1 ; int 1
|
||||
i_trace_cs rw 1
|
||||
i_nomask_ip rw 1 ; int 2
|
||||
i_nomask_cs rw 1
|
||||
i_break_ip rw 1 ; int 3
|
||||
i_break_cs rw 1
|
||||
i_ovrflw_ip rw 1 ; int 4
|
||||
i_ovrflw_cs rw 1
|
||||
i_interrupts rw ((osint-5)*2)
|
||||
i_os_ip rw 1
|
||||
i_os_cs rw 1
|
||||
i_debug_ip rw 1
|
||||
i_debug_cs rw 1
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* XIOS function jump table offsets
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
if ccpm
|
||||
|
||||
io_const equ 0 ;func 50, direct BIOS
|
||||
io_conin equ 1 ;can access io_funcs 0-6
|
||||
io_conout equ 2
|
||||
io_listst equ 3
|
||||
io_list equ 4
|
||||
io_auxin equ 5
|
||||
io_auxout equ 6
|
||||
io_switch equ 7
|
||||
io_statline equ 8
|
||||
io_seldsk equ 9
|
||||
io_read equ 10
|
||||
io_write equ 11
|
||||
io_flush equ 12
|
||||
io_polldev equ 13
|
||||
|
||||
nxiosfuncs equ io_flush
|
||||
endif
|
||||
|
||||
if mpm
|
||||
io_const equ 0
|
||||
io_conin equ 1
|
||||
io_conout equ 2
|
||||
io_list equ 3
|
||||
;io_punch equ 4 ;not used
|
||||
;io_reader equ 5 ;not used
|
||||
io_home equ 6
|
||||
io_seldsk equ 7
|
||||
io_settrk equ 8
|
||||
io_setsec equ 9
|
||||
io_setdma equ 10
|
||||
io_read equ 11
|
||||
io_write equ 12
|
||||
;io_listst equ 13 ;not used
|
||||
io_sectran equ 14
|
||||
io_setdmab equ 15
|
||||
;io_getsegt equ 16 ;not used
|
||||
io_polldev equ 17
|
||||
io_strtclk equ 18
|
||||
io_stopclk equ 19
|
||||
io_maxconsole equ 20
|
||||
io_maxlist equ 21
|
||||
io_selmemory equ 22
|
||||
io_idle equ 23
|
||||
io_flush equ 24
|
||||
nxiosfuncs equ io_flush
|
||||
endif
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* XIOS Parameter Block for CALL XIOS functions
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
xcb_func equ 0
|
||||
xcb_cx equ word ptr xcb_func + byte
|
||||
xcb_dx equ word ptr xcb_cx + word
|
||||
xcblen equ xcb_dx + word
|
||||
@@ -0,0 +1,15 @@
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Concurrent CP/M XIOS Data Area
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
DSEG
|
||||
|
||||
org 0C0CH
|
||||
|
||||
tick rb 1
|
||||
;see XIOS for format of the rest of the
|
||||
;XIOS header, most of the variables
|
||||
;are copied to the System Data Segment
|
||||
;by GENSYS.
|
||||
Reference in New Issue
Block a user