;*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 = 8514.inc
;*
;* DESCRIPTIVE NAME = 8514 include file
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION  definitions and macros for the 8514 driver
;*
;* 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
;*   02/26/89  @D1A               P.J.Vickers IBM Hursley DCR 24230
;*                                Add support for the DALLAS monitor
;*   01/19/89  @D2A               AVIO CellSize Modifications, Data Connection Ltd.
;*                                Add definition of cell-size table structure
;*   06/28/88                     Revision 3.5 geoffs
;*                                Fix up LoadPattern macro, add non-ES loading   
;*                                versions of Grab- and Release- Screen.         
;*   05/09/88                     Revision 1.9 geoffs
;*                                Merged rev 1.7 and 1.8 because 1.7 was lost    
;*                                when delta'ing in 1.8 (got it?)                
;*   05/06/88                     Revision 1.8 geoffs
;*                                Alter WaitQ macro to allow rewind of          
;*                                accumulated # outs to 8514/A queues.          
;*   04/27/88                     Revision 1.6 geoffs
;*                                Made all ports WAIT ports instead of DISCARD  
;*                                port #s, added WAIT_PORT_BIT definition.      
;*   01/29/88                     Revision 1.2 geoffs
;*                                Extend secondary decode values to 16 bit      
;*                                quantities.                                   
;*   01/27/88                     Revision 1.1 geoffs
;*                                Initial revision                              
;*
;*****************************************************************************/

;/*
;** I/O port definitions for the INMOS RAMDAC:
;*/

RAMDAC_PMASK    Equ     002eah          ; pixel mask
RAMDAC_RADDR    Equ     002ebh          ; read lut index address
RAMDAC_WADDR    Equ     002ech          ; write lut index address
RAMDAC_RGB      Equ     002edh          ; rgb data port

;/*
;** I/O port definitions for the 8514/A Update Controller (primary decodes):
;** (NOTE: We utilize the discard feature i/o ports)
;*/

WAIT_PORT_BIT   Equ     0100000000000000b; reset this bit in port # to get
                                        ; discard port instead of wait port

Y0              Equ     0c2e8h          ; src y coordinate for primitives
X0              Equ     0c6e8h          ; src x coordinate for primitives
Y1              Equ     0cae8h          ; dest y coordinate for Copy Rectangle
X1              Equ     0cee8h          ; dest x coordinate for Copy Rectangle
XY_NEG          Equ     0000011000000000b; x or y coordinate is negative
XY_SIGNIFICANT  Equ     0000011111111111b; significant bits in x,y addr

K1              Equ     0cae8h          ; Bresenham term1 for vectors
K2              Equ     0cee8h          ; Bresenham term2 for vectors
ERR_TERM        Equ     0d2e8h          ; Bresenham error term accumulator

LX              Equ     0d6e8h          ; x-axis length for primitives

CMD_FLAGS       Equ     0dae8h          ; command/flags register (w)
CMD_COMMAND     Equ     1110000000000000b; command field
CMD_C_NULL      Equ     0000000000000000b; null command
CMD_C_VECTOR    Equ     0010000000000000b; output vector
CMD_C_HRECT     Equ     0100000000000000b; horizontal rectangle
CMD_C_VRECT     Equ     0110000000000000b; vertical rectangle
CMD_C_FRECT     Equ     1000000000000000b; fast rectangle
CMD_C_OUTLINE   Equ     1010000000000000b; outline draw
CMD_C_CRECT     Equ     1100000000000000b; copy rectangle
CMD_BYTEORDER   Equ     0001000000000000b; byte order field
CMD_BYTE_LO     Equ     0001000000000000b; lo byte first to/from queues
CMD_BYTE_HI     Equ     0000000000000000b; hi byte first to/from queues
CMD_BYTE_WORD   Equ     0000001000000000b; byte/word field
CMD_BYTE        Equ     0000001000000000b; queue access contains 2 bytes
CMD_WORD        Equ     0000000000000000b; queue access contains 1 byte
CMD_FIX_VAR     Equ     0000000100000000b; fixed/variable data field
CMD_FV_VAR      Equ     0000000100000000b; use variable data
CMD_FV_FIX      Equ     0000000000000000b; use fixed data
CMD_DYZX        Equ     0000000011100000b; direction flags
CMD_DY          Equ     0000000010000000b; y increment
CMD_DZ          Equ     0000000001000000b; z increment
CMD_DX          Equ     0000000000100000b; x increment
CMD_D210        Equ     CMD_DYZX        ; coded direction flags
CMD_D2          Equ     CMD_DY
CMD_D1          Equ     CMD_DZ
CMD_D0          Equ     CMD_DX
CMD_MOVE_ACCESS Equ     0000000000010000b; move/access flag field
CMD_MA_MOVE     Equ     0000000000000000b; move (no access of bit planes)
CMD_MA_ACCESS   Equ     0000000000010000b; access bit planes
CMD_CODED_DIR   Equ     0000000000001000b; coded direction flag
CMD_CD_ANGLED   Equ     0000000000000000b; direction flags == DYZX
CMD_CD_45       Equ     0000000000001000b; direction flags == D210
CMD_LAST_PEL_NUL Equ    0000000000000100b; draw last pel field
CMD_LP_NULL     Equ     0000000000000100b; don't draw last pel
CMD_LP_DRAW     Equ     0000000000000000b; draw last pel
CMD_PEL_ACCRUAL Equ     0000000000000010b; pel accrual field
CMD_PA_FOUR     Equ     0000000000000010b; r/w 4 pels at a time
CMD_PA_ONE      Equ     0000000000000000b; r/w 1 pel at a time
CMD_RW          Equ     0000000000000001b; r/w bit planes
CMD_RW_R        Equ     0000000000000000b; read bit planes
CMD_RW_W        Equ     0000000000000001b; write bit planes

