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,27 @@
include cpyright.def
;*****************************************************
;*
;* BDOS - Basic Disk Operating System
;*
;*****************************************************
eject ! include equ.bdo ; symbol definitions
eject ! include system.def
eject ! include pd.def
eject ! include err.def
eject ! include qd.def
eject ! include modfunc.def
eject ! include xioscb.def
eject ! include bdosif.bdo ; system initialization
eject ! include file1.bdo ; file system part 1
eject ! include file2.bdo ; file system part 2
eject ! include file3.bdo ; file system part 3
eject ! include file4.bdo ; file system part 4
eject ! include patch.cod
eject ! include uda.fmt ; User Data area
eject ! include sysdat.fmt
eject ! include data.bdo
end


View File

@@ -0,0 +1,514 @@
;*****************************************************
;*
;* BDOS Interface
;*
;*****************************************************
MPM equ true
CPM equ false
cseg
org 0
jmp init ;BDOS initialization
jmp entry ;inter module entry pt.
sysdat dw 0 ;seg address of sysdat
supervisor equ offset $
dw 3
dw 0 ;SUP segment
db 'COPYRIGHT (C) 1981,'
db ' DIGITAL RESEARCH '
serial db '654321'
;====
init:
;====
; initialize bdos/xios modules
; assume ds=system data area
; save sysdat segment
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
; create disk mx queue
mov dx,offset mxdiskqd ! mov cx,f_qmake
call mpmif
; open mx disk queue
mov dx,offset mxdiskqpb ! mov cx,f_qopen
call mpmif
; write mx disk queue
mov dx,offset mxdiskqpb ! mov cx,f_qwrite
call mpmif
retf
;*****************************************************
;*
;* BDOS function table
;*
;*****************************************************
;
; format of entry in functab
;
btab_addr equ word ptr 0
btab_flag equ byte ptr (btab_addr + word)
btablen equ btab_flag + byte
bf_getmx equ 0001h ;get mxdisk queue
BF_CSHELL EQU 0002H ;CONDITIONAL SHELL FUNCTION
BF_TANDW EQU 0004H ;TEST & WRITE FUNCTION
BF_FCB36 EQU 0008H ;SHELL 36 BYTE FCB FLAG
;
; bdos function table
;
functab dw func13 ! db 1 ; 0: disk reset
dw func14 ! db 1 ; 1: select disk
dw func15 ! db 1 ; 2: open file
dw func16 ! db 1 ; 3: close file
dw func17 ! db 1 ; 4: search first
dw func18 ! db 1 ; 5: search next
dw func19 ! db 1 ; 6: delete file
dw func20 ! db 3 ; 7: read sequential
dw func21 ! db 3 ; 8: write sequential
dw func22 ! db 1 ; 9: make file
dw func23 ! db 1 ; 10: rename file
dw func24 ! db 0 ; 11: return login vector
dw func25 ! db 0 ; 12: return current disk
dw func26 ! db 0 ; 13: set dma address
dw func27 ! db 1 ; 14: get alloc addr
dw func28 ! db 1 ; 15: write protect disk
dw func29 ! db 0 ; 16: get r/o vector
dw func30 ! db 1 ; 17: set file attributes
dw func31 ! db 1 ; 18: get disk parm addr
dw func32 ! db 0 ; 19: set/get user code
RDRAN_OFF dw func33 ! db 11 ; 20: read random
WRRAN_OFF dw func34 ! db 11 ; 21: write random
dw func35 ! db 1 ; 22: compute file size
dw func36 ! db 1 ; 23: set random record
dw func37 ! db 1 ; 24: reset drive
dw func38 ! db 1 ; 25: access drive
dw func39 ! db 1 ; 26: free drive
dw func40 ! db 3 ; 27: write random w/zero fill
DW FUNC41 ! DB 13 ; 28: TEST & WRITE RECORD
DW FUNC42 ! DB 1 ; 29: LOCK RECORD
DW FUNC43 ! DB 1 ; 30: UNLOCK RECORD
DW FUNC44 ! DB 0 ; 31: SET MULTI-SECTOR COUNT
DW FUNC45 ! DB 0 ; 32: SET BDOS ERROR MODE
DW FUNC46 ! DB 1 ; 33: GET DISK FREE SPACE
DW FUNC47 ! DB 1 ; 34: CHAIN TO PROGRAM
DW FUNC48 ! DB 1 ; 35: FLUSH BUFFERS
dw func51 ! db 0 ; 36: set dma base
dw func52 ! db 0 ; 37: get dma base
DW FUNC100 ! DB 1 ; 38: SET DIRECTORY LABEL
DW FUNC101 ! DB 1 ; 39: RETURN DIRECTORY LABEL DATA
DW FUNC102 ! DB 1 ; 40: READ FILE XFCB
DW FUNC103 ! DB 1 ; 41: WRITE OR UPDATE FILE XFCB
DW FUNC104 ! DB 1 ; 42: SET CURRENT DATE AND TIME
DW FUNC105 ! DB 1 ; 43: GET CURRENT DATE AND TIME
DW FUNC106 ! DB 1 ; 44: SET DEFAULT PASSWORD
DW FUNC107 ! DB 0 ; 45: RETURN SERIAL NUMBER
DW PR_TERM ! DB 1 ; 46: TERMINATE PROCESS
;=====
entry:
;=====
mov ch,0 ! mov ax,btablen
push dx ! mul cx ! pop dx
mov si,offset functab ! add si,ax
TEST cs:btab_flag[si],bf_getmx ! jz nomx
call getdiskmx ! jmps exit
nomx: call cs:btab_addr[si]
exit: mov ax,bx ! retf
;=========
getdiskmx:
;=========
; si = address of functab entry
; dx = argument
push si! push dx
MOV CX,F_CONSTAT
CALL MPMIF
pop dx! pop si
;do not allow ctrl c while in bdos
mov bx,rlr
mov ax,p_flag[bx] ! and ax,pf_tempkeep
PUSH AX
or p_flag[bx],pf_tempkeep
push si! push dx
mov cx,f_qread ! mov dx,offset mxdiskqpb
call mpmif
pop dx ! pop si
mov bx,rlr! test p_flag[bx],pf_ctlc
jz $+5
jmp retmonx
;switch to internal bdos stack
pushf ! pop ax ! cli
mov sssave,ss
mov spsave,sp
mov ss,sysdat
mov sp,offset bdosstack
push ax ! popf
;initialize bdos data area for user
push si ! push dx
mov ax,u_wrkseg
mov parametersegment,ax
mov ax,u_retseg
mov returnseg,ax
mov bx,rlr ! MOV PDADDR,BX
;set default user code
mov al,p_user[bx] ! mov usrcode,al
;set default disk
mov dl,p_dsk[bx]
MOV SELDSK,DL
;set default dma
mov setbf,false
mov ax,u_dma_ofst
cmp ax,dmaad ! je nodmaoch
mov setbf,true
nodmaoch:
mov ax,u_dma_seg
cmp ax,dmabase ! je nodmabch
mov setbf,true
nodmabch:
;copy uda bdos vars to local area
push es ! push ds ! pop es ! pop ds
mov si,offset u_dma_ofst ! mov di,offset dmaad
mov cx,uda_ovl_len ! rep movs al,al
push es ! push ds ! pop es ! pop ds
TEST PDCNT,1! JZ PDCNT_OK ;RESET PDCNT IF LOW ORDER BIT SET
MOV AL,PDCNT! CALL INC_PDCNT
PDCNT_OK:
pop dx ! push dx
mov info,dx ;info=dx
mov linfo,dl ;linfo = low(info) - don't equ
call entryzero
;Set DMA buffer if needed
cmp setbf,true ! jne nsetbf
call setdata
nsetbf:
;ready to go to the function
pop dx ! pop si
PUSH ES! PUSH DS! POP ES
MOV AH,CS:BTABFLAG[SI]
TEST AH,BF_TANDW ! JNZ SHELL
CMP MULT_CNT,1 ! JE NOSHELL
TEST AH,BF_CSHELL ! JNZ SHELL
NOSHELL:
CALL CALL_BDOS
RETMON:
POP ES
mov si,offset dmaad ! mov di,offset u_dma_ofst
mov cx,uda_ovl_len
rep movs al,al
;setup return registers
mov dx,returnseg
mov u_retseg,dx
mov bx,aret
;switch back to user's stack
pushf ! pop dx ! cli
mov ss,sssave
mov sp,spsave
push dx ! popf
;release mxdisk queue
RETMONX:
push bx
mov cx,f_qwrite ! mov dx,offset mxdiskqpb
call mpmif
;see if control c occured
mov si,rlr
pop bx! pop ax! not ax
xor ax,pf_tempkeep! and p_flag[si],ax
test p_flag[si],pf_ctlc
jz mxdiskexit
mov cx,f_terminate ! push bx
sub dx,dx ! call mpmif
pop bx
mxdiskexit:
ret
;
SHELL:
MOV SHELL_SI,SI
MOV BX,DMAAD! MOV SHELL_DMA,BX
MOV BX,OFFSET SHELL_RTN! PUSH BX
TEST AH,BF_FCB36! JNZ SHELL01
CALL PARSAVE33! JMP SHELL02
SHELL01:
CALL PARSAVE36! CALL SAVE_RR
SHELL02:
MOV SHELL_FLAG,TRUE
TEST AH,BF_TANDW! JNZ TST_WRT
JMP MULTIO
;
CBDOS:
MOV SI,SHELL_SI
CBDOS1:
MOV DX,INFO
CALL CALL_BDOS! MOV AL,BYTE PTR ARET! RET
;
SHELL_ERR:
MOV BX,ARET
MOV DL,MULT_CNT! POP AX! SUB DL,AL
MOV CL,4! SHL DL,CL! OR BH,DL
RET
;
SHELL_RTN:
MOV ARET,BX
TEST AH,BF_FCB36! JZ $+5! CALL RESET_RR
MOV BX,SHELL_DMA! MOV DMAAD,BX! CALL SET_DATA
MOV SHELL_FLAG,FALSE! CALL PARUNSAVE
JMP RETMON
;
INCR_RR:
CALL GET_RRA
INC W[BX]! JNZ INCR_RR_RET
INC BX! INC BX! INC B[BX]
INCR_RR_RET:
RET
;
SAVE_RR:
CALL SAVE_RR2! XCHG BX,DX
SAVE_RR1:
MOV CL,3! JMP MOVE
SAVE_RR2:
CALL GET_RRA! MOV DX,OFFSET SHELL_RR! RET
;
RESET_RR:
CALL SAVE_RR2! JMP SAVE_RR1
;
TST_WRT:
MOV AL,MULT_CNT! PUSH AX
CALL SET_DIR! POP AX
TST_WRT1:
PUSH AX! MOV SI,OFFSET RDRAN_OFF! CALL CBDOS1
OR AL,AL! JNZ SHELL_ERR
CALL COMPARE_RECS
CALL INCR_RR
ADD DMAAD,80H
POP AX! DEC AL! JNZ TST_WRT1
PUSH AX! CALL SET_DATA
CALL RESET_RR
MOV SHELL_SI,OFFSET WRRAN_OFF
POP AX
;
MULT_IO:
MOV AL,MULT_CNT
MULT_IO1:
PUSH AX! CALL CBDOS
OR AL,AL! JZ $+5! JMP SHELL_ERR
POP AX! PUSH AX! TEST AH,BF_FCB36! JZ MULT_IO2
CALL INCR_RR
MULT_IO2:
ADD DMAAD,80H! CALL SET_DATA
POP AX! DEC AL! JNZ MULT_IO1
XOR BX,BX
RET
;
COMPARE_RECS:
PUSH ES! MOV ES,DMABASE! MOV DI,DMAAD
MOV SI,BUFFA! MOV CL,64
REP CMPS AX,AX
POP ES
JNZ $+3! RET
POP BX! MOV BX,7! JMP SHELL_ERR
;
CALL_BDOS:
MOV SAVESP,SP
call cs:btab_addr[si]
BDOS_RETURN:
MOV AL,SELDSK
cmp resel,0
JE RETMON5
CMP COMP_FCB_CKS,TRUE! JNE RETMON1
CALL SET_CHKSUM_FCB
RETMON1:
MOV AL,XFCB_READ_ONLY! OR AL,AL! JZ RETMON2
MOV BX,INFO! OR 7[BX],AL
RETMON2:
CALL GETEXTA! MOV AL,HIGHEXT! CMP AL,60H! JNE RETMON3
SUB BX,4! MOV AL,80H
RETMON3:
OR [BX],AL
MOV AL,ACTUAL_RC! OR AL,AL! JZ RETMON4
CALL GETRCNTA! OR [BX],AL
RETMON4:
MOV AL,SELDSK
mov cl,fcbdsk
mov bx,info ! mov [bx],cl
cmp cl,0 ! je RETMON5
mov al,olddsk
RETMON5:
cmp parcopfl,true
jne RETMON6
call parunsave
RETMON6:
;copy local vars to uda
RET
;
XCRLF: mov cx,F_CONPRINT
mov dx,offset crlfstr
XOR BX,BX
jmp mpmif
;
XPRINT: mov dx,cx ! mov cx,F_CONPRINT
XOR BX,BX
jmp mpmif
;
parsave: ;copy parameterblock from user segment to bdos segment
;cl-reg = lenght of parameter block
;
TEST SHELL_FLAG,TRUE
JNZ PARRET
push ds
push ax
mov parcopfl,true
mov parlg,cl
xor ch,ch
mov si,info
mov infosave,si
mov di,offset loc_par_area
mov info,di
mov ds,parametersegment
rep movs al,al
pop ax
pop ds
parret: ret
;
parsave33: ;copy 33 byte length parameterblock
push cx
mov cl,33
jmps pscommon
;
parsave36: ;copy 36 byte length parameterblock
push cx
mov cl,36
pscommon:
call parsave
pop cx
ret
;
parunsave: ;copy local parameter block to user segment
;
TEST SHELL_FLAG,TRUE
JNZ PARRET
push es
push ax
push cx
mov cl,parlg
xor ch,ch
mov es,parametersegment
mov si,offset loc_par_area
mov di,infosave
mov info,di
rep movs al,al
pop cx
pop ax
pop es
ret
;these functions taken out of the
;bdosio.a86 module
setlret1: mov al,1
staret: mov lret,al
funcret: ret
;these functions added for mpm interface
;=====
mpmif:
;=====
; call mpm function
MOV SI,RLR
PUSH ES
MOV ES,P_UDA[SI]
callf cs:dword ptr .supervisor
POP ES
ret
entryzero:
;---------
push cx ! push es
mov cx,ds ! mov es,cx
mov cx,zerolength ! mov al,0
mov di,offset fcbdsk
rep stos al
pop es ! pop cx
ret
;*****************************************************
;*
;* bdos - xios interface
;*
;*****************************************************
bootf:
wbootf: mov cx,f_terminate ! jmp mpmif
homef: mov al,io_home ! jmps xiosif
seldskf:mov al,io_seldsk ! jmps xiosif
settrkf:mov al,io_settrk ! jmps xiosif
setsecf:mov al,io_setsec ! jmps xiosif
setdmf: mov al,io_setdma ! jmps xiosif
setdmbf:mov al,io_setdmab ! jmps xiosif
readf: mov al,io_read ! jmps xiosif
writef: mov al,io_write ! jmps xiosif
sectran:mov al,io_sectran ! jmps xiosif
flush: mov al,io_flush ! jmps xiosif
;====== ========================
xiosif: ; xios interface routine
;====== ========================
; input: al = function number
; cx = argument 1
; dx = argument 2
; output: ax = bx = output
MOV SI,RLR! PUSH ES! MOV ES,P_UDA[SI]
callf dword ptr .xiosmod
CLD! POP ES
ret


