Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM II/MPM II SOURCE 2/nucleus/xdos.asm
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1284 lines
19 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

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

title 'MP/M II V2.0 Extended Disk Operating System'
name 'xdos'
dseg
@@xdos:
public @@xdos
cseg
;xdos:
@xdos:
public @xdos
;do;
;/*
; Copyright (C) 1979,1980,1981
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 14 Sept 81 by Thomas Rolander
;*/
;$include (common.lit)
;$nolist
;$include (queue.lit)
;$nolist
;$include (proces.lit)
;$nolist
;$include (memmgr.lit)
;$nolist
;$include (datapg.ext)
;$nolist
;$include (proces.ext)
;$nolist
;$include (queue.ext)
;$nolist
;$include (flag.ext)
;$nolist
;$include (memmgr.ext)
;$nolist
;$include (th.ext)
;$nolist
; flshbf:
extrn flshbf
; procedure;
; end flshbf;
; parse$filename:
extrn parsefilename
; procedure (pcb$address) address external;
; declare pcb$address address;
; end parse$filename;
; exitr:
extrn exitr
; procedure external;
; end exitr;
; flgwt:
extrn flgwt
; procedure (flgnmb) byte external;
; declare flgnmb byte;
; end flgwt;
; flgset:
extrn flgset
; procedure (flgnmb) byte external;
; declare flgnmb byte;
; end flgset;
; absrq:
extrn absrq
; procedure (mdadr) byte external;
; declare mdadr address;
; end absrq;
; relrq:
extrn relrq
; procedure (mdadr) byte external;
; declare mdadr address;
; end relrq;
; memfr:
extrn memfr
; procedure (mdadr) byte external;
; declare mdadr address;
; end memfr;
; dispat:
extrn dispat
; procedure external;
; end dispat;
; makeq:
extrn makeq
; procedure (qcbadr) byte external;
; declare qcbadr address;
; end makeq;
; openq:
extrn openq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end openq;
; deletq:
extrn deletq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end deletq;
; readq:
extrn readq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end readq;
; creadq:
extrn creadq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end creadq;
; writeq:
extrn writeq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end writeq;
; cwriteq:
extrn cwriteq
; procedure (uqcbadr) byte external;
; declare uqcbadr address;
; end cwriteq;
; assign:
extrn assign
; procedure (pname) byte external;
; declare pname address;
; end assign;
; declare dparam address external;
extrn dparam
; declare rlr address external;
extrn rlr
; declare drl address external;
extrn drl
; declare dlr address external;
extrn dlr
; declare plr address external;
extrn plr
; declare slr address external;
extrn slr
; declare qlr address external;
extrn qlr
; declare thrdrt address external
extrn thrdrt
; declare nmbcns literally '16';
nmbcns equ 16
; declare cnsatt (1) address external;
extrn cnsatt
; declare lstatt (1) address external;
extrn lstatt
; declare mpmver address external;
extrn mpmver
; declare cnsque (1) address external;
extrn cnsque
; declare tod structure (
extrn tod
; day address,
; hr byte,
; min byte,
; sec byte ) external;
; declare nmbflags byte external;
extrn nmbflags
; declare sysfla (1) address external;
extrn sysfla
; declare nmblst byte external;
extrn nmblst
; declare lstque (1) address external;
extrn lstque
; declare sysdat address external;
extrn sysdat
; declare cli$lqcb address external;
extrn clilqcb
dseg
; declare cli$uqcb userqcbhead
; initial (.cli$lqcb,0);
;cliuqcb: /* This data structure has been moved to the stack */
; dw clilqcb ; pointer
; dw $-$ ; msgadr
; declare rsp$adr address;
rspadr: ds 2
; declare rsp$uqcb userqcb
; initial (0,.rsp$adr,'$$$$$$$$');
rspuqcb:
dw $-$ ; pointer
dw rspadr ; msgadr
db '$$$$$$$$' ; name
; declare cpb$adr address;
cpbadr: ds 2
; declare cpb based cpb$adr structure (
; rsp$name$adr address,
; rsp$param address);
; declare flag$wait$function literally '4';
; declare flag$set$function literally '5';
; declare (svstk,old$drl,old$thread$root) address;
svstk: ds 2
olddrl: ds 2
oldthreadroot:
ds 2
cseg
; xdos:
xdos:
public xdos
; procedure (function,parameter) address reentrant public;
; declare function byte;
; declare parameter address;
; declare ret address;
; declare pd based parameter process$descriptor;
; ret = 0000H;
MOV A,C
; function = function - 128;
SUI 80H
; if function > max$xdos$function then
CPI maxfunc
LXI H,0FFFFH
RNC
; do;
; ret = 0FFFFH;
; end;
; else
; do case function;
CPI 4H
JZ @1 ; SETUP RETURN TO DISPATCH
CPI 5H ; FOR ALL BUT FLAG OP'S
JZ @1
LXI H,DISPAT
PUSH H
@1:
LXI H,EXDOS
PUSH H
MOV B,D
MOV C,E
MOV E,A
MVI D,0
LXI H,@37
DAD D
DAD D
MOV E,M
INX H
MOV D,M
LHLD RLR
INX H
INX H ; HL = .RLR.STATUS
XCHG
PCHL
; /* function = 128, Absolute Memory Request */
; ret = abs$rq (parameter);
; CALL ABSRQ
; /* function = 129, Relocatable Memory Request */
; ret = rel$rq (parameter);
; CALL RELRQ
; /* function = 130, Memory Free */
; call mem$fr (parameter);
; CALL MEMFR
; /* function = 131, Poll Device */
; do;
@7:
; enter$region;
DI
; dsptch$param = parameter;
MOV L,C
MOV H,B
SHLD DPARAM
; rlrpd.status = poll$status;
XCHG
MVI M,3H
; end;
RET
; /* function = 132, Flag Wait */
; ret = flag$wait (parameter);
; CALL FLGWT
; /* function = 133, Flag Set */
; ret = flag$set (parameter);
; CALL FLGSET
; /* function = 134, Make Queue */
; ret = makeq (parameter);
; CALL MAKEQ
; /* function = 135, Open Queue */
; ret = openq (parameter);
; CALL OPENQ
; /* function = 136, Delete Queue */
; ret = deletq (parameter);
; CALL DELETQ
; /* function = 137, Read Queue */
; ret = readq (parameter);
; CALL READQ
; /* function = 138, Conditional Read Queue */
; ret = creadq (parameter);
; CALL CREADQ
; /* function = 139, Write Queue */
; ret = writeq (parameter);
; CALL WRITEQ
; /* function = 140, Conditional Write Queue */
; ret = cwriteq (parameter);
; CALL CWRITEQ
; /* function = 141, Delay */
; do;
@17:
; enter$region;
DI
; dsptch$param = parameter;
MOV L,C
MOV H,B
SHLD DPARAM
; rlrpd.status = delay$status;
XCHG
MVI M,5H
; end;
RET
; /* function = 142, Dispatch */
; do;
@18:
; enter$region;
DI
; rlrpd.status = dispatch$status;
XCHG
MVI M,9H
; end;
RET
; /* function = 143, Terminate */
; do;
@19:
; call flush$buffers;
push b
push d
call flshbf
pop d
pop b
; enter$region;
DI
; dsptch$param = parameter;
MOV L,C
MOV H,B
SHLD DPARAM
; rlrpd.status = terminate$status;
XCHG
MVI M,7H
; end;
RET
; /* function = 144, Create */
; do;
@20:
; enter$region;
DI
; old$drl = drl;
LHLD DRL
SHLD OLDDRL
; old$thread$root = thread$root;
LHLD THRDRT
SHLD OLDTHREADROOT
; drl,
; thread$root = parameter;
MOV L,C
MOV H,B
SHLD DRL
SHLD THRDRT
; do while pd.pl <> 0;
@38:
MOV E,M
INX H
MOV D,M
MOV A,E
ORA D
JZ @39
; pd.thread = pd.pl;
LXI H,12H
DAD B
MOV M,E
INX H
MOV M,D
CALL @39A
; parameter = pd.pl;
MOV B,D
MOV C,E
XCHG
; end;
JMP @38
@39:
; pd.pl = old$drl;
XCHG
LHLD OLDDRL
XCHG
MOV M,D
DCX H
MOV M,E
; pd.thread = old$thread$root;
LHLD OLDTHREADROOT
XCHG
LXI H,12H
DAD B
MOV M,E
INX H
MOV M,D
@39A:
; pd.drvacc = 0;
lxi h,1ch
dad b
xra a
mov m,a
inx h
mov m,a
; pd.multcnt = 1;
lxi h,32h
dad b
mvi m,1
; pd.pdcnt = 0;
inx h
mov m,a
; end;
RET
; /* function = 145, Set Priority */
; do;
@21:
; enter$region;
DI
; dsptch$param = parameter;
MOV L,C
MOV H,B
SHLD DPARAM
; rlrpd.status = set$prior$status;
XCHG
MVI M,8H
; end;
RET
; /* function = 146, Attach */
; do;
@22:
; enter$region;
DI
; rlrpd.status = attach$status;
XCHG
MVI M,0AH
; end;
RET
; /* function = 147, Detach */
; do;
@23:
; enter$region;
DI
; rlrpd.status = detach$status;
XCHG
MVI M,0BH
; end;
RET
; /* function = 148, Set Console */
; do;
@24:
; rlrpd.console = parameter;
lxi h,0eh-02h
dad d ;HL = .rlrpd.console
mov a,m
ani 0f0h
ora c
mov m,a
pop h ;discard EXDOS return
; end;
RET
; /* function = 149, Assign Console */
; ret = assign (parameter);
; CALL ASSIGN
; /* function = 150, Send CLI Command */
; do;
@26:
; +------+
; |msgadr|
; +------+
; Stk Ptr ------->| qptr |
; +------+
; cli$uqcb.msgadr = parameter;
push b
; cli$uqcb.pointer = .cli$lqcb;
lxi h,clilqcb
push h
; ret = writeq (.cli$uqcb);
lxi h,0
dad sp
mov b,h
mov c,l
call WRITEQ
pop h
pop h
ret
; end;
; /* function = 151, Call Resident System Process */
; do;
@27:
POP H ; DISCARD EXDOS RETURN
mov h,b
mov l,c ;HL = .cpb
; cpb$adr = parameter;
mov c,m
inx h
mov b,m ;BC = cpb.name
inx h
mov e,m
inx h
mov d,m ;DE = cpb.param
lxi h,-14
dad sp
sphl ;make room for uqcb+2 on stk
push d
;
; Stack Structure:
;
; +-----------------------+
; | Return Address |
; +-----------------------+
; | |
; uqcb.name(0) - name(7)
; | |
; +-----------------------+
; | uqcb.msgadr | ---+
; +-----------------------+ |
; | uqcb.pointer | |
; +-----------------------+ |
; | (space for .proc) | <--+
; +-----------------------+
; S--->| .cpb.param |
; +-----------------------+
;
mov d,h
mov e,l
inx h
inx h
inx h
inx h
mov m,e
inx h
mov m,d ;uqcb.msgadr <-
inx h
; call move (8,cpb.rsp$name$adr,.rsp$uqcb.name);
mvi e,8
clresploop:
ldax b
mov m,a
inx b
inx h
dcr e
jnz clresploop
; /* open queue having passed procedure name */
; if openq(.rsp$uqcb) <> 0ffh then
lxi b,-12
dad b ;HL = .uqcb
mov b,h
mov c,l
call openq
inr a
; else
; do;
; /* procedure not resident */
; ret = 1;
; end;
lxi h,0001h
pop d ;DE = cpb.param
jz clrespdone ;queue not found
; do;
; /* read queue to get procedure entry point address */
; call readq (.rsp$uqcb);
lxi h,2
dad sp
mov b,h
mov c,l
push d
call readq ;read proc adr from queue
; /* execute the procedure (function) */
; ret = xfunc (cpb.rsp$param,rsp$adr);
pop b ;BC = cpb.param
pop h ;HL = procadr
push h
lxi d,clresprtn
push d ;setup return addr
pchl ;call proc (param)
clresprtn: ;return here from proc call
push h ;save returned result
; /* write queue to put message back on queue, this
; mechanism makes the procedure a serially
; resuseable resource */
; call writeq (.rsp$uqcb);
; end;
lxi h,4
dad sp
mov b,h
mov c,l ;BC = .uqcb
call writeq ;write proc adr to queue
pop h ;DE = result returned from proc
clrespdone:
xchg
lxi h,14
dad sp
sphl ;discard uqcb on stack
xchg
; end;
ret ;return with HL = proc()
; /* function = 152, Parse Filename */
; ret = parse$filename (parameter);
@31:
POP H ; DISCARD EXDOS RETURN
JMP PARSEFILENAME
; /* function = 153, Get Console Number */
; ret = rlrpd.console;
@32:
LXI B,0CH
XCHG
DAD B
MOV A,M
ani 0fh
RET
; /* function = 154, System Data Address */
; ret = sysdat;
@33:
POP H ; DISCARD EXDOS RETURN
LHLD SYSDAT
RET
; /* function = 155, Get Time & Date */
; do;
@34:
; call move (5,.tod,parameter);
LXI D,TOD
MVI L,5H
LDAX D
STAX B
INX B
INX D
DCR L
JNZ $-5H
; end;
RET
; /* function = 156, Return Process Descriptor Address */
; do;
rtnpdadr:
; return rlr;
pop h ; discard EXDOS return
lhld rlr
; end;
ret
; /* function = 157, Abort Specified Process */
; do;
abort:
;
; BC -> Abort$parameter$control$block
; declare apcb structure (
; pdadr address,
; param address,
; pname (8) byte );
ldax b
inx b
mov e,a
ldax b
inx b
mov d,a
ora e ;test for PD address present
ldax b
inx b
mov l,a
ldax b
inx b
mov h,a ;DE = apcb.pdadr, HL = apcb.param
di
shld dparam
shld tparam
jnz @15 ;jump if already have pdadr
; pdadr = thread$root;
LHLD THRDRT
XCHG
; do while pdadr <> 0;
@9:
; i = 1;
PUSH B
LXI H,6
DAD D
PUSH H
MVI L,8 ;** this no longer includes the pd.console byte !
; do while (i <> 9) and (pd.name(i-1) = pname(i));
@11:
XTHL
LDAX B
sub M
INX B
INX H
JZ @11A
ani 7fh
jz @11a ;also don't care on high order bit
POP H
POP B
JMP @6
@11A:
XTHL
DCR L
JNZ @11
xthl ;now test console byte
ldax b
mov b,a
mov a,m
ani 0fh
cmp b
; i = i + 1;
; end;
pop h
pop b
jz @15
@6:
; pdadr = pd.thread;
LXI H,12H
DAD D
MOV E,M
INX H
MOV D,M
MOV A,D
ORA E
JNZ @9
; end;
exitabort:
; return 0FFFFH;
ei
mvi a,0ffh
RET
@15:
lxi h,13
dad d
mov a,m
ani 80h
jnz @15b ;jump if no abort flag bit set
push h
lxi h,7
dad d
mov a,m
ani 80h
pop h
jz @15a ;jump if in bdos flag bit not set
dcx h
ora m
mov m,a
dcx h
dcx h
dcx h
dcx h
mov a,m
ori 80h
mov m,a ;set no sys stk swp flag bit
dcx h
dcx h
dcx h
dcx h
dcx h
xra a
mov m,a ;set priority to zero
ei
ret
@15b:
dcx h
ora m
mov m,a ;set process abort flag
jmp exitabort ;cannot abort
@15a:
lhld rlr
mov a,e
cmp l
jnz @16
mov a,d
cmp h
jnz @16
;
; aborting the running process
inx h
inx h
mvi m,7 ;set pd.status to terminate
ret
@16:
lxi b,setupabort
push b ;setup return address
lxi h,2
dad d
mov c,m
mvi b,0
lxi h,abtbl
dad b
dad b
mov a,m
inx h
mov h,m
mov l,a
pchl
abtbl:
dw abtrun ; 0 = Ready to run
dw abtque ; 1 = DQ
dw abtque ; 2 = NQ
dw abtpol ; 3 = Poll
dw abtflg ; 4 = Flag Wait
dw abtdly ; 5 = Delay
dw abtswp ; 6 = Swap
dw abtrun ; 7 = Terminate
dw abtrun ; 8 = Set Priority
dw abtrun ; 9 = Dispatch
dw abtcns ;10 = Attach
dw abtrun ;11 = Detach
dw abtcns ;12 = Set Console
dw abtlst ;13 = Attach List
dw abtrun ;14 = Detach List
;
; 0 Ready to run
; 7 Terminate
; 8 Set Priority
; 9 Dispatch
;11 Detach
;
abtrun:
pop h ;discard return addr
jmp procrdy ;no action simply setup abort
;
; 1 DQ
; 2 NQ
;
abtque:
;find queue link & remove
lxi b,qlr
abtq0:
ldax b
mov l,a
inx b
ldax b
mov h,a
ora l
rz ;not DQing or NQing ?
push h
lxi b,14
dad b
mov b,h
mov c,l
push b
call delpr
pop b
pop h
rc ;return if DQing & removed
push h
inx b
inx b
call delpr
pop b
rc ;return if NQing & removed
jmp abtq0
;
; 3 Poll
;
abtpol:
;remove PD from poll list
lxi b,plr
jmp delpr
;ret
;
; 4 Flag Wait
;
abtflg:
;remove PD from flag
lda nmbflags
mov c,a
inr c
lxi h,sysfla-1
abtfl0:
inx h
dcr c
rz ;not waiting for a flag ?!
mov a,e
cmp m
inx h
jnz abtfl0
mov a,d
cmp m
jnz abtfl0
mvi m,0ffh
dcx h
mvi m,0ffh
ret
;
; 5 Delay
;
abtdly:
;remove PD from delay list
lxi b,dlr
jmp delpr
;ret
;
; 6 Swap
;
abtswp:
;remove PD from swap list
lxi b,slr
jmp delpr
;ret
;
;10 Attach
;12 Set Console
;
abtcns:
;remove PD from console queue
mvi l,nmbcns
inr l
lxi b,cnsque
abct0:
dcr l
rz ;not queued for any console ?
push b
push h
call delpr
pop h
pop b
inx b
inx b
jnc abct0
ret
;
;13 Attach List
;
abtlst:
;remove PD from list queue
mvi l,nmbcns
inr l
lxi b,lstque
ablt0:
dcr l
rz ;not queued for any list ?
push b
push h
call delpr
pop h
pop b
inx b
inx b
jnc ablt0
ret
setupabort:
;put PD on dispatcher ready list
lhld drl
xchg
mov m,e
inx h
mov m,d
dcx h
shld drl
xchg
procrdy:
;compute process return address location in stack
;and fill in with address of abort code.
xchg
inx h
inx h
inx h
mvi m,0 ;pd.priority = 0
inx h ;HL = .pd.stkptr
mov e,m
inx h
mov d,m ;DE = pd.stkptr
dcx d
dcx d ;DE = pd.stkptr-2 (PUSHed)
mov m,d
dcx h
mov m,e
inx h
inx h
inx h
inx h
mov a,m
ori 80h
mov m,a
lhld tparam
xchg
lxi b,abortcode
mov m,c
inx h
mov m,b
inx h
mov m,e
inx h
mov m,d
ei
xra a
ret
abortcode:
di
mvi c,143
pop d
jmp xdos
dseg
tparam: ds 2
cseg
; end;
; /* function = 158, Attach List */
; do;
@40:
; enter$region;
DI
; rlrpd.status = attach$list$status;
XCHG
MVI M,0DH
; end;
RET
; /* function = 159, Detach List */
; do;
@41:
; enter$region;
DI
; rlrpd.status = detach$list$status;
XCHG
MVI M,0EH
; end;
RET
; /* function = 160, Set List */
; do;
@42:
; rlrpd.console = parameter;
mov a,c
ral
ral
ral
ral
mov c,a
lxi h,0eh-02h
dad d ;HL = .rlrpd.console
mov a,m
ani 0fh
ora c
mov m,a
pop h ;discard EXDOS return
; end;
RET
; /* function = 161, Conditional Attach List */
; do;
@43:
; enter$region;
DI
lhld rlr
xchg ;DE = Ready List Root
lxi h,0eh ;rlrpd.console offset
dad d
mov a,m
ani 0f0h
rrc
rrc
rrc
rrc
lxi h,lstatt
jmp attcmn
; end;
RET
; /* function = 162, Conditional Attach Console */
; do;
@44:
; enter$region;
DI
lhld rlr
xchg ;DE = Ready List Root
lxi h,0eh ;rlrpd.console offset
dad d
mov a,m
ani 0fh
lxi h,cnsatt
attcmn:
add a
mov c,a
mvi b,0
dad b
mov a,m
cmp e
inx h
jnz @44a
mov a,m
cmp d
jz @44b
@44a:
mov a,m
dcx h
ora m ;testing for non-attached
jnz @44b
mov m,e
inx h
mov m,d
xra a
@44b:
mvi a,0
rz
dcr a
; end;
RET
; /* function = 163, Return MP/M Version Number */
; do;
@45:
pop h ;discard EXDOS return
lhld mpmver
; end;
RET
; /* function = 164, Get List Number */
; ret = rlrpd.console$list;
@46:
LXI B,0CH
XCHG
DAD B
MOV A,M
rlc
rlc
rlc
rlc
ani 0fh
RET
; end; /* case */
@37:
DW ABSRQ
DW RELRQ
DW MEMFR
DW @7
DW FLGWT
DW FLGSET
DW MAKEQ
DW OPENQ
DW DELETQ
DW READQ
DW CREADQ
DW WRITEQ
DW CWRITEQ
DW @17
DW @18
DW @19
DW @20
DW @21
DW @22
DW @23
DW @24
DW ASSIGN
DW @26
DW @27
DW @31
DW @32
DW @33
DW @34
dw rtnpdadr
dw abort
dw @40
dw @41
dw @42
dw @43
dw @44
dw @45
dw @46
maxfunc equ ($-@37)/2
; if function <> flag$set$function then
; do;
; if function <> flag$wait$function then
; do;
; call dispatch;
; end;
; end;
; return ret;
EXDOS:
MVI H,0
MOV L,A
RET
; end xdos;
delpr0:
mov b,h
mov c,l
; delete$process:
; procedure (nxtpdladr,pdadr) public;
delpr:
public delpr
; declare (nxtpdladr,pdadr) address;
; declare pdladr based nxtpdladr address;
ldax b
mov l,a
inx b
ldax b
dcx b
mov h,a
ora l
rz ;end of list with no match
mov a,l
cmp e
jnz delpr0
mov a,h
cmp d
jnz delpr0
mov a,m ;found match, update pointers
stax b
inx h
inx b
mov a,m
stax b
stc ;indicate success
ret
;end xdos;
END