;*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.;
;*****************************************************************************/
        page ,132
;***********************************************************************
;
;   Module          = VIOSUBR.ASM
;
;   Description     = Private AI code
;
;   Function        = Does AVIO text work
;
;
;   Change log:
;   Date      Mark         APAR      Description
;   --------  ------------ --------- -----------------------------------
;
;***********************************************************************

INCL_GPIBITMAPS EQU     1
INCL_FONTFILEFORMAT     equ     1       ; to include pmfont.inc
include os2.inc
include eddinclt.inc

include eddhcone.inc
include eddhmacr.inc
include eddhtype.inc

?DF     equ     1       ; we dont want _TEXT segment defined
include cmacros.inc
include eddhavio.inc

ifdef _8514
include 8514.inc
endif

ifndef PALETTE_MGR
 .err "PALETTE_MGR is not defined."
 .err "This file can't be built without Palette Manager."
endif ;/* end PALETTE_MGR */

ifdef _8514
include viomacro.inc
endif


extrn  _eddt_InvalidateCache    :PROC


_DATA           segment dword use32 public 'DATA'

_DATA           ends

_TEXT           segment dword use32 public 'CODE'
                assume  cs:FLAT, ds:FLAT, es:FLAT

IFDEF _8514

          align   4
cProc AVIO24HVLine,     <PUBLIC>, <edi,ebx,ecx>
        parmD   xPos
        parmD   yPos
        parmD   xWidth      ; one based
        parmD   yHeight     ; one based
cBegin

        WaitQIdle
        WaitQ   1
        ; Set the mode to use foreground color for the horizontal/vertical line.
        outwQ   MODE,(MODE_2DECODE+MD_PS_ONES+MD_UP_FALSE)

        dec     yHeight         ; make zero based

        dec     xWidth          ; make zero based
        mov     ecx, xWidth

ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      @f
        sub     ecx, ecx        ; zero clear
        mov     eax,xPos
        mov     dx,3
        mul     dx
        mov     xPos,ax
        mov     ebx,_Shadow8514Regs.Color_1     ; Foreground color
        swap    ebx
endif


next_x_pos:

ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      @f
        mov     edi,3

next_color:
        WaitQ   2
        movzx   ax,bl
        outwQ   COLOR_1,ax
@@:
endif

        WaitQ   5

        mov     eax,xPos
        outwQ   X0,ax

        mov     eax,yPos
        outwQ   Y0,ax

        outwQ   LX,cx
        outwQ   LY,yHeight

        outwQ   CMD_FLAGS,CMDSOLID

ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      short @f
        rol     ebx,8
        inc     xPos
        dec     di
        jnz     short next_color
@@:
endif
        cmp     xWidth,0
        jz      short @f

        dec     xWidth
ifdef   BPP24
        rol     ebx,8
endif
        jmp     next_x_pos
@@:

        WaitQ   1
        ; Set the mode back to plane mode for Fonts
        outwQ   MODE,(MODE_2DECODE+MD_PS_COPY+MD_UP_FALSE)

cEnd

ENDIF ;_8514


ifdef _8514
  ifdef   BPP24
        align   4
cProc   Copy16MonoToVRAM, <PUBLIC>, <esi, edi, ebx, ecx>
        parmD   pSystemMemory
        parmD   pVRAMMemory
        parmD   total_width     ; = ulPels
        parmD   ulWidth
        parmD   total_height    ; = ulHeight
        parmD   ulBPPFormat
        parmW   StartBits       ; Number of bits into the first byte

        localW  x_src
        localW  y_src
        localW  x_dst
        localW  y_dst
        localW  tempRows                ; working scan counter
        localW  CenterWords             ; # words in center of src blt
        localW  ncxExt                  ; cxExt adjust to src word boundaries
        localW  nxDst                   ; dest x origin adj to src word bdry's
        localW  BltFlags                ; local src to board blt flags
        localW  src_width               ; width of memory bitmap
