;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/

;/*****************************************************************************
;*
;* SOURCE FILE NAME = FSRTHUNK.ASM
;*
;* DESCRIPTIVE NAME = Thunked fast safe ram semaphore functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/14/92
;*
;* DESCRIPTION  32 bit callable routines to use 16 Fast safe ram semaphores
;*             
;*
;* FUNCTIONS   FSRSemEnter32  
;*             FSRSemLeave32  
;*             FSRSemExit32  
;*             FSRSemCheck32  
;*             T_FSRSEMENTER  
;*             T_FSRSEMLEAVE  
;*             T_FSRSEMCHECK  
;*                           
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/14/92                     File Compiled
;*                                Command Line: thunk -zy fsrsem.mif fsrthunk.asm
;*
;*****************************************************************************/

;/*
;**        Static Name Aliases
;*/

        TITLE        $fsrthunk.asm

        .386
        .MODEL FLAT,SYSCALL

OPTION PROLOGUE:None 
OPTION EPILOGUE:None

EXTERNDEF DOS32FLATDS:ABS
EXTERN   DOS32FLATTOSEL:NEAR

        FSRSemEnter32 PROTO SYSCALL,
                pSem:DWORD
        FSRSemLeave32 PROTO SYSCALL,
                pSem:DWORD
        FSRSemExit32 PROTO SYSCALL,
                pSem:DWORD
        FSRSemCheck32 PROTO SYSCALL,
                pSem:DWORD

        EXTRN        FSRSEMENTER:FAR16
        EXTRN        FSRSEMLEAVE:FAR16
        EXTRN        FSRSEMEXIT:FAR16
        EXTRN        FSRSEMCHECK:FAR16


        ASSUME DS:FLAT,ES:FLAT

.CODE

;/***************************************************************************
;*
;* FUNCTION NAME = FSRSemEnter32
;*
;* DESCRIPTION   = Enter a FSR Semaphore from Flat model.
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4
FSRSemEnter32 PROC SYSCALL,
        pSem:DWORD

        push    ebp
        mov     ebp,esp


        cld                        ;Assume direction flag clear
        xor     eax,eax
        push    eax                ; temp storage for return value
        push    esi
        push    edi
        push    eax                ; temp storage 
        push    eax                ;Error flag for cleanup
        push    eax                ; temp storage for Stack Allocation Flags
        push    eax                ; temp storage for BMP Flags
        push    eax                ; temp storage for Alias Flags
        push    eax                ; temp storage for ptr param #1

;/*
;** Compare stack selector against FLAT:R3DSB
;** If the selector is not equal, then don't bump stack.
;*/

        mov     eax,ss
        cmp     ax,DOS32FLATDS                ;32 bit stack?
        jne     short L1                ; if not, skip bumping code

;/*
;** Bump the stack down if too near 64K boundary.
;*/

        mov     eax,esp
        cmp     ax,256
        jae     short L1
        xor     ax,ax
        mov     esp,eax                ; bump the stack down

;/*
;** Insure that 1 DWORD exists on stack
;*/

        push    eax
L1:

;/*
;** ****> BEGIN Pointer/Structure Section
;*/

        mov     esi,[ebp+8]                ;pSem base address

;/*
;** Pointer pSem --> pSem
;*/

        or      esi,esi
        jz      L2

        mov     [ebp-36],esi

;/*
;** Structures are Identical
;** Structures don't have pointers
;** Treat structure same as buffer
;** Check Boundary Crossing - fixed size item
;*/

        cmp     si,65516
        jbe     L2                        ;Enough room

;/*
;** Allocate space on stack
;*/

        sub     esp,20                        ;Alloc Mem
        and     esp,0FFFFFFFCh                ;DWORD align
        mov     edi,esp                        ;Points to new data area
        mov     [ebp-36],edi

;/*
;**Transfer 20 bytes
;*/

        mov     ecx,5
        rep     movsd

L2:

;/*
;** ****> END Pointer/Structure Section
;*/

