;*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   SVGAXFER.ASM - Video Device Handler Ring 2 PVB Transfer Routines

;/*****************************************************************************
;*
;* SOURCE FILE NAME = SVGAXFER.ASM
;*
;* DESCRIPTIVE NAME = Video Device Handler Ring 2 PVB Transfer Routines
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION
;*
;*      Routines to transfer video buffer contents to and from memory.
;*      One for each of the supported SVGA adapters and chipsets.
;*
;*      Each routine copies the video buffer contents from offset zero
;*      to 'SourceSize' bytes.
;*
;*      The destination is assumed to be large enough to hold the size
;*      requested.
;*
;*      Huge pointers are assumed to be normalised, on entry, ie. only
;*      the selector is passed, the offset is assumed to be zero.
;*
;*      Calling sequence:
;*
;*      Transfer(SEL   PVBSel,          Selector to PVB
;*               SEL   HugeSel,         Selector to Huge area of memory
;*               ULONG Size,            number of bytes to transfer
;*               WORD  Mode,            Whether to SAVE/RESTORE
;*               WORD  Planar,          Linear(256 colour)/Planar(16 colour)
;*               WORD  Adapter,         Adapter type we're using
;*               WORD  ChipVersion)     Chip version on the adapter
;*
;* FUNCTIONS    TRANSFER
;*              IBMEntry
;*              IBMExit
;*              IBMSetBank
;*              TrEntry
;*              TrExit
;*              TrSetBank
;*              TsengEntry
;*              TsengExit
;*              TsengSetBank
;*              ATIEntry
;*              ATIExit
;*              ATISetBank
;*              V7Entry
;*              V7Exit
;*              V7EnableExt
;*              V7DisableExt
;*              V7SetReadBank
;*              V7SetWriteBank
;*              V7SetReadBankA
;*              V7SetWriteBankA
;*              V7SetSingleBank
;*              WDEntry
;*              WDExit
;*              WDSetBank
;*              WDSetSingleBank
;*              WDEnableExt
;*              WDDisableExt
;*              MoveBytes
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/14/93                     Senja    Cirrus Logic support.
;*   03/03/93                     Use setbank from PMI-file if pointer passed.
;*   06/02/93             F69306  Add support for S3
;*   11/01/93             D75458  Merge r206v, r205, r206, r207 S3 code
;*   02/21/94             D79562  Add 2M support for WD
;*
;*****************************************************************************/

;/*
;** Include files
;*/

                        INCLUDE struc.inc               ;Structured assembly macros
                        INCLUDE vdh.inc                 ;Definitions
                        INCLUDE vdhequ.inc              ;OEMFlags bit definitions
                        INCLUDE svgatype.inc            ;        

                        .386p

;/*
;** Exported entry points
;*/

                        PUBLIC  TRANSFER

;/*
;** Externals
;*/

                        EXTRN   _HugeShift:WORD         ; 
                        EXTRN   SETMAPMASK:FAR          ; 
                        EXTRN   _pHWCurrSetBank:DWORD   ;          
                        EXTRN   EXECCOMMANDS:FAR        ;          

;/*
;** Stack parameters passed
;*/

VideoBufferSel          EQU     [bp+24]                 ; 
MemorySel               EQU     [bp+22]                 ; 
SourceSize              EQU     [bp+18]                 ; 
Mode                    EQU     word ptr [bp+16]        ;Save / Restore
LinearMode              EQU     word ptr [bp+14]        ;zero => linear mode otherwise planar
Adapter                 EQU     word ptr [bp+12]        ; 
ChipVersion             EQU     word ptr [bp+10]        ; 
pSetBankData            EQU     [bp+6]                  ; 

;/*
;** Constants
;*/

LINEAR_MODE             EQU     0                       ; 
TEXT_MODE               EQU     80h                     
TEXTMODERESET           EQU     7Fh                     

;/*
;** Data Segment
;*/

R2DATA          SEGMENT WORD PUBLIC 'DATA' USE16

EntryRoutine    DW      GenericEntry    ;          
                DW      V7Entry         ; 
                DW      TrEntry         ; 
                DW      TsengEntry      ; 
                DW      WDEntry         ; 
                DW      ATIEntry        ; 
                DW      IBMEntry        ; 
                DW      CIRRUSEntry     ;          
                DW      S3Entry         ;                          

