        page    80,132  ;
        title   DEMIOC2 - DOS Emulation IOCTL Support

;***EM  demioc2.asm
;
;       Version 1.22, for src/dos/mvdm/demioc2.asm, dem, mer.krnl, 960610.1
;
;       SUMMARY
;           DOS Emulation ioctl Support
;
;       NOTES
;
;       REVISIONS
;
;Local  DCR/
;Tag    PTR     Who     When
;               danno   15-Mar-1989
;                   Created for MVDM
;

;
;   Throughout the routines in this file, when loading registers
;   from the client stack frame, we will perform a 32-bit load.
;   Generally, the upper-16 bits of the register are ignored and
;   only the lower 16-bits are needed.  This is done only to avoid
;   an override.
;
;   When storing registers into the stack frame, however, we always
;   perform 16-bit stores, since the upper 16-bits of the 32-bit
;   registers are reserved *exclusively* for DOS applications.
;
;   -- danno 08-Mar-1989
;
; REVISION HISTORY:
;  B001 - ptr J200275 - EMK - 02/05/91 - INT 21h IOCTL (AX=440DH)       ;BN001;
;       causes TrapD, because the TASKARE:[ptda_pCDS] is not            ;BN001;
;       initialized in the DemGetDriveInfo Proc.                        ;BN001;
;********************************************************************** ;BN004;
; 15Mar91 - G.L.Fulk                                                    ;BN004;
; IOCtl calls to an OS/2 device driver fail.  The routin IOFunc is      ;BN004;
; being changed to detect the presents of an OS/2 driver as opposed     ;BN004;
; to a DOS driver.  The BX register needs to be preserved in this file. ;BN004;
; Files affected:   v86code\DemIoctl.asm                                ;BN004;
;                   v86code\DemDev.asm                                  ;BN004;
;                   mvdm\DemIoc2.asm                                    ;BN004;
;********************************************************************** ;BN004;
; 15Mar91 - G.L.Fulk                                                    ;BN005;
; New IOCTL commands added to DOS 5.0 Tech Ref, but not in the function ;BN005;
; Spec.                                                                 ;BN005;
;********************************************************************** ;BN005;
; 15Jul91 - G.L.Fulk                                                    ;BN006;
; Family 1 machines needs to have HMA address normalized so that the    ;BN006;
; selectors avoid the FFFF0h-FFFFFh range of bytes.  This is the ROM    ;BN006;
; BIOS area and is marked in memory management as "uvirt".  The device  ;BN006;
; drivers for family 1 machines are "locking" the entire segment, and   ;BN006;
; a segment value of FFFFh is causing problems.  The technique is to    ;BN006;
; add 10h to the base address and subtract 10h from the offset value.   ;BN006;
;********************************************************************** ;BN006;
; 14Oct91 - G.L.Fulk                                                    ;BN007;
; The MODE command uses a FAPI call to IOCTL 440Ch.  It passes in a NULL;BN007;
; pointer for the data packet.  The segment value of 0 is translated    ;BN007;
; into a valid selector.  This is no good because it must remain a 0    ;BN007;
; so as to be treated a NULL.                                           ;BN007;
;********************************************************************** ;BN007;
; 20Nov91 - G.L.Fulk                                                    ;BN008;
; IOCTL 440Dh is producing a bad selector because it is getting the real;BN008;
; mode word value into a double word register with a "MOV EAX,DWORD ".  ;BN008;
; Replace it with a "MOVZX EAX,WORD ".                                  ;BN008;
;********************************************************************** ;BN008;
; 1/20/92 - CP20 B731298                                                ;BN009;
; IOCTL 4404h is being called for drive C:. This is not handled by the  ;BN009;
; disk device driver and needs to be rejected as an invalid function.   ;BN009;
;********************************************************************** ;BN009;
; 10Feb92 - G.L.Fulk                                                    ;BN010;
; Invalid sub-function calls to IOCTL, to an OS/2 device driver cause   ;BN010;
; a deliberate system internal error.                                   ;BN010;
;********************************************************************** ;BN010;
; 29Feb92 - G.L.Fulk                                                    ;BN011;
; Ioctl in/out status should return AL=0 or FFh, not just NZ/ZF.        ;BN011;
;********************************************************************** ;BN011;
; 60317  1/15/93 - Mark Rogalski                                        ;BN012;
; Because device drivers may try to lock down data and parm packet      ;BN012;
; segments, we need to make sure the selectors we allocate aren't       ;BN012;
; near each other (have common pages).                                  ;BN012;
;********************************************************************** ;BN012;
; 13Jan93 - G.L.Fulk                                                    ;57908;
; Some very ill behaved DOS apps are depending on an random value in    ;57908;
; certain bits of the SFT flags.   Modify our Get_ioctl bits to try     ;57908;
; and match the DOS settings.                                           ;57908;
;********************************************************************** ;57908;
; 15Dec92 - G.L.Fulk                                                    ;51637;
; DOS has a nasty bug that causes it to respond to CD-Roms as invalid   ;51637;
; function to removable media query.                                    ;51637;
;********************************************************************** ;51637;
; 15Jan93 - G.L.Fulk                                                    ;60024;
; DOS expects error code 1 (invalid function) if a 4408 query for       ;60024;
; removable media is done on a network drive.                           ;60024;
;********************************************************************** ;60024;
; 59348  1/24/93 - Mark Rogalski                                        ;BN013;
; Corillary to above defect. If data block and parm block segs are the  ;BN013;
; same, then only allocate one selector for both to use.                ;BN013;
;********************************************************************** ;BN013;
; 59664  3/01/93 - Mark Rogalski                                        ;BN014;
; The above fix was merged incorrectly and has an error.                ;BN014;
;********************************************************************** ;BN014;
; 18Mar93 - Fulkgl                                                      ;64247;
; Ioctl calls 4409 has a stupid special meaning for CDRoms.             ;64247;
;********************************************************************** ;64247;
; 10Jun93 - Fulkgl                                                      ;70483;
; Ioctl calls 440A should return the value in AX, not DX to DOSKRNL.    ;70483;
;********************************************************************** ;70483;
; 13Jul93 - John Hare, Fulkgl                                           ;71139;
; Ioctl calls 4400 should return the value in bits in DX to DOSKRNL.    ;71139;
;********************************************************************** ;71139;
; 05Aug1993 - ChangeTeam                                                ;72108;
; Ioctl calls 440E not supported for CD Rom in order to maintain        ;72108;
; compatibility with DOS - return error 01 in AX.                       ;72108;
;                                                                       ;72108;
; Also some calls to demCDRom were preceeded by:                        ;CT001;
;    dec    al                                                          ;CT001;
;    .if    b                                                           ;CT001;
;       move al,ss:[LCurDrv]                                            ;CT001;
;       ...                                                             ;CT001;
; But, '.if b' is translated to 'jnc' and the dec instruction does not  ;CT001;
;    change the carry flag so the move instruction is never executed    ;CT001;
;    (or is executed based on the wrong conditions).  Therefore, the    ;CT001;
;    '.if b's were all changed to '.if s's (jns).                       ;CT001;
;********************************************************************** ;75871;
; 15Nov1993 - Catherine E. Bundy                                        ;75871;
; Saved INT 440b loop count to ptda's loop count in order to support    ;75871;
; the user abililty to control retries on lock violations.              ;75871;
;**********************************************************************
; 19Sep1994 - bjn
; Changed segment names for page tuning
;**********************************************************************
; 4 Oct 1994 - Change Team INT 440bH demiocSetRetries                  ;101023;
; enabled a CX value of 0 to be valid (pause between retries).         ;101023;
; VSF_CX value is now also passed to ECX                               ;101023;
;**********************************************************************
;  11/27/95 MLM         Defect 72417                                    ;72417
;  moved from PTDA to TCB: RetryCount, RetryLoop                        ;72417
;***********************************************************************;72417
INCL_DEF        equ     1                       ; include typedef macros

