2
* $Id: names.c,v 1.6 2000/04/29 12:56:23 mj Exp $
4
* The PCI Library -- ID to Name Translation
6
* Copyright (c) 1997--2000 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
8
* Can be freely distributed and used under the terms of the GNU GPL.
22
struct nl_entry *next;
23
word id1, id2, id3, id4;
30
#define NL_SUBSYSTEM 2
35
#define HASH_SIZE 1024
37
static inline unsigned int nl_calc_hash(int cat, int id1, int id2, int id3, int id4)
41
h = id1 ^ id2 ^ id3 ^ id4 ^ (cat << 5);
43
return h & (HASH_SIZE-1);
46
static struct nl_entry *nl_lookup(struct pci_access *a, int num, int cat, int id1, int id2, int id3, int id4)
53
h = nl_calc_hash(cat, id1, id2, id3, id4);
55
while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat))
60
static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text)
62
unsigned int h = nl_calc_hash(cat, id1, id2, id3, id4);
63
struct nl_entry *n = a->nl_hash[h];
65
while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat))
69
n = pci_malloc(a, sizeof(struct nl_entry));
76
n->next = a->nl_hash[h];
82
err_name_list(struct pci_access *a, char *msg)
84
a->error("%s: %s: %s\n", a->id_file_name, msg, strerror(errno));
88
parse_name_list(struct pci_access *a)
93
unsigned int id1=0, id2=0, id3=0, id4=0;
100
while (*p && *p != '\n')
105
while (*p && *p != '\n')
116
while (r > q && r[-1] == ' ')
123
if (q[0] == 'C' && q[1] == ' ')
125
if (strlen(q+2) < 3 ||
127
sscanf(q+2, "%x", &id1) != 1)
135
sscanf(q, "%x", &id1) != 1)
148
if (sscanf(q, "%x", &id2) != 1 || q[4] != ' ')
157
if (sscanf(q, "%x", &id2) != 1 || q[2] != ' ')
171
if (sscanf(q, "%x%x", &id3, &id4) != 2 || q[9] != ' ')
179
if (sscanf(q, "%x", &id3) != 1 || q[2] != ' ')
194
if (nl_add(a, cat, id1, id2, id3, id4, q))
195
a->error("%s, line %d: duplicate entry", a->id_file_name, lino);
200
a->error("%s, line %d: parse error", a->id_file_name, lino);
204
load_name_list(struct pci_access *a)
209
fd = open(a->id_file_name, O_RDONLY);
215
if (fstat(fd, &st) < 0)
216
err_name_list(a, "stat");
217
a->nl_list = pci_malloc(a, st.st_size + 1);
218
if (read(fd, a->nl_list, st.st_size) != st.st_size)
219
err_name_list(a, "read");
220
a->nl_list[st.st_size] = 0;
221
a->nl_hash = pci_malloc(a, sizeof(struct nl_entry *) * HASH_SIZE);
222
bzero(a->nl_hash, sizeof(struct nl_entry *) * HASH_SIZE);
228
pci_free_name_list(struct pci_access *a)
230
pci_mfree(a->nl_list);
232
pci_mfree(a->nl_hash);
237
pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
239
int num = a->numeric_ids;
243
if (flags & PCI_LOOKUP_NUMERIC)
245
flags &= PCI_LOOKUP_NUMERIC;
248
if (!a->nl_hash && !num)
251
num = a->numeric_ids;
255
case PCI_LOOKUP_VENDOR:
256
if (n = nl_lookup(a, num, NL_VENDOR, arg1, 0, 0, 0))
259
res = snprintf(buf, size, "%04x", arg1);
261
case PCI_LOOKUP_DEVICE:
262
if (n = nl_lookup(a, num, NL_DEVICE, arg1, arg2, 0, 0))
265
res = snprintf(buf, size, "%04x", arg2);
267
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE:
270
struct nl_entry *e, *e2;
271
e = nl_lookup(a, 0, NL_VENDOR, arg1, 0, 0, 0);
272
e2 = nl_lookup(a, 0, NL_DEVICE, arg1, arg2, 0, 0);
274
res = snprintf(buf, size, "Unknown device %04x:%04x", arg1, arg2);
276
res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg2);
278
res = snprintf(buf, size, "%s %s", e->name, e2->name);
281
res = snprintf(buf, size, "%04x:%04x", arg1, arg2);
283
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM:
284
if (n = nl_lookup(a, num, NL_VENDOR, arg3, 0, 0, 0))
287
res = snprintf(buf, size, "%04x", arg1);
289
case PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
290
if (n = nl_lookup(a, num, NL_SUBSYSTEM, arg1, arg2, arg3, arg4))
292
else if (arg1 == arg3 && arg2 == arg4 && (n = nl_lookup(a, num, NL_DEVICE, arg1, arg2, 0, 0)))
295
res = snprintf(buf, size, "%04x", arg2);
297
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
300
struct nl_entry *e, *e2;
301
e = nl_lookup(a, 0, NL_VENDOR, arg3, 0, 0, 0);
302
e2 = nl_lookup(a, 0, NL_SUBSYSTEM, arg1, arg2, arg3, arg4);
303
if (!e2 && arg1 == arg3 && arg2 == arg4)
304
/* Cheat for vendors blindly setting subsystem ID same as device ID */
305
e2 = nl_lookup(a, 0, NL_DEVICE, arg1, arg2, 0, 0);
307
res = snprintf(buf, size, "Unknown device %04x:%04x", arg3, arg4);
309
res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg4);
311
res = snprintf(buf, size, "%s %s", e->name, e2->name);
314
res = snprintf(buf, size, "%04x:%04x", arg3, arg4);
316
case PCI_LOOKUP_CLASS:
317
if (n = nl_lookup(a, num, NL_SUBCLASS, arg1 >> 8, arg1 & 0xff, 0, 0))
319
else if (n = nl_lookup(a, num, NL_CLASS, arg1, 0, 0, 0))
320
res = snprintf(buf, size, "%s [%04x]", n->name, arg1);
322
res = snprintf(buf, size, "Class %04x", arg1);
324
case PCI_LOOKUP_PROGIF:
325
if (n = nl_lookup(a, num, NL_PROGIF, arg1 >> 8, arg1 & 0xff, arg2, 0))
329
/* IDE controllers have complex prog-if semantics */
332
res = snprintf(buf, size, "%s%s%s%s%s",
333
(arg2 & 0x80) ? "Master " : "",
334
(arg2 & 0x08) ? "SecP " : "",
335
(arg2 & 0x04) ? "SecO " : "",
336
(arg2 & 0x02) ? "PriP " : "",
337
(arg2 & 0x01) ? "PriO " : "");
344
return "<pci_lookup_name: invalid request>";
346
return (res == size) ? "<too-large>" : buf;