;*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 = BVHIOPL.ASM
;*
;* DESCRIPTIVE NAME = Video Device Handler Ring 2 Routines
;*
;*
;* 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
;*   06/28/93              Senja  Created new BVHPMI.
;*   1/27/94                      Convert to C for Workplace OS
;*  08/18/94               91152  WD24: T4700CS Frequent Flyer Problem
;*  02/01/95              111227  ThinkPad ID mechanism doesn't work
;*  02/09/95   @V3.0YEE01 111794  WDPanelOn restores lock register incorrectly
;*****************************************************************************/

.286p

;/*
;**  Include files
;*/

        include struc.inc               ; Structured assembly macros
;        include bvhtype.inc            ;
;        include svgadefs.inc            ;           

        extrn   _BVHHardware:qword     ; BVH Info
        extrn   _OEMHardware:qword      ; OEM Manufacturer Info
        extrn   _SVGAMonitorType:word   ; 
        extrn   _GlobalInfoSeg:word     ; 
        extrn   BVH_INIT:FAR
        PUBLIC  SETDIAMONDCLK           ; 
        PUBLIC  Prog_Clock              ; 
        PUBLIC  Send_Serial             ; 
        PUBLIC  GetCRTCAddr             ; 
        PUBLIC  GetDACTypeRtn           ; 
        PUBLIC  SetDACCMDReg            ; 

        PUBLIC  SETNUMBER9CLK           ;            ;          
        PUBLIC  Set_Frequency
        PUBLIC  New_Refresh_Selected

        PUBLIC  _WDPanelOn              ;           
        PUBLIC  _WDSetPanelClk          ;           
        PUBLIC  _ThinkPadHighestRes     ;           

        PUBLIC  HWINPBYTE
        PUBLIC  HWINPWORD
        PUBLIC  HWOUTPBYTE
        PUBLIC  HWOUTPWORD



IF DEBUG
        PUBLIC  DPRINTF
ENDIF

_DATA   SEGMENT WORD PUBLIC 'DATA'
_DATA   ENDS

CONST   SEGMENT WORD PUBLIC 'CONST'
CONST   ENDS

_BSS    SEGMENT WORD PUBLIC 'BSS'
_BSS    ENDS

R2DATA  SEGMENT WORD PUBLIC 'DATA'
R2DATA  ENDS

DGROUP  GROUP   CONST, _BSS, _DATA, R2DATA

R2SEG   SEGMENT PARA PUBLIC 'CODE'
        ASSUME  CS: R2SEG, DS: DGROUP

.386p


                ASSUME  ES:NOTHING

TOTALREGS       EQU     256                     ; 

TSENG_ADAPTER   EQU     3
S3_ADAPTER      EQU     8

R2DATA          SEGMENT
VarRegs         DW      TOTALREGS DUP(0)
org_5c          DB      0                       ; 
R2DATA          ENDS

.286p

;/*
; *           
; */
MISCOUTPUTREGREAD   EQU     003CCh
CRTADDRESSPORT      EQU     003B4h
SEQADDRESSPORT      EQU     003C4h

;/*********************************************************           
;*
;* FUNCTION NAME = GetCRTCAddrInDX
;*
;* DESCRIPTION   = Get CRTC Addr adjusted for color or monochrome in dx
;*
;*                 ENTRY POINT: GetCRTCAddrInDX
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = CRTC Addr in DX
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

GetCRTCAddrInDX     PROC    NEAR

        push    ax
        mov     dx, MISCOUTPUTREGREAD   ;Get Misc read register
        in      al, dx                  ;Read the register
        and     al, 001h                ;Extract color bit      /*          */
        shl     al, 005h                ;Shift to difference    /*          */
        mov     dl, CRTADDRESSPORT AND 000ffh  ;Set Mono
        add     dl, al                  ;Add difference if color/*          */
        pop     ax
        ret