View File

@@ -0,0 +1,30 @@
;*****************************************************
;*
;* 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
;*
;* PROPRIETORY
;* ===========
;*
;* All rights reserved. No part of this document
;* may be reproduced, transmitted, stored in a
;* retrieval system, or translated into any language
;* or computer language, in any form or by any means
;* without the prior written permission of Digital
;* Research, P.O Box 579, Pacific Grove, California.
;*
;*****************************************************


View File

@@ -0,0 +1,404 @@
;*****************************************************
;*
;* BDOS Data Area
;*
;*****************************************************
if CPM
;
; 8086 variables that must reside in code segment
;
cseg $
;
axsave dw 0 ; register saves
SS_save dw 0
SP_save dw 0
stack_begin dw endstack
;
; Variables in data segment:
;
dseg cpmsegment
org bdosoffset+bdoscodesize
header rs 128
rs 72
pag0 dw 0 ;address of user's page zero
ip0 db 0 ;initial page value for IP register
;
; memory control block
;
umembase dw 0 ;user'sbase for memory request
umemlg dw 0 ;length of memory req
contf db 0 ;flag indicates added memory is avail
;
;
hold_info dw 0 ;save info
hold_spsave dw 0 ;save user SP during program load
hold_sssave dw 0 ;save user SS during program load
mod8080 db 0
;
; byte I/O variables:
;
compcol db 0 ;true if computing column position
strtcol db 0 ;starting column position after read
column db 0 ;column position
listcp db 0 ;listing toggle
kbchar db 0 ;initial key char = 00
endif
if MPM
DSEG
org 0c00h
endif
efcb db 0e5h ;0e5=avail dir entry
rodsk dw 0 ;read only disk vector
dlog dw 0 ;logged-in disks
if MPM
RLOG DW 0 ;REMOVEABLE LOGGED-IN DISKS
TLOG DW 0 ;REMOVEABLE DISK TEST LOGIN VECTOR
NTLOG DW 0 ;NEW TLOG VECTOR
REM_DRV DB 0 ;REMOVABLE DRIVE FLAG
;1 = REMOVABLE DRIVE
;0 = PERMANENT DRIVE
endif
;The following variables are set to zero upon entry to file system
fcbdsk db 0 ;disk named in fcb
parcopfl db 0 ;true if parameter block copied
resel db 0 ;reselection flag
aret dw 0 ;adr value to return
lret equ byte ptr aret ;low(aret)
COMP_FCB_CKS DB 0 ;COMPUTE FCB CHECKSUM FLAG
SEARCH_USER0 DB 0 ;SEARCH USER 0 FOR FILE (OPEN)
MAKE_XFCB DB 0 ;MAKE & SEARCH XFCB FLAG
FIND_XFCB DB 0 ;SEARCH FIND XFCB FLAG
usrcode db 0 ;curr user num
zerolength equ (offset usrcode)-(offset fcbdsk)
if CPM
curdsk db 0 ;curr disk num
endif
SELDSK DB 0 ;SELECTED DISK NUM
info dw 0 ;info adr
srcha dw 0 ;search adr
;The Following variable order is critical
;Variables copied from UDA for MP/M X
;Variables included in FCB checksum for MP/M and CP/M X
;Variables used to access System Lock List for MP/M X
dmaad dw 0 ;dma offset 1
dmabase dw 0 ;dma base 2
FX DB 0 ;BDOS FUNCTION # 3
srchl db 0 ;search len 4
if MPM
srchaofst dw 0 ;search adr ofst 5
srchabase dw 0 ;search adr base 6
endif
dcnt dw 0 ;directory counter 7
DBLK DW 0 ;DIRECTORY BLOCK 8
ERROR_MODE DB 0 ;BDOS ERROR MODE 9
MULT_CNT DB 0 ;BDOS MULTI-SECTOR CNT 10
DF_PASSWORD RB 8 ;PROCESS DEFAULT PW 11
if MPM
PD_CNT DB 0 ;BDOS PROCESS CNT 12 1
endif
HIGH_EXT DB 0 ;FCB HIGH EXTENT BITS 2
XFCB_READ_ONLY DB 0 ;XFCB READ ONLY FLAG 3
CURDSK DB 0FFH ;CURRENT DISK 4 1
if MPM
PACKED_DCNT DB 0 ;PACKED DBLK+DCNT 2
DB 0
DB 0
PDADDR DW 0 ;PROCESS DESCRIPTOR ADDR 3
endif
; curtrka - alloca are set upon disk select
; (data must be adjacent)
cdrmaxa dw 0 ;ptr to cur dir max val
DRVLBLA dw 0 ;DRIVE LABEL DATA BYTE ADDR
buffa dw 0 ;ptr to dir dma addr
dpbaddr dw 0 ;curr disk param block addr
checka dw 0 ;curr checksum vector addr
alloca dw 0 ;curr alloc vector addr
addlist EQU 8 ;"$-buffa" = addr list size
; sectpt - offset obtained from disk parm block at dpbaddr
; (data must be adjacent)
sectpt dw 0 ;sectors per track
blkshf db 0 ;block shift factor
blkmsk db 0 ;block mask
extmsk db 0 ;extent mask
maxall dw 0 ;max alloc num
dirmax dw 0 ;max dir num
dirblk dw 0 ;reserved alloc bits for dir
chksiz dw 0 ;size of checksum vector
offsetv dw 0 ;offset tracks at beginning
endlist rs 0 ;end of list
dpblist equ (offset endlist)-(offset sectpt)
;size
; local variables
COMMON_DMA RB 16 ;COPY OF USER'S DMA 1ST 16 BYTES
XDMAAD DW OFFSET COMMON_DMA
RETURN_FFFF DB 0 ;SEL ERR FLAG FOR FXS 27 & 31
MAKE_FLAG DB 0 ;MAKE FUNCTION FLAG
FCB_EXISTS DB 0 ;FCB EXISTS FLAG (MAKE)
ACTUAL_RC DB 0 ;DIRECTORY EXT RECORD COUNT
SAVE_XFCB DB 0 ;SEARCH XFCB SAVE FLAG
SAVE_MOD DB 0 ;OPEN_REEL MODULE SAVE FIELD
SAVE_EXT DB 0 ;OPEN_REEL EXTENT SAVE FIELD
ATTRIBUTES DB 0 ;FCB INTERFACE ATTRIBUTES HOLD BYTE
if MPM
CHK_OLIST_FLAG DB 0 ;CHECK | TEST OLIST FLAG
LOCK_SP DW 0 ;LOCK STACK PTR
LOCK_SHELL DB 0 ;LOCK SHELL FLAG
CHECK_FCB_RET DB 0 ;CHECK_FCB RETURN SWITCH
LOCK_UNLOCK DB 0 ;LOCK | UNLOCK FUNCTION FLAG
INCR_PDCNT DB 0 ;INCREMENT PROCESS_CNT FLAG ??
FREE_MODE DB 0 ;FREE LOCK LIST ENTRIES FLAG ??
;1=FREE ENTRIES FOR CURDSK
;0=FREE ALL ENTRIES
CUR_POS DW 0 ;CURRENT POSITION IN LOCK LIST
PRV_POS DW 0 ;PREVIOUS POSITION IN LOCK LIST
;SDCNT, SDBLK, SDCNT0, SDBLK0 order critical
SDCNT DW 0 ;SAVED DCNT OF FILE'S 1ST FCB
SDBLK DW 0 ;SAVED DBLK OF FILE'S 1ST FCB
SDCNT0 DW 0 ;SAVED DCNT (USER 0 PASS)
SDBLK0 DW 0 ;SAVED DBLK (USER 0 PASS)
DONT_CLOSE DB 0 ;INHIBIT ACTUAL CLOSE FLAG
OPEN_CNT DB 0 ;PROCESS OPEN FILE COUNT
LOCK_CNT DB 0 ;PROCESS LOCKED RECORD COUNT
FILE_ID DW 0 ;ADDRESS OF FILE' LOCK LIST ENTRY
DELETED_FILES DB 0 ;DELETED FILES FLAG
SET_RO_FLAG DB 0 ;SET DRIVE R/O FLAG
CHECK_DISK DB 0 ;DISK RESET OPEN FILE CHECK FLAG
FLUSHED DB 0 ;LOCK LIST OPEN FILE FLUSH FLAG
;FREE_ROOT, LOCK_MAX, OPEN_MAX INITIALIZED BY SYSGEN
DW OFFSET FREE_ROOT
OPEN_ROOT DW 0 ;LOCK LIST OPEN FILE LIST ROOT
LOCK_ROOT DW 0 ;LOCK LIST LOCKED RECORD LIST ROOT
endif
if CPM
CHAIN_FLAG DB 0 ;CHAIN FLAG ??
STAMP DB 0FFH,0FFH,0FFH,0FFH ??
endif
tranv dw 0 ;adr of translate vector
fcbcopied db 0 ;true if copy$fcb called
rmf db 0 ;read mode flag for open$reel
wflag db 0 ;XIOS/BIOS write flag
dirloc db 0 ;directory flag in rename, etc.
seqio db 0 ;1 if seq i/o
linfo db 0 ;low(info)
dminx db 0 ;local for diskwrite
tinfo dw 0 ;temp for info in "make"
single db 0 ;set true if single byte
;alloc map
olddsk db 0 ;disk on entry to bdos
rcount db 0 ;record count in curr fcb
extval db 0 ;extent num and extmsk
VRECORD DB 0 ;curr virtual record
arecord dw 0 ;curr actual record
DB 0 ;CURR ACTUAL RECORD HIGH BYTE
ablock dw 0 ;curr actual block# * blkmsk
; local variables for directory access
dptr db 0 ;directory pointer 0,1,2,3
ldcnt equ byte ptr dcnt ;low(dcnt)
XDCNT DW 0 ;EMPTY DIRECTORY DCNT
XDBLK DW 0 ;EMPTY DIRECTORY DBLK
USER_ZERO_PASS DB 0 ;SEARCH USER ZERO FLAG
; SHELL VARIABLES
SHELL_SI DW 0 ;BDOS COMMAND OFFSET
SHELL_DMA DW 0 ;DMAAD SAVE AREA
SHELL_FLAG DB 0 ;PARSAVE SHELL FLAG
SHELL_RR DB 0,0,0 ;R0,R1,R2 SAVE AREA
; Special 8086 variables:
infosave dw 0 ;save for FCB adr
parametersegment dw 0 ;user parameter segment
if MPM
returnseg dw 0 ;user return segment
endif
parlg db 0 ;len of parameter block
; error messages
dskmsg db 'Bdos Err On '
dskerr db ' : ',0
permsg db 'Bad Sector',0
selmsg db 'Select',0
rofmsg db 'File '
rodmsg db 'R/O',0
XERR_LIST:
DW XE3,XE4,XE5,XE6,XE7,XE8,XE9,XE10,XE11
XE3 DB 'File Opened in Read/Only Mode'
XE4 DB 0
XE5 DB 'File Currently Open',0
XE6 DB 'Close Checksum Error',0
XE7 DB 'Password Error',0
XE8 DB 'File Already Exists',0
XE9 DB 'Illegal ? in FCB',0
XE10 DB 'Open File Limit Exceeded',0
XE11 DB 'No Room in System Lock List',0
crlfstr db 13,10,0
PR_FX DB 'Bdos Function: '
PR_FX1 DB ' '
PR_FCB DB ' File: '
PR_FCB1 RS 12
DB 0
DENIEDMSG DB 13,13,'Disk reset denied, Drive '
DENIEDDRV DB 0,':'
DB ' Console '
DENIEDCNS DB 0
DB ' Program '
DENIEDPRC DB '12345678',0
; Local buffer area:
loc_par_area rb 258 ;local user parameter (FCB,...)
if MPM
; bdos stack switch variables and stack
; used for all bdos disk functions
SAVE_SP RW 1
sssave rw 1
spsave rw 1
; 60 word BDOS stack
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
bdosstack rw 0
setdf db 0 ;flag to see if disk needs set on entry
setbf db 0 ;flag to see if dma needs set on entry
pf_keepsav dw 0 ;save pf_keep flag
mxdiskqd dw 0 ;link
db 0,0 ;net,org
dw qf_mx ;flags (MX queue)
db 'MXdisk '
dw 0,1 ;msglen,nmsgs
dw 0,0 ;nq,dq
dw 0,0 ;msgcnt,out
dw 0 ;buffer ptr
mxdiskqpb db 0 ;flgs
db 0 ;net
dw 0 ;qaddr
dw 1 ;nmsgs
dw 0 ;buffer
db 'MXdisk '
endif
if CPM
;
; Special 8086 variables:
;
ioloc db 0 ;iobyte
user_parm_seg dw 0 ;holds user parameter seg during load
nallocmem db 0 ;no. of allocated memory segments
ncrmem db 0 ;no. of available memory segments
crmem dw 0,0 ;memory table (16 elements)
dw 0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
mem_stack_length equ 40
memstack rs mem_stack_length
;8 possible allocations
stbase equ word ptr 0
stlen equ word ptr 2
ccpflag equ byte ptr 4
nccpalloc db 0 ;number of current ccp allocations
mem_stk_ptr dw 0 ;current memory stack location
stackarea rw ssize ;stack size
endstack rb 0 ;top of stack
;
endif
org 0fffh
db 0
end