cBegin

        mov     ebx,pVRAMMemory
        mov     y_dst, bx
        swap    ebx
        mov     x_dst, bx

        WaitQIdle
        WaitQ   4                       ; need room in the queue
        mov     bx,x_dst                ; set up scissor rectangle
        mov     ax,bx
        or      ax,XMIN_2DECODE
        outwQ   XMIN,ax
        mov     eax,total_width         ; width of the blt
        add     ax,bx                   ; Calculate the right edge of the scissor rect.
        or      ax,XMAX_2DECODE
        outwQ   XMAX,ax

        outwQ   MODE,(MODE_2DECODE+MD_PS_VAR+MD_UP_FALSE); variable pattern
        outwQ   CMD_FLAGS,CMDMONO   ; 1 bpp blt from memory
        mov     dx,COLOR_0_WAIT     ; variable data port.

        mov     ax, StartBits
        mov     x_src, ax
        mov     y_src, 0
        swap    esi

PURGE_PIPELINE  equ 1
ODDBYTE         equ 2
PREFETCH        equ 4

        ; calculate phase shift
        mov     cx, x_dst               ; target pel
        mov     bx, cx                  ; save it
        and     cx, 7                   ; bit # in destination byte
        mov     ax, x_src               ; source pel
        and     ax, 7                   ; bit # in source byte
        sub     cx, ax                  ; get right shift count
        jnz     short @F
        jmp     ss_mono_equal_align
@@:
        ; get new destination
        mov     ax, bx                  ; target pel
        and     ax, XY_SIGNIFICANT AND NOT 7
        mov     nxDst, ax               ; byte aligned destination

        ; calculate output size
        mov     edx, total_width        ; 0-based width in pels
        add     bx, dx                  ; offset of last pel
        sub     bx, ax                  ; less offset of nxDst
        shr     bx, 4                   ; get 0-based word count
        inc     bx                      ; 1-based word count

        ; calculate total bytes to read
        mov     ax, x_src
        add     dx, ax                  ; offset of last pel
        and     dx, NOT 7
        shr     dx, 3                   ; 0-based offset of last byte
        and     ax, NOT 7
        shr     ax, 3                   ; 0-based offset of first byte
        sub     dx, ax                  ; 0-based byte count
        inc     dx                      ; 1-based byte count

        ; set blt flags
        mov     BltFlags, 0             ; clear flags
        or      cl, cl                  ; negative shift?
        jns     short @F
        or      BltFlags, PREFETCH
        dec     dx
@@:
        test    dx, 1                   ; odd # of bytes?
        jz      short @F
        or      BltFlags, ODDBYTE
@@:
        shr     dx, 1
        cmp     dx, bx                  ; matching word count?
        jz      short @F
        or      BltFlags, PURGE_PIPELINE
@@:
        ; set widths for input and output
        mov     CenterWords, dx
        shl     bx, 4                   ; 1-based pel count
        dec     bx                      ; 0-based pel count
        mov     ncxExt, bx              ; save 0-based pel output count

        ; H/W initializations common to all mono to board cases.
        WaitQ   8                       ; need room in the queue
        outwQ   LX,ncxExt               ; 0-based width of blt
        mov     eax, total_height
        outwQ   LY, ax
        inc     ax                      ; make height (still in ax) 1 based
        mov     tempRows,ax             ; working counter storage
        outwQ   Y0,y_dst                ; destination y origin
        outwQ   X0,nxDst                ; destination x origin
        outwQ   CMD_FLAGS,CMDMONO       ; 1 bpp blt from memory

        ; get pointer to bitmap in esi
;;        mov     ebx,AIxfer.pbmhSrc
;;        movzx   edi,[ebx].bm_width      ; scansize in pels
        mov     edi, ulWidth            ; scansize in pels
        inc     edi                     ; make one based*****
        add     edi,7                   ; round up to byte boundary
        and     edi,NOT 7
        shr     edi,3                   ; get byte count
        mov     src_width,di            ; save the width
        movzx   eax,y_src               ; src y origin
        mul     edi                     ; offset to scan of interest
