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 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 * 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 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 * 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 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 * 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 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 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 * 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 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 * 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 * 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 * 556*abc79d9dSRobert Mustacchi pcidb_subvd_vendor(pcidb_subvd_t *s) 557*abc79d9dSRobert Mustacchi { 558*abc79d9dSRobert Mustacchi return (s->ps_vend); 559*abc79d9dSRobert Mustacchi } 560