;       SCCSID = @(#)mscode.asm 6.1 91/07/12
;       SCCSID = @(#)mscode.asm 6.1 90/11/17
;       SCCSID = @(#)mscode.asm 1.16    90/10/10
;
; MSCODE.ASM -- MSDOS code
;
;   Revisions:
;
;Local  DCR/
;Tag    PTM(R)  Who     When
;               danno   05-Dec-1988
;                   Created from dos4\dos\ms_code.asm.  Deleted sections
;                   are if'd and commented out to ease deltas.
;
;75462  75462   BClare  17 Dec 1993  Changeteam defect
;                   Added CLD instruction to ETAB_LK to ensure that table
;                   lookup proceeds upward into the table.
;


.xlist
include v86seg.inc
.xcref
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include demmac.inc
include mvdmexp.inc
include demsvc.inc
include dossymc.inc
include devsym.inc
include demver.inc
;include ifssym.inc
;include fastopen.inc
;include fastxxxx.inc
include mi.inc
include error.inc
include mult.inc
include demmult.inc
include harderr.inc
.cref
.list
        CpuMode 386

AsmVars <Kanji, Debug>

V86CODE    SEGMENT

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

    ReferV86  InDos,BYTE                  ; TRUE => we are in dos, no interrupt
    ReferV86  OpenBuf,128                 ; temp name buffer
    ReferV86  ExtErr,WORD                 ; extended error code
    ReferV86  User_SS,WORD                ; stack segment from user
    ReferV86  User_SP,WORD                ; stack pointer from user
;m    ReferV86  DskStack,BYTE               ; stack segment inside DOS
    ReferV86  Err_Table_21                ; allowed return map table for errors
    ReferV86  FailErr,BYTE                ; TRUE => system call is being failed
    ReferV86  ExtErr_Action,BYTE          ; recommended action
    ReferV86  ExtErr_Class,BYTE           ; error classification
    ReferV86  ExtErr_Locus,BYTE           ; error location
    ReferV86  I21_Map_E_Tab,BYTE          ; mapping extended error table
    ReferV86  User_In_AX,WORD             ; initial input user AX
;m    ReferV86  FOO,WORD                    ; return address for dos 2f dispatch
;m    ReferV86  DTAB,WORD                   ; dos 2f dispatch table
;m    ReferV86  HIGH_SECTOR,WORD            ; >32mb
;m    ReferV86  IFS_DRIVER_ERR,WORD         ; >32mb
;m    ReferV86  CURSC_DRIVE,BYTE            ;
    ReferV86  TEMP_VAR,WORD
    ReferV86  vheVDM,BYTE
;m    ReferV86  VDMInt28Count,WORD          ; VPL Idle detection
;m    ReferV86  VDMNotBusy,WORD             ; VPL Idle detection
    ReferV86  os2_handled,BYTE            ;mdr
    ReferV86  vm_save_drive,BYTE          ;mdr

        EXTRN   Get_User_Stack:NEAR
        EXTRN   TableDispatch:NEAR
;m        EXTRN   CheckHardError:NEAR
        EXTRN   save_world:NEAR
        EXTRN   restore_world:NEAR
        EXTRN   $IOCTL:NEAR

BREAK <NullDev -- Driver for null device>

procedure   SNULDEV,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
        MOV     ES:[BX.NDRbyte],0
        OR      ES:[BX.REQSTAT],STDON   ; Set done bit
entry INULDEV,,,nocheck
        RET                             ; MUST NOT BE A RETURN!
EndProc SNULDEV


BREAK <AbsDRD, AbsDWRT -- INT int_disk_read, int_disk_write handlers>


V86TABLE   SEGMENT
Public MSC001S,MSC001E
MSC001S label byte
        IF      IBM
; Codes returned by BIOS
ERRIN:
        DB      2                       ; NO RESPONSE
        DB      6                       ; SEEK FAILURE
        DB      12                      ; GENERAL ERROR
        DB      4                       ; BAD CRC
        DB      8                       ; SECTOR NOT FOUND
        DB      0                       ; WRITE ATTEMPT ON WRITE-PROTECT DISK
ERROUT:
; DISK ERRORS RETURNED FROM INT 25 and 26
        DB      80H                     ; NO RESPONSE
        DB      40H                     ; Seek failure
        DB      2                       ; Address Mark not found
        DB      10H                     ; BAD CRC
        DB      4                       ; SECTOR NOT FOUND
        DB      3                       ; WRITE ATTEMPT TO WRITE-PROTECT DISK

NUMERR  EQU     $-ERROUT
        ENDIF
MSC001E label byte

V86TABLE   ENDS

IF NOT_FILTER

; Interrupt 25 handler.  Performs absolute disk read.
; Inputs:       AL - 0-based drive number
;               DS:BX point to destination buffer
;               CX number of logical sectors to read
;               DX starting  logical sector number (0-based)
; Outputs:      Original flags still on stack
;               Carry set
;                   AH error from BIOS
;                   AL same as low byte of DI from INT 24

        procedure   ABSDRD,FAR
        ASSUME  CS:V86Group,DS:NOTHING,ES:NOTHING,SS:NOTHING

        CLI
        MOV     [user_SS],SS
        MOV     [user_SP],SP
        PUSH    CS
        POP     SS
ASSUME  SS:V86GROUP
        MOV     SP,OFFSET V86GROUP:DSKSTACK
        PUSH    [user_SS]
        PUSH    [user_SP]
        CALL    Save_World                    ;>32mb save all regs  ;AN000;
        MOV     [user_SS],SS
        MOV     [user_SP],SP
        CMP     CX,0
        JE      ILEAVE
        XOR     AH,AH

        SVC     SVC_DEMABSDRD
TLEAVE:
        JNC      ILEAVE

ar2:
; Clear any pending hard error which might have
; taken place in SVC call. INT25/26 does'nt support this. This is required
; to clear it so that an errorenous popup can be prevented on next system
; entry.
        and     cs:[vheVDM.vhe_fbMisc],not VHE_FLAG_ACTIVE
        IF      IBM
; Translate the error code to ancient 1.1 codes
        PUSH    ES
        PUSH    CS
        POP     ES
        XOR     AH,AH                   ; Nul error code
        MOV     CX,NUMERR               ; Number of possible error conditions
        MOV     DI,OFFSET  V86GROUP:ERRIN    ; Point to error conditions
        REPNE   SCASB
        JNZ     LEAVECODE               ; Not found
        MOV     AH,ES:[DI+NUMERR-1]     ; Get translation
LEAVECODE:
        POP     ES
        ENDIF
        MOV     [TEMP_VAR],AX           ;>32mb save error
        STC
ILEAVE:
        CALL    Restore_World                ;>32mb                             ;AN000;
        CLI
        DEC     INDOS
        POP     [user_SP]
        POP     [user_SS]
        MOV     SS,[user_SS]
ASSUME  SS:NOTHING
        MOV     SP,[user_SP]
        MOV     AX,[TEMP_VAR]           ;>32mb restore error               ;AN000;


        STI
        RET                             ; This must not be a RETURN!
EndProc ABSDRD

; Interrupt 26 handler.  Performs absolute disk write.
; Inputs:       AL - 0-based drive number
;               DS:BX point to source buffer
;               CX number of logical sectors to write
;               DX starting  logical sector number (0-based)
; Outputs:      Original flags still on stack
;               Carry set
;                   AH error from BIOS
;                   AL same as low byte of DI from INT 24

        procedure   ABSDWRT,FAR
ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

        CLI
        MOV     [user_SS],SS
        MOV     [user_SP],SP
        PUSH    CS
        POP     SS
ASSUME  SS:V86GROUP
        MOV     SP,OFFSET V86GROUP:DSKSTACK
        PUSH    [user_SS]
        PUSH    [user_SP]
        CALL    Save_World                    ;>32mb save all regs   ;AN000;
        MOV     [user_SS],SS
        MOV     [user_SP],SP
        CMP     CX,0
        JE      ILEAVE

;       We do not allow writes to a drive with non-removeable media.


        PUSH    DX
        PUSH    CX
        PUSH    BX
        PUSH    AX

        XCHG    AL,BL
        INC     BL                      ; bl = drive (1 = 'A')
        JZ      ABW1                    ; Drive passed was FF, 0-based.  Since
                                        ; $IOCtl takes 1-based drive numbers,
                                        ; we cannot accept FF.  Treat as bad
                                        ; drive number.  Note that passing 0
                                        ; to $IOCtl selects default drive.
        MOV     AL,8                    ; (al) = check removable media
        PUSH    DS
        INVOKE  $IOCTL                  ; Check for removeable media.
        POP     DS
        JC      SHORT ABW1                    ;   Invalid drive

        OR      AX,AX                   ; Check return value
        JZ      SHORT ABW3                    ;   drive has removeable media

        MOV     AX,ERROR_I24_NOT_READY  ; Drive has fixed media
        JMP     SHORT ABW2

ABW1:   MOV     AX,ERROR_I24_BAD_UNIT   ; Invalid drive or network drive
ABW2:   POP     BX                      ; Eat AX
        POP     BX
        POP     CX
        POP     DX
        STC                             ;    indicate error
        JMP     TLEAVE                  ;

ABW3:   POP     AX
        POP     BX
        POP     CX
        POP     DX
        XOR     AH,AH
        SVC     SVC_DEMABSDWRT
        JMP     TLEAVE
EndProc ABSDWRT

; VPL Idle detection
; Interrupt 28 handler.  Counts int 28 calls.
; Inputs:       None.
; Outputs:      None.
PUBLIC  VPLINT28
VPLINT28   PROC    FAR
ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

        STI                             ; enable if before sleep
        push    bp
        MOV     BP,SP
        push    ax
        mov     ax,cs

        cmp     ax,[bp+4]               ; who made the call?
        jne     v28_10                  ;   call is from outside DOS

        mov     cs:[VDMInt28Count],0fh  ; start new countdown
        jmp     short v28_50

v28_10: dec     cs:[VDMInt28Count]      ; countdown of int 28h's
        jne     v28_50                  ;   no, skip vpol notification

        push    dx
        xor     dx,dx                   ; dx:ax == 1 indicates Int28 loop
        mov     ax,1                    ;
        SVC     SVC_DEMSLEEP            ; Give VPOL a chance to examine count
        pop     dx

        mov     cs:[VDMInt28Count],0fh  ; start new countdown

v28_50: pop     ax
        pop     bp
        IRET                            ; assumes this is first handler
VPLINT28   ENDP

;filter
ENDIF

BREAK <Sys_Return, Sys_Ret_OK, Sys_Ret_Err, CAL_LK, ETAB_LK>
;
; These are the general system call exit mechanisms.  All internal system
; calls will transfer (jump) to one of these at the end.  Their sole purpose
; is to set the user's flags and set his AX register for return.
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure Sys_Return,near
        jc      short Sys_Ret_Err

Entry   Sys_Ret_OK
;       call    FETCHI_CHECK            ; TAG checking for FETCHI
        cmp     cs:os2_handled,0        ;mdr if os2 didn't handle don't alter AX!
        je      syr10                   ;mdr
        call    get_user_stack
        and     [SI.user_F],not f_Carry ; turn off user's carry flag
        mov     [SI.user_AX],ax         ; really only sets AH
syr10:  ret

Entry   Sys_Ret_Err_AL                  ; saves a little space
        xor     ah,ah                   ; hack to allow for smaller error rets

Entry   Sys_Ret_Err
;m        invoke  CheckHardError
;m        jnc     short Sys_Ret_OK        ; jump if ignore
        cmp     cs:os2_handled,0        ;mdr if os2 didn't handle don't alter AX!
        je      syr12                   ;mdr
        call    ETAB_LK                 ; make sure code is OK, EXTERR gets set
        call    ErrorMap
        invoke  get_user_stack
        or      [SI.user_F],f_Carry     ; signal carry to user
        mov     [SI.user_AX],ax         ; really only sets AH
        stc                             ; also, signal internal error
syr12:  ret                             ; mdr


;***************************************************************************
;  expect ds:dx to point to FCB

Entry   FCB_Return
        pushf                          ; mdr save carry flag
        mov     si,dx                  ; mdr have to use index reg
        cmp     byte ptr ds:[si],0ffh  ; mdr determine type of FCB
        jne     fr10                   ; mdr
        add     si,7                   ; mdr adjust to point to drive number
fr10:   mov     bl,cs:vm_save_drive    ; mdr restore original drive number
        mov     ds:[si],bl             ; mdr  to this field in FCB
        popf                           ; mdr get carry flag
        jc      short FCB_Ret_Err

Entry   FCB_Ret_OK
Entry   CPMFunc
        xor     al,al
        ret

Entry   FCB_Ret_Err
;m        invoke  CheckHardError
;m        jnc     short FCB_Ret_OK        ; jump if ignore
        mov     [ExtErr],ax
        call    ErrorMap
        mov     al,-1
        ret

Entry   ErrorMap
        push    si
        mov     si,offset V86GROUP:Err_Table_21
        cmp     [FailErr],0             ; check for SPECIAL case.
        jz      short syr20             ; all is OK.
        mov     [ExtErr],ERROR_FAIL_I24 ; oops, this is the REAL reason
        mov     si,offset V86GROUP:Err_Table_21
syr20:  call    CAL_LK                  ; set CLASS,ACTION,LOCUS for EXTERR
        pop     si
        ret
EndProc Sys_Return


;***    CAL_LK - Set error Class, Action and Locus values
;
;       This function look ups and sets CLASS, ACTION and LOCUS
;       values for GetExtendedError
;
;       ENTRY   SI is OFFSET in V86GROUP of CLASS,ACTION,LOCUS Table to use
;                       (DS NEED not be V86GROUP)
;               [ExtErr] is set with error
;
;       EXIT    [ExtErr_Class] set
;               [ExtErr_Action] set
;               [ExtErr_Locus] set
;                       (EXCEPT on certain errors as determined by table)
;
;       USES    SI, FLAGS
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure CAL_LK,near
        PUSH    DS
        PUSH    AX
        PUSH    BX
        Context DS              ; DS:SI -> Table
        MOV     BX,[ExtErr]     ; Get error in BL
        OR      BH,BH
        JZ      TABLK1

TABLK0:                         ; If error code > 255, then use default
        LODSB
        CMP     AL,0FFH
        JZ      GOT_VALS        ; End of table
        ADD     SI,3            ; Next table entry
        JMP     TABLK0

TABLK1:
        LODSB
        CMP     AL,0FFH
        JZ      GOT_VALS        ; End of table
        CMP     AL,BL
        JZ      GOT_VALS        ; Got entry
        ADD     SI,3            ; Next table entry
        JMP     TABLK1

GOT_VALS:
        LODSW                   ; AL is CLASS, AH is ACTION
        CMP     AH,0FFH
        JZ      NO_SET_ACT
        MOV     [ExtErr_Action],AH      ; Set ACTION
NO_SET_ACT:
        CMP     AL,0FFH
        JZ      NO_SET_CLS
        MOV     [ExtErr_Class],AL       ; Set CLASS
NO_SET_CLS:
        LODSB                   ; Get LOCUS
        CMP     AL,0FFH
        JZ      NO_SET_LOC
        MOV     [ExtErr_Locus],AL
NO_SET_LOC:
        POP     BX
        POP     AX
        POP     DS
        RET
EndProc   CAL_LK

;***    ETAB_LK -- Make sure error code is appropriate to this call.
;
;       The error code in AX is checked to insure that it is an
;       appropriate error code for the current system call.  If
;       not, it is mapped into an error code which is compatible
;       with previous versions of MS-DOS.
;
;       ENTRY   AX is error code
;               [User_In_AX] has AX value of system call involved
;       EXIT    AX MAY be mapped error code
;               [ExtErr] = Input AX
;       USES    AX, FLAGS
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

Procedure ETAB_LK,near
        SaveReg <DS,SI,CX,BX>
        Context DS
        MOV     [ExtErr],AX             ; Set ExtErr with "real" error
        MOV     SI,OFFSET V86GROUP:I21_MAP_E_TAB
        MOV     BX,AX                   ; Real code to BX
        MOV     CL,BYTE PTR [User_In_AX + 1]    ; Sys call to CL
        CLD                             ;Go UP in lookup table          ;75462;
TABLK2:
        LODSW
        CMP     AL,0FFH                 ; End of table?
        JZ      NOT_IN_TABLE            ; Yes
        CMP     AL,CL                   ; Found call?
        JZ      GOT_CALL                ; Yes
        XCHG    AH,AL                   ; Count to AL
        XOR     AH,AH                   ; Make word for add
        ADD     SI,AX                   ; Next table entry
        JMP     TABLK2

NOT_IN_TABLE:
        MOV     AX,BX                   ; Restore original code
        JMP     SHORT NO_MAP

GOT_CALL:
        LODSB                           ; (AL) = # of mappings
        MOV     CL,AL
        XOR     CH,CH                   ; Count of valid err codes to CX
        JCXZ    try_legal
map_loop:
        LODSW                           ; (AX) = map_from
        CMP     AX,BX                   ;
        LODSW                           ; (AX) = map_to
        JE      NO_MAP                  ;
        LOOP    map_loop
try_legal:
        XOR     AH,AH
        LODSB                           ; (AX) = # valid err codes
        MOV     CX,AX                   ; (CX) = # valid err codes
        OR      BH,BH
        JZ      check_code              ; Ok, high byte of err code = 0;
;
        ADD     SI,CX                   ; if error code > 255, use default
        DEC     SI
        LODSB
        JMP     SHORT NO_MAP

CHECK_CODE:
        LODSB
        CMP     AL,BL                   ; Code OK?
        JZ      NO_MAP                  ; Yes
        LOOP    CHECK_CODE
NO_MAP:
        RestoreReg <BX,CX,SI,DS>
        RET
EndProc   ETAB_LK

BREAK <DOS 2F Handler and default NET 2F handler>

IF installed

;
; SetBad sets up info for bad functions
;
Procedure   SetBad,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        MOV     AX,error_invalid_function       ; ALL NET REQUESTS get inv func
        MOV     ExtErr_LOCUS,errLoc_UNK
        STC
        ret
EndProc SetBad
;
; BadCall is the initial routine for bad function calls
;
procedure   BadCall,FAR
        call    SetBad
        ret
EndProc BadCall
;
; OKCall always sets carry to off.
;
Procedure   OKCall,FAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        CLC
        ret
EndProc OKCall


IF NOT_FILTER

;***LP  Win386Multiplex - handle Win386 int2f functions
;
;       ENTRY   al = subfunction number
;               other registers depend on subfunction
;
;       EXIT    depends on subfunction
;
;       USES    ax,flags

; NOTE: These functions should move to MVDM int2f.c

Win386Multiplex proc    near

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

;*  NOTE: If we choose to support some of these Win386 APIs at a
;         later date, then this code should become table-driven.

        cmp     al,W386_Get_Version     ; Installation check?
        jne     wm10                    ;   NO, test for next subfunction

;*  We pretend to be Win386 ver 3.0, so that Word 5.0 will decide
;   to issue the ReleaseTimeSlice call!

        mov     ax,0003                 ; al=major ver, ah=minor ver
        jmp     short wmx               ; go exit


;       VPL Idle detection
wm10:   cmp     al,W386_Release_Time    ; Release Time Slice service?
        jne     wme                     ;   NO, return failure

;*  Voluntary release of time slice.

        push    ax                      ;   YES, sleep for a bit and return
        push    dx
        xor     dx,dx
        xor     ax,ax
        mov     cs:VDMNotBusy,1         ; force sleep regardless
        SVC     SVC_DEMSLEEP            ; Do sleep
        pop     dx
        pop     ax
        mov     al,0                    ; success
        jmp     short wmx               ; go exit

;*  The various Win386 functions are very inconsistent about what return
;   value constitutes an error.
;

wme:    mov     al,0                    ; failure

wmx:    ret

Win386Multiplex endp


; INT 2F handler works as follows:
;   PUSH    AX
;   MOV     AX,multiplex:function
;   INT     2F
;   POP     ...
; The handler itself needs to make the AX available for the various routines.

PUBLIC  Int2F
INT2F   PROC    FAR

INT2FNT:
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        STI
        cmp     ah,multWIN386           ; win386 call?
        jne     TestNet                 ;   NO, try next category

        call    Win386Multiplex
        retf    2                       ; return, keeping current flags

TestNet:
        CMP     AH,multNET
        JNZ     INT2FSHR
TestInstall:
        OR      AL,AL
        JZ      Leave2F
BadFunc:
        CALL    SetBad
        entry   Leave2F
        RET     2                       ; long return + clear flags off stack
INT2FSHR:
        CMP     AH,multSHARE            ; is this a share request
        JZ      TestInstall             ; yes, check for installation

INT2FNLS:
        CMP     AH,NLSFUNC              ; is this a DOS 3.3 NLSFUNC request
        JZ      TestInstall             ; yes check for installation

INT2FDOS:
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        CMP     AH,multDOS
        JZ      DispatchDOS
        IRET                            ; This assume that we are at the head
                                        ; of the list
INT2F   ENDP

DispatchDOS:
        PUSH    FOO                     ; push return address
        PUSH    DTab                    ; push table address
        PUSH    AX                      ; push index
        PUSH    BP
        MOV     BP,SP
; stack looks like:
;   0   BP
;   2   DISPATCH
;   4   TABLE
;   6   RETURN
;   8   LONG-RETURN
;   c   FLAGS
;   e   AX

        MOV     AX,[BP+0Eh]             ; get AX value
        POP     BP
        Invoke  TableDispatch
        JMP     BadFunc                 ; return indicates invalid function

Procedure   INT2F_etcetera,NEAR
        entry   DosGetGroup
        PUSH    CS
        POP     DS
        return

        entry   DOSInstall
        MOV     AL,0FFh
        return
EndProc INT2F_etcetera

ENDIF

ifdef NOT_MVDM ; BUGBUG danno 06-Dec-1988

;Input: same as ABSDRD and ABSDWRT
;        ES:BP -> DPB
;Functions: convert 32bit absolute RW input parms to 16bit input parms
;Output: carry set when CX=-1 and drive is less then 32mb
;        carry clear, parms ok
;
Procedure   RW32_CONVERT,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        CMP     CX,-1                        ;>32mb  new format ?               ;AN000;
        JZ      new32format                  ;>32mb  yes                        ;AN000;
        PUSH    AX                           ;>32mb  save ax                    ;AN000;
        PUSH    DX                           ;>32mb  save dx                    ;AN000;
        MOV     AX,ES:[BP.dpb_max_cluster]   ;>32mb  get max cluster #          ;AN000;
        MOV     DL,ES:[BP.dpb_cluster_mask]  ;>32mb                             ;AN000;
        CMP     DL,0FEH                      ;>32mb  removable ?                ;AN000;
        JZ      letold                       ;>32mb  yes                        ;AN000;
        INC     DL                           ;>32mb                             ;AN000;
        XOR     DH,DH                        ;>32mb  dx = sector/cluster        ;AN000;
        MUL     DX                           ;>32mb  dx:ax= max sector #        ;AN000;
        OR      DX,DX                        ;>32mb  > 32mb ?                   ;AN000;
letold:
        POP     DX                           ;>32mb  retore dx                  ;AN000;
        POP     AX                           ;>32mb  restore ax                 ;AN000;
        JZ      old_style                    ;>32mb  no                         ;AN000;
        MOV     [IFS_DRIVER_ERR],0207H       ;>32mb  error                      ;AN000;
        STC                                  ;>32mb                             ;AN000;
        return                               ;>32mb                             ;AN000;
new32format:
        MOV     DX,WORD PTR [BX.SECTOR_RBA+2];>32mb                             ;AN000;
        MOV     [HIGH_SECTOR],DX             ;>32mb                             ;AN000;
        MOV     DX,WORD PTR [BX.SECTOR_RBA]  ;>32mb                             ;AN000;
        MOV     CX,[BX.ABS_RW_COUNT]         ;>32mb                             ;AN000;
        LDS     BX,[BX.BUFFER_ADDR]          ;>32mb                             ;AN000;
old_style:                                   ;>32mb                             ;AN000;
        CLC                                  ;>32mb                             ;AN000;
        return                               ;>32mb                             ;AN000;
EndProc RW32_CONVERT

;Input: None
;Functions: Purge Fastopen/seek Cache Buffers
;Output: None
;
;
Procedure   Fastxxx_Purge,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        PUSH    AX                            ; save regs.                      ;AN000;
        PUSH    SI                                                              ;AN000;
        PUSH    DX                                                              ;AN000;
        TEST    FastSeekflg,Fast_yes          ; fastseek installed ?            ;AN000;
        JZ      topen                         ; no                              ;AN000;
        MOV     AH,FastSeek_ID                ; set fastseek id                 ;AN000;
        JMP     SHORT dofast                  ;                                 ;AN000;
topen:
        TEST    FastOpenflg,Fast_yes          ; fastopen installed ?            ;AN000;
        JZ      nofast                        ; no                              ;AN000;
        MOV     AH,FastOpen_ID                ; set fastseek installed          ;AN000;
dofast:
        MOV     AL,FONC_purge                 ; purge                           ;AN000;
        MOV     DL,ES:[BP.dpb_drive]          ; set up drive number             ;AN000;
        invoke  Fast_Dispatch                 ; call fastopen/seek              ;AN000;
nofast:
        POP     DX                                                              ;AN000;
        POP     SI                            ; restore regs                    ;AN000;
        POP     AX                            ;                                 ;AN000;

        return                                ; exit                            ;AN000;
EndProc Fastxxx_Purge

endif ; BUGBUG danno 05-Dec-1988

;filter
ENDIF

V86CODE    ENDS

        END