ExitRoutine     DW      GenericExit     ;          
                DW      V7Exit          ; 
                DW      TrExit          ; 
                DW      TsengExit       ; 
                DW      WDExit          ; 
                DW      ATIExit         ; 
                DW      IBMExit         ; 
                DW      CIRRUSExit      ;          
                DW      S3Exit          ;                      

GDCSegSelect    DB      0                       ;Tseng save
TextMode        DB      0                       ;Text mode in question

R2DATA          ENDS

DGROUP  GROUP   R2DATA

R2SEG           SEGMENT BYTE PUBLIC 'CODE' USE16
                ASSUME  CS: R2SEG, DS: DGROUP


;/***************************************************************************
;*
;* FUNCTION NAME = TRANSFER
;*
;* DESCRIPTION   = Transfer Video buffer to/from System RAM and Video RAM.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

MapMask         EQU     word ptr [bp-2]         ; 
ReadMap         EQU     word ptr [bp-4]         ; 
SetBank         EQU     word ptr [bp-6]         ; 

TRANSFER        PROC    FAR
                push    bp                      ; 
                mov     bp, sp                  ; 
                sub     sp, 6                   ; 
                push    ds
                push    es
                push    fs
                pusha

                mov     ax, DGROUP              ; 
                mov     ds, ax                  ; 
                test    LinearMode, TEXT_MODE   
                jz      short @F
                mov     TextMode, 1
                and     LinearMode, TEXTMODERESET
@@:
                mov     si,word ptr pSetBankData
                or      si,word ptr pSetBankData+2
                mov     si, Adapter             ; 
                jnz     short @F                ;          
                cmp     si, DEFAULT_ADAPTER     ;          
                jz      short @F                ;          
                shl     si, 1                   ; 
                call    EntryRoutine[si]        ; 
                jmp     short TransferTop       ; 
@@:             mov     Adapter, 0              ; 
                call    GenericEntry            ; 

TransferTop:    cld
                xor     si, si                  ; 
                xor     di, di                  ; 
                mov     ax, VideoBufferSel      ; 
                mov     ds, ax                  ;DS:SI -> Video buffer
                mov     ax, MemorySel           ; 
                mov     es, ax                  ;ES:DI -> Huge memory

                mov     ax, SEG _HugeShift      ;Set up FS = HugeShift
                mov     fs, ax                  ;  segment

                mov     MapMask, 1              ;Initialise Map Mask
                mov     ReadMap, WriteFunction  ;Assume Write to Video Buffer
                cmp     Mode, RESTORE           ; 
                je      short @F                ; 
                mov     ReadMap, 0              ;Initialise to map 0
@@:
                cmp     LinearMode, LINEAR_MODE ; 
                jz      short LinearTransfer    ; 

;/*
;**     Handle transfer in 16-colour mode
;*/

PlanarTransfer:

NextPlane:
                push    ReadMap                 ;ReadMap
                push    MapMask                 ;MapMask
                call    SETMAPMASK              ; 

                mov     ah, 0                   ; 

                xor     cx, cx                  ;force 64k move
                xor     si, si                  ;Start of plane
                cmp     word ptr SourceSize[2], 0 ;does this span > 1 segment
                jnz     short @F                ;do 64k move

NextSegment:
                mov     cx, word ptr SourceSize[0] ;get full/part plane size
                or      cx, cx                  ;tricky, segment is exactly
                jz      short CheckMapMask      ; 64k large??
@@:
                call    SetBank                 ;set bank no in AH

                call    MoveBytes               ; 

                or      cx, cx                  ;if zero, we moved a 64k
                jnz     short CheckMapMask      ; chunk, so more to do
                                                ; for this plane?
                mov     ax, es                  ; 
                add     ax, fs:_HugeShift       ; 
                mov     es, ax                  ;ES has next huge segment

                inc     ah                      ;bump up bank no.
                jmp     NextSegment             ; 

CheckMapMask:   cmp     MapMask, 01000B         ;Done the last bit plane?
                je      short TransferExit      ;yes, time to go

                shl     MapMask, 1              ;Set up for next plane
                cmp     Mode, RESTORE           ; 
                je      NextPlane               ; 
                inc     ReadMap                 ;bump up read map
                jmp     NextPlane               ;do the next one


;/*
;**     Handle transfer in 256-colour mode
;*/