;/*
;** Create new call frame, using 16-bit semantics.
;*/

        push    es
        push    ds
        push    ebx
        push    ebp                        ; save ebp
        mov     eax,esp                        ; save current esp
        push    ss
        push    eax


        mov     edx,ss                       ; get cpl bits to use as dpl bits
        and     edx,3                        ; mask off rest of register

        or      dl,4                         ;Force LDT bit on


;/*
;** From Name: pSem  Type: struct FSRS
;*/

        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L5                     ;NULL pointer

        call    DOS32FLATTOSEL               ;Convert in packed region

L5:        
        push    ax                           ;push near pointer
        shr     eax,16                       ;get seg of pointer into ds
                                             ;for pmwin!!!
        mov     ds,ax

;/*
;** Convert SS:ESP to 16-bit SS:SP.
;*/

        mov     eax,esp                        ; use CRMA on ESP to get SS
        ror     eax,16
        shl     eax,3
        or      al,dl
        mov     ss,eax

;/*
;** Jump to 16-bit segment to issue call (so that 16-bit API can RETF).
;** The following two lines are the same as:
;*/

          jmp   FAR PTR T_FSRSEMENTER
ALIGN 4

;/*
;**  but they trick masm into not generating nops.
;*/

R_FSRSEMENTER::                                ; label defining return jmp location

;/*
;** Restore 32-bit SS:ESP - it is on top of stack.
;*/

        movzx   esp,sp                        ; make sure that esp is correct
        lss     esp,[esp]
        pop     ebp
        pop     ebx
        pop     ds
        pop     es

;/*
;** Convert Return Code
;** USHORT --> ULONG
;*/

        movzx   eax,ax
L6:

;/*
;** Functions contain pointers, save return code
;*/

        mov     [ebp-4],eax                ;Save return code

;/*
;** ****> BEGIN Pointer/Structure Unpack Section
;*/

;/*
;** Undo Pointer pSem --> pSem
;*/

        mov     esi,[ebp-36]                ;pSem temp address
        or      esi,esi
        jz      L7



        mov     edi,[ebp+8]                ;pSem original address

;/*
;**Structures are Identical
;**Structures don't have pointers
;**Structure has output semantics
;**Treat structure same as buffer
;**Types are identical and no imbedded pointers exist
;**This means that we treated the pointer as a buffer
;**If temp address == original address then no work required
;*/

        cmp     esi,edi
        je      L7

;/*
;** Item is fixed size
;*/

        test    BYTE PTR[ebp-20],1         ;Check for errors C
        jnz     L11                        ;No copy if error

;/*
;** Space was allocated on stack
;** Transfer 20 bytes
;*/


        mov     ecx,5
        rep     movsd

L11:                                       ;ErrorLabel C

;/*
;** stack deallocated implicitly
;*/

L7:                                        ;No action required

;/*
;** ****> END Pointer/Structure Unpack Section
;*/

;/*
;** 32-bit return code.
;*/

        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax                ;Pop saved return code
        leave
        ret                                ; Remove parameters

FSRSemEnter32 endp

;/***************************************************************************
;*
;* FUNCTION NAME = FSRSemLeave32
;*
;* DESCRIPTION   = Leave a FSR Semaphore from Flat model.
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4
FSRSemLeave32 PROC SYSCALL,
        pSem:DWORD

        xor     eax,eax

C_FSRSemLeave32::

        push    ebp
        mov     ebp,esp

        push    eax                ;Save call number


        cld                        ;Assume direction flag clear
        xor     eax,eax
        push    eax                ; temp storage for return value
        push    esi
        push    edi
        push    eax                ; temp storage 
        push    eax                ;Error flag for cleanup
        push    eax                ; temp storage for Stack Allocation Flags
        push    eax                ; temp storage for BMP Flags
        push    eax                ; temp storage for Alias Flags
        push    eax                ; temp storage for ptr param #1

;/*
;** Compare stack selector against FLAT:R3DSB
;** If the selector is not equal, then don't bump stack.
;*/

        mov     eax,ss
        cmp     ax,DOS32FLATDS                ;32 bit stack?
        jne     short L13                ; if not, skip bumping code

