;*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.;
;*****************************************************************************/
;       SCCSID = @(#)svgabank.asm       1.0 92/12/25
; ****************************************************************************
; *                                                                          *
; *                                                                          *
; *                                                                          *
; ****************************************************************************
        PAGE    58,132
        TITLE   Screen Device Driver - (svgabank.Asm)
        .286p                                                           ;@T30

;/***********************************************************************/
;/*                                                                     */
;/* SOURCE FILE NAME: svgabank.asm      STATUS: Version 1.1             */
;/*                                                                     */
;/* DESCRIPTIVE NAME:  Base Video Subsystem Screen Device Driver        */
;/*                                                                     */
;/* FUNCTION:   Provide SVGA bank routines, called by routines          */
;/*               GetSVGABank and                                       */
;/*               SetSVGABank                                           */
;/*                                                                     */
;/* NOTES:  Executes on Level 0                                         */
;/*                                                                     */
;/* ENTRY POINT:                                                        */
;/*   LINKAGE: Far Call                                                 */
;/*                                                                     */
;/* INPUT:  ES:BX = request packet address                              */
;/*       DS = BIODATA                                                  */
;/*                                                                     */
;/* EXIT-NORMAL:                                                        */
;/*                                                                     */
;/* EFFECTS:  None                                                      */
;/*                                                                     */
;/*   ROUTINES:                                                         */
;/*                                                                     */
;/************************ END OF SPECIFICATIONS ************************/
.xlist
        INCLUDE basemaca.inc            ;;;;;; 2.0 unique (dosmac replacement)
        INCLUDE devhlp.inc              ; Define DevHlp functions
        INCLUDE devsym.inc              ; Define DOS equates
        INCLUDE error.inc               ; Define Error Messages
        INCLUDE struc.inc               ; Define STRUC macros
;        include iodelay.inc            ;                       /*          */
        include bsedev.inc              ;@senja
        include svgadefs.inc            ;                       /*          */
.list

;@senja READ_BANK               EQU    0H
;WRITE_BANK              EQU    1H

;MODE_TEXT               EQU    0H
;MODE_PLANAR             EQU    1H
;MODE_LINEAR             EQU    2H

;SEQ_LOCKED              EQU    1H      ;                       /*          */
;GDC_LOCKED              EQU    2H      ;                       /*          */

BioData SEGMENT WORD PUBLIC 'DATA'
        ASSUME  DS:BioData

        EXTRN   _sSVGA : WORD           ;                       /*          */
        EXTRN   _XGAInstance : WORD     ;Speedway XGA instance  /*          */
        EXTRN   SvgaOEMInfo : WORD      ;                       /*          */

        EXTRN   SVGA_SET_BANK_TABLE : WORD      ;               /*          */
        EXTRN   SVGA_GET_BANK_TABLE : WORD      ;               /*          */

BioData ENDS


BiosSeg SEGMENT WORD Public 'CODE'
        ASSUME  CS:BiosSeg

PUBLIC  NOPSetBank
PUBLIC  ATISetBank
PUBLIC  CirrusSetBank
PUBLIC  IBMSetBank
PUBLIC  S3SetBank                     ;           
PUBLIC  TridentSetBank
PUBLIC  TsengSetBank
PUBLIC  Video7SetBank
PUBLIC  WDSetBank
PUBLIC  WeitekSetBank

PUBLIC  NOPGetBank
PUBLIC  ATIGetBank
PUBLIC  CirrusGetBank
PUBLIC  IBMGetBank
PUBLIC  S3GetBank                     ;           
PUBLIC  TridentGetBank
PUBLIC  TsengGetBank
PUBLIC  Video7GetBank
PUBLIC  WDGetBank
PUBLIC  WeitekGetBank

;!!svgaxfer too!

        EXTRN  SVGAPhysToUVirt   : Near
        EXTRN  SVGAUnPhysToUVirt : Near

;/***************************************************************************
;*
;* FUNCTION NAME = GetTridentRegDef
;*
;* DESCRIPTION   = Return the current definition of the extended sequencer
;*                 registers.
;*
;* INPUT         = None
;*
;* OUTPUT        = AX = TRUE  - registers are in 'new' mode
;*                     = FALSE - registers are in 'old' mode
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* CLOBBERS      = DX
;*
;**************************************************************************/

GetTridentRegDef      PROC      NEAR

        mov     dx, 03c4h               ;SEQ index address
;                                                               /*          */
;       Let the calling routine save this index!                /*          */
;                                                               /*          */
;       in      al, dx                  ;Get current SEQ index  /*          */
;       mov     cl, al                  ;Save SEQ index.        /*          */
        mov     al, 00eh                ;Mode Ctrl Reg 1 index
        cli
        out     dx, al                  ;select Mode Control Reg 1
        inc     dx                      ;SEQ data address
        in      al, dx                  ;get current contents
        mov     ah, al                  ; 
        out     dx, al                  ;write out again
        in      al, dx                  ;get contents
        out     dx, al                  ;guarantee the same
        cmp     al, ah                  ;reverse page bit ?
        mov     ah, 001h                ;Assume new             /*          */
        .if     < z >                   ;reverse page bit ?
            dec     ah                  ;Not new, old instead.  /*          */
;
;               You could do the following read unconditionally.
;               It is not a toggle, but forces new definitions.
;
            mov     al, 00bh            ;read version => set 64K mode
            dec     dx                  ;SEQ index address
            out     dx, al              ; 
            inc     dx                  ;SEQ data address
            in      al, dx              ;Dummy read to set 64K mode.
        .endif                          ;                       /*          */
;       dec     dx                      ;SEQ index address      /*          */
;       mov     al, cl                  ;Restore SEQ index      /*          */
;       out     dx, al                  ;                       /*          */
        mov     dl, 0cch                ;Misc Output Read addr
        in      al, dx                  ; 
;       mov     ah, al                  ;                       /*          */
        mov     dl, 0c2h                ;Misc Output Write addr
        or      al, 020h                ;select low page memory
        out     dx, al                  ;set Misc Output
        sti                             ; 
        mov     al, ah                  ;1 if new, 0 if old.
        cbw                             ;                       /*          */

;/****************************************************************************
;*
;* FUNCTION NAME = NOPSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

NOPSetBank      PROC    NEAR

        ret

NOPSetBank      ENDP

GetTridentRegDef         ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = ATISetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

ATISetBank      PROC    NEAR
        shl     cl, 001h                ;Convert to 32K page num/*          */
        .if     <[_sSVGA.ChipType] ae ATI_88800_CHIP> ;         /*          */
            mov     al, cl              ;Get the bank           /*          */
            cbw                         ;Extend to fullword     /*          */
            mov     dx, 056ech          ;MEM_VGA_WPS0           /*          */
            out     dx, ax              ;Set the bank           /*          */
            mov     dx, 05aech          ;MEM_VGA_RPS0           /*          */
            out     dx, ax              ;Set the bank           /*          */
            inc     al                  ;Use 2nd 32K page num   /*          */
            mov     dx, 056eeh          ;MEM_VGA_WPS1           /*          */
            out     dx, ax              ;Set the bank           /*          */
            mov     dx, 05aeeh          ;MEM_VGA_RPS1           /*          */
            out     dx, ax              ;Set the bank           /*          */
        .endif                          ;                       /*          */
;       Do always because 88800 needs this in 16 color modes!   /*          */
;!!Does 2M require 128K pages?
;
;       Note: ATI index register value does not remain the same after use!
;       So there is no use saving and restoring it.
;       And you must re-index to re-write a read value.
;
        and     cl, not 0e1h            ;Prevent bank overrun.  /*          */
        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     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).
        or      al, cl                  ;Add in new bank select
        xchg    ah, al
        out     dx, ax                  ;Set the bank
        ret