QSTATUS         Equ     09ae8h          ; queue status register (r)
Q_STATUS_REG    equ     9ae8h
CMD_STATUS_REG  equ     9ae9h
CMD_ACTIVE      equ     0002h       ; command is active
QS_AFC_OPTION   Equ     1000000000000000b; AFC option installed field
QS_BUSY         Equ     0000001000000000b; reset when input queue empty
QS_R_Q_STAT     Equ     0000000100000000b; data available in read queue
QS_W_Q_STAT     Equ     0000000011111111b; # words in write queue field
QS_W_Q_FULL     Equ     0000000011111111b; write queue is full
QS_W_Q_EMPTY    Equ     0000000000000000b; write queue is empty

SHORTSTROKE     Equ     0dee8h          ; short stroke data (w)
SS_D012         Equ     11100000b       ; coded direction flag fields
SS_MOVE_ACCESS  Equ     00010000b       ; move/access field
SS_LX           Equ     00001111b       ; length of short stroke field

COLOR_0         Equ     0e2e8h          ; background color (r/w)
COLOR_1         Equ     0e6e8h          ; foreground color (r/w)

WRITE_ENABLE    Equ     0eae8h          ; plane write enable register (w)
READ_ENABLE     Equ     0eee8h          ; plane read enable register (w)

COLOR_COMP      Equ     0f2e8h          ; color comparison register (w)

FUNCTION_0      Equ     0f6e8h          ; background mix (w)
FUNCTION_1      Equ     0fae8h          ; foreground mix (w)
FUNC_2OPSRC     Equ     01100000b       ; second operand src field (w)
FUNC_2OP_COL0   Equ     00000000b       ; second operand src is COLOR_0
FUNC_2OP_COL1   Equ     00100000b       ; second operand src is COLOR_1
FUNC_2OP_VAR    Equ     01000000b       ; second operand src is variable data
FUNC_2OP_COPY   Equ     01100000b       ; second operand src is copy rectangle
FUNC_ALU        Equ     00011111b       ; ALU function (mix mode, w)
FUNC_ND         Equ     00000000b       ; ~dest -> dest
FUNC_ZEROS      Equ     00000001b       ; 0s -> dest
FUNC_ONES       Equ     00000010b       ; 1s -> dest
FUNC_D          Equ     00000011b       ; dest -> dest
FUNC_NS         Equ     00000100b       ; ~src -> dest
FUNC_S_XOR_D    Equ     00000101b       ; src xor dest -> dest
FUNC_S_XNOR_D   Equ     00000110b       ; src xnor dest -> dest
FUNC_S          Equ     00000111b       ; src -> dest
FUNC_NS_OR_ND   Equ     00001000b       ; ~src or ~dest -> dest
FUNC_NS_OR_D    Equ     00001001b       ; ~src or dest -> dest
FUNC_S_OR_ND    Equ     00001010b       ; src or ~dest -> dest
FUNC_S_OR_D     Equ     00001011b       ; src or ~dest -> dest
FUNC_S_AND_D    Equ     00001100b       ; src and dest -> dest
FUNC_S_AND_ND   Equ     00001101b       ; src and ~dest -> dest
FUNC_NS_AND_D   Equ     00001110b       ; ~src and dest -> dest
FUNC_NS_AND_ND  Equ     00001111b       ; ~src and ~dest -> dest
FUNC_MIN_S_D    Equ     00010000b       ; min(src,dest) -> dest
FUNC_D_SUB_S    Equ     00010001b       ; dest - src -> dest
FUNC_S_SUB_D    Equ     00010010b       ; src - dest -> dest
FUNC_D_ADD_S    Equ     00010011b       ; src + dest -> dest
FUNC_MAX_S_D    Equ     00010100b       ; max(src,dest) -> dest
FUNC_D_SUB_S_2  Equ     00010101b       ; (dest - src)/2 -> dest
FUNC_S_SUB_D_2  Equ     00010110b       ; (src - dest)/2 -> dest
FUNC_D_ADD_S_2  Equ     00010111b       ; (src + dest)/2 -> dest
FUNC_D_SUBS_S   Equ     00011001b       ; dest - src -> dest w/saturate
FUNC_S_SUBS_D   Equ     00011010b       ; src - dest -> dest w/saturate
FUNC_D_ADDS_S   Equ     00011011b       ; src + dest -> dest w/saturate
FUNC_D_SUBS_S_2 Equ     00011101b       ; (dest - src)/2 -> dest w/saturate
FUNC_S_SUBS_D_2 Equ     00011110b       ; (src - dest)/2 -> dest

