Site hosted by Angelfire.com: Build your free website today!

Hands-on Projects for the Linux Graphics Subsystem

New book from Christos Karayiannis

Available in Amazon Kindle format at:

amazon.com   amazon.co.uk   amazon.de   amazon.es   amazon.fr   amazon.it

Driver's PreInit()

We continue with InitOutput():

    /*
     * Call the driver's PreInit()'s to complete initialisation for the first
     * generation.
     */
    
    for (i = 0; i < xf86NumScreens; i++) {
	xf86EnableAccess(xf86Screens[i]);
	if (xf86Screens[i]->PreInit &&
	    xf86Screens[i]->PreInit(xf86Screens[i], 0))
	    xf86Screens[i]->configured = TRUE;
    }
    for (i = 0; i < xf86NumScreens; i++)
	if (!xf86Screens[i]->configured)
	    xf86DeleteScreen(i--, 0);

As seen in the Driver Processing section function xf86Screens[i]->PreInit for the current example (MGA driver) is MGAPreInit(). The first argument passed to the PreInit() is xf86Screens[i], which is the current ScrnInfoRec that is further initialized. Therefore the process of filling the fields of this struct that started in section 3.2.2.6 continues here. For the example we follow the xf86Screens[] items are two.

MGAPreInit()

The next paragraphs describe the MGAPreInit() functionality. In the code that follows pScrn is the current xf86Screens[] item, passed as the first argument.

    pMga = MGAPTR(pScrn);

pMga points to the driverPrivate field of the currently processed item of xf86Screens[] (the ScrnInfoRec passed as first argument). It is defined in mga.h as:

#define MGAPTR(p) ((MGAPtr)((p)->driverPrivate))

    /*
     * Set our own access functions, which control the vgaioen bit.
     */
    pMga->Access.AccessDisable = VgaIODisable;
    pMga->Access.AccessEnable = VgaIOEnable;
    pMga->Access.arg = pMga;
    xf86SetAccessFuncs(pMga->pEnt, &pMga->Access, &pMga->Access);
    ...
    /* Set pScrn->monitor */
    pScrn->monitor = pScrn->confScreen->monitor;

    /* Prefer 24bpp fb unless the Overlay option is set, or DRI is
     * supported.
     */
    flags24 = Support24bppFb | Support32bppFb | SupportConvert32to24;
. . .
    if (pMga->SecondCrtc)
	flags24 = Support32bppFb;

    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
	return FALSE;
    } else {
	/* Check that the returned depth is one we support */
	switch (pScrn->depth) {
	case 8:
	case 15:
	case 16:
	case 24:
	    /* OK */
	    break;

xf86SetDepthBpp() is implemented in xf86Helper.c. It sets the following fields of the ScrnInfoRec that is passed as first argument to MGAPreInit():

depth
bitsPerPixel
pixmap24
bitsPerPixelFrom 
depthFrom


    pScrn->progClock = TRUE;

    /* Collect all of the relevant option flags (fill in pScrn->options) */
    xf86CollectOptions(pScrn, NULL);

    /* Process the options */
    if (!(pMga->Options = xalloc(sizeof(MGAOptions))))
	return FALSE;
    memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions));
    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options);

For xf86CollectOptions() we read at its comment:

 * xf86CollectOptions collects the options from each of the config file
 * sections used by the screen and puts the combined list in pScrn->options.

The memcpy() that follows copies the contents of MGAOptions[] to pMga->Options. MGAOptions[] is defined in mga_driver.c as:

static const OptionInfoRec MGAOptions[] = {
    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_OVERLAY,		"Overlay",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_MGA_SDRAM,		"MGASDRAM",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_FBDEV,		"UseFBDev",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,	{0}, FALSE },
    { OPTION_OVERCLOCK_MEM,	"OverclockMem",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
    { OPTION_ROTATE,		"Rotate",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_TEXTURED_VIDEO,	"TexturedVideo",OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_CRTC2HALF,		"Crtc2Half",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_CRTC2RAM,		"Crtc2Ram",	OPTV_INTEGER,	{0}, FALSE },
    { OPTION_INT10,		"Int10",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_AGP_MODE,		"AGPMode",	OPTV_INTEGER,	{0}, FALSE },
    { OPTION_AGP_SIZE,		"AGPSize",      OPTV_INTEGER,   {0}, FALSE },
    { OPTION_DIGITAL1,		"DigitalScreen1",OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_DIGITAL2,		"DigitalScreen2",OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_TV,		"TV",		OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_TVSTANDARD,	"TVStandard",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_CABLETYPE,		"CableType",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_NOHAL,		"NoHal",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_SWAPPED_HEAD,	"SwappedHead",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_DRI,		"DRI",		OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_MERGEDFB,		"MergedFB",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_HSYNC2,	"Monitor2HSync",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_VREFRESH2,	"Monitor2VRefresh",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_MONITOR2POS,   "Monitor2Position",	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_METAMODES,   "MetaModes",  	OPTV_ANYSTR,	{0}, FALSE },
    { OPTION_OLDDMA,		"OldDmaInit",	OPTV_BOOLEAN,	{0}, FALSE },
    { OPTION_PCIDMA,		"ForcePciDma",	OPTV_BOOLEAN,	{0}, FALSE },
    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
};