ATISetBank      ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = CirrusSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

CirrusSetBank   PROC    NEAR
;                                       ;Up to 2M should be OK!

        mov     dx, 03c4h               ;SEQ index address
        in      al, dx
        mov     ah, al                  ;Save SEQ index.
;*
        mov     al, 006h                ;Get lock index.
        out     dx, al
        inc     dx                      ;SEQ data address
        in      al, dx                  ;Get lock value.
        push    ax                      ;Save lock & SEQ index  /*          */
        mov     al, 012h                ;Unlock it now.         /*          */
        out     dx, al                  ;                       /*          */
;*
        mov     dl, 0ceh                ;GDC address            /*          */
        in      al, dx
        mov     ah, al                  ;Save GDC index.
;*
;*!!            Make sure GRB 3ce.0b has bit 5 set!             /*          */
;*!!            Make sure GRB 3ce.00 has bit 0 reset!           /*          */
;*
        mov     al, 00bh                ;GRB Mode Extensions reg/*          */
        out     dx, al                  ;                       /*          */
        inc     dx                      ;GDC data address       /*          */
        in      al, dx                  ;                       /*          */
        and     al, 0deh                ;Set Offset Register 0  /*          */
        or      al, 020h                ;Set Offset Granularity /*          */
        out     dx, al                  ;Set GR[B]              /*          */
;*
        mov     al, 009h
        dec     dx                      ;GDC index              /*          */
        out     dx, al

        shl     cl, 2                   ;Shift bank select to 7:2.
        mov     al, cl
        inc     dx                      ;GDC data address
        out     dx, al                  ;Set the bank
        dec     dx                      ;GDC index address
;*
        mov     al, ah                  ;Restore GDC index.
        out     dx, al
;*
        pop     ax                      ;Restore SEQ idx&(un)lck/*          */
        mov     dl, 0c4h + 001h         ;SEQ data address       /*          */
        out     dx, al                  ;Index still set!
        dec     dx                      ;SEQ index address      /*          */
;*
        mov     al, ah                  ;Restore SEQ index      /*          */
        out     dx, al
        ret

CirrusSetBank   ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = IBMSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

IBMSetBank      PROC    NEAR

        mov     al, cl                  ;set the bank           /*          */
        mov     dx, [_XGAInstance]      ;                       /*          */
        add     dx, 008h                ;offset register
        out     dx, al
        ret

IBMSetBank      ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = S3SetBank                                   
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

S3SetBank       PROC    NEAR                       ;           
;                                       ;Up to 4M should be OK!
;!!What about monochrome displays!? 3b4?

        mov     dx, 03d4h               ;CRTC index address
        in      al, dx
        mov     ch, al                  ;Save CRTC index        /*          */
;*
        mov     ax, 04838h              ;CR38 lock/unlock index /*          */
        out     dx, al
        inc     dx                      ;CRTC data address
        in      al, dx
        xchg    ah, al                  ;Save (un)lock/get unlck/*          */
        out     dx, al                  ;Unlock ext regs        /*          */
        dec     dx                      ;CRTC index address
;*
;       and     cx, 03fh                ;prevent overrun.       /*          */
        mov     al, 035h
;       mov     dl, 0d4h                ;CRTC index address     /*          */
        out     dx, al                  ;Output both index&data
        mov     al, cl                  ; supports up to 4 MB
        and     al, 00fh
        inc     dx                      ;CRTC data address
        out     dx, al
        dec     dx                      ;CRTC index address
;*
        mov     al, 031h                ;CR31 mem config reg.   /*          */
        out     dx, al                  ; 
        inc     dx                      ;CRTC data address
        in      al, dx                  ; 
        or      al, 001h                ;Enable 64K page addr.
        out     dx, al                  ;                       /*          */
        dec     dx                      ;CRTC index address
;*
        mov     al, 038h                ;CR38 lock/unlock index /*          */
        out     dx, ax                  ;Restore lock/unlock    /*          */
;*
        mov     ax, 0a039h              ;CR39 lock/unlock index /*          */
        out     dx, al
        inc     dx                      ;CRTC data address
        in      al, dx
        xchg    ah, al                  ;Save (un)lock/get unlck/*          */
        out     dx, al                  ;Unlock ext regs        /*          */
        dec     dx                      ;CRTC index address
