mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
904 lines
25 KiB
Plaintext
904 lines
25 KiB
Plaintext
|
||
;*****************************************************************
|
||
;*****************************************************************
|
||
;** **
|
||
;** 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
|
||
|