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