Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,429 @@
;*************************************************************
;*
;* Terminate and Abort Specify Process Entry Points
;*
;* (D.H - July 1981)
;*
;*************************************************************
;============== ==============
sysreset_entry: ; System Reset
;============== ==============
sub dx,dx
; jmp terminate_entry
;=============== ===============================
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
cmp cx,0 ! jle term_err
terminate: pushf ! cli
mov bx,(offset thrdrt)-p_thread
mov ax,rlr
nchld: mov bx,p_thread[bx]
cmp bx,0 ! je nochld
cmp p_parent[bx],ax ! jne nchld
mov p_parent[bx],0 ! jmps nchld
nochld: mov bx,ax
test p_flag[bx],pf_ctlc ! jz term_r1
and p_flag[bx],not pf_ctlc
mov bx,p_parent[bx]
cmp bx,0 ! je term_r1
or p_flag[bx],pf_childabort
term_r1: popf
mov si,rlr ! call rlsmx
mov u_error_mode,0feh
mov cx,f_bdosterm ! call mpmif
mov dx,offset mxmemqpb ! mov cx,f_qread
call mpmif
mov bx,rlr
mov mxmemowner,bx
mov mxmemcount,1
mov p_stat[bx],ps_term
jmp dsptch
term_err:
jcxz term_err1
sub bx,bx ! mov cx,bx ! ret
term_err1:
mov cx,e_pd_noterm
mov bx,0ffffh ! ret
; end of terminate entry point
;================
abort_spec_entry: ;Abort the specified process
;================
; 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,
; return failure. If the keep flag is on, return failure.
; If the conditional terminate byte is not 0FFH
; (low byte of passed parameter) - meaning conditional
; termination - and the system 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.
; Its u_dparam is set to the termination code, its priority is made the
; best possible and the address of abort_code: is pushed on its UDA stack.
; Abort_code: is shared by the terminate entry point.
;
; Input: DX = address of APB in the caller's u_wrkseg
; Output: BX = 0 if success, 0FFFFH if failure
; CX = 0 " " , err code if failure
push ds ! mov ds,u_wrkseg
mov si,dx ! 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
jcxz abt_err
jmps abt_foundpd
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
jcxz abt_err
abt_foundpd:
cmp bx,rlr ; BX has verified PD address to abort
jnz abt_notus
pop dx ; put term code in dx
jmp terminate_entry ; we are the PD to abort
abt_notus:
call abt_chk ; ok to abort this PD ?
pop dx ; if error - balance stack
cmp cx,0 ! jle term_err ; in terminate entry point
push dx
mov dl,p_stat[bx] ; call abort function based on status
mov dh,0 ! mov di,dx
pop dx ! push dx
add di,di
pushf ! cli
call cs:abort_tab[di] ; find via p_link and take PD of its list
popf ; allow interrupts
jcxz abt_err ; couldn't find PD, if several processes
; are attempting an abort of the same
; process, only one of the abort calls
; will find it
; PD is only on thread list - can't come back into context
; until put on drl. It is safe to fiddle with its priority
; and stack
pop dx ; recall termination code
mov p_prior[bx],abt_prior
and p_flag[bx],not pf_ctlc
push es ; set to low priority
mov es,p_uda[bx] ; uda of PD being aborted
mov si,(ulen-2)
mov u_sp,si
mov u_ss,es
mov u_inint,false
mov es:[si],offset terminate ; terminate code
mov u_dparam,dx ; put in terminate code
pop es ; restore calling PD's UDA
call abt_putdrl ; PD will now terminate itself when next
; in context
xor cx,cx ; indicate sucess
mov bx,cx
jmp pdisp ; force abort to happen before we return
; Error exits for abort routines
abt_tab_err: ; if we can't find PD a status function,
pop dx ! popf ; throw out return adr, restore flags.
abt_err: ; if error from above
pop dx ; throw out termination code
mov cx,e_no_pdname ; one kind of error returned
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:
; input: BX = PD addr to be aborted
; AH = cons
; output: return if success
; else a jump abort_tab_err:
;
; abort_specified process jump table
;
; Status
abort_tab dw abtrun ; 0 = ready list root
dw abtpol ; 1 = poll
dw abtdly ; 2 = delay
dw abtswp ; 3 = swap
dw abtrun ; 4 = term
dw abtrun ; 5 = sleep
dw abtdq ; 6 = dq
dw abtnq ; 7 = nq
dw abtflg ; 8 = flagwait
dw abtcns ; 9 = ciowait
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
abtdq:
;------
; On a dq list
xor al,al ; arg to find_pdq: to look on DQ lists
jmps abtq_common
abtnq:
;-------
; On an nq list
mov al,0ffh ; to look on NQ lists
abtq_common:
call find_pdq
jcxz abt_tab_err
jmps snip_it ; BX,SI = PD;DI = last link
; BP = adr of nq or dq root
abtpol:
;------
mov di,offset plr - p_link
jmps abt_common
abtflg:
;-------
call fflgpd ; Find flag we are waiting on
jcxz abt_tab_err
inc flg_ignore[di]
mov flg_pd[di],flag_off
ret
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
abtswp:
;----
mov di,offset slr - p_link
jmps abt_common
abtcns:
;------
mov al,p_cns[bx] ; Assume legal cns #
call gccba
lea di,(c_queue-p_link)[si] ; offset of root - p_link
call findpd ! jcxz abtlst
jmps snipit
abtlst: mov al,p_lst[bx]
call gccba
lea di,(c_queue-p_link)[si]
jmps abt_common
gccba: ; get ccb address - AL=cio index
xor ah,ah ! mov cx,ccblen
mul cx ; figure offset for this console
mov si,ax
add si,ccb ; add base of ccb table
ret
abtdrl:
;------
mov di,(offset drl) - p_link
;jmps abt_common
abt_common:
;----------
call find_pd ! jcxz aterr1
jmps snip_it
aterr1: jmp abt_tab_err
snip_it:
;-------
; Take PD out of linked list of PDs
; input: 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
;
; End of abort_tab(le) functions
;
abt_putdrl:
;-------
; Puts PD on DRL
; Input: BX = PD to insert
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.
; input: BX = offset of thread list root - p_thread
; DX = adr of name in u_wrkseg
; AH = console number
; output: BX = PD
; CX = 0 failure
pushf ! cli ! xor cx,cx
nxt_pdname:
push ax ! call findpdname_entry ! pop ax
jcxz fnc_found_one ; CX = 0 is success from findpdname
xor cx,cx ! popf
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 ! popf ! ret ; success
findpdq:
;-------
; find the queue list a PD is on
; input: BX = PD address
; AL = ff if looking on NQ, 0 if on DQ lists
; output: DI = previous link,p_link[DI] = BX
; SI = BX = PD address
; CX = 0 if failure
xor cx,cx
mov di,(offset qlr) - q_link
push di
fpdq_nxtq: ; DI is QD currently scanning
pop di ; Recall QD adr
mov di,q_link[di] ; Next QD adr
test di,di ; End of queues ?
jz fpdq_no_pd
test al,al ; DQ or NQ ?
jz fpdq_dq_lst
lea di,(q_nq-p_link)[di]
jmps fpdq_nxt_pd
fpdq_dq_lst:
lea di,(q_dq-p_link)[di] ; root address of list to search
fpdq_nxt_pd:
push di ; Save QD adr
call find_pd
jcxz fpdq_nxt_q ; PD not in this QD, try next QD
pop dx ; Clean stack
fpdq_no_pd: ; find_pd returns non-zero CX if found
ret
find_pdthrd:
; Find PD on thread list
; input: BX = PD address we want
; output: CX = 0 if not found
pushf ! cli
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:
popf ! ret
find_pd:
; Find PD on linked list of PDs. Interrupts are assumed off
; input: BX = PD address
; DI = offset of list root - p_link
; output: 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
; input: BX = PD
; output: DI = offset in RTM data of flag
; CX = 0 if failure
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
; end of abort specified process code
abt_chk:
;-------
; Check flags and termination code for abort,termination
; Input: BX = PD to possibly abort
; DX = termination code
; Output: CX = 00000H if NOT ok to abort
; 00001H IF OK TO ABORT
; 0FFFFH IF tempkeep
sub cx,cx ! mov ax,p_flag[bx]
test ax,pf_keep ! jnz ac_n ;KEEP=ctlc off,no abort
test ax,pf_tempkeep ! jnz ac_tk ;TEMPKEEP=ctlc on,no abort
test ax,pf_sys ! jz ac_y ;not SYS=abort
cmp dl,0ffh ! jne ac_n ;SYS and FF=abort,else no abort
ac_y: inc cx ! ret
ac_tk: or p_flag[bx],pf_ctlc ! dec cx ! ret
ac_n: and p_flag[bx],not pf_ctlc ! ret


View File

@@ -0,0 +1,13 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,52 @@
;
; GENERATE SUP.MPM
;
a86 sup
gencmd sup
era sup.mpm
ren sup.mpm=sup.cmd
vax sup.lst $$atn
xref86 sup
vax sup.xrf $$atn
;
; GENERATE RTM.MPM
;
a86 rtm
gencmd rtm
era rtm.mpm
ren rtm.mpm=rtm.cmd
vax rtm.lst $$atn
xref86 rtm
vax rtm.xrf $$atn
;
; GENERATE MEM.MPM
;
a86 mem
gencmd mem
era mem.mpm
ren mem.mpm=mem.cmd
vax mem.lst $$atn
xref86 mem
vax mem.xrf $$atn
;
; GENERATE CIO.MPM
;
a86 cio
gencmd cio
era cio.mpm
ren cio.mpm=cio.cmd
vax cio.lst $$atn
xref86 cio
vax cio.xrf $$atn
;
; GENERATE SYSDAT.MPM
;
a86 sysdat
gencmd sysdat
era sysdat.mpm
ren sysdat.mpm=sysdat.cmd
vax sysdat.lst $$atn
xref86 sysdat
vax sysdat.xrf $$atn
;


View File

@@ -0,0 +1,15 @@
abt_prior equ 32
;*************************************************************
;*
;* 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


View File

@@ -0,0 +1,50 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,48 @@
;*****************************************************
;*
;* Console Control Block Definition
;*
;* +---------+---------+---------+---------+
;* 00 | attach | queue |
;* +---------+---------+---------+---------+
;* 04 | flag | startcol| column | nchar |
;* +---------+---------+---------+---------+
;* 08 | mimic | msource | type | xdev |
;* +---------+---------+---------+---------+
;*
;* 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
;* xdev - XIOS device number
;*
;*****************************************************
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_xdev equ byte ptr c_type + byte
ccblen equ byte ptr c_xdev + byte
; Flags for c_flag
cf_listcp equ 001h ;control P toggle
cf_compc equ 002h ;suppress output


View File

@@ -0,0 +1,25 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,25 @@
include cpyright.def
;*****************************************************
;*
;* MP/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
eject ! include ccb.def
eject ! include char.def
eject ! include cioif.cio
eject ! include console.cio
eject ! include chario.cio
eject ! include patch.cod
eject ! include uda.fmt
eject ! include sysdat.fmt
eject ! end


View File

@@ -0,0 +1,78 @@
;*****************************************************
;*
;* Character I/O Interface
;*
;*****************************************************
CSEG
org 0
jmp init
jmp entry
sysdat dw 0 ;SYSDAT segment
supervisor equ (offset $)
rw 2
db 'COPYRIGHT (C) 1981,'
db ' DIGITAL RESEARCH '
serial db '654321'
;====
init:
;====
mov sysdat,ds
mov bx,offset supmod ! mov si,supervisor
mov ax,[bx]
mov cs:[si],ax
mov ax,2[bx]
mov cs:2[si],ax
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 mimic_entry ; 21- mimic device
dw unmimic_entry ; 22- unmimic device
;===== =================
entry: ; CIO entry point
;===== =================
mov ch,0 ! shl cx,1 ! mov si,cx
call cs:functab[si] ! retf
;===== ===============
mpmif: ; MPM interface
;===== ===============
callf cs:dword ptr .supervisor ! ret
;====== ================
xiosif: ; XIOS interface
;====== ================
callf dword ptr .xiosmod ! ret


View File

@@ -0,0 +1,9 @@
ERA *.LST
ERA *.H86
ERA *.SYM
ERA *.RSP
ERA *.BAK
ERA *.XRF
era *.mpm
era junk*.*


View File

@@ -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


View File

@@ -0,0 +1,16 @@
;*****************************************************
;*
;* Command Header Entry 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


View File

