;       SCCSID = @(#)demfcbio.asm       6.3 92/01/13
;
;   Revisions:
;
;Local  DCR/
;Tag    PTM(R)  Who     When/What
;               danno   09-Mar-1989
;                       Created for MVDM
;***********************************************************************;BN001;
;  31Oct91 - G.L.Fulk                                                   ;BN001;
;  Pass the user environment to the file system delete worker.          ;BN001;
;***********************************************************************;BN001;
;

.xlist
include v86seg.inc

.xcref
include basemaca.inc
include osmaca.inc
include demmac.inc
include dossymc.inc
include mvdmexp.inc
include demsvc.inc
include cpmfcb.inc
include error.inc
include opncreat.inc
include devhdr.inc
include dos3dev.inc
include struc30.inc
.cref
.list

Random  =   2                           ; random operation
FCBRead =   4                           ; doing a read
Block   =   8                           ; doing a block I/O


        CpuMode 386


V86CODE SEGMENT

        ReferV86   DMAADD
        ReferV86    CurrentPDB,WORD                                     ;BN001;

        EXTRN   FCB_Ret_Err:NEAR
        EXTRN   FCB_Ret_OK:NEAR
        EXTRN   FCB_Return:NEAR
        EXTRN   RMDevCheckNameFCB:NEAR
        EXTRN   RMDevCheckFCB:NEAR
        EXTRN   RMDevCloseDI:NEAR
        EXTRN   RMDevXFLAGS:NEAR
        EXTRN   RMDevAllocDI:NEAR
        EXTRN   RMDevOpen:NEAR
        EXTRN   RMDevClose:NEAR
        EXTRN   RMDevRead:NEAR
        EXTRN   RMDevWrite:NEAR
        EXTRN   SFFromSFN:NEAR
        EXTRN   get_user_stack:NEAR
        EXTRN   GetExtended:near
        EXTRN   GetExtent:near
        EXTRN   SetExtent:near
        EXTRN   GetRecSize:near

        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING


;***    $FCB_Create - create a new directory entry
;
;       CPM compatability file create.  The user has formatted an
;       FCB for us and asked to have the rest filled in.
;
;       ENTRY   DS:DX point to an unopenned FCB
;       EXIT    AL indicates status 0 is ok FF is error
;               FCB has the following fields filled in:
;                   Time/Date Extent/NR Size
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Create,NEAR
        call    RMDevCheckNameFCB       ; local device?
        jnc     short fop1              ; Yes go open it!
        mov     ax,exist_replace+nexist_create
        xor     bx,bx                   ; (BX) = create attributes
        call    GetExtended             ; (DS:SI) = fcb pointer
        .if     nz
          mov     bl,[si-1]
        .endif
        SVC     SVC_DEMFCBOPEN
        jmp     FCB_Return

EndProc   $FCB_Create

;***    $FCB_Open - open an old-style FCB
;
;       CPM compatability file open.  The user has formatted an FCB
;       for us and asked to have the rest filled in.
;
;       ENTRY   DS:DX point to an unopenned FCB
;       EXIT    AL indicates status 0 is ok FF is error
;               FCB has the following fields filled in:
;                   Time/Date Extent/NR Size
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Open,NEAR
        call    RMDevCheckNameFCB           ; Local device?
        jnc     short fop1                  ; Skip if so

        mov     ax,exist_open+nexist_fail
        SVC     SVC_DEMFCBOPEN
        jmp     FCB_Return

fop1:   SaveReg <ds,dx>
        mov     ax,es:[bx].SDevAtt      ; Get device attributes
        call    RMDevXFlags             ; Translate to RMDI flags
        call    RMDevAllocDI            ; Assign a DevInfo entry (V86 SFT)
        jc      short fop5              ; Exit if none available

        mov     bx,ax
        SaveReg <ax>                    ; save VSFN
        call    SFFromSFN               ; ES:DI points to VSFN
        dec     es:[di].rmdi_refcnt     ; Remove extra reference
        call    RMDevOpen               ; Open it; Will increment refcnt
        RestoreReg <ax>
        RestoreReg <si,ds>
        jc      short fop10             ; jump if open failed
        mov     ds:[si].fcb_sfn, al     ; put sfn in fcb
        call    GetRecSize
        jmp     FCB_Ret_OK

fop5:   jmp     FCB_Ret_Err

fop10:  push    ax                      ; push error code
        call    RMDevClose              ; Deallocate DI entry
        pop     ax
        jmp     short fop5

EndProc   $FCB_Open

;***    $FCB_Random_write_Block - write a block of records to a file
;
;       Retrieve a location from the FCB, seek to it and write a number
;       of blocks from it.
;
;       ENTRY   DS:DX point to an FCB
;               CX number of records to write
;       EXIT    AL = 0 write was successful and the FCB position is updated
;               AL <> 0 Not enough room on disk for the output
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Random_Write_Block,NEAR
        MOV     AL,Random+Block
        JMP     short FCBIO
EndProc $FCB_Random_Write_Block

;***    $FCB_Random_Read_Block - read a block of records to a file
;
;       Retrieve a location from the FCB, seek to it and read a
;       number of blocks from it.
;
;       ENTRY   DS:DX point to an FCB
;               CX number of records to read
;       EXIT    AL = error codes defined above
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Random_Read_Block,NEAR
        MOV     AL,Random+FCBRead+Block
        jmp     short FCBIO
EndProc $FCB_Random_Read_Block

;***    $FCB_Seq_Read - read the next record from a file
;
;       Retrieve the next record from an FCB and read it into memory.
;
;       ENTRY   DS:DX point to an FCB
;       EXIT    AL = error codes defined above

        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Seq_Read,NEAR
        MOV     AL,FCBRead
        jmp     short FCBIO
EndProc $FCB_Seq_Read

;***    $FCB_Seq_Write - write the next record to a file
;
;       Retrieve the next record from an FCB and write it to the file.
;
;       ENTRY   DS:DX point to an FCB
;       EXIT    AL = error codes defined above
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Seq_Write,NEAR
        MOV     AL,0
        jmp     short FCBIO
EndProc $FCB_SEQ_WRITE

;***    $FCB_Random_Read - Read a single record from a file
;
;       Retrieve a location from the FCB, seek to it and read a
;       record from it.
;
;       ENTRY   DS:DX point to an FCB
;       EXIT    AL = error codes defined above
;
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Random_Read,NEAR
        MOV     AL,Random+FCBRead
        jmp     short FCBIO                   ; single block
EndProc $FCB_RANDOM_READ

;***    $FCB_Random_Write - write a single record to a file
;
;       Retrieve a location from the FCB, seek to it and write
;       a record to it.
;
;       ENTRY   DS:DX point to an FCB
;       EXIT    AL = error codes defined above
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure $FCB_Random_Write,NEAR
        MOV     AL,Random
;       jmp     short FCBIO
EndProc $FCB_RANDOM_WRITE

;***    FCBIO - do internal FCB I/O
;
;       Look at FCBOP and merge all FCB operations into a single routine.
;
;       ENTRY   FCBOP flags which operations need to be performed
;               DS:DX point to FCB
;               CX may have count of number of records to xfer
;       EXIT    AL has error code
;       USES    all
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure FCBIO,NEAR
        push    ax
        xor     al,al                   ; re-open FCB if closed
        call    GetExtended
        call    RMDevCheckFCB           ; local device?
        pop     ax
        jnc     short fio3              ; skip if so
        SVC     SVC_DEMFCBIO            ; (AX) = error code, (DL) = FCBErr
        jc      short fio1              ; skip if error
        call    get_user_stack          ; (DS:SI) = user stack
        mov     ds:[si.User_CX],cx      ; return CX
        mov     al,dl                   ; (AL) = FCBErr
        ret

fio1:   push    dx                      ; save FCBErr
        call    FCB_Ret_Err
        pop     ax                      ; (AL) = FCBErr
fio2:   ret

fio3:
        .if     <BIT AL nand Block>     ; Is it block I/O
          mov     cx,1                  ;       cRec = 1;
        .endif
        call    GetRecSize
        push    ds
        push    si
        push    ax                      ; At this point CX = nRecords
        mov     ax,cx                   ; and BX = Rec Size
        mul     bx
        mov     cx,ax                   ; CX = cBytes to transfer
        pop     ax
        push    ax
        mov     dx, word ptr [DMAADD]
        test    al,FCBRead
        jz      short fio7              ; do write

        call    RMDevRead
        jnc     short fio45
        call    FCB_Ret_Err
        jmp     short fio50

fio45:  call    get_user_stack          ; (DS:SI) = user stack
        mov     ds:[si.User_CX],ax      ; return CX
        .if     nz                      ; end of file indication
          jmp     short fio15           ; successful read but not at eof
        .endif
        or      ax,ax
        jz      short fio6
        mov     ax,3                    ; At end of file and Partial read
fio50:  pop     bx
        pop     si
        pop     ds
        ret                             ; cant call FCB_Ret_OK

fio6:   mov     ax,1                    ; At end of file and no data read
        jmp     short fio50             ; cant call FCB_Ret_OK

fio7:   call    RMDevWrite
        jnc     short fio10             ; operation successful
        call    FCB_Ret_Err
        jmp     short fio50

fio10:  call    get_user_stack          ; (DS:SI) = user stack
        mov     ds:[si.User_CX],ax      ; return CX
fio15:  pop     ax                      ; Can not pop ax
        pop     si
        pop     ds
        test    ax,Block+Random         ; Set extent/NR field for seq ops.
        jnz     short fio20
        call    GetExtent
        add     ax,1
        adc     dx,0
        call    SetExtent
fio20:  jmp     FCB_Ret_OK
EndProc FCBIO

V86CODE ENDS

        END
