1231200Smm/* $XFree86: xc/programs/Xserver/hw/xfree68/fbdev/fbdev.c,v 3.1 1996/08/18 03:54:46 dawes Exp $ */
2231200Smm/*
3231200Smm *
4231200Smm *  Author: Thomas Gerner. Taken from fbdev.c by Martin Schaller
5231200Smm *
6231200Smm *  Generic version by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
7231200Smm *
8231200Smm *  This version contains support for:
9231200Smm *
10231200Smm *	- Monochrome, 1 bitplane [mfb]
11231200Smm *	- Color, 4/8 interleaved bitplanes with 2 bytes interleave [iplan2p?]
12231200Smm */
13231200Smm
14231200Smm
15231200Smm#define fbdev_PATCHLEVEL "4"
16231200Smm
17231200Smm
18231200Smm#include "X.h"
19231200Smm#include "input.h"
20231200Smm#include "scrnintstr.h"
21231200Smm#include "pixmapstr.h"
22231200Smm#include "regionstr.h"
23231200Smm#include "mipointer.h"
24231200Smm#include "cursorstr.h"
25231200Smm#include "gcstruct.h"
26231200Smm
27231200Smm#include "compiler.h"
28231200Smm
29231200Smm#include "xf86.h"
30231200Smm#include "xf86Priv.h"
31231200Smm#include "xf86_OSlib.h"
32231200Smm#include "xf86_Config.h"
33231200Smm#include "mfb.h"
34231200Smm
35231200Smm#include "colormapst.h"
36232153Smm#include "resource.h"
37231200Smm
38231200Smm#undef MODES
39231200Smm
40231200Smm#include <sys/queue.h>
41231200Smm#include "/sys/arch/atari/dev/grfabs_reg.h"
42232153Smm#include "/sys/arch/atari/dev/viewioctl.h"
43231200Smm
44231200Smmstatic int *fbdevPrivateIndexP;
45231200Smmstatic void (*fbdevBitBlt)();
46231200Smmstatic int (*CreateDefColormap)(ScreenPtr);
47231200Smm
48231200Smmextern int mfbCreateDefColormap(ScreenPtr);
49231200Smm
50231200Smm#if defined(CONFIG_IPLAN2p2) || defined(CONFIG_IPLAN2p4) || \
51232153Smm     defined(CONFIG_IPLAN2p8)
52232153Smmextern int iplCreateDefColormap(ScreenPtr);
53231200Smm#ifdef CONFIG_IPLAN2p2
54232153Smmextern int ipl2p2ScreenPrivateIndex;
55232153Smmextern void ipl2p2DoBitblt();
56231200Smm#endif /* CONFIG_IPLAN2p2 */
57231200Smm#ifdef CONFIG_IPLAN2p4
58231200Smmextern int ipl2p4ScreenPrivateIndex;
59232153Smmextern void ipl2p4DoBitblt();
60232153Smm#endif /* CONFIG_IPLAN2p4 */
61231200Smm#ifdef CONFIG_IPLAN2p8
62232153Smmextern int ipl2p8ScreenPrivateIndex;
63232153Smmextern void ipl2p8DoBitblt();
64231200Smm#endif /* CONFIG_IPLAN2p8 */
65232153Smm#endif /* defined(CONFIG_IPLAN2p2) || defined(CONFIG_IPLAN2p4) || \
66231200Smm	  defined(CONFIG_IPLAN2p8) */
67232153Smm#ifdef CONFIG_CFB16
68232153Smmextern int cfb16ScreenPrivateIndex;
69232153Smmextern void cfb16DoBitblt();
70232153Smm#endif /* CONFIG_CFB16 */
71231200Smm
72232153Smmextern int fbdevValidTokens[];
73232153Smm
74232153Smmstatic Bool fbdevProbe(void);
75232153Smmstatic void fbdevPrintIdent(void);
76231200Smmstatic Bool fbdevSaveScreen(ScreenPtr pScreen, int on);
77232153Smmstatic Bool fbdevScreenInit(int scr_index, ScreenPtr pScreen, int argc,
78232153Smm			    char **argv);
79232153Smmstatic void fbdevEnterLeaveVT(Bool enter, int screen_idx);
80232153Smmstatic Bool fbdevCloseScreen(int screen_idx, ScreenPtr screen);
81231200Smmstatic Bool fbdevValidMode(DisplayModePtr mode);
82232153Smmstatic Bool fbdevSwitchMode(DisplayModePtr mode);
83232153Smm
84232153Smmstatic void xfree2fbdev(DisplayModePtr mode, struct view_size *var);
85232153Smmstatic void fbdev2xfree(struct view_size *var, DisplayModePtr mode);
86231200Smm
87231200Smmextern Bool xf86Exiting, xf86Resetting, xf86ProbeFailed;
88231200Smm
89231200SmmScrnInfoRec fbdevInfoRec = {
90231200Smm    FALSE,			/* Bool configured */
91232153Smm    -1,				/* int tmpIndex */
92232153Smm    -1,				/* int scrnIndex */
93232153Smm    fbdevProbe,			/* Bool (*Probe)() */
94232153Smm    fbdevScreenInit,		/* Bool (*Init)() */
95231200Smm    (Bool (*)())NoopDDA,	/* Bool (*ValidMode)() */
96232153Smm    fbdevEnterLeaveVT,		/* void (*EnterLeaveVT)() */
97232153Smm    (void (*)())NoopDDA,	/* void (*EnterLeaveMonitor)() */
98232153Smm    (void (*)())NoopDDA,	/* void (*EnterLeaveCursor)() */
99232153Smm    (void (*)())NoopDDA,	/* void (*AdjustFrame)() */
100231200Smm    (Bool (*)())NoopDDA,	/* void (*SwitchMode)() */
101232153Smm    (void (*)())NoopDDA,	/* void (*DPMSSet)() */
102232153Smm    fbdevPrintIdent,		/* void (*PrintIdent)() */
103232153Smm    8,				/* int depth */
104232153Smm    {0, },			/* xrgb weight */
105232153Smm    8,				/* int bitsPerPixel */
106232153Smm    PseudoColor,		/* int defaultVisual */
107232153Smm    -1, -1,			/* int virtualX,virtualY */
108232153Smm    -1,				/* int displayWidth */
109231200Smm    -1, -1, -1, -1,		/* int frameX0, frameY0, frameX1, frameY1 */
110232153Smm    {0, },			/* OFlagSet options */
111232153Smm    {0, },			/* OFlagSet clockOptions */
112232153Smm    {0, },			/* OFlagSet xconfigFlag */
113232153Smm    NULL,			/* char *chipset */
114232153Smm    NULL,			/* char *ramdac */
115232153Smm    {0, },			/* int dacSpeeds[MAXDACSPEEDS] */
116232153Smm    0,				/* int dacSpeed */
117232153Smm    0,				/* int clocks */
118232153Smm    {0, },			/* int clock[MAXCLOCKS] */
119248616Smm    0,				/* int maxClock */
120231200Smm    0,				/* int videoRam */
121231200Smm    0,				/* int BIOSbase */
122231200Smm    0,				/* unsigned long MemBase */
123231200Smm    240, 180,			/* int width, height */
124231200Smm    0,				/* unsigned long speedup */
125231200Smm    NULL,			/* DisplayModePtr modes */
126231200Smm    NULL,			/* MonPtr monitor */
127    NULL,			/* char *clockprog */
128    -1,				/* int textclock */
129    FALSE,			/* Bool bankedMono */
130    "FBDev",			/* char *name */
131    {0, },			/* RgbRec blackColour */
132    {0, },			/* RgbRec whiteColour */
133    fbdevValidTokens,		/* int *validTokens */
134    fbdev_PATCHLEVEL,		/* char *patchLevel */
135    0,				/* unsigned int IObase */
136    0,				/* unsigned int DACbase */
137    0,				/* unsigned int COPbase */
138    0,				/* unsigned int POSbase */
139    0,				/* unsigned int instance */
140    0,				/* int s3Madjust */
141    0,				/* int s3Nadjust */
142    0,				/* int s3MClk */
143    0,				/* int chipID */
144    0,				/* int chipRev */
145    0,				/* unsigned long VGAbase */
146    0,				/* int s3RefClk */
147    -1,				/* int s3BlankDelay */
148    0,				/* int textClockFreq */
149    NULL,			/* char *DCConfig */
150    NULL,			/* char *DCOptions */
151    0,				/* int MemClk */
152    0,				/* int LCDClk */
153#ifdef XFreeXDGA
154    0,				/* int directMode */
155    NULL,			/* void (*setBank)() */
156    0,				/* unsigned long physBase */
157    0,				/* int physSize */
158#endif
159#ifdef XF86SETUP
160    NULL,			/* void *device */
161#endif
162};
163
164static pointer fbdevVirtBase = NULL;
165
166static ScreenPtr savepScreen = NULL;
167static PixmapPtr ppix = NULL;
168
169extern miPointerScreenFuncRec xf86PointerScreenFuncs;
170
171#define NOMAPYET	(ColormapPtr)0
172
173static ColormapPtr InstalledMaps[MAXSCREENS];
174	/* current colormap for each screen */
175
176
177#define StaticGrayMask	(1 << StaticGray)
178#define GrayScaleMask	(1 << GrayScale)
179#define StaticColorMask	(1 << StaticColor)
180#define PseudoColorMask	(1 << PseudoColor)
181#define TrueColorMask	(1 << TrueColor)
182#define DirectColorMask	(1 << DirectColor)
183
184#define ALL_VISUALS	(StaticGrayMask|\
185			 GrayScaleMask|\
186			 StaticColorMask|\
187			 PseudoColorMask|\
188			 TrueColorMask|\
189			 DirectColorMask)
190
191
192typedef struct {
193    struct view_size vs;
194    bmap_t bm;
195    colormap_t colormap;
196    size_t smem_len;
197} fb_fix_screeninfo;
198
199static int fb_fd = -1;
200
201static u_long colorentry[256];
202static int colorbitshift;
203static struct view_size vs;
204static fb_fix_screeninfo fb_fix;
205
206
207static Bool UseModeDB = FALSE;
208
209
210static void open_framebuffer(void)
211{
212    char buffer[13];
213    int i;
214
215    if (fb_fd == -1) {
216	for (i = 0; i < 100; i++) {
217	    sprintf(buffer, "/dev/view%02d", i);
218	    fb_fd = open(buffer, O_RDWR);
219	    if (fb_fd < 0 && errno != EBUSY) {
220	    	FatalError("open_framebuffer: failed to open %s (%s)\n",
221	    	       buffer, strerror(errno));
222		fb_fd = -1;
223		return;
224	    } else if (fb_fd > 0) {
225		xf86Info.screenFd = fb_fd;
226		return;
227	    }
228	}
229	FatalError("open_framebuffer: Ran out of views.\n");
230    }
231}
232
233static void close_framebuffer(void)
234{
235    if (fb_fd != -1) {
236	close(fb_fd);
237	fb_fd = -1;
238    }
239}
240
241static pointer MapVidMem(int ScreenNum, unsigned long Size)
242{
243    pointer base;
244
245    open_framebuffer();
246    base = (pointer)mmap((caddr_t)0, Size, PROT_READ | PROT_WRITE,
247			 MAP_SHARED, fb_fd, (off_t)0);
248    if ((long)base == -1)
249	FatalError("MapVidMem: Could not mmap framebuffer (%s)\n",
250		   strerror(errno));
251    return(base);
252}
253
254static void UnMapVidMem(int ScreenNum, unsigned long Size)
255{
256    munmap(fbdevVirtBase, Size);
257    close_framebuffer();
258}
259
260static void fbdevUpdateColormap(ScreenPtr pScreen, int dex, int count,
261				unsigned char *rmap, unsigned char *gmap,
262				unsigned char *bmap)
263{
264    int		i;
265    colormap_t	*cmap = &fb_fix.colormap;
266
267    if (!xf86VTSema)
268	/* Switched away from server vt, do nothing. */
269	return;
270
271#if 0
272    while(count--) {
273	cmap->entry[dex] = (rmap[dex] << 16 | gmap[dex] << 8 | bmap[dex]);
274	dex++;
275    }
276#else
277    cmap->first = dex;
278    cmap->size = count;
279
280    for (i = 0; i < count; i++, dex++) {
281	cmap->entry[i] = (rmap[dex] << 16 | gmap[dex] << 8 | bmap[dex]);
282    }
283#endif
284    if (ioctl(fb_fd, VIOCSCMAP, cmap) < 0)
285	FatalError("fbdevUpdateColormap: VIOCSCMAP failed (%s)\n",
286			   strerror(errno));
287}
288
289static int fbdevListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
290{
291    *pmaps = InstalledMaps[pScreen->myNum]->mid;
292    return(1);
293}
294
295static void fbdevStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
296{
297    unsigned char rmap[256], gmap[256], bmap[256];
298    register int i;
299    register int first = -256;
300    register int priv = -256;
301    register int count = 0;
302    register int bitshift = colorbitshift;
303
304    if (pmap != InstalledMaps[pmap->pScreen->myNum])
305	return;
306
307    while (ndef--) {
308	i = pdefs->pixel;
309	if (i != priv + 1) {
310	    if (count)
311		fbdevUpdateColormap(pmap->pScreen, first, count, rmap, gmap, bmap);
312	    first = i;
313	    count = 0;
314	}
315	priv = i;
316	rmap[i] = pdefs->red >> bitshift;
317	gmap[i] = pdefs->green >> bitshift;
318	bmap[i] = pdefs->blue >> bitshift;
319	pdefs++;
320	count++;
321    }
322    if (count)
323	fbdevUpdateColormap(pmap->pScreen, first, count, rmap, gmap, bmap);
324}
325
326static void fbdevInstallColormap(ColormapPtr pmap)
327{
328    ColormapPtr oldmap = InstalledMaps[pmap->pScreen->myNum];
329    int entries = pmap->pVisual->ColormapEntries;
330    Pixel ppix[256];
331    xrgb prgb[256];
332    xColorItem defs[256];
333    int i;
334
335    if (pmap == oldmap)
336	return;
337
338    if (oldmap != NOMAPYET)
339	WalkTree(pmap->pScreen, TellLostMap, &oldmap->mid);
340
341    InstalledMaps[pmap->pScreen->myNum] = pmap;
342
343    for (i = 0 ; i < entries; i++)
344	ppix[i]=i;
345    QueryColors(pmap, entries, ppix, prgb);
346
347    for (i = 0 ; i < entries; i++) {
348	defs[i].pixel = ppix[i];
349	defs[i].red = prgb[i].red;
350	defs[i].green = prgb[i].green;
351	defs[i].blue = prgb[i].blue;
352    }
353
354    fbdevStoreColors(pmap, entries, defs);
355
356    WalkTree(pmap->pScreen, TellGainedMap, &pmap->mid);
357
358    return;
359}
360
361static void fbdevUninstallColormap(ColormapPtr pmap)
362{
363    ColormapPtr defColormap;
364
365    if (pmap != InstalledMaps[pmap->pScreen->myNum])
366	return;
367    defColormap = (ColormapPtr)LookupIDByType(pmap->pScreen->defColormap,
368    					      RT_COLORMAP);
369    if (defColormap == InstalledMaps[pmap->pScreen->myNum])
370	return;
371    (*pmap->pScreen->InstallColormap)(defColormap);
372}
373
374/*
375 *  fbdevPrintIdent -- Prints out identifying strings for drivers included in
376 *		       the server
377 */
378
379static void fbdevPrintIdent(void)
380{
381    ErrorF("   %s: Server for frame buffer device\n", fbdevInfoRec.name);
382    ErrorF("   (Patchlevel %s): mfb", fbdevInfoRec.patchLevel);
383#ifdef CONFIG_IPLAN2p2
384    ErrorF(", iplan2p2");
385#endif
386#ifdef CONFIG_IPLAN2p4
387    ErrorF(", iplan2p4");
388#endif
389#ifdef CONFIG_IPLAN2p8
390    ErrorF(", iplan2p8");
391#endif
392#ifdef CONFIG_CFB16
393    ErrorF(", cfb16");
394#endif
395    ErrorF("\n");
396}
397
398
399static Bool fbdevLookupMode(DisplayModePtr target)
400{
401    DisplayModePtr p;
402    Bool found_mode = FALSE;
403
404    for (p = fbdevInfoRec.monitor->Modes; p != NULL; p = p->next)
405	if (!strcmp(p->name, target->name)) {
406	    target->Clock          = p->Clock;
407	    target->HDisplay       = p->HDisplay;
408	    target->HSyncStart     = p->HSyncStart;
409	    target->HSyncEnd       = p->HSyncEnd;
410	    target->HTotal         = p->HTotal;
411	    target->VDisplay       = p->VDisplay;
412	    target->VSyncStart     = p->VSyncStart;
413	    target->VSyncEnd       = p->VSyncEnd;
414	    target->VTotal         = p->VTotal;
415	    target->Flags          = p->Flags;
416	    target->SynthClock     = p->SynthClock;
417	    target->CrtcHDisplay   = p->CrtcHDisplay;
418	    target->CrtcHSyncStart = p->CrtcHSyncStart;
419	    target->CrtcHSyncEnd   = p->CrtcHSyncEnd;
420	    target->CrtcHTotal     = p->CrtcHTotal;
421	    target->CrtcVDisplay   = p->CrtcVDisplay;
422	    target->CrtcVSyncStart = p->CrtcVSyncStart;
423	    target->CrtcVSyncEnd   = p->CrtcVSyncEnd;
424	    target->CrtcVTotal     = p->CrtcVTotal;
425	    target->CrtcHAdjusted  = p->CrtcHAdjusted;
426	    target->CrtcVAdjusted  = p->CrtcVAdjusted;
427	    if (fbdevValidMode(target)) {
428		found_mode = TRUE;
429		break;
430	    }
431	}
432    return(found_mode);
433}
434
435
436/*
437 *  fbdevProbe -- Probe and initialize the hardware driver
438 */
439
440static Bool fbdevProbe(void)
441{
442    DisplayModePtr pMode, pEnd;
443
444    open_framebuffer();
445
446    if (ioctl(fb_fd, VIOCGSIZE, &vs))
447	FatalError("fbdevProbe: unable to get screen params (%s)\n",
448		   strerror(errno));
449
450    pMode = fbdevInfoRec.modes;
451    if (pMode == NULL)
452	FatalError("No modes supplied in XF86Config\n");
453
454    if (!strcmp(pMode->name, "default")) {
455	ErrorF("%s %s: Using default frame buffer video mode\n", XCONFIG_GIVEN,
456	       fbdevInfoRec.name);
457	fbdevInfoRec.depth = vs.depth;
458	fbdevInfoRec.bitsPerPixel = fbdevInfoRec.depth;
459    } else {
460	ErrorF("%s %s: Using XF86Config video mode database\n", XCONFIG_GIVEN,
461	       fbdevInfoRec.name);
462	UseModeDB = TRUE;
463	pEnd = NULL;
464	fbdevInfoRec.bitsPerPixel = fbdevInfoRec.depth;
465	do {
466	    DisplayModePtr pModeSv;
467
468	    pModeSv = pMode->next;
469	    if (!fbdevLookupMode(pMode))
470		xf86DeleteMode(&fbdevInfoRec, pMode);
471	    else {
472		/*
473		 *  Successfully looked up this mode.  If pEnd isn't
474		 *  initialized, set it to this mode.
475		 */
476		if (pEnd == (DisplayModePtr)NULL)
477		    pEnd = pMode;
478	    }
479	    pMode = pModeSv;
480	} while (pMode != pEnd);
481#if 0
482	fbdevInfoRec.SwitchMode = fbdevSwitchMode;
483#endif
484    }
485
486    return(TRUE);
487}
488
489static void fbdevRestoreColors(ScreenPtr pScreen)
490{
491    ColormapPtr pmap = InstalledMaps[pScreen->myNum];
492    int entries;
493    Pixel ppix[256];
494    xrgb prgb[256];
495    xColorItem defs[256];
496    int i;
497
498    if (!pmap)
499	pmap = (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
500    entries = pmap->pVisual->ColormapEntries;
501    if (entries) {
502	for (i = 0 ; i < entries; i++)
503	    ppix[i] = i;
504	QueryColors(pmap, entries, ppix, prgb);
505
506	for (i = 0 ; i < entries; i++) {
507	    defs[i].pixel = ppix[i];
508	    defs[i].red = prgb[i].red;
509	    defs[i].green = prgb[i].green;
510	    defs[i].blue = prgb[i].blue;
511	}
512
513	fbdevStoreColors(pmap, entries, defs);
514    }
515}
516
517static Bool fbdevSaveScreen(ScreenPtr pScreen, int on)
518{
519    switch (on) {
520	case SCREEN_SAVER_ON:
521	    {
522		unsigned char map[256];
523		int i, numentries;
524
525		numentries = 1 << fb_fix.bm.depth;
526
527		for (i = 0; i < numentries; i++)
528		    map[i] = 0;
529		fbdevUpdateColormap(pScreen, 0, numentries, map, map, map);
530		return(TRUE);
531	    }
532
533	case SCREEN_SAVER_OFF:
534	    fbdevRestoreColors(pScreen);
535	    return(TRUE);
536    }
537    return(FALSE);
538}
539
540static Bool fbdevSaveScreenDummy(ScreenPtr pScreen, int on)
541{
542    return(FALSE);
543}
544
545/*
546 *  fbdevScreenInit -- Attempt to find and initialize a framebuffer
547 *		       Most of the elements of the ScreenRec are filled in.
548 *		       The video is enabled for the frame buffer...
549 *
550 *  Arguments:	scr_index	: The index of pScreen in the ScreenInfo
551 *		pScreen		: The Screen to initialize
552 *		argc		: The number of the Server's arguments.
553 *		argv		: The arguments themselves. Don't change!
554 */
555
556static Bool fbdevScreenInit(int scr_index, ScreenPtr pScreen, int argc,
557			    char **argv)
558{
559    int displayResolution = 75;	/* default to 75dpi */
560    int dxres,dyres;
561    extern int monitorResolution;
562    struct view_size *var = &vs;
563    static unsigned short bw[] = {
564	0xffff, 0x0000
565    };
566    int black, white;
567    DisplayModePtr mode;
568    int bpp, xsize, ysize;
569    char *fbtype;
570    Bool NoColormap = FALSE;
571
572    open_framebuffer();
573
574    /*
575     *  Take display resolution from the -dpi flag if specified
576     */
577
578    if (monitorResolution)
579	displayResolution = monitorResolution;
580
581    dxres = displayResolution;
582    dyres = displayResolution;
583
584    mode = fbdevInfoRec.modes;
585    if (!UseModeDB) {
586	fbdev2xfree(var, mode);
587	mode->name = "default";
588	fbdevInfoRec.virtualX = var->x;
589	fbdevInfoRec.virtualY = var->y;
590    } else
591	xfree2fbdev(mode, var);
592
593    if (ioctl(fb_fd, VIOCSSIZE, var))
594	FatalError("fbdevScreenInit: unable to set screen params (%s)\n",
595		   strerror(errno));
596
597    if (ioctl(fb_fd, VIOCGSIZE, &fb_fix.vs))
598	FatalError("ioctl(fd, VIOCGSIZE, ...)");
599
600    if (ioctl(fb_fd, VIOCGBMAP, &fb_fix.bm))
601	 FatalError("ioctl(fd, VIOCGBMAP, ...)");
602
603    fb_fix.colormap.first = 0;
604    fb_fix.colormap.size = 1 << fb_fix.bm.depth;
605    fb_fix.colormap.entry = colorentry;
606
607    if (ioctl(fb_fd, VIOCGCMAP, &fb_fix.colormap))
608	FatalError("ioctl(fd, VIOCGCMAP, ...)");
609
610    if (ioctl(fb_fd, VIOCDISPLAY, 0))
611	FatalError("ioctl(fd, VIOCDISPLAY ...)");
612
613    switch (fb_fix.colormap.red_mask)
614    {
615	case 0x0f:
616		colorbitshift = 12;
617		break;
618	case 0x3f:
619		colorbitshift = 10;
620		break;
621	default:
622		colorbitshift = 8;
623    }
624
625    fb_fix.smem_len = fb_fix.bm.bytes_per_row * fb_fix.bm.rows;
626    fbdevInfoRec.videoRam = fb_fix.smem_len>>10;
627
628    if (xf86Verbose) {
629	ErrorF("%s %s: Video memory: %dk\n", XCONFIG_PROBED, fbdevInfoRec.name,
630	       fbdevInfoRec.videoRam);
631	ErrorF("%s %s: Width %d, Height %d, Depth %d\n", XCONFIG_PROBED,
632	       fbdevInfoRec.name, fb_fix.vs.width, fb_fix.vs.height,
633	       fb_fix.vs.depth);
634    }
635
636    fbdevVirtBase = MapVidMem(scr_index, fb_fix.smem_len);
637
638
639    bpp = fb_fix.bm.depth;
640    xsize = fb_fix.vs.width;
641    ysize = fb_fix.vs.height;
642
643    switch (bpp) {
644	case 1:
645		if (xf86FlipPixels) {
646			black = 1;
647			white = 0;
648    			NoColormap = TRUE;
649		} else {
650			black = 0;
651			white = 1;
652		}
653		if ((xsize == 1280) && (ysize == 960)) {
654			int temp;
655			temp = white; white = black; black = temp;
656    			NoColormap = TRUE;
657		}
658		pScreen->blackPixel = black;
659		pScreen->whitePixel = white;
660		fbtype = "mfb";
661		mfbScreenInit(pScreen, fbdevVirtBase, xsize, ysize, dxres,
662			      dyres, xsize);
663		fbdevPrivateIndexP = NULL;
664		fbdevBitBlt = mfbDoBitblt;
665		CreateDefColormap = mfbCreateDefColormap;
666		break;
667#ifdef CONFIG_IPLAN2p2
668	case 2:
669		fbtype = "iplan2p2";
670		ipl2p2ScreenInit(pScreen, fbdevVirtBase, xsize,
671				 ysize, dxres, dyres, xsize);
672		fbdevPrivateIndexP=&ipl2p2ScreenPrivateIndex;
673		fbdevBitBlt=ipl2p2DoBitblt;
674		CreateDefColormap=iplCreateDefColormap;
675		break;
676#endif
677
678#ifdef CONFIG_IPLAN2p4
679	case 4:
680		fbtype = "iplan2p4";
681		ipl2p4ScreenInit(pScreen, fbdevVirtBase, xsize,
682				 ysize, dxres, dyres, xsize);
683		fbdevPrivateIndexP=&ipl2p4ScreenPrivateIndex;
684		fbdevBitBlt=ipl2p4DoBitblt;
685		CreateDefColormap=iplCreateDefColormap;
686		break;
687#endif
688
689#ifdef CONFIG_IPLAN2p8
690	case 8:
691		fbtype = "iplan2p8";
692		ipl2p8ScreenInit(pScreen, fbdevVirtBase, xsize,
693			    	 ysize, dxres, dyres, xsize);
694		fbdevPrivateIndexP=&ipl2p8ScreenPrivateIndex;
695		fbdevBitBlt=ipl2p8DoBitblt;
696		CreateDefColormap=iplCreateDefColormap;
697		break;
698#endif
699
700#ifdef CONFIG_CFB16
701	case 16:
702		fbtype = "cfb16";
703		cfb16ScreenInit(pScreen, fbdevVirtBase, xsize, ysize,
704				dxres, dyres, xsize);
705		fbdevPrivateIndexP = &cfb16ScreenPrivateIndex;
706		fbdevBitBlt = cfb16DoBitblt;
707		CreateDefColormap = cfbCreateDefColormap;
708		break;
709#endif
710	default:
711		FatalError("Unsupported bitmap depth %d\n", bpp);
712	}
713
714    ErrorF("%s %s: Using %s driver\n", XCONFIG_PROBED, fbdevInfoRec.name,
715	   fbtype);
716    pScreen->CloseScreen = fbdevCloseScreen;
717    pScreen->SaveScreen = (SaveScreenProcPtr)fbdevSaveScreenDummy;
718
719    if ((bpp <=8) && !NoColormap) {
720        pScreen->SaveScreen = (SaveScreenProcPtr)fbdevSaveScreen;
721	pScreen->InstallColormap = fbdevInstallColormap;
722	pScreen->UninstallColormap = fbdevUninstallColormap;
723	pScreen->ListInstalledColormaps = fbdevListInstalledColormaps;
724	pScreen->StoreColors = fbdevStoreColors;
725    }
726    miDCInitialize(pScreen, &xf86PointerScreenFuncs);
727
728    if (!(*CreateDefColormap)(pScreen))
729	return(FALSE);
730
731    savepScreen = pScreen;
732
733    return(TRUE);
734}
735
736/*
737 *  fbdevEnterLeaveVT -- Grab/ungrab the current VT completely.
738 */
739
740static void fbdevEnterLeaveVT(Bool enter, int screen_idx)
741{
742    BoxRec pixBox;
743    RegionRec pixReg;
744    DDXPointRec pixPt;
745    PixmapPtr pspix;
746    ScreenPtr pScreen = savepScreen;
747
748    if (!xf86Resetting && !xf86Exiting) {
749	pixBox.x1 = 0; pixBox.x2 = pScreen->width;
750	pixBox.y1 = 0; pixBox.y2 = pScreen->height;
751	pixPt.x = 0; pixPt.y = 0;
752	(pScreen->RegionInit)(&pixReg, &pixBox, 1);
753	if (fbdevPrivateIndexP)
754	    pspix = (PixmapPtr)pScreen->devPrivates[*fbdevPrivateIndexP].ptr;
755	else
756	    pspix = (PixmapPtr)pScreen->devPrivate;
757    }
758
759    if (enter) {
760
761	/*
762	 *  point pspix back to fbdevVirtBase, and copy the dummy buffer to the
763	 *  real screen.
764	 */
765	if (!xf86Resetting)
766	    if (pspix->devPrivate.ptr != fbdevVirtBase && ppix) {
767		pspix->devPrivate.ptr = fbdevVirtBase;
768		(*fbdevBitBlt)(&ppix->drawable, &pspix->drawable, GXcopy,
769			       &pixReg, &pixPt, ~0);
770	    }
771	if (ppix) {
772	    (pScreen->DestroyPixmap)(ppix);
773	    ppix = NULL;
774	}
775
776	if (!xf86Resetting) {
777	    /* Update the colormap */
778	    ColormapPtr pmap = InstalledMaps[pScreen->myNum];
779	    int entries;
780	    Pixel ppix[256];
781	    xrgb prgb[256];
782	    xColorItem defs[256];
783	    int i;
784
785	    if (!pmap)
786		pmap = (ColormapPtr) LookupIDByType(pScreen->defColormap,
787						    RT_COLORMAP);
788	    entries = pmap->pVisual->ColormapEntries;
789	    if (entries) {
790		for (i = 0 ; i < entries; i++)
791		ppix[i] = i;
792		QueryColors (pmap, entries, ppix, prgb);
793
794		for (i = 0 ; i < entries; i++) {
795		    defs[i].pixel = ppix[i];
796		    defs[i].red = prgb[i].red;
797		    defs[i].green = prgb[i].green;
798		    defs[i].blue = prgb[i].blue;
799		}
800
801		fbdevStoreColors(pmap, entries, defs);
802	    }
803	}
804    } else {
805	/*
806	 *  Create a dummy pixmap to write to while VT is switched out.
807	 *  Copy the screen to that pixmap
808	 */
809	if (!xf86Exiting) {
810	    ppix = (pScreen->CreatePixmap)(pScreen, pScreen->width,
811	    				   pScreen->height, pScreen->rootDepth);
812	    if (ppix) {
813		(*fbdevBitBlt)(&pspix->drawable, &ppix->drawable, GXcopy,
814			       &pixReg, &pixPt, ~0);
815		pspix->devPrivate.ptr = ppix->devPrivate.ptr;
816	    }
817	}
818	if(ioctl(fb_fd, VIOCREMOVE, 0))
819	    FatalError("ioctl(fd, VIOCREMOVE ...)");
820
821	UnMapVidMem(screen_idx, fb_fix.smem_len);
822    }
823}
824
825/*
826 *  fbdevCloseScreen -- Called to ensure video is enabled when server exits.
827 */
828
829static Bool fbdevCloseScreen(int screen_idx, ScreenPtr screen)
830{
831    /*
832     *  Hmm... The server may shut down even if it is not running on the
833     *  current vt. Let's catch this case here.
834     */
835    xf86Exiting = TRUE;
836    if (xf86VTSema)
837	fbdevEnterLeaveVT(LEAVE, screen_idx);
838    else if (ppix) {
839	/*
840	 *  7-Jan-94 CEG: The server is not running on the current vt.
841	 *  Free the screen snapshot taken when the server vt was left.
842	 */
843	(savepScreen->DestroyPixmap)(ppix);
844	ppix = NULL;
845    }
846    return(TRUE);
847}
848
849/*
850 *  fbdevValidMode -- Check whether a mode is valid. If necessary, values will
851 *		      be rounded up by the Frame Buffer Device
852 */
853
854static Bool fbdevValidMode(DisplayModePtr mode)
855{
856    return(1);
857}
858
859/*
860 *  fbdevSwitchMode -- Change the video mode `on the fly'
861 */
862
863static Bool fbdevSwitchMode(DisplayModePtr mode)
864{
865ErrorF("fbdevSwitchMode called\n");
866#if 0
867    struct view_size var = vs;
868    ScreenPtr pScreen = savepScreen;
869    BoxRec pixBox;
870    RegionRec pixReg;
871    DDXPointRec pixPt;
872    PixmapPtr pspix, ppix;
873    Bool res = FALSE;
874
875    xfree2fbdev(mode, &var);
876    var.x = fbdevInfoRec.frameX0;
877    var.y = fbdevInfoRec.frameY0;
878
879    /* Save the screen image */
880    pixBox.x1 = 0; pixBox.x2 = pScreen->width;
881    pixBox.y1 = 0; pixBox.y2 = pScreen->height;
882    pixPt.x = 0; pixPt.y = 0;
883    (pScreen->RegionInit)(&pixReg, &pixBox, 1);
884    if (fbdevPrivateIndexP)
885	pspix = (PixmapPtr)pScreen->devPrivates[*fbdevPrivateIndexP].ptr;
886    else
887	pspix = (PixmapPtr)pScreen->devPrivate;
888    ppix = (pScreen->CreatePixmap)(pScreen, pScreen->width, pScreen->height,
889    				   pScreen->rootDepth);
890    if (ppix)
891	(*fbdevBitBlt)(&pspix->drawable, &ppix->drawable, GXcopy, &pixReg,
892		       &pixPt, ~0);
893
894    if (!ioctl(fb_fd, VIOCSSIZE, &var)) {
895	/* Restore the colormap */
896	fbdevRestoreColors(pScreen);
897	/* restore the screen image */
898	if (ppix)
899	    (*fbdevBitBlt)(&ppix->drawable, &pspix->drawable, GXcopy, &pixReg,
900	    		   &pixPt, ~0);
901	vs.width = var.width;
902	vs.height = var.height;
903	res = TRUE;
904    }
905    if (ppix)
906	(pScreen->DestroyPixmap)(ppix);
907
908    return(res);
909#endif
910    return(0);
911}
912
913
914/*
915 *  Convert timings between the XFree style and the Frame Buffer Device style
916 */
917
918static void xfree2fbdev(DisplayModePtr mode, struct view_size *var)
919{
920    var->width = mode->HDisplay;
921    var->height = mode->VDisplay;
922    var->depth = fbdevInfoRec.bitsPerPixel;
923    var->x = mode->HDisplay;
924    var->y = mode->VDisplay;
925}
926
927static void fbdev2xfree(struct view_size *var, DisplayModePtr mode)
928{
929    mode->Clock = 0;
930    mode->HDisplay = var->width;
931    mode->HSyncStart = 0;
932    mode->HSyncEnd = 0;
933    mode->HTotal = 0;
934    mode->VDisplay = var->height;
935    mode->VSyncStart = 0;
936    mode->VSyncEnd = 0;
937    mode->VTotal = 0;
938    mode->Flags = 0;
939    mode->SynthClock = mode->Clock;
940    mode->CrtcHDisplay = mode->HDisplay;
941    mode->CrtcHSyncStart = mode->HSyncStart;
942    mode->CrtcHSyncEnd = mode->HSyncEnd;
943    mode->CrtcHTotal = mode->HTotal;
944    mode->CrtcVDisplay = mode->VDisplay;
945    mode->CrtcVSyncStart = mode->VSyncStart;
946    mode->CrtcVSyncEnd = mode->VSyncEnd;
947    mode->CrtcVTotal = mode->VTotal;
948    mode->CrtcHAdjusted = FALSE;
949    mode->CrtcVAdjusted = FALSE;
950}
951