@@ -0,0 +1,599 @@
;*****************************************************
;*
;* Command Line Interpreter, Program Chain
;*
;*****************************************************
;===========
chain_entry:
;===========
sub dx,dx
;============
clicmd_entry:
;============
; 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. If this succeeds, The default console
; is assigned to a process by the same name.
; The commandtail is then written to the queue and
; the we exit (even if assign fails).
; If there is a failure, We make the type name in the
; FCB to be 'CMD' and 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 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
push dx ! call mxread ! pop dx
mov bx,rlr ! mov ax,p_flag[bx]
mov cli_pflag,ax
and ax,not pf_keep ! or ax,pf_tempkeep
mov p_flag[bx],ax
; we have MXcli queue.
; 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 mpmif ! 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_copy
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_copy:
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_goodparse
mov clierr,cx
jmp cli_exit
cli_goodparse:
call shifttail
;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 mpmif ! jcxz cli_goodq
retcli1: cmp cx,0 ! ret
;we successfully opened the queue
;check for process by assign console
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 mpmif ! 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],0
call conasn ! sub 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
sub ax,ax ! rep stosw
pop es
; Initialize the PD for Load
mov al,cli_fcb
mov cli_lddsk,al
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
mov al,cli_user ! mov p_user[bx],al
mov al,cli_cns ! mov p_cns[bx],al
mov al,p_lst[si] ! sub al,ncondev
mov p_lst[bx],al
; 3. Open the file
mov si,(offset cli_fcb)+fcb_dskmap
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 fileopen
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_bopen ;extended error
mov cl,srchdisk
cmp cl,cli_dsk ! je cli_bopen
cmp cli_fcb,0 ! jne cli_bopen
; try system disk
mov bx,rlr
mov p_dsk[bx],cl
call fileopen
cmp bl,0ffh ! je cli_bopen
;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 fileclose
mov bx,rlr
cmp p_user[bx],0 ! je cli_bopene
mov p_user[bx],0
call fileopen
cmp bl,0ffh ! je cli_bopen
mov bx,offset cli_fcb
test byte ptr fcb_type+1[bx],080h
jnz cli_gopen
call fileclose
jmps cli_bopene
;could not find CMD file
cli_bopen: cmp bh,0 ! jne cli_rmpd2
cli_bopene: 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 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
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
mov cx,f_cload
cli_ld: call mpmif
cli_cl: push bx ! push cx
mov u_error_mode,0
call fileclose
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
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
; init default fcb
push es ! mov es,cli_bpage
mov al,cli_lddsk
mov es:bpg_lddsk,al
mov di,offset bpg_fcb0
sub ax,ax ! stosb ;default disk
mov al,' '
mov cx,11 ! rep stosb ;name,type
sub 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
; init load disk
; if cmdtail, parse
cmp cli_cmdtail,0 ! je cmdtaildone
call pfn
cmp bx,0ffffh ! je cmdtaildone
; 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]
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 cmdtaildone
push cli_pcb ! inc bx
mov cli_pcb,bx
call pfn
pop cli_pcb
cmp bx,0ffffh ! je cmdtaildone
; 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]
mov es:bpg_pw2ptr,ax
mov al,fcb_plen[si]
mov es:bpg_pw2len,al
mov cx,8
rep movsw
pop es
cmdtaildone:
; 10. Create the process
cmp cli_chain,true ! jne noprior
mov cx,f_setprior
mov dx,1 ! call mpmif
noprior:
mov dx,cli_pd ! mov cx,f_createproc
call mpmif
; 11. Assign Console to new process
cmp cli_dfil,true ! jne nocrlf
call crlf
nocrlf: 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
pushf ! cli
mov bx,pul ! mov si,cli_pd
mov p_link[si],bx ! mov pul,si
popf
; Normal EXIT
cli_exit: ; close file and release MXCli queue
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
cmp cli_term,true ! jne clirls
mov bx,rlr
and p_flag[bx],not (pf_keep+pf_sys+pf_tempkeep+pf_ctlc)
mov cx,f_terminate
jmp mpmif
clirls:
push cli_pflag
call mxwrite
pop ax ! and ax,pf_tempkeep+pf_keep
mov bx,rlr ! mov cx,p_flag[bx]
and cx,not pf_tempkeep+pf_keep
or cx,ax ! mov p_flag[bx],cx
test p_flag[bx],pf_ctlc ! jz cli_nctl
mov cx,f_terminate ! sub dx,dx
call mpmif
mov cli_err,e_abort
; setup error return if needed
cli_nctl:
mov cx,clierr ! sub bx,bx
jcxz cli_gexit
mov bx,0ffffh
cli_gexit:
ret
shifttail:
;---------
; setup command tail to be parsed
; input: AX = output of previous parsefilename
cmp ax,0 ! je cli_notail
;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
cli_notail:
mov cli_cmdtail,0
ret
crlf: mov dl,13 ! call prchar
mov dl,10
;jmps prchar
prchar: mov cx,f_conout ! jmp mpmif
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: sub bx,bx ! push ds
mov ax,cs ! mov ds,ax
call cprnt ! pop ds ! ret
prtyp: mov bh,3 ! jmps prn1
prnam: mov bh,8
prn1: mov bl,' '
cprnt: mov cx,f_conprint ! jmps jmpm
fileclose:
mov cx,f_fclose ! mov dx,offset cli_fcb
jmps fo1
fileopen:
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 mpmif ! pop es ! ret
mxwrite:mov cx,f_qwrite
jmps mxw1
mxread: mov cx,f_qread
mxw1: mov dx,offset mxcliqpb
jmpm: jmp mpmif
pfn: mov dx,offset cli_pcb ! mov cx,f_parsefilename
jmps jmpm
conasn: mov cx,f_conassign ! mov dx,offset cli_acb
jmps jmpm
questr db ' Msg Qued',0
userstr db '(User 0)',0
;=========
user_retf:
;=========
; If a user does a RETF expecting to go to CCP,
; The process ends here
mov bx,rlr
and p_flag[bx],not pf_keep+pf_tempkeep+pf_ctlc+pf_sys
mov cx,f_terminate ! sub dx,dx ! int mpmint


View File

@@ -0,0 +1,176 @@
;*****************************************************
;*
;* 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
;
; 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
call getmemory ! jcxz caa_gm
mov bx,0ffffh ! ret
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 mpmif
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: and 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 mpmif
pop dx ! pop dx ! pop ds
ret
;=============
freeall_entry: ; 58 - Free All Mem
;=============
mov cx,f_terminate ! sub dx,dx
jmp mpmif


View File

@@ -0,0 +1,29 @@
;*****************************************************
;*
;* M P / M - 8 6 I I
;* ===================
;*
;* Copyright (c) 1981
;*
;* Digital Research
;* P.O.Box 579
;* Pacific Grove, California 93950
;*
;* (408) 649-3896
;* TWX 9103605001
;*
;* All Information contained in this source listing is
;*
;* PROPRIETARY
;* ===========
;*
;* 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.
;*
;*****************************************************


View File

@@ -0,0 +1,384 @@
;*****************************************************
;*
;* Dispatch Routines
;*
;*****************************************************
;=====
fdisp:
;=====
; This entry point used by interrupt routines in XIOS
cli
push ds ! mov ds,sysdat
cmp indisp,true ! jne do_dispatch
pop ds ! iret
do_dispatch:
mov es_sav,es
mov bx_sav,bx
mov bx,rlr
mov es,p_uda[bx]
mov u_in_int,true
pop u_ds_sav
push bx
mov bl,p_stat[bx]
mov u_stat_sav,bl
pop bx
mov p_stat[bx],ps_run
mov bx,es_sav
mov u_es_sav,bx
mov bx,bx_sav
jmp dsptch
;dispatcher will jump to here if
; u_in_int = true.
int_disp_exit:
mov u_in_int,false
mov bx_sav,bx
mov es_sav,ax
mov bx,rlr
mov al,u_stat_sav
mov p_stat[bx],al
mov ax,es_sav
mov bx,bx_sav
mov indisp,false
mov ds,u_ds_sav
mov es,u_es_sav
iret
;========
farpdisp:
;========
; Intermodule pdisp (non-interrupt)
call pdisp ! ret
;=====
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 ! cld ! cli
cmp indisp,true ! jne dispin
popf ! ret
dispin: mov indisp,true
pop u_flag_sav
; store and switch stack
mov u_ss,ss ! mov u_sp,sp
mov ss,sysdat ! mov sp,offset dsptchtos
sti
; save registers
; NOTE: We will use DS instead of ES
; No segment overrides...
push es ! pop ds
mov ds:u_ax,ax
mov ds:u_bx,bx
mov ds:u_cx,cx
mov ds:u_dx,dx
mov ds:u_di,di
mov ds:u_si,si
mov ds:u_bp,bp
; save interrupt vectors
; block move first 5
mov bx,0 ! mov ds,bx
mov si,bx ! mov di,offset u_ivectors
mov cx,10 ! rep movs ax,ax
; block move mpmint,debugint
mov si,offset i_mpm_ip ! mov di,offset u_mpm_ip
mov cx,4 ! rep movs ax,ax
; take current process off RLR.
mov ds,sysdat
cli
mov si,rlr
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
mov bh,0 ! mov bl,p_stat[si] ! shl bx,1
jmp cs:dsp_table[bx]
dsp_table dw disp_act ;00 - run
dw poll_act ;01 - poll device
dw delay_act ;02 - delay
dw swap_act ;03 - 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
;09 - (nop)-ciowait
sleep_act:
;---------
; insert running process into list specified by
; u_dparam and set p_stat from p_scratch
mov bx,u_dparam
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
poll_act:
;--------
; set p_wait field of process = device number.
; put running process on poll list and wait
; for the device specified by u_dparam
; input: SI=pd address
mov dx,u_dparam
mov p_wait[si],dx
mov ax,plr ! mov p_link[si],ax
mov plr,si ! 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
push si ! mov al,io_strtclk
call xiosif ! pop si
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
swap_act:
;--------
; put running process on swap list
; input: SI=pd address
mov bx,(offset slr)-p_link
call insert_process ! 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
; BX=address of Flag entry
mov bx,u_dparam
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
jmps disp_act
term_act:
;--------
; terminate the running process
; free memory,free pd
; input: SI=pd address
mov ax,rlr
mov p_link[si],ax
mov rlr,si
mov ch,0 ! mov cl,ncondev
nxtcon: jcxz delst
dec cx ! mov p_cns[si],cl
push cx ! push si
mov cx,f_condetach ! call mpmif
pop si ! pop cx ! jmps nxtcon
delst: mov cl,nlstdev
nxtlst: jcxz free_nxt
dec cx ! mov dx,cx
add dl,ncondev
mov p_lst[si],dl
push cx ! push si
mov cx,f_lstdetach ! call mpmif
pop si ! pop cx ! jmps nxtlst
free_nxt:
push si
mov si,p_mem[si]
test si,si ! jz end_free
push ds ! sub cx,cx ! push cx
push ms_start[si]
mov ax,ss ! mov ds,ax ! mov dx,sp
mov cx,f_memfree ! call mpmif
pop bx ! pop cx ! pop ds ! pop si
jmps free_nxt
end_free:
mov mxmemowner,0
mov dx,offset mxmemqpb ! mov cx,f_qwrite
call mpmif
pop si
mov ax,p_link[si]
mov rlr,ax
mov p_link[si],0
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
;
; input: BX = list root
; SI = pd number
mov cx,pflag[si] ! and cx,pf_resource
ins_npd: mov di,p_link[bx]
cmp di,0 ! jz ins_out
mov al,p_prior[di]
cmp al,p_prior[si]
ja ins_out
jb ins_nxt
cmp cx,0 ! jz ins_nxt
jmps ins_out
ins_nxt: mov bx,di ! jmp ins_npd
ins_out: cmp cx,0 ! jz ins_exit
mov cx,pf_resource
not cx ! and p_flag[si],cx
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
cmp si,0 ! jz drltorlr
;SI is valid PD, poll it.
push di ! mov cx,p_wait[si]
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
push di ! mov bx,(offset rlr)-p_link
mov p_stat[si],ps_run
call insert_process ! pop si
;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.
cli ! mov si,drl
cmp si,0 ! jz switch
mov ax,p_link[si] ! mov drl,ax
mov p_stat[si],ps_run
mov bx,(offset rlr)-p_link
call insert_process
sti ! jmps drltorlr
switch:
;------
; switch to the first process on the Ready List
mov bx,rlr
mov dx,p_uda[bx] ! mov ds,dx
push dx ;UDA on stack
; restore interrupt vectors
mov ax,0 ! mov es,ax
mov si,offset u_ivectors ! mov di,ax
mov cx,10 ! rep movs ax,ax
mov si,offset u_mpm_ip
mov di,offset i_mpm_ip
mov cx,4 ! rep movs ax,ax
; restore registers
mov ax,ds:u_ax
mov bx,ds:u_bx
mov cx,ds:u_cx
mov dx,ds:u_dx
mov si,ds:u_si
mov di,ds:u_di
mov bp,ds:u_bp
; restore DS and ES and stack
pop es
mov ss,u_ss
mov sp,u_sp
mov ds,sysdat
cmp u_in_int,true ! jne dret
jmp int_disp_exit
dret: push u_flag_sav ! popf
mov indisp,false
ret


View File

@@ -0,0 +1,48 @@
;*****************************************************
;*
;* 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 in
e_q_inuse equ 10 ; queue in use
e_q_notactive equ 11 ; queue not on qrl
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
e_no_cqbuf equ 17 ; no que buff space
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


View File

@@ -0,0 +1,29 @@
;*****************************************************
;*
;* File Control Block Format
;*
;*****************************************************
fcb_dr equ byte ptr 0
fcb_name equ byte ptr fcb_dr + byte
fcb_type equ byte ptr fcb_name + fnamsiz
fcb_rofile equ byte ptr fcb_type ; high bits of
fcb_invis equ byte ptr fcb_rofile + byte ; these
fcb_reserved equ byte ptr fcb_invis + byte ; fields
fcb_extnum equ byte ptr fcb_type + ftypsiz
fcb_ubytes equ byte ptr fcb_extnum + byte
fcb_modnum equ byte ptr fcb_ubytes + byte
fcb_reccnt equ byte ptr fcb_modnum + byte
fcb_dskmap equ byte ptr fcb_reccnt + byte
fpwdsiz equ 8 * byte
fcb_passwd equ byte ptr fcb_dskmap
fcb_pptr equ word ptr fcb_passwd + fpwdsiz
fcb_plen equ byte ptr fcb_pptr + word
fcb_nxtrec equ byte ptr fcblen
fcb_ranrec equ word ptr fcb_nxtrec + byte


