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