xf86ProcessOptions() then processes each option by calling ParseOptionValue() to assign the option's value at the 'value' field of the option (OptionInfoRec), according to the option type (p->value.num, p->value.str. etc). Also if a non NULL value exists the 'found' field becomes TRUE. When this finishes the fourth column of MGAOptions[], copied now to
pMga->Options, is filled.

OptionInfoRec is defined as:

typedef struct {
    int                 token;
    const char*         name;
    OptionValueType     type;
    ValueUnion          value;
    Bool                found;
} OptionInfoRec, *OptionInfoPtr;

    /* Set the bits per RGB for 8bpp mode */
    if (pScrn->depth == 8)
	pScrn->rgbBits = 8;

The following part uses xf86ReturnOptValBool() to lookup some options from pMga->Options to find id the found field of the option is set. The respective filed of pMga is then set. For instance if the option UseFBDev is set then pMga->FBDev becomes TRUE.

    if (xf86GetOptValBool(pMga->Options, OPTION_HW_CURSOR, &pMga->HWCursor)) {
	from = X_CONFIG;
    }

    /* For compatibility, accept this too (as an override) */
    if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) {
	pMga->NoAccel = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) {
	pMga->UsePCIRetry = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
	pMga->SyncOnGreen = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHOWCACHE, FALSE)) {
	pMga->ShowCache = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_MGA_SDRAM, FALSE)) {
	pMga->HasSDRAM = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Has SDRAM\n");
    }
    if (xf86GetOptValFreq(pMga->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
	pMga->MemClk = (int)(real * 1000.0);
    }
    if ((s = xf86GetOptValString(pMga->Options, OPTION_OVERLAY))) {
      if (!*s || !xf86NameCmp(s, "8,24") || !xf86NameCmp(s, "24,8")) {
	if(pScrn->bitsPerPixel == 32 && pMga->SecondCrtc == FALSE) {
	    pMga->Overlay8Plus24 = TRUE;
	    if(!xf86GetOptValInteger(
			pMga->Options, OPTION_COLOR_KEY,&(pMga->colorKey)))
		pMga->colorKey = TRANSPARENCY_KEY;
	    pScrn->colorKey = pMga->colorKey;
	    pScrn->overlayFlags = OVERLAY_8_32_PLANAR;
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
				"PseudoColor overlay enabled\n");
	} else {
	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
	         "Option \"Overlay\" is only supported in 32 bits per pixel on"
		 "the first CRTC\n");
	}
      } else {
	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		"\"%s\" is not a valid value for Option \"Overlay\"\n", s);
      }
    }

    if(xf86GetOptValInteger(pMga->Options, OPTION_VIDEO_KEY, &(pMga->videoKey))) {
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
				pMga->videoKey);
    } else {
	pMga->videoKey =  (1 << pScrn->offset.red) |
			  (1 << pScrn->offset.green) |
        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHADOW_FB, FALSE)) {
	pMga->ShadowFB = TRUE;
	pMga->NoAccel = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_FBDEV, FALSE)) {
	pMga->FBDev = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		"Using framebuffer device\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_OVERCLOCK_MEM, FALSE)) {
	pMga->OverclockMem = TRUE;
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overclocking memory\n");
    }
    if (xf86ReturnOptValBool(pMga->Options, OPTION_TEXTURED_VIDEO, FALSE)) {
	pMga->TexturedVideo = TRUE;
    }

NOTES:

Blue colored code indicates that a value is assigned to a ScrnInfoRec field.

REFERENCES:

MGA man page
xorg.conf man page
MGA Options
MGA driver options
Xorg man page
Graphic Stack Overview
RELNOTES2
RGB color model