;/*
;** Bump the stack down if too near 64K boundary.
;*/

        mov     eax,esp
        cmp     ax,256
        jae     short L13
        xor     ax,ax
        mov     esp,eax                ; bump the stack down

;/*
;** Insure that 1 DWORD exists on stack
;*/

        push    eax
L13:

;/*
;** ****> BEGIN Pointer/Structure Section
;*/

        mov     esi,[ebp+8]                ;pSem base address

;/*
;** Pointer pSem --> pSem
;*/

        or        esi,esi
        jz        L14

        mov     [ebp-40],esi

;/*
;** Structures are Identical
;** Structures don't have pointers
;** Treat structure same as buffer
;** Check Boundary Crossing - fixed size item
;*/

        cmp     si,65516
        jbe     L14                        ;Enough room

;/*
;** Allocate space on stack
;*/

        sub     esp,20                     ;Alloc Mem
        and     esp,0FFFFFFFCh             ;DWORD align
        mov     edi,esp                    ;Points to new data area
        mov     [ebp-40],edi

;/*
;** Transfer 20 bytes
;*/

        mov     ecx,5
        rep     movsd

L14:

;/*
;** ****> END Pointer/Structure Section
;*/

;/*
;** Create new call frame, using 16-bit semantics.
;*/

        push    es
        push    ds
        push    ebx
        push    ebp                        ; save ebp
        mov     eax,esp                        ; save current esp
        push    ss
        push    eax


        mov     edx,ss                      ; get cpl bits to use as dpl bits
        and     edx,3                       ; mask off rest of register

        or      dl,4                        ;Force LDT bit on


;/*
;** From Name: pSem  Type: struct FSRS
;*/

        mov     eax,DWORD PTR [ebp-40]
        or      eax,eax
        jz      short L17                    ;NULL pointer

        call    DOS32FLATTOSEL               ;Convert in packed region

L17:        
        push    ax              ;push near pointer
        shr     eax,16          ;get seg of pointer into ds
                                ;for pmwin!!!

;/*
;** Generic Routine: get function number into ecx
;*/

        mov     ecx,[ebp-4]

        mov     ds,ax

;/*
;** Convert SS:ESP to 16-bit SS:SP.
;*/

        mov     eax,esp                        ; use CRMA on ESP to get SS
        ror     eax,16
        shl     eax,3
        or      al,dl
        mov     ss,eax

;/*
;** Jump to 16-bit segment to issue call (so that 16-bit API can RETF).
;** The following two lines are the same as:
;*/

          jmp   FAR PTR T_FSRSEMLEAVE
ALIGN 4

;/*
;**  but they trick masm into not generating nops.
;*/



R_FSRSEMLEAVE::                                ; label defining return jmp location

;/*
;** Restore 32-bit SS:ESP - it is on top of stack.
;*/

        movzx   esp,sp                        ; make sure that esp is correct
        lss     esp,[esp]
        pop     ebp
        pop     ebx
        pop     ds
        pop     es

;/*
;** Convert Return Code  Return type maps directly.
;*/

L18:

;/*
;** Functions contain pointers, save return code
;*/

        mov     [ebp-8],eax                ;Save return code

;/*
;** ****> BEGIN Pointer/Structure Unpack Section
;*/

;/*
;** Undo Pointer pSem --> pSem
;*/

        mov     esi,[ebp-40]                ;pSem temp address
        or      esi,esi
        jz      L19



        mov     edi,[ebp+8]                ;pSem original address

;/*
;** Structures are Identical
;** Structures don't have pointers
;** Structure has output semantics
;** Treat structure same as buffer
;** Types are identical and no imbedded pointers exist
;** This means that we treated the pointer as a buffer
;** If temp address == original address then no work required
;*/

        cmp     esi,edi
        je      L19

