1 /* $NetBSD: grfconfig.c,v 1.10 2001/01/22 21:11:23 is 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.10 2001/01/22 21:11:23 is 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(*p); ++p) 146 continue; 147 if (*p == '\0' || *p == '#') 148 continue; 149 for (p = strchr(buf, '\0'); isspace(*--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(*tbuf2)) { 161 *tbuf2 = tolower(*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