        page    ,132

;/*****************************************************************************
;*
;* SOURCE FILE NAME = OPASUBR.ASM
;*
;* DESCRIPTIVE NAME = Assembly language subroutines for Optical Dev Mgr
;*
;* COPYRIGHT    COPYRIGHT IBM CORPORATION, 1991, 1992
;*              LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
;*              REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
;*              RESTRICTED MATERIALS OF IBM
;*              IBM CONFIDENTIAL
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION
;*
;* FUNCTIONS
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*****************************************************************************/

        title   ddasubr - OS/2 2.0 OS2DASD.DMD device driver
        name    ddasubr

        page    ,132

        .xlist
        include struc.inc
        include abmac.inc
        include basemaca.inc
        include devhlp.inc
        include devsym.inc
        include strat2.inc
        .list

_DATA           segment dword public 'DATA'
_DATA           ends

CONST           segment dword public 'CONST'
CONST           ends

_BSS            segment dword public 'BSS'
_BSS            ends

_TEXT           segment dword public 'CODE'
_TEXT           ends

Code            segment dword public 'CODE'
Code            ends

SwapCode        segment dword public 'CODE'
SwapCode        ends

DGROUP          group   CONST, _BSS, _DATA
StaticGroup     group   Code, _TEXT
SwapGroup       group   SwapCode

;*
;* ABIOS Related
;*

;*StaticCode SEGMENT use16 'CODE'
;*           assume cs:StaticCode

_DATA   segment dword public 'DATA'
        extrn   _Device_Help:dword

_DATA   ends


_TEXT   segment dword public 'CODE'
        extrn   _Strat1:near

_TEXT   ends


_TEXT     segment dword public 'CODE'
          assume  CS:_TEXT, DS:_DATA

        .386


