;*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.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CRITSEC.ASM
;*
;* DESCRIPTIVE NAME = Critical Sections
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/21/89
;*
;* DESCRIPTION  This file contains critical sections that must be aligned so  
;*              as to not cross page boundaries, as well as any data they     
;*              access.  We use the fact that segments are aligned on page    
;*              boundaries, so that our critical sections will be protected   
;*              from page faults as long as they don't fill a whole page.     
;*              This can be checked at initialization in a firewall.  In      
;*              addition, there are .erre directives at the end of the code   
;*              segment in this file to halt compilation if it's size exceeds 
;*              a page size.  Unfortunately, the system page size can change  
;*              in future releases of OS/2.  If this file compiles, but the   
;*              firewall causes a rip, then the page size has probably        
;*              changed.  In that case, adjust the PAGESIZE constant defined  
;*              on the "make" command line.  Since there's no way to guarantee
;*              that the desired data segment will be in RAM when it is       
;*              accessed, any data accessed from within a critical section    
;*              must be stored in a fixed memory segment, in this case        
;*              PtrData.  The Data segment, if any, in this file may contain  
;*              relevant data for the critical code, but data in it cannot be 
;*              accessed from within the cli/sti bracket.                     
;*
;* FUNCTIONS    LoadGreyPalette
;*              FarSetHWPalette
;*              tHWPalette
;*              etHWPalette
;*              LoadKColorPalette
;*              RESET_BOARD_STATE
;*                                
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   08/22/88                     Wes Rupel [wesleyr] Moved JeffPar's EGA
;*                                changes to 8514.
;*   01/10/89                     Bob Grudem [bobgru] Moved to beginning of
;*                                segment to prevent page faults in critical
;*                                section.
;*   01/21/89                     Written by Bob Grudem
;*   06/23/90                     Bob Grudem [bobgru] Rewrote to reduce
;*                                hardware snow during palette animation.
;*   10/07/90                     Bob Grudem [bobgru] Commented out the polling
;*                                because it slows down the system noticeably.
;*                                The snow is still annoying during palette
;*                                animation, but some other method besides
;*                                polling the vertical restrace should be used
;*                                to avoid it.
;*****************************************************************************


.286p
        .xlist
        include cmacros.inc
ifdef PALMGR
INCL_GPIBITMAPS         equ                      1   ;for RGB2 defintion
INCL_GPILOGCOLORTABLE   equ                      1
endif
        include pmgre.inc
        include driver.inc
        include 8514.inc
        include 8514mem.inc
        include palette.inc
        .list


        page

;/*
;**  PtrData segment
;** 
;**  Data is here if it needs to be present at interrupt-time, or if we
;**  cannot allow it to be swapped out, such as when it is accessed from
;**  within a cli/sti critical section.
;*/

sBegin  PtrData
        externB screen_busy

;/*
;**  abPalScratch is scratch space used by SetHWPalette to translate
;**  color components.  By preprocessing the color data, we reduce the
;**  time spent between the first and last "out" instructions, which
;**  helps to reduce "snow" during palette animation.
;*/

abPalScratch    db      SIZE_HW_PAL * 4 dup (0)

sEnd    PtrData

sBegin  Data
        externB fGrimReaper
        externW wDisplay                          ;Display Type
sEnd    Data

;/*
;**  Code segment
;** 
;**  Code is here if it contains a cli/sti critical section.  This file
;**  is linked first, so these subroutines are at the beginning of the
;**  segment.  Segments are loaded a page at a time, so as soon as one
;**  of these subroutines is called, it will be entirely in memory, as
;**  long as it doesn't extend beyond a page boundary.  We can check for
;**  code crossing a page boundary with a .errnz directive.
;*/

sBegin  PalSeg
        assumes cs,PalSeg

;/*
;**-----------------------------------------------------------------------;
;*/
begin_crit_code label   byte
;/*
;**-----------------------------------------------------------------------;
;*/

        externW PalSegData
        externW MyPtrPalSegData
        externW MyPtrCodeData

ifdef PALMGR
        externB argbLinearTo8514
        externB argbLinearTo8515
endif

;/***************************************************************************
;*
;* FUNCTION NAME = LoadGreyPalette
;*
;* DESCRIPTION   = 
;*                 Registers Preserved:
;*                       AH,BX,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AL,CX,DX,FLAGS
;*                                                                           
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   LoadGreyPalette,<PUBLIC,NEAR>
cBegin

;/*
;** Load a greyscale palette...
;*/
        Mov     Cx,64                   ; will always load 64 color entries