View File

@@ -0,0 +1,47 @@
;
; BDOS symbols:
;
on EQU 0ffffh
off EQU 00000h
testf EQU off
;
; Special 8086 symbols:
;
b equ byte ptr 0
w equ word ptr 0
;
; literal constants
;
enddir EQU 0ffffh ;end of directory
;
; file control block (fcb) constants
;
fcblen EQU 32 ;fcb length
empty EQU 0e5h ;empty directory entry
lstrec EQU 127 ;last record# in extent
recsiz EQU 128 ;record size
dirrec EQU recsiz/fcblen ;directory elts / record
dskshf EQU 2 ;log2(dirrec)
dskmsk EQU dirrec-1
fcbshf EQU 5 ;log2(fcblen)
extnum EQU 12 ;extent number field
maxext EQU 31 ;largest extent number
ubytes EQU 13 ;unfilled bytes field
modnum EQU 14 ;data module number
maxmod EQU 63 ;largest module number
fwfmsk EQU 80h ;file write flag is high
;order modnum
namlen EQU 15 ;name length
reccnt EQU 15 ;record count field
dskmap EQU 16 ;disk map field
lstfcb EQU fcblen-1
nxtrec EQU fcblen
ranrec EQU nxtrec+1 ;random record field (2 bytes)
;
; reserved file indicators
;
rofile EQU 9 ;high order of first type char
invis EQU 10 ;invisible file in dir command
ARCHIVE EQU 11 ;FILE HAS BEEN ARCHIVED ATTRIBUTE
;


View File

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


View File

