Home | History | Annotate | Line # | Download | only in grfconfig
grfconfig.c revision 1.14
      1 /*	$NetBSD: grfconfig.c,v 1.14 2009/04/26 19:24:18 mlelstv Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Ezra Story and Bernd Ernesti.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __COPYRIGHT("@(#) Copyright (c) 1997\
     35  The NetBSD Foundation, Inc.  All rights reserved.");
     36 #endif /* not lint */
     37 
     38 #ifndef lint
     39 __RCSID("$NetBSD: grfconfig.c,v 1.14 2009/04/26 19:24:18 mlelstv Exp $");
     40 #endif /* not lint */
     41 
     42 #include <sys/file.h>
     43 #include <sys/ioctl.h>
     44 #include <ctype.h>
     45 #include <limits.h>
     46 #include <stdio.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <unistd.h>
     50 
     51 #include <amiga/dev/grfioctl.h>
     52 
     53 int main __P((int, char **));
     54 static void print_rawdata __P((struct grfvideo_mode *, int));
     55 
     56 static struct grf_flag {
     57 	u_short	grf_flag_number;
     58 	const char	*grf_flag_name;
     59 } grf_flags[] = {
     60 	{GRF_FLAGS_DBLSCAN,		"doublescan"},
     61 	{GRF_FLAGS_LACE,		"interlace"},
     62 	{GRF_FLAGS_PHSYNC,		"+hsync"},
     63 	{GRF_FLAGS_NHSYNC,		"-hsync"},
     64 	{GRF_FLAGS_PVSYNC,		"+vsync"},
     65 	{GRF_FLAGS_NVSYNC,		"-vsync"},
     66 	{GRF_FLAGS_SYNC_ON_GREEN,	"sync-on-green"},
     67 	{0,				0}
     68 };
     69 
     70 /*
     71  * Dynamic mode loader for NetBSD/Amiga grf devices.
     72  */
     73 int
     74 main(ac, av)
     75 	int     ac;
     76 	char  **av;
     77 {
     78 	struct	grfvideo_mode gv[1];
     79 	struct	grf_flag *grf_flagp;
     80 	FILE	*fp;
     81 	int	c, y, grffd;
     82 	int	i, lineno = 0;
     83 	int	uplim, lowlim;
     84 	char	rawdata = 0, testmode = 0;
     85 	char	*grfdevice = 0;
     86 	char	*modefile = 0;
     87 	char	buf[_POSIX2_LINE_MAX];
     88 	char	*cps[31];
     89 	char	*p;
     90 	const char	*errortext;
     91 
     92 
     93 	while ((c = getopt(ac, av, "rt")) != -1) {
     94 		switch (c) {
     95 		case 'r':	/* raw output */
     96 			rawdata = 1;
     97 			break;
     98 		case 't':	/* test the modefile without setting it */
     99 			testmode = 1;
    100 			break;
    101 		default:
    102 			printf("grfconfig [-r] device [file]\n");
    103 			return (1);
    104 		}
    105 	}
    106 	ac -= optind;
    107 	av += optind;
    108 
    109 
    110 	if (ac >= 1)
    111 		grfdevice = av[0];
    112 	else {
    113 		printf("grfconfig: No grf device specified.\n");
    114 		return (1);
    115 	}
    116 
    117 	if (ac >= 2)
    118 		modefile = av[1];
    119 
    120 	if ((grffd = open(grfdevice, O_RDWR)) < 0) {
    121 		printf("grfconfig: can't open grf device.\n");
    122 		return (1);
    123 	}
    124 	/* If a mode file is specificied, load it in, don't display any info. */
    125 
    126 	if (modefile) {
    127 		if (!(fp = fopen(modefile, "r"))) {
    128 			printf("grfconfig: Cannot open mode definition "
    129 			    "file.\n");
    130 			return (1);
    131 		}
    132 		while (fgets(buf, sizeof(buf), fp)) {
    133 			char *obuf, tbuf[_POSIX2_LINE_MAX], *tbuf2;
    134 			/*
    135 			 * check for end-of-section, comments, strip off trailing
    136 			 * spaces and newline character.
    137 			 */
    138 			for (p = buf; isspace((unsigned char)*p); ++p)
    139 				continue;
    140 			if (*p == '\0' || *p == '#')
    141 				continue;
    142 			for (p = strchr(buf, '\0'); isspace((unsigned char)*--p);)
    143 				continue;
    144 			*++p = '\0';
    145 
    146 			obuf = buf;
    147 			tbuf2 = tbuf;
    148 			while ((*tbuf2 = *obuf) != '\0') {
    149 				if (*tbuf2 == '#') {
    150 					*tbuf2 = '\0';
    151 					break;
    152 				}
    153 				if (isupper((unsigned char)*tbuf2)) {
    154 					*tbuf2 = tolower((unsigned char)*tbuf2);
    155 				}
    156 				obuf++;
    157 				tbuf2++;
    158 			}
    159 			obuf = tbuf;
    160 
    161 			lineno = lineno + 1;
    162 
    163 			for (i = 0, *cps = strtok(buf, " \b\t\r\n");
    164 			    cps[i] != NULL && i < 30; i++)
    165 				cps[i + 1] = strtok(NULL, " \b\t\r\n");
    166 			cps[i] = NULL;
    167 
    168 			if (i < 14) {
    169 				printf("grfconfig: too few values in mode "
    170 				    "definition file:\n %s\n", obuf);
    171 				return (1);
    172 			}
    173 
    174 			gv->pixel_clock	= atoi(cps[1]);
    175 			gv->disp_width	= atoi(cps[2]);
    176 			gv->disp_height	= atoi(cps[3]);
    177 			gv->depth	= atoi(cps[4]);
    178 			gv->hblank_start	= atoi(cps[5]);
    179 			gv->hsync_start	= atoi(cps[6]);
    180 			gv->hsync_stop	= atoi(cps[7]);
    181 			gv->htotal	= atoi(cps[8]);
    182 			gv->vblank_start	= atoi(cps[9]);
    183 			gv->vsync_start	= atoi(cps[10]);
    184 			gv->vsync_stop	= atoi(cps[11]);
    185 			gv->vtotal	= atoi(cps[12]);
    186 
    187 			if ((y = atoi(cps[0])))
    188 				gv->mode_num = y;
    189 			else
    190 				if (strncasecmp("c", cps[0], 1) == 0) {
    191 					gv->mode_num = 255;
    192 					gv->depth = 4;
    193 				} else {
    194 					printf("grfconfig: Illegal mode "
    195 					    "number: %s\n", cps[0]);
    196 					return (1);
    197 				}
    198 
    199 			if ((gv->pixel_clock == 0) ||
    200 			    (gv->disp_width == 0) ||
    201 			    (gv->disp_height == 0) ||
    202 			    (gv->depth == 0) ||
    203 			    (gv->hblank_start == 0) ||
    204 			    (gv->hsync_start == 0) ||
    205 			    (gv->hsync_stop == 0) ||
    206 			    (gv->htotal == 0) ||
    207 			    (gv->vblank_start == 0) ||
    208 			    (gv->vsync_start == 0) ||
    209 			    (gv->vsync_stop == 0) ||
    210 			    (gv->vtotal == 0)) {
    211 				printf("grfconfig: Illegal value in "
    212 				    "mode #%d:\n %s\n", gv->mode_num, obuf);
    213 				return (1);
    214 			}
    215 
    216 			if (strstr(obuf, "default") != NULL) {
    217 				gv->disp_flags = GRF_FLAGS_DEFAULT;
    218 			} else {
    219 				gv->disp_flags = GRF_FLAGS_DEFAULT;
    220 				for (grf_flagp = grf_flags;
    221 				  grf_flagp->grf_flag_number; grf_flagp++) {
    222 				    if (strstr(obuf, grf_flagp->grf_flag_name) != NULL) {
    223 					gv->disp_flags |= grf_flagp->grf_flag_number;
    224 				    }
    225 				}
    226 				if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
    227 					printf("grfconfig: Your are using an "
    228 					    "mode file with an obsolete "
    229 					    "format.\n See the manpage of "
    230 					    "grfconfig for more information "
    231 					    "about the new mode definition "
    232 					    "file.\n");
    233 					return (1);
    234 				}
    235 			}
    236 
    237 			/*
    238 			 * Check for impossible gv->disp_flags:
    239 			 * doublescan and interlace,
    240 			 * +hsync and -hsync
    241 			 * +vsync and -vsync.
    242 			 */
    243 			errortext = NULL;
    244 			if ((gv->disp_flags & GRF_FLAGS_DBLSCAN) &&
    245 			    (gv->disp_flags & GRF_FLAGS_LACE))
    246 				errortext = "Interlace and Doublescan";
    247 			if ((gv->disp_flags & GRF_FLAGS_PHSYNC) &&
    248 			    (gv->disp_flags & GRF_FLAGS_NHSYNC))
    249 				errortext = "+hsync and -hsync";
    250 			if ((gv->disp_flags & GRF_FLAGS_PVSYNC) &&
    251 			    (gv->disp_flags & GRF_FLAGS_NVSYNC))
    252 				errortext = "+vsync and -vsync";
    253 
    254 			if (errortext != NULL) {
    255 				printf("grfconfig: Illegal flags in "
    256 				    "mode #%d: %s are both defined!\n",
    257 				    gv->mode_num, errortext);
    258 				return (1);
    259 			}
    260 
    261 			/* Check for old horizontal cycle values */
    262 			if ((gv->htotal < (gv->disp_width / 4))) {
    263 				gv->hblank_start *= 8;
    264 				gv->hsync_start *= 8;
    265 				gv->hsync_stop *= 8;
    266 				gv->htotal *= 8;
    267 				printf("grfconfig: Old and no longer "
    268 				    "supported horizontal videoclock cycle "
    269 				    "values.\n Wrong mode line:\n  %s\n "
    270 				    "This could be a possible good mode "
    271 				    "line:\n  ", obuf);
    272 				printf("%d ", gv->mode_num);
    273 				print_rawdata(gv, 0);
    274 				printf(" See the manpage of grfconfig for "
    275 				    "more information about the new mode "
    276 				    "definition file.\n");
    277 				return (1);
    278 			}
    279 
    280 			/* Check for old interlace or doublescan modes */
    281 			uplim = gv->disp_height + (gv->disp_height / 4);
    282 			lowlim = gv->disp_height - (gv->disp_height / 4);
    283 			if (((gv->vtotal * 2) > lowlim) &&
    284 			    ((gv->vtotal * 2) < uplim)) {
    285 				gv->vblank_start *= 2;
    286 				gv->vsync_start *= 2;
    287 				gv->vsync_stop *= 2;
    288 				gv->vtotal *= 2;
    289 				gv->disp_flags &= ~GRF_FLAGS_DBLSCAN;
    290 				gv->disp_flags |= GRF_FLAGS_LACE;
    291 				printf("grfconfig: Old and no longer "
    292 				    "supported vertical values for "
    293 				    "interlace modes.\n Wrong mode "
    294 				    "line:\n  %s\n This could be a "
    295 				    "possible good mode line:\n  ", obuf);
    296 				printf("%d ", gv->mode_num);
    297 				print_rawdata(gv, 0);
    298 				printf(" See the manpage of grfconfig for "
    299 				    "more information about the new mode "
    300 				    "definition file.\n");
    301 				return (1);
    302 			} else if (((gv->vtotal / 2) > lowlim) &&
    303 			    ((gv->vtotal / 2) < uplim)) {
    304 				gv->vblank_start /= 2;
    305 				gv->vsync_start /= 2;
    306 				gv->vsync_stop /= 2;
    307 				gv->vtotal /= 2;
    308 				gv->disp_flags &= ~GRF_FLAGS_LACE;
    309 				gv->disp_flags |= GRF_FLAGS_DBLSCAN;
    310 				printf("grfconfig: Old and no longer "
    311 				    "supported vertical values for "
    312 				    "doublescan modes.\n Wrong mode "
    313 				    "line:\n  %s\n This could be a "
    314 				    "possible good mode line:\n  ", obuf);
    315 				printf("%d ", gv->mode_num);
    316 				print_rawdata(gv, 0);
    317 				printf(" See the manpage of grfconfig for "
    318 				    "more information about the new mode "
    319 				    "definition file.\n");
    320 				return (1);
    321 			}
    322 
    323 			if (testmode == 1) {
    324 				if (lineno == 1)
    325 					printf("num clk wid hi dep hbs "
    326 					    "hss hse ht vbs vss vse vt "
    327 					    "flags\n");
    328 				printf("%d ", gv->mode_num);
    329 				print_rawdata(gv, 1);
    330 			} else {
    331 				gv->mode_descr[0] = 0;
    332 				if (ioctl(grffd, GRFIOCSETMON, (char *) gv) < 0)
    333 					printf("grfconfig: bad monitor "
    334 					    "definition for mode #%d.\n",
    335 					    gv->mode_num);
    336 			}
    337 		}
    338 		fclose(fp);
    339 	} else {
    340 		ioctl(grffd, GRFGETNUMVM, &y);
    341 		y += 2;
    342 		for (c = 1; c < y; c++) {
    343 			c = gv->mode_num = (c != (y - 1)) ? c : 255;
    344 			if (ioctl(grffd, GRFGETVMODE, gv) < 0)
    345 				continue;
    346 			if (rawdata) {
    347 				if (c == 255)
    348 					printf("c ");
    349 				else
    350 					printf("%d ", c);
    351 				print_rawdata(gv, 0);
    352 				continue;
    353 			}
    354 			if (c == 255)
    355 				printf("Console: ");
    356 			else
    357 				printf("%2d: ", gv->mode_num);
    358 
    359 			printf("%dx%d",
    360 			    gv->disp_width,
    361 			    gv->disp_height);
    362 
    363 			if (c != 255)
    364 				printf("x%d", gv->depth);
    365 			else
    366 				printf(" (%dx%d)",
    367 				    gv->disp_width / 8,
    368 				    gv->disp_height / gv->depth);
    369 
    370 			printf("\t%ld.%ldkHz @ %ldHz",
    371 			    gv->pixel_clock / (gv->htotal * 1000),
    372 			    (gv->pixel_clock / (gv->htotal * 100))
    373     	    	    	    	% 10,
    374 			    gv->pixel_clock / (gv->htotal * gv->vtotal));
    375 			printf(" flags:");
    376 
    377 			if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
    378 				printf(" default");
    379 			} else {
    380 				for (grf_flagp = grf_flags;
    381 				  grf_flagp->grf_flag_number; grf_flagp++) {
    382 				    if (gv->disp_flags & grf_flagp->grf_flag_number) {
    383 					printf(" %s", grf_flagp->grf_flag_name);
    384 				    }
    385 				}
    386 			}
    387 			printf("\n");
    388 		}
    389 	}
    390 
    391 	close(grffd);
    392 	return (0);
    393 }
    394 
    395 static void
    396 print_rawdata(gv, rawflags)
    397 	struct grfvideo_mode *gv;
    398 	int rawflags;
    399 {
    400 	struct	grf_flag *grf_flagp;
    401 
    402 	printf("%ld %d %d %d %d %d %d %d %d %d %d %d",
    403 		gv->pixel_clock,
    404 		gv->disp_width,
    405 		gv->disp_height,
    406 		gv->depth,
    407 		gv->hblank_start,
    408 		gv->hsync_start,
    409 		gv->hsync_stop,
    410 		gv->htotal,
    411 		gv->vblank_start,
    412 		gv->vsync_start,
    413 		gv->vsync_stop,
    414 		gv->vtotal);
    415 		if (rawflags) {
    416 			printf(" 0x%.2x", gv->disp_flags);
    417 		} else {
    418 			if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
    419 				printf(" default");
    420 			} else {
    421 				for (grf_flagp = grf_flags;
    422 				  grf_flagp->grf_flag_number; grf_flagp++) {
    423 				    if (gv->disp_flags & grf_flagp->grf_flag_number) {
    424 					printf(" %s", grf_flagp->grf_flag_name);
    425 				    }
    426 				}
    427 			}
    428 		}
    429 		printf("\n");
    430 }
    431