View File

@@ -0,0 +1,38 @@
;*****************************************************
;*
;* Find Process Descriptor
;*
;*****************************************************
;================ =================================
findpdname_entry: ; Find Process Descriptor by Name
;================ =================================
; find process by name in thread list
; 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
pushf ! cli
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 ! popf ! ret


View File

@@ -0,0 +1,89 @@
;*****************************************************
;*
;* Flag Management
;*
;* FLAGS-flag table offset NFLAGS-number of flags
;*
;* Format of Flag Table Entry:
;* +-------------+------+
;* | flag |ignore|
;* +-------------+------+
;* flag - 0ffffh, flag is off
;* 0fffeh, flag is set
;* 0xxxxh, PD that is waiting
;* ignore- 0ffh, normal case
;* 0xxh, number of flags to ignore-1
;*
;* GENSYS initializes the flag table with 0ffh's.
;*
;*****************************************************
;============== ==========================
flag_set_entry: ; Set Logical Interrupt Flag
;============== ==========================
; NOTE: the flagset routine can 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 = Error Code:0,e_flag_ovrrun
call flag_valid
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
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
;---------- -----------------------------
; output: SI = ptr to flag entry
; BX = contents of flag entry
; clear interrupt flag - Flags on stack
pop ax ! pushf
cmp dl,nflags ! jb flag_good
mov cx,e_ill_flag ! jmp flag_bexit
flag_good:
mov dh,0 ! push ax ! cli
mov ax,dx ! mov bx,flglen ! mul bx
mov si,flags ! add si,ax
mov bx,[si] ! ret
flag_exit: ; Successful Exit
;--------- ---------------
sub bx,bx ! mov cx,bx ! popf ! ret
flag_bexit: ; Exit with Error
;---------- ---------------
mov bx,0ffffh ! popf ! ret


View File

@@ -0,0 +1,116 @@
;*****************************************************
;*
;* MP/M-86 Supervisor Initialization
;*
;*****************************************************
cseg
org 0
jmp init ;system initialization
jmp entry ;intermodule entry pt.
sysdat dw 0 ;sysdat segment
supervisor dw entry ;Supervisor entry point
dw 0 ; (segment address)
db 'COPYRIGHT (C) 1981,'
db ' DIGITAL RESEARCH '
serial db '654321'
ver db 13,10,10
db 'MP/M-86 2.0 '
db '[5 Oct 81]'
db 13,10
db 'Copyright (C) 1981, Digital Research'
db 13,10,10,'$'
;====
init:
;====
; system initialization
; assume DS = Sysdat Segment
;
; set up stack,remember DSEG
mov ax,ds
mov ss,ax ! mov sp,offset (init_tos)
mov sysdat,ax
; set up supervisor entry point
mov bx,(offset supmod)+2 ! mov ax,[bx]
mov si,offset supervisor
mov cs:2[si],ax
mov version,offset ver
mov tick_tos,offset notick
mov idle_tos,offset idle
; set up mpm entry point
mov ax,ds ! sub bx,bx ! mov ds,bx
mov i_mpm_ip,offset user_entry
mov i_mpm_cs,cs
mov ds,ax
;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
;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 nbdom
push bx ! callf dword ptr bdosmod[bx] ! pop bx ; init BDOS
nbdom: test module_map,ciomod_bit ! jz nciom
push bx ! callf dword ptr ciomod[bx] ! pop bx ; init CIO
nciom: test module_map,xiosmod_bit ! jz nxiom
push ds ! push es
callf dword ptr xiosmod[bx] ! pop es ! pop ds ; init XIOS
nxiom:
;if intflag is non-zero, interrupts
;are explicitly turned on at the RTM
;entry point.
mov intflag,0ffh
; reset interrupt vectors
mov ax,ds ! sub bx,bx ! mov ds,bx
mov i_mpm_ip,offset user_entry
mov i_mpm_cs,cs
mov ds,ax
; get Character Dev Info from XIOS
mov ax,io_maxconsole ! call xiosif
mov ncondev,bl ! mov nciodev,bl
mov ax,io_maxlist ! call xiosif
mov nlstdev,bl ! add nciodev,bl
; Start RSPs
nrsp: ;loop til done
mov ds,sysdat ;reset DS
mov cx,rspseg ! jcxz rsp_out ;?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 cl,f_createproc ;Create RSP Process(s)
mov dx,si ! int mpmint
jmps nrsp ;Do another...
rsp_out:
; terminate init process
mov cl,f_terminate
mov dl,0ffh ! int mpmint


View File

@@ -0,0 +1,18 @@
;*****************************************************
;*
;* Format of Load Table Used by Load Program
;*
;*****************************************************
ldtab_start equ word ptr 0
ldtab_min equ word ptr ldtab_start + word
ldtab_max equ word ptr ldtab_min + word
ldtab_pd equ word ptr ldtab_max + word
ldtab_attrib equ word ptr ldtab_pd + word
ldtab_fstrt equ word ptr ldtab_attrib + word
ldtab_flen equ word ptr ldtab_fstrt + word
ldtab_type equ byte ptr ldtab_flen + word
ldtab_id equ word ptr ldtab_type + byte
ldtablen equ ldtab_id + word


View File

@@ -0,0 +1,438 @@
;*****************************************************
;*
;* Program Load
;*
;*****************************************************
;===========
cload_entry: ; entry point to load for a chain command
;===========
; Assumes UDA is set in passed PD.
push bx ! mov bx,1
jmps load
;==========
load_entry: ; 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 mpmif
mov load_chain,false
pop load_pd ! pop load_fcb
cmp load_pd,1 ! jne ld_read
pop load_pd ! mov load_chain,true
; Read the Header
ld_read:
mov bx,load_fcb
mov fcb_nxtrec[bx],0 ;read 1st record
mov dx,offset load_dma
mov cx,sysdat
call diskread ! jcxz have_header
jmp load_exit
have_header:
mov load_indma,0
; 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 load_nldtabents,0
mov si,offset ldtab
cmp load_pd,0 ! jne form_uda
jmp get_ch_info
form_uda: mov ldtab_min[si],(lstklen+ulen)/16 ;min=max=UDA+STK paragraphs
mov ldtab_max[si],(lstklen+ulen)/16
mov ax,load_pd ! mov ldtab_pd[si],ax
mov ldtab_attrib[si],mf_load
add si,ldtablen
inc load_nldtabents
cmp load_chain,true ! jne get_ch_info
;free any memory obtained by process
;except uda,ldstack segment
push si
mov bx,load_pd ! mov ax,p_uda[bx]
mov bx,rlr ! mov bx,p_mem[bx]
ld_fnext: cmp bx,0 ! je ld_freeit
cmp ms_start[bx],ax ! je ld_freenxt
and ms_flags[bx],not mf_load
ld_freenxt: mov bx,ms_link[bx] ! jmps ld_fnext
ld_freeit: push ax ! mov cl,0ffh ! push cx
push cx ! push cx
mov dx,sp ! mov cx,ss ! mov ds,cx
mov cx,f_freemem ! call mpmif
pop cx ! pop cx ! pop cx
mov ds,sysdat ! pop ax
; free load memory except uda,ldstack
mov bx,offset ldtab ! mov ldtab_start[bx],ax
sub cx,cx ! push cx
add ax,(lstklen+ulen)/16 ! push ax
mov dx,sp ! mov ax,ss ! mov ds,ax
mov cx,f_memfree ! call mpmif
pop ax ! pop ax
mov ds,sysdat
;transfer memory to new pd
mov bx,rlr
mov ax,p_mem[bx] ! mov p_mem[bx],0
mov bx,load_pd ! mov p_mem[bx],ax
pop si
get_ch_info:
;go through CMD header and init
;a ldtab entry per header entry.
;alloc abs mem
mov cx,ch_entmax ! mov bx,offset load_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 ldtab_type[si],al ;type of seg
mov ax,ch_length[bx] ! mov ldtab_flen[si],ax ;length
mov ldtab_fstrt[si],dx ! add dx,ax ;pos in file
mov ax,ch_base[bx] ! mov ldtab_start[si],ax ;abs seg
mov ax,ch_min[bx] ! mov ldtab_min[si],ax ;min needed
mov ax,ch_max[bx]
cmp ax,0 ! jne setmax
mov ax,ch_min[bx]
setmax: mov ldtab_max[si],ax ;max wanted
mov ax,load_pd ! mov ldtab_pd[si],ax ;pd to alloc to
cmp ax,0 ! je not_load
mov ax,mf_load
jmps not_load
skipjmp:jmps ch_more
not_load: cmp ch_form[bx],1 ! jne try_shared
add ax,mf_code ! jmps set_attrib
try_shared: cmp ch_form[bx],9 ! jne set_attrib
add ax,mf_code+mf_share
set_attrib: mov ldtab_attrib[si],ax ;memory flags
;if abs, allocate memory
cmp ldtab_start[si],0 ! je ch_notabs ;see if abs mem
jmps ch_alloc
ch_notabs: cmp ldtab_type[si],9 ! jne ch_nxt ;see if shared code
ch_alloc: push bx ! push dx ! push cx ! push si
mov cx,f_malloc ! mov dx,si
call mpmif ! pop si
mov ax,ldtab_start[si] ! mov ldtab_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 load_giveup
ch_nxt: add si,ldtablen
inc load_nldtabents
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,load_nldtabents
mov load_nrelsegs,0
lt_more:cmp ldtab_min[bx],0 ! je lt_next
cmp ldtab_start[bx],0 ! jne lt_next
mov ax,ldtab_min[bx] ! add ldtab_min[si],ax
mov ax,ldtab_max[bx] ! add ldtab_max[si],ax
inc load_nrelsegs
lt_next:add bx,ldtablen ! loop lt_more
;malloc
mov ax,ldtab_max[si] ! mov load_maxwanted,ax
mov ax,ldtab_min[si] ! mov load_minwanted,ax
cmp load_pd,0 ! je noloadf
mov ldtab_attrib[si],mf_load
noloadf:mov ax,load_pd ! mov ldtab_pd[si],ax
push si ! mov dx,si ! mov cx,f_malloc
call mpmif ! pop si
mov ax,ldtab_start[si] ! mov ldtab_id[si],ax
cmp bx,0ffffh ! jne lt_spread
;Not Enough Memory - release any
; memory already allocated
load_giveup:push cx
mov bx,offset ldtab
mov cx,load_nldtabents ! inc cx
lg_more: cmp ldtab_id[bx],0 ! je lg_next
push cx ! push bx ! push ds
;push MFPB on stack
push ldtab_pd[bx]
push ldtab_id[bx]
mov dx,sp ! push ss ! pop ds
mov cx,f_memfree
call mpmif
pop cx ! pop cx
pop ds ! pop bx ! pop cx
lg_next: add bx,ldtablen ! loop lg_more
mov bx,0ffffh ! pop cx ! jmp load_exit
lt_spread:
;spread the memory allocated
;amongst the nrelsegs
ls_spread1: ;1st give everyone the minimum
mov bx,offset ldtab
mov cx,load_nldtabents
ls_more:cmp ldtab_start[bx],0 ! jne ls_next
mov ax,ldtab_min[bx]
sub ldtab_min[si],ax
cmp ax,ldtab_max[bx] ! jne ls_next
mov dx,ldtab_start[si] ! mov ldtab_start[bx],dx
add ldtab_start[si],ax
dec load_nrelsegs
ls_next:add bx,ldtablen ! loop ls_more
;spread whats left amongst those that need more
mov bx,offset ldtab
mov cx,load_nldtabents
lsl_mre:cmp ldtab_start[bx],0 ! jne lsl_nxt
mov ax,ldtab_start[si] ! mov ldtab_start[bx],ax
mov ax,ldtab_min[si]
cmp ax,0 ! je adj_start
push cx ! sub cx,cx
mov dx,cx ! mov cl,load_nrelsegs
div cx ! pop cx
cmp dx,0 ! je evendiv
inc ax
evendiv: mov dx,ldtab_max[bx] ! sub dx,ldtab_min[bx]
cmp ax,dx ! jbe nottoomuch
mov ax,dx
nottoomuch: add ldtab_min[bx],ax ! sub ldtab_min[si],ax
adj_start: mov ax,ldtab_min[bx] ! add ldtab_start[si],ax
dec load_nrelsegs
lsl_nxt:add bx,ldtablen ! loop lsl_mre
; fill memory from file
mov si,offset ldtab
mov cx,load_nldtabents
lf_mre: cmp ldtab_flen[si],0 ! je lf_nxt
push cx ! push ldtab_start[si] ! push si
call load_group
pop si ! pop ldtab_start[si]
cmp cx,0 ! pop cx
je lf_nxt
jmp load_giveup
lf_nxt: add si,ldtablen ! loop lf_mre
; init Base Page
; 1st Data Group has Base Page
; if none then first nonshared
; Code Group (8080 model)
mov load_8080,0
mov si,offset ldtab
mov cx,load_nldtabents
lb_more:cmp ldtab_type[si],2 ! je lb_found
add si,ldtablen ! loop lb_more
mov si,offset ldtab
mov cx,load_nldtabents
lbc_mre: cmp ldtab_type[si],1 ! je lb_found8080
add si,ldtablen ! loop lbc_mre
mov cx,e_no_cseg ! jmp load_giveup
lb_found8080: mov load_8080,1
lb_found:
push es ! mov es,ldtab_start[si]
mov load_basep,es
sub ax,ax ! mov di,ax
mov cx,05bh/2 ! rep stos ax
mov al,load_8080 ! mov es:.5,al
mov si,offset ldtab
mov cx,load_nldtabents
lbb_mre:cmp ldtab_type[si],0 ! je lbb_nxt
mov ax,6 ! mov bl,ldtab_type[si]
dec bl ! mul bl ! mov bx,ax
mov dx,ldtab_min[si] ! push dx
mov cl,12 ! shr dx,cl ! mov es:2[bx],dl
pop dx ! mov cl,4 ! shl dx,cl
dec dx ! mov es:[bx],dx
mov ax,ldtab_start[si] ! mov es:3[bx],ax
lbb_nxt:add si,ldtablen ! loop lbb_mre
;if 8080 model, copy CS info into DS info
cmp load_8080,1 ! jne lnot8080
push ds ! push es ! pop ds ! mov si,0
mov di,6 ! mov cx,3
rep movsw ! pop ds
lnot8080:
pop es
; init PD ,UDA and LDSTK
mov bx,load_basep
cmp load_pd,0 ! jne lip_1
jmp load_exit
lip_1: mov si,offset ldtab
mov bx,load_pd
mov ax,ldtab_start[si]
mov p_uda[bx],ax
; remember where lstk,uda are
mov load_uda,ax
push es ! mov es,ax
add ax,(ulen/16) ! mov load_lstk,ax
; initialize UDA,LDSTK with zeros
sub 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,p_user[bx] ! mov p_luser[bx],al
mov al,p_dsk[bx] ! mov p_ldsk[bx],al
push es ! mov es,u_wrkseg
mov di,load_fcb
cmp es:byte ptr [di],0 ! je ldisk_set
mov al,es:[di] ! mov p_ldsk[bx],al
ldisk_set:
pop es
; init UDA
push es ! mov es,load_uda
mov u_dma_ofst,(offset bpg_dma)
mov bx,load_basep
mov u_dma_seg,bx
mov ax,load_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 have_cs
pop ds ! pop es ! mov cx,e_no_cseg
jmp load_giveup
have_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 not8080mod
mov dx,0100h
not8080mod:
mov ds,u_initss
mov ls_offset,dx
mov ls_flags,0200h
mov ls_roffset,offset user_retf
mov ls_rcseg,cs
pop ds ! pop es
mov bx,load_basep
sub cx,cx
load_exit:
push cx ! push bx
mov cx,f_qwrite ! mov dx,offset mxloadqpb
call mpmif ! pop bx ! pop cx ! ret
load_giveup1: jmp load_giveup
load_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,load_indma
mov cx,ldtab_fstrt[bx]
;CX = starting paragraph to transfer
;BX -> ldtab entry
cmp cx,load_indma ! jb read_first
;starts at or after the pp. in dma
sub cx,load_indma
cmp cx,8 ! jae read_first
;starts in the dma
mov dx,8 ! sub dx,cx
;CX = # of pp. to skip
;DX = length of remaining buffer
cmp dx,ldtab_flen[bx] ! jbe transfer
mov dx,ldtab_flen[bx]
transfer: mov si,offset load_dma
mov ax,cx ! mov cl,4 ! shl ax,cl
add si,ax
;SI -> beginning of transfer area
; in load_dma
mov ax,dx ! mov cl,3 ! shl ax,cl
mov cx,ax
;CX = number of words to transfer
sub di,di
push es ! mov es,ldtab_start[bx]
rep movsw ! pop es
add ldtab_start[bx],dx
sub ldtab_flen[bx],dx ! add ldtab_fstrt[bx],dx
read_first:
cmp ldtab_flen[bx],0 ! jne read_1st
sub cx,cx ! ret
read_1st:
cmp ldtab_flen[bx],8 ! jae xfer_direct
push bx ! mov dx,offset load_dma
mov cx,sysdat
call diskread ! pop bx
jcxz read_again
ret
read_again: mov ax,ldtab_fstrt[bx]
mov load_indma,ax
mov si,bx ! jmp load_group
xfer_direct:
push bx ! sub dx,dx
mov cx,ldtab_start[bx]
call diskread ! pop bx
jcxz xfer_1
ret
xfer_1: add ldtab_start[bx],8
add ldtab_fstrt[bx],8
sub ldtab_flen[bx],8
jmp read_first
diskread:
; input: DX = dma offset
; CX = dma segment
push es ! xchg dx,cx ! push cx
mov cx,f_setdmab ! call mpmif
pop dx ! mov cx,f_setdma
call mpmif ! pop es
mov cx,f_freadseq ! mov dx,load_fcb
push ds ! mov ds,u_wrkseg
push es ! call mpmif ! pop es ! pop ds
sub cx,cx
cmp bl,0ffh ! jne dr_ret
mov cx,e_bad_read ! mov bx,0ffffh ! ret
dr_ret: mov bx,rlr
test p_flag[bx],pf_ctlc ! jz dr_r1
mov cx,e_abort ! mov bx,0ffffh
dr_r1: ret