grey_palette_load_loop:
        Mov     Dx,RAMDAC_WADDR         ; set index of next RGB to set
        Cli                             ; entering critical region
        Out     Dx,Al
        Mov     Dx,RAMDAC_RGB           ; send RGB data to this port
        Out     Dx,Al                   ; set R
        Out     Dx,Al                   ; set G
        Out     Dx,Al                   ; set B
        Sti                             ; exit critical region
        Inc     Al                      ; bump to next color index
        Loop    grey_palette_load_loop  ; for all palette entries to load...
cEnd

page
;/***************************************************************************
;*
;* FUNCTION NAME = SetHWPalette
;*
;* DESCRIPTION   = 
;*    Set the given RGB values into the 8514's hardware palette.  The 8-bit
;*    components of the input values are converted to 6-bit components by
;*    shifting off the low two bits.  Note:  If it becomes necessary to shrink
;*    PtrData, then this subroutine can easily be rewritten to load the color
;*    values from Data into registers, thereby avoiding memory references
;*    within the cli/sti bracket.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS,ES   
;*                 Registers Destroyed:   
;*                       AX,BX,CX,DX,FLAGS
;*                                                                           
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

ifdef PALMGR

CHUNK_SIZE      equ     256

        CPUMode 386

cProc SetHWPalette,<PUBLIC,NEAR,NODATA>,<si,di,ds>
        parmW   usFirst
        parmW   crgb
        parmD   prgb
        parmW   fOverrideReaper

cBegin

;/*
;** -----------------------------------------------------------------------;
;**  If the PM screen group is "dead", then don't change the palette.
;**  When we are resurrected, this function will be called to reinstate
;**  the correct PM palette.  However, if the fOverrideReaper flag is
;**  set, set the colors in anyway.
;** -----------------------------------------------------------------------;
;*/

        cmp     fOverrideReaper,0
        ja      @F
        cmp     fGrimReaper,WE_BE_DEAD
        je      shwp_exit
@@:

;/*
;** -----------------------------------------------------------------------;
;**  Fill the palette scratch buffer with the translated colors.  The
;**  buffer format is:
;** 
;**  batch count (word)
;**  batch start index (byte)
;**  batch colors (packed 3-byte rgb's, stored in order of R, G, B)
;** -----------------------------------------------------------------------;
;*/

        cld                                        ; work up in address
        mov     bx,PalSegOFFSET argbLinearTo8514
        cmp     wDisplay,DISPLAY_8515              ; if this is the 8514 driver
        jne     @F                                 ; this may be a Dallas monitor
        mov     bx,PalSegOFFSET argbLinearTo8515
@@:
        lds     si,prgb
        assumes ds,nothing
        mov     di,PtrDataBASE
        mov     es,di
        assumes es,PtrData
        mov     di,PtrDataOFFSET abPalScratch

shwp_fill_scratch_next_batch:
        mov     ax,crgb
        usmin_ax CHUNK_SIZE
        sub     crgb,ax
        mov     cx,ax
        stosw                                     ; store next batch count
        jcxz    shwp_set_in_colors
        mov     al,byte ptr usFirst
        add     usFirst,cx
        stosb                                     ; store next batch starting index

shwp_fill_scratch_buffer:
        lodsd                                     ; EAX = rgb

        ror     eax,16                            ; rotate rgb2_bRed into AL
        shr     al,2                              ; convert 8-bit to 6-bit
        xlatb   cs:[bx]                           ; convert to 8514/8515 value
        stosb                                     ; store in scratch table

        rol     eax,8                             ; rotate rgb2_bGreen into AL
        shr     al,2
        xlatb   cs:[bx]                           ; convert to 8514/8515 value
        stosb

        rol     eax,8                             ; rotate rgb2_bBlue into AL
        shr     al,2
        xlatb   cs:[bx]                           ; convert to 8514/8515 value
        stosb

        loop    shwp_fill_scratch_buffer
        jmp     short shwp_fill_scratch_next_batch

;/*
;** -----------------------------------------------------------------------;
;**  Run through the batches, setting colors into the hardware palette.
;**  The batch size is whatever is needed to reduce hardware snow to
;**  an acceptable level, whatever can be done during the vertical retrace.
;**  This routine is relative seldom called, so speed is not an issue.
;**  Snow, however is visible and is an issue.
;** -----------------------------------------------------------------------;
;*/