@@ -0,0 +1,904 @@
;*****************************************************************
;*****************************************************************
;** **
;** b a s i c d i s k o p e r a t i n g s y s t e m **
;** **
;*****************************************************************
;*****************************************************************
;
;
; error message handlers
;
pererror:
;report permanent error
MOV BX,OFFSET PERMSG
MOV CH,1
JMPS GOERR
roderror:
;report read/only disk error
MOV BX,OFFSET RODMSG
MOV CH,2
JMPS GOERR
roferror:
;report read/only file error
MOV BX,OFFSET ROFMSG
MOV CH,3
JMPS GOERR
selerror:
;report select error
MOV BX,OFFSET SELMSG
MOV CH,4
goerr:
MOV CL,0FFH
MOV ARET,CX ;SET ARET
CMP ERROR_MODE,0FFH ;IF ERROR_MODE = 0FFH THEN
JE RTN_PHY_ERRS ;RETURN PHYSICAL ERROR TO USER
JMPS REPORT_ERR ;REPORT ERROR TO USER
RTN_PHY_ERRS:
MOV BX,OFFSET RETURN_FFFF ;IF RETURN_FFFF THEN ARET = 0FFFFH
TEST B[BX],TRUE
JNZ $+5
JMP GOBACK
MOV B[BX],FALSE
MOV ARET,0FFFFH
JMP GOBACK
REPORT_ERR:
PUSH BX ;SAVE ERROR MESSAGE OFFSET
CALL XCRLF ;PRINT CR,LF
MOV AL,SELDSK
ADD AL,'A'
MOV DSKERR,AL ;SET D: FIELD
MOV CX,OFFSET DSKMSG
CALL XPRINT ;PRINT "Bdos Err On D:"
POP CX
CALL XPRINT ;PRINT ERROR MESSAGE
MOV AL,FX ;CONVERT FUNCTION TO CHARACTER
MOV CH,30H
MOV BX,OFFSET PRFX1
CMP AL,100
JC RPT_ERR1
MOV B[BX],31H
INC BX
SUB AL,100
RPT_ERR1:
SUB AL,10
JC RPT_ERR2
INC CH
JMPS RPT_ERR1
RPT_ERR2:
MOV [BX],CH
INC BX
ADD AL,3AH
MOV [BX],AL
INC BX
MOV B[BX],20H
MOV BX,OFFSET PR_FCB ;0 = MESSAGE DELIMITER
MOV B[BX],0
TEST RESEL,TRUE ;WAS RESELECT CALLED?
JZ RPT_ERR3 ;NO - DON'T PRINT FCB
MOV B[BX],20H ;REMOVE DELIMITER
MOV DX,INFO
INC DX
MOV BX,OFFSET PR_FCB1
MOV CL,8
CALL MOVE ;MOVE FILE NAME TO MESSAGE
MOV BX,DI
MOV DX,SI
MOV B[BX],'.' ;MOVE '.' TO MESSAGE
INC BX
MOV CL,3 ;MOVE FILE TYPE TO MESSAGE
CALL MOVE
RPT_ERR3:
CALL XCRLF ;ADVANCE TO NEW LINE
MOV CX,OFFSET PR_FX
CALL XPRINT ;PRINT "Bdos Function : ### "
; + "File: FFFFFFFF.TTT"
CALL XCRLF
CMP ERROR_MODE,0FEH ;IS ERROR MODE PRINT &
; RETURN ERRORS?
JE RPT_ERR4 ;YES
MOV SI,RLR
OR PFLAG[SI],PF_CTLC ;SET PROCESS ^C FLAG
RPT_ERR4:
JMP RTN_PHY_ERRS
;
; local subroutines for bios interface
;
;
;
move:
;move data length of length cl from source dx to
;destination given by bx
push cx
mov ch,0
mov si,dx
mov di,bx
rep movs al,al
pop cx
ret
;
;
selectdisk:
;select the disk drive given by curdsk, and fill
;the base addresses curtrka - alloca, then fill
;the values of the disk parameter block
;
MOV CURDSK,0FFH
MOV CL,SELDSK ;current disk# to cl
;lsb of dl = 0 if not yet
;logged in
call seldskf ;bx filled by call
;bx = 0000 if error,
;otherwise disk headers
cmp bx,0
jz ret4 ;rz
mov dx,[bx]
add bx,2
mov cdrmaxa,bx
add bx,2
MOV DRVLBLA,BX
ADD BX,4
;dx still contains .tran
xchg bx,dx
mov tranv,bx ;.tran vector
mov bx,offset buffa ;dx= source for move, bx=dest
mov cl,addlist
call move ;addlist filled
;now fill the disk
;parameter block
mov dx,dpbaddr
mov bx,offset sectpt ;bx is destination
mov cl,dpblist
call move ;data filled
;set single/double map mode
mov al,byte ptr maxall+1 ;largest allocation number
MOV SINGLE,TRUE ;assume a=00
or al,al
jz retselect
;high order of maxall not
;zero, use double dm
MOV SINGLE,FALSE
retselect:
MOV AL,SELDSK
MOV CURDSK,AL
INC AL
ret4: ret ;select disk function ok
;
home:
;move to home position, then offset to start of dir
call homef
;first directory pos. selected
MOV DBLK,0
ret
;
PASS_ARECORD:
MOV DX,ARECORD
MOV CH,BYTE PTR ARECORD+2
RET
;
rdbuff:
;read buffer and check if ok
CALL PASS_ARECORD
call readf ;current drive, track,....
jmps diocomp ;check for i/o errors
;
wrbufflg:
mov cl,wflag
wrbuff:
;write buffer and check condition
;write type (wrtype) is in register cl
;wrtype = 0 => normal write operation
;wrtype = 1 => directory write operation
;wrtype = 2 => start of new block
CALL PASS_ARECORD
OR CL,REM_DRV
call writef ;current drive, track, ...
diocomp: ;check for disk errors
or al,al
jz ret4 ;rz
CMP AL,2
JZ $+5
jmp pererror
JMP RODERROR
;
seekdir:
;seek the record containing the current dir entry
MOV DX,0FFFFH! XOR AH,AH ; MASK = FFFF
MOV BX,DBLK! CMP BX,0! JZ SEEKDIR1
INC DX! MOV DL,BLKMSK
MOV CL,BLKSHF! MOV AL,BH
; AH+BX = SHL(DBLK,BLKSHF)
SHL BX,CL! SHL AX,CL
SEEKDIR1:
MOV SI,DCNT
MOV CL,DSKSHF! SHR SI,CL
; ARECORD = SHL(DBLK,BLKSHF) + SHR(DCNT,DSKSHF) & MASK
AND DX,SI
ADD BX,DX! ADC AH,0
MOV ARECORD,BX! MOV BYTE PTR ARECORD+2,AH
seek:
;seek the track given by arecord (actual record)
MOV AX,ARECORD ;COMPUTE TRACK/SECTOR
XOR DX,DX
MOV DL,BYTE PTR ARECORD+2
DIV SECTPT ;DX=SECTOR, AX=TRACK
PUSH DX! MOV CX,AX
ADD CX,OFFSETV
CALL SETTRKF ;SET BIOS/XIOS TRACK
POP CX! MOV DX,TRANV
CALL SECTRAN ;SET BIOS/XIOS SECTOR
MOV CX,BX
JMP SETSECF ;RET
;
; utility functions for file access
;
dmposition:
;compute disk map position for vrecord to bx
mov bx,offset blkshf
mov cl,[bx] ;shift count to cl
mov al,vrecord ;current virtual record to a
shr al,cl
;a = shr(vrecord,blkshf) = vrecord/2**(sect/block)
mov ch,al ;save it for later addition
mov cl,7
sub cl,[bx]
mov al,extval ;extent value ani extmsk
;
;blkshf = 3,4,5,6,7
;cl=4,3,2,1,0
;shift is 4,3,2,1,0
shl al,cl
;arrive here with a = shl(ext and extmsk,7-blkshf)
add al,ch ;add the previous
;shr(vrecord,blkshf) value
;al is one of the following
;values, depending upon alloc
;bks blkshf
;1k 3 v/8 + extval * 16
;2k 4 v/16+ extval * 8
;4k 5 v/32+ extval * 4
;8k 6 v/64+ extval * 2
;16k 7 v/128+extval * 1
ret ;with dm$position in a
;
GET_DMA: ;BX = .FCB(DSKMAP)
MOV BX,INFO
ADD BX,DSKMAP
RET
;
getdm:
;return disk map value from position given by cx
CALL GET_DMA
add bx,cx ;index by asingle byte value
cmp single,0 ;single byte/map entry?
jz getdmd ;get disk map single byte
mov bl,[bx]
mov bh,0
ret ;with bx=00bb
getdmd:
add bx,cx ;bx=.fcb(dm+1*2)
;return double precision value
mov bx,[bx]
ret
;
index:
;compute disk block number from current fcb
call dmposition ;0...15 in register al
mov cl,al
mov ch,0
call getdm ;value to bx
mov arecord,bx
ret
;
alloct:
;called following index to see if block allocated
mov bx,arecord
or bx,bx
ret
;
atran:
;compute actual record address, assuming index called
mov cl,blkshf ;shift count to reg al
mov bx,arecord
XOR AH,AH
MOV AL,BH
shl bx,cl
SHL AX,CL
mov ablock,bx ;save shifted block #
mov al,vrecord
and al,blkmsk ;masked value in al
or bl,al
mov arecord,bx ;arecord=bx or
;(vrecord and blkmsk)
MOV BYTE PTR ARECORD+2,AH
ret
;
GET_ATTS:
;GET INTERFACE ATTRIBUTES (F5' - F8') FROM FCB
;RETURN ATTRIBUTES LEFT SHIFTED IN AL
;ZERO INTERFACE ATTRIBUTE BITS IN FCB
MOV BX,INFO! ADD BX,5
MOV CL,4! MOV DX,01111111B
GET_ATTS_LOOP:
MOV AL,[BX]! MOV CH,AL
RCL AL,1! ADC DH,DH
AND CH,DL! MOV [BX],CH
INC BX! DEC CL! JNZ GET_ATTS_LOOP
MOV AL,DH! MOV CL,4! SHL AL,CL! RET
;
GET_S1: ;GET CURRENT S1 FIELD TO AL
CALL GETEXTA! INC BX! MOV AL,[BX]! RET
;
GET_RRA:
;GET CURRENT RAN REC FIELD ADDRES TO BX
MOV BX,INFO! ADD BX,RANREC! RET
;
GET_RCNTA:
;GET RECCNT ADDRES TO BX
MOV BX,INFO! ADD BX,RECCNT! RET
;
getexta:
;get current extent field address to al
mov bx,info
add bx,extnum ;bx=.fcb(extnum)
; mov al,[bx] ;*************** removed 7/14
ret
;
gtfcba:
;compute reccnt and nxtrec addresses for get/setfcb
mov dx,reccnt
add dx,info ;dx=.fcb(reccnt)
mov bx,(nxtrec-reccnt)
add bx,dx ;bx=.fcb(nxtrec)
ret
;
getfcb:
;set variables from currently addressed fcb
call gtfcba ;addresses in dx, bx
mov al,[bx]
mov vrecord,al ;vrecord=fcb(nxtrec)
xchg bx,dx
mov al,[bx]
mov rcount,al ;rcount=fcb(reccnt)
call getexta ;bx=.fcb(extnum)
mov al,extmsk ;extent mask to a
and al,[bx] ;fcb(extnum) and extmsk
mov extval,al
ret
;
setfcb:
;place values back into current fcb
call gtfcba ;addresses to dx, bx
mov al,seqio
cmp al,02
jnz setfc1
xor al,al ;check ranfill
setfc1:
;=1 if sequential i/o
add al,vrecord
mov [bx],al ;fcb(nxtrec)=vrecord+seqio
xchg bx,dx
mov al,rcount
mov [bx],al ;fcb(reccnt)=rcount
ret
;
;
cmpecs:
;compute checksum for current directory buffer
mov cx,recsiz ;size of directory buffer
mov bx,buffa ;current directory buffer
xor al,al ;clear checksum value
cmpec0:
add al,[bx]
inc bx
loop cmpec0
ret ;with checksum in a
;
CHKSUM_FCB: ;COMPUTE CHECKSUM FOR FCB
;ADD 1ST 12 BYTES OF FCB + CURDSK +
; HIGH_EXT + XFCB_READONLY + BBH
SUB AL,AL
if MPM
MOV BX,OFFSET PDCNT
MOV CX,4
endif
if CPM
MOV BX,OFFSET HIGH_EXT
MOV CX,3
endif
CALL CMPEC0
ADD AL,0BBH ;ADD BIAS
MOV BX,INFO ;ADD 1ST 12 BYTES OF FCB
MOV CX,12
CALL CMPEC0
INC BX ;SKIP EXTENT
ADD AL,[BX] ;ADD S1
ADD BX,3 ;SKIP MODNUM & RECCNT
MOV CX,16 ;CHECKSUM DISK MAP
CALL CMPEC0
OR AL,AL ;ZERO FLAG SET IF CHEKSUM VALID
RET
;
SET_CHKSUM_FCB:
CALL CHKSUM_FCB ;COMPUTE FCB CHECKSUM
JZ RET45 ;RETURN IF VALID
MOV AH,AL ;SAVE CURRENT CHECKSUM VALUE
CALL GETS1 ;GET S1 BYTE
SUB AH,AL ;SUBTRACT FROM CHECKSUM VALUE
NEG AH ;NEGATE RESULT
MOV [BX],AH ;RESTORE S1
RET45: RET
;
RESET_CHECKSUM_FCB:
MOV COMP_FCB_CKS,0
CALL CHKSUM_FCB ;COMPUTE FCB CHECKSUM
JNZ RET45 ;RETURN IF INVALID
CALL GETS1 ;INVALIDATE S1
INC B[BX]
RET
;
CHEK_FCB:
CMP HIGH_EXT,01100000B ;DOES HIGH_EXT = 60H
JNE CHKSUM_FCB ;NO
MOV BX,INFO ;YES - SET FCB(0) TO ZERO
MOV B[BX],0
JMP CHKSUM_FCB
;
CHECK_FCB:
if MPM
MOV CHECK_FCB_RET,FALSE
CHECK_FCB1:
endif
CALL CHEK_FCB ;COMPUTE FCB CHECKSUM
JZ RET45 ;VALID IF ZERO
if MPM
AND AL,0FH ;IS MOD(CHKSUM,16) = 0 ?
JNZ CHECK_FCB3 ;NO - INVALID CHECKSUM
CMP PD_CNT,0 ;IS PDCNT = 0 ?
JZ CHECK_FCB3 ;YES - INVALID CHECKSUM
MOV BYTE PTR SDCNT+1,0FFH
MOV DONT_CLOSE,TRUE
CALL CLOSE1 ;ATTEMPT PARTIAL CLOSE
MOV BX,OFFSET LRET
INC B[BX]
JZ CHECK_FCB3 ;PARTIAL CLOSE FAILED
MOV B[BX],0 ;ZERO LRET
CALL PACK_SDCNT ;LOOK FOR FILE IN LOCK LIST
MOV CH,5
CALL SEARCH_OLIST
JNZ CHECK_FCB3 ;NOT FOUND - INVALID CHECKSUM
RET ;FOUND - CHECKSUM OK
CHECK_FCB3:
endif
POP BX ;DISCARD RETURN ADDRESS
if MPM
CHECK_FCB4:
TEST CHECK_FCB_RET,TRUE
JNZ RET45
endif
MOV AL,10 ;10 = CHECKSUM ERROR
JMP STA_RET
setcdisk:
;set a "1" value in SELDSK position of cx
MOV AL,SELDSK
SET_CDISK1: ;SET A "1" VALUE IN AL POSITION OF CX
push cx ;save input parameter
MOV CL,AL
mov bx,1 ;number to shift
shl bx,cl ;bx = mask to integrate
pop cx ;original mask
or bx,cx ;bx = mask or rol(1,curdsk)
ret
;
nowrite:
;return true if dir checksum difference occurred
MOV DX,RODSK
TEST_VECTOR:
MOV CL,SELDSK
TEST_VECTOR1:
SHR DX,CL
AND DX,1
ret ;non zero if nowrite
;
setro:
;set current disk to read only
mov cx,rodsk
call setcdisk ;sets bit to 1
mov rodsk,bx
;high water mark in directory
;goes to max
mov dx,dirmax
inc dx
mov bx,cdrmaxa ;bx = .cdrmax
mov [bx],dx ;cdrmax = dirmax
ret
;
ckrodir:
;check current directory element for read/only status
call getdptra ;address of element
;
ckrofile:
;check current buff(dptr) or fcb(0) for r/o status
CALL RO_TEST
jae ret5 ;rnc
jmp roferror
RO_TEST:
ADD BX,ROFILE ;offset to r/o bit
mov al,[bx]
rcl al,1
RET
checkwrite:
;check for write protected disk
call nowrite
jz ret5 ;rz
jmp roderror
;
getdptra:
;compute the address of a directory element at
;positon dptr in the buffer
mov bx,buffa
mov al,dptr
addh:
;bx = bx + al
mov ah,0
add bx,ax
ret5: ret
;
;
getmodnum:
;compute the address of the module number
;bring module number to accumulator
;(high order bit is fwf (file write flag)
mov bx,info
add bx,modnum
mov al,[bx]
ret ;al=fcb(modnum)
;
clrmodnum:
;clear the module number field for user open/make
call getmodnum
mov b[bx],0 ;fcb(modnum)=0
ret
;
CLR_EXT:
CALL GETEXTA
AND B[BX],1FH
RET
;
setfwf:
call getmodnum ;bx=.fcb(modnum),
;al=fcb(modnum)
;set fwf(file write flag) to 1
or al,fwfmsk
mov [bx],al ;fcb(modnum)=fcb(modnum) + 80h
;also returns non zero
;in accumulator
ret
;
;
compcdr:
;return cy if cdrmax > dcnt
mov dx,dcnt ;dx = directory counter
mov bx,cdrmaxa ;bx=.cdrmax
cmp dx,[bx]
;condition dcnt - cdrmax
;produces cy if cdrmax>dcnt
ret6: ret
;
setcdr:
;if not (cdrmax > dcnt) then cdrmax = dcnt+1
call compcdr
jb ret6 ;return if cdrmax > dcnt
;otherwise, bx = .cdrmax+1,
;dx = dcnt
inc dx
mov [bx],dx
ret
;
subdh:
;compute bx = dx - bx
push dx
sub dx,bx
mov bx,dx
pop dx
ret
;
newchecksum:
;drop through to compute new checksum
mov cl,true
checksum:
;compute current checksum record and update the
;directory element if cl=true, or check for = if not
;drec < chksiz?
MOV DX,ARECORD
mov bx,chksiz
AND BH,7FH ;REMOVE PERMANENT DRIVE BIT
call subdh ;dx-bx
jae ret6 ;skip checksum if past
;checksum vector size
;drec < chksiz, so continue
push cx ;save init flag
call cmpecs ;check sum value to al
MOV BX,ARECORD ;value of ARECORD
add bx,checka ;bx=.check(ARECORD)
pop cx ;recall true or false to cl
inc cl ;true produces zero flag
jz initcs
if MPM
INC CL ;0FEH PRODUCES ZERO FLAG
JZ TEST_DIR_CS
endif
;not initializing, compare
cmp al,[bx] ;compute$cs=check(ARECORD)?
jz ret7 ;no message if ok
;checksum error, are we beyond
;the end of the disk?
call compcdr
jae ret7 ;no message if so
if MPM
CALL NOWRITE ;FLUSH FILES IF DRIVE IS NOT
JNZ RET7 ;READ/ONLY
CALL FLUSH_FILE0
endif
jmp setro ;read/only disk set
if MPM
TEST_DIR_CS:
CMP AL,[BX] ;COMPUTE_CS=CHECK(ARECORD)
JZ RET7
JMP FLUSH_FILES
endif
initcs:
;initializing the checksum
mov [bx],al
ret7: ret
;
;
wrdir:
;write the current directory entry, set checksum
CALL CHECK_WRITE ;VERIFY DISK IS READ/WRITE
call newchecksum ;initialize entry
call setdir ;directory dma
mov cl,1 ;indicates a write directory
call wrbuff ;write the buffer
jmp setdata ;to data dma address
;ret
;
rddirbuf:
;read a directory entry into the directory buffer
call setdir ;directory dma
call rdbuff ;directory record loaded
; jmp setdata
; ret
;
setdata:
;set data dma address
mov cx,dmabase
call setdmbf ;set disk i/o base
mov bx,offset dmaad
jmps setdma ;to complete the call
;
setdir:
;set directory dma address
mov cx,ds
call setdmbf ;set bios disk i/o base
mov bx,offset buffa ;jmp setdma to complete call
;
setdma:
;bx=.dma address to set (i.e., buffa or dmaad)
mov cx,[bx] ;parameter ready
jmp setdmf
;
;
dirtouser:
;copy the directory entry to the user buffer
;after call to search or searchn by user code
mov dx,buffa ;source is directory buffer
mov bx,dmaad ;destination is user dma addr.
mov cl,recsiz ;copy entire record
push es ;move to user segment
mov es,parametersegment
call move
pop es
ret
MAKE_FCB_INV:
;FLAG FCB AS INVALID
CALL SETFWF ;RESET FCB WRITE FLAG
INC BX
INC BX
MOV W[BX],0FFFFH
RET
CHK_INV_FCB:
;CHECK FOR INVALID FCB
CALL GETDMA
JMPS TEST_FFFF
TST_INV_FCB:
;TEST FOR INVALID FCB
CALL CHK_INV_FCB
JNZ RET8
POP BX
MOV AL,9
JMP STA_RET
endofdir:
;return zero flag if at end of director, non zero
;if not at end (end of dir if dcnt = 0ffffh)
mov bx,offset dcnt
TEST_FFFF:
CMP W[BX],0FFFFH
; mov al,[bx] ;may be 0ffh
; inc bx
; cmp al,[bx] ;low(dcnt) = high(dcnt)?
; jnz ret8 ;return non zero if different
; ;high and low the same,= 0ffh?
; inc al ;0ffh becomes 00 if so
ret8: ret
;
setenddir:
;set dcnt to the end of the directory
MOV DCNT,ENDDIR
ret
;
rddir:
;read next directory entry, with cl=true if initializing
mov dx,dirmax ;in preparation for subtract
mov bx,dcnt
inc bx
mov dcnt,bx ;dcnt=dcnt+1
;continue while dirmax >= dcnt
;(dirmax-dcnt no cy)
call subdh ;dx-bx
jae rddir0
;yes, set dcnt to end
;of directory
jmps setenddir
; ret
rddir0:
;not at end of directory, seek next element
;cl=initialization flag
mov al,ldcnt
and al,dskmsk ;low(dcnt) and dskmsk
push cx
mov cl,fcbshf ;to multiply by fcb size
shl al,cl
pop cx
;a = (low(dcnt) and dskmsk)
;shl fcbshf
mov dptr,al ;ready for next dir operation
or al,al
jnz ret71 ;return if not a new record
push cx ;save initialization flag cl
call seekdir ;seek proper record
call rddirbuf ;read the directory record
pop cx ;recall initialization flag
jmp checksum ;checksum the directory elt
;ret
;
;
getallocbit:
;given allocation vector
;position on cx, return byte
;containing cx shifted so that the least significant
;bit is in the low order accumulator position. bx is
;the address of the byte for
;possible replacement in
;memory upon return, and dh contains the number of shifts
;required to place the returned value back into position
;
mov dx,cx
and cl,111b
inc cl
mov ch,cl
;ch and cl both contain the
;number of bit positions to
;shift
mov cl,3
shr dx,cl ;shift bit address right 3 for byte address
;dx shr 3 to dx
mov bx,alloca ;base addr. of alloc. vector
add bx,dx
;byte to a, hl =
mov al,[bx] ;.alloc(cx shr 3)
;now move the bit to the
;low order position of al
mov cl,ch
rol al,cl
mov dx,cx
ret71: ret
;
;
setallocbit:
;cx is the bit position of alloc to set or reset. the
;value of the bit is in register dl.
push dx
call getallocbit ;shifted val al,count in dl
and al,11111110b ;mask low bit to zero
;(may be set)
pop cx
or al,cl ;low bit of cl masked into al
; jmp rotr
; ret
rotr:
;byte value from alloc is in register al, with shift count
;in register ch (to place bit back into position), and
;target alloc position in registers bx, rotate and replace
;
push cx
mov cl,dh
ror al,cl
mov [bx],al
pop cx
ret
;
;************* end bdos filesystem part 1 **************
end


File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
; a86 bdos
gencmd bdos
era bdos.mpm
ren bdos.mpm=bdos.cmd
xref86 bdos
; era bdos.lst
vax bdos.xrf $$atn
; pip lst:=bdos.xrf
; era bdos.xrf
; era bdos.sym
; era bdos.h86
;
;
; MAKE BDOS.MPM COMPLETE
;


View File

@@ -0,0 +1,147 @@
;*****************************************************
;*
;* 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_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_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
; Internal CIO functions
f_conprint equ (cio * 0100h) + 14


View File

@@ -0,0 +1,41 @@
;*****************************************************
;*
;* PATCH AREA -- 128 bytes long
;*
;*****************************************************
patch:
nop ! nop ! nop ! nop ! nop ! nop ;00-0f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;10-1f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;20-2f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;30-3f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;40-4f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;50-5f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;60-6f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;70-7f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop


View File

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


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,190 @@
;*****************************************************
;*
;* 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 5 ;Time of Day Structure
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
ldtab rb ldtabsiz
;
; Data Used by Send Cli Command
;
cli_dma rb dskrecl ;dma buffer
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
;
;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
indisp rb 1 ;?currently in dispatch?
intflag rb 1 ;if 0, interrupts not enabled
rw 18
dsptchtos rw 0
es_sav rw 1
bx_sav rw 1
mxmemowner rw 1
mxmemcount rb 1


View File

@@ -0,0 +1,25 @@
;*****************************************************
;*
;* 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
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,71 @@
;*****************************************************
;*
;* 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
org (ulen-(3*word))
u_rtm_ret rw 1
u_sup_user_ret rw 1
u_sup_cs rw 1


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_idle
;*****************************************************
;*
;* 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


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


View File

@@ -0,0 +1,590 @@
;*****************************************************
;*
;* Character I/0 Routines
;*
;*****************************************************
;===========
conin_entry: ;Function 1:console input
;===========
call coninit ! call attach ;verify attach
call conbrk ! call conin ;chk for ctl char pending
mov bl,dl ! call chkctl ;wait for input, chk for ctl
cmp al,0 ! je conin_entry
call echoc ! jb ciexit ;check nonprint char
call tabout ;echo character
ciexit: mov bl,dl ! ret
;============
conout_entry: ;Function 2:console output - DL = char
;============
call coninit ! call attach ;verify attach
jmp tabout ;output char
;============
rconin_entry: ; raw console input
;============
call rawinit ! call attach
conin: mov dl,c_nchar[si]
mov c_nchar[si],0
cmp dl,0 ! jne ciout
call coninf ! mov dl,bl ! ret
ciout: mov bl,dl ! ret
;=============
rconout_entry: ; raw console output - DL = char
;=============
call rawinit ! call attach
rconout:jmp conout
;=============
listout_entry: ; write to list device - DL = char
;=============
mov bx,rlr ! mov dh,p_lst[bx]
call getccbadr
push dx ! call lstattach_entry ! pop dx
sub dh,ncondev ! jmp listf
;=============
constat_entry: ;check console status
;=============
call coninit
mov di,rlr ! cmp di,c_attach[si]
je cse_cl
mov cl,f_dispatch ! call mpmif
mov bl,0 ! ret
cse_cl: call conbrk
mov bl,al ! ret
;===========
dirio_entry:
;===========
; direct console i/o - read if 0ffh
; input: DL = 0ffh if readif (ret=0 on not ready)
; = 0feh if status
; = 0fdh if read (hang until ready)
; = char if write
call rawinit ! call attach
cmp dl,0fdh ! je conin ;DL=0FDh, read
jb rconout ;output DL
call conbrk ! mov bl,al ;get status
cmp dl,0feh ! jne diocin ;DL=0FEh, return status
dec bl ! not bl ! ret
diocin: cmp bl,0 ! jne conin ;DL=0FFh, if char,conin
mov cx,f_dispatch
call mpmif
mov bl,0 ! ret
;==============
conwrite_entry: ;write line until $ encountered
;==============
; input: DX = buffer addr in u_wrkseg
mov bh,0 ! mov bl,'$'
;jmps conprint_entry
;==============
conprint_entry: ;write line until delimiter or max
;==============
; input: DX = address of buffer in u_wrkseg
; BH = max characters (0=no max)
; BL = delimiter character
push bx ! push dx
call coninit ! call attach
pop bx ! pop ax ! sub cx,cx ! and al,07fh
; AH=max, AL=delimiter, BX->buffer
; CX = count = 0
cpr1: cmp ah,cl ! jne cpr2
cmp ah,0 ! jne cpr_e
cpr2: push ds ! mov ds,u_wrkseg
mov dl,[bx] ! pop ds
and dl,07fh
cmp dl,al ! je cpr_e
push ax ! push cx ! push bx
call tabout
pop bx ! pop cx ! pop ax
inc cl ! inc bx
jmps cpr1
cpr_e: ret
;=============
conread_entry: ;read a buffered console line
;=============
; buffer=(max length, current length, buffer)
push dx ! call coninit
call attach ! pop bx
read: push bx ;[SP] = buffer offset
mov al,c_column[si]
mov c_strtcol[si],al ;start column = current column
sub bx,bx ;BX = character count
;read next character, CX, BX active
readnx: push bx
readn0: call conin ! and dl,07fh ;DL = char just read
pop bx
; Carriage Return
cmp dl,cr ! jnz notcr
eofre: jmp readen
notcr:
; Line Feed
cmp dl,lf ! jz eofre
; check for Ctrl C,Ctrl D and Ctrl S
; only if first character
or bl,bl ! jnz tryh
push bx
mov bl,dl ! call chkctl
pop bx
cmp al,1 ! je tryh
pop dx ! jmp conread_entry
tryh: ; Backspace
cmp dl,ctlh ! jnz noth
or bl,bl ! jz readnx ;if not 1st char
dec bl ! mov al,c_column[si] ;decrement char count
mov di,rlr ! mov p_scratch[di],al ;temporary hold
or c_flag[si],cf_compc ! jmp linelen
noth:
; Rubout
cmp dl,rubout ! jnz notrub
or bl,bl ! jz readnxx ;only if not 1st char
pop di ! push di
push ds ! mov ds,u_wrkseg
mov dl,1[di+bx] ! pop ds ;make char=last char
dec bx ;dec char count
jmp rdech1 ;echo, read next
readnxx: jmp readnx
notrub:
; Control E
cmp dl,ctle ! jnz note
push bx
call pcr ! mov dl,lf ! call conoutf
mov c_column[si],0
mov c_strtcol[si],0
jmp readn0
note:
; Control P
cmp dl,ctlp ! jnz notp
call control_p
jmps readnxx
notp:
; Control X
cmp dl,ctlx ! jnz notx
backx: mov al,c_strtcol[si]
cmp al,c_column[si] ! jb backxxx
sub bx,bx ! jmps readnxx
backxxx: call pbacksp ! call pspace
call pbacksp
dec c_column[si]
jmps backx
notx:
; Control U
cmp dl,ctlu ! jnz notu
call crlfp
pop bx ! jmp read
notu:
; CONTROL R - redraw line
cmp dl,ctlr ! jnz notr
linelen: push bx ! call crlfp
;print buffer on screen
pop cx ! sub bx,bx
rep0: or cl,cl ! jz rep1
pop di ! push di
push ds ! mov ds,u_wrkseg
inc bx ! dec cl
mov dl,1[di+bx] ! pop ds ;DL = nxt char
mov ch,bl ! push cx
call ctlout
pop cx ! mov bh,0 ! mov bl,ch
jmps rep0
rep1: test c_flag[si],cf_compc
push bx ! jz l_22
and c_flag[si],not cf_compc
backsp: mov di,rlr ! mov al,p_scratch[di]
sub al,c_column[si]
or al,al ! jz l_22
call pbacksp ! call pspace
call pbacksp
mov di,rlr ! dec byte ptr p_scratch[di]
jmps backsp
l_22: jmp readn0
notr:
; All other characters
rdecho: inc bx
pop di ! push di
push ds ! mov ds,u_wrkseg
mov 1[di+bx],dl ! pop ds
rdech1: push bx ! call ctlout ! pop bx
pop di ! push di
push ds ! mov ds,u_wrkseg
cmp bl,[di] ! pop ds ! jae readen
push bx ! jmps l_22
; End of Console String
readen: pop di
push ds ! mov ds,u_wrkseg
mov 1[di],bl ! pop ds
call pcr
mov c_column[si],0
ret
rawinit:
;-------
call getconnum
or p_flag[bx],pf_raw
jmps getccbadr
coninit:
;-------
call getconnum
and p_flag[bx],not pf_raw
jmps getccbadr
getconnum: ;get console number
;---------
; output: DH = console #
; DL = character (unchanged)
; BX = PD address
mov bx,rlr
mov dh,p_cns[bx]
ret
attach: ;attach to default console
;------
; output: DH = console #
; DL = character (unchanged)
; SI = CCB address
cmp c_attach[si],bx ! je attret
push dx ! push si
call conattach_entry
mov bx,rlr
test p_flag[bx],pf_ctld ! jz noattmsg
and p_flag[bx],not pf_ctld
mov dx,offset attachmsg
call prcsmsg
mov dx,rlr ! add dx,p_name
call prname
pop si ! pop dx ! call crlf
mov bx,rlr ! ret
noattmsg: pop si ! pop dx
attret: ret
getccbadr:
;---------
; get CCB for calling proc's default console
; input: DH = console number
; DL = character
; output: SI = address of ccb
; BX = PD address
; DX unchanged
mov bx,rlr
sub ax,ax ! mov al,dh
shl ax,1 ! shl ax,1
mov si,ccb ! add si,ax
add si,ax ! add si,ax ;ccb+12(ccbnum)
ret
echoc:
;-----
; check if character is graphic
; input: DL = character
; DH = console #
; SI = CCB address
; output: carry set if not graphic
; DL,DH,SI pass through
cmp dl,cr ! je ret0
cmp dl,lf ! je ret0
cmp dl,tab ! je ret0
cmp dl,ctlh ! je ret0
cmp dl,' '
ret0: ret
conbrk:
;------
; read next character, check for break
; input: DH = console #
; DL = current char
; SI -> CCB
; output: DX,SI unchanged
; AL = 0 if no character
; = 1 if character
; see if char already available
cmp c_nchar[si],0 ! jne conb_y
;char not ready, check external break
call constf
and bl,1 ! jz conb_no
;character ready, read it
call coninf
mov di,rlr ! mov ax,p_flag[di]
test p_flag[di],pf_raw ! jnz conb0
call chkctl
cmp al,0 ! je conb_no
conb0: mov c_nchar[si],bl ! jmps conb_y
conb_no: mov al,0 ! ret
conb_y: mov al,1 ! ret
chkctl:
;------
; input: bl=char to check
; return: al=0 if ctr char found
; al=1 if char is not ctrl c,d,s
; dx,si preserved
; bl preserved if al=1
mov al,1
chkd: cmp bl,ctld ! jne chks
push dx ! push si
mov bx,rlr
or p_flag[bx],pf_ctld
call condetach_entry
pop si ! pop dx
jmp chk0
chks: cmp bl,ctls ! jne chkc
control_s: call coninf
cmp bl,ctlc ! je chkc
cmp bl,ctlq ! je chk0
push dx ! mov dl,bell
call conoutf ! pop dx
jmps control_s
chkc: cmp bl,ctlc ! jne chk1
;print Abort string
chkc1: push dx ! push si
call crlf ; CR,LF
mov bx,rlr
lea dx,p_name[bx]
call prname ; Process Name
mov dx,offset abortmsg
call prcsmsg ; Abort String
pop si ! pop dx
;get answer from user
call coninf ! and bl,05fh
cmp bl,' ' ! jb ctlc_r
push dx ! push bx
mov dl,bl ! call conoutf
pop bx ! pop dx
cmp bl,'Y' ! jne ctlc_r
mov bx,rlr ! or p_flag[bx],pf_ctlc
push dx ! mov cx,f_terminate ! sub dx,dx
push si ! call mpmif ! pop si ! pop dx
ctlc_r: cmp bl,ctlc ! je chkc1
call crlf
chk0: mov al,0
chk1: ret
control_p:
;---------
push bx ! push dx ! push si
mov bx,rlr
test c_flag[si],cf_listcp
jz mimic
; turn off control p
mov dl,c_mimic[si]
call unmimic_entry ! jcxz mimout
pop si ! jmps mimpret
; turn on control p
mimic: mov dh,p_cns[bx]
mov dl,p_lst[bx]
call mimic_entry
jcxz mimout
; print 'Printer Busy'
mov dx,offset ptrmsg
call prcsmsg
pop si ! jmps mimpret
; toggle listcp for current console
mimout: pop si ! xor c_flag[si],cf_listcp
mimpret:pop dx ! pop bx ! ret
prcsmsg:
;-------
; print string in Code Segment
; input: DX->null terminated string in CS
sub bx,bx ! mov ax,cs
prstr: push u_wrkseg
mov u_wrkseg,ax
call conprint_entry
pop u_wrkseg ! ret
prname:
;------
; print name
; input: DX->8 char name in DS
mov bh,8 ! mov bl,' '
mov ax,ds ! jmps prstr
conout:
;------
; compute character position/write console
; input: DL = character
; DH = console #
; SI = ccb address
; output: DL = character
; DH = console #
; SI = ccb address
;check if only calculating column position
test c_flag[si],cf_compc ! jnz compout
;write the character, then compute column.
call conbrk ! call attach
call conoutf
; check if mimic device
cmp c_mimic[si],0ffh ! je compout
push dx ! push si
mov dh,c_mimic[si]
call getccbadr
call stdout
pop si ! pop dx
;compute column position
compout:
mov al,c_column[si]
cmp dl,rubout ! je ccret
inc al
cmp dl,' ' ! jae ccret
dec al
or al,al ! jz ccret
cmp dl,ctlh ! jnz notbs
dec al ! jmps ccret
notbs: cmp dl,cr ! jne ccret
mov al,0
ccret: mov c_column[si],al
ret
stdout:
;------
cmp dh,ncondev ! jl xcout
push dx ! sub dh,ncondev
cmp dh,nlstdev ! jl xlout
ret
xlout: call listf ! pop dx ! ret
xcout: jmp conoutf
ctlout:
;------
; send CTRL character with possible preceding up-arrow
; input: DL = character
; DH = console #
; SI = ccb address
; output: DL,DH = character,console
; SI = ccb address
call echoc ! jae tabout
push dx ! mov dl,ctl ! call conout
pop dx ! or dl,40h
; jmp tabout
tabout:
;------
; expand tabs to console
; input: DL = character
; DH = console
; SI = ccb address
; output: DL,DH = char,console
; SI = ccb address
cmp dl,tab ! jne conout
mov dl,' '
tab0: call conout
mov al,c_column[si]
and al,111b ! jnz tab0
mov dl,tab
ret2: ret
pspace:
;------
; print space
mov dl,' ' ! jmps conoutf
pbacksp:
;-------
; print backspace
mov dl,ctlh ! jmps conoutf
pcr:
;---
; print CR
mov dl,cr ! jmps conoutf
crlf:
;----
push dx ! mov dl,cr ! call conout
mov dl,lf ! call conout ! pop dx
ret
crlfp:
;-----
; print #, cr, lf for ctlx, ctlu, ctlr functions
; then print ' ' until we are at strtcol (starting column)
; input: DH = console
; SI = ccb address
; output: DH = console
; SI = ccb address
mov dl,'#' ! call conout
call crlf
mov dl,' '
crlfp0: mov al,c_column[si]
cmp al,c_strtcol[si] ! jae crlfp1
call conout ! jmps crlfp0
crlfp1: ret
;
; XIOS CHARACTER I/O INTERFACE
;
; input: DH = console #
; DL = character
; SI = ccb address
; output: DH = console #
; DL = character
; SI = ccb address
; AX = BX = return
listf: mov ax,io_list ! jmps xiolst
conoutf:mov ax,io_conout
xiolst: push dx ! mov cl,dl
mov dl,dh ! mov dh,0
call xiosc
pop dx ! ret
constf: mov ax,io_const ! jmps xio1
coninf: mov ax,io_conin
xio1: mov cl,dh
xiosc: push si ! push dx
mov ch,0 ! call xiosif
pop dx ! pop si ! ret
;
; String Constants
;
ptrmsg db cr,lf,'Printer Busy',cr,lf,0
abortmsg db ': Abort (Y/N)? ',0
attachmsg db cr,lf,'Attach: ',0


View File

@@ -0,0 +1,305 @@
;*****************************************************
;*
;* More CIO Routines
;*
;*****************************************************
;===============
lstattach_entry:
;===============
mov cx,0 ! mov si,p_lst
jmps cioattach
;===============
clstattch_entry:
;===============
mov cx,0ffffh ! mov si,p_lst
jmps cioattach
;===============
cconattch_entry:
;===============
mov cx,0ffffh ! mov si,p_cns
jmps cioattach
;===============
conattach_entry:
;===============
mov cx,0 ! mov si,p_cns
;jmps cioattach
;=========
cioattach:
;=========
; Attach calling process to default ciodev.
; if ciodev is being used, sleep on c_queue
; until another process detaches from device
; and calling process is next in queue.
; input: SI = offset of dev number in PD
; CX = 0ffffh if conditional
push si ! push cx ! mov bx,rlr
mov dh,[si+bx] ! call getccbadr
pop cx
; BX = PD addr
; SI = CCB addr
pushf ! cli
cmp bx,c_attach[si] ! je ca_ret
cmp c_attach[si],0 ! je ca_atch
cmp c_attach[si],0ffffh ! jne ca_chkslp
;This is a Mimic Device
mov dh,c_msource[si]
push cx ! push si ! call getccbadr
cmp bx,c_attach[si]
pop si ! pop cx ! je ca_ret
ca_chkslp: jcxz ca_sleep
popf ! pop si ! mov bx,0ffffh
mov cx,e_no_attach ! ret
ca_sleep: lea dx,c_queue[si]
mov p_stat[bx],ps_ciowait
mov cx,f_sleep ! call mpmif
popf ! pop si ! sub cx,cx
jmps cioattach
ca_atch: mov c_attach[si],bx
ca_ret: popf ! pop si
sub bx,bx ! mov cx,bx ! ret
;===============
lstdetach_entry:
;===============
mov si,p_lst ! jmps ciodetach
;===============
condetach_entry:
;===============
mov si,p_cns
;jmps ciodetach
;=========
ciodetach:
;=========
; Detach Calling process from default ciodev.
; If current owner of ciodev then zero c_attach
; and wakeup the c_queue list to give another
; process the ciodev.
; input: SI = offset of default dev in PD
mov bx,rlr
mov dh,[si+bx] ! call getccbadr
; SI = CCB address
; BX = PD address
pushf ! cli
cmp c_attach[si],0 ! je cd_ret
cmp c_attach[si],bx ! je cd_detach
popf ! mov bx,0ffffh
mov cx,e_not_owner ! ret
cd_detach: mov ax,c_queue[si]
mov c_attach[si],ax
mov cx,f_wakeup
lea dx,c_queue[si]
call mpmif
cd_ret: popf ! sub bx,bx
mov cx,bx ! ret
;===============
conassign_entry:
;===============
; Attach specified console to specified process
;
; input: DX -> acb address in u_wrkseg
;
; +-----+-----+-----+-----+
; | cns |match| PD addr |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; | Name |
; +-----+-----+-----+-----+-----+-----+-----+-----+
;
; cns - console to assign
; match - if not 0,
; PD's default console must match acb_cns
; PD addr - PD to assign to
; name - PD name to assign to if PD addr=0
;
; return: BX = 0 if success,0ffffh if failure
; CX = Error Code
;get console #
push ds ! mov ds,u_wrkseg
mov di,dx ! mov ah,acb_cns[di] ! pop ds
;DI->ACB in u_wrkseg
;AH = console
;check if legal console
cmp ah,ncns ! jbe as_gcns
mov cx,e_ill_cns ! mov bx,0ffffh ! ret
;check if owner is passing console
as_gcns:push di ! push dx ! push ax ! mov dh,ah
call getccbadr ! pop ax ! pop dx ! pop di
mov bx,si ! mov si,rlr
; AH = console
; BX = CCB address
; SI = Calling PD address
; DI = ACB in u_wrkseg
cmp c_attach[bx],0 ! je as_own
cmp c_attach[bx],si ! je as_own
mov cx,e_not_owner ! mov bx,0ffffh ! ret
as_own:
;find pd to assign to
mov bp,bx
push ds ! mov ds,u_wrkseg
mov bx,acb_pd[di]
cmp bx,0 ! jne as_gpd
mov bx,(offset thrdrt)-p_thread
as_trya: push bp ! push ax ! push di
lea dx,acb_name[di]
mov cx,f_findpdname ! call mpmif
pop di ! pop ax ! pop bp
jcxz as_gpd
pop ds ! mov bx,0ffffh ! ret
as_gpd:
;see if pd has same default cns
; BP -> CCB
; BX -> matched pd
mov cl,acb_match[di]
pop ds
cmp cl,0 ! jz as_mok
cmp ah,p_cns[bx] ! je as_mok
push ds ! mov ds,u_wrkseg
jmps as_trya
; see if process is waiting in c_queue
; wakeup if it is
as_mok: mov si,bx ! mov bx,bp
; BP=BX = CCB
; SI = PD to assign to
mov c_attach[bx],si ! add bx,c_queue-p_link
pushf ! cli
as_nqpd:cmp p_link[bx],0 ! jz as_gexit ; cnsque
cmp p_link[bx],si ! je as_qfix
mov bx,p_link[bx] ! jmps as_nqpd
;found pd in c_queue
;take off queue and wakeup
as_qfix: mov ax,p_link[si] ! mov p_link[bx],ax
mov bx,bp ! mov bp,c_queue[bx]
mov c_queue[bx],si
mov p_link[si],bp
popf ! lea dx,c_queue[bx]
mov cx,f_wakeup ! call mpmif
jmps as_ge
as_gexit: ; console is assigned
popf
as_ge: sub cx,cx ! mov bx,cx ! ret
;=============== =====================
getdefcon_entry: ; Get Default Console
;=============== =====================
mov si,rlr
mov bh,0 ! mov bl,p_cns[si]
sub cx,cx ! ret
;=============== ==================
getdeflst_entry: ; Get Default List
;=============== ==================
mov si,rlr
mov bh,0 ! mov bl,p_lst[si]
sub bl,ncondev
sub cx,cx ! ret
;=============== =====================
setdefcon_entry: ; Set Default Console
;=============== =====================
cmp dl,ncondev ! jb sd_good
mov cx,e_ill_cns
mov bx,0ffffh ! ret
sd_good:mov si,rlr
cmp dl,p_cns[si] ! je sd_nodet
push dx ! call condetach_entry ! pop dx
sd_nodet:
mov si,rlr ! mov p_cns[si],dl
sub bx,bx ! mov cx,bx ! ret
; jmp conattach_entry ; NO AUTO ATTACH
;=============== ==================
setdeflst_entry: ; Set Default List
;=============== ==================
cmp dl,nlstdev ! jb sdl_good
mov cx,e_ill_lst
mov bx,0ffffh ! ret
sdl_good:
add dl,ncondev
mov si,rlr
cmp dl,p_lst[si] ! je sdl_nodet
push dx ! call lstdetach_entry ! pop dx
sdl_nodet:
mov si,rlr ! mov p_lst[si],dl
sub bx,bx ! mov cx,bx ! ret
; jmp lstattach_entry ; NO AUTO ATTACH
;=========== ========================
mimic_entry: ; mimic character device
;=========== ========================
; mimic a device. All character output from a source device
; will be echoed on the mimic device.
; input: DH=source
; DL=mimic device
; output: BX = 0 if successful
; BX = 0ffffh on error
; CX = Error Code
; check if source is owned
push dx ! call getccbadr
mov bx,rlr ! pop dx
pushf ! cli
cmp c_attach[si],bx ! jne mim_err
cmp c_mimic[si],0ffh ! jne mim_err
push si ! push dx ! mov dh,dl
call getccbadr ! pop dx ! pop di
cmp c_attach[si],0 ! jne mim_err
cmp c_mimic[si],0ffh ! jne mim_err
; SI->mimic CCB , DI->source CCB
mov c_attach[si],0ffffh
mov c_msource[si],dh
mov c_mimic[di],dl ! popf ! ret
mim_err:mov bx,0ffffh ! mov cx,e_no_mimic
popf ! ret
;============= ===================
unmimic_entry: ; un mimic a device
;============= ===================
; input: DL = device
mov dh,dl ! call getccbadr
pushf ! cli
cmp c_attach[si],0ffffh ! jne mim_err
push dx ! push si
mov dh,c_msource[si]
call getccbadr ! pop di ! pop dx
cmp c_mimic[si],dl ! jne mim_err
mov bx,rlr
mov c_attach[di],bx
mov c_msource[di],0ffh
mov al,c_mimic[di]
mov c_mimic[si],al
mov al,p_lst[bx]
mov p_lst[bx],dl
push ax ! push bx
call lstdetach_entry
pop bx ! pop ax ! mov p_lst[bx],al
popf ! ret


View File

@@ -0,0 +1,404 @@
;*****************************************************
;*
;* BDOS Data Area
;*
;*****************************************************
if CPM
;
; 8086 variables that must reside in code segment
;
cseg $
;
axsave dw 0 ; register saves
SS_save dw 0
SP_save dw 0
stack_begin dw endstack
;
; Variables in data segment:
;
dseg cpmsegment
org bdosoffset+bdoscodesize
header rs 128
rs 72
pag0 dw 0 ;address of user's page zero
ip0 db 0 ;initial page value for IP register
;
; memory control block
;
umembase dw 0 ;user'sbase for memory request
umemlg dw 0 ;length of memory req
contf db 0 ;flag indicates added memory is avail
;
;
hold_info dw 0 ;save info
hold_spsave dw 0 ;save user SP during program load
hold_sssave dw 0 ;save user SS during program load
mod8080 db 0
;
; byte I/O variables:
;
compcol db 0 ;true if computing column position
strtcol db 0 ;starting column position after read
column db 0 ;column position
listcp db 0 ;listing toggle
kbchar db 0 ;initial key char = 00
endif
if MPM
DSEG
org 0c00h
endif
efcb db 0e5h ;0e5=avail dir entry
rodsk dw 0 ;read only disk vector
dlog dw 0 ;logged-in disks
if MPM
RLOG DW 0 ;REMOVEABLE LOGGED-IN DISKS
TLOG DW 0 ;REMOVEABLE DISK TEST LOGIN VECTOR
NTLOG DW 0 ;NEW TLOG VECTOR
REM_DRV DB 0 ;REMOVABLE DRIVE FLAG
;1 = REMOVABLE DRIVE
;0 = PERMANENT DRIVE
endif
;The following variables are set to zero upon entry to file system
fcbdsk db 0 ;disk named in fcb
parcopfl db 0 ;true if parameter block copied
resel db 0 ;reselection flag
aret dw 0 ;adr value to return
lret equ byte ptr aret ;low(aret)
COMP_FCB_CKS DB 0 ;COMPUTE FCB CHECKSUM FLAG
SEARCH_USER0 DB 0 ;SEARCH USER 0 FOR FILE (OPEN)
MAKE_XFCB DB 0 ;MAKE & SEARCH XFCB FLAG
FIND_XFCB DB 0 ;SEARCH FIND XFCB FLAG
usrcode db 0 ;curr user num
zerolength equ (offset usrcode)-(offset fcbdsk)
if CPM
curdsk db 0 ;curr disk num
endif
SELDSK DB 0 ;SELECTED DISK NUM
info dw 0 ;info adr
srcha dw 0 ;search adr
;The Following variable order is critical
;Variables copied from UDA for MP/M X
;Variables included in FCB checksum for MP/M and CP/M X
;Variables used to access System Lock List for MP/M X
dmaad dw 0 ;dma offset 1
dmabase dw 0 ;dma base 2
FX DB 0 ;BDOS FUNCTION # 3
srchl db 0 ;search len 4
if MPM
srchaofst dw 0 ;search adr ofst 5
srchabase dw 0 ;search adr base 6
endif
dcnt dw 0 ;directory counter 7
DBLK DW 0 ;DIRECTORY BLOCK 8
ERROR_MODE DB 0 ;BDOS ERROR MODE 9
MULT_CNT DB 0 ;BDOS MULTI-SECTOR CNT 10
DF_PASSWORD RB 8 ;PROCESS DEFAULT PW 11
if MPM
PD_CNT DB 0 ;BDOS PROCESS CNT 12 1
endif
HIGH_EXT DB 0 ;FCB HIGH EXTENT BITS 2
XFCB_READ_ONLY DB 0 ;XFCB READ ONLY FLAG 3
CURDSK DB 0FFH ;CURRENT DISK 4 1
if MPM
PACKED_DCNT DB 0 ;PACKED DBLK+DCNT 2
DB 0
DB 0
PDADDR DW 0 ;PROCESS DESCRIPTOR ADDR 3
endif
; curtrka - alloca are set upon disk select
; (data must be adjacent)
cdrmaxa dw 0 ;ptr to cur dir max val
DRVLBLA dw 0 ;DRIVE LABEL DATA BYTE ADDR
buffa dw 0 ;ptr to dir dma addr
dpbaddr dw 0 ;curr disk param block addr
checka dw 0 ;curr checksum vector addr
alloca dw 0 ;curr alloc vector addr
addlist EQU 8 ;"$-buffa" = addr list size
; sectpt - offset obtained from disk parm block at dpbaddr
; (data must be adjacent)
sectpt dw 0 ;sectors per track
blkshf db 0 ;block shift factor
blkmsk db 0 ;block mask
extmsk db 0 ;extent mask
maxall dw 0 ;max alloc num
dirmax dw 0 ;max dir num
dirblk dw 0 ;reserved alloc bits for dir
chksiz dw 0 ;size of checksum vector
offsetv dw 0 ;offset tracks at beginning
endlist rs 0 ;end of list
dpblist equ (offset endlist)-(offset sectpt)
;size
; local variables
COMMON_DMA RB 16 ;COPY OF USER'S DMA 1ST 16 BYTES
XDMAAD DW OFFSET COMMON_DMA
RETURN_FFFF DB 0 ;SEL ERR FLAG FOR FXS 27 & 31
MAKE_FLAG DB 0 ;MAKE FUNCTION FLAG
FCB_EXISTS DB 0 ;FCB EXISTS FLAG (MAKE)
ACTUAL_RC DB 0 ;DIRECTORY EXT RECORD COUNT
SAVE_XFCB DB 0 ;SEARCH XFCB SAVE FLAG
SAVE_MOD DB 0 ;OPEN_REEL MODULE SAVE FIELD
SAVE_EXT DB 0 ;OPEN_REEL EXTENT SAVE FIELD
ATTRIBUTES DB 0 ;FCB INTERFACE ATTRIBUTES HOLD BYTE
if MPM
CHK_OLIST_FLAG DB 0 ;CHECK | TEST OLIST FLAG
LOCK_SP DW 0 ;LOCK STACK PTR
LOCK_SHELL DB 0 ;LOCK SHELL FLAG
CHECK_FCB_RET DB 0 ;CHECK_FCB RETURN SWITCH
LOCK_UNLOCK DB 0 ;LOCK | UNLOCK FUNCTION FLAG
INCR_PDCNT DB 0 ;INCREMENT PROCESS_CNT FLAG ??
FREE_MODE DB 0 ;FREE LOCK LIST ENTRIES FLAG ??
;1=FREE ENTRIES FOR CURDSK
;0=FREE ALL ENTRIES
CUR_POS DW 0 ;CURRENT POSITION IN LOCK LIST
PRV_POS DW 0 ;PREVIOUS POSITION IN LOCK LIST
;SDCNT, SDBLK, SDCNT0, SDBLK0 order critical
SDCNT DW 0 ;SAVED DCNT OF FILE'S 1ST FCB
SDBLK DW 0 ;SAVED DBLK OF FILE'S 1ST FCB
SDCNT0 DW 0 ;SAVED DCNT (USER 0 PASS)
SDBLK0 DW 0 ;SAVED DBLK (USER 0 PASS)
DONT_CLOSE DB 0 ;INHIBIT ACTUAL CLOSE FLAG
OPEN_CNT DB 0 ;PROCESS OPEN FILE COUNT
LOCK_CNT DB 0 ;PROCESS LOCKED RECORD COUNT
FILE_ID DW 0 ;ADDRESS OF FILE' LOCK LIST ENTRY
DELETED_FILES DB 0 ;DELETED FILES FLAG
SET_RO_FLAG DB 0 ;SET DRIVE R/O FLAG
CHECK_DISK DB 0 ;DISK RESET OPEN FILE CHECK FLAG
FLUSHED DB 0 ;LOCK LIST OPEN FILE FLUSH FLAG
;FREE_ROOT, LOCK_MAX, OPEN_MAX INITIALIZED BY SYSGEN
DW OFFSET FREE_ROOT
OPEN_ROOT DW 0 ;LOCK LIST OPEN FILE LIST ROOT
LOCK_ROOT DW 0 ;LOCK LIST LOCKED RECORD LIST ROOT
endif
if CPM
CHAIN_FLAG DB 0 ;CHAIN FLAG ??
STAMP DB 0FFH,0FFH,0FFH,0FFH ??
endif
tranv dw 0 ;adr of translate vector
fcbcopied db 0 ;true if copy$fcb called
rmf db 0 ;read mode flag for open$reel
wflag db 0 ;XIOS/BIOS write flag
dirloc db 0 ;directory flag in rename, etc.
seqio db 0 ;1 if seq i/o
linfo db 0 ;low(info)
dminx db 0 ;local for diskwrite
tinfo dw 0 ;temp for info in "make"
single db 0 ;set true if single byte
;alloc map
olddsk db 0 ;disk on entry to bdos
rcount db 0 ;record count in curr fcb
extval db 0 ;extent num and extmsk
VRECORD DB 0 ;curr virtual record
arecord dw 0 ;curr actual record
DB 0 ;CURR ACTUAL RECORD HIGH BYTE
ablock dw 0 ;curr actual block# * blkmsk
; local variables for directory access
dptr db 0 ;directory pointer 0,1,2,3
ldcnt equ byte ptr dcnt ;low(dcnt)
XDCNT DW 0 ;EMPTY DIRECTORY DCNT
XDBLK DW 0 ;EMPTY DIRECTORY DBLK
USER_ZERO_PASS DB 0 ;SEARCH USER ZERO FLAG
; SHELL VARIABLES
SHELL_SI DW 0 ;BDOS COMMAND OFFSET
SHELL_DMA DW 0 ;DMAAD SAVE AREA
SHELL_FLAG DB 0 ;PARSAVE SHELL FLAG
SHELL_RR DB 0,0,0 ;R0,R1,R2 SAVE AREA
; Special 8086 variables:
infosave dw 0 ;save for FCB adr
parametersegment dw 0 ;user parameter segment
if MPM
returnseg dw 0 ;user return segment
endif
parlg db 0 ;len of parameter block
; error messages
dskmsg db 'Bdos Err On '
dskerr db ' : ',0
permsg db 'Bad Sector',0
selmsg db 'Select',0
rofmsg db 'File '
rodmsg db 'R/O',0
XERR_LIST:
DW XE3,XE4,XE5,XE6,XE7,XE8,XE9,XE10,XE11
XE3 DB 'File Opened in Read/Only Mode'
XE4 DB 0
XE5 DB 'File Currently Open',0
XE6 DB 'Close Checksum Error',0
XE7 DB 'Password Error',0
XE8 DB 'File Already Exists',0
XE9 DB 'Illegal ? in FCB',0
XE10 DB 'Open File Limit Exceeded',0
XE11 DB 'No Room in System Lock List',0
crlfstr db 13,10,0
PR_FX DB 'Bdos Function: '
PR_FX1 DB ' '
PR_FCB DB ' File: '
PR_FCB1 RS 12
DB 0
DENIEDMSG DB 13,13,'Disk reset denied, Drive '
DENIEDDRV DB 0,':'
DB ' Console '
DENIEDCNS DB 0
DB ' Program '
DENIEDPRC DB '12345678',0
; Local buffer area:
loc_par_area rb 258 ;local user parameter (FCB,...)
if MPM
; bdos stack switch variables and stack
; used for all bdos disk functions
SAVE_SP RW 1
sssave rw 1
spsave rw 1
; 60 word BDOS stack
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
dw 0cccch,0cccch,0cccch
bdosstack rw 0
setdf db 0 ;flag to see if disk needs set on entry
setbf db 0 ;flag to see if dma needs set on entry
pf_keepsav dw 0 ;save pf_keep flag
mxdiskqd dw 0 ;link
db 0,0 ;net,org
dw qf_mx ;flags (MX queue)
db 'MXdisk '
dw 0,1 ;msglen,nmsgs
dw 0,0 ;nq,dq
dw 0,0 ;msgcnt,out
dw 0 ;buffer ptr
mxdiskqpb db 0 ;flgs
db 0 ;net
dw 0 ;qaddr
dw 1 ;nmsgs
dw 0 ;buffer
db 'MXdisk '
endif
if CPM
;
; Special 8086 variables:
;
ioloc db 0 ;iobyte
user_parm_seg dw 0 ;holds user parameter seg during load
nallocmem db 0 ;no. of allocated memory segments
ncrmem db 0 ;no. of available memory segments
crmem dw 0,0 ;memory table (16 elements)
dw 0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
mem_stack_length equ 40
memstack rs mem_stack_length
;8 possible allocations
stbase equ word ptr 0
stlen equ word ptr 2
ccpflag equ byte ptr 4
nccpalloc db 0 ;number of current ccp allocations
mem_stk_ptr dw 0 ;current memory stack location
stackarea rw ssize ;stack size
endstack rb 0 ;top of stack
;
endif
org 0fffh
db 0
end


View File

@@ -0,0 +1,16 @@
;*****************************************************
;*
;* System Entry Table entry format
;*
;*****************************************************
ent_mod equ byte ptr 0
ent_func equ byte ptr (ent_mod + byte)
ent_flag equ byte ptr (ent_func + byte)
entlen equ ent_flag + byte
; Flags Values in ent_flag
ef_network equ 001h ; network intercept


View File

@@ -0,0 +1,15 @@
;*****************************************************
;*
;* Format of Flag Table Entry
;*
;*****************************************************
flg_pd equ word ptr 0
flg_ignore equ byte ptr (flg_pd + word)
flglen equ flg_ignore + byte
flag_off equ 0ffffh ;flag not set
flag_on equ 0fffeh ;flag set
flag_zig equ 0ffh ;normal value


View File

@@ -0,0 +1,18 @@
;*****************************************************
;*
;* Idle Process
;*
;*****************************************************
;====
idle: ;Idle Process
;====
; Jump to the XIOS idle routine
mov ds,sysdat
mov bx,rlr
mov es,p_uda[bx]
mov ax,io_idle
jmp xiosif


View File

@@ -0,0 +1,41 @@
;*****************************************************
;*
;* PATCH AREA -- 128 bytes long
;*
;*****************************************************
patch:
nop ! nop ! nop ! nop ! nop ! nop ;00-0f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;10-1f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;20-2f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;30-3f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;40-4f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;50-5f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;60-6f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop
nop ! nop ! nop ! nop ! nop ! nop ;70-7f
nop ! nop ! nop ! nop ! nop ! nop
nop ! nop ! nop ! nop


View File

@@ -0,0 +1,57 @@
;*****************************************************
;*
;* RSP.DEF - Describes the relative offsets of
;* data items in the Data Segment of a
;* Resident System Process. GENSYS
;* links all RSP's together through the
;* rsp_link field (segment address ptrs).
;* Each RSP is started up as System
;* Initialization.
;*
;* Format:
;*
;* +---+---+---+---+---+---+---+---+
;* 00 | link |sdatvar|ncp| reserved |
;* +---+---+---+---+---+---+---+---+
;* 08 | reserved | CS |reserve|
;* +---+---+---+---+---+---+---+---+
;* 10 | Process Descriptor |
;* +---+---+---+---+---+---+---+---+
;* +---+---+---+---+---+---+---+---+
;* 40 | User Data Area |
;* +---+---+---+---+---+---+---+---+
;* +---+---+---+---+---+---+---+---+
;* E0 | RSP data area |
;* +---+---+---+---+---+---+---+---+
;*
;* link - GENSYS links all RSP's through this.
;* At system init, this value is filled
;* with the SYSDAT segment address
;*
;* sdatvar - if non-zero, this is a variable address
;* in the SYSDAT area which indicates the
;* a value to put into ncopies (ncp).
;*
;* ncp - Number of copies - Used by GENSYS to determine
;* how many copies of this RSP to generate.
;* This number is modified to be the specific
;* copy that was generated.
;*
;* CS - Used by GENSYS to determine where a shared
;* code segment may exist in multiple copy
;* RSPs.
;*
;*****************************************************
rsp_top equ 0
rsp_link equ word ptr rsp_top
rsp_sysdat equ rsp_link
rsp_sdatvar equ word ptr rsp_link + word
rsp_ncopies equ byte ptr rsp_sdatvar + word
rsp_reserved equ rsp_ncopies + byte
rsp_md equ 08h
rsp_pd equ 10h
rsp_uda equ ((rsp_pd+pdlen+0fh)/10h)*10h
rsp_bottom equ rsp_uda + ulen


View File

@@ -0,0 +1,26 @@
;*****************************************************
;*
;* Interrupt Vectors - to fiddle with the interrupt
;* vectors, set the Data Segment Register to 0
;* and use the following variables.
;*
;*****************************************************
DSEG
i_divide_ip rw 1 ; int 0
i_divide_cs rw 1
i_trace_ip rw 1 ; int 1
i_trace_cs rw 1
i_nomask_ip rw 1 ; int 2
i_nomask_cs rw 1
i_break_ip rw 1 ; int 3
i_break_cs rw 1
i_ovrflw_ip rw 1 ; int 4
i_ovrflw_cs rw 1
i_interrupts rw ((mpmint-5)*2)
i_mpm_ip rw 1
i_mpm_cs rw 1
i_debug_ip rw 1
i_debug_cs rw 1


View File

@@ -0,0 +1,350 @@
;*****************************************************
;* *
;* Sector Blocking / Deblocking *
;* *
;* This algorithm is a direct translation of the *
;* CP/M-80 Version, and is included here for refer- *
;* ence purposes only. The file DEBLOCK.LIB is in- *
;* cluded on your MP/M-86 disk, and should be used *
;* for actual applications. You may wish to contact *
;* Digital Research for notices of updates. *
;* *
;*****************************************************
;
;*****************************************************
;* *
;* CP/M to host disk constants *
;* *
;* (This example is setup for CP/M block size of 16K *
;* with a host sector size of 512 bytes, and 12 sec- *
;* tors per track. Blksiz, hstsiz, hstspt, hstblk *
;* and secshf may change for different hardware.) *
;*****************************************************
una equ byte ptr [BX] ;name for byte at BX
;
blksiz equ 16384 ;CP/M allocation size
hstsiz equ 512 ;host disk sector size
hstspt equ 12 ;host disk sectors/trk
hstblk equ hstsiz/128 ;CP/M sects/host buff
;
;*****************************************************
;* *
;* secshf is log2(hstblk), and is listed below for *
;* values of hstsiz up to 2048. *
;* *
;* hstsiz hstblk secshf *
;* 256 2 1 *
;* 512 4 2 *
;* 1024 8 3 *
;* 2048 16 4 *
;* *
;*****************************************************
secshf equ 2 ;log2(hstblk)
cpmspt equ hstblk * hstspt ;CP/M sectors/track
secmsk equ hstblk-1 ;sector mask
;
;*****************************************************
;* *
;* BDOS constants on entry to write *
;* *
;*****************************************************
wrall equ 0 ; deferred write
wrdir equ 1 ; non-deferred write
wrual equ 2 ; def wrt 1st sect unalloc blk
wrdal equ 3 ; non-def 1st sect unalloc blk
;
;*****************************************************
;* *
;* The BIOS entry points given below show the *
;* code which is relevant to deblocking only. *
;* *
;*****************************************************
seldsk:
;select disk
;is this the first activation of the drive?
test DL,1 ;lsb = 0?
jnz selset
;this is the first activation, clear host buff
mov hstact,0
mov unacnt,0
selset:
mov al,cl ! cbw ;put in AX
mov sekdsk,al ;seek disk number
mov cl,4 ! shl al,cl ;times 16
add ax,offset dpbase
mov bx,ax
ret
;
home:
;home the selected disk
mov al,hstwrt ;check for pending write
test al,al
jnz homed
mov hstact,0 ;clear host active flag
homed:
mov cx,0 ;now, set track zero
; (continue HOME routine)
ret
;
settrk:
;set track given by registers CX
mov sektrk,CX ;track to seek
ret
;
setsec:
;set sector given by register cl
mov seksec,cl ;sector to seek
ret
;
setdma:
;set dma address given by CX
mov dma_off,CX
ret
;
setdmab:
;set segment address given by CX
mov dma_seg,CX
ret
;
sectran:
;translate sector number CX with table at [DX]
test DX,DX ;test for hard skewed
jz notran ;(blocked must be hard skewed)
mov BX,CX
add BX,DX
mov BL,[BX]
ret
no_tran:
;hard skewed disk, physical = logical sector
mov BX,CX
ret
;
read:
;read the selected CP/M sector
mov unacnt,0 ;clear unallocated counter
mov readop,1 ;read operation
mov rsflag,1 ;must read data
mov wrtype,wrual ;treat as unalloc
jmp rwoper ;to perform the read
;
write:
;write the selected CP/M sector
mov readop,0 ;write operation
mov wrtype,cl
and cl,wrual ;write unallocated?
jz chkuna ;check for unalloc
;
; write to unallocated, set parameters
;
mov unacnt,(blksiz/128) ;next unalloc recs
mov al,sekdsk ;disk to seek
mov unadsk,al ;unadsk = sekdsk
mov ax,sektrk
mov unatrk,ax ;unatrk = sektrk
mov al,seksec
mov unasec,al ;unasec = seksec
;
chkuna:
;check for write to unallocated sector
;
mov bx,offset unacnt ;point "UNA" at UNACNT
mov al,una ! test al,al ;any unalloc remain?
jz alloc ;skip if not
;
; more unallocated records remain
dec al ;unacnt = unacnt-1
mov una,al
mov al,sekdsk ;same disk?
mov BX,offset unadsk
cmp al,una ;sekdsk = unadsk?
jnz alloc ;skip if not
;
; disks are the same
mov AX, unatrk
cmp AX, sektrk
jnz alloc ;skip if not
;
; tracks are the same
mov al,seksec ;same sector?
;
mov BX,offset unasec ;point una at unasec
;
cmp al,una ;seksec = unasec?
jnz alloc ;skip if not
;
; match, move to next sector for future ref
inc una ;unasec = unasec+1
mov al,una ;end of track?
cmp al,cpmspt ;count CP/M sectors
jb noovf ;skip if below
;
; overflow to next track
mov una,0 ;unasec = 0
inc unatrk ;unatrk=unatrk+1
;
noovf:
;match found, mark as unnecessary read
mov rsflag,0 ;rsflag = 0
jmps rwoper ;to perform the write
;
alloc:
;not an unallocated record, requires pre-read
mov unacnt,0 ;unacnt = 0
mov rsflag,1 ;rsflag = 1
;drop through to rwoper
;
;*****************************************************
;* *
;* Common code for READ and WRITE follows *
;* *
;*****************************************************
rwoper:
;enter here to perform the read/write
mov erflag,0 ;no errors (yet)
mov al, seksec ;compute host sector
mov cl, secshf
shr al,cl
mov sekhst,al ;host sector to seek
;
; active host sector?
mov al,1
xchg al,hstact ;always becomes 1
test al,al ;was it already?
jz filhst ;fill host if not
;
; host buffer active, same as seek buffer?
mov al,sekdsk
cmp al,hstdsk ;sekdsk = hstdsk?
jnz nomatch
;
; same disk, same track?
mov ax,hsttrk
cmp ax,sektrk ;host track same as seek track
jnz nomatch
;
; same disk, same track, same buffer?
mov al,sekhst
cmp al,hstsec ;sekhst = hstsec?
jz match ;skip if match
nomatch:
;proper disk, but not correct sector
mov al, hstwrt
test al,al ;"dirty" buffer ?
jz filhst ;no, don't need to write
call writehst ;yes, clear host buff
; (check errors here)
;
filhst:
;may have to fill the host buffer
mov al,sekdsk ! mov hstdsk,al
mov ax,sektrk ! mov hsttrk,ax
mov al,sekhst ! mov hstsec,al
mov al,rsflag
test al,al ;need to read?
jz filhst1
;
call readhst ;yes, if 1
; (check errors here)
;
filhst1:
mov hstwrt,0 ;no pending write
;
match:
;copy data to or from buffer depending on "readop"
mov al,seksec ;mask buffer number
and ax,secmsk ;least signif bits are masked
mov cl, 7 ! shl ax,cl ;shift left 7 (* 128 = 2**7)
;
; ax has relative host buffer offset
;
add ax,offset hstbuf ;ax has buffer address
mov si,ax ;put in source index register
mov di,dma_off ;user buffer is dest if readop
;
push DS ! push ES ;save segment registers
;
mov ES,dma_seg ;set destseg to the users seg
;SI/DI and DS/ES is swapped
;if write op
mov cx,128/2 ;length of move in words
mov al,readop
test al,al ;which way?
jnz rwmove ;skip if read
;
; write operation, mark and switch direction
mov hstwrt,1 ;hstwrt = 1 (dirty buffer now)
xchg si,di ;source/dest index swap
mov ax,DS
mov ES,ax
mov DS,dma_seg ;setup DS,ES for write
;
rwmove:
cld ! rep movs AX,AX ;move as 16 bit words
pop ES ! pop DS ;restore segment registers
;
; data has been moved to/from host buffer
and wrtype,wrdir ;write type to directory?
mov al,erflag ;in case of errors
jz return_rw ;no further processing
;
; clear host buffer for directory write
test al,al ;errors?
jnz return_rw ;skip if so
mov hstwrt,0 ;buffer written
call writehst
mov al,erflag
return_rw:
ret
;
;*****************************************************
;* *
;* WRITEHST performs the physical write to the host *
;* disk, while READHST reads the physical disk. *
;* *
;*****************************************************
writehst:
ret
;
readhst:
ret
;
;*****************************************************
;* *
;* Use the GENDEF utility to create disk def tables *
;* *
;*****************************************************
dpbase equ offset $
; disk parameter tables go here
;
;*****************************************************
;* *
;* Uninitialized RAM areas follow, including the *
;* areas created by the GENDEF utility listed above. *
;* *
;*****************************************************
sek_dsk rb 1 ;seek disk number
sek_trk rw 1 ;seek track number
sek_sec rb 1 ;seek sector number
;
hst_dsk rb 1 ;host disk number
hst_trk rw 1 ;host track number
hst_sec rb 1 ;host sector number
;
sek_hst rb 1 ;seek shr secshf
hst_act rb 1 ;host active flag
hst_wrt rb 1 ;host written flag
;
una_cnt rb 1 ;unalloc rec cnt
una_dsk rb 1 ;last unalloc disk
una_trk rw 1 ;last unalloc track
una_sec rb 1 ;last unalloc sector
;
erflag rb 1 ;error reporting
rsflag rb 1 ;read sector flag
readop rb 1 ;1 if read operation
wrtype rb 1 ;write operation type
dma_seg rw 1 ;last dma segment
dma_off rw 1 ;last dma offset
hstbuf rb hstsiz ;host buffer
end


View File

@@ -0,0 +1,132 @@
;******************* BDOS data area ********************
;
;
; 8086 variables that must recide in code segment
;
cseg $
;
axsave dw 0 ; register saves
SS_save dw 0
SP_save dw 0
;
; Variables in data segment:
;
dseg cpmsegment
org bdosoffset+bdoscodesize
;
; byte I/O variables:
;
compcol db 0 ;true if computing column position
strtcol db 0 ;starting column position after read
column db 0 ;column position
listcp db 0 ;listing toggle
kbchar db 0 ;initial key char = 00
;
; common values shared between bdosi and bdos
;
usrcode db 0 ;current user number
curdsk db 0 ;current disk number
info dw 0 ;information address
aret dw 0 ;address value to return
lret EQU byte ptr aret ;low(aret)
;
; data areas for file system:
;
; initialized data
;
efcb db empty ;0e5=available dir entry
rodsk dw 0 ;read only disk vector
dlog dw 0 ;logged-in disks
dmaad dw 0 ;dma address
;
; curtrka - alloca are set upon disk select
; (data must be adjacent, do not insert variables)
; (address of translate vector, not used)
;
cdrmaxa dw 0 ;pointer to cur dir max value
curtrka dw 0 ;current track address
curreca dw 0 ;current record address
buffa dw 0 ;pointer to directory dma address
dpbaddr dw 0 ;current disk parameter block address
checka dw 0 ;current checksum vector address
alloca dw 0 ;current allocation vector address
addlist EQU 8 ;"$-buffa" = address list size
;
; sectpt - offset obtained from disk parm block at dpbaddr
; (data must be adjacent, do not insert variables)
sectpt dw 0 ;sectors per track
blkshf db 0 ;block shift factor
blkmsk db 0 ;block mask
extmsk db 0 ;extent mask
maxall dw 0 ;maximum allocation number
dirmax dw 0 ;largest directory number
dirblk dw 0 ;reserved allocation bits for direct.
chksiz dw 0 ;size of checksum vector
offsetv dw 0 ;offset tracks at beginning
endlist rs 0 ;end of list
dpblist equ (offset endlist)-(offset sectpt) ;size
;
; local variables
tranv dw 0 ;address of translate vector
fcbcopied db 0 ;set true if copy$fcb called
rmf db 0 ;read mode flag for open$reel
dirloc db 0 ;directory flag in rename, etc.
seqio db 0 ;1 if sequential i/o
linfo db 0 ;low(info)
dminx db 0 ;local for diskwrite
srchl db 0 ;search length
srcha dw 0 ;search address
tinfo dw 0 ;temp for info in "make"
single db 0 ;set true if single byte
;allocation map
resel db 0 ;reselection flag
olddsk db 0 ;disk on entry to bdos
fcbdsk db 0 ;disk named in fcb
rcount db 0 ;record count in current fcb
extval db 0 ;extent number and extmsk
vrecord dw 0 ;current virtual record
lvrecord equ byte ptr vrecord ;low (vrecord)
arecord dw 0 ;current actual record
ablock dw 0 ;current actual block# * blkmsk
;
; local variables for directory access
dptr db 0 ;directory pointer 0,1,2,3
dcnt dw 0 ;directory counter 0,1,...,dirmax
ldcnt equ byte ptr dcnt ;low(dcnt)
drec dw 0 ;directory record 0,1,...,dirmax/4
;
; Special 8086 variables:
;
ioloc db 0 ;iobyte
dmabase dw 0 ;segment base for disk I/O
infosave dw 0 ;save for FCB address
parametersegment dw 0 ;user parameter segment
parcopfl db 0 ;true if parameter block copied
parlg db 0 ;length of parameter block
nallocmem db 0 ;no. of allocated memory segments
ncrmem db 0 ;no. of available memory segments
crmem dw 0,0 ;memory table (16 elements)
dw 0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
;
; error messages
;
dskmsg db 'Bdos Err On '
dskerr db ' : $' ;filled in by errflg
permsg db 'Bad Sector$'
selmsg db 'Select$'
rofmsg db 'File '
rodmsg db 'R/O$'
;
; Local buffer area:
;
loc_par_area rb 258 ;local user parameter (FCB,...)
stackarea rw ssize ;stack size
endstack rb 0 ;top of stack
;
;******************** end BDOS data area *******************
end


Some files were not shown because too many files have changed in this diff Show More