LinearTransfer:

                mov     bx, es                  ;Save copy of Huge selector

                cmp     Mode, RESTORE           ; 
                jne     short @F                ; 
                push    es                      ;Switch selectors
                push    ds                      ;  if direction
                pop     es                      ;  is a RESTORE.
                pop     ds                      ; 
@@:
                xor     ax, ax                  ;AX = current segment

                mov     cx, word ptr SourceSize[2];no of 64k portions to do
                or      cx, cx                  ; 
                jz      short Remains           ; 

Loop64k:        push    cx                      ;no of segments to do
                call    SetBank                 ; 
                mov     cx, 4000h               ;64k bytes
                rep     movsd                   ;move them

                add     bx, fs:_HugeShift       ;BX has huge selector
                cmp     Mode, RESTORE           ;if mode is RESTORE
                je      short @F                ;  they got switched
                mov     es, bx                  ;update selector
                jmp     short IncSeg            ; 
@@:             mov     ds, bx                  ;update selector

IncSeg:         inc     ah                      ;increment segment
                pop     cx
                loop    Loop64k                 ; 

Remains:
                mov     cx, word ptr SourceSize ;get remaining bytes
                or      cx, cx                  ; 
                jz      short TransferExit      ; 

                call    SetBank                 ;wkb 6-22

                push    cx                      ; 
                shr     cx, 2                   ;make dwords
                rep     movsd                   ;move them
                pop     cx                      ; 
                and     cx, 3                   ;do the remaining bytes
                rep     movsb                   ; 

TransferExit:
                mov     ax, DGROUP              ; 
                mov     ds, ax                  ; 
                mov     si, Adapter             ; 
                or      si, si                  ;          
                jz      short @F                ;          
                dec     si                      ; 
                shl     si, 1                   ; 
@@:             call    ExitRoutine[si]         ; 

                popa                            ; 
                pop     fs                      ; 
                pop     es                      ; 
                pop     ds                      ; 
                mov     sp, bp                  ; 
                pop     bp                      ; 
                ret     20                      ; 
TRANSFER        ENDP

