From 6962e55a393c6b1cddf6b23f9c39842234b4ef7d Mon Sep 17 00:00:00 2001 From: Kaleb Keithley Date: Mon, 17 Nov 2003 19:03:45 +0000 Subject: merge XFree86 4.3.0.1 to -CURRENT --- README.NV1 | 206 +------- src/nv_dma.h | 180 +++++++ src/nv_hw.c | 1257 +++++++++++++++++++++++++++++++++++++++++++++++ src/riva_const.h | 14 + src/riva_cursor.c | 165 +++++++ src/riva_dac.c | 280 +++++++++++ src/riva_dga.c | 305 ++++++++++++ src/riva_driver.c | 1384 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/riva_include.h | 59 +++ src/riva_local.h | 74 +++ src/riva_proto.h | 41 ++ src/riva_setup.c | 279 +++++++++++ src/riva_shadow.c | 194 ++++++++ src/riva_type.h | 122 +++++ src/riva_xaa.c | 554 +++++++++++++++++++++ 15 files changed, 4932 insertions(+), 182 deletions(-) create mode 100644 src/nv_dma.h create mode 100644 src/nv_hw.c create mode 100644 src/riva_const.h create mode 100644 src/riva_cursor.c create mode 100644 src/riva_dac.c create mode 100644 src/riva_dga.c create mode 100644 src/riva_driver.c create mode 100644 src/riva_include.h create mode 100644 src/riva_local.h create mode 100644 src/riva_proto.h create mode 100644 src/riva_setup.c create mode 100644 src/riva_shadow.c create mode 100644 src/riva_type.h create mode 100644 src/riva_xaa.c diff --git a/README.NV1 b/README.NV1 index 28488f2..47bc437 100644 --- a/README.NV1 +++ b/README.NV1 @@ -1,200 +1,42 @@ + Information for NVidia NV1 / SGS-Thomson STG2000 Users + David McKay + 20th March 1997 +1. XFree driver for NVidia NV1 / SGS-Thomson STG2000 v1.0 - - - - - - Information for NVidia NV1 / SGS-Thomson STG2000 and Riva128 Users - - David McKay, Dirk Hohndel - - 26 February 1998 - - - -1. XFree86 driver for NVidia NV1 / SGS-Thomson STG2000 and Riva128 - -This driver supports good acceleration for both the NV1/STG2000 as well as the -Riva128. It is known to work on PCI and AGP versions of the Riva128. +This driver now accelerates bitblits and filled rectangles. It also support a +hardware cursor. More graphic acceleration is planned. There is no plan to +support the audio functionality of the chip. 1.1 Notes - o On the NV1/STG2000, the driver does not support the virtual desktop fea- - tures of xfree86. This is because the NV1 does not have the necessary - hardware to support this feature. If you want to change resolutions, you - will have to modify your config file. Comment out all but the mode you - wish to use. + o THE DRIVER DOES NOT SUPPORT THE VIRTUAL DESKTOP FEATURES OF XFREE86 This + is because the NV1 does not have the necessary hardware to support this + feature. If you want to change resolutions, you will have to modify your + config file. Comment out all but the mode you wish to use. o The generic VGA16 server will not work with the NV1. For this reason - XF86Setup cannot be used to configure the server. Use xf86config instead. - Select `Diamond Edge 3D' as your board, and select only ONE mode for each - of 8bpp and 16bpp. Do not select a virtual desktop. Also, make sure you - don't select a RAMDAC or clock chip. This does not apply if you own a - Riva128 card, as the VGA16 server works just fine on that. - - o Both the NV1 and the Riva128 only support a 555 RGB Weight in 16 bpp, the - hardware does not do 565. If you run into problems with some window man- - agers in 16bpp, try putting a Weight 555 in the Display section. - - o 24 bpp is not supported. - - o In some modes the hardware cursor gets out of sync with the display. Use - Option "sw_cursor" to work around this problem. - - o There are modelines that confuse the Riva128 chip. This results in a - greenish display. Slightly modifying the modeline usually fixes the prob- - lem. In most cases all that is needed is to reduce the HTotal. You can use - xvidtune to do that. - - o The dotclock limits for this driver seem to be lower than the hardware - specs (and drivers for other graphical user interfaces) seem to indicate. - If you get a flickery screen with flashes, try to limit the modes you use - to about 160MHz in 16bpp and about 100MHz in 32bpp. - - Generated from XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/NV1.sgml,v 3.2.2.3 1998/02/26 20:11:27 hohndel Exp $ - - - - - - -Information for NVidia NV1 / SGS-Thomson STG2000 and Riva128 Users - - - - - -Information for NVidia NV1 / SGS-Thomson STG2000 and Riva128 Users - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CONTENTS - - - -1. XFree86 driver for NVidia NV1 / SGS-Thomson STG2000 and Riva128 .......... 1 - 1.1 Notes ................................................................ 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + XF86Setup cannot be used to configure the server. Use xf86config + instead. Select `Diamond Edge 3D' as your board, and select only ONE + mode for each of 8bpp and 16bpp. Do not select a virtual desktop. + Also, make sure you don't select a RAMDAC or clock chip. + o The NV1 only supports a 555 RGB Weight in 16 bpp, the hardware does not + do 565. You must put a Weight 555 in the Display section. + o 24/32 bpp mode is not yet supported. +1.2 Known Bugs + o The driver should force Weight 555 in 16 bpp mode + o The hardware cursor doesn't work if an doublescan mode is selected. - i + o Screen blanking doesn't work, nor does DPMS. + Generated from XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/NV1.sgml,v 3.3 1997/03/22 09:35:30 hohndel Exp $ -$XFree86: xc/programs/Xserver/hw/xfree86/doc/README.NV1,v 3.5.2.3 1998/02/27 02:54:59 dawes Exp $ +$XFree86: xc/programs/Xserver/hw/xfree86/doc/README.NV1,v 3.7 1999/04/15 03:34:51 dawes Exp $ diff --git a/src/nv_dma.h b/src/nv_dma.h new file mode 100644 index 0000000..6506068 --- /dev/null +++ b/src/nv_dma.h @@ -0,0 +1,180 @@ + + /***************************************************************************\ +|* *| +|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING 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 SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_dma.h,v 1.2 2003/07/31 21:41:26 mvojkovi Exp $ */ + +#define SURFACE_FORMAT 0x00000300 +#define SURFACE_FORMAT_DEPTH8 0x00000001 +#define SURFACE_FORMAT_DEPTH15 0x00000002 +#define SURFACE_FORMAT_DEPTH16 0x00000004 +#define SURFACE_FORMAT_DEPTH24 0x00000006 +#define SURFACE_PITCH 0x00000304 +#define SURFACE_PITCH_SRC 15:0 +#define SURFACE_PITCH_DST 31:16 +#define SURFACE_OFFSET_SRC 0x00000308 +#define SURFACE_OFFSET_DST 0x0000030C + +#define ROP_SET 0x00002300 + +#define PATTERN_FORMAT 0x00004300 +#define PATTERN_FORMAT_DEPTH8 0x00000003 +#define PATTERN_FORMAT_DEPTH16 0x00000001 +#define PATTERN_FORMAT_DEPTH24 0x00000003 +#define PATTERN_COLOR_0 0x00004310 +#define PATTERN_COLOR_1 0x00004314 +#define PATTERN_PATTERN_0 0x00004318 +#define PATTERN_PATTERN_1 0x0000431C + +#define CLIP_POINT 0x00006300 +#define CLIP_POINT_X 15:0 +#define CLIP_POINT_Y 31:16 +#define CLIP_SIZE 0x00006304 +#define CLIP_SIZE_WIDTH 15:0 +#define CLIP_SIZE_HEIGHT 31:16 + +#define LINE_FORMAT 0x00008300 +#define LINE_FORMAT_DEPTH8 0x00000003 +#define LINE_FORMAT_DEPTH16 0x00000001 +#define LINE_FORMAT_DEPTH24 0x00000003 +#define LINE_COLOR 0x00008304 +#define LINE_MAX_LINES 16 +#define LINE_LINES(i) 0x00008400\ + +(i)*8 +#define LINE_LINES_POINT0_X 15:0 +#define LINE_LINES_POINT0_Y 31:16 +#define LINE_LINES_POINT1_X 47:32 +#define LINE_LINES_POINT1_Y 63:48 + +#define BLIT_POINT_SRC 0x0000A300 +#define BLIT_POINT_SRC_X 15:0 +#define BLIT_POINT_SRC_Y 31:16 +#define BLIT_POINT_DST 0x0000A304 +#define BLIT_POINT_DST_X 15:0 +#define BLIT_POINT_DST_Y 31:16 +#define BLIT_SIZE 0x0000A308 +#define BLIT_SIZE_WIDTH 15:0 +#define BLIT_SIZE_HEIGHT 31:16 + +#define RECT_FORMAT 0x0000C300 +#define RECT_FORMAT_DEPTH8 0x00000003 +#define RECT_FORMAT_DEPTH16 0x00000001 +#define RECT_FORMAT_DEPTH24 0x00000003 +#define RECT_SOLID_COLOR 0x0000C3FC +#define RECT_SOLID_RECTS_MAX_RECTS 32 +#define RECT_SOLID_RECTS(i) 0x0000C400\ + +(i)*8 +#define RECT_SOLID_RECTS_Y 15:0 +#define RECT_SOLID_RECTS_X 31:16 +#define RECT_SOLID_RECTS_HEIGHT 47:32 +#define RECT_SOLID_RECTS_WIDTH 63:48 + +#define RECT_EXPAND_ONE_COLOR_CLIP 0x0000C7EC +#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X 15:0 +#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y 31:16 +#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X 47:32 +#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y 63:48 +#define RECT_EXPAND_ONE_COLOR_COLOR 0x0000C7F4 +#define RECT_EXPAND_ONE_COLOR_SIZE 0x0000C7F8 +#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH 15:0 +#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT 31:16 +#define RECT_EXPAND_ONE_COLOR_POINT 0x0000C7FC +#define RECT_EXPAND_ONE_COLOR_POINT_X 15:0 +#define RECT_EXPAND_ONE_COLOR_POINT_Y 31:16 +#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS 128 +#define RECT_EXPAND_ONE_COLOR_DATA(i) 0x0000C800\ + +(i)*4 + +#define RECT_EXPAND_TWO_COLOR_CLIP 0x0000CBE4 +#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X 15:0 +#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y 31:16 +#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X 47:32 +#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y 63:48 +#define RECT_EXPAND_TWO_COLOR_COLOR_0 0x0000CBEC +#define RECT_EXPAND_TWO_COLOR_COLOR_1 0x0000CBF0 +#define RECT_EXPAND_TWO_COLOR_SIZE_IN 0x0000CBF4 +#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH 15:0 +#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT 31:16 +#define RECT_EXPAND_TWO_COLOR_SIZE_OUT 0x0000CBF8 +#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH 15:0 +#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT 31:16 +#define RECT_EXPAND_TWO_COLOR_POINT 0x0000CBFC +#define RECT_EXPAND_TWO_COLOR_POINT_X 15:0 +#define RECT_EXPAND_TWO_COLOR_POINT_Y 31:16 +#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS 128 +#define RECT_EXPAND_TWO_COLOR_DATA(i) 0x0000CC00\ + +(i)*4 + +#define STRETCH_BLIT_FORMAT 0x0000E300 +#define STRETCH_BLIT_FORMAT_DEPTH8 0x00000004 +#define STRETCH_BLIT_FORMAT_DEPTH16 0x00000007 +#define STRETCH_BLIT_FORMAT_DEPTH24 0x00000004 +#define STRETCH_BLIT_FORMAT_X8R8G8B8 0x00000004 +#define STRETCH_BLIT_FORMAT_YUYV 0x00000005 +#define STRETCH_BLIT_FORMAT_UYVY 0x00000006 +#define STRETCH_BLIT_CLIP_POINT 0x0000E308 +#define STRETCH_BLIT_CLIP_POINT_X 15:0 +#define STRETCH_BLIT_CLIP_POINT_Y 31:16 +#define STRETCH_BLIT_CLIP_POINT 0x0000E308 +#define STRETCH_BLIT_CLIP_SIZE 0x0000E30C +#define STRETCH_BLIT_CLIP_SIZE_WIDTH 15:0 +#define STRETCH_BLIT_CLIP_SIZE_HEIGHT 31:16 +#define STRETCH_BLIT_DST_POINT 0x0000E310 +#define STRETCH_BLIT_DST_POINT_X 15:0 +#define STRETCH_BLIT_DST_POINT_Y 31:16 +#define STRETCH_BLIT_DST_SIZE 0x0000E314 +#define STRETCH_BLIT_DST_SIZE_WIDTH 15:0 +#define STRETCH_BLIT_DST_SIZE_HEIGHT 31:16 +#define STRETCH_BLIT_DU_DX 0x0000E318 +#define STRETCH_BLIT_DV_DY 0x0000E31C +#define STRETCH_BLIT_SRC_SIZE 0x0000E400 +#define STRETCH_BLIT_SRC_SIZE_WIDTH 15:0 +#define STRETCH_BLIT_SRC_SIZE_HEIGHT 31:16 +#define STRETCH_BLIT_SRC_FORMAT 0x0000E404 +#define STRETCH_BLIT_SRC_FORMAT_PITCH 15:0 +#define STRETCH_BLIT_SRC_FORMAT_ORIGIN 23:16 +#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER 0x00000001 +#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER 0x00000002 +#define STRETCH_BLIT_SRC_FORMAT_FILTER 31:24 +#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE 0x00000000 +#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR 0x00000001 +#define STRETCH_BLIT_SRC_OFFSET 0x0000E408 +#define STRETCH_BLIT_SRC_POINT 0x0000E40C +#define STRETCH_BLIT_SRC_POINT_U 15:0 +#define STRETCH_BLIT_SRC_POINT_V 31:16 diff --git a/src/nv_hw.c b/src/nv_hw.c new file mode 100644 index 0000000..b5bb015 --- /dev/null +++ b/src/nv_hw.c @@ -0,0 +1,1257 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING 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 SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */ + +#include "nv_local.h" +#include "compiler.h" +#include "nv_include.h" + + +void NVLockUnlock ( + NVPtr pNv, + Bool Lock +) +{ + CARD8 cr11; + + VGA_WR08(pNv->PCIO, 0x3D4, 0x1F); + VGA_WR08(pNv->PCIO, 0x3D5, Lock ? 0x99 : 0x57); + + VGA_WR08(pNv->PCIO, 0x3D4, 0x11); + cr11 = VGA_RD08(pNv->PCIO, 0x3D5); + if(Lock) cr11 |= 0x80; + else cr11 &= ~0x80; + VGA_WR08(pNv->PCIO, 0x3D5, cr11); +} + +int NVShowHideCursor ( + NVPtr pNv, + int ShowHide +) +{ + int current = pNv->CurrentState->cursor1; + + pNv->CurrentState->cursor1 = (pNv->CurrentState->cursor1 & 0xFE) | + (ShowHide & 0x01); + VGA_WR08(pNv->PCIO, 0x3D4, 0x31); + VGA_WR08(pNv->PCIO, 0x3D5, pNv->CurrentState->cursor1); + return (current & 0x01); +} + +/****************************************************************************\ +* * +* The video arbitration routines calculate some "magic" numbers. Fixes * +* the snow seen when accessing the framebuffer without it. * +* It just works (I hope). * +* * +\****************************************************************************/ + +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv4_fifo_info; + +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv4_sim_state; + +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv10_fifo_info; + +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_type; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv10_sim_state; + + +static void nvGetClocks(NVPtr pNv, unsigned int *MClk, unsigned int *NVClk) +{ + unsigned int pll, N, M, MB, NB, P; + + if(pNv->twoStagePLL) { + pll = pNv->PRAMDAC0[0x0504/4]; + M = pll & 0xFF; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x0F; + pll = pNv->PRAMDAC0[0x0574/4]; + if(pll & 0x80000000) { + MB = pll & 0xFF; + NB = (pll >> 8) & 0xFF; + } else { + MB = 1; + NB = 1; + } + *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P; + + pll = pNv->PRAMDAC0[0x0500/4]; + M = pll & 0xFF; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x0F; + pll = pNv->PRAMDAC0[0x0570/4]; + if(pll & 0x80000000) { + MB = pll & 0xFF; + NB = (pll >> 8) & 0xFF; + } else { + MB = 1; + NB = 1; + } + *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P; + } else + if(((pNv->Chipset & 0x0ff0) == 0x0300) || + ((pNv->Chipset & 0x0ff0) == 0x0330)) + { + pll = pNv->PRAMDAC0[0x0504/4]; + M = pll & 0x0F; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x07; + if(pll & 0x00000080) { + MB = (pll >> 4) & 0x07; + NB = (pll >> 19) & 0x1f; + } else { + MB = 1; + NB = 1; + } + *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P; + + pll = pNv->PRAMDAC0[0x0500/4]; + M = pll & 0x0F; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x07; + if(pll & 0x00000080) { + MB = (pll >> 4) & 0x07; + NB = (pll >> 19) & 0x1f; + } else { + MB = 1; + NB = 1; + } + *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P; + } else { + pll = pNv->PRAMDAC0[0x0504/4]; + M = pll & 0xFF; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x0F; + *MClk = (N * pNv->CrystalFreqKHz / M) >> P; + + pll = pNv->PRAMDAC0[0x0500/4]; + M = pll & 0xFF; + N = (pll >> 8) & 0xFF; + P = (pll >> 16) & 0x0F; + *NVClk = (N * pNv->CrystalFreqKHz / M) >> P; + } +} + + +static void nv4CalcArbitration ( + nv4_fifo_info *fifo, + nv4_sim_state *arb +) +{ + int data, pagemiss, cas,width, video_enable, bpp; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; + int found, mclk_extra, mclk_loop, cbs, m1, p1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; + int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width >> 6; + video_enable = arb->enable_video; + bpp = arb->pix_bpp; + mp_enable = arb->enable_mp; + clwm = 0; + vlwm = 0; + cbs = 128; + pclks = 2; + nvclks = 2; + nvclks += 2; + nvclks += 1; + mclks = 5; + mclks += 3; + mclks += 1; + mclks += cas; + mclks += 1; + mclks += 1; + mclks += 1; + mclks += 1; + mclk_extra = 3; + nvclks += 2; + nvclks += 1; + nvclks += 1; + nvclks += 1; + if (mp_enable) + mclks+=4; + nvclks += 0; + pclks += 0; + found = 0; + vbs = 0; + while (found != 1) + { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq; + us_p = nvclks*1000*1000 / pclk_freq; + if (video_enable) + { + video_drain_rate = pclk_freq * 2; + crtc_drain_rate = pclk_freq * bpp/8; + vpagemiss = 2; + vpagemiss += 1; + crtpagemiss = 2; + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ; + else + video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq; + us_video = vpm_us + us_m + us_n + us_p + video_fill_us; + vlwm = us_video * video_drain_rate/(1000*1000); + vlwm++; + vbs = 128; + if (vlwm > 128) vbs = 64; + if (vlwm > (256-64)) vbs = 32; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ; + else + video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video + +video_fill_us + +cpm_us + +us_m + us_n +us_p + ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + else + { + crtc_drain_rate = pclk_freq * bpp/8; + crtpagemiss = 2; + crtpagemiss += 1; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + m1 = clwm + cbs - 512; + p1 = m1 * pclk_freq / mclk_freq; + p1 = p1 * bpp / 8; + if ((p1 < m1) && (m1 > 0)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + else if (video_enable) + { + if ((clwm > 511) || (vlwm > 255)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + else + { + if (clwm > 519) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + if (clwm < 384) clwm = 384; + if (vlwm < 128) vlwm = 128; + data = (int)(clwm); + fifo->graphics_lwm = data; + fifo->graphics_burst_size = 128; + data = (int)((vlwm+15)); + fifo->video_lwm = data; + fifo->video_burst_size = vbs; + } +} + +static void nv4UpdateArbitrationSettings ( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + NVPtr pNv +) +{ + nv4_fifo_info fifo_data; + nv4_sim_state sim_data; + unsigned int MClk, NVClk, cfg1; + + nvGetClocks(pNv, &MClk, &NVClk); + + cfg1 = pNv->PFB[0x00000204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv4CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + +static void nv10CalcArbitration ( + nv10_fifo_info *fifo, + nv10_sim_state *arb +) +{ + int data, pagemiss, width, video_enable, bpp; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss; + int nvclk_fill; + int found, mclk_extra, mclk_loop, cbs, m1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_m_min, us_n, us_p, crtc_drain_rate; + int vus_m; + int vpm_us, us_video, cpm_us, us_crt,clwm; + int clwm_rnd_down; + int m2us, us_pipe_min, p1clk, p2; + int min_mclk_extra; + int us_min_mclk_extra; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; /* freq in KHz */ + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + width = arb->memory_width/64; + video_enable = arb->enable_video; + bpp = arb->pix_bpp; + mp_enable = arb->enable_mp; + clwm = 0; + + cbs = 512; + + pclks = 4; /* lwm detect. */ + + nvclks = 3; /* lwm -> sync. */ + nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */ + + mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */ + + mclks += 1; /* arb_hp_req */ + mclks += 5; /* ap_hp_req tiling pipeline */ + + mclks += 2; /* tc_req latency fifo */ + mclks += 2; /* fb_cas_n_ memory request to fbio block */ + mclks += 7; /* sm_d_rdv data returned from fbio block */ + + /* fb.rd.d.Put_gc need to accumulate 256 bits for read */ + if (arb->memory_type == 0) + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 4; + else + mclks += 2; + else + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 2; + else + mclks += 1; + + if ((!video_enable) && (arb->memory_width == 128)) + { + mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */ + min_mclk_extra = 17; + } + else + { + mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */ + /* mclk_extra = 4; */ /* Margin of error */ + min_mclk_extra = 18; + } + + nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */ + nvclks += 1; /* fbi_d_rdv_n */ + nvclks += 1; /* Fbi_d_rdata */ + nvclks += 1; /* crtfifo load */ + + if(mp_enable) + mclks+=4; /* Mp can get in with a burst of 8. */ + /* Extra clocks determined by heuristics */ + + nvclks += 0; + pclks += 0; + found = 0; + while(found != 1) { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */ + us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */ + us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */ + us_pipe_min = us_m_min + us_n + us_p; + + vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + + if(video_enable) { + crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */ + + vpagemiss = 1; /* self generating page miss */ + vpagemiss += 1; /* One higher priority before */ + + crtpagemiss = 2; /* self generating page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + + us_video = vpm_us + vus_m; /* Video has separate read return path */ + + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video /* Wait for video */ + +cpm_us /* CRT Page miss */ + +us_m + us_n +us_p /* other latency */ + ; + + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + } else { + crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */ + + crtpagemiss = 1; /* self generating page miss */ + crtpagemiss += 1; /* MA0 page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + + /* + // + // Another concern, only for high pclks so don't do this + // with video: + // What happens if the latency to fetch the cbs is so large that + // fifo empties. In that case we need to have an alternate clwm value + // based off the total burst fetch + // + us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ; + us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq; + clwm_mt = us_crt * crtc_drain_rate/(1000*1000); + clwm_mt ++; + if(clwm_mt > clwm) + clwm = clwm_mt; + */ + /* Finally, a heuristic check when width == 64 bits */ + if(width == 1){ + nvclk_fill = nvclk_freq * 8; + if(crtc_drain_rate * 100 >= nvclk_fill * 102) + clwm = 0xfff; /*Large number to fail */ + + else if(crtc_drain_rate * 100 >= nvclk_fill * 98) { + clwm = 1024; + cbs = 512; + } + } + } + + + /* + Overfill check: + + */ + + clwm_rnd_down = ((int)clwm/8)*8; + if (clwm_rnd_down < clwm) + clwm += 8; + + m1 = clwm + cbs - 1024; /* Amount of overfill */ + m2us = us_pipe_min + us_min_mclk_extra; + + /* pclk cycles to drain */ + p1clk = m2us * pclk_freq/(1000*1000); + p2 = p1clk * bpp / 8; /* bytes drained. */ + + if((p2 < m1) && (m1 > 0)) { + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) { + if(cbs <= 32) { + found = 1; /* Can't adjust anymore! */ + } else { + cbs = cbs/2; /* reduce the burst size */ + } + } else { + min_mclk_extra--; + } + } else { + if (clwm > 1023){ /* Have some margin */ + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) + found = 1; /* Can't adjust anymore! */ + else + min_mclk_extra--; + } + } + + if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8; + data = (int)(clwm); + /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */ + fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs; + + fifo->video_lwm = 1024; fifo->video_burst_size = 512; + } +} + +static void nv10UpdateArbitrationSettings ( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + NVPtr pNv +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int MClk, NVClk, cfg1; + + nvGetClocks(pNv, &MClk, &NVClk); + + cfg1 = pNv->PFB[0x0204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 1; + sim_data.enable_mp = 0; + sim_data.memory_type = (pNv->PFB[0x0200/4] & 0x01) ? 1 : 0; + sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + +static void nForceUpdateArbitrationSettings ( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + NVPtr pNv +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk; + unsigned int uMClkPostDiv, memctrl; + + uMClkPostDiv = (pciReadLong(pciTag(0, 0, 3), 0x6C) >> 8) & 0xf; + if(!uMClkPostDiv) uMClkPostDiv = 4; + MClk = 400000 / uMClkPostDiv; + + pll = pNv->PRAMDAC0[0x0500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * pNv->CrystalFreqKHz / M) >> P; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_type = (pciReadLong(pciTag(0, 0, 1), 0x7C) >> 12) & 1; + sim_data.memory_width = 64; + + memctrl = pciReadLong(pciTag(0, 0, 3), 0x00) >> 16; + + if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) { + int dimm[3]; + + dimm[0] = (pciReadLong(pciTag(0, 0, 2), 0x40) >> 8) & 0x4F; + dimm[1] = (pciReadLong(pciTag(0, 0, 2), 0x44) >> 8) & 0x4F; + dimm[2] = (pciReadLong(pciTag(0, 0, 2), 0x48) >> 8) & 0x4F; + + if((dimm[0] + dimm[1]) != dimm[2]) { + ErrorF("WARNING: " + "your nForce DIMMs are not arranged in optimal banks!\n"); + } + } + + sim_data.mem_latency = 3; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = 10; + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + + +/****************************************************************************\ +* * +* RIVA Mode State Routines * +* * +\****************************************************************************/ + +/* + * Calculate the Video Clock parameters for the PLL. + */ +static void CalcVClock ( + int clockIn, + int *clockOut, + U032 *pllOut, + NVPtr pNv +) +{ + unsigned lowM, highM; + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + VClk = (unsigned)clockIn; + + if (pNv->CrystalFreqKHz == 13500) { + lowM = 7; + highM = 13; + } else { + lowM = 8; + highM = 14; + } + + for (P = 0; P <= 4; P++) { + Freq = VClk << P; + if ((Freq >= 128000) && (Freq <= 350000)) { + for (M = lowM; M <= highM; M++) { + N = ((VClk << P) * M) / pNv->CrystalFreqKHz; + if(N <= 255) { + Freq = ((pNv->CrystalFreqKHz * N) / M) >> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if (DeltaNew < DeltaOld) { + *pllOut = (P << 16) | (N << 8) | M; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + } +} + +static void CalcVClock2Stage ( + int clockIn, + int *clockOut, + U032 *pllOut, + U032 *pllBOut, + NVPtr pNv +) +{ + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + *pllBOut = 0x80000401; /* fixed at x4 for now */ + + VClk = (unsigned)clockIn; + + for (P = 0; P <= 6; P++) { + Freq = VClk << P; + if ((Freq >= 400000) && (Freq <= 1000000)) { + for (M = 1; M <= 13; M++) { + N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2); + if((N >= 5) && (N <= 255)) { + Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if (DeltaNew < DeltaOld) { + *pllOut = (P << 16) | (N << 8) | M; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + } +} + +/* + * Calculate extended mode parameters (SVGA) and save in a + * mode state structure. + */ +void NVCalcStateExt ( + NVPtr pNv, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock, + int flags +) +{ + int pixelDepth, VClk; + /* + * Save mode parameters. + */ + state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */ + state->width = width; + state->height = height; + /* + * Extended RIVA registers. + */ + pixelDepth = (bpp + 1)/8; + if(pNv->twoStagePLL) + CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv); + else + CalcVClock(dotClock, &VClk, &state->pll, pNv); + + switch (pNv->Architecture) + { + case NV_ARCH_04: + nv4UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + pNv); + state->cursor0 = 0x00; + state->cursor1 = 0xbC; + if (flags & V_DBLSCAN) + state->cursor1 |= 2; + state->cursor2 = 0x00000000; + state->pllsel = 0x10000700; + state->config = 0x00001114; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + case NV_ARCH_10: + case NV_ARCH_20: + case NV_ARCH_30: + default: + if(((pNv->Chipset & 0xffff) == 0x01A0) || + ((pNv->Chipset & 0xffff) == 0x01f0)) + { + nForceUpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + pNv); + } else { + nv10UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + pNv); + } + state->cursor0 = 0x80 | (pNv->CursorStart >> 17); + state->cursor1 = (pNv->CursorStart >> 11) << 2; + state->cursor2 = pNv->CursorStart >> 24; + if (flags & V_DBLSCAN) + state->cursor1 |= 2; + state->pllsel = 0x10000700; + state->config = pNv->PFB[0x00000200/4]; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + } + + if(bpp != 8) /* DirectColor */ + state->general |= 0x00000030; + + state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3; + state->pixel = (pixelDepth > 2) ? 3 : pixelDepth; +} + + +void NVLoadStateExt ( + NVPtr pNv, + RIVA_HW_STATE *state +) +{ + int i; + + pNv->PMC[0x0140/4] = 0x00000000; + pNv->PMC[0x0200/4] = 0xFFFF00FF; + pNv->PMC[0x0200/4] = 0xFFFFFFFF; + + pNv->PTIMER[0x0200] = 0x00000008; + pNv->PTIMER[0x0210] = 0x00000003; + pNv->PTIMER[0x0140] = 0x00000000; + pNv->PTIMER[0x0100] = 0xFFFFFFFF; + + if(pNv->Architecture == NV_ARCH_04) { + pNv->PFB[0x0200/4] = state->config; + } else { + pNv->PFB[0x0240/4] = 0; + pNv->PFB[0x0244/4] = pNv->FbMapSize - 1; + pNv->PFB[0x0250/4] = 0; + pNv->PFB[0x0254/4] = pNv->FbMapSize - 1; + pNv->PFB[0x0260/4] = 0; + pNv->PFB[0x0264/4] = pNv->FbMapSize - 1; + pNv->PFB[0x0270/4] = 0; + pNv->PFB[0x0274/4] = pNv->FbMapSize - 1; + pNv->PFB[0x0280/4] = 0; + pNv->PFB[0x0284/4] = pNv->FbMapSize - 1; + pNv->PFB[0x0290/4] = 0; + pNv->PFB[0x0294/4] = pNv->FbMapSize - 1; + pNv->PFB[0x02A0/4] = 0; + pNv->PFB[0x02A4/4] = pNv->FbMapSize - 1; + pNv->PFB[0x02B0/4] = 0; + pNv->PFB[0x02B4/4] = pNv->FbMapSize - 1; + } + + pNv->PRAMIN[0x0000] = 0x80000010; + pNv->PRAMIN[0x0001] = 0x80011201; + pNv->PRAMIN[0x0002] = 0x80000011; + pNv->PRAMIN[0x0003] = 0x80011202; + pNv->PRAMIN[0x0004] = 0x80000012; + pNv->PRAMIN[0x0005] = 0x80011203; + pNv->PRAMIN[0x0006] = 0x80000013; + pNv->PRAMIN[0x0007] = 0x80011204; + pNv->PRAMIN[0x0008] = 0x80000014; + pNv->PRAMIN[0x0009] = 0x80011205; + pNv->PRAMIN[0x000A] = 0x80000015; + pNv->PRAMIN[0x000B] = 0x80011206; + pNv->PRAMIN[0x000C] = 0x80000016; + pNv->PRAMIN[0x000D] = 0x80011207; + pNv->PRAMIN[0x000E] = 0x80000017; + pNv->PRAMIN[0x000F] = 0x80011208; + pNv->PRAMIN[0x0800] = 0x00003000; + pNv->PRAMIN[0x0801] = pNv->FbMapSize - 1; + pNv->PRAMIN[0x0802] = 0x00000002; + pNv->PRAMIN[0x0803] = 0x00000002; + if(pNv->Architecture >= NV_ARCH_10) + pNv->PRAMIN[0x0804] = 0x01008062; + else + pNv->PRAMIN[0x0804] = 0x01008042; + pNv->PRAMIN[0x0805] = 0x00000000; + pNv->PRAMIN[0x0806] = 0x12001200; + pNv->PRAMIN[0x0807] = 0x00000000; + pNv->PRAMIN[0x0808] = 0x01008043; + pNv->PRAMIN[0x0809] = 0x00000000; + pNv->PRAMIN[0x080A] = 0x00000000; + pNv->PRAMIN[0x080B] = 0x00000000; + pNv->PRAMIN[0x080C] = 0x01008044; + pNv->PRAMIN[0x080D] = 0x00000002; + pNv->PRAMIN[0x080E] = 0x00000000; + pNv->PRAMIN[0x080F] = 0x00000000; + pNv->PRAMIN[0x0810] = 0x01008019; + pNv->PRAMIN[0x0811] = 0x00000000; + pNv->PRAMIN[0x0812] = 0x00000000; + pNv->PRAMIN[0x0813] = 0x00000000; + pNv->PRAMIN[0x0814] = 0x0100A05C; + pNv->PRAMIN[0x0815] = 0x00000000; + pNv->PRAMIN[0x0816] = 0x00000000; + pNv->PRAMIN[0x0817] = 0x00000000; + pNv->PRAMIN[0x0818] = 0x0100805F; + pNv->PRAMIN[0x0819] = 0x00000000; + pNv->PRAMIN[0x081A] = 0x12001200; + pNv->PRAMIN[0x081B] = 0x00000000; + pNv->PRAMIN[0x081C] = 0x0100804A; + pNv->PRAMIN[0x081D] = 0x00000002; + pNv->PRAMIN[0x081E] = 0x00000000; + pNv->PRAMIN[0x081F] = 0x00000000; + pNv->PRAMIN[0x0820] = 0x01018077; + pNv->PRAMIN[0x0821] = 0x00000000; + pNv->PRAMIN[0x0822] = 0x01201200; + pNv->PRAMIN[0x0823] = 0x00000000; + pNv->PRAMIN[0x0824] = 0x00003002; + pNv->PRAMIN[0x0825] = 0x00007FFF; + pNv->PRAMIN[0x0826] = pNv->FbUsableSize | 0x00000002; + pNv->PRAMIN[0x0827] = 0x00000002; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + pNv->PRAMIN[0x0804] |= 0x00080000; + pNv->PRAMIN[0x0808] |= 0x00080000; + pNv->PRAMIN[0x080C] |= 0x00080000; + pNv->PRAMIN[0x0810] |= 0x00080000; + pNv->PRAMIN[0x0814] |= 0x00080000; + pNv->PRAMIN[0x0818] |= 0x00080000; + pNv->PRAMIN[0x081C] |= 0x00080000; + pNv->PRAMIN[0x0820] |= 0x00080000; + + pNv->PRAMIN[0x080D] = 0x00000001; + pNv->PRAMIN[0x081D] = 0x00000001; +#endif + + if(pNv->Architecture < NV_ARCH_10) { + if((pNv->Chipset & 0x0fff) == 0x0020) { + pNv->PRAMIN[0x0824] |= 0x00020000; + pNv->PRAMIN[0x0826] += pNv->FbAddress; + } + pNv->PGRAPH[0x0080/4] = 0x000001FF; + pNv->PGRAPH[0x0080/4] = 0x1230C000; + pNv->PGRAPH[0x0084/4] = 0x72111101; + pNv->PGRAPH[0x0088/4] = 0x11D5F071; + pNv->PGRAPH[0x008C/4] = 0x0004FF31; + + pNv->PGRAPH[0x0140/4] = 0x00000000; + pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF; + pNv->PGRAPH[0x0170/4] = 0x10010100; + pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF; + pNv->PGRAPH[0x0720/4] = 0x00000001; + + pNv->PGRAPH[0x0810/4] = 0x00000000; + } else { + pNv->PGRAPH[0x0080/4] = 0xFFFFFFFF; + pNv->PGRAPH[0x0080/4] = 0x00000000; + + pNv->PGRAPH[0x0140/4] = 0x00000000; + pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF; + pNv->PGRAPH[0x0144/4] = 0x10010100; + pNv->PGRAPH[0x0714/4] = 0xFFFFFFFF; + pNv->PGRAPH[0x0720/4] = 0x00000001; + + if(pNv->Architecture == NV_ARCH_10) { + pNv->PGRAPH[0x0084/4] = 0x00118700; + pNv->PGRAPH[0x0088/4] = 0x24E00810; + pNv->PGRAPH[0x008C/4] = 0x55DE0030; + + for(i = 0; i < 32; i++) + pNv->PGRAPH[(0x0B00/4) + i] = pNv->PFB[(0x0240/4) + i]; + + pNv->PGRAPH[0x640/4] = 0; + pNv->PGRAPH[0x644/4] = 0; + pNv->PGRAPH[0x684/4] = pNv->FbMapSize - 1; + pNv->PGRAPH[0x688/4] = pNv->FbMapSize - 1; + + pNv->PGRAPH[0x0810/4] = 0x00000000; + } else { + if(pNv->Architecture >= NV_ARCH_30) { + pNv->PGRAPH[0x0084/4] = 0x40108700; + pNv->PGRAPH[0x0890/4] = 0x00140000; + pNv->PGRAPH[0x008C/4] = 0xf00e0431; + pNv->PGRAPH[0x0090/4] = 0x00008000; + pNv->PGRAPH[0x0610/4] = 0xf04b1f36; + pNv->PGRAPH[0x0B80/4] = 0x1002d888; + pNv->PGRAPH[0x0B88/4] = 0x62ff007f; + } else { + pNv->PGRAPH[0x0084/4] = 0x00118700; + pNv->PGRAPH[0x008C/4] = 0xF20E0431; + pNv->PGRAPH[0x0090/4] = 0x00000000; + pNv->PGRAPH[0x009C/4] = 0x00000040; + + if((pNv->Chipset & 0x0ff0) >= 0x0250) { + pNv->PGRAPH[0x0890/4] = 0x00080000; + pNv->PGRAPH[0x0610/4] = 0x304B1FB6; + pNv->PGRAPH[0x0B80/4] = 0x18B82880; + pNv->PGRAPH[0x0B84/4] = 0x44000000; + pNv->PGRAPH[0x0098/4] = 0x40000080; + pNv->PGRAPH[0x0B88/4] = 0x000000ff; + } else { + pNv->PGRAPH[0x0880/4] = 0x00080000; + pNv->PGRAPH[0x0094/4] = 0x00000005; + pNv->PGRAPH[0x0B80/4] = 0x45CAA208; + pNv->PGRAPH[0x0B84/4] = 0x24000000; + pNv->PGRAPH[0x0098/4] = 0x00000040; + pNv->PGRAPH[0x0750/4] = 0x00E00038; + pNv->PGRAPH[0x0754/4] = 0x00000030; + pNv->PGRAPH[0x0750/4] = 0x00E10038; + pNv->PGRAPH[0x0754/4] = 0x00000030; + } + } + + for(i = 0; i < 32; i++) + pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0240/4) + i]; + + pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4]; + pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4]; + pNv->PGRAPH[0x0750/4] = 0x00EA0000; + pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4]; + pNv->PGRAPH[0x0750/4] = 0x00EA0004; + pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4]; + + pNv->PGRAPH[0x0820/4] = 0; + pNv->PGRAPH[0x0824/4] = 0; + pNv->PGRAPH[0x0864/4] = pNv->FbMapSize - 1; + pNv->PGRAPH[0x0868/4] = pNv->FbMapSize - 1; + + pNv->PGRAPH[0x0B20/4] = 0x00000000; + } + } + pNv->PGRAPH[0x053C/4] = 0; + pNv->PGRAPH[0x0540/4] = 0; + pNv->PGRAPH[0x0544/4] = 0x00007FFF; + pNv->PGRAPH[0x0548/4] = 0x00007FFF; + + pNv->PFIFO[0x0140] = 0x00000000; + pNv->PFIFO[0x0141] = 0x00000001; + pNv->PFIFO[0x0480] = 0x00000000; + pNv->PFIFO[0x0494] = 0x00000000; + pNv->PFIFO[0x0481] = 0x00000100; + pNv->PFIFO[0x0490] = 0x00000000; + pNv->PFIFO[0x0491] = 0x00000000; + pNv->PFIFO[0x048B] = 0x00001209; + pNv->PFIFO[0x0400] = 0x00000000; + pNv->PFIFO[0x0414] = 0x00000000; + pNv->PFIFO[0x0084] = 0x03000100; + pNv->PFIFO[0x0085] = 0x00000110; + pNv->PFIFO[0x0086] = 0x00000112; + pNv->PFIFO[0x0143] = 0x0000FFFF; + pNv->PFIFO[0x0496] = 0x0000FFFF; + pNv->PFIFO[0x0050] = 0x00000000; + pNv->PFIFO[0x0040] = 0xFFFFFFFF; + pNv->PFIFO[0x0415] = 0x00000001; + pNv->PFIFO[0x048C] = 0x00000000; + pNv->PFIFO[0x04A0] = 0x00000000; +#if X_BYTE_ORDER == X_BIG_ENDIAN + pNv->PFIFO[0x0489] = 0x800F0078; +#else + pNv->PFIFO[0x0489] = 0x000F0078; +#endif + pNv->PFIFO[0x0488] = 0x00000001; + pNv->PFIFO[0x0480] = 0x00000001; + pNv->PFIFO[0x0494] = 0x00000001; + pNv->PFIFO[0x0495] = 0x00000001; + pNv->PFIFO[0x0140] = 0x00000001; + + if(pNv->Architecture >= NV_ARCH_10) { + if(pNv->twoHeads) { + pNv->PCRTC0[0x0860/4] = state->head; + pNv->PCRTC0[0x2860/4] = state->head2; + } + pNv->PRAMDAC[0x0404/4] |= (1 << 25); + + pNv->PMC[0x8704/4] = 1; + pNv->PMC[0x8140/4] = 0; + pNv->PMC[0x8920/4] = 0; + pNv->PMC[0x8924/4] = 0; + pNv->PMC[0x8908/4] = pNv->FbMapSize - 1; + pNv->PMC[0x890C/4] = pNv->FbMapSize - 1; + pNv->PMC[0x1588/4] = 0; + + pNv->PCRTC[0x0810/4] = state->cursorConfig; + + if(pNv->FlatPanel) { + if((pNv->Chipset & 0x0ff0) == 0x0110) { + pNv->PRAMDAC[0x0528/4] = state->dither; + } else + if((pNv->Chipset & 0x0ff0) >= 0x0170) { + pNv->PRAMDAC[0x083C/4] = state->dither; + } + + VGA_WR08(pNv->PCIO, 0x03D4, 0x53); + VGA_WR08(pNv->PCIO, 0x03D5, 0); + VGA_WR08(pNv->PCIO, 0x03D4, 0x54); + VGA_WR08(pNv->PCIO, 0x03D5, 0); + VGA_WR08(pNv->PCIO, 0x03D4, 0x21); + VGA_WR08(pNv->PCIO, 0x03D5, 0xfa); + } + + VGA_WR08(pNv->PCIO, 0x03D4, 0x41); + VGA_WR08(pNv->PCIO, 0x03D5, state->extra); + } + + VGA_WR08(pNv->PCIO, 0x03D4, 0x19); + VGA_WR08(pNv->PCIO, 0x03D5, state->repaint0); + VGA_WR08(pNv->PCIO, 0x03D4, 0x1A); + VGA_WR08(pNv->PCIO, 0x03D5, state->repaint1); + VGA_WR08(pNv->PCIO, 0x03D4, 0x25); + VGA_WR08(pNv->PCIO, 0x03D5, state->screen); + VGA_WR08(pNv->PCIO, 0x03D4, 0x28); + VGA_WR08(pNv->PCIO, 0x03D5, state->pixel); + VGA_WR08(pNv->PCIO, 0x03D4, 0x2D); + VGA_WR08(pNv->PCIO, 0x03D5, state->horiz); + VGA_WR08(pNv->PCIO, 0x03D4, 0x1B); + VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration0); + VGA_WR08(pNv->PCIO, 0x03D4, 0x20); + VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1); + VGA_WR08(pNv->PCIO, 0x03D4, 0x30); + VGA_WR08(pNv->PCIO, 0x03D5, state->cursor0); + VGA_WR08(pNv->PCIO, 0x03D4, 0x31); + VGA_WR08(pNv->PCIO, 0x03D5, state->cursor1); + VGA_WR08(pNv->PCIO, 0x03D4, 0x2F); + VGA_WR08(pNv->PCIO, 0x03D5, state->cursor2); + VGA_WR08(pNv->PCIO, 0x03D4, 0x39); + VGA_WR08(pNv->PCIO, 0x03D5, state->interlace); + + if(!pNv->FlatPanel) { + pNv->PRAMDAC0[0x050C/4] = state->pllsel; + pNv->PRAMDAC0[0x0508/4] = state->vpll; + if(pNv->twoHeads) + pNv->PRAMDAC0[0x0520/4] = state->vpll2; + if(pNv->twoStagePLL) { + pNv->PRAMDAC0[0x0578/4] = state->vpllB; + pNv->PRAMDAC0[0x057C/4] = state->vpll2B; + } + } else { + pNv->PRAMDAC[0x0848/4] = state->scale; + } + pNv->PRAMDAC[0x0600/4] = state->general; + + pNv->PCRTC[0x0140/4] = 0; + pNv->PCRTC[0x0100/4] = 1; + + pNv->CurrentState = state; +} + +void NVUnloadStateExt +( + NVPtr pNv, + RIVA_HW_STATE *state +) +{ + VGA_WR08(pNv->PCIO, 0x03D4, 0x19); + state->repaint0 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x1A); + state->repaint1 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x25); + state->screen = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x28); + state->pixel = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x2D); + state->horiz = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x1B); + state->arbitration0 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x20); + state->arbitration1 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x30); + state->cursor0 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x31); + state->cursor1 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x2F); + state->cursor2 = VGA_RD08(pNv->PCIO, 0x03D5); + VGA_WR08(pNv->PCIO, 0x03D4, 0x39); + state->interlace = VGA_RD08(pNv->PCIO, 0x03D5); + state->vpll = pNv->PRAMDAC0[0x0508/4]; + if(pNv->twoHeads) + state->vpll2 = pNv->PRAMDAC0[0x0520/4]; + if(pNv->twoStagePLL) { + state->vpllB = pNv->PRAMDAC0[0x0578/4]; + state->vpll2B = pNv->PRAMDAC0[0x057C/4]; + } + state->pllsel = pNv->PRAMDAC0[0x050C/4]; + state->general = pNv->PRAMDAC[0x0600/4]; + state->scale = pNv->PRAMDAC[0x0848/4]; + state->config = pNv->PFB[0x0200/4]; + + if(pNv->Architecture >= NV_ARCH_10) { + if(pNv->twoHeads) { + state->head = pNv->PCRTC0[0x0860/4]; + state->head2 = pNv->PCRTC0[0x2860/4]; + VGA_WR08(pNv->PCIO, 0x03D4, 0x44); + state->crtcOwner = VGA_RD08(pNv->PCIO, 0x03D5); + } + VGA_WR08(pNv->PCIO, 0x03D4, 0x41); + state->extra = VGA_RD08(pNv->PCIO, 0x03D5); + state->cursorConfig = pNv->PCRTC[0x0810/4]; + + if((pNv->Chipset & 0x0ff0) == 0x0110) { + state->dither = pNv->PRAMDAC[0x0528/4]; + } else + if((pNv->Chipset & 0x0ff0) >= 0x0170) { + state->dither = pNv->PRAMDAC[0x083C/4]; + } + } +} + +void NVSetStartAddress ( + NVPtr pNv, + CARD32 start +) +{ + pNv->PCRTC[0x800/4] = start; +} + + diff --git a/src/riva_const.h b/src/riva_const.h new file mode 100644 index 0000000..31dc8d5 --- /dev/null +++ b/src/riva_const.h @@ -0,0 +1,14 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_const.h,v 1.1 2003/07/31 20:24:29 mvojkovi Exp $ */ + +#ifndef __RIVA_CONST_H__ +#define __RIVA_CONST_H__ + +#define RIVA_VERSION 4000 +#define RIVA_NAME "RIVA128" +#define RIVA_DRIVER_NAME "riva128" +#define RIVA_MAJOR_VERSION 1 +#define RIVA_MINOR_VERSION 0 +#define RIVA_PATCHLEVEL 1 + +#endif /* __RIVA_CONST_H__ */ + diff --git a/src/riva_cursor.c b/src/riva_cursor.c new file mode 100644 index 0000000..7dcaed9 --- /dev/null +++ b/src/riva_cursor.c @@ -0,0 +1,165 @@ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Rewritten with reference from mga driver and 3.3.4 NVIDIA driver by + Jarno Paananen */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_cursor.c,v 1.1 2003/07/31 20:24:29 mvojkovi Exp $ */ + +#include "riva_include.h" + +#include "cursorstr.h" + +/****************************************************************************\ +* * +* HW Cursor Entrypoints * +* * +\****************************************************************************/ + +#define TRANSPARENT_PIXEL 0 + +#define ConvertToRGB555(c) \ +(((c & 0xf80000) >> 9 ) | ((c & 0xf800) >> 6 ) | ((c & 0xf8) >> 3 ) | 0x8000) + + +static void +RivaConvertCursor1555(RivaPtr pRiva, CARD32 *src, CARD16 *dst) +{ + CARD32 b, m; + int i, j; + + for ( i = 0; i < 32; i++ ) { + b = *src++; + m = *src++; + for ( j = 0; j < 32; j++ ) { + if ( m & 1 ) + *dst = ( b & 1) ? pRiva->curFg : pRiva->curBg; + else + *dst = TRANSPARENT_PIXEL; + b >>= 1; + m >>= 1; + dst++; + } + } +} + + +static void +RivaTransformCursor (RivaPtr pRiva) +{ + CARD32 *tmp; + int i, dwords; + + dwords = (32 * 32) >> 1; + if(!(tmp = ALLOCATE_LOCAL(dwords * 4))) return; + RivaConvertCursor1555(pRiva, pRiva->curImage, (CARD16*)tmp); + + for(i = 0; i < dwords; i++) + pRiva->riva.CURSOR[i] = tmp[i]; + + DEALLOCATE_LOCAL(tmp); +} + +static void +RivaLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src ) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + /* save copy of image for color changes */ + memcpy(pRiva->curImage, src, 256); + + RivaTransformCursor(pRiva); +} + +static void +RivaSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + pRiva->riva.PRAMDAC[0x0000300/4] = (x & 0xFFFF) | (y << 16); +} + +static void +RivaSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + RivaPtr pRiva = RivaPTR(pScrn); + CARD32 fore, back; + + fore = ConvertToRGB555(fg); + back = ConvertToRGB555(bg); + + if ((pRiva->curFg != fore) || (pRiva->curBg != back)) { + pRiva->curFg = fore; + pRiva->curBg = back; + + RivaTransformCursor(pRiva); + } +} + + +static void +RivaShowCursor(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + /* Enable cursor - X-Windows mode */ + pRiva->riva.ShowHideCursor(&pRiva->riva, 1); +} + +static void +RivaHideCursor(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + /* Disable cursor */ + pRiva->riva.ShowHideCursor(&pRiva->riva, 0); +} + +static Bool +RivaUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + + +Bool +RivaCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RivaPtr pRiva = RivaPTR(pScrn); + xf86CursorInfoPtr infoPtr; + + infoPtr = xf86CreateCursorInfoRec(); + if(!infoPtr) return FALSE; + + pRiva->CursorInfoRec = infoPtr; + + infoPtr->MaxWidth = infoPtr->MaxHeight = 32; + infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32; + infoPtr->SetCursorColors = RivaSetCursorColors; + infoPtr->SetCursorPosition = RivaSetCursorPosition; + infoPtr->LoadCursorImage = RivaLoadCursorImage; + infoPtr->HideCursor = RivaHideCursor; + infoPtr->ShowCursor = RivaShowCursor; + infoPtr->UseHWCursor = RivaUseHWCursor; + + return(xf86InitCursor(pScreen, infoPtr)); +} diff --git a/src/riva_dac.c b/src/riva_dac.c new file mode 100644 index 0000000..348e526 --- /dev/null +++ b/src/riva_dac.c @@ -0,0 +1,280 @@ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_dac.c,v 1.2 2003/09/16 00:17:46 mvojkovi Exp $ */ + +#include "riva_include.h" + +Bool +RivaDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + int i; + int horizDisplay = (mode->CrtcHDisplay/8) - 1; + int horizStart = (mode->CrtcHSyncStart/8) - 1; + int horizEnd = (mode->CrtcHSyncEnd/8) - 1; + int horizTotal = (mode->CrtcHTotal/8) - 5; + int horizBlankStart = (mode->CrtcHDisplay/8) - 1; + int horizBlankEnd = (mode->CrtcHTotal/8) - 1; + int vertDisplay = mode->CrtcVDisplay - 1; + int vertStart = mode->CrtcVSyncStart - 1; + int vertEnd = mode->CrtcVSyncEnd - 1; + int vertTotal = mode->CrtcVTotal - 2; + int vertBlankStart = mode->CrtcVDisplay - 1; + int vertBlankEnd = mode->CrtcVTotal - 1; + + + RivaPtr pRiva = RivaPTR(pScrn); + RivaRegPtr rivaReg = &pRiva->ModeReg; + RivaFBLayout *pLayout = &pRiva->CurrentLayout; + vgaRegPtr pVga; + + /* + * This will initialize all of the generic VGA registers. + */ + if (!vgaHWInit(pScrn, mode)) + return(FALSE); + + pVga = &VGAHWPTR(pScrn)->ModeReg; + + /* + * Set all CRTC values. + */ + + if(mode->Flags & V_INTERLACE) + vertTotal |= 1; + + pVga->CRTC[0x0] = Set8Bits(horizTotal); + pVga->CRTC[0x1] = Set8Bits(horizDisplay); + pVga->CRTC[0x2] = Set8Bits(horizBlankStart); + pVga->CRTC[0x3] = SetBitField(horizBlankEnd,4:0,4:0) + | SetBit(7); + pVga->CRTC[0x4] = Set8Bits(horizStart); + pVga->CRTC[0x5] = SetBitField(horizBlankEnd,5:5,7:7) + | SetBitField(horizEnd,4:0,4:0); + pVga->CRTC[0x6] = SetBitField(vertTotal,7:0,7:0); + pVga->CRTC[0x7] = SetBitField(vertTotal,8:8,0:0) + | SetBitField(vertDisplay,8:8,1:1) + | SetBitField(vertStart,8:8,2:2) + | SetBitField(vertBlankStart,8:8,3:3) + | SetBit(4) + | SetBitField(vertTotal,9:9,5:5) + | SetBitField(vertDisplay,9:9,6:6) + | SetBitField(vertStart,9:9,7:7); + pVga->CRTC[0x9] = SetBitField(vertBlankStart,9:9,5:5) + | SetBit(6) + | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00); + pVga->CRTC[0x10] = Set8Bits(vertStart); + pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5); + pVga->CRTC[0x12] = Set8Bits(vertDisplay); + pVga->CRTC[0x13] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8)); + pVga->CRTC[0x15] = Set8Bits(vertBlankStart); + pVga->CRTC[0x16] = Set8Bits(vertBlankEnd); + + pVga->Attribute[0x10] = 0x01; + + rivaReg->screen = SetBitField(horizBlankEnd,6:6,4:4) + | SetBitField(vertBlankStart,10:10,3:3) + | SetBitField(vertStart,10:10,2:2) + | SetBitField(vertDisplay,10:10,1:1) + | SetBitField(vertTotal,10:10,0:0); + + rivaReg->horiz = SetBitField(horizTotal,8:8,0:0) + | SetBitField(horizDisplay,8:8,1:1) + | SetBitField(horizBlankStart,8:8,2:2) + | SetBitField(horizStart,8:8,3:3); + + rivaReg->extra = SetBitField(vertTotal,11:11,0:0) + | SetBitField(vertDisplay,11:11,2:2) + | SetBitField(vertStart,11:11,4:4) + | SetBitField(vertBlankStart,11:11,6:6); + + if(mode->Flags & V_INTERLACE) { + horizTotal = (horizTotal >> 1) & ~1; + rivaReg->interlace = Set8Bits(horizTotal); + rivaReg->horiz |= SetBitField(horizTotal,8:8,4:4); + } else { + rivaReg->interlace = 0xff; /* interlace off */ + } + + /* + * Initialize DAC palette. + */ + if(pLayout->bitsPerPixel != 8 ) + { + for (i = 0; i < 256; i++) + { + pVga->DAC[i*3] = i; + pVga->DAC[(i*3)+1] = i; + pVga->DAC[(i*3)+2] = i; + } + } + + /* + * Calculate the extended registers. + */ + + if(pLayout->depth < 24) + i = pLayout->depth; + else i = 32; + + pRiva->riva.CalcStateExt(&pRiva->riva, + rivaReg, + i, + pLayout->displayWidth, + mode->CrtcHDisplay, + pScrn->virtualY, + mode->Clock, + mode->Flags); + + rivaReg->cursorConfig = 0x02000100; + if(mode->Flags & V_DBLSCAN) + rivaReg->cursorConfig |= (1 << 4); + + return (TRUE); +} + +void +RivaDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg, + Bool primary) +{ + RivaPtr pRiva = RivaPTR(pScrn); + int restore = VGA_SR_MODE; + + restore |= primary ? (VGA_SR_CMAP | VGA_SR_FONTS) : VGA_SR_CMAP; + pRiva->riva.LoadStateExt(&pRiva->riva, rivaReg); + vgaHWRestore(pScrn, vgaReg, restore); +} + +/* + * RivaDACSave + * + * This function saves the video state. + */ +void +RivaDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, RivaRegPtr rivaReg, + Bool saveFonts) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + pRiva->riva.LockUnlock(&pRiva->riva, 0); + + vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE | + (saveFonts? VGA_SR_FONTS : 0)); + pRiva->riva.UnloadStateExt(&pRiva->riva, rivaReg); +} + +#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8))) +#define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3) + +void +RivaDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, + VisualPtr pVisual ) +{ + int i, index; + RivaPtr pRiva = RivaPTR(pScrn); + vgaRegPtr pVga; + + pVga = &VGAHWPTR(pScrn)->ModeReg; + + if(pRiva->CurrentLayout.depth != 8) + return; + + for(i = 0; i < numColors; i++) { + index = indices[i]; + pVga->DAC[index*3] = colors[index].red; + pVga->DAC[(index*3)+1] = colors[index].green; + pVga->DAC[(index*3)+2] = colors[index].blue; + } + vgaHWRestore(pScrn, pVga, VGA_SR_CMAP); +} + +/* + * DDC1 support only requires DDC_SDA_MASK, + * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK + */ +#define DDC_SDA_READ_MASK (1 << 3) +#define DDC_SCL_READ_MASK (1 << 2) +#define DDC_SDA_WRITE_MASK (1 << 4) +#define DDC_SCL_WRITE_MASK (1 << 5) + +static void +Riva_I2CGetBits(I2CBusPtr b, int *clock, int *data) +{ + RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]); + unsigned char val; + + /* Get the result. */ + VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase); + val = VGA_RD08(pRiva->riva.PCIO, 0x3d5); + + *clock = (val & DDC_SCL_READ_MASK) != 0; + *data = (val & DDC_SDA_READ_MASK) != 0; +} + +static void +Riva_I2CPutBits(I2CBusPtr b, int clock, int data) +{ + RivaPtr pRiva = RivaPTR(xf86Screens[b->scrnIndex]); + unsigned char val; + + VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1); + val = VGA_RD08(pRiva->riva.PCIO, 0x3d5) & 0xf0; + if (clock) + val |= DDC_SCL_WRITE_MASK; + else + val &= ~DDC_SCL_WRITE_MASK; + + if (data) + val |= DDC_SDA_WRITE_MASK; + else + val &= ~DDC_SDA_WRITE_MASK; + + VGA_WR08(pRiva->riva.PCIO, 0x3d4, pRiva->DDCBase + 1); + VGA_WR08(pRiva->riva.PCIO, 0x3d5, val | 0x1); +} + +Bool +RivaDACi2cInit(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + I2CBusPtr I2CPtr; + + I2CPtr = xf86CreateI2CBusRec(); + if(!I2CPtr) return FALSE; + + pRiva->I2C = I2CPtr; + + I2CPtr->BusName = "DDC"; + I2CPtr->scrnIndex = pScrn->scrnIndex; + I2CPtr->I2CPutBits = Riva_I2CPutBits; + I2CPtr->I2CGetBits = Riva_I2CGetBits; + I2CPtr->AcknTimeout = 5; + + if (!xf86I2CBusInit(I2CPtr)) { + return FALSE; + } + return TRUE; +} + diff --git a/src/riva_dga.c b/src/riva_dga.c new file mode 100644 index 0000000..cbe4224 --- /dev/null +++ b/src/riva_dga.c @@ -0,0 +1,305 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_dga.c,v 1.1 2003/07/31 20:24:29 mvojkovi Exp $ */ + +#include "riva_local.h" +#include "riva_include.h" +#include "riva_type.h" +#include "riva_proto.h" +#include "xaalocal.h" +#include "dgaproc.h" + + +static Bool Riva_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool Riva_SetMode(ScrnInfoPtr, DGAModePtr); +static int Riva_GetViewport(ScrnInfoPtr); +static void Riva_SetViewport(ScrnInfoPtr, int, int, int); +static void Riva_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void Riva_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +static void Riva_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); + +static +DGAFunctionRec Riva_DGAFuncs = { + Riva_OpenFramebuffer, + NULL, + Riva_SetMode, + Riva_SetViewport, + Riva_GetViewport, + RivaSync, + Riva_FillRect, + Riva_BlitRect, + Riva_BlitTransRect +}; + + + +static DGAModePtr +RivaSetupDGAMode( + ScrnInfoPtr pScrn, + DGAModePtr modes, + int *num, + int bitsPerPixel, + int depth, + Bool pixmap, + int secondPitch, + unsigned long red, + unsigned long green, + unsigned long blue, + short visualClass +){ + DisplayModePtr firstMode, pMode; + RivaPtr pRiva = RivaPTR(pScrn); + DGAModePtr mode, newmodes; + int size, pitch, Bpp = bitsPerPixel >> 3; + +SECOND_PASS: + + pMode = firstMode = pScrn->modes; + + while(1) { + + pitch = (pMode->HDisplay + 31) & ~31; + size = pitch * Bpp * pMode->VDisplay; + + if((!secondPitch || (pitch != secondPitch)) && + (size <= pRiva->FbUsableSize)) { + + if(secondPitch) + pitch = secondPitch; + + if(!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)))) + break; + + modes = newmodes; + mode = modes + *num; + + mode->mode = pMode; + mode->flags = DGA_CONCURRENT_ACCESS; + + if(pixmap) + mode->flags |= DGA_PIXMAP_AVAILABLE; + if(!pRiva->NoAccel) + mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if(pMode->Flags & V_DBLSCAN) + mode->flags |= DGA_DOUBLESCAN; + if(pMode->Flags & V_INTERLACE) + mode->flags |= DGA_INTERLACED; + mode->byteOrder = pScrn->imageByteOrder; + mode->depth = depth; + mode->bitsPerPixel = bitsPerPixel; + mode->red_mask = red; + mode->green_mask = green; + mode->blue_mask = blue; + mode->visualClass = visualClass; + mode->viewportWidth = pMode->HDisplay; + mode->viewportHeight = pMode->VDisplay; + mode->xViewportStep = 4 / Bpp; + mode->yViewportStep = 1; + mode->viewportFlags = DGA_FLIP_RETRACE; + mode->offset = 0; + mode->address = pRiva->FbStart; + mode->bytesPerScanline = pitch * Bpp; + mode->imageWidth = pitch; + mode->imageHeight = pRiva->FbUsableSize / mode->bytesPerScanline; + mode->pixmapWidth = mode->imageWidth; + mode->pixmapHeight = mode->imageHeight; + mode->maxViewportX = mode->imageWidth - mode->viewportWidth; + mode->maxViewportY = mode->imageHeight - mode->viewportHeight; + (*num)++; + } + + pMode = pMode->next; + if(pMode == firstMode) + break; + } + + if(secondPitch) { + secondPitch = 0; + goto SECOND_PASS; + } + + return modes; +} + + +Bool +RivaDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RivaPtr pRiva = RivaPTR(pScrn); + DGAModePtr modes = NULL; + int num = 0; + + /* 8 */ + modes = RivaSetupDGAMode (pScrn, modes, &num, 8, 8, + (pScrn->bitsPerPixel == 8), + (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth, + 0, 0, 0, PseudoColor); + + /* 15 */ + modes = RivaSetupDGAMode (pScrn, modes, &num, 16, 15, + (pScrn->bitsPerPixel == 16), + (pScrn->depth != 15) ? 0 : pScrn->displayWidth, + 0x7c00, 0x03e0, 0x001f, TrueColor); + + /* 32 */ + modes = RivaSetupDGAMode (pScrn, modes, &num, 32, 24, + (pScrn->bitsPerPixel == 32), + (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth, + 0xff0000, 0x00ff00, 0x0000ff, TrueColor); + + pRiva->numDGAModes = num; + pRiva->DGAModes = modes; + + return DGAInit(pScreen, &Riva_DGAFuncs, modes, num); +} + + +static int +BitsSet(unsigned long data) +{ + unsigned long mask; + int set = 0; + + for(mask = 1; mask; mask <<= 1) + if(mask & data) set++; + + return set; +} + +static Bool +Riva_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static RivaFBLayout SavedLayouts[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + + RivaPtr pRiva = RivaPTR(pScrn); + + if(!pMode) { /* restore the original mode */ + if(pRiva->DGAactive) + memcpy(&pRiva->CurrentLayout, &SavedLayouts[index], sizeof(RivaFBLayout)); + + pScrn->currentMode = pRiva->CurrentLayout.mode; + RivaSwitchMode(index, pScrn->currentMode, 0); + RivaAdjustFrame(index, pScrn->frameX0, pScrn->frameY0, 0); + pRiva->DGAactive = FALSE; + } else { + if(!pRiva->DGAactive) { /* save the old parameters */ + memcpy(&SavedLayouts[index], &pRiva->CurrentLayout, sizeof(RivaFBLayout)); + pRiva->DGAactive = TRUE; + } + + /* update CurrentLayout */ + pRiva->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; + pRiva->CurrentLayout.depth = pMode->depth; + pRiva->CurrentLayout.displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + pRiva->CurrentLayout.weight.red = BitsSet(pMode->red_mask); + pRiva->CurrentLayout.weight.green = BitsSet(pMode->green_mask); + pRiva->CurrentLayout.weight.blue = BitsSet(pMode->blue_mask); + /* RivaModeInit() will set the mode field */ + RivaSwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + + + +static int +Riva_GetViewport( + ScrnInfoPtr pScrn +){ + RivaPtr pRiva = RivaPTR(pScrn); + + return pRiva->DGAViewportStatus; +} + +static void +Riva_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags +){ + RivaPtr pRiva = RivaPTR(pScrn); + + RivaAdjustFrame(pScrn->pScreen->myNum, x, y, flags); + + while(VGA_RD08(pRiva->riva.PCIO, 0x3da) & 0x08); + while(!(VGA_RD08(pRiva->riva.PCIO, 0x3da) & 0x08)); + + pRiva->DGAViewportStatus = 0; +} + +static void +Riva_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + RivaPtr pRiva = RivaPTR(pScrn); + + if(!pRiva->AccelInfoRec) return; + + (*pRiva->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pRiva->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + + SET_SYNC_FLAG(pRiva->AccelInfoRec); +} + +static void +Riva_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + RivaPtr pRiva = RivaPTR(pScrn); + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + if(!pRiva->AccelInfoRec) return; + + (*pRiva->AccelInfoRec->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, -1); + + (*pRiva->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + + SET_SYNC_FLAG(pRiva->AccelInfoRec); +} + + +static void +Riva_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + /* not implemented... yet */ +} + + +static Bool +Riva_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + RivaPtr pRiva = RivaPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)pRiva->FbAddress; + *size = pRiva->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/riva_driver.c b/src/riva_driver.c new file mode 100644 index 0000000..1b4ca07 --- /dev/null +++ b/src/riva_driver.c @@ -0,0 +1,1384 @@ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_driver.c,v 1.5 2003/11/03 05:11:26 tsi Exp $ */ + +#include "riva_include.h" + +#include "xf86int10.h" + +/* + * Forward definitions for the functions that make up the driver. + */ +/* Mandatory functions */ +static Bool RivaPreInit(ScrnInfoPtr pScrn, int flags); +static Bool RivaScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool RivaEnterVT(int scrnIndex, int flags); +static Bool RivaEnterVTFBDev(int scrnIndex, int flags); +static void RivaLeaveVT(int scrnIndex, int flags); +static Bool RivaCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool RivaSaveScreen(ScreenPtr pScreen, int mode); + +/* Optional functions */ +static void RivaFreeScreen(int scrnIndex, int flags); +static ModeStatus RivaValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flags); + +/* Internally used functions */ + +static Bool RivaMapMem(ScrnInfoPtr pScrn); +static Bool RivaMapMemFBDev(ScrnInfoPtr pScrn); +static Bool RivaUnmapMem(ScrnInfoPtr pScrn); +static void RivaSave(ScrnInfoPtr pScrn); +static void RivaRestore(ScrnInfoPtr pScrn); +static Bool RivaModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); + + +/* + * List of symbols from other modules that this module references. This + * list is used to tell the loader that it is OK for symbols here to be + * unresolved providing that it hasn't been told that they haven't been + * told that they are essential via a call to xf86LoaderReqSymbols() or + * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about + * unresolved symbols that are not required. + */ + +static const char *vgahwSymbols[] = { + "vgaHWUnmapMem", + "vgaHWDPMSSet", + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + NULL +}; + +static const char *fbSymbols[] = { + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACopyROP", + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAFallbackOps", + "XAAInit", + "XAAPatternROP", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86DoEDID_DDC2", + "xf86SetDDCproperties", + NULL +}; + +#ifdef XFree86LOADER +static const char *vbeSymbols[] = { + "VBEInit", + "vbeFree", + "vbeDoEDID", + NULL +}; +#endif + +static const char *i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + NULL +}; + +static const char *shadowSymbols[] = { + "ShadowFBInit", + NULL +}; + +static const char *fbdevHWSymbols[] = { + "fbdevHWInit", + "fbdevHWUseBuildinMode", + + "fbdevHWGetVidmem", + + /* colormap */ + "fbdevHWLoadPalette", + + /* ScrnInfo hooks */ + "fbdevHWAdjustFrame", + "fbdevHWEnterVT", + "fbdevHWLeaveVT", + "fbdevHWModeInit", + "fbdevHWSave", + "fbdevHWSwitchMode", + "fbdevHWValidMode", + + "fbdevHWMapMMIO", + "fbdevHWMapVidmem", + + NULL +}; + +static const char *int10Symbols[] = { + "xf86FreeInt10", + "xf86InitInt10", + NULL +}; + + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(rivaSetup); + +static XF86ModuleVersionInfo rivaVersRec = +{ + "riva", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + RIVA_MAJOR_VERSION, RIVA_MINOR_VERSION, RIVA_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + +XF86ModuleData riva128ModuleData = { &rivaVersRec, rivaSetup, NULL }; +#endif + + +typedef enum { + OPTION_SW_CURSOR, + OPTION_HW_CURSOR, + OPTION_NOACCEL, + OPTION_SHOWCACHE, + OPTION_SHADOW_FB, + OPTION_FBDEV, + OPTION_ROTATE +} RivaOpts; + + +static const OptionInfoRec RivaOptions[] = { + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +/* + * ramdac info structure initialization + */ +static RivaRamdacRec DacInit = { + FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL, NULL +}; + + + +static Bool +RivaGetRec(ScrnInfoPtr pScrn) +{ + /* + * Allocate an RivaRec, and hook it into pScrn->driverPrivate. + * pScrn->driverPrivate is initialised to NULL, so we can check if + * the allocation has already been done. + */ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(RivaRec), 1); + /* Initialise it */ + + RivaPTR(pScrn)->Dac = DacInit; + return TRUE; +} + +static void +RivaFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + + +#ifdef XFree86LOADER + +static pointer +rivaSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + /* This module should be loaded only once, but check to be sure. */ + + if (!setupDone) { + setupDone = TRUE; + + LoaderRefSymLists(vgahwSymbols, xaaSymbols, fbSymbols, + ramdacSymbols, shadowSymbols, + i2cSymbols, ddcSymbols, vbeSymbols, + fbdevHWSymbols, int10Symbols, NULL); + } + return (pointer)1; +} + + +#endif /* XFree86LOADER */ + +const OptionInfoRec * +RivaAvailableOptions(int chipid, int busid) +{ + return RivaOptions; +} + + +Bool +RivaGetScrnInfoRec(PciChipsets *chips, int chip) +{ + ScrnInfoPtr pScrn; + + pScrn = xf86ConfigPciEntity(NULL, 0, chip, + chips, NULL, NULL, NULL, + NULL, NULL); + + if(!pScrn) return FALSE; + + pScrn->driverVersion = RIVA_VERSION; + pScrn->driverName = RIVA_DRIVER_NAME; + pScrn->name = RIVA_NAME; + + pScrn->Probe = NULL; + pScrn->PreInit = RivaPreInit; + pScrn->ScreenInit = RivaScreenInit; + pScrn->SwitchMode = RivaSwitchMode; + pScrn->AdjustFrame = RivaAdjustFrame; + pScrn->EnterVT = RivaEnterVT; + pScrn->LeaveVT = RivaLeaveVT; + pScrn->FreeScreen = RivaFreeScreen; + pScrn->ValidMode = RivaValidMode; + + return TRUE; +} + +/* Usually mandatory */ +Bool +RivaSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return RivaModeInit(xf86Screens[scrnIndex], mode); +} + +/* + * This function is used to initialize the Start Address - the first + * displayed location in the video memory. + */ +/* Usually mandatory */ +void +RivaAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int startAddr; + RivaPtr pRiva = RivaPTR(pScrn); + RivaFBLayout *pLayout = &pRiva->CurrentLayout; + + if(pRiva->ShowCache && y && pScrn->vtSema) + y += pScrn->virtualY - 1; + + startAddr = (((y*pLayout->displayWidth)+x)*(pLayout->bitsPerPixel/8)); + pRiva->riva.SetStartAddress(&pRiva->riva, startAddr); +} + + +/* + * This is called when VT switching back to the X server. Its job is + * to reinitialise the video mode. + * + * We may wish to unmap video/MMIO memory too. + */ + +/* Mandatory */ +static Bool +RivaEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!RivaModeInit(pScrn, pScrn->currentMode)) + return FALSE; + RivaAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return TRUE; +} + +static Bool +RivaEnterVTFBDev(int scrnIndex, int flags) +{ + fbdevHWEnterVT(scrnIndex,flags); + return TRUE; +} + +/* + * This is called when VT switching away from the X server. Its job is + * to restore the previous (text) mode. + * + * We may wish to remap video/MMIO memory too. + */ + +/* Mandatory */ +static void +RivaLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RivaPtr pRiva = RivaPTR(pScrn); + + RivaRestore(pScrn); + pRiva->riva.LockUnlock(&pRiva->riva, 1); +} + + + +/* + * This is called at the end of each server generation. It restores the + * original (text) mode. It should also unmap the video memory, and free + * any per-generation data allocated by the driver. It should finish + * by unwrapping and calling the saved CloseScreen function. + */ + +/* Mandatory */ +static Bool +RivaCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RivaPtr pRiva = RivaPTR(pScrn); + + if (pScrn->vtSema) { + RivaRestore(pScrn); + pRiva->riva.LockUnlock(&pRiva->riva, 1); + } + + RivaUnmapMem(pScrn); + vgaHWUnmapMem(pScrn); + if (pRiva->AccelInfoRec) + XAADestroyInfoRec(pRiva->AccelInfoRec); + if (pRiva->CursorInfoRec) + xf86DestroyCursorInfoRec(pRiva->CursorInfoRec); + if (pRiva->ShadowPtr) + xfree(pRiva->ShadowPtr); + if (pRiva->DGAModes) + xfree(pRiva->DGAModes); + if ( pRiva->expandBuffer ) + xfree(pRiva->expandBuffer); + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pRiva->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + +/* Free up any persistent data structures */ + +/* Optional */ +static void +RivaFreeScreen(int scrnIndex, int flags) +{ + /* + * This only gets called when a screen is being deleted. It does not + * get called routinely at the end of a server generation. + */ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + RivaFreeRec(xf86Screens[scrnIndex]); +} + + +/* Checks if a mode is suitable for the selected chipset. */ + +/* Optional */ +static ModeStatus +RivaValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + return (MODE_OK); +} + +static void +rivaProbeDDC(ScrnInfoPtr pScrn, int index) +{ + vbeInfoPtr pVbe; + + if (xf86LoadSubModule(pScrn, "vbe")) { + pVbe = VBEInit(NULL,index); + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } +} + + +Bool RivaI2CInit(ScrnInfoPtr pScrn) +{ + char *mod = "i2c"; + + if (xf86LoadSubModule(pScrn, mod)) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + + mod = "ddc"; + if(xf86LoadSubModule(pScrn, mod)) { + xf86LoaderReqSymLists(ddcSymbols, NULL); + return RivaDACi2cInit(pScrn); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Couldn't load %s module. DDC probing can't be done\n", mod); + + return FALSE; +} + +/* Mandatory */ +Bool +RivaPreInit(ScrnInfoPtr pScrn, int flags) +{ + RivaPtr pRiva; + MessageType from; + int i; + ClockRangePtr clockRanges; + const char *s; + + if (flags & PROBE_DETECT) { + rivaProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); + return TRUE; + } + + /* + * Note: This function is only called once at server startup, and + * not at the start of each server generation. This means that + * only things that are persistent across server generations can + * be initialised here. xf86Screens[] is (pScrn is a pointer to one + * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() + * are too, and should be used for data that must persist across + * server generations. + * + * Per-generation data should be allocated with + * AllocateScreenPrivateIndex() from the ScreenInit() function. + */ + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + /* Allocate the RivaRec driverPrivate */ + if (!RivaGetRec(pScrn)) { + return FALSE; + } + pRiva = RivaPTR(pScrn); + + /* Get the entity, and make sure it is PCI. */ + pRiva->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pRiva->pEnt->location.type != BUS_PCI) + return FALSE; + + /* Find the PCI info for this screen */ + pRiva->PciInfo = xf86GetPciInfoForEntity(pRiva->pEnt->index); + pRiva->PciTag = pciTag(pRiva->PciInfo->bus, pRiva->PciInfo->device, + pRiva->PciInfo->func); + + pRiva->Primary = xf86IsPrimaryPci(pRiva->PciInfo); + + /* Initialize the card through int10 interface if needed */ + if (xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols, NULL); +#if !defined(__alpha__) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); + pRiva->pInt = xf86InitInt10(pRiva->pEnt->index); +#endif + } + + xf86SetOperatingState(resVgaIo, pRiva->pEnt->index, ResUnusedOpr); + xf86SetOperatingState(resVgaMem, pRiva->pEnt->index, ResDisableOpr); + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + pRiva->ChipRev = pRiva->PciInfo->chipRev; + if((pRiva->PciInfo->vendor != 0x12D2) || (pRiva->PciInfo->chipType != 0x0018)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "This is not a RIVA 128\n"); + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + + pScrn->chipset = "RIVA 128"; + + /* + * The first thing we should figure out is the depth, bpp, etc. + */ + + if (!xf86SetDepthBpp(pScrn, 15, 0, 0, Support32bppFb)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 8: + case 15: + case 24: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } else { + /* We don't currently support DirectColor at > 8bpp */ + if (pScrn->depth > 8 && (pScrn->defaultVisual != TrueColor)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" + " (%s) is not supported at depth %d\n", + xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + } + + /* The vgahw module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "vgahw")) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + /* + * Allocate a vgaHWRec + */ + if (!vgaHWGetHWRec(pScrn)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + + /* We use a programmable clock */ + pScrn->progClock = TRUE; + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(pRiva->Options = xalloc(sizeof(RivaOptions)))) + return FALSE; + memcpy(pRiva->Options, RivaOptions, sizeof(RivaOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pRiva->Options); + + /* Set the bits per RGB for 8bpp mode */ + if (pScrn->depth == 8) + pScrn->rgbBits = 8; + + from = X_DEFAULT; + pRiva->HWCursor = TRUE; + /* + * The preferred method is to use the "hw cursor" option as a tri-state + * option, with the default set above. + */ + if (xf86GetOptValBool(pRiva->Options, OPTION_HW_CURSOR, &pRiva->HWCursor)) { + from = X_CONFIG; + } + /* For compatibility, accept this too (as an override) */ + if (xf86ReturnOptValBool(pRiva->Options, OPTION_SW_CURSOR, FALSE)) { + from = X_CONFIG; + pRiva->HWCursor = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pRiva->HWCursor ? "HW" : "SW"); + if (xf86ReturnOptValBool(pRiva->Options, OPTION_NOACCEL, FALSE)) { + pRiva->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + if (xf86ReturnOptValBool(pRiva->Options, OPTION_SHOWCACHE, FALSE)) { + pRiva->ShowCache = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); + } + if (xf86ReturnOptValBool(pRiva->Options, OPTION_SHADOW_FB, FALSE)) { + pRiva->ShadowFB = TRUE; + pRiva->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\" - acceleration disabled\n"); + } + if (xf86ReturnOptValBool(pRiva->Options, OPTION_FBDEV, FALSE)) { + pRiva->FBDev = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using framebuffer device\n"); + } + if (pRiva->FBDev) { + /* check for linux framebuffer device */ + if (!xf86LoadSubModule(pScrn, "fbdevhw")) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + + xf86LoaderReqSymLists(fbdevHWSymbols, NULL); + if (!fbdevHWInit(pScrn, pRiva->PciInfo, NULL)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + pScrn->SwitchMode = fbdevHWSwitchMode; + pScrn->AdjustFrame = fbdevHWAdjustFrame; + pScrn->EnterVT = RivaEnterVTFBDev; + pScrn->LeaveVT = fbdevHWLeaveVT; + pScrn->ValidMode = fbdevHWValidMode; + } + pRiva->Rotate = 0; + if ((s = xf86GetOptValString(pRiva->Options, OPTION_ROTATE))) { + if(!xf86NameCmp(s, "CW")) { + pRiva->ShadowFB = TRUE; + pRiva->NoAccel = TRUE; + pRiva->HWCursor = FALSE; + pRiva->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise - acceleration disabled\n"); + } else + if(!xf86NameCmp(s, "CCW")) { + pRiva->ShadowFB = TRUE; + pRiva->NoAccel = TRUE; + pRiva->HWCursor = FALSE; + pRiva->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen counter clockwise - acceleration disabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "\"%s\" is not a valid value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } + + if (pRiva->pEnt->device->MemBase != 0) { + /* Require that the config file value matches one of the PCI values. */ + if (!xf86CheckPciMemBase(pRiva->PciInfo, pRiva->pEnt->device->MemBase)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MemBase 0x%08lX doesn't match any PCI base register.\n", + pRiva->pEnt->device->MemBase); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + pRiva->FbAddress = pRiva->pEnt->device->MemBase; + from = X_CONFIG; + } else { + int i = 1; + pRiva->FbBaseReg = i; + if (pRiva->PciInfo->memBase[i] != 0) { + pRiva->FbAddress = pRiva->PciInfo->memBase[i] & 0xff800000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid FB address in PCI config space\n"); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pRiva->FbAddress); + + if (pRiva->pEnt->device->IOBase != 0) { + /* Require that the config file value matches one of the PCI values. */ + if (!xf86CheckPciMemBase(pRiva->PciInfo, pRiva->pEnt->device->IOBase)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "IOBase 0x%08lX doesn't match any PCI base register.\n", + pRiva->pEnt->device->IOBase); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + pRiva->IOAddress = pRiva->pEnt->device->IOBase; + from = X_CONFIG; + } else { + int i = 0; + if (pRiva->PciInfo->memBase[i] != 0) { + pRiva->IOAddress = pRiva->PciInfo->memBase[i] & 0xffffc000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid MMIO address in PCI config space\n"); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", + (unsigned long)pRiva->IOAddress); + + if (xf86RegisterResources(pRiva->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + + Riva3Setup(pScrn); + + /* + * If the user has specified the amount of memory in the XF86Config + * file, we respect that setting. + */ + if (pRiva->pEnt->device->videoRam != 0) { + pScrn->videoRam = pRiva->pEnt->device->videoRam; + from = X_CONFIG; + } else { + if (pRiva->FBDev) { + pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024; + } else { + pScrn->videoRam = pRiva->riva.RamAmountKBytes; + } + from = X_PROBED; + } + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kBytes\n", + pScrn->videoRam); + + pRiva->FbMapSize = pScrn->videoRam * 1024; + + /* + * If the driver can do gamma correction, it should call xf86SetGamma() + * here. + */ + + { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) { + xf86FreeInt10(pRiva->pInt); + return FALSE; + } + } + + pRiva->FbUsableSize = pRiva->FbMapSize - (32 * 1024); + + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + + pRiva->MinClock = 12000; + pRiva->MaxClock = pRiva->riva.MaxVClockFreqKHz; + + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = pRiva->MinClock; + clockRanges->maxClock = pRiva->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = TRUE; + + + /* + * xf86ValidateModes will check that the mode HTotal and VTotal values + * don't exceed the chipset's limit if pScrn->maxHValue and + * pScrn->maxVValue are set. Since our RivaValidMode() already takes + * care of this, we don't worry about setting them here. + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 2048, + 32 * pScrn->bitsPerPixel, 128, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, + pRiva->FbUsableSize, + LOOKUP_BEST_REFRESH); + + if (i < 1 && pRiva->FBDev) { + fbdevHWUseBuildinMode(pScrn); + pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */ + i = 1; + } + if (i == -1) { + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + + /* + * Set the CRTC parameters for all of the modes based on the type + * of mode, and the chipset's interlace requirements. + * + * Calling this is required if the mode->Crtc* values are used by the + * driver and if the driver doesn't provide code to set them. They + * are not pre-initialised at all. + */ + xf86SetCrtcForModes(pScrn, 0); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + + /* + * XXX This should be taken into account in some way in the mode valdation + * section. + */ + + if (xf86LoadSubModule(pScrn, "fb") == NULL) { + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(fbSymbols, NULL); + + /* Load XAA if needed */ + if (!pRiva->NoAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + /* Load ramdac if needed */ + if (pRiva->HWCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + /* Load shadowfb if needed */ + if (pRiva->ShadowFB) { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + xf86FreeInt10(pRiva->pInt); + RivaFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + pRiva->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; + pRiva->CurrentLayout.depth = pScrn->depth; + pRiva->CurrentLayout.displayWidth = pScrn->displayWidth; + pRiva->CurrentLayout.weight.red = pScrn->weight.red; + pRiva->CurrentLayout.weight.green = pScrn->weight.green; + pRiva->CurrentLayout.weight.blue = pScrn->weight.blue; + pRiva->CurrentLayout.mode = pScrn->currentMode; + + xf86FreeInt10(pRiva->pInt); + + pRiva->pInt = NULL; + return TRUE; +} + + +/* + * Map the framebuffer and MMIO memory. + */ + +static Bool +RivaMapMem(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva; + + pRiva = RivaPTR(pScrn); + + /* + * Map IO registers to virtual address space + */ + pRiva->IOBase = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, + pRiva->PciTag, pRiva->IOAddress, 0x1000000); + if (pRiva->IOBase == NULL) + return FALSE; + + pRiva->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pRiva->PciTag, pRiva->FbAddress, + pRiva->FbMapSize); + if (pRiva->FbBase == NULL) + return FALSE; + + pRiva->FbStart = pRiva->FbBase; + + return TRUE; +} + +Bool +RivaMapMemFBDev(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva; + + pRiva = RivaPTR(pScrn); + + pRiva->FbBase = fbdevHWMapVidmem(pScrn); + if (pRiva->FbBase == NULL) + return FALSE; + + pRiva->IOBase = fbdevHWMapMMIO(pScrn); + if (pRiva->IOBase == NULL) + return FALSE; + + pRiva->FbStart = pRiva->FbBase; + + return TRUE; +} + +/* + * Unmap the framebuffer and MMIO memory. + */ + +static Bool +RivaUnmapMem(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva; + + pRiva = RivaPTR(pScrn); + + /* + * Unmap IO registers to virtual address space + */ + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pRiva->IOBase, 0x1000000); + pRiva->IOBase = NULL; + + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pRiva->FbBase, pRiva->FbMapSize); + pRiva->FbBase = NULL; + pRiva->FbStart = NULL; + + return TRUE; +} + + +/* + * Initialise a new mode. + */ + +static Bool +RivaModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg; + RivaPtr pRiva = RivaPTR(pScrn); + RivaRegPtr rivaReg; + + + /* Initialise the ModeReg values */ + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + + vgaReg = &hwp->ModeReg; + rivaReg = &pRiva->ModeReg; + + if(!(*pRiva->ModeInit)(pScrn, mode)) + return FALSE; + + pRiva->riva.LockUnlock(&pRiva->riva, 0); + + /* Program the registers */ + vgaHWProtect(pScrn, TRUE); + + (*pRiva->Restore)(pScrn, vgaReg, rivaReg, FALSE); + + RivaResetGraphics(pScrn); + + vgaHWProtect(pScrn, FALSE); + + pRiva->CurrentLayout.mode = mode; + + return TRUE; +} + +/* + * Restore the initial (text) mode. + */ +static void +RivaRestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + RivaPtr pRiva = RivaPTR(pScrn); + RivaRegPtr rivaReg = &pRiva->SavedReg; + + + pRiva->riva.LockUnlock(&pRiva->riva, 0); + + /* Only restore text mode fonts/text for the primary card */ + vgaHWProtect(pScrn, TRUE); + (*pRiva->Restore)(pScrn, vgaReg, rivaReg, pRiva->Primary); + vgaHWProtect(pScrn, FALSE); +} + +static void +RivaDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + unsigned char crtc1A; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (!pScrn->vtSema) return; + + crtc1A = hwp->readCrtc(hwp, 0x1A) & ~0xC0; + + switch (PowerManagementMode) { + case DPMSModeStandby: /* HSync: Off, VSync: On */ + crtc1A |= 0x80; + break; + case DPMSModeSuspend: /* HSync: On, VSync: Off */ + crtc1A |= 0x40; + break; + case DPMSModeOff: /* HSync: Off, VSync: Off */ + crtc1A |= 0xC0; + break; + case DPMSModeOn: /* HSync: On, VSync: On */ + default: + break; + } + + /* vgaHWDPMSSet will merely cut the dac output */ + vgaHWDPMSSet(pScrn, PowerManagementMode, flags); + + hwp->writeCrtc(hwp, 0x1A, crtc1A); +} + + +/* Mandatory */ + +/* This gets called at the start of each server generation */ + +static Bool +RivaScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + RivaPtr pRiva; + RivaRamdacPtr Rivadac; + int ret; + VisualPtr visual; + unsigned char *FBStart; + int width, height, displayWidth; + BoxRec AvailFBArea; + + /* + * First get the ScrnInfoRec + */ + pScrn = xf86Screens[pScreen->myNum]; + + + hwp = VGAHWPTR(pScrn); + pRiva = RivaPTR(pScrn); + Rivadac = &pRiva->Dac; + + /* Map the Riva memory and MMIO areas */ + if (pRiva->FBDev) { + if (!RivaMapMemFBDev(pScrn)) + return FALSE; + } else { + if (!RivaMapMem(pScrn)) + return FALSE; + } + + /* Map the VGA memory when the primary video */ + if (pRiva->Primary && !pRiva->FBDev) { + hwp->MapSize = 0x10000; + if (!vgaHWMapMem(pScrn)) + return FALSE; + } + + if (pRiva->FBDev) { + fbdevHWSave(pScrn); + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) + return FALSE; + } else { + /* Save the current state */ + RivaSave(pScrn); + /* Initialise the first mode */ + if (!RivaModeInit(pScrn, pScrn->currentMode)) + return FALSE; + } + + + /* Darken the screen for aesthetic reasons and set the viewport */ + RivaSaveScreen(pScreen, SCREEN_SAVER_ON); + pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + * For most PC hardware at depths >= 8, the defaults that cfb uses + * are not appropriate. In this driver, we fixup the visuals after. + */ + + /* + * Reset the visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 8, + pScrn->defaultVisual)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), 8, + pScrn->defaultVisual)) + return FALSE; + } + if (!miSetPixmapDepths ()) return FALSE; + + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + + width = pScrn->virtualX; + height = pScrn->virtualY; + displayWidth = pScrn->displayWidth; + + + if(pRiva->Rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } + + if(pRiva->ShadowFB) { + pRiva->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + pRiva->ShadowPtr = xalloc(pRiva->ShadowPitch * height); + displayWidth = pRiva->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FBStart = pRiva->ShadowPtr; + } else { + pRiva->ShadowPtr = NULL; + FBStart = pRiva->FbStart; + } + + switch (pScrn->bitsPerPixel) { + case 8: + case 16: + case 32: + ret = fbScreenInit(pScreen, FBStart, width, height, + pScrn->xDpi, pScrn->yDpi, + displayWidth, pScrn->bitsPerPixel); + break; + default: + xf86DrvMsg(scrnIndex, X_ERROR, + "Internal error: invalid bpp (%d) in RivaScreenInit\n", + pScrn->bitsPerPixel); + ret = FALSE; + break; + } + if (!ret) + return FALSE; + + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + fbPictureInit (pScreen, 0, 0); + + xf86SetBlackWhitePixels(pScreen); + + + if(!pRiva->ShadowFB) /* hardware cursor needs to wrap this layer */ + RivaDGAInit(pScreen); + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (min(pRiva->FbUsableSize, 32*1024*1024)) / + (pScrn->displayWidth * pScrn->bitsPerPixel / 8); + xf86InitFBManager(pScreen, &AvailFBArea); + + if (!pRiva->NoAccel) + RivaAccelInit(pScreen); + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + + /* Initialize software cursor. + Must precede creation of the default colormap */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + + /* Initialize HW cursor layer. + Must follow software cursor initialization*/ + if (pRiva->HWCursor) { + if(!RivaCursorInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + } + + /* Initialise default colourmap */ + if (!miCreateDefColormap(pScreen)) + return FALSE; + + + /* Initialize colormap layer. + Must follow initialization of the default colormap */ + if(!xf86HandleColormaps(pScreen, 256, 8, + (pRiva->FBDev ? fbdevHWLoadPalette : Rivadac->LoadPalette), + NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) + return FALSE; + + + if(pRiva->ShadowFB) { + RefreshAreaFuncPtr refreshArea = RivaRefreshArea; + + if(pRiva->Rotate) { + pRiva->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RivaPointerMoved; + + switch(pScrn->bitsPerPixel) { + case 8: refreshArea = RivaRefreshArea8; break; + case 16: refreshArea = RivaRefreshArea16; break; + case 32: refreshArea = RivaRefreshArea32; break; + } + } + + ShadowFBInit(pScreen, refreshArea); + } + + xf86DPMSInit(pScreen, RivaDPMSSet, 0); + + + pScrn->memPhysBase = pRiva->FbAddress; + pScrn->fbOffset = 0; + + pScreen->SaveScreen = RivaSaveScreen; + + /* Wrap the current CloseScreen function */ + pRiva->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = RivaCloseScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + /* Done */ + return TRUE; +} + +/* Free up any persistent data structures */ + + +/* Do screen blanking */ + +/* Mandatory */ +static Bool +RivaSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + +static void +RivaSave(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + RivaRegPtr rivaReg = &pRiva->SavedReg; + vgaHWPtr pVga = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &pVga->SavedReg; + + (*pRiva->Save)(pScrn, vgaReg, rivaReg, pRiva->Primary); +} + diff --git a/src/riva_include.h b/src/riva_include.h new file mode 100644 index 0000000..e64d78f --- /dev/null +++ b/src/riva_include.h @@ -0,0 +1,59 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_include.h,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#ifndef __RIVA_INCLUDE_H__ +#define __RIVA_INCLUDE_H__ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +/* All drivers implementing backing store need this */ +#include "mibstore.h" + +#include "micmap.h" + +#include "xf86DDC.h" + +#include "vbe.h" + +#include "xf86RAC.h" + +#include "riva_const.h" + +#include "dixstruct.h" +#include "scrnintstr.h" + +#include "fb.h" + +#include "xaa.h" +#include "xf86cmap.h" +#include "shadowfb.h" +#include "fbdevhw.h" + +#include "xf86xv.h" +#include "Xv.h" + +#include "vgaHW.h" + +#include "xf86Cursor.h" +#include "xf86DDC.h" + +#include "region.h" + +#include "riva_local.h" +#include "riva_type.h" +#include "riva_proto.h" + +#endif /* __RIVA_INCLUDE_H__ */ diff --git a/src/riva_local.h b/src/riva_local.h new file mode 100644 index 0000000..efe0c7e --- /dev/null +++ b/src/riva_local.h @@ -0,0 +1,74 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING 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 SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_local.h,v 1.2 2003/11/03 05:11:26 tsi Exp $ */ + +#ifndef __RIVA_LOCAL_H__ +#define __RIVA_LOCAL_H__ + +/* + * This file includes any environment or machine specific values to access the + * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files + * can stay generic in nature. + */ +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86_OSproc.h" + +/* + * Typedefs to force certain sized values. + */ +typedef unsigned char U008; +typedef unsigned short U016; +typedef unsigned int U032; + +/* + * HW access macros. These assume memory-mapped I/O, and not normal I/O space. + */ +#define RIVA_WR08(p,i,d) MMIO_OUT8((pointer)(p), (i), (d)) +#define RIVA_RD08(p,i) MMIO_IN8((pointer)(p), (i)) +#define RIVA_WR16(p,i,d) MMIO_OUT16((pointer)(p), (i), (d)) +#define RIVA_RD16(p,i) MMIO_IN16((pointer)(p), (i)) +#define RIVA_WR32(p,i,d) MMIO_OUT32((pointer)(p), (i), (d)) +#define RIVA_RD32(p,i) MMIO_IN32((pointer)(p), (i)) + +/* VGA I/O is now always done through MMIO */ +#define VGA_WR08(p,i,d) RIVA_WR08(p,i,d) +#define VGA_RD08(p,i) RIVA_RD08(p,i) + +#endif /* __RIVA_LOCAL_H__ */ diff --git a/src/riva_proto.h b/src/riva_proto.h new file mode 100644 index 0000000..75f5d01 --- /dev/null +++ b/src/riva_proto.h @@ -0,0 +1,41 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_proto.h,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#ifndef __RIVA_PROTO_H__ +#define __RIVA_PROTO_H__ + +/* in riva_driver.c */ +Bool RivaSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +void RivaAdjustFrame(int scrnIndex, int x, int y, int flags); +Bool RivaI2CInit(ScrnInfoPtr pScrn); +const OptionInfoRec * RivaAvailableOptions(int chipid, int busid); +Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip); + +/* in riva_dac.c */ +Bool RivaDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +void RivaDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, + RivaRegPtr rivaReg, Bool saveFonts); +void RivaDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, + RivaRegPtr rivaReg, Bool restoreFonts); +void RivaDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual ); +Bool RivaDACi2cInit(ScrnInfoPtr pScrn); + + +/* in riva_setup.c */ +void RivaEnterLeave(ScrnInfoPtr pScrn, Bool enter); +void Riva3Setup(ScrnInfoPtr pScrn); + +/* in riva_cursor.c */ +Bool RivaCursorInit(ScreenPtr pScreen); + +/* in riva_xaa.c */ +Bool RivaAccelInit(ScreenPtr pScreen); +void RivaSync(ScrnInfoPtr pScrn); +void RivaResetGraphics(ScrnInfoPtr pScrn); + +/* in riva_dga.c */ +Bool RivaDGAInit(ScreenPtr pScreen); + + +#endif /* __RIVA_PROTO_H__ */ + diff --git a/src/riva_setup.c b/src/riva_setup.c new file mode 100644 index 0000000..6a0d32e --- /dev/null +++ b/src/riva_setup.c @@ -0,0 +1,279 @@ +/* + * Copyright 1996-1997 David J. McKay + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_setup.c,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#include "riva_include.h" + +/* + * Override VGA I/O routines. + */ +static void RivaWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); + VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET, value); +} +static CARD8 RivaReadCrtc(vgaHWPtr pVga, CARD8 index) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); + return (VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET)); +} +static void RivaWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_INDEX, index); + VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_DATA, value); +} +static CARD8 RivaReadGr(vgaHWPtr pVga, CARD8 index) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_INDEX, index); + return (VGA_RD08(pRiva->riva.PVIO, VGA_GRAPH_DATA)); +} +static void RivaWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_INDEX, index); + VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_DATA, value); +} +static CARD8 RivaReadSeq(vgaHWPtr pVga, CARD8 index) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_INDEX, index); + return (VGA_RD08(pRiva->riva.PVIO, VGA_SEQ_DATA)); +} +static void RivaWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + if (pVga->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, index); + VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_DATA_W, value); +} +static CARD8 RivaReadAttr(vgaHWPtr pVga, CARD8 index) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + if (pVga->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, index); + return (VGA_RD08(pRiva->riva.PCIO, VGA_ATTR_DATA_R)); +} +static void RivaWriteMiscOut(vgaHWPtr pVga, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PVIO, VGA_MISC_OUT_W, value); +} +static CARD8 RivaReadMiscOut(vgaHWPtr pVga) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + return (VGA_RD08(pRiva->riva.PVIO, VGA_MISC_OUT_R)); +} +static void RivaEnablePalette(vgaHWPtr pVga) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, 0x00); + pVga->paletteEnabled = TRUE; +} +static void RivaDisablePalette(vgaHWPtr pVga) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, 0x20); + pVga->paletteEnabled = FALSE; +} +static void RivaWriteDacMask(vgaHWPtr pVga, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PDIO, VGA_DAC_MASK, value); +} +static CARD8 RivaReadDacMask(vgaHWPtr pVga) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + return (VGA_RD08(pRiva->riva.PDIO, VGA_DAC_MASK)); +} +static void RivaWriteDacReadAddr(vgaHWPtr pVga, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PDIO, VGA_DAC_READ_ADDR, value); +} +static void RivaWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PDIO, VGA_DAC_WRITE_ADDR, value); +} +static void RivaWriteDacData(vgaHWPtr pVga, CARD8 value) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + VGA_WR08(pRiva->riva.PDIO, VGA_DAC_DATA, value); +} +static CARD8 RivaReadDacData(vgaHWPtr pVga) +{ + RivaPtr pRiva = (RivaPtr)pVga->MMIOBase; + return (VGA_RD08(pRiva->riva.PDIO, VGA_DAC_DATA)); +} + + + +static xf86MonPtr +RivaProbeDDC (ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + xf86MonPtr MonInfo = NULL; + + if(!pRiva->I2C) return NULL; + + pRiva->DDCBase = 0x3e; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for EDID...\n"); + + if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pRiva->I2C))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " ... found one\n"); + xf86PrintEDID( MonInfo ); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " ... none found\n"); + } + + return MonInfo; +} + +void +Riva3Setup(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + vgaHWPtr pVga = VGAHWPTR(pScrn); + CARD32 regBase = pRiva->IOAddress; + CARD32 frameBase = pRiva->FbAddress; + xf86MonPtr monitor; + int mmioFlags; + + pRiva->Save = RivaDACSave; + pRiva->Restore = RivaDACRestore; + pRiva->ModeInit = RivaDACInit; + + pRiva->Dac.LoadPalette = RivaDACLoadPalette; + + /* + * Override VGA I/O routines. + */ + pVga->writeCrtc = RivaWriteCrtc; + pVga->readCrtc = RivaReadCrtc; + pVga->writeGr = RivaWriteGr; + pVga->readGr = RivaReadGr; + pVga->writeAttr = RivaWriteAttr; + pVga->readAttr = RivaReadAttr; + pVga->writeSeq = RivaWriteSeq; + pVga->readSeq = RivaReadSeq; + pVga->writeMiscOut = RivaWriteMiscOut; + pVga->readMiscOut = RivaReadMiscOut; + pVga->enablePalette = RivaEnablePalette; + pVga->disablePalette = RivaDisablePalette; + pVga->writeDacMask = RivaWriteDacMask; + pVga->readDacMask = RivaReadDacMask; + pVga->writeDacWriteAddr = RivaWriteDacWriteAddr; + pVga->writeDacReadAddr = RivaWriteDacReadAddr; + pVga->writeDacData = RivaWriteDacData; + pVga->readDacData = RivaReadDacData; + /* + * Note: There are different pointers to the CRTC/AR and GR/SEQ registers. + * Bastardize the intended uses of these to make it work. + */ + pVga->MMIOBase = (CARD8 *)pRiva; + pVga->MMIOOffset = 0; + + /* + * No IRQ in use. + */ + pRiva->riva.EnableIRQ = 0; + pRiva->riva.IO = VGA_IOBASE_COLOR; + + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + + pRiva->riva.PRAMDAC = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00680000, 0x00003000); + pRiva->riva.PFB = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00100000, 0x00001000); + pRiva->riva.PFIFO = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00002000, 0x00002000); + pRiva->riva.PGRAPH = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00400000, 0x00002000); + pRiva->riva.PEXTDEV = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00101000, 0x00001000); + pRiva->riva.PTIMER = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00009000, 0x00001000); + pRiva->riva.PMC = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00000000, 0x00009000); + pRiva->riva.FIFO = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + regBase+0x00800000, 0x00010000); + pRiva->riva.PRAMIN = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pRiva->PciTag, + frameBase+0x00C00000, 0x00008000); + + /* + * These registers are read/write as 8 bit values. Probably have to map + * sparse on alpha. + */ + pRiva->riva.PCIO = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pRiva->PciTag, regBase+0x00601000, + 0x00003000); + pRiva->riva.PDIO = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pRiva->PciTag, regBase+0x00681000, + 0x00003000); + pRiva->riva.PVIO = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pRiva->PciTag, regBase+0x000C0000, + 0x00001000); + + pRiva->riva.PCRTC = pRiva->riva.PGRAPH; + + RivaGetConfig(pRiva); + + pRiva->riva.LockUnlock(&pRiva->riva, 0); + + RivaI2CInit(pScrn); + + monitor = RivaProbeDDC(pScrn); + + if(monitor) + xf86SetDDCproperties(pScrn, monitor); + + pRiva->Dac.maxPixelClock = pRiva->riva.MaxVClockFreqKHz; +} diff --git a/src/riva_shadow.c b/src/riva_shadow.c new file mode 100644 index 0000000..90f1f12 --- /dev/null +++ b/src/riva_shadow.c @@ -0,0 +1,194 @@ +/* + Copyright (c) 1999, The XFree86 Project Inc. + Written by Mark Vojkovich +*/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_shadow.c,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#include "riva_local.h" +#include "riva_include.h" +#include "riva_type.h" +#include "shadowfb.h" +#include "servermd.h" + + +void +RivaRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + RivaPtr pRiva = RivaPTR(pScrn); + int width, height, Bpp, FBPitch; + unsigned char *src, *dst; + + Bpp = pScrn->bitsPerPixel >> 3; + FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); + + while(num--) { + width = (pbox->x2 - pbox->x1) * Bpp; + height = pbox->y2 - pbox->y1; + src = pRiva->ShadowPtr + (pbox->y1 * pRiva->ShadowPitch) + + (pbox->x1 * Bpp); + dst = pRiva->FbStart + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); + + while(height--) { + memcpy(dst, src, width); + dst += FBPitch; + src += pRiva->ShadowPitch; + } + + pbox++; + } +} + +void +RivaPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + RivaPtr pRiva = RivaPTR(pScrn); + int newX, newY; + + if(pRiva->Rotate == 1) { + newX = pScrn->pScreen->height - y - 1; + newY = x; + } else { + newX = y; + newY = pScrn->pScreen->width - x - 1; + } + + (*pRiva->PointerMoved)(index, newX, newY); +} + +void +RivaRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + RivaPtr pRiva = RivaPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pRiva->Rotate * pRiva->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* in dwords */ + + if(pRiva->Rotate == 1) { + dstPtr = pRiva->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = pRiva->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = pRiva->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = pRiva->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 8) | + (src[srcPitch * 2] << 16) | + (src[srcPitch * 3] << 24); + src += srcPitch * 4; + } + srcPtr += pRiva->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +RivaRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + RivaPtr pRiva = RivaPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD16 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pRiva->Rotate * pRiva->ShadowPitch >> 1; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~1; + y2 = (pbox->y2 + 1) & ~1; + height = (y2 - y1) >> 1; /* in dwords */ + + if(pRiva->Rotate == 1) { + dstPtr = (CARD16*)pRiva->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = (CARD16*)pRiva->ShadowPtr + + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD16*)pRiva->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = (CARD16*)pRiva->ShadowPtr + + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 16); + src += srcPitch * 2; + } + srcPtr += pRiva->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +RivaRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + RivaPtr pRiva = RivaPTR(pScrn); + int count, width, height, dstPitch, srcPitch; + CARD32 *dstPtr, *srcPtr, *src, *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pRiva->Rotate * pRiva->ShadowPitch >> 2; + + while(num--) { + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + if(pRiva->Rotate == 1) { + dstPtr = (CARD32*)pRiva->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; + srcPtr = (CARD32*)pRiva->ShadowPtr + + ((1 - pbox->y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD32*)pRiva->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; + srcPtr = (CARD32*)pRiva->ShadowPtr + + (pbox->y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = dstPtr; + count = height; + while(count--) { + *(dst++) = *src; + src += srcPitch; + } + srcPtr += pRiva->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + + diff --git a/src/riva_type.h b/src/riva_type.h new file mode 100644 index 0000000..7913128 --- /dev/null +++ b/src/riva_type.h @@ -0,0 +1,122 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_type.h,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#ifndef __Riva_STRUCT_H__ +#define __Riva_STRUCT_H__ + +#include "riva_hw.h" +#include "colormapst.h" +#include "vgaHW.h" +#include "xaa.h" +#include "xf86Cursor.h" +#include "xf86int10.h" + + +#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) +#define MASKEXPAND(mask) BITMASK(1?mask,0?mask) +#define SetBF(mask,value) ((value) << (0?mask)) +#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) +#define SetBitField(value,from,to) SetBF(to, GetBF(value,from)) +#define SetBit(n) (1<<(n)) +#define Set8Bits(value) ((value)&0xff) + +typedef RIVA_HW_STATE* RivaRegPtr; + +typedef struct { + Bool isHwCursor; + int CursorMaxWidth; + int CursorMaxHeight; + int CursorFlags; + int CursorOffscreenMemSize; + Bool (*UseHWCursor)(ScreenPtr, CursorPtr); + void (*LoadCursorImage)(ScrnInfoPtr, unsigned char*); + void (*ShowCursor)(ScrnInfoPtr); + void (*HideCursor)(ScrnInfoPtr); + void (*SetCursorPosition)(ScrnInfoPtr, int, int); + void (*SetCursorColors)(ScrnInfoPtr, int, int); + long maxPixelClock; + void (*LoadPalette)(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); + void (*Save)(ScrnInfoPtr, vgaRegPtr, RivaRegPtr, Bool); + void (*Restore)(ScrnInfoPtr, vgaRegPtr, RivaRegPtr, Bool); + Bool (*ModeInit)(ScrnInfoPtr, DisplayModePtr); +} RivaRamdacRec, *RivaRamdacPtr; + +typedef struct { + int bitsPerPixel; + int depth; + int displayWidth; + rgb weight; + DisplayModePtr mode; +} RivaFBLayout; + +typedef struct { + RIVA_HW_INST riva; + RIVA_HW_STATE SavedReg; + RIVA_HW_STATE ModeReg; + EntityInfoPtr pEnt; + pciVideoPtr PciInfo; + PCITAG PciTag; + xf86AccessRec Access; + int ChipRev; + Bool Primary; + CARD32 IOAddress; + unsigned long FbAddress; + int FbBaseReg; + unsigned char * IOBase; + unsigned char * FbBase; + unsigned char * FbStart; + long FbMapSize; + long FbUsableSize; + RivaRamdacRec Dac; + Bool NoAccel; + Bool HWCursor; + Bool ShowCache; + Bool ShadowFB; + unsigned char * ShadowPtr; + int ShadowPitch; + int MinClock; + int MaxClock; + XAAInfoRecPtr AccelInfoRec; + xf86CursorInfoPtr CursorInfoRec; + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + void (*Save)(ScrnInfoPtr, vgaRegPtr, RivaRegPtr, Bool); + void (*Restore)(ScrnInfoPtr, vgaRegPtr, RivaRegPtr, Bool); + Bool (*ModeInit)(ScrnInfoPtr, DisplayModePtr); + void (*PointerMoved)(int index, int x, int y); + CloseScreenProcPtr CloseScreen; + Bool FBDev; + /* Color expansion */ + unsigned char *expandBuffer; + unsigned char *expandFifo; + int expandWidth; + int expandRows; + CARD32 FgColor; + CARD32 BgColor; + int Rotate; + RivaFBLayout CurrentLayout; + /* Cursor */ + CARD32 curFg, curBg; + CARD32 curImage[64]; + /* Misc flags */ + unsigned int opaqueMonochrome; + int currentRop; + /* I2C / DDC */ + I2CBusPtr I2C; + xf86Int10InfoPtr pInt; + OptionInfoPtr Options; + unsigned char DDCBase; +} RivaRec, *RivaPtr; + +#define RivaPTR(p) ((RivaPtr)((p)->driverPrivate)) + +void RivaRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void RivaRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void RivaRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void RivaRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void RivaPointerMoved(int index, int x, int y); + +int RivaGetConfig(RivaPtr); + +#endif /* __Riva_STRUCT_H__ */ diff --git a/src/riva_xaa.c b/src/riva_xaa.c new file mode 100644 index 0000000..240e9ec --- /dev/null +++ b/src/riva_xaa.c @@ -0,0 +1,554 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING 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 SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + +/* Hacked together from mga driver and 3.3.4 NVIDIA driver by + Jarno Paananen */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_xaa.c,v 1.1 2003/07/31 20:24:31 mvojkovi Exp $ */ + +#include "riva_include.h" +#include "xaalocal.h" +#include "xaarop.h" + +#include "miline.h" + +static void +RivaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + int height = y2-y1 + 1; + int width = x2-x1 + 1; + RivaPtr pRiva = RivaPTR(pScrn); + + RIVA_FIFO_FREE(pRiva->riva, Clip, 2); + pRiva->riva.Clip->TopLeft = (y1 << 16) | (x1 & 0xffff); + pRiva->riva.Clip->WidthHeight = (height << 16) | width; +} + + +static void +RivaDisableClipping(ScrnInfoPtr pScrn) +{ + RivaSetClippingRectangle(pScrn, 0, 0, 0x7fff, 0x7fff); +} + +/* + * Set pattern. Internal routine. The upper bits of the colors + * are the ALPHA bits. 0 == transparency. + */ +static void +RivaSetPattern(RivaPtr pRiva, int clr0, int clr1, int pat0, int pat1) +{ + RIVA_FIFO_FREE(pRiva->riva, Patt, 4); + pRiva->riva.Patt->Color0 = clr0; + pRiva->riva.Patt->Color1 = clr1; + pRiva->riva.Patt->Monochrome[0] = pat0; + pRiva->riva.Patt->Monochrome[1] = pat1; +} + +/* + * Set ROP. Translate X rop into ROP3. Internal routine. + */ +static void +RivaSetRopSolid(RivaPtr pRiva, int rop) +{ + if (pRiva->currentRop != rop) { + if (pRiva->currentRop >= 16) + RivaSetPattern(pRiva, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + pRiva->currentRop = rop; + RIVA_FIFO_FREE(pRiva->riva, Rop, 1); + pRiva->riva.Rop->Rop3 = XAACopyROP[rop]; + } +} + +static void +RivaSetRopPattern(RivaPtr pRiva, int rop) +{ + if (pRiva->currentRop != (rop + 16)) { + pRiva->currentRop = rop + 16; /* +16 is important */ + RIVA_FIFO_FREE(pRiva->riva, Rop, 1); + pRiva->riva.Rop->Rop3 = XAAPatternROP[rop]; + } +} + +/* + * Fill solid rectangles. + */ +static +void RivaSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned planemask) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RivaSetRopSolid(pRiva, rop); + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1); + pRiva->riva.Bitmap->Color1A = color; +} + +static void +RivaSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2); + pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; + write_mem_barrier(); + pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; + write_mem_barrier(); +} + +/* + * Screen to screen BLTs. + */ +static void +RivaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned planemask, int transparency_color) +{ + RivaSetRopSolid(RivaPTR(pScrn), rop); +} + +static void +RivaSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RIVA_FIFO_FREE(pRiva->riva, Blt, 3); + pRiva->riva.Blt->TopLeftSrc = (y1 << 16) | x1; + pRiva->riva.Blt->TopLeftDst = (y2 << 16) | x2; + write_mem_barrier(); + pRiva->riva.Blt->WidthHeight = (h << 16) | w; + write_mem_barrier(); +} + + +/* + * Fill 8x8 monochrome pattern rectangles. patternx and patterny are + * the overloaded pattern bits themselves. The pattern colors don't + * support 565, only 555. Hack around it. + */ +static void +RivaSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, + int fg, int bg, int rop, unsigned planemask) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RivaSetRopPattern(pRiva, rop); + if (pScrn->depth == 16) + { + fg = ((fg & 0x0000F800) << 8) + | ((fg & 0x000007E0) << 5) + | ((fg & 0x0000001F) << 3) + | 0xFF000000; + if (bg != -1) + bg = ((bg & 0x0000F800) << 8) + | ((bg & 0x000007E0) << 5) + | ((bg & 0x0000001F) << 3) + | 0xFF000000; + else + bg = 0; + } + else + { + fg |= pRiva->opaqueMonochrome; + bg = (bg == -1) ? 0 : bg | pRiva->opaqueMonochrome; + }; + RivaSetPattern(pRiva, bg, fg, patternx, patterny); + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1); + pRiva->riva.Bitmap->Color1A = fg; +} + +static void +RivaSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, int w, int h) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2); + pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; + write_mem_barrier(); + pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; + write_mem_barrier(); +} + + +void +RivaResetGraphics(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + if(pRiva->NoAccel) return; + + RIVA_FIFO_FREE(pRiva->riva, Patt, 1); + pRiva->riva.Patt->Shape = 0; + RivaDisableClipping(pScrn); + pRiva->currentRop = 16; /* to force RivaSetRopSolid to reset the pattern */ + RivaSetRopSolid(pRiva, GXcopy); +} + + + +/* + * Synchronise with graphics engine. Make sure it is idle before returning. + * Should attempt to yield CPU if busy for awhile. + */ +void RivaSync(ScrnInfoPtr pScrn) +{ + RivaPtr pRiva = RivaPTR(pScrn); + RIVA_BUSY(pRiva->riva); +} + +/* Color expansion */ +static void +RivaSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RivaSetRopSolid(pRiva, rop); + + if ( bg == -1 ) + { + /* Transparent case */ + bg = 0x80000000; + pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData1C; + } + else + { + pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E; + if (pScrn->depth == 16) + { + bg = ((bg & 0x0000F800) << 8) + | ((bg & 0x000007E0) << 5) + | ((bg & 0x0000001F) << 3) + | 0xFF000000; + } + else + { + bg |= pRiva->opaqueMonochrome; + }; + } + pRiva->FgColor = fg; + pRiva->BgColor = bg; +} + +static void +RivaSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + int t = pRiva->expandWidth; + CARD32 *pbits = (CARD32*)pRiva->expandBuffer; + CARD32 *d = (CARD32*)pRiva->expandFifo; + + while(t >= 16) + { + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 16); + d[0] = pbits[0]; + d[1] = pbits[1]; + d[2] = pbits[2]; + d[3] = pbits[3]; + d[4] = pbits[4]; + d[5] = pbits[5]; + d[6] = pbits[6]; + d[7] = pbits[7]; + d[8] = pbits[8]; + d[9] = pbits[9]; + d[10] = pbits[10]; + d[11] = pbits[11]; + d[12] = pbits[12]; + d[13] = pbits[13]; + d[14] = pbits[14]; + d[15] = pbits[15]; + t -= 16; pbits += 16; + } + if(t) { + RIVA_FIFO_FREE(pRiva->riva, Bitmap, t); + while(t >= 4) + { + d[0] = pbits[0]; + d[1] = pbits[1]; + d[2] = pbits[2]; + d[3] = pbits[3]; + t -= 4; pbits += 4; + } + while(t--) + *(d++) = *(pbits++); + } + + if (!(--pRiva->expandRows)) { /* hardware bug workaround */ + RIVA_FIFO_FREE(pRiva->riva, Blt, 1); + write_mem_barrier(); + pRiva->riva.Blt->TopLeftSrc = 0; + } + write_mem_barrier(); +} + +static void +RivaSubsequentColorExpandScanlineFifo(ScrnInfoPtr pScrn, int bufno) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + if ( --pRiva->expandRows ) { + RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth); + } else { /* hardware bug workaround */ + RIVA_FIFO_FREE(pRiva->riva, Blt, 1); + write_mem_barrier(); + pRiva->riva.Blt->TopLeftSrc = 0; + } + write_mem_barrier(); +} + +static void +RivaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, + int y, int w, int h, + int skipleft) +{ + int bw; + RivaPtr pRiva = RivaPTR(pScrn); + + bw = (w + 31) & ~31; + pRiva->expandWidth = bw >> 5; + + if ( pRiva->BgColor == 0x80000000 ) + { + /* Use faster transparent method */ + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 5); + pRiva->riva.Bitmap->ClipC.TopLeft = (y << 16) | ((x+skipleft) + & 0xFFFF); + pRiva->riva.Bitmap->ClipC.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); + pRiva->riva.Bitmap->Color1C = pRiva->FgColor; + pRiva->riva.Bitmap->WidthHeightC = (h << 16) | bw; + write_mem_barrier(); + pRiva->riva.Bitmap->PointC = (y << 16) | (x & 0xFFFF); + write_mem_barrier(); + } + else + { + /* Opaque */ + RIVA_FIFO_FREE(pRiva->riva, Bitmap, 7); + pRiva->riva.Bitmap->ClipE.TopLeft = (y << 16) | ((x+skipleft) + & 0xFFFF); + pRiva->riva.Bitmap->ClipE.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); + pRiva->riva.Bitmap->Color0E = pRiva->BgColor; + pRiva->riva.Bitmap->Color1E = pRiva->FgColor; + pRiva->riva.Bitmap->WidthHeightInE = (h << 16) | bw; + pRiva->riva.Bitmap->WidthHeightOutE = (h << 16) | bw; + write_mem_barrier(); + pRiva->riva.Bitmap->PointE = (y << 16) | (x & 0xFFFF); + write_mem_barrier(); + } + + pRiva->expandRows = h; + + if(pRiva->expandWidth > (pRiva->riva.FifoEmptyCount >> 2)) { + pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandBuffer; + pRiva->AccelInfoRec->SubsequentColorExpandScanline = + RivaSubsequentColorExpandScanline; + } else { + pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandFifo; + pRiva->AccelInfoRec->SubsequentColorExpandScanline = + RivaSubsequentColorExpandScanlineFifo; + RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth); + } +} + +static void +RivaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RivaSetRopSolid(pRiva, rop); + pRiva->FgColor = color; +} + +static void +RivaSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir) +{ + RivaPtr pRiva = RivaPTR(pScrn); + + RIVA_FIFO_FREE(pRiva->riva, Line, 3); + pRiva->riva.Line->Color = pRiva->FgColor; + pRiva->riva.Line->Lin[0].point0 = ((y << 16) | ( x & 0xffff)); + write_mem_barrier(); + if ( dir ==DEGREES_0 ) + pRiva->riva.Line->Lin[0].point1 = ((y << 16) | (( x + len ) & 0xffff)); + else + pRiva->riva.Line->Lin[0].point1 = (((y + len) << 16) | ( x & 0xffff)); + write_mem_barrier(); +} + +static void +RivaSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int flags) +{ + RivaPtr pRiva = RivaPTR(pScrn); + Bool lastPoint = !(flags & OMIT_LAST); + + RIVA_FIFO_FREE(pRiva->riva, Line, lastPoint ? 5 : 3); + pRiva->riva.Line->Color = pRiva->FgColor; + pRiva->riva.Line->Lin[0].point0 = ((y1 << 16) | (x1 & 0xffff)); + write_mem_barrier(); + pRiva->riva.Line->Lin[0].point1 = ((y2 << 16) | (x2 & 0xffff)); + write_mem_barrier(); + if (lastPoint) + { + pRiva->riva.Line->Lin[1].point0 = ((y2 << 16) | (x2 & 0xffff)); + write_mem_barrier(); + pRiva->riva.Line->Lin[1].point1 = (((y2 + 1) << 16) | (x2 & 0xffff)); + write_mem_barrier(); + } +} + +static void +RivaValidatePolyArc( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + if(pGC->planemask != ~0) return; + + if(!pGC->lineWidth && + ((pGC->alu != GXcopy) || (pGC->lineStyle != LineSolid))) + { + pGC->ops->PolyArc = miZeroPolyArc; + } +} + +static void +RivaValidatePolyPoint( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + pGC->ops->PolyPoint = XAAFallbackOps.PolyPoint; + + if(pGC->planemask != ~0) return; + + if(pGC->alu != GXcopy) + pGC->ops->PolyPoint = miPolyPoint; +} + +/* Initialize XAA acceleration info */ +Bool +RivaAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RivaPtr pRiva = RivaPTR(pScrn); + + pRiva->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if(!infoPtr) return FALSE; + + /* fill out infoPtr here */ + infoPtr->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS; + + /* sync */ + infoPtr->Sync = RivaSync; + + /* solid fills */ + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = RivaSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = RivaSubsequentSolidFillRect; + + /* screen to screen copy */ + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK; + infoPtr->SetupForScreenToScreenCopy = RivaSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = RivaSubsequentScreenToScreenCopy; + + /* 8x8 mono patterns */ + /* + * Set pattern opaque bits based on pixel format. + */ + pRiva->opaqueMonochrome = ~((1 << pScrn->depth) - 1); + + infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS | + NO_PLANEMASK; + infoPtr->SetupForMono8x8PatternFill = RivaSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + RivaSubsequentMono8x8PatternFillRect; + + /* Color expansion */ + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + BIT_ORDER_IN_BYTE_LSBFIRST | + NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + LEFT_EDGE_CLIPPING | + LEFT_EDGE_CLIPPING_NEGATIVE_X; + + infoPtr->NumScanlineColorExpandBuffers = 1; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + RivaSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + RivaSubsequentScanlineCPUToScreenColorExpandFill; + + pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E; + + /* Allocate buffer for color expansion and also image writes in the + future */ + pRiva->expandBuffer = xnfalloc(((pScrn->virtualX*pScrn->bitsPerPixel)/8) + 8); + + + infoPtr->ScanlineColorExpandBuffers = &pRiva->expandBuffer; + infoPtr->SubsequentColorExpandScanline = RivaSubsequentColorExpandScanline; + + infoPtr->SolidLineFlags = infoPtr->SolidFillFlags; + infoPtr->SetupForSolidLine = RivaSetupForSolidLine; + infoPtr->SubsequentSolidHorVertLine = + RivaSubsequentSolidHorVertLine; + infoPtr->SubsequentSolidTwoPointLine = + RivaSubsequentSolidTwoPointLine; + infoPtr->SetClippingRectangle = RivaSetClippingRectangle; + infoPtr->DisableClipping = RivaDisableClipping; + infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE; + miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6); + + infoPtr->ValidatePolyArc = RivaValidatePolyArc; + infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask; + infoPtr->ValidatePolyPoint = RivaValidatePolyPoint; + infoPtr->PolyPointMask = GCFunction | GCPlaneMask; + + RivaResetGraphics(pScrn); + + return(XAAInit(pScreen, infoPtr)); +} + -- cgit v1.2.3