1 /*
2  *  Linux Frame Buffer Device Configuration
3  *
4  *  � Copyright 1995-1999 by Geert Uytterhoeven
5  *		       (Geert.Uytterhoeven@cs.kuleuven.ac.be)
6  *
7  *  --------------------------------------------------------------------------
8  *
9  *  This file is subject to the terms and conditions of the GNU General Public
10  *  License. See the file COPYING in the main directory of the Linux
11  *  distribution for more details.
12  *
13  *  Petr Vandrovec <vandrove@vc.cvut.cz>:
14  *           -grayscale, -rgba, -nonstd, VGA modes reporting
15  *
16  *  Brad Midgley <brad@exodus.pht.com>:
17  *           -match
18  *
19  */
20 
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/ioctl.h>
29 #include <sys/stat.h>
30 
31 #include "QF/sys.h"
32 
33 #include "fbset.h"
34 
35 struct file;
36 struct inode;
37 
38 /* Default Frame Buffer Special Device Node */
39 #define DEFAULT_FRAMEBUFFER	"/dev/fb0"
40 
41 /* Default Video Mode Database File */
42 #define DEFAULT_MODEDBFILE	"/etc/fb.modes"
43 
44 /* Command Line Options */
45 
46 static const char *ProgramName;
47 
48 static int Opt_test = 0;
49 static int Opt_show = 0;
50 static int Opt_info = 0;
51 static int Opt_version = 0;
52 static int Opt_verbose = 0;
53 static int Opt_xfree86 = 0;
54 static int Opt_change = 0;
55 static int Opt_all = 0;
56 
57 static const char *Opt_fb = NULL;
58 const char *Opt_modedb = DEFAULT_MODEDBFILE;
59 static const char *Opt_xres = NULL;
60 static const char *Opt_yres = NULL;
61 static const char *Opt_vxres = NULL;
62 static const char *Opt_vyres = NULL;
63 static const char *Opt_depth = NULL;
64 static const char *Opt_pixclock = NULL;
65 static const char *Opt_left = NULL;
66 static const char *Opt_right = NULL;
67 static const char *Opt_upper = NULL;
68 static const char *Opt_lower = NULL;
69 static const char *Opt_hslen = NULL;
70 static const char *Opt_vslen = NULL;
71 static const char *Opt_accel = NULL;
72 static const char *Opt_hsync = NULL;
73 static const char *Opt_vsync = NULL;
74 static const char *Opt_csync = NULL;
75 static const char *Opt_gsync = NULL;
76 static const char *Opt_extsync = NULL;
77 static const char *Opt_bcast = NULL;
78 static const char *Opt_laced = NULL;
79 static const char *Opt_double = NULL;
80 static const char *Opt_move = NULL;
81 static const char *Opt_step = NULL;
82 static const char *Opt_modename = NULL;
83 static const char *Opt_rgba = NULL;
84 static const char *Opt_nonstd = NULL;
85 static const char *Opt_grayscale = NULL;
86 static const char *Opt_matchyres = NULL;
87 
88 static struct {
89     const char *name;
90     const char **value;
91     const int change;
92 } Options[] = {
93     { "-fb", &Opt_fb, 0 },
94     { "-db", &Opt_modedb, 0 },
95     { "-xres", &Opt_xres, 1 },
96     { "-yres", &Opt_yres, 1 },
97     { "-vxres", &Opt_vxres, 1 },
98     { "-vyres", &Opt_vyres, 1 },
99     { "-depth", &Opt_depth, 1 },
100     { "-nonstd", &Opt_nonstd, 1},
101     { "-pixclock", &Opt_pixclock, 1 },
102     { "-left", &Opt_left, 1 },
103     { "-right", &Opt_right, 1 },
104     { "-upper", &Opt_upper, 1 },
105     { "-lower", &Opt_lower, 1 },
106     { "-hslen", &Opt_hslen, 1 },
107     { "-vslen", &Opt_vslen, 1 },
108     { "-accel", &Opt_accel, 1 },
109     { "-hsync", &Opt_hsync, 1 },
110     { "-vsync", &Opt_vsync, 1 },
111     { "-csync", &Opt_csync, 1 },
112     { "-gsync", &Opt_gsync, 1 },
113     { "-extsync", &Opt_extsync, 1 },
114     { "-bcast", &Opt_bcast, 1 },
115     { "-laced", &Opt_laced, 1 },
116     { "-double", &Opt_double, 1 },
117     { "-move", &Opt_move, 1 },
118     { "-step", &Opt_step, 1 },
119     { "-rgba", &Opt_rgba, 1 },
120     { "-grayscale", &Opt_grayscale, 1 },
121     { NULL, NULL, 0 }
122 };
123 
124 /* Video Mode Database */
125 struct VideoMode *VideoModes = NULL;
126 
127 /* Hardware Text Modes */
128 static struct textentry {
129     __u32 id;
130     const char *name;
131 } Textmodes[] = {
132     { FB_AUX_TEXT_MDA, "Monochrome text" },
133     { FB_AUX_TEXT_CGA, "CGA/EGA/VGA Color text" },
134     { FB_AUX_TEXT_S3_MMIO, "S3 MMIO fasttext" },
135     { FB_AUX_TEXT_MGA_STEP16, "MGA Millennium I step 16 text" },
136     { FB_AUX_TEXT_MGA_STEP8, "MGA step 8 text" },
137 };
138 
139 static struct textentry VGAModes[] = {
140 #ifdef HAVE_FB_AUX_VGA_PLANES_VGA4
141     { FB_AUX_VGA_PLANES_VGA4, "VGA 16 colors in 4 planes" },
142 #endif
143 #ifdef HAVE_FB_AUX_VGA_PLANES_CFB4
144     { FB_AUX_VGA_PLANES_CFB4, "VGA 16 colors in 1 plane" },
145 #endif
146 #ifdef HAVE_FB_AUX_VGA_PLANES_CFB8
147     { FB_AUX_VGA_PLANES_CFB8, "VGA 256 colors in 4 planes" },
148 #endif
149     /* last entry has name == NULL */
150     { 0,					  NULL}
151 };
152 
153 /* Hardware Accelerators */
154 static struct accelentry {
155     __u32 id;
156     const char *name;
157 } Accelerators[] = {
158     { FB_ACCEL_NONE, "No" },
159     { FB_ACCEL_ATARIBLITT, "Atari Blitter" },
160     { FB_ACCEL_AMIGABLITT, "Amiga Blitter" },
161     { FB_ACCEL_S3_TRIO64, "S3 Trio64" },
162     { FB_ACCEL_NCR_77C32BLT, "NCR 77C32BLT" },
163     { FB_ACCEL_S3_VIRGE, "S3 ViRGE" },
164     { FB_ACCEL_ATI_MACH64GX, "ATI Mach64GX" },
165     { FB_ACCEL_DEC_TGA, "DEC 21030 TGA" },
166     { FB_ACCEL_ATI_MACH64CT, "ATI Mach64CT" },
167     { FB_ACCEL_ATI_MACH64VT, "ATI Mach64VT" },
168     { FB_ACCEL_ATI_MACH64GT, "ATI Mach64GT" },
169     { FB_ACCEL_SUN_CREATOR, "Sun Creator/Creator3D" },
170     { FB_ACCEL_SUN_CGSIX, "Sun cg6" },
171     { FB_ACCEL_SUN_LEO, "Sun leo/zx" },
172     { FB_ACCEL_IMS_TWINTURBO, "IMS Twin Turbo" },
173     { FB_ACCEL_3DLABS_PERMEDIA2, "3Dlabs Permedia 2" },
174     { FB_ACCEL_MATROX_MGA2064W, "Matrox MGA2064W (Millennium)" },
175     { FB_ACCEL_MATROX_MGA1064SG, "Matrox MGA1064SG (Mystique)" },
176     { FB_ACCEL_MATROX_MGA2164W, "Matrox MGA2164W (Millennium II)" },
177     { FB_ACCEL_MATROX_MGA2164W_AGP, "Matrox MGA2164W (Millennium II AGP)" },
178     { FB_ACCEL_MATROX_MGAG100, "Matrox G100 (Productiva G100)" },
179     { FB_ACCEL_MATROX_MGAG200, "Matrox G200 (Millennium, Mystique)" },
180     { FB_ACCEL_SUN_CG14, "Sun cg14" },
181     { FB_ACCEL_SUN_BWTWO, "Sun bw2" },
182     { FB_ACCEL_SUN_CGTHREE, "Sun cg3" },
183     { FB_ACCEL_SUN_TCX, "Sun tcx" },
184     { FB_ACCEL_MATROX_MGAG400, "Matrox G400" },
185 };
186 
187 /* Current Video Mode */
188 struct VideoMode Current;
189 
190 /* Function Prototypes */
191 
192 static int OpenFrameBuffer(const char *name);
193 static void CloseFrameBuffer(int fh);
194 static int GetVarScreenInfo(int fh, struct fb_var_screeninfo *var);
195 static int SetVarScreenInfo(int fh, struct fb_var_screeninfo *var);
196 static int GetFixScreenInfo(int fh, struct fb_fix_screeninfo *fix);
197 static int atoboolean(const char *var);
198 struct VideoMode *FindVideoMode(const char *name);
199 static void ModifyVideoMode(struct VideoMode *vmode);
200 static void DisplayVModeInfo(struct VideoMode *vmode);
201 static void DisplayFBInfo(struct fb_fix_screeninfo *fix);
202 static int FillScanRates(struct VideoMode *vmode);
203 static void Usage(void);
204 
205 
206 #undef puts
207 #undef printf
208 #define Die Sys_Printf
209 #define puts(s) Sys_Printf("%s\n",(s))
210 #define printf Sys_Printf
211 
212 
213 /* Open the Frame Buffer Device */
214 int
OpenFrameBuffer(const char * name)215 OpenFrameBuffer (const char *name)
216 {
217     int fh;
218 
219     if (Opt_verbose)
220 	printf("Opening frame buffer device `%s'\n", name);
221 
222     if ((fh = open(name, O_RDWR)) == -1)
223 	Die("open %s: %s\n", name, strerror(errno));
224     return fh;
225 }
226 
227 /* Close the Frame Buffer Device */
228 void
CloseFrameBuffer(int fh)229 CloseFrameBuffer (int fh)
230 {
231     close(fh);
232 }
233 
234 /* Get the Variable Part of the Screen Info */
235 int
GetVarScreenInfo(int fh,struct fb_var_screeninfo * var)236 GetVarScreenInfo (int fh, struct fb_var_screeninfo *var)
237 {
238     if (ioctl(fh, FBIOGET_VSCREENINFO, var)) {
239 	Die("ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno));
240 	return -1;
241     }
242     return 0;
243 }
244 
245 /* Set (and Get) the Variable Part of the Screen Info */
246 int
SetVarScreenInfo(int fh,struct fb_var_screeninfo * var)247 SetVarScreenInfo (int fh, struct fb_var_screeninfo *var)
248 {
249     if (ioctl(fh, FBIOPUT_VSCREENINFO, var)) {
250 	Die("ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
251 	return -1;
252     }
253     return 0;
254 }
255 
256 /* Get the Fixed Part of the Screen Info */
257 int
GetFixScreenInfo(int fh,struct fb_fix_screeninfo * fix)258 GetFixScreenInfo (int fh, struct fb_fix_screeninfo *fix)
259 {
260     if (ioctl(fh, FBIOGET_FSCREENINFO, fix)) {
261 	Die("ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno));
262 	return -1;
263     }
264     return 0;
265 }
266 
267 /* Conversion Routines */
268 void
ConvertFromVideoMode(const struct VideoMode * vmode,struct fb_var_screeninfo * var)269 ConvertFromVideoMode (const struct VideoMode *vmode,
270 					  struct fb_var_screeninfo *var)
271 {
272     memset(var, 0, sizeof(struct fb_var_screeninfo));
273     var->xres = vmode->xres;
274     var->yres = vmode->yres;
275     var->xres_virtual = vmode->vxres;
276     var->yres_virtual = vmode->vyres;
277     var->bits_per_pixel = vmode->depth;
278     var->nonstd = vmode->nonstd;
279 
280     if (Opt_test)
281 		var->activate = FB_ACTIVATE_TEST;
282     else
283 		var->activate = FB_ACTIVATE_NOW;
284     if (Opt_all)
285 		var->activate = FB_ACTIVATE_ALL;
286 
287     var->accel_flags = vmode->accel_flags;
288     var->pixclock = vmode->pixclock;
289     var->left_margin = vmode->left;
290     var->right_margin = vmode->right;
291     var->upper_margin = vmode->upper;
292     var->lower_margin = vmode->lower;
293     var->hsync_len = vmode->hslen;
294     var->vsync_len = vmode->vslen;
295 
296     if (vmode->hsync == HIGH)
297 		var->sync |= FB_SYNC_HOR_HIGH_ACT;
298     if (vmode->vsync == HIGH)
299 		var->sync |= FB_SYNC_VERT_HIGH_ACT;
300     if (vmode->csync == HIGH)
301 		var->sync |= FB_SYNC_COMP_HIGH_ACT;
302     if (vmode->gsync == HIGH)
303 		var->sync |= FB_SYNC_ON_GREEN;
304     if (vmode->extsync == TRUE)
305 		var->sync |= FB_SYNC_EXT;
306     if (vmode->bcast == TRUE)
307 		var->sync |= FB_SYNC_BROADCAST;
308 
309     if (vmode->laced == TRUE)
310 		var->vmode = FB_VMODE_INTERLACED;
311     else if (vmode->dblscan == TRUE)
312 		var->vmode = FB_VMODE_DOUBLE;
313     else
314 		var->vmode = FB_VMODE_NONINTERLACED;
315 
316     var->vmode |= FB_VMODE_CONUPDATE;
317     var->red.length = vmode->red.length;
318     var->red.offset = vmode->red.offset;
319     var->green.length = vmode->green.length;
320     var->green.offset = vmode->green.offset;
321     var->blue.length = vmode->blue.length;
322     var->blue.offset = vmode->blue.offset;
323     var->transp.length = vmode->transp.length;
324     var->transp.offset = vmode->transp.offset;
325     var->grayscale = vmode->grayscale;
326 }
327 
328 void
ConvertToVideoMode(const struct fb_var_screeninfo * var,struct VideoMode * vmode)329 ConvertToVideoMode (const struct fb_var_screeninfo *var,
330 					struct VideoMode *vmode)
331 {
332     vmode->name = NULL;
333     vmode->xres = var->xres;
334     vmode->yres = var->yres;
335     vmode->vxres = var->xres_virtual;
336     vmode->vyres = var->yres_virtual;
337     vmode->depth = var->bits_per_pixel;
338     vmode->nonstd = var->nonstd;
339     vmode->accel_flags = var->accel_flags;
340     vmode->pixclock = var->pixclock;
341     vmode->left = var->left_margin;
342     vmode->right = var->right_margin;
343     vmode->upper = var->upper_margin;
344     vmode->lower = var->lower_margin;
345     vmode->hslen = var->hsync_len;
346     vmode->vslen = var->vsync_len;
347     vmode->hsync = var->sync & FB_SYNC_HOR_HIGH_ACT ? HIGH : LOW;
348     vmode->vsync = var->sync & FB_SYNC_VERT_HIGH_ACT ? HIGH : LOW;
349     vmode->csync = var->sync & FB_SYNC_COMP_HIGH_ACT ? HIGH : LOW;
350     vmode->gsync = var->sync & FB_SYNC_ON_GREEN ? TRUE : FALSE;
351     vmode->extsync = var->sync & FB_SYNC_EXT ? TRUE : FALSE;
352     vmode->bcast = var->sync & FB_SYNC_BROADCAST ? TRUE : FALSE;
353     vmode->grayscale = var->grayscale;
354     vmode->laced = FALSE;
355     vmode->dblscan = FALSE;
356 
357     switch (var->vmode & FB_VMODE_MASK) {
358 	case FB_VMODE_INTERLACED:
359 	    vmode->laced = TRUE;
360 	    break;
361 	case FB_VMODE_DOUBLE:
362 	    vmode->dblscan = TRUE;
363 	    break;
364     }
365 
366     vmode->red.length = var->red.length;
367     vmode->red.offset = var->red.offset;
368     vmode->green.length = var->green.length;
369     vmode->green.offset = var->green.offset;
370     vmode->blue.length = var->blue.length;
371     vmode->blue.offset = var->blue.offset;
372     vmode->transp.length = var->transp.length;
373     vmode->transp.offset = var->transp.offset;
374     FillScanRates(vmode);
375 }
376 
377 
378 static int
atoboolean(const char * var)379 atoboolean (const char *var)
380 {
381     int value = 0;
382 
383     if (!strcasecmp (var, "false") || !strcasecmp (var, "low") ||
384 		!strcasecmp (var, "no") || !strcasecmp (var, "off") ||
385 		!strcmp (var, "0"))
386 		value = 0;
387     else if (!strcasecmp (var, "true") || !strcasecmp (var, "high") ||
388 			 !strcasecmp (var, "yes") || !strcasecmp (var, "on") ||
389 			 !strcmp (var, "1"))
390 		value = 1;
391     else
392 		Die("Invalid value `%s'\n", var);
393 
394     return value;
395 }
396 
397 void
AddVideoMode(const struct VideoMode * vmode)398 AddVideoMode (const struct VideoMode *vmode)
399 {
400     struct VideoMode *vmode2;
401 
402     if (FindVideoMode(vmode->name))
403 		Die("%s:%d: Duplicate mode name `%s'\n", Opt_modedb, line,
404 			vmode->name);
405     vmode2 = malloc(sizeof(struct VideoMode));
406 	SYS_CHECKMEM (vmode2);
407     *vmode2 = *vmode;
408     if (!FillScanRates(vmode2))
409 		Die("%s:%d: Bad video mode `%s'\n", Opt_modedb, line, vmode2->name);
410     vmode2->next = VideoModes;
411     VideoModes = vmode2;
412 }
413 
414 /* Read the Video Mode Database */
415 void
ReadModeDB(void)416 ReadModeDB (void)
417 {
418     if (Opt_verbose)
419 	printf("Reading mode database from file `%s'\n", Opt_modedb);
420 
421     if (!(yyin = fopen(Opt_modedb, "r"))) {
422 	Die("fopen %s: %s\n", Opt_modedb, strerror(errno));
423 	return;
424     }
425     yyparse();
426     fclose(yyin);
427 }
428 
429 static void
getColor(struct color * color,const char ** opt)430 getColor (struct color *color, const char** opt)
431 {
432     char* ptr;
433 
434     color->length = 0;
435     color->offset = 0;
436     ptr = (char*)(*opt);
437     if (!ptr)
438 	return;
439     color->length = strtoul(ptr, &ptr, 0);
440     if (!ptr)
441 		return;
442     if (*ptr == '/')
443 		color->offset = strtoul(ptr+1, &ptr, 0);
444     if (ptr) {
445 		while (*ptr && isspace(*ptr))
446 			ptr++;
447 		if (*ptr == ',') {
448 			ptr++;
449 		} else if (*ptr)
450 			Die("Bad RGBA syntax, rL/rO,gL/gO,bL/bO,tL/tO or rL,gL,bL,tL\n");
451     }
452     *opt = ptr;
453     return;
454 }
455 
456 void
makeRGBA(struct VideoMode * vmode,const char * opt)457 makeRGBA (struct VideoMode *vmode, const char* opt)
458 {
459     getColor(&vmode->red, &opt);
460     getColor(&vmode->green, &opt);
461     getColor(&vmode->blue, &opt);
462     getColor(&vmode->transp, &opt);
463 }
464 
465 /* Find a Video Mode */
466 struct VideoMode
FindVideoMode(const char * name)467 *FindVideoMode (const char *name)
468 {
469     struct VideoMode *vmode;
470 
471     for (vmode = VideoModes; vmode; vmode = vmode->next)
472 	if (!strcmp(name, vmode->name))
473 	    break;
474 
475     return vmode;
476 }
477 
478 /* Modify a Video Mode */
479 static void
ModifyVideoMode(struct VideoMode * vmode)480 ModifyVideoMode (struct VideoMode *vmode)
481 {
482     u_int hstep = 8, vstep = 2;
483 
484     if (Opt_xres)
485 		vmode->xres = strtoul(Opt_xres, NULL, 0);
486     if (Opt_yres)
487 		vmode->yres = strtoul(Opt_yres, NULL, 0);
488     if (Opt_vxres)
489 		vmode->vxres = strtoul(Opt_vxres, NULL, 0);
490     if (Opt_vyres)
491 		vmode->vyres = strtoul(Opt_vyres, NULL, 0);
492     if (Opt_depth)
493 		vmode->depth = strtoul(Opt_depth, NULL, 0);
494     if (Opt_nonstd)
495 		vmode->nonstd = strtoul(Opt_nonstd, NULL, 0);
496     if (Opt_accel)
497 		vmode->accel_flags = atoboolean(Opt_accel) ? FB_ACCELF_TEXT : 0;
498     if (Opt_pixclock)
499 		vmode->pixclock = strtoul(Opt_pixclock, NULL, 0);
500     if (Opt_left)
501 		vmode->left = strtoul(Opt_left, NULL, 0);
502     if (Opt_right)
503 		vmode->right = strtoul(Opt_right, NULL, 0);
504     if (Opt_upper)
505 		vmode->upper = strtoul(Opt_upper, NULL, 0);
506     if (Opt_lower)
507 		vmode->lower = strtoul(Opt_lower, NULL, 0);
508     if (Opt_hslen)
509 		vmode->hslen = strtoul(Opt_hslen, NULL, 0);
510     if (Opt_vslen)
511 		vmode->vslen = strtoul(Opt_vslen, NULL, 0);
512     if (Opt_hsync)
513 		vmode->hsync = atoboolean(Opt_hsync);
514     if (Opt_vsync)
515 		vmode->vsync = atoboolean(Opt_vsync);
516     if (Opt_csync)
517 		vmode->csync = atoboolean(Opt_csync);
518     if (Opt_gsync)
519 		vmode->gsync = atoboolean(Opt_gsync);
520     if (Opt_extsync)
521 		vmode->extsync = atoboolean(Opt_extsync);
522     if (Opt_bcast)
523 		vmode->bcast = atoboolean(Opt_bcast);
524     if (Opt_laced)
525 		vmode->laced = atoboolean(Opt_laced);
526     if (Opt_double)
527 		vmode->dblscan = atoboolean(Opt_double);
528     if (Opt_grayscale)
529 		vmode->grayscale = atoboolean(Opt_grayscale);
530     if (Opt_step)
531 		hstep = vstep = strtoul(Opt_step, NULL, 0);
532     if (Opt_matchyres)
533         vmode->vyres = vmode->yres;
534     if (Opt_move) {
535 	if (!strcasecmp(Opt_move, "left")) {
536 	    if (hstep > vmode->left)
537 			Die("The left margin cannot be negative\n");
538 	    vmode->left -= hstep;
539 	    vmode->right += hstep;
540 	} else if (!strcasecmp(Opt_move, "right")) {
541 	    if (hstep > vmode->right)
542 			Die("The right margin cannot be negative\n");
543 	    vmode->left += hstep;
544 	    vmode->right -= hstep;
545 	} else if (!strcasecmp(Opt_move, "up")) {
546 	    if (vstep > vmode->upper)
547 			Die("The upper margin cannot be negative\n");
548 	    vmode->upper -= vstep;
549 	    vmode->lower += vstep;
550 	} else if (!strcasecmp(Opt_move, "down")) {
551 	    if (vstep > vmode->lower)
552 			Die("The lower margin cannot be negative\n");
553 	    vmode->upper += vstep;
554 	    vmode->lower -= vstep;
555 	} else
556 	    Die("Invalid direction `%s'\n", Opt_move);
557     }
558     if (Opt_rgba)
559 		makeRGBA(vmode, Opt_rgba);
560     if (!FillScanRates(vmode))
561 		Die("Bad video mode\n");
562 }
563 
564 /* Display the Video Mode Information */
565 static void
DisplayVModeInfo(struct VideoMode * vmode)566 DisplayVModeInfo (struct VideoMode *vmode)
567 {
568     u_int		res, sstart, send, total;
569 
570     puts("");
571     if (!Opt_xfree86) {
572 		printf("mode \"%dx%d", vmode->xres, vmode->yres);
573 		if (vmode->pixclock) {
574 			printf("-%d\"\n", (int)(vmode->vrate+0.5));
575 			printf("    # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n",
576 				   vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate);
577 		} else
578 			puts("\"");
579 		printf("    geometry %d %d %d %d %d\n", vmode->xres, vmode->yres,
580 			   vmode->vxres, vmode->vyres, vmode->depth);
581 		printf("    timings %d %d %d %d %d %d %d\n", vmode->pixclock,
582 			   vmode->left, vmode->right, vmode->upper, vmode->lower,
583 			   vmode->hslen, vmode->vslen);
584 		if (vmode->hsync)
585 			puts("    hsync high");
586 		if (vmode->vsync)
587 			puts("    vsync high");
588 		if (vmode->csync)
589 			puts("    csync high");
590 		if (vmode->gsync)
591 			puts("    gsync true");
592 		if (vmode->extsync)
593 			puts("    extsync true");
594 		if (vmode->bcast)
595 			puts("    bcast true");
596 		if (vmode->laced)
597 			puts("    laced true");
598 		if (vmode->dblscan)
599 			puts("    double true");
600 		if (vmode->nonstd)
601             printf("    nonstd %u\n", vmode->nonstd);
602 		if (vmode->accel_flags)
603 			puts("    accel true");
604 		if (vmode->grayscale)
605 			puts("    grayscale true");
606 		printf("    rgba %u/%u,%u/%u,%u/%u,%u/%u\n",
607 			   vmode->red.length, vmode->red.offset, vmode->green.length,
608 			   vmode->green.offset, vmode->blue.length, vmode->blue.offset,
609 			   vmode->transp.length, vmode->transp.offset);
610 		puts("endmode\n");
611     } else {
612 		printf("Mode \"%dx%d\"\n", vmode->xres, vmode->yres);
613 		if (vmode->pixclock) {
614 			printf("    # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n",
615 				   vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate);
616 			printf("    DotClock %5.3f\n", vmode->drate/1E6+0.001);
617 		} else
618 			puts("    DotClock Unknown");
619 		res = vmode->xres;
620 		sstart = res+vmode->right;
621 		send = sstart+vmode->hslen;
622 		total = send+vmode->left;
623 		printf("    HTimings %d %d %d %d\n", res, sstart, send, total);
624 		res = vmode->yres;
625 		sstart = res+vmode->lower;
626 		send = sstart+vmode->vslen;
627 		total = send+vmode->upper;
628 		printf("    VTimings %d %d %d %d\n", res, sstart, send, total);
629 		printf("    Flags   ");
630 		if (vmode->laced)
631 			printf(" \"Interlace\"");
632 		if (vmode->dblscan)
633 			printf(" \"DoubleScan\"");
634 		if (vmode->hsync)
635 			printf(" \"+HSync\"");
636 		else
637 			printf(" \"-HSync\"");
638 		if (vmode->vsync)
639 			printf(" \"+VSync\"");
640 		else
641 			printf(" \"-VSync\"");
642 		if (vmode->csync)
643 			printf(" \"Composite\"");
644 		if (vmode->extsync)
645 			puts("    # Warning: XFree86 doesn't support extsync\n");
646 		if (vmode->bcast)
647 			printf(" \"bcast\"");
648 		if (vmode->accel_flags)
649 			puts("    # Warning: XFree86 doesn't support accel\n");
650 		if (vmode->grayscale)
651 			puts("    # Warning: XFree86 doesn't support grayscale\n");
652 		puts("\nEndMode\n");
653     }
654 }
655 
656 /* Display the Frame Buffer Device Information */
657 static void
DisplayFBInfo(struct fb_fix_screeninfo * fix)658 DisplayFBInfo (struct fb_fix_screeninfo *fix)
659 {
660     size_t i;
661 
662     puts("Frame buffer device information:");
663     printf("    Name        : %s\n", fix->id);
664     printf("    Address     : %p\n", (void *)fix->smem_start);
665     printf("    Size        : %d\n", fix->smem_len);
666     printf("    Type        : ");
667     switch (fix->type) {
668 	case FB_TYPE_PACKED_PIXELS:
669 	    puts("PACKED PIXELS");
670 	    break;
671 	case FB_TYPE_PLANES:
672 	    puts("PLANES");
673 	    break;
674 	case FB_TYPE_INTERLEAVED_PLANES:
675 	    printf("INTERLEAVED PLANES (%d bytes interleave)\n",
676 		   fix->type_aux);
677 	    break;
678 	case FB_TYPE_TEXT:
679 	    for (i = 0; i < sizeof(Textmodes)/sizeof(*Textmodes); i++)
680 			if (fix->type_aux == Textmodes[i].id)
681 				break;
682 	    if (i < sizeof(Textmodes)/sizeof(*Textmodes))
683 			puts(Textmodes[i].name);
684 	    else
685 			printf("Unknown text (%d)\n", fix->type_aux);
686 	    break;
687 	case FB_TYPE_VGA_PLANES:
688 	    {
689 	    	struct textentry *t;
690 
691 			for (t = VGAModes; t->name; t++)
692 				if (fix->type_aux == t->id)
693 					break;
694 			if (t->name)
695 				puts(t->name);
696 			else
697 	            printf("Unknown VGA mode (%d)\n", fix->type_aux);
698 	    }
699 	    break;
700 	default:
701 	    printf("%d (UNKNOWN)\n", fix->type);
702 	    printf("    Type_aux    : %d\n", fix->type_aux);
703 	    break;
704     }
705     printf("    Visual      : ");
706     switch (fix->visual) {
707 	case FB_VISUAL_MONO01:
708 	    puts("MONO01");
709 	    break;
710 	case FB_VISUAL_MONO10:
711 	    puts("MONO10");
712 	    break;
713 	case FB_VISUAL_TRUECOLOR:
714 	    puts("TRUECOLOR");
715 	    break;
716 	case FB_VISUAL_PSEUDOCOLOR:
717 	    puts("PSEUDOCOLOR");
718 	    break;
719 	case FB_VISUAL_DIRECTCOLOR:
720 	    puts("DIRECTCOLOR");
721 	    break;
722 	case FB_VISUAL_STATIC_PSEUDOCOLOR:
723 	    puts("STATIC PSEUDOCOLOR");
724 	    break;
725 	default:
726 	    printf("%d (UNKNOWN)\n", fix->visual);
727 	    break;
728     }
729     printf("    XPanStep    : %d\n", fix->xpanstep);
730     printf("    YPanStep    : %d\n", fix->ypanstep);
731     printf("    YWrapStep   : %d\n", fix->ywrapstep);
732     printf("    LineLength  : %d\n", fix->line_length);
733     if (fix->mmio_len) {
734 		printf("    MMIO Address: %p\n", (void *)fix->mmio_start);
735 		printf("    MMIO Size   : %d\n", fix->mmio_len);
736     }
737     printf("    Accelerator : ");
738     for (i = 0; i < sizeof(Accelerators)/sizeof(*Accelerators); i++)
739 		if (fix->accel == Accelerators[i].id)
740 			break;
741     if (i < sizeof(Accelerators)/sizeof(*Accelerators))
742 		puts(Accelerators[i].name);
743     else
744 		printf("Unknown (%d)\n", fix->accel);
745 }
746 
747 /* Calculate the Scan Rates for a Video Mode */
748 static int
FillScanRates(struct VideoMode * vmode)749 FillScanRates (struct VideoMode *vmode)
750 {
751     u_int htotal = vmode->left+vmode->xres+vmode->right+vmode->hslen;
752     u_int vtotal = vmode->upper+vmode->yres+vmode->lower+vmode->vslen;
753 
754     if (vmode->dblscan)
755 		vtotal <<= 2;
756     else if (!vmode->laced)
757 		vtotal <<= 1;
758 
759     if (!htotal || !vtotal)
760 		return 0;
761 
762     if (vmode->pixclock) {
763 		vmode->drate = 1E12/vmode->pixclock;
764 		vmode->hrate = vmode->drate/htotal;
765 		vmode->vrate = vmode->hrate/vtotal*2;
766     } else {
767 		vmode->drate = 0;
768 		vmode->hrate = 0;
769 		vmode->vrate = 0;
770     }
771 
772     return 1;
773 }
774 
775 /* Print the Usage Template and Exit */
776 static void
Usage(void)777 Usage (void)
778 {
779     puts(FBSET_VERSION);
780     printf("\nUsage: %s [options] [mode]\n\n"
781 		   "Valid options:\n"
782 		   "  General options:\n"
783 		   "    -h, --help         : display this usage information\n"
784 		   "    --test             : don't change, just test whether the mode "
785 		   "is "
786 		   "valid\n"
787 		   "    -s, --show         : display video mode settings\n"
788 		   "    -i, --info         : display all frame buffer information\n"
789 		   "    -v, --verbose      : verbose mode\n"
790 		   "    -V, --version      : print version information\n"
791 		   "    -x, --xfree86      : XFree86 compatibility mode\n"
792 		   "    -a, --all          : change all virtual consoles on this "
793 		   "device\n"
794 		   "  Frame buffer special device nodes:\n"
795 		   "    -fb <device>       : processed frame buffer device\n"
796 		   "                         (default is " DEFAULT_FRAMEBUFFER ")\n"
797 		   "  Video mode database:\n"
798 		   "    -db <file>         : video mode database file\n"
799 		   "                         (default is " DEFAULT_MODEDBFILE ")\n"
800 		   "  Display geometry:\n"
801 		   "    -xres <value>      : horizontal resolution (in pixels)\n"
802 		   "    -yres <value>      : vertical resolution (in pixels)\n"
803 		   "    -vxres <value>     : virtual horizontal resolution (in "
804 		   "pixels)\n"
805 		   "    -vyres <value>     : virtual vertical resolution (in pixels)\n"
806 		   "    -depth <value>     : display depth (in bits per pixel)\n"
807 		   "    -nonstd <value>    : select nonstandard video mode\n"
808 		   "    -g, --geometry ... : set all geometry parameters at once\n"
809 		   "    -match             : set virtual vertical resolution by "
810 		   "virtual resolution\n"
811 		   "  Display timings:\n"
812 		   "    -pixclock <value>  : pixel clock (in picoseconds)\n"
813 		   "    -left <value>      : left margin (in pixels)\n"
814 		   "    -right <value>     : right margin (in pixels)\n"
815 		   "    -upper <value>     : upper margin (in pixel lines)\n"
816 		   "    -lower <value>     : lower margin (in pixel lines)\n"
817 		   "    -hslen <value>     : horizontal sync length (in pixels)\n"
818 		   "    -vslen <value>     : vertical sync length (in pixel lines)\n"
819 		   "    -t, --timings ...  : set all timing parameters at once\n"
820 		   "  Display flags:\n"
821 		   "    -accel <value>     : hardware text acceleration enable (false "
822 		   "or true)\n"
823 		   "    -hsync <value>     : horizontal sync polarity (low or high)\n"
824 		   "    -vsync <value>     : vertical sync polarity (low or high)\n"
825 		   "    -csync <value>     : composite sync polarity (low or high)\n"
826 		   "    -gsync <value>     : synch on green (false or true)\n"
827 		   "    -extsync <value>   : external sync enable (false or true)\n"
828 		   "    -bcast <value>     : broadcast enable (false or true)\n"
829 		   "    -laced <value>     : interlace enable (false or true)\n"
830 		   "    -double <value>    : doublescan enable (false or true)\n"
831 		   "    -rgba <r,g,b,a>    : recommended length of color entries\n"
832 		   "    -grayscale <value> : grayscale enable (false or true)\n"
833 		   "  Display positioning:\n"
834 		   "    -move <direction>  : move the visible part (left, right, up "
835 		   "or down)\n"
836 		   "    -step <value>      : step increment (in pixels or pixel "
837 		   "lines)\n"
838 		   "                         (default is 8 horizontal, 2 vertical)\n",
839 		   ProgramName);
840 }
841 
842 /* Main Routine */
843 int
fbset_main(int argc,const char * argv[])844 fbset_main (int argc, const char *argv[])
845 {
846     struct VideoMode *vmode;
847     struct fb_var_screeninfo var;
848     struct fb_fix_screeninfo fix;
849     int fh = -1, i;
850 
851     ProgramName = argv[0];
852 
853     /* Parse the Options */
854 
855     while (--argc > 0) {
856 		argv++;
857 		if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
858 			Usage();
859 			return 1;
860 		} else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose"))
861 			Opt_verbose = 1;
862 		else if (!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version"))
863 			Opt_version = 1;
864 		else if (!strcmp(argv[0], "--test"))
865 			Opt_test = 1;
866 		else if (!strcmp(argv[0], "-s") || !strcmp(argv[0], "--show"))
867 			Opt_show = 1;
868 		else if (!strcmp(argv[0], "-i") || !strcmp(argv[0], "--info")) {
869 			Opt_show = 1;
870 			Opt_info = 1;
871 		} else if (!strcmp(argv[0], "-x") || !strcmp(argv[0], "--xfree86"))
872 			Opt_xfree86 = 1;
873 		else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--all"))
874 			Opt_all = 1;
875 		else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--geometry")) {
876 			if (argc > 5) {
877 				Opt_xres = argv[1];
878 				Opt_yres = argv[2];
879 				Opt_vxres = argv[3];
880 				Opt_vyres = argv[4];
881 				Opt_depth = argv[5];
882 				Opt_change = 1;
883 				argc -= 5;
884 				argv += 5;
885 			} else {
886 				Usage();
887 				return 1;
888 			}
889 		} else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--timings")) {
890 			if (argc > 7) {
891 				Opt_pixclock = argv[1];
892 				Opt_left = argv[2];
893 				Opt_right = argv[3];
894 				Opt_upper = argv[4];
895 				Opt_lower = argv[5];
896 				Opt_hslen = argv[6];
897 				Opt_vslen = argv[7];
898 				Opt_change = 1;
899 				argc -= 7;
900 				argv += 7;
901 			} else {
902 				Usage();
903 				return 1;
904 			}
905 		} else if (!strcmp(argv[0], "-match")) {
906 			Opt_matchyres = argv[0];
907 			Opt_change = 1;
908 		} else {
909 			for (i = 0; Options[i].name; i++)
910 				if (!strcmp(argv[0], Options[i].name))
911 					break;
912 			if (Options[i].name) {
913 				if (argc-- > 1) {
914 					*Options[i].value = argv[1];
915 					Opt_change |= Options[i].change;
916 					argv++;
917 				} else {
918 					Usage();
919 					return 1;
920 				}
921 			} else if (!Opt_modename) {
922 				Opt_modename = argv[0];
923 				Opt_change = 1;
924 			} else {
925 				Usage();
926 				return 1;
927 			}
928 		}
929     }
930 
931     if (Opt_version || Opt_verbose)
932 		puts(FBSET_VERSION);
933 
934     if (!Opt_fb) {
935 		Opt_fb = getenv("FRAMEBUFFER");
936 		if (!Opt_fb)
937 			Opt_fb = DEFAULT_FRAMEBUFFER;
938     }
939 
940 	/* Open the Frame Buffer Device */
941 	fh = OpenFrameBuffer(Opt_fb);
942     if (fh < 0)
943 	return 1;
944 
945     /* Get the Video Mode */
946     if (Opt_modename) {
947 
948 #if 0
949 		/* Read the Video Mode Database */
950 		ReadModeDB();
951 #endif
952 
953 		if (!(vmode = FindVideoMode(Opt_modename))) {
954 			Die("Unknown video mode `%s'\n", Opt_modename);
955 			return 1;
956 		}
957 		Current = *vmode;
958 		if (Opt_verbose)
959 			printf("Using video mode `%s'\n", Opt_modename);
960     } else {
961 		GetVarScreenInfo(fh, &var);
962 		ConvertToVideoMode(&var, &Current);
963 		if (Opt_verbose)
964 			printf("Using current video mode from `%s'\n", Opt_fb);
965     }
966 
967     if (Opt_change) {
968 		/* Optionally Modify the Video Mode */
969 		ModifyVideoMode(&Current);
970 
971 		/* Set the Video Mode */
972 		ConvertFromVideoMode(&Current, &var);
973 		if (Opt_verbose)
974 			printf("Setting video mode to `%s'\n", Opt_fb);
975 		SetVarScreenInfo(fh, &var);
976 		ConvertToVideoMode(&var, &Current);
977     }
978 
979     /* Display some Video Mode Information */
980 
981     if (Opt_show || !Opt_change)
982 		DisplayVModeInfo(&Current);
983 
984     if (Opt_info) {
985 		if (Opt_verbose)
986 			puts("Getting further frame buffer information");
987 		if (GetFixScreenInfo(fh, &fix) != -1)
988 			DisplayFBInfo(&fix);
989     }
990 
991     /* Close the Frame Buffer Device */
992     CloseFrameBuffer(fh);
993 
994     return 0;
995 }
996