View File

@@ -0,0 +1,31 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,19 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,284 @@
;*****************************************************
;*
;* 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
mov dl,.0
cmp cx,sat_start[bx] ! je maua_nabs ;?exact?
sub cx,sat_start[bx]
mov bx,cx ! call mau_split ;make exact
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] ! jne mauf_nsat
cmp dx,es:maf_start[si] ! je mauf_free
mov cx,es:maf_start[si]
mov ax,sat_start[bx]
add ax,sat_length[bx]
cmp ax,cx ! jb mauf_err
; must split this SAT
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
mov bp,0ffffh ;assume empty
sub bx,bx ! mov cx,bx
mov di,satlen
mauc_nsat:
inc cx
cmp cx,.0 ! jb mauc_notend
mauc_done: sub cx,cx ! mov bx,bp ! ret
mauc_notend:
add bx,satlen ! lea di,satlen[bx]
cmp sat_start[bx],0 ! je mauc_done
cmp sat_start[di],0 ! je mauc_done
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
sub bp,bp ;not empty
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
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


View File

@@ -0,0 +1,26 @@
include cpyright.def
;*****************************************************
;*
;* MP/M-86 Memory Management Module
;*
;*****************************************************
eject ! include system.def
eject ! include modfunc.def
eject ! include pd.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 sysdat.fmt
eject ! end


View File

@@ -0,0 +1,32 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,97 @@
;*****************************************************
;*
;* Memory Management Module Interface
;*
;*****************************************************
CSEG
org 0
jmp init
jmp entry
sysdat dw 0 ;SYSDAT segment
supervisor equ (offset $)
rw 2
db 'COPYRIGHT (C) 1981,'
db ' DIGITAL RESEARCH '
serial db '654321'
;====
init:
;====
mov sysdat,ds
mov bx,offset supmod ! mov si,supervisor
mov ax,[bx]
mov cs:[si],ax
mov ax,2[bx]
mov cs:2[si],ax
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
;===== =================
mov ax,rlr
cmp ax,mxmemowner
je havemx
push bx ! push cx ! push dx
mov dx,offset mxmemqpb ! mov cx,f_qread
call mpmif ! pop dx ! pop cx ! pop bx
mov si,rlr ! mov mxmemowner,si
mov mxmemcount,0
push p_flag[si]
or p_flag[si],pf_tempkeep
havemx: inc mxmemcount
mov ch,0 ! shl cx,1
mov si,cx
call cs:functab[si]
dec mxmemcount
cmp mxmemcount,0
jne entry_out
mov mxmemowner,0
pop ax ! and ax,pf_tempkeep ! jnz tkon
mov si,rlr
and p_flag[si],not pf_tempkeep
tkon: push cx ! push bx
mov dx,offset mxmemqpb ! mov cx,f_qwrite
call mpmif ! pop bx ! pop cx
mov si,rlr
test p_flag[si],pf_ctlc ! jz entry_out
push bx ! push cx
sub dx,dx
mov cx,f_terminate ! call mpmif
pop cx ! pop bx
entry_out:
mov ax,bx ! retf
;===== ===============
mpmif: ; MPM interface
;===== ===============
callf cs:dword ptr .supervisor ! ret
;====== ================
xiosif: ; XIOS interface
;====== ================
callf dword ptr .xiosmod ! ret


View File

@@ -0,0 +1,282 @@
;*****************************************************
;*
;* 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 | flags | mau |
;* +----+----+----+----+----+----+----+----+
;*
;* link link field for p_mem list
;* start starting paragraph 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.
;
; (Future - if MPB flags indicate load shared code,
; we try to allocate from MAU's used by another process
; of the same name and from the same load file.)
;
; 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
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
cmp ax,rlr ! je mall_pdver
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 bx,0ffffh
mov cx,e_active_pd
ret
mall_pdver:
; try to allocate memory
mov si,ax ! add si,(p_mem - ms_link)
mov cx,0 ;CX=last MAU we've tried
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]
push bx ! call mall_try_mau ! pop di
pop si ! pop bx ! pop dx
; Plus DI=MAU address
cmp cx,0 ! pop cx ! jne mall_next
; 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 mpmif
mov ds,sysdat
;BX=MAU, (New MD,MPB on stack)
jcxz mall_ml0
pop dx ! pop bx ! jmp mall_err
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
push bx ! call mall_try_mau ! pop di
pop dx ! pop bx
;DI=MAU, BX=New MD, DX=MPB in u_wrkseg
cmp cx,0 ! jne mall_err
; Successful allocation
mov si,0
jmps mall_linkit
mall_err: ; No memory available
call freemd ; Free the Memory Descriptor
mov bx,0ffffh ! ret ; CX=Error Code set previously
mall_linkit:
;SI = MD addr which MAU came from
; if zero, from new MAU
;BX -> MD
;DX -> MPB in u_wrkseg
;DI -> MAU
push es ! mov es,u_wrkseg
push di ! mov di,dx
mov ax,es:mpb_start[di]
mov ms_start[bx],ax
mov ax,es:mpb_min[di]
mov ms_length[bx],ax
mov ax,es:mpb_flags[di]
mov ms_flags[bx],ax
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
pop di ! 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
; output: CX = Error Code
mov ds,u_wrkseg
mov cx,f_maualloc ! call mpmif
mov ds,sysdat ! 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_gotpd
mfree_chkpd:
mov si,(offset thrdrt)-p_thread
mfree_nxtpd:
mov si,p_link[si]
cmp si,0 ! je mfree_gotpd
cmp si,bx ! jne mfree_nxtpd
cmp si,rlr ! je mfree_gotpd
mov bx,0ffffh
mov cx,e_active_pd
ret
mfree_gotpd:
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 mpmif
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_r
cmp dx,ms_start[si] ! je mfree_off
;decrease length
sub dx,ms_start[si]
mov ms_length[si],dx
mfree_r: ret
;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,0 ! je mfree_r
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 mpmif


View File