.xlist
include dosseg.inc
.xcref
include fnomvdm.inc
include basemaca.inc
include osmaca.inc
include dossymc.inc
include kmode.inc
include mi.inc
include bpb.inc
include devsym.inc
include ioctl.inc
include dskioctl.inc
include curdir.inc
include error.inc
include sft.inc
include tkexport.inc
include struc30.inc
include dem.inc                                                         ;BN006;
include mft.inc                                                         ;64247;
.cref
.list
        ModName  demfioc2, FNO_DEMIOC2_ASM

        CpuMode 386

        ReferTask   LCurDrv,BYTE                                        ;51637;
                                                                        ;72417;
        ReferTask   CurrTCB,WORD                                        ;155310
;       ReferTask   ptda_pCDS,WORD
        ReferGlobal ErrMap24,BYTE
        EXTRN16     GetHandleInfo
        EXTRN16     GetDriveInfo
        EXTRN16     AllocReqPacketWait
        EXTRN16     DevIOCall2
        EXTRN16     FreeReqPacket
        EXTRN16     w_16DevIOCtl

DefCode IMPORT, SWAP
DefFn   demMapSeg
DefFn   demMapSegX                                                      ;BN007;
DefFn   demMapSegFixup                                                  ;BN006;
DefFn   demMapDSDX
DefFn   demMapDS
DefFn   demMapES
DefFn   demMapSegLenCX
EndCode

        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL
SWAP32_22 segment
;***LP  demIOCTL - Perform special device I/O control
;
;       Perform special device I/O control
;
;       ENTRY
;           AL = ioctl Function code
;           Other parameters vary by function: see entry points.
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX, VSF(DX) contains returned data
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CY = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           if invalid function code -->
;               Abort the VDM
;           else -->
;               table jump according to function
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

apfnIOCTL       label   dword
        DD      OFFSET FLAT:demiocGetDevData            ;  0
        DD      OFFSET FLAT:demiocSetDevData            ;  1
        DD      OFFSET FLAT:demiocReadHandle            ;  2
        DD      OFFSET FLAT:demiocWriteHandle           ;  3
        DD      OFFSET FLAT:demiocReadBlock             ;  4
        DD      OFFSET FLAT:demiocWriteBlock            ;  5
        DD      OFFSET FLAT:demiocInputStatus           ;  6
        DD      OFFSET FLAT:demiocOutputStatus          ;  7
        DD      OFFSET FLAT:demiocRemovableMedia        ;  8
        DD      OFFSET FLAT:demiocRedirBlock            ;  9
        DD      OFFSET FLAT:demiocRedirHandle           ;  A
        DD      OFFSET FLAT:demiocSetRetries            ;  B
        DD      OFFSET FLAT:demiocGenericHandle         ;  C
        DD      OFFSET FLAT:demiocGenericBlock          ;  D
        DD      OFFSET FLAT:demiocGetLogDrive           ;  E
        DD      OFFSET FLAT:demiocSetLogDrive           ;  F
        DD      OFFSET FLAT:demiocQueryHandle           ; 10
        DD      OFFSET FLAT:demiocQueryBlock            ; 11
cpfnIOCTL       equ     ($ - apfnIOCTL) / 4
        DD      OFFSET FLAT:demiocInvalidFunction       ;>11

        align   4

Procedure demIOCTL
LocalVar dummycds,<SIZE curdir>
        EnterProc
        push    ax
;### PTR B720732   mov  ss:[ptda_pCDS],ax       ; Initialize ptda_pCDS
        push    ebx                             ;### PTR B720732
        mov     ebx,[_pTCBCur]                  ;### PTR B720732
        lea     ax,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,ax       ; Initialize TCBpTmpCDS ;### PTR B720732
        pop     ebx                             ;### PTR B720732
        pop     ax
        .if     <AL ae cpfnIOCTL>
          mov     al,cpfnIOCTL
        .endif
        movzx   eax,al
        call    apfnIOCTL[eax*type apfnIOCTL]
        LeaveProc
        ret