;;        mov     esi,[ebx]               ; get pointer to virtual memory
        mov     esi,pSystemMemory       ; get pointer to virtual memory
        add     esi,eax                 ; add offset into bitmap
        movzx   eax,x_src               ; pixels into scanline
        shr     ax, 3                   ; make byte offset
        add     esi,eax                 ; -> byte containing pixel

        mov     dx, COLOR_0_WAIT        ; variable data port

        ; use phase difference to calculate the mask needed for
        ; preserving bits to be pipelined to the next operation.
        mov     ch, 0FFh                ; for creating mask
        and     cl, 7                   ; phase shift MOD 8
        shr     ch, cl                  ; 0s to high end,this is the ror mask

ss_mono_nextscan:
        push    esi                     ; save scan start offset
        mov     bh, 0                   ; clear initial bits (not needed)

        ; save initial bits directly into BH
        test    BltFlags, PREFETCH      ; need to prefetch a nibble?
        jz      short @F                ; if not, continue
        lodsb                           ; get first byte
        ror     ax, cl                  ; shift rightmost bits into AH
        mov     bh, ah
        not     ch
        and     bh, ch
        not     ch
@@:
        mov     di,CenterWords          ; # src words to be fetched
        shr     di,1                    ; Preserve the odd word count
        jz      short ss_mono_no_dword
@@:
        lodsd                           ; fetch P2|P3|P0|P1:P2|P3|P0|P1
        DoPhaseShift                    ; phase shift and output AX

        ror     eax,16                  ; move the hi-word down to low-word
        DoPhaseShift                    ; phase shift and output AX

        dec     di                      ; drop word count
        jnz     short @B                ; for all whole src words to output...

ss_mono_no_dword:
        mov     di,CenterWords          ; # src words to be fetched
        and     di,1                    ; The fetch for the odd word if any
        jz      short @F

        lodsw
        DoPhaseShift                    ; phase shift and output AX
@@:
        ; handle odd byte case (also does PURGE_PIPELINE function)
        test    BltFlags, ODDBYTE
        jz      short @F
        mov     al, [esi]               ; get next byte
        DoPhaseShift                    ; phase shift and output AX
        jmp     short ss_mono_next
@@:
        ; output pipelined nibble, ignoring rest of word output.
        test    BltFlags,PURGE_PIPELINE
        jz      short ss_mono_next
        and     al, ch
        or      al, bh
        ; for 8514, an additional out is needed for alignment
        IFNDEF S3
        ror     al,3                    ; into hw position
        out     dx,ax                   ; output pipelined nibble
        ENDIF
        out     dx,ax

ss_mono_next:
        pop     esi                     ; recover original src offset
        movzx   eax,src_width           ; get total number of bytes
        add     esi,eax                 ; go to next source scan

        dec     tempRows                ; 1 less row to blt
        jnz     ss_mono_nextscan        ; else for all rows to blt...
        jmp     ss_done                 ; get out if no more...

;------------------------------------------------------------------------------
; Mono src, src and destination nibble alignments are equal.
;------------------------------------------------------------------------------

ss_mono_equal_align:

        mov     edx,total_width         ; width of blt in pixels
        inc     dx

        mov     ax,x_src                ; src left edge x
        mov     bx,ax                   ; need it later also
        and     ax,15                   ; bit position in src word
        add     ax,cx                   ; adjust for right phase shift
        neg     ax                      ; # pixels to adjust dest x by
        add     ax,x_dst                ; dest adj. for src word fetches
        and     ax,XY_SIGNIFICANT       ; mask to just hw bits
        mov     nxDst,ax                ; save new left x for bottom level

        mov     ax,bx                   ; src left edge x
        add     ax,dx                   ; point to right edge x + 1
        and     bx,Not 15               ; src left rounded down to word bdry
        sub     ax,bx                   ; # pixels in extended scan
        mov     di,ax                   ; need this later
        add     ax,15                   ; round up to word boundary
        shr     ax,4                    ; now # whole src words to fetch
        mov     CenterWords,ax          ; save for bottom level

        mov     ax,di                   ; # pixels in extended scan
        add     ax,cx                   ; adjust extent by phase shift
        add     ax,15                   ; round up to word boundary
        and     ax,Not 15               ; now # pixels in adj extent
        dec     ax                      ; 0-based for hw
        mov     ncxExt,ax               ; save for bottom level

        inc     ax                      ; back to 1-based new x extent
        shr     ax,4                    ; # words in extent
        mov     BltFlags,0
        cmp     ax,CenterWords          ; equal to src word fetches ?
        jbe     short @F                ; yes, no pipelined pixels...
        or      BltFlags,PURGE_PIPELINE ; have to write pipelined pixels
