;*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.;
;*****************************************************************************/
        page    ,132

;/*****************************************************************************
;*
;* SOURCE FILE NAME = CDASUBR.ASM
;*
;* DESCRIPTIVE NAME = Assembly language subroutines for CD-ROM Dev Mgr
;*
;*
;* 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   _CD_Strat1:near

_TEXT   ends


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

        .386


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

         public CD_Strat1
         public CD_Exit
CD_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    _CD_Strat1                    ; call c strategy entry point

        pop     bx
        pop     es
        jmp     CD_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     CD_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

CD_Exit:
        retf


CD_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    _CD_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


;/***************************************************************************
;*
;* FUNCTION NAME = _PadRaw2340
;*
;* DESCRIPTION   = PadRaw2340 (PBYTE RawData, USHORT RawCnt)
;*
;* INPUT         =
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

RawData EQU    [bp+4]
RawCnt  EQU    [bp+8]

public _PadRaw2340
_PadRaw2340 proc near

        push    bp
        mov     bp,sp

        SaveReg <ds,es,di,si,ecx,bx,eax>

        mov     bx,RawCnt

        lds     si,RawData
        mov     ax,bx
        mov     dx,2340
        mul     dx
        add     si,ax
        sub     si,4            ; ds:si ->last dword of last sector read

        les     di,RawData
        mov     ax,bx
        mov     dx,2352
        mul     dx
        add     di,ax
        sub     di,4            ; es:di -> dest for last dword of last sector

        std                     ; Reverse direction copy

padnxt:
        mov     cx,2340/4
        rep     movsd

        mov     eax,0           ; Prepend 12 byte pad for synch
        mov     ecx,3
        rep     stosd

        dec     bx
        jnz     padnxt

        RestoreReg <eax,bx,ecx,si,di,es,ds>

        cld
        pop     bp
        ret


_PadRaw2340 endp


;/***************************************************************************
;*
;* FUNCTION NAME = HSGtoRedBook
;*
;* DESCRIPTION   = Convert HSG address to RedBook binary address
;*
;*                 RedBook address is binary, not BCD, ( frame,sec,min,0 )
;*
;*                 PSEUDOCODE:
;*                      HSG = (min * 60 + sec) * 75 + frame - 150
;*
;* INPUT         = HSG address
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL = dx:ax = RedBook address     ( dl= min, ah=sec, al=frame )
;*
;* RETURN-ERROR  = none
;*
;**************************************************************************/

                PUBLIC  _HSGtoRedBook
_HSGtoRedBook   proc    near

                push    bp
                mov     bp, sp

                mov     ax, [bp+4]              ; low word of HSG address
                mov     dx, [bp+6]              ; high word of HSG address
                add     ax, 150                 ; base block number
                adc     dx, 0
                mov     cx, 4500                ; 60 * 75
                div     cx                      ; al = min, dx = remainder
                xchg    dx, ax                  ; dl = min, ax = remainder
                mov     cl, 75
                div     cl                      ; al = sec, ah = remainder
                xchg    ah, al                  ; ah = sec, al = frame

                pop     bp
                ret

_HSGtoRedBook   endp


;/***************************************************************************
;*
;* FUNCTION NAME = RedBookToHSG
;*
;* DESCRIPTION   = Convert RedBook binary address to HSG address
;*
;*                 RedBook address must be binary and in order frame,sec,min,0
;*                 on the stack, that is a long with low to high order as shown
;*
;*                 PSEUDOCODE:
;*                    HSG = (min * 60 + sec) * 75 + frame - 150
;*
;* INPUT         = redbook address     (long - frame sec min 0)
;*                                             low -------> high
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL = dx:ax = HSG address
;*
;* RETURN-ERROR  = none
;*
;**************************************************************************/

                PUBLIC  _RedBookToHSG
_RedBookToHSG   proc    near

                push    bp                      ; [bp+4] = frame sec min 0
                mov     bp, sp

                mov     al, byte ptr [bp+6]     ; al = min
                mov     cl, 60
                mul     cl                      ; ax = min * 60
                mov     bx, [bp+4]              ; bl = frame, bh = sec
                cmp     bl, 74
                ja      RedBookToHSGerror
                cmp     bh, 59
                ja      RedBookToHSGerror
                add     al, bh
                adc     ah, 0                   ; ax = min * 60 + sec
                mov     cx, 75
                mul     cx                      ; dx:ax = (min*60 + sec) * 75
                xor     bh, bh
                add     ax, bx
                adc     dx, 0                   ; dx:ax = (min*60 + sec) * 75
                                                ;  + frame
                sub     ax, 150
                sbb     dx, 0                   ; dx:ax = HSG address
                jmp     short RedBookToHSGexit

RedBookToHSGerror:
                mov     ax, -1                  ; to get hardware error
                mov     dx, ax
RedBookToHSGexit:
                pop     bp
                ret

_RedBookToHSG   endp


;/***************************************************************************
;*
;* FUNCTION NAME = BinaryToBCD
;*
;* DESCRIPTION   = Convert binary byte to BCD byte ( 2 digits )
;*
;*                 PSEUDOCODE:
;*                     return ( (n / 10 << 4) | (n % 10) );
;*
;* INPUT         = binary byte
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL = al = BCD
;*
;* RETURN-ERROR  = none
;*
;**************************************************************************/

                PUBLIC  _BinaryToBCD
_BinaryToBCD    proc    near

                push    bp
                mov     bp, sp

                mov     al, byte ptr [bp+4]             ; binary byte
                xor     ah, ah
                mov     cl, 10
                div     cl
                xchg    ah, al
                shl     ah, 4
                or      al, ah

                pop     bp
                ret

_BinaryToBCD    endp


;/***************************************************************************
;*
;* FUNCTION NAME = BCDtoBinary
;*
;* DESCRIPTION   = Convert BCD byte to binary byte ( 2 digits )
;*
;*                 PSEUDOCODE:
;*                     return ( ( n >> 4 ) * 10 + ( n & 0x0F ));
;*
;* INPUT         = BCD byte
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL = al = binary
;*
;* RETURN-ERROR  = none
;*
;**************************************************************************/

                PUBLIC  _BCDtoBinary
_BCDtoBinary    proc    near

                push    bp
                mov     bp, sp

                mov     al, byte ptr [bp+4]             ; BCD byte
                mov     bl, al                          ; save it
                shr     al, 4                           ; high digit
                mov     cl, al                          ; save it
                shl     al, 1                           ; times 2
                shl     al, 1                           ; times 2
                add     al, cl                          ; + 1 = times 5
                shl     al, 1                           ; times 2 = times 10
                and     bl, 0Fh                         ; low digit
                add     al, bl                          ; al = binary 0 - 99

                pop     bp
                ret

_BCDtoBinary    endp



                PUBLIC  _ZeroFSGS
_ZeroFSGS       proc    near

                push    0
                pop     fs
                push    0
                pop     gs

                ret

_ZeroFSGS       endp



_TEXT ends
     end

