grfconfig.c revision 1.6 1 /* $NetBSD: grfconfig.c,v 1.6 1997/07/29 23:41:12 veego 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 REGENTS OR CONTRIBUTORS BE
30 * 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.6 1997/07/29 23:41:12 veego 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 extern char *optarg;
61 extern int optind;
62
63 int main __P((int, char **));
64 static void print_rawdata __P((struct grfvideo_mode *, int));
65
66 static struct grf_flag {
67 u_short grf_flag_number;
68 char *grf_flag_name;
69 } grf_flags[] = {
70 {GRF_FLAGS_DBLSCAN, "doublescan"},
71 {GRF_FLAGS_LACE, "interlace"},
72 {GRF_FLAGS_PHSYNC, "+hsync"},
73 {GRF_FLAGS_NHSYNC, "-hsync"},
74 {GRF_FLAGS_PVSYNC, "+vsync"},
75 {GRF_FLAGS_NVSYNC, "-vsync"},
76 {GRF_FLAGS_SYNC_ON_GREEN, "sync-on-green"},
77 {0, 0}
78 };
79
80 /*
81 * Dynamic mode loader for NetBSD/Amiga grf devices.
82 */
83 int
84 main(ac, av)
85 int ac;
86 char **av;
87 {
88 struct grfvideo_mode gv[1];
89 struct grf_flag *grf_flagp;
90 FILE *fp;
91 int c, y, grffd;
92 int i, lineno = 0;
93 int uplim, lowlim;
94 char rawdata = 0, testmode = 0;
95 char *grfdevice = 0;
96 char *modefile = 0;
97 char buf[_POSIX2_LINE_MAX], obuf[_POSIX2_LINE_MAX];
98 char *cps[31];
99 char *p;
100 char *errortext;
101
102
103 while ((c = getopt(ac, av, "rt")) != -1) {
104 switch (c) {
105 case 'r': /* raw output */
106 rawdata = 1;
107 break;
108 case 't': /* test the modefile without setting it */
109 testmode = 1;
110 break;
111 default:
112 printf("grfconfig [-r] device [file]\n");
113 return (1);
114 }
115 }
116 ac -= optind;
117 av += optind;
118
119
120 if (ac >= 1)
121 grfdevice = av[0];
122 else {
123 printf("grfconfig: No grf device specified.\n");
124 return (1);
125 }
126
127 if (ac >= 2)
128 modefile = av[1];
129
130 if ((grffd = open(grfdevice, O_RDWR)) < 0) {
131 printf("grfconfig: can't open grf device.\n");
132 return (1);
133 }
134 /* If a mode file is specificied, load it in, don't display any info. */
135
136 if (modefile) {
137 if (!(fp = fopen(modefile, "r"))) {
138 printf("grfconfig: Cannot open mode definition "
139 "file.\n");
140 return (1);
141 }
142 while (fgets(buf, sizeof(buf), fp)) {
143 /*
144 * check for end-of-section, comments, strip off trailing
145 * spaces and newline character.
146 */
147 for (p = buf; isspace(*p); ++p)
148 continue;
149 if (*p == '\0' || *p == '#')
150 continue;
151 for (p = strchr(buf, '\0'); isspace(*--p);)
152 continue;
153 *++p = '\0';
154
155 sprintf(obuf, "%s", buf);
156 lineno = lineno + 1;
157
158 for (i = 0, *cps = strtok(buf, " \b\t\r\n");
159 cps[i] != NULL && i < 30; i++)
160 cps[i + 1] = strtok(NULL, " \b\t\r\n");
161 cps[i] = NULL;
162
163 if (cps[13] == NULL) {
164 printf("grfconfig: too few values in mode "
165 "definition file:\n %s\n", obuf);
166 return (1);
167 }
168
169 gv->pixel_clock = atoi(cps[1]);
170 gv->disp_width = atoi(cps[2]);
171 gv->disp_height = atoi(cps[3]);
172 gv->depth = atoi(cps[4]);
173 gv->hblank_start = atoi(cps[5]);
174 gv->hsync_start = atoi(cps[6]);
175 gv->hsync_stop = atoi(cps[7]);
176 gv->htotal = atoi(cps[8]);
177 gv->vblank_start = atoi(cps[9]);
178 gv->vsync_start = atoi(cps[10]);
179 gv->vsync_stop = atoi(cps[11]);
180 gv->vtotal = atoi(cps[12]);
181
182 if ((y = atoi(cps[0])))
183 gv->mode_num = y;
184 else
185 if (strncasecmp("c", cps[0], 1) == 0) {
186 gv->mode_num = 255;
187 gv->depth = 4;
188 } else {
189 printf("grfconfig: Illegal mode "
190 "number: %s\n", cps[0]);
191 return (1);
192 }
193
194 if ((gv->pixel_clock == 0) ||
195 (gv->disp_width == 0) ||
196 (gv->disp_height == 0) ||
197 (gv->depth == 0) ||
198 (gv->hblank_start == 0) ||
199 (gv->hsync_start == 0) ||
200 (gv->hsync_stop == 0) ||
201 (gv->htotal == 0) ||
202 (gv->vblank_start == 0) ||
203 (gv->vsync_start == 0) ||
204 (gv->vsync_stop == 0) ||
205 (gv->vtotal == 0)) {
206 printf("grfconfig: Illegal value in "
207 "mode #%d:\n %s\n", gv->mode_num, obuf);
208 return (1);
209 }
210
211 if (strstr(obuf, "default") != NULL) {
212 gv->disp_flags = GRF_FLAGS_DEFAULT;
213 } else {
214 gv->disp_flags = GRF_FLAGS_DEFAULT;
215 for (grf_flagp = grf_flags;
216 grf_flagp->grf_flag_number; grf_flagp++) {
217 if (strstr(obuf, grf_flagp->grf_flag_name) != NULL) {
218 gv->disp_flags |= grf_flagp->grf_flag_number;
219 }
220 }
221 if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
222 printf("grfconfig: Your are using an "
223 "mode file with an obsolete "
224 "format.\n See the manpage of "
225 "grfconfig for more information "
226 "about the new mode definition "
227 "file.\n");
228 return (1);
229 }
230 }
231
232 /*
233 * Check for impossible gv->disp_flags:
234 * doublescan and interlace,
235 * +hsync and -hsync
236 * +vsync and -vsync.
237 */
238 errortext = NULL;
239 if ((gv->disp_flags & GRF_FLAGS_DBLSCAN) &&
240 (gv->disp_flags & GRF_FLAGS_LACE))
241 errortext = "Interlace and Doublescan";
242 if ((gv->disp_flags & GRF_FLAGS_PHSYNC) &&
243 (gv->disp_flags & GRF_FLAGS_NHSYNC))
244 errortext = "+hsync and -hsync";
245 if ((gv->disp_flags & GRF_FLAGS_PVSYNC) &&
246 (gv->disp_flags & GRF_FLAGS_NVSYNC))
247 errortext = "+vsync and -vsync";
248
249 if (errortext != NULL) {
250 printf("grfconfig: Illegal flags in "
251 "mode #%d: %s are both defined!\n",
252 gv->mode_num, errortext);
253 return (1);
254 }
255
256 /* Check for old horizontal cycle values */
257 if ((gv->htotal < (gv->disp_width / 4))) {
258 gv->hblank_start *= 8;
259 gv->hsync_start *= 8;
260 gv->hsync_stop *= 8;
261 gv->htotal *= 8;
262 printf("grfconfig: Old and no longer "
263 "supported horizontal videoclock cycle "
264 "values.\n Wrong mode line:\n %s\n "
265 "This could be a possible good mode "
266 "line:\n ", obuf);
267 printf("%d ", gv->mode_num);
268 print_rawdata(gv, 0);
269 printf(" See the manpage of grfconfig for "
270 "more information about the new mode "
271 "definition file.\n");
272 return (1);
273 }
274
275 /* Check for old interlace or doublescan modes */
276 uplim = gv->disp_height + (gv->disp_height / 4);
277 lowlim = gv->disp_height - (gv->disp_height / 4);
278 if (((gv->vtotal * 2) > lowlim) &&
279 ((gv->vtotal * 2) < uplim)) {
280 gv->vblank_start *= 2;
281 gv->vsync_start *= 2;
282 gv->vsync_stop *= 2;
283 gv->vtotal *= 2;
284 gv->disp_flags &= ~GRF_FLAGS_DBLSCAN;
285 gv->disp_flags |= GRF_FLAGS_LACE;
286 printf("grfconfig: Old and no longer "
287 "supported vertical values for "
288 "interlace modes.\n Wrong mode "
289 "line:\n %s\n This could be a "
290 "possible good mode line:\n ", obuf);
291 printf("%d ", gv->mode_num);
292 print_rawdata(gv, 0);
293 printf(" See the manpage of grfconfig for "
294 "more information about the new mode "
295 "definition file.\n");
296 return (1);
297 } else if (((gv->vtotal / 2) > lowlim) &&
298 ((gv->vtotal / 2) < uplim)) {
299 gv->vblank_start /= 2;
300 gv->vsync_start /= 2;
301 gv->vsync_stop /= 2;
302 gv->vtotal /= 2;
303 gv->disp_flags &= ~GRF_FLAGS_LACE;
304 gv->disp_flags |= GRF_FLAGS_DBLSCAN;
305 printf("grfconfig: Old and no longer "
306 "supported vertical values for "
307 "doublescan modes.\n Wrong mode "
308 "line:\n %s\n This could be a "
309 "possible good mode line:\n ", obuf);
310 printf("%d ", gv->mode_num);
311 print_rawdata(gv, 0);
312 printf(" See the manpage of grfconfig for "
313 "more information about the new mode "
314 "definition file.\n");
315 return (1);
316 }
317
318 if (testmode == 1) {
319 if (lineno == 1)
320 printf("num clk wid hi dep hbs "
321 "hss hse ht vbs vss vse vt "
322 "flags\n");
323 printf("%d ", gv->mode_num);
324 print_rawdata(gv, 1);
325 } else {
326 gv->mode_descr[0] = 0;
327 if (ioctl(grffd, GRFIOCSETMON, (char *) gv) < 0)
328 printf("grfconfig: bad monitor "
329 "definition for mode #%d.\n",
330 gv->mode_num);
331 }
332 }
333 fclose(fp);
334 } else {
335 ioctl(grffd, GRFGETNUMVM, &y);
336 y += 2;
337 for (c = 1; c < y; c++) {
338 c = gv->mode_num = (c != (y - 1)) ? c : 255;
339 if (ioctl(grffd, GRFGETVMODE, gv) < 0)
340 continue;
341 if (rawdata) {
342 if (c == 255)
343 printf("c ");
344 else
345 printf("%d ", c);
346 print_rawdata(gv, 0);
347 continue;
348 }
349 if (c == 255)
350 printf("Console: ");
351 else
352 printf("%2d: ", gv->mode_num);
353
354 printf("%dx%d",
355 gv->disp_width,
356 gv->disp_height);
357
358 if (c != 255)
359 printf("x%d", gv->depth);
360 else
361 printf(" (%dx%d)",
362 gv->disp_width / 8,
363 gv->disp_height / gv->depth);
364
365 printf("\t%ld.%ldkHz @ %ldHz",
366 gv->pixel_clock / (gv->htotal * 1000),
367 (gv->pixel_clock / (gv->htotal * 100))
368 % 10,
369 gv->pixel_clock / (gv->htotal * gv->vtotal));
370 printf(" flags:");
371
372 if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
373 printf(" default");
374 } else {
375 for (grf_flagp = grf_flags;
376 grf_flagp->grf_flag_number; grf_flagp++) {
377 if (gv->disp_flags & grf_flagp->grf_flag_number) {
378 printf(" %s", grf_flagp->grf_flag_name);
379 }
380 }
381 }
382 printf("\n");
383 }
384 }
385
386 close(grffd);
387 return (0);
388 }
389
390 static void
391 print_rawdata(gv, rawflags)
392 struct grfvideo_mode *gv;
393 int rawflags;
394 {
395 struct grf_flag *grf_flagp;
396
397 printf("%ld %d %d %d %d %d %d %d %d %d %d %d",
398 gv->pixel_clock,
399 gv->disp_width,
400 gv->disp_height,
401 gv->depth,
402 gv->hblank_start,
403 gv->hsync_start,
404 gv->hsync_stop,
405 gv->htotal,
406 gv->vblank_start,
407 gv->vsync_start,
408 gv->vsync_stop,
409 gv->vtotal);
410 if (rawflags) {
411 printf(" 0x%.2x", gv->disp_flags);
412 } else {
413 if (gv->disp_flags == GRF_FLAGS_DEFAULT) {
414 printf(" default");
415 } else {
416 for (grf_flagp = grf_flags;
417 grf_flagp->grf_flag_number; grf_flagp++) {
418 if (gv->disp_flags & grf_flagp->grf_flag_number) {
419 printf(" %s", grf_flagp->grf_flag_name);
420 }
421 }
422 }
423 }
424 printf("\n");
425 }
426