Source file: /~heha/argon/multimed.zip/SNDBLST/COMMONA.ASM

        page 60, 132
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   commona.asm
;
;   Copyright (c) 1991-1992 Microsoft Corporation.  All rights reserved.
;
;   General Description:
;      Contains wave and midi support routines that don't need to be fixed.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        .286

        .xlist
        include cmacros.inc                   
        include windows.inc
        include mmsystem.inc
        include mmddk.inc
        include sndblst.inc
        include vsbd.inc
        .list

        ?PLM=1                          ; Pascal calling convention
        ?WIN=0                          ; NO! Windows prolog/epilog code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   extrn declarations
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

        externW  <gwPort>
        externFP <dspWrite>             ; sndblst.asm
        externFP <dspRead>              ; sndblst.asm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   segmentation
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IFNDEF SEGNAME
        SEGNAME equ <_TEXT>
ENDIF

createSeg %SEGNAME, CodeSeg, word, public, CODE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   data segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sBegin Data

    globalD glpVSBDEntry,       0   ; the VSBD api entry point is stored here
    globalW gwAcquireCount,     0   ; acquire count for sound blaster

sEnd Data

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   code segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sBegin CodeSeg

        assumes cs, CodeSeg
        assumes ds, DATA

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CritEnter
;
;   Saves the current state of the interrupt flag on the stack and
;   then disables interrupts.
;
; Registers Destroyed:
;       BX, FLAGS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, nothing
        assumes es, nothing

cProc CritEnter <FAR, PASCAL, PUBLIC>, <>
cBegin nogen
        pop     dx                      ; get return address
        pop     ax
        pushf
        pushf
        pop     bx
        test    bh, 2                   ; if interrupts are already off, don't
        jz      no_cli                  ; ... blow ~300 clocks doing the cli
        cli
no_cli:
        push    ax
        push    dx
        ret
cEnd nogen

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CritLeave
;
;   Restores the interrupt state saved by CritEnter
;
; Registers Destroyed:
;       BX, FLAGS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, nothing
        assumes es, nothing

cProc CritLeave <FAR, PASCAL, PUBLIC>, <>
cBegin nogen
        pop     dx                      ; get return address
        pop     ax

        pop     bx
        test    bh, 2
        jz      no_sti
        sti
no_sti:
        push    ax
        push    dx
        ret
cEnd nogen

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @doc INTERNAL
;
; @asm dspSpeakerOn | Turn on the speaker.
;
; @rdesc There is no return value.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, Data
        assumes es, nothing

cProc dspSpeakerOn <FAR, PASCAL, PUBLIC> <>
cBegin

        push    ax

        D2 <dspSpeakerOn>

; The Media Vision Thunder Board does not properly support the speaker
; status command, so we're not using it here.

        mov     al, SPKRON
        call    dspWrite

dspSpeakerOnExit:

        pop     ax

cEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @doc INTERNAL
;
; @asm dspSpeakerOff | Turn off the speaker.
;
; @rdesc There is no return value.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, Data
        assumes es, nothing

cProc dspSpeakerOff <FAR, PASCAL, PUBLIC> <>
cBegin

        push    ax

        D2 <dspSpeakerOff>

; The Media Vision Thunder Board does not properly support the speaker
; status command, so we're not using it here.

        mov     al, SPKROFF
        call    dspWrite

dspSpeakerOffExit:

        pop     ax

cEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; WORD FAR PASCAL vsbdAcquireSoundBlaster(void)
;
; EXIT:
;     IF success
;         AX = 0, go ahead and open
;     ELSE
;         AX = non-zero error code:
;             SB_API_ASB_Err_Bad_Sound_Blaster    equ 01h
;                 The SB base specified is not being virtualized by VSBD.
;
;             SB_API_ASB_Err_Already_Owned        equ 02h
;                 The SB is currently owned by another VM.
;
; USES:
;     Flags, AX, BX, DX
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, Data
        assumes es, nothing