;/*
;** Item is fixed size
;*/

        test    BYTE PTR[ebp-24],1                ;Check for errors C
        jnz     L23                        ;No copy if error

;/*
;** Space was allocated on stack, Transfer 20 bytes 
;*/

        mov     ecx,5
        rep     movsd

L23:                        ;ErrorLabel C

;/*
;** stack deallocated implicitly
;*/

L19:                ;No action required

;/*
;** ****> END Pointer/Structure Unpack Section
;*/

;/*
;** 32-bit return code.
;*/

        lea     esp,[ebp-16]
        pop     edi
        pop     esi
        pop     eax                ;Pop saved return code
        leave
        ret                                ; Remove parameters

FSRSemLeave32 endp

;/***************************************************************************
;*
;* FUNCTION NAME = FSRSemExit32
;*
;* DESCRIPTION   = Jumps to C_FSRSemLeave32 after setting EAX to 1
;*                 
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
FSRSemExit32 PROC SYSCALL,
        pSem:DWORD

        push        1
        pop        eax
        jmp        C_FSRSemLeave32
FSRSemExit32 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = FSRSemCheck32
;*
;* DESCRIPTION   = Calls T_FSRSEMCHECK and handles the appropriate thunking.
;*                 
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

ALIGN 4
FSRSemCheck32 PROC SYSCALL,
        pSem:DWORD

        push        ebp
        mov         ebp,esp


        cld                            ;Assume direction flag clear
        xor         eax,eax
        push        eax                ; temp storage for return value
        push        esi
        push        edi
        push        eax                ; temp storage 
        push        eax                ;Error flag for cleanup
        push        eax                ; temp storage for Stack Allocation Flags
        push        eax                ; temp storage for BMP Flags
        push        eax                ; temp storage for Alias Flags
        push        eax                ; temp storage for ptr param #1

;/*
;** Compare stack selector against FLAT:R3DSB
;** If the selector is not equal, then don't bump stack.
;*/

        mov        eax,ss
        cmp        ax,DOS32FLATDS                ;32 bit stack?
        jne        short L26                ; if not, skip bumping code

;/*
;** Bump the stack down if too near 64K boundary.
;*/

        mov        eax,esp
        cmp        ax,1024
        jae        short L26
        xor        ax,ax
        mov        esp,eax                ; bump the stack down

;/*
;** Insure that 1 DWORD exists on stack
;*/

        push        eax
L26:

;/*
;** ****> BEGIN Pointer/Structure Section
;*/

        mov        esi,[ebp+8]                ;pSem base address

;/*
;** Pointer pSem --> pSem
;*/

        or        esi,esi
        jz        L27

        mov        [ebp-36],esi

;/*
;** Structures are Identical
;** Structures don't have pointers
;** Treat structure same as buffer
;** Check Boundary Crossing - fixed size item
;*/

        cmp        si,65516
        jbe        L27                        ;Enough room

;/*
;** Allocate space on stack
;*/

        sub        esp,20                        ;Alloc Mem
        and        esp,0FFFFFFFCh                ;DWORD align
        mov        edi,esp                        ;Points to new data area
        mov        [ebp-36],edi

;/*
;** Transfer 20 bytes
;*/

        mov        ecx,5
        rep        movsd

L27:

;/*
;** ****> END Pointer/Structure Section
;*/

;/*
;** Create new call frame, using 16-bit semantics.
;*/

        push        es
        push        ds
        push        ebx
        push        ebp                            ; save ebp
        mov         eax,esp                        ; save current esp
        push        ss
        push        eax


        mov         edx,ss                       ; get cpl bits to use as dpl bits
        and         edx,3                        ; mask off rest of register

        or          dl,4                         ;Force LDT bit on

;/*
;** From Name: pSem  Type: struct FSRS
;*/

        mov         eax,DWORD PTR [ebp-36]
        or          eax,eax
        jz          short L30                     ;NULL pointer

        call        DOS32FLATTOSEL                ;Convert in packed region

