299 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			299 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XConsortium: cards.c /main/9 1996/10/19 18:15:32 kaleb $ */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *  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;
 | |
| #ifdef __UNIXOS2__
 | |
| 	{
 | |
| 		char *p = strchr(l,'\r');
 | |
| 		if (p) {
 | |
| 			*p = '\n';
 | |
| 			*(p+1) = '\0';
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| 	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];
 | |
| 
 | |
| #ifndef __UNIXOS2__
 | |
| 	strcpy(filename, CARD_DATABASE_FILE);
 | |
| #else
 | |
| 	strcpy(filename, (char*)__XOS2RedirRoot(CARD_DATABASE_FILE));
 | |
| #endif
 | |
| 	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);
 | |
| }
 |