;*
;*      Do we need to check chiptype? Why not just write?
;*      Does the index register wrap?
        .if     <[_sSVGA.ChipType] ae S3_86C864_CHIP>
            mov     al, 06ah            ;Ext System Ctrl Reg 4.
            out     dx, al
            inc     dx                  ;CRTC data address
            mov     al, cl              ;Extend the bank number.
            out     dx, al              ;write ext system cntl reg
            dec     dx                  ;CRTC index address     /*          */
        .endif
        and     cl, 030h                ;get bits 5:4
        shr     cl, 4-2                 ;bits 5:4 of the bank into bits 3:2
        mov     al, 051h
        out     dx, al
        inc     dx                      ;CRTC data address
        in      al, dx
        and     al, not 00ch            ;clear bits 3:2
        or      al, cl                  ;set the extended bank bits
        out     dx, al                  ;write it
        dec     dx                      ;CRTC index address     /*          */
;*
        mov     al, 039h                ;CR39 lock/unlock index /*          */
        out     dx, ax                  ;Restore lock/unlock    /*          */
;*
;                                                               /*           end */
;       mov     dl, 0d4h                ;CRTC index address     /*          */
        mov     al, ch                  ;Restore CRTC index
        out     dx, al
        ret

S3SetBank       ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = TridentSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;*                 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.  The
;*                      register's previous state therefore can't be
;*                      restored.  All we need in a multi-tasking
;*                      environment......  Note also that Page bit (bit 1)
;*                      is inverted when setting the write bank and doesn't
;*                      read back as written.
;*
;*                 Mode Control registers 1 & 2 are at 3c4/5 index
;*                 0Dh and 0Eh.
;*
;*                 Write operations require bit 1 (Page Select) to be
;*                 inverted.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

TridentSetBank  PROC    NEAR

        .if <di ae MODE_PLANAR>         ;Only grafix modes handled /*          */
            mov     dx, 03ceh           ;GDC index address
            in      al, dx
            mov     ah, al              ;Save GDC index.        /*          */
;*
            mov     al, 006h            ;Misc reg index         /*          */
            out     dx, al
            inc     dx                  ;GDC data address
            in      al, dx              ;Read GDC misc reg
            test    al, 008h
            .if     < z >               ;Exit if A0000 not referenced
                mov     dl, 0c4h        ;SEQ index address      /*          */
                in      al, dx
                push    ax              ;Save GDC&SEQ indices   /*          */
;               push    cx              ;Save bank              /*          */
                call    GETTRIDENTREGDEF ; this destroys ax, dx, cx.
;               pop     cx              ;Restore bank           /*          */
                mov     ch, al          ;save the result AX=1 new mode.
;                                                               /*          */
;               GDC index still points to miscellaneus reg!     /*          */
;                                                               /*          */
;               mov     al, 006h        ;Misc reg index         /*          */
;               mov     dl, 0ceh        ;GDC index address      /*          */
;               out     dx, al                                  /*          */
                mov     al, 005h        ;Mem addr mode to 64K   /*          */
                mov     dl, 0ceh + 001h ;GDC data address       /*          */
                out     dx, al
;*
                mov     al, 00bh        ;                       /*          */
                mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, al
                inc     dx              ;SEQ data address
                in      al, dx          ;Chgs mode ctrl to new definition.
                dec     dx              ;SEQ index address      /*          */
;*
                mov     ah, cl          ;Get bank               /*          */
                xor     ah, 002h        ;Invert bank bit        /*          */
                mov     al, 00eh        ;Mode Ctrl 1 reg index
                out     dx, ax          ;Output both index&data /*          */
;               mov     al, ah                                  /*          */
;               inc     dx              ;SEQ data address       /*          */
;               out     dx, al                                  /*          */
;               dec     dx              ;SEQ index address.     /*          */
;*
                and     ch, ch          ;Test reg definition    /*          */
                .if     < z >           ;Is definition old? Restore it
                    mov     al, 00bh    ;AH doesn't matter!     /*          */
;                   mov     dl, 0c4h    ;SEQ index address      /*          */
                    out     dx, ax      ;Output both index&data /*          */
;                   mov     al, ah                              /*          */
;                   inc     dx          ;SEQ data address       /*          */
;                   out     dx, al                              /*          */
;                   dec     dx          ;SEQ index address.     /*          */
                .endif
;*
                pop     ax              ;Restore GDC&SEQ indices/*          */
;               mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, al
            .endif
;*
            mov     al, ah              ;Restore GDC index      /*          */
            mov     dl, 0ceh            ;GDC index address      /*          */
            out     dx, al
        .endif
ExitTrident:
        ret

TridentSetBank  ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = TsengSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*                                                              /*          */
;*      Set read and write bank to same values.
;*      Read bank 5:0 @ 5:4 of 3CB, 7:4 of 3CD
;*      Write bank 5:0 @ 1:0 of 3CB, 3:0 of 3CD
;*      ET4000/ET3000 do not have a 3CB.
;*      ET3000 has read bank in 5:3 of 3CD and write bank in 2:0.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

TsengSetBank    PROC    NEAR
;                                       ;Up to 4M should be OK!

        mov     ch, cl
        and     cx, 00f30h              ;Prevent bank overrun.
        mov     ax, cx
        mov     dx, [_sSVGA.ChipType] ;                         /*          */
        rol     al, 4
        shl     ah, 3                   ;Get read bank.
        .if     <dx ae TSENG_ET4000_CHIP> ; adjust for ET4000   /*          */
            shl     ah, 1
        .endif
        or      ax, cx
        .if     <dx a TSENG_ET4000_CHIP>; adjust for ET4000W32  /*          */
            mov     dx, 003cbh          ;Get GDC Segment Select 2 addr.
            out     dx, al              ;Output bits 4:5 of read/write banks.
        .endif                          ;Does not exist on ET4000/ET3000.
        mov     dx, 003cdh              ;Get GDC Segment Select 1 addr.
        mov     al, ah
        out     dx, al                  ;Output bits 0:3 of read/write banks.
        ret

TsengSetBank    ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = Video7SetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;*     We have two scenarios here, one for the HT205 chip
;*     (Version 3) and another for HT208/HT209 (Version 4/5)
;*     chips.
;*
;*     Version 4/5 are easy, a single register is dedicated to
;*     selecting the read bank and another to the write bank.
;*     The chip should first be set into single bank mode before
;*     setting these registers.
;*
;*     Version 3 chips are a nightmare.  There are different
;*     registers to be set according to whether the mode is
;*     16/256 colour and also for read/write bank selection.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;* CLOBBERS      = AX, CX, DX
;*
;****************************************************************************/