GetCRTCAddrInDX     ENDP
;                                                               /*          */
;/***************************************************************           
;*
;* FUNCTION NAME = _WDPanelOn
;*
;* DESCRIPTION   = Test for WD Panel Display on
;*
;*                 Assumes 3d4.29 has these registers unlocked:
;*                 That is, SVGA with PMI file, not VGA.
;*
;*                 ENTRY POINT: _WDPanelOn
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = AX = Panel is On
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

_WDPanelOn      PROC    FAR             ; 

        call    GetCRTCAddrInDX         ; 
        mov     al, 034h                ;PR1B Flat Panel Unlock
        mov     bl, al                  ;Save index for lock pop    @V3.0YEE01
        out     dx, al                  ; 
        inc     dx                      ;CRT data port
        in      al, dx                  ;Get old lock
        mov     bh, al                  ;                           @V3.0YEE01
        or      al, 0a0h                ;Unlock flat panel
        out     dx, al                  ; 
        dec     dx                      ;CRT index port
        mov     al, 032h                ;PR19 Flat Panel Ctrl
        out     dx, al                  ; 
        inc     dx                      ;CRT data port
        in      al, dx                  ;Get int/ext flags
        dec     dx                      ;CRT index port
        xchg    bx, ax                  ;Get relock
        out     dx, ax                  ;Relock flat panel
        mov     ax, bx                  ;Restore int/ext flags
        and     ax, 030h                ; 
        xor     al, 020h                ; 
        .if     <nz>                    ; 
            mov     al, 001h            ; 
        .endif                          ; 
        ret                             ; 

_WDPanelOn      ENDP                    ; 
;

;/***************************************************************           
;*
;* FUNCTION NAME = _ThinkPadHighestRes
;*
;* DESCRIPTION   = Test if it is a ThinkPad w/ WD chip.
;*                 If it is, check the highest res. supported.
;*
;*                 ENTRY POINT: _ThinkPadHighestRes
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = AX = Highest res or 0 if it is not a ThinkPad
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

_ThinkPadHighestRes      PROC    FAR             ; 

        cli
        mov     al, 07ch
        mov     dx, 070h
        out     dx, al
        inc     dx
        in      al, dx

        cmp     al, 049h                          ; 'I'
        jne     exit0

        dec     dx
        mov     al, 07dh
        out     dx, al
        inc     dx
        in      al, dx

        cmp     al, 053h                          ; 'S'
        je      getres
        cmp     al, 06h
        jne     exit0
getres:
        mov     dx, 0d00h                         ; (al + 1) * 8
        mov     al, 012h
        out     dx, al
        inc     dx
        xor     ah, ah
        in      al, dx
        inc     al
        shl     ax, 03h
        sti
        ret
exit0:
        xor     ax, ax
        sti
        ret
_ThinkPadHighestRes        ENDP                    ; 

;/***********************************************************           
;*
;* FUNCTION NAME = _WDSetPanelClk
;*
;* DESCRIPTION   = Set clocking for WD Panel display
;*
;*                 Assumes SVGA registers are unlocked
;*
;*                 ENTRY POINT: _WDSetPanelClk
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

_WDSetPanelClk  PROC    FAR             ; 

        mov     dx, SEQADDRESSPORT      ;SEQ index port
        mov     al, 031h                ;PR68 Programmable Clock
        out     dx, al                  ; 
        inc     dx                      ;SEQ data port
        in      al, dx                  ; 
        and     al, not 018h            ;Clear video dot clock
        out     dx, al                  ; 
        ret                             ; 

_WDSetPanelClk  ENDP                    ; 


;/***************************************************************************
;*
;* FUNCTION NAME = SETNUMBER9CLK                                           ;          
;*
;* DESCRIPTION   = Set the video clock on #9 adapter with S3
;*
;*                 ENTRY POINT: SetNumber9Clk
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = (Passed on stack)
;*                 horizontal resolution
;*
;* 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

N9HRes            equ     WORD  PTR [bp+6]

SETNUMBER9CLK  PROC    FAR

        push    bp
        mov     bp, sp

        push    di
        push    cx
        push    dx

        mov     cx,N9HRes               ;horizontal resolution in cx

;****************************************************************
; Set the frequency generator to the desired VGA frequency.
; Read the register CR42 to determine the frequency to run at.
; This register is used as an offset into the frequency table.
;****************************************************************
;Set_Nine_VGAFreq        PROC    NEAR
;       PUSH    BX                      ; save the mode number!!

        MOV     DX,03CCh                ; read clock bits in Misc Output reg
        IN      AL,DX
        TEST    AL,08h                  ; do we need to do this routine?
        JZ      SHORT No_Frequency_Setup; no, so just set m clock

        PUSH    SI                      ; save SI before i use it
        CALL    Find_6845_Address       ; Get CRT index address
        CALL    New_Refresh_Selected    ; put higher refresh in SI:BX
;;      JC      SHORT Hi_Refresh

;;      CALL    Freq_Setup              ; setup AX register for freq call
;;      MOV     AL, AH                  ; set to normal read
;;      AND     AX,0Fh                  ; AX is an index into freq table
;;      SHL     AL,1                    ; Convert to dword index
;;      SHL     AL,1                    ; Convert to dword index
;;      MOV     SI,OFFSET Frequency_Table ; Get offset for ICD2061A table
;;      ADD     SI,AX
;;      LODS    WORD PTR CS:[SI]        ; Read the low clock word
;;      MOV     BX,AX                   ; low word goes in BX
;;      LODS    WORD PTR CS:[SI]        ; Read the high clock word
;;      MOV     SI,AX                   ; SI,BX now has the 24-bit clock #

Hi_Refresh:
        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     SI                      ; restore the original contents

No_Frequency_Setup:
;       POP     BX                      ; restore the mode number

        pop     dx
        pop     cx
        pop     di

        pop     bp

        ret     2                       ;bump stack by 2Bytes

Frequency_Table:
;;      DD      0835178h        ; Index   0: Frequency =  25.172284
;;      DD      08AC158h        ; Index   1: Frequency =  28.325095
;;      DD      0A2E140h        ; Index   2: Frequency =  40.006679
;;      DD      0835178h        ; Index   3: Reserved
;;      DD      083587Ah        ; Index   4: Frequency =  49.999992
;;      DD      0A3B056h        ; Index   5: Frequency =  76.999990
;;      DD      09AA942h        ; Index   6: Frequency =  35.999995
;;      DD      0AB8946h        ; Index   7: Frequency =  44.889429
;;      DD      0835178h        ; Index   8: Reserved
;;      DD      0835178h        ; Index   9: Reserved
;;      DD      0A2E040h        ; Index  10: Frequency =  80.013358
;;      DD      093B16Ah        ; Index  11: Frequency =  31.499996
;;      DD      0B22822h        ; Index  12: Frequency = 108.516732
;;      DD      0968846h        ; Index  13: Frequency =  65.012276
;;      DD      09F5850h        ; Index  14: Frequency =  74.999990
;;      DD      0835178h        ; Index  15: Reserved
;Set_Nine_VGAFreq        ENDP

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:  SI:BX   - pointer to 24 bit clock Number
;               AH      - contains the saved CR42 reg
;               dx      - 3?4
;****************************************************************
Set_Frequency   PROC    NEAR
        PUSH    DX
;;      PUSH    AX                      ; save CR42

        PUSH    AX                      ; save CR42 (twice!)
;;;     CALL    Find_6845_Address       ; Get CRT index address
        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

        CALL    Find_6845_Address       ; Get CRT index address
        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

;**************************************************************************
;***************** 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     CX, 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
        MOV     CX, 24           ; Program the 24 bit value into REG0

programREG0:
        SAR     SI, 1            ; clock_value >>= 1
        RCR     BX, 1
        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

;;IF      DELAY_CLOCK_SETUP
;;      MOV     CX,CLOCK_DELAY  ; Brief wait period (defined above)
;;      MOV     AL, 0           ; no tone during wait period
;;;     CALL    Gate_Timer      ; Wait for Clock Freq to synchronize
;;ENDIF

        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     AX              ; restore the saved CR42 in AX
        POP     DX              ; Restore callers registers

        RET
Set_Frequency           ENDP
;****************************************************************
;
;
;****************************************************************
; If the scratch register calls for it, set the new refresh rate
; for the vesa modes (CR52 contains selected refresh rate)
; CR52 is initialized to 0AAh at init time.
;
; The structure for CR52 is:
;   Bits:  7 6| 5 4| 3 2| 1 0
;          x x| x x| x x| x x
;                       
;           ³    ³    ³    ÀÄ 640x480 resolutions
;           ³    ³    ÀÄÄÄÄÄÄ 800x600 resolutions
;           ³    ÀÄÄÄÄÄÄÄÄÄÄÄ 1024x768 resolutions
;           ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ- 1280x1024 and 1600x1200 resolutions
;
; where:    00 = 70 Hz
;           01 = 76 Hz
;           10 = 60/56 Hz (this is really Default Hz!)
;           11 = 72 Hz
;
;    cx = horizontal resolution
;    dx = 3?4
;****************************************************************
New_Refresh_Selected    PROC    NEAR    ; Test GXe system subfunctions
;;      PUSH    AX
;;      PUSH    DI                      ; Dont destroy DI

        CMP     cx, 640                 ; which gross resolution?
        JE      SHORT Refresh_640
        CMP     cx, 800                 ; which gross resolution?
        JE      SHORT Refresh_800
        CMP     cx, 1024                ; which gross resolution?
        JE      SHORT Refresh_1024
        CMP     cx, 1280                ; which gross resolution?
        JE      SHORT Refresh_1280
        CMP     cx, 1600                ; which gross resolution?
        JE      SHORT Refresh_1600
        CMP     cx, 1056                ; 132 cols text
        JE      SHORT Refresh_132
        CMP     cx, 1188                ; 132 cols text
        JE      SHORT Refresh_132
        JMP     SHORT No_HiRefresh      ; fail-safe exit

Refresh_640:
        MOV     CL, 0                   ; offset in CR52 is 1'st position
        MOV     BL, 0                   ; offset in table is...
        JMP     SHORT Set_Refresh

Refresh_800:
        MOV     CL, 2                   ; offset in CR52 is 2'nd position
        MOV     BL, 4                   ; offset in table is...
        JMP     SHORT Set_Refresh

Refresh_1024:
        MOV     CL, 4                   ; offset in CR52 is 3'rd position
        MOV     BL, 8                   ; offset in table is...
        JMP     SHORT Set_Refresh

Refresh_1280:
        MOV     CL, 6                   ; offset in CR52 is 4'th position
        MOV     BL, 12                  ; offset in table is...
        JMP     SHORT Set_Refresh

Refresh_1600:
        MOV     CL, 6                   ; offset in CR52 is 4'th position
        MOV     BL, 16                  ; offset in table is...

Set_Refresh:
        MOV     AL, 52h
        OUT     DX, AL                  ; CR52 is the multiple mon-id reg.
        INC     dx
        in      al, dx
        dec     dx                      ; Get CRT index address

;;;     XCHG    AL, AH                  ; Get Monitor info in AL
        SHR     AL, CL                  ; Get the corresponding monitor-id
        AND     AL, 03                  ; Get the bits I want by themselves
        MOV     BH, AL                  ; store bits here...

        CMP     BH, 02                  ; is register set to 60 Hz?
        JE      SHORT No_New_HSync      ; user wants 60 Hz

        MOV     AL, 04h                 ; read the Horiz Sync Start Pos
        OUT     DX, AL                  ; Unlock the soft switches
        INC     dx
        in      al, dx
        DEC     AL                      ; by one character clock
        OUT     DX, AL                  ; to adjust screen position.
        dec     dx                      ; Get CRT index address
        jmp     SHORT No_New_HSync      ; continue

Refresh_132:
        MOV     bh, 0                   ; initialize to 0
        MOV     BL, 20                  ; offset in table is...

No_New_HSync:
        MOV     AL, BH                  ; get the value back now
        XOR     AH, AH                  ; clear the AH reg for add to SI
        ADD     AL, BL                  ; add res jump for total index jump
        SHL     AL, 1                   ; convert to DWORD offset
        SHL     AL, 1                   ; convert to DWORD offset
        MOV     SI,OFFSET Hi_Refresh_Table ; Get offset for Hi_Refresh table
        ADD     SI, AX                  ; increment to the refresh rate
        LODS    WORD PTR CS:[SI]        ; Read the low clock word
        MOV     BX, AX                  ; low word goes in BX
        LODS    WORD PTR CS:[SI]        ; Read the high clock word
        MOV     SI, AX                  ; SI,BX now has the 24-bit clock #
        STC                             ; indicate the new numbers in regs
        JMP     SHORT End_Refresh       ; skip to the end with carry set

No_HiRefresh:
        CLC                             ; use standard frequency

End_Refresh:
;;      POP     DI
;;      POP     AX

        RET

;****************************************************************
Hi_Refresh_Table:
        DD      08FA170h        ; Index   0:  640 @ 70Hz  29.376 Mhz
        DD      093B16Ah        ; Index   1:  640 @ 76Hz  31.499 Mhz
        DD      08AC158h        ; Index   2:  640 @ 60Hz  28.325 Mhz
        DD      08F896Ah        ; Index   3:  640 @ 72Hz  30.198 Mhz
        DD      0AB5942h        ; Index   4:  800 @ 70Hz  44.999 Mhz
        DD      0AF8940h        ; Index   5:  800 @ 76Hz  48.850 Mhz
        DD      09AA942h        ; Index   6:  800 @ 56Hz  35.999 Mhz
        DD      0AEF138h        ; Index   7:  800 @ 72Hz  46.295 Mhz
        DD      0A2F846h        ; Index   8: 1024 @ 70Hz  75.847 Mhz
        DD      0A7804Ch        ; Index   9: 1024 @ 76Hz  82.329 Mhz
        DD      0968846h        ; Index  10: 1024 @ 60Hz  65.012 Mhz
        DD      0A26036h        ; Index  11: 1024 @ 72Hz  78.009 Mhz
        DD      093D86Eh        ; Index  12: 1280 @ 70Hz  126.5 / 2 Mhz
        DD      09B785Ah        ; Index  13: 1280 @ 76Hz  139.0 / 2 Mhz
        DD      08B486Eh        ; Index  14: 1280 @ 60Hz  108.5 / 2 Mhz
        DD      0937862h        ; Index  15: 1280 @ 72Hz  128.0 / 2 Mhz
        DD      0AAE03Ch        ; Index  16: 1600 @ 60Hz  170.028 Mhz
        DD      0AAE03Ch        ; Index  17: 1600 @ 60Hz  170.028 Mhz
        DD      0AAE03Ch        ; Index  18: 1600 @ 60Hz  170.028 Mhz
        DD      0AAE03Ch        ; Index  19: 1600 @ 60Hz  170.028 Mhz
        DD      0A2E140h        ; Index  20: 132 columns text mode
;****************************************************************
New_Refresh_Selected            ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = SETDIAMONDCLK
;*
;* DESCRIPTION   = Set the video clock on diamond speedstar 24X on per
;*                 mode basis.
;*
;*                 ENTRY POINT: SetDiamondClk
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = (Passed on stack)
;*                 horizontal resolution
;*                 text/graphics mode
;*                 #colors
;*
;* RETURN-NORMAL = Specified clock bits set serially.
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

HRes            equ     WORD  PTR [bp+10]
fbType          equ     WORD  PTR [bp+8]
nColor          equ     WORD  PTR [bp+6]

SETDIAMONDCLK  PROC    FAR

        jmp     program_clk_chip

        ;                                                  Monitor type
        ;NEC 5Fg ---------------------------------------------- 8x
        ;NEC 4Fg ---------------------------------------------- ax
        ;NEC 3Fgx --------------------------------------------- 9x
        ;NEC 3Fg, SONY 1302 ----------------------------------- 7x
        ;Fixed Freq, 8514 ------------------------------------- fx
        ; 
clk_data:
; BIOS verions 1.xx (>=1.00 and <2.00)
; supports ICD 2061 clock chip
; 24-bit serial data for clock frequency
table_2061      label   byte
 ;       bits 8-15, bits 0-7,  bits 15-23                |fx |7x |9x |ax |8x
 ;                                                       |---|---|---|---|---
 db      00010101b,00111101b,10100010b   ;0  - 25.175    |   |   |   |   |
 db      00000110b,00110101b,10010010b   ;1  - 28.322    |   |   |   |   |
 db      00011011b,10101101b,11010010b   ;2  - 31.5      |   |480|480|480|480
 db      00101010b,10000101b,11110010b   ;3  - 36.0      |600|   |   |   |
 db      00101010b,10111100b,11000010b   ;4  - 40.0      |   |   |   |   |
 db      00010000b,01010100b,11000010b   ;5  - 44.9      |768|768|   |   |
 db      00110101b,10111100b,10100010b   ;6  - 50.0      |   |   |600|600|600
 db      00011011b,10101100b,11010010b   ;7  - 63.0      |   |   |   |   |
 db      00100010b,11000100b,10110010b   ;8  - 65.0      |   |   |768|   |
 db      00101010b,10000100b,11110010b   ;9  - 72.0      |   |   |   |   |
 db      00110101b,00010100b,11110010b   ;10 - 75.00     |   |   |   |768|
 db      00100011b,10010100b,11110010b   ;11 - 77.25     |   |   |   |   |768
 db      00001101b,00010100b,11110010b   ;12 - 75.68     |   |   |   |   |
 db      00010101b,00111100b,10100010b   ;13 - 50.35     |   |   |   |   |

 db      00101010b,10111100b,10100010b   ;14 - xx.xx     |   |600|   |   |
 db      00011110b,10101100b,10100110b   ;15 - xx.xx     |480|   |   |   |

clk_data1:

; BIOS verions 2.xx (>=2.00)
; supports ICD 2061A clock chip
; 24-bit serial data for clock frequency
table_2061A     label   byte
 ;      ;bits 8-15, bits 0-7,  bits 15-23                |fx |7x |9x |ax |8x
 ;      ;                                                |---|---|---|---|---
 db      00010101b,00111101b,10000000b   ;0  - 25.175    |   |   |   |   |
 db      00000110b,00110101b,10100001b   ;1  - 28.322    |   |   |   |   |
 db      00011011b,10101101b,10010010b   ;2  - 31.5      |   |480|480|480|480
 db      00101010b,10000101b,10110010b   ;3  - 36.0      |600|   |   |   |
 db      00001110b,00000101b,10001010b   ;4  - 40.0      |   |   |   |   |
 db      00010000b,00101001b,10101010b   ;5  - 44.9      |768|768|   |   |
 db      00110101b,10111100b,10000010b   ;6  - 50.0      |   |   |600|600|600
 db      00011011b,10101100b,10010010b   ;7  - 63.0      |   |   |   |   |
 db      00100010b,11000100b,11010010b   ;8  - 65.0      |   |   |768|   |
 db      00101010b,10000100b,10110010b   ;9  - 72.0      |   |   |   |   |
 db      00110101b,00010100b,11110010b   ;10 - 75.00     |   |   |   |768|
 db      00100011b,10010100b,10001010b   ;11 - 77.25     |   |   |   |   |768
 db      00001101b,00010100b,10001010b   ;12 - 75.68     |   |   |   |   |
 db      00010101b,00111100b,10000010b   ;13 - 50.35     |   |   |   |   |

 db      00111101b,00000101b,11101110b   ;14 - xx.xx     |   |600|   |   |
 db      00011110b,10101100b,10000110b   ;15 - xx.xx     |480|   |   |   |
 db      00011011b,10111100b,10100110b   ;16 - xx.xx

color_256:
 db      00001001b,11110100b,11100110b   ;2nd pass for 256 color graphics modes

clk_data2:

; BIOS verions 5.xx (>=5.00 and <6.00)
; supports ICD 2061A clock chip
; 24-bit serial data for clock frequency
;table_2061A     label   byte
 ;      ;bits 8-15, bits 0-7,  bits 15-23                |fx |7x |9x |ax |8x
 ;      ;                                                |---|---|---|---|---
 db      00010101b,00111101b,10100010b   ;0  - 25.175    |   |   |   |   |
 db      00000110b,00110101b,10010010b   ;1  - 28.322    |   |   |   |   |
 db      00110101b,00010100b,11110010b   ;2  - 75.00     |   |   |   |768|
 db      00101010b,10000100b,11110010b   ;3  - 72.0      |   |   |   |   |
 db      00001110b,00000100b,11110010b   ;4  - 80.0      |   |   |   |   |
 db      00010000b,01010100b,11000010b   ;5  - 44.9      |   |   |   |   |
 db      00110101b,10111100b,10100010b   ;6  - 50.0      |   |   |   |600|
 db      00100010b,11000100b,10110010b   ;7  - 65.0      |   |   |   |480|
 db      00100111b,00110100b,11110010b   ;8  - 77.16     |   |   |   |   |

 db      00001110b,00000100b,10001010b   ;9  - xx.xx     |   |   |   |132|

clk_data3:

; BIOS verions 6.xx (>=6.00)
; supports ICD 2061A clock chip
; 24-bit serial data for clock frequency
;table_2061A     label   byte
 ;      ;bits 8-15, bits 0-7,  bits 15-23                |fx |7x |9x |ax |8x
 ;      ;                                                |---|---|---|---|---
 db      00010101b,00111101b,10000010b   ;0  - 25.175    |   |   |   |   |
 db      00000110b,00110101b,10100010b   ;1  - 28.322    |   |   |   |   |
 db      00110101b,00010100b,11110010b   ;2  - 75.00     |   |   |   |768|
 db      00101010b,10000100b,10110010b   ;3  - 72.0      |   |   |   |   |
 db      00001110b,00000100b,10001010b   ;4  - 80.0      |   |   |   |   |
 db      00010000b,00101001b,10101010b   ;5  - 44.9      |   |   |   |   |
 db      00110101b,10111100b,10000010b   ;6  - 50.0      |   |   |   |600|
 db      00100010b,11000100b,11010010b   ;7  - 65.0      |   |   |   |480|
 db      00011110b,01000100b,10001010b   ;8  - 77.16     |   |   |   |   |

 db      00001110b,00000100b,10001010b   ;9  - xx.xx     |   |   |   |132|

clk_data4:
; BIOS version 3.33 (S3)
; supports ICD 2061A clock chip
; 24-bit serial data for clock frequency
;table_2061A     label   byte
 ;       bits 8-15  bits 0-7   bits 16-23                |fx |7x |9x |ax |8x
 ;                                                       |---|---|---|---|---
 db      00010101b,00111101b,10000010b   ;0  - 25.175    |   |   |   |   |
 db      00000110b,00110101b,10100010b   ;1  - 28.322    |   |   |   |   |
 db      00001110b,00000101b,10001010b   ;2  - 40.0      |   |480|480|480|480
 db      00100010b,11000101b,11010010b   ;3  - 32.5      |600|   |   |   |
 db      00110101b,10111100b,10000010b   ;4  - 50.0      |   |   |   |   |
 db      00100010b,11000100b,11010010b   ;5  - 65.0      |768|768|   |   |
 db      00101010b,10000101b,10110010b   ;6  - 36.0      |   |   |600|600|600
 db      00010000b,00101001b,10101010b   ;7  - 44.9      |   |   |   |   |
 db      00111111b,00001100b,11110010b   ;8  - 74.5      |   |   |768|   |
 db      00110111b,11010100b,10001010b   ;9  - 80.16     |   |   |   |   |
 db      00010101b,00111100b,10000010b   ;10 - 50.35     |   |   |   |768|
 db      00011011b,10101101b,10010010b   ;11 - 31.5      |   |   |   |   |768
 db      00011011b,10101100b,10010010b   ;12 - 63.0      |   |   |   |   |
 db      00011110b,01000100b,10001010b   ;13 - 77.16     |   |   |   |   |

;                                                        |   |600|   |   |
;                                                        |480|   |   |   |

clk_data5:
; BIOS versions 2.xx (S3)
; supports ICD 2061 clock chip
; 24-bit serial data for clock frequency
;table_2061      label   byte
 ;       bits 8-15  bits 0-7   bits 16-23                | 0 | 1 | 2 | 3 | 4
 ;                                                       |---|---|---|---|---
 db      00010101b, 00111101b, 10100010b ;0  - 25.175    |   |   |   |   |
 db      00000110b, 00110101b, 10010010b ;1  - 28.322    |   |   |   |   |
 db      00101010b, 10111100b, 11000010b ;2  - 40        |   |   |   |   |
 db      00100010b, 11000101b, 10110010b ;3  - 32.5      |   |   |   |   |
 db      00110101b, 10111100b, 10100010b ;4  - 50        |   |   |   |   |
 db      00100010b, 11000100b, 10110010b ;5  - 65.0      |   |   |   |   |
 db      00101010b, 10000101b, 11110010b ;6  - 36.0      |   |   |   |   |
 db      00010000b, 01010100b, 11000010b ;7  - 44.9      |   |   |   |   |
 db      00111111b, 00001100b, 11110010b ;8  - 74.5      |   |   |   |768|
 db      00110111b, 11010100b, 11110010b ;9  - 80.16     |   |   |   |   |
 db      00010101b, 00111100b, 10100010b ;10 - 50.35     |   |   |   |600|
 db      00011011b, 10101101b, 11010010b ;11 - 31.5      |   |   |   |480|
 db      00011011b, 10101100b, 11010010b ;12 - 63.0      |   |   |   |   |
 db      00100111b, 00110100b, 11110010b ;13 - 77.16     |   |   |   |   |

;                                                        |   |600|   |   |
;                                                        |480|   |   |   |

; for S3
;  input  si    points to 24-bit data for programmable clock
;  assumes video is disabled
; Note on Diamond S3 implementations:
; Stealth VRAM uses the same serial 24bit clock programming as
; WD and TSENG 24 implementations. It is manufactured only with 924 chip
; and its monitor bits are configured by the configuration switches whitch
; are reflected thru the CRT 37 configuration register. The 924 chip is
; not supported, so the VRAM code in here is dormant. No code path leads to
; it. Both Stealth 24 and PRO use EEPROM data to get the 3 clock bytes, regardless
; of the BIOS revision. Therefore, SetDiamondClk supports 24 and PRO
; implementation only.

program_clk_chip:

        push    bp
        mov     bp, sp

        push    si
        push    di
        push    cx
        push    dx

        mov     cx,WORD PTR ds:_BVHHardware
        cmp     cx,S3_ADAPTER
        jne     get_mon
        mov     cx, nColor              ;setup colors
        mov     dx, HRes                ;horizontal resolution in dx
        call    s3_proc                 ; support for Stealth 24 and PRO
        jmp     s3_done                 ;adapter is S3

get_mon:
        call    GetMonitorType
        mov     al,byte ptr cs:[di]     ;mode index pointer
check_monitor:
        cmp     al, 254
        jne     supported_mode
        jmp     not_hires               ;unknown monitor type

supported_mode:

        mov     dx,HRes                 ;horizontal resolution in dx
        mov     cx,fbType               ;text or graphics?
        test    cx,2
        je      text_mode

        cmp     dx, 1024                ;1024x768x256/16 color modes
        jne     hres_800
        mov     dx,2
        jmp     short set_index
hres_800:
        cmp     dx, 800                 ;800x600x256/16 color modes
        jne     hres_640
        mov     dx,1
        jmp     short set_index
hres_640:
        cmp     dx, 640                 ;640x480x256/16 color modes
        je      mode_480
        jmp     not_hires
mode_480:
        mov     dx,0
        jmp     short set_index

text_mode:
        cmp     dx, 1188                ;132 column mode (24x)
        je      mode_132
        cmp     dx, 1056                ;132 column mode (24)
        jne     hres_720t
mode_132:
        mov     dx, 3
        jmp     short set_index
hres_720t:
        cmp     dx, 720                 ;80 column mode
        jne     hres_360t
        mov     dx, 4
        jmp     short set_index
hres_360t:
        cmp     dx, 360                 ;40 column mode
        je      set_360t
        jmp     short not_hires
set_360t:
        mov     dx, 5

set_index:
        add     di,dx
        xor     ah,ah
        mov     al,byte ptr cs:[di]     ;mode index pointer

        cmp     al, 255                 ; 
        jne     @F                      ; 
        jmp     short not_hires         ; 
@@:                                     ; 
        mov     cx,3                    ;width of data table
        mul     cx                      ;ax is now table aligned

        mov     cx,WORD PTR ds:_BVHHardware
        cmp     cx,TSENG_ADAPTER
        je      ss24                    ;must be Western Digital

        mov     cx,WORD PTR ds:_OEMHardware+6   ; 
        cmp     cx,1                    ;BIOS Rev 1 (Major)
        jne     clk1
        lea     si, clk_data
        jmp     short supported
clk1:
        cmp     cx,2                    ;BIOS Rev 2 (Major)
        je      @F
        jmp     short not_hires         ;bios rev not currently supported
@@:
        lea     si, clk_data1
        jmp     short supported

ss24:
        mov     cx,WORD PTR ds:_OEMHardware+6   ; 
        cmp     cx,5                    ;BIOS Rev 5 (Major)
        jg      ss24_clk2
        lea     si, clk_data2
        jmp     short supported

ss24_clk2:
        lea     si, clk_data3           ;BIOS Rev 6 (Major)
        jmp     short supported
;S3_VRAM:
;       lea     si, clk_data5           ;BIOS Rev 2 (Major)
;       add     si,ax                   ;point to serial data
;       call    program_clk_chip_s3

supported:
        add     si,ax                   ;point to serial data

        mov     dx,3cch
        in      al, dx
        push    ax

        mov     cx, 256
ploop:
        push    cx
        call    prog_clock

        mov     cx,WORD PTR ds:_OEMHardware+6   ; 
        cmp     cx,2                    ;BIOS Rev 2 (Major)
        jne     short done_prog

        lea     si, color_256   ;2nd pass for 256 color graphics modes
        call    prog_clock
done_prog:
        pop     cx
        in      al,dx
        test    al, 10h
        jnz     ppp_done
        sub     si,2
        loop    ploop

ppp_done:
        pop     ax
        out     dx,al

        call    VGAWait                 ;wait for vertical retrace

not_hires:
s3_done:
        sti

        pop     dx
        pop     cx
        pop     di
        pop     si

        pop     bp

        ret     6                       ;bump stack by 2Bytes

SETDIAMONDCLK   ENDP
        ; assumes dx = Hres
s3_proc:                                ;          

;       mov     cx, nColor              ;get #colors
        mov     ax,eeprom_tab_l*index_m1024
        cmp     dx, 1024
        jne     short res_800

        cmp     cx, 16                  ;check for hi-color
        jne     @F
        mov     ax,eeprom_tab_l*index_m1024h

@@:
        jmp     short   update_eeprom

res_800:
        cmp     dx, 800
        jne     short res_640
        cmp     cx, 16                  ;check for hi-color
        jne     @F
        mov     ax,eeprom_tab_l*index_m800h
        jmp     short   update_eeprom

@@:
        cmp     cx, 24                  ;check for true-color
        jne     @F
        mov     ax,eeprom_tab_l*index_m800t
        jmp     short   update_eeprom

@@:
        mov     ax,eeprom_tab_l*index_m800
        jmp     short   update_eeprom

res_640:
        cmp     dx, 640
        jne     res_1280
        cmp     cx, 16                  ;check for hi-color
        jne     @F
        mov     ax,eeprom_tab_l*index_m640h
        jmp     short   update_eeprom

@@:
        cmp     cx, 24                  ;check for true-color
        jne     @F
        mov     ax,eeprom_tab_l*index_m640t
        jmp     short   update_eeprom

@@:
        mov     ax,eeprom_tab_l*index_m640
        jmp     short   update_eeprom

res_1280:                               ;          
        cmp     dx, 1280
        jne     @F
;;;;;;; Index_m1280_256 (10 = computed value of 64h) yields a flickering or   ;          
;;;;;;; strobe effect on the OS/2 and WinOS/2 desktop after a save/restore    ;          
;;;;;;; on 1280x1024x256.  Index_m1280_16 (9 = computed value of 5Ah) works   ;          
;;;;;;; for all refresh rates supported by the StlMode Utility (43.5, 60, 72) ;          
;;      mov     ax,eeprom_tab_l*index_m1280_256                               ;          
        mov     ax,eeprom_tab_l*index_m1280_16                                ;          
        jmp     short   update_eeprom

@@:
        cmp     dx, 1056
        jne     @F
        mov     ax,eeprom_tab_l*index_m5455
        jmp     short   update_eeprom
@@:

update_eeprom:
        call    upd_crtc_eeprom         ;stealth 24, PRO
        ret

;/***************************************************************************
;*
;* FUNCTION NAME = GetMonitorType
;*
;* DESCRIPTION   =
;*
;*
;* ENTRY POINT: GetMonitorType
;* LINKAGE:     CALL NEAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

GetMonitorType PROC NEAR

;equates for SpeedSTAR 24 supported monitor types or compatibles

MONITOR_NEC2A           equ     0
MONITOR_IBM8514         equ     1
MONITOR_NEC3FGX         equ     2
MONITOR_NEC3FG          equ     3
MONITOR_NEC4FG          equ     4
MONITOR_FIXED           equ     5
MONITOR_CS1572FS        equ     6
MONITOR_CS1024NI        equ     7

;equates for S3 supported monitor types or compatibles            
S3_IBM8514              equ     0
S3_NEC3FG               equ     1
S3_MAG1448              equ     2
S3_NEC4FG               equ     3
S3_SONY1304             equ     4
S3_NEC5FG               equ     5
S3_RESERVED             equ     6
S3_NEC3FGX              equ     7

UNSUPPORTED_MONITOR     equ     254


        jmp     short getmon_cont

;/*************************************************************************
;* Monitor table for SpeedStar 24x
;**************************************************************************/

                       ;+----------------------------------------- 640x480g
                       ;|       +--------------------------------- 800x600g
                       ;|       |       +------------------------- 1024x768g
                       ;|       |       |       +----------------- 132 col text
                       ;|       |       |       |       +--------- 80 col text
                       ;|       |       |       |       |       +- 40 col text
                       ;|       |       |       |       |       |
