;       SCCSID = @(#)mscode.asm 6.12 92/03/24
;
; 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.
;
;***********************************************************************;BN001;
; 10May91 - G.L.Fulk                                                    ;BN001;
; Int 2Fh, AH=16h, was returning AL=0 return codes for any subfunction  ;BN001;
; it did not know about.  This is causing a problem with Windows.  I've ;BN001;
; removed the AL=0 for unknown functions.                               ;BN001;
;                                                                       ;BN001;
;***********************************************************************;BN001;
; 28Jul91 - G.L.Fulk                                                    ;BN002;
; Share should always return it is installed.                           ;BN002;
;***********************************************************************;BN002;
; B003  10/22/91  CP20 B726727  Mark Rogalski                           ;BN003;
;       Do not return that Windows is present.                          ;BN003;
;***********************************************************************;BN003;
; 12Nov91 - G.L.Fulk                                                    ;BN004;
; Hack for int 25h/int 13h for Lotus Symphony and 1-2-3.                ;BN004;
;***********************************************************************;BN004;
; 12Dec91 - G.L.Fulk                                                    ;BN005;
; Missing Inc [Indos] for an int 25h.                                   ;BN005;
;********************************************************************** ;BN005;
; 28Feb92 - G.L.Fulk                                                    ;BN006;
; Implement int 2Fh, ax=1213h.                                          ;BN006;
;********************************************************************** ;BN006;
; 24Mar92 - G.L.Fulk                                                    ;BN007;
; Implement int 2Fh, ax=122Ah, fake a return of no FASTOPEN installed.  ;BN007;
;********************************************************************** ;BN007;
; 11Jun92 - G.L.Fulk                                                    ;BN008;
; Implement the int 2Fh DispatchDOS jump table.  Add support for 1218h. ;BN008;
;********************************************************************** ;BN008;
; 11Aug92 - G.L.Fulk                                                    ;BN009;
; Use push cs/pop ds to assert the V86GROUP segment value.              ;BN009;
;********************************************************************** ;BN009;
; 15Oct92 - G.L.Fulk                                                    ;BN010;
; Add "In_int25" flag to speed up int 13h calls.  See also MSPROC.ASM.  ;BN010;
;********************************************************************** ;BN010;
; 16Feb93 - G.L.Fulk                                                    ;62101;
; Need to correctly handle B: drive.                                    ;62101;
;********************************************************************** ;62101;
; 11Mar93 - L.M.Primm                                                   ;62491;
; Don't munch on return for Int25 if it isn't in BIOS/DOS trans table   ;62491;
;********************************************************************** ;62491;
; 11Dec93 - B.Clare (changeteam)                                        ;75460;
; Added CLD instruction to ETAB_LK to ensure that scanning proceeds     ;75460;
; UPward into the error table. Change was required to allow changes     ;75460;
; to $unlink to work properly when $find_first fails.                   ;75460;
;********************************************************************** ;75460;
; 12Jan94 - D.Azzarito                                                  ;74953;
; Check for locked disk before allowing direct write                    ;74953;
;********************************************************************** ;74953;


.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 mi.inc
include error.inc
include mult.inc
include demmult.inc
include harderr.inc
include struc30.inc                                                     ;BN002;
.cref
.list
        CpuMode 8086

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
    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
    ReferV86  FOO,WORD                    ; return address for dos 2f dispatch
    ReferV86  DTAB,WORD                   ; dos 2f dispatch table
    ReferV86  HIGH_SECTOR,WORD            ; >32mb
    ReferV86  IFS_DRIVER_ERR,WORD         ; >32mb
    ReferV86  CURSC_DRIVE,BYTE            ;
    ReferV86  TEMP_VAR,WORD
    ReferV86  vheVDM,BYTE
    ReferV86  VDMInt28Count,WORD          ; VPL Idle detection
    ReferV86  VDMNotBusy,WORD             ; VPL Idle detection
    ReferV86  UCASE_TAB,BYTE                                            ;BN006;
        EXTRN   GETLET3:NEAR                                            ;BN006;
        EXTRN   Get_User_Stack:NEAR
        EXTRN   TableDispatch:NEAR
        EXTRN   CheckHardError:NEAR
        EXTRN   save_world:NEAR
        EXTRN   restore_world:NEAR
        EXTRN   $IOCTL:NEAR

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


V86TABLE   SEGMENT
Public MSC001S,MSC001E
MSC001S label byte
;BD008; 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
;BD008; ENDIF
MSC001E label byte

V86TABLE   ENDS

; 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

        public  In_int25                                                ;BN010;
In_int25        DB      0                                               ;BN010;
procedure   ABSDRD,FAR
        ASSUME  CS:V86Group,DS:NOTHING,ES:NOTHING,SS:NOTHING

        CLI
        MOV     cs:[user_SS],SS
        MOV     cs:[user_SP],SP

;------ establish addressability
        PUSH    CS
        POP     SS
        ASSUME  SS:V86GROUP

        MOV     SP,OFFSET V86GROUP:DSKSTACK


;------ if A:&B: drives only, perform the int 13h hack.                 ;56845;
        .if     <AL be 1>                                               ;56845;
          push    ax                                                    ;BN004;
          push    dx                                                    ;BN004;
          mov     dl,al                                                 ;BN004;
;62101;   mov     ah,al                                                 ;BN004;
          xor     ah,ah                                                 ;62101;
          mov     cs:[In_int25],1                                       ;BN010;
          int     13h                                                   ;BN004;
          mov     cs:[In_int25],0                                       ;BN010;
          pop     dx                                                    ;BN004;
          pop     ax                                                    ;BN004;
        .endif                                                          ;BN004;


        PUSH    [user_SS]
        PUSH    [user_SP]
        CALL    Save_World                    ;>32mb save all regs  ;AN000;
        MOV     [user_SS],SS
        MOV     [user_SP],SP
        INC     [INDOS]                                                 ;BN005;
        CMP     CX,0
        JE      ILEAVE
        XOR     AH,AH

        SVC     SVC_DEMABSDRD
TLEAVE:
        JNC     short 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

; Translate the error code to ancient 1.1 codes
        PUSH    ES

        PUSH    CS
        POP     ES

        MOV     [TEMP_VAR],AX           ; save original rc              ;62491;
        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
        .if     z                       ; Not found?
          mov     ah,es:[DI+NUMERR-1]   ; Get translation (if found)
        .else                                                           ;62491;
          MOV     AX,[TEMP_VAR]         ; restore original rc if !found ;62491;
        .endif
        POP     ES

        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

;------ Establish addressability
        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      short 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


; @74953 Is the "fixed-disk" locked?  If so, permit the Absolute write.
        MOV     AX,BX
        DEC     AX
        XOR     BX,BX
        MOV     DX,9
        SVC     SVC_DEMGENERIC
        .IF     NC
          OR      AX,AX
          JNZ     SHORT ABW3
        .ENDIF
; @74953 ends

        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

        .if     <AX eq <[BP+4]>>        ; is the call from outside DOS
          mov     cs:[VDMInt28Count],0fh  ; start new countdown
        .else
          dec     cs:[VDMInt28Count]    ; countdown of int 28h's
          .if     z                     ;   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
          .endif
        .endif

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


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    get_user_stack
        and     [SI.user_F],not f_Carry ; turn off user's carry flag
        jmp     short syr10             ; carry is now clear

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

Entry   Sys_Ret_Err
        invoke  CheckHardError
        jnc     short Sys_Ret_OK        ; jump if ignore
        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
        stc                             ; also, signal internal error
syr10:  mov     [SI.user_AX],ax         ; really only sets AH
        ret

Entry   FCB_Return
        jc      short FCB_Ret_Err

Entry   FCB_Ret_OK
Entry   NO_OP
        xor     al,al
        ret

Entry   FCB_Ret_Err
        invoke  CheckHardError
        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
        .if     <[FailErr] ne 0>        ; check for SPECIAL case.
          mov     [ExtErr],ERROR_FAIL_I24 ; oops, this is the REAL reason
  ;BD008; mov     si,offset V86GROUP:Err_Table_21  ;<-redundant
        .endif
        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

;------ preserve registers
        PUSH    DS
        PUSH    AX
        PUSH    BX

;------ establish addressability
        push    cs                                                      ;BC009;
        pop     ds
        assume  ds:V86GROUP

        MOV     BX,[ExtErr]     ; Get error in BL
        .if     <NONZERO BH>
          ; If error code > 255, then use default
          .repeat
            LODSB
            CMP     AL,0FFh
            JZ      short GOT_VALS        ; End of table
            ADD     SI,3            ; Next table entry
          .until
        .endif

        .repeat
          LODSB
          CMP     AL,0FFh
          JZ      short GOT_VALS          ; End of table
          CMP     AL,BL
          JZ      short GOT_VALS          ; Got entry
          ADD     SI,3            ; Next table entry
        .until

GOT_VALS:
        LODSW                   ; AL is CLASS, AH is ACTION

        .if     <AH ne -1>
          mov     [ExtErr_Action],AH      ; Set ACTION
        .endif

        .if     <AL ne -1>
          mov     [ExtErr_Class],AL       ; Set CLASS
        .endif

        LODSB                   ; Get LOCUS
        .if     <AL ne -1>
          mov     [ExtErr_Locus],AL
        .endif

;------ restore registers
        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
;------ preserve registers
        push    ds
        push    si
        push    cx
        push    bx

;------ establish addressability
        push    cs                                                      ;BC009;
        pop     ds
        assume  ds:V86GROUP

        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          ;75460;
        .repeat
          LODSW
          .leave  <AL eq -1>            ; End of table?
          CMP     AL,CL                 ; Found call?
          JZ      short GOT_CALL        ; Yes
          XCHG    AH,AL                 ; Count to AL
          XOR     AH,AH                 ; Make word for add
          ADD     SI,AX                 ; Next table entry
        .until

        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
        .if     ncxz
          .repeat
            LODSW                       ; (AX) = map_from
            CMP     AX,BX               ;
            LODSW                       ; (AX) = map_to
            JE      short NO_MAP        ;
          .loop
        .endif
        XOR     AH,AH
        LODSB                           ; (AX) = # valid err codes
        MOV     CX,AX                   ; (CX) = # valid err codes
        .if     <NONZERO BH>            ; Ok, high byte of err code = 0;
          ADD     SI,CX                 ; if error code > 255, use default
          DEC     SI
          LODSB
          JMP     SHORT NO_MAP
        .endif

        .repeat
          LODSB
          CMP     AL,BL                   ; Code OK?
          JZ      short NO_MAP            ; Yes
        .loop
NO_MAP:
;------ restore registers
        pop     bx
        pop     cx
        pop     si
        pop     ds

        ret
EndProc   ETAB_LK

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

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


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

;BD003  cmp     al,W386_Get_Version     ; Installation check?
;BD003  jne     short wm10              ;   NO, test for next subfunction
;BD003
;BD003;*  We pretend to be Win386 ver 3.0, so that Word 5.0 will decide
;BD003;   to issue the ReleaseTimeSlice call!
;BD003
;BD003  mov     ax,0003                 ; al=major ver, ah=minor ver
;BD003  jmp     short wmx               ; go exit


;       VPL Idle detection
wm10:   cmp     al,W386_Release_Time    ; Release Time Slice service?
        jne     short 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:                                                                    ;BC001;
;       mov     al,0                    ; failure                       ;BD001;

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

        assume  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        sti

;------ We fake a return telling the user that SHARE and NLSFUNC are installed.
        .if     <AX eq <(NLSFUNC)*100h>> or     ;AX=1400h               ;BN002;
        .if     <AX eq <(multSHARE)*100h>>      ;AX=1000h               ;BN002;
          dec     al                    ;return AL=-1                   ;BN002;
          jmp     short Leave2F                                         ;BN002;
        .endif                                                          ;BN002;

        .if     <AH eq NLSFUNC> or      ;AH=14h
        .if     <AH eq multSHARE> or    ;AH=10h
        .if     <AH eq multNET>         ;AH=11h
          .if     <NONZERO AL>
BadFunc:    call    SetBad
          .endif
          entry   Leave2F
          retf    2                     ; long return + clear flags off stack
        .endif

        .if     <AH eq multDOS>         ;AH=12h
          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
        .endif

        .if     <AH eq multWIN386>      ;AH=16h
          call    Win386Multiplex
          retf    2                     ; return, keeping current flags
        .endif

        IRET                            ; This assume that we are at the head
                                        ; of the list
INT2F   ENDP

public  FastInit                                                        ;BN008;
FastInit proc    near                   ;int 2F ax=122Ah                ;BN008;
        clc                                                             ;BN007;
        ret                                                             ;BN008;
FastInit endp                                                           ;BN008;

public  UCase                                                           ;BN008;
UCase   proc    near                    ;int 2F ax=1213h                ;BN008;
        ; mimic int 21h func=6520h handling in demgset.asm              ;BN006;
        push   bp                                                       ;BN006;
        push   bx                                                       ;BN006;
        push   ds                                                       ;BN006;

        mov    bp,sp                                                    ;BN006;
        mov    bx,offset V86GROUP:UCASE_TAB + 2                         ;BN006;
        invoke GETLET3                                                  ;BN006;

        pop    ds                                                       ;BN006;
        pop    BX                                                       ;BN006;
        pop    bp                                                       ;BN006;
        ret
UCase   endp                                                            ;BN008;

Procedure   INT2F_etcetera,NEAR
        entry   DosGetGroup
        PUSH    CS
        POP     DS
        ret

        entry   DOSInstall
        mov     al,0FFh
        ret
EndProc INT2F_etcetera

;BD008; 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;
        ret                                  ;>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;
        ret                                  ;>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;

        ret                                   ; exit                            ;AN000;
EndProc Fastxxx_Purge

endif ; BUGBUG danno 05-Dec-1988

V86CODE    ENDS

        END
