/* $NetBSD: grfconfig.c,v 1.16 2016/02/29 18:59:52 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Ezra Story and Bernd Ernesti. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint __COPYRIGHT("@(#) Copyright (c) 1997\ The NetBSD Foundation, Inc. All rights reserved."); #endif /* not lint */ #ifndef lint __RCSID("$NetBSD: grfconfig.c,v 1.16 2016/02/29 18:59:52 christos Exp $"); #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include static void print_modeline(FILE *fp, struct grfvideo_mode *, int); static void suggest(struct grfvideo_mode *, const char *, const char *); static struct grf_flag { u_short grf_flag_number; const char *grf_flag_name; } grf_flags[] = { {GRF_FLAGS_DBLSCAN, "doublescan"}, {GRF_FLAGS_LACE, "interlace"}, {GRF_FLAGS_PHSYNC, "+hsync"}, {GRF_FLAGS_NHSYNC, "-hsync"}, {GRF_FLAGS_PVSYNC, "+vsync"}, {GRF_FLAGS_NVSYNC, "-vsync"}, {GRF_FLAGS_SYNC_ON_GREEN, "sync-on-green"}, {0, 0} }; /* * Dynamic mode loader for NetBSD/Amiga grf devices. */ int main(int ac, char **av) { struct grfvideo_mode gv[1]; struct grf_flag *grf_flagp; FILE *fp; int c, y, grffd; size_t i; int lineno = 0; int uplim, lowlim; char rawdata = 0, testmode = 0; char *grfdevice = 0, *ptr; char *modefile = 0; char buf[_POSIX2_LINE_MAX]; char *cps[31]; char *p; const char *errortext; while ((c = getopt(ac, av, "rt")) != -1) { switch (c) { case 'r': /* raw output */ rawdata = 1; break; case 't': /* test the modefile without setting it */ testmode = 1; break; default: printf("grfconfig [-r] device [file]\n"); return (1); } } ac -= optind; av += optind; if (ac < 1) errx(EXIT_FAILURE, "No grf device specified"); grfdevice = av[0]; if (ac >= 2) modefile = av[1]; if ((grffd = open(grfdevice, O_RDWR)) == -1) err(EXIT_FAILURE, "Can't open grf device `%s'", grfdevice); /* If a mode file is specificied, load it in, don't display any info. */ if (modefile) { if (!(fp = fopen(modefile, "r"))) err(EXIT_FAILURE, "Cannot open mode definition file `%s'", modefile); while (fgets(buf, sizeof(buf), fp)) { char *obuf, tbuf[_POSIX2_LINE_MAX], *tbuf2; /* * check for end-of-section, comments, strip off trailing * spaces and newline character. */ for (p = buf; isspace((unsigned char)*p); ++p) continue; if (*p == '\0' || *p == '#') continue; for (p = strchr(buf, '\0'); isspace((unsigned char)*--p);) continue; *++p = '\0'; obuf = buf; tbuf2 = tbuf; while ((*tbuf2 = *obuf) != '\0') { if (*tbuf2 == '#') { *tbuf2 = '\0'; break; } if (isupper((unsigned char)*tbuf2)) { *tbuf2 = tolower((unsigned char)*tbuf2); } obuf++; tbuf2++; } obuf = tbuf; lineno = lineno + 1; #define SP " \b\t\r\n" memset(cps, 0, sizeof(cps)); for (i = 0, ptr = strtok(buf, SP); ptr != NULL && i < __arraycount(cps); i++, ptr = strtok(NULL, SP)) cps[i] = ptr; if (i < 14) errx(EXIT_FAILURE, "Too few values in mode " "definition file: `%s'\n", obuf); gv->pixel_clock = atoi(cps[1]); gv->disp_width = atoi(cps[2]); gv->disp_height = atoi(cps[3]); gv->depth = atoi(cps[4]); gv->hblank_start = atoi(cps[5]); gv->hsync_start = atoi(cps[6]); gv->hsync_stop = atoi(cps[7]); gv->htotal = atoi(cps[8]); gv->vblank_start = atoi(cps[9]); gv->vsync_start = atoi(cps[10]); gv->vsync_stop = atoi(cps[11]); gv->vtotal = atoi(cps[12]); if ((y = atoi(cps[0]))) gv->mode_num = y; else if (strncasecmp("c", cps[0], 1) == 0) { gv->mode_num = 255; gv->depth = 4; } else { errx(EXIT_FAILURE, "Illegal mode number: %s", cps[0]); } if ((gv->pixel_clock == 0) || (gv->disp_width == 0) || (gv->disp_height == 0) || (gv->depth == 0) || (gv->hblank_start == 0) || (gv->hsync_start == 0) || (gv->hsync_stop == 0) || (gv->htotal == 0) || (gv->vblank_start == 0) || (gv->vsync_start == 0) || (gv->vsync_stop == 0) || (gv->vtotal == 0)) { errx(EXIT_FAILURE, "Illegal value in " "mode #%d: `%s'", gv->mode_num, obuf); } if (strstr(obuf, "default") != NULL) { gv->disp_flags = GRF_FLAGS_DEFAULT; } else { gv->disp_flags = GRF_FLAGS_DEFAULT; for (grf_flagp = grf_flags; grf_flagp->grf_flag_number; grf_flagp++) { if (strstr(obuf, grf_flagp->grf_flag_name) != NULL) { gv->disp_flags |= grf_flagp->grf_flag_number; } } if (gv->disp_flags == GRF_FLAGS_DEFAULT) errx(EXIT_FAILURE, "Your are using a " "mode file with an obsolete " "format"); } /* * Check for impossible gv->disp_flags: * doublescan and interlace, * +hsync and -hsync * +vsync and -vsync. */ errortext = NULL; if ((gv->disp_flags & GRF_FLAGS_DBLSCAN) && (gv->disp_flags & GRF_FLAGS_LACE)) errortext = "Interlace and Doublescan"; if ((gv->disp_flags & GRF_FLAGS_PHSYNC) && (gv->disp_flags & GRF_FLAGS_NHSYNC)) errortext = "+hsync and -hsync"; if ((gv->disp_flags & GRF_FLAGS_PVSYNC) && (gv->disp_flags & GRF_FLAGS_NVSYNC)) errortext = "+vsync and -vsync"; if (errortext != NULL) errx(EXIT_FAILURE, "Illegal flags in " "mode #%d: `%s' are both defined", gv->mode_num, errortext); /* Check for old horizontal cycle values */ if ((gv->htotal < (gv->disp_width / 4))) { gv->hblank_start *= 8; gv->hsync_start *= 8; gv->hsync_stop *= 8; gv->htotal *= 8; suggest(gv, "horizontal videoclock cycle " "values", obuf); return EXIT_FAILURE; } /* Check for old interlace or doublescan modes */ uplim = gv->disp_height + (gv->disp_height / 4); lowlim = gv->disp_height - (gv->disp_height / 4); if (((gv->vtotal * 2) > lowlim) && ((gv->vtotal * 2) < uplim)) { gv->vblank_start *= 2; gv->vsync_start *= 2; gv->vsync_stop *= 2; gv->vtotal *= 2; gv->disp_flags &= ~GRF_FLAGS_DBLSCAN; gv->disp_flags |= GRF_FLAGS_LACE; suggest(gv, "vertical values for interlace " "modes", obuf); return EXIT_FAILURE; } else if (((gv->vtotal / 2) > lowlim) && ((gv->vtotal / 2) < uplim)) { gv->vblank_start /= 2; gv->vsync_start /= 2; gv->vsync_stop /= 2; gv->vtotal /= 2; gv->disp_flags &= ~GRF_FLAGS_LACE; gv->disp_flags |= GRF_FLAGS_DBLSCAN; suggest(gv, "vertical values for doublescan " "modes", obuf); return EXIT_FAILURE; } if (testmode == 1) { if (lineno == 1) printf("num clk wid hi dep hbs " "hss hse ht vbs vss vse vt " "flags\n"); print_modeline(stdout, gv, 1); } else { gv->mode_descr[0] = 0; if (ioctl(grffd, GRFIOCSETMON, (char *) gv) < 0) err(EXIT_FAILURE, "bad monitor " "definition for mode #%d", gv->mode_num); } } fclose(fp); } else { ioctl(grffd, GRFGETNUMVM, &y); y += 2; for (c = 1; c < y; c++) { c = gv->mode_num = (c != (y - 1)) ? c : 255; if (ioctl(grffd, GRFGETVMODE, gv) < 0) continue; if (rawdata) { print_modeline(stdout, gv, 0); continue; } if (c == 255) printf("Console: "); else printf("%2d: ", gv->mode_num); printf("%dx%d", gv->disp_width, gv->disp_height); if (c != 255) printf("x%d", gv->depth); else printf(" (%dx%d)", gv->disp_width / 8, gv->disp_height / gv->depth); printf("\t%ld.%ldkHz @ %ldHz", gv->pixel_clock / (gv->htotal * 1000), (gv->pixel_clock / (gv->htotal * 100)) % 10, gv->pixel_clock / (gv->htotal * gv->vtotal)); printf(" flags:"); if (gv->disp_flags == GRF_FLAGS_DEFAULT) { printf(" default\n"); continue; } for (grf_flagp = grf_flags; grf_flagp->grf_flag_number; grf_flagp++) if (gv->disp_flags & grf_flagp->grf_flag_number) printf(" %s", grf_flagp->grf_flag_name); printf("\n"); } } close(grffd); return EXIT_SUCCESS; } static void suggest(struct grfvideo_mode *gv, const char *d, const char *s) { warnx("Old and no longer supported %s: %s", d, s); warnx("Wrong mode line, this could be a possible good model line:"); fprintf(stderr, "%s: ", getprogname()); print_modeline(stderr, gv, 0); } static void print_modeline(FILE *fp, struct grfvideo_mode *gv, int rawflags) { struct grf_flag *grf_flagp; if (gv->mode_num == 255) fprintf(fp, "c "); else fprintf(fp, "%d ", gv->mode_num); fprintf(fp, "%ld %d %d %d %d %d %d %d %d %d %d %d", gv->pixel_clock, gv->disp_width, gv->disp_height, gv->depth, gv->hblank_start, gv->hsync_start, gv->hsync_stop, gv->htotal, gv->vblank_start, gv->vsync_start, gv->vsync_stop, gv->vtotal); if (rawflags) { fprintf(fp, " 0x%.2x\n", gv->disp_flags); return; } if (gv->disp_flags == GRF_FLAGS_DEFAULT) { fprintf(fp, " default\n"); return; } for (grf_flagp = grf_flags; grf_flagp->grf_flag_number; grf_flagp++) if (gv->disp_flags & grf_flagp->grf_flag_number) fprintf(fp, " %s", grf_flagp->grf_flag_name); fprintf(fp, "\n"); }