fixed_freq:     db    15,      3,      5,      5,     15,      15
nec3fg:         db     2,     14,      5,      5,     15,      15
nec3fgx:        db     2,      6,      8,      5,     15,      15
nec4fg:         db     2,      6,     10,      5,     15,      15
nec5fg:         db     2,      6,     11,      5,     15,      15

;/*************************************************************************
;* Monitor table for SpeedStar 24
;**************************************************************************/

nec2a_24:       db   255,      3,      5,      9
ibm8514_24:     db   255,      3,      5,      9
nec3fg_24:      db     7,      9,      5,      9
nec3fgx_24:     db     7,      6,      7,      9
nec4fg_24:      db     7,      6,      2,      9
fixed_24:       db   255,      7,      4,      9
cs1572fs_24:    db     7,      6,      8,      9
cs1024ni_24:    db   255,      6,      7,      9

;/*************************************************************************
;* Monitor table for SpeedStar S3
;**************************************************************************/

fixed_freq_s3:
ibm8514_s3:     db     0,      6,      7,      0,      0,       0
nec3fg_s3:      db     2,     14,      5,      0,      0,       0
mag1448_s3:     db     2,      6,     10,      0,      0,       0
nec4fg_s3:      db    11,     10,      8,      0,      0,       0
sony1304_s3:    db     2,      6,     11,      0,      0,       0
nec5fg_s3:      db     2,      6,     11,      0,      0,       0
nec3fgx_s3:     db     2,      6,      8,      0,      0,       0

