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

1142 lines
17 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'MP/M II V2.0 Dispatcher'
name 'dsptch'
dseg
@@dsptch:
public @@dsptch
cseg
;dsptch:
@dsptch:
public @dsptch
;do;
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
;/*
; Common Literals
;*/
; declare true literally '0FFFFH';
; declare false literally '0';
; declare forever literally 'while true';
; declare boolean literally 'byte';
; declare enter$region literally
; 'disable';
;/*
; Proces Literals
;*/
; declare process$header literally
; 'structure (pl address,
; status byte,
; priority byte,
; stkptr address';
; declare bdos$save literally
; 'disk$set$dma address,
; disk$slct byte,
; dcnt byte,
; searchl byte,
; searcha address,
; thread address,
; scratch (14) byte)';
; declare process$descriptor literally
; 'process$header,
; name (8) byte,
; console byte,
; memseg byte,
; b address,
; bdos$save';
; declare rtr$status literally '0',
; dq$status literally '1',
; nq$status literally '2',
; poll$status literally '3',
; FlgWt$status literally '4',
; Delay$status literally '5',
; Sleep$status literally '6',
; Terminate$status literally '7',
; Set$Prior$status literally '8',
; Dispatch$status literally '9',
; Attach$status literally '10',
; Detach$status literally '11',
; Set$cns$status literally '12',
; Att$list$status literally '13',
; Det$list$status literally '14';
;/*
; Memmgr Literals
;*/
; declare memory$descriptor literally
; 'structure (base byte,
; size byte,
; attrib byte)';
;/*
; Th Literals
;*/
; declare nmb$consoles literally '16';
;/*
; Bdosi Externals
;*/
; xios$pl:
extrn xiospl
; procedure (device) byte external;
; declare device byte;
; end xios$pl;
; xios$ms:
extrn xiosms
; procedure (memsegadr) external;
; declare memsegadr address;
; end xios$ms;
; str$clk:
extrn strclk
; procedure external;
; end str$clk;
;/*
; Flag Externals
;*/
; declare sys$flag (1) address external;
extrn sysflag
;/*
; Memmgr Externals
;*/
; declare memsegtbl (1) memory$descriptor external;
extrn memsegtbl
; user$process:
extrn userprocess
; procedure (pdadr) byte external;
; declare pdadr$address;
; end user$process;
; mem$fr:
extrn memfr
; procedure (mdadr) external;
; declare mdadr address;
; end mem$fr;
;/*
; Th Externals
;*/
; attach:
extrn attach
; procedure (pdadr) external;
; declare pdadr address;
; end attach;
; detach:
extrn detach
; procedure (pdadr) external;
; declare pdadr address;
; end detach;
;/*
; List Externals
;*/
; attlst:
extrn attlst
; procedure (pdadr) external;
; declare pdadr address;
; end attlst;
; detlst:
extrn detlst
; procedure (pdadr) external;
; declare pdadr address;
; end detlst;
;/*
; Release Console & List Externals
;*/
; rlsmx:
extrn rlsmx
; procedure (pdadr) external;
; declare pdadr address;
; end rlsmx;
; rlscon:
extrn rlscon
; procedure (pdadr) external;
; declare pdadr address;
; end rlscon;
; rlslst:
extrn rlslst
; procedure (pdadr) external;
; declare pdadr address;
; end rlslst;
; Ver module externals
;
; remfl:
extrn remfl
; procedure external;
; end remfl;
dseg
; declare rlr address external;
extrn rlr
; declare rlrpd based rlr process$descriptor;
; declare thread$root address external;
extrn thrdrt
; declare drl address external;
extrn drl
; declare drlpd based drl process$descriptor;
; declare plr address external;
extrn plr
; declare dlr address external;
extrn dlr
; declare slr address external;
extrn slr
; declare indisp byte public initial (0);
public indisp
indisp: db 0
; declare dsptch$param address public;
public dparam
dparam:
dsptchparam:
dw 0
; declare pdadr address;
pdadr:
dw 0
; declare pd based pdadr process$descriptor;
; declare pollpointer address;
pollpointer:
dw 0
; declare oldpollptr address;
oldpollptr:
nextthreadptr:
dw 0
; declare oldpoll based oldpollptr address;
; declare next$thread$ptr address at (.oldpollptr);
; declare next$thread based next$thread$ptr address;
; declare pdladr address;
pdladr:
dw 0
; declare pdl based pdladr process$descriptor;
; declare first$time boolean;
;/*
; delay$list$insert:
; The purpose of the delay list insert procedure is to
; place a process descriptor on the delay list. The delay
; list is maintained in such a manner that the tick counts
; in the process descriptor represent the value required to
; produce the specified delay, by adding together all the
; tick counts of the preceding processes on the delay list.
; Entry Conditions:
; Dispatch$param = ticks
; Exit Conditions:
; Note
; *** NOTE *** this procedure assumes that
; a critical region has been entered.
;*/
cseg
; delay$list$insert:
delaylistinsert:
; procedure;
dseg
; declare accum address;
accum:
dw 0
; declare nxtpdladr address;
nxtpdladr:
dw 0
; declare nxtpdl based nxtpdladr address;
;
cseg
; dsptch$param = dsptch$param+1;
xchg ;Note: DE = dsptch$param on entry
inx h
shld dsptchparam
; if dlr = 0 then call strclk;
LHLD DLR
MOV A,H
ORA L
CZ STRCLK
; accum = 0;
LXI H,0H
SHLD ACCUM
; nxtpdladr = .dlr;
LXI H,DLR
@25:
SHLD NXTPDLADR
; do forever;
;
; pdladr = nxtpdl;
MOV E,M
INX H
MOV D,M
XCHG
SHLD PDLADR
; if (nxtpdl = 0) or
XCHG
DCX H
MOV A,M
INX H
ORA M
LXI H,10H
DAD D
push h ;save .pdl.b
jz @25a
XCHG
LHLD ACCUM
CALL PADD
LXI D,DSPTCHPARAM
CALL PSUB
JNC @3
; ((accum + pdl.b) > dsptch$param) then
; do;
@25A:
; pd.pl = nxtpdl;
LHLD NXTPDLADR
MOV C,M
INX H
MOV B,M
DCX H
XCHG
LHLD PDADR
MOV M,C
INX H
MOV M,B
; nxtpdl = pdadr;
DCX H
XCHG
MOV M,E
INX H
MOV M,D
; accum = dsptch$param - accum;
LHLD ACCUM
LXI D,DSPTCHPARAM
CALL PSUB
SHLD ACCUM
; pd.b = accum;
XCHG
LXI B,10H
LHLD PDADR
DAD B
MOV M,E
INX H
MOV M,D
; if pd.pl <> 0 then pdl.b = pdl.b - accum;
LHLD PDADR
MOV A,M
INX H
ORA M
pop d ;DE = .pdl.b
RZ
LHLD ACCUM
call psub
xchg
dcx h
mov m,e
inx h
mov m,d
; return;
RET
; end;
@3:
; accum = accum + pdl.b;
pop d ;DE = .pdl.b
LHLD ACCUM
CALL PADD
SHLD ACCUM
; nxtpdladr = nxtpdl;
LHLD NXTPDLADR
MOV E,M
INX H
MOV D,M
XCHG
; end;
JMP @25
; end;
; end delay$list$insert;
PSUB:
; HL = [DE] - HL
LDAX D
SUB L
MOV L,A
INX D
LDAX D
SBB H
MOV H,A
RET
PADD:
; HL = [DE] + HL
LDAX D
ADD L
MOV L,A
INX D
LDAX D
ADC H
MOV H,A
RET
;/*
; insert$process:
; The purpose of the insert process procedure is to
; place a process desciptor into a list pointed to by a
; passed parameter in priority order. The algorithm
; searches for a process in the list with a lower priority
; (lower priorities have high priority numbers) to make
; the insertion. This ensures that processes of the same
; priority are round-robin scheduled.
; Entry Conditions:
; BC = list root
; DE = process descriptor
; *** NOTE *** this procedure assumes that
; a critical region has been entered.
; Exit Conditions:
; None
;*/
cseg
@5:
MOV B,H
MOV C,L
; insert$process:
inspr:
insertprocess:
; procedure (nxtpdladr,pdadr) public;
public inspr
; declare (nxtpdladr,pdadr) address;
; declare nxtpdl based nxtpdladr address;
; declare pd based pdadr process$descriptor;
; do forever;
; pdladr = nxtpdl;
; BC = NXTPDLADR, DE = PDADR
@27:
LDAX B
MOV L,A
INX B
LDAX B
MOV H,A
; if (nxtpdl = 0) or
ORA L
INX D
INX D
INX D
LDAX D
DCX D
DCX D
DCX D
JZ @27A
; HL = PDLADR
INX H
INX H
INX H
SUB M
DCX H
DCX H
DCX H
JNC @5
; (pd.priority < pdl.priority) then
; do;
; pd.pl = nxtpdl;
@27A:
MOV A,L
STAX D
INX D
MOV A,H
STAX D
DCX D
; nxtpdl = pdadr;
MOV A,D
STAX B
DCX B
MOV A,E
STAX B
; return;
RET
; end;
; nxtpdladr = nxtpdl;
; end;
; end insert$process;
;/*
; dispatch:
; The purpose of the dispatch procedure is to perform the
; action required by the status of the current running
; process, to determine the highest priority ready process,
; and then to give it the processor resource. The procedure
; takes all the processes linked to the dispatcher
; ready list and inserts them into the ready list before
; executing the highest priority ready process.
; Entry Conditions:
; None
; Exit Conditions:
; None
;*/
dseg
svhl: ds 2 ; saved HL
svde: ds 2 ; saved DE
svret: ds 2 ; saved return
svsp: ds 2 ; saved SP
dspstk:
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
cseg
; dispatch:
pdisp:
public pdisp
; Note: This entry point should only be used from an
; interrupt handler, i.e. interrupts disabled.
; rlrpd.status = dispatch
di
shld svhl
lhld rlr
inx h
inx h
mvi m,9
lhld svhl
dispatch:
; procedure public;
public dispatch
; enter$region;
DI
;
; save registers in the Process Desciptor
;
shld svhl
pop h
shld svret
push psw
;
; test for in dispatcher
;
; if not indisp then
lda indisp
ora a
jz notindisp
; do;
pop psw
lhld svret
push h
lhld svhl
; enable;
ei
; return;
ret
; end;
notindisp:
lxi h,0
dad sp
shld svsp
xchg
shld svde
lhld rlr
lxi d,50
dad d
xchg
pop psw
lhld svret
push h
xchg
sphl
lhld svde
xchg
lhld svhl
PUSH PSW
PUSH B
PUSH D
PUSH H
; call svz80;
public dspsvz80
dspsvz80:
jmp noz80save
db 0ddh,0e5h ;Push IX
db 0fdh,0e5h ;Push IY
db 008h ;Ex AF,AF'
db 0d9h ;Exx
push psw
push b
push d
push h
noz80save:
mvi a,0ffh
sta indisp ;set in dipatcher flag
; pdadr = stackptr;
lhld svsp
XCHG
; rlrpd.stkptr = pdadr;
LHLD RLR
; pdadr = rlr;
SHLD PDADR
MOV B,H
MOV C,L
inx h
inx h
inx h
inx h
MOV M,E
INX H
MOV M,D
;
LXI SP,DSPSTK+24
; if rlrpd.status <> rtr$status then rlr = rlrpd.pl;
dcx h
dcx h
dcx h
MOV A,M
ORA A
JZ @7
DCX H
DCX H
MOV E,M
INX H
MOV D,M
XCHG
SHLD RLR
; do case pd.status;
MOV E,A
MVI D,0
LXI H,@29
DAD D
DAD D
MOV E,M
INX H
MOV D,M
LHLD DSPTCHPARAM
XCHG
PCHL
; /* status = 0, Ready to Run */
; do;
; end;
; /* status = 1, DQ */
; do;
@9:
; call insert$process (dsptch$param,pdadr);
; end;
; /* status = 2, NQ */
; do;
@10:
; call insert$process (dsptch$param,pdadr);
MOV H,B
MOV L,C
MOV B,D
MOV C,E
XCHG
; end;
JMP @6
; /* status = 3, Poll */
; do;
@11:
; pd.b = dsptch$param;
LXI H,10H
DAD B
MOV M,E
INX H
MOV M,D
; pd.pl = plr;
LHLD PLR
XCHG
LHLD PDADR
MOV M,E
INX H
MOV M,D
; plr = pdadr;
DCX H
SHLD PLR
; end;
JMP @7
; /* status = 4, Flag Wait */
; do;
@12:
; sys$flag(dsptch$param) = pdadr;
LXI H,SYSFLAG
DAD D
DAD D
MOV M,C
INX H
MOV M,B
; pd.pl = 0;
XRA A
STAX B
INX B
STAX B
; end;
JMP @7
; /* status = 5, Delay */
; do;
@13:
; call delay$list$insert;
CALL DELAYLISTINSERT
; end;
JMP @7
; /* status = 6, Sleep */
; do;
; end;
; /* status = 7, Terminate */
; do;
@15:
; if dsptch$param = 0ffh or /* sys pr. term */
; user$process (pdadr) then
PUSH D
CALL USERPROCESS
POP D
RAR
JC @15A
INR E
JZ @15C
JMP @16
; do;
@15A:
; call mem$fr (.memsegtbl(pd.memseg));
; free memory segment only if BDOS system reset call
LHLD DSPTCHPARAM
INR H
JZ @15C
LXI B,0FH
LHLD PDADR
DAD B
MOV A,M
ora a
jz @15c ;never release OS memory segment
LXI H,MEMSEGTBL
ADD A
ADD A
MOV E,A
MVI D,0
DAD D
MOV B,H
MOV C,L
CALL MEMFR
@15c:
; call rlsmx (pdadr);
lhld pdadr
mov b,h
mov c,l
push b
call rlsmx ; release all owned MX queues
; call rlscon (pdadr);
pop b
push b
CALL rlscon
; call rlslst (pdadr);
pop b
push b
CALL rlslst
; next$thread$ptr = .thread$root;
pop b
LXI H,thrdrt
@30:
; BC = PDADR, HL = NEXTTHREADPTR
; do while (pdladr := next$thread) <> pdadr;
MOV E,M
INX H
MOV D,M
; DE = PDLADR, NEXTTHREAD
MOV A,E
CMP C
JNZ @30A
MOV A,D
CMP B
JZ @31
@30A:
; next$thread$ptr = .pdl.thread;
LXI H,12H
DAD D
; end;
JMP @30
@31:
; next$thread = pdl.thread;
DCX H
XCHG
push h
LXI B,12H
DAD B
MOV A,M
STAX D
INX D
INX H
MOV A,M
STAX D
; call remfl; /* remove locked records & files */
pop b
call remfl
; end;
JMP @7
@16:
; else
; do;
; pd.status = rtr$status;
LHLD PDADR
INX H
INX H
MVI M,0H
; pd.pl = drl;
; drl = pdadr;
; end;
; end;
JMP @19
; /* status = 8, Set Priority */
; do;
@18:
; pd.priority = dsptch$param;
INX B
INX B
INX B
MOV A,E
STAX B
; pd.pl = drl;
; drl = pdadr;
; end;
; JMP @19
@19:
; pd.pl = drl;
lhld drl
xchg
lhld pdadr
mov m,e
inx h
mov m,d
; drl = pdadr;
dcx h
shld drl
jmp @7
; /* status = 9, Dispatch */
; do;
@17:
; call insert$process (.rlr,pdadr);
mov d,b
mov e,c
lxi b,rlr
; end;
JMP @6
; /* status = 10, Attach */
; do;
;@20: (see end of set console)
; call attach (pdadr);
; end;
; /* status = 11, Detach */
; do;
@21:
; call detach (pdadr);
CALL DETACH
; pd.pl = drl;
; drl = pdadr;
; end;
JMP @19
; /* status = 12, Set Console */
; do;
@22:
; call detach (pdadr);
CALL DETACH
; if dsptch$param < nmb$consoles then
LDA DSPTCHPARAM
cpi 16
JNC @7
; do;
; pd.console = dsptch$param;
LXI B,0EH
LHLD PDADR
DAD B
MOV M,A
; call attach (pdadr);
@20:
LHLD PDADR
MOV B,H
MOV C,L
CALL ATTACH
; end;
; end;
JMP @7
; /* status = 13, Attach List */
; do;
@23:
; call attlst (pdadr);
LHLD PDADR
MOV B,H
MOV C,L
call attlst
; end;
; end;
JMP @7
; /* status = 14, Detach List */
; do;
@24:
; call detlst (pdadr);
call detlst
; pd.pl = drl;
; drl = pdadr;
; end;
JMP @19
; end; /* case */
@29:
DW @7
DW @9
DW @10
DW @11
DW @12
DW @13
DW @7
DW @15
DW @18
DW @17
DW @20
DW @21
DW @22
dw @23
dw @24
@6:
CALL INSERTPROCESS
@7:
; /* poll all required devices and place any
; readied processes on the ready list */
; pdadr = .plr;
ei
LXI D,PLR
; pollpointer = plr;
LHLD PLR
; do while pollpointer <> 0;
@36: ; BC = oldpollptr, DE = pdadr, HL = pollpointer
MOV A,H
ORA L
JZ @37
; oldpollptr = pdadr;
MOV B,D
MOV C,E
; pdadr = pollpointer;
MOV D,H
MOV E,L
; pollpointer = pd.pl;
MOV A,M
INX H
MOV H,M
MOV L,A
; if xios$pl (pd.b) then
PUSH B
PUSH D
PUSH H
LXI H,10H
DAD D
MOV C,M
CALL XIOSPL
POP H
POP D
POP B
RAR
JNC @36
; do;
; oldpoll = pollpointer;
MOV A,L
STAX B
INX B
MOV A,H
STAX B
DCX B
PUSH H
; disable;
di
; pd.pl = drl;
lhld drl
xchg
mov m,e
inx h
mov m,d
dcx h
; drl = pdadr;
shld drl
; enable;
ei
POP H
; pdadr = oldpollptr;
MOV D,B
MOV E,C
; end;
; end;
JMP @36
@37:
ei
nop
di
; /* insert all processes on ready list from
; the dispatcher ready list */
; do while drl <> 0;
LHLD DRL
MOV A,H
ORA L
jz @39
; pdadr = drlpd.pl;
MOV E,M
INX H
MOV D,M
xchg
shld drl
xchg
; drlpd.status = rtr$status;
INX H
MVI M,0H
; call insert$process (.rlr,drl);
DCX H
DCX H
XCHG
LXI B,RLR
CALL INSERTPROCESS
; drl = pdadr;
; end;
JMP @37
@39:
; call xios$ms (.memsegtbl(rlrpd.memseg));
lhld rlr
LXI B,0FH
DAD B
MOV A,M
add a
jm @38 ;system process, no xiosms
add a
LXI H,MEMSEGTBL
mov e,a
mvi d,0
dad d
MOV B,H
MOV C,L
CALL XIOSMS
; stackptr = rlrpd.stkptr;
@38:
LHLD RLR
LXI B,4H
DAD B
MOV E,M
INX H
MOV D,M
XCHG
shld svsp
xra a
sta indisp ;clear in dispatcher flag
lhld rlr
lxi d,50-8
dad d
sphl
public dsprsz80
dsprsz80:
jmp noz80restore
lxi d,-12
dad d
sphl
pop h
pop d
pop b
pop psw
db 0d9h ;Exx
db 008h ;Ex AF,AF'
db 0fdh,0e1h ;Pop IY
db 0ddh,0e1h ;Pop IX
noz80restore:
POP H
POP D
POP B
POP PSW
; exit$region;
shld svhl
lhld svsp
sphl
lhld svhl
EI
RET
; end dispatch;
;end dsptch;
end