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

2379 lines
54 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

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

;************ bdos file system part 3 ************
conv_rr: ;convert random record #
;-------
mov al,info_fcb+ranrec ;AL = fcb(ranrec(0))
mov dl,al
and dl,7fh ;record number
rcl al,1 ;cy=lsb of extent#
mov al,info_fcb+ranrec+1 ;AL = fcb(ranrec(1))
mov ch,al
rcl ch,1
and ch,11111b ;CH = extent #
;DL = record #
and al,11110000b
or al,info_fcb+ranrec+2
mov cl,4
rol al,cl
mov cl,ch
mov ch,al ;CH = mod#, CL = ext#
ret
rseek: ;random access seek operation
;-----
; fcb is assumed to address an active fcb
; (modnum has been set to 1100$0000b if previous bad seek)
; entry: CL = true if read operation
; = false if write operation
; exit: Z flag set if successful
push cx ;save r/w flag (indexed on stack)
call conv_rr ;CH = mod #, CL = ext#, DL = record #
cmp byte ptr info_fcb+ranrec+2,3 ;r(3) field must
;be <= 3
mov bl,6 ;zero flag, BL=6
;produce error 6,
jbe $+5 ;seek past physical eod
jmp seekerr ;random record out of range
;otherwise, high byte = 0
mov info_fcb+nxtrec,dl ;record number
; arrive here with CH=mod#, CL=ext#, SI=.fcb, rec stored
; the r/w flag is still stacked. compare fcb values
cmp fx_intrn,fxi99
je rseek3
call chk_inv_fcb
jz rseek3
;check module # first
mov al,ch ;b=seek mod#
;could be overflow at eof,
;producing module# of 90h
;or 10h, so compare all
;but fwf
sub al,info_fcb+modnum
and al,3fh ;same modnum?
jnz ranclose ; no
mov al,info_fcb+extnum
cmp al,cl
jnz $+5
jmp seekok1 ;extents equal
call compext
jnz ranclose
push cx
call get_dir_ext
pop cx
cmp al,cl ;is dir_ext < new extent?
jnb rseek2 ;no
test high_ext,80h ;is open mode unlocked?
jnz rseek2 ;yes
pop dx! push dx ;dl = read/write flag
inc dl ;is this a write fx?
jnz rseek2 ;yes
inc dl ;reset z flag
pop dx ;discard read/write flag
jmp set_lret1 ;lret=1, reading unwritten data
rseek2:
mov info_fcb+extnum,cl ;fcb(ex) = new extent
mov cl,al
call restore_rc
call set_rc
jmps seekok1
ranclose:
push cx ;save seek ext# and mod#
call close ;current extent closed
pop cx ;recall ext# and mod#
mov bl,3 ;cannot close error #3
mov al,lret
inc al
jz seekerr
rseek3:
mov xdcnt,0ffffh ;reset xdcnt for make
if BMPM
mov byte ptr sdcnt+1,0ffh
endif
xchg info_fcb+extnum,cl ;fcb(extnum)=ext#
mov al,info_fcb+modnum
xchg ch,al
push cx ;save CL=extent and CH=module
and ch,40h ;copy file write flag
or al,ch
mov info_fcb+modnum,al ;fcb(modnum)=mod#
call open ;is the file present?
mov al,lret
inc al
jnz seekok ;open successful?
;cannot open file, read mode?
mov bp,sp ;CL = r/w flag (=0ffh if read)
mov cx,2[bp] ;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 BMPM
call fix_olist_item
endif
seekok:
pop cx ;discard ext and mod
if BMPM
mov comp_fcb_cks,true
endif
if BCPM
call set_lsn
endif
seekok1:
pop cx ;discard r/w flag
xor al,al
jmp set_lret ;with Z flag set
badseek: ;restore fcb(ext) and fcb(mod)
pop ax ;AL = extent, AH = module
mov info_fcb+extnum,al
mov info_fcb+modnum,ah
seekerr:
pop cx ;discard r/w flag
mov lret,bl ;lret=#
or bl,bl ;Z flag reset
ret
if BMPM
test_disk_fcb:
;-------------
; exit: Z flag reset if file opened in unlock mode and
; access of dir fcb was successful
test high_ext,80h ;was file opened in unlocked mode
jz ret13a ;no
test dont_close,0ffh ;return if dont_close false
jz ret13a
call close1 ;fcb in memory
test_disk_fcb1:
mov bx,offset lret
cmp b[bx],0ffh
jne not_err
pop si ;discard return address
mov al,11 ;unallocated block verify error
mov lock_shell,false ;in case called from check_rec
jmp set_lret ;error - close operation unsuccessful
not_err:
mov b[bx],0 ;lret = 0
mov al,info_fcb+reccnt
mov rcount,al
xor al,al
mov dont_close,al ;dont_close = false
inc al ;successful operation, reset zero flag
ret13a: ret
endif
CHECK_NPRS:
;----------
; DIR_CNT CONTAINS THE NUMBER OF 128 BYTE RECORDS
; TO TRANSFER DIRECTLY. THIS ROUTINE SET DIR_CNT
; WHEN INITIATING A SEQUENCE OF DIRECT PHYSICAL I/O
; OPERATIONS. DIR_CNT IS DECREMENTED EACH TIME CHECK_NPRS
; IS CALLED DURING SUCH A SEQUENCE.
; exit: ~C FLG & ~Z FLG - DIRECT PHYSICAL I/O OPERATION
; ~C FLG & Z FLG - INDIRECT(DEBLOCK) I/O OPERATION
; C FLG - NO PHYSICAL I/O OPERATION
MOV CH,blk_off ;CH = VRECORD & BLKMSK
MOV AL,DIR_CNT
CMP AL,2 ;IS DIR_CNT > 1?
JC CHECK_NPR1 ;NO
DEC AL ;DIR_CNT = DIR_CNT - 1
MOV DIR_CNT,AL ;we are in mid-multi sector i/o
STC
ret ;RETURN WITH C FLAG SET
CHECK_NPR1:
MOV AL,PHYMSK ;CL = PHYMSK
MOV CL,AL
AND AL,CH ;AL = VRECORD & PHYMSK
;ARE WE IN MID-PHYSICAL RECORD?
JZ CHECK_NPR11 ;NO
CHECK_NPR1X:
OR CL,CL ;IS PHYMSK = 0?
JZ CHECK_NPR1Y ;YES
XOR AL,AL ;RETURN WITH Z FLAG SET & C FLAG RESET
RET
CHECK_NPR1Y:
OR AL,1 ;RESET C & Z FLAGS
RET
CHECK_NPR11:
MOV DH,CL
not DH ;DH = ~ PHYMSK
MOV AL,MULT_NUM
CMP AL,2 ;IS MULT_NUM < 2?
JC CHECK_NPR1X ;YES
TEST HIGH_EXT,80H ;WAS FILE OPENED IN UNLOCKED MODE?
JNZ CHECK_NPR1X ;YES
CMP FX_INTRN,FXI40 ;DOES FX = F_WRITEZF?
JE CHECK_NPR1X ;YES
MOV BX,OFFSET VRECORD
MOV AH,[BX] ;AH = VRECORD
ADD AL,ah
CMP AL,80H
JC CHECK_NPR2
MOV AL,80H
CHECK_NPR2: ;AL = MIN(VRECORD + MULT_NUM,80H) = X
PUSH CX ;SAVE VRECORD & BLKMSK, PHYMSK
MOV B[BX],7FH ;VRECORD = 7F
PUSH BX! PUSH AX
MOV BL,AL ;BL = X
MOV AL,BLKMSK
MOV DL,AL
INC DL ;DL = BLKMSK + 1
not AL
AND AH,AL ;AH = VRECORD & ~BLKMSK
TEST RMF,0FFH ;READ FUNCTION?
JZ CHECK_NPR21 ;NO
MOV AL,RCOUNT
AND AL,DH ;AL = RCOUNT & ~PHYMSK
CMP AL,BL ;IS AL < X?
JC CHECK_NPR23 ;YES
CHECK_NPR21:
MOV AL,BL ;AL = MIN(VRECORD + MULT_NUM,80H) = X
CHECK_NPR23:
SUB AL,AH ;AL = AL - VRECORD & ~BLKMSK
CMP AL,DL ;IS AL < BLKMSK + 1?
JC CHECK_NPR9 ;YES
PUSH AX ;AL = MAX # OF RECORDS
CALL DMPOSITION ;COMPUTE MAXIMUM DISK POSITION
MOV CH,AL ;CH = MAX DISK POS
MOV AL,DMINX ;AL = CURRENT DISK POS
CMP AL,CH ;IS CURR POS = MAX POS?
MOV DL,AL
JZ CHECK_NPR5 ;YES
MOV CL,AL
PUSH CX ;CL = CURR POS, CH = MAX POS
MOV CH,0
CALL GETDM ;BX = BLOCK NUMBER (CURR POS)
CHECK_NPR4:
PUSH BX
INC CX ;CURR POS = CURR POS + 1
CALL GETDM ;GET NEXT BLOCK(CURR POS)
POP DX
INC DX
CMP BX,DX ;DOES CURR BLK = LAST BLK + 1?
JZ CHECK_NPR4 ;YES
test rmf,0ffh ;write function?
jnz check_npr45 ; no
or bx,bx! jnz check_npr45 ;does curr blk = 0?
cmp dx,maxall ;is last blk + 1 >= max alloc blk
jae check_npr45 ; yes
push cx! push dx
mov cx,dx
call getallocbit
pop bx! pop cx
shr al,1! jnc check_npr4 ;if blk not allocated it will be
check_npr45:
DEC CL ;CL = INDEX OF LAST SEQ BLK
POP DX
MOV AL,DH ;AL = MAX POS
CMP AL,CL ;IS AL < LAST SEQ BLK POS
JC CHECK_NPR5 ;YES
MOV AL,CL
CHECK_NPR5: ;AL = LAST BLK POS
SUB AL,DL ;AL = AL - STARTING POS
MOV CH,AL
INC CH ;CH = # OF CONSECUTIVE BLOCKS
MOV AL,BLKMSK
INC AL ;AL = BLKMSK + 1
MUL CH ;AL = # OF CONSECUTIVE LOGICAL RECS
POP CX ;CL = MAXIMUM # OF RECORDS
XCHG AL,CL
TEST RMF,0FFH ;READ FUNCTION?
JZ CHECK_NPR8 ;NO
CMP AL,CL ;IS MAX < # OF CONS. RECS?
JC CHECK_NPR9 ;YES
CHECK_NPR8:
MOV AL,CL
CHECK_NPR9: ;AL = # OF CONSECUTIVE RECS
POP CX
POP BX
MOV [BX],CH ;RESTORE VRECORD
POP CX
MOV DH,MULT_NUM
SUB AL,CH ;AL = AL - VRECORD & blkmsk
CMP AL,DH ;IS AL < MULT_NUM
JC CHECK_NPR10 ;YES
MOV AL,DH
CHECK_NPR10: ;AL = # OF CONSECUTIVE RECS
not CL
AND AL,CL ;IF DIR_CNT = 0 THEN
JZ RET13B ;RETURN WITH Z FLAG SET, C FLAG RESET
MOV DIR_CNT,AL ;DIR_CNT = AL & ~PHYMSK
TEST RMF,0FFH ;READ FUNCTION?
JZ CHECK_NPR10X ;NO
PUSH AX
CALL flushx ;FLUSH BLOCKING/DEBLOCKING
POP AX ;BUFFERS FOR DRIVE
CHECK_NPR10X:
MOV CL,PHYSHF
SHR AL,CL ;AL = # OF CONSECUTIVE PHYSICAL RECS
mov mult_sec,al ;save multisector count for r/w
OR AL,1 ;RETURN WITH C AND Z FLAGS RESET
RET13B: RET
diskread: ;enter here for sequential and random disk reads
;--------
call tst_inv_fcb ;verify fcb has not been flagged
mov al,true ;as invalid
mov rmf,al ;read mode flag =
;true (open$reel)
;read the next record from
;the current fcb
if BMPM
mov dont_close,al
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 BMPM
; 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 disk_read0 if dont_close
jnz disk_read0 ;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
;now check for open ok
cmp lret,0 ;stop at eof
jnz diskeof
recordok: ;fcb addresses a record to read
call index ;error 2 if reading
;unwritten data
;(returns 1 to be compatible
;with 1.4)
;arecord=0000?
if BMPM
jnz recordok1
call test_disk_fcb ;jump back to disk_read0 if dont_close
jnz disk_read0 ;true, file opened in unlocked mode,
;and access of dir fcb successful
endif
jz diskeof
recordok1: ;record has been allocated, read it
if BMPM
call test_lock ;check if record locked by another
endif
call atran ;arecord now a disk address
CALL CHECK_NPRS
JC RECORDOK2
JNZ $+5
JMP READ_DEBLOCK
CALL SETDATA
call seek ;to proper track,sector
call rdbuff ;to dma address
RECORDOK2:
jmp setfcb ;replace parameter
diskeof:
jmp set_lret1 ;lret = 1
;ret
init_wzf: ;F_WRITEZF physical record initialization routine
;--------
MOV AL,PHYMSK
INC AL
XOR AH,AH
PUSH AX ;AX = PHYMSK + 1
xchg al,ah
shr ax,1 ;times 128
mov cx,ax ;CX = # OF BYTES IN PHY RECORD
MOV di,DIR_BCBA
sub di,12
FILL00:
mov di,12[di]
cmp word ptr 12[di],0 ;check if last bcb
JNZ FILL00 ;BX = OLDEST DIRECTORY BCB
MOV b[di],0ffh ;BCB(0) = 0FFH, DISCARD BCB
mov di,10[di]
mov cur_dma,di
mov cur_dma_seg,ds
XOR AL,AL ;ZERO PHYSICAL RECORD BUFFER
REP STOS AL
pop ax
ret
diskwrite: ;enter here for sequential and random disk writes
;---------
mov rmf,false ;read mode flag
;write record to currently
;selected file
call checkwrite ;in case write protected
mov al,info_fcb+modnum
rcl al,1! not al
test xfcb_read_only,al ;read/only error if xfcb_read_only true
mov ah,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,offset info_fcb ;bx = .fcb(0)
call ckrofile ;may be a read-only file
call tst_inv_fcb ;test for valid fcb
call update_stamp
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 openreel ;try to open next extent
test lret,true
jz dskwr0
ret
dskwr0:
if BMPM
mov dont_close,true
;if file is opened unlocked,
call test_lock ; verify record is not locked
; by another process
disk_write1:
endif
call index
JZ DISK_WRITE2
mov cl,0 ;marked as normal write
;operation for wrbuff
jmps dskwr1
disk_write2:
if BMPM
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 set_lret ;lret=2
blockok:
if BMPM
mov comp_fcb_cks,true ;must recompute fcb checksum
endif
mov arecord,bx ;bx contains allocated block #
mov dx,bx ;place unallocated block in
call ua_setup ; list for pre read check
;block number in dx preserved
mov bx,offset info_fcb+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:
add bx,ax ;allocate a word value
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
mov wflag,cl ;save the write flag
call atran ;arecord set
diskwr10:
cmp fx_intrn,fxi40 ;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 WFLAG,0 ;RESET WRITE FLAG
PUSH arecord ;SAVE ARECORD
call init_wzf
push ax ;AX = phymsk + 1
mov cl,blkmsk ;set high water mark for
call ua_preread ; pre read check
MOV ax,ARECORD1
MOV CL,2 ;SET WRITE FLAG
FILL2:
MOV ARECORD,ax
PUSH CX
call discard_data
CALL SEEK
POP CX
CALL WRBUFF
MOV ax,ARECORD ;ARECORD = ARECORD + PHYMSK + 1
POP bx
PUSH bx
ADD ax,bx
MOV bl,BLKMSK ;END OF BLOCK?
AND bl,al
MOV CL,0
JNZ FILL2 ;NO
POP BX
POP ARECORD ;RESTORE ARECORD
dskw11:
CALL CHECK_NPRS
JC DONT_WRITE
JNZ WRITE
MOV AH,2
CALL DEBLOCK_DTA
jmps write_done
WRITE:
CALL SETDATA
call seek ;to proper file position
call discard_data
mov cl,blk_off ;set high water mark for
call ua_preread ; preread check
MOV CL,WFLAG ;(cl=2 if new block,0 if not)
;set wflag to zero if blk_off
cmp blk_off,0 ;does not specify 1st record of
JZ WRITE0 ;new block
MOV CL,0
WRITE0:
call wrbuff ;written to disk
;inc rec count if rcount <= vrecord
jmps write_done
dont_write:
call discard_data ;discard existing block for phys write
write_done:
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 BMPM
;disabling extention of reccnt to block size for unlocked files
test high_ext,00h
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
and info_fcb+modnum,not fwfmsk
if BMPM
test high_ext,80h ;is file open mode unlocked?
jz dskwr2a
mov al,[bx]
mov info_fcb+reccnt,al ;restore fcb(rcount)
cmp mult_cnt,1
jne dskwr2a
call close
call test_disk_fcb1
dskwr2a:
endif
noupdate:
call getmodnum ;set file write flag if reset
and al,40h
jnz dskwr3
or b[bx],40h
and info_fcb+modnum,not fwfmsk ;reset fcb write flag to ensure
;t3' gets reset by the close function
dskwr3:
jmp setfcb ;replace parameters
;ret
compute_rr: ;compute random record position for getfilesize/setrandom
;----------
; entry: BX = offset of fcb
; DX = index into fcb to pick record no. from
; exit: AL,CX = random record number
; BX = offset of fcb
xchg bx,dx
add bx,dx
;dx=.buf(dptr) or .fcb(0),
;bx=.f(nxtrec/reccnt)
mov cl,[bx] ;pick up record no.
xor ch,ch ;cx = 0000 0000 ?rrr rrrr
mov bx,dx
mov ah,extnum[bx]
shr ax,1
and ax,0f80h
add cx,ax ;cx = 000? eeee errrr rrrr
mov al,modnum[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
compare_rr: ;compare dir to fcb random records
;----------
; entry: AL,CX = directory random record #
; exit: C flag set
; BX = .fcb(rndrec)
mov bx,offset info_fcb+ranrec
cmp al,2[bx]! jne ret19
cmp cx,[bx] ;carry if .fcb(ranrec) >
ret ;directory
selectdisk:
;----------
; select the disk drive given in AL, and fill
; the base addresses curtrka - alloca, then fill
; the values of the disk parameter block
; entry: AL = disk to select
; exit: C flag set if no error
push dx
mov cl,al ;current disk# to CL
;lsb of DL = 0 if not yet
mov al,io_seldsk ;logged in
call xiosif ;BX filled by call
pop dx ;BX = 0000 if error,
or bx,bx ;otherwise disk headers
jz ret19 ;rz - carry flag reset
inc bx! inc bx
mov cdrmaxa,bx
inc bx! inc bx
mov drvlbla,bx ;media flag = drv lbl + 1
add bx,4 ;lsn_add = drvlbl + 2
mov si,bx
MOV di,offset dpbaddr ;SI= source for move, DI=dest
mov cx,addlist ;addlist filled
rep movsb ;now fill the disk
mov si,dpbaddr ;parameter block
if PCMODE
lodsw
cmp ax,0FFFFh ! jne cpm_format ;if format is PC-DOS
add dpbaddr,(pclist + 2 - dpblist) ;DPBADDR -> CPM DPB
mov di,offset nfats
mov cx,pclist
rep movsb ;copy extended DPB to local area
test dl,1 ! jnz loggedin ;if disk is not logged in
push ax
call get_fat ;read FAT into hash table area
pop ax
or bx,bx ! jz ret4
loggedin:
mov al,1 ; PC-DOS media format
jmps sel_exit
cpm_format:
mov di,offset sectpt ;DI is destination
stosw
mov cx,dpblist-2
rep movsb ;copy in CP/M DPB
xor al,al ; CP/M media format
sel_exit:
mov media_format,al
else
mov di,offset sectpt ;DI is destination
mov cx,dpblist
rep movsb ;copy in CP/M DPB
endif
;set single/double map mode
mov al,byte ptr maxall+1 ;largest allocation number
or al,al
jz retselect ;if high order of maxall not
mov al,1 ;zero then use double disk map
retselect:
dec al
mov single,al ;true if single disk map mode
stc ;select disk function ok
ret4:
ret
if PCMODE
get_fat:
;-------
; Exit: BX = 0 if no fats could be read
mov ax,fatadd ;AX = phys record offset of first FAT
mov cx,nfats ;get number of FATs for error retries
get_fat1:
push ax ! push cx
xor dx,dx ;convert FAT record offset to
div sectpt ;sectors and tracks for I/O system
mov track,ax
mov sector,dx
mov al,byte ptr nfatrecs
mov mult_sec,al ;multi sector count = # FAT records
mov ax,hash_seg
mov cur_dma_seg,ax ;read FAT into hash table area
mov cur_dma,0
mov al,IO_READ
call rwxiosif ;call I/O system to read FAT
mov bx,1
pop cx ! pop dx
or al,al ! jz get_fat2 ;if an error occured during the read
mov ax,nfatrecs ; try reading the next FAT
add ax,dx
loop get_fat1
xor bx,bx ;could'nt read any of the FAT's
get_fat2:
ret
update_fat:
;----------
mov ax,fatadd ;AX = save physical record offset
; of first FAT
mov cx,nfats ;get number of FATs to update
xor bx,bx
update_fat1:
push ax ! push bx ! push cx
xor dx,dx ;convert FAT record offset to
div sectpt ;sectors and tracks for I/O system
mov track,ax
mov sector,dx
mov al,byte ptr nfatrecs
mov mult_sec,al ;multi sector count = # FAT records
mov ax,hash_seg
mov cur_dma_seg,ax ;write FAT in hash table area
mov cur_dma,0
mov al,IO_WRITE
call rwxiosif ;call I/O system to write FAT
pop cx ! pop bx
or bx,ax ;save error code
pop ax
add ax,nfatrecs ;write the next FAT
loop update_fat1
mov al,bl
mov ah,true
jmp diocomp
endif
disk_select:
;-----------
; entry: AL = disk to select
; exit: Z flag set if drive logged in
mov adrive,al
disk_select1:
mov curdsk,al
mov dx,dlog
call test_vector ;dl = 1 if drive logged in
push dx ;save it for test below, send to seldsk
call selectdisk
pop bx ;recall dlog vector
jnc select0 ;carry set if select ok
dec bl ;is the disk logged in?
ret
tmp_select:
;----------
; entry: DL = drive to select (0-f)
mov seldsk,dl
curselect:
;---------
mov al,seldsk
cmp al,curdsk
jne select ;don't select if seldsk = curdsk
inc al! jz select0
ret19a: ret
SELECT: ;select disk in info_fcb for subsequent input or output ops
;------
cmp al,16 ! jb sel0
select0:
jmp selerror
sel0:
call disk_select
jz ret19a ;rz
;return if bit is set
if PCMODE
cmp media_format,0
jne sel_pc
call initialize ;disk not logged in,
jmps sel1
sel_pc:
call initialize_pc
sel1: ;set bit and initialize
else
call initialize ;disk not logged in,
endif
mov bx,offset dlog
call setcdisk ;dlog=set$cdisk(dlog)
cmp chksiz,8000h
je select2 ;drive is permanent
mov bx,offset rlog
call setcdisk ;rlog=setcdisk(rlog)
select2:
ret
reselectx:
;---------
xor al,al
mov high_ext,al
mov xfcb_read_only,al
jmps reselect1
reselect:
;--------
mov cx,807fh ;ch = 80h, cl = 7fh
mov bx,offset info_fcb+f7
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
mov al,4[bx] ;else high_ext = fcb(12) & e0h
and al,0e0h
reselect0:
mov high_ext,al
call clr_ext
reselect1: ;check current fcb to see if reselection necessary
mov resel,true ;mark possible reselect
mov al,info_fcb ;drive select code
mov fcbdsk,al ;save drive
and al,00011111b ;non zero is auto drive select
dec al ;drive code normalized to
;0...30, or 255
cmp al,0ffh
jz noselect ;auto select function,
mov seldsk,al ;save seldsk
noselect:
call curselect
;set user code
mov al,usrcode ;0...31
mov info_fcb,al
noselect0:
CALL TST_LOG_FXS ;IS FX = 15,17,22,23,30?
JNZ noselect1
mov rd_dir_flag,0f0h ; yes - must read directory to
noselect1:
call check_media ;chk media change on current disk
;jmps check_all_media ;chk media change on other disks
check_all_media:
;---------------
; This routine checks all logged-in drives for
; a set DPH media flag and pending buffers. It reads
; the directory for these drives to verify the media
; has not changed. If the media has changed the drive
; gets reset (but not relogged-in).
xor al,al
xchg media_flag,al ;reset SCB media flag
test al,al ;was SCB media flag set
jz ret20 ; no
mov bx,dlog ;test logged-in drives only
mov al,16
chk_am1:
dec al
shl bx,1! jnc chk_am5 ;is drive logged-in
push ax! push bx ; yes
call disk_select ;get DPH
mov bx,dat_bcba
mov bx,[bx]
chk_am2:
or bx,bx! jz chk_am4 ;end of bcb list?
test byte ptr 4[bx],0ffh ; no - is buffer pending
jnz chk_am3 ; yes
mov bx,12[bx] ;get next bcb
jmps chk_am2
chk_am3:
call check_media ;write pending, chk media change
chk_am4:
pop bx! pop ax
chk_am5:
or al,al! jnz chk_am1
jmp curselect
check_media: ;chk media if DPH media flag set
;-----------
mov bx,drvlbla
xor al,al
xchg 1[bx],al ;RESET MEDIA FLAG
or al,al ;was media flag set
JZ RET20 ;NO
;DISCARD DIRECTORY BUFFERS
CALL discard_dir ;READ DIRECTORY TO TEST FOR MEDIA
CALL SETENDDIR ;CHANGE
push dcnt ;save dcnt incase media hasnt changed
check_media1:
MOV CL,FALSE
CALL RDIR
xor al,al ;reset relog flag
xchg relog,al
test al,al ;HAS CHECKSUM ERROR BEEN DETECTED?
jz check_media2 ; no
cmp fx_intrn,fxi48 ;is func# = flush buffer
jz check_media3 ; yes
mov al,adrive ;is flush to another drive ?
cmp al,seldsk
jnz check_media3 ; yes
pop dcnt ;restore dcnt
call drv_relog
jmp chk_exit_fxs
check_media2:
CALL COMPCDR ;HAS DIR HIGH WATER MARK BEEN REACHED
jc check_media1 ; no
check_media3:
pop dcnt ;restore dcnt media has not changed
ret20: ret
copy_dma_in_8:
;-------------
mov cl,8
copy_dma_in: ;copy (cl) bytes from user's
;-----------
; entry: CL = number of bytes to copy
mov si,dma_ofst ;dma to common_dma
mov di,offset common_dma
push ds
mov ds,dma_seg
xor ch,ch
rep movs al,al
pop ds
ret
get_dir_mode:
;------------
; exit: AL = directory label data byte
mov bx,drvlbla ;return dir lbl data byte in al
mov al,[bx]
ret
get_xfcb: ;get xfcb (search mode)
;--------
; exit: Z flag set if no xfcb exists
; BX = .xfcb(pwmode)
; DX = .xfcb(0)
; AL = pwmode + 1
mov bx,offset info_fcb
mov al,[bx]
push ax
or b[bx],10h ;fcb(0) = fcb(0) | 10h
call search_ext ;returns with zero flag set if
pop ax ; xfcb not found
mov info_fcb,al ;restore fcb(0)
mov lret,0 ;zero lret
jnz get_xfcb1
ret ;xfcb not found - al = 0, zflag set
get_xfcb1:
call get_dptra ;get directory pointer
mov dx,bx ;DX = .directory_xfcb(0)
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 get_dptra ;does not use cx
mov si,offset info_fcb ;xfcb(0) = fcb(0) | ch
lodsb
or al,ch
mov [bx],al
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
ret
chk_pw_error:
;------------
mov byte ptr xdcnt+1,0 ;disable special searches
mov si,offset info_fcb
mov di,offset save_fcb ;save info_fcb
mov cx,16
rep movsb
call get_dptra
mov si,bx! inc si
mov di,offset info_fcb+1 ;info_fcb = dir_xfcb
mov cx,11
rep movsb
xor al,al! stos al ;fcb(extnum) = 0
inc di!stos al ;fcb(modnum) = 0
lods al ;save password mode
mov pw_mode,al
call search_name ;does fcb(ext=0,mod=0) exist
jz chk_pwe2 ; no
call get_dtba8 ;does sfcb exist
or al,al! jnz chk_pwe1 ; no
mov si,offset pw_mode
mov ch,[si] ;CH = xfcb.pwmode
mov al,[bx] ;AL = sfcb.pwmode
mov [si],al ;pw_mode = sfcb.pwmode
or al,al! jz chk_pwe2 ;is sfcb password mode nonzero
xor al,ch! and al,0e0h ; yes
jz chk_pwe1 ;do password modes match
call get_xfcb ; no - update xfcb
jz chk_pwe1 ;error - no xfcb
mov al,pw_mode
mov [bx],al ;xfcb.pwmode = sfcb.pwmode
call nowrite
jnz chk_pwe1
call wrdir
chk_pwe1:
call chk_pwe3
mov al,fx_intrn ;is func# = open or make?
cmp al,fxi15! je ret20a
cmp al,fxi22! je ret20a
pw_error: ; no
mov ah,7 ;password error
jmp set_aret
chk_pwe2:
mov pw_mode,0
call nowrite ;delete unused xfcb
jnz chk_pwe3
call get_xfcb ;get xfcb
jz chk_pwe3 ; it should have been there
or info_fcb,10h
call delete11 ;delete xfcb
chk_pwe3:
mov si,offset save_fcb
mov di,offset info_fcb ;restore info_fcb
mov cx,16
rep movsb
ret20a: ret
chk_password:
;------------
call get_dir_mode ;al = dir lbl data byte
and al,80h
jz ret20a ;bit 0 on => passwords active
call get_xfcb ;al = xfcb password mode | 01h
jz ret20a ;zero set if no xfcb found
cmp_pw: ;compare passwords
;------
; entry: BX = .xfcb(12)
; exit: Z flag set if password is valid
inc bx
mov ch,[bx] ;fcb(13) = xfcb checksum
or ch,ch
jnz cmp_pw2 ;jump if xfcb(13) ~= 0
mov si,bx ;save bx
add si,3 ;because xfcb checksum is zero
;test for null password
mov cl,9 ;null passwords are all blanks and/or
cmp_pw1: ;zeros that sum to zero
lodsb ;any password matches a null password
dec cl
jz ret20a ;password is all blanks and/or zeros
or al,al
jz cmp_pw1
cmp al,20h
jz cmp_pw1 ;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,offset common_dma
mov cl,8
std ;lods decrements si
cmp_pw3:
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
chk_xfcb_password:
;-----------------
; exit: BX = .xfcb(12)
call get_xfcb1 ;access xfcb in directory buffer
;al = (xfcb(ext) & e0h) | 1
chk_xfcb_password1:
push bx ;bx = .xfcb(ex)
call cmp_pw ;check password
pop bx
ret ;return with bx = .xfcb(ex)
set_pw: ;set password in xfcb
;------
; entry: BX = .xfcb(12)
; SI = .password in common dma area
mov cx,8 ;ch = 0, cl = 8
lea di,11[bx] ;di = .xfcb(23)
set_pw0:
sub ah,ah ;zero null password flag
set_pw1:
lodsb
mov [di],al ;copy password char to xfcb
or al,al ;is password char zero?
jz set_pw2 ;yes
cmp al,20h ;is password char blank?
je set_pw2 ;yes
inc ah ;password is not null
set_pw2:
add ch,al ;add password char to xfcb chksum
dec di
dec cl
jnz set_pw1
or ah,ch ;if (ah | ch) = 0 then password is null
jnz set_pw3
mov [bx],ah ;xfcb(ex) = 0, zero password mode
set_pw3:
inc di
mov cl,8
set_pw4:
xor [di],ch ;encrypt password chars in xfcb
inc di
dec cl
jnz set_pw4
mov 1[bx],ch ;bx + 1 = .xfcb(13)
ret ;ch = xfcb pasword checksum
get_dtba8: ;get password mode address
;---------
mov ch,8
GET_DTBA: ;GET STAMP ADDRESS IN SFCB
;--------
; entry: CH = offset into sfcb
; exit: BX = address of offset into sfcb
MOV AL,3 ;RET WITH AL ~= 0 IF STAMP CANNOT
mov ah,byte ptr dcnt ;BE MADE
and ah,dskmsk
CMP AL,AH ;IS LRET = 3? (SFCB POSITION)
JZ RET21A ;YES
mov bx,buffa
add bx,96
MOV AL,[BX]
SUB AL,21H ;DOES DIR FCB(3) BEGIN WITH 21H?
JNZ RET21A ;NO
MOV AL,ah
MOV CL,10
MUL CL ;AL = LRET*10
INC AL ; + 1
ADD AL,CH ; + CH
ADD BX,AX ;RETURN WITH BX = STAMP ADDR
xor al,al
RET21A:
RET
QDIRFCB1:
;--------
; exit: Z flag reset if fcb is first dir fcb of file
; CL = preserved
mov bx,offset info_fcb+extnum ;IS FCB IN 1ST DIR FCB OF FILE?
MOV AL,[BX]
mov ah,extmsk
not ah
and al,ah
and al,01fh
JNZ RET21A ;NO
TEST BYTE PTR 2[BX],3FH ;IS FCB(MOD) = 0?
RET ;Z FLAG RESET IF NOT
QSTAMP:
;------
; exit: Z flag reset if stamp is requested
CALL QDIRFCB1 ;IS FCB IN 1ST DIR FCB OF FILE?
JNZ RET21A ;NO
QSTAMP1:
call get_dir_mode ;ARE REQUIRED DIR LBL OPTIONS SET?
and al,cl! jz $+5 ; NO
JMP NOWRITE ; yes - VERIFY DISK NOT READ/ONLY
inc al ;return z flag reset
ret
stamp1:
;------
MOV CH,0
jmps stamp3
stamp2:
;------
MOV CH,4
stamp3:
;------
; entry: CH = stamp offset
CALL GET_DTBA ;GET STAMP ADDRESS
OR AL,AL
JNZ ret21a ;NON-ZERO - CAN'T STAMP
STAMP4:
mov dx,offset tod
stamp45:
MOV CL,4
PUSH BX! PUSH DX
CALL COMPARE ;COMPARE EXISTING STAMP TO NEW STAMP
POP DX! POP BX
jz ret21a ;EQUAL - SKIP CALL TO WRDIR
MOV CL,4
call move
jmp wrdir
STAMP5: ;DIR LBL STAMP ENTRY
;------
; entry: CX = stamp offset
CALL GET_DPTRA
ADD BX,CX
MOV AX,OFFSET FUNCRET
PUSH AX
jmps STAMP4
update_stamp:
;------------
mov cl,20h ;is update stamp requested
call qstamp1 ; on drive
jnz ret21a ; no
test info_fcb+modnum,40h ;has file been written to since
jnz ret21a ; it was opened
mov ah,info_fcb+extnum ; yes - search for first
mov al,info_fcb+modnum ; dir fcb
push ax ;save extnum and modnum
call search_1_name
jz $+5 ;perform update stamp
call stamp2 ; if 1st dir fcb found
mov lret,0
pop ax ;restore extnum and modnum
mov info_fcb+extnum,ah
mov info_fcb+modnum,al
ret
if BMPM
pack_sdcnt: ;packed_dcnt = sdcnt
;----------
mov ax,sdcnt
mov word ptr packed_dcnt,ax
mov byte ptr packed_dcnt+2,0
ret
;
; olist element:
; +------+------+------+------+------+------+
; 00h | LINK | ATTS | DCNT |
; +------+------+------+------+------+------+
; 06h | PDADDR | OPNCNT |
; +------+------+------+------+
;
; link = 0 -> end of list
;
; atts - 8x - open in locked mode
; 4x - open in unlocked mode
; 2x - open in read/only mode
; 1x - PC media function 116 update stamp flag
; xN - 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:
; +------+------+------+------+------+------+
; 00h | LINK | DRV | RECORD |
; +------+------+------+------+------+------+
; 06h | CNT | .OLISTITEM |
; +------+------+------+------+
;
; link = 0 -> end of list
;
; drive - 0x - Prevent Other Reads + Writes
; 8x - Prevent All Writes - allow reads if PAW locked
; xN - drive code (0-f)
;
; record = starting record number of locked records
; count = # of locked records starting at record
; .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
;
; entry: CH = 0 -> return next item
; CH = 1 -> search for matching drive
; CH = 3 -> search for matching dcnt
; CH = 5 -> search for matching dcnt + pdaddr
;
; exit: Z flag set if found and
; prv_pos -> previous list element
; cur_pos -> found list element
; BX = cur_pos
; else prv_pos -> list element to insert after
;
; olist and llist are maintained in drive order
;
srch_list1:
mov bx,[bx]
or bx,bx! jnz srch_list2 ;if (end of list)
or al,1 ; return( NZ )
ret
srch_list2:
or ch,ch! je srch_list5
mov cl,2[bx]! and cl,0fh
mov si,offset curdsk
lods al
cmp al,cl! jne srch_list4 ;do drive # match?
cmp ch,1! je srch_list5 ; is search for matching drive only?
;SI = offset packed_dcnt
mov cl,ch
push cx
xor al,al
xchg al,5[bx] ;save f1' env switch
;set dcnt+2 to zero
xor ch,ch ;do items match?
lea di,3[bx] ;DI = offset item.dcnt
repe cmps al,al
mov 5[bx],al ;restore f1' env switch
pop cx
jz srch_list5
srch_list3:
mov prv_pos,bx ; no - check next item
jmps srch_list1
srch_list4:
jae srch_list3 ;no need to continue if curdsk < drv
srch_list5:
mov cur_pos,bx
ret
delete_item:
;-----------
; entry: 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
mov cl,2[bx]! and cl,0fh ;get drive of deleted entry
mov bx,offset open_root
chk_open1:
mov bx,[bx] ;do any open files
or bx,bx! jz chk_open2 ; exist on drive
mov al,2[bx]! and al,0fh
cmp al,cl
jne chk_open1
ret
chk_open2:
mov bx,offset open_vector ; no - zero drive bit
jmps remove_drive1 ; in open file vector
;ret
remove_drive:
;------------
mov cl,curdsk
remove_drive1: ;reset bit in vector at bx
;-------------
; entry: BX = address of vector
; CL = bit in vector to reset
mov ax,1! shl ax,cl
not ax! and [bx],ax
ret
remove_locks:
;------------
; entry: BX = offset of olist_item
; exit: BX = preserved
test byte ptr 2[bx],40h! jz retl25
push prv_pos
push bx
mov ax,offset lock_root
mov cur_pos,ax
remove_lock1:
mov ch,0
call searchn_list
jnz remove_lock2
pop dx! push dx
cmp 8[bx],dx
jnz remove_lock1
call delete_item
jmps remove_lock1
remove_lock2:
;
; **3.1M** Record locking patch
;
; remove item from list
;
pop ax ;AX = .olist
push ax
mov bx,offset name_root ;BX = .name_root
dl0:
;for(;;)
; {
mov si,[bx] ; SI = BX-> link 1st item
cmp 2[si],ax ; if (2[si] == .olist)
jnz dl1 ; {
mov di,[si] ; DI = SI->link 2nd item
mov ax,[di] ; link
mov [bx],ax ; BX->link = DI-> link new name_root
mov ax,free_root
mov [di],ax ; DI-> = free_root old free root
mov free_root,si ; free_root = SI new free root
jmps dl2
;
dl1:
mov bx,[si] ; BX-> next item
jmps dl0 ; }
dl2:
;
; **3.1M** End of record locking patch
;
pop bx! pop prv_pos
retl25:
ret
compare_pds:
;-----------
; exit: Z flag set if proccess descriptors match
mov ax,pdaddr
cmp 6[bx],ax
ret
tst_olist:
;---------
mov chk_olist_flag,false
jmps chk_olist0
chk_olist:
;---------
mov chk_olist_flag,true
chk_olist0:
mov ax,dcnt
mov sdcnt,ax
call pack_sdcnt! mov ch,3
call search_olist! jnz retl25
; if in compatibility mode f1', r/o mode is the default open mode
; otherwise default is locked mode. branch to openx06 if the open
; mode is not the default mode.
call get_cmp_mode
rol al,1! mov al,2[bx]
jnb chk_olist01
rol al,1! rol al,1
chk_olist01:
rol al,1! jnb chk_olist05
call compare_pds
jnz chk_olist05
; verify another process does not have the file open when
; the default open mode is r/o as a result of compatibility
; attribute f1' = 1.
call get_cmp_mode
rol al,1! jnb chk_olist02
mov ch,3! call searchn_list
jz chk_olist05
mov ch,3! call search_olist
chk_olist02:
test chk_olist_flag,true! jz retl1
; check to see if the lock list item is extended and if the interface
; attribute requesting that the lock item continue to be extended is
; set. if so, control is returned to the routine calling chk$olist and
; the lock item is retained. otherwise, the lock item is deleted and
; pd_cnt is incremented unless an extended lock was placed on the file.
cmp byte ptr 9[bx],0ffh
jne chk_olist07
test attributes,080h
js retl1
jmp delete_item
chk_olist05:
jmp openx06
chk_olist07:
call delete_item
inc_pdcnt:
;---------
mov al,pd_cnt
and al,0f0h
chk_olist1:
add al,16! jz chk_olist1
mov pd_cnt,al
retl1: ret
pr_term:
;-------
mov ax,offset open_root
mov cur_pos,ax
pr_term1:
mov ch,0
call searchn_list
jnz pr_term2
mov ax,pdaddr
cmp 6[bx],ax
jnz pr_term1
call remove_locks
call delete_item
jmps pr_term1
pr_term2:
call flush0
retl2: ret
flush_files:
;-----------
mov al,true
xchg flushed,al
test al,al! jnz retl2
flush_file0:
mov ax,offset open_root
mov cur_pos,ax
flush_file1:
mov ch,1
call searchn_list! jnz retl2
call remove_locks
call delete_item
jmps flush_file1
free_files:
;----------
; free_mode = 1 - remove curdsk files for process
; 0 - remove all files for process
mov ax,offset open_root
mov cur_pos,ax
free_files1:
mov ch,free_mode
call searchn_list
jnz retl2
mov ax,pdaddr
cmp 6[bx],ax
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
jmps free_files1
create_item:
;-----------
; exit: BX = offset of new item if successful
; Z flag set if no free items
mov bx,free_root
or bx,bx! je retl2
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
create_olist_item:
;-----------------
mov ch,1! call search_olist
call create_item
create_olist_item1:
mov al,curdsk
or al,attributes
mov 2[bx],al ; set drive and attributes
mov si,offset packed_dcnt
lea di,3[bx]
mov cx,5
rep movsb ;copy dcnt and pd_addr
xor ax,ax! stosw ;open_cnt = 0;
mov cl,curdsk
inc ax! shl ax,cl ;set curdsk bit in
or open_vector,ax ; open file vector
ret
create_llist_item:
;-----------------
; exit: BX = llist item address
; DI = offset l_item.rec
mov ch,1! call search_llist
call create_item
lea di,3[bx]
mov ax,file_id
mov 8[bx],ax
ret
count_opens:
;-----------
mov open_cnt,0
mov ax,offset open_root
mov cur_pos,ax
count_open1:
mov ch,0! call searchn_list
jnz count_open2
mov ax,pdaddr
cmp 6[bx],ax
jnz count_open1
inc open_cnt! jmps count_open1
count_open2:
mov al,open_cnt
sub al,open_max
retl3:
ret
check_free0:
check_free: ;check for required # of entries in free list
;----------
; entry: DL = required # of free entries
mov bx,offset free_root
xor dh,dh ;for (free_entries = 0;
check_free1:
mov bx,[bx]
or bx,bx! jz check_free2 ; (next_free_item ~= end_of_flist) &&
inc dh ; (free_entries < required_#);
cmp dh,dl! jb check_free1 ; free_entries++);
retl4:
ret
check_free2:
pop bx ;remove return address
mov al,14 ;(end_of_flist) return(error -
jmp set_lret ; no room in sys lock list);
move_arecord: ;packed_dcnt = arecord
;------------
mov dx,offset arecord
mov bx,offset packed_dcnt
mov cl,3! jmp move
chk_rec:
;-------
; exit: Z flag reset if unwritten data
call index
jz chk_rec1 ;error - unwritten data
mov al,vrecord
cmp al,rcount
jnb chk_rec1
xor al,al
ret
chk_rec1:
or al,1
ret
check_rec:
;---------
mov lock_sp,sp
mov lock_shell,true
if PCMODE
cmp media_format,0
je $+5
jmp pc_chkrec
endif
mov cl,true ;assume read operation for rseek
call rseek
mov lock_shell,false
call getfcb
test lret,0ffh
jnz retl6
; verify that the block has not been allocated by another
; process before returning error code 1 (reading unwritten data)
call chk_rec
jz retl6
mov dont_close,true
mov lock_shell,true
call test_disk_fcb
mov lock_shell,false
jz lock_err1 ;error - unwritten data
call chk_rec
jnz lock_err1
lock_err:
;--------
retl6:
ret
lock_err1:
jmp set_lret1
cmp_recs: ;compare l_item.rec(+l_item.cnt) and rand_rec(+mult_cnt)
;--------
; entry: SI = l_item.rec (1st record #) offset
; DI = rand_rec (2nd record #) offset
; CL = 00h - no counts added
; = 01h - add mult_cnt to rand_rec
; = 02h - add l_item.cnt to l_item.rec
; exit: Z,C flags set
; SI,DI = preserved
mov bl,[si]! mov ax,1[si] ;AX,BL = l_item.rec
mov bh,[di]! mov dx,1[di] ;DX,BH = rand_rec
test cl,02h! jz cmp_rec1
add bl,3[si]
adc ax,0 ;AX,BL = l_item.rec + l_item.cnt
cmp_rec1:
test cl,01h! jz cmp_rec2
add bh,mult_cnt
adc dx,0 ;DX,BH = rand_rec + mult_cnt
cmp_rec2:
cmp ax,dx! jne cmp_rec3
cmp bl,bh
cmp_rec3:
ret
srch_llist: ;search lock list for matching item
;----------
; exit: AL = 0ffh - end of llist
; = 0feh - incompatable lock type
; = 001h - complete overlap
; = 002h - subset overlap
; = 004h - pre partial overlap
; = 008h - post partial overlap
; BX = cur_pos if AL ~= 0ffh
; DI = o_item.pdaddr if AL ~= 0ffh
mov ch,1! call searchn_list ;search for matching drive
jz srch_l1 ;while(not_end_of_llist) and
mov al,0ffh
ret
srch_l1:
mov di,file_id ; if (file_id.dcnt == o_item.dcnt);
mov cx,3
mov si,8[bx] ; SI = o_item
add si,cx! add di,cx
repe cmpsb
jne srch_llist
lea si,3[bx] ; SI = l_item.rec
mov di,offset info_fcb+ranrec
;check for no overlap
mov cl,01h! call cmp_recs ;if (l_item.rec >=
jae srch_llist ; rand_rec + mult_cnt) or
mov cl,02h! call cmp_recs ; (l_item.rec + cnt <= rand_rec)
jbe srch_llist ; no_olap - search for next l_item
;check for complete overlap
mov cl,00h! call cmp_recs ;else if (l_item.rec >= rand_rec)
jnae srch_l3
mov cl,03h! call cmp_recs ; if (l_item.rec + cnt <=
jnbe srch_l2a ; rand_rec + mult_cnt)
mov al,01h ; srch_ret = complete_olap;
jmps srch_l4
srch_l2a: ; else ;(l_item.rec + cnt >
mov al,04h ; rand_rec + mult_cnt)
jmps srch_l4 ; srch_ret = pre_part_olap;
srch_l3:
;check for subset overlap
mov cl,03h ;else ;(l_item.rec < rand_rec)
call cmp_recs ; if (l_item.rec + cnt >
jna srch_l3a ; rand_rec + mult_cnt)
mov al,02h ; srch_ret = subset_olap;
jmps srch_l4
srch_l3a: ; else ;(l_item.rec + cnt <=
; rand_rec + mult_cnt)
mov al,08h ; srch_ret = post_part_olap;
srch_l4:
;check for incompatable lock type
mov bx,cur_pos ;BX = l_item;
mov si,8[bx] ;SI = o_item;
mov di,6[si] ;DI = o_item.pd_addr
cmp pdaddr,di ;if (o_item.pd_addr == pd_addr)
je srch_l7 ; return(srch_ret);
test attributes,80h
jz srch_l6 ;if (l_item.attrib ~= paw_lock) or
test byte ptr 2[bx],80h
jnz srch_l7 ; (request_type ~= paw_lock)
srch_l6:
mov al,0feh ; return(incompatable_lock_type);
srch_l7:
ret
;
;
; **3.1M** Patch for record locking
;
chk_name:
mov al,6[si] ;
cmp al,curdsk ;does SI ->drive = curdsk ?
jnz cn2a ;no
; cmp media_format,0 ;PC media ?
; jz cn2 ;no
; mov ax,4[si] ;is file in same directory - .chdblk
; mov bx,hdsaddr ;
; or bx,bx
; jz cn1
; mov bx,6[bx]
;cn1:
; cmp ax,bx
; jnz cn2a ;no
;cn2:
lea di,7[si] ;do first 3 chars pf name match
mov bx,offset info_fcb+1
mov cx,3
call namecmp ;
jnz cn2a ;no
mov cx,8
mov dx,si ;does rest of name match
mov si,[si] ; SI -> item2
lea di,2[si] ; DI -> olist item
call namecmp
jnz cn3 ;no
;
;name has matched
;
mov bx,dx ; BX -> item1
mov ax,2[bx] ; AX = file_id = .olist
mov file_id,ax ; set file id
mov es,uda_save
mov u_nameitem,bx ;save name item addr in UDA
push ds
pop es
ret
;
cn2a:
mov si,[si] ; SI -> item2
cn3:
mov si,[si] ;SI now points to next file is and name
ret
;
cn4:
mov bx,dx
ret
;
namecmp:
mov al,[di]
xor al,[bx]
inc bx
inc di
and al,7fh
loopz namecmp
ret
;
; **3.1M** End of patch for record locking
;
test_lock: ;check llist for records with an incompatable lock type
;---------
test high_ext,80h ;was file opened in unlocked mode?
jz retl7 ; no
;
; **3.1*** Record locking patch
;
cmp file_id,0 ;is file_id zero
jnz gf3 ;no
mov es,uda_save
mov si,u_nameitem ;is UDA nameitem addr zero
; mov es,ds
push ds
pop es
or si,si ;no
jz gf0
call chk_name ;does it match FCB
jz gf3 ;yes
gf0:
mov si,name_root ;no search name list
gf1:
or si,si
jnz gf2
pop bx
mov al,0bh
jmp set_lret
gf2:
call chk_name
jz gf3
jmps gf1
gf3:
;
; **3.1M** End of record locking patch
;
cmp fx_intrn,fxi22
jnb rand_op
call func36 ;set random record #
rand_op:
mov ax,offset lock_root
mov cur_pos,ax
test_lock1:
push word ptr mult_cnt
mov mult_cnt,1
call srch_llist ;while(not_end_of_llist);
pop word ptr mult_cnt
cmp al,0ffh! jne test_lock2
retl7:
ret ; return(no errors)
test_lock2:
cmp al,0feh ; if (incompatable_lock_type)
je test_lock3 ; return(error)
test rmf,true
jnz test_lock1 ; if (write) and
mov bx,cur_pos
test byte ptr 2[bx],80h ; (l_item.attrib == paw_lock)
jz test_lock1
test_lock3:
pop bx ; remove return address
mov al,8 ; return(error -
jmp set_lret ; locked by an other proccess);
lock: ;record lock or unlock
;----
mov cl,2
call copy_dma_in
call get_atts ;get & clear atts f5' - f8'
call check_fcb
test high_ext,80h ;if (open mode ~= unlocked)
jz retl7 ; yes - return ok
mov bx,word ptr common_dma
mov ax,pdaddr
cmp 6[bx],ax! jz lock01 ;if (olist.pd_addr ~= pdaddr)
mov al,13! jmp set_lret ; yes - invalid file id
lock01:
mov file_id,bx
test lock_unlock,true ;if (~lock_unlock)
jnz lock01a
test attributes,80h ; if (attributes && 80h)
jz lock01a
jmp remove_locks ; remove all locks
lock01a:
mov al,info_fcb+ranrec ;if (fcb(ranrec) > 3ffffh)
mov bx,word ptr info_fcb+ranrec+1
cmp bh,4 ; return with lret = 6
jae lock01b
mov ah,mult_cnt
dec ah
add al,ah ;if fcb(ranrec)+mult_cnt > 3ffffh
adc bx,0 ; return with lret = 6
cmp bh,4
jb lock01c
lock01b:
mov lret,6 ;error - random record #
ret ; out of range
lock01c:
;mov olap_type,0 ;olap_type = no_olap;
; check llist for records with an incompatable lock type
mov ax,offset lock_root
mov cur_pos,ax
lock02a:
call srch_llist ;while(not_end_of_llist);
cmp al,0ffh! je lock04a
cmp al,0feh! jne lock03a ; if (incompatable_lock_type)
test lock_unlock,true ; yes - if (lock)
jz lock02a
mov al,8! jmp set_lret ; yes - return(error -
; locked by an other proccess);
lock03a: ; else
cmp pdaddr,di ; if (o_item.pdaddr == pdaddr)
jne lock02a
or olap_type,al ; olap_type |= llist_ret;
jmps lock02a
lock04a:
;determine number of lock entries required by overlap type
mov bx,offset required_table ;CS over ride on table in const area
mov al,olap_type
xlat required_table ;AL = required_table[olap_type];
test lock_unlock,true
jnz lock05a ;if (unlock) &&
or al,al! jz lock05a ; (required_# ~= 0)
dec al ; required_#--;
lock05a:
;check if max entries / proccess will be exceeded
mov dx,file_id
mov cur_pos,offset lock_root
xor ah,ah ;lock_cnt = 0;
count_lock1:
mov ch,0
push ax! push dx
call searchn_list ;get next llist item
pop dx! pop ax
jnz count_lock2 ;while(not_end_of_llist)
cmp 8[bx],dx
jnz count_lock1 ; if (l_item.olist == file_id)
inc ah ; lock_cnt++;
jmps count_lock1
count_lock2:
mov dl,al ;DL = required #, for check_free
add al,ah! jb lock02 ;if (lock_max <
cmp lock_max,al! jae lock05 ; (lock_cnt + required_#))
lock02:
mov al,12! jmp set_lret ; return(error - lock limit exceeded);
lock05:
;check for required # of entries in free list
;
; 3.1M patch for deleting lock list item after all items used
;
;
; call check_free
;
;check for record in file if required
test lock_unlock,true
jz lock4 ;if (lock) &&
;
call check_free ;check for items only if locking
;
; end of 3.1M patch
;
test attributes,40h ; (lock_type == rec_required_in_file)
jnz lock4
mov ah,mult_cnt
lock2: ;for (i = 0; i < mult_cnt; i++);
push ax
call check_rec ; check_for_record(rand_rec + i);
pop ax
test lret,0ffh ; if (record_not_in_file)
jz $+5
jmp reset_rr ; return(error - unwritten data);
dec ah! jz lock4
call incr_rr! jmps lock2
lock4:
call reset_rr
;remove over lapping records from lock list
test olap_type,00Fh ;if (olap_type ~= no_olap)
jnz $+5
jmp lock08a
mov ax,offset lock_root
mov cur_pos,ax
lock06a:
call srch_llist
cmp al,0ffh! jne $+5 ; while(not_end_of_llist);
jmp lock08a
cmp pdaddr,di ; if (o_item.pdaddr == pdaddr)
jne lock06a
test al,01h ; if (llist_ret && complete_olap)
jz lock07a
call delete_item ; delete(cur_item);
jmps lock06a
lock07a: ; else
test al,04h ; if (llist_ret && pre_part_olap)
jz lock07b
mov ch,3[bx] ; l_item.cnt = (l_item.rec+cnt) -
add ch,6[bx] ; (rand_rec+mult_cnt);
mov cl,info_fcb+ranrec ; CH = low(l_item.rec + l_item.cnt);
mov ax,word ptr info_fcb+ranrec+1
add cl,mult_cnt
adc ax,0 ; AX,CL = rand_rec + mult_cnt
sub ch,cl
mov 6[bx],ch ; store l_item.cnt
mov 3[bx],cl ; l_item.rec = rand_rec + mult_cnt;
mov 4[bx],ax ; store l_item.rec
jmps lock06a
lock07b: ; else
test al,08h ; if (llist_ret && post_part_olap)
jz lock07c
mov cl,info_fcb+ranrec ; l_item.cnt = rand_rec-l_item.rec;
sub cl,3[bx] ; CL = low(rand_rec - l_item.rec);
mov 6[bx],cl ; store l_item.cnt
jmps lock06a
lock07c: ; else ;(llist_ret && subset_olap)
push bx ; save current item address
call create_llist_item ; create new llist item
pop si
mov al,2[si]! mov 2[bx],al ; set attributes and drive
mov cl,info_fcb+ranrec ; rec = (rand_rec + mult_cnt)
mov ax,word ptr info_fcb+ranrec+1
add cl,mult_cnt
adc ax,0 ; AX,CL = rand_rec + mult_cnt
mov 3[bx],cl
mov 4[bx],ax ; store new l_item.rec
mov ch,3[si]! add ch,6[si] ; cnt = (l_item + cnt) -
sub ch,cl ; (rand_rec+mult_cnt)
mov 6[bx],ch ; store new l_item.cnt
mov cl,info_fcb+ranrec ; l_item.cnt = rand_rec -
sub cl,3[si] ; l_item.rec;
mov 6[si],cl ; store l_item.cnt
jmp lock06a
lock08a: ; end of while
test lock_unlock,true ;if (lock)
jz lock09a
call create_llist_item ; create(rand_rec,mult_cnt);
mov al,curdsk
or al,attributes
mov 2[bx],al ; set drive and attributes
mov si,offset info_fcb+ranrec
mov cx,3
rep movsb ; copy record #
mov al,mult_cnt
mov 6[bx],al ; l_item.cnt = mult_cnt;
lock09a:
ret
fix_olist_item:
;--------------
mov ax,xdcnt
cmp ax,sdcnt ; is xdcnt < sdcnt?
jae retl8 ; no
;yes - update olist entries
call swap
mov ax,xdcnt
mov sdcnt,ax
mov ax,offset open_root
mov cur_pos,ax
;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 item with new dcnt value
push bx! call pack_sdcnt! pop bx
add bx,3
mov dx,offset packed_dcnt
mov cl,3
call move
jmps fix_ol1
diskreset:
;---------
; exit: Z flag reset if TLOG has been setup
xor ax,ax
mov ntlog,ax
mov set_ro_flag,al
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
retl8:
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 searchn_list! jnz dskrst6
test check_disk,true
jz dskrst5
push bx
call compare_pds! jz dskrst45
pop dx
xor al,al! jmps dskrst6
dskrst45:
mov bx,offset ntlog
call setcdisk
pop bx! jmps dskrst4
dskrst5:
mov bx,offset info
call remove_drive
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
mov err_drv,ch
mov bx,dx! mov ax,6[bx]
mov err_pd_addr,ax
mov err_type,0ffh
dskrst7:
pop bx! mov aret,0ffffh
ret
endif
if BCPM
chk_reset:
;---------
; exit: AX = accumulated vector of drives to not be reset
xor ax,ax
push es
mov es,tlr
chk_rst0:
cmp p_status,ps_term ;if process environment status
je chk_rst1 ; is <> terminated
or ax,p_alc_vec ; OR in processes alloc block vector
chk_rst1:
mov cx,p_thread ;CX = next process environment address
mov es,cx
or cx,cx! jnz chk_rst0 ;check next process if not zero
pop es
ret
chk_drv:
;-------
; exit: Z flag set if file is being written on CURDSK
call chk_reset
not ax! mov dx,ax
jmp test_vector
endif
;********** end bdos file system part 3 **********