g80_driver.c revision bd304fc0
1fc5a983dSmrg/*
271ba42d0Smrg * Copyright (c) 2007,2010 NVIDIA Corporation
3fc5a983dSmrg *
4fc5a983dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5fc5a983dSmrg * copy of this software and associated documentation files (the
6fc5a983dSmrg * "Software"), to deal in the Software without restriction, including
7fc5a983dSmrg * without limitation the rights to use, copy, modify, merge, publish,
8fc5a983dSmrg * distribute, sublicense, and/or sell copies of the Software, and to
9fc5a983dSmrg * permit persons to whom the Software is furnished to do so, subject to
10fc5a983dSmrg * the following conditions:
11fc5a983dSmrg *
12fc5a983dSmrg * The above copyright notice and this permission notice shall be included
13fc5a983dSmrg * in all copies or substantial portions of the Software.
14fc5a983dSmrg *
15fc5a983dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16fc5a983dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17fc5a983dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18fc5a983dSmrg * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19fc5a983dSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20fc5a983dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21fc5a983dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22fc5a983dSmrg */
23fc5a983dSmrg
24fc5a983dSmrg
25fc5a983dSmrg#ifdef HAVE_CONFIG_H
26fc5a983dSmrg#include "config.h"
27fc5a983dSmrg#endif
28fc5a983dSmrg
29fc5a983dSmrg#include <string.h>
30fc5a983dSmrg
3171ba42d0Smrg#include <xf86.h>
32fc5a983dSmrg#include <xf86_OSproc.h>
3371ba42d0Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
34fc5a983dSmrg#include <xf86Resources.h>
3571ba42d0Smrg#endif
36fc5a983dSmrg#include <mipointer.h>
37fc5a983dSmrg#include <mibstore.h>
38fc5a983dSmrg#include <micmap.h>
39fc5a983dSmrg#include <xf86cmap.h>
40fc5a983dSmrg#include <fb.h>
4171ba42d0Smrg#ifdef HAVE_XEXTPROTO_71
4271ba42d0Smrg#include <X11/extensions/dpmsconst.h>
4371ba42d0Smrg#else
44fc5a983dSmrg#define DPMS_SERVER
45fc5a983dSmrg#include <X11/extensions/dpms.h>
4671ba42d0Smrg#endif
4771ba42d0Smrg
4871ba42d0Smrg#include <xf86RandR12.h>
49fc5a983dSmrg
50fc5a983dSmrg#include "nv_const.h"
51fc5a983dSmrg#include "g80_type.h"
52fc5a983dSmrg#include "g80_cursor.h"
53fc5a983dSmrg#include "g80_display.h"
54fc5a983dSmrg#include "g80_dma.h"
55fc5a983dSmrg#include "g80_output.h"
56fc5a983dSmrg#include "g80_exa.h"
57fc5a983dSmrg#include "g80_xaa.h"
58fc5a983dSmrg
59fc5a983dSmrg#define G80_REG_SIZE (1024 * 1024 * 16)
6071ba42d0Smrg#define G80_RESERVED_VIDMEM 0xe000
61fc5a983dSmrg
62fc5a983dSmrgtypedef enum {
63fc5a983dSmrg    OPTION_HW_CURSOR,
64fc5a983dSmrg    OPTION_NOACCEL,
65fc5a983dSmrg    OPTION_ACCEL_METHOD,
66fc5a983dSmrg    OPTION_FP_DITHER,
67fc5a983dSmrg    OPTION_ALLOW_DUAL_LINK,
68fc5a983dSmrg} G80Opts;
69fc5a983dSmrg
70fc5a983dSmrgstatic const OptionInfoRec G80Options[] = {
71fc5a983dSmrg    { OPTION_HW_CURSOR,         "HWCursor",             OPTV_BOOLEAN,   {0}, FALSE },
72fc5a983dSmrg    { OPTION_NOACCEL,           "NoAccel",              OPTV_BOOLEAN,   {0}, FALSE },
73fc5a983dSmrg    { OPTION_ACCEL_METHOD,      "AccelMethod",          OPTV_STRING,    {0}, FALSE },
74fc5a983dSmrg    { OPTION_FP_DITHER,         "FPDither",             OPTV_BOOLEAN,   {0}, FALSE },
75fc5a983dSmrg    { OPTION_ALLOW_DUAL_LINK,   "AllowDualLinkModes",   OPTV_BOOLEAN,   {0}, FALSE },
76fc5a983dSmrg    { -1,                       NULL,                   OPTV_NONE,      {0}, FALSE }
77fc5a983dSmrg};
78fc5a983dSmrg
79fc5a983dSmrgstatic Bool
80fc5a983dSmrgG80GetRec(ScrnInfoPtr pScrn)
81fc5a983dSmrg{
82fc5a983dSmrg    if(pScrn->driverPrivate == NULL)
836086d97eSmrg        pScrn->driverPrivate = calloc(sizeof(G80Rec), 1);
84fc5a983dSmrg
85fc5a983dSmrg    return (pScrn->driverPrivate != NULL);
86fc5a983dSmrg}
87fc5a983dSmrg
88fc5a983dSmrgstatic void
89fc5a983dSmrgG80FreeRec(ScrnInfoPtr pScrn)
90fc5a983dSmrg{
916086d97eSmrg    free(pScrn->driverPrivate);
92fc5a983dSmrg    pScrn->driverPrivate = NULL;
93fc5a983dSmrg}
94fc5a983dSmrg
95fc5a983dSmrgstatic Bool
96fc5a983dSmrgG80ResizeScreen(ScrnInfoPtr pScrn, int width, int height)
97fc5a983dSmrg{
98fc5a983dSmrg    ScreenPtr pScreen = pScrn->pScreen;
99fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrn);
100fc5a983dSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
101fc5a983dSmrg    int pitch = width * (pScrn->bitsPerPixel / 8);
102fc5a983dSmrg    int i;
103fc5a983dSmrg
104fc5a983dSmrg    pitch = (pitch + 255) & ~255;
105fc5a983dSmrg
106fc5a983dSmrg    pScrn->virtualX = width;
107fc5a983dSmrg    pScrn->virtualY = height;
108fc5a983dSmrg
109fc5a983dSmrg    /* Can resize if XAA is disabled or EXA is enabled */
110bd304fc0Smrg    if(
111bd304fc0Smrg#ifdef HAVE_XAA_H
112bd304fc0Smrg       !pNv->xaa ||
113bd304fc0Smrg#endif
114bd304fc0Smrg       pNv->exa) {
115fc5a983dSmrg        (*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen)->devKind = pitch;
116fc5a983dSmrg        pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
117fc5a983dSmrg
118fc5a983dSmrg        /* Re-set the modes so the new pitch is taken into account */
119fc5a983dSmrg        for(i = 0; i < xf86_config->num_crtc; i++) {
120fc5a983dSmrg            xf86CrtcPtr crtc = xf86_config->crtc[i];
121fc5a983dSmrg            if(crtc->enabled)
122fc5a983dSmrg                xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y);
123fc5a983dSmrg        }
124fc5a983dSmrg    }
125fc5a983dSmrg
126fc5a983dSmrg    /*
127fc5a983dSmrg     * If EXA is enabled, use exaOffscreenAlloc to carve out a chunk of memory
128fc5a983dSmrg     * for the screen.
129fc5a983dSmrg     */
130fc5a983dSmrg    if(pNv->exa) {
131fc5a983dSmrg        if(pNv->exaScreenArea)
132fc5a983dSmrg            exaOffscreenFree(pScreen, pNv->exaScreenArea);
133fc5a983dSmrg        pNv->exaScreenArea = exaOffscreenAlloc(pScreen, pitch * pScrn->virtualY,
134fc5a983dSmrg                                               256, TRUE, NULL, NULL);
135fc5a983dSmrg        if(!pNv->exaScreenArea || pNv->exaScreenArea->offset != 0) {
136fc5a983dSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
137fc5a983dSmrg                       "Failed to reserve EXA memory for the screen or EXA "
138fc5a983dSmrg                       "returned an area with a nonzero offset.  Don't be "
139fc5a983dSmrg                       "surprised if your screen is corrupt.\n");
140fc5a983dSmrg        }
141fc5a983dSmrg    }
142fc5a983dSmrg
143fc5a983dSmrg    return TRUE;
144fc5a983dSmrg}
145fc5a983dSmrg
146fc5a983dSmrgstatic const xf86CrtcConfigFuncsRec randr12_screen_funcs = {
147fc5a983dSmrg    .resize = G80ResizeScreen,
148fc5a983dSmrg};
149fc5a983dSmrg
150fc5a983dSmrgstatic Bool
151fc5a983dSmrgG80PreInit(ScrnInfoPtr pScrn, int flags)
152fc5a983dSmrg{
153fc5a983dSmrg    G80Ptr pNv;
154fc5a983dSmrg    EntityInfoPtr pEnt;
155fc5a983dSmrg#if XSERVER_LIBPCIACCESS
156fc5a983dSmrg    struct pci_device *pPci;
157fc5a983dSmrg    int err;
158fc5a983dSmrg    void *p;
159fc5a983dSmrg#else
160fc5a983dSmrg    pciVideoPtr pPci;
161fc5a983dSmrg    PCITAG pcitag;
162fc5a983dSmrg#endif
163fc5a983dSmrg    MessageType from;
164fc5a983dSmrg    Bool primary;
165fc5a983dSmrg    const rgb zeros = {0, 0, 0};
166fc5a983dSmrg    const Gamma gzeros = {0.0, 0.0, 0.0};
167fc5a983dSmrg    char *s;
168fc5a983dSmrg    CARD32 tmp;
169fc5a983dSmrg    memType BAR1sizeKB;
170fc5a983dSmrg
171f3561b8bSmrg    if(flags & PROBE_DETECT)
172f3561b8bSmrg        return TRUE;
173fc5a983dSmrg
174fc5a983dSmrg    /* Check the number of entities, and fail if it isn't one. */
175fc5a983dSmrg    if(pScrn->numEntities != 1)
176fc5a983dSmrg        return FALSE;
177fc5a983dSmrg
178fc5a983dSmrg    /* Allocate the NVRec driverPrivate */
179fc5a983dSmrg    if(!G80GetRec(pScrn)) {
180fc5a983dSmrg        return FALSE;
181fc5a983dSmrg    }
182fc5a983dSmrg    pNv = G80PTR(pScrn);
183fc5a983dSmrg
184fc5a983dSmrg    /* Get the entity, and make sure it is PCI. */
185fc5a983dSmrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
186fc5a983dSmrg    if(pEnt->location.type != BUS_PCI) goto fail;
187fc5a983dSmrg    pPci = xf86GetPciInfoForEntity(pEnt->index);
188fc5a983dSmrg#if XSERVER_LIBPCIACCESS
189fc5a983dSmrg    /* Need this to unmap */
190fc5a983dSmrg    pNv->pPci = pPci;
191fc5a983dSmrg#endif
192fc5a983dSmrg    primary = xf86IsPrimaryPci(pPci);
193fc5a983dSmrg
194fc5a983dSmrg    /* The ROM size sometimes isn't read correctly, so fix it up here. */
195fc5a983dSmrg#if XSERVER_LIBPCIACCESS
196fc5a983dSmrg    if(pPci->rom_size == 0)
197fc5a983dSmrg        /* The BIOS is 64k */
198fc5a983dSmrg        pPci->rom_size = 64 * 1024;
199fc5a983dSmrg#else
200fc5a983dSmrg    if(pPci->biosSize == 0)
201fc5a983dSmrg        /* The BIOS is 64k */
202fc5a983dSmrg        pPci->biosSize = 16;
203fc5a983dSmrg#endif
204fc5a983dSmrg
205fc5a983dSmrg    pNv->int10 = NULL;
206fc5a983dSmrg    pNv->int10Mode = 0;
207fc5a983dSmrg    if(xf86LoadSubModule(pScrn, "int10")) {
208fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
209fc5a983dSmrg        pNv->int10 = xf86InitInt10(pEnt->index);
210fc5a983dSmrg    }
211fc5a983dSmrg
212fc5a983dSmrg    if(!pNv->int10) {
213fc5a983dSmrg        if(primary) {
214fc5a983dSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
215fc5a983dSmrg                       "Failed to initialize the int10 module; the console "
216fc5a983dSmrg                       "will not be restored.\n");
217fc5a983dSmrg        } else {
218fc5a983dSmrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
219fc5a983dSmrg                       "Failed to initialize the int10 module; this screen "
220fc5a983dSmrg                       "will not be initialized.\n");
221fc5a983dSmrg            goto fail;
222fc5a983dSmrg        }
223fc5a983dSmrg    }
224fc5a983dSmrg
225fc5a983dSmrg    if(primary && pNv->int10) {
226fc5a983dSmrg        const xf86Int10InfoPtr int10 = pNv->int10;
227fc5a983dSmrg
228fc5a983dSmrg        /* Get the current video mode */
229fc5a983dSmrg        int10->num = 0x10;
230fc5a983dSmrg        int10->ax = 0x4f03;
231fc5a983dSmrg        int10->bx = int10->cx = int10->dx = 0;
232fc5a983dSmrg        xf86ExecX86int10(int10);
233fc5a983dSmrg        pNv->int10Mode = int10->bx & 0x3fff;
234fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Console is VGA mode 0x%x\n",
235fc5a983dSmrg                   pNv->int10Mode);
236fc5a983dSmrg    }
237fc5a983dSmrg
238fc5a983dSmrg    /* Disable VGA access */
23971ba42d0Smrg#ifndef XSERVER_LIBPCIACCESS
240fc5a983dSmrg    xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
241fc5a983dSmrg    xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
24271ba42d0Smrg#endif
243fc5a983dSmrg
244fc5a983dSmrg    pScrn->monitor = pScrn->confScreen->monitor;
245fc5a983dSmrg
246fc5a983dSmrg    if(!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) goto fail;
247fc5a983dSmrg    switch (pScrn->depth) {
248fc5a983dSmrg        case 8:
249fc5a983dSmrg        case 15:
250fc5a983dSmrg        case 16:
251fc5a983dSmrg        case 24:
252fc5a983dSmrg            /* OK */
253fc5a983dSmrg            break;
254fc5a983dSmrg        default:
255fc5a983dSmrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
256fc5a983dSmrg                    "Given depth (%d) is not supported by this driver\n",
257fc5a983dSmrg                    pScrn->depth);
258fc5a983dSmrg            goto fail;
259fc5a983dSmrg    }
260fc5a983dSmrg    xf86PrintDepthBpp(pScrn);
261fc5a983dSmrg
262fc5a983dSmrg    if(!xf86SetWeight(pScrn, zeros, zeros)) goto fail;
263fc5a983dSmrg    if(!xf86SetDefaultVisual(pScrn, -1)) goto fail;
264fc5a983dSmrg
265fc5a983dSmrg    /* We use a programmable clock */
266fc5a983dSmrg    pScrn->progClock = TRUE;
267fc5a983dSmrg
268fc5a983dSmrg    /* Process options */
269fc5a983dSmrg    xf86CollectOptions(pScrn, NULL);
2706086d97eSmrg    if(!(pNv->Options = malloc(sizeof(G80Options)))) goto fail;
271fc5a983dSmrg    memcpy(pNv->Options, G80Options, sizeof(G80Options));
272fc5a983dSmrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options);
273fc5a983dSmrg
274fc5a983dSmrg    from = X_DEFAULT;
275fc5a983dSmrg    pNv->HWCursor = TRUE;
276fc5a983dSmrg    if(xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor))
277fc5a983dSmrg        from = X_CONFIG;
278fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
279fc5a983dSmrg               pNv->HWCursor ? "hardware" : "software");
280fc5a983dSmrg    if(xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) {
281fc5a983dSmrg        pNv->NoAccel = TRUE;
282fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
283fc5a983dSmrg    }
284fc5a983dSmrg    s = xf86GetOptValString(pNv->Options, OPTION_ACCEL_METHOD);
285fc5a983dSmrg    if(!s || !strcasecmp(s, "xaa"))
286fc5a983dSmrg        pNv->AccelMethod = XAA;
287fc5a983dSmrg    else if(!strcasecmp(s, "exa"))
288fc5a983dSmrg        pNv->AccelMethod = EXA;
289fc5a983dSmrg    else {
290fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unrecognized AccelMethod "
291fc5a983dSmrg        "\"%s\".\n", s);
292fc5a983dSmrg        goto fail;
293fc5a983dSmrg    }
294fc5a983dSmrg
295fc5a983dSmrg    pNv->Dither = xf86ReturnOptValBool(pNv->Options, OPTION_FP_DITHER, FALSE);
296fc5a983dSmrg    pNv->AllowDualLink = xf86ReturnOptValBool(pNv->Options, OPTION_ALLOW_DUAL_LINK, FALSE);
297fc5a983dSmrg
298fc5a983dSmrg    /* Set the bits per RGB for 8bpp mode */
299fc5a983dSmrg    if(pScrn->depth == 8)
300fc5a983dSmrg        pScrn->rgbBits = 8;
301fc5a983dSmrg
302fc5a983dSmrg    if(!xf86SetGamma(pScrn, gzeros)) goto fail;
303fc5a983dSmrg
304fc5a983dSmrg    /* Map memory */
305fc5a983dSmrg    pScrn->memPhysBase = MEMBASE(pPci, 1);
306fc5a983dSmrg    pScrn->fbOffset = 0;
307fc5a983dSmrg
308fc5a983dSmrg#if XSERVER_LIBPCIACCESS
309fc5a983dSmrg    err = pci_device_map_range(pPci, pPci->regions[0].base_addr, G80_REG_SIZE,
310fc5a983dSmrg                               PCI_DEV_MAP_FLAG_WRITABLE, &p);
311fc5a983dSmrg    if(err) {
312fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
313fc5a983dSmrg                   "Failed to map MMIO registers: %s\n", strerror(err));
314fc5a983dSmrg        goto fail;
315fc5a983dSmrg    }
316fc5a983dSmrg    pNv->reg = p;
317fc5a983dSmrg#else
318fc5a983dSmrg    pcitag = pciTag(pPci->bus, pPci->device, pPci->func);
319fc5a983dSmrg    pNv->reg = xf86MapPciMem(pScrn->scrnIndex,
320fc5a983dSmrg                             VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
321fc5a983dSmrg                             pcitag, pPci->memBase[0], G80_REG_SIZE);
322fc5a983dSmrg#endif
323fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MMIO registers mapped at %p\n",
324fc5a983dSmrg               (void*)pNv->reg);
325fc5a983dSmrg
32671ba42d0Smrg#ifndef XSERVER_LIBPCIACCESS
327fc5a983dSmrg    if(xf86RegisterResources(pEnt->index, NULL, ResExclusive)) {
328fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86RegisterResources() found "
329fc5a983dSmrg                   "resource conflicts\n");
330fc5a983dSmrg        goto fail;
331fc5a983dSmrg    }
33271ba42d0Smrg#endif
333fc5a983dSmrg
334fc5a983dSmrg    pNv->architecture = pNv->reg[0] >> 20 & 0x1ff;
335fc5a983dSmrg    tmp = pNv->reg[0x0010020C/4];
336fc5a983dSmrg    pNv->videoRam = pNv->RamAmountKBytes = tmp >> 10 | (tmp & 1) << 22;
337fc5a983dSmrg
338fc5a983dSmrg    /* Determine the size of BAR1 */
339fc5a983dSmrg    /* Some configs have BAR1 < total RAM < 256 MB */
340fc5a983dSmrg#if XSERVER_LIBPCIACCESS
341fc5a983dSmrg    BAR1sizeKB = pPci->regions[1].size / 1024;
342fc5a983dSmrg#else
343fc5a983dSmrg    BAR1sizeKB = 1UL << (pPci->size[1] - 10);
344fc5a983dSmrg#endif
345fc5a983dSmrg    if(BAR1sizeKB > 256 * 1024) {
346fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "BAR1 is > 256 MB, which is "
347fc5a983dSmrg                   "probably wrong.  Clamping to 256 MB.\n");
348fc5a983dSmrg        BAR1sizeKB = 256 * 1024;
349fc5a983dSmrg    }
350fc5a983dSmrg
351fc5a983dSmrg    /* Limit videoRam to the size of BAR1 */
352fc5a983dSmrg    if(pNv->videoRam <= 1024 || BAR1sizeKB == 0) {
353fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to determine the amount of "
354fc5a983dSmrg                   "available video memory\n");
355fc5a983dSmrg        goto fail;
356fc5a983dSmrg    }
357fc5a983dSmrg    pNv->videoRam -= 1024;
358fc5a983dSmrg    if(pNv->videoRam > BAR1sizeKB)
359fc5a983dSmrg        pNv->videoRam = BAR1sizeKB;
360fc5a983dSmrg
361fc5a983dSmrg    pScrn->videoRam = pNv->videoRam;
362fc5a983dSmrg
363fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Total video RAM: %.1f MB\n",
364fc5a983dSmrg               pNv->RamAmountKBytes / 1024.0);
365fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "      BAR1 size: %.1f MB\n",
366fc5a983dSmrg               BAR1sizeKB / 1024.0);
367fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "  Mapped memory: %.1f MB\n",
368fc5a983dSmrg               pScrn->videoRam / 1024.0);
369fc5a983dSmrg
370fc5a983dSmrg#if XSERVER_LIBPCIACCESS
371fc5a983dSmrg    err = pci_device_map_range(pPci, pPci->regions[1].base_addr,
372fc5a983dSmrg                               pScrn->videoRam * 1024,
373fc5a983dSmrg                               PCI_DEV_MAP_FLAG_WRITABLE |
374fc5a983dSmrg                               PCI_DEV_MAP_FLAG_WRITE_COMBINE,
375fc5a983dSmrg                               &p);
376fc5a983dSmrg    if(err) {
377fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
378fc5a983dSmrg                   "Failed to map framebuffer: %s\n", strerror(err));
379fc5a983dSmrg        goto fail;
380fc5a983dSmrg    }
381fc5a983dSmrg    pNv->mem = p;
382fc5a983dSmrg#else
383fc5a983dSmrg    pNv->mem = xf86MapPciMem(pScrn->scrnIndex,
384fc5a983dSmrg                             VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
385fc5a983dSmrg                             pcitag, pPci->memBase[1], pScrn->videoRam * 1024);
386fc5a983dSmrg#endif
387fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer mapped at %p\n",
388fc5a983dSmrg               (void*)pNv->mem);
389fc5a983dSmrg
390fc5a983dSmrg    pNv->table1 = (unsigned const char*)&pNv->reg[0x00800000/4];
391fc5a983dSmrg    tmp = pNv->reg[0x00619F04/4] >> 8;
392fc5a983dSmrg    if(tmp)
393fc5a983dSmrg        pNv->table1 -= ((pNv->RamAmountKBytes << 10) - (tmp << 16));
394fc5a983dSmrg    else
395fc5a983dSmrg        pNv->table1 -= 0x10000;
396fc5a983dSmrg
397fc5a983dSmrg    xf86CrtcConfigInit(pScrn, &randr12_screen_funcs);
398fc5a983dSmrg    xf86CrtcSetSizeRange(pScrn, 320, 200, 8192, 8192);
399fc5a983dSmrg
400fc5a983dSmrg    if(!xf86LoadSubModule(pScrn, "i2c")) goto fail;
401fc5a983dSmrg    if(!xf86LoadSubModule(pScrn, "ddc")) goto fail;
402fc5a983dSmrg
403fc5a983dSmrg    if(!G80DispPreInit(pScrn)) goto fail;
404fc5a983dSmrg    /* Read the DDC routing table and create outputs */
405fc5a983dSmrg    if(!G80CreateOutputs(pScrn)) goto fail;
406fc5a983dSmrg    /* Create the crtcs */
407fc5a983dSmrg    G80DispCreateCrtcs(pScrn);
408fc5a983dSmrg
409fc5a983dSmrg    /* We can grow the desktop if XAA is disabled */
410fc5a983dSmrg    if(!xf86InitialConfiguration(pScrn, pNv->NoAccel || pNv->AccelMethod == EXA)) {
411fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
412fc5a983dSmrg            "No valid initial configuration found\n");
413fc5a983dSmrg        goto fail;
414fc5a983dSmrg    }
415fc5a983dSmrg    pScrn->displayWidth = (pScrn->virtualX + 255) & ~255;
416fc5a983dSmrg
417fc5a983dSmrg    if(!xf86RandR12PreInit(pScrn)) {
418fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
419fc5a983dSmrg        goto fail;
420fc5a983dSmrg    }
421fc5a983dSmrg    if(!pScrn->modes) {
422fc5a983dSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
423fc5a983dSmrg        goto fail;
424fc5a983dSmrg    }
425fc5a983dSmrg
426fc5a983dSmrg    pScrn->currentMode = pScrn->modes;
427fc5a983dSmrg    xf86PrintModes(pScrn);
428fc5a983dSmrg    xf86SetDpi(pScrn, 0, 0);
429fc5a983dSmrg
430fc5a983dSmrg    /* Load fb */
431fc5a983dSmrg    if(!xf86LoadSubModule(pScrn, "fb")) goto fail;
432fc5a983dSmrg
433fc5a983dSmrg    if(!pNv->NoAccel) {
434fc5a983dSmrg        switch(pNv->AccelMethod) {
435fc5a983dSmrg        case XAA:
436bd304fc0Smrg            if(!xf86LoadSubModule(pScrn, "xaa")) pNv->NoAccel = 1;
437fc5a983dSmrg            break;
438fc5a983dSmrg        case EXA:
439bd304fc0Smrg            if(!xf86LoadSubModule(pScrn, "exa")) pNv->NoAccel = 1;
440fc5a983dSmrg            break;
441fc5a983dSmrg        }
442fc5a983dSmrg    }
443fc5a983dSmrg
444fc5a983dSmrg    /* Load ramdac if needed */
445fc5a983dSmrg    if(pNv->HWCursor) {
446fc5a983dSmrg        if(!xf86LoadSubModule(pScrn, "ramdac")) {
447fc5a983dSmrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load ramdac. "
448fc5a983dSmrg                       "Falling back to software cursor.\n");
449fc5a983dSmrg            pNv->HWCursor = FALSE;
450bd2f6fc9Smrg	}
451fc5a983dSmrg    }
452fc5a983dSmrg
453fc5a983dSmrg    return TRUE;
454fc5a983dSmrg
455fc5a983dSmrgfail:
456fc5a983dSmrg    if(pNv->int10) xf86FreeInt10(pNv->int10);
457fc5a983dSmrg    G80FreeRec(pScrn);
458fc5a983dSmrg    return FALSE;
459fc5a983dSmrg}
460fc5a983dSmrg
461fc5a983dSmrg/*
462fc5a983dSmrg * Initialize the display and set the current mode.
463fc5a983dSmrg */
464fc5a983dSmrgstatic Bool
465fc5a983dSmrgAcquireDisplay(ScrnInfoPtr pScrn)
466fc5a983dSmrg{
467fc5a983dSmrg    if(!G80DispInit(pScrn))
468fc5a983dSmrg        return FALSE;
469fc5a983dSmrg    if(!G80CursorAcquire(pScrn))
470fc5a983dSmrg        return FALSE;
471fc5a983dSmrg    xf86SetDesiredModes(pScrn);
472fc5a983dSmrg
473fc5a983dSmrg    return TRUE;
474fc5a983dSmrg}
475fc5a983dSmrg
476fc5a983dSmrg/*
477fc5a983dSmrg * Tear down the display and restore the console mode.
478fc5a983dSmrg */
479fc5a983dSmrgstatic Bool
480fc5a983dSmrgReleaseDisplay(ScrnInfoPtr pScrn)
481fc5a983dSmrg{
482fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrn);
483fc5a983dSmrg
484fc5a983dSmrg    G80CursorRelease(pScrn);
485fc5a983dSmrg    G80DispShutdown(pScrn);
486fc5a983dSmrg
487fc5a983dSmrg    if(pNv->int10 && pNv->int10Mode) {
488fc5a983dSmrg        xf86Int10InfoPtr int10 = pNv->int10;
489fc5a983dSmrg
490fc5a983dSmrg        /* Use int10 to restore the console mode */
491fc5a983dSmrg        int10->num = 0x10;
492fc5a983dSmrg        int10->ax = 0x4f02;
493fc5a983dSmrg        int10->bx = pNv->int10Mode | 0x8000;
494fc5a983dSmrg        int10->cx = int10->dx = 0;
495fc5a983dSmrg        xf86ExecX86int10(int10);
496fc5a983dSmrg    }
497fc5a983dSmrg
498fc5a983dSmrg    return TRUE;
499fc5a983dSmrg}
500fc5a983dSmrg
501fc5a983dSmrgstatic Bool
502bd304fc0SmrgG80CloseScreen(CLOSE_SCREEN_ARGS_DECL)
503fc5a983dSmrg{
504bd304fc0Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
505fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrn);
506fc5a983dSmrg
507fc5a983dSmrg    if(pScrn->vtSema)
508fc5a983dSmrg        ReleaseDisplay(pScrn);
509fc5a983dSmrg
510bd304fc0Smrg#ifdef HAVE_XAA_H
511fc5a983dSmrg    if(pNv->xaa)
512fc5a983dSmrg        XAADestroyInfoRec(pNv->xaa);
513bd304fc0Smrg#endif
514fc5a983dSmrg    if(pNv->exa) {
515fc5a983dSmrg        if(pNv->exaScreenArea) {
516fc5a983dSmrg            exaOffscreenFree(pScreen, pNv->exaScreenArea);
517fc5a983dSmrg            pNv->exaScreenArea = NULL;
518fc5a983dSmrg        }
519fc5a983dSmrg        exaDriverFini(pScrn->pScreen);
520fc5a983dSmrg    }
521fc5a983dSmrg    xf86_cursors_fini(pScreen);
522fc5a983dSmrg
523fc5a983dSmrg    if(xf86ServerIsExiting()) {
524fc5a983dSmrg        if(pNv->int10) xf86FreeInt10(pNv->int10);
525fc5a983dSmrg#if XSERVER_LIBPCIACCESS
526fc5a983dSmrg        pci_device_unmap_range(pNv->pPci, pNv->mem, pNv->videoRam * 1024);
527fc5a983dSmrg        pci_device_unmap_range(pNv->pPci, (void*)pNv->reg, G80_REG_SIZE);
528fc5a983dSmrg#else
529fc5a983dSmrg        xf86UnMapVidMem(pScrn->scrnIndex, pNv->mem, pNv->videoRam * 1024);
530fc5a983dSmrg        xf86UnMapVidMem(pScrn->scrnIndex, (void*)pNv->reg, G80_REG_SIZE);
531fc5a983dSmrg#endif
532fc5a983dSmrg        pNv->reg = NULL;
533fc5a983dSmrg        pNv->mem = NULL;
534fc5a983dSmrg    }
535fc5a983dSmrg
536fc5a983dSmrg    pScrn->vtSema = FALSE;
537fc5a983dSmrg    pScreen->CloseScreen = pNv->CloseScreen;
538fc5a983dSmrg    pScreen->BlockHandler = pNv->BlockHandler;
539bd304fc0Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
540fc5a983dSmrg}
541fc5a983dSmrg
542fc5a983dSmrgstatic void
543bd304fc0SmrgG80BlockHandler(BLOCKHANDLER_ARGS_DECL)
544fc5a983dSmrg{
545bd304fc0Smrg    SCREEN_PTR(arg);
546bd304fc0Smrg    ScrnInfoPtr pScrnInfo = xf86ScreenToScrn(pScreen);
547fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrnInfo);
548fc5a983dSmrg
549fc5a983dSmrg    if(pNv->DMAKickoffCallback)
550fc5a983dSmrg        (*pNv->DMAKickoffCallback)(pScrnInfo);
551fc5a983dSmrg
552fc5a983dSmrg    G80OutputResetCachedStatus(pScrnInfo);
553fc5a983dSmrg
554fc5a983dSmrg    pScreen->BlockHandler = pNv->BlockHandler;
555bd304fc0Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
556fc5a983dSmrg    pScreen->BlockHandler = G80BlockHandler;
557fc5a983dSmrg}
558fc5a983dSmrg
559fc5a983dSmrgstatic Bool
560fc5a983dSmrgG80SaveScreen(ScreenPtr pScreen, int mode)
561fc5a983dSmrg{
562fc5a983dSmrg    return FALSE;
563fc5a983dSmrg}
564fc5a983dSmrg
565fc5a983dSmrgstatic void
566fc5a983dSmrgG80InitHW(ScrnInfoPtr pScrn)
567fc5a983dSmrg{
568fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrn);
569fc5a983dSmrg    CARD32 bar0_pramin = 0;
570fc5a983dSmrg    const int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
571fc5a983dSmrg    volatile CARD32 *p;
572fc5a983dSmrg
573fc5a983dSmrg    /* Clear registers */
574fc5a983dSmrg    for(p = &pNv->reg[0x00700000/4]; p < (const CARD32*)pNv->table1; p++)
575fc5a983dSmrg        *p = 0;
576fc5a983dSmrg
577fc5a983dSmrg    bar0_pramin = pNv->reg[0x00001700/4] << 16;
578fc5a983dSmrg
579fc5a983dSmrg    pNv->reg[0x00000200/4] = 0xffff00ff;
580fc5a983dSmrg    pNv->reg[0x00000200/4] = 0xffffffff;
581fc5a983dSmrg    pNv->reg[0x00002100/4] = 0xffffffff;
582fc5a983dSmrg    pNv->reg[0x0000250c/4] = 0x6f3cfc34;
583fc5a983dSmrg    pNv->reg[0x00400804/4] = 0xc0000000;
584fc5a983dSmrg    pNv->reg[0x00406800/4] = 0xc0000000;
585fc5a983dSmrg    pNv->reg[0x00400c04/4] = 0xc0000000;
586fc5a983dSmrg    pNv->reg[0x00401800/4] = 0xc0000000;
587fc5a983dSmrg    pNv->reg[0x00405018/4] = 0xc0000000;
588fc5a983dSmrg    pNv->reg[0x00402000/4] = 0xc0000000;
589fc5a983dSmrg    pNv->reg[0x00400108/4] = 0xffffffff;
590fc5a983dSmrg    pNv->reg[0x00400100/4] = 0xffffffff;
591fc5a983dSmrg
592fc5a983dSmrg    if(pNv->architecture != 0x50) {
593fc5a983dSmrg        pNv->reg[0x00700000/4] = 0x00000001;
594fc5a983dSmrg        pNv->reg[0x00700004/4] = bar0_pramin + 0x00200;
595fc5a983dSmrg        pNv->reg[0x00700020/4] = 0x00190002;
596fc5a983dSmrg        pNv->reg[0x00700024/4] = bar0_pramin + 0x7ffff;
597fc5a983dSmrg        pNv->reg[0x00700028/4] = bar0_pramin + 0x20000;
598fc5a983dSmrg        pNv->reg[0x00700034/4] = 0x00010000;
599fc5a983dSmrg    } else {
600fc5a983dSmrg        pNv->reg[0x00700200/4] = 0x00190002;
601fc5a983dSmrg        pNv->reg[0x00700204/4] = bar0_pramin + 0x7ffff;
602fc5a983dSmrg        pNv->reg[0x00700208/4] = bar0_pramin + 0x20000;
603fc5a983dSmrg        pNv->reg[0x00700214/4] = 0x00010000;
604fc5a983dSmrg    }
605fc5a983dSmrg
606fc5a983dSmrg    pNv->reg[0x00710004/4] = 0x00100642;
607fc5a983dSmrg    pNv->reg[0x00710008/4] = 0x80000011;
608fc5a983dSmrg    pNv->reg[0x0071000c/4] = 0x00000644;
609fc5a983dSmrg    pNv->reg[0x00710010/4] = 0x80000012;
610fc5a983dSmrg    pNv->reg[0x00710014/4] = 0x00100646;
611fc5a983dSmrg    pNv->reg[0x00710018/4] = 0x80000013;
612fc5a983dSmrg    pNv->reg[0x0071001c/4] = 0x00100648;
613fc5a983dSmrg    pNv->reg[0x00710020/4] = 0x80000014;
614fc5a983dSmrg    pNv->reg[0x00710024/4] = 0x0000064a;
615fc5a983dSmrg    pNv->reg[0x00706420/4] = 0x00190030;
616fc5a983dSmrg    pNv->reg[0x00706434/4] = 0x00010000;
617fc5a983dSmrg    pNv->reg[0x00706440/4] = 0x0019003d;
618fc5a983dSmrg    pNv->reg[0x00706444/4] = (pNv->videoRam << 10) - 0x4001;
619fc5a983dSmrg    pNv->reg[0x00706448/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM;
620fc5a983dSmrg    pNv->reg[0x00706454/4] = 0x00010000;
621fc5a983dSmrg    pNv->reg[0x00706460/4] = 0x0000502d;
622fc5a983dSmrg    pNv->reg[0x00706474/4] = 0x00010000;
62371ba42d0Smrg    if(pNv->architecture == 0xaa || pNv->architecture == 0xac) {
62471ba42d0Smrg        uint64_t base = (uint64_t)pNv->reg[0x00100E10/4] << 12;
62571ba42d0Smrg        size_t size = (uint64_t)pNv->reg[0x00100E14/4] << 12;
62671ba42d0Smrg        uint64_t limit = base + size - G80_RESERVED_VIDMEM;
62771ba42d0Smrg
62871ba42d0Smrg        pNv->reg[0x00706480/4] = 0x1a003d;
62971ba42d0Smrg        pNv->reg[0x00706484/4] = limit;
63071ba42d0Smrg        pNv->reg[0x00706488/4] = base;
63171ba42d0Smrg        pNv->reg[0x0070648c/4] = base >> 32 | ((limit >> 8) & 0xff000000);
63271ba42d0Smrg    } else {
63371ba42d0Smrg        pNv->reg[0x00706480/4] = 0x0019003d;
63471ba42d0Smrg        pNv->reg[0x00706484/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM;
63571ba42d0Smrg        pNv->reg[0x00706494/4] = 0x00010000;
63671ba42d0Smrg    }
637fc5a983dSmrg    pNv->reg[0x007064a0/4] = 0x0019003d;
638fc5a983dSmrg    pNv->reg[0x007064a4/4] = bar0_pramin + 0x1100f;
639fc5a983dSmrg    pNv->reg[0x007064a8/4] = bar0_pramin + 0x11000;
640fc5a983dSmrg    pNv->reg[0x007064b4/4] = 0x00010000;
641fc5a983dSmrg
642fc5a983dSmrg    if(pNv->architecture != 0x50) {
643fc5a983dSmrg        pNv->reg[0x00002604/4] = 0x80000002 | (bar0_pramin >> 8);
644fc5a983dSmrg    } else {
645fc5a983dSmrg        pNv->reg[0x00002604/4] = 0x80000000 | (bar0_pramin >> 12);
646fc5a983dSmrg    }
647fc5a983dSmrg
648fc5a983dSmrg    pNv->reg[0x00003224/4] = 0x000f0078;
649fc5a983dSmrg    pNv->reg[0x0000322c/4] = 0x00000644;
65071ba42d0Smrg    pNv->reg[0x00003234/4] = G80_RESERVED_VIDMEM - 0x6001;
651fc5a983dSmrg    pNv->reg[0x00003254/4] = 0x00000001;
652fc5a983dSmrg    pNv->reg[0x00002210/4] = 0x1c001000;
653fc5a983dSmrg
654fc5a983dSmrg    if(pNv->architecture != 0x50) {
655fc5a983dSmrg        pNv->reg[0x0000340c/4] = (bar0_pramin + 0x1000) >> 10;
656fc5a983dSmrg        pNv->reg[0x00003410/4] = (bar0_pramin >> 12);
657fc5a983dSmrg    }
658fc5a983dSmrg
659fc5a983dSmrg    pNv->reg[0x00400824/4] = 0x00004000;
660fc5a983dSmrg    pNv->reg[0x00400784/4] = 0x80000000 | (bar0_pramin >> 12);
661fc5a983dSmrg    pNv->reg[0x00400320/4] = 0x00000004;
662fc5a983dSmrg    pNv->reg[0x0040032C/4] = 0x80000000 | (bar0_pramin >> 12);
663fc5a983dSmrg    pNv->reg[0x00400500/4] = 0x00010001;
664fc5a983dSmrg    pNv->reg[0x00003250/4] = 0x00000001;
665fc5a983dSmrg    pNv->reg[0x00003200/4] = 0x00000001;
666fc5a983dSmrg    pNv->reg[0x00003220/4] = 0x00001001;
667fc5a983dSmrg    pNv->reg[0x00003204/4] = 0x00010001;
668fc5a983dSmrg
669fc5a983dSmrg    pNv->dmaBase = (CARD32*)(pNv->mem + (pNv->videoRam << 10) -
670fc5a983dSmrg        G80_RESERVED_VIDMEM);
671fc5a983dSmrg    memset(pNv->dmaBase, 0, SKIPS*4);
672fc5a983dSmrg
673fc5a983dSmrg    pNv->dmaPut = 0;
674fc5a983dSmrg    pNv->dmaCurrent = SKIPS;
67571ba42d0Smrg    pNv->dmaMax = (G80_RESERVED_VIDMEM - 0x6000) / 4 - 2;
676fc5a983dSmrg    pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
677fc5a983dSmrg
678fc5a983dSmrg    G80DmaStart(pNv, 0, 1);
679fc5a983dSmrg    G80DmaNext (pNv, 0x80000012);
680fc5a983dSmrg    G80DmaStart(pNv, 0x180, 3);
681fc5a983dSmrg    G80DmaNext (pNv, 0x80000014);
682fc5a983dSmrg    G80DmaNext (pNv, 0x80000013);
683fc5a983dSmrg    G80DmaNext (pNv, 0x80000013);
684fc5a983dSmrg    G80DmaStart(pNv, 0x200, 2);
685fc5a983dSmrg    switch(pScrn->depth) {
686fc5a983dSmrg        case  8: G80DmaNext (pNv, 0x000000f3); break;
687fc5a983dSmrg        case 15: G80DmaNext (pNv, 0x000000f8); break;
688fc5a983dSmrg        case 16: G80DmaNext (pNv, 0x000000e8); break;
689fc5a983dSmrg        case 24: G80DmaNext (pNv, 0x000000e6); break;
690fc5a983dSmrg    }
691fc5a983dSmrg    G80DmaNext (pNv, 0x00000001);
692fc5a983dSmrg    G80DmaStart(pNv, 0x214, 5);
693fc5a983dSmrg    G80DmaNext (pNv, pitch);
694fc5a983dSmrg    G80DmaNext (pNv, pitch);
695fc5a983dSmrg    G80DmaNext (pNv, pNv->offscreenHeight);
696fc5a983dSmrg    G80DmaNext (pNv, 0x00000000);
697fc5a983dSmrg    G80DmaNext (pNv, 0x00000000);
698fc5a983dSmrg    G80DmaStart(pNv, 0x230, 2);
699fc5a983dSmrg    switch(pScrn->depth) {
700fc5a983dSmrg        case  8: G80DmaNext (pNv, 0x000000f3); break;
701fc5a983dSmrg        case 15: G80DmaNext (pNv, 0x000000f8); break;
702fc5a983dSmrg        case 16: G80DmaNext (pNv, 0x000000e8); break;
703fc5a983dSmrg        case 24: G80DmaNext (pNv, 0x000000e6); break;
704fc5a983dSmrg    }
705fc5a983dSmrg    G80DmaNext (pNv, 0x00000001);
706fc5a983dSmrg    G80DmaStart(pNv, 0x244, 5);
707fc5a983dSmrg    G80DmaNext (pNv, pitch);
708fc5a983dSmrg    G80DmaNext (pNv, pitch);
709fc5a983dSmrg    G80DmaNext (pNv, pNv->offscreenHeight);
710fc5a983dSmrg    G80DmaNext (pNv, 0x00000000);
711fc5a983dSmrg    G80DmaNext (pNv, 0x00000000);
712fc5a983dSmrg    G80DmaStart(pNv, 0x260, 1);
713fc5a983dSmrg    G80DmaNext (pNv, 0x00000001);
714fc5a983dSmrg    G80DmaStart(pNv, 0x290, 1);
715fc5a983dSmrg    G80DmaNext (pNv, 1);
716fc5a983dSmrg    G80DmaStart(pNv, 0x29c, 1);
717fc5a983dSmrg    G80DmaNext (pNv, 0);
718fc5a983dSmrg    G80DmaStart(pNv, 0x2e8, 2);
719fc5a983dSmrg    switch(pScrn->depth) {
720fc5a983dSmrg        case  8: G80DmaNext (pNv, 3); break;
721fc5a983dSmrg        case 15: G80DmaNext (pNv, 1); break;
722fc5a983dSmrg        case 16: G80DmaNext (pNv, 0); break;
723fc5a983dSmrg        case 24: G80DmaNext (pNv, 2); break;
724fc5a983dSmrg    }
725fc5a983dSmrg    G80DmaNext (pNv, 1);
726fc5a983dSmrg    G80DmaStart(pNv, 0x584, 1);
727fc5a983dSmrg    switch(pScrn->depth) {
728fc5a983dSmrg        case  8: G80DmaNext (pNv, 0xf3); break;
729fc5a983dSmrg        case 15: G80DmaNext (pNv, 0xf8); break;
730fc5a983dSmrg        case 16: G80DmaNext (pNv, 0xe8); break;
731fc5a983dSmrg        case 24: G80DmaNext (pNv, 0xe6); break;
732fc5a983dSmrg    }
733fc5a983dSmrg    G80DmaStart(pNv, 0x58c, 1);
734fc5a983dSmrg    G80DmaNext (pNv, 0x111);
735fc5a983dSmrg    G80DmaStart(pNv, 0x804, 1);
736fc5a983dSmrg    switch(pScrn->depth) {
737fc5a983dSmrg        case  8: G80DmaNext (pNv, 0xf3); break;
738fc5a983dSmrg        case 15: G80DmaNext (pNv, 0xf8); break;
739fc5a983dSmrg        case 16: G80DmaNext (pNv, 0xe8); break;
740fc5a983dSmrg        case 24: G80DmaNext (pNv, 0xe6); break;
741fc5a983dSmrg    }
742fc5a983dSmrg
743fc5a983dSmrg    pNv->currentRop = ~0; /* Set to something invalid */
744fc5a983dSmrg}
745fc5a983dSmrg
746fc5a983dSmrgstatic Bool
747bd304fc0SmrgG80ScreenInit(SCREEN_INIT_ARGS_DECL)
748fc5a983dSmrg{
749fc5a983dSmrg    ScrnInfoPtr pScrn;
750fc5a983dSmrg    G80Ptr pNv;
751fc5a983dSmrg    CARD32 pitch;
752fc5a983dSmrg    int visualMask, i;
753fc5a983dSmrg    BoxRec AvailFBArea;
754fc5a983dSmrg
755fc5a983dSmrg    /* First get the ScrnInfoRec */
756bd304fc0Smrg    pScrn = xf86ScreenToScrn(pScreen);
757fc5a983dSmrg    pNv = G80PTR(pScrn);
758fc5a983dSmrg
759fc5a983dSmrg    pScrn->vtSema = TRUE;
760fc5a983dSmrg
761fc5a983dSmrg    /* DIX visual init */
762fc5a983dSmrg    miClearVisualTypes();
763fc5a983dSmrg    visualMask = miGetDefaultVisualMask(pScrn->depth);
764fc5a983dSmrg    if(!miSetVisualTypes(pScrn->depth, visualMask, 8, pScrn->defaultVisual))
765fc5a983dSmrg        return FALSE;
766fc5a983dSmrg    if(!miSetPixmapDepths())
767fc5a983dSmrg        return FALSE;
768fc5a983dSmrg
769fc5a983dSmrg    /* pad the screen pitch to 256 bytes */
770fc5a983dSmrg    pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
771fc5a983dSmrg
772fc5a983dSmrg    /* fb init */
773fc5a983dSmrg    if(!fbScreenInit(pScreen, pNv->mem,
774fc5a983dSmrg                     pScrn->virtualX, pScrn->virtualY,
775fc5a983dSmrg                     pScrn->xDpi, pScrn->yDpi,
776fc5a983dSmrg                     pScrn->displayWidth, pScrn->bitsPerPixel))
777fc5a983dSmrg        return FALSE;
778fc5a983dSmrg
779fc5a983dSmrg    if(pScrn->bitsPerPixel > 8) {
780fc5a983dSmrg        VisualPtr visual;
781fc5a983dSmrg
782fc5a983dSmrg        /* Fixup RGB ordering */
783fc5a983dSmrg        visual = pScreen->visuals + pScreen->numVisuals;
784fc5a983dSmrg        while(--visual >= pScreen->visuals) {
785fc5a983dSmrg            if((visual->class | DynamicClass) == DirectColor) {
786fc5a983dSmrg                visual->offsetRed = pScrn->offset.red;
787fc5a983dSmrg                visual->offsetGreen = pScrn->offset.green;
788fc5a983dSmrg                visual->offsetBlue = pScrn->offset.blue;
789fc5a983dSmrg                visual->redMask = pScrn->mask.red;
790fc5a983dSmrg                visual->greenMask = pScrn->mask.green;
791fc5a983dSmrg                visual->blueMask = pScrn->mask.blue;
792fc5a983dSmrg            }
793fc5a983dSmrg        }
794fc5a983dSmrg    }
795fc5a983dSmrg
796fc5a983dSmrg    fbPictureInit(pScreen, 0, 0);
797fc5a983dSmrg
798fc5a983dSmrg    xf86SetBlackWhitePixels(pScreen);
799fc5a983dSmrg
800fc5a983dSmrg    pNv->offscreenHeight = ((pNv->videoRam << 10) - G80_RESERVED_VIDMEM) / pitch;
801fc5a983dSmrg    if(pNv->offscreenHeight > 32767) pNv->offscreenHeight = 32767;
802fc5a983dSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
803fc5a983dSmrg        "%.2f MB available for offscreen pixmaps\n",
804fc5a983dSmrg        (pNv->offscreenHeight - pScrn->virtualY) * pitch / 1024.0 / 1024.0);
805fc5a983dSmrg
806fc5a983dSmrg    AvailFBArea.x1 = 0;
807fc5a983dSmrg    AvailFBArea.y1 = 0;
808fc5a983dSmrg    AvailFBArea.x2 = pScrn->displayWidth;
809fc5a983dSmrg    AvailFBArea.y2 = pNv->offscreenHeight;
810fc5a983dSmrg    xf86InitFBManager(pScreen, &AvailFBArea);
811fc5a983dSmrg
812fc5a983dSmrg    pNv->reg[0x00001708/4] = 0;
813fc5a983dSmrg    for(i = 0; i < 8; i++)
814fc5a983dSmrg        pNv->reg[0x00001900/4 + i] = 0;
815fc5a983dSmrg
816fc5a983dSmrg    if(!pNv->NoAccel) {
817fc5a983dSmrg        G80InitHW(pScrn);
818fc5a983dSmrg        switch(pNv->AccelMethod) {
819fc5a983dSmrg        case XAA:
820fc5a983dSmrg            if(!G80XAAInit(pScreen)) {
821fc5a983dSmrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
822fc5a983dSmrg                           "XAA hardware acceleration initialization failed\n");
823fc5a983dSmrg                return FALSE;
824fc5a983dSmrg            }
825fc5a983dSmrg            break;
826fc5a983dSmrg        case EXA:
827fc5a983dSmrg            if(!G80ExaInit(pScreen, pScrn)) {
828fc5a983dSmrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
829fc5a983dSmrg                           "EXA hardware acceleration initialization failed\n");
830fc5a983dSmrg                return FALSE;
831fc5a983dSmrg            }
832fc5a983dSmrg            break;
833fc5a983dSmrg        }
834fc5a983dSmrg    }
835fc5a983dSmrg
836fc5a983dSmrg    miInitializeBackingStore(pScreen);
837fc5a983dSmrg    xf86SetBackingStore(pScreen);
838fc5a983dSmrg    xf86SetSilkenMouse(pScreen);
839fc5a983dSmrg
840fc5a983dSmrg    /* Initialize software cursor.
841fc5a983dSmrg       Must precede creation of the default colormap */
842fc5a983dSmrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
843fc5a983dSmrg
84471ba42d0Smrg    if(!xf86CrtcScreenInit(pScreen))
84571ba42d0Smrg        return FALSE;
84671ba42d0Smrg
847fc5a983dSmrg    /* Initialize default colormap */
848fc5a983dSmrg    if(!miCreateDefColormap(pScreen))
849fc5a983dSmrg        return FALSE;
850fc5a983dSmrg
851fc5a983dSmrg    /* Initialize colormap layer.
852fc5a983dSmrg       Must follow initialization of the default colormap */
853fc5a983dSmrg    if(!xf86HandleColormaps(pScreen, 256, 8, G80LoadPalette, NULL,
854fc5a983dSmrg                            CMAP_PALETTED_TRUECOLOR))
855fc5a983dSmrg        return FALSE;
856fc5a983dSmrg
857fc5a983dSmrg    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
858fc5a983dSmrg
859bd304fc0Smrg#ifdef HAVE_XAA_H
860fc5a983dSmrg    /* Clear the screen */
861fc5a983dSmrg    if(pNv->xaa) {
862fc5a983dSmrg        /* Use the acceleration engine */
863fc5a983dSmrg        pNv->xaa->SetupForSolidFill(pScrn, 0, GXcopy, ~0);
864fc5a983dSmrg        pNv->xaa->SubsequentSolidFillRect(pScrn,
865fc5a983dSmrg            0, 0, pScrn->displayWidth, pNv->offscreenHeight);
866fc5a983dSmrg        G80DmaKickoff(pNv);
867bd304fc0Smrg    } else
868bd304fc0Smrg#endif
869bd304fc0Smrg    {
870fc5a983dSmrg        /* Use a slow software clear path */
871fc5a983dSmrg        memset(pNv->mem, 0, pitch * pNv->offscreenHeight);
872fc5a983dSmrg    }
873fc5a983dSmrg
874fc5a983dSmrg    /* Initialize the display */
875fc5a983dSmrg    if(!AcquireDisplay(pScrn))
876fc5a983dSmrg        return FALSE;
877fc5a983dSmrg
878f3561b8bSmrg    /* Initialize hardware cursor.  Must follow software cursor initialization. */
879f3561b8bSmrg    if(pNv->HWCursor && !G80CursorInit(pScreen)) {
880f3561b8bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
881f3561b8bSmrg                   "Hardware cursor initialization failed\n");
882f3561b8bSmrg        pNv->HWCursor = FALSE;
883f3561b8bSmrg    }
884f3561b8bSmrg
885fc5a983dSmrg    pScreen->SaveScreen = G80SaveScreen;
886fc5a983dSmrg
887fc5a983dSmrg    pNv->CloseScreen = pScreen->CloseScreen;
888fc5a983dSmrg    pScreen->CloseScreen = G80CloseScreen;
889fc5a983dSmrg
890fc5a983dSmrg    pNv->BlockHandler = pScreen->BlockHandler;
891fc5a983dSmrg    pScreen->BlockHandler = G80BlockHandler;
892fc5a983dSmrg
893fc5a983dSmrg    return TRUE;
894fc5a983dSmrg}
895fc5a983dSmrg
896fc5a983dSmrgstatic void
897bd304fc0SmrgG80FreeScreen(FREE_SCREEN_ARGS_DECL)
898fc5a983dSmrg{
899bd304fc0Smrg    SCRN_INFO_PTR(arg);
900bd304fc0Smrg    G80FreeRec(pScrn);
901fc5a983dSmrg}
902fc5a983dSmrg
903fc5a983dSmrgstatic Bool
904bd304fc0SmrgG80SwitchMode(SWITCH_MODE_ARGS_DECL)
905fc5a983dSmrg{
906bd304fc0Smrg    SCRN_INFO_PTR(arg);
907fc5a983dSmrg    return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
908fc5a983dSmrg}
909fc5a983dSmrg
910fc5a983dSmrgstatic void
911bd304fc0SmrgG80AdjustFrame(ADJUST_FRAME_ARGS_DECL)
912fc5a983dSmrg{
913fc5a983dSmrg}
914fc5a983dSmrg
915fc5a983dSmrgstatic Bool
916bd304fc0SmrgG80EnterVT(VT_FUNC_ARGS_DECL)
917fc5a983dSmrg{
918bd304fc0Smrg    SCRN_INFO_PTR(arg);
919fc5a983dSmrg    G80Ptr pNv = G80PTR(pScrn);
920fc5a983dSmrg
921fc5a983dSmrg    /* Reinit the hardware */
922bd304fc0Smrg#ifdef HAVE_XAA_H
923fc5a983dSmrg    if(pNv->xaa)
924fc5a983dSmrg        G80InitHW(pScrn);
925bd304fc0Smrg#endif
926fc5a983dSmrg
927fc5a983dSmrg    if(!AcquireDisplay(pScrn))
928fc5a983dSmrg        return FALSE;
929fc5a983dSmrg
930fc5a983dSmrg    return TRUE;
931fc5a983dSmrg}
932fc5a983dSmrg
933fc5a983dSmrgstatic void
934bd304fc0SmrgG80LeaveVT(VT_FUNC_ARGS_DECL)
935fc5a983dSmrg{
936bd304fc0Smrg    SCRN_INFO_PTR(arg);
937fc5a983dSmrg
938fc5a983dSmrg    ReleaseDisplay(pScrn);
939fc5a983dSmrg}
940fc5a983dSmrg
941fc5a983dSmrgBool G80GetScrnInfoRec(PciChipsets *chips, int chip)
942fc5a983dSmrg{
943fc5a983dSmrg    ScrnInfoPtr pScrn;
944fc5a983dSmrg
945fc5a983dSmrg    pScrn = xf86ConfigPciEntity(NULL, 0, chip,
946fc5a983dSmrg                                chips, NULL, NULL, NULL,
947fc5a983dSmrg                                NULL, NULL);
948fc5a983dSmrg
949fc5a983dSmrg    if(!pScrn) return FALSE;
950fc5a983dSmrg
951fc5a983dSmrg    pScrn->driverVersion    = NV_VERSION;
952fc5a983dSmrg    pScrn->driverName       = NV_DRIVER_NAME;
953fc5a983dSmrg    pScrn->name             = NV_NAME;
954fc5a983dSmrg
955fc5a983dSmrg    pScrn->PreInit          = G80PreInit;
956fc5a983dSmrg    pScrn->ScreenInit       = G80ScreenInit;
957fc5a983dSmrg    pScrn->SwitchMode       = G80SwitchMode;
958fc5a983dSmrg    pScrn->AdjustFrame      = G80AdjustFrame;
959fc5a983dSmrg    pScrn->EnterVT          = G80EnterVT;
960fc5a983dSmrg    pScrn->LeaveVT          = G80LeaveVT;
961fc5a983dSmrg    pScrn->FreeScreen       = G80FreeScreen;
962fc5a983dSmrg    // pScrn->ValidMode        = G80ValidMode;
963fc5a983dSmrg
964fc5a983dSmrg    return TRUE;
965fc5a983dSmrg}
966