@@ -0,0 +1,200 @@
;*****************************************************
;*
;* 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
; = 0 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:sub bx,bx ! 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
jmps mlav_err
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: (for now)
; #partitions = #partitions + 1 if next
; to contiquous memory
; value = (abs(max-length) SHR 4) +
; ((#partitions-1) SHL 5)
; idea is that 8K = 1 partition 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,5 ! shl ax,cl
mov cx,es:mpb_max[si]
add cx,(2*satlen)
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
mlav_err:
mov cx,0ffffh ! sub ax,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


View File

@@ -0,0 +1,156 @@
;*****************************************************
;*
;* 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_rawconin equ (user * 0100h) + 3
;f_rawconout equ (user * 0100h) + 4
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_getversion 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_freeallmem equ (user * 0100h) + 58
;f_userload equ (user * 0100h) + 59
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_mpmvernum equ (user * 0100h) + 163
;f_getdeflst equ (user * 0100h) + 164
; 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
; 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 SUP functions
f_load equ (sup * 0100h) + 10
f_cload equ (sup * 0100h) + 14
; Internal CIO functions
f_conprint equ (cio * 0100h) + 14
f_mimic equ (cio * 0100h) + 21
f_unmimic equ (cio * 0100h) + 22
; Internal BDOS functions
f_bdosterm equ (bdos * 0100h) + 46


View File

@@ -0,0 +1,11 @@
;*****************************************************
;*
;* Definition of Module Table Entry
;*
;*****************************************************
mod_entry equ 0
mod_init equ mod_entry + dword
modlen equ mod_init + dword


View File

@@ -0,0 +1,47 @@
;*****************************************************
;*
;* 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
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,6 @@
a86 $1
gencmd $1
era $1.$2
ren $1.$2=$1.cmd
vax $1.lst $$atn


View File

@@ -0,0 +1,152 @@
;*****************************************************
;*
;* Parse Filename Function
;*
;*****************************************************
;=========== =========================
parse_entry: ; 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 fcbinit ! call deblank ;init FCB, deblank parse str
mov bp,e_badfname ;BAD FILENAME
;BP=error code if error
call delim ! jnz parse1 ;chk 1st char
jmp pfn_endp
parse1: mov ch,al ! inc si ! mov al,[si] ;see if Disk spec
cmp al,':' ! jne parse2
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 parse3 ;check nxt char
cmp al,'.' ! je pfn_err ;hit delim
cmp al,':' ! je pfn_err ; see if legal
cmp al,';' ! je pfn_err
jmp parse3
parse2: dec si ;use default disk
parse3: ;parse filename
mov di,bx ! lea bx,fcb_name[di]
mov ch,8 ! call setfld ;fill in FCB
cmp ch,0 ! jne parse4
call delim ! jz parse4 ;see if more than 8 chars
pfn_err: mov cx,bp
mov bx,0ffffh ! pop es ! pop ds ! ret
parse4: cmp al,'.' ! jnz parse5 ;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 parse5
call delim ! jz parse5
jmp pfn_err
;parse passwd
parse5:
cmp al,';' ! jnz parse8 ;see if password delim
mov bp,e_ill_passwd
mov ch,8 ! lea bx,fcb_passwd[di]
inc si ! call setfld ;yes
mov cl,8 ! sub cl,ch
mov fcb_plen[di],cl
cmp ch,0 ! jne parse8
call delim ! jz parse8
jmp pfn_err
parse8: mov bx,si ! call deblank ;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)
deblank: ;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 deblank
fcbinit: ; 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


View File

@@ -0,0 +1,11 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,112 @@
;*****************************************************
;*
;* Process Descriptor - with the UDA associated
;* with the PD, describes the current
;* state of a Process under MP/M-86
;*
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 00| link | thread |stat |prior| flag |
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 08| Name |
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 10| uda | dsk | user| ldsk|luser| mem |
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 18| dvract | wait | org | net | parent |
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 20| cns |abort| cin |cout | lst | sf3 | sf4 | sf5 |
;* +-----+-----+-----+-----+-----+-----+-----+-----+
;* 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
;* dvract - bit map of currently active drives
;* 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 - controlling console
;* abort - abort code
;* cin - standard file #0 (console input)
;* cout - standard file #1 (console output)
;* lst - standard file #2 (list output)
;* sf3 - standard file #3
;* sf4 - standard file #4
;* sf5 - standard file #5
;* 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_dvract equ word ptr p_mem + word
p_wait equ word ptr p_dvract + word
p_org equ byte ptr p_wait + word
p_net equ byte ptr p_org + byte
p_parent equ word ptr p_net + byte
p_cns equ byte ptr p_parent + word
p_abort equ byte ptr p_cns + byte
p_cin equ byte ptr p_abort + byte
p_cout equ byte ptr p_cin + byte
p_lst equ byte ptr p_cout + byte
p_sf3 equ byte ptr p_lst + byte
p_sf4 equ byte ptr p_sf3 + byte
p_sf5 equ byte ptr p_sf4 + byte
p_reserved equ word ptr p_sf5 + byte
p_pret equ word ptr p_reserved + (2*word)
p_scratch equ byte ptr p_pret + word
p_wscrtch equ word ptr p_scratch
;
; Process descriptor pd_status values
;
ps_run equ 00 ; in ready list root
ps_poll equ 01 ; in poll list
ps_delay equ 02 ; in delay list
ps_swap equ 03 ; in swap list
ps_term equ 04 ; terminating
ps_sleep equ 05 ; sleep processing
ps_dq equ 06 ; in dq list
ps_nq equ 07 ; in nq list
ps_flagwait equ 08 ; in flag table
ps_ciowait equ 09 ; in c_queue list
;
; 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


View File

@@ -0,0 +1,190 @@
;*****************************************************
;*
;* Process Routines
;*
;*****************************************************
;====== =========================
freepd: ; Free Process Descriptor
;====== =========================
; Assumes no memory and on no list except thread.
; input: SI = pd address
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
and p_flag[bx],not pf_childabort
mov al,p_lst[si]
cmp al,nlstdev ! jb cp_slst
mov al,0
cp_slst:add al,ncondev
mov p_lst[si],al
and p_flag[si],not pf_resource
;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 mpmif ! 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 ! sub 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
mov ds:u_initds,ax
cp_uda2:cmp ds:u_initss,dx ! jne cp_uda3
mov ds:u_initss,ax
cp_uda3:cmp ds:u_inites,dx ! jne cp_uda4
mov ds:u_inites,ax
cp_uda4:
;interrupt vector save areas
;DX = 0
; set ints 0-4
mov ds,dx
mov si,dx ! mov di,offset u_ivectors
mov cx,10 ! rep movs ax,ax
; set mpmint,debugint
mov si,offset i_mpm_ip
mov di,offset u_mpm_ip
mov cx,4 ! rep movs ax,ax
; 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
mov ds:u_error_mode,0
mov ds:u_pd_cnt,0
mov ds:u_mult_cnt,1
mov ds:u_in_int,true
mov ds:u_insys,0
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,0
; 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
pop ds ! pop es
; put on thread list
pop si ! pushf ! cli
mov dx,thrdrt ! mov p_thread[si],dx
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
getpdadr:
;--------
; Make sure pd address is in operating system. If not, copy into
; one in pd table. Make address relative to sysdat
; input: DX = pd address in u_wrkseg
; output: SI = pd address in sysdat
push dx ! mov ax,u_wrkseg
push ax ! mov cl,4 ! shr dx,cl
add ax,dx
cmp ax,sysdat ! jb gpd_bad
cmp ax,endseg ! jae gpd_bad
mov cx,sysdat ! add cx,1000h
cmp ax,cx ! jae gpd_bad
pop ax ! sub ax,sysdat
mov cl,4 ! shl ax,cl
pop dx ! add dx,ax
mov si,dx ! sub cx,cx ! ret
gpd_bad:
pop ax ! pop dx ! pushf ! cli
mov di,pul
cmp di,0 ! jne gpd_have
mov cx,e_no_pd ! popf ! ret
gpd_have:
mov ax,p_link[di] ! mov pul,ax
push di ! push es ! push ds
mov ds,u_wrkseg ! pop es
mov si,dx ! mov cx,pdlen/2
rep movsw
push es ! pop ds ! pop es ! pop si
or p_flag[si],pf_table ! popf ! ret


View File

@@ -0,0 +1,84 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,238 @@
;*****************************************************
;*
;* Queue Routines
;*
;*****************************************************
;=========== =======================
makeq_entry: ; Create a System Queue
;=========== =======================
; input : DX = address of QD in u_wrkseg
; u_wrkseg = segment of QD
; output: BX = 0 if okay , 0ffffh if error
; CX = Error Code
call getqdaddr ! mov di,dx ;DI->QD addr
cmp cx,0 ! je qm_chk
mov bx,0ffffh ! ret
;Make sure this queue doesn't already exist
qm_chk: pushf ! cli
push es ! mov es,sysdat
mov si,(offset qlr)-q_link
qm_nxt: mov si,q_link[si]
cmp si,0 ! je qm_go
push di ! push si ! mov cx,qnamsiz/2
add di,q_name ! add si,q_name
repe cmpsw
pop si ! pop di ! jne qm_nxt
;Names match
mov bx,0ffffh ! mov cx,e_q_inuse
pop es ! popf ! ret
qm_go: pop es
;We have a QD initialize it
mov dx,0 ! mov q_dq[di],dx
mov q_nq[di],dx ! mov q_msgcnt[di],dx
mov q_msgout[di],dx
;put it on QLR
mov ax,qlr ! mov q_link[di],ax
mov qlr,di ! sub bx,bx
mov cx,bx ! popf ! ret
;=========== ======================
openq_entry: ; Find an active Queue
;=========== ======================
; input: DX = address of QPB
; segment is u_wrkseg
; output: Fills QPB with appropriate info
; BX = 0 if okay, 0ffffh if not
; CX = Error Code
pushf ! cli
push es ! mov es,u_wrkseg
mov si,(offset qlr)-q_link ! mov di,dx
qo_nqd: mov si,q_link[si]
cmp si,0 ! je qo_noq
push di ! push si ! mov cx,qnamsiz/2
add si,q_name ! add di,qpb_name
repe cmpsw
pop si ! pop di ! jne qo_nqd
;Names match
mov es:qpb_qaddr[di],si
sub bx,bx ! mov cx,bx
pop es ! popf ! ret
qo_noq: ;No name matches
mov cx,e_no_queue ! mov bx,0ffffh
pop es ! popf ! ret
;============= =======================
deleteq_entry: ; Delete a System Queue
;============= =======================
; Takes a qd off the qlr and places it in the qul.
; input: DX = offset of QPB
; in u_wrkseg
; output: BX = 0 if ok, 0ffffh if bad
; CX = Error Code
pushf ! cli
push es ! mov es,u_wrkseg
mov di,dx ! add di,qpb_qaddr
mov di,es:[di]
mov ax,q_dq[di] ! mov dx,q_nq[di]
add dx,ax ! jnz qd_use
mov bx,(offset qlr)-q_link
qd_nqd: mov si,q_link[bx]
cmp si,0 ! jz qd_noq
cmp si,di ! jne qd_neq
mov ax,q_link[si]!mov q_link[bx],ax
call remqd
mov bx,0 ! mov cx,bx
pop es ! jmps qd_e
qd_neq: mov bx,si ! jmps qd_nqd
qd_noq: mov cx,e_q_notactive ! jmps qd_be
qd_use: pop ax ! mov cx,e_q_inuse
qd_be: mov bx,0ffffh
qd_e: popf ! ret
;=========== ============
readq_entry: ; Read Queue
;=========== ============
mov ax,0 ! jmps readq
;============
creadq_entry: ; Conditional Read Queue
;============
mov ax,0ffffh
; jmps readq
readq: ; Read message from queue
;----- -------------------------
; If no buffer is available, the process is placed into the DQ list
; of the queue and waits until another process writes into the queue.
; input: DX = address of qpb in u_wrkseg
; AX = 0ffffh if conditional
; 0 if not
; output: BX = 0 if okay
; 0ffffh if error
; CX = Error Code
push ax ! call queverify ! pop ax
cmp cx,0 ! je qr_ver
mov bx,0ffffh ! ret
qr_ver: push es ! mov es,u_wrkseg
mov si,dx ;es:[si]->QPB
mov bx,es:qpb_qaddr[si] ;bx->QD
mov di,es:qpb_buffptr[si] ;es:[di]->buff
pushf ! cli
mov cx,q_msgcnt[bx]
cmp cx,0 ! jne qr_gmsg
inc ax ! jnz qr_wait
mov bx,0ffffh ! mov cx,e_q_empty
popf ! pop es ! jmps qr_exit
qr_wait: lea dx,q_dq[bx] ;DX=addr of DQ List
mov bx,rlr ! mov p_stat[bx],ps_dq ;status=DQ
popf ! pop es ! push si
mov cx,f_sleep ! call mpmif ;Sleep on DQ List
pop dx ! jmps qr_ver
qr_gmsg:mov cx,q_msglen[bx]
cmp cx,0 ! jne qr_lmsg
mov cx,q_flags[bx] ; msglen=0
and cx,qf_mx ! jz qr_finish
mov ax,rlr ;Its a MX queue
mov q_buf[bx],ax ;BUF = PD addr (owner)
jmps qr_finish
qr_lmsg: ; msglen > 0
mov ax,q_msgout[bx] ! push ax
mul cx ! add ax,q_buf[bx]
mov si,ax ! rep movsb
pop ax ! inc ax
cmp ax,q_nmsgs[bx] ! jne qr_nend
mov ax,0
qr_nend:mov q_msgout[bx],ax
qr_finish:
dec q_msgcnt[bx] ! popf
mov si,bx ! pop es
lea dx,q_nq[si] ;DX = NQ List
mov cx,f_wakeup ;Wakeup a process
call mpmif ; waiting to write
mov cx,0 ! mov bx,cx
qr_exit:ret
;============ =============
writeq_entry: ; Write Queue
;============ =============
mov ax,0 ! jmps writeq
;============= =========================
cwriteq_entry: ; conditional Write Queue
;============= =========================
mov ax,0ffffh
;jmps writeq
writeq: ; Write message into queue
;------ --------------------------
; If no buffer is available, the process is placed into the NQ list
; of the queue and waits until another process reads from the queue.
; input: DX = address of qpb in u_wrkseg
; BX = pd address
; AX = 0ffffh if conditional
; 0 if not
; output: BX = 0 if okay
; 0ffffh if error
; CX = Error Code
push ax ! call queverify ! pop ax
cmp cx,0 ! je qw_ver
mov bx,0ffffh ! ret
qw_ver: push es ! mov es,u_wrkseg
mov di,dx ; es:[di]->QPB
mov bx,es:qpb_qaddr[di] ; bx -> QD
mov si,es:qpb_buffptr[di] ; es:[si]->QPB.buff
pushf ! cli
mov cx,q_msgcnt[bx]
cmp cx,q_nmsgs[bx] ! jne qw_gbuf
inc ax ! jnz qw_wait
popf ! pop es ! mov bx,0ffffh
mov cx,e_q_full ! jmps qw_exit
qw_wait: lea dx,q_nq[bx] ;DX = NQ List
mov bx,rlr ! mov p_stat[bx],ps_nq ;status=NQ
popf ! pop es ! push si
mov cx,f_sleep ! call mpmif ;Sleep on NQ List
pop dx ! jmps qw_ver ;try again
qw_gbuf:mov cx,q_msglen[bx] ;there is a buffer
cmp cx,0 ! je qw_fin
mov ax,q_msgout[bx] ! add ax,q_msgcnt[bx]
cmp ax,q_nmsgs[bx] ! jb qw_move
sub ax,q_nmsgs[bx]
qw_move: mul cx ! add ax,q_buf[bx]
mov di,ax ;DI=start of new msg
push ds ! push es ! pop ds ! pop es
rep movsb ; copy message
push ds ! push es ! pop ds ! pop es
qw_fin: inc q_msgcnt[bx]
mov cx,q_flags[bx] ! and cx,qf_mx
jz qw_nomx
mov q_buf[bx],0 ;an MX queue,no owner
qw_nomx:mov si,bx ! popf ! pop es
lea dx,q_dq[si] ;DX = DQ List
mov cx,f_wakeup ;Wakeup a process trying
call mpmif ; to read a message
sub bx,bx ! mov cx,bx
qw_exit:ret
queverify: ; check QLR for existence of QD address
;--------- ---------------------------------------
; input: DX = offset of QPB
; output: CX = error code
push ds ! mov ds,u_wrkseg
mov bx,dx ! mov si,qpb_qaddr[bx] ! pop ds
mov bx,offset qlr
qv_nxt: mov bx,q_link[bx]
cmp bx,0 ! jne qv_chk
mov cx,e_no_queue ! ret
qv_chk: cmp bx,si ! je qv_fnd
jmps qv_nxt
qv_fnd: mov cx,0 ! ret


View File

@@ -0,0 +1,123 @@
;=====
rlsmx:
;=====
; Release all MX queues held by a given process
; input: SI = pd address
pushf ! cli ! mov di,(offset qlr)-q_link
rm_nxt:
mov bx,q_link[di]
or bx,bx ! jz rm_dne
test q_flags[bx],qf_mx ! jz rm_notthis
cmp si,q_buf[bx] ! jne rm_notthis
push bx ! sub ax,ax ! push ax
mov dx,sp ! mov cx,f_cqwrite
push ds ! push ss ! pop ds
call mpmif ! pop ds ! pop ax ! pop bx
rm_notthis: mov di,bx ! jmps rm_nxt
rm_dne: popf ! ret
getqdaddr:
;----------
; Check qd address. If within MPM, use it else grab
; qd from table and initialize with buffer space
; returning its address. also set qf_table flag.
; input: DX = offset of qd in u_wrkseg
; output: DX = offset of qd in MPM CSEG.
push dx ! mov ax,u_wrkseg
push ax ! mov cl,4 ! shr dx,cl
add ax,dx
;must be above SYSDAT
cmp ax,sysdat ! jb gqd_bad
;must be below end of system
cmp ax,endseg ! jae gqd_bad
;must be within 64K of SYSDAT
; 64K=1000h memory paragraphs
mov cx,sysdat ! add cx,1000h
cmp ax,cx ! jae gqd_bad
pop ax ! sub ax,sysdat
mov cl,4 ! shl ax,cl
pop dx ! add dx,ax
mov si,dx ! sub cx,cx
cmp q_buf[si],cx
je gqd_ret
add q_buf[si],ax
gqd_ret: ret
gqd_bad:
pop ax ! pop dx ! pushf ! cli
mov di,qul
cmp di,0 ! jne gqd_have
mov cx,e_no_qd ! popf ! ret
gqd_have:
mov bx,q_link[di] ! mov qul,bx
push di ! push es ! push ds
mov ds,u_wrkseg ! pop es
mov cx,qdlen/2 ! mov si,dx
rep movs ax,ax
push es ! pop ds ! pop es ! pop di
or q_flags[di],qf_table
push di ! mov si,di
call qspace ! pop di
cmp cx,0 ! je gqd_exit
mov ax,qul ! mov q_link[di],ax
mov qul,di
gqd_exit:
mov dx,di ! popf ! ret
remqd:
;-------
; Place qd on queue unused list
; Input SI = qd address
mov ax,q_flags[si]
and ax,qf_table ! jz rqd_exit
pushf ! cli
mov ax,qul ! mov q_link[si],ax
mov qul,ax ! call qrelease
popf
rqd_exit:
ret
qspace:
;------
; find buffer space for qd
; input SI = QD address
; output CX = Error Code
;compute AX=size of buffer wanted
mov ax,q_msglen[si] ! mul q_nmsgs[si]
;call maualloc
mov cx,0 ! push cx ! push cx ! push ax
push ax ! push cx
mov dx,sp ! mov ax,ss ! mov ds,ax
mov bx,offset qmau
push si
mov cx,f_maualloc ! call mpmif
pop si ! mov ds,sysdat
cmp cx,0 ! jne qspace_ret
mov bp,sp ! mov ax,mpb_start[bp]
mov q_buf[si],ax
qspace_ret:
pop ax ! pop ax ! pop ax ! pop ax ! pop ax
ret
qrelease:
;--------
; release buffer space for qd
; if the released space is ajacent to another
; free area, they are joined and a md is freed.
; input SI = QD address
mov ax,q_buf[si]
mov cx,offset qmau
push ax ! push ax ! push cx
mov cx,f_maufree
mov dx,sp ! mov ax,ss ! mov ds,ax
call mpmif
pop ax ! pop ax ! pop ax
ret


View File

@@ -0,0 +1,80 @@
;**********************************************************
;*
;* Call Resident System Procedure
;*
;**********************************************************
cpb_name equ word ptr 0
cpb_param equ word ptr cpb_name + qnamsiz
;=========
rpl_entry: ; 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 mpmif
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 mpmif ! 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


View File

@@ -0,0 +1,37 @@
include cpyright.def
;*****************************************************
;*
;* RTM - 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 fcb.def
eject ! include cmdh.def
eject ! include apb.def
eject ! include ccb.def
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.fmt
eject ! end


View File

@@ -0,0 +1,103 @@
;*****************************************************
;*
;* 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
db 'COPYRIGHT (C) 1981,'
db ' DIGITAL RESEARCH '
serial db '654321'
;==== ===========================
init: ; RTM module Initialization
;==== ===========================
mov sysdat,ds ;save sysdat
mov bx,offset supmod ;init supif
mov si,offset supervisor
mov ax,[bx]
mov cs:[si],ax
mov ax,2[bx]
mov cs:2[si],ax
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
;create tick and idle process
mov bx,offset tickpd ;Tick
mov ax,p_uda[bx]
add ax,sysdat
push es ! mov es,ax
mov si,supervisor
mov ax,cs:2[si]
mov u_initcs,ax ! pop es
mov bx,offset idlepd ;IDLE
mov ax,p_uda[bx]
add ax,sysdat
push es ! mov es,ax
mov si,supervisor
mov ax,cs:2[si]
mov u_initcs,ax ! pop es
mov dx,bx ! call proc_creat
;init is now a process and can run
;concurrently with idle process
retf
;*****************************************************
;*
;* RTM Function Table
;*
;*****************************************************
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
;===== =================
entry: ; RTM Entry Point
;===== =================
mov ch,0 ! shl cx,1 ! mov si,cx
call cs:function[si]
rtm_ret:retf
;===== ===============
mpmif: ; MPM Interface
;===== ===============
callf cs:dword ptr .supervisor ! ret
;====== ================
xiosif: ; XIOS Interface
;====== ================
mov si,mod_entry
callf dword ptr xiosmod[si] ! ret


View File

@@ -0,0 +1,72 @@
;*****************************************************
;*
;* 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


View File

@@ -0,0 +1,44 @@
include cpyright.def
;*****************************************************
;*
;* MP/M-86 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 ldtab.def
eject ! include char.def
eject ! include init.sup
eject ! include idle.sup
eject ! include tick.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.fmt
eject ! end


View File

@@ -0,0 +1,154 @@
;*****************************************************
;*
;* SUPERVISOR INTERFACE ROUTINES
;*
;*****************************************************
;=========
user_entry:
;=========
; User Entry Point - enter here from a INT 224
;
; REGISTER USAGE
; INPUT OUTPUT
; ----- ------
; CL - Function Code AX - Copy of BX
; DL - Byte Param BX - Return
; DX - Word Param CX - Error Code
; ES - Segment Return
;
; SETUP FOR ENTRY POINTS
; ----------------------
; contents of users stack
; Flags
; CS
; IP <- u_stack_ss,_sp
; in u_stack of uda:
; DS
; user_ret <- SS,SP
; DS = Sysdat Segment
; ES -> user_data_area
; BX -> pd address
; DX -> function parameter
; u_wrkseg == user's DS
; u_retseg == user's ES
;initialize critical areas
cld ! mov di,ds ;DI=user's DSEG
mov ds,sysdat ! mov bx,rlr ;BX=pd address
mov ax,es ! mov es,p_uda[bx] ;ES=uda
cmp u_insys,0 ! jne noswt
mov u_stack_ss,ss ;switch stacks
mov u_stack_sp,sp
mov bp,es ! mov ss,bp
mov sp,ulen
jmps uecont
noswt: push u_wrkseg
uecont: inc u_insys
;enable interrupts if intflag
cmp intflag,0 ! je noints
sti
noints: ;initialized non-critical areas
mov u_retseg,ax
mov u_wrkseg,di
mov ch,0 ! call func ; execute function
mov ax,bx ; for INTEL's PL/M
mov ds,u_wrkseg ! cli
dec u_insys
cmp u_insys,0 ! jne nstk
mov ss,u_stack_ss ; restore user's stack
mov sp,u_stack_sp
jmps ueout
nstk: pop u_wrkseg
ueout: mov es,u_retseg
iret ; back to user
func: ; call system function
;---- -----------------------
; input: CH = module (for explicit module function)
; bypassing network check...
; 0 if User function.
; network check is done
; CL = function #
; DX = arg
mov u_func,cl
func1: cmp ch,0 ! je userf
mov al,ch ! mov ch,0
jmps inmod
userf: mov si,cx ! shl si,1 ! add si,cx
add si,offset sysent
test ent_flag[si],ef_network ! jz nonet
test module_map,netmod_bit ! jz nonet
push si ! callf dword ptr .netmod ! pop si
cmp al,true ! jne nonet
mov si,0 ! mov ax,bx ! ret
nonet: mov cl,ent_func[si] ! mov ch,0
mov al,ent_mod[si]
;AL=mod,CL=func,CH=0
inmod: cmp al,sup ! jne gofar
shl cx,1 ! mov si,cx
jmp cs:supfunc[si]
gofar: push cx ! mov cx,ax ! dec cl
mov al,module_map ! shr al,cl
and al,1 ! jnz goodmod
pop cx ! mov cx,e_not_implemented
mov bx,0ffffh ! mov ax,bx ! ret
goodmod:mov ch,0 ! mov si,cx
mov cl,3 ! shl si,cl ! pop cx
callf dword ptr module_table[si]
ret
;=====
entry:
;=====
; Supervisor module entry point
cmp cl,f_flagset ! jne entry_notfs
mov cx,f_inflagset
call func1 ! mov ax,bx ! retf
entry_notfs:
call mpmif ! retf
;=====
mpmif:
;=====
push u_wrkseg
mov al,u_func ! push ax
mov u_wrkseg,ds
mov ds,sysdat
call func
mov ds,u_wrkseg
pop ax ! mov u_func,al
pop u_wrkseg
mov ax,bx
ret
;======
xiosif:
;======
callf dword ptr .xiosmod ! ret
;*****************************************************
;*
;* Supervisor function table
;*
;*****************************************************
supfunc dw not_implemented ; 0-not implemented
dw bad_entry ; 1-bad function number
dw version_entry ; 2-(12)get version
dw callbios_entry ; 3-(50)call bios
dw load_entry ; 4-(59)user load function
dw clicmd_entry ; 5-(150)CLI
dw rpl_entry ; 6-(151)Call RPL
dw parse_entry ; 7-(152)parse filename
dw sysdat_entry ; 8-(154)get sysdat addr
dw tod_entry ; 9-(155)get tod addr
dw load ; 10-load function
dw mpmversion_entry; 11-MP/M version number
dw chain_entry ; 12-(47)Program Chain
dw serial_entry ; 13-(107)return serial
dw cload_entry ; 14-chain load function


View File

@@ -0,0 +1,18 @@
eject ! include cpyright.def
;*****************************************************
;*
;* System Data Area - Initialized Data
;*
;*****************************************************
eject ! include system.def
eject ! include pd.def
eject ! include qd.def
eject ! include modfunc.def
eject ! include system.dat
eject
cpm equ false
mpm equ true
include data.bdo
eject ! end


View File

@@ -0,0 +1,201 @@
;*****************************************************
;*
;* System Data Area
;*
;*****************************************************
DSEG
org 0
;
;This data is initialized by GENSYS
;
;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 $)
rw 4
rtmmod equ (offset $)
rw 4
memmod equ (offset $)
rw 4
ciomod equ (offset $)
rw 4
bdosmod equ (offset $)
rw 4
xiosmod equ (offset $)
rw 4
netmod equ (offset $)
rw 4
dispatcher equ (offset $)
rw 2
rtm_pdisp equ (offset $)
rw 2
; location in memory of MP/M-86
mpmseg rw 1 ;1st parag. of MP/M
rspseg rw 1 ;segment of first RSP
endseg rw 1 ;1st parag. outside of MP/M
module_map rb 1 ;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 GENSYS questions
ncns rb 1 ;# system console devices
nlst rb 1 ;# system list devices
nccb rb 1 ;# character control blocks
nflags rb 1 ;# flags
srchdisk rb 1 ;default search disk
mmp rw 1 ;Max Memory per process
nslaves rb 1 ;Number of Network requestors
dayfile rb 1 ;if 0ffh, display command info
tempdisk rb 1 ;Temporary Disk
tickspersec rb 1 ;number of ticks per second
; data lists created by GENSYS
free_root rw 1 ;locked unused list
ccb rw 1 ;addr. Console Ctrl Blk Table
flags rw 1 ;addr. Flag Table
mdul rw 1 ;Mem descr. Unused List
mfl rw 1 ;Memory Free List
pul rw 1 ;Proc. descr. Unused List
qul rw 1 ;QCB Unused List
qmau rw 4 ;MAU for queue buffer
;
;This data is initialized at Assembly time
;
rlr rw 1 ;Ready List Root
dlr rw 1 ;Delay List Root
drl rw 1 ;Dispatcher Ready List
plr rw 1 ;Poll List Root
slr rw 1 ;Swap List Root
thrdrt rw 1 ;Process Thread Root
qlr rw 1 ;Queue List Root
mal rw 1 ;Memory Alloc List
version rw 1 ;addr. version str in SUP code segment
vernum rw 1 ;MPM-86 w/BDOS v3.0
mpmvernum rw 1 ;MPM-86 Version 1.0
tod rb 0 ;Time of Day Structure
tod_day rw 1
tod_hr rb 1
tod_min rb 1
tod_sec rb 1
ncondev rb 1 ;# XIOS consoles
nlstdev rb 1 ;# XIOS list devices
nciodev rb 1 ;# character i/o devices
; supported by XIOS.
;syslrec
rw 1 ;Total Locked records
;syslfil
rw 1 ;Total Open files
lock_max rb 1 ;Max locked recs/process
rb 1
open_max rb 1 ;Max Open files/process
rb 1
;sysltot
rw 1 ;Total Locked List records
rw 8 ;Reserved
sysent rb 256*3
; System MX queues (preinitialized)
mxloadqd rb 28
mxloadqpb rb 16
mxcliqd rb 28
mxcliqpb rb 16
mxmemqd rb 28
mxmemqpb rb 16
; Data Used by Load Program
load_dma rb dskrecl
load_uda rw 1
load_lstk rw 1
load_basep rw 1
load_8080 rb 1
load_nrelsegs rb 1
load_nldtabents rw 1
load_pd rw 1
load_fcb rw 1
load_maxwanted rw 1
load_minwanted rw 1
load_indma rw 1
load_chain rb 1
ldtab rb ldtabsiz
;
; Data Used by Send Cli Command
;
cli_dma rb dskrecl ;dma buffer
cli_dma_ofst rw 1
cli_dma_seg rw 1
cli_chain rb 1
cli_term rb 1
cli_pflag rw 1
cli_net rb 1 ;net
cli_ppd rw 1 ;parent PD
cli_cmdtail rb 130 ;command sent
cli_fcb rb fcblen+1 ;internal FCB
cli_cuspqpb rb 16
cli_acb rb 12
cli_pcb rw 2
cli_pd rw 1 ;pd of load prog
cli_err rw 1 ;error return
cli_bpage rw 1
cli_lddsk rb 1 ;load disk
cli_cns rb 1 ;pd.p_cns save
cli_user rb 1 ;pd.p_dsk save
cli_dsk rb 1 ;pd.p_user save
cli_err_mode rb 1 ;u_error_mode save
cli_dfil rb 1 ;flag for dayfile info
;
;System Initialization Variables
;
;User Data Area of Init process
org ((offset $)+0fh) AND 0fff0h
inituda rb ulen
org ((offset $)+0fh) AND 0fff0h
idleuda rb ulen
org ((offset $)+0fh) AND 0fff0h
tickuda rb ulen
initpd rb pdlen
idlepd rb pdlen
tickpd rb pdlen
rw 21
idle_tos rw 3
rw 21
tick_tos rw 3
rw 39
init_tos rw 0
rw 48
dsptchtos rw 0
indisp rb 1 ;?currently in dispatch?
intflag rb 1 ;if 0, interrupts not enabled
es_sav rw 1
bx_sav rw 1
mxmemowner rw 1
mxmemcount rb 1


