aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/utils/xorgconfig/cards.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/utils/xorgconfig/cards.c')
-rw-r--r--xorg-server/hw/xfree86/utils/xorgconfig/cards.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/utils/xorgconfig/cards.c b/xorg-server/hw/xfree86/utils/xorgconfig/cards.c
new file mode 100644
index 000000000..8116f0a03
--- /dev/null
+++ b/xorg-server/hw/xfree86/utils/xorgconfig/cards.c
@@ -0,0 +1,278 @@
+/*
+ * Functions to manipulate card database.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cards.h"
+
+/* Some vars to make path names in texts more flexible. */
+#ifndef PROJECTROOT
+# define PROJECTROOT "/usr"
+#endif
+#define TREEROOT PROJECTROOT
+#define TREEROOTLX TREEROOT "/lib/X11"
+#define TREEROOTCFG TREEROOT "/etc/X11"
+#ifdef XDOCDIR
+# define TREEROOTDOC XDOCDIR
+#else
+# define TREEROOTDOC TREEROOTLX "/doc"
+#endif
+
+/*
+ * Database format:
+ *
+ * NAME <name of card>
+ * CHIPSET <chipset description>
+ * SERVER <server name>
+ * DRIVER <driver name>
+ *
+ * Optional keywords:
+ * RAMDAC <ramdac identifier>
+ * CLOCKCHIP <clockchip identifier>
+ * DACSPEED <dacspeed>
+ * NOCLOCKPROBE
+ * UNSUPPORTED
+ *
+ * SEE <name of card> refers to another card definition; parameters that
+ * are already defined are not overridden.
+ *
+ * <server name> is one of Mono, VGA16, SVGA, S3, Mach32, Mach8, 8514,
+ * P9000, AGX, W32.
+ *
+ * A useful additional keywords may be CLOCKS.
+ */
+
+
+
+/* Database vars. */
+
+int lastcard;
+
+Card card[MAX_CARDS];
+
+
+static int
+getnextline(FILE *f, char *l)
+{
+ if (fgets(l, 128, f) == NULL)
+ return -1;
+ return 0;
+}
+
+static void
+appendstring(char **destp, char *src)
+{
+ char *newstr;
+ newstr = malloc(strlen(*destp) + strlen(src) + 1);
+ strcpy(newstr, *destp);
+ strcat(newstr, src);
+ if (strlen(*destp) > 0)
+ free(*destp);
+ *destp = newstr;
+}
+
+int
+lookupcard(char *name) {
+ int i;
+ for (i = 0; i <= lastcard; i++)
+ if (strcmp(name, card[i].name) == 0)
+ return i;
+ return -1;
+}
+
+static char *s3_comment =
+"# Use Option \"nolinear\" if the server doesn't start up correctly\n"
+"# (this avoids the linear framebuffer probe). If that fails try\n"
+"# option \"nomemaccess\".\n"
+"#\n"
+"# Refer to " TREEROOTDOC "/README.S3, and the XF86_S3 man page.\n";
+
+static char *cirrus_comment =
+"# Use Option \"no_bitblt\" if you have graphics problems. If that fails\n"
+"# try Option \"noaccel\".\n"
+"# Refer to " TREEROOTDOC "/README.cirrus.\n"
+"# To allow linear addressing, uncomment the Option line and the\n"
+"# address that the card maps the framebuffer to.\n";
+
+int parse_database() {
+ FILE *f;
+ char buf[128];
+ int i, lineno;
+ char filename[128];
+
+ strcpy(filename, CARD_DATABASE_FILE);
+ f = fopen(filename, "r");
+ if (f == NULL)
+ return -1;
+
+ lastcard = -1;
+ lineno = 0;
+
+ for (;;) {
+ if (getnextline(f, buf))
+ break;
+ lineno++;
+ if (buf[0] == '#')
+ /* Comment. */
+ continue;
+ if (strncmp(buf, "END", 3) == 0)
+ /* End of database. */
+ break;
+ if (strncmp(buf, "LINE", 4) == 0 && lastcard>=0) {
+ /* Line of Device comment. */
+ /* Append to existing lines. */
+ appendstring(&card[lastcard].lines, buf + 5);
+ continue;
+ }
+ /*
+ * The following keywords require the trailing newline
+ * to be deleted.
+ */
+ i = strlen(buf);
+ buf[--i] = '\0';
+
+ /* remove trailing spaces or tabs */
+ for(--i; i>=0 && (buf[i] == ' ' || buf[i] == '\011'); i--) ;
+ if (i>=0)
+ buf[i+1] = '\0';
+ else
+ continue; /* skip empty lines */
+
+ if (strncmp(buf, "NAME", 4) == 0) {
+ /* New entry. */
+ lastcard++;
+ card[lastcard].name = malloc(strlen(buf + 5) + 1);
+ strcpy(card[lastcard].name, buf + 5);
+ card[lastcard].chipset = NULL;
+ card[lastcard].server = NULL;
+ card[lastcard].driver = NULL;
+ card[lastcard].ramdac = NULL;
+ card[lastcard].clockchip = NULL;
+ card[lastcard].dacspeed = NULL;
+ card[lastcard].flags = 0;
+ card[lastcard].lines = "";
+ continue;
+ }
+ if (lastcard < 0) /* no NAME line found yet */
+ continue;
+ if (strncmp(buf, "SEE", 3) == 0) {
+ /* Reference to another entry. */
+ int i;
+ i = lookupcard(buf + 4);
+ if (i == -1) {
+ printf("Error in database, invalid reference: %s.\n",
+ buf + 4);
+ free(card[lastcard].name);
+ lastcard--;
+ continue;
+ }
+ if (card[lastcard].chipset == NULL)
+ card[lastcard].chipset = card[i].chipset;
+ if (card[lastcard].server == NULL)
+ card[lastcard].server = card[i].server;
+ if (card[lastcard].driver == NULL)
+ card[lastcard].driver = card[i].driver;
+ if (card[lastcard].ramdac == NULL)
+ card[lastcard].ramdac = card[i].ramdac;
+ if (card[lastcard].clockchip == NULL)
+ card[lastcard].clockchip = card[i].clockchip;
+ if (card[lastcard].dacspeed == NULL)
+ card[lastcard].dacspeed = card[i].dacspeed;
+ card[lastcard].flags |= card[i].flags;
+ appendstring(&card[lastcard].lines, card[i].lines);
+ continue;
+ }
+ if (strncmp(buf, "CHIPSET", 7) == 0) {
+ /* Chipset description. */
+ card[lastcard].chipset = malloc(strlen(buf + 8) + 1);
+ strcpy(card[lastcard].chipset, buf + 8);
+ continue;
+ }
+ if (strncmp(buf, "SERVER", 6) == 0) {
+ /* Server identifier. */
+ card[lastcard].server = malloc(strlen(buf + 7) + 1);
+ strcpy(card[lastcard].server, buf + 7);
+ continue;
+ }
+ if (strncmp(buf, "DRIVER", 6) == 0) {
+ /* Driver identifier. */
+ card[lastcard].driver = malloc(strlen(buf + 7) + 1);
+ strcpy(card[lastcard].driver, buf + 7);
+ continue;
+ }
+ if (strncmp(buf, "RAMDAC", 6) == 0) {
+ /* Ramdac indentifier. */
+ card[lastcard].ramdac = malloc(strlen(buf + 7) + 1);
+ strcpy(card[lastcard].ramdac, buf + 7);
+ continue;
+ }
+ if (strncmp(buf, "CLOCKCHIP", 9) == 0) {
+ /* Clockchip indentifier. */
+ card[lastcard].clockchip = malloc(strlen(buf + 10) + 1);
+ strcpy(card[lastcard].clockchip, buf + 10);
+ card[lastcard].flags |= NOCLOCKPROBE;
+ continue;
+ }
+ if (strncmp(buf, "DACSPEED", 8) == 0) {
+ /* Clockchip indentifier. */
+ card[lastcard].dacspeed = malloc(strlen(buf + 9) + 1);
+ strcpy(card[lastcard].dacspeed, buf + 9);
+ continue;
+ }
+ if (strncmp(buf, "NOCLOCKPROBE", 12) == 0) {
+ card[lastcard].flags |= NOCLOCKPROBE;
+ continue;
+ }
+ if (strncmp(buf, "UNSUPPORTED", 12) == 0) {
+ card[lastcard].flags |= UNSUPPORTED;
+ continue;
+ }
+ /* test for missing required fields */
+ if (card[lastcard].driver == NULL) {
+ fprintf(stderr, "Warning DRIVER specification missing "
+ "in Card database entry %s (line %d).\n",
+ card[lastcard].name, lineno);
+ keypress();
+ card[lastcard].driver = "unknown";
+ }
+ if (card[lastcard].chipset == NULL) {
+ fprintf(stderr, "Warning CHIPSET specification missing "
+ "in Card database entry %s (line %d).\n",
+ card[lastcard].name, lineno);
+ keypress();
+ card[lastcard].chipset = "unknown";
+ }
+ }
+
+ fclose(f);
+
+ /*
+ * Add general comments.
+ */
+ for (i = 0; i <= lastcard; i++) {
+ if (card[i].server && strcmp(card[i].server, "S3") == 0)
+ appendstring(&card[i].lines, s3_comment);
+ if (card[i].chipset &&
+ strncmp(card[i].chipset, "CL-GD", 5) == 0)
+ appendstring(&card[i].lines, cirrus_comment);
+ }
+
+ sort_database();
+
+ return 0;
+}
+
+static int
+compare_card(const void *e1, const void *e2)
+{
+ return strcmp(((Card *)e1)->name, ((Card *)e2)->name);
+}
+
+void
+sort_database() {
+ /* Each element is a bunch of words, but nothing too bad. */
+ qsort(card, lastcard + 1, sizeof(Card), compare_card);
+}