SECOND_DECODE   Equ     0fee8h          ; secondary decodes

CNTL_STATUS     Equ     042e8h          ; control/status register
CS_RESET_CNTL   Equ     1100000000000000b; reset control field (w)
CS_R_NULL       Equ     0000000000000000b; null effect
CS_R_NORMAL     Equ     0100000000000000b; update controller normal operation
CS_R_RESET      Equ     1000000000000000b; reset update controller
CS_TESTMODE_CNTL Equ    0011000000000000b; test mode control field (w)
CS_T_NULL       Equ     0000000000000000b; null effect
CS_T_NORMAL     Equ     0001000000000000b; normal mode
CS_T_TESTMODE   Equ     0010000000000000b; test mode
CS_INTMASK      Equ     0000111100000000b; interrupt mask field (w)
CS_I_OPDONE     Equ     0000100000000000b; op completed interrupt
CS_I_OVERRUN    Equ     0000010000000000b; queue overrun interrupt
CS_I_CORRELATE  Equ     0000001000000000b; correlation interrupt
CS_I_VRETRACE   Equ     0000000100000000b; frame flyback interrupt
CS_MISR         Equ     1111111100000000b; diagnostic MISR bits (r)
CS_OPTIONS      Equ     0000000011110000b; hardware options field (r)
CS_O_4PLANES    Equ     0000000010000000b; 4-bit plane extension installed (r)
CS_O_MONITORS   Equ     0000000001110000b; monitor id field (r)
CS_O_HIRES_MONO Equ     0000000000010000b; 1024x768 mono monitor
CS_O_HIRES_COL  Equ     0000000000100000b; 1024x768 color monitor
CS_O_LORES_MONO Equ     0000000001010000b; 640x480 mono monitor
CS_O_LORES_COL  Equ     0000000001100000b; 640x480 color monitor
CS_O_NONE       Equ     0000000001110000b; no monitor attached
CS_OPDONE       Equ     0000000000001000b; op complete (r/w)
CS_OVERRUN      Equ     0000000000000100b; queue overrun field (r/w)
CS_CORRELATE    Equ     0000000000000010b; correlate status (r/w)
CS_VRETRACE     Equ     0000000000000001b; frame flyback status (r/w)

PROM_PAGE       Equ     046e8h          ; prom page select register

MISC_IO         Equ     04ae8h          ; miscellaneous i/o register
MI_PELCLK       Equ     00000100b       ; pel clock rate
MI_PELCLK_640   Equ     00000000b       ; pel clock for 640 wide
MI_PELCLK_1024  Equ     00000100b       ; pel clock for 1024 wide
MI_AF_MODE      Equ     00000001b       ; advanced function mode select
MI_AF_VGA       Equ     00000000b       ; VGA has control
MI_AF_AFC       Equ     00000001b       ; 8514A has control