@@:

        ; H/W initializations common to all mono to board cases.
        WaitQ   8                       ; need room in the queue
        outwQ   MODE,(MODE_2DECODE+MD_PS_VAR+MD_UP_FALSE); variable pattern
        outwQ   LX,ncxExt               ; 0-based width of blt
        mov     eax, total_height
        outwQ   LY, ax
        inc     ax                      ; make height (still in ax) 1 based
        mov     tempRows,ax             ; working counter storage
        outwQ   Y0,y_dst                ; destination y origin
        outwQ   X0,nxDst                ; destination x origin
        outwQ   CMD_FLAGS,CMDMONO       ; 1 bpp blt from memory

        ; get pointer to bitmap in esi
;;        mov     ebx,AIxfer.pbmhSrc
;;        movzx   edi,[ebx].bm_width      ; scansize in pels
        mov     edi, ulWidth            ; scansize in pels
        inc     edi                     ; make one based*****
        add     edi,7                   ; round up to byte boundry
        and     edi,not 7
        shr     edi,3                   ; get byte count
        mov     src_width,di            ; save the width
        movzx   eax,y_src               ; src y origin
        mul     edi                     ; offset to scan of interest
;;        mov     esi,[ebx]               ; get pointer to virtual memory
        mov     esi,pSystemMemory       ; get pointer to virtual memory
        add     esi,eax                 ; add offset into bitmap
        movzx   eax,x_src               ; pixels into scanline
        mov     cx,(1 Shl  8) + 4       ; shift count for xyaddr
        shr     ax,cl
        xchg    ch,cl                   ; round to specified boundary
        shl     ax,cl                   ; now make byte offset
        add     esi,eax                 ; -> byte containing pixel

        mov     dx,COLOR_0_WAIT         ; variable data port
        mov     bx,tempRows

ss_mono_eqScan_lp:

        IFNDEF  MEMMAPIO
        mov     edi,esi                 ; save scan offset
        ELSE
        mov     edx,esi                 ; wont be using dx in twistbits
        ; @DMS can we go over  64k here
        mov     edi,pVRAM
        ENDIF
        movzx   ecx,CenterWords         ; # whole src words to fetch
        shr     cx,1
        jz      short ss_mono_eqno_dword


@@:
        ; @DMS can do this faster with a dword load instead of two word loads
        twistbits16
        twistbits16

        loop    @B                      ; for all whole src words to output...

ss_mono_eqno_dword:
        movzx   ecx,CenterWords
        and     cx,1                    ; the last fetch for the odd word
        jz      short @F

        twistbits16
@@:

        IFNDEF  MEMMAPIO
        mov     esi,edi                 ; recover original src offset
        ELSE
        mov     esi,edx                 ; recover original src offset
        ENDIF
        movzx   eax,src_width           ; get total number of bytes
        add     esi,eax                 ; go to next source scan

        dec     Bx                      ; 1 less row to blt
        jnz     Short ss_mono_eqScan_lp ; else for all rows to blt...

ss_done:

;;  begin - temp temp temp
        WaitQ   2
        outwQ   XMIN,(XMIN_2DECODE+0)   ;; set scissor to full screen
        mov     ax,SCR_S3_WIDTH-1
        or      ax,XMAX_2DECODE
        outwQ   XMAX,ax                 ; set max scissor x extent

        WaitQ   1                                           ;; (temp temp)
        outwQ   MODE,(MODE_2DECODE+MD_PS_COPY+MD_UP_FALSE)  ;; restore (temp temp)
;;  end - temp temp temp
cEnd

  endif ; BPP24
ENDIF ;_8514

_TEXT           ends

END