View File

@@ -0,0 +1,34 @@
;*****************************************************
;*
;* System Data Area
;*
;*****************************************************
org 00h
supmod rw 2
org 038h
dispatcher equ (offset $)
org 040h
mpmseg rw 1
org 044h
endseg rw 1
org 068h
rlr rw 1 ;Ready List Root
org 072h
thrdrt rw 1 ;Process Thread Root
qlr rw 1 ;Queue List Root
org 078h
version rw 1 ;addr. version str in SUP code segment
vernum rw 1 ;MPM-86 w/BDOS v3.0
mpmvernum rw 1 ;MPM-86 Version 1.0
tod rb 5 ;Time of Day Structure
org 01000h


View File

@@ -0,0 +1,80 @@
;*****************************************************
;*
;* SYSTEM ENTRY FUNCTIONS
;*
;*****************************************************
;========== =========================
poll_entry: ; Poll device - DL=device
;========== =========================
mov bx,rlr
mov p_stat[bx],ps_poll
mov u_dparam,dx
mov bx,0 ! mov cx,bx
jmp dsptch
;=========== ===================
delay_entry: ;Delay - DX = ticks
;=========== ===================
mov bx,rlr
mov p_stat[bx],ps_delay
mov u_dparam,dx
mov bx,0 ! mov cx,bx
jmp dsptch
;=============== ==============
dispatch_entry: ;Call dispatch
;=============== ==============
mov bx,0 ! mov cx,bx
jmp pdisp
;=============== ===========================
set_prior_entry: ;Set Priority - DX=priority
;=============== ===========================
mov bx,rlr
mov p_prior[bx],dl
mov bx,0 ! mov cx,bx
jmp pdisp
;======== ==================
pd_entry: ;Return addr of PD
;======== ==================
mov u_retseg,ds
mov bx,rlr
mov cx,0 ! ret
;================ ============================
creat_proc_entry: ;Create Process - DX->new PD
;================ ============================
call proc_creat ! jmp pdisp
;=========== ==============================
sleep_entry: ;Put Calling PD on System List
;=========== ==============================
mov bx,rlr
mov u_dparam,dx
mov al,p_stat[bx] ! mov p_scratch[bx],al
mov p_stat[bx],ps_sleep
jmp dsptch
;============ ==============================
wakeup_entry: ;wakeup top PD in System List
;============ ==============================
pushf ! cli
mov bx,dx ! mov si,[bx]
cmp si,0 ! je wke_out
mov ax,p_link[si] ! mov [bx],ax
mov ax,drl ! mov p_link[si],ax
mov drl,si
mov p_stat[si],ps_run
call pdisp
wke_out:popf ! ret


