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