unknown:        db   UNSUPPORTED_MONITOR

getmon_cont:
        mov     cx,WORD PTR ds:_BVHHardware
        cmp     cx,8
        jne     @F
        jmp     getmon_S3               ;must be S3
@@:
        mov     cx,WORD PTR ds:_BVHHardware
        cmp     cx,TSENG_ADAPTER
        jne     getmon_24x              ;must be Western Digital

        mov     cx,WORD PTR ds:_SVGAMonitorType
        cmp     cx,MONITOR_NEC2A
        jne     mon_ibm8514
        lea     di, nec2a_24
        jmp     mon_exit
mon_ibm8514:
        cmp     cx,MONITOR_IBM8514
        jne     mon_nec3fg
        lea     di, ibm8514_24
        jmp     mon_exit
mon_nec3fg:
        cmp     cx,MONITOR_NEC3FG
        jne     mon_nec3fgx
        lea     di, nec3fg_24
        jmp     mon_exit
mon_nec3fgx:
        cmp     cx,MONITOR_NEC3FGX
        jne     mon_nec4fg
        lea     di, nec3fgx_24
        jmp     mon_exit
mon_nec4fg:
        cmp     cx,MONITOR_NEC4FG
        jne     mon_fixed
        lea     di, nec4fg_24
        jmp     mon_exit
