2 * $Id: names.c,v 1.2 1999/06/21 20:17:19 mj Exp $
4 * The PCI Library -- ID to Name Translation
6 * Copyright (c) 1997--1999 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;
32 #define NL_SUBSYSTEM_VENDOR 4
33 #define NL_SUBSYSTEM_DEVICE 5
35 #define HASH_SIZE 1024
37 static inline unsigned int nl_calc_hash(int cat, int id1, int id2)
41 h = id1 ^ id2 ^ (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)
53 h = nl_calc_hash(cat, id1, id2);
55 while (n && (n->id1 != id1 || n->id2 != id2 || n->cat != cat))
60 static int nl_add(struct pci_access *a, int cat, int id1, int id2, byte *text)
62 unsigned int h = nl_calc_hash(cat, id1, id2);
63 struct nl_entry *n = a->nl_hash[h];
65 while (n && (n->id1 != id1 || n->id2 != id2 || n->cat != cat))
69 n = pci_malloc(a, sizeof(struct nl_entry));
74 n->next = a->nl_hash[h];
80 err_name_list(struct pci_access *a, char *msg)
82 a->error("%s: %s: %s\n", a->id_file_name, msg, strerror(errno));
86 parse_name_list(struct pci_access *a)
91 unsigned int id1=0, id2=0;
92 int cat, last_cat = -1;
98 while (*p && *p != '\n')
103 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)
129 cat = last_cat = NL_CLASS;
131 else if (q[0] == 'S' && q[1] == ' ')
133 if (strlen(q+2) < 5 ||
135 sscanf(q+2, "%x", &id1) != 1)
137 cat = last_cat = NL_SUBSYSTEM_VENDOR;
144 sscanf(q, "%x", &id1) != 1)
146 cat = last_cat = NL_VENDOR;
152 if (sscanf(q, "%x", &id2) != 1)
156 if (last_cat == NL_CLASS)
166 if (nl_add(a, cat, id1, id2, q))
167 a->error("%s, line %d: duplicate entry", a->id_file_name, lino);
172 a->error("%s, line %d: parse error", a->id_file_name, lino);
176 load_name_list(struct pci_access *a)
181 fd = open(a->id_file_name, O_RDONLY);
187 if (fstat(fd, &st) < 0)
188 err_name_list(a, "stat");
189 a->nl_list = pci_malloc(a, st.st_size + 1);
190 if (read(fd, a->nl_list, st.st_size) != st.st_size)
191 err_name_list(a, "read");
192 a->nl_list[st.st_size] = 0;
193 a->nl_hash = pci_malloc(a, sizeof(struct nl_entry *) * HASH_SIZE);
194 bzero(a->nl_hash, sizeof(struct nl_entry *) * HASH_SIZE);
200 pci_free_name_list(struct pci_access *a)
202 pci_mfree(a->nl_list);
204 pci_mfree(a->nl_hash);
209 compound_name(struct pci_access *a, int num, char *buf, int size, int cat, int v, int i)
213 struct nl_entry *e, *e2;
215 e = nl_lookup(a, 0, cat, v, 0);
216 e2 = nl_lookup(a, 0, cat+1, v, i);
218 return snprintf(buf, size, "Unknown device %04x:%04x", v, i);
220 return snprintf(buf, size, "%s: Unknown device %04x", e->name, i);
222 return snprintf(buf, size, "%s %s", e->name, e2->name);
225 return snprintf(buf, size, "%04x:%04x", v, i);
229 pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, u32 arg1, u32 arg2)
231 int num = a->numeric_ids;
235 if (flags & PCI_LOOKUP_NUMERIC)
237 flags &= PCI_LOOKUP_NUMERIC;
240 if (!a->nl_hash && !num)
243 num = a->numeric_ids;
247 case PCI_LOOKUP_VENDOR:
248 if (n = nl_lookup(a, num, NL_VENDOR, arg1, 0))
251 res = snprintf(buf, size, "%04x", arg1);
253 case PCI_LOOKUP_DEVICE:
254 if (n = nl_lookup(a, num, NL_DEVICE, arg1, arg2))
257 res = snprintf(buf, size, "%04x", arg2);
259 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE:
260 res = compound_name(a, num, buf, size, NL_VENDOR, arg1, arg2);
262 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM:
263 if (n = nl_lookup(a, num, NL_SUBSYSTEM_VENDOR, arg1, 0))
266 res = snprintf(buf, size, "%04x", arg1);
268 case PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
269 if (n = nl_lookup(a, num, NL_SUBSYSTEM_DEVICE, arg1, arg2))
272 res = snprintf(buf, size, "%04x", arg2);
274 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
275 res = compound_name(a, num, buf, size, NL_SUBSYSTEM_VENDOR, arg1, arg2);
277 case PCI_LOOKUP_CLASS:
278 if (n = nl_lookup(a, num, NL_SUBCLASS, arg1 >> 8, arg1 & 0xff))
280 else if (n = nl_lookup(a, num, NL_CLASS, arg1, 0))
281 res = snprintf(buf, size, "%s [%04x]", n->name, arg1);
283 res = snprintf(buf, size, "Class %04x", arg1);
286 return "<pci_lookup_name: invalid request>";
288 return (res == size) ? "<too-large>" : buf;