;/***************************************************************************
;*
;* FUNCTION NAME = Strat1
;*
;* DESCRIPTION   = Strategy entry point for Optical device driver
;*
;* INPUT         = ES:BX            - request packet
;*
;* OUTPUT        = status word in request packet header
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

         public Strat1
         public OP_Exit
Strat1 proc far

;*      int     3                             ;
        cmp     es:[bx].PktCmd,0              ; Init command code ?
        je      setup_ring0_init              ;

        push    es                            ; Push RP pointer on stack
        push    bx                            ;
        call    _Strat1                       ; call c strategy entry point

        pop     bx
        pop     es
        jmp     OP_Exit                       ;

setup_ring0_init:

        mov     si,bx
        mov     ax,cs                         ; ax:bx = ring 0 init routine
        and     ax,0FFFCH                     ; make ring 0 selector
        mov     bx,offset Ring0_Init          ;
        mov     cx,2                          ; 2 parms
        mov     dh,3                          ; 16-bit call gate
        mov     dl,DevHlp_DynamicAPI          ;
        call    dword ptr es:[si].InitDevHlp  ; Create ring-0 call gate
        mov     bx,si
        jnc     call_ring0                    ;
        mov     es:[bx].PktStatus,810CH       ; return init error
        jmp     OP_Exit

call_ring0:
        push    di                            ; Save call gate pointer
        push    0                             ;  on stack for call indirect
        mov     bp,sp                         ;    below

        push    es                            ; Save pointer to RP
        push    bx                            ;

        push    es                            ; Push RP pointer on stack
        push    bx                            ;
        call    dword ptr ss:[bp]             ; call via ring-0 call gate

        pop     bx                            ; Restore es:bx
        pop     es                            ;

        add     sp,4                          ; clear saved call gate pointer

                                              ; no way to delete call gate,
                                              ;  so it'll have to stay allocated

OP_Exit:
        retf


Strat1 endp


;/***************************************************************************
;*
;* FUNCTION NAME = Ring0_Init
;*
;* DESCRIPTION   = Ring-0 worker for init routine
;*
;* INPUT         =
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

Ring0_Init proc far

        push    DGROUP
        pop     ds

        push    ss:[si+2]       ; push es:bx
        push    ss:[si]

        call    _Strat1

        pop     bx              ; clear stack and retf
        pop     es

        retf

Ring0_Init endp


;/***************************************************************************
;*
;* FUNCTION NAME = f_SWait
;*
;* DESCRIPTION   = Wait for a semaphore for far call
;*
;* INPUT         = Semaphore        - semaphore to wait on                                                                         = NONE
;*                                                                                      = NONE
;* OUTPUT        = VOID
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

BIOS_BLOCK_ID   equ     0fffch

         public _f_SWait
_f_SWait proc far

        push    bp
        mov     bp,sp
        push    bx
        mov     bx,[bp+6]
        push    bx
        call    _SWait
        pop     bx
        pop     bx
        pop     bp
        ret

_f_SWait endp


;/***************************************************************************
;*
;* FUNCTION NAME = SWait
;*
;* DESCRIPTION   = Wait for a semaphore
;*
;*       This is the same routine as the DOS "ram semaphore" routine.
;*       It operates on a semaphore made up of a pair of bytes- an "in
;*       use" flag and a "someone is wait" flag.
;*
;*       USABLE IN SYSTEM and USER MODE.
;*
;*       WARNING - Enables Interrupts
;*
;*       DB      busyflag
;*       DB      waitingflag
;*
;*       If busyflag is clear then
;*               set busyflag
;*               return
;*       else
;*               set waitingflag (to notify owner to do a wakeup when he's done)
;*               ProcBlock on address of busyflag
;*
;*       Note that when ProcBlock returns interrupts will be enabled.
;*       Since the entire procblock interval was an "interrupts enabled"
;*       window we figure we must be called with interrupts on and
;*       thus don't mess with PUSHF/POPFF but just jam the interrupts
;*       on and off as necessary.  (In keeping with good practice we
;*       keep them on as much as possible.)
;*
;*
;*       VOID NEAR SWait (NPUSHORT Semaphore)
;*                                                                                      = NONE
;*       VOID FAR  f_SWait (NPUSHORT Semaphore)
;*                                                                                      = NONE
;* INPUT         = Semaphore        - semaphore to wait on                                                                         = NONE
;*                                                                                      = NONE
;* OUTPUT        = VOID
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

WaitSem         equ     [bp+4]

      public _SWait
_SWait proc near

        push    bp
        mov     bp,sp

        SaveReg <ax,bx>
        mov     bx,WaitSem
;*      retest semaphore
;*
;*      (ds:bx) = address
;*      (TOS) = caller's AX

swa0:   DISABLE
        mov     al,1
        xchg    al,BYTE PTR ds:[bx]     ; set semaphore

;*      If busyflag was set then its still set and (al) = 1
;*      If busyflag was clear then its set now and (al) = 0

        and     al,al
        jnz     swa1                    ; foo - it was already set so Block
        ENABLE
        RestoreReg <bx, ax>
        pop     bp
        ret                             ; done  - we've got it

;*      The thing is set.  We're going to have to block on it
;*
;*      (al) = 1

swa1:   mov     BYTE PTR ds:1[bx],al        ; set waiting

        SaveReg <bx,cx,dx,di>
        mov     ax,BIOS_BLOCK_ID
        mov     di,-1
        mov     cx,-1                   ; Never time out
        mov     dh,1                    ; Non-Interruptible
        DEVHLP DevHlp_ProcBlock         ; Block until Proc_Run
        RestoreReg <di,dx,cx,bx>

        jmp     swa0                            ; Re-Test this.

_SWait   endp



;/***************************************************************************
;*
;* FUNCTION NAME = f_SSig
;*
;* DESCRIPTION   = Signal a disk semaphore for far call
;*
;* INPUT         = Semaphore        - semaphore to signal
;*
;* OUTPUT        = VOID
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

         public _f_SSig
_f_SSig  proc far

        push    bp
        mov     bp,sp
        push    bx
        mov     bx,[bp+6]
        push    bx
        call    _SSig
        pop     bx
        pop     bx
        pop     bp
        ret

_f_SSig  endp


;/***************************************************************************
;*
;* FUNCTION NAME = SSig
;*
;* DESCRIPTION   = Signal a disk semaphore
;*
;*       SSig releases a semaphore (it is presumed that the caller indeed
;*       owns it!) and, if anyone was waiting, wakes them up.
;*
;*       Usable in SYSTEM-TASK, USER and INTERRUPT mode.
;*       Callable in BOOT mode if we're sure no one is "waiting" on the
;*               semaphore (which should always be the case)
;*
;*       VOID NEAR SSig (NPUSHORT Semaphore)
;*
;*       VOID FAR  f_SSig (NPUSHORT Semaphore)
;*
;* INPUT         = Semaphore        - semaphore to signal
;*
;* OUTPUT        = VOID
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

SigSem  EQU  [bp+4]

      public _SSig
_SSig proc near

        push    bp
        mov     bp,sp
        SaveReg <ax,bx>

        mov     bx,SigSem
        xor     ax,ax
        xchg    ax,ds:[bx]              ; clear semaphore and wait flag

;*      (al) = semaphore flag
;*      (ah) = wait flag

        and     al,al
        jz      SSig8                   ; TROUBLE! Not SET!
        and     ah,ah
        jz      SSig2                   ; nobody waiting, don't ProcRun

;*      Someone is waiting on this semaphore.  Wake him/them up.
;*
;*      (AX:BX) = block/run code value

        SaveReg <bx, cx, dx>
        mov     ax, BIOS_BLOCK_ID
        DEVHLP  DevHlp_ProcRun          ; Block until Proc_Run
        RestoreReg <dx, cx, bx>
SSig2:
        RestoreReg <bx, ax>
        pop     bp
        ret

SSig8:  jmp     SSig8
        db      "Semaphore cleared that was never set!!"

_SSig    endp


;/***************************************************************************
;*
;* FUNCTION NAME = f_add32
;*
;* DESCRIPTION   = ULONG = add32 (ULONG operand1, ULONG operand2)
;*
;* INPUT         =
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

AddOp1  EQU    [bp+6]
AddOp2  EQU    [bp+10]

public _f_add32
_f_add32 proc far

        push    bp
        mov     bp,sp
        mov     eax,AddOp1
        add     eax,AddOp2
        jc      Over
        mov     edx,eax
        shr     edx,16
        jmp     short NotOver
Over:
        mov     ax,0
        mov     dx,0
NotOver:
        pop     bp
        ret


_f_add32 endp


;/***************************************************************************
;*
;* FUNCTION NAME = f_ZeroCB
;*
;* DESCRIPTION   = Zero fill the input control block
;*
;*                 _f_ZeroCB (PBYTE ControlBlock, USHORT Length)
;* INPUT         =
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

CtrlBlk EQU [bp+6]
BlkLen  EQU [bp+10]

public _f_ZeroCB
_f_ZeroCB proc far

        push    bp
        mov     bp,sp

        SaveReg <es,bx,cx,di>

        xor     eax,eax
        les     di,CtrlBlk
        mov     cx,BlkLen
        mov     bx,cx
        and     bx,3
        shr     cx,2
        cmp     cx,0
        je      zcb_rem
        rep     stosd

zcb_rem:
        mov     cx,bx
        cmp     cx,0
        je      zcb_ret
        rep     stosb

zcb_ret:
        RestoreReg <di,cx,bx,es>

        pop     bp
        ret

_f_ZeroCB endp


;/***************************************************************************
;*
;* FUNCTION NAME = _f_BlockCopy
;*
;* DESCRIPTION   = Copy a block of data
;*
;*                 VOID _f_BlockCopy (PBYTE Dest, PBYTE Orig, USHORT Length
;*
;* INPUT         =
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

BlkDest  EQU [bp+6]
BlkSrc   EQU [bp+10]
BlkCLen  EQU [bp+14]

public _f_BlockCopy
_f_BlockCopy proc far

        push    bp
        mov     bp,sp

        SaveReg <ds,es,di,si,cx,bx>

        les     di,BlkDest
        lds     si,BlkSrc
        mov     cx,BlkCLen

        mov     bx,cx
        and     bx,3
        shr     cx,2
        cmp     cx,0
        je      bc_rem
        rep     movsd

bc_rem:
        mov     cx,bx
        cmp     cx,0
        je      bc_ret
        rep     movsb

bc_ret:
        RestoreReg <bx,cx,si,di,es,ds>

        pop     bp

        ret

_f_BlockCopy endp


                PUBLIC  _ZeroFSGS
_ZeroFSGS       proc    near

                push    0
                pop     fs
                push    0
                pop     gs

                ret

_ZeroFSGS       endp



_TEXT ends
     end

