xref: /titanic_41/usr/src/lib/libpcidb/common/pcidb.c (revision 799d90a47c55505edaae809d753ad319c0a5c7aa)
1*abc79d9dSRobert Mustacchi /*
2*abc79d9dSRobert Mustacchi  * CDDL HEADER START
3*abc79d9dSRobert Mustacchi  *
4*abc79d9dSRobert Mustacchi  * The contents of this file are subject to the terms of the
5*abc79d9dSRobert Mustacchi  * Common Development and Distribution License (the "License").
6*abc79d9dSRobert Mustacchi  * You may not use this file except in compliance with the License.
7*abc79d9dSRobert Mustacchi  *
8*abc79d9dSRobert Mustacchi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*abc79d9dSRobert Mustacchi  * or http://www.opensolaris.org/os/licensing.
10*abc79d9dSRobert Mustacchi  * See the License for the specific language governing permissions
11*abc79d9dSRobert Mustacchi  * and limitations under the License.
12*abc79d9dSRobert Mustacchi  *
13*abc79d9dSRobert Mustacchi  * When distributing Covered Code, include this CDDL HEADER in each
14*abc79d9dSRobert Mustacchi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*abc79d9dSRobert Mustacchi  * If applicable, add the following below this CDDL HEADER, with the
16*abc79d9dSRobert Mustacchi  * fields enclosed by brackets "[]" replaced with your own identifying
17*abc79d9dSRobert Mustacchi  * information: Portions Copyright [yyyy] [name of copyright owner]
18*abc79d9dSRobert Mustacchi  *
19*abc79d9dSRobert Mustacchi  * CDDL HEADER END
20*abc79d9dSRobert Mustacchi  */
21*abc79d9dSRobert Mustacchi /*
22*abc79d9dSRobert Mustacchi  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
23*abc79d9dSRobert Mustacchi  */
24*abc79d9dSRobert Mustacchi 
25*abc79d9dSRobert Mustacchi /*
26*abc79d9dSRobert Mustacchi  * This library exists to understand and parse the pci.ids database that is
27*abc79d9dSRobert Mustacchi  * maintained at http://pci-ids.ucw.cz/ and in the gate at cmd/hwdata. This
28*abc79d9dSRobert Mustacchi  * database provides a way to map the PCI device, vendor, and subsystem ids to
29*abc79d9dSRobert Mustacchi  * a human understandable name.
30*abc79d9dSRobert Mustacchi  *
31*abc79d9dSRobert Mustacchi  * This library exports this data in a similar way to a tree. The handle that
32*abc79d9dSRobert Mustacchi  * is returned from pcidb_open is the root of the tree. The next level are the
33*abc79d9dSRobert Mustacchi  * vendors. Each vendor has a unique set of devices and each device has a unique
34*abc79d9dSRobert Mustacchi  * set of subvendor and subdevice pairs.
35*abc79d9dSRobert Mustacchi  *
36*abc79d9dSRobert Mustacchi  * Parsing information:
37*abc79d9dSRobert Mustacchi  *
38*abc79d9dSRobert Mustacchi  * The database is formatted in the following basic format:
39*abc79d9dSRobert Mustacchi  * vendor_id<two spaces>vendor_name
40*abc79d9dSRobert Mustacchi  * <tab>device_id<two spaces>device_name
41*abc79d9dSRobert Mustacchi  * <tab><tab>subvendor<space>subdevice<two spaces>subsystem_name
42*abc79d9dSRobert Mustacchi  *
43*abc79d9dSRobert Mustacchi  * For any given vendor, there can be multiple devices. And for any given device
44*abc79d9dSRobert Mustacchi  * there will be multiple subsystems. In addition, there can be comments that
45*abc79d9dSRobert Mustacchi  * start a line which use the '#' character.
46*abc79d9dSRobert Mustacchi  *
47*abc79d9dSRobert Mustacchi  * At the end of the file, there are a series of PCI classes. Those will start
48*abc79d9dSRobert Mustacchi  * with a single C<space>. Once we hit those, we stop all parsing. We currently
49*abc79d9dSRobert Mustacchi  * don't care about consuming or presenting those.
50*abc79d9dSRobert Mustacchi  */
51*abc79d9dSRobert Mustacchi 
52*abc79d9dSRobert Mustacchi #include <sys/types.h>
53*abc79d9dSRobert Mustacchi #include <stdint.h>
54*abc79d9dSRobert Mustacchi #include <stdio.h>
55*abc79d9dSRobert Mustacchi #include <stdlib.h>
56*abc79d9dSRobert Mustacchi #include <errno.h>
57*abc79d9dSRobert Mustacchi #include <string.h>
58*abc79d9dSRobert Mustacchi #include <assert.h>
59*abc79d9dSRobert Mustacchi #include <unistd.h>
60*abc79d9dSRobert Mustacchi 
61*abc79d9dSRobert Mustacchi #include "pcidb.h"
62*abc79d9dSRobert Mustacchi 
63*abc79d9dSRobert Mustacchi #define	PCI_NAME_MAX	256
64*abc79d9dSRobert Mustacchi #define	PCI_READLINE	1024
65*abc79d9dSRobert Mustacchi 
66*abc79d9dSRobert Mustacchi /* Forward declarations */
67*abc79d9dSRobert Mustacchi struct pcidb_vendor;
68*abc79d9dSRobert Mustacchi struct pcidb_device;
69*abc79d9dSRobert Mustacchi struct pcidb_subvd;
70*abc79d9dSRobert Mustacchi 
71*abc79d9dSRobert Mustacchi struct pcidb_subvd {
72*abc79d9dSRobert Mustacchi 	uint16_t		ps_vid;
73*abc79d9dSRobert Mustacchi 	uint16_t		ps_did;
74*abc79d9dSRobert Mustacchi 	char			ps_name[PCI_NAME_MAX];
75*abc79d9dSRobert Mustacchi 	struct pcidb_subvd	*ps_prev;
76*abc79d9dSRobert Mustacchi 	struct pcidb_subvd	*ps_next;
77*abc79d9dSRobert Mustacchi 	struct pcidb_device	*ps_dev;
78*abc79d9dSRobert Mustacchi 	struct pcidb_vendor	*ps_vend;
79*abc79d9dSRobert Mustacchi };
80*abc79d9dSRobert Mustacchi 
81*abc79d9dSRobert Mustacchi struct pcidb_device {
82*abc79d9dSRobert Mustacchi 	uint16_t		pd_id;
83*abc79d9dSRobert Mustacchi 	char			pd_name[PCI_NAME_MAX];
84*abc79d9dSRobert Mustacchi 	struct pcidb_subvd	*pd_sstart;
85*abc79d9dSRobert Mustacchi 	struct pcidb_subvd	*pd_send;
86*abc79d9dSRobert Mustacchi 	struct pcidb_device	*pd_next;
87*abc79d9dSRobert Mustacchi 	struct pcidb_device	*pd_prev;
88*abc79d9dSRobert Mustacchi 	struct pcidb_vendor	*pd_vend;
89*abc79d9dSRobert Mustacchi };
90*abc79d9dSRobert Mustacchi 
91*abc79d9dSRobert Mustacchi struct pcidb_vendor {
92*abc79d9dSRobert Mustacchi 	uint16_t		pv_id;
93*abc79d9dSRobert Mustacchi 	char 			pv_name[PCI_NAME_MAX];
94*abc79d9dSRobert Mustacchi 	struct pcidb_device	*pv_dstart;
95*abc79d9dSRobert Mustacchi 	struct pcidb_device	*pv_dend;
96*abc79d9dSRobert Mustacchi 	struct pcidb_vendor	*pv_prev;
97*abc79d9dSRobert Mustacchi 	struct pcidb_vendor	*pv_next;
98*abc79d9dSRobert Mustacchi };
99*abc79d9dSRobert Mustacchi 
100*abc79d9dSRobert Mustacchi struct pcidb_hdl {
101*abc79d9dSRobert Mustacchi 	pcidb_vendor_t	*ph_vstart;
102*abc79d9dSRobert Mustacchi 	pcidb_vendor_t	*ph_vend;
103*abc79d9dSRobert Mustacchi };
104*abc79d9dSRobert Mustacchi 
105*abc79d9dSRobert Mustacchi typedef enum pcidb_parse {
106*abc79d9dSRobert Mustacchi 	PDB_VENDOR,
107*abc79d9dSRobert Mustacchi 	PDB_DEVICE,
108*abc79d9dSRobert Mustacchi 	PDB_SUBDEV
109*abc79d9dSRobert Mustacchi } pcidb_parse_t;
110*abc79d9dSRobert Mustacchi 
111*abc79d9dSRobert Mustacchi static const char *pci_db = "/usr/share/hwdata/pci.ids";
112*abc79d9dSRobert Mustacchi 
113*abc79d9dSRobert Mustacchi static void
pcihdl_add_vendor(pcidb_hdl_t * hdl,pcidb_vendor_t * v)114*abc79d9dSRobert Mustacchi pcihdl_add_vendor(pcidb_hdl_t *hdl, pcidb_vendor_t *v)
115*abc79d9dSRobert Mustacchi {
116*abc79d9dSRobert Mustacchi 	if (hdl->ph_vstart == NULL && hdl->ph_vend == NULL) {
117*abc79d9dSRobert Mustacchi 		hdl->ph_vstart = v;
118*abc79d9dSRobert Mustacchi 		hdl->ph_vend = v;
119*abc79d9dSRobert Mustacchi 		v->pv_prev = NULL;
120*abc79d9dSRobert Mustacchi 		v->pv_next = NULL;
121*abc79d9dSRobert Mustacchi 	} else {
122*abc79d9dSRobert Mustacchi 		v->pv_prev = hdl->ph_vend;
123*abc79d9dSRobert Mustacchi 		v->pv_next = NULL;
124*abc79d9dSRobert Mustacchi 		hdl->ph_vend->pv_next = v;
125*abc79d9dSRobert Mustacchi 		hdl->ph_vend = v;
126*abc79d9dSRobert Mustacchi 	}
127*abc79d9dSRobert Mustacchi }
128*abc79d9dSRobert Mustacchi 
129*abc79d9dSRobert Mustacchi static pcidb_vendor_t *
parse_vendor(char * buf,pcidb_hdl_t * hdl)130*abc79d9dSRobert Mustacchi parse_vendor(char *buf, pcidb_hdl_t *hdl)
131*abc79d9dSRobert Mustacchi {
132*abc79d9dSRobert Mustacchi 	pcidb_vendor_t *v;
133*abc79d9dSRobert Mustacchi 	size_t len;
134*abc79d9dSRobert Mustacchi 
135*abc79d9dSRobert Mustacchi 	v = malloc(sizeof (pcidb_vendor_t));
136*abc79d9dSRobert Mustacchi 	if (v == NULL)
137*abc79d9dSRobert Mustacchi 		return (NULL);
138*abc79d9dSRobert Mustacchi 
139*abc79d9dSRobert Mustacchi 	pcihdl_add_vendor(hdl, v);
140*abc79d9dSRobert Mustacchi 	v->pv_dstart = NULL;
141*abc79d9dSRobert Mustacchi 	v->pv_dend = NULL;
142*abc79d9dSRobert Mustacchi 
143*abc79d9dSRobert Mustacchi 	buf[4] = '\0';
144*abc79d9dSRobert Mustacchi 	v->pv_id = strtol(buf, NULL, 16);
145*abc79d9dSRobert Mustacchi 	buf += 6;
146*abc79d9dSRobert Mustacchi 	len = strlen(buf);
147*abc79d9dSRobert Mustacchi 	if (buf[len-1] == '\n')
148*abc79d9dSRobert Mustacchi 		buf[len-1] = '\0';
149*abc79d9dSRobert Mustacchi 
150*abc79d9dSRobert Mustacchi 	(void) strlcpy(v->pv_name, buf, PCI_NAME_MAX);
151*abc79d9dSRobert Mustacchi 
152*abc79d9dSRobert Mustacchi 	return (v);
153*abc79d9dSRobert Mustacchi }
154*abc79d9dSRobert Mustacchi 
155*abc79d9dSRobert Mustacchi static void
insert_device(pcidb_vendor_t * v,pcidb_device_t * d)156*abc79d9dSRobert Mustacchi insert_device(pcidb_vendor_t *v, pcidb_device_t *d)
157*abc79d9dSRobert Mustacchi {
158*abc79d9dSRobert Mustacchi 	d->pd_vend = v;
159*abc79d9dSRobert Mustacchi 	if (v->pv_dstart == NULL && v->pv_dend == NULL) {
160*abc79d9dSRobert Mustacchi 		v->pv_dstart = d;
161*abc79d9dSRobert Mustacchi 		v->pv_dend = d;
162*abc79d9dSRobert Mustacchi 		d->pd_next = NULL;
163*abc79d9dSRobert Mustacchi 		d->pd_prev = NULL;
164*abc79d9dSRobert Mustacchi 	} else {
165*abc79d9dSRobert Mustacchi 		d->pd_prev = v->pv_dend;
166*abc79d9dSRobert Mustacchi 		d->pd_next = NULL;
167*abc79d9dSRobert Mustacchi 		v->pv_dend->pd_next = d;
168*abc79d9dSRobert Mustacchi 		v->pv_dend = d;
169*abc79d9dSRobert Mustacchi 	}
170*abc79d9dSRobert Mustacchi }
171*abc79d9dSRobert Mustacchi 
172*abc79d9dSRobert Mustacchi static pcidb_device_t *
parse_device(char * buf,pcidb_vendor_t * v)173*abc79d9dSRobert Mustacchi parse_device(char *buf, pcidb_vendor_t *v)
174*abc79d9dSRobert Mustacchi {
175*abc79d9dSRobert Mustacchi 	pcidb_device_t *d;
176*abc79d9dSRobert Mustacchi 	size_t len;
177*abc79d9dSRobert Mustacchi 
178*abc79d9dSRobert Mustacchi 	d = malloc(sizeof (pcidb_device_t));
179*abc79d9dSRobert Mustacchi 	if (d == NULL)
180*abc79d9dSRobert Mustacchi 		return (d);
181*abc79d9dSRobert Mustacchi 
182*abc79d9dSRobert Mustacchi 	d->pd_sstart = NULL;
183*abc79d9dSRobert Mustacchi 	d->pd_send = NULL;
184*abc79d9dSRobert Mustacchi 	insert_device(v, d);
185*abc79d9dSRobert Mustacchi 
186*abc79d9dSRobert Mustacchi 	buf++;
187*abc79d9dSRobert Mustacchi 	buf[4] = '\0';
188*abc79d9dSRobert Mustacchi 	d->pd_id = strtol(buf, NULL, 16);
189*abc79d9dSRobert Mustacchi 	buf += 6;
190*abc79d9dSRobert Mustacchi 	len = strlen(buf);
191*abc79d9dSRobert Mustacchi 	if (buf[len-1] == '\n')
192*abc79d9dSRobert Mustacchi 		buf[len-1] = '\0';
193*abc79d9dSRobert Mustacchi 
194*abc79d9dSRobert Mustacchi 	(void) strlcpy(d->pd_name, buf, PCI_NAME_MAX);
195*abc79d9dSRobert Mustacchi 	return (d);
196*abc79d9dSRobert Mustacchi }
197*abc79d9dSRobert Mustacchi 
198*abc79d9dSRobert Mustacchi static void
insert_subdev(pcidb_device_t * d,pcidb_subvd_t * s)199*abc79d9dSRobert Mustacchi insert_subdev(pcidb_device_t *d, pcidb_subvd_t *s)
200*abc79d9dSRobert Mustacchi {
201*abc79d9dSRobert Mustacchi 	s->ps_dev = d;
202*abc79d9dSRobert Mustacchi 	s->ps_vend = d->pd_vend;
203*abc79d9dSRobert Mustacchi 	if (d->pd_sstart == NULL) {
204*abc79d9dSRobert Mustacchi 		d->pd_sstart = s;
205*abc79d9dSRobert Mustacchi 		d->pd_send = s;
206*abc79d9dSRobert Mustacchi 		s->ps_prev = NULL;
207*abc79d9dSRobert Mustacchi 		s->ps_next = NULL;
208*abc79d9dSRobert Mustacchi 	} else {
209*abc79d9dSRobert Mustacchi 		s->ps_prev = d->pd_send;
210*abc79d9dSRobert Mustacchi 		s->ps_next = NULL;
211*abc79d9dSRobert Mustacchi 		d->pd_send->ps_next = s;
212*abc79d9dSRobert Mustacchi 		d->pd_send = s;
213*abc79d9dSRobert Mustacchi 	}
214*abc79d9dSRobert Mustacchi }
215*abc79d9dSRobert Mustacchi 
216*abc79d9dSRobert Mustacchi static pcidb_subvd_t *
parse_subdev(char * buf,pcidb_device_t * d)217*abc79d9dSRobert Mustacchi parse_subdev(char *buf, pcidb_device_t *d)
218*abc79d9dSRobert Mustacchi {
219*abc79d9dSRobert Mustacchi 	pcidb_subvd_t *s;
220*abc79d9dSRobert Mustacchi 	size_t len;
221*abc79d9dSRobert Mustacchi 
222*abc79d9dSRobert Mustacchi 	s = malloc(sizeof (pcidb_subvd_t));
223*abc79d9dSRobert Mustacchi 	if (s == NULL)
224*abc79d9dSRobert Mustacchi 		return (NULL);
225*abc79d9dSRobert Mustacchi 	insert_subdev(d, s);
226*abc79d9dSRobert Mustacchi 
227*abc79d9dSRobert Mustacchi 	buf += 2;
228*abc79d9dSRobert Mustacchi 	buf[4] = '\0';
229*abc79d9dSRobert Mustacchi 	s->ps_vid = strtol(buf, NULL, 16);
230*abc79d9dSRobert Mustacchi 	buf += 5;
231*abc79d9dSRobert Mustacchi 	buf[4] = '\0';
232*abc79d9dSRobert Mustacchi 	s->ps_did = strtol(buf, NULL, 16);
233*abc79d9dSRobert Mustacchi 	buf += 6;
234*abc79d9dSRobert Mustacchi 
235*abc79d9dSRobert Mustacchi 	len = strlen(buf);
236*abc79d9dSRobert Mustacchi 	if (buf[len-1] == '\n')
237*abc79d9dSRobert Mustacchi 		buf[len-1] = '\0';
238*abc79d9dSRobert Mustacchi 
239*abc79d9dSRobert Mustacchi 	(void) strlcpy(s->ps_name, buf, PCI_NAME_MAX);
240*abc79d9dSRobert Mustacchi 
241*abc79d9dSRobert Mustacchi 	return (s);
242*abc79d9dSRobert Mustacchi }
243*abc79d9dSRobert Mustacchi 
244*abc79d9dSRobert Mustacchi static int
readline(FILE * f,char * buf,size_t len)245*abc79d9dSRobert Mustacchi readline(FILE *f, char *buf, size_t len)
246*abc79d9dSRobert Mustacchi {
247*abc79d9dSRobert Mustacchi 	for (;;) {
248*abc79d9dSRobert Mustacchi 		if (fgets(buf, len, f) == NULL)
249*abc79d9dSRobert Mustacchi 			return (-1);
250*abc79d9dSRobert Mustacchi 
251*abc79d9dSRobert Mustacchi 		if (buf[0] == 'C')
252*abc79d9dSRobert Mustacchi 			return (-1);
253*abc79d9dSRobert Mustacchi 
254*abc79d9dSRobert Mustacchi 		if (buf[0] != '#' && buf[0] != '\n')
255*abc79d9dSRobert Mustacchi 			return (0);
256*abc79d9dSRobert Mustacchi 	}
257*abc79d9dSRobert Mustacchi }
258*abc79d9dSRobert Mustacchi 
259*abc79d9dSRobert Mustacchi static int
parse_db(FILE * f,pcidb_hdl_t * hdl)260*abc79d9dSRobert Mustacchi parse_db(FILE *f, pcidb_hdl_t *hdl)
261*abc79d9dSRobert Mustacchi {
262*abc79d9dSRobert Mustacchi 	char buf[1024];
263*abc79d9dSRobert Mustacchi 	pcidb_vendor_t *v = NULL;
264*abc79d9dSRobert Mustacchi 	pcidb_device_t *d = NULL;
265*abc79d9dSRobert Mustacchi 	pcidb_parse_t state = PDB_VENDOR;
266*abc79d9dSRobert Mustacchi 
267*abc79d9dSRobert Mustacchi 	for (;;) {
268*abc79d9dSRobert Mustacchi 		errno = 0;
269*abc79d9dSRobert Mustacchi 		if (readline(f, buf, sizeof (buf)) != 0) {
270*abc79d9dSRobert Mustacchi 			if (errno != 0)
271*abc79d9dSRobert Mustacchi 				return (-1);
272*abc79d9dSRobert Mustacchi 			else
273*abc79d9dSRobert Mustacchi 				return (0);
274*abc79d9dSRobert Mustacchi 		}
275*abc79d9dSRobert Mustacchi 
276*abc79d9dSRobert Mustacchi newstate:
277*abc79d9dSRobert Mustacchi 		switch (state) {
278*abc79d9dSRobert Mustacchi 		case PDB_VENDOR:
279*abc79d9dSRobert Mustacchi 			v = parse_vendor(buf, hdl);
280*abc79d9dSRobert Mustacchi 			if (v == NULL)
281*abc79d9dSRobert Mustacchi 				return (NULL);
282*abc79d9dSRobert Mustacchi 			state = PDB_DEVICE;
283*abc79d9dSRobert Mustacchi 			continue;
284*abc79d9dSRobert Mustacchi 		case PDB_DEVICE:
285*abc79d9dSRobert Mustacchi 			if (buf[0] != '\t') {
286*abc79d9dSRobert Mustacchi 				state = PDB_VENDOR;
287*abc79d9dSRobert Mustacchi 				goto newstate;
288*abc79d9dSRobert Mustacchi 			}
289*abc79d9dSRobert Mustacchi 
290*abc79d9dSRobert Mustacchi 			if (buf[1] == '\t') {
291*abc79d9dSRobert Mustacchi 				state = PDB_SUBDEV;
292*abc79d9dSRobert Mustacchi 				goto newstate;
293*abc79d9dSRobert Mustacchi 			}
294*abc79d9dSRobert Mustacchi 
295*abc79d9dSRobert Mustacchi 			assert(v != NULL);
296*abc79d9dSRobert Mustacchi 			d = parse_device(buf, v);
297*abc79d9dSRobert Mustacchi 			if (d == NULL)
298*abc79d9dSRobert Mustacchi 				return (NULL);
299*abc79d9dSRobert Mustacchi 			continue;
300*abc79d9dSRobert Mustacchi 		case PDB_SUBDEV:
301*abc79d9dSRobert Mustacchi 			if (buf[0] != '\t') {
302*abc79d9dSRobert Mustacchi 				state = PDB_VENDOR;
303*abc79d9dSRobert Mustacchi 				goto newstate;
304*abc79d9dSRobert Mustacchi 			}
305*abc79d9dSRobert Mustacchi 
306*abc79d9dSRobert Mustacchi 			if (buf[0] == '\t' && buf[1] != '\t') {
307*abc79d9dSRobert Mustacchi 				state = PDB_DEVICE;
308*abc79d9dSRobert Mustacchi 				goto newstate;
309*abc79d9dSRobert Mustacchi 			}
310*abc79d9dSRobert Mustacchi 
311*abc79d9dSRobert Mustacchi 			assert(buf[0] == '\t' && buf[1] == '\t');
312*abc79d9dSRobert Mustacchi 			assert(d != NULL);
313*abc79d9dSRobert Mustacchi 			(void) parse_subdev(buf, d);
314*abc79d9dSRobert Mustacchi 		}
315*abc79d9dSRobert Mustacchi 	}
316*abc79d9dSRobert Mustacchi }
317*abc79d9dSRobert Mustacchi 
318*abc79d9dSRobert Mustacchi pcidb_hdl_t *
pcidb_open(int version)319*abc79d9dSRobert Mustacchi pcidb_open(int version)
320*abc79d9dSRobert Mustacchi {
321*abc79d9dSRobert Mustacchi 	pcidb_hdl_t *h;
322*abc79d9dSRobert Mustacchi 	FILE *f;
323*abc79d9dSRobert Mustacchi 
324*abc79d9dSRobert Mustacchi 	if (version != PCIDB_VERSION) {
325*abc79d9dSRobert Mustacchi 		errno = EINVAL;
326*abc79d9dSRobert Mustacchi 		return (NULL);
327*abc79d9dSRobert Mustacchi 	}
328*abc79d9dSRobert Mustacchi 
329*abc79d9dSRobert Mustacchi 	h = malloc(sizeof (pcidb_hdl_t));
330*abc79d9dSRobert Mustacchi 	if (h == NULL)
331*abc79d9dSRobert Mustacchi 		return (NULL);
332*abc79d9dSRobert Mustacchi 
333*abc79d9dSRobert Mustacchi 	h->ph_vstart = NULL;
334*abc79d9dSRobert Mustacchi 	h->ph_vend = NULL;
335*abc79d9dSRobert Mustacchi 
336*abc79d9dSRobert Mustacchi 	f = fopen(pci_db, "rF");
337*abc79d9dSRobert Mustacchi 	if (f == NULL) {
338*abc79d9dSRobert Mustacchi 		free(h);
339*abc79d9dSRobert Mustacchi 		return (NULL);
340*abc79d9dSRobert Mustacchi 	}
341*abc79d9dSRobert Mustacchi 
342*abc79d9dSRobert Mustacchi 	if (parse_db(f, h) < 0) {
343*abc79d9dSRobert Mustacchi 		pcidb_close(h);
344*abc79d9dSRobert Mustacchi 		free(h);
345*abc79d9dSRobert Mustacchi 		return (NULL);
346*abc79d9dSRobert Mustacchi 	}
347*abc79d9dSRobert Mustacchi 
348*abc79d9dSRobert Mustacchi 	return (h);
349*abc79d9dSRobert Mustacchi }
350*abc79d9dSRobert Mustacchi 
351*abc79d9dSRobert Mustacchi void
pcidb_close(pcidb_hdl_t * h)352*abc79d9dSRobert Mustacchi pcidb_close(pcidb_hdl_t *h)
353*abc79d9dSRobert Mustacchi {
354*abc79d9dSRobert Mustacchi 	pcidb_vendor_t *v, *tv;
355*abc79d9dSRobert Mustacchi 
356*abc79d9dSRobert Mustacchi 	pcidb_device_t *d, *td;
357*abc79d9dSRobert Mustacchi 	pcidb_subvd_t *s, *ts;
358*abc79d9dSRobert Mustacchi 
359*abc79d9dSRobert Mustacchi 	if (h == NULL)
360*abc79d9dSRobert Mustacchi 		return;
361*abc79d9dSRobert Mustacchi 
362*abc79d9dSRobert Mustacchi 	v = h->ph_vstart;
363*abc79d9dSRobert Mustacchi 	while (v != NULL) {
364*abc79d9dSRobert Mustacchi 		d = v->pv_dstart;
365*abc79d9dSRobert Mustacchi 		while (d != NULL) {
366*abc79d9dSRobert Mustacchi 			s = d->pd_sstart;
367*abc79d9dSRobert Mustacchi 			while (s != NULL) {
368*abc79d9dSRobert Mustacchi 				ts = s;
369*abc79d9dSRobert Mustacchi 				s = s->ps_next;
370*abc79d9dSRobert Mustacchi 				free(ts);
371*abc79d9dSRobert Mustacchi 			}
372*abc79d9dSRobert Mustacchi 			td = d;
373*abc79d9dSRobert Mustacchi 			d = d->pd_next;
374*abc79d9dSRobert Mustacchi 			free(td);
375*abc79d9dSRobert Mustacchi 		}
376*abc79d9dSRobert Mustacchi 		tv = v;
377*abc79d9dSRobert Mustacchi 		v = v->pv_next;
378*abc79d9dSRobert Mustacchi 		free(tv);
379*abc79d9dSRobert Mustacchi 	}
380*abc79d9dSRobert Mustacchi 
381*abc79d9dSRobert Mustacchi 	free(h);
382*abc79d9dSRobert Mustacchi }
383*abc79d9dSRobert Mustacchi 
384*abc79d9dSRobert Mustacchi pcidb_vendor_t *
pcidb_lookup_vendor(pcidb_hdl_t * hdl,uint16_t id)385*abc79d9dSRobert Mustacchi pcidb_lookup_vendor(pcidb_hdl_t *hdl, uint16_t id)
386*abc79d9dSRobert Mustacchi {
387*abc79d9dSRobert Mustacchi 	pcidb_vendor_t *v;
388*abc79d9dSRobert Mustacchi 
389*abc79d9dSRobert Mustacchi 	for (v = hdl->ph_vstart; v != NULL; v = v->pv_next) {
390*abc79d9dSRobert Mustacchi 		if (v->pv_id == id)
391*abc79d9dSRobert Mustacchi 			return (v);
392*abc79d9dSRobert Mustacchi 	}
393*abc79d9dSRobert Mustacchi 
394*abc79d9dSRobert Mustacchi 	return (NULL);
395*abc79d9dSRobert Mustacchi }
396*abc79d9dSRobert Mustacchi 
397*abc79d9dSRobert Mustacchi const char *
pcidb_vendor_name(pcidb_vendor_t * v)398*abc79d9dSRobert Mustacchi pcidb_vendor_name(pcidb_vendor_t *v)
399*abc79d9dSRobert Mustacchi {
400*abc79d9dSRobert Mustacchi 	return (v->pv_name);
401*abc79d9dSRobert Mustacchi }
402*abc79d9dSRobert Mustacchi 
403*abc79d9dSRobert Mustacchi uint16_t
pcidb_vendor_id(pcidb_vendor_t * v)404*abc79d9dSRobert Mustacchi pcidb_vendor_id(pcidb_vendor_t *v)
405*abc79d9dSRobert Mustacchi {
406*abc79d9dSRobert Mustacchi 	return (v->pv_id);
407*abc79d9dSRobert Mustacchi }
408*abc79d9dSRobert Mustacchi 
409*abc79d9dSRobert Mustacchi pcidb_vendor_t *
pcidb_vendor_iter(pcidb_hdl_t * h)410*abc79d9dSRobert Mustacchi pcidb_vendor_iter(pcidb_hdl_t *h)
411*abc79d9dSRobert Mustacchi {
412*abc79d9dSRobert Mustacchi 	return (h->ph_vstart);
413*abc79d9dSRobert Mustacchi }
414*abc79d9dSRobert Mustacchi 
415*abc79d9dSRobert Mustacchi pcidb_vendor_t *
pcidb_vendor_iter_next(pcidb_vendor_t * v)416*abc79d9dSRobert Mustacchi pcidb_vendor_iter_next(pcidb_vendor_t *v)
417*abc79d9dSRobert Mustacchi {
418*abc79d9dSRobert Mustacchi 	assert(v != NULL);
419*abc79d9dSRobert Mustacchi 	return (v->pv_next);
420*abc79d9dSRobert Mustacchi }
421*abc79d9dSRobert Mustacchi 
422*abc79d9dSRobert Mustacchi pcidb_device_t *
pcidb_lookup_device_by_vendor(pcidb_vendor_t * v,uint16_t id)423*abc79d9dSRobert Mustacchi pcidb_lookup_device_by_vendor(pcidb_vendor_t *v, uint16_t id)
424*abc79d9dSRobert Mustacchi {
425*abc79d9dSRobert Mustacchi 	pcidb_device_t *d;
426*abc79d9dSRobert Mustacchi 	assert(v != NULL);
427*abc79d9dSRobert Mustacchi 
428*abc79d9dSRobert Mustacchi 	for (d = v->pv_dstart; d != NULL; d = d->pd_next)
429*abc79d9dSRobert Mustacchi 		if (d->pd_id == id)
430*abc79d9dSRobert Mustacchi 			return (d);
431*abc79d9dSRobert Mustacchi 
432*abc79d9dSRobert Mustacchi 	return (NULL);
433*abc79d9dSRobert Mustacchi }
434*abc79d9dSRobert Mustacchi 
435*abc79d9dSRobert Mustacchi pcidb_device_t *
pcidb_lookup_device(pcidb_hdl_t * h,uint16_t vid,uint16_t did)436*abc79d9dSRobert Mustacchi pcidb_lookup_device(pcidb_hdl_t *h, uint16_t vid, uint16_t did)
437*abc79d9dSRobert Mustacchi {
438*abc79d9dSRobert Mustacchi 	pcidb_vendor_t *v;
439*abc79d9dSRobert Mustacchi 
440*abc79d9dSRobert Mustacchi 	v = pcidb_lookup_vendor(h, vid);
441*abc79d9dSRobert Mustacchi 	if (v == NULL)
442*abc79d9dSRobert Mustacchi 		return (NULL);
443*abc79d9dSRobert Mustacchi 
444*abc79d9dSRobert Mustacchi 	return (pcidb_lookup_device_by_vendor(v, did));
445*abc79d9dSRobert Mustacchi }
446*abc79d9dSRobert Mustacchi 
447*abc79d9dSRobert Mustacchi pcidb_device_t *
pcidb_device_iter(pcidb_vendor_t * v)448*abc79d9dSRobert Mustacchi pcidb_device_iter(pcidb_vendor_t *v)
449*abc79d9dSRobert Mustacchi {
450*abc79d9dSRobert Mustacchi 	return (v->pv_dstart);
451*abc79d9dSRobert Mustacchi }
452*abc79d9dSRobert Mustacchi 
453*abc79d9dSRobert Mustacchi pcidb_device_t *
pcidb_device_iter_next(pcidb_device_t * d)454*abc79d9dSRobert Mustacchi pcidb_device_iter_next(pcidb_device_t *d)
455*abc79d9dSRobert Mustacchi {
456*abc79d9dSRobert Mustacchi 	return (d->pd_next);
457*abc79d9dSRobert Mustacchi }
458*abc79d9dSRobert Mustacchi 
459*abc79d9dSRobert Mustacchi const char *
pcidb_device_name(pcidb_device_t * d)460*abc79d9dSRobert Mustacchi pcidb_device_name(pcidb_device_t *d)
461*abc79d9dSRobert Mustacchi {
462*abc79d9dSRobert Mustacchi 	return (d->pd_name);
463*abc79d9dSRobert Mustacchi }
464*abc79d9dSRobert Mustacchi 
465*abc79d9dSRobert Mustacchi uint16_t
pcidb_device_id(pcidb_device_t * d)466*abc79d9dSRobert Mustacchi pcidb_device_id(pcidb_device_t *d)
467*abc79d9dSRobert Mustacchi {
468*abc79d9dSRobert Mustacchi 	return (d->pd_id);
469*abc79d9dSRobert Mustacchi }
470*abc79d9dSRobert Mustacchi 
471*abc79d9dSRobert Mustacchi pcidb_vendor_t *
pcidb_device_vendor(pcidb_device_t * d)472*abc79d9dSRobert Mustacchi pcidb_device_vendor(pcidb_device_t *d)
473*abc79d9dSRobert Mustacchi {
474*abc79d9dSRobert Mustacchi 	return (d->pd_vend);
475*abc79d9dSRobert Mustacchi }
476*abc79d9dSRobert Mustacchi 
477*abc79d9dSRobert Mustacchi pcidb_subvd_t *
pcidb_lookup_subvd_by_device(pcidb_device_t * d,uint16_t svid,uint16_t sdid)478*abc79d9dSRobert Mustacchi pcidb_lookup_subvd_by_device(pcidb_device_t *d, uint16_t svid, uint16_t sdid)
479*abc79d9dSRobert Mustacchi {
480*abc79d9dSRobert Mustacchi 	pcidb_subvd_t *s;
481*abc79d9dSRobert Mustacchi 
482*abc79d9dSRobert Mustacchi 	assert(d != NULL);
483*abc79d9dSRobert Mustacchi 
484*abc79d9dSRobert Mustacchi 	for (s = d->pd_sstart; s != NULL; s = s->ps_next)
485*abc79d9dSRobert Mustacchi 		if (s->ps_vid == svid && s->ps_did == sdid)
486*abc79d9dSRobert Mustacchi 			return (s);
487*abc79d9dSRobert Mustacchi 
488*abc79d9dSRobert Mustacchi 	return (NULL);
489*abc79d9dSRobert Mustacchi }
490*abc79d9dSRobert Mustacchi 
491*abc79d9dSRobert Mustacchi pcidb_subvd_t *
pcidb_lookup_subvd_by_vendor(pcidb_vendor_t * v,uint16_t devid,uint16_t svid,uint16_t sdid)492*abc79d9dSRobert Mustacchi pcidb_lookup_subvd_by_vendor(pcidb_vendor_t *v, uint16_t devid, uint16_t svid,
493*abc79d9dSRobert Mustacchi     uint16_t sdid)
494*abc79d9dSRobert Mustacchi {
495*abc79d9dSRobert Mustacchi 	pcidb_device_t *d;
496*abc79d9dSRobert Mustacchi 
497*abc79d9dSRobert Mustacchi 	assert(v != NULL);
498*abc79d9dSRobert Mustacchi 	d = pcidb_lookup_device_by_vendor(v, devid);
499*abc79d9dSRobert Mustacchi 	if (d == NULL)
500*abc79d9dSRobert Mustacchi 		return (NULL);
501*abc79d9dSRobert Mustacchi 
502*abc79d9dSRobert Mustacchi 	return (pcidb_lookup_subvd_by_device(d, svid, sdid));
503*abc79d9dSRobert Mustacchi }
504*abc79d9dSRobert Mustacchi 
505*abc79d9dSRobert Mustacchi pcidb_subvd_t *
pcidb_lookup_subvd(pcidb_hdl_t * h,uint16_t vid,uint16_t did,uint16_t svid,uint16_t sdid)506*abc79d9dSRobert Mustacchi pcidb_lookup_subvd(pcidb_hdl_t *h, uint16_t vid, uint16_t did, uint16_t svid,
507*abc79d9dSRobert Mustacchi     uint16_t sdid)
508*abc79d9dSRobert Mustacchi {
509*abc79d9dSRobert Mustacchi 	pcidb_device_t *d;
510*abc79d9dSRobert Mustacchi 
511*abc79d9dSRobert Mustacchi 	assert(h != NULL);
512*abc79d9dSRobert Mustacchi 	d = pcidb_lookup_device(h, vid, did);
513*abc79d9dSRobert Mustacchi 	if (d == NULL)
514*abc79d9dSRobert Mustacchi 		return (NULL);
515*abc79d9dSRobert Mustacchi 
516*abc79d9dSRobert Mustacchi 	return (pcidb_lookup_subvd_by_device(d, svid, sdid));
517*abc79d9dSRobert Mustacchi }
518*abc79d9dSRobert Mustacchi 
519*abc79d9dSRobert Mustacchi pcidb_subvd_t *
pcidb_subvd_iter(pcidb_device_t * d)520*abc79d9dSRobert Mustacchi pcidb_subvd_iter(pcidb_device_t *d)
521*abc79d9dSRobert Mustacchi {
522*abc79d9dSRobert Mustacchi 	return (d->pd_sstart);
523*abc79d9dSRobert Mustacchi }
524*abc79d9dSRobert Mustacchi 
525*abc79d9dSRobert Mustacchi pcidb_subvd_t *
pcidb_subvd_iter_next(pcidb_subvd_t * s)526*abc79d9dSRobert Mustacchi pcidb_subvd_iter_next(pcidb_subvd_t *s)
527*abc79d9dSRobert Mustacchi {
528*abc79d9dSRobert Mustacchi 	return (s->ps_next);
529*abc79d9dSRobert Mustacchi }
530*abc79d9dSRobert Mustacchi 
531*abc79d9dSRobert Mustacchi const char *
pcidb_subvd_name(pcidb_subvd_t * s)532*abc79d9dSRobert Mustacchi pcidb_subvd_name(pcidb_subvd_t *s)
533*abc79d9dSRobert Mustacchi {
534*abc79d9dSRobert Mustacchi 	return (s->ps_name);
535*abc79d9dSRobert Mustacchi }
536*abc79d9dSRobert Mustacchi 
537*abc79d9dSRobert Mustacchi uint16_t
pcidb_subvd_svid(pcidb_subvd_t * s)538*abc79d9dSRobert Mustacchi pcidb_subvd_svid(pcidb_subvd_t *s)
539*abc79d9dSRobert Mustacchi {
540*abc79d9dSRobert Mustacchi 	return (s->ps_vid);
541*abc79d9dSRobert Mustacchi }
542*abc79d9dSRobert Mustacchi 
543*abc79d9dSRobert Mustacchi uint16_t
pcidb_subvd_sdid(pcidb_subvd_t * s)544*abc79d9dSRobert Mustacchi pcidb_subvd_sdid(pcidb_subvd_t *s)
545*abc79d9dSRobert Mustacchi {
546*abc79d9dSRobert Mustacchi 	return (s->ps_did);
547*abc79d9dSRobert Mustacchi }
548*abc79d9dSRobert Mustacchi 
549*abc79d9dSRobert Mustacchi pcidb_device_t *
pcidb_subvd_device(pcidb_subvd_t * s)550*abc79d9dSRobert Mustacchi pcidb_subvd_device(pcidb_subvd_t *s)
551*abc79d9dSRobert Mustacchi {
552*abc79d9dSRobert Mustacchi 	return (s->ps_dev);
553*abc79d9dSRobert Mustacchi }
554*abc79d9dSRobert Mustacchi 
555*abc79d9dSRobert Mustacchi pcidb_vendor_t *
pcidb_subvd_vendor(pcidb_subvd_t * s)556*abc79d9dSRobert Mustacchi pcidb_subvd_vendor(pcidb_subvd_t *s)
557*abc79d9dSRobert Mustacchi {
558*abc79d9dSRobert Mustacchi 	return (s->ps_vend);
559*abc79d9dSRobert Mustacchi }
560