;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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 = IPMIMISC.ASM
;*
;* DESCRIPTIVE NAME = Clock routines for Number 9 and Diamond Speedstar.
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  Clock functions for Number 9 GXE and Diamond Speedstar cards.
;*
;* FUNCTIONS
;*
;*
;* NOTES        Diamond Stealth was too difficult to convert to 32bit, so
;*              I left it in bvhsvga for the time being.
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   07/16/94              89439  Build break, _Pascal is not recognized.
;*   08/27/94              89853  Fixin's needed for S3864 w/ICD2061 to work
;*****************************************************************************/

.386p
CODE32    SEGMENT DWORD USE32 PUBLIC 'CODE'
                ASSUME CS:FLAT, DS:FLAT, ES:NOTHING
                ALIGN   4

        PUBLIC  SETDIAMONDCLK
        PUBLIC  SETNUMBER9CLK           ;            ;          
Read_Miscellaneous      EQU     03CCH           ;Misc output read register
CRT_3B4                 EQU     03B4H           ;Monochrome CRT index addr
CRT_3D4                 EQU     03D4H           ;Monochrome CRT index addr
;/***************************************************************************
;*
;* FUNCTION NAME = SETNUMBER9CLK                                           ;          
;*
;* DESCRIPTION   = Set the video clock on #9 adapter with S3
;*
;*                 ENTRY POINT: SetNumber9Clk
;*                 LINKAGE:   CALL NEAR
;*
;* INPUT         = (Passed on stack)
;*                 SerialClockValue (dword)
;*
;* RETURN-NORMAL = Specified clock bits set serially.
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
 CLOCK_DELAY0           EQU     73              ; delay loop for 1/8 sec
 CLOCK_DELAY1           EQU     145             ; delay loop for 1/4 sec

 C_NONE                 EQU     0       ; for freq synth programming
 C_CLK                  EQU     1       ; for freq synth programming
 C_DATA                 EQU     2       ; for freq synth programming
 C_BOTH                 EQU     3       ; for freq synth programming
 CLOCK_DELAY            EQU     CLOCK_DELAY1

 DELAY_CLOCK_SETUP      EQU     1       ; Delay when changing freq

SerialClockValue            equ     DWORD  PTR [ebp+8]

SETNUMBER9CLK  PROC    NEAR
        push    ebp
        mov     ebp, esp
        push    esi
        push    edi
        push    ebx
        MOV     ESI, WORD PTR SS:SerialClockValue
        MOV     DX,Read_Miscellaneous           ;Get Misc read register           
        IN      AL,DX                           ;Read the register                
        MOV     DX,CRT_3B4                      ;Set Mono                         
        TEST    AL,01                           ;0 - MONO 1 - Color               
        JE      Set_Mono                        ;Return Mono                      
        MOV     DX,CRT_3D4                      ;Set Color                        

CRT_Mono:                                                              ;          
        MOV     AL, 42h                 ; go to the mode ctrl reg (CR42)
        out     dx, al
        inc     dx
        IN      AL,DX                   ; and read it again
        dec     dx
        AND     AL,0F0h
        MOV     AH,AL                   ; save this for later
        OR      AH,2                    ; set the index to two
        CALL    Set_Frequency           ; set the frequency synthesizer
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp
;        ret     4             
        ret

SETNUMBER9CLK   ENDP

;****************************************************************
;
;
;****************************************************************
; Set the frequency synthesizer to the desired frequency.
; The frequency synthesizer is an IDC 2061a part.
; This code turns off the video display prior to setting
; the synthesizer, and then returns the display to the
; previous state.
;       Entry:  ESI     - contains the 24 bit clock Number
;               AH      - contains the saved CR42 reg
;               dx      - 3?4
;****************************************************************
Set_Frequency   PROC
        PUSH    DX

;        PUSH    AX                      ; save CR42 (twice!)
;        MOV     AX, 0A039H              ; register lock 1 index
;        OUT     DX, AX                  ; Unlock the soft switches
;        POP     AX                      ; restore the saved CR42 in AX

        MOV     AL, 1                   ; To turn off video display
        MOV     DX, 03C4h               ; go to the Clocking Mode register
        OUT     DX, AL
        INC     DX
        IN      AL, DX                  ; read the Clocking Mode reg
        PUSH    AX                      ; save the Clocking Mode Reg
        OR      AL, 20h                 ; set video OFF bit
        OUT     DX, AL                  ; turn off video output

        MOV     DX, 03CCh               ; read clock bits in Misc Output reg
        IN      AL, DX
        PUSH    AX                      ; save this old value
        OR      AL, 0Ch                 ; enable CR42 bits 2 & 3
        MOV     DX, 03C2h
        OUT     DX, AL                  ; write new misc output value
        POP     AX
        PUSH    AX
        MOV     DX,Read_Miscellaneous           ;Get Misc read register
        IN      AL,DX                           ;Read the register
        MOV     DX,CRT_3B4                      ;Set Mono
        TEST    AL,01                           ;0 - MONO 1 - Color
        JE      Set_Mono                        ;Return Mono
        MOV     DX,CRT_3D4                      ;Set Color

Set_Mono:
        MOV     AL, 42h                 ; the Mode Control Reg (CR42)
        OUT     DX, AL                  ; write index to 3?4
        INC     DX                      ; Move DX to 3?5
        XCHG    AH,AL                   ; Swap Index/Data
        OUT     DX,AL                   ; Program the data
        XCHG    AH,AL                   ; AH=Data                      

;**************************************************************************
;***************** START OF CRITICAL SECTION OF CODE **********************
;**************************************************************************
        PUSHF                   ; save the flags prior to critical section
        CLI                     ; no interupts please...

        MOV     AL, C_NONE      ; start programming ICD2061A
        OUT     DX, AL
        MOV     AL, C_DATA
        OUT     DX, AL
        MOV     ECX, 6

unLockSeq:
        MOV     AL, C_BOTH       ; Unlock sequence
        OUT     DX, AL
        MOV     AL, C_DATA
        OUT     DX, AL
        LOOP    SHORT unLockSeq

        MOV     AL, C_NONE
        OUT     DX, AL
        MOV     AL, C_CLK
        OUT     DX, AL
        MOV     AL, C_NONE
        OUT     DX, AL
        MOV     AL, C_CLK
        OUT     DX, AL

;        SAR     SI, 1            ; do shift (ignore 1st bit)
;        RCR     BX, 1            ; set the carry flag
;            removed this extra rcr and adjusted #9 clock values by
;            shifting right 1 bit in ipmimain.c
;            RCR     ESI, 1           ; set the carry flag
        MOV     ECX, 24           ; Program the 24 bit value into REG0

programREG0:
;        SAR     SI, 1            ; clock_value >>= 1
;        RCR     BX, 1
        RCR     ESI, 1           ; set the carry flag
        JNC     SHORT clock0

clock1:
        MOV     AL, C_CLK
        OUT     DX, AL
        MOV     AL, C_NONE
        OUT     DX, AL
        MOV     AL, C_DATA
        OUT     DX, AL
        MOV     AL, C_BOTH
        OUT     DX, AL
        JMP     SHORT programCont
clock0:
        MOV     AL, C_BOTH
        OUT     DX, AL
        MOV     AL, C_DATA
        OUT     DX, AL
        MOV     AL, C_NONE
        OUT     DX, AL
        MOV     AL, C_CLK
        OUT     DX, AL

programCont:
        LOOP    SHORT programREG0

        MOV     AL, C_BOTH
        OUT     DX, AL
        MOV     AL, C_DATA
        OUT     DX, AL
        MOV     AL, C_BOTH
        OUT     DX, AL

        POPF                    ; resore all flags
        STI                     ; ok for interupts now
;**************************************************************************
;******************* END OF CRITICAL SECTION OF CODE **********************
;**************************************************************************

        MOV     AL, AH          ; AH has contained the saved CR42 reg
        OUT     DX, AL          ; Select the VCLOCK index in CR42

        POP     AX              ; old Misc Output reg value
        MOV     DX, 03C2h       ; write to write port
        OUT     DX, AL          ; reset the value

        MOV     DX, 03C4h       ; To set screen to previous state
        MOV     AL, 1           ; go to the Clocking Mode reg
        OUT     DX, AL
        INC     DX
        POP     AX              ; use old value pushed from Clk Mode Reg
        OUT     DX, AL          ; restore video

        POP     DX              ; Restore callers registers

        RET
Set_Frequency           ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = SETDIAMONDCLK
;*
;* DESCRIPTION   = Set the video clock on diamond speedstar 24X on per
;*                 mode basis.
;*
;*                 ENTRY POINT: SetDiamondClk
;*                 LINKAGE:   CALL NEAR
;*
;* INPUT         = (Passed on stack)
;*                 SerialClockValue (dword)
;*
;* RETURN-NORMAL = Specified clock bits set serially.
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
SETDIAMONDCLK  PROC    NEAR
        push    ebp
        mov     ebp, esp
        push    edi
        push    esi
        push    ebx
        lea     esi,ss:SerialClockValue                   ;point to serial data

        mov     dx,3cch
        in      al, dx
        push    ax

        mov     ecx, 256
ploop:
        push    ecx
        call    Prog_Clock

        pop     ecx
        in      al,dx
        test    al, 10h
        jnz     ppp_done
        sub     si,2
        loop    ploop

ppp_done:
        pop     ax
        out     dx,al

        sti

        pop    ebx
        pop     esi
        pop     edi
        pop     ebp
;        ret     4             
        ret

SETDIAMONDCLK   ENDP
;/***************************************************************************
;*
;* FUNCTION NAME = Prog_Clock
;*
;* DESCRIPTION   = Program the speedstar 24 clock using 24 bit data
;*                 for desired clock frequency
;*
;* ENTRY POINT: Prog_Clock
;* LINKAGE:     CALL
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Prog_Clock PROC

        push    bx
        mov     dx,3cch
        in      al,dx
        mov     dx,3c2h

        or      al,8
        mov     ecx,6
        cli

kk_1:
        and     al, 0fbh                ;clock low
        out     dx,al
        or      al,4                    ;clock high
        out     dx,al
        loop    kk_1

        and     al, 0fbh
        out     dx,al
        and     al, 0f3h                ;clock low data low
        out     dx,al
        or      al,4                    ;clock high

        out     dx,al
        and     al,0f3h                 ;clock low data low
        out     dx,al
        or      al,4                    ;clock high
        out     dx,al

        mov     bx,8000h                ;program first 16 bits
        call    Send_Serial
        add     si,2                    ;update pointer
        mov     bx,80h                  ;program last 8 bits
        call    Send_Serial

        or      al,8
        out     dx,al
        and     al,0fbh                 ;clock low
        out     dx,al
        or      al,4                    ;clock high
        out     dx,al

        sti
        pop     bx
        ret

Prog_Clock ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = Send_Serial
;*
;* DESCRIPTION   = Program the speedstar 24 clock using 24 bit data
;*                 for desired clock frequency
;*
;*                 ENTRY POINT: Send_Serial
;*                 LINKAGE:   CALL NEAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Send_Serial PROC

Send_Serial_data:

        and     al, 0f7h
        test    word ptr [esi],bx
        jnz     Send_Serial_1
        or      al,8

Send_Serial_1:

        out     dx,al
        and     al, 0fbh
        out     dx,al

        xor     al,8
        out     dx,al
        or      al,4
        out     dx,al
        shr     bx,1
        jnc     Send_Serial_data
        ret

Send_Serial ENDP

CODE32 ENDS
        END