;/*
;**********************************  Generic  *****************************
;*

;***    GenericEntry                            ;          
;*
;*****************************************************************************

GenericEntry    PROC    NEAR

                mov     SetBank, OFFSET cs:GenericSetBank
                ret

GenericEntry    ENDP

;***    GenericExit                             ;          
;*
;*****************************************************************************

GenericExit     PROC    NEAR

                ret

GenericExit     ENDP

;* FUNCTION NAME = GenericSetBank               ;          
;*
;* DESCRIPTION   =
;*      Call ExecCommands routine with pointer to current setbank routine
;*      to perform the operation. First scan the list for the first
;*      register assigment operation and insert bank number to be set.
;*
;* INPUT         = AH has bank to set.
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*****************************************************************************

GenericSetBank  PROC    NEAR

                push    es
                push    ds
                push    ax
                push    bx

                mov     al,ah                   ; 
                xor     ah,ah                   ;AX == bank to set
                mov     bx,DGROUP               ; 
                mov     ds,bx                   ; 
                mov     bx,word ptr pSetBankData
                or      bx,word ptr pSetBankData+2
                je      short ScanListExit      ; 
                les     bx,_pHWCurrSetBank      ; 
                jmp     short @F                ; 

ScanListNext:
                mov     bx,es:[bx].pNextCmd     ; 
                or      bx,bx                   ; 
                jz      short ScanListExit      ; 
@@:             cmp     word ptr es:[bx],PMICMD_REGOP
                jne     ScanListNext            ; 
                cmp     es:[bx].usIndexPort,PMI_REGOP_ASSIGN
                jne     ScanListNext            ; 

                mov     es:[bx].usData,ax       ; 

                push    word ptr pSetBankData+2 ; 
                push    word ptr pSetBankData   ; 
                call    EXECCOMMANDS            ; 

ScanListExit:
                pop     bx
                pop     ax
                pop     ds
                pop     es
                ret

GenericSetBank  ENDP

;/*
;**********************************  S3  *******************            ******             
;*

;***    S3Entry
;*
;*****************************************************************************
S3Entry         PROC    NEAR

                mov     SetBank, OFFSET cs:S3SetBank
                ret

S3Entry         ENDP

;***    S3Exit
;*
;*****************************************************************************

S3Exit          PROC    NEAR

                ret

S3Exit          ENDP

;***    S3SetBank
;*
;*****************************************************************************

S3SetBank       PROC    NEAR

;               push    ax              ;ah contains bank to set
;               mov     al, 35h
;               mov     dx, 3d4h
;               out     dx, ax
;               pop     ax
;
;               ret

                push    ax
                push    cx
                mov     cl, ah                  ;ah has bank to set
                xor     ch, ch
                and     cx, 1Fh                 ;prevent overrun in Bank
                mov     ah, cl
                and     ah, 0fh
                mov     al, 35h
                mov     dx, 3d4h
                out     dx, ax

                and     cl, 10h
                cmp     cl, 0
                je      short @F
                mov     al, 51h
                out     dx, al

                inc     dl
                in      al, dx

                or      al, 4                   ;isolate bit 2
                mov     ah, al                  ;result in ah
                mov     al, 51h

                mov     dx, 3d4h
                out     dx, ax
                jmp     short S3_finish
@@:
                mov     al, 51h
                out     dx, al

                inc     dl
                in      al, dx
                and     al, 0fbh                ;turn off extended bank addr
                out     dx, al

S3_finish:

                pop     cx
                pop     ax

                ret

S3SetBank       ENDP

;/*
;**********************************  CIRRUS  *****************************
;*

;***    CIRRUSEntry
;*
;*****************************************************************************
;          
CIRRUSEntry     PROC    NEAR

                mov     SetBank, OFFSET cs:CIRRUSSetBank
                ret

CIRRUSEntry     ENDP

;***    CIRRUSExit
;*
;*****************************************************************************

CIRRUSExit      PROC    NEAR

                ret

CIRRUSExit      ENDP

;***    CIRRUSSetBank
;*
;*****************************************************************************

CIRRUSSetBank      PROC    NEAR

                push    ax
                mov     dx, 3ceh
                mov     al, 09h
                shl     ah, 4
                out     dx, ax
                pop     ax

                ret

CIRRUSSetBank      ENDP


;/*
;**********************************  IBM  ********************************
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = IBMEntry
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

IBMEntry        PROC    NEAR

                mov     SetBank, OFFSET cs:IBMSetBank
                ret

IBMEntry        ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = IBMExit
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

IBMExit         PROC    NEAR

                ret

IBMExit         ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = IBMSetBank
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

IBMSetBank      PROC    NEAR



                push    ax                      ;                       wkb 6/22
                xchg    ah, al                  ;                       wkb 6/22
                mov     dx, 2108h               ;IBM extended reg       wkb 6/22
                out     dx, al                  ;select bank            wkb 6/22
                pop     ax                      ;                       wkb 6/22

                ret

IBMSetBank      ENDP


;/*
;**********************************  Trident  ********************************
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = TrEntry
;*
;* DESCRIPTION   =
;*
;*      Register 0bh at port 3c4h (Hardware Version Register) is read-only.
;*
;*      BUT, By writing to the register the Mode Control registers will
;*           assume their 'old' definitions.
;*           Reading the register causes the Mode Control registers to
;*           assume 'new' definitions.
;*
;*      Mode Control registers 1 & 2 are at 3c4/5 index 0Dh and 0Eh.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TrEntry         PROC    NEAR

                mov     dx, 3c4h                ;This changes the Mode
                mov     al, 0bh                 ;  Control register's
                out     dx, ax                  ;  definition from 'old'
                inc     dl                      ;  to 'new'.
                in      al, dx                  ; 
                mov     SetBank, OFFSET cs:TrSetBank
                ret

TrEntry         ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = TrExit
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TrExit          PROC    NEAR

                ret

TrExit          ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = TrSetBank
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TrSetBank       PROC    NEAR

                push    ax                      ; 
                xor     ah, 2                   ;flip the bit
                mov     dx, 3c4h                ; 
                mov     al, 0eh                 ; 
                out     dx, ax                  ; 
                pop     ax
                ret

TrSetBank       ENDP

;/*
;***********************************  Tseng  *********************************
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = TsengEntry
;*
;* DESCRIPTION   =
;*
;*      Set "KEY" to enable access to Segment Select Register
;*
;*      Save Segment Select Register contents
;*
;*      Set up local var (SetBank) with the address of the Read/Write routine
;*      we need to call.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TsengEntry      PROC    NEAR

                mov     dx, 03bfh               ;Set "KEY"
                mov     al, 3                   ; to enable access to the
                out     dx, al                  ; Segment Select Register
                mov     dx, 3d8h                ; 
                mov     al, 0a0h                ; 
                out     dx, al                  ; 

                mov     dx, 03CDH               ;Save segment select reg
                in      al, dx                  ; 
                mov     GDCSegSelect, al        ; 
                xor     ax, ax                  ; 
                out     dx, al                  ;Reset read/write segments

                mov     SetBank, OFFSET cs:TsengSetBank

                ret

TsengEntry      ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = TsengExit
;*
;* DESCRIPTION   = Restore Segment Select Register
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TsengExit       PROC    NEAR

                mov     al, GDCSegSelect        ; 
                mov     dx, 03CDH               ;Restore segment select reg
                out     dx, al                  ; 

                ret

TsengExit       ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = TsengSetBank
;*
;* DESCRIPTION   =
;*
;*      AH has read/write bank number
;*      DX destroyed
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

TsengSetBank    PROC    Near

                push    ax                      ; 
                mov     al, ah                  ;get copy in AL
                shl     ah, 3                   ;shift read bank value into place
                cmp     ChipVersion, TSENG_ET4000_CHIP
                jne     short @F                ; 
                shl     ah, 1                   ;ET4000 is one more position left
@@:             or      al, ah                  ;combine read/write seg values
                mov     dx, 03CDH               ;Segment select register
                out     dx, al                  ;set segment to read/write
                pop     ax
                ret

TsengSetBank    ENDP


;/*
;************************************  ATI  **********************************
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = ATIEntry
;*
;* DESCRIPTION   =
;*
;*      Set single bank mode for access to video RAM.
;*      Setup local var to point to SetBank routine.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ATIEntry        PROC    NEAR

        mov     al, 0beh                ;ATI3E Miscellaneous register.
        mov     ah, al
        mov     dx, 01ceh               ;ATI index address
        out     dx, al
        inc     dl                      ;ATI data address
        in      al, dx                  ;get current contents
        dec     dl                      ;ATI index address
        and     al, not 008h            ;clear bit 3
        xchg    ah, al
        out     dx, ax                  ;set single bank mode
        mov     SetBank, OFFSET cs:ATISetBank
        ret

ATIEntry        ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = ATIExit
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ATIExit         PROC    NEAR

                ret

ATIExit         ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = ATISetBank
;*
;* DESCRIPTION   = Bank selection assumes single-bank mode and bank size 64k.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ATISetBank      PROC    NEAR

        push    ax
        push    cx
        mov     cl, ah                  ;Save new bank.
        mov     dx, 01ceh               ;ATI index address
        mov     al, 0b2h                ;ATI32 memory page select reg.
        mov     ah, al
        out     dx, al                  ;memory page select
        inc     dl                      ;ATI data address
        in      al, dx
        dec     dl                      ;ATI index address
        and     al, 0e1h                ;Remove old bank select bits (4:1).
        and     cl, 00fh                ;Prevent bank overrun.
        shl     cl, 1                   ;Shift bank select to 4:1.
        or      al, cl                  ;Add in new bank select bits.
        xchg    ah, al
        out     dx, ax                  ;Set the bank.
        pop     cx
        pop     ax
        ret

ATISetBank      ENDP

;/*
;**********************************  Video 7  ********************************
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = V7Entry
;*
;* DESCRIPTION   =
;*
;*      Enable Extended registers
;*
;*      Set Single Bank address mode
;*
;*      Set up local var (SetBank) with the address of the Read/Write routine
;*      we need to call.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7Entry         PROC    NEAR

                call    V7EnableExt             ;Enable Extended Registers

                call    V7SetSingleBank         ;Set Single Bank Address Mode

                mov     ax, OFFSET cs:V7SetReadBank
                mov     bx, OFFSET cs:V7SetWriteBank
                cmp     ChipVersion, VIDEO7_HT205_CHIP
                je      short @F                ; 
                mov     ax, OFFSET cs:V7SetReadBankA
                mov     bx, OFFSET cs:V7SetWriteBankA
@@:             mov     SetBank, ax             ;Assume read from video buffer
                cmp     Mode, RESTORE           ; 
                jne     short @F                ; 
                mov     SetBank, bx             ;Set write
@@:             ret

V7Entry         ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7Exit
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7Exit          PROC    NEAR

                call    V7DisableExt            ; 
                ret

V7Exit          ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7EnableExt
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7EnableExt     PROC    Near

                mov     dx, 03c4h               ;Extension Control register
                mov     ax, 0ea06h              ;write 0eah to reg 6
                out     dx, ax                  ; 
                ret
V7EnableExt     ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = V7DisableExt
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7DisableExt    PROC    Near
                mov     dx, 03c4h               ;Extension Control register
                mov     ax, 0ae06h              ;write 0aeh to reg 6
                out     dx, ax                  ; 
                ret
V7DisableExt    ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7SetReadBank  Versions 1-3
;*
;* DESCRIPTION   =
;*
;*      On Entry: AH has read bank number
;*      Destroys: DX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7SetReadBank   PROC    Near

                push    ax
                cmp     LinearMode, LINEAR_MODE ; 
                je      short V7SetRead256      ; 

V7SetRead16:                                    ;Set 16-colour Read Bank
                mov     dx, 03C4H               ;select Bank Select Reg
                mov     al, 0F6H                ; 
                out     dx, al                  ; 
                inc     dl                      ; 
                in      al, dx                  ;get current value
                and     al, 0FCH                ;clear bits 0-1
                and     ah, 1                   ;can only be 0 or 1
                shl     ah, 2                   ;move into position
                or      al, ah                  ; 
                out     dx, al                  ; 
                pop     ax                      ; 
                ret

V7SetRead256:                                   ;Set 256-colour Read Bank
                push    bx                      ; 
                mov     bl, ah                  ;save read bank
                and     ah, 1                   ;isolate bit 0
                mov     al, 0F9H                ;Extended Page Select Reg
                out     dx, ax                  ;set read bank bit 0

                mov     ah, bl                  ; 
                and     ah, 2                   ;isolate bit 1
                shl     ah, 4                   ;shift read bit 1 into place
                mov     dx, 03CCH               ;Miscellaneous Register read
                in      al, dx                  ;get current value
                and     al, 0DFH                ;clear bit 5
                or      al, ah                  ;move in new bit 5
                mov     dx, 03C2H               ;Miscellaneous Register write
                out     dx, al                  ; 

                mov     dx, 03C4H               ;Bank Select Reg
                mov     al, 0F6H                ; 
                out     dx, al                  ; 
                inc     dl                      ; 
                in      al, dx                  ;get current value
                and     al, 0F3H                ;clear bits 3-2
                and     bl, 0CH                 ;isolate bits 3-2
                or      al, bl                  ;move in new bits
                out     dx, al                  ; 

                pop     bx                      ; 
                pop     ax                      ; 
                ret
V7SetReadBank   ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7SetWriteBank  Versions 1-3
;*
;* DESCRIPTION   =
;*
;*      On Entry: AH has write bank number
;*      Destroys: DX, AX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7SetWriteBank  PROC    Near
                push    ax                      ; 
                cmp     LinearMode, LINEAR_MODE ; 
                je      short V7SetWrite256     ; 

V7SetWrite16:                                   ;Set 16-colour Write Bank
                mov     al, 0F6H                ; 
                mov     dx, 03C4H               ;select Bank Select Reg
                out     dx, al                  ; 
                inc     dl                      ; 
                in      al, dx                  ;get current value
                and     al, 0FCH                ;clear bits 0-1
                and     ah, 1                   ;can only be 0 or 1
                or      al, ah                  ; 
                out     dx, al                  ; 
                pop     ax                      ; 
                ret

V7SetWrite256:                                  ;Set 256-colour Write Bank
                push    bx                      ; 

                mov     bl, ah                  ;save write bank
                and     ah, 1                   ;isolate bit 0
                mov     al, 0F9H                ;Extended Page Select Reg
                out     dx, ax                  ;set write bank bit 0

                mov     ah, bl                  ; 
                and     ah, 2                   ;isolate bit 1
                shl     ah, 4                   ;shift into write position
                mov     dx, 03CCH               ;Miscellaneous Register read
                in      al, dx                  ;get current value
                and     al, 0DFH                ;clear bit 5
                or      al, ah                  ;move in new bit 5
                mov     dx, 03C2H               ;Miscellaneous Register write
                out     dx, al                  ; 

                mov     dx, 03C4H               ;Bank Select Reg
                mov     al, 0F6H                ; 
                out     dx, al                  ; 
                inc     dl                      ; 
                in      al, dx                  ;get current value
                and     al, 0FCH                ;clear bits 0-1
                shr     bl, 2                   ; 
                and     bl, 3                   ;isolate bits 0-1
                or      al, bl                  ;move them in
                out     dx, al                  ;do bits 3 and 2

                pop     bx                      ; 
                pop     ax                      ; 
                ret
V7SetWriteBank  ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7SetReadBankA  Versions 4/5
;*
;* DESCRIPTION   =
;*
;*      On Entry: AH has read bank number
;*      Destroys: DX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7SetReadBankA  PROC    Near

                push    ax                      ; 
                push    bx                      
                mov     bx, ax                  ;save AX
                push    ds                      
                mov     ax, DGROUP              
                mov     ds, ax                  
                mov     ax, bx                  
                shl     ah, 4                   ; 
                cmp     TextMode, 1             
                jnz      short @F
                or      ah, 20h                 ;set bit 5 for text modes
@@:             mov     al, 0E9H                ;read bank register
                mov     dx, 03C4H               ;select Write Bank Reg
                out     dx, ax                  ; 
                pop     ds                      
                pop     bx                      ; 
                pop     ax                      ; 
                ret


V7SetReadBankA  ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7SetWriteBankA  Versions 4/5
;*
;* DESCRIPTION   =
;*
;*      On Entry: AH has write bank number
;*      Destroys: DX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7SetWriteBankA PROC    Near

                push    ax                      ; 
                push    bx                      
                mov     bx, ax                  ;save AX
                push    ds                      
                mov     ax, DGROUP              
                mov     ds, ax                  
                mov     ax, bx                  
                shl     ah, 4                   ; 
                cmp     TextMode, 1             
                jnz      short @F
                or      ah, 20h                 ;set bit 5 for text modes
@@:             mov     al, 0E8H                ; 
                mov     dx, 03C4H               ;select Write Bank Reg
                out     dx, ax                  ; 
                pop     ds                      
                pop     bx                      ; 
                pop     ax                      ; 
                ret

V7SetWriteBankA ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = V7SetSingleBank
;*
;* DESCRIPTION   = sets up Single Bank mode for Version 4+ chips
;*
;*      Destroys: DX, AX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

V7SetSingleBank PROC    Near

                mov     al, 0E0H                ;Miscellaneous Control Reg
                mov     dx, 03C4H               ; 
                out     dx, al                  ; 
                inc     dx                      ; 
                in      al, dx                  ; 
                and     al, 07FH                ;clear bit 7
                out     dx, al                  ; 
                ret

V7SetSingleBank ENDP

;/*
;********************************  Western Digital  ****************************
;*/