View File

@@ -0,0 +1,88 @@
;*****************************************************
;*
;* SYSTEM ENTRY FUNCTIONS
;*
;*****************************************************
;=============== ==========================
not_implemented: ; Function not implemented
;=============== ==========================
mov cx,e_not_implemented
mov bx,0ffffh ! ret
;========= =========================
bad_entry: ; Illegal System Function
;========= =========================
mov cx,e_bad_entry
mov bx,0ffffh ! ret
;============= ===============
version_entry: ; Get Version #
;============= ===============
mov bx,vernum ! sub cx,cx ! ret
;================ ====================
mpmversion_entry: ; Get MP/M Version #
;================ ====================
mov bx,mpmvernum ! sub cx,cx ! ret
;============== ==================
callbios_entry: ; Direct BIOS call
;============== ==================
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 mpmif
goxios: cmp al,7 ! jbe gx1 ;7=reader input
cmp al,15 ! je gx1 ;15=list status
mov bx,0ffffh ! mov cx,bx ! 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: mov dl,p_lst[bx]
cmp al,15 ! jne jxio
mov cl,dl
jxio: sub al,2 ! mov ah,0
jmp xiosif
;============ ==============================
sysdat_entry: ; Ret Addr of System Data Area
;============ ==============================
mov u_retseg,ds
sub bx,bx ! mov cx,bx ! ret
;========= ============================
tod_entry: ; 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 movs al,al
pop es ! sub cx,cx ! mov bx,cx ! ret
;============ ======================
serial_entry: ; 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
sub cx,cx ! mov bx,cx ! ret


View File

