First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / utils / xorgcfg / cards.c
blobdcd5828cb0de03f5ebb43df2bdbd3bb8da117f17
1 /*
2 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
22 * Except as contained in this notice, the name of Conectiva Linux shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from
25 * Conectiva Linux.
27 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
31 #define CARDS_PRIVATE
32 #include "cards.h"
34 #undef SERVER /* defined in config.h, but of no use here */
36 /* return values from ReadCardsLine. */
37 #define ERROR -3
38 #define UNKNOWN -2
39 #define END -1
40 #define NOTUSEFUL 0
41 #define NAME 1
42 #define CHIPSET 2
43 #define SERVER 3
44 #define DRIVER 4
45 #define RAMDAC 5
46 #define CLOCKCHIP 6
47 #define DACSPEED 7
48 #define NOCLOCKPROBE 8
49 #define UNSUPPORTED 9
50 #define SEE 10
51 #define LINE 11
54 * Prototypes
56 static int ReadCardsLine(FILE*, char*); /* must have 256 bytes */
57 static int CompareCards(_Xconst void *left, _Xconst void *right);
58 static int BCompareCards(_Xconst void *left, _Xconst void *right);
59 static void DoReadCardsDatabase(void);
60 static char **DoFilterCardNames(char *pattern, int *result);
62 #ifdef USE_MODULES
64 typedef struct {
65 int ivendor;
66 unsigned short vendor;
67 unsigned short valid_vendor;
68 char *chipsets;
69 int num_chipsets;
70 } chipset_check;
71 #endif
74 * Initialization
76 static int linenum = 0;
77 static char *Cards = "lib/X11/Cards";
78 CardsEntry **CardsDB;
79 int NumCardsEntry;
82 * Implementation
84 #ifdef USE_MODULES
85 const pciVendorInfo *xf86PCIVendorInfo;
86 #endif
88 #ifdef USE_MODULES
89 void
90 InitializePciInfo(void)
92 xf86PCIVendorInfo = pciVendorInfoList;
95 void
96 CheckChipsets(xf86cfgModuleOptions *opts, int *err)
98 int i, j, ichk, ivnd = 0, vendor = -1, device;
99 const pciDeviceInfo **pDev;
100 SymTabPtr chips = opts->chipsets;
101 chipset_check *check = NULL;
102 int num_check = 0;
104 if (!chips) {
105 CheckMsg(CHECKER_NO_CHIPSETS, "WARNING No chipsets specified.\n");
106 ++*err;
107 return;
110 while (chips->name) {
111 device = chips->token & 0xffff;
112 vendor = (chips->token & 0xffff0000) >> 16;
113 if (vendor == 0)
114 vendor = opts->vendor;
116 for (ichk = 0; ichk < num_check; ichk++)
117 if (check[ichk].vendor == vendor)
118 break;
119 if (ichk >= num_check) {
120 check = (chipset_check*)
121 XtRealloc((XtPointer)check,
122 sizeof(chipset_check) * (num_check + 1));
123 check[num_check].vendor = vendor;
124 memset(&check[num_check], 0, sizeof(chipset_check));
125 ++num_check;
128 /* Search for vendor in xf86PCIVendorInfo */
129 if (xf86PCIVendorInfo) {
130 for (ivnd = 0; xf86PCIVendorInfo[ivnd].VendorID; ivnd++)
131 if (vendor == xf86PCIVendorInfo[ivnd].VendorID)
132 break;
134 if (xf86PCIVendorInfo && xf86PCIVendorInfo[ivnd].VendorID) {
135 check[ichk].valid_vendor = 1;
136 check[ichk].ivendor = ivnd;
138 else {
139 CheckMsg(CHECKER_CANNOT_VERIFY_CHIPSET,
140 "WARNING Cannot verify chipset \"%s\" (0x%x)\n",
141 chips->name, device);
142 ++*err;
143 ++chips;
144 continue;
147 if (xf86PCIVendorInfo &&
148 (pDev = xf86PCIVendorInfo[ivnd].Device) != NULL) {
149 if (check[ichk].chipsets == NULL) {
150 for (j = 0; pDev[j]; j++)
152 check[ichk].chipsets = (char*)XtCalloc(1, j);
154 for (j = 0; pDev[j]; j++) {
155 if (device == pDev[j]->DeviceID) {
156 if (strcmp(chips->name, pDev[j]->DeviceName)) {
157 CheckMsg(CHECKER_NOMATCH_CHIPSET_STRINGS,
158 "WARNING chipset strings don't match: \"%s\" \"%s\" (0x%x)\n",
159 chips->name, xf86PCIVendorInfo[ivnd].Device[j]->DeviceName,
160 device);
161 ++*err;
163 break;
166 if (!pDev[j]) {
167 CheckMsg(CHECKER_CHIPSET_NOT_LISTED,
168 "WARNING chipset \"%s\" (0x%x) not in list.\n", chips->name, device);
169 ++*err;
171 else
172 check[ichk].chipsets[j] = 1;
174 ++chips;
177 for (i = 0; i < num_check; i++) {
178 if (!check[i].valid_vendor) {
179 CheckMsg(CHECKER_CHIPSET_NO_VENDOR,
180 "WARNING No such vendor 0x%x\n", vendor);
181 ++*err;
183 for (j = 0; j < check[i].num_chipsets; j++) {
184 if (xf86PCIVendorInfo && !check[i].chipsets[j]) {
185 CheckMsg(CHECKER_CHIPSET_NOT_SUPPORTED,
186 "NOTICE chipset \"%s\" (0x%x) not listed as supported.\n",
187 xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceName,
188 xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceID);
191 XtFree(check[i].chipsets);
194 XtFree((XtPointer)check);
196 #endif
198 void
199 ReadCardsDatabase(void)
201 #ifdef USE_MODULES
202 if (!nomodules) {
203 int i, j, ivendor, idevice;
204 char name[256];
205 _Xconst char *vendor, *device;
206 CardsEntry *entry = NULL, *tmp;
207 xf86cfgModuleOptions *opts = module_options;
208 const pciDeviceInfo **pDev;
210 /* Only list cards that have a driver installed */
211 while (opts) {
212 if (opts->chipsets) {
213 SymTabPtr chips = opts->chipsets;
215 while (chips->name) {
216 vendor = opts->name;
217 device = chips->name;
218 ivendor = (chips->token & 0xffff0000) >> 16;
219 idevice = chips->token & 0xffff0;
220 if (ivendor == 0)
221 ivendor = opts->vendor;
223 if (xf86PCIVendorInfo) {
224 for (i = 0; xf86PCIVendorInfo[i].VendorName; i++)
225 if (ivendor == xf86PCIVendorInfo[i].VendorID) {
226 vendor = xf86PCIVendorInfo[i].VendorName;
227 break;
229 if (xf86PCIVendorInfo[i].VendorName) {
230 if ((pDev = xf86PCIVendorInfo[i].Device)) {
231 for (j = 0; pDev[j]; j++)
232 if (idevice == pDev[j]->DeviceID) {
233 device = pDev[j]->DeviceName;
234 break;
240 /* Since frequently there is more than one driver for a
241 * single vendor, it is required to avoid duplicates.
243 XmuSnprintf(name, sizeof(name), "%s %s", vendor, device);
244 tmp = LookupCard(name);
246 if (tmp == NULL || strcmp(tmp->chipset, chips->name) ||
247 strcmp(tmp->driver, opts->name)) {
248 entry = (CardsEntry*)XtCalloc(1, sizeof(CardsEntry));
249 if (NumCardsEntry % 16 == 0) {
250 CardsDB = (CardsEntry**)XtRealloc((XtPointer)CardsDB,
251 sizeof(CardsEntry*) * (NumCardsEntry + 16));
253 CardsDB[NumCardsEntry++] = entry;
254 entry->name = XtNewString(name);
256 /* XXX no private copy of strings */
257 entry->chipset = (char*)chips->name;
258 entry->driver = opts->name;
260 /* better than linear searchs to find duplicates */
261 qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*),
262 CompareCards);
264 ++chips;
267 opts = opts->next;
270 /* fix entries with the same name */
271 for (i = 0; i < NumCardsEntry - 2;) {
272 for (j = i + 1; j < NumCardsEntry - 1 &&
273 strcmp(CardsDB[i]->name, CardsDB[j]->name) == 0; j++)
276 if (i + 1 != j) {
277 while (i < j) {
278 char *str;
280 if (strcmp(CardsDB[i]->chipset, CardsDB[j]->chipset))
281 str = CardsDB[i]->chipset;
282 else
283 str = CardsDB[i]->driver;
285 XmuSnprintf(name, sizeof(name), "%s (%s)",
286 CardsDB[i]->name, str);
287 XtFree(CardsDB[i]->name);
288 CardsDB[i]->name = XtNewString(name);
290 ++i;
293 else
294 ++i;
297 /* make sure data is valid to bsearch in */
298 qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
300 else
301 #endif
302 DoReadCardsDatabase();
305 static void
306 DoReadCardsDatabase(void)
308 char buffer[256];
309 FILE *fp = fopen(Cards, "r");
310 int i, result;
311 CardsEntry *entry = NULL;
312 static char *CardsError = "Error reading Cards database, at line %d (%s).\n";
314 if (fp == NULL) {
315 fprintf(stderr, "Cannot open Cards database.\n");
316 exit(1);
319 while ((result = ReadCardsLine(fp, buffer)) != END) {
320 switch (result) {
321 case ERROR:
322 fprintf(stderr, CardsError, linenum, buffer);
323 break;
324 case UNKNOWN:
325 fprintf(stderr,
326 "Unknown field type in Cards database, at line %d (%s).\n",
327 linenum, buffer);
328 break;
329 case NAME:
330 entry = calloc(1, sizeof(CardsEntry));
331 if (NumCardsEntry % 16 == 0) {
332 CardsDB = realloc(CardsDB, sizeof(CardsEntry*) *
333 (NumCardsEntry + 16));
334 if (CardsDB == NULL) {
335 fprintf(stderr, "Out of memory reading Cards database.\n");
336 exit(1);
339 CardsDB[NumCardsEntry++] = entry;
340 entry->name = strdup(buffer);
341 break;
342 case CHIPSET:
343 if (entry == NULL || entry->chipset != NULL) {
344 fprintf(stderr, CardsError, linenum, buffer);
346 #if 0
347 else
348 entry->chipset = strdup(buffer);
349 #endif
350 break;
351 case SERVER:
352 if (entry == NULL || entry->server != NULL) {
353 fprintf(stderr, CardsError, linenum, buffer);
355 else
356 entry->server = strdup(buffer);
357 break;
358 case DRIVER:
359 if (entry == NULL || entry->driver != NULL) {
360 fprintf(stderr, CardsError, linenum, buffer);
362 else
363 entry->driver = strdup(buffer);
364 break;
365 case RAMDAC:
366 if (entry == NULL || entry->ramdac != NULL) {
367 fprintf(stderr, CardsError, linenum, buffer);
369 else
370 entry->ramdac = strdup(buffer);
371 break;
372 case CLOCKCHIP:
373 if (entry == NULL || entry->clockchip != NULL) {
374 fprintf(stderr, CardsError, linenum, buffer);
376 else
377 entry->clockchip = strdup(buffer);
378 break;
379 case DACSPEED:
380 if (entry == NULL || entry->dacspeed != NULL) {
381 fprintf(stderr, CardsError, linenum, buffer);
383 else
384 entry->dacspeed = strdup(buffer);
385 break;
386 case NOCLOCKPROBE:
387 if (entry == NULL) {
388 fprintf(stderr, CardsError, linenum, buffer);
390 else
391 entry->flags |= F_NOCLOCKPROBE;
392 break;
393 case UNSUPPORTED:
394 if (entry == NULL) {
395 fprintf(stderr, CardsError, linenum, buffer);
397 else
398 entry->flags |= F_UNSUPPORTED;
399 break;
400 case SEE:
401 if (entry == NULL || entry->see != NULL) {
402 fprintf(stderr, CardsError, linenum, buffer);
404 else
405 entry->see = strdup(buffer);
406 break;
407 case LINE:
408 if (entry == NULL) {
409 fprintf(stderr, CardsError, linenum, buffer);
411 else if (entry->lines == NULL)
412 entry->lines = strdup(buffer);
413 else {
414 char *str = malloc(strlen(entry->lines) + strlen(buffer) + 2);
416 sprintf(str, "%s\n%s", entry->lines, buffer);
417 free(entry->lines);
418 entry->lines = str;
420 break;
424 fclose(fp);
426 qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
428 #ifdef DEBUG
429 for (i = 0; i < NumCardsEntry - 1; i++) {
430 if (strcmp(CardsDB[i]->name, CardsDB[i+1]->name) == 0)
431 fprintf(stderr, "Duplicate entry in Cards database: (%s).\n",
432 CardsDB[i]->name);
434 #endif
436 for (i = 0; i < NumCardsEntry - 1; i++) {
437 if (CardsDB[i]->see != NULL) {
438 if ((entry = LookupCard(CardsDB[i]->see)) == NULL) {
439 fprintf(stderr, "Cannot find card '%s' for filling defaults.\n",
440 CardsDB[i]->see);
441 continue;
443 if (CardsDB[i]->chipset == NULL && entry->chipset != NULL)
444 CardsDB[i]->chipset = strdup(entry->chipset);
445 if (CardsDB[i]->server == NULL && entry->server != NULL)
446 CardsDB[i]->server = strdup(entry->server);
447 if (CardsDB[i]->driver == NULL && entry->driver != NULL)
448 CardsDB[i]->driver = strdup(entry->driver);
449 if (CardsDB[i]->ramdac == NULL && entry->ramdac != NULL)
450 CardsDB[i]->ramdac = strdup(entry->ramdac);
451 if (CardsDB[i]->clockchip == NULL && entry->clockchip != NULL)
452 CardsDB[i]->clockchip = strdup(entry->clockchip);
453 if (CardsDB[i]->dacspeed == NULL && entry->dacspeed != NULL)
454 CardsDB[i]->dacspeed = strdup(entry->dacspeed);
455 if (CardsDB[i]->flags & F_NOCLOCKPROBE)
456 CardsDB[i]->flags |= F_NOCLOCKPROBE;
457 if (CardsDB[i]->flags & F_UNSUPPORTED)
458 CardsDB[i]->flags |= F_UNSUPPORTED;
459 if (entry->lines != NULL) {
460 if (CardsDB[i]->lines == NULL)
461 CardsDB[i]->lines = strdup(entry->lines);
462 else {
463 char *str = malloc(strlen(entry->lines) +
464 strlen(CardsDB[i]->lines) + 2);
466 sprintf(str, "%s\n%s", CardsDB[i]->lines, entry->lines);
467 free(CardsDB[i]->lines);
468 CardsDB[i]->lines = str;
471 if (entry->see != NULL) {
472 #ifdef DEBUG
473 fprintf(stderr, "Nested SEE entry: %s -> %s -> %s\n",
474 CardsDB[i]->name, CardsDB[i]->see, entry->see);
475 #endif
476 CardsDB[i]->see = strdup(entry->see);
477 --i;
478 continue;
480 free(CardsDB[i]->see);
481 CardsDB[i]->see = NULL;
486 CardsEntry *
487 LookupCard(char *name)
489 CardsEntry **ptr;
491 if (NumCardsEntry == 0 || CardsDB == 0)
492 return NULL;
494 ptr = (CardsEntry**)bsearch(name, CardsDB, NumCardsEntry,
495 sizeof(CardsEntry*), BCompareCards);
497 return (ptr != NULL ? *ptr : NULL);
500 char **
501 GetCardNames(int *result)
503 char **cards = NULL;
504 int ncards;
506 for (ncards = 0; ncards < NumCardsEntry; ncards++) {
507 if (ncards % 16 == 0) {
508 if ((cards = (char**)realloc(cards, sizeof(char*) *
509 (ncards + 16))) == NULL) {
510 fprintf(stderr, "Out of memory.\n");
511 exit(1);
514 cards[ncards] = strdup(CardsDB[ncards]->name);
517 *result = ncards;
519 return (cards);
522 char **
523 FilterCardNames(char *pattern, int *result)
525 #ifdef USE_MODULES
526 if (!nomodules) {
527 char **cards = NULL;
528 int i, ncards = 0;
530 for (i = 0; i < NumCardsEntry; i++) {
531 if (strstr(CardsDB[i]->name, pattern) == NULL)
532 continue;
533 if (ncards % 16 == 0) {
534 if ((cards = (char**)realloc(cards, sizeof(char*) *
535 (ncards + 16))) == NULL) {
536 fprintf(stderr, "Out of memory.\n");
537 exit(1);
540 cards[ncards] = strdup(CardsDB[i]->name);
541 ++ncards;
544 *result = ncards;
546 return (cards);
548 #endif
549 return (DoFilterCardNames(pattern, result));
552 static char **
553 DoFilterCardNames(char *pattern, int *result)
555 FILE *fp;
556 char **cards = NULL;
557 int len, ncards = 0;
558 char *cmd, *ptr, buffer[256];
560 cmd = malloc(32 + (strlen(pattern) * 2) + strlen(Cards));
562 strcpy(cmd, "egrep -i '^NAME\\ .*");
563 len = strlen(cmd);
564 ptr = pattern;
565 while (*ptr) {
566 if (!isalnum(*ptr)) {
567 cmd[len++] = '\\';
569 cmd[len++] = *ptr++;
571 cmd[len] = '\0';
572 strcat(cmd, ".*$' ");
573 strcat(cmd, Cards);
574 strcat(cmd, " | sort");
575 /*sprintf(cmd, "egrep -i '^NAME\\ .*%s.*$' %s | sort", pattern, Cards);*/
577 if ((fp = popen(cmd, "r")) == NULL) {
578 fprintf(stderr, "Cannot read Cards database.\n");
579 exit(1);
581 while (fgets(buffer, sizeof(buffer), fp) != NULL) {
582 ptr = buffer + strlen(buffer) - 1;
583 while (isspace(*ptr) && ptr > buffer)
584 --ptr;
585 if (!isspace(*ptr) && ptr > buffer)
586 ptr[1] = '\0';
587 ptr = buffer;
588 while (!isspace(*ptr) && *ptr) /* skip NAME */
589 ++ptr;
590 while (isspace(*ptr) && *ptr)
591 ++ptr;
592 if (ncards % 16 == 0) {
593 if ((cards = (char**)realloc(cards, sizeof(char*) *
594 (ncards + 16))) == NULL) {
595 fprintf(stderr, "Out of memory.\n");
596 exit(1);
599 cards[ncards++] = strdup(ptr);
601 free(cmd);
603 *result = ncards;
605 return (cards);
608 static int
609 ReadCardsLine(FILE *fp, char *value)
611 char name[32], buffer[256], *ptr, *end;
612 int result = NOTUSEFUL;
614 ++linenum;
616 if (fgets(buffer, sizeof(buffer), fp) == NULL)
617 return (END);
619 ptr = buffer;
620 /* skip initial spaces; should'nt bother about this.. */
621 while (isspace(*ptr) && *ptr)
622 ++ptr;
624 if (*ptr == '#' || *ptr == '\0')
625 return (NOTUSEFUL);
627 end = ptr;
628 while (!isspace(*end) && *end)
629 ++end;
630 if (end - ptr > sizeof(buffer) - 1) {
631 strncpy(value, buffer, 255);
632 value[255] = '\0';
633 return (ERROR);
635 strncpy(name, ptr, end - ptr);
636 name[end - ptr] = '\0';
638 /* read the optional arguments */
639 ptr = end;
640 while (isspace(*ptr) && *ptr)
641 ++ptr;
643 end = ptr + strlen(ptr) - 1;
644 while (isspace(*end) && end > ptr)
645 --end;
646 if (!isspace(*end))
647 ++end;
648 *end = '\0';
650 if (strcmp(name, "NAME") == 0)
651 result = NAME;
652 else if (strcmp(name, "CHIPSET") == 0)
653 result = CHIPSET;
654 else if (strcmp(name, "SERVER") == 0)
655 result = SERVER;
656 else if (strcmp(name, "DRIVER") == 0)
657 result = DRIVER;
658 else if (strcmp(name, "RAMDAC") == 0)
659 result = RAMDAC;
660 else if (strcmp(name, "CLOCKCHIP") == 0)
661 result = CLOCKCHIP;
662 else if (strcmp(name, "DACSPEED") == 0)
663 result = DACSPEED;
664 else if (strcmp(name, "NOCLOCKPROBE") == 0)
665 result = NOCLOCKPROBE;
666 else if (strcmp(name, "UNSUPPORTED") == 0)
667 result = UNSUPPORTED;
668 else if (strcmp(name, "SEE") == 0)
669 result = SEE;
670 else if (strcmp(name, "LINE") == 0)
671 result = LINE;
672 else if (strcmp(name, "END") == 0)
673 result = END;
674 else {
675 strcpy(value, name);
676 return (UNKNOWN);
679 /* value *must* have at least 256 bytes */
680 strcpy(value, ptr);
682 return (result);
685 static int
686 CompareCards(_Xconst void *left, _Xconst void *right)
688 return strcasecmp((*(CardsEntry**)left)->name, (*(CardsEntry**)right)->name);
691 static int
692 BCompareCards(_Xconst void *name, _Xconst void *card)
694 return (strcasecmp((char*)name, (*(CardsEntry**)card)->name));