Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM-86/MPM-86 2.0 SOURCES/01/FILE3.BDO
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1494 lines
37 KiB
Plaintext

;******************** bdos file system part 3 ****************
;
;
sqread:
;sequential disk read operation
mov seqio,1
;drop through to diskread
;
diskread: ;(may enter from seqdiskread)
CALL TST_INV_FCB ;VERIFY FCB HAS NOT BEEN FLAGGED
;AS INVALID
mov rmf,true ;read mode flag =
;true (open$reel)
;read the next record from
;the current fcb
if MPM
MOV DONT_CLOSE,TRUE
endif
call getfcb ;sets parameters for the read
DISK_READ0:
mov al,vrecord
cmp al,rcount ;vrecord-rcount
;skip if rcount > vrecord
jb recordok
if MPM
;IF FCB WAS OPENED IN UNLOCKED MODE, CHECK THE DIRECTORY FCB
;TO MAKE SURE ANOTHER PROCESS HAS NOT ALLOCATED A BLOCK TO
;THE FCB SINCE THIS PROCESS OPENED THE FCB
CALL TEST_DISK_FCB ;JUMP BACK TO DISKREAD0 IF DONT_CLOSE
JNZ DISKREAD0 ;TRUE, FILE OPENED IN UNLOCKED MODE,
;AND ACCESS OF DIR FCB SUCCESSFUL
;DONT_CLOSE SET TO FALSE
MOV AL,VRECORD
endif
;not enough records in extent
;record count must be 128
;to continue
cmp al,128 ;vrecord = 128?
jnz diskeof ;skip if vrecord<>128
call openreel ;go to next extent if so
; mov vrecord,0 ;vrecord=00
;now check for open ok
cmp lret,0 ;stop at eof
jnz diskeof
recordok:
;arrive with fcb addressing a record to read
call index
;error 2 if reading
;unwritten data
;(returns 1 to be compatible
;with 1.4)
call alloct ;arecord=0000?
if MPM
JNZ RECORDOK1
CALL TEST_DISK_FCB ;JUMP BACK TO DISKREAD0 IF DONT_CLOSE
JNZ DISKREAD0 ;TRUE, FILE OPENED IN UNLOCKED MODE,
;AND ACCESS OF DIR FCB SUCCESSFUL
endif
jz diskeof
RECORDOK1:
;record has been allocated,
;read it
call atran ;arecord now a disk address
call seek ;to proper track,sector
call rdbuff ;to dma address
jmp setfcb ;replace parameter
; ret
diskeof:
jmp setlret1 ;lret = 1
;ret
if MPM
TEST_DISK_FCB:
TEST HIGH_EXT,80H ;WAS FILE OPENED IN UNLOCKED MODE
JZ RET14 ;NO
TEST DONT_CLOSE,0FFH ;RETURN IF DONT_CLOSE FALSE
JZ RET14
CALL CLOSE1 ;FCB IN MEMORY
TEST_DISK_FCB1:
POP SI
MOV BX,OFFSET LRET
CMP B[BX],0FFH
MOV AL,11
JNE $+5
JMP STA_RET ;ERROR - CLOSE OPERATION UNSUCCESSFUL
MOV B[BX],0 ;LRET = 0
PUSH SI
CALL GET_RCNTA
MOV AL,[BX]
MOV RCOUNT,AL
XOR AL,AL
MOV DONT_CLOSE,AL ;DONT_CLOSE = FALSE
INC AL ;SUCCESSFUL OPERATION, RESET ZERO FLAG
RET
endif
;
RESET_FWF:
call getmodnum ;bx=.fcb(modnum)
;al=fcb(modnum)
;reset the fcb write flag to
;mark as written fcb
and al,not fwfmsk ;high order bit of modnum fld reset
mov [bx],al ;fcb(modnum) = fcb(modnum) & 7fh
RET14: RET
sqwrite:
;sequential disk write
mov seqio,1
;drop through to diskwrite
;
diskwite: ;(may enter here from
;seqdiskwrite above)
mov rmf,false ;read mode flag
;write record to currently
;selected file
call checkwrite ;in case write protected
TEST XFCB_READ_ONLY,TRUE ;READ/ONLY ERROR IF XFCB_READ_ONLY TRUE
MOV AL,3 ;XFCB_READ_ONLY TRUE IF FILE IS
JZ $+5 ;PASSWORD PROTECTED IN WRITE MODE
;AND PASSWORD WAS NOT SUPPLIED
;WHEN THE FILE WAS OPENED.
JMP_SET_ARET:
JMP SET_ARET
TEST HIGH_EXT,40H ;READ/ONLY ERROR IF FCB OPENED
JNZ JMP_SET_ARET ;IN READ/ONLY MODE
mov bx,info ;bx = .fcb(0)
call ckrofile ;may be a read-only file
CALL TST_INV_FCB ;TTEST FOR VALID FCB
call getfcb ;to set local parameters
mov al,vrecord
cmp al,lstrec+1 ;vrecord-128
;skip if vrecord > lstrec
;vrecord = 128, cannot open
;next extent
jb dskwr0
CALL OPEN_REEL ;TRY TO OPEN NEXT EXTENT
TEST LRET,TRUE
JNZ RET14
dskwr0:
;
if MPM
MOV DONT_CLOSE,TRUE
DISK_WRITE1:
endif
call index
call alloct
if MPM
JZ DISKWRITE2
;IF FILE IS UNLOCKED, VERIFY RECORD IS NOT LOCKED
;RECORD HAS TO BE ALLOCATED TO BE LOCKED
TEST HIGH_EXT,80H ;WAS FILE OPENED IN UNLOCKED MODE?
JZ NOT_UNLOCKED ;NO
CALL ATRAN
MOV CH,MULT_CNT ;TEST_LOCK EXPECTS MULT_CNT
PUSH CX ;PUSHED ON STACK
CALL TEST_LOCK ;VERIFY RECORD IS NOT LOCKED BY
;ANOTHER PROCESS
POP CX
MOV WFLAG,0
JMPS DISKWR10
NOT_UNLOCKED:
OR AL,TRUE ;RESET Z FLAG FOR FOLLOWING JNZ
endif
mov cl,0 ;marked as normal write
;operation for wrbuff
jnz dskwr1
if MPM
DISK_WRITE2:
CALL TEST_DISK_FCB ;JUMP BACK TO DISK_WRITE1 IF
;DONT_CLOSE IS TRUE, FILE WAS OPENED
;IN UNLOCKED MODE, AND ACCESS OF
;DIR FCB WAS SUCCESSFUL
JNZ DISK_WRITE1
endif
;not allocated:
;the argument to getblock is the starting
;position for the disk search, and should be
;the last allocated block for this file, or
;the value 0 if no space has been allocated
;
call dmposition
mov dminx,al ;save for later
xor cx,cx ;may use block zero
or al,al
jz nopblock ;skip if no previous block
;previous block exists at a
mov cl,al
dec cx
call getdm ;previous block # to bx
mov cx,bx ;cx=prev block#
nopblock:
;cx = 0, or previous block #
call getblock ;block # to bx
;arrive with block# or zero
or bx,bx
jnz blockok
;cannot find block to allocate
mov al,2
jmp staret ;lret=2
blockok:
MOV COMP_FCB_CKS,TRUE ;MUST RECOMPUTE FCB CHECKSUM
;bx contains allocated block #
mov arecord,bx
xchg bx,dx ;block number to dx
mov bx,info
add bx,dskmap ;bx=.fcb(diskmap)
cmp single,0 ;set flags for single byte dm
mov al,dminx ;recall dm index
mov ah,0
jz allocwd ;skip if allocating word
;allocating a byte value
add bx,ax
mov [bx],dl ;single byte alloc
jmps dskwru ;to continue
allocwd:
;allocate a word value
add bx,ax
add bx,ax ;bx=.fcb(dminx*2)
mov [bx],dx ;double wd
inc bx
dskwru:
;disk write to previously unallocated block
mov cl,2 ;marked as unallocated write
dskwr1:
;continue the write operation of no allocation error
;c = 0 if normal write, 2 if to prev unalloc block
;
; cmp lret,0
; jz dskwr10
; ret
;dskwr10: ;stop if non zero value
mov wflag,cl ;save the write flag
call atran ;arecord set
DISKWR10:
cmp seqio,2 ;check random with 0 fill
jnz dskw11
;
; this is random write with zero fill
;
cmp wflag,2 ;check for new allocation
jnz dskw11 ;old allocation
;
; new alloction for random with zero fill
;
mov di,buffa
xor ax,ax ;zero and fill
mov cx,64 ;zero 64 words in dirbuf
rep stos ax
call setdir
PUSH ARECORD ;SAVE ARECORD
mov bx,ablock
fill1: mov arecord,bx
call seek
;reg cl used for deblocking
call wrbufflg ;write fill record
mov bx,arecord ;restore last record
mov wflag,0 ;change allocate flag
mov al,bl ;arecord in bx
mov dh,blkmsk
and al,dh
inc bx
cmp al,dh
jnz fill1 ;cont until cluster is zeroed
POP ARECORD ;RESTORE ARECORD
MOV WFLAG,2 ;RESTORE WFLAG
call setdata
dskw11:
call seek ;to proper file position
;(cl=2 if new block,0 if not)
;SET WFLAG TO ZERO IF VRECORD
MOV AL,VRECORD ;DOES NOT SPECIFY 1ST RECORD OF
MOV AH,BLKMSK ;NEW BLOCK
AND AH,AL
JZ WRITE
MOV WFLAG,0
WRITE:
CALL WRBUFFLG ;written to disk
;increment record count
;if rcount <= vrecord
mov al,vrecord
mov bx,offset rcount
cmp al,[bx] ;vrecord-rcount
jb dskwr2
;rcount <= vrecord
mov [bx],al
inc b[bx] ;rcount = vrecord+1
if MPM
TEST HIGH_EXT,80H
JZ WRITE1
;FOR UNLOCKED FILE
; RCOUNT = VRECORD & (~ BLKMSK) + BLKMSK + 1
MOV CH,BLKMSK
MOV CL,CH
NOT CL
INC CH
AND AL,CL
ADD AL,CH
MOV [BX],AL
WRITE1:
endif
MOV WFLAG,2 ;mark as record count
;incremented
dskwr2:
CMP WFLAG,2 ;WFLAG=2 IF NEW BLOCK OR NEW RECORD #
JNZ NOUPDATE
if MPM
TEST HIGH_EXT,80H ;IS FILE OPEN MODE UNLOCKED?
JZ DSKWR2A
MOV AL,[BX]
CALL GET_RCNTA ;RESTORE FCB(RCOUNT)
MOV [BX],AL
CALL CLOSE
CALL TEST_DISK_FCB1
DSKWR2A:
endif
CALL RESET_FWF
noupdate:
CALL GETMODNUM ;SET FILE WRITE FLAG IF RESET
AND AL,40H
JNZ DSKWR3
OR B[BX],40H
CALL RESET_FWF ;RESET FCB WRITE FLAG TO ENSURE
;T3' GETS RESET BY THE CLOSE FUNCTION
dskwr3:
jmp setfcb ;replace parameters
;ret
;
rseek:
;random access seek operation, c=0ffh if read mode
;fcb is assumed to address an active fcb
;(modnum has been set to 1100$0000b if previous bad seek)
;
mov seqio,0 ;marked as random access op.
rseek1:
push cx ;save r/w flag
mov dx,info
;dx will hold base of fcb
mov bx,ranrec
add bx,dx ;bx=.fcb(ranrec)
mov al,[bx]
and al,7fh
push ax ;record number
mov al,[bx]
rcl al,1 ;cy=lsb of extent#
inc bx
MOV CH,[BX]
RCL CH,1
AND CH,11111B ;CH=EXT#
;CH holds extent number,
;record stacked
MOV AL,[BX]
AND AL,11110000B
INC BX
OR AL,[BX]
MOV CL,4
ROL AL,CL
MOV CL,AL
XCHG CH,CL ;CH=MOD#, CL=EXT#
pop ax ;recall sought record #
MOV AH,[BX] ;HIGH BYTE OF RR FIELD MUST
AND AH,11111100B ;BE <= 3
mov bl,6 ;zero flag, l=6
;produce error 6,
;seek past physical eod
JZ $+5
JMP SEEKERR
;otherwise, high byte = 0
mov bx,nxtrec
add bx,dx ;bx=.fcb(nxtrec)
mov [bx],al ;sought rec# stored away
;
;arrive here with ch=mod#, cl=ext#, dx=.fcb, rec stored
;the r/w flag is still stacked. compare fcb values
;
PUSH DX
CALL CHK_INV_FCB
POP DX
JZ RANCLOSE
mov bx,modnum ;CHECK MODULE # FIRST
add bx,dx
mov al,ch ;b=seek mod#
;could be overflow at eof,
;producing module# of 90h
;or 10h, so compare all
;but fwf
sub al,[bx]
AND AL,3FH
JNZ RANCLOSE ;same?
mov bx,extnum
add bx,dx
MOV AL,[BX]
CMP AL,CL
JZ SEEKOK1 ;EXTENTS EQUAL
CALL COMPEXT
JNZ RANCLOSE
MOV [BX],CL ;EXTENTS IN SAME DIR FCB
;FCB(EXT) = CL
CALL GET_DIR_EXT
MOV CL,AL
CALL RESTORE_RC
CALL SET_RC
JMPS SEEKOK1
ranclose:
push cx
push dx ;save seek mod#,ext#, .fcb
call close ;current extent closed
pop dx
pop cx ;recall parameters and fill
mov bl,3 ;cannot close error #3
mov al,lret
inc al
jz badseek
MOV XDCNT,0FFFFH ;RESET XDCNT FOR MAKE
if MPM
MOV BYTE PTR SDCNT+1,0FFH
endif
mov bx,extnum
add bx,dx
mov [bx],cl ;fcb(extnum)=ext#
INC BX
INC BX
MOV AL,[BX] ;FCB(MODNUM)=MOD#
AND AL,40H ;COPY FILE WRITE FLAG
OR AL,CH
MOV [BX],AL
call open ;is the file present?
mov al,lret
inc al
jnz seekok ;open successful?
;cannot open file, read mode?
pop cx ;r/w flag to c (=0ffh if read)
push cx ;everyone expects this
;item stacked
mov bl,4 ;seek to unwritten extent #4
inc cl ;becomes 00 if read operation
jz badseek ;error if read operation
;write, make new extent
call make
mov bl,5 ;cannot create new extent #5
mov al,lret
inc al
jz badseek ;no dir space
;file make successful
if MPM
CALL FIX_OLIST_ITEM
endif
seekok:
MOV COMP_FCB_CKS,TRUE
SEEKOK1:
pop cx ;discard r/w flag
xor al,al
jmp staret ;with zero set
badseek:
;
;fcb no longer contains a valid fcb, mark
;with 1100$000b in modnum field so that it
;appears as overflow with file write flag set
;
push bx ;save error flag
MOV COMP_FCB_CKS,TRUE
CALL MAKE_FCB_INV
pop bx ;and drop through
seekerr:
pop cx ;discard r/w flag
MOV LRET,BL ;lret=#, nonzero
RET
;close ok
;ret
;
rdread:
;
;random disk read operation
;
mov cl,true ;marked as read operation
call rseek
JNZ RET19
JMP DISKREAD ;if seek successful
;
rdwrite:
;random disk write operation
mov cl,false ;marked as write operation
call rseek
JNZ RET19
JMP DISKWITE ;if seek successful
;
cmperr:
;compute random record position for getfilesize/setrandom
xchg bx,dx
add bx,dx
;dx=.buf(dptr) or .fcb(0),
;bx=.f(nxtrec/reccnt)
mov cl,[bx] ;pick up record no.
mov ch,0 ;cx = 0000 0000 ?rrr rrrr
mov bx,extnum
add bx,dx
mov ah,[bx]
mov al,0
shr ax,1
and ah,0fh
add cx,ax
;cx = 000? eeee errrr rrrr
mov bx,modnum
add bx,dx
mov al,[bx] ;AL = XXMM MMMM
AND AL,3FH
mov ah,16
mul ah ;AX = 0000 00MM MMMM 0000
add ch,al
;cx = mmmm eeee errr rrrr
MOV AL,0
ADC AL,AH ;AL = 0000 0?MM
RET19: ret
;
getfilesize:
;compute logical file size for current fcb
CALL GET_RRA ;ZERO RECEIVING RANREC FIELD
PUSH BX
XOR AL,AL
MOV [BX],AL
INC BX
MOV [BX],AL
INC BX
MOV [BX],AL
mov cl,extnum
call srch
getsize:
jz setsize
;current fcb addressed by dptr
call getdptra
mov dx,reccnt ;ready for compute size
call cmperr
;al=0000 000?,
;cx = mmmm eeee errr rrrr
;compare with memory, larger?
pop bx
push bx ;recall, replace .fcb(ranrec)
mov dl,al ;save cy
mov ax,cx
sub ax,[bx]
mov al,dl
sbb al,2[bx] ;carry if .fcb(ranrec) >
;directory
jb getnextsize ;for another try
;fcb is less or equal,
;fill from directory
mov 2[bx],dl
mov [bx],cx
getnextsize:
call srchn
MOV LRET,0
jmps getsize
setsize:
pop bx ;discard .fcb(ranrec)
ret
;
setrandom:
;set random record from the current fcb
MOV BX,DX
mov dx,nxtrec ;ready params for computesize
call cmperr ;dx=info, al=cy,
;cx=mmmm eeee errr rrrr
mov bx,ranrec
add bx,dx ;bx=.fcb(ranrec)
mov [bx],cx
mov 2[bx],al ;to ranrec
ret
;
TMP_SELECT: ;DL=DRIVE TO SELECT (0-F)
MOV BX,OFFSET SELDSK
MOV AL,[BX]
PUSH AX
MOV [BX],DL
CALL CUR_SELECT
POP AX
MOV SELDSK,AL
RET
;
XCURSELECT:
MOV RETURN_FFFF,TRUE
CALL CURSELECT
MOV RETURN_FFFF,FALSE
RET20A: RET
;
CURSELECT:
MOV AL,SELDSK
CMP AL,CURDSK
JE TEST_FF_DISK ;DON'T SELECT IF SELDSK = CURDSK
;
SELECT:
;select disk word ptr info for subsequent input or output ops
MOV DX,DLOG
CALL TEST_VECTOR
PUSH DX ;DL = 1 IF DRIVE LOGGED IN
;save it for test below,
;send to seldsk
call selectdisk
pop bx ;recall dlog vector
JNZ $+5
call selerror
;returns true if select ok
;is the disk logged in?
rcr bl,1
if MPM
JNB SELECT1
MOV DX,RLOG
CALL TEST_VECTOR
MOV REM_DRV,DL
RET
SELECT1:
endif
if CPM
JB RET20A ;rc
endif
;return if bit is set
;disk not logged in,
;set bit and initialize
mov cx,dlog
call setcdisk
mov dlog,bx ;dlog=set$cdisk(dlog)
if MPM
MOV AL,BYTE PTR CHKSIZ+1 ;IF HIGH ORDER BIT OF CHKSUM
RCL AL,1 ;VECTOR IS ZERO, THEN DRIVE
MOV AL,0
JB SELECT2 ;IS REMOVEABLE
MOV CX,RLOG
CALL SETCDISK
MOV RLOG,BX ;RLOG=SET_CDISK(RLOG)
MOV AL,1
SELECT2:
MOV REM_DRV,AL
endif
jmp initialize ;ret
;
TEST_FF_DISK:
INC AL
JNZ RET20A
JMP SEL_ERROR
;
SET_SELDSK:
MOV AL,LINFO
MOV SELDSK,AL
RET
;
RESELECTX:
MOV HIGH_EXT,0
JMP RESELECT1
;
reselect:
MOV CX,807FH ;CH = 80H, CL = 7FH
MOV BX,INFO
ADD BX,7
MOV AL,[BX] ;IF FCB(7) & 80H
AND AL,CH ;THEN XFCB_READ_ONLY = 80H
MOV XFCB_READ_ONLY,AL ;ELSE XFCB_READ_ONLY = 00H
AND [BX],CL ;FCB(7) = FCB(7) & 7FH
INC BX
MOV AL,[BX]
AND AL,CL ;FCB(8) = FCB(8) & 7FH
CMP AL,[BX]
MOV [BX],AL ;IF FCB(8) & 80H
MOV AL,60H ;THEN HIGH_EXT = 60H
JNZ RESELECT0
ADD BX,4 ;ELSE HIGH_EXT = FCB(12) & E0H
MOV AL,0E0H
AND AL,[BX]
RESELECT0:
MOV HIGH_EXT,AL
CALL CLR_EXT
CALL GETRCNTA
MOV AL,[BX] ;IF FCB(RCOUNT) & 80H
AND AL,CH ;THEN ACTUAL_RC = FCB(RCOUNT) & 7FH
JZ RESELECT1 ; FCB(RCOUNT) = 80H
MOV AL,[BX] ;ELSE ACTUAL_RC = 0
AND AL,CL
MOV [BX],CH
RESELECT1:
MOV ACTUAL_RC,AL
;check current fcb to see if reselection necessary
mov resel,true ;mark possible reselect
mov bx,info
mov al,[bx] ;drive select code
and al,00011111b ;non zero is auto drive select
dec al ;drive code normalized to
;0...30, or 255
mov linfo,al ;save drive code
cmp al,0FFH
JZ NOSELECT
;auto select function,
;save curdsk
MOV AL,SELDSK
mov olddsk,al ;olddsk=curdsk
mov al,[bx]
mov fcbdsk,al ;save drive code
and al,11100000b
mov [bx],al ;preserve hi bits
CALL SET_SELDSK
noselect:
CALL CURSELECT
;set user code
mov al,usrcode ;0...31
mov bx,info
or al,[bx]
mov [bx],al
ret20: ret
;
;
parsave33r:
call parsave33
jmp reselect
;
parsave36r:
call parsave36
jmp reselect
;
COPY_DMA_IN: ;COPY (CL) BYTES FROM USER'S
MOV SI,DMAAD ;DMA TO COMMON_DMA
MOV DI,OFFSET COMMON_DMA
PUSH DS
MOV DS,DMABASE
XOR CH,CH
REP MOVS AL,AL
POP DS
RET
;
COPY_DMA_OUT: ;COPY (CL) BYTES FROM COMMON_DMA
MOV DI,DMAAD ;TO USER'S DMA
MOV SI,OFFSET COMMON_DMA
PUSH ES
MOV ES,DMABASE
XOR CH,CH
REP MOVS AL,AL
POP ES
RET
;
CHK_PASSWORD:
CALL GET_DIR_MODE ;AL = DIR LBL DATA BYTE
AND AL,80H
JNZ CHK_PW ;BIT 0 ON => PASSWORDS ACTIVE
RET
;
GET_DIR_MODE:
MOV BX,DRVLBLA ;RETURN DIR LBL DATA BYTE IN AL
MOV AL,[BX]
RET
;
CHK_PW:
CALL GET_XFCB ;AL = XFCB PASSWORD MODE | 01H
JZ RET20 ;ZERO SET IF NO XFCB FOUND
DEC AL ;REMOVE LOW ORDER BIT
JZ RET20 ;ZERO SET IF PASSWORD MODE = 0
CALL CMP_PW ;COMPARE PASSWORDS
JZ RET20 ;ZERO SET IF PASSWORD OK
CHK_PW1: ;PASSWORD ERROR
MOV AL,7
JMP SET_ARET
;
CMP_PW: ;COMPARE PASSWORDS
;BX = .XFCB(12)
INC BX
MOV CH,[BX] ;FCB(13) = XFCB CHECKSUM
OR CH,CH
JNZ CMP_PW2 ;JUMP IF XFCB(13) ~= 0
MOV DX,BX ;SAVE BX
INC BX ;BECAUSE XFCB CHECKSUM IS ZERO
INC BX ;TEST FOR NULL PASSWORD
MOV CL,9 ;NULL PASSWORDS ARE ALL BLANKS AND/OR
CMP_PW1: ;ZEROS THAT SUM TO ZERO
INC BX ;ANY PASSWORD MATCHES A NULL PASSWORD
MOV AL,[BX]
DEC CL
JZ RET20 ;PASSWORD IS ALL BLANKS AND/OR ZEROS
OR AL,AL
JZ CMP_PW1
CMP AL,20H
JZ CMP_PW1
MOV BX,DX ;PASSWORD CONTAINS A VALUE OTHER
;THAN BLANK OR ZERO
CMP_PW2: ;BX = .XFCB(13)
LEA SI,10[BX]
LEA DX,3[BX] ;DX = .XFCB(16)
MOV BX,XDMAAD
MOV CL,8
CMP_PW3:
STD ;LODS DECREMENTS SI
LODS AL
XOR AL,CH ;EXCLUSIVE OR PASSWORD BYTE WITH CKS
CMP AL,[BX]
JNZ CMP_PW4 ;PASSWORD MISMATCH
INC BX
DEC CL
JNZ CMP_PW3
CLD
RET ;PASSWORD MATCHES
;
CMP_PW4:
CLD
MOV BX,OFFSET DF_PASSWORD ;COMPARE XFCB PASSWORD TO DEFAULT PW
MOV CL,8 ;BX = .DEFAULT PW, DX = .XFCB PASSWORD
JMP COMPARE
;
SET_PW: ;SET PASSWORD IN XFCB
PUSH BX ;SAVE .XFCB(12)
MOV CX,8 ;CH = 0, CL = 8
LEA SI,11[BX] ;SI = .XFCB(23)
MOV BX,XDMAAD
SET_PW0:
SUB AH,AH ;ZERO NULL PASSWORD FLAG
SET_PW1:
MOV AL,[BX]
MOV [SI],AL ;COPY PASSWORD CHAR TO XFCB
OR AL,AL ;IS PASSWORD CHAR ZERO?
JZ SET_PW2 ;YES
CMP AL,20H ;IS PASSWORD CHAR BLANK?
JZ SET_PW2 ;YES
INC AH ;PASSWORD IS NOT NULL
SET_PW2:
ADD CH,AL ;ADD PASSWORD CHAR TO XFCB CHKSUM
INC BX
DEC SI
DEC CL
JNZ SET_PW1
OR AH,CH ;IF (AH | CH) = 0 THEN PASSWORD IS NULL
POP BX
JNZ SET_PW3
MOV [BX],AH ;XFCB(EX) = 0, ZERO PASSWORD MODE
SET_PW3:
INC SI
MOV CL,8
SET_PW4:
MOV AL,[SI]
XOR AL,CH ;ENCRYPT PASSWORD CHARS IN XFCB
MOV [SI],AL
INC SI
DEC CL
JNZ SET_PW4
INC BX ;BX = .XFCB(13)
RET ;CH = XFCB PASWORD CHECKSUM
;
GET_XFCB: ;GET XFCB (SEARCH MODE)
SUB CH,CH
GET_XFCB0: ;GET NEXT XFCB (SEARCHN MODE)
MOV BX,INFO
MOV AL,[BX]
PUSH AX
OR B[BX],10H ;FCB(0) = FCB(0) | 10H
MOV CL,EXTNUM
CMP CH,0 ;TEST FOR MODE
JNZ GET_XFCB00
CALL SEARCH ;RETURNS WITH ZERO FLAG SET IF
JMPS GET_XFCB01 ;XFCB NOT FOUND
GET_XFCB00:
CALL SEARCHN ;RETURNS WITH ZERO FLAG SET IF
GET_XFCB01: ;XFCB NOT FOUND
MOV AL,0
MOV LRET,AL ;ZERO LRET
MOV BX,INFO
POP CX
MOV [BX],CL ;RESTORE FCB(0)
JNZ GET_XFCB1
RET ;XFCB NOT FOUND - AL = 0, ZFLAG SET
GET_XFCB1:
CALL GET_DPTRA
MOV DX,BX
ADD BX,EXTNUM
MOV AL,[BX]
AND AL,0E0H
OR AL,1 ;AL = XFCB(EXTNUM) & 0E0H + 1
RET ;XFCB FOUND, ZERO FLAG RESET
;
INIT_XFCB:
CALL SETCDR ;MAY HAVE EXTENDED THE DIRECTORY
MOV CX,1014H ;CH = 16, CL = 20
INIT_XFCB0: ;CH = FCB(0) LOGICAL OR MASK
;CL = ZERO COUNT
PUSH CX
CALL GETDPTRA ;DOES NOT USE CX
MOV SI,INFO ;XFCB(0) = FCB(0) | CH
MOV AL,[SI]
OR AL,CH
MOV [BX],AL
INC SI
INC BX
MOV CL,11
MOV DX,SI
CALL MOVE ;XFCB(1..11) = FCB(1..11)
MOV DX,SI ;DX = .FCB(12)
MOV BX,DI ;BX = .XFCB(12)
POP CX ;CL CONTAINS # OF REMAINING BYTES
SUB CH,CH ;OF XFCB TO ZERO
XOR AL,AL ;MOVE SETS DI TO ADDR OF NEXT CHAR
REP STOS AL
RET21: RET
;
CHK_XFCB_PASSWORD:
CALL GET_XFCB1 ;ACCESS XFCB IN DIRECTORY BUFFER
;BX = .XFCB(EX)
;AL = (XFCB(EXT) & E0H) | 1
DEC AL
CHK_XFCB_PASSWORD1:
JZ RET21
PUSH BX
CALL CMP_PW ;CHECK PASSWORD
POP BX
JZ RET21 ;RETURN WITH BX = .XFCB(EX)
JMP CHK_PW1
;
CHK_PWS:
CALL GET_DIR_MODE ;GET DIR LBL DATA BYTE
AND AL,80H
JZ RET21 ;RETURN IF PASSWORDS NOT ACTIVE
CALL GET_XFCB ;GET 1ST XFCB
CHK_PWS1:
JZ RET21 ;ZERO SET IF XFCB NOT FOUND
DEC AL
JZ $+7
CALL CMP_PW ;CHK PWS FOR XFCBS WITH NON-ZERO
;PASSWORD MODE
JNZ RET21 ;ZERO FLAG RESET => PASSWORD ERROR
MOV CH,1
CALL GET_XFCB0 ;GET NEXT XFCB
JMPS CHK_PWS1
;
STAMP1:
MOV CX,24
JMPS STAMP3
STAMP2:
MOV CX,28
STAMP3:
if MPM
MOV DX,OFFSET TOD
endif
if CPM
MOV DX,OFFSET STAMP
endif
CALL GETDPTRA
ADD BX,CX
MOV CL,4
JMP MOVE
;
COMPARE:
MOV CH,0
MOV SI,BX
MOV DI,DX
REP CMPS AL,AL
RET
if MPM
PACK_SDCNT:
;
;Packed_dcnt = dblk(low 15 bits) || dcnt (low 9 bits)
;
; if sdblk = 0 then dblk = shr(sdcnt,blkshf+2)
; else dblk = sdblk
; dcnt = sdcnt & (blkmsk || '11'b)
;
; packed_dcnt format (24 bits)
;
; 12345678 12345678 12345678
; 23456789 .......1 ........ sdcnt (low 9 bits)
; ........ 9abcdef. 12345678 sdblk (low 15 bits)
;
MOV BX,SDBLK
CMP BX,0 ;DOES SDBLK = 0?
JNE PACK_SDCNT1 ;NO
MOV BX,SDCNT
MOV CL,BLKSHF
ADD CL,2
SHR BX,CL
PACK_SDCNT1:
SHL BX,1 ;SHIFT DBLK LEFT 1
MOV DX,SDCNT
XOR AH,AH
MOV AL,BLKMSK
SHL AX,1
SHL AX,1
OR AL,11B
AND AX,DX ;DCNT = SDCNT & (BLKMSK || '11'B)
OR BL,AH
MOV PACKED_DCNT,AL
MOV WORD PTR PACKED_DCNT+1,BX
RET
;
;
;olist element = link(2) || atts(1) || dcnt (3) ||
; pdaddr(2) || opncnt(2)
;
; link = 0 -> end of list
;
; atts - 80 - open in locked mode
; 40 - open in unlocked mode
; 20 - open in read/only mode
; 10 - deleted item
; 0n - drive code (0-f)
;
; dcnt = packed sdcnt+sdblk
; pdaddr = process descriptor addr
; opncnt = # of open calls - # of close calls
; olist item freed by close when opncnt = 0
;
;llist element = link(2) || drive(1) || arecord(3)
; pdaddr(2) || .olist_item(2)
;
; link = 0 -> end of list
;
; drive - 0n - drive code (0-f)
;
; arecord = record number of locked record
; pdaddr = process descriptor addr
; .olist_item = address of file's olist item
;
SEARCH_OLIST:
mov bx,offset open_root! jmps search_listo
SEARCH_LLIST:
mov bx,offset lock_root! jmps search_listo
SEARCHN_LIST:
mov bx,cur_pos
search_listo:
mov prv_pos,bx
;
;search_olist, search_llist, searchn_list conventions
;
; CH = 0 -> return next item
; CH = 1 -> search for matching drive
; CH = 2 -> search for matching DCNT
; CH = 5 -> search for matching dcnt + pdaddr
;
; if found then z flag is set
; prv_pos -> previous list element
; cur_pos -> found list element
; else prv_pos -> list element to insert after
;
; olist and llist are maintained in drive order
;
srch_list1:
mov bx,[bx]! or bx,bx! jz srch_list3
or ch,ch! je srch_list6
inc bx! inc bx! mov cl,[bx]! and cl,0fh
mov dx,offset curdsk! mov si,dx
lods al! cmp al,cl! jne srch_list4
cmp ch,1! je srch_list5
mov cl,ch! push cx! push bx
inc dx! inc bx! call compare! pop bx
pop cx! jz srch_list5
srch_list2:
dec bx! dec bx
mov prv_pos,bx! jmp srch_list1
srch_list3:
or al,1! ret
srch_list4:
jae srch_list2
srch_list5:
pushf! dec bx! dec bx! popf
srch_list6:
mov cur_pos,bx! ret
DELETE_ITEM: ;BX -> item to be deleted
pushf! cli
mov si,[bx]! mov di,prv_pos! mov cur_pos,di
;prv_pos.link = delete_item.link
mov [di],si
;
mov si,free_root! mov free_root,bx
;delete_item.link = previous free_root
mov [bx],si! popf! ret
CREATE_ITEM: ;BX -> new item if successful
;Z flag set if no free items
mov bx,free_root! cmp bx,0! jnz $+3! ret
mov cur_pos,bx
;free_root = free_root.link
mov si,[bx]! mov free_root,si
;
mov si,prv_pos! mov di,[si]
;create_item.link = prv_pos.link
mov [bx],di
;prv_pos.link = .create_item
mov [si],bx! ret
SET_OLIST_ITEM: ;AL = attributes
;BX = olist entry address
inc bx! inc bx
mov si,offset curdsk! mov ah,[si]! or al,ah
lea dx,1[si]! mov [bx],al! inc bx
mov cl,5! call move
mov w[di],0
retl1:
ret
TST_OLIST:
mov chk_olist_flag,false! jmp chk_olist0
CHK_OLIST:
mov chk_olist_flag,true
chk_olist0:
mov dx,offset dcnt! mov bx,offset sdcnt
mov cl,4! call move
call pack_sdcnt! mov ch,3! call search_olist! jnz retl1
pop dx! test byte ptr 2[bx],80h! jz chk_olist05
push dx! push bx! call compare_pds! pop bx! pop dx! jz $+5
chk_olist05:
jmp openx06
push dx
test chk_olist_flag,true
jz retl1
call delete_item
inc_pdcnt:
mov al,pdcnt
chk_olist1:
add al,16! jz chk_olist1
mov pdcnt,al
ret
PR_TERM:
mov dx,pdaddr
mov bx,offset open_root! mov cur_pos,bx
pr_term1:
mov ch,0! push dx! call search_nlist! pop dx! jnz pr_term2
mov cx,6! push bx! call tst_tbl_lmt! pop bx! jnz pr_term1
call remove_locks! call delete_item
jmp pr_term1
pr_term2:
call func48
retl2:
ret
FLUSH_FILES:
test flushed,true! jnz retl2
mov flushed,true
FLUSH_FILE0:
mov bx,offset open_root! mov cur_pos,bx
flush_file1:
push ds! pop es
mov ch,1! call search_nlist! jnz retl2
push bx! call remove_locks! call delete_item! pop bx
mov bx,6[bx]! mov es,p_uda[bx]
test u_pd_cnt,1! jnz flush_file1
or u_pd_cnt,1! push ds! pop es
cmp bx,pdaddr! jnz flush_file1
call inc_pdcnt! jmps flush_file1
FREE_FILES:
;free_mode = 1 - remove curdsk files for process
; 0 - remove all files for process
mov dx,pdaddr! mov bx,offset open_root! mov cur_pos,bx
free_files1:
mov ch,free_mode
push dx! call search_nlist! pop dx! jnz retl25
mov cx,6! push bx! call tst_tbl_lmt! pop bx! jnz free_files1
cmp word ptr 3[bx],0ffffh! jnz free_files2
cmp byte ptr 5[bx],0ffh! jz free_files3
free_files2:
mov incr_pdcnt,true
free_files3:
call remove_locks! call delete_item
jmp free_files1
REMOVE_LOCKS: ;BX -> .olist_item
test byte ptr 2[bx],40h! jz retl25
push dx! push prv_pos
mov dx,bx! mov bx,offset lock_root! mov cur_pos,bx
remove_lock1:
mov ch,0! push dx! call searchn_list! pop dx
jnz remove_lock2
mov cx,8! push bx! call tst_tbl_lmt! pop bx! jnz remove_lock1
call delete_item
jmp remove_lock1
remove_lock2:
pop prv_pos! mov bx,dx! pop dx
retl25:
ret
TST_TBL_LMT:
add bx,cx
lea si,[bx]! cmp [si],dx! ret
CREATE_OLIST_ITEM:
mov ch,1! call search_olist
call create_item! mov al,attributes! call set_olist_item
ret
COUNT_OPENS:
mov open_cnt,0
mov dx,pdaddr! mov bx,offset open_root! mov cur_pos,bx
count_open1:
mov ch,0! push dx! call searchn_list! pop dx! jnz count_open2
mov cx,6! call tst_tbl_lmt! jnz count_open1
inc open_cnt! jmp count_open1
count_open2:
mov al,open_cnt! sub al,open_max
retl3:
ret
COUNT_LOCKS:
mov lock_cnt,0
mov dx,bx! mov bx,offset lock_root! mov cur_pos,bx
count_lock1:
mov ch,0! push dx! call searchn_list! pop dx! jnz retl3
mov cx,8! call tst_tbl_lmt! jnz count_lock1
inc lock_cnt! jmp count_lock1
CHECK_FREE:
mov dl,mult_cnt
CHECK_FREE0:
mov dh,0
mov bx,offset free_root! mov cur_pos,bx
check_free1:
mov ch,0! push dx! call searchn_list! pop dx! jnz check_free2
inc dh! cmp dh,dl! jb check_free1
retl4:
ret
check_free2:
pop bx! mov al,14! jmp sta_ret
LOCK:
mov cl,2! call copy_dma_in
call parsave36r! call check_fcb
test high_ext,80h! jz retl4
mov bx,xdmaad! mov bx,[bx]
mov al,curdsk! sub al,2[bx]! and al,0fh! jnz lock8
mov file_id,bx
test lock_unlock,true! jz lock1 ; jump if unlock
call count_locks
mov al,lock_cnt! add al,mult_cnt! jb lock0
cmp lock_max,al! jae lock05
lock0:
mov al,12! jmp sta_ret ; too many locks
lock05:
call check_free
lock1:
call save_rr! mov bx,offset lock9! push bx! mov ah,mult_cnt
lock2:
push ax! call get_lock_add
test lock_unlock,true! jz lock3 ; jump if unlock
call test_lock
lock3:
pop ax! dec ah! jz lock4
call incr_rr! jmps lock2
lock4:
call reset_rr! mov ah,mult_cnt
lock5:
push ax! call get_lock_add
test lock_unlock,true! jz lock6 ; jump if unlock
call set_lock! jmp lock7
lock6:
call free_lock
lock7:
pop ax! dec ah! jz retl5
call incr_rr! jmps lock5
lock8:
mov al,13! jmp sta_ret
lock9:
call reset_rr
retl5:
ret
GET_LOCKADD:
mov lock_sp,sp! mov lock_shell,true
call rseek
mov lock_shell,false
call getfcb
cmp aret,0! jnz lock_err
call index! call alloct
mov bx,1! jz lock_err
call atran
ret
LOCK_PERR:
mov lock_shell,false! mov sp,lock_sp
LOCK_ERR:
pop dx ; discard return address
pop cx ; CH = mult_cnt - # recs processed
mov al,mult_cnt! sub al,ch
mov cl,4! shl al,cl! or bh,al! mov aret,bx
retl6:
ret
TEST_LOCK:
call move_arecord
mov ch,3! call search_llist! jnz retl6
call compare_pds! jz retl6
mov bx,8! jmp lock_err
SET_LOCK:
call move_arecord
mov ch,1! call search_llist
pushf! cli
call create_item
xor al,al! call set_olist_item
mov dx,file_id! mov [di],dx
popf
retl7:
ret
FREE_LOCK:
call move_arecord
mov ch,5! call search_llist! jnz retl7
free_lock0:
call delete_item
mov ch,5! call searchn_list! jnz retl7
jmp free_lock0
COMPARE_PDS:
add bx,6! mov dx,offset pdaddr
mov cl,2! jmp compare
MOVE_ARECORD:
mov dx,offset arecord! mov bx,offset packed_dcnt
mov cl,3! jmp move
FIX_OLIST_ITEM:
mov si,offset xdcnt! mov di,offset sdcnt
mov cx,2
rep cmps ax,ax ; is xdcnt < sdcnt?
jae retl7 ; no
;yes - update olist entries
call swap! call sdcnt_eq_xdcnt
mov bx,offset open_root! mov cur_pos,bx
;find file's olist entries & change dcnt values
fix_ol1:
call swap! call pack_sdcnt! call swap
mov ch,3! call searchn_list! jnz retl8
;update olist entry with new dcnt value
push bx! call pack_sdcnt! pop bx
add bx,3! mov dx,offset packed_dcnt
mov cl,3! call move! jmp fix_ol1
REMOVE_DRIVE:
mov cl,curdsk! mov dx,1! shl dx,cl
not dx! and bx,dx
retl8:
ret
DISKRESET:
mov ntlog,0! mov set_ro_flag,0
mov bx,info
intrnl_disk_reset:
cmp open_root,0! jz retl8
mov al,curdsk! push ax! mov ch,0
dskrst1:
shr bx,1! jb dskrst3
dskrst2:
inc ch! cmp bx,0! jnz dskrst1
pop ax! mov curdsk,al
mov bx,ntlog! or tlog,bx
inc al! ret
dskrst3:
push cx! push bx! mov curdsk,ch! mov cl,ch
mov dx,tlog! call test_vector1! push dx
mov dx,rlog! call test_vector1! push dx
mov dx,rodsk! call test_vector1! pop bx
or bl,set_ro_flag! or bl,dl! pop dx! or bl,dl! mov check_disk,bl
mov bx,offset open_root! mov cur_pos,bx
dskrst4:
mov ch,1! call search_nlist! jnz dskrst6
test check_disk,true! jz dskrst5
push bx! call compare_pds! jz dskrst45
pop dx! xor al,al! jmp dskrst6
dskrst45:
mov cx,ntlog! mov al,curdsk! call set_cdisk1
mov ntlog,bx! pop bx! jmp dskrst4
dskrst5:
mov bx,info! call remove_drive! mov info,bx
or al,1
dskrst6:
pop bx! pop cx! jz $+5! jmp dskrst2
;error - olist item exists for another process
; on a removeable or read/only drive to be reset
; or any kind of drive if function is write protect disk
pop ax! mov curdsk,al
cmp error_mode,0ffh! je dskrst7
add ch,41h! mov denieddrv,ch
mov bx,dx! mov bx,6[bx]! mov al,p_cns[bx]! add al,30h
mov deniedcns,al
lea dx,p_name[bx]! mov bx,offset deniedprc
mov cl,8! call move
mov cx,offset deniedmsg
call xprint
dskrst7:
pop bx! mov aret,0ffffh! ret
endif