ADAPTER_ID      Equ     00100h          ; adapter id register
ADAPTER_ENABLE  Equ     00102h          ; adapter enable register


;/*
;** I/O port definitions for the 8514/A Update Controller (secondary decodes):
;** (NOTE: We utilize the discard feature i/o ports)
;*/

DECODE_FIELD    Equ     1111000000000000b

LY              Equ     0fee8h          ; y-axis length for primitives (w)
LY_2DECODE      Equ     0000000000000000b; secondary decode

YMIN            Equ     0fee8h          ; scissor min y (w)
YMIN_2DECODE    Equ     0001000000000000b; secondary decode

XMIN            Equ     0fee8h          ; scissor min x (w)
XMIN_2DECODE    Equ     0010000000000000b; secondary decode

YMAX            Equ     0fee8h          ; scissor max y (w)
YMAX_2DECODE    Equ     0011000000000000b; secondary decode

XMAX            Equ     0fee8h          ; scissor max x (w)
XMAX_2DECODE    Equ     0100000000000000b; secondary decode

CONFIG          Equ     0fee8h          ; configuration (w)
CONFIG_2DECODE  Equ     0101000000000000b; secondary decode
CFG_UPDATE_BANK Equ     10000b          ; chooses 1k vs 512 line modes (w)
CFG_VRAM_BANK   Equ     01100b          ; vram bank select field (w)
CFG_VRAM_1024   Equ     00100b          ; value for 1k line mode
CFG_VRAM_512    Equ     00000b          ; value for 512 line mode
CFG_INTERLEAVE  Equ     00010b          ; interleave field (w)
CFG_WORDWIDTH   Equ     00001b          ; wordwidth field (w)

PATTERN_0       Equ     0fee8h          ; pattern 0 register (w)
PATTERN_0_2DECODE Equ   1000000000000000b; secondary decode
PATTERN_0_DATA  Equ     00011110b       ; lo 4 bits pattern field

PATTERN_1       Equ     0fee8h          ; pattern 1 register (w)
PATTERN_1_2DECODE Equ   1001000000000000b; secondary decode
PATTERN_1_DATA  Equ     00011110b       ; hi 4 bits pattern field

MODE            Equ     0fee8h          ; mode register (w)
MODE_2DECODE    Equ     1010000000000000b; secondary decode
MD_PATT_SRC     Equ     11000000b       ; pattern source select field
MD_PS_ONES      Equ     00000000b       ; pattern = ONEs
MD_PS_PATT      Equ     01000000b       ; pattern = PATTERN_0,PATTERN_1 regs
MD_PS_VAR       Equ     10000000b       ; pattern = variable data
MD_PS_COPY      Equ     11000000b       ; pattern = copy rectangle (read phase)
MD_UNDERPAINT   Equ     00111000b       ; underpaint control field
MD_UP_FALSE     Equ     00000000b       ; always false
MD_UP_TRUE      Equ     00001000b       ; always true
MD_UP_GE        Equ     00010000b       ; plane data >= color compare
MD_UP_LT        Equ     00011000b       ; plane data <  color compare
MD_UP_NE        Equ     00100000b       ; plane data != color compare
MD_UP_EQ        Equ     00101000b       ; plane data == color compare
MD_UP_LE        Equ     00110000b       ; plane data <= color compare
MD_UP_GT        Equ     00111000b       ; plane data >  color compare
MD_AREAFILL     Equ     00000110b       ; area fill control field
MD_AF_W_NORMAL  Equ     00000000b       ; normal operation for writes
MD_AF_R_THRU    Equ     00000000b       ; thru planes for reads
MD_AF_W_SPP     Equ     00000100b       ; special plane fill for writes
MD_AF_R_ACROSS  Equ     00000100b       ; across planes for reads
MD_AF_W_SPC     Equ     00000110b       ; special color fill for writes
MD_WORDWIDTH    Equ     00000001b       ; word width field

;/*
;** I/O port definitions for the 8514/A Display Controller:
;*/

LINE_TOTAL      Equ     002e8h          ; line total length
LINE_BLANK      Equ     006e8h          ; line blank start
LINE_SYNC_POS   Equ     00ae8h          ; line sync position
LINE_SYNC_WIDE  Equ     00ee8h          ; line sync width
FRAME_TOTAL     Equ     012e8h          ; frame total length
FRAME_BLANK     Equ     016e8h          ; frame blank start
FRAME_SYNC_POS  Equ     01ae8h          ; frame sync position
FRAME_SYNC_WIDE Equ     01ee8h          ; frame sync width

