;       SCCSID = @(#)filemacs.inc	6.1 90/11/17
;      SCCSID = @(#)filemacs.inc 1.0 90/5/21
;**** Master file for File System macros

; include seldesc.inc
; include virtsym.inc    ; depends on seldesc
; include fsh.inc        ; nedded for get_advise; depends on virtsym & seldesc
; include sft.inc        ; nedded for get_advise

;**	get_advise - obtain advisory bits
;
;	Locate the handle flags, then translates into format used by the
;	FS_ and FSH_ entry points (i.e. write-thru = 0x10, no-cache = 0x20)
;	TCBJfnFlag is set by pJFNFromHandle and SFFromHandle.
;
;	Since we are only interested in these two bits, we can extract them
;	via appropriate shifting and masking.
;
;	ENTRY	TCBJfnFlag = handle flags
;
;	EXIT	ax = advisory bits
;
;       USES    ax,si,flags
;
; Called from : DISK.ASM DOSFS.ASM FHANDLE.ASM FINFO.ASM VOLIO.ASM

get_advise MACRO

        mov     si,TASKAREA:CurrTCB
	mov	al,TASKAREA:[si].TCBJfnFlag ; al = handle flags

.errnz JFN_WRTTHR - 80h
         cbw                             ; propogate high bit through upper byte
         and     ah,FSH_DOV_OPWRTHRU     ; (ah) = write through bit if present
.errnz JFN_NCACHE - FSH_DOV_OPNCACHE
         and     al,FSH_DOV_OPNCACHE     ; (al) = no-cache bit if present

         or      al,ah                   ; (al) = all relevant bits
         xor     ah,ah                   ; (ax) = all bits

ENDM


;
; In the course of doing I/O, we need to wait for both the VPB associated with
; a request and the DPB associated with the VPB to become free.  We examine
; a locked flag and proc-block until the lock gets released.  If we blocked
; then we return an indicator that we may have to reexamine all other pending
; conditions.  During the course of verifying a volume, we use an internal
; static buffer; this must be semaphored too.
;

;
;   WaitVPBandDPB  - wait until a flag is removed from a specified
;   VPB; then wait until a check-in-progress flag is removed from
;   the corresponding DPB.
;
;   Inputs:	ax  contains handle to VPB
;               bl  contains the flag bit to test in vpb_flags
;               pDPB points to pDevDriverHeader or DPB.
;   Outputs:    ds:si contains valid pointer to DPB
;   Registers modified: bh, es
;
; Called from : VOLIO.ASM

WaitVPBandDPB   MACRO pDPB
        local   l0,l1,l2

        push    bp
ifnb <pDPB>
        lds     si,pDPB
endif
l0:
        mov     bp,ax
        VPBContext ES,BP

        test    es:[bp].vpb_flags,bl    ; is bit free?
        jz      l1                      ; yes, check fo DPB.
        call    WaitVPB
l1:
ifb <pDPB>
        lds     si,es:[bp].vpb_fsi.vpi_pDPB
endif
        test    ds:[si].dpb_flags,DPBCHECK
        jz      l2                      ; jump if not locked
        call    WaitDPB
        jc      l0
l2:
        pop     bp

ENDM


;***	UpdateSFTPosition - update an SFT based on a transfer
;
;	Changes the position field of the SFT based on the number of bytes
;	completed in a transfer
;
;	ENTRY	(es:di) point to SFT
;		(cx)	number of bytes transferred
;
;	EXIT	carry clear
;
;       USES    flags
;
; Called from : DISK.ASM
;
UpdateSFTPosition MACRO
	add	es:[di].sf_fsi.sfi_position.LowWord,cx	; Update current position
	adc	es:[di].sf_fsi.sfi_position.HighWord,0
	clc
ENDM


;*** FigRec32 -- Figure sector in allocation unit
;
;	ENTRY	DX = Physical cluster number
;		BL = Sector postion within cluster
;               ES:<hVPB> points to VPB
;
;       EXIT    SI:DX = sector number
;
;       USES    Flags
;
FigRec32 macro hVPB

CpuMode 386
        push    ECX
        mov     ECX,EDX     ; Save EDX msw
        movzx   EDX,DX
        sub     EDX,2       ; First 2 entries in FAT are not mapped to disk
        mov     CL,ES:[hVPB].vpb_fsd.vpdFAT_cluster_shift
        shl     EDX,CL
	OR	DL,BL
        ADD     EDX,dword ptr ES:[hVPB].vpb_fsd.vpdFAT_first_sector
        SHR     ESI,16      ; Move ESI msw to SI
        mov     CX,DX       ; CX = DX Result , ECX msw = EDX msw intact
        SHLD    ESI,EDX,16  ; SI = Result , ESI msw intact
        mov     EDX,ECX     ; DX = Result , EDX msw intact
        pop     ECX
CpuMode Reset

ENDM ; FigRec32


;*** SearchBuf -- Search buffer pool
;
;       ENTRY   Dir    - MRU, LRU or UNUSED to get unused buffer
;               hVPB   - Volume handle
;               SecNum - Sector number
;               DS = Buffer segment
;
;       if Dir == UNUSED hVPB SecNum are not used, LRU implied
;
;       EXIT    ZF set if found, clear if not found.
;               DI offset of desired buffer.
;
;       USES    AX, Flags
;
SearchBuf macro Dir,hVPB,SecNum
        local   sb0,sb1,sb2,sb3

CpuMode 386
ifdif <Dir>,<UNUSED>
ifdif <SecNum>,<ECX>
        push    ecx
        mov     ecx,SecNum
endif
ifdifi <hVPB>,<AX>
        mov     ax,hVPB
endif
else
        mov     ax,BUF_WANT or BUF_BUSY or BUF_DIRTY or BUF_VISIT
endif

ifidni <Dir>,<MRU>
        mov     di,DS:[bs_MRUHead]      ; DS:DI points to first buffer.
else
        mov     di,DS:[bs_MRUTail]      ; DS:DI points to last buffer.
endif
sb0:
ifdifi <Dir>,<UNUSED>
        cmp     ds:[di].buf_sector,ecx
        je      sb2
else
        test    ds:[di].buf_flags,al
        je      sb3
endif
sb1:
ifidni <Dir>,<MRU>
        mov     di,ds:[di].buf_next
else
        mov     di,ds:[di].buf_prev
endif
        cmp     di,BUF_NIL
        jne     sb0
ifdifi <Dir>,<UNUSED>
        or      cl,1                    ; Not found - clear ZF
        jmp     sb3
sb2:    cmp     ds:[di].buf_hVPB,ax
        jne     sb1
else
        or      ax,ax                   ; Not found - clear ZF
endif
sb3:
ifdifi <Dir>,<UNUSED>
ifdifi <SecNum>,<ECX>
        pop     ecx
endif
endif
CpuMode Reset
ENDM ; SearchBuf
