;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
ifdef DCAF
        PAGE     55,132
        TITLE    ScrBits
        SUBTITLE Header
;/*****************************************************************************
;*
;* SOURCE FILE NAME = SCRBITS.ASM
;*
;* DESCRIPTIVE NAME = GetScreenBits and SetScreenBits Entry Points.
;*
;*
;* VERSION      V2.0
;*
;* DATE         04/22/92
;*
;* DESCRIPTION
;*             These are two of the main entry points for DCAF
;*
;*
;* FUNCTIONS   GetScreenBits
;*             SetScreenBits
;*             init_devinfo_struc
;*
;* NOTES       NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   04/22/92                     Created for DCAF 1.3
;*   08/01/92                     Changed to 32-bit for DCAF 2.0
;*
;*****************************************************************************/

        .386p
        .xlist
INCL_ERRORS             equ     1
INCL_DDICOMFLAGS        equ     1
INCL_GRE_REGIONS        equ     1
INCL_GPIREGIONS         equ     1
INCL_GRE_DCAF           equ     1
INCL_GRE_CLIP           equ     1
INCL_GRE_SCREEN         equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1
        include pmgre.inc
        include pmerr.inc       ; how is this meant to be included??
        include driver.inc
        include assert.mac
        include protos.inc
        include extern.inc
        include egafam.inc

;/*
;** Include DCAF macros
;*/
        include dcafmac.inc

        .list

        .MODEL  FLAT
        ASSUME  CS:FLAT, SS:FLAT, DS:FLAT, ES:FLAT

        .CODE


;** --------------------------Exported-Routine-------------------------;
;/**********************************************************************
;**
;** GetScreenBits
;** -------------
;**
;** A region of screen pixel data is saved into the memory provided by
;** the caller. It can be compressed, converted into a format suitable
;** for another supported display device and will stop either when:
;**
;**   - the supplied memory area is full
;**   - the requested region has been returned.
;**
;** The region can be specified as either:
;**
;**   - a pointer to a single rectangle (rcl - long values)
;**   - a region handle
;**
;** setting the GSB_OPT_RGN flag in the flCmd parameter accordingly.
;** If a RECTL is specified then it is assumed to be inclusive
;** (as provided by GetBoundsData(GBD_SCREEN)).
;**
;** The function modifies the supplied rectangle/region to indicate the
;** area that was NOT returned in the call. If the whole requested region
;** was returned the rectangle/region will be a null area.
;**
;** The supplied DC must be direct - it is the source of the pixel data.
;**
;** This is not a drawing primitive, therefore no correlation, boundary
;** accumulation or drawing will take place.
;**
;** Entry:
;**   None
;** Returns:
;**   DX:AX  = 1 => entire area was saved in buffer
;**   DX:AX  = 2 => a subset of the area was saved in buffer
;** Error Returns:
;**   DX:AX  = 0
;** Registers Preserved:
;**   EBX, EDI, ESI
;** Registers Destroyed:
;**   EAX,ECX,EDX,FLAGS
;** Calls:
;** History:
;**   Fri April 24, 1992, Andy Rogers. Created it
;**********************************************************************/

GetScreenBits PROC SYSCALL USES EBX EDI ESI,
        hdc       :HDC,
        hrgn      :ULONG,
        pDest     :PVOID,
        pulLength :PVOID,
        flCmd     :ULONG,
        hddc      :PVOID,
        FunN      :ULONG

LOCAL   ulBufferSize: DWORD            ; The buffer size

;/*
;** Check that the supplied hddc is valid
;*/
        ddc?    hddc

;/*
;** Ensure that the direction flag is cleared (i.e. inc pointers)
;*/
        cld

;/*
;** Enter the driver - grab semaphore etc.
;*/
        mov     esi,hddc               ; ESI --> ddc
        mov     edx,esi
        call    enter_driver
        jc      gsb_exit_no_lock        ; EAX = 0 on an error