;/***************************************************************************
;*
;* FUNCTION NAME = WDEntry
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDEntry         PROC    NEAR

                call    WDEnableExt             ; 
                call    WDSetSingleBank         ; 
                mov     SetBank, OFFSET cs:WDSetBank
                ret

WDEntry         ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = WDExit
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDExit          PROC    NEAR

                call    WDDisableExt            
                ret

WDExit          ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = WDSetBank
;*
;* DESCRIPTION   =
;*
;*      Only use Bank Register PR0A because we set up Single Bank mode
;*      previously. The register has 4k granularity, so adjust to 64k.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDSetBank       PROC    NEAR

        push    ax                      ; 
        mov     al, 014h                ;PR34 index Dsp Mem Map /*          */
        mov     dx, 003c4h              ;SEQ index address      /*          */
        out     dx, al                  ;Idx Display Mem Map reg/*          */
        inc     dx                      ;SEQ data address       /*          */
        in      al, dx                  ;Get Display Mem Map reg/*          */
        and     al, 0bfh                ;clear bit 6=PR0A bit 8 /*          */
        shl     ah, 2                   ;Move 4:4 to PR0A bit 8 /*          */
        xor     al, ah                  ;Add in all bank bits   /*          */
        and     ah, not 040h            ;Just change this bit   /*          */
        xor     al, ah                  ;Just add new PR0A bit 8/*          */
        out     dx, al                  ;restore reg            /*          */