Video7SetBank   PROC    NEAR

        mov     dx, 03c4h               ;SEQ index address
        in      al, dx
        mov     ch, al                  ;Save SEQ index         /*          */
;*
        mov     ax, 00606h              ;Lock reg index (twice) /*          */
        out     dx, al
        inc     dx                      ;SEQ data address
        in      al, dx                  ;Not read as written    /*          */
        and     al, 001h                ;0=locked, 1=unlocked   /*          */
        mov     al, 0eah                ;Assume unlocked        /*          */
        out     dx, al                  ;Unlock it now.         /*          */
        dec     dx                      ;SEQ index address      /*          */
        .if     < z >                                           /*@V2.1MNH13*/
            mov     al, 0aeh            ;Locked instead         /*          */
        .endif                          ;0aeh=lock, 0eah=unlock /*          */
        xchg    al, ah                  ;Xchg index&unlock      /*          */
        push    ax                      ;Save lock index&(un)lck/*          */
;*
        .if     <[_sSVGA.ChipType] eq VIDEO7_HT205_CHIP> ;HT_205/*          */
            .if     <di ne MODE_PLANAR> ;other than planar mode /*          */
                mov     al, 0f9h
                mov     ah, cl          ;                       /*          */
                and     ah, 001h        ;Get first bit of bank  /*          */
;               mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, ax          ;Output both index&data /*          */
;               mov     al, ah          ;                       /*          */
;               inc     dx              ;SEQ data address       /*          */
;               out     dx, al          ;                       /*          */
;               dec     dx              ;SEQ index address.     /*          */
;*
                mov     dl, 0cch        ;Misc Output Read addr
                in      al, dx
                and     al, 0dfh        ;Clear bit 5 of misc.
                mov     ah, cl          ;Bank that needs to be set.
                and     ah, 002h        ;Move second bit into bit 5
                shl     ah, 4
                or      al, ah
                mov     dl, 0c2h        ;Misc Output Write addr
                out     dx, al          ;Write new Misc Output reg value
;*
                mov     dl, 0c4h        ;SEQ index address      /*          */
                shr     cl, 2           ;Now save next 2 bits
            .endif                      ;End if non-planar
;*
            mov     al, 0f6h            ;Get Bank select        /*          */
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al
            inc     dx                  ;SEQ data address
            in      al, dx              ;Read bank select register
            and     al, 0f0h            ;Reset bit 0:1 for write & 2:3 for read
            and     cl, 003h            ;Prevent bank overrun.
            mov     ah, cl
            shl     ah, 2
            or      ah, cl
            or      al, ah              ;Set read=write bank.
            out     dx, al
            dec     dx                  ;SEQ index address.     /*          */
        .else                           ;Else HT_208 or HT_209
            mov     al, 0e0h            ;                       /*          */
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al              ;Misc Ctrl
            inc     dx                  ;SEQ data address
            in      al, dx
            and     al, 07fh
            out     dx, al              ;Set single bank mode
            dec     dx                  ;SEQ index address      /*          */
;*
            mov     ah, cl
            shl     ah, 4
            .if <di eq MODE_TEXT>
                or      ah, 020h
            .endif
            mov     al, 0e8h            ;Write bank select reg
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, ax              ;Output both index&data /*          */
;           mov     al, ah                                      /*          */
;           inc     dx                  ;SEQ data address       /*          */
;           out     dx, al                                      /*          */
;           dec     dx                  ;SEQ index address.     /*          */
;           mov     al, 0e9h            ;Read bank select reg   /*          */
;*
            inc     al                  ;Read bank select reg   /*          */
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, ax              ;Output both index&data /*          */
;           mov     al, ah                                      /*          */
;           inc     dx                  ;SEQ data address       /*          */
;           out     dx, al                                      /*          */
;           dec     dx                  ;SEQ index address.     /*          */
        .endif                          ;HT_208 or HT_209       /*          */
Video7EndSetBank:
;*
;       mov     dl, 0c4h                ;SEQ index address.     /*          */
;       mov     al, 006h                ;Lock register index    /*          */
        pop     ax                      ;Restore lock idx&unlock/*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                  ;                       /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                  ;                       /*          */
;       dec     dx                      ;SEQ index address.     /*          */
;*
        mov     al, ch                  ;Restore SEQ index.     /*          */
;       mov     dl, 0c4h                ;SEQ index address.     /*          */
        out     dx, al                  ;Restore SEQ index
        ret

Video7SetBank   ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = WDSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WDSetBank       PROC    NEAR

        mov     dx, 03c4h               ;SEQ index address
        in      al, dx
        mov     ch, al                  ;Save SEQ index         /*          */
;
        mov     ax, 04048h              ;Test index.
        out     dx, al                  ;Write 7 bit index.
        in      al, dx                  ;Read 3 bits locked, 6 bits unlocked
        or      ah, al                  ;Add in required for (un)lock.
        mov     al, 006h                ;PR20 index             /*          */
        push    ax                      ;Save PR20index&(un)lock/*          */
;*
        mov     ah, 048h                ;Unlock SEQ             /*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                                          /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                                          /*          */
;       dec     dx                      ;SEQ index address.     /*          */
;*
        mov     al, 011h                ;PR31 index             /*          */
;       mov     dl, 0c4h                ;SEQ index address      /*          */
        out     dx, al                  ;Fix System Interface reg
        inc     dx                      ;SEQ data address
        in      al, dx
        and     al, 07fh                ;clear bit 7
        out     dx, al                  ;restore reg
        dec     dx                      ;SEQ index address      /*          */
;*
        mov     al, 014h                ;PR34 index Dsp Mem Map /*          */
;       mov     dl, 0c4h                ;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 /*          */
        mov     ah, cl                  ;Get bank               /*          */
        and     ah, 010h                ;Get 4th bit of bank    /*          */
        shl     ah, 2                   ;Move to PR0A bit 8     /*          */
        or      al, ah                  ;Add in new PR0A bit 8  /*          */
        out     dx, al                  ;restore reg            /*          */
        dec     dx                      ;SEQ index address      /*          */