mon_fixed:
        cmp     cx,MONITOR_FIXED
        jne     mon_cs1572fs
        lea     di, fixed_24
        jmp     mon_exit
mon_cs1572fs:
        cmp     cx,MONITOR_CS1572FS
        jne     mon_cs1024ni
        lea     di, cs1572fs_24
        jmp     mon_exit
mon_cs1024ni:
        cmp     cx,MONITOR_CS1024NI
        jne     unknown_monitor
        lea     di, cs1024ni_24
        jmp     mon_exit

unknown_monitor:
        lea     di, unknown
        jmp     mon_exit

getmon_24x:

        call    GetCRTCAddr
        mov     al,2bh
        out     dx,al
        inc     dx
        in      al,dx
        and     al,0f0h
        cmp     al,0f0h
        jne     nec3fg_mon
        jmp     short default_mon

nec3fg_mon:
        cmp     al,70h
        jne     nec3fgx_mon
        lea     di, nec3fg
        jmp     mon_exit

nec3fgx_mon:
        cmp     al,90h
        jne     nec4fg_mon
        lea     di, nec3fgx
        jmp     mon_exit

nec4fg_mon:
        cmp     al,0a0h
        jne     nec5fg_mon
        lea     di, nec4fg
        jmp     short mon_exit

nec5fg_mon:
        cmp     al,80h
        jne     default_mon
        lea     di, nec5fg
        jmp     short mon_exit

default_mon:
        lea     di, fixed_freq
        jmp     short mon_exit

;S3_VRAM part. Not used.
getmon_s3:

        call    unlock_sc       ;unlock sc regs
        call    unlock_s3       ;unlock sc regs

        call    GetCRTCAddr
        mov     al,37h
        out     dx,al
        inc     dx
        in      al,dx
        and     al,60h
        shr     al,5
        cmp     al,S3_IBM8514
        jne     s3_nec3fg_mon
        lea     di, ibm8514_s3
        jmp     short mon_exit

s3_nec3fg_mon:
        cmp     al,S3_NEC3FG
        jne     s3_mag1448_mon
        lea     di, nec3fg_s3
        jmp     short mon_exit

s3_mag1448_mon:
        cmp     al,S3_MAG1448
        jne     s3_nec4fg_mon
        lea     di, mag1448_s3
        jmp     short mon_exit

s3_nec4fg_mon:
        cmp     al,S3_NEC4FG
        jne     s3_sony1304_mon
        lea     di, nec4fg_s3
        jmp     short mon_exit

s3_sony1304_mon:
        cmp     al,S3_SONY1304
        jne     s3_nec5fg_mon
        lea     di, sony1304_s3
        jmp     short mon_exit

s3_nec5fg_mon:
        cmp     al,S3_NEC5FG
        jne     s3_reserved_mon
        lea     di, nec5fg_s3
        jmp     short mon_exit

s3_reserved_mon:
        cmp     al,S3_RESERVED
        jne     s3_nec3fgx_mon
        lea     di, ibm8514_s3
        jmp     short mon_exit

s3_nec3fgx_mon:
        cmp     al,S3_NEC3FGX
        jne     s3_default_mon
        lea     di, nec3fgx_s3
        jmp     short mon_exit

s3_default_mon:
        lea     di, fixed_freq_s3

mon_exit:
        ret

GetMonitorType 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 NEAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Prog_Clock PROC NEAR

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

        or      al,8
        mov     cx,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 FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

Send_Serial PROC NEAR

send_serial_data:

        and     al, 0f7h
        test    word ptr cs:[si],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