;       mov     dl, 03ceh               ;                       /*          */
        mov     dl, 0ceh                ;                       /*          */
        mov     al, 09h                 ; 
        shl     ah, 2                   ;Shift remaining amount /*          */
        out     dx, ax                  ; 
        pop     ax                      ; 
        ret

WDSetBank       ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = WDSetSingleBank
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDSetSingleBank PROC    NEAR

                mov     dx, 03c4h               ;Fix System Interface reg
                mov     al, 11h                 ;  in case a WD chip present
                out     dx, al                  ; 

                inc     dx                      ; 
                in      al, dx                  ; 
                and     al, 07fh                ;zero bit 7
                out     dx, al                  ;restore register

                mov     dx, 03ceh               ;Fix Memory Size register
                mov     al, 0bh                 ;disable PR0B
                out     dx, al                  ; 

                inc     dx                      ; 
                in      al, dx                  ; 
                and     al, 0f7h                ;reset bit 3
                out     dx, al                  ; 

                ret

WDSetSingleBank ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = WDEnableExt
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDEnableExt     PROC    NEAR

                mov     dx, 03ceh               ; 
                mov     ax, 050fh               ; 
                out     dx, ax                  

                mov     dx, 03d4h               ; 
                mov     ax, 08529h              ; 
                out     dx, ax                  ;unlock read/write

                mov     dx, 03c4h               ; 
                mov     ax, 04806h              ; 
                out     dx, ax                  ;unlock extended sequencer

                ret