;*
        pop     ax                      ;Restore PR20index&unlck/*          */
;       mov     dl, 0c4h                ;SEQ index address      /*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                                          /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                  ;SEQ (un)lock           /*          */
;       dec     dx                      ;SEQ index address      /*          */
;*
        mov     al, ch                  ;Restore SEQ index      /*          */
        out     dx, al
;*
        mov     dl, 0ceh                ;GDC index address      /*          */
        in      al, dx
        mov     ch, al                  ;Save GDC index         /*          */
;*
        mov     ax, 00f0fh              ;PR05 index (twice)
        out     dx, al                  ;Are GDC's locked?
        inc     dx                      ;GDC data address
        in      al, dx                  ;Get (un)lock
        xchg    al, ah                  ;Xchg index&unlock      /*          */
        push    ax                      ;Save PR05index&(un)lock/*          */
        mov     al, 005h                ;Unlock GDC             /*          */
        out     dx, al                  ;                       /*          */
        dec     dx                      ;GDC index address      /*          */
;*
        mov     al, 00bh                ;                       /*          */
;       mov     dl, 0ceh                ;GDC index address      /*          */
        out     dx, al                  ;fix memory size reg
        inc     dx                      ;GDC data address
        in      al, dx
        and     al, 0f7h                ;clear bit 3            /*          */
        out     dx, al
        dec     dx                      ;GDC index address      /*          */
;*
        mov     ah, cl                  ;                       /*          */
        shl     ah, 4                   ;Get the bank           /*          */
        mov     al, 009h                ;PROA index
;       mov     dl, 0ceh                ;GDC index address      /*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                  ;                       /*          */
;       inc     dx                      ;GDC data address       /*          */
;       out     dx, al                  ;                       /*          */
;       dec     dx                      ;GDC index address      /*          */
;*
;       mov     al, 00fh                ;PR05 index             /*          */
        pop     ax                      ;Restore PR05index&unlck/*          */
;       mov     dl, 0ceh
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                  ;                       /*          */
;       inc     dx                      ;GDC data address       /*          */
;       out     dx, al                  ;GDC (un)lock
;       dec     dx                      ;GDC index address      /*          */
;*
        mov     al, ch                  ;Restore GDC index
;       mov     dl, 0ceh                ;GDC index address      /*          */
        out     dx, al
        ret

WDSetBank       ENDP

;*                                                              /*          */
;/****************************************************************************
;*
;* FUNCTION NAME = WeitekSetBank
;*
;* DESCRIPTION   = Set bank. No error checking or indication.
;*
;* INPUT         = CX Bank, DX Direction and DI video mode
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WeitekSetBank   PROC    NEAR

        .if     <[_sSVGA.ChipType] e WEITEK_P9000_CHIP>
            push    bx
            push    [_sSVGA.ChipType]
            mov     ax, word ptr [SvgaOEMInfo.ManufacturerData][1*word]
            mov     [_sSVGA.ChipType], ax
            mov     bx, word ptr [SvgaOEMInfo.ManufacturerData][0*word]
            shl     bx, 1
            call    [SVGA_SET_BANK_TABLE][bx]
            pop     [_sSVGA.ChipType]
            pop     bx
        .else                           ;Just VGA, not coprocessor:
            mov     dx, 003c5h          ;SEQ index address.
            mov     al, 011h            ;SEQ Misc Reg.
            out     dx, al
            inc     dx                  ;SEQ data address.
            in      al, dx              ;Get possibly FAKE current contents.
            out     dx, al              ;Write out twice to unlock.
            out     dx, al              ;Write out twice to unlock.
            in      al, dx              ;Get REAL current contents.
;
;!!         Don't really have to set control register lock!?
;
            and     al, not 040h        ;Turn off Bank Switch Disable.
            out     dx, al              ;Write out again.
            and     cl, 00fh            ;Prevent bank overrun.
            mov     al, cl              ;Get the bank.
            shl     al, 4               ;Shift to read bank position (7:4).
            or      al, cl              ;Merge read & write banks.
            mov     dl, 0cdh            ;WEITEK Bank Select address.
            out     dx, al              ;Set the banks.
        .endif
        ret

WeitekSetBank   ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = NOPGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

NOPGetBank      PROC    NEAR

        xor     ax, ax
        ret

NOPGetBank      ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = ATIGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

ATIGetBank      PROC    NEAR
        mov     cl, dl                  ;Remember the direction /*          */
        .if     <[_sSVGA.ChipType] ae ATI_88800_CHIP> ;         /*          */
            mov     dx, 056ech          ;MEM_VGA_WPS0           /*          */
            .if     <cl e READ_BANK>    ;                       /*          */
                mov     dx, 05aech      ;MEM_VGA_RPS0           /*          */
            .endif                      ;                       /*          */
            in      ax, dx              ;                       /*          */
            shr     al, 001h            ;Convert to 64K page num/*          */
            cbw                         ;Extend to fullword     /*          */
        .else                           ;                       /*          */
;
;       Note: ATI index register value does not remain the same after use!
;       So there is no use saving and restoring it.
;       And you must re-index to re-write a read value.
;
            mov     al, 0beh            ;ATI3D Miscellaneous register.
            mov     dx, 001ceh
            out     dx, al              ;misc register
            inc     dx
            in      al, dx              ;Get bank mode.
            dec     dx
            mov     ch, al
;*
            mov     al, 0b2h            ;ATI32 Memory Page Select register.
            out     dx, al              ; memory page select
            inc     dx
            in      al, dx
            ror     al, 1
            test    ch, 008h            ;if bit set, dual page mode
            .if     < ne >
                .if     <cl e READ_BANK>
                    ror     al, 4
                .endif
            .endif
            and     ax, 00fh
        .endif                          ;                       /*          */
        ret

ATIGetBank      ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = CirrusGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

CirrusGetBank   PROC    NEAR

        mov     dx, 03c4h
        in      al, dx
        mov     ah, al                  ;Save SEQ index.
;*
        mov     al, 006h                ;Get lock index.
        out     dx, al
        inc     dx                      ;SEQ data address
        in      al, dx                  ;Get lock value.
        push    ax                      ;Save lock & SEQ index  /*          */
        mov     al, 012h                ;Unlock it now.         /*          */
        out     dx, al                  ;                       /*          */
