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