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