@@ -0,0 +1,694 @@
;*****************************************************
;*
;* System Data Area
;*
;*****************************************************
DSEG
org 0
;
;This data is initialized by GENSYS
;
;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 0d73h,0,0d70h,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
mpmseg dw 1008h ;1st parag. of MP/M
rspseg dw 0 ;segment of first RSP
endseg dw 0 ;1st parag. outside of MP/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 GENSYS 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 0ffffh ;Max Memory per process
nslaves db 0 ;Number of network requestors
dayfile db 0ffh ;if 0ffh,display command info
tempdisk db 0 ;Temporary disk
tickspersec db 60 ;Number of ticks per second
; data lists created by GENSYS
free_root dw 0 ;locked unused list
ccb dw 0 ;addr. Console Ctrl Blk Table
flags dw 0 ;addr. Flag Table
mdul dw 030h ;Mem descr. Unused List
mfl dw 0 ;Memory Free List
pul dw 020h ;Proc. descr. Unused List
qul dw 020h ;QCB Unused List
; MAU for queue buffer info
qmau dw 0 ;link
dw 0 ;start segment
dw 200h ;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
slr dw 0 ;Swap List Root
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
vernum dw 01130h ;MPM-86 w/BDOS v3.0
mpmvernum dw 01120h ;MPM-86 V1.0
; Time of Day Structure
tod rw 0
tod_day dw 0554H ;day since 1/1/78 (5 Oct 81)
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.
syslrec dw 32 ; Total System Locked Records
syslfil dw 32 ; Total System Open Files
lock_max db 16,0 ; Max Locked Records/process
open_max db 16,0 ; Max Open Files/process
sysltot dw 48 ; Total Lock List Items
dw 0,0,0,0 ; RESERVED
dw 0,0,0,0 ; RESERVED
; SYSENT Table - MP/M-86 system function information
; The supervisor calls the appropriate module
; through this table.
;
; +-------+-------+-------+
; | module| func #| flags |
; +-------+-------+-------+
;
; module - module number
; func # - function to call within module
; flags - 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.
; standard CPM-2 functions
; module func flags
sysent db rtm, 0, 0 ; 0-system reset
db cio, 0, 0 ; 1-conin
db cio, 1, 0 ; 2-conout
db cio, 2, 0 ; 3-raw conin
db cio, 3, 0 ; 4-raw conout
db cio, 4, 0 ; 5-list out
db cio, 5, 0 ; 6-raw conio
db sup, 0, 0 ; 7-getiobyte
db sup, 0, 0 ; 8-setiobyte
db cio, 6, 0 ; 9-conwrite
db cio, 7, 0 ; 10-conread
db cio, 8, 0 ; 11-constat
db sup, 2, 0 ; 12-get version
db bdos, 0, 0 ; 13-diskreset
db bdos, 1, 0 ; 14-diskselect
db bdos, 2, 0 ; 15-file open
db bdos, 3, 0 ; 16-file close
db bdos, 4, 0 ; 17-search first
db bdos, 5, 0 ; 18-search next
db bdos, 6, 0 ; 19-file delete
db bdos, 7, 0 ; 20-file read seq
db bdos, 8, 0 ; 21-file write seq
db bdos, 9, 0 ; 22-file make
db bdos, 10, 0 ; 23-file rename
db bdos, 11, 0 ; 24-login vector
db bdos, 12, 0 ; 25-get def disk
db bdos, 13, 0 ; 26-set dma
db bdos, 14, 0 ; 27-get alloc vector
db bdos, 15, 0 ; 28-write protect
db bdos, 16, 0 ; 29-get r/0 vector
db bdos, 17, 0 ; 30-set file attr.
db bdos, 18, 0 ; 31-get disk parm block
db bdos, 19, 0 ; 32-user code
db bdos, 20, 0 ; 33-file read random
db bdos, 21, 0 ; 34-file write random
db bdos, 22, 0 ; 35-file size
db bdos, 23, 0 ; 36-set random record
db bdos, 24, 0 ; 37-reset drive
db bdos, 25, 0 ; 38-access drive
db bdos, 26, 0 ; 39-free drive
db bdos, 27, 0 ; 40-file write random w/zero fill
;CPM-3 extensions
db bdos, 28, 0 ; 41-Test and Write
db bdos, 29, 0 ; 42-Lock Record
db bdos, 30, 0 ; 43-Unlock Record
db bdos, 31, 0 ; 44-Set Multi-sector
db bdos, 32, 0 ; 45-Set Bdos Error Mode
db bdos, 33, 0 ; 46-Get Disk Free Space
db sup, 12, 0 ; 47-Chain to Program
db bdos, 35, 0 ; 48-Flush Buffers
db sup, 1, 0 ; 49-
;CPM-86 extensions
db sup, 3, 0 ; 50-call xios
db bdos, 36, 0 ; 51-set dma base
db bdos, 37, 0 ; 52-get dma
db mem, 0, 0 ; 53-get max mem
db mem, 1, 0 ; 54-get abs max mem
db mem, 2, 0 ; 55-alloc mem
db mem, 3, 0 ; 56-alloc abs mem
db mem, 4, 0 ; 57-free mem
db mem, 5, 0 ; 58-free all mem
db sup, 4, 0 ; 59-load
db sup, 1, 0 ; 60-
db sup, 1, 0 ; 61-
db sup, 1, 0 ; 62-
db sup, 1, 0 ; 63-
;CP/NET functions
db net, 64, 0 ; 64-network login
db net, 65, 0 ; 65-network logoff
db net, 66, 0 ; 66-network send msg
db net, 67, 0 ; 67-network rcv msg
db net, 68, 0 ; 68-network status
db net, 69, 0 ; 69-get network config addr
db sup, 1, 0 ; 70-
db sup, 1, 0 ; 71-
db sup, 1, 0 ; 72-
db sup, 1, 0 ; 73-
db sup, 1, 0 ; 74-
db sup, 1, 0 ; 75-
db sup, 1, 0 ; 76-
db sup, 1, 0 ; 77-
db sup, 1, 0 ; 78-
db sup, 1, 0 ; 79-
db sup, 1, 0 ; 80-
db sup, 1, 0 ; 81-
db sup, 1, 0 ; 82-
db sup, 1, 0 ; 83-
db sup, 1, 0 ; 84-
db sup, 1, 0 ; 85-
db sup, 1, 0 ; 86-
db sup, 1, 0 ; 87-
db sup, 1, 0 ; 88-
db sup, 1, 0 ; 89-
db sup, 1, 0 ; 90-
db sup, 1, 0 ; 91-
db sup, 1, 0 ; 92-
db sup, 1, 0 ; 93-
db sup, 1, 0 ; 94-
db sup, 1, 0 ; 95-
db sup, 1, 0 ; 96-
db sup, 1, 0 ; 97-
db sup, 1, 0 ; 98-
db sup, 1, 0 ; 99-
;CP/M-3 extensions
db bdos, 38, 0 ;100-Set Dir Label
db bdos, 39, 0 ;101-Return Dir Label
db bdos, 40, 0 ;102-Read File XFCB
db bdos, 41, 0 ;103-Write File XFCB
db bdos, 42, 0 ;104-Set Date and Time
db bdos, 43, 0 ;105-Get Date and Time
db bdos, 44, 0 ;106-Set Default Password
db sup, 13, 0 ;107-Return Serial Number
db sup, 1, 0 ;108-
db sup, 1, 0 ;109-
db sup, 1, 0 ;110-
db sup, 1, 0 ;111-
db sup, 1, 0 ;112-
db sup, 1, 0 ;113-
db sup, 1, 0 ;114-
db sup, 1, 0 ;115-
db sup, 1, 0 ;116-
db sup, 1, 0 ;117-
db sup, 1, 0 ;118-
db sup, 1, 0 ;119-
db sup, 1, 0 ;120-
db sup, 1, 0 ;121-
db sup, 1, 0 ;122-
db sup, 1, 0 ;123-
db sup, 1, 0 ;124-
db sup, 1, 0 ;125-
db sup, 1, 0 ;126-
db sup, 1, 0 ;127-
; MP/M functions
db mem, 6, 0 ;128-abs mem req
db mem, 6, 0 ;129-rel mem req
db mem, 7, 0 ;130-mem free
db rtm, 1, 0 ;131-poll device
db rtm, 2, 0 ;132-flag wait
db rtm, 3, 0 ;133-flag set
db rtm, 4, 0 ;134-queue make
db rtm, 5, 0 ;135-queue open
db rtm, 6, 0 ;136-queue delete
db rtm, 7, 0 ;137-queue read
db rtm, 8, 0 ;138-cond. queue read
db rtm, 9, 0 ;139-queue write
db rtm, 10, 0 ;140-cond. queue write
db rtm, 11, 0 ;141-delay
db rtm, 12, 0 ;142-dispatch
db rtm, 13, 0 ;143-terminate
db rtm, 14, 0 ;144-create process
db rtm, 15, 0 ;145-set priority
db cio, 9, 0 ;146-console attach
db cio, 10, 0 ;147-console detach
db cio, 11, 0 ;148-set def console
db cio, 12, 0 ;149-console assign
db sup, 5, 0 ;150-CLI
db sup, 6, 0 ;151-call RPL
db sup, 7, 0 ;152-parse filename
db cio, 13, 0 ;153-get def console
db sup, 8, 0 ;154-sysdat addr
db sup, 9, 0 ;155-time of day
db rtm, 16, 0 ;156-get PD addr
db rtm, 17, 0 ;157-abort process
; MPM II extensions
db cio, 15, 0 ;158-attach list
db cio, 16, 0 ;159-detach list
db cio, 17, 0 ;160-set list dev
db cio, 18, 0 ;161-Cond. Attach list
db cio, 19, 0 ;162-Cond. Attach Console
db sup, 11, 0 ;163-MP/M Version Number
db cio, 20, 0 ;164-get list dev
db sup, 1, 0 ;165-
db sup, 1, 0 ;166-
db sup, 1, 0 ;167-
db sup, 1, 0 ;168-
db sup, 1, 0 ;169-
db sup, 1, 0 ;170-
db sup, 1, 0 ;171-
db sup, 1, 0 ;172-
db sup, 1, 0 ;173-
db sup, 1, 0 ;174-
db sup, 1, 0 ;175-
db sup, 1, 0 ;176-
db sup, 1, 0 ;177-
db sup, 1, 0 ;178-
db sup, 1, 0 ;179-
db sup, 1, 0 ;180-
db sup, 1, 0 ;181-
db sup, 1, 0 ;182-
db sup, 1, 0 ;183-
db sup, 1, 0 ;184-
db sup, 1, 0 ;185-
db sup, 1, 0 ;186-
db sup, 1, 0 ;187-
db sup, 1, 0 ;188-
db sup, 1, 0 ;189-
db sup, 1, 0 ;190-
db sup, 1, 0 ;191-
;MP/M-86 extensions
db sup, 1, 0 ;192-set signal
db sup, 1, 0 ;193-signal process
db sup, 1, 0 ;194-wait for process
db sup, 1, 0 ;195-open std file
db sup, 1, 0 ;196-close std file
db sup, 1, 0 ;197-read std file
db sup, 1, 0 ;198-write std file
db sup, 1, 0 ;199-flush std file
db sup, 1, 0 ;200-mimic std file
db sup, 1, 0 ;201-make std file
db sup, 1, 0 ;202-
db sup, 1, 0 ;203-
db sup, 1, 0 ;204-
db sup, 1, 0 ;205-
db sup, 1, 0 ;206-
db sup, 1, 0 ;207-
db sup, 1, 0 ;208-
db sup, 1, 0 ;209-
db sup, 1, 0 ;210-
db sup, 1, 0 ;211-
db sup, 1, 0 ;212-
db sup, 1, 0 ;213-
db sup, 1, 0 ;214-
db sup, 1, 0 ;215-
db sup, 1, 0 ;216-
db sup, 1, 0 ;217-
db sup, 1, 0 ;218-
db sup, 1, 0 ;219-
db sup, 1, 0 ;220-
db sup, 1, 0 ;221-
db sup, 1, 0 ;222-
db sup, 1, 0 ;223-
db sup, 1, 0 ;224-
db sup, 1, 0 ;225-
db sup, 1, 0 ;226-
db sup, 1, 0 ;227-
db sup, 1, 0 ;228-
db sup, 1, 0 ;229-
db sup, 1, 0 ;230-
db sup, 1, 0 ;231-
db sup, 1, 0 ;232-
db sup, 1, 0 ;233-
db sup, 1, 0 ;234-
db sup, 1, 0 ;235-
db sup, 1, 0 ;236-
db sup, 1, 0 ;237-
db sup, 1, 0 ;238-
db sup, 1, 0 ;239-
db sup, 1, 0 ;240-
db sup, 1, 0 ;241-
db sup, 1, 0 ;242-
db sup, 1, 0 ;243-
db sup, 1, 0 ;244-
db sup, 1, 0 ;245-
db sup, 1, 0 ;246-
db sup, 1, 0 ;247-
db sup, 1, 0 ;248-
db sup, 1, 0 ;249-
db sup, 1, 0 ;250-
db sup, 1, 0 ;251-
db sup, 1, 0 ;252-
db sup, 1, 0 ;253-
db sup, 1, 0 ;254-
db sup, 1, 0 ;255-
; Initialized Queues
mxloadqd dw mxcliqd
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 '
mxcliqd dw mxmemqd ;link
db 0,0 ;net,org
dw qf_keep+qf_mx ;flags
db 'MXcli ' ;name
dw 0,1,0,0,1,0,0
mxcliqpb db 0,0
dw mxcliqd,1,0
db 'MXcli ' ;name
mxmemqd dw 0 ;link
db 0,0 ;net,org
dw qf_keep+qf_mx ;flags
db 'MXmemory' ;name
dw 0,1,0,0,1,0,0
mxmemqpb db 0,0
dw mxmemqd,1,0
db 'MXmemory'
; Data Used by Load Program
load_dma rb dskrecl
load_uda dw 0
load_lstk dw 0
load_basep dw 0
load_8080 db 0
load_nrelsegs db 0
load_nldtabents dw 0
load_pd dw 0
load_fcb dw 0
load_maxwanted dw 0
load_minwanted dw 0
load_indma dw 0
load_chain db 0
ldtab rb ldtabsiz
;
; Data Used by Send Cli Command
;
cli_dma rb dskrecl ;dma buffer
cli_dma_ofst rw 1
cli_dma_seg rw 1
cli_chain rb 1
cli_term rb 1
cli_pflag rw 1
;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
;
;User Data Area of Init process
org ((offset $)+0fh) AND 0fff0h
inituda rb ulen
;User Data Area of Idle process
org ((offset $)+0fh) AND 0fff0h
idleuda rw 1 ;dparam
dw 0 ;dma
rw 24
dw offset idle_tos ;stack offset
rw 13
dw 0,0 ;init cs,ds
dw 0,0 ;init es,ss
rb ulen-((offset $)-(offset idleuda))
;User Data Area of Tick process
org ((offset $)+0fh) AND 0fff0h
tickuda rw 1 ;dparam
dw 0 ;dma
rw 24
dw offset tick_tos ;stack offset
rw 13
dw 0,0 ;init cs,ds
dw 0,0 ;init es,ss
rb ulen-((offset $)-(offset tickuda))
;Init Process Descriptor
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
;Idle process descriptor
idlepd dw tickpd ;link
dw 0 ;thread
db ps_run ;status
db 255 ;prior
dw pf_sys+pf_kernal+pf_keep
;flag
db 'Idle ' ;name
dw ((offset idleuda)/10h) ;uda
db 0,0 ;disk,user
db 0,0 ;ldsk,luser
dw 0,0,0 ;mem,dvract,wait
db 0,0 ;org,net
dw 0 ;parent
db 0,0,0,0 ;console,abort,cin,cout
db 0,0,0,0 ;lst,sf3,4,5
rb 4 ;reserved
dw 0,0 ;pret,scratch
;Tick process descriptor
tickpd dw 0 ;link
dw 0 ;thread
db ps_run ;status
db 10 ;prior
dw pf_sys+pf_kernal+pf_keep
;flag
db 'Tick ' ;name
dw ((offset tickuda)/10h) ;uda
db 0,0,0,0 ;disk,user,ldsk,luser
dw 0,0,0 ;mem,dvract,wait
db 0,0 ;org,net
dw 0 ;parent
db 0,0,0,0 ;cns,abort,cin,cout
db 0,0,0,0 ;lst,sf3,4,5
rb 4 ;reserved
dw 0,0 ;pret,scratch
;Idle Stack - ready for a RETF
; from RTM
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
idle_tos dw unknown ;start address
dw unknown ;segment
dw 0200h ;init flags
;Tick 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
tick_tos dw unknown ;start address
dw unknown ;segment
dw 0200h ;init flags
;Init 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
init_tos rw 0
; RTM data
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
es_sav dw 0
bx_sav dw 0
; CIO Data
mxmemowner dw 0
mxmemcount db 0


View File

@@ -0,0 +1,26 @@
;*****************************************************
;*
;* 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
mpmint equ 224 ; int vec for mpm ent.
debugint equ mpmint+1 ; int vec for debuggers
ulen equ 0100h ; size of uda
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


View File

@@ -0,0 +1,41 @@
;*****************************************************
;*
;* TICK Process
;*
;*****************************************************
;======
notick: ;NO ONE ON DELAY LIST
;======
mov bx,rlr ! mov es,p_uda[bx]
mov u_wrkseg,ds
mov al,io_stopclk ! call xiosif
tick: ;SOMEONE MAY BE ON DELAY LIST
;----
; flag wait on the TICK flag
mov dx,flag_tick ! mov cx,f_flagwait
int mpmint
; see if anyone delaying
pushf ! cli
mov bx,dlr
cmp bx,0 ! jz drl_empty
; decrement # of ticks to wait
; see if done waiting
dec p_wait[bx] ! jnz next_tick
; our process is done waiting
enddelay: 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_empty
cmp p_wait[si],0 ! jne next_tick
mov bx,si ! jmps enddelay
next_tick: popf ! jmps tick
drl_empty:
popf ! jmps notick

View File

@@ -0,0 +1,65 @@
;*****************************************************
;*
;* 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.
;*
;*****************************************************
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 10 ; save int 0-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_mpm_ip rw 1 ; MPM vec save
u_mpm_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


View File

@@ -0,0 +1,32 @@
;*****************************************************
;*
;* 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
mov cx,0
mov si,m_link[bx] ! mov mdul,si
mov m_link[bx],0 ! mov m_start[bx],0
mov m_length[bx],0 ! mov m_plist[bx],0
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


View File

@@ -0,0 +1,45 @@
;*****************************************************
;*
;* XIOS function jump table offsets
;*
;*****************************************************
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
;*****************************************************
;*
;* 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