/* $XConsortium: oak_bank.s,v 1.3 95/01/05 20:49:58 kaleb Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/oak/oak_bank.s,v 3.2 1995/01/28 17:09:02 dawes Exp $ */ /* * Copyright 1993 by David Wexelblat * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of David Wexelblat not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. David Wexelblat makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * These are here the very lowlevel VGA bankswitching routines. * The segment to switch to is passed via %eax. Only %eax and %edx my be used * without saving the original contents. * * WHY ASSEMBLY LANGUAGE ??? * * These routines must be callable by other assembly routines. But I don't * want to have the overhead of pushing and poping the normal stack-frame. */ /* * All XFree86 assembler-language files are written in a macroized assembler * format. This is done to allow a single .s file to be assembled under * the USL-syntax assemblers with SVR3/4, the GAS-syntax used by 386BSD, * Linux, and Mach, and the Intel-syntax used by Amoeba and Minix. * * All of the 386 instructions, addressing modes, and appropriate assembler * pseudo-ops are definined in the "assyntax.h" header file. */ #include "assyntax.h" /* * Three entry points must be defined in this file: * * OAKSetRead - Set the read-bank pointer * OAKSetWrite - Set the write-bank pointer * OAKSetReadWrite - Set both bank pointers to the same bank * * Most SVGA chipsets have two bank pointers - a read bank and a write bank. * In general, the server sets the read and write banks to the same bank, * via the SetReadWrite function. For BitBlt operations, it is much more * efficient to use two banks independently. * * If the new chipset only has one bank pointer, then all three entry * points must still be defined, but they will be all the same function. * In this case, make sure the ChipUse2Banks field of the OAKChipRec is * set to FALSE in the oak_driver.c file. * * Built from Xfree86 1.3 stub file. * 9/1/93 Initial version Steve Goldman sgoldman@encore.com * */ FILE("oak_bank.s") /* Define the file name for the .o file */ AS_BEGIN /* This macro does all generic setup */ /* * Some chipsets maintain both bank pointers in a single register. To * avoid having to do a read/modify/write cycle on the register, it is * best to maintain a copy of the register in memory, modify the * appropriate part of it, and then do a single 'OUT_B' to set it. * */ SEG_DATA /* Switch to the data segment */ Segment: /* Storage for efficiency */ D_BYTE 0 SEG_TEXT /* Switch to the text segment */ /* * The SetReadWrite function sets both bank pointers. The bank will be * passed in AL. */ ALIGNTEXT4 GLOBL GLNAME(OAKSetReadWrite) GLNAME(OAKSetReadWrite): MOV_B (AL, AH) /* Move bank to high half */ SHL_B (CONST(4),AH) /* position to write bank */ OR_B (AL,AH) /* both in AH */ MOV_B (AH,CONTENT(Segment)) /* save it for speed */ MOV_B (CONST(0x11),AL) /* OTI segment register index */ MOV_L (CONST(0x3DE),EDX) /* Extended index register */ OUT_W /* Send index, and then bank */ RET /* Now we do the same function for the OTI087 chipset which supports 2MB */ ALIGNTEXT4 GLOBL GLNAME(OTI87SetReadWrite) GLNAME(OTI87SetReadWrite): MOV_B (AL, AH) /* Move bank to high half */ MOV_B (CONST(0x25),AL) /* Put read index in low byte, it * addresses the Extended R/W Reg. */ MOV_L (CONST(0x3DE),EDX) /* Store base register */ OUT_W /* Output read/write bank */ RET /* * The SetWrite function sets just the write bank pointer */ ALIGNTEXT4 GLOBL GLNAME(OAKSetWrite) GLNAME(OAKSetWrite): MOV_B (CONTENT(Segment),AH) /* get current value of segment reg */ AND_B (CONST(0xF),AH) /* strip old write segment */ SHL_B (CONST(4),AL) /* position write segment */ OR_B (AL,AH) /* both banks */ MOV_B (AH,CONTENT(Segment)) /* save it for speed */ MOV_L (CONST(0x3DE),EDX) /* Extended index register */ MOV_B (CONST(0x11),AL) /* OTI segment register index */ OUT_W /* Output r/w segment */ RET /* Now we do the same function for the OTI087 chipset which supports 2MB */ ALIGNTEXT4 GLOBL GLNAME(OTI87SetWrite) GLNAME(OTI87SetWrite): MOV_B (AL, AH) /* Move bank to high half */ MOV_L (CONST(0x3DE),EDX) /* Store base register */ MOV_B (CONST(0x24),AL) /* Put write index in low byte */ OUT_W /* Output write bank */ RET /* * The SetRead function sets just the read bank pointer */ ALIGNTEXT4 GLOBL GLNAME(OAKSetRead) GLNAME(OAKSetRead): MOV_B (CONTENT(Segment),AH) /* get current value of segment reg */ AND_B (CONST(0xF0),AH) /* strip old read segment */ OR_B (AL,AH) /* both banks */ MOV_B (AH,CONTENT(Segment)) /* save it for speed */ MOV_L (CONST(0x3DE),EDX) /* Extended index register */ MOV_B (CONST(0x11),AL) /* OTI segment register index */ OUT_W /* Output r/w segment */ RET /* Now we do the same function for the OTI087 chipset which supports 2MB */ ALIGNTEXT4 GLOBL GLNAME(OTI87SetRead) GLNAME(OTI87SetRead): MOV_B (AL, AH) /* Move bank to high half */ MOV_B (CONST(0x23),AL) /* Put read index in low byte */ MOV_L (CONST(0x3DE),EDX) /* Store base register */ OUT_W /* Output read bank */ RET