;*
        mov     dl, 0ceh                ;GDC address            /*          */
        in      al, dx
        mov     ah, al                  ;Save GDC index.
;*
        mov     al, 00bh                ;Mode extn register
        out     dx, al
        inc     dx                      ;GDC data address       /*          */
        in      al, dx
        dec     dx                      ;GDC index address      /*          */
        mov     ch, al                  ;Remember granularity.  /*          */
;*
        and     al, 001h                ;Get offset register.   /*          */
        add     al, 009h                ;Offset reg 0@9, 1@10   /*          */
        out     dx, al                  ;Address the offset reg
        inc     dx                      ;GDC data address
        in      al, dx
        dec     dx                      ;GDC index address      /*          */
        test    ch, 020h                ;2MB Addressing?        /*          */
        .if     < nz >                  ;If yes:                /*          */
            and     al, 07fh
            shr     al, 2
        .else
            shr     al, 4
        .endif
        mov     cl, al                  ;Save current bank.     /*          */
;*
        mov     al, ah                  ;Restore GDC index.
        out     dx, al                  ; 
;*
        pop     ax                      ;Restore SEQ idx&(un)lck/*          */
        mov     dl, 0c4h + 001h         ;SEQ data address       /*          */
        out     dx, al                  ;Index still set!
        dec     dx                      ;SEQ index address      /*          */
;*
        mov     al, ah                  ;Restore SEQ index      /*          */
        out     dx, al                  ; 
;*
        mov     al, cl                  ;                       /*          */
        cbw                             ;                       /*          */
        ret

CirrusGetBank   ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = IBMGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

IBMGetBank      PROC    NEAR

        mov     dx, [_XGAInstance]      ;                       /*          */
        add     dx, 008h                ;aperture index reg
        in      al, dx                  ;return current index value
        and     ah, ah
        ret

IBMGetBank      ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = S3GetBank                                   
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

S3GetBank       PROC    NEAR                       ;           

;*
;*      Save the CRTC register index so as not to disturb applications!
;*
;!!What about monochrome displays!? 3b4?
        mov     dx, 03d4h
        in      al, dx
        mov     ch, al                  ;Save the current index.
;*
;                                                               /*           end */
        mov     ax, 0a039h              ;CR39 lock/unlock index /*          */
        out     dx, al
        inc     dx                      ;CRTC data address
        in      al, dx
        xchg    ah, al                  ;Save lock/get unlock   /*          */
        out     dx, al
        dec     dx                      ;CRTC index address
;*
        xor     cl, cl
        .if     <[_sSVGA.ChipType] ae S3_86C864_CHIP>
            mov     al, 06ah            ;Ext System Ctrl Reg 4.
            out     dx, al
            inc     dx                  ;CRTC data address
            in      al, dx              ;read ext system cntl reg
            dec     dx                  ;CRTC index address     /*          */
            mov     cl, al              ;Extend the bank number.
        .endif
;*
        mov     al, 039h                ;CR39 lock/unlock index /*          */
        .if     <zero cl>
            mov     al, 051h            ;Ext System Ctrl Reg 2.
            out     dx, al
            inc     dx                  ;CRTC data address
            in      al, dx              ;read ext system cntl reg
            dec     dx                  ;CRTC index address     /*          */
            and     al, 00ch            ;Is extended bank bit set?
            shl     al, 2               ;Shift bit 2 (004h) to bit 4 (010h).
            mov     cl, al              ;Extend the bank number.
;*
            mov     al, 039h            ;CR39 lock/unlock index /*          */
            out     dx, ax              ;Restore lock/unlock    /*          */
;
;!!Do we really need to avoid reading the Ext System Ctrl Reg?  /*          */
;                                                               /*           start */
            mov     ax, 04838h          ;CR38 lock/unlock index /*          */
            out     dx, al
            inc     dx                  ;CRTC data address
            in      al, dx
            xchg    ah, al              ;Save lock/get unlock   /*          */
            out     dx, al
            dec     dx                  ;CRTC index address
;*
            mov     al, 035h            ;Bank Select register.
            out     dx, al
            inc     dx                  ;CRTC data address
            in      al, dx              ;read bank select register
            dec     dx                  ;CRTC index address
            and     al, 00fh
            or      cl, al              ;Save bank in cl.
;*
            mov     al, 038h            ;CR38 lock/unlock index /*          */
        .endif
        out     dx, ax                  ;Restore lock/unlock    /*          */
;*
        mov     al, ch                  ;Restore original CRTC index.
        out     dx, al
;*
        mov     al, cl                  ;Get back current bank.
        cbw                             ;Extend to word.
        ret

S3GetBank       ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = TridentGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

TridentGetBank  PROC    NEAR

        xor     ax, ax                  ;Text mode current bank /*          */
        .if     <di ge MODE_PLANAR>     ;We process only graphic modes
            mov     dx, 03c4h           ;SEQ index address
            in      al, dx
            push    ax                  ;Save SEQ index         /*          */
;*
            call    GETTRIDENTREGDEF
            mov     cx, ax              ;TRUE new def, FALSE old/*          */
;*
            mov     al, 00bh            ;                       /*          */
            mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al
            inc     dx                  ;SEQ data address
            in      al, dx              ;Mode ctrl reg changed to new def
            dec     dx                  ;SEQ index address      /*          */
;*
            mov     al, 00eh
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al              ; select mode ctrl reg #1
            inc     dx                  ;SEQ data address
            in      al, dx
            dec     dx                  ;SEQ index address      /*          */
            and     ax, 00fh            ;Extract current bank   /*          */
;*
            xchg    cx, ax              ;Save current bank      /*          */
            and     ax, ax              ;Test new/old def
            .if     < z >               ;If old def: restore old def
                mov     al, 00bh        ;AH doesn't matter!     /*          */
;               mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, ax          ;Output both index&data /*          */
;               mov     al, ah                                  /*          */
;               inc     dx              ;SEQ data address       /*          */
;               out     dx, al                                  /*          */
;               dec     dx              ;SEQ index address.     /*          */
            .endif