;/*
;** Initialise the device structure
;*/
        INVOKE  init_devinfo_struc,hddc

;/*
;** Perform some initial error checking
;**
;** Read COM flags into edi
;*/
        mov     edi,FunN

;/*
;** This call is invalid in a path or area
;*/
        test    edi,COM_PATH or COM_AREA
        jnz     gsb_error_path_or_area

;/*
;** Check that the DC is direct (i.e. the screen)
;*/
        cmp     gsbdev.GSB_DEV_STRUCT.gsb_fDirectDC,TRUE
        jne     gsb_error_bad_device

;/*
;** Now check the parameters
;** First make sure the buffer length is not too big (<= 64K)
;*/
        mov     edi,pulLength
        ASSUME  EDI:PTR DWORD
        mov     eax,[edi]
        cmp     eax,10000h
        ja      gsb_error_bad_count

;/*
;** Now check that the buffer size is big enough
;*/
        cmp     eax,MIN_BUFFER_SIZE
        jb      gsb_error_bad_count

;/*
;** Save buffer size
;*/
        mov     ulBufferSize, eax

;/*
;** Check the flags supplied are ones we know about
;*/
        mov     eax,flCmd
        test    eax,NOT GSB_OPT_FLAGS   ; Check for invalid options
        jnz     gsb_error_invalid_option ; Jump to error handler if necessary

;/*
;** Check whether we are dead
;*/
        cmp     fGrimReaper,WE_BE_DEAD
        je      gsb_exit_PM_session_background

;/*
;** Call the common compression function
;*/
        INVOKE   CompressScreenBits,
                 hdc,
                 hrgn,
                 pDest,
                 ulBufferSize,
                 flCmd,
                 hddc

        or      eax, eax
        jz      gsb_exit_eax

;/*
;** Check to see if a NULL region was passed in - the length
;** will not be in the buffer
;*/
        cmp     eax, 3
        jne     @F
        mov     eax, 1          ; NULL region is an uninterrupted exit
        xor     ecx, ecx        ; with buffer size of 0
        mov     edi, pulLength
        mov     [edi], ecx
        jmp     short gsb_exit_eax

@@:
;/*
;** Update the length of the buffer passed in
;*/
        mov     esi, pDest     ; The length is stored at the start of the buffer
        ASSUME  ESI:PTR DWORD
        mov     edi, pulLength

        mov     ebx, [esi]
        mov     [edi],ebx

        jmp     short gsb_exit_eax

;/*
;** Error handlers
;*/

gsb_exit_PM_session_background:
        mov     eax, PMERR_PEL_NOT_AVAILABLE
        save_error_code
        push    0
        jmp     short gsb_exit_eax_on_stack

gsb_error_path_or_area:
        mov     eax,PMERR_INV_IN_PATH
        test    edi,COM_PATH
        jnz     short gsb_log_error_in_eax
        mov     eax,PMERR_INV_IN_AREA
        jmp     short gsb_log_error_in_eax

gsb_error_bad_count:
        mov     eax,PMERR_INV_LENGTH_OR_COUNT
        jmp     short gsb_log_error_in_eax

gsb_error_invalid_option:
        mov     eax,PMERR_INV_FORMAT_CONTROL
        jmp     short gsb_log_error_in_eax

gsb_error_bad_device:
        mov     eax,PMERR_INV_DC_TYPE

gsb_log_error_in_eax:
        save_error_code

gsb_exit_error_logged:
        xor     eax,eax

gsb_exit_eax:

;/*
;** Release the Driver semaphore etc. before exiting.
;** (without losing return code)
;*/
        push    eax

;/*
;** Reset the VGA registers we have used
;*/
        mov     al,MM_ALL               ;Enable all planes
        mov     dx,EGA_BASE+SEQ_DATA
        out     dx,al
        mov     ax,GRAF_ENAB_SR         ;Disable set/reset
        mov     dl,GRAF_ADDR
        out     dx,ax
        mov     ax,DR_SET shl 8 + GRAF_DATA_ROT
        out     dx,ax
        mov     ax,0FF00h+GRAF_BIT_MASK ;Enable all bits
        out     dx,ax

