]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/names.c
Reorganized the pci.ids file. Subsystems are listed under devices, classes
[thirdparty/pciutils.git] / lib / names.c
CommitLineData
727ce158 1/*
d4798a32 2 * $Id: names.c,v 1.3 1999/10/09 13:26:12 mj Exp $
727ce158
MM
3 *
4 * The PCI Library -- ID to Name Translation
5 *
6 * Copyright (c) 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <fcntl.h>
15#include <unistd.h>
16#include <sys/stat.h>
17#include <errno.h>
18
19#include "internal.h"
20
21struct nl_entry {
22 struct nl_entry *next;
d4798a32 23 word id1, id2, id3, id4;
727ce158
MM
24 int cat;
25 byte *name;
26};
27
28#define NL_VENDOR 0
29#define NL_DEVICE 1
d4798a32
MM
30#define NL_SUBSYSTEM 2
31#define NL_CLASS 3
32#define NL_SUBCLASS 4
33#define NL_PROGIF 5
727ce158
MM
34
35#define HASH_SIZE 1024
36
d4798a32 37static inline unsigned int nl_calc_hash(int cat, int id1, int id2, int id3, int id4)
727ce158
MM
38{
39 unsigned int h;
40
d4798a32 41 h = id1 ^ id2 ^ id3 ^ id4 ^ (cat << 5);
727ce158
MM
42 h += (h >> 6);
43 return h & (HASH_SIZE-1);
44}
45
d4798a32 46static struct nl_entry *nl_lookup(struct pci_access *a, int num, int cat, int id1, int id2, int id3, int id4)
727ce158
MM
47{
48 unsigned int h;
49 struct nl_entry *n;
50
51 if (num)
52 return NULL;
d4798a32 53 h = nl_calc_hash(cat, id1, id2, id3, id4);
727ce158 54 n = a->nl_hash[h];
d4798a32 55 while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat))
727ce158
MM
56 n = n->next;
57 return n;
58}
59
d4798a32 60static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text)
727ce158 61{
d4798a32 62 unsigned int h = nl_calc_hash(cat, id1, id2, id3, id4);
727ce158
MM
63 struct nl_entry *n = a->nl_hash[h];
64
d4798a32 65 while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat))
727ce158
MM
66 n = n->next;
67 if (n)
68 return 1;
69 n = pci_malloc(a, sizeof(struct nl_entry));
70 n->id1 = id1;
71 n->id2 = id2;
d4798a32
MM
72 n->id3 = id3;
73 n->id4 = id4;
727ce158
MM
74 n->cat = cat;
75 n->name = text;
76 n->next = a->nl_hash[h];
77 a->nl_hash[h] = n;
78 return 0;
79}
80
81static void
82err_name_list(struct pci_access *a, char *msg)
83{
84 a->error("%s: %s: %s\n", a->id_file_name, msg, strerror(errno));
85}
86
87static void
88parse_name_list(struct pci_access *a)
89{
90 byte *p = a->nl_list;
91 byte *q, *r;
92 int lino = 0;
d4798a32
MM
93 unsigned int id1=0, id2=0, id3=0, id4=0;
94 int cat = -1;
727ce158
MM
95
96 while (*p)
97 {
98 lino++;
99 q = p;
100 while (*p && *p != '\n')
101 {
102 if (*p == '#')
103 {
104 *p++ = 0;
105 while (*p && *p != '\n')
106 p++;
107 break;
108 }
727ce158
MM
109 p++;
110 }
111 if (*p == '\n')
112 *p++ = 0;
113 if (!*q)
114 continue;
115 r = p;
116 while (r > q && r[-1] == ' ')
117 *--r = 0;
118 r = q;
d4798a32 119 while (*q == '\t')
727ce158 120 q++;
d4798a32 121 if (q == r)
727ce158
MM
122 {
123 if (q[0] == 'C' && q[1] == ' ')
124 {
125 if (strlen(q+2) < 3 ||
126 q[4] != ' ' ||
127 sscanf(q+2, "%x", &id1) != 1)
128 goto parserr;
d4798a32 129 cat = NL_CLASS;
727ce158
MM
130 }
131 else
132 {
133 if (strlen(q) < 5 ||
134 q[4] != ' ' ||
135 sscanf(q, "%x", &id1) != 1)
136 goto parserr;
d4798a32 137 cat = NL_VENDOR;
727ce158 138 }
d4798a32
MM
139 id2 = id3 = id4 = 0;
140 q += 4;
727ce158 141 }
d4798a32
MM
142 else if (q == r+1)
143 switch (cat)
144 {
145 case NL_VENDOR:
146 case NL_DEVICE:
147 case NL_SUBSYSTEM:
148 if (sscanf(q, "%x", &id2) != 1 || q[4] != ' ')
149 goto parserr;
150 q += 5;
151 cat = NL_DEVICE;
152 id3 = id4 = 0;
153 break;
154 case NL_CLASS:
155 case NL_SUBCLASS:
156 case NL_PROGIF:
157 if (sscanf(q, "%x", &id2) != 1 || q[2] != ' ')
158 goto parserr;
159 q += 3;
160 cat = NL_SUBCLASS;
161 id3 = id4 = 0;
162 break;
163 default:
727ce158 164 goto parserr;
d4798a32
MM
165 }
166 else if (q == r+2)
167 switch (cat)
168 {
169 case NL_DEVICE:
170 case NL_SUBSYSTEM:
171 if (sscanf(q, "%x%x", &id3, &id4) != 2 || q[9] != ' ')
172 goto parserr;
173 q += 10;
174 cat = NL_SUBSYSTEM;
175 break;
176 case NL_CLASS:
177 case NL_SUBCLASS:
178 case NL_PROGIF:
179 if (sscanf(q, "%x", &id3) != 1 || q[2] != ' ')
180 goto parserr;
181 q += 3;
182 cat = NL_PROGIF;
183 id4 = 0;
184 break;
185 default:
727ce158 186 goto parserr;
d4798a32
MM
187 }
188 else
189 goto parserr;
727ce158
MM
190 while (*q == ' ')
191 q++;
192 if (!*q)
193 goto parserr;
d4798a32 194 if (nl_add(a, cat, id1, id2, id3, id4, q))
727ce158
MM
195 a->error("%s, line %d: duplicate entry", a->id_file_name, lino);
196 }
197 return;
198
199parserr:
200 a->error("%s, line %d: parse error", a->id_file_name, lino);
201}
202
203static void
204load_name_list(struct pci_access *a)
205{
206 int fd;
207 struct stat st;
208
209 fd = open(a->id_file_name, O_RDONLY);
210 if (fd < 0)
211 {
212 a->numeric_ids = 1;
213 return;
214 }
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);
223 parse_name_list(a);
224 close(fd);
225}
226
227void
228pci_free_name_list(struct pci_access *a)
229{
230 pci_mfree(a->nl_list);
231 a->nl_list = NULL;
232 pci_mfree(a->nl_hash);
233 a->nl_hash = NULL;
234}
235
727ce158 236char *
d4798a32 237pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
727ce158
MM
238{
239 int num = a->numeric_ids;
240 int res;
241 struct nl_entry *n;
242
243 if (flags & PCI_LOOKUP_NUMERIC)
244 {
245 flags &= PCI_LOOKUP_NUMERIC;
246 num = 1;
247 }
248 if (!a->nl_hash && !num)
249 {
250 load_name_list(a);
251 num = a->numeric_ids;
252 }
253 switch (flags)
254 {
255 case PCI_LOOKUP_VENDOR:
d4798a32 256 if (n = nl_lookup(a, num, NL_VENDOR, arg1, 0, 0, 0))
727ce158
MM
257 return n->name;
258 else
259 res = snprintf(buf, size, "%04x", arg1);
260 break;
261 case PCI_LOOKUP_DEVICE:
d4798a32 262 if (n = nl_lookup(a, num, NL_DEVICE, arg1, arg2, 0, 0))
727ce158
MM
263 return n->name;
264 else
7bed2d83 265 res = snprintf(buf, size, "%04x", arg2);
727ce158
MM
266 break;
267 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE:
d4798a32
MM
268 if (!num)
269 {
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);
273 if (!e)
274 res = snprintf(buf, size, "Unknown device %04x:%04x", arg1, arg2);
275 else if (!e2)
276 res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg2);
277 else
278 res = snprintf(buf, size, "%s %s", e->name, e2->name);
279 }
280 else
281 res = snprintf(buf, size, "%04x:%04x", arg1, arg2);
727ce158
MM
282 break;
283 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM:
d4798a32 284 if (n = nl_lookup(a, num, NL_VENDOR, arg3, 0, 0, 0))
727ce158
MM
285 return n->name;
286 else
287 res = snprintf(buf, size, "%04x", arg1);
288 break;
289 case PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
d4798a32 290 if (n = nl_lookup(a, num, NL_SUBSYSTEM, arg1, arg2, arg3, arg4))
727ce158
MM
291 return n->name;
292 else
7bed2d83 293 res = snprintf(buf, size, "%04x", arg2);
727ce158
MM
294 break;
295 case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM:
d4798a32
MM
296 if (!num)
297 {
298 struct nl_entry *e, *e2;
299 e = nl_lookup(a, 0, NL_VENDOR, arg3, 0, 0, 0);
300 e2 = nl_lookup(a, 0, NL_SUBSYSTEM, arg1, arg2, arg3, arg4);
301 if (!e)
302 res = snprintf(buf, size, "Unknown device %04x:%04x", arg1, arg2);
303 else if (!e2)
304 res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg2);
305 else
306 res = snprintf(buf, size, "%s %s", e->name, e2->name);
307 }
308 else
309 res = snprintf(buf, size, "%04x:%04x", arg3, arg4);
727ce158
MM
310 break;
311 case PCI_LOOKUP_CLASS:
d4798a32 312 if (n = nl_lookup(a, num, NL_SUBCLASS, arg1 >> 8, arg1 & 0xff, 0, 0))
727ce158 313 return n->name;
d4798a32 314 else if (n = nl_lookup(a, num, NL_CLASS, arg1, 0, 0, 0))
727ce158
MM
315 res = snprintf(buf, size, "%s [%04x]", n->name, arg1);
316 else
317 res = snprintf(buf, size, "Class %04x", arg1);
318 break;
d4798a32
MM
319 case PCI_LOOKUP_PROGIF:
320 if (n = nl_lookup(a, num, NL_PROGIF, arg1 >> 8, arg1 & 0xff, arg2, 0))
321 return n->name;
322 if (arg1 == 0x0101)
323 {
324 /* IDE controllers have complex prog-if semantics */
325 if (arg2 & 0x70)
326 return NULL;
327 res = snprintf(buf, size, "%s%s%s%s%s",
328 (arg2 & 0x80) ? "Master " : "",
329 (arg2 & 0x08) ? "SecP " : "",
330 (arg2 & 0x04) ? "SecO " : "",
331 (arg2 & 0x02) ? "PriP " : "",
332 (arg2 & 0x01) ? "PriO " : "");
333 if (res)
334 buf[--res] = 0;
335 break;
336 }
337 return NULL;
727ce158
MM
338 default:
339 return "<pci_lookup_name: invalid request>";
340 }
341 return (res == size) ? "<too-large>" : buf;
342}