shwp_set_in_colors:
        mov     ax,es
        mov     ds,ax
        assumes ds,PtrData
        mov     si,PtrDataOFFSET abPalScratch

shwp_restart:
        lodsw                                     ; get count
        or      ax,ax                             ; if 0, we're done
        jz      shwp_exit
        xchg    ax,cx

        lodsb                                     ; get starting index
        cli                                       ; entering critical region
shwp_slam_color:
        mov     dx,RAMDAC_WADDR                   ; set index of next RGB to set
        out     dx,al
        mov     dx,RAMDAC_RGB                     ; send RGB data to this port
        outsb
        outsb
        outsb
        inc     al
        loop    shwp_slam_color
        sti                                       ; exit critical region

        jmp     short shwp_restart
shwp_exit:
cEnd
        CPUMode 286

else

cProc  SetHWPalette,<PUBLIC,NEAR>,<ds>
        parmW   usFirst
        parmW   crgb
        parmD   prgb
        parmW   fOverrideReaper

cBegin

        cld                                       ; work up in address

        lds     si,prgb
        assumes ds,nothing
        mov     di,PtrDataBASE
        mov     es,di
        assumes es,PtrData
        mov     di,PtrDataOFFSET abPalScratch

        Sub     Al,Al
        Mov     Cx,256                  ; will always load 256 color entries
        Cld                             ; work up in address
color_palette_load_loop:
        Mov     Dx,RAMDAC_WADDR         ; set index of next RGB to set
        Cli                             ; entering critical region
        Out     Dx,Al
        Mov     Dx,RAMDAC_RGB           ; send RGB data to this port
        Outsb                           ; set R
        Outsb                           ; set G
        Outsb                           ; set B
        Sti                             ; exit critical region
        Inc     Al                      ; bump to next color index
        Loop    color_palette_load_loop ; for all palette entries to load...
cEnd
endif ; PALMGR

page

;/***************************************************************************
;*
;* FUNCTION NAME = LoadKColorPalette
;*
;* DESCRIPTION   = 
;*
;*                 Registers Preserved:
;*                       BH,SI,DI,BP,DS,ES 
;*                 Registers Destroyed:    
;*                       AX,BL,CX,DX,FLAGS 
;*                                                                           
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   LoadKColorPalette,<PUBLIC,NEAR>
cBegin

        Sub     Bl,Bl
        Sub     Ah,Ah
        Mov     Cx,256                  ; will always load 256 color entries
kcolor_palette_load_loop:
        Mov     Dx,RAMDAC_WADDR         ; set index of next RGB to set
        Cli                             ; entering critical region
        Mov     Al,Bl
        Out     Dx,Al
        Mov     Dx,RAMDAC_RGB           ; send RGB data to this port
        Mov     Al,Ah
        Out     Dx,Al                   ; set R
        Sub     Al,Al
        Out     Dx,Al                   ; set G
        Out     Dx,Al                   ; set B
        Mov     Ah,0ffh
        Sti                             ; exit critical region
        Inc     Bl                      ; bump to next color index
        Loop    kcolor_palette_load_loop; for all palette entries to load...
cEnd

;/*
;** This label is compared to DOSPAGESIZE in DeviceSpecificInit
;*/
        public  end_crit_code
end_crit_code   label   byte

page
ifdef   KLUGE

;/***************************************************************************
;*
;* FUNCTION NAME = RESET_BOARD_STATE
;*
;* DESCRIPTION   = 
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,ES  
;*                 Registers Destroyed:     
;*                       AX,DX,FLAGS        
;*                                                                           
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   RESET_BOARD_STATE,<PUBLIC,NEAR>
cBegin

;/*
;** We return to VGA mode and leave gracefully:
;*/

        cli
        mov     ax,53h                            ;set CRTC mode
        mov     dx,22e8h                          ; 
        out     dx,ax                             ; 
        mov     al,2                              ;set misc I/O back to VGA
        mov     dx,4ae8h                          ; 
        out     dx,ax                             ; 
        mov     ax,0ah                            ;set CRTC status
        mov     dx,2e8h                           ; 
        out     dx,ax                             ; 
        mov     ax,33h                            ;set CRTC mode
        mov     dx,22e8h                          ; 
        out     dx,ax                             ; 
        mov     al,0ffh                           ;set pixel mask
        mov     dx,2eah                           ; 
        out     dx,al                             ; 
        sti

cEnd
endif  ;KLUGE
sEnd    PalSeg

end