CRTC_MODE       Equ     022e8h          ; crtc mode
CRTM_RESET      Equ     01100000b       ; crtc reset field
CRTM_R_NULL     Equ     00000000b       ; no effect
CRTM_R_NORMAL   Equ     00100000b       ; normal operation
CRTM_R_RESET    Equ     01000000b       ; reset crt controller
CRTM_INTERLACE  Equ     00010000b       ; interlace field
CRTM_VREPL      Equ     00001000b       ; vertical replication
CRTM_VRAM_BANK  Equ     00000110b       ; vram bank select field
CRTM_VB_1024    Equ     00000010b       ; vram bank select for 1024 lines
CRTM_VB_512     Equ     00000000b       ; vram bank select for 512 lines
CRTM_INTERLEAVE Equ     00000001b       ; interleave mode

CRTC_STATUS     Equ     002e8h          ; crtc status


;/*
;** Configuration information determined at initialization time is described
;** in the variable hwFlags in the default data segment. The significance of
;** the bits in the flags is described below:
;*/

HW_OPTIONS      Equ     00000111b       ; hw options field

ifdef   4BPP_USED
HW_8_BPP        Equ     001h            ; will be running 8 bpp
HW_4_BPP        Equ     000h            ; will be running 4 bpp
endif;  4BPP_USED

HW_MON_640      Equ     002h            ; monitor dictates 640x480 mode
HW_MON_1024     Equ     000h            ; monitor allows 1024x768 mode
HW_MONO_MON     Equ     004h            ; monochrome monitor attached
HW_COLOR_MON    Equ     000h            ; color monitor attached
HW_DALLAS       Equ     008h            ; DALLAS monitor attached           @D1A
HW_LEGAL        Equ     08000h          ; legal hw mode detected
HW_ILLEGAL      Equ     00000h          ; illegal hw mode detected


;/*
;** id. of font resource for the Dallas monitor                             @D1A
;*/

RES_ID_DALLAS   equ     102             ;alternative font for DALLAS        @D1A

;/*
;** Plane read enable masks
;*/

READ_PLANE_0    Equ     002h
READ_PLANE_1    Equ     READ_PLANE_0 SHL 1
READ_PLANE_2    Equ     READ_PLANE_0 SHL 2
READ_PLANE_3    Equ     READ_PLANE_0 SHL 3
READ_PLANE_4    Equ     READ_PLANE_0 SHL 4
READ_PLANE_5    Equ     READ_PLANE_0 SHL 5
READ_PLANE_6    Equ     READ_PLANE_0 SHL 6
READ_PLANE_7    Equ     READ_PLANE_0 SHR 1
READ_ALL_PLANES Equ     0ffh


;/*
;** Plane write enable masks
;*/

WRITE_PLANE_0   Equ     001h
WRITE_PLANE_1   Equ     WRITE_PLANE_0 SHL 1
WRITE_PLANE_2   Equ     WRITE_PLANE_0 SHL 2
WRITE_PLANE_3   Equ     WRITE_PLANE_0 SHL 3
WRITE_PLANE_4   Equ     WRITE_PLANE_0 SHL 4
WRITE_PLANE_5   Equ     WRITE_PLANE_0 SHL 5
WRITE_PLANE_6   Equ     WRITE_PLANE_0 SHL 6
WRITE_PLANE_7   Equ     WRITE_PLANE_0 SHL 7
WRITE_ALL_PLANES    Equ 0ffh



;/*
;** Macros to access the hardware:
;*/


;/*
;**  WaitIO
;**  ------
;**  General purpose macro to sit on an i/o port and test for a particular value:
;** 
;**        Port:           port # to be polled. If not present then it is assumed
;**                        that the port # has already been loaded into Dx.
;** 
;**        Sense:          sense of jump needed to remain in polling loop.
;** 
;**        Mask:           if present then the value that will be and'ed with the
;**                        polled contents of Port.
;** 
;**        EquVal:         if present then the value that must match the Port
;**                        contents, after masking if Mask is present.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

WaitIO  Macro   Port,Sense,Mask,EquVal,SaveRegs
        Local   SpinOnStatus

;/*
;** Save registers we will use if requested to do so:
;*/
        Ifnb    <SaveRegs>
        mpush   ?AX+?DX
        Endif

