2
* Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
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
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
27
* Author: Paulo CĆ©sar Pereira de Andrade <pcpa@conectiva.com.br>
29
* $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/cards.c,v 1.14 2002/09/12 15:19:07 tsi Exp $
35
#undef SERVER /* defined in config.h, but of no use here */
37
/* return values from ReadCardsLine. */
49
#define NOCLOCKPROBE 8
57
static int ReadCardsLine(FILE*, char*); /* must have 256 bytes */
58
static int CompareCards(_Xconst void *left, _Xconst void *right);
59
static int BCompareCards(_Xconst void *left, _Xconst void *right);
60
static void DoReadCardsDatabase(void);
61
static char **DoFilterCardNames(char *pattern, int *result);
67
unsigned short vendor;
68
unsigned short valid_vendor;
77
static int linenum = 0;
78
static char *Cards = "lib/X11/Cards";
86
const pciVendorInfo *xf86PCIVendorInfo;
91
InitializePciInfo(void)
93
xf86PCIVendorInfo = pciVendorInfoList;
97
CheckChipsets(xf86cfgModuleOptions *opts, int *err)
99
int i, j, ichk, ivnd = 0, vendor = -1, device;
100
const pciDeviceInfo **pDev;
101
SymTabPtr chips = opts->chipsets;
102
chipset_check *check = NULL;
106
CheckMsg(CHECKER_NO_CHIPSETS, "WARNING No chipsets specified.\n");
111
while (chips->name) {
112
device = chips->token & 0xffff;
113
vendor = (chips->token & 0xffff0000) >> 16;
115
vendor = opts->vendor;
117
for (ichk = 0; ichk < num_check; ichk++)
118
if (check[ichk].vendor == vendor)
120
if (ichk >= num_check) {
121
check = (chipset_check*)
122
XtRealloc((XtPointer)check,
123
sizeof(chipset_check) * (num_check + 1));
124
check[num_check].vendor = vendor;
125
memset(&check[num_check], 0, sizeof(chipset_check));
129
/* Search for vendor in xf86PCIVendorInfo */
130
if (xf86PCIVendorInfo) {
131
for (ivnd = 0; xf86PCIVendorInfo[ivnd].VendorID; ivnd++)
132
if (vendor == xf86PCIVendorInfo[ivnd].VendorID)
135
if (xf86PCIVendorInfo && xf86PCIVendorInfo[ivnd].VendorID) {
136
check[ichk].valid_vendor = 1;
137
check[ichk].ivendor = ivnd;
140
CheckMsg(CHECKER_CANNOT_VERIFY_CHIPSET,
141
"WARNING Cannot verify chipset \"%s\" (0x%x)\n",
142
chips->name, device);
148
if (xf86PCIVendorInfo &&
149
(pDev = xf86PCIVendorInfo[ivnd].Device) != NULL) {
150
if (check[ichk].chipsets == NULL) {
151
for (j = 0; pDev[j]; j++)
153
check[ichk].chipsets = (char*)XtCalloc(1, j);
155
for (j = 0; pDev[j]; j++) {
156
if (device == pDev[j]->DeviceID) {
157
if (strcmp(chips->name, pDev[j]->DeviceName)) {
158
CheckMsg(CHECKER_NOMATCH_CHIPSET_STRINGS,
159
"WARNING chipset strings don't match: \"%s\" \"%s\" (0x%x)\n",
160
chips->name, xf86PCIVendorInfo[ivnd].Device[j]->DeviceName,
168
CheckMsg(CHECKER_CHIPSET_NOT_LISTED,
169
"WARNING chipset \"%s\" (0x%x) not in list.\n", chips->name, device);
173
check[ichk].chipsets[j] = 1;
178
for (i = 0; i < num_check; i++) {
179
if (!check[i].valid_vendor) {
180
CheckMsg(CHECKER_CHIPSET_NO_VENDOR,
181
"WARNING No such vendor 0x%x\n", vendor);
184
for (j = 0; j < check[i].num_chipsets; j++) {
185
if (xf86PCIVendorInfo && !check[i].chipsets[j]) {
186
CheckMsg(CHECKER_CHIPSET_NOT_SUPPORTED,
187
"NOTICE chipset \"%s\" (0x%x) not listed as supported.\n",
188
xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceName,
189
xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceID);
192
XtFree(check[i].chipsets);
195
XtFree((XtPointer)check);
200
ReadCardsDatabase(void)
204
int i, j, ivendor, idevice;
206
_Xconst char *vendor, *device;
207
CardsEntry *entry = NULL, *tmp;
208
xf86cfgModuleOptions *opts = module_options;
209
const pciDeviceInfo **pDev;
211
/* Only list cards that have a driver installed */
213
if (opts->chipsets) {
214
SymTabPtr chips = opts->chipsets;
216
while (chips->name) {
218
device = chips->name;
219
ivendor = (chips->token & 0xffff0000) >> 16;
220
idevice = chips->token & 0xffff0;
222
ivendor = opts->vendor;
224
if (xf86PCIVendorInfo) {
225
for (i = 0; xf86PCIVendorInfo[i].VendorName; i++)
226
if (ivendor == xf86PCIVendorInfo[i].VendorID) {
227
vendor = xf86PCIVendorInfo[i].VendorName;
230
if (xf86PCIVendorInfo[i].VendorName) {
231
if ((pDev = xf86PCIVendorInfo[i].Device)) {
232
for (j = 0; pDev[j]; j++)
233
if (idevice == pDev[j]->DeviceID) {
234
device = pDev[j]->DeviceName;
241
/* Since frequently there is more than one driver for a
242
* single vendor, it is required to avoid duplicates.
244
XmuSnprintf(name, sizeof(name), "%s %s", vendor, device);
245
tmp = LookupCard(name);
247
if (tmp == NULL || strcmp(tmp->chipset, chips->name) ||
248
strcmp(tmp->driver, opts->name)) {
249
entry = (CardsEntry*)XtCalloc(1, sizeof(CardsEntry));
250
if (NumCardsEntry % 16 == 0) {
251
CardsDB = (CardsEntry**)XtRealloc((XtPointer)CardsDB,
252
sizeof(CardsEntry*) * (NumCardsEntry + 16));
254
CardsDB[NumCardsEntry++] = entry;
255
entry->name = XtNewString(name);
257
/* XXX no private copy of strings */
258
entry->chipset = (char*)chips->name;
259
entry->driver = opts->name;
261
/* better than linear searchs to find duplicates */
262
qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*),
271
/* fix entries with the same name */
272
for (i = 0; i < NumCardsEntry - 2;) {
273
for (j = i + 1; j < NumCardsEntry - 1 &&
274
strcmp(CardsDB[i]->name, CardsDB[j]->name) == 0; j++)
281
if (strcmp(CardsDB[i]->chipset, CardsDB[j]->chipset))
282
str = CardsDB[i]->chipset;
284
str = CardsDB[i]->driver;
286
XmuSnprintf(name, sizeof(name), "%s (%s)",
287
CardsDB[i]->name, str);
288
XtFree(CardsDB[i]->name);
289
CardsDB[i]->name = XtNewString(name);
298
/* make sure data is valid to bsearch in */
299
qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
303
DoReadCardsDatabase();
307
DoReadCardsDatabase(void)
310
FILE *fp = fopen(Cards, "r");
312
CardsEntry *entry = NULL;
313
static char *CardsError = "Error reading Cards database, at line %d (%s).\n";
316
fprintf(stderr, "Cannot open Cards database.\n");
320
while ((result = ReadCardsLine(fp, buffer)) != END) {
323
fprintf(stderr, CardsError, linenum, buffer);
327
"Unknown field type in Cards database, at line %d (%s).\n",
331
entry = calloc(1, sizeof(CardsEntry));
332
if (NumCardsEntry % 16 == 0) {
333
CardsDB = realloc(CardsDB, sizeof(CardsEntry*) *
334
(NumCardsEntry + 16));
335
if (CardsDB == NULL) {
336
fprintf(stderr, "Out of memory reading Cards database.\n");
340
CardsDB[NumCardsEntry++] = entry;
341
entry->name = strdup(buffer);
344
if (entry == NULL || entry->chipset != NULL) {
345
fprintf(stderr, CardsError, linenum, buffer);
349
entry->chipset = strdup(buffer);
353
if (entry == NULL || entry->server != NULL) {
354
fprintf(stderr, CardsError, linenum, buffer);
357
entry->server = strdup(buffer);
360
if (entry == NULL || entry->driver != NULL) {
361
fprintf(stderr, CardsError, linenum, buffer);
364
entry->driver = strdup(buffer);
367
if (entry == NULL || entry->ramdac != NULL) {
368
fprintf(stderr, CardsError, linenum, buffer);
371
entry->ramdac = strdup(buffer);
374
if (entry == NULL || entry->clockchip != NULL) {
375
fprintf(stderr, CardsError, linenum, buffer);
378
entry->clockchip = strdup(buffer);
381
if (entry == NULL || entry->dacspeed != NULL) {
382
fprintf(stderr, CardsError, linenum, buffer);
385
entry->dacspeed = strdup(buffer);
389
fprintf(stderr, CardsError, linenum, buffer);
392
entry->flags |= F_NOCLOCKPROBE;
396
fprintf(stderr, CardsError, linenum, buffer);
399
entry->flags |= F_UNSUPPORTED;
402
if (entry == NULL || entry->see != NULL) {
403
fprintf(stderr, CardsError, linenum, buffer);
406
entry->see = strdup(buffer);
410
fprintf(stderr, CardsError, linenum, buffer);
412
else if (entry->lines == NULL)
413
entry->lines = strdup(buffer);
415
char *str = malloc(strlen(entry->lines) + strlen(buffer) + 2);
417
sprintf(str, "%s\n%s", entry->lines, buffer);
427
qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
430
for (i = 0; i < NumCardsEntry - 1; i++) {
431
if (strcmp(CardsDB[i]->name, CardsDB[i+1]->name) == 0)
432
fprintf(stderr, "Duplicate entry in Cards database: (%s).\n",
437
for (i = 0; i < NumCardsEntry - 1; i++) {
438
if (CardsDB[i]->see != NULL) {
439
if ((entry = LookupCard(CardsDB[i]->see)) == NULL) {
440
fprintf(stderr, "Cannot find card '%s' for filling defaults.\n",
444
if (CardsDB[i]->chipset == NULL && entry->chipset != NULL)
445
CardsDB[i]->chipset = strdup(entry->chipset);
446
if (CardsDB[i]->server == NULL && entry->server != NULL)
447
CardsDB[i]->server = strdup(entry->server);
448
if (CardsDB[i]->driver == NULL && entry->driver != NULL)
449
CardsDB[i]->driver = strdup(entry->driver);
450
if (CardsDB[i]->ramdac == NULL && entry->ramdac != NULL)
451
CardsDB[i]->ramdac = strdup(entry->ramdac);
452
if (CardsDB[i]->clockchip == NULL && entry->clockchip != NULL)
453
CardsDB[i]->clockchip = strdup(entry->clockchip);
454
if (CardsDB[i]->dacspeed == NULL && entry->dacspeed != NULL)
455
CardsDB[i]->dacspeed = strdup(entry->dacspeed);
456
if (CardsDB[i]->flags & F_NOCLOCKPROBE)
457
CardsDB[i]->flags |= F_NOCLOCKPROBE;
458
if (CardsDB[i]->flags & F_UNSUPPORTED)
459
CardsDB[i]->flags |= F_UNSUPPORTED;
460
if (entry->lines != NULL) {
461
if (CardsDB[i]->lines == NULL)
462
CardsDB[i]->lines = strdup(entry->lines);
464
char *str = malloc(strlen(entry->lines) +
465
strlen(CardsDB[i]->lines) + 2);
467
sprintf(str, "%s\n%s", CardsDB[i]->lines, entry->lines);
468
free(CardsDB[i]->lines);
469
CardsDB[i]->lines = str;
472
if (entry->see != NULL) {
474
fprintf(stderr, "Nested SEE entry: %s -> %s -> %s\n",
475
CardsDB[i]->name, CardsDB[i]->see, entry->see);
477
CardsDB[i]->see = strdup(entry->see);
481
free(CardsDB[i]->see);
482
CardsDB[i]->see = NULL;
488
LookupCard(char *name)
492
if (NumCardsEntry == 0 || CardsDB == 0)
495
ptr = (CardsEntry**)bsearch(name, CardsDB, NumCardsEntry,
496
sizeof(CardsEntry*), BCompareCards);
498
return (ptr != NULL ? *ptr : NULL);
502
GetCardNames(int *result)
507
for (ncards = 0; ncards < NumCardsEntry; ncards++) {
508
if (ncards % 16 == 0) {
509
if ((cards = (char**)realloc(cards, sizeof(char*) *
510
(ncards + 16))) == NULL) {
511
fprintf(stderr, "Out of memory.\n");
515
cards[ncards] = strdup(CardsDB[ncards]->name);
524
FilterCardNames(char *pattern, int *result)
531
for (i = 0; i < NumCardsEntry; i++) {
532
if (strstr(CardsDB[i]->name, pattern) == NULL)
534
if (ncards % 16 == 0) {
535
if ((cards = (char**)realloc(cards, sizeof(char*) *
536
(ncards + 16))) == NULL) {
537
fprintf(stderr, "Out of memory.\n");
541
cards[ncards] = strdup(CardsDB[i]->name);
550
return (DoFilterCardNames(pattern, result));
554
DoFilterCardNames(char *pattern, int *result)
559
char *cmd, *ptr, buffer[256];
561
cmd = malloc(32 + (strlen(pattern) * 2) + strlen(Cards));
563
strcpy(cmd, "egrep -i '^NAME\\ .*");
567
if (!isalnum(*ptr)) {
573
strcat(cmd, ".*$' ");
575
strcat(cmd, " | sort");
576
/*sprintf(cmd, "egrep -i '^NAME\\ .*%s.*$' %s | sort", pattern, Cards);*/
578
if ((fp = popen(cmd, "r")) == NULL) {
579
fprintf(stderr, "Cannot read Cards database.\n");
582
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
583
ptr = buffer + strlen(buffer) - 1;
584
while (isspace(*ptr) && ptr > buffer)
586
if (!isspace(*ptr) && ptr > buffer)
589
while (!isspace(*ptr) && *ptr) /* skip NAME */
591
while (isspace(*ptr) && *ptr)
593
if (ncards % 16 == 0) {
594
if ((cards = (char**)realloc(cards, sizeof(char*) *
595
(ncards + 16))) == NULL) {
596
fprintf(stderr, "Out of memory.\n");
600
cards[ncards++] = strdup(ptr);
610
ReadCardsLine(FILE *fp, char *value)
612
char name[32], buffer[256], *ptr, *end;
613
int result = NOTUSEFUL;
617
if (fgets(buffer, sizeof(buffer), fp) == NULL)
621
/* skip initial spaces; should'nt bother about this.. */
622
while (isspace(*ptr) && *ptr)
625
if (*ptr == '#' || *ptr == '\0')
629
while (!isspace(*end) && *end)
631
if (end - ptr > sizeof(buffer) - 1) {
632
strncpy(value, buffer, 255);
636
strncpy(name, ptr, end - ptr);
637
name[end - ptr] = '\0';
639
/* read the optional arguments */
641
while (isspace(*ptr) && *ptr)
644
end = ptr + strlen(ptr) - 1;
645
while (isspace(*end) && end > ptr)
651
if (strcmp(name, "NAME") == 0)
653
else if (strcmp(name, "CHIPSET") == 0)
655
else if (strcmp(name, "SERVER") == 0)
657
else if (strcmp(name, "DRIVER") == 0)
659
else if (strcmp(name, "RAMDAC") == 0)
661
else if (strcmp(name, "CLOCKCHIP") == 0)
663
else if (strcmp(name, "DACSPEED") == 0)
665
else if (strcmp(name, "NOCLOCKPROBE") == 0)
666
result = NOCLOCKPROBE;
667
else if (strcmp(name, "UNSUPPORTED") == 0)
668
result = UNSUPPORTED;
669
else if (strcmp(name, "SEE") == 0)
671
else if (strcmp(name, "LINE") == 0)
673
else if (strcmp(name, "END") == 0)
680
/* value *must* have at least 256 bytes */
687
CompareCards(_Xconst void *left, _Xconst void *right)
689
return strcasecmp((*(CardsEntry**)left)->name, (*(CardsEntry**)right)->name);
693
BCompareCards(_Xconst void *name, _Xconst void *card)
695
return (strcasecmp((char*)name, (*(CardsEntry**)card)->name));