;*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    60,132
        TITLE   CGAREAD.ASM -- CGA Buffer Read Routines

;/*****************************************************************************
;*
;* SOURCE FILE NAME = CGAREAD.ASM
;*
;* DESCRIPTIVE NAME = CGA Buffer Read Routines 
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION  BVS Device Handler for Windowable Sessions   
;*              This module contains the equivalent of the OS/2 1.1
;*              hooks for Windowable and Advanced VIO.
;*
;* FUNCTIONS    ReadCellTypes, ReadCharStr,
;*              ReadCellStr, LocateBuffAddr
;*
;* NOTES        NONE
;*             
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES  _MOVSW, MOVSB_SKIP_SI   
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;****************************************************************************/

        .286c                                     ; 286 protect mode instructions

        .xlist
        INCLUDE struc.inc                         ; Structure macro
        INCLUDE error2.inc                        ; Subsystem error equates
        INCLUDE vdhstruc.inc                      ; Buffer update data structures
        INCLUDE vdhequ.inc                        ; Buffer update equates
        .list

        EXTRN   _MOVSW         : FAR              ; Move words from DS:SI to ES:DI
        EXTRN   MOVSB_SKIP_SI  : FAR              ; Move bytes from DS:SI to ES:DI

R2CSEG  SEGMENT WORD PUBLIC 'CODE'
        ASSUME  CS:R2CSEG,DS:NOTHING,ES:NOTHING

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     ReadCellTypes                
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler read cell types  
;*                                                    
;* FUNCTION:    Process read cell types sub-function.   
;*                                                    
;* ENTRY POINT: ReadCellTypes                         
;*   LINKAGE:   Near Call from BUFFERUPDATE rouinte   
;*                                                    
;* INPUT:                                             
;*                                                    
;* AX = 0                                             
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (source data buffer - LVB, PVB) 
;*   DWORD  Application data address  (target data buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (0)                                 
;*   WORD   Starting row                               (source row)   
;*   WORD   Starting column                            (source column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (net used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:                                            
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     All                                   
;*                                                    
;* INTERNAL REFERENCES: LocateBuffAddr               
;*                                                    
;* EXTERNAL REFERENCES: _MOVSW                        
;*                                                    
;****************************************************************************/

        PUBLIC  ReadCellTypes
ReadCellTypes   PROC    NEAR

        mov     bx, 1                              ; Set indicator for word move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?
            shr     cx, 1                          ; Adjust for word move

;/*
;**   On exit from LocateBuffAddr:                     
;**     If PVB & LVB flags are set then BX = LVB selector   
;**        [bp].PVB_Sel = PVB selector 
;**     else BX = LVB or PVB selector  
;**                                                     
;**   If both PVB and LVB are selected then the LVB must sync up with 
;**   PVB starting at the row, column until repeatfactor/2 is reached. 
;**   The valid cell type for this OS/2 release is a word of zero. 
;*/

            .if     <[bp].PVB_Sel a 0>             ; PVB & LVB flags set?
                push    ds                         ; Save parameter block addr
                push    si                         ; 
                push    cx                         ; Save repeat factor
                mov     ds, [bp].PVB_Sel           ; Use PVB as source
                mov     si, ax                     ; 
                mov     es, bx                     ; Use LVB as destination
                mov     di, ax                     ; 
                call    _MOVSW                     ; Refresh LVB from PVB
                pop     cx                         ; Restore repeat count
                pop     si                         ; Restore paramter block addr
                pop     ds                         ; 
            .endif                                 ; 
            les     di, [si].AppDataAddr           ; Setup destination address
            sub     ax, ax                         ; Clear return code
            rep     stosw                          ; Transfer zeros to user buffer
        .endif                                     ; 
        ret

ReadCellTypes   ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     ReadCharStr                  
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler read characters  
;*                                                    
;* FUNCTION:    Process read characters sub-function.   
;*              The characters are read from either PVB or LVB  
;*              starting at the specified row, column location.  
;*              Line wrap occurs if the end of a line is reached. 
;*              Read function is terminated if the end of PVB or 
;*              LVB is reached.  The characters read are placed  
;*              in the specified buffer and the number of chars  
;*              read is returned in the RepeatFactor field of  
;*              the parameter block.                 
;*                                                    
;* ENTRY POINT: ReadCharStr                           
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* AX = 0                                             
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (source data buffer - LVB, PVB) 
;*   DWORD  Application data address  (target data buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (1)                                 
;*   WORD   Starting row                               (source row)   
;*   WORD   Starting column                            (source column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      Application data buffer = characters read  
;*              RepeatFactor = number of characters read  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     All registers                         
;*                                                    
;* INTERNAL REFERENCES: LocateBuffAddr               
;*                                                    
;* EXTERNAL REFERENCES: _MOVSW, MOVSB_SKIP_SI       
;*                                                    
;****************************************************************************/

        PUBLIC  ReadCharStr
ReadCharStr     PROC    NEAR

        sub     bx, bx                             ; Set indicator for byte move
        call    LocateBuffAddr                     ; Setup LVB, PVB selectors
        .if     <nc>                               ; Continue?

;/*
;**   On exit from LocateBuffAddr:                     
;**     If PVB & LVB flags are set then BX = LVB selector   
;**        [bp].PVB_Sel = PVB selector 
;**     else BX = LVB or PVB selector  
;**                                                     
;**   If both PVB and LVB are selected then the information requested
;**   will be read into the LVB first before it is returned.
;*/

            .if     <[bp].PVB_Sel a 0>             ; PVB & LVB flags set?
                push    ds                         ; Save parameter block addr
                push    si                         ; 
                push    cx                         ; Save repeat factor
                push    ax                         ; 
                mov     ds, [bp].PVB_Sel           ; Use PVB as source
                mov     si, ax                     ; 
                mov     es, bx                     ; Use LVB as destination
                mov     di, ax                     ; 
                call    _MOVSW                     ; Refresh LVB from PVB
                pop     ax                         ; Restore LVB address
                pop     cx                         ; Restore repeat count
                pop     si                         ; Restore paramter block addr
                pop     ds                         ; 
            .endif                                 ; 
            les     di, [si].AppDataAddr           ; Setup destination address
            mov     ds, bx                         ; Setup source selector
            mov     si, ax                         ; Setup source offset
            mov     bx, [bp].Retrace               ; Pass retrace information
            call    MOVSB_SKIP_SI                  ; Read characters
            sub     ax,ax                          ; Clear return code
        .endif                                     ; 
        ret

ReadCharStr     ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     ReadCellStr                  
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler read cells   
;*                                                    
;* FUNCTION:    Process read cells sub-function.   
;*              The cells are read from either PVB or LVB starting 
;*              at the specified row, column location. Line wrap 
;*              occurs if the end of a line is reached.  Read  
;*              function is terminated if the end of PVB or LVB  
;*              is reached.  The cells read are placed in the  
;*              specified buffer and the number of cells read  
;*              is returned in the RepeatFactor field of the  
;*              parameter block.                     
;*                                                    
;* ENTRY POINT: ReadCellStr                           
;*   LINKAGE:   Near Call from BUFFERUPDATE routine   
;*                                                    
;* INPUT:                                             
;*                                                    
;* AX =   0                                           
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* PARAMETER BLOCK FORMAT:                            
;*                                                    
;*   SIZE   DESCRIPTION                               
;*   ----   -----------                               
;*                                                    
;*   WORD   Parameter length                          
;*   WORD   Flags                                      (source data buffer - LVB, PVB) 
;*   DWORD  Application data address  (target data buffer)  
;*   DWORD  Application data2 address (not used in this call)  
;*   WORD   Index (2)                                 
;*   WORD   Starting row                               (source row)   
;*   WORD   Starting column                            (source column)   
;*   WORD   Secondary row                              (not used in this call)  
;*   WORD   Secondary column                           (not used in this call)  
;*   WORD   RepeatFactor                               (input and output length)  
;*   WORD   LogicalBufSel                             
;*                                                    
;* OUTPUT:      Application data buffer = character cells read  
;*              RepeatFactor = sum of char/attr pairs read  
;*                                                    
;* EXIT-NORMAL: AX = 0                                
;*                                                    
;* EXIT-ERROR:  AX = Error from LocateBuffAddr      
;*                                                    
;* EFFECTS:     All                                   
;*                                                    
;* INTERNAL REFERENCES: LocateBuffAddr               
;*                                                    
;* EXTERNAL REFERENCES: _MOVSW                        
;*                                                    
;****************************************************************************/

        PUBLIC  ReadCellStr
ReadCellStr     PROC    NEAR

        mov     bx, 1                              ; Set indicator for word move
        call    LocateBuffAddr                     ; On exit: BX = sel, AX = off
        .if     <nc>                               ; Continue?
            shr     cx, 1                          ; Adjust for word move

;/*
;**   On exit from LocateBuffAddr:                     
;**     If PVB & LVB flags are set then BX = LVB selector   
;**        [bp].PVB_Sel = PVB selector 
;**     else BX = LVB or PVB selector  
;**                                                     
;**   If both PVB and LVB are selected then the information requested
;**   will be read into the LVB first before it is returned.
;*/

            .if     <[bp].PVB_Sel a 0>             ; PVB & LVB flags set?
                push    ds                         ; Save parameter block addr
                push    si                         ; 
                push    cx                         ; Save repeat factor
                push    bx                         ; Save LVB selecotr, offset
                push    ax                         ; 
                mov     ds, [bp].PVB_Sel           ; Use PVB as source
                mov     si, ax                     ; 
                mov     es, bx                     ; Use LVB as destination
                mov     di, ax                     ; 
                call    _MOVSW                     ; Refresh LVB from PVB
                pop     ax                         ; Restore LVB address
                pop     bx                         ; 
                pop     cx                         ; Restore repeat count
                pop     si                         ; Restore paramter block addr
                pop     ds                         ; 
            .endif                                 ; 
            les     di, [si].AppDataAddr           ; Setup destination address
            mov     ds, bx                         ; Setup source selector
            mov     si, ax                         ; Setup source offset
            mov     bx, [bp].Retrace               ; Pass retrace information
            call    _MOVSW                         ; Transfer cells to destination
            sub     ax, ax                         ; Clear return code
        .endif                                     ; 
        ret                                        ; 

ReadCellStr     ENDP

;/****************************************************************************
;*                                                    
;* SUBROUTINE NAME:     LocateBuffAddr               
;*                                                    
;* DESCRIPTIVE NAME:    Video device handler locate video buffer addr 
;*                                                    
;* FUNCTION:    Determine the source/target buffer address for the 
;*              read/write function based on the information in the 
;*              parameter buffer and the mode data buffer.  
;*                                                    
;* ENTRY POINT: LocateBuffAddr                        
;*   LINKAGE:   Near Call from ReadCharacters, ReadCells,  
;*                             RepeatAttribute,    
;*                                                    
;*                                                    
;* INPUT:                                             
;*                                                    
;* AX = 0                                             
;* BX = Type of transfer                              
;*      0 - byte transfer (character or attribute only)   
;*      1 - word transfer (character cell - char/attr pair)  
;* SS:BP  --->  Stack frame                        (see VDHSTRUC.INC) 
;* DS:SI  --->  Parameter block buffer            (see CGABUFUP.ASM) 
;* ES:DI  --->  Mode data in environment buffer (see CGABUFUP.ASM) 
;*                                                    
;* OUTPUT:      AX = source buffer offset           
;*              BX = source buffer selector         
;*              CX = adjusted repeat factor         
;*              DX = offset to the end of source buffer   
;*              DS:[SI].RepeatFactor = # of bytes to be transfered 
;*              CY = 1 Error encountered            
;*                                                    
;* EXIT-NORMAL: CY = clear                            
;*                                                    
;* EXIT-ERROR:  CY = set                              
;*              AX = 0  if RepeatFactor = 0 for char or attr move 
;*                                                = 0 or 1 for cell move  
;*              AX = ERROR_VIO_COL                   
;*              AX = ERROR_VIO_ROW                   
;*                                                    
;* EFFECTS:     AX, BX, CX, DX, CY                   
;*                                                    
;* INTERNAL REFERENCES: None                          
;*                                                    
;* EXTERNAL REFERENCES: None                          
;*
;****************************************************************************/

        PUBLIC  LocateBuffAddr
LocateBuffAddr  PROC    NEAR


;/*
;**   Validate row, column value based on the current text mode setting.
;**   Make sure CY is set if validation fails.
;*/

        mov     cx, es:[di].TextCols              ; Get column value from EnvBuf
        .if     <cx a [si].Col>                   ; Valid input column value?
            mov     cx, es:[di].TextRows          ; Get row value from EnvBuf
            .if     <cx a [si].Row>               ; Valid input row value?

;/*
;**  Minimum transfer count for either character or attribute is 1 and
;**  the minimum transfer count for a cell is 2.
;**  Transfer will not take place if minimum transfer count is not met.
;**  This is determine by the request type indicated in BX on entry.
;*/

                mov     cx, [si].RepeatFactor     ; Get repeat factor
                .if     <cx a bx>                 ; Pass minimum requirement?

;/*
;**   Calculate the starting offset within the PVB or LVB based on the
;**   starting row, column value.
;*/
 
                    mov     ax, [si].Row          ; Buffer offset = (parm row
                    mul     es:[di].TextCols      ;   * screen columns + parm
                    add     ax, [si].Col          ;   column) * 2
                    add     ax, ax                ; AX = buffer offset

;/*
;**   Determine how many bytes left to the end of the video buffer.
;**   Length = size of PVB - video buffer offset
;*/

                    mov     dx, es:[di].BufferLenLo
                    sub     dx, ax                ; Calculate eob length

;/*
;**   For either character or attribute only transfer, cut the end of
;**   buffer length in half to allow for proper determination of buffer
;**   overflow condition.
;*/

                    .if     <zero bx>              ; Byte transfer request?
                        shr                      dx, 1  ; Adjust end of buffer length
                    .endif                         ; 

;/*
;**   If overflow condition occurs, use the adjusted end-of-buffer
;**   length as the repeat factor count.
;*/

                    .if     <cx a dx>              ; Over flow buffer?
                        mov    cx, dx              ; Repeat factor = eob length
                    .endif                         ; 
                    mov     [si].RepeatFactor, cx

;/*
;**   Setup BX with either the PVB or LVB selector.  Selection of which 
;**   buffer to use is based on the Flags field in the parameter block. 
;**                                                     
;**   If both PVB and LVB flag bits are ON            
;**   then                                              
;**       BX = LVB selector                             
;**       [bp].PVB_Sel = PVB selector                  
;**   else                                              
;**       BX = LVB or PVB as indicated by either of the two flag bits 
;*/

                    mov     bx, [bp].PVB_Sel        ; Assume PVB update
                    test    [si].Flags, LVB_SEL_BIT ; 
                    .if     <nz>                    ; LVB requested?
                        test                     [si].Flags, PVB_SEL_BIT ; 
                        .if                      <z>  ; LVB update only?
                            mov     [bp].PVB_Sel, 0 ; Indicate as such
                        .endif                      ; 
                        mov        bx, [si].LogicalBufSel ; Use LVB instead
                    .else                           ; PVB only!
                        mov        [bp].PVB_Sel, 0  ; Indicate BX has PVB
                        inc        [bp].Retrace     ; Retrace wait required
                    .endif                          ; 
                    clc                             ; Normal completion
                .else                               ; 
                    sub     ax, ax                  ; Clear return code
                    mov     [si].RepeatFactor, ax   ; Indicate no-op
                    stc                             ; Force exit condition
                .endif                              ; 
            .else                                   ; 
                mov     ax, ERROR_VIO_ROW           ; 
                stc                                 ; 
            .endif                                  ; 
        .else                                       ; 
            mov     ax, ERROR_VIO_COL               ; 
            stc                                     ; 
        .endif                                      ; 
        ret                                         ; 

LocateBuffAddr  ENDP

R2CSEG  ENDS
        END