;/*
;** Load up the port address:
;*/
        Ifnb    <Port>
        Mov     Dx,Port
        Endif

;/*
;** Now wait for status to go to sense specified:
;*/
SpinOnStatus:
        In      Ax,Dx                   ;; fetch the port value
        Ifnb    <Mask>                  ;; if masking off input value
        And     Ax,Mask                 ;;   mask it off
        Endif
        Ifnb    <EquVal>                ;; if comparing to a specific value
        Cmp     Ax,EquVal               ;;   do the comparison
        Endif
        J&Sense SpinOnStatus            ;; spin until required status is met...

;/*
;** Restore registers we used if requested to do so:
;*/
        Ifnb    <SaveRegs>
        mpop    ?AX+?DX
        Endif
        Endm


;/*
;**  WaitQIN
;**  -------
;**  Special purpose macro to wait for the 8514/A adapter's output queue to
;**  have available data.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;** 
;*/

WaitQIN macro   SaveRegs
        WaitIO  QSTATUS,z,QS_R_Q_STAT,,SaveRegs
        endm


;/*
;**  WaitQOUT
;**  --------
;**  Special purpose macro to wait for the 8514/A adapter's input queue to
;**  be ready to accept data.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

WaitQOUT        macro   SaveRegs
        WaitIO  QSTATUS,ne,(QS_BUSY+QS_W_Q_FULL),(QS_BUSY+QS_W_Q_EMPTY),SaveRegs
                endm

;/*
;**  ChkERRSTATUS
;**  ------------
;**  Special purpose macro to check for underrun/overrun state after execution
;**  of a variable data command to the 8514/A
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

ChkERRSTATUS    macro   SaveRegs
        local   catbox
ifdef   FIREWALLS

;/*
;** Save registers we will use if requested to do so:
;*/
        ifnb    <SaveRegs>
        mpush   ?AX+?DX
        endif

        mov     dx,CNTL_STATUS
        in      ax,dx                   ;; check overrun/underrun bit
        test    al,LOW CS_OVERRUN
        .errnz  HIGH CS_OVERRUN
        jz      catbox                  ;; no overrun/underrun detected
        out     dx,ax                   ;; undo overrun/underrun
        rip     text,<Underrun/Overrun during variable data i/o to 8514/A>
catbox:

;/*
;** Restore registers we used if requested to do so:
;*/
        ifnb    <SaveRegs>
        mpop    ?AX+?DX
        endif
endif
                endm