;/***************************************************************************
;*
;* FUNCTION NAME = GetCRTCAddr
;*
;* DESCRIPTION   = Get CRTC Addr adjusted for color or monochrome
;*
;*                 ENTRY POINT: GetCRTCAddr
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = CRTC Addr in DX
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

GetCRTCAddr PROC NEAR

        push    ax
        mov     dx,3cch
        in      al,dx
        test    al,1
        mov     dx,3d4h
        jnz     get_crtc_1
        mov     dl,0b4h
get_crtc_1:
        pop     ax
        ret

GetCRTCAddr ENDP

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

program_clk_chip_s3:            ; 
        push    bx
        push    cx
        push    dx

        call    unlock_sc       ;unlock sc regs
        call    unlock_s3       ;unlock sc regs

        mov     ah,40h
        call    in_crtc
        push    ax              ;save crtc reg 40h value
        or      al,1            ;enable enhanced command
        call    out_crtc

        mov     ah,42h          ;use bits 1-0 of enhanced clock select
        call    in_crtc         ;this is done to ensure same state as 3C2h
        and     al,0fch         ;cs1 and cs0
        mov     ah,al

        mov     dx,3cch         ;read misc. out reg
        in      al,dx
        push    ax              ;save misc. out reg value
        and     al,0ch          ;mask off cs1 and cs0
        shr     al,1
        shr     al,1
        or      ah,al           ;same clock selection as misc out.
        mov     al,42h          ;get crtc addr, dx has been changed
        call    GetCRTCAddr     ;ret dx=crtc addr 3x4h
        out     dx,ax
        pop     ax
        push    ax              ;misc out reg value
        or      al,0ch          ;set for enhanced clock
        mov     dx,3c2h
        out     dx,al

        mov     cx,25           ;try 25 times if error
skip_0:
        push    cx
        call    p_clock_s3      ;program 24-bit data
        sub     si,2            ;update pointer to clock data for retry
        pop     cx              ;if error

        mov     ah,43h          ;check for alternate i/o enable
        call    in_crtc         ;to read clock programming error bit
        mov     dx,42e8h
        test    al,10h
        jz      skip_1
        mov     dx,4148h
skip_1:
        in      ax,dx           ;use bit 1 from monitor id bits in
        test    al,40h          ;subsystem  status register for clock
        jnz     skip_2          ;if error
        loop    skip_0
skip_2:
        pop     ax
        mov     dx,3c2h         ;restore misc out reg
        or      al,0ch
        out     dx,al
        pop     ax              ;restore crtc reg 40h value
        call    out_crtc
        mov     ah,42h
        call    in_crtc
        or      al,3            ;force enhaced clock
        call    out_crtc
;       call    lock_s3         ;lock s3 regs
;       call    lock_sc         ;lock sc regs

        call    VGAWait         ;wait for vertical retrace
        call    VGAWait         ;wait for vertical retrace

        pop     dx
        pop     cx
        pop     bx
        ret


p_clock_s3:
        mov     ah,42h          ;sc2
        call    in_crtc         ;setup dx for crtc 3x4h
        xchg    al,ah
        push    ax              ;previous vclock selection
                                ;unlock seq
        or      ah,2            ;data high
        mov     cx,6            ;toggle clk 6 times
        cli
kk_1_s3:
        and     ah,0feh         ;clock low
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        loop    kk_1_s3

        and     ah,0feh
        out     dx,ax
        and     ah,0fch         ;clock low data low
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        and     ah,0fch         ;clock low data low
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax

        mov     bx,8000h        ;16 bits to send
        call    s3_send_serial
        add     si,2
        mov     bx,80h          ;8 bits to send
        call    s3_send_serial
                                ;stop bit
        or      ah,2            ;data_high
        out     dx,ax
        and     ah,0feh         ;clock low
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        pop     ax
        out     dx,ax           ;restore prev. clock for vertical retrace

        sti
        ret


s3_send_serial:
        and     ah,0fdh         ;send inverted data first
        test    word ptr cs:[si],bx
        jnz     s3_send_serial_1
        or      ah,2
s3_send_serial_1:
        out     dx,ax           ;not data out
        and     ah,0feh         ;clock low
        out     dx,ax

        xor     ah,2            ;now real data out
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        shr     bx,1            ;next data bit
        jnc     s3_send_serial
        ret

; input  ah     internal register to set
;        dx     port address of indexed register (data = index+1)
; output al     register value
in_crtc:
        call    GetCRTCAddr     ;get crtc address 3x4h
in_crtc_1:
        xchg    al,ah
        out     dx,al
        inc     dx
        jmp     $+2
        xchg    al,ah
        in      al,dx
        dec     dx
        ret

; input  ah     internal register to set
;        al     value to output
;        dx     port of index register (data register must be index + 1)
out_crtc:
        call    GetCRTCAddr     ;get crtc address 3x4h
out_crtc_1:
        xchg    al,ah
        out     dx,al
        inc     dx
        jmp     $+2
        xchg    al,ah
        out     dx,al
        dec     dx
        ret


; unlock s3 extended regs
unlock_s3:
        mov     ax,3848h
        jmp     short out_crtc

; unlock sc extended regs
unlock_sc:
        mov     ax,39a0h
        jmp     short out_crtc

; lock s3 extended regs
lock_s3:
        mov     ax,3800h
        jmp     short out_crtc

; lock sc extended regs
lock_sc:
        mov     ax,3900h
        jmp     short out_crtc

;;;;;;;;;;begin code for stealth 24
;
eeprom_tab_l            equ     20/2            ;10 words
index_m640              equ     0
index_m640h             equ     1
index_m640t             equ     2
index_m800              equ     3
index_m800h             equ     4
index_m800t             equ     5
index_m1024             equ     6
index_m1024h            equ     7
index_m960              equ     8
index_m1280_16          equ     9
index_m1280_256         equ     10
index_m5455             equ     11

COUNTER                 equ     7fh             ; 2K x 1
mon_port                equ     3c2h
mon_bit                 equ     10h
Read_Miscellaneous      EQU     03CCH           ;Misc output read register

Sequencer               EQU     03C4H           ;Sequencer index register

CRT_3B4                 EQU     03B4H           ;Monochrome CRT index addr
CRT_3D4                 EQU     03D4H           ;Monochrome CRT index addr
BT_FIX                  equ     1

;org_5c                  db      0
;---------------------------------------------------------------------------
;       EEPROM Data Format (Each entry 20 bytes)
;       db      0       ;bit7=vpol. bit6=hpol. bit5=interlace
;                        bit4,3   = reserved
;                        bit2,1,0 = entry
;       db      0,0,0   ;clock data (3 bytes)
eeprom_reg_index        label   byte
        db      3bh,0,1,2,3,4,5,6,7,10h,11h,16h,17h,5Dh,33h,0ffh
;
;---------------------------------------------------------------------------
;       input   (al)=eeprom table entry address
;       output  all registers saved except (ax)
upd_crtc_eeprom:
;htotal adjust
        push    bx
        push    cx
        push    dx
        push    ax
        call    Find_6845_Address
        mov     ax,0011h                ;unlock crtc
        out     dx,ax
        pop     ax
        mov     bx,offset eeprom_reg_index
        push    ax              ;(al)=address of eeprom +0
        inc     al              ;(al)=address of eeprom +1
;       inc     al              ;(al)=address of eeprom +2
pp_1:   inc     al              ;(al)=address of eeprom +3
        push    ax
        call    read_eeprom
        mov     cx,ax
        mov     al,cs:[bx]
        cmp     al,0ffh
        jz      pp_2
        mov     ah,cl
        out     dx,ax
        inc     bx
        mov     al,cs:[bx]
        cmp     al,0ffh
        jz      pp_2
        mov     ah,ch
        out     dx,ax
        inc     bx
        pop     ax
        jmp     pp_1

pp_2:   pop     ax
        pop     ax
        push    ax
        call    read_eeprom
        mov     cx,ax
        ;--------------------------------------------;
        ;  update vclk params & interlaced bit       ;
        ;--------------------------------------------;
;set interlace & clock select
        mov     ah,cl
        and     ah,28h          ;entry.5 interlace bit of cr42.5
                                ;entry.3 clk3 bit of cr42.3
        or      ah,3            ;clock select 0,1
        mov     al,42h          ;crtc 42 (clock & interlace)
        out     dx,ax
;set polarity
        push    dx
        mov     dx,3cch
        in      al,dx
        and     al,3fh
        and     cl,0c0h         ;polarity
        or      al,cl
        or      al,0ch          ;clock force to extended
        mov     dx,3c2h
        out     dx,al
        pop     dx
;clock program
        mov     bh,ch           ;1st byte
        pop     ax
        inc     al              ;offset +1
        call    read_eeprom
        mov     cl,al           ;2nd byte
        mov     bl,ah           ;3rd byte
;
        call    program_clk_chip_stl24

        pop     dx
        pop     cx
        pop     bx
        ret
;
;---------------------------------------------------------------------------
;       input   (cl)= 2nd byte, (bh)=1st byte, (bl)= 3rd byte
;       output  bx,cx destroed
;
;;      public  program_clk_chip_stl24
program_clk_chip_stl24 :
        push    ax
        push    dx

        mov     dx,3c4h
        mov     al,1
        out     dx,al
        mov     ah,al
        inc     dx
        in      al,dx
        push    ax
        or      al,20h
        out     dx,al           ;screen off

        call    Find_6845_Address
        mov     ax,0a039h       ;unlock sc regs
        out     dx,ax
        mov     ax,04838h       ;unlock s3 regs
        out     dx,ax

        mov     ch,80h          ;25     ;1000   ;25
skip_0_stl24:
        push    bx
        push    cx
        call    p_clock_stl24
        pop     cx
        pop     bx
        mov     dx,3c2h
        in      al,dx
        test    al,10h
        jnz     skip_2_stl24
        dec     ch
        jnz     skip_0_stl24
skip_2_stl24:

        mov     dx,3c4h
        mov     al,1
        out     dx,al
        inc     dx
        pop     ax              ;screen recover
        out     dx,al           ;LIN fix 12/17/92 should be al ; not ax

        call    wait_vertical_retrace_stl24
        call    wait_vertical_retrace_stl24

        pop     dx
        pop     ax
        ret

;
;---------------------------------------------------------------------------
;public p_clock
p_clock_stl24:
        mov     dx,3cch         ;read misc. out reg
        in      al,dx
        push    ax              ;save value
        or      al,0ch
        mov     dx,3c2h
        out     dx,al
        call    Find_6845_Address
        mov     al,42h          ;sc2
        out     dx,al
        xchg    al,ah
        inc     dx
        in      al,dx
        xchg    al,ah
        dec     dx
        push    ax              ;previous vclock selection

;unlock seq
        or      ah,2            ;data high
        mov     ch,6    ;5      ;toggle clk 5 times
        cli
kk_1_stl24:
        and     ah,0feh         ;clock low
        out     dx,ax
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        out     dx,ax
        dec     ch
        jnz     kk_1_stl24

        and     ah,0feh
        out     dx,ax
        out     dx,ax
        and     ah,0fch         ;clock low data low
        out     dx,ax
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        out     dx,ax
        and     ah,0fch         ;clock low data low
        out     dx,ax
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        out     dx,ax
;
        mov     ch,24
send_serial_stl24:
        and     ah,0fdh         ;send inverted data first
        shl     bx,1
        rcl     cl,1
        jc      send_serial_1_stl24
        or      ah,2
send_serial_1_stl24:
        out     dx,ax           ;not data out
        out     dx,ax
        and     ah,0feh         ;clock low
        out     dx,ax
        out     dx,ax
        xor     ah,2            ;now real data out
        out     dx,ax
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
        out     dx,ax
        dec     ch
        jnz     send_serial_stl24
;stop bit
        or      ah,2            ;data_high
        out     dx,ax
        out     dx,ax
        and     ah,0feh         ;clock low
        out     dx,ax
        out     dx,ax
        or      ah,1            ;clock high
        out     dx,ax
;
        pop     ax
        out     dx,ax           ;restore prev. clock for vertical retrace
        out     dx,ax
;
        pop     ax              ;save value
        mov     dx,3c2h         ;misc. out reg for vclock recover
        out     dx,al
        sti
        ret
;
;----------------------------------------------------------------------------
;        public  wait_vertical_retrace
;
wait_vertical_retrace_stl24:
        push    ax
        push    cx
        push    dx
        call    Find_6845_Address               ;Get CRTC address
        add     dl,6

        mov     cx,0
wv_0:   in      al,dx
        test    al,8
        jnz     wv_1
        loop    wv_0

        mov     cx,0
wv_1:   in      al,dx
        test    al,8
        jz      wv_2
        loop    wv_1

wv_2:   pop     dx
        pop     cx
        pop     ax
        ret
;
;---------------------------------------------------------------------------
        ;input cs:(si) = dat table start address to read
        ;all registers save except (ax)
read_eeprom_all:
        push    si
        push    bx
        push    cx
        push    dx
        mov     bl,00h
vcr_3:  push    bx
        call    read_conf
        mov     cs:[si],ax
        pop     bx
        add     si,2
        inc     bl
        and     bl,COUNTER
        jnz     vcr_3
        pop     dx
        pop     cx
        pop     bx
        pop     si
        ret

;---------------------------------------------------------------------------
        ;input al=adress, unlocked
        ;output ax=data
        ;all registers reserved
read_eeprom:
        push    bx
        mov     bx,ax
        call    read_conf
        pop     bx
        ret
;
;---------------------------------------------------------------------------
        ;input bl=adress
        ;output ax=data
        ;all registers reserved
read_conf:
        push    bx
        push    cx
        push    dx
        call    init_ports      ;video disabled ,crtc 41 bit1 set
                                ;(dx)=3d5/3b5   crtc index = 5ch selected
                                ;(al)=crtc 5ch data
;
        mov     bh,bl
        push    bx
        mov     cx,4
        mov     bx,0110000000000000b
        call    send_data_stl24 ;send read command
        pop     bx

        mov     cx,9
        call    send_data_stl24 ;send address
        mov     cx,16
        mov     bx,0
rc_1:
        and     al,0efh         ;clock low
        call    del_out
        shl     bx,1

        push    dx
        push    ax
        mov     dx,mon_port
        in      al,dx
        test    al,mon_bit
        pop     ax
        pop     dx

        jz      rc_2
        or      bl,1
rc_2:
        or      al,10h          ;clock high
        call    del_out
        loop    rc_1

        and     al,0efh         ;clock low
        call    del_out
;LIN    and     al,0bfh          ;chip select low
;LIN    call    del_out
        call    recover_ports
        mov     ax,bx
        pop     dx
        pop     cx
        pop     bx
        ret

;
;---------------------------------------------------------------------------
init_ports:
        mov     dx,3c4h
        mov     al,1
        out     dx,al
        inc     dx
        in      al,dx
        or      al,20h          ;screen off
        out     dx,al

        mov     dx,3cch
        in      al,dx
        mov     dx,3d4h
        test    al,1
        jnz     init_1
        mov     dx,3b4h
init_1:
        mov     ax,04838h
        out     dx,ax           ;unlock s3
        mov     ax,0a539h
        out     dx,ax           ;unlock sc

        mov     al,5ch
        out     dx,al
        inc     dx
        in      al,dx

        mov     byte ptr [org_5c] ,al           ; save the original cr.5c

        or      al,40h          ;enable chip
        and     al,0cfh
        out     dx,al
        ret
;
;---------------------------------------------------------------------------
recover_ports:
        mov     al, byte ptr [org_5c]          ; recover the original cr.5c
        and     al,0bfh         ;chip select low
        call    del_out         ;out dx(3d5.5c),al

        dec     dx              ;3d4/3b4
        mov     ax,038h
        out     dx,ax           ;lock s3
        mov     ax,039h
        out     dx,ax           ;lock sc

        mov     dx,3c4h
        mov     al,1
        out     dx,al
        inc     dx
        in      al,dx
        and     al,0dfh         ;screen on
        out     dx,al
        ret

        ;input bl=adress, (ax)=data
        ;output  all registers reserved
;write_conf:
;        push    bx
;        push    cx
;        push    dx
;        push    ax              ;data
;        call    init_ports      ;video disabled ,crtc 41 bit1 set
;                                ;(dx)=3d5/3b5   crtc index = 5ch selected
;                                ;(al)=crtc 5ch data
;                                ;out dx(3d5.5c),al
;        mov     bh,bl
;        push    bx
;        mov     cx,12
;        mov     bx,0100110000000000b
;        call    send_data_stl24 ;out dx(3d5.5c),al write enable command
;        call    a_clock
;;       and     al,7fh          ;chip select low
;        and     al,0bfh         ;chip select low
;        call    del_out         ;out dx(3d5.5c),al
;        call    a_clock
;;       or      al,80h          ;chip select high
;        or      al,40h          ;chip select high
;        call    del_out         ;out dx(3d5.5c),al
;        mov     cx,4
;        mov     bx,0111000000000000b
;        call    send_data_stl24 ;out dx(3d5.5c),al  erase command
;        pop     bx              ;address
;        push    bx
;        mov     cx,8
;        call    send_data_stl24
;        call    a_clock
;        and     al,0bfh         ;chip select low
;        call    del_out         ;out dx(3d5.5c),al
;        call    a_clock
;        or      al,40h          ;chip select high
;        call    del_out         ;out dx(3d5.5c),al
;        call    chk_ready
;        mov     cx,4
;        mov     bx,0101000000000000b
;        call    send_data_stl24 ;out dx(3d5.5c),al   write command
;        pop     bx              ;address
;        mov     cx,8
;        call    send_data_stl24 ;out dx(3d5.5c),al
;        mov     cx,16
;        pop     bx              ;data
;        call    send_data_stl24 ;out dx(3d5.5c),al
;        call    a_clock
;        and     al,0bfh         ;chip select low
;        call    del_out         ;out dx(3d5.5c),al
;        call    a_clock         ;clock high to low
;        or      al,40h          ;chip select high
;        call    del_out         ;out dx(3d5.5c),al
;        call    chk_ready
;        mov     cx,12
;        mov     bx,0100000000000000b
;        call    send_data_stl24 ;out dx(3d5.5c),al   write disable command
;        call    a_clock
;        and     al,0bfh         ;chip select low
;        call    del_out         ;out dx(3d5.5c),al
;        call    a_clock
;        call    recover_ports
;        pop     dx
;        pop     cx
;        pop     bx
;        ret

chk_ready:
        push    dx
        push    ax
wait_1: mov     dx,mon_port
        in      al,dx
        test    al,mon_bit
        jz      wait_1
        pop     ax
        pop     dx
        ret

a_clock:
        and     al,0dfh         ;data low
        or      al,10h          ;clock high
        call    del_out
        and     al,0efh         ;clock low
        call    del_out
        ret
;
;---------------------------------------------------------------------------
send_data_stl24:
        and     al,0cfh
        shl     bx,1
        jnc     send_data_1_stl24
        or      al,20h
send_data_1_stl24:
        call    del_out         ;data & clock low
        or      al,10h
        call    del_out         ;clock high
        loop    send_data_stl24
        ret

del_out:
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        out     dx,al
        ret
;
;---------------------------------------------------------------------------
Find_6845_Address PROC    NEAR
        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:
        POP     AX
        RET
Find_6845_Address ENDP
;
;end code for stealth 24

;/***************************************************************************
;*
;* FUNCTION NAME = GetDACTypeRtn
;*
;* DESCRIPTION   = Diamond specific DAC routine
;*
;*                 ENTRY POINT: GetDACTypeRtn
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

GetDACTypeRtn  PROC NEAR

        push    bx
        push    dx

        call    cmd_off
        in      al,dx

ddd_1:
        mov     ah,al
        in      al,dx
        cmp     al,ah
        jnz     ddd_1
        mov     bl,al

        mov     ah,8
        call    cmd_on
        cmp     al,8eh
        jz      music_dac

ddd_2:

        in      al,dx
        cmp     al,8eh
        jz      music_dac
        dec     ah
        jnz     ddd_2

        call    cmd_on
        in      al,dx
        mov     bh,al
        call    cmd_off
        mov     al,0ffh
        out     dx,al

        mov     ah,055h

ddd_3:
        call    cmd_on
        mov     al,ah
        out     dx,al
        call    cmd_off
        in      al,dx
        cmp     al,ah
        sub     ah,ah

ddd_4:
        call    cmd_on
        mov     al,bh
        out     dx,al
        call    cmd_off
        mov     al,bl
        out     dx,al

ddd_5:
        pop     dx
        pop     bx
        ret

music_dac:
        call    cmd_off
        mov     ah,2
        jmp short ddd_5

;enable access to dac command register

cmd_on:
        mov     dx,3c9h
        in      al,dx           ;reset sequencer
        mov     dx,3c6h
        in      al,dx
        jmp     $+2
        in      al,dx
        jmp     $+2
        in      al,dx
        jmp     $+2
        in      al,dx
        ret

;disable access to dac command register

cmd_off:
        mov     dx,3c9h
        in      al,dx           ;reset sequencer
        mov     dx,3c6h
        ret

GetDACTypeRtn  ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = SetDACCMDReg
;*
;* DESCRIPTION   = Diamond specific DAC routine
;*
;*                 ENTRY POINT: SetDACCMDReg
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

SetDACCMDReg PROC NEAR

        push    ax
        call    GetDACTypeRtn
        or      ah,ah
        jz      set_cmd_ret
        cmp     ah,2
        jz      set_cmd_music

        call    cmd_on
        pop     ax
        out     dx,al
        call    cmd_off

set_cmd_ret:
        ret

set_cmd_music:

        mov     ah,10h
        call    cmd_on
        cmp     al,8eh
        jz      qqq_3

qqq_2:
        in      al,dx
        cmp     al,8eh
        jz      qqq_3
        dec     ah
        jnz     qqq_2
        pop     ax
        ret

qqq_3:

        pop     ax
        out     dx,al
        ret

SetDACCMDReg ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = VGAWait
;*
;* DESCRIPTION   = wait for video retrace before a write to port
;*                 3C0h, register 10h
;*
;*                 ENTRY POINT: VGAWait
;*                 LINKAGE:   CALL FAR
;*
;* INPUT         = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ColorMode               equ     <WORD PTR [bp+12]>
TRUE                    equ     1
FeatureControlWrite     equ     03BAh   ; Read Feature Control Register

VGAWait PROC    NEAR
        sti
        push    ax
        push    cx
        push    dx
        mov     dx, FeatureControlWrite
        .if     < ColorMode eq TRUE >
            add     dx, 20h             ; use color ports
        .endif
        xor     cx,cx           ; time out in case a card never sets this bit
VGAWait1:
        in      al,dx
        test    al,8            ; look for retrace bit
        loopnz  VGAWait1        ; wait for retrace to end
        xor     cx,cx           ; time out in case a card never sets this bit
VGAWait2:
        sti
        nop
        nop                     ; 486     work around
        cli
        in      al,dx
        test    al,8            ; look for retrace bit
        loopz   VGAWait2        ;wait for retrace to begin again

        pop     dx
        pop     cx
        pop     ax
        ret
VGAWait ENDP


IF DEBUG

;/*
;** Equates for com ports
;*/

