Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.sbin / grfconfig / grfconfig.c
blobb68abe2286e933f6d889493d93479f25b1093712
1 /* $NetBSD: grfconfig.c,v 1.13 2008/07/21 13:36:58 lukem Exp $ */
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ezra Story and Bernd Ernesti.
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.
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.
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 */
38 #ifndef lint
39 __RCSID("$NetBSD: grfconfig.c,v 1.13 2008/07/21 13:36:58 lukem Exp $");
40 #endif /* not lint */
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>
51 #include <amiga/dev/grfioctl.h>
53 int main __P((int, char **));
54 static void print_rawdata __P((struct grfvideo_mode *, int));
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}
71 * Dynamic mode loader for NetBSD/Amiga grf devices.
73 int
74 main(ac, av)
75 int ac;
76 char **av;
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;
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);
106 ac -= optind;
107 av += optind;
110 if (ac >= 1)
111 grfdevice = av[0];
112 else {
113 printf("grfconfig: No grf device specified.\n");
114 return (1);
117 if (ac >= 2)
118 modefile = av[1];
120 if ((grffd = open(grfdevice, O_RDWR)) < 0) {
121 printf("grfconfig: can't open grf device.\n");
122 return (1);
124 /* If a mode file is specificied, load it in, don't display any info. */
126 if (modefile) {
127 if (!(fp = fopen(modefile, "r"))) {
128 printf("grfconfig: Cannot open mode definition "
129 "file.\n");
130 return (1);
132 while (fgets(buf, sizeof(buf), fp)) {
133 char *obuf, tbuf[_POSIX2_LINE_MAX], *tbuf2;
135 * check for end-of-section, comments, strip off trailing
136 * spaces and newline character.
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';
146 obuf = buf;
147 tbuf2 = tbuf;
148 while ((*tbuf2 = *obuf) != '\0') {
149 if (*tbuf2 == '#') {
150 *tbuf2 = '\0';
151 break;
153 if (isupper((unsigned char)*tbuf2)) {
154 *tbuf2 = tolower((unsigned char)*tbuf2);
156 obuf++;
157 tbuf2++;
159 obuf = tbuf;
161 lineno = lineno + 1;
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;
168 if (i < 14) {
169 printf("grfconfig: too few values in mode "
170 "definition file:\n %s\n", obuf);
171 return (1);
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]);
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);
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);
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;
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);
238 * Check for impossible gv->disp_flags:
239 * doublescan and interlace,
240 * +hsync and -hsync
241 * +vsync and -vsync.
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";
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);
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);
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);
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);
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;
354 if (c == 255)
355 printf("Console: ");
356 else
357 printf("%2d: ", gv->mode_num);
359 printf("%dx%d",
360 gv->disp_width,
361 gv->disp_height);
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);
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:");
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);
387 printf("\n");
391 close(grffd);
392 return (0);
395 static void
396 print_rawdata(gv, rawflags)
397 struct grfvideo_mode *gv;
398 int rawflags;
400 struct grf_flag *grf_flagp;
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);
429 printf("\n");