/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/dummy/dummy_driver.c,v 1.5tsi Exp $ */ /* * Copyright 2002, SuSE Linux AG, Author: Egbert Eich */ /* All drivers should typically include these */ #include "xf86.h" #include "xf86_OSproc.h" #include "xf86_ansic.h" /* This is used for module versioning */ #include "xf86Version.h" /* All drivers initialising the SW cursor need this */ #include "mipointer.h" /* All drivers implementing backing store need this */ #include "mibstore.h" /* All drivers using the mi colormap manipulation need this */ #include "micmap.h" /* identifying atom needed by magnifiers */ #include "Xatom.h" #include "property.h" #include "xf86cmap.h" #include "xf86fbman.h" #include "fb.h" #include "picturestr.h" #include "xf86xv.h" #include "Xv.h" /* * Driver data structures. */ #include "dummy.h" /* These need to be checked */ #include "X.h" #include "Xproto.h" #include "scrnintstr.h" #include "servermd.h" #define _XF86DGA_SERVER_ #include "extensions/xf86dgastr.h" /* Mandatory functions */ static const OptionInfoRec * DUMMYAvailableOptions(int chipid, int busid); static void DUMMYIdentify(int flags); static Bool DUMMYProbe(DriverPtr drv, int flags); static Bool DUMMYPreInit(ScrnInfoPtr pScrn, int flags); static Bool DUMMYScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); static Bool DUMMYEnterVT(int scrnIndex, int flags); static void DUMMYLeaveVT(int scrnIndex, int flags); static Bool DUMMYCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool DUMMYCreateWindow(WindowPtr pWin); static void DUMMYFreeScreen(int scrnIndex, int flags); static ModeStatus DUMMYValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags); static Bool DUMMYSaveScreen(ScreenPtr pScreen, int mode); /* Internally used functions */ static Bool dummyModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); static void dummySave(ScrnInfoPtr pScrn); static void dummyRestore(ScrnInfoPtr pScrn, Bool restoreText); /* static void DUMMYDisplayPowerManagementSet(ScrnInfoPtr pScrn, */ /* int PowerManagementMode, int flags); */ #define VERSION 4000 #define DUMMY_NAME "DUMMY" #define DUMMY_DRIVER_NAME "dummy" #define DUMMY_MAJOR_VERSION 0 #define DUMMY_MINOR_VERSION 1 #define DUMMY_PATCHLEVEL 0 /* * This is intentionally screen-independent. It indicates the binding * choice made in the first PreInit. */ static int pix24bpp = 0; /* * This contains the functions needed by the server after loading the driver * module. It must be supplied, and gets passed back by the SetupProc * function in the dynamic case. In the static case, a reference to this * is compiled in, and this requires that the name of this DriverRec be * an upper-case version of the driver name. */ DriverRec DUMMY = { VERSION, DUMMY_DRIVER_NAME, DUMMYIdentify, DUMMYProbe, DUMMYAvailableOptions, NULL, 0 }; static SymTabRec DUMMYChipsets[] = { { DUMMY_CHIP, "dummy" }, { -1, NULL } }; typedef enum { OPTION_SW_CURSOR } DUMMYOpts; static const OptionInfoRec DUMMYOptions[] = { { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; /* * List of symbols from other modules that this module references. This * list is used to tell the loader that it is OK for symbols here to be * unresolved providing that it hasn't been told that they haven't been * told that they are essential via a call to xf86LoaderReqSymbols() or * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about * unresolved symbols that are not required. */ static const char *fbSymbols[] = { "fbPictureInit", "fbScreenInit", NULL }; static const char *ramdacSymbols[] = { "xf86CreateCursorInfoRec", "xf86DestroyCursorInfoRec", "xf86InitCursor", NULL }; #ifdef XFree86LOADER static MODULESETUPPROTO(dummySetup); static XF86ModuleVersionInfo dummyVersRec = { "dummy", MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, DUMMY_MAJOR_VERSION, DUMMY_MINOR_VERSION, DUMMY_PATCHLEVEL, ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_VIDEODRV, {0,0,0,0} }; /* * This is the module init data. * Its name has to be the driver name followed by ModuleData */ XF86ModuleData dummyModuleData = { &dummyVersRec, dummySetup, NULL }; static pointer dummySetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; if (!setupDone) { setupDone = TRUE; xf86AddDriver(&DUMMY, module, 0); /* * Modules that this driver always requires can be loaded here * by calling LoadSubModule(). */ /* * Tell the loader about symbols from other modules that this module * might refer to. */ LoaderRefSymLists(fbSymbols, ramdacSymbols, NULL); /* * The return value must be non-NULL on success even though there * is no TearDownProc. */ return (pointer)1; } else { if (errmaj) *errmaj = LDR_ONCEONLY; return NULL; } } #endif /* XFree86LOADER */ static Bool DUMMYGetRec(ScrnInfoPtr pScrn) { /* * Allocate a DUMMYRec, and hook it into pScrn->driverPrivate. * pScrn->driverPrivate is initialised to NULL, so we can check if * the allocation has already been done. */ if (pScrn->driverPrivate != NULL) return TRUE; pScrn->driverPrivate = xnfcalloc(sizeof(DUMMYRec), 1); if (pScrn->driverPrivate == NULL) return FALSE; return TRUE; } static void DUMMYFreeRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate == NULL) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } static const OptionInfoRec * DUMMYAvailableOptions(int chipid, int busid) { return DUMMYOptions; } /* Mandatory */ static void DUMMYIdentify(int flags) { xf86PrintChipsets(DUMMY_NAME, "Driver for Dummy chipsets", DUMMYChipsets); } /* Mandatory */ static Bool DUMMYProbe(DriverPtr drv, int flags) { Bool foundScreen = FALSE; int numDevSections, numUsed; GDevPtr *devSections; int i; if (flags & PROBE_DETECT) return FALSE; /* * Find the config file Device sections that match this * driver, and return if there are none. */ if ((numDevSections = xf86MatchDevice(DUMMY_DRIVER_NAME, &devSections)) <= 0) { return FALSE; } numUsed = numDevSections; if (numUsed > 0) { for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn = NULL; int entityIndex = xf86ClaimNoSlot(drv,DUMMY_CHIP,devSections[i],TRUE); /* Allocate a ScrnInfoRec and claim the slot */ if ((pScrn = xf86AllocateScreen(drv,0 ))) { xf86AddEntityToScreen(pScrn,entityIndex); pScrn->driverVersion = VERSION; pScrn->driverName = DUMMY_DRIVER_NAME; pScrn->name = DUMMY_NAME; pScrn->Probe = DUMMYProbe; pScrn->PreInit = DUMMYPreInit; pScrn->ScreenInit = DUMMYScreenInit; pScrn->SwitchMode = DUMMYSwitchMode; pScrn->AdjustFrame = DUMMYAdjustFrame; pScrn->EnterVT = DUMMYEnterVT; pScrn->LeaveVT = DUMMYLeaveVT; pScrn->FreeScreen = DUMMYFreeScreen; pScrn->ValidMode = DUMMYValidMode; foundScreen = TRUE; } } } return foundScreen; } # define RETURN \ { DUMMYFreeRec(pScrn);\ return FALSE;\ } /* Mandatory */ Bool DUMMYPreInit(ScrnInfoPtr pScrn, int flags) { ClockRangePtr clockRanges; int i; DUMMYPtr dPtr; int maxClock = 230000; GDevPtr device = xf86GetEntityInfo(pScrn->entityList[0])->device; if (flags & PROBE_DETECT) return TRUE; /* Allocate the DummyRec driverPrivate */ if (!DUMMYGetRec(pScrn)) { return FALSE; } dPtr = DUMMYPTR(pScrn); pScrn->chipset = (char *)xf86TokenToString(DUMMYChipsets, DUMMY_CHIP); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Chipset is a DUMMY\n"); pScrn->monitor = pScrn->confScreen->monitor; if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) return FALSE; else { /* Check that the returned depth is one we support */ switch (pScrn->depth) { case 8: case 15: case 16: case 24: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by this driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); if (pScrn->depth == 8) pScrn->rgbBits = 8; /* Get the depth24 pixmap format */ if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); /* * This must happen after pScrn->display has been set because * xf86SetWeight references it. */ if (pScrn->depth > 8) { /* The defaults are OK for us */ rgb zeros = {0, 0, 0}; if (!xf86SetWeight(pScrn, zeros, zeros)) { return FALSE; } else { /* XXX check that weight returned is supported */ ; } } if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; if (pScrn->depth > 1) { Gamma zeros = {0.0, 0.0, 0.0}; if (!xf86SetGamma(pScrn, zeros)) return FALSE; } xf86CollectOptions(pScrn, device->options); /* Process the options */ if (!(dPtr->Options = xalloc(sizeof(DUMMYOptions)))) return FALSE; memcpy(dPtr->Options, DUMMYOptions, sizeof(DUMMYOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, dPtr->Options); xf86GetOptValBool(dPtr->Options, OPTION_SW_CURSOR,&dPtr->swCursor); if (device->videoRam != 0) { pScrn->videoRam = device->videoRam; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", pScrn->videoRam); } else { pScrn->videoRam = 4096; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", pScrn->videoRam); } if (device->dacSpeeds[0] != 0) { maxClock = device->dacSpeeds[0]; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Max Clock: %d kHz\n", maxClock); } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max Clock: %d kHz\n", maxClock); } pScrn->progClock = TRUE; /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. */ clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1); clockRanges->next = NULL; clockRanges->ClockMulFactor = 1; clockRanges->minClock = 11000; /* guessed §§§ */ clockRanges->maxClock = 300000; clockRanges->clockIndex = -1; /* programmable */ clockRanges->interlaceAllowed = TRUE; clockRanges->doubleScanAllowed = TRUE; /* Subtract memory for HW cursor */ { int apertureSize = (pScrn->videoRam * 1024); i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, 256, 2048,(8 * pScrn->bitsPerPixel), 128, 2048, pScrn->display->virtualX, pScrn->display->virtualY, apertureSize, LOOKUP_BEST_REFRESH); if (i == -1) RETURN; } /* Prune the modes marked as invalid */ xf86PruneDriverModes(pScrn); if (i == 0 || pScrn->modes == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); RETURN; } /* * Set the CRTC parameters for all of the modes based on the type * of mode, and the chipset's interlace requirements. * * Calling this is required if the mode->Crtc* values are used by the * driver and if the driver doesn't provide code to set them. They * are not pre-initialised at all. */ xf86SetCrtcForModes(pScrn, 0); /* Set the current mode to the first in the list */ pScrn->currentMode = pScrn->modes; /* Print the list of modes being used */ xf86PrintModes(pScrn); /* If monitor resolution is set on the command line, use it */ xf86SetDpi(pScrn, 0, 0); if (xf86LoadSubModule(pScrn, "fb") == NULL) { RETURN; } xf86LoaderReqSymLists(fbSymbols, NULL); if (!dPtr->swCursor) { if (!xf86LoadSubModule(pScrn, "ramdac")) RETURN; xf86LoaderReqSymLists(ramdacSymbols, NULL); } /* We have no contiguous physical fb in physical memory */ pScrn->memPhysBase = 0; pScrn->fbOffset = 0; return TRUE; } #undef RETURN /* Mandatory */ static Bool DUMMYEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; /* Should we re-save the text mode on each VT enter? */ if(!dummyModeInit(pScrn, pScrn->currentMode)) return FALSE; DUMMYAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); return TRUE; } /* Mandatory */ static void DUMMYLeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; dummyRestore(pScrn, TRUE); } static void DUMMYLoadPalette( ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual ){ int i, index, shift, Gshift; DUMMYPtr dPtr = DUMMYPTR(pScrn); switch(pScrn->depth) { case 15: shift = Gshift = 1; break; case 16: shift = 0; Gshift = 0; break; default: shift = Gshift = 0; break; } for(i = 0; i < numColors; i++) { index = indices[i]; dPtr->colors[index].red = colors[index].red << shift; dPtr->colors[index].green = colors[index].green << Gshift; dPtr->colors[index].blue = colors[index].blue << shift; } } static ScrnInfoPtr DUMMYScrn; /* static-globalize it */ /* Mandatory */ static Bool DUMMYScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn; DUMMYPtr dPtr; int ret; VisualPtr visual; /* * we need to get the ScrnInfoRec for this screen, so let's allocate * one first thing */ pScrn = xf86Screens[pScreen->myNum]; dPtr = DUMMYPTR(pScrn); DUMMYScrn = pScrn; if (!(dPtr->FBBase = xalloc(pScrn->videoRam * 1024))) return FALSE; /* * next we save the current state and setup the first mode */ dummySave(pScrn); if (!dummyModeInit(pScrn,pScrn->currentMode)) return FALSE; DUMMYAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); /* * Reset visual list. */ miClearVisualTypes(); /* Setup the visuals we support. */ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) return FALSE; if (!miSetPixmapDepths ()) return FALSE; /* * Call the framebuffer layer's ScreenInit function, and fill in other * pScreen fields. */ ret = fbScreenInit(pScreen, dPtr->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel); if (!ret) return FALSE; if (pScrn->depth > 8) { /* Fixup RGB ordering */ visual = pScreen->visuals + pScreen->numVisuals; while (--visual >= pScreen->visuals) { if ((visual->class | DynamicClass) == DirectColor) { visual->offsetRed = pScrn->offset.red; visual->offsetGreen = pScrn->offset.green; visual->offsetBlue = pScrn->offset.blue; visual->redMask = pScrn->mask.red; visual->greenMask = pScrn->mask.green; visual->blueMask = pScrn->mask.blue; } } } /* must be after RGB ordering fixed */ fbPictureInit(pScreen, 0, 0); xf86SetBlackWhitePixels(pScreen); DUMMYDGAInit(pScreen); if (dPtr->swCursor) xf86DrvMsg(scrnIndex, X_CONFIG, "Using Software Cursor.\n"); { BoxRec AvailFBArea; int lines = pScrn->videoRam * 1024 / (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); AvailFBArea.x1 = 0; AvailFBArea.y1 = 0; AvailFBArea.x2 = pScrn->displayWidth; AvailFBArea.y2 = lines; xf86InitFBManager(pScreen, &AvailFBArea); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %i scanlines of offscreen memory \n" , lines - pScrn->virtualY); } miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); xf86SetSilkenMouse(pScreen); /* Initialise cursor functions */ miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); if (!dPtr->swCursor) { /* HW cursor functions */ if (!DUMMYCursorInit(pScreen)) { xf86DrvMsg(scrnIndex, X_ERROR, "Hardware cursor initialization failed\n"); return FALSE; } } /* Initialise default colourmap */ if(!miCreateDefColormap(pScreen)) return FALSE; if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, DUMMYLoadPalette, NULL, CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; /* DUMMYInitVideo(pScreen); */ pScreen->SaveScreen = DUMMYSaveScreen; /* Wrap the current CloseScreen function */ dPtr->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = DUMMYCloseScreen; /* Wrap the current CreateWindow function */ dPtr->CreateWindow = pScreen->CreateWindow; pScreen->CreateWindow = DUMMYCreateWindow; /* Report any unused options (only for the first generation) */ if (serverGeneration == 1) { xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); } return TRUE; } /* Mandatory */ Bool DUMMYSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { return dummyModeInit(xf86Screens[scrnIndex], mode); } /* Mandatory */ void DUMMYAdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn; int Base; pScrn = xf86Screens[scrnIndex]; Base = (y * pScrn->displayWidth + x) >> 2; /* Scale Base by the number of bytes per pixel. */ switch (pScrn->depth) { case 8 : break; case 15 : case 16 : Base *= 2; break; case 24 : Base *= 3; break; default : break; } } /* Mandatory */ static Bool DUMMYCloseScreen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; DUMMYPtr dPtr = DUMMYPTR(pScrn); if(pScrn->vtSema){ dummyRestore(pScrn, TRUE); xfree(dPtr->FBBase); } if (dPtr->CursorInfo) xf86DestroyCursorInfoRec(dPtr->CursorInfo); pScrn->vtSema = FALSE; pScreen->CloseScreen = dPtr->CloseScreen; return (*pScreen->CloseScreen)(scrnIndex, pScreen); } /* Optional */ static void DUMMYFreeScreen(int scrnIndex, int flags) { DUMMYFreeRec(xf86Screens[scrnIndex]); } static Bool DUMMYSaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = NULL; DUMMYPtr dPtr; if (pScreen != NULL) { pScrn = xf86Screens[pScreen->myNum]; dPtr = DUMMYPTR(pScrn); dPtr->screenSaver = xf86IsUnblank(mode); } return TRUE; } /* Optional */ static ModeStatus DUMMYValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { return(MODE_OK); } static void dummySave(ScrnInfoPtr pScrn) { } static void dummyRestore(ScrnInfoPtr pScrn, Bool restoreText) { } static Bool dummyModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { dummyRestore(pScrn, FALSE); return(TRUE); } Atom VFB_PROP = 0; #define VFB_PROP_NAME "VFB_IDENT" static Bool DUMMYCreateWindow(WindowPtr pWin) { DUMMYPtr dPtr = DUMMYPTR(DUMMYScrn); WindowPtr pWinRoot; int ret; ret = dPtr->CreateWindow(pWin); if(ret != TRUE) return(ret); if(dPtr->prop == FALSE) { pWinRoot = WindowTable[DUMMYScrn->pScreen->myNum]; if (! ValidAtom(VFB_PROP)) VFB_PROP = MakeAtom(VFB_PROP_NAME, strlen(VFB_PROP_NAME), 1); ret = ChangeWindowProperty(pWinRoot, VFB_PROP, XA_STRING, 8, PropModeReplace, (int)4, (pointer)"TRUE", FALSE); if( ret != Success) ErrorF("Could not set VFB root window property"); dPtr->prop = TRUE; return TRUE; } return TRUE; }