cProc vsbdAcquireSoundBlaster <FAR, PASCAL, PUBLIC> <>
cBegin

        xor     ax, ax                      ; make sure this is zero
        cmp     [gwAcquireCount], ax        ; Q: do we already own it?
        jne     vsbd_Acquire_Success        ;   Y: then succeed

        mov     ax, [glpVSBDEntry].off      ; Q: is VSBD installed?
        or      ax, [glpVSBDEntry].sel
        jz      vsbd_Acquire_Success        ;   N: then leave (return success)


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   AX = Base of SB to acquire (for example, 0240h)
;   BX = Flags: fSB_ASB_Acquire_DSP, fSB_ASB_Acquire_AdLib_Synth
;   DX = SB_API_Acquire_Sound_Blaster (1)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

        mov     ax, [gwPort]                ; base port to acquire
        mov     bx, fSB_ASB_Acquire_DSP+fSB_ASB_Auto_Reset_DSP
        mov     dx, SB_API_Acquire_Sound_Blaster
        call    [glpVSBDEntry]

        test    ax, not SB_API_ASB_Err_State_Unknown
        jnz     vsbd_Acquire_Exit           ; fail? vamoose with error code!


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   If we owned it last, we know what state we left it in, so don't waste
;   time or turn the speaker on, etc.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

        test    ax, SB_API_ASB_Err_State_Unknown
        jz      vsbd_Acquire_Success

        cCall   dspSpeakerOn
        xor     ax, ax                      ; success

vsbd_Acquire_Success:

        inc     [gwAcquireCount]            ; increment acquire count

vsbd_Acquire_Exit:

cEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   WORD FAR PASCAL vsbdReleaseSoundBlaster(void)
;
;   EXIT:
;       IF success
;           AX = 0, go ahead and close
;       ELSE
;           AX = non-zero error code:
;               SB_API_RSB_Err_Bad_SB       equ 01h
;                   The SB base specified is not being virtualized by VSBD.
;
;               SB_API_RSB_Err_Not_Yours    equ 02h
;                   The SB is NOT owned by callers VM.
;
;   USES:
;       Flags, AX, BX, DX
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, Data
        assumes es, nothing

cProc vsbdReleaseSoundBlaster <FAR, PASCAL, PUBLIC> <>
cBegin

        AssertF byte ptr gwAcquireCount

        xor     ax, ax                      ; assume success
        dec     [gwAcquireCount]            ; Q: final release?
        jnz     vsbd_Release_Exit           ;   N: succeed...

        mov     ax, [glpVSBDEntry].off      ; Q: is VSBD installed?
        or      ax, [glpVSBDEntry].sel
        jz      vsbd_Release_Exit           ;   N: then leave (return success)


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
;   AX = Base of SB to release (for example, 0240h)
;   BX = Flags: fSB_ASB_Acquire_DSP, fSB_ASB_Acquire_AdLib_Synth
;   DX = SB_API_Release_Sound_Blaster (2)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;

        mov     ax, [gwPort]                ; base port to release
        mov     bx, fSB_ASB_Acquire_DSP     ; just the DSP
        mov     dx, SB_API_Release_Sound_Blaster
        call    [glpVSBDEntry]

vsbd_Release_Exit:

cEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @doc INTERNAL
;
; @asm dspReset | Reset the DSP.
;
; @rdesc If the reset is completed successfully then the carry
;     flag is cleared and 0 is returned in AX.  If an error
;     occurs, carry is set and an error code is returned in AX.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, Data
        assumes es, nothing

        public dspReset
dspReset proc far

        D2 <dspReset>

        AssertF byte ptr [gwAcquireCount]   ; better have acquired it already!

        mov     dx, [gwPort]                ; get the base port address
        add     dx, DSP_PORT_RESET          ; point to reset port
        mov     al, 1
        out     dx, al                      ; reset active

        ; wait 3 microseconds for DSP reset to take a good hold

        mov     cx, 100
        loop    $

        xor     al, al
        out     dx, al                      ; clear the reset

        ; read the data port to confirm 0AAH is there

        mov     cx, 25                      ; lots of tries

reset1:
        call    dspRead
        jc      reset2                      ; jump if it timed out

        cmp     al, 0AAH                    ; correct return value ?
        jz      reset3                      ; jump if it is

reset2:
        loop    reset1 
        mov     ax, -1                      ; bad reset!
        jmp     reset4

reset3:

        xor     ax, ax

reset4:
        ret

dspReset endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; @doc INTERNAL 
;
; @asm  void | MemCopy | memory copy
;
; @parm LPVOID | lpDst | destiation
; @parm LPVOID | lpSrc | source
; @parm WORD   | wCount | number of bytes to copy
;
; @rdesc nothing
;
; @comm This function does not handle segment crossings
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        assumes ds, nothing
        assumes es, nothing

cProc MemCopy <FAR, PASCAL, PUBLIC> <ds, si, di>
        ParmD   lpDst
        ParmD   lpSrc
        ParmW   wCount
cBegin

        cld                             ; let's not assume this

        lds     si, lpSrc               ; get source pointer
        les     di, lpDst               ; get dest pointer
        mov     cx, wCount              ; cx is count of bytes

        shr     cx, 1                   ; copy the memory
        rep     movsw
        adc     cl, cl
        rep     movsb

cEnd

sEnd CodeSeg

        end
Detected encoding: ASCII (7 bit)2