COM1_DAT=       03f8H           ; base for COM1
COM2_DAT=       02f8H           ; base for COM2
R_IEN   =       1               ; Interrupt enable
R_IER   =       2               ; interrupt ID
R_LCR   =       3               ; line control registers
R_MCR   =       4               ; modem control register
R_LSR   =       5               ; line status register
R_MSR   =       6               ; modem status regiser
R_DLL   =       0               ; divisor latch least sig
R_DLM   =       1               ; divisor latch most sig

; Exactly one of the next two lines should be uncommented to select port
;UR_DAT =       COM2_DAT        ; select COM2 = 02f8H
UR_DAT  =       COM1_DAT        ; select COM1 = 03f8H
UR_IEN  =       UR_DAT+1        ; Interrupt enable
UR_IER  =       UR_DAT+2        ; interrupt ID
UR_LCR  =       UR_DAT+3        ; line control registers
UR_MCR  =       UR_DAT+4        ; modem control register
UR_LSR  =       UR_DAT+5        ; line status register
UR_MSR  =       UR_DAT+6        ; modem status regiser
UR_DLL  =       UR_DAT          ; divisor latch least sig
UR_DLM  =       UR_DAT+1        ; divisor latch most sig


;/***************************************************************************
;*
;* FUNCTION NAME = DPRINTF - Debug Printf
;*
;* DESCRIPTION   =
;*
;*      Dprintf is a kernel debug print formatting package.
;*      This version is a hastily stripped version of another routine
;*      with the same name.
;*      Due to difficulties passing variable length argument lists
;*      through a call gate transition, only one argument, a zero
;*      terminated string is passed to this routine.  The string
;*      will be sent to either COM1 or COM2 depending on the definition
;*      of UR_DAT.
;*
;*      About the only intelligent thing this routine can do is process
;*      XON/XOFF characters from the equipment attached to the debug
;*      port so that the output will not overrun the recieving device.
;*      However after recieving an XOFF, this routine will simply spin
;*      in a loop waiting for XON.  Using equipment/software on that
;*      can keep up on the debug port is recommended.
;*
;*      The format string is an ASCIZ string which can contain
;*      literal characters.
;*
;*      Literal characters
;*          - any character not part of a format specification.  Special
;*            non-printing characters are:
;*              \n      - CRLF
;*              \t      - tab
;*              \b      - bell
;*              \\      - \
;*
;*      WARNINGS
;*          As befitting a debug routine, DPRINTF does not have a whole lot
;*          of "failsafe" code in it.
;*
;* INPUT         = (sp+6  ) = segment of string
;*                 (sp+4  ) = offset of string
;*                 (sp+2  ) = seg of return address
;*                 (sp    ) = offset of return address
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

DPRINTF PROC    far

        push    bp
        mov     bp,sp
        push    ds
        push    es
        push    di
        push    si
        push    dx
        push    cx
        push    bx
        push    ax
        cld

;/*
;** Change string address to far ptr on stack
;*/
        add     bp,6
        mov     si,[bp]
        add     bp,2
        mov     ax,[bp]
        push    ax
        pop     ds

