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