WDEnableExt     ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = WDDisableExt
;*
;* DESCRIPTION   =
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

WDDisableExt    PROC    NEAR

                mov     dx, 03ceh               ; 
                mov     ax, 000fh               ; 
                out     dx, ax                  

                mov     dx, 03d4h               ; 
                mov     ax, 0029h               ; 
                out     dx, ax                  ;lock read/write

                mov     dx, 03c4h               ; 
                mov     ax, 0006h               ; 
                out     dx, ax                  ;lock extended sequencer

                ret

WDDisableExt    ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = MoveBytes
;*
;* DESCRIPTION   =
;*
;*      On Entry: CX has no of bytes to move
;*                DS:SI -> system memory
;*                ES:DI -> video memory
;*                FS has segment of _HugeShift
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

MoveBytes       PROC    Near                    ; 

                push    cx                      ;save no of bytes to move

                mov     ax, 0FFFFh              ;Segment size - 1
                sub     ax, di                  ;ax = amount left -1

                xor     bx, bx                  ;Assume everything will fit
                .if     <nonzero di>            ;Not at start of segment
                  inc   ax                      ;ax = amount left
                  mov   bx, cx                  ;bx = section size
                  sub   bx, ax                  ;bx = Amount not copied
                  .if <nz>                      ;cx = zero => 64k move and bx == ax
                      mov       cx, ax          ;cx = room left in huge segment
                  .else
                    .if < nc >                  ;PVBLength > room left in huge segment
                      mov       cx, ax          ;cx = room left in huge segment
                    .else
                      xor       bx, bx          ;Everything will fit
                    .endif
                  .endif
                .endif

                @SwitchIfReverse

                .if     <bit cx and 3>          ;Odd number of bytes to move
                  push    cx                    ; 
                  shr     cx, 2                 ;Compute number of dwords
                  rep     movsd                 ;Move all full dwords
                  pop     cx                    ; 
                  and     cx, 3                 ; 
                  rep     movsb                 ;Move remaining byte
                .else                           ; 
                  shr     cx, 2                 ;Compute number of dwords
                  .if     <z>                   ; 
                    mov     cx, 4000h           ;Compensate for CX=0 ==> CX=64K         ;
                  .endif                        ; 
                  rep     movsd                 ;Move all full words
                .endif                          ; 

                @SwitchIfReverse

                .if     <nonzero bx>            ;Segment overflow
                  mov   ax, es                  ; 
                  add   ax, fs:_HugeShift       ; 
                  mov   es, ax                  ;es:di = next huge segment
                  mov   cx, bx                  ;get leftover amount

                  @SwitchIfReverse

                  shr   cx, 2                   ;Compute number of dwords
                  rep   movsd                   ;Move all full dwords
                  .if   <bit bx and 3>          ;Odd number of bytes to move
                    rep movsb                   ;Move remaining byte
                  .endif                        ; 

                  @SwitchIfReverse

                .endif

                pop     cx                      ;recover bytes moved

                ret
MoveBytes       ENDP

R2SEG           ENDS

                END