;*
            pop     ax                  ;Restore SEQ index.     /*          */
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al              ;Restore SEQ index
;*
            mov     ax, cx              ;Restore current bank.  /*          */
        .endif
        ret

TridentGetBank  ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = TsengGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

TsengGetBank    PROC    NEAR

        xor     al, al                  ;Assume no bank sel high.
        mov     ch, dl                  ;Save direction.
        mov     cl, byte ptr [_sSVGA.ChipType] ;                /*          */
        .if     <cl ae TSENG_ET4000W32_CHIP> ; 
            mov     dx, 003cbh          ;Get GDC Segment Select 2.
            in      al, dx              ;Read bank select high register.
            .if     <ch ne READ_BANK>   ;                       /*          */
                shl     al, 4           ;Get write bank (1:0) instead.
            .endif                      ;                       /*          */
            and     al, 030h            ;Extract bank 5:4.
        .endif                          ; 
        mov     ah, al                  ;Save bank 5:4.
        mov     dx, 003cdh              ;Get GDC Segment Select 1.
        in      al, dx                  ;Read bank select low register.
        .if     <ch e READ_BANK>        ; 
            .if     <cl be TSENG_ET3000_CHIP> ; 
                shl     al, 1           ;Shift 5:3 to 6:4.
            .endif                      ; 
            shr     al, 4               ;Shift 7:4 to 3:0.
        .endif                          ; 
        and     al, 00fh                ;on ET4000 bits 0-3 write bank
        .if     <cl be TSENG_ET3000_CHIP> ; 
            and     al, 007h            ;on ET3000 bits 0-2 write bank
        .endif                          ; 
        or      al, ah                  ;Add 5:4 to 3:0.
        cbw                             ;Extend to full word.
        ret                             ; 

TsengGetBank    ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = Video7GetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

Video7GetBank   PROC    NEAR

        mov     ch, dl                  ;Save the direction     /*          */
        mov     dx, 03c4h               ;SEQ index address
        in      al, dx
        push    ax                      ;Save SEQ index         /*          */
;*
        mov     al, 006h                ;Lock register index
        out     dx, al
        inc     dx                      ;SEQ data address
        in      al, dx                  ;Not read as written    /*          */
        and     al, 001h                ;0=locked, 1=unlocked   /*          */
        mov     al, 0eah                ;Assume unlocked        /*          */
        out     dx, al                  ;Unlock it now.         /*          */
        dec     dx                      ;SEQ index address      /*          */
        .if     < z >                                           /*@V2.1MNH13*/
            mov     al, 0aeh            ;Locked instead         /*          */
        .endif                          ;0aeh=lock, 0eah=unlock /*          */
        xchg    al, ah                  ;Xchg index&unlock      /*          */
        push    ax                      ;Save lock index&(un)lck/*          */
;*
                                        ; chipset specific
;                                       ;HT205 or HT208         /*          */
        .if     <[_sSVGA.ChipType] be VIDEO7_HT208_CHIP>        /*@V2.1MNH13*/
            mov     al, 0f6h
;           mov     dl, 0c4h            ;SEQ index address      /*          */
            out     dx, al
            inc     dx                  ;SEQ data address
            in      al, dx              ;Read bank select register
            dec     dx                  ;SEQ index address      /*          */
            .if     <ch e READ_BANK>                            /*@V2.1MNH13*/
                shr     al, 2           ;Read bank bits are 2:3 /*          */
            .endif
            and     al, 003h            ;Extract the bits 1:0   /*          */
            .if     <di ne MODE_PLANAR> ;256 color bank select
                shl     al, 2           ;Bank bits are 2:3      /*          */
                mov     ah, al
                mov     al, 0f9h
;               mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, al
                inc     dx              ;SEQ data address
                in      al, dx          ;Read extended page select register
                and     al, 001h        ;Get first bit
                or      ah, al          ;                       /*          */
                mov     dl, 0cch        ;Misc Output Read addr  /*          */
                in      al, dx
                and     al, 020h        ;Bit 5 in Misc. Output Reg is bit
                shr     al, 4
                or      al, ah          ;Merge bank bits.       /*          */
           .endif
        .else
;                                       ;HT 209 chip            /*          */
            .if     <[_sSVGA.ChipType] eq VIDEO7_HT209_CHIP>    /*@V2.1MNH13*/
                mov     al, 0e9h        ;Read bank sel
                sub     al, ch          ;May convert to write   /*          */
;               mov     dl, 0c4h        ;SEQ index address      /*          */
                out     dx, al
                inc     dx              ;SEQ data address
                in      al, dx          ;Get bank
                shr     al, 4           ;                       /*          */
                .if <di b MODE_PLANAR>   ;text mode, bit 1 must be reset
;!!                 This seems odd! Not "and al, 001h"?
                    and     al, 0fdh
                .endif
;               xor     ah, ah                                  /*          */
            .endif
        .endif
        mov     cl, al                  ;Save the bank          /*          */
        mov     dl, 0c4h                ;SEQ index address      /*          */
;       mov     al, 006h                ;Lock register index    /*          */
        pop     ax                      ;Restore lock idx&unlock/*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                  ;                       /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                  ;                       /*          */
;       dec     dx                      ;SEQ index address.     /*          */
;*
        pop     ax                      ;Restore SEQ index.     /*          */
;       mov     dl, 0c4h                ;SEQ index address      /*          */
        out     dx, al                  ;Restore SEQ index
;*
        mov     al, cl                  ;Return the bank        /*          */
        cbw                             ;Extend to word         /*          */
        ret

Video7GetBank   ENDP

;/****************************************************************************
;*
;* FUNCTION NAME = WDGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WDGetBank       PROC    NEAR

        mov     dx, 03ceh               ;GDC index address      /*          */
        in      al, dx
        mov     ch, al                  ;Save GDC index         /*          */
;*
        mov     ax, 00f0fh              ;PR05 index (twice)     /*          */
        out     dx, al                  ;Are GDC's locked?
        inc     dx                      ;GDC data address
        in      al, dx                  ;Get (un)lock
        xchg    al, ah                  ;Xchg index&unlock      /*          */
        push    ax                      ;Save PR05index&(un)lock/*          */
        mov     al, 005h                ;Unlock GDC             /*          */
        out     dx, al                  ;                       /*          */
        dec     dx                      ;GDC index address      /*          */
