xref: /netbsd/usr.sbin/grfconfig/grfconfig.c (revision cc224765)
1*cc224765Schristos /*	$NetBSD: grfconfig.c,v 1.16 2016/02/29 18:59:52 christos Exp $	*/
2b6873a23Schopps 
344b9795eSveego /*-
444b9795eSveego  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5b6873a23Schopps  * All rights reserved.
6b6873a23Schopps  *
744b9795eSveego  * This code is derived from software contributed to The NetBSD Foundation
844b9795eSveego  * by Ezra Story and Bernd Ernesti.
944b9795eSveego  *
10b6873a23Schopps  * Redistribution and use in source and binary forms, with or without
11b6873a23Schopps  * modification, are permitted provided that the following conditions
12b6873a23Schopps  * are met:
13b6873a23Schopps  * 1. Redistributions of source code must retain the above copyright
14b6873a23Schopps  *    notice, this list of conditions and the following disclaimer.
15b6873a23Schopps  * 2. Redistributions in binary form must reproduce the above copyright
16b6873a23Schopps  *    notice, this list of conditions and the following disclaimer in the
17b6873a23Schopps  *    documentation and/or other materials provided with the distribution.
18b6873a23Schopps  *
1944b9795eSveego  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2044b9795eSveego  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2144b9795eSveego  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223bc5599fSjtc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233bc5599fSjtc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2444b9795eSveego  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2544b9795eSveego  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2644b9795eSveego  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2744b9795eSveego  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2844b9795eSveego  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2944b9795eSveego  * POSSIBILITY OF SUCH DAMAGE.
30b6873a23Schopps  */
3144b9795eSveego 
3244b9795eSveego #include <sys/cdefs.h>
3344b9795eSveego #ifndef lint
349c194566Slukem __COPYRIGHT("@(#) Copyright (c) 1997\
359c194566Slukem  The NetBSD Foundation, Inc.  All rights reserved.");
3644b9795eSveego #endif /* not lint */
3744b9795eSveego 
3844b9795eSveego #ifndef lint
39*cc224765Schristos __RCSID("$NetBSD: grfconfig.c,v 1.16 2016/02/29 18:59:52 christos Exp $");
4044b9795eSveego #endif /* not lint */
4144b9795eSveego 
4244b9795eSveego #include <sys/file.h>
4344b9795eSveego #include <sys/ioctl.h>
44*cc224765Schristos #include <err.h>
4544b9795eSveego #include <ctype.h>
4644b9795eSveego #include <limits.h>
47b6873a23Schopps #include <stdio.h>
48b6873a23Schopps #include <stdlib.h>
49b6873a23Schopps #include <string.h>
5044b9795eSveego #include <unistd.h>
51b6873a23Schopps 
52b6873a23Schopps #include <amiga/dev/grfioctl.h>
53b6873a23Schopps 
54*cc224765Schristos static void print_modeline(FILE *fp, struct grfvideo_mode *, int);
55*cc224765Schristos static void suggest(struct grfvideo_mode *, const char *, const char *);
5644b9795eSveego 
5744b9795eSveego static struct grf_flag {
5844b9795eSveego 	u_short	grf_flag_number;
594c90ae5cSmlelstv 	const char	*grf_flag_name;
6044b9795eSveego } grf_flags[] = {
6144b9795eSveego 	{GRF_FLAGS_DBLSCAN,		"doublescan"},
6244b9795eSveego 	{GRF_FLAGS_LACE,		"interlace"},
6344b9795eSveego 	{GRF_FLAGS_PHSYNC,		"+hsync"},
6444b9795eSveego 	{GRF_FLAGS_NHSYNC,		"-hsync"},
6544b9795eSveego 	{GRF_FLAGS_PVSYNC,		"+vsync"},
6644b9795eSveego 	{GRF_FLAGS_NVSYNC,		"-vsync"},
6744b9795eSveego 	{GRF_FLAGS_SYNC_ON_GREEN,	"sync-on-green"},
6844b9795eSveego 	{0,				0}
6944b9795eSveego };
7044b9795eSveego 
71b6873a23Schopps /*
72b6873a23Schopps  * Dynamic mode loader for NetBSD/Amiga grf devices.
73b6873a23Schopps  */
74b6873a23Schopps int
main(int ac,char ** av)75*cc224765Schristos main(int ac, char  **av)
76b6873a23Schopps {
7744b9795eSveego 	struct	grfvideo_mode gv[1];
7844b9795eSveego 	struct	grf_flag *grf_flagp;
7944b9795eSveego 	FILE	*fp;
80b6873a23Schopps 	int	c, y, grffd;
81*cc224765Schristos 	size_t  i;
82*cc224765Schristos 	int	lineno = 0;
8344b9795eSveego 	int	uplim, lowlim;
8444b9795eSveego 	char	rawdata = 0, testmode = 0;
85*cc224765Schristos 	char	*grfdevice = 0, *ptr;
86b6873a23Schopps 	char	*modefile = 0;
87a77f2190Sveego 	char	buf[_POSIX2_LINE_MAX];
8844b9795eSveego 	char	*cps[31];
8944b9795eSveego 	char	*p;
904c90ae5cSmlelstv 	const char	*errortext;
91b6873a23Schopps 
9244b9795eSveego 
9344b9795eSveego 	while ((c = getopt(ac, av, "rt")) != -1) {
94b6873a23Schopps 		switch (c) {
95b6873a23Schopps 		case 'r':	/* raw output */
96b6873a23Schopps 			rawdata = 1;
97b6873a23Schopps 			break;
9844b9795eSveego 		case 't':	/* test the modefile without setting it */
9944b9795eSveego 			testmode = 1;
100b6873a23Schopps 			break;
101b6873a23Schopps 		default:
102dc683639Schopps 			printf("grfconfig [-r] device [file]\n");
103b6873a23Schopps 			return (1);
104b6873a23Schopps 		}
105b6873a23Schopps 	}
106b6873a23Schopps 	ac -= optind;
107b6873a23Schopps 	av += optind;
108b6873a23Schopps 
109b6873a23Schopps 
110*cc224765Schristos 	if (ac < 1)
111*cc224765Schristos 		errx(EXIT_FAILURE, "No grf device specified");
112b6873a23Schopps 	grfdevice = av[0];
113b6873a23Schopps 
114b6873a23Schopps 	if (ac >= 2)
115b6873a23Schopps 		modefile = av[1];
116b6873a23Schopps 
117*cc224765Schristos 	if ((grffd = open(grfdevice, O_RDWR)) == -1)
118*cc224765Schristos 		err(EXIT_FAILURE, "Can't open grf device `%s'", grfdevice);
119*cc224765Schristos 
120b6873a23Schopps 	/* If a mode file is specificied, load it in, don't display any info. */
121b6873a23Schopps 
122b6873a23Schopps 	if (modefile) {
123*cc224765Schristos 		if (!(fp = fopen(modefile, "r")))
124*cc224765Schristos 			err(EXIT_FAILURE,
125*cc224765Schristos 			    "Cannot open mode definition file `%s'", modefile);
126*cc224765Schristos 
12744b9795eSveego 		while (fgets(buf, sizeof(buf), fp)) {
128a77f2190Sveego 			char *obuf, tbuf[_POSIX2_LINE_MAX], *tbuf2;
12944b9795eSveego 			/*
13044b9795eSveego 			 * check for end-of-section, comments, strip off trailing
13144b9795eSveego 			 * spaces and newline character.
13244b9795eSveego 			 */
133f5ee27d6She 			for (p = buf; isspace((unsigned char)*p); ++p)
134b6873a23Schopps 				continue;
13544b9795eSveego 			if (*p == '\0' || *p == '#')
13644b9795eSveego 				continue;
137f5ee27d6She 			for (p = strchr(buf, '\0'); isspace((unsigned char)*--p);)
13844b9795eSveego 				continue;
13944b9795eSveego 			*++p = '\0';
140b6873a23Schopps 
141a77f2190Sveego 			obuf = buf;
142a77f2190Sveego 			tbuf2 = tbuf;
143a77f2190Sveego 			while ((*tbuf2 = *obuf) != '\0') {
144a77f2190Sveego 				if (*tbuf2 == '#') {
145a77f2190Sveego 					*tbuf2 = '\0';
146a77f2190Sveego 					break;
147a77f2190Sveego 				}
148f5ee27d6She 				if (isupper((unsigned char)*tbuf2)) {
149f5ee27d6She 					*tbuf2 = tolower((unsigned char)*tbuf2);
150a77f2190Sveego 				}
151a77f2190Sveego 				obuf++;
152a77f2190Sveego 				tbuf2++;
153a77f2190Sveego 			}
154a77f2190Sveego 			obuf = tbuf;
155a77f2190Sveego 
15644b9795eSveego 			lineno = lineno + 1;
157b6873a23Schopps 
158*cc224765Schristos #define SP " \b\t\r\n"
159*cc224765Schristos 			memset(cps, 0, sizeof(cps));
160*cc224765Schristos 			for (i = 0, ptr = strtok(buf, SP);
161*cc224765Schristos 			    ptr != NULL && i < __arraycount(cps);
162*cc224765Schristos 			    i++, ptr = strtok(NULL, SP))
163*cc224765Schristos 				cps[i] = ptr;
16444b9795eSveego 
165*cc224765Schristos 
166*cc224765Schristos 			if (i < 14)
167*cc224765Schristos 				errx(EXIT_FAILURE, "Too few values in mode "
168*cc224765Schristos 				    "definition file: `%s'\n", obuf);
16944b9795eSveego 
17044b9795eSveego 			gv->pixel_clock	= atoi(cps[1]);
17144b9795eSveego 			gv->disp_width	= atoi(cps[2]);
17244b9795eSveego 			gv->disp_height	= atoi(cps[3]);
17344b9795eSveego 			gv->depth	= atoi(cps[4]);
17444b9795eSveego 			gv->hblank_start	= atoi(cps[5]);
17544b9795eSveego 			gv->hsync_start	= atoi(cps[6]);
17644b9795eSveego 			gv->hsync_stop	= atoi(cps[7]);
17744b9795eSveego 			gv->htotal	= atoi(cps[8]);
17844b9795eSveego 			gv->vblank_start	= atoi(cps[9]);
17944b9795eSveego 			gv->vsync_start	= atoi(cps[10]);
18044b9795eSveego 			gv->vsync_stop	= atoi(cps[11]);
18144b9795eSveego 			gv->vtotal	= atoi(cps[12]);
18244b9795eSveego 
18344b9795eSveego 			if ((y = atoi(cps[0])))
184b6873a23Schopps 				gv->mode_num = y;
185b6873a23Schopps 			else
18644b9795eSveego 				if (strncasecmp("c", cps[0], 1) == 0) {
187b6873a23Schopps 					gv->mode_num = 255;
188b6873a23Schopps 					gv->depth = 4;
18944b9795eSveego 				} else {
190*cc224765Schristos 					errx(EXIT_FAILURE,
191*cc224765Schristos 					    "Illegal mode number: %s", cps[0]);
192b6873a23Schopps 				}
19344b9795eSveego 
19444b9795eSveego 			if ((gv->pixel_clock == 0) ||
19544b9795eSveego 			    (gv->disp_width == 0) ||
19644b9795eSveego 			    (gv->disp_height == 0) ||
19744b9795eSveego 			    (gv->depth == 0) ||
19844b9795eSveego 			    (gv->hblank_start == 0) ||
19944b9795eSveego 			    (gv->hsync_start == 0) ||
20044b9795eSveego 			    (gv->hsync_stop == 0) ||
20144b9795eSveego 			    (gv->htotal == 0) ||
20244b9795eSveego 			    (gv->vblank_start == 0) ||
20344b9795eSveego 			    (gv->vsync_start == 0) ||
20444b9795eSveego 			    (gv->vsync_stop == 0) ||
20544b9795eSveego 			    (gv->vtotal == 0)) {
206*cc224765Schristos 				errx(EXIT_FAILURE, "Illegal value in "
207*cc224765Schristos 				    "mode #%d: `%s'", gv->mode_num, obuf);
20844b9795eSveego 			}
20944b9795eSveego 
21044b9795eSveego 			if (strstr(obuf, "default") != NULL) {
21144b9795eSveego 				gv->disp_flags = GRF_FLAGS_DEFAULT;
21244b9795eSveego 			} else {
21344b9795eSveego 				gv->disp_flags = GRF_FLAGS_DEFAULT;
21444b9795eSveego 				for (grf_flagp = grf_flags;
21544b9795eSveego 				  grf_flagp->grf_flag_number; grf_flagp++) {
21644b9795eSveego 				    if (strstr(obuf, grf_flagp->grf_flag_name) != NULL) {
21744b9795eSveego 					gv->disp_flags |= grf_flagp->grf_flag_number;
21844b9795eSveego 				    }
21944b9795eSveego 				}
220*cc224765Schristos 				if (gv->disp_flags == GRF_FLAGS_DEFAULT)
221*cc224765Schristos 					errx(EXIT_FAILURE, "Your are using a "
22244b9795eSveego 					    "mode file with an obsolete "
223*cc224765Schristos 					    "format");
22444b9795eSveego 			}
22544b9795eSveego 
22644b9795eSveego 			/*
22744b9795eSveego 			 * Check for impossible gv->disp_flags:
22844b9795eSveego 			 * doublescan and interlace,
22944b9795eSveego 			 * +hsync and -hsync
23044b9795eSveego 			 * +vsync and -vsync.
23144b9795eSveego 			 */
23244b9795eSveego 			errortext = NULL;
23344b9795eSveego 			if ((gv->disp_flags & GRF_FLAGS_DBLSCAN) &&
23444b9795eSveego 			    (gv->disp_flags & GRF_FLAGS_LACE))
23544b9795eSveego 				errortext = "Interlace and Doublescan";
23644b9795eSveego 			if ((gv->disp_flags & GRF_FLAGS_PHSYNC) &&
23744b9795eSveego 			    (gv->disp_flags & GRF_FLAGS_NHSYNC))
23844b9795eSveego 				errortext = "+hsync and -hsync";
23944b9795eSveego 			if ((gv->disp_flags & GRF_FLAGS_PVSYNC) &&
24044b9795eSveego 			    (gv->disp_flags & GRF_FLAGS_NVSYNC))
24144b9795eSveego 				errortext = "+vsync and -vsync";
24244b9795eSveego 
243*cc224765Schristos 			if (errortext != NULL)
244*cc224765Schristos 				errx(EXIT_FAILURE, "Illegal flags in "
245*cc224765Schristos 				    "mode #%d: `%s' are both defined",
24644b9795eSveego 				    gv->mode_num, errortext);
24744b9795eSveego 
24844b9795eSveego 			/* Check for old horizontal cycle values */
24944b9795eSveego 			if ((gv->htotal < (gv->disp_width / 4))) {
25044b9795eSveego 				gv->hblank_start *= 8;
25144b9795eSveego 				gv->hsync_start *= 8;
25244b9795eSveego 				gv->hsync_stop *= 8;
25344b9795eSveego 				gv->htotal *= 8;
254*cc224765Schristos 				suggest(gv, "horizontal videoclock cycle "
255*cc224765Schristos 				    "values", obuf);
256*cc224765Schristos 				return EXIT_FAILURE;
25744b9795eSveego 			}
25844b9795eSveego 
25944b9795eSveego 			/* Check for old interlace or doublescan modes */
26044b9795eSveego 			uplim = gv->disp_height + (gv->disp_height / 4);
26144b9795eSveego 			lowlim = gv->disp_height - (gv->disp_height / 4);
26244b9795eSveego 			if (((gv->vtotal * 2) > lowlim) &&
26344b9795eSveego 			    ((gv->vtotal * 2) < uplim)) {
26444b9795eSveego 				gv->vblank_start *= 2;
26544b9795eSveego 				gv->vsync_start *= 2;
26644b9795eSveego 				gv->vsync_stop *= 2;
26744b9795eSveego 				gv->vtotal *= 2;
26881fde155Sveego 				gv->disp_flags &= ~GRF_FLAGS_DBLSCAN;
26981fde155Sveego 				gv->disp_flags |= GRF_FLAGS_LACE;
270*cc224765Schristos 				suggest(gv, "vertical values for interlace "
271*cc224765Schristos 				    "modes", obuf);
272*cc224765Schristos 				return EXIT_FAILURE;
27381fde155Sveego 			} else if (((gv->vtotal / 2) > lowlim) &&
27444b9795eSveego 			    ((gv->vtotal / 2) < uplim)) {
27544b9795eSveego 				gv->vblank_start /= 2;
27644b9795eSveego 				gv->vsync_start /= 2;
27744b9795eSveego 				gv->vsync_stop /= 2;
27844b9795eSveego 				gv->vtotal /= 2;
27981fde155Sveego 				gv->disp_flags &= ~GRF_FLAGS_LACE;
28081fde155Sveego 				gv->disp_flags |= GRF_FLAGS_DBLSCAN;
281*cc224765Schristos 				suggest(gv, "vertical values for doublescan "
282*cc224765Schristos 				    "modes", obuf);
283*cc224765Schristos 				return EXIT_FAILURE;
28444b9795eSveego 			}
28544b9795eSveego 
28644b9795eSveego 			if (testmode == 1) {
28744b9795eSveego 				if (lineno == 1)
28844b9795eSveego 					printf("num clk wid hi dep hbs "
28944b9795eSveego 					    "hss hse ht vbs vss vse vt "
29044b9795eSveego 					    "flags\n");
291*cc224765Schristos 				print_modeline(stdout, gv, 1);
29244b9795eSveego 			} else {
293b6873a23Schopps 				gv->mode_descr[0] = 0;
294b6873a23Schopps 				if (ioctl(grffd, GRFIOCSETMON, (char *) gv) < 0)
295*cc224765Schristos 					err(EXIT_FAILURE, "bad monitor "
296*cc224765Schristos 					    "definition for mode #%d",
29726003d1cSveego 					    gv->mode_num);
298b6873a23Schopps 			}
299b6873a23Schopps 		}
300b6873a23Schopps 		fclose(fp);
301b6873a23Schopps 	} else {
302b6873a23Schopps 		ioctl(grffd, GRFGETNUMVM, &y);
303b6873a23Schopps 		y += 2;
304b6873a23Schopps 		for (c = 1; c < y; c++) {
305b6873a23Schopps 			c = gv->mode_num = (c != (y - 1)) ? c : 255;
306b6873a23Schopps 			if (ioctl(grffd, GRFGETVMODE, gv) < 0)
307b6873a23Schopps 				continue;
308b6873a23Schopps 			if (rawdata) {
309*cc224765Schristos 				print_modeline(stdout, gv, 0);
310b6873a23Schopps 				continue;
311b6873a23Schopps 			}
312b6873a23Schopps 			if (c == 255)
313b6873a23Schopps 				printf("Console: ");
314b6873a23Schopps 			else
315b6873a23Schopps 				printf("%2d: ", gv->mode_num);
316b6873a23Schopps 
317b6873a23Schopps 			printf("%dx%d",
318b6873a23Schopps 			    gv->disp_width,
319b6873a23Schopps 			    gv->disp_height);
320b6873a23Schopps 
321b6873a23Schopps 			if (c != 255)
322b6873a23Schopps 				printf("x%d", gv->depth);
323b6873a23Schopps 			else
324b6873a23Schopps 				printf(" (%dx%d)",
325b6873a23Schopps 				    gv->disp_width / 8,
326b6873a23Schopps 				    gv->disp_height / gv->depth);
327b6873a23Schopps 
32844b9795eSveego 			printf("\t%ld.%ldkHz @ %ldHz",
32944b9795eSveego 			    gv->pixel_clock / (gv->htotal * 1000),
33044b9795eSveego 			    (gv->pixel_clock / (gv->htotal * 100))
331b6873a23Schopps     	    	    	    	% 10,
33244b9795eSveego 			    gv->pixel_clock / (gv->htotal * gv->vtotal));
33344b9795eSveego 			printf(" flags:");
33444b9795eSveego 
33544b9795eSveego 			if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
336*cc224765Schristos 				printf(" default\n");
337*cc224765Schristos 				continue;
338*cc224765Schristos 			}
339*cc224765Schristos 
34044b9795eSveego 			for (grf_flagp = grf_flags;
341*cc224765Schristos 			    grf_flagp->grf_flag_number; grf_flagp++)
342*cc224765Schristos 				if (gv->disp_flags & grf_flagp->grf_flag_number)
34344b9795eSveego 					printf(" %s", grf_flagp->grf_flag_name);
34444b9795eSveego 			printf("\n");
345b6873a23Schopps 		}
346b6873a23Schopps 	}
347b6873a23Schopps 
348b6873a23Schopps 	close(grffd);
349*cc224765Schristos 	return EXIT_SUCCESS;
350b6873a23Schopps }
35144b9795eSveego 
35244b9795eSveego static void
suggest(struct grfvideo_mode * gv,const char * d,const char * s)353*cc224765Schristos suggest(struct	grfvideo_mode *gv, const char *d, const char *s)
354*cc224765Schristos {
355*cc224765Schristos 	warnx("Old and no longer supported %s: %s", d, s);
356*cc224765Schristos 	warnx("Wrong mode line, this could be a possible good model line:");
357*cc224765Schristos 	fprintf(stderr, "%s: ", getprogname());
358*cc224765Schristos 	print_modeline(stderr, gv, 0);
359*cc224765Schristos }
360*cc224765Schristos 
361*cc224765Schristos static void
print_modeline(FILE * fp,struct grfvideo_mode * gv,int rawflags)362*cc224765Schristos print_modeline(FILE *fp, struct grfvideo_mode *gv, int rawflags)
36344b9795eSveego {
36444b9795eSveego 	struct	grf_flag *grf_flagp;
36544b9795eSveego 
366*cc224765Schristos 	if (gv->mode_num == 255)
367*cc224765Schristos 		fprintf(fp, "c ");
368*cc224765Schristos 	else
369*cc224765Schristos 		fprintf(fp, "%d ", gv->mode_num);
370*cc224765Schristos 
371*cc224765Schristos 	fprintf(fp, "%ld %d %d %d %d %d %d %d %d %d %d %d",
37244b9795eSveego 		gv->pixel_clock,
37344b9795eSveego 		gv->disp_width,
37444b9795eSveego 		gv->disp_height,
37544b9795eSveego 		gv->depth,
37644b9795eSveego 		gv->hblank_start,
37744b9795eSveego 		gv->hsync_start,
37844b9795eSveego 		gv->hsync_stop,
37944b9795eSveego 		gv->htotal,
38044b9795eSveego 		gv->vblank_start,
38144b9795eSveego 		gv->vsync_start,
38244b9795eSveego 		gv->vsync_stop,
38344b9795eSveego 		gv->vtotal);
384*cc224765Schristos 
38544b9795eSveego 	if (rawflags) {
386*cc224765Schristos 		fprintf(fp, " 0x%.2x\n", gv->disp_flags);
387*cc224765Schristos 		return;
388*cc224765Schristos 	}
38944b9795eSveego 	if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
390*cc224765Schristos 		fprintf(fp, " default\n");
391*cc224765Schristos 		return;
39244b9795eSveego 	}
393*cc224765Schristos 
394*cc224765Schristos 	for (grf_flagp = grf_flags; grf_flagp->grf_flag_number; grf_flagp++)
395*cc224765Schristos 		if (gv->disp_flags & grf_flagp->grf_flag_number)
396*cc224765Schristos 			fprintf(fp, " %s", grf_flagp->grf_flag_name);
397*cc224765Schristos 	fprintf(fp, "\n");
39844b9795eSveego }
399