;/*
;**  WaitQ
;**  -----
;**  Special purpose macro to wait for the 8514A adapter's input queue to have
;**  a minimum # of words of free space. The queue is up to 8 words deep and
;**  at any time the # words still to be dequeued can be ascertained.
;** 
;**        MinQSpace:      fall out of wait loop if at least this many words are
;**                        available in the queue. This parameter must be present.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

WaitQ   Macro   MinQSpace,SaveRegs
        Local   QBitVec

        if      MinQSpace LT 0
??Qouts         =       ??Qouts + MinQSpace
        else
        errnz   <MinQSpace EQ 0>        ;; waiting on a full queue ?
        errnz   <MinQSpace GT 8>        ;; queue is only 8 words deep

??QMaxOuts      =       MinQSpace       ;; assemble-time indicator of max # outs
                                        ;; allowed
??Qouts         =       0               ;; not yet registered any outs

QBitVec =       80h Shr (MinQSpace - 1) ;; mask to test on
        WaitIO  QSTATUS,nz,QBitVec,,SaveRegs
        endif
        Endm


;/*
;**  outwQ
;**  -----
;**  Special purpose macro to output a word value to the 8514A input queue.
;** 
;**        Port:           port # for which data that is written will be queued.
;**                        If this parameter is not present the port # will be
;**                        assumed to already have been loaded into Dx.
;** 
;**        Data:           immediate or indirect specification of data that will
;**                        be output to Port. If this parameter is not present
;**                        the data will be assumed to already have been loaded
;**                        into the Ax register.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

outwQ   Macro   Port,Data,SaveRegs

??Qouts =       ??Qouts + 1
        If      ??Qouts GT ??QMaxOuts
        ??error <Readjust min # words free space in queue in WaitQ>
        Endif

        Ifnb    <SaveRegs>
        mpush   ?AX+?DX
        Endif

        Ifnb    <Data>
        Ifidn   <Data>,<0>
        Sub     Ax,Ax                   ;; save some code for zero data
        Else
        Ifdifi  <Data>,<Ax>
        Mov     Ax,Data                 ;; fetch data value
        Endif
        Endif
        Endif

        Ifnb    <Port>                  ;; if port # not already loaded
        Mov     Dx,Port                 ;;   we load it here
        Endif
        Out     Dx,Ax                   ;; output queue data

        Ifnb    <SaveRegs>
        mpop    ?AX+?DX
        Endif
        Endm



;/*
;**  outbQ
;**  -----
;**  Special purpose macro to output a byte value to the 8514A input queue. This
;**  macro differs from outwQ in that it is assumed that only the low half of the
;**  Ax register needs to be loaded. A slight saving in code size is thereby
;**  achieved.
;** 
;**        Port:           port # for which data that is written will be queued.
;**                        If this parameter is not present the port # will be
;**                        assumed to already have been loaded into the Dx register
;** 
;**        Data:           immediate or indirect specification of data that will
;**                        be output to Port. If this parameter is not present
;**                        the data will be assumed to already have been loaded
;**                        into the Ax register.
;** 
;**        SaveRegs:       parameter is present if registers used in polling are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

outbQ   Macro   Port,Data,SaveRegs

??Qouts =       ??Qouts + 1
        If      ??Qouts GT ??QMaxOuts
        ??error <Readjust min # of words free space in queue in WaitQ>
        Endif

        Ifnb    <SaveRegs>
        mpush   ?AX+?DX
        Endif

        Ifnb    <Data>
        Ifidn   <Data>,<0>
        Sub     Al,Al                   ;; save some code for zero data
        Else
        Ifdifi  <Data>,<Al>
        Mov     Al,Data                 ;; fetch data value
        Endif
        Endif
        Endif

        Ifnb    <Port>                  ;; if port # not already loaded
        Mov     Dx,Port                 ;;   we load it here
        Endif
        Out     Dx,Ax                   ;; output queue data

        Ifnb    <SaveRegs>
        mpop    ?AX+?DX
        Endif
        Endm

;/*
;**----------------- 8514 Registers ------------------------------;
;*/

MAJ_AXIS_PCNT   equ     (96e8h+WAIT_PORT_BIT)
COMMAND_REG     equ     (9ae8h+WAIT_PORT_BIT)
WRITE_MASK_REG  equ     (0aae8h+WAIT_PORT_BIT)
READ_MASK_REG   equ     (0aee8h+WAIT_PORT_BIT)
BKGD_MIX_REG    equ     (0b6e8h+WAIT_PORT_BIT)
FRGD_MIX_REG    equ     (0bae8h+WAIT_PORT_BIT)
MISC_REG        equ     (0bee8h+WAIT_PORT_BIT)
PIXEL_TRANS_REG equ     0e2e8h


;/*
;** BLOCK_POINTER
;*/

block_pointer   MACRO
        LOCAL wait_for_clear
        mov     ax,MyPtrVioSegData
        mov     es,ax
        assumes es,PtrData
        xor     ax,ax
wait_for_clear:
        xchg    al,es:screen_busy
        or      al,al
        jz      wait_for_clear
        ENDM

;/*
;** ALLOW_POINTER
;*/

allow_pointer MACRO
        mov     ax,MyPtrVioSegData
        mov     es,ax
        assumes es,PtrData
        mov     es:screen_busy,1
        ENDM

;/*
;**---------------- Functions --------------------------------------;
;*/

FILL_SCREEN equ CMD_C_HRECT+CMD_RW_W+CMD_PA_FOUR+CMD_MA_ACCESS+CMD_DX+CMD_DY+CMD_DZ


;/*
;**  WAITCMD - polls the command status register until the
;**  command status flag indicates that there are no
;**  commands executing.
;*/

WaitCMD MACRO
        WaitIO  CMD_STATUS_REG,NZ,CMD_ACTIVE
        ENDM

;/*
;**  LoadPattern
;**  -----------
;**  Load the 8514/A pattern registers with an 8 bit pattern value. The macro
;**  shields us from the fact that an 8 bit pattern gets loaded into the 8514/A
;**  as two 4 bit values, each half shifted up 1 bit, and sent out to independent
;**  ports.
;** 
;**        Pattern:        8 bit pattern to be loaded. If not present then it is
;**                        assumed that the pattern is already loaded into Al.
;** 
;** 
;**        SaveRegs:       parameter is present if registers used are
;**                        to be saved and restored, the actual content of this
;**                        parameter is ignored, only its presence matters.
;*/

