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