;*
        mov     al, 009h                ;PROA index             /*          */
;       mov     dl, 0ceh                ;GDC index address      /*          */
        out     dx, al
        inc     dx                      ;GDC data address
        in      al, dx                  ;Read bank select reg
        dec     dx                      ;GDC index address      /*          */
        shr     al, 4
        mov     cl, al                  ;Save bank
;*
;       mov     al, 00fh                ;PR05 index             /*          */
        pop     ax                      ;Restore PR05index&unlck/*          */
;       mov     dl, 0ceh
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                                          /*          */
;       inc     dx                      ;GDC data address       /*          */
;       out     dx, al                  ;GDC (un)lock
;       dec     dx                      ;GDC index address      /*          */
;*
        mov     al, ch                  ;Restore GDC index
;       mov     dl, 0ceh                ;GDC index address      /*          */
        out     dx, al
;*
        mov     dl, 0c4h                ;SEQ index address
        in      al, dx
        mov     ch, al                  ;Save SEQ index         /*          */
;*
        mov     ax, 04048h              ;Test index.
        out     dx, al                  ;Write 7 bit index.
        in      al, dx                  ;Read 3 bits locked, 6 bits unlocked
        or      ah, al                  ;Add in required for (un)lock.
        mov     al, 006h                ;PR20 index             /*          */
        push    ax                      ;Save PR20index&(un)lock/*          */
;*
        mov     ah, 048h                ;Unlock SEQ             /*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                                          /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                                          /*          */
;       dec     dx                      ;SEQ index address.     /*          */
;*
        mov     al, 014h                ;PR34 index Dsp Mem Map /*          */
;       mov     dl, 0c4h                ;SEQ index address      /*          */
        out     dx, al                  ;Idx Display Mem Map reg/*          */
        inc     dx                      ;SEQ data address       /*          */
        in      al, dx                  ;Get Display Mem Map reg/*          */
        dec     dx                      ;SEQ index address      /*          */
        and     al, 040h                ;get bit 6=PR0A bit 8   /*          */
        shr     al, 2                   ;Move to bank bit 4     /*          */
        or      cl, al                  ;Add in new bank bit 4  /*          */
;*
        pop     ax                      ;Restore PR20index&unlck/*          */
;       mov     dl, 0c4h                ;SEQ index address      /*          */
        out     dx, ax                  ;Output both index&data /*          */
;       mov     al, ah                                          /*          */
;       inc     dx                      ;SEQ data address       /*          */
;       out     dx, al                  ;SEQ (un)lock           /*          */
;       dec     dx                      ;SEQ index address      /*          */
;*
        mov     al, ch                  ;Restore SEQ index      /*          */
        out     dx, al
;*
        mov     al, cl                  ;Restore bank           /*          */
        cbw                             ;Extend to word         /*          */
        ret

WDGetBank       ENDP

;*                                                              /*          */
;/****************************************************************************
;*
;* FUNCTION NAME = WeitekGetBank
;*
;* DESCRIPTION   = Get bank. No error checking or indication.
;*
;* INPUT         = DX Direction and DI video mode
;* OUTPUT        = AX Bank
;*
;* RETURN-NORMAL = NONE.
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

WeitekGetBank   PROC    NEAR

        .if     <[_sSVGA.ChipType] e WEITEK_P9000_CHIP>
;!!         Do we call the coprocessor?                         /*          */
            push    es
            push    bx                  ;!!Do we need to?
            mov     ax, WEITEK_P9000_REGISTERS  ;High word of physical addr.
            xor     bx, bx              ;Low word of physical address.
            mov     cx, WEITEK_P9000_REGLENGTH  ;Length of area selected
            call    SVGAPhysToUVirt
            mov     ax, 00000h          ;Assume first bank.
            .if     <nc>                ;If selector returned:
                mov     ax, word ptr es:[bx][WEITEK_P9000_SYSCONFIG]
                shr     ax, 9
                mov     cl, dl          ;Get direction.
                xor     cl, WRITE_BANK  ;0 iff WRITE_BANK, 1 iff READ_BANK.
                shr     ax, cl
                and     ax, 00001h      ;Get actual bank number.
                call    SVGAUnPhysToUVirt ;ES=selector to free.
            .endif                      ;Else some type of system failure!
            pop     bx
            pop     es
        .else                           ;Just VGA, not coprocessor:
            mov     ah, dl              ;Save direction.
            mov     dx, 003c5h          ;SEQ index address.
            mov     al, 011h            ;SEQ Misc Reg.
            out     dx, al
            inc     dx                  ;SEQ data address.
            in      al, dx              ;Get possibly FAKE current contents.
            out     dx, al              ;Write out twice to unlock.
            out     dx, al              ;Write out twice to unlock.
            in      al, dx              ;Get REAL current contents.
            and     al, 040h            ;Turn off Bank Switch Disable.
            .if     < nz >              ;If banking disabled:
                xor     al, al          ;First bank!
            .else                       ;If banking enabled:
                mov     dl, 0cdh        ;WEITEK Bank Select address.
                in      al, dx          ;Get the banks.
                .if     <ah e READ_BANK>
                    shr     al, 4       ;Shift from read bank position (7:4).
                .endif
                and     ax, 00fh        ;Prevent bank overrun.
            .endif
        .endif
        ret

WeitekGetBank   ENDP

BiosSeg ends

        end
;           12/28/92 SVGA support. File created.
;           06/04/93 F69306 Add support for S3
;           11/01/93 D75458 Merge r206v, r206, r207 S3 code.
;           11/05/93 D74047 Add support for S3 911/924
;           11/05/93        Merge S3 911/924 Support
;           03/01/94 D79562 Add support for 2M WDs
;           05/13/94 F74819 ATI Mach8/32 check in files
;           05/17/94        TSENGW32 fix get/setbank
;           06/15/94        Fix Cirrus setbank
;           07/31/94  87887 Fix Cirrus setbank to always use 16Kbyte granularity
;           08/02/94 D89681 ATI Mach64 Get/Set Bank differs from Mach8/32
;*   08/25/94             D       Add PCI detection via a BIOS call.