LoadPattern     Macro   Pattern,SaveRegs

;/*
;** Save registers we will use if requested to do so:
;*/
        Ifnb    <SaveRegs>
        mpush   ?AX+?DX
        Endif

;/*
;** Load up the pattern:
;*/
        Ifnb    <Pattern>               ;; if pattern needs to be fetched
        Mov     Al,Pattern              ;;   we fetch it to Ax
        Endif

;/*
;** Output the low 4 bits of the pattern:
;*/
        Mov     Dx,PATTERN_1            ;; point to low pattern register
        Rol     Al,1                    ;; P0-P3 go out in Al bits 1-4
        Mov     Ah,HIGH PATTERN_1_2DECODE;; add in the secondary decode value
        Out     Dx,Ax

;/*
;** Output the high 4 bits of the pattern:
;*/
      ; Mov     Dx,PATTERN_0                      ;; point to high pattern register
        .errnz  PATTERN_1 - PATTERN_0
        Rol     Al,4                    ;; P4-P7 go out in Al bits 1-4
        Mov     Ah,HIGH PATTERN_0_2DECODE;; add in the secondary decode value
        Out     Dx,Ax

;/*
;** Restore registers we used if requested to do so:
;*/
        Ifnb    <SaveRegs>
        mpop    ?AX+?DX
        Endif

        Endm


;/*
;**  StoreRGB
;**  --------
;**  Store the specified RGB values, chopping off the least significant 2
;**  bits because the Inmos color palette is only 6 bits wide for each of the
;**  r,g,b registers.
;*/

StoreRGB        macro   r,g,b
        db      (r shr 2),(g shr 2),(b shr 2)
                endm

;/*
;** MapXY
;** -----
;** Map the coordinate to the hardware representation
;*/

MapXY   Macro   dest,coord,is_x,mapping
lcoord  =       coord
        Ifdifi  <is_x>,<IS_X>
        Ifidni  <mapping>,<IS_512>
lcoord  =       ((lcoord And (Not 1)) Shl 1) Or (lcoord And 1)
        Endif
        Endif
        Mov     dest,lcoord
        Endm


;/*
;**  GrabScreen
;**  ----------
;**  Grab the screen semaphore used in the cursor handling code to prevent
;**  cursor operations from invalidating current hardware state.
;** 
;**  Assumes DS == data segment
;**  Destroys CX,ES
;*/

GrabScreen      macro   lbl,far,seg              
        local   still_busy
ifnb    <lbl>
        public  GrabScreen_&lbl
GrabScreen_&lbl&:
endif
ifnb    <far>
ifnb    <seg>
        mov     es,MyPtr&seg&Data
else
        mov     es,MyPtrFarCodeData     ;; access to pointer data segment
endif
else
        mov     es,MyPtrCodeData        ;; access to pointer data segment
endif
        assumes es,PtrData
        sub     cx,cx                   ;; IS_BUSY
still_busy:
        xchg    cl,screen_busy          ;; try to grab screen
        jcxz    still_busy              ;; loop until we've gotten the sempahore
                endm

GrabScreenEs    macro   lbl
        local   still_busy
ifnb    <lbl>
        public  GrabScreen_&lbl
GrabScreen_&lbl&:
endif
        sub     cx,cx                   ;; IS_BUSY
still_busy:
        xchg    cl,screen_busy          ;; try to grab screen
        jcxz    still_busy              ;; loop until we've gotten the sempahore
                endm


;/*
;**  ReleaseScreen
;**  -------------
;**  Release a previously grabbed screen semaphore
;** 
;**  Assumes DS == data segment
;**  Destroys ES
;*/

ReleaseScreen   macro   lbl,far,seg
ifnb    <lbl>
        public  ReleaseScreen_&lbl
ReleaseScreen_&lbl&:
endif
ifnb    <far>
ifnb    <seg>
        mov     es,MyPtr&seg&Data
else
        mov     es,MyPtrFarCodeData     ;; access to pointer data segment
endif
else
        mov     es,MyPtrCodeData        ;; access to pointer data segment
endif
        assumes es,PtrData
        mov     screen_busy,1           ;; NOT_BUSY
                endm

ReleaseScreenEs macro   lbl
ifnb    <lbl>
        public  ReleaseScreen_&lbl
ReleaseScreen_&lbl&:
endif
        mov     screen_busy,1           ;; NOT_BUSY
                endm
