1 /* $NetBSD: grfconfig.c,v 1.14 2009/04/26 19:24:18 mlelstv 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 * 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. 30 */ 31 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 */ 37 38 #ifndef lint 39 __RCSID("$NetBSD: grfconfig.c,v 1.14 2009/04/26 19:24:18 mlelstv Exp $"); 40 #endif /* not lint */ 41 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> 50 51 #include <amiga/dev/grfioctl.h> 52 53 int main __P((int, char **)); 54 static void print_rawdata __P((struct grfvideo_mode *, int)); 55 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} 68 }; 69 70 /* 71 * Dynamic mode loader for NetBSD/Amiga grf devices. 72 */ 73 int 74 main(ac, av) 75 int ac; 76 char **av; 77 { 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; 91 92 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); 104 } 105 } 106 ac -= optind; 107 av += optind; 108 109 110 if (ac >= 1) 111 grfdevice = av[0]; 112 else { 113 printf("grfconfig: No grf device specified.\n"); 114 return (1); 115 } 116 117 if (ac >= 2) 118 modefile = av[1]; 119 120 if ((grffd = open(grfdevice, O_RDWR)) < 0) { 121 printf("grfconfig: can't open grf device.\n"); 122 return (1); 123 } 124 /* If a mode file is specificied, load it in, don't display any info. */ 125 126 if (modefile) { 127 if (!(fp = fopen(modefile, "r"))) { 128 printf("grfconfig: Cannot open mode definition " 129 "file.\n"); 130 return (1); 131 } 132 while (fgets(buf, sizeof(buf), fp)) { 133 char *obuf, tbuf[_POSIX2_LINE_MAX], *tbuf2; 134 /* 135 * check for end-of-section, comments, strip off trailing 136 * spaces and newline character. 137 */ 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'; 145 146 obuf = buf; 147 tbuf2 = tbuf; 148 while ((*tbuf2 = *obuf) != '\0') { 149 if (*tbuf2 == '#') { 150 *tbuf2 = '\0'; 151 break; 152 } 153 if (isupper((unsigned char)*tbuf2)) { 154 *tbuf2 = tolower((unsigned char)*tbuf2); 155 } 156 obuf++; 157 tbuf2++; 158 } 159 obuf = tbuf; 160 161 lineno = lineno + 1; 162 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; 167 168 if (i < 14) { 169 printf("grfconfig: too few values in mode " 170 "definition file:\n %s\n", obuf); 171 return (1); 172 } 173 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]); 186 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); 197 } 198 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); 214 } 215 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; 224 } 225 } 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); 234 } 235 } 236 237 /* 238 * Check for impossible gv->disp_flags: 239 * doublescan and interlace, 240 * +hsync and -hsync 241 * +vsync and -vsync. 242 */ 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"; 253 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); 259 } 260 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); 278 } 279 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); 321 } 322 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); 336 } 337 } 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; 353 } 354 if (c == 255) 355 printf("Console: "); 356 else 357 printf("%2d: ", gv->mode_num); 358 359 printf("%dx%d", 360 gv->disp_width, 361 gv->disp_height); 362 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); 369 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:"); 376 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); 384 } 385 } 386 } 387 printf("\n"); 388 } 389 } 390 391 close(grffd); 392 return (0); 393 } 394 395 static void 396 print_rawdata(gv, rawflags) 397 struct grfvideo_mode *gv; 398 int rawflags; 399 { 400 struct grf_flag *grf_flagp; 401 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); 425 } 426 } 427 } 428 } 429 printf("\n"); 430 } 431