L30: 
        push        ax                            ; push near pointer
        shr     eax,16                            ; get seg of pointer into ds
                                                  ; for pmwin!!!
        mov     ds,ax

;/*
;** Convert SS:ESP to 16-bit SS:SP.
;*/

        mov        eax,esp                        ; use CRMA on ESP to get SS
        ror        eax,16
        shl        eax,3
        or        al,dl
        mov        ss,eax

;/*
;** Jump to 16-bit segment to issue call (so that 16-bit API can RETF).
;** The following two lines are the same as:
;*/

          jmp        FAR PTR T_FSRSEMCHECK
ALIGN 4

;/*
;**  but they trick masm into not generating nops.
;*/

R_FSRSEMCHECK::                                ; label defining return jmp location

;/*
;** Restore 32-bit SS:ESP - it is on top of stack.
;*/

        movzx        esp,sp                        ; make sure that esp is correct
        lss        esp,ss:[esp]
        pop        ebp
        pop        ebx
        pop     ds
        pop        es

;/*
;** Convert Return Code
;** ULONG --> ULONG
;*/

        rol        eax,16
        mov        ax,dx
        rol        eax,16
L31:

;/*
;** Functions contain pointers, save return code
;*/

        mov        [ebp-4],eax                ;Save return code

;/*
;** ****> BEGIN Pointer/Structure Unpack Section
;*/

;/*
;** Undo Pointer pSem --> pSem
;*/

        mov        esi,[ebp-36]                ;pSem temp address
        or        esi,esi
        jz        L32



        mov        edi,[ebp+8]                ;pSem original address

;/*
;** Structures are Identical
;** Structures don't have pointers
;** Structure doesn't have output semantics
;** Treat structure same as buffer
;** Types are identical and no imbedded pointers exist
;** This means that we treated the pointer as a buffer
;** If temp address == original address then no work required
;*/

        cmp        esi,edi
        je        L32

;/*
;** Item is fixed size
;** stack deallocated implicitly
;*/

L32:                ;No action required

;/*
;** ****> END Pointer/Structure Unpack Section
;*/

;/*
;** 32-bit return code.
;*/

        lea        esp,[ebp-12]
        pop        edi
        pop        esi
        pop        eax                ;Pop saved return code
        leave
        ret                                ; Remove parameters

FSRSemCheck32 endp

;/***************************************************************************
;*
;* FUNCTION NAME = T_FSRSEMENTER
;*
;* DESCRIPTION   = 16-bit FSR semaphore enter routine
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

_CODE16        SEGMENT        PARA USE16 PUBLIC 'CODE'

ALIGN 4
T_FSRSEMENTER PROC FAR
        call        FAR PTR FSRSEMENTER                ; call 16-bit version
        jmp        FAR PTR FLAT:R_FSRSEMENTER                ; jump back
T_FSRSEMENTER ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = T_FSRSEMLEAVE
;*
;* DESCRIPTION   = 16-bit FSR semaphore leave routine
;*                 
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4
T_FSRSEMLEAVE PROC FAR

;/*
;** Target is at L24 + (cx * 8)
;*/

        or      ecx,ecx
        jnz     do_2
        call    FAR PTR FSRSEMLEAVE
        jmp        FAR PTR FLAT:R_FSRSEMLEAVE                ; jump back
ALIGN 4
do_2:
        call    FAR PTR FSRSEMEXIT
        jmp        FAR PTR FLAT:R_FSRSEMLEAVE                ; jump back

;L24 LABEL DWORD

T_FSRSEMLEAVE ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = T_FSRSEMCHECK
;*
;* DESCRIPTION   = 16-bit FSR semaphore check routine
;*                
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4
T_FSRSEMCHECK PROC FAR
        call        FAR PTR FSRSEMCHECK                ; call 16-bit version
        jmp        FAR PTR FLAT:R_FSRSEMCHECK          ; jump back
T_FSRSEMCHECK ENDP

_CODE16        ENDS
        END