gsb_exit_eax_on_stack:
        call     leave_driver

;/*
;** Recover return code and extend into dx
;*/
        pop     eax

gsb_exit_no_lock:
        fw_zero <ecx>
        ret

GetScreenBits ENDP


;--------------------------Exported-Routine-----------------------------;
;/*********************************************************************
;* SetScreenBits                                                      *
;*                                                                    *
;* A region of screen pixel data is reconstructed from the buffer     *
;* provided by the caller and copied into a memory bitmap of the      *
;* display device.  The buffer contains data provided by the          *
;* GetScreenBits function.                                            *
;*                                                                    *
;* The supplied DC must be of memory type with a bitmap selected.     *
;*                                                                    *
;* For performance reasons there is no clipping.  If a rectangle      *
;* exceeds the bitmap dimensions then the function will terminate     *
;* immediately with an error logged. The bitmap may be left in a      *
;* partially drawn state as prior rectangles may have been copied     *
;* into it.                                                           *
;*                                                                    *
;* This is a drawing primitive, therefore correlation, boundary       *
;* accumulation and drawing could take place.  However this is        *
;* essentially a private interface (at least the caller is well       *
;* behaved) so we will totally ignore the function bits, and will     *
; * always just do the drawing and nothing else.                      *
;*                                                                    *
;* The routine may be passed a region handle, in which case the area  *
;* defined by the set bits will be added to the region.               *
;*                                                                    *
;* The VGA driver will only ever be passed 4bpp data.                 *
;*                                                                    *
;**********************************************************************
;*
;* Entry:
;*       None
;* Returns:
;*       DX:AX = TRUE (1)
;* Error Returns:
;*       DX:AX = FALSE (0)
;*       Error logged
;* Registers Preserved:
;*       SI,DI,BP,DS
;* Registers Destroyed:
;*       AX,BX,CX,DX,ES,FLAGS
;* Calls:
;*       enter_driver
;*       leave_driver
;* History:
;*
;* Wed 22-Apr-1992       -by-    Mark Berry, Data Connection Ltd.
;*     Rewrote it.
;* Sat 20 Jul 1991,       by     Greg Loten.
;*     Created it for DCAF 1.2.
;*********************************************************************/

SetScreenBits PROC SYSCALL USES EBX EDI ESI,
        hdc       :HDC,
        pBuffer   :PVOID,
        cBytes    :ULONG,
        hrgn      :ULONG,
        hddc      :PVOID,
        FunN      :ULONG

;/*
;** Grab the driver semaphore etc.
;*/
        cld
        mov     esi,hddc                ; ESI --> ddc
        ASSUME  ESI:PTR DDC
        mov     edx,esi
        call    enter_driver
        jc      ssb_exit_no_lock        ; DX:AX = 0 on an error

;/*
;** Perform some initial error checking
;*/
        mov     edi,FunN                 ;Has COM_ flags in it
        test    edi,COM_PATH or COM_AREA ;This call is invalid in a path or area
        jnz     ssb_path_or_area
        test    [esi].ddc_fb,DDC_DEVICE  ;Must be a bitmap
        jnz     ssb_is_phy_device
        test    [esi].ddc_fb,DDC_PRESENT ;Must have a surface (bitmap selected)
        jz      ssb_no_surface

;/*
;** Do some checking of the passed data length
;** 0 is a valid data length - but we must not access the buffer
;** (but any other value < the header size is invalid)
;*/
        mov     eax,cBytes
        or      eax,eax
        jz      ssb_good_exit           ; buffer length 0 - nothing to do
        cmp     eax,10000h              ; >64K ?
        ja      ssb_error_bad_count     ; Error if so
        cmp     eax, size PACKETHDR
        jb      ssb_error_bad_count     ; Not enough data for a header