EndProc demIOCTL
SWAP32_22 ENDS

        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demiocInvalidFunction,near,local
Entry   demiocSetDevData                ;4401h
Entry   demiocQueryHandle               ;4410h
Entry   demiocQueryBlock                ;4411h
        mov     ax,ERROR_INVALID_FUNCTION
        stc
        ret
EndProc demiocInvalidFunction

SWAP32_23 segment
;***LP  demiocGetDevData - Get SFT/JFN flags
;
;       Get SFT/JFN flags
;
;       ENTRY
;           VSF(BX)
;               real handle
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = flags
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CY = 1
;           AX = 0FFFFh
;
;       STEPS
;           GetHandleInfo
;           return results
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           GetHandleInfo
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocGetDevData,near,local   ;int 21h/ax=4400h
        movzx   ebx,[ebx].vsf_bx
        CALL16  GetHandleInfo
        ;return CY(AX=error #)
        ;  else NC, no error
        ;       AL=unit number
        ;       DX=SFT Flags
        ;       ZF=pipe or network device  (DS:SI=NULL)
        ;       NZ=not pipe nor network    (DS:SI=&DD hdr)
        ASSUME  ES:NOTHING,DS:NOTHING
        .if     nc                      ;CY=handle is in error
          xchg    al,dl                                                 ;57908;
          ;AL=low 8 bits of SFT flags                                   ;57908;
          ;DL=unit number                                               ;57908;
          xor     ah,ah                 ;AH=0 for named pipes and net   ;57908;
          mov     bx,ds                                                 ;57908;
          or      bx,si                                                 ;57908;
          .if     nz                                                    ;57908;
            ;---file                                                    ;57908;
            .if     <BIT al and DEVID_DEVICE>                           ;71139;
              ;---os2 device driver
              mov     ah,byte ptr ds:[si].SDevAtt+1
            .else
              and   al,2fh     ; bit 0-5 zero out                       ;71139;
              or    al,dl      ; add in bit for drive letter of file    ;71139;
            .endif
          .endif
        .endif
        ret

        assume   ES:NOTHING,DS:NOTHING
Entry   demiocErrorExit
        stc
        ret
EndProc   demiocGetDevData
SWAP32_23 ENDS

;***LP  demiocInputStatus - Perform old ioctl handle input status       ;BN004;
;***LP  demiocOutputStatus - Perform old ioctl handle output status     ;BN004;

Procedure demiocInputStatus,near,local  ;4406h

Entry   demiocOutputStatus,near,local   ;4407h

        mov     cl,al
        push    ebx
        movzx   ebx,[ebx].vsf_bx                ; get the handle
        CALL16  GetHandleInfo
        ;return CY(AX=error #)
        ;  else NC, no error
        ;       AL=unit number
        ;       DX=SFT Flags
        ;       ZF=pipe or network device  (DS:SI=NULL)
        ;       NZ=not pipe nor network    (DS:SI=&DD hdr)
        ASSUME   DS:NOTHING,ES:NOTHING
        pop     ebx
        jc      bad_GetHandleInfo         ; exit on error
        mov     ax,ds
        or      ax,si
        jz      invalid_handle
        test    ds:[si].SDevAtt,DEV_CHAR_DEV    ; is this a character device?
        jz      demiocInvalidFunction           ; skip if OK

        CALL16  AllocReqPacketWait              ; (ES:BX) = tiled request packet
        ASSUME   ES:NOTHING

        .if     <CL eq 6>
          mov     es:[bx].PktCmd,CMDInputS
        .else
          mov     es:[bx].PktCmd,CMDOutputS
        .endif
        mov     es:[bx].PktLen,PktHeadSize
        xor     eax,eax
        mov     es:[bx].PktUnit,al              ; (AL) = unit number
        mov     es:[bx].PktStatus,ax
        CALL16  DevIOCall2
        mov     di,es:[bx].PktStatus            ; (DI) = packet status
        CALL16  FreeReqPacket
        test    di,STERR                        ; check for error from device
        jnz     demiocMapErr
        not     di
        .if     <di and STBUI>                                          ;BN011;
          mov     al,-1                                                 ;BN011;
        .endif                                                          ;BN011;
;BD011; test    di,STBUI
;Exit with AL=00h ZF=not ready (busy)
;      and AL=FFh NZ=ready
        ret

EndProc demiocInputStatus

        page

;***LP  demiocReadHandle - Perform old ioctl read handle
;***LP  demiocWriteHandle - Perform old ioctl write handle
;***LP  demiocReadWriteHandle - Perform old ioctl read/write handle
;***LP  demiocReadBlock - Perform old ioctl read block
;***LP  demiocWriteBlock - Perform old ioctl write block
;***LP  demiocReadWriteBlock - Perform old ioctl read/write block
;***LP  demiocReadWrite - Perform old ioctl read/write
;
;       Perform old ioctl read/write
;
;       ENTRY
;           VSF(BX)
;               real handle or (BL) drive code (0=default)
;           VSF(DS:DX)
;               address of data
;           VSF(CX)
;               size of buffer
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = count
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           GetHandleInfo
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES, FS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocReadHandle,near,local
        mov     ch,CMDIOCTLR            ; (CH) = ioctl read command
        jmp     short demiocReadWriteHandle
                                                                        ;BN004;
Entry   demiocWriteHandle,near,local
        mov     ch,CMDIOCTLW            ; (CH) = ioctl write command

Entry   demiocReadWriteHandle,near,local
        push    ebx
        movzx   ebx,[ebx].vsf_bx                ; get the handle
        CALL16  GetHandleInfo
        ;return CY(AX=error #)
        ;  else NC, no error
        ;       AL=unit number
        ;       DX=SFT Flags
        ;       ZF=pipe or network device  (DS:SI=NULL)
        ;       NZ=not pipe nor network    (DS:SI=&DD hdr)
        ASSUME   DS:NOTHING,ES:NOTHING
        pop     ebx
        jc      short bad_GetHandleInfo         ; exit on error
        mov     cl,al
        mov     ax,ds
        or      ax,si
        .if     z                               ; skip if no local device
invalid_handle:
          mov     ax,ERROR_INVALID_HANDLE
bad_GetHandleInfo:
          stc
          ret
        .endif
        mov     ax,cx
        test    ds:[si].SDevAtt,DEV_CHAR_DEV    ; is this a character device?
        jnz     short demiocReadWrite           ; skip if OK
        jmp     demiocInvalidFunction

Entry   demiocReadBlock,near,local
        ASSUME  ds:FLAT,es:FLAT
        mov     cl,CMDIOCTLR
        jmp     short demiocReadWriteBlock
TUNESWP5:  jmp demiocErrorExit
Entry   demiocWriteBlock,near,local
        ASSUME  ds:FLAT,es:FLAT
        mov     cl,CMDIOCTLW

Entry   demiocReadWriteBlock,near,local
        assume  ds:FLAT,ES:FLAT
        call    demGetDriveInfo
        assume  ds:nothing,es:nothing
        jc      TUNESWP5 ; demiocErrorExit
        test    ah,CD_ISNET             ; if the network drive, return error
        jnz     demiocInvalidFunction
        mov     ah,cl

Entry   demiocReadWrite,near,local

;       (AL) = unit number (0 for character devices)
;       (AH) = request packet command
;       (DS:SI) = device header
;       VSF(CX) = count
;       VSF(DS:DX) = address for data
;       EBX points to VSF

        test    ds:[si].SDevAtt,DEV_IOCTL       ; is this ioctl supported? ;BC009
        jz      demiocInvalidFunction           ; exit if not              ;BC009

        FlatContext <es>,ecx
        movzx   ecx,es:[ebx].vsf_cx             ; cx has count
        movzx   edx,es:[ebx].vsf_dx

        push    eax
        movzx   eax,es:[ebx].vsf_ds             ;BC009 need to use ES
        push    ds                              ;BN009 save DS
        push    es                              ;BN009 move ES to DS
        pop     ds                              ;BN009
        call    demMapSeg
        pop     ds                              ;BN009 restore DS
        shl     eax,16
        or      edx,eax                         ; (EDX) = seg:offset of data
        pop     eax

        CALL16  AllocReqPacketWait              ; (ES:BX) = tiled request packet
        assume  es:nothing
        mov     es:[bx].PktCmd,ah
        mov     es:[bx].PktLen,LENIO+PktHeadSize
        mov     es:[bx].PktUnit,al              ; (AL) = unit number
        xor     eax,eax
        mov     es:[bx].PktStatus,ax
        mov     es:[bx].IOmedia,al
        mov     es:[bx].IOcount,cx
        mov     es:[bx].IOpData,edx
        CALL16  DevIOCall2
        mov     di,es:[bx].PktStatus            ; (DI) = packet status
        mov     ax,es:[bx].IOcount              ; (AX) = actual bytes xfered
        CALL16  FreeReqPacket
        test    di,STERR                        ; check for error from device
        jnz     short demiocMapErr
        ret

Entry   demiocMapErr,near,local
        assume  ds:nothing,es:nothing
        and     di,STECODE                      ; get relevant bits
        DosContext <ds>
        mov     al,ErrMap24[di]                 ; (AL) = dos error code
        stc
        ret
EndProc demiocReadHandle

SWAP32_25 segment
;***LP  demiocRemovableMedia - Get removable media information
;
;       Get removable media information
;
;       ENTRY
;           VSF(BL)
;               drive code (0=default)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX
;                   0 = removable
;                   1 = fixed
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demGetDriveInfo
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES, FS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocRemovableMedia,near,local
        call    demGetDriveInfo
        assume  ds:nothing,es:nothing
        .if     c                                                       ;60024;
          cmp     AX,ERROR_NOT_SUPPORTED   ;=50                         ;60024;
          jne     TUNESWP4 ; demiocErrorExit                                       ;60024;
          jmp     demiocInvalidFunction    ;=1                          ;60024;
TUNESWP4:  jmp  demiocErrorExit
        .endif                                                          ;60024;
        test    ah,CD_ISNET             ; if the network drive, return error
        jnz     TUNBG

; NOTE: We assume in OS/2 that all block devices support the removable
;       media call.

        push    ebx                                                     ;51637;
        CALL16  AllocReqPacketWait      ; (ES:BX) = request packet
        mov     es:[bx].PktCmd,CMDRemMed
        mov     es:[bx].PktLen,LENRemMed+PktHeadSize
        mov     es:[bx].PktUnit,al      ; (AL) = unit number
        mov     es:[bx].PktStatus,0
        CALL16  DevIOCall2
        mov     ax,es:[bx].PktStatus    ; get Status word
        and     ax,STBUI                ; mask to busy bit
        shr     ax,9                    ; busy bit to bit 0
        CALL16  FreeReqPacket
        pop     ebx                                                     ;51637;
                                                                        ;51637;
        or      ax,ax                                                   ;51637;
        .if     z                                                       ;51637;
          FlatContext <ds>,eax                                          ;51637;
          assume  ds:FLAT                                               ;51637;
          mov     al,[ebx].vsf_bl                                       ;51637;
          dec     al                                                    ;51637;
          .if     s                                               ;51637;ct001;
            mov     al,ss:[LCurDrv]                               ;51637;
          .endif                                                        ;51637;
          call    demCDRom              ;CY set for CD-Roms             ;51637;
          ;returns: ZF=CD-Rom                                           ;51637;
          ;         NZ=not CD (ie. diskette)                            ;51637;
          jz     TUNBG   ;  demiocInvalidFunction    ;=1                          ;51637;
          xor     eax,eax                                               ;51637;
        .endif                                                          ;51637;
        ret
TUNBG:  jmp demiocInvalidFunction
EndProc demiocRemovableMedia
SWAP32_25 ends

SWAP32_25 segment
;***LP  demCDRom - determine if a drive is a CD-Rom                     ;51637;
;                                                                       ;51637;
;       ENTRY                                                           ;51637;
;           AL                                                          ;51637;
;               Drive number (A=0, B=1, C=2, ...)                       ;51637;
;                                                                       ;51637;
;       EXIT                                                            ;51637;
;           NZ                                                          ;51637;
;               Not a CD-Rom                                            ;51637;
;           ZF                                                          ;51637;
;               Yes, it is a CD-Rom                                     ;51637;
;                                                                       ;51637;
;       CONTEXT                                                         ;51637;
;           Called from Kernel                                          ;51637;
;                                                                       ;51637;
;       STEPS                                                           ;51637;
;           use DDD ioctl call                                          ;51637;
;                                                                       ;51637;
;       CALLS                                                           ;51637;
;                                                                       ;51637;
;       USES                                                            ;51637;
;           EAX,EBX,ECX,EDX,ESI,EDI                                     ;51637;
;                                                                       ;51637;
ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING                ;51637;
align  4                                                                ;51637;
                                                                        ;51637;
Procedure demCDRom,near                                                 ;51637;
LocalVar  dcd_ParmPacket,WORD                                           ;51637;
LocalVar  dcd_DataPacket,<36>                                           ;51637;
        EnterProc                                                       ;51637;
                                                                        ;51637;
        push    es                                                      ;51637;
        push    ds                                                      ;51637;
                                                                        ;51637;
        shl     eax,8                   ;AL=command=0 AH=drive          ;51637;
        mov     dcd_ParmPacket,ax                                       ;51637;
                                                                        ;51637;
        mov     eax,6308h                                               ;51637;
        mov     ebx,-1                                                  ;51637;
        mov     ecx,2                                                   ;51637;
        mov     esi,36                                                  ;51637;
        push    ss                                                      ;51637;
        pop     ds                                                      ;51637;
        assume  ds:nothing                                              ;51637;
        push    ss                                                      ;51637;
        pop     es                                                      ;51637;
        assume  es:nothing                                              ;51637;
        lea     di,dcd_ParmPacket                                       ;51637;
        lea     dx,dcd_DataPacket                                       ;51637;
        ;entry: AL=category (8)                                         ;51637;
        ;       AH=function (63h)                                       ;51637;
        ;       BX=handle (-1)                                          ;51637;
        ;       ES:DI=parm packet                                       ;51637;
        ;       CX=length of parm packet (2)                            ;51637;
        ;       DS:DX=data packet                                       ;51637;
        ;       SI=length of data packet                                ;51637;
        CALL16  w_16DevIOCtl            ;filesys\devioctl.asm           ;51637;
        ;exit:  CY=error, NC=success                                    ;51637;
        ;       uses ax,bx,cx,dx,di,si,ds,es                            ;51637;
        .if     c                       ;default to no CDRom if error   ;51637;
          mov     byte ptr dcd_DataPacket+33,0                          ;51637;
        .endif                                                          ;51637;
        .if     <<byte ptr dcd_DataPacket+33> eq 7> and                 ;51637;
        .if     <<dcd_DataPacket.BPB_BytesPerSector> eq 2048>           ;51637;
          cmp     dcd_DataPacket.BPB_SectorsPerTrack,-1                 ;51637;
        .endif                                                          ;51637;
                                                                        ;51637;
        pop     ds                                                      ;51637;
        pop     es                                                      ;51637;
                                                                        ;51637;
        LeaveProc                                                       ;51637;
        ret                                                             ;51637;
EndProc demCDRom                                                        ;51637;
SWAP32_25 ends
                                                                        ;51637;
SWAP32_25 segment
;***LP  demiocRedirBlock - Get redirection information
;
;       Get redirection information
;
;       ENTRY
;           VSF(BL)
;               drive code (0=default)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               VSF(DX) = device attribute word
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demGetDriveInfo
;
;       USES
;           EAX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocRedirBlock,near,local
        call    demGetDriveInfo
        assume  ds:nothing,es:nothing
        jc    TUNESWP3 ;    demiocErrorExit

;       (AL) = unit number
;       (AH) = CDS flags (cd_flags)
;       (DX) = device attribute word
;       (DS:SI) = device driver header addr (if not network)
;       (EBX) = pvsf

                                                                        ;64247;
        mov     dx,ds:[si].SDevAtt                                      ;64247;
        FlatContext <ds>,esi                                            ;64247;
        assume  ds:FLAT                                                 ;64247;
                                                                        ;64247;
        .if     <BIT ah nand CD_ISNET>                                  ;64247;
                                                                        ;64247;
          ;------ Is this a CD-Rom, if so, fake it to be a network      ;64247;
          push    eax                                                   ;64247;
          push    ebx                                                   ;64247;
          push    edx                                                   ;64247;
          mov     al,[ebx].vsf_bl                                       ;64247;
          dec     al                                                    ;64247;
          .if     s                                               ;64247;CT001;
            mov     al,ss:[LCurDrv]                                     ;64247;
          .endif                                                        ;64247;
          call    demCDRom              ;ZR set for CD-Roms             ;64247;
          ;returns: ZF=CD-Rom                                           ;64247;
          ;         NZ=not CD (ie. diskette)                            ;64247;
          pop     edx                                                   ;64247;
          pop     ebx                                                   ;64247;
          pop     eax                                                   ;64247;
          jz      short CDRom_4409                                      ;64247;
        .else                                                           ;64247;
CDRom_4409:                                                             ;64247;
          mov     dx,1000h                ; set remote bit              ;64247;
        .endif                                                          ;64247;
                                                                        ;64247;
        .if     <BIT ah and CD_LOCAL>                                   ;64247;
          or      dx,8000h              ; set redirected bit            ;64247;
        .endif                                                          ;64247;
                                                                        ;64247;
;64247; mov     dx,1000h                ; set remote bit
;64247; test    ah,CD_ISNET
;64247; jnz     short irb1
;64247; mov     dx,ds:[si].SDevAtt
;64247; irb1:   test    ah,CD_LOCAL
;64247; jz      short irb2
;64247; or      dx,8000h                ; set redirected bit
;64247; irb2:   FlatContext <ds>,ecx
        mov     [ebx].vsf_dx,dx
        ret
TUNESWP3: jmp  demiocErrorExit
EndProc demiocRedirBlock
SWAP32_25 ends

;***LP  demiocRedirHandle - Get redirection information
;
;       Get redirection information
;
;       ENTRY
;           VSF(BL)
;               drive code (0=default)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = device attribute word
;           FAILURE
;               CY = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CY = 1
;           AX = 0FFFFh
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           GetHandleInfo
;
;       USES
;           EAX, ECX, EDX, ESI, EDI, DS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocRedirHandle,near,local
        push    ebx
        movzx   ebx,[ebx].vsf_bx
        CALL16  GetHandleInfo
        ;return CY(AX=error #)
        ;  else NC, no error
        ;       AL=unit number
        ;       DX=SFT Flags
        ;       ZF=pipe or network device  (DS:SI=NULL)
        ;       NZ=not pipe nor network    (DS:SI=&DD hdr)
        pop     ebx
        jc      TUNESWP2 ; demiocErrorExit
        .if     nz                      ;only if real device            ;64247;
          mov     eax,es:[di].sf_MFT                                    ;64247;
          FlatContext <ds>,ecx                                          ;64247;
          mov     eax,dword ptr ds:[eax].mft_name                       ;64247;
          .if     <AH eq ":">                                           ;64247;
            push    ebx                                                 ;64247;
            push    edx                                                 ;64247;
            or      al,'a'-'A'                                          ;64247;
            sub     al,'a'                                              ;64247;
            call    demCDRom              ;ZR set for CD-Roms           ;64247;
            ;returns: ZF=CD-Rom                                         ;64247;
            ;         NZ=not CD (ie. diskette)                          ;64247;
            pop     edx                                                 ;64247;
            pop     ebx                                                 ;64247;
            .if     z                   ;if CD-Rom force on network bit ;64247;
              and     edx,8000h                                         ;64247;
            .endif                                                      ;64247;
          .endif                                                        ;64247;
        .endif                                                          ;64247;
        FlatContext <ds>,ecx
;70483; mov     [ebx].vsf_dx,dx                                         ;70483;
        mov     eax,edx                                                 ;70483;
        clc                                                             ;70483;
        ret
TUNESWP2: jmp demiocErrorExit
EndProc demiocRedirHandle

;***LP  demiocSetRetries - Set Redirector Retry Count
;
;       Set Redirector Retry Count
;
;       ENTRY
;           VSF(DX)
;               new retry count (!= 0)
;           VSF(CX)
;               CX=0 is a valid delay between retries    ;101023
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAILURE
;               CY = 1
;               AX = error code
;
;       STEPS
;           validate count
;           store into RetryCount
;           validate retry delay loop count     ;75871;
;           store into RetryLoop                ;75871;
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           None
;
;       USES
;           EAX, EDX, ESI
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,GS:NOTHING,FS:NOTHING
        align   4
Procedure demiocSetRetries,near,local
        movzx   edx,[ebx].vsf_dx
        or      dx,dx                   ; zero retries not allowed
        jz      demiocInvalidFunction
        movzx  ecx,[ebx].vsf_cx                                ;101023
;       defect 101023 cx=0 is now a valid option               ;101023
;       or      cx,cx ;ceb 75871 zero retry loops not allowed  ;101023
;       jz      demiocInvalidFunction   ; ceb 75871            ;101023
                                        ;72417 moved from PTDA to TCB

dof10:  push    bp                       ; 155310 set BP to TKOPTDA
        mov     bp,ss:[CurrTCB]          ; 155310
        mov     ss:[bp].TCBRetryCount,dx
        mov     ss:[bp].TCBRetryLoop,cx ; ceb 75871
        pop     bp                      ; 155310
                                        ;72417 end
        ret
EndProc demiocSetRetries

;***LP  demiocGenericHandle - Perform Generic ioctl I/O by handle
;
;       Perform Generic ioctl I/O
;
;       ENTRY
;           VSF(BX)
;               handle
;           VSF(CH)
;               category indicator
;           VSF(CL)
;               function within category
;           VSF(DS:DX)
;               address of data packet (arbitrary size)
;           VSF(SI:DI)
;               address of parm packet (arbitrary size)
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAILURE
;               CY = 1
;               AX = error code
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           BUGBUG - as it turns out, SI is trashed by DOS 3.x &
;           4.x in this call, and is replaced with the contents
;           of DS.  For OS/2 1.2 compatibility, we treat SI as a
;           segment and convert it to a selector.  As long as DS
;           and SI are the same, this is OK, but be warned.
;
;           Inorder to fix 5.25 extern drive problem, we need to      BN012
;           downsize the parm packet segment length. We have to       BN012
;           assume a reasonable size for this so let's choose 1k.     BN012
;           Note: I tried to think of an elegant solution to prevent  BN012
;           all cases of segment overlap, but had no luck with        BN012
;           dynamically sizing both segments or altering the          BN012
;           segment of one packet to match the other packet segment.  BN012
;           An alternative to this fix may be to move the parm packet BN012
;           to the stack so that it is sufficiently separated from    BN012
;           the data packet. (also messy)                             BN012
;
;       CALLS
;           w_16DevIOCtl
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocGenericHandle,near,local

;BD012        movzx   eax,[ebx].vsf_si
;BD012        or      ax,ax
;BD012        .if     nz
;BD012          call    demMapSeg
;BD012        .endif
;BD012        mov     es,eax
;BD012        assume  es:nothing

;START BN012

        movzx   eax,[ebx].vsf_si
        or      eax,eax
        jz      short null_sidi        ; if null skip over rest
        cmp     ax,[ebx].vsf_ds        ; if ES = DS then use one selector ;BN013
        je      short same_ds_es       ;BN013

        movzx   ecx,[ebx].vsf_di
        add     ecx,1024
        .if     <ecx gt 0ffffh>        ; if ES seg length is greater than 64k
          xor      ecx,ecx
          mov      cx,0ffffh           ; make size 64k
        .endif
        call    demMapSegLenCX
null_sidi:
        mov     es,ax

same_ds_es:                            ;BN013
        movzx   eax,[ebx].vsf_ds
        or      eax,eax                ; if DS = 0
        .if     nz short               ; then we treat it as a NULL ptr
          mov     edx,ISELDEMDS
          call    demMapSegX
        .endif
        mov     ecx,eax                ; save DS value for later
;END BN012

        movzx   eax,[ebx].vsf_si       ;BN013
        cmp     ax,[ebx].vsf_ds        ; if ES=DS then setup ES with DS sel ;BN013
        jne     short @F               ;BN014
        mov     es,cx                  ;BN013

@@:     movzx   edi,[ebx].vsf_di       ;BN014
        movzx   eax,[ebx].vsf_cx
        xchg    ah,al                   ; (AL) = category, (AH) = function
        movzx   edx,[ebx].vsf_dx                                        ;BN012
        movzx   ebx,[ebx].vsf_bx        ;setup ebx                      ;BC012
        mov     ds,cx                   ;move mapped DS value into DS   ;BN012


;BD007; call    demMapDSDX                                              ;BD007;
;BD012; movzx   edx,[ebx].vsf_dx                                        ;BN007;
;BD012; push    eax                                                     ;BN007;
;BD012; push    ecx                                                     ;BN007;
;BD012; push    edx                                                     ;BN007;
;BD012; movzx   eax,[ebx].vsf_ds        ; (EAX) = ds segment            ;BN007;
;BD012; or      edx,eax                 ; if DS:DX=0:0                  ;BN007;
;BD012; .if     nz short                ; then we treat it as a NULL ptr;BN007;
;BD012;   mov     edx,ISELDEMDS                                         ;BN007;
;BD012;   call    demMapSegX                                            ;BN007;
;BD012; .endif                                                          ;BN007;
;BD012; mov     ds,eax                                                  ;BN007;
;BD012; pop     edx                                                     ;BN007;
;BD012; pop     ecx                                                     ;BN007;
;BD012; pop     eax                                                     ;BN007;

        assume  ds:nothing
        xor     ecx,ecx                 ; Unknow length of parameter packet
        mov     esi,ecx                 ; Unknow length of data packet
        CALL16  w_16DevIOCtl
        ret
EndProc demiocGenericHandle

;***LP  demiocGenericBlock - Perform Generic ioctl I/O by Drive
;
;       Perform Generic ioctl I/O
;
;       ENTRY
;           VSF(BX)
;               Drive or (BL) drive code (0=default)
;           VSF(CH)
;               category indicator
;           VSF(CL)
;               function within category
;           VSF(DS:DX)
;               address of data packet (arbitrary size)
;           VSF(SI)
;               arbitrary argument
;           VSF(DI)
;               arbitrary argument
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAILURE
;               CY = 1
;               AX = error code
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           BUGBUG - as it turns out, SI is trashed by DOS 3.x &
;           4.x in this call, and is replaced with the contents
;           of DS.  For OS/2 1.2 compatibility, we treat SI as a
;           segment and convert it to a selector.  As long as DS
;           and SI are the same, this is OK, but be warned.
;
;       CALLS
;           w_16DevIOCtl
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocGenericBlock,near,local

LocalVar  dgb_reqpkt,<PktHeadSize + LENGenIOCTL2>

        EnterProc
        movzx   ecx,[ebx].vsf_cx        ;(CL)= function, (CH)= category
        movzx   eax,[ebx].vsf_si

        or      ax,ax
        .if     nz
          ;The parameter packet is in the address EAX:EDI.              ;BN006;
          ;Use "demMapSegFixup" instead of "demMapSeg" so that it can   ;BN006;
          ;normalize the segment:offset value is the case of seg=FFFFh. ;BN006;
;         call    demMapSeg                                             ;BD006;
          movzx   edi,[ebx].vsf_di                                      ;BN006;
          xor     edx,edx                                               ;BN006;
          .errnz  ISELDEMTEMP                                           ;BN006;
          call    demMapSegFixup                                        ;BN006;
        .endif
        mov     esi,eax                 ; (SI:DI) = parameter packet address

;BD006; mov     edi,[ebx].vsf_edi       ; (SI:DI) = parameter packet address
;BD006; call    demMapDSDX              ; (DS:DX) = data packet address
        ;The data packet needs the same fixup routine.  In the case of  ;BN006;
        ;seg=FFFFh, we want to normalize the segment:offset value.      ;BN006;
        push    eax                                                     ;BN006;
        push    edi                                                     ;BN006;
        movzx   eax,[ebx].vsf_ds                                        ;BN006;
        movzx   edi,[ebx].vsf_dx                                        ;BN006;
        mov     edx,ISELDEMDS                                           ;BN006;
        call    demMapSegFixup                                          ;BN006;
        mov     ds,eax                                                  ;BN006;
        mov     dx,di                   ; (DS:DX) = data packet address ;BN006;
        pop     edi                                                     ;BN006;
        pop     eax                                                     ;BN006;
        ASSUME  DS:NOTHING

;       Set up generic IOCTL request block

        mov     [dgb_reqpkt].PktStatus,0
        mov     [dgb_reqpkt].PktCmd,CMDGenIOCTL
        mov     [dgb_reqpkt].PktLen,(PktHeadSize + LENGenIOCTL2)

        mov     [dgb_reqpkt].GIOFunction,cl
        mov     [dgb_reqpkt].GIOCategory,ch
        mov     [dgb_reqpkt].GIODataPack.Segmt,ds
        mov     [dgb_reqpkt].GIODataPack.Offst,dx
        mov     [dgb_reqpkt].GIODataLen,0
        mov     [dgb_reqpkt].GIOParaPack.Segmt,si
        mov     [dgb_reqpkt].GIOParaPack.Offst,di
        mov     [dgb_reqpkt].GIOParaLen,0

        FlatContext <ds>,eax
        call    demGetDriveInfo
        ASSUME  DS:NOTHING,ES:NOTHING
        jc      short dgb20
        test    ah,CD_ISNET             ; if the network drive, return error
        jnz     demiocInvalidFunction
        mov     [dgb_reqpkt].PktUnit,al

        mov     ax,ss
        mov     es,ax
        lea     bx,[dgb_reqpkt]         ; (ES:BX) = request packet address

;       (ES:BX) = request packet address
;       (DS:SI) = device driver address

        CALL16  DevIOCall2
        mov     di,es:[bx].PktStatus    ; (DI) = packet status
        LeaveProc
        test    di,STERR                ; check for error from device
        jnz     demiocMapErr
        ret

dgb20:  LeaveProc NoCheck
        jmp     demiocErrorExit

EndProc demiocGenericBlock

SWAP32_25 segment
;***LP  demiocGetLogDrive - Get Logical Drive Mapping
;***LP  demiocSetLogDrive - Set Logical Drive Mapping
;***LP  demiocLogDrive - Get/Set Logical Drive Mapping
;
;       Get/Set Logical Drive Mapping
;
;       ENTRY
;           VSF(BL)
;               Drive code (0=default)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AL = mapping code
;           FAILURE
;               CY = 1
;               AX = error code
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX, EBX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demiocGetLogDrive,near,local
        mov     cl,CMDGetLogMap
        jmp     short demiocLogDrive
TUNESWP1: jmp     demiocErrorExit
TUNBG2:   jmp demiocInvalidFunction
Entry   demiocSetLogDrive
        mov     cl,CMDSetLogMap

Entry   demiocLogDrive
        call    demGetDriveInfo
        assume  ds:nothing,es:nothing
        jc     TUNESWP1;  demiocErrorExit
        test    ah,CD_ISNET             ; if the network drive, return error
        jnz   TUNBG2

        push    eax                  ;push registers used, but not saved;72108;
        push    ebx                  ;   by demCDRom                    ;72108;
        push    ecx                                                     ;72108;
        push    edx                                                     ;72108;
        push    esi                                                     ;72108;
        push    edi                                                     ;72108;
                                                                        ;72108;
        push    ds                                                      ;72108;
        FlatContext <ds>,eax                                            ;72108;
        assume  ds:FLAT                                                 ;72108;
                                                                        ;72108;
        mov     al,[ebx].vsf_bl                                         ;72108;
        dec     al                   ;dec because demCDRom expects drive;72108;
                                     ;   designator to be zero relative ;72108;
                                     ;   (i.e. A=0, B=1, ...)           ;72108;
        .if     s                    ;before dec, al is 00 for dflt drv ;72108;
           mov     al,ss:[LCurDrv]   ;Set to default drive          ;72108;
                                     ;   SS points to current PTDA      ;72108;
        .endif                                                          ;72108;
        call    demCDRom             ; check if CD-Rom Drive            ;72108;
                                     ;    returns: ZF=CD-Rom            ;72108;
                                     ;             NZ=not CD (ie. disk) ;72108;
        pop     ds                                                      ;72108;
        pop     edi                                                     ;72108;
        pop     esi                                                     ;72108;
        pop     edx                                                     ;72108;
        pop     ecx                                                     ;72108;
        pop     ebx                                                     ;72108;
        pop     eax                                                     ;72108;
        assume  ds:nothing                                              ;72108;
        jz    TUNBG2  ;demiocInvalidFunction  ;function invalid for CD ROM ->   ;72108;
                                      ;to maintain DOS compatibility    ;72108;
        CALL16  AllocReqPacketWait      ; (ES:BX) = tiled request packet
        mov     es:[bx].PktCmd,cl
        mov     es:[bx].PktUnit,al      ; unit number
        mov     es:[bx].PktLen,LenGetSetLog+PktHeadSize
        mov     es:[bx].PktStatus,0
        CALL16  DevIOCall2
        mov     di,es:[bx].PktStatus    ; (DI) = packet status
        mov     al,es:[bx].PktUnit      ; (AL) = owner returned by device
        CALL16  FreeReqPacket
        test    di,STERR                ; check for error from device
        jnz   TUNBG3
        ret
TUNBG3:  jmp   demiocMapErr
EndProc demiocGetLogDrive
SWAP32_25 ends

SWAP32_25 segment
;***LP  demGetDriveInfo - Get Drive Info
;
;       call GetDriveInfo for the V86 kernel
;
;       ENTRY
;           VSF(BL)
;               Drive code (0=default)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AH = CDS Flags
;               AL = unit number
;               DS:SI = device header
;           FAILURE
;               CY = 1
;               AX = error code
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           GetDriveInfo
;
;       USES
;           EAX, ECX, EDX, ESI, EDI, DS, ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demGetDriveInfo
LocalVar dummycds,<SIZE curdir>    ;BN001; create temp work area as CDS
        EnterProc                  ;BN001;
        push    ebx                              ;### PTR B720732
        mov     ebx,[_pTCBCur]                   ;### PTR B720732
        lea     ax,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,ax            ; Initialize TCBpTmpCDS ;### PTR B720732
;### PTR B720732        mov     ss:[ptda_pCDS],ax       ; Initialize ptda_pCDS
        pop     ebx                              ;### PTR B720732
        movzx   eax,[ebx].vsf_bx
        CALL16  GetDriveInfo
        LeaveProc                  ;BN001; cleanup temp var
        ret
EndProc demGetDriveInfo
SWAP32_25 ends

EndCode

        END