;/*
;**     Scan format string for next character
;**
;**     (ds:si) = address of format string
;**     (ss:bp) = address of next argument
;*/

public dpf1
dpf1:   lodsb                   ; (al) = format string byte
        and     al,al
        je      dpf3            ; all done
        cmp     al,'\'
        jnz     dpf2            ; got the character

;/*
;**       it's an "\" escape code - crack the argument character
;*/

        lodsb
        and     al,al
        je      dpf3            ; all done, ignore hanging \
        xchg    ah,al
        mov     al,0Ch
        cmp     ah,'n'
        jne     dpf1$5          ; not \n
        mov     al,0dH
        call    putchar
        mov     al,0aH
        jmp     SHORT dpf2      ; print LF

dpf1$5: cmp     ah,'t'
        mov     al,9
        je      dpf2            ; is \t
        cmp     ah,'b'
        mov     al,7
        je      dpf2            ; is \b
        xchg    ah,al
dpf2:   call    putchar
        jmp     dpf1

;/*
;**       have the end of the format string - exit
;*/

dpf3:   pop     ax
        pop     bx
        pop     cx
        pop     dx
        pop     si
        pop     di
        pop     es
        pop     ds
        pop     bp
        ret     4       ; pop 4 bytes after return address

DPRINTF ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = inchr
;*
;* DESCRIPTION   = input character
;*
;* INPUT         = NONE
;* OUTPUT        = 'z' set if no character
;*                 'z' clear if char
;*                   (al) = char
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

IF 1
inchr   PROC NEAR
        ret
inchr   ENDP
ELSE
inchr   PROC NEAR
        mov     dx,UR_LSR
        in      al,dx
        and     al,1
        jz      inchr1
        mov     dx,UR_DAT
        in      al,dx
        and     al,07fh
inchr1: ret
inchr   ENDP
ENDIF

;/***************************************************************************
;*
;* FUNCTION NAME = putchar
;*
;* DESCRIPTION   = put a character on the console
;*
;* INPUT         = (al) = character
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

putchar PROC    NEAR
        pushf
        cli
        push    dx
        push    cx
        push    bx
        push    ax              ; (al) = character

;/*
;**     see if CTL-Q or CTL-S
;*/

        pushf
        cli
        call    inchr
        jz      putc3           ; no characters incomming
        cmp     al,19           ; ctl-S?
        jnz     putc3           ; no, ignore

;/*
;**     have ctl-s.  wait till we see ctl-Q
;*/

putc2:  call    inchr
        jz      putc2
        cmp     al,17
        jnz     putc2

putc3:  popf
        mov     dx,UR_LSR
putc4:  in      al,dx
        test    al,020h
        jz      putc4

;/*
;**     ready.  crank it out!
;*/

        mov     dx,UR_DAT

        pop     ax
        out     dx,al

        pop     bx
        pop     cx
        pop     dx
        popf
        ret
putchar ENDP

ENDIF   ;DEBUG



;/************************************************************************
;*
;* Hardware I/O function
;*
;************************************************************************/

;************************************************************************
;*
;* FUNCTION NAME = HWInpByte
;*
;* DESCRIPTION   =
;*
;* INPUT         = Port from which to read
;* OUTPUT        = EAX has data read.
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*************************************************************************

HWINPBYTE       PROC    FAR

                push    bp                      ; 
                mov     bp,sp                   ; 

                xor     ax,ax                   ; 
                mov     dx,word ptr [bp+6]      ; 
                in      al,dx                   ; 

                pop     bp                      ; 
                ret     2                       ; 

HWINPBYTE       ENDP

;************************************************************************
;*
;* FUNCTION NAME = HWInpWord
;*
;* DESCRIPTION   =
;*
;* INPUT         = Port from which to read
;* OUTPUT        = EAX has data read.
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*************************************************************************

HWINPWORD       PROC    FAR

                push    bp                      ; 
                mov     bp,sp                   ; 

                xor     ax,ax                   ; 
                mov     dx,word ptr [bp+6]      ; 
                in      ax,dx                   ; 

                pop     bp                      ; 
                ret     2                       ; 

HWINPWORD       ENDP

;************************************************************************
;*
;* FUNCTION NAME = HWOutpByte
;*
;* DESCRIPTION   =
;*
;* INPUT         = Port to write to
;*                 Byte of data to write
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*************************************************************************

HWOUTPBYTE      PROC    FAR

                push    bp                      ; 
                mov     bp,sp                   ; 

                mov     dx,word ptr [bp+8]      ; 
                mov     al,byte ptr [bp+6]      ; 
                out     dx,al                   ; 

                pop     bp                      ; 
                ret     4                       ; 

HWOUTPBYTE      ENDP

;************************************************************************
;*
;* FUNCTION NAME = HWOutpWord
;*
;* DESCRIPTION   =
;*
;* INPUT         = Port to write to
;*                 Word of data to write
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*************************************************************************

HWOUTPWORD      PROC    FAR

                push    bp                      ; 
                mov     bp,sp                   ; 

                mov     dx,word ptr [bp+8]      ; 
                mov     ax,word ptr [bp+6]      ; 
                out     dx,ax                   ; 

                pop     bp                      ; 
                ret     4                       ; 

HWOUTPWORD      ENDP

R2SEG   ENDS

; THIS MUST BE LINKED LAST!
END     BVH_INIT