;/*
;** Compare data length with length in buffer
;*/
        mov     esi, pBuffer
        ASSUME  ESI:PTR PACKETHDR
        cmp     eax, [esi].phd_length
        jne     ssb_error_bad_count

        jmp     done_checks

ssb_path_or_area:
        mov     eax,PMERR_INV_IN_PATH
        test    edi,COM_PATH
        jnz     ssb_log_error_in_eax
        mov     eax,PMERR_INV_IN_AREA
        jmp     short ssb_log_error_in_eax

ssb_error_bad_count:
        mov     eax,PMERR_INV_LENGTH_OR_COUNT
        jmp     short ssb_log_error_in_eax

ssb_is_phy_device:
        mov     eax,PMERR_INV_DC_TYPE
        jmp     short ssb_log_error_in_eax

ssb_no_surface:
        mov     eax,PMERR_BITMAP_NOT_SELECTED
        ;jmp     short ssb_log_error_in_eax

ssb_log_error_in_eax:
        save_error_code

ssb_exit_error_logged:
        xor     eax,eax
        jmp     ssb_exit

done_checks:
        INVOKE  DecompressScreenBits, hddc, hrgn, pBuffer
        and     eax,eax
        jz      ssb_exit

ssb_good_exit:
        mov     eax,1

ssb_exit:
;/*
;** Release the driver semaphore
;*/
        call    leave_driver
ssb_exit_no_lock:
        fw_zero <ecx>
        ret

SetScreenBits ENDP


;/**********************************************************************
;**
;** init_devinfo_struc
;** ------------------
;**
;** A routine to initialise the DCAF devinfo struct for the VGA display
;** driver
;**
;** Fills in the following information:
;**
;**         fDirectDC
;**         cxScreenWidth
;**         cyScreenHeight
;**         usScreenBitsPerPel
;**         fbScreenFormatFlags
;**         pScreenStart
;**         cbScanLineDelta
;**         cPlanes
;**
;** Parameters:
;**         phdc - pointer to direct DC
;**
;** Returns:
;**         None
;** Registers Preserved:
;**         di, si
;** Registers Destroyed:
;**
;** Calls:
;** History:
;** Mon April 27, 1992, Andy Rogers. Created it
;**
;**********************************************************************/
ALIGN 4
init_devinfo_struc PROC SYSCALL USES ESI,
        init_hddc :DWORD           ; Direct DC handle

;/*
;** Get access to DCAF structure
;*/
        lea     ebx, gsbdev
        ASSUME  EBX:PTR GSB_DEV_STRUCT

;/*
;** Fill in all values
;*/

;/*
;** See if we have a direct DC or not
;*/
        mov     esi,init_hddc              ; ESI --> ddc
        ASSUME  ESI:PTR DDC

        test    [esi].ddc_fb, DDC_DEVICE
        jz      not_direct_dc
        mov     [ebx].gsb_fDirectDC, TRUE
        jmp     dc_type_filled_in
not_direct_dc:
        mov     [ebx].gsb_fDirectDC, FALSE

dc_type_filled_in:

        mov     [ebx].gsb_cxScreenWidth, SCREEN_CX
        mov     [ebx].gsb_cyScreenHeight, SCREEN_CY
        mov     [ebx].gsb_ulScreenBitsPerPel, 4
        mov     [ebx].gsb_fbScreenFormatFlags,GSB_OPT_4BPP or GSB_OPT_PLANAR
        mov     [ebx].gsb_cbScanLineDelta, 640 / 2 / 4
        mov     [ebx].gsb_cPlanes, 4

;/*
;** Store pointer to the screen bits
;*/
        mov     eax, sdScreen.sd_pBits
        mov     [ebx].gsb_pScreenStart, eax
        ret

init_devinfo_struc ENDP


endif ; DCAF

end
