# HG changeset patch # User Robert Mustacchi # Date 1364948701 25200 # Node ID 779e63d911a51259e6e3918b47e510a0450f7f4d # Parent 61e74b16a6911c243733c6aa8740cc6b39144dd9 3679 prtconf should print out PCI database information 3680 Want a library to allow programatic access to the pci database Reviewed by: Jerry Jelinek Reviewed by: Theo Schlossnagle Reviewed by: Josef 'Jeff' Sipek Reviewed by: Hans Rosenfeld Approved by: Gordon Ross diff -r 61e74b16a691 -r 779e63d911a5 exception_lists/packaging --- a/exception_lists/packaging Thu Apr 11 10:46:40 2013 -0700 +++ b/exception_lists/packaging Tue Apr 02 17:25:01 2013 -0700 @@ -981,3 +981,13 @@ usr/lib/amd64/libsaveargs.so i386 usr/lib/amd64/libstandsaveargs.so i386 usr/lib/amd64/llib-lsaveargs.ln i386 + +# +# libpcidb is private +# +usr/include/pcidb.h +usr/lib/amd64/libpcidb.so +usr/lib/amd64/llib-lpcidb.ln +usr/lib/libpcidb.so +usr/lib/llib-lpcidb +usr/lib/llib-lpcidb.ln diff -r 61e74b16a691 -r 779e63d911a5 usr/src/cmd/prtconf/Makefile.com --- a/usr/src/cmd/prtconf/Makefile.com Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/cmd/prtconf/Makefile.com Tue Apr 02 17:25:01 2013 -0700 @@ -33,7 +33,7 @@ CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-uninitialized -LDLIBS += -ldevinfo -lnvpair +LDLIBS += -ldevinfo -lnvpair -lpcidb FILEMODE= 02555 diff -r 61e74b16a691 -r 779e63d911a5 usr/src/cmd/prtconf/pdevinfo.c --- a/usr/src/cmd/prtconf/pdevinfo.c Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/cmd/prtconf/pdevinfo.c Tue Apr 02 17:25:01 2013 -0700 @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ /* * For machines that support the openprom, fetch and print the list @@ -44,6 +47,7 @@ #include #include #include +#include #include "prtconf.h" @@ -95,6 +99,7 @@ typedef struct di_args { di_prom_handle_t prom_hdl; di_devlink_handle_t devlink_hdl; + pcidb_hdl_t *pcidb_hdl; } di_arg_t; static const dumpops_t sysprop_dumpops = { @@ -155,6 +160,7 @@ static void promclose(); static di_node_t find_target_node(di_node_t); static void node_display_set(di_node_t); +static int dump_pciid(char *, int, di_node_t, pcidb_hdl_t *); void prtconf_devinfo(void) @@ -163,6 +169,7 @@ di_arg_t di_arg; di_prom_handle_t prom_hdl = DI_PROM_HANDLE_NIL; di_devlink_handle_t devlink_hdl = NULL; + pcidb_hdl_t *pcidb_hdl = NULL; di_node_t root_node; uint_t flag; char *rootpath; @@ -219,8 +226,16 @@ exit(0); } + if (opts.o_verbose || opts.o_pciid) { + pcidb_hdl = pcidb_open(PCIDB_VERSION); + if (pcidb_hdl == NULL) + (void) _error(NULL, "pcidb facility not available, " + "continuing anyways"); + } + di_arg.prom_hdl = prom_hdl; di_arg.devlink_hdl = devlink_hdl; + di_arg.pcidb_hdl = pcidb_hdl; /* * ...and walk all nodes to report them out... @@ -293,6 +308,8 @@ di_prom_fini(prom_hdl); if (devlink_hdl != NULL) (void) di_devlink_fini(&devlink_hdl); + if (pcidb_hdl != NULL) + pcidb_close(pcidb_hdl); di_fini(root_node); } @@ -750,7 +767,7 @@ (void) printf("%s", di_node_name(node)); if (opts.o_pciid) - (void) print_pciid(node, di_arg->prom_hdl); + (void) print_pciid(node, di_arg->prom_hdl, di_arg->pcidb_hdl); /* * if this node does not have an instance number or is the @@ -790,9 +807,13 @@ /* Ensure that 'compatible' is printed under Hardware header */ if (!compat_printed) - (void) dump_compatible(printed ? NULL : "Hardware", + printed |= dump_compatible(printed ? NULL : "Hardware", ilev + 1, node); + /* Ensure that pci id information is printed under Hardware */ + (void) dump_pciid(printed ? NULL : "Hardware", + ilev + 1, node, di_arg->pcidb_hdl); + dump_priv_data(ilev + 1, node); dump_pathing_data(ilev + 1, node); dump_link_data(ilev + 1, node, devlink_hdl); @@ -1924,3 +1945,104 @@ (void) putchar('\n'); return (1); } + +static int +dump_pciid(char *name, int ilev, di_node_t node, pcidb_hdl_t *pci) +{ + char *t = NULL; + int *vid, *did, *svid, *sdid; + const char *vname, *dname, *sname; + pcidb_vendor_t *pciv; + pcidb_device_t *pcid; + pcidb_subvd_t *pcis; + di_node_t pnode = di_parent_node(node); + + const char *unov = "unknown vendor"; + const char *unod = "unknown device"; + const char *unos = "unknown subsystem"; + + if (pci == NULL) + return (0); + + vname = unov; + dname = unod; + sname = unos; + + if (di_prop_lookup_strings(DDI_DEV_T_ANY, pnode, + "device_type", &t) <= 0) + return (0); + + if (t == NULL || (strcmp(t, "pci") != 0 && + strcmp(t, "pciex") != 0)) + return (0); + + /* + * All devices should have a vendor and device id, if we fail to find + * one, then we're going to return right here and not print anything. + * + * We're going to also check for the subsystem-vendor-id and + * subsystem-id. If we don't find one of them, we're going to assume + * that this device does not have one. In that case, we will never + * attempt to try and print anything related to that. If it does have + * both, then we are going to look them up and print the appropriate + * string if we find it or not. + */ + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vid) <= 0) + return (0); + + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &did) <= 0) + return (0); + + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "subsystem-vendor-id", + &svid) <= 0 || di_prop_lookup_ints(DDI_DEV_T_ANY, node, + "subsystem-id", &sdid) <= 0) { + svid = NULL; + sdid = NULL; + sname = NULL; + } + + pciv = pcidb_lookup_vendor(pci, vid[0]); + if (pciv == NULL) + goto print; + vname = pcidb_vendor_name(pciv); + + pcid = pcidb_lookup_device_by_vendor(pciv, did[0]); + if (pcid == NULL) + goto print; + dname = pcidb_device_name(pcid); + + if (svid != NULL) { + pcis = pcidb_lookup_subvd_by_device(pcid, svid[0], sdid[0]); + if (pcis == NULL) + goto print; + sname = pcidb_subvd_name(pcis); + } + +print: + /* If name is non-NULL, produce header */ + if (name) { + indent_to_level(ilev); + (void) printf("%s properties:\n", name); + } + ilev++; + + /* These are all going to be single string properties */ + indent_to_level(ilev); + (void) printf("name='vendor-name' type=string items=1\n"); + indent_to_level(ilev); + (void) printf(" value='%s'\n", vname); + + indent_to_level(ilev); + (void) printf("name='device-name' type=string items=1\n"); + indent_to_level(ilev); + (void) printf(" value='%s'\n", dname); + + if (sname != NULL) { + indent_to_level(ilev); + (void) printf("name='subsystem-name' type=string items=1\n"); + indent_to_level(ilev); + (void) printf(" value='%s'\n", sname); + } + + return (0); +} diff -r 61e74b16a691 -r 779e63d911a5 usr/src/cmd/prtconf/prt_xxx.c --- a/usr/src/cmd/prtconf/prt_xxx.c Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/cmd/prtconf/prt_xxx.c Tue Apr 02 17:25:01 2013 -0700 @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include @@ -418,8 +420,10 @@ * Print vendor ID and device ID for PCI devices */ int -print_pciid(di_node_t node, di_prom_handle_t ph) +print_pciid(di_node_t node, di_prom_handle_t ph, pcidb_hdl_t *pci) { + pcidb_vendor_t *vend; + pcidb_device_t *dev; di_node_t pnode = di_parent_node(node); char *s = NULL; int *i, type = di_nodeid(node); @@ -436,10 +440,28 @@ "vendor-id", &i) > 0) (void) printf("%x", i[0]); + if (pci != NULL) + vend = pcidb_lookup_vendor(pci, i[0]); + if (LOOKUP_PROP(ints, ph, type, DDI_DEV_T_ANY, node, "device-id", &i) > 0) (void) printf(",%x", i[0]); - (void) printf(")"); + + if (pci != NULL) + dev = pcidb_lookup_device_by_vendor(vend, i[0]); + + (void) printf(") ["); + if (vend != NULL) + (void) printf("%s ", pcidb_vendor_name(vend)); + else + (void) printf("unknown vendor, "); + + if (dev != NULL) + (void) printf("%s", pcidb_device_name(dev)); + else + (void) printf("unknown device"); + + (void) printf("]"); return (1); } diff -r 61e74b16a691 -r 779e63d911a5 usr/src/cmd/prtconf/prtconf.h --- a/usr/src/cmd/prtconf/prtconf.h Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/cmd/prtconf/prtconf.h Tue Apr 02 17:25:01 2013 -0700 @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Joyent, Inc. All rights reserved. */ #ifndef _PRT_CONF_H @@ -31,11 +32,12 @@ #endif #include +#include #include extern void init_priv_data(struct di_priv_data *); extern void dump_priv_data(int, di_node_t); -extern int print_pciid(di_node_t, di_prom_handle_t); +extern int print_pciid(di_node_t, di_prom_handle_t, pcidb_hdl_t *); extern void indent_to_level(int); extern void prtconf_devinfo(); extern int do_fbname(); diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/Makefile --- a/usr/src/lib/Makefile Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/lib/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -22,6 +22,7 @@ # Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. include ../Makefile.master @@ -157,7 +158,8 @@ libdscfg \ librdc \ libinstzones \ - libpkg + libpkg \ + libpcidb SUBDIRS += \ passwdutil \ @@ -432,6 +434,7 @@ libnsl \ libnwam \ libpam \ + libpcidb \ libpctx \ libpicl \ libpicltree \ diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.lib + +HDRS = pcidb.h +HDRDIR = common + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +install: install_h $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/Makefile.com --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/Makefile.com Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# + +LIBRARY = libpcidb.a +VERS = .1 +OBJECTS = pcidb.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) $(LINTLIB) + +SRCDIR = ../common + +LDLIBS += -lc + +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/amd64/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/amd64/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/common/llib-lpcidb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/common/llib-lpcidb Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/common/mapfile-vers --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/common/mapfile-vers Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,69 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate { + global: + pcidb_open; + pcidb_close; + pcidb_lookup_vendor; + pcidb_vendor_iter; + pcidb_vendor_iter_next; + pcidb_vendor_name; + pcidb_vendor_id; + pcidb_lookup_device; + pcidb_lookup_device_by_vendor; + pcidb_device_iter; + pcidb_device_iter_next; + pcidb_device_name; + pcidb_device_id; + pcidb_device_vendor; + pcidb_lookup_subvd; + pcidb_lookup_subvd_by_vendor; + pcidb_lookup_subvd_by_device; + pcidb_subvd_iter; + pcidb_subvd_iter_next; + pcidb_subvd_name; + pcidb_subvd_svid; + pcidb_subvd_sdid; + pcidb_subvd_device; + pcidb_subvd_vendor; + local: + *; +}; diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/common/pcidb.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/common/pcidb.c Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,559 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ + +/* + * This library exists to understand and parse the pci.ids database that is + * maintained at http://pci-ids.ucw.cz/ and in the gate at cmd/hwdata. This + * database provides a way to map the PCI device, vendor, and subsystem ids to + * a human understandable name. + * + * This library exports this data in a similar way to a tree. The handle that + * is returned from pcidb_open is the root of the tree. The next level are the + * vendors. Each vendor has a unique set of devices and each device has a unique + * set of subvendor and subdevice pairs. + * + * Parsing information: + * + * The database is formatted in the following basic format: + * vendor_idvendor_name + * device_iddevice_name + * subvendorsubdevicesubsystem_name + * + * For any given vendor, there can be multiple devices. And for any given device + * there will be multiple subsystems. In addition, there can be comments that + * start a line which use the '#' character. + * + * At the end of the file, there are a series of PCI classes. Those will start + * with a single C. Once we hit those, we stop all parsing. We currently + * don't care about consuming or presenting those. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcidb.h" + +#define PCI_NAME_MAX 256 +#define PCI_READLINE 1024 + +/* Forward declarations */ +struct pcidb_vendor; +struct pcidb_device; +struct pcidb_subvd; + +struct pcidb_subvd { + uint16_t ps_vid; + uint16_t ps_did; + char ps_name[PCI_NAME_MAX]; + struct pcidb_subvd *ps_prev; + struct pcidb_subvd *ps_next; + struct pcidb_device *ps_dev; + struct pcidb_vendor *ps_vend; +}; + +struct pcidb_device { + uint16_t pd_id; + char pd_name[PCI_NAME_MAX]; + struct pcidb_subvd *pd_sstart; + struct pcidb_subvd *pd_send; + struct pcidb_device *pd_next; + struct pcidb_device *pd_prev; + struct pcidb_vendor *pd_vend; +}; + +struct pcidb_vendor { + uint16_t pv_id; + char pv_name[PCI_NAME_MAX]; + struct pcidb_device *pv_dstart; + struct pcidb_device *pv_dend; + struct pcidb_vendor *pv_prev; + struct pcidb_vendor *pv_next; +}; + +struct pcidb_hdl { + pcidb_vendor_t *ph_vstart; + pcidb_vendor_t *ph_vend; +}; + +typedef enum pcidb_parse { + PDB_VENDOR, + PDB_DEVICE, + PDB_SUBDEV +} pcidb_parse_t; + +static const char *pci_db = "/usr/share/hwdata/pci.ids"; + +static void +pcihdl_add_vendor(pcidb_hdl_t *hdl, pcidb_vendor_t *v) +{ + if (hdl->ph_vstart == NULL && hdl->ph_vend == NULL) { + hdl->ph_vstart = v; + hdl->ph_vend = v; + v->pv_prev = NULL; + v->pv_next = NULL; + } else { + v->pv_prev = hdl->ph_vend; + v->pv_next = NULL; + hdl->ph_vend->pv_next = v; + hdl->ph_vend = v; + } +} + +static pcidb_vendor_t * +parse_vendor(char *buf, pcidb_hdl_t *hdl) +{ + pcidb_vendor_t *v; + size_t len; + + v = malloc(sizeof (pcidb_vendor_t)); + if (v == NULL) + return (NULL); + + pcihdl_add_vendor(hdl, v); + v->pv_dstart = NULL; + v->pv_dend = NULL; + + buf[4] = '\0'; + v->pv_id = strtol(buf, NULL, 16); + buf += 6; + len = strlen(buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + (void) strlcpy(v->pv_name, buf, PCI_NAME_MAX); + + return (v); +} + +static void +insert_device(pcidb_vendor_t *v, pcidb_device_t *d) +{ + d->pd_vend = v; + if (v->pv_dstart == NULL && v->pv_dend == NULL) { + v->pv_dstart = d; + v->pv_dend = d; + d->pd_next = NULL; + d->pd_prev = NULL; + } else { + d->pd_prev = v->pv_dend; + d->pd_next = NULL; + v->pv_dend->pd_next = d; + v->pv_dend = d; + } +} + +static pcidb_device_t * +parse_device(char *buf, pcidb_vendor_t *v) +{ + pcidb_device_t *d; + size_t len; + + d = malloc(sizeof (pcidb_device_t)); + if (d == NULL) + return (d); + + d->pd_sstart = NULL; + d->pd_send = NULL; + insert_device(v, d); + + buf++; + buf[4] = '\0'; + d->pd_id = strtol(buf, NULL, 16); + buf += 6; + len = strlen(buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + (void) strlcpy(d->pd_name, buf, PCI_NAME_MAX); + return (d); +} + +static void +insert_subdev(pcidb_device_t *d, pcidb_subvd_t *s) +{ + s->ps_dev = d; + s->ps_vend = d->pd_vend; + if (d->pd_sstart == NULL) { + d->pd_sstart = s; + d->pd_send = s; + s->ps_prev = NULL; + s->ps_next = NULL; + } else { + s->ps_prev = d->pd_send; + s->ps_next = NULL; + d->pd_send->ps_next = s; + d->pd_send = s; + } +} + +static pcidb_subvd_t * +parse_subdev(char *buf, pcidb_device_t *d) +{ + pcidb_subvd_t *s; + size_t len; + + s = malloc(sizeof (pcidb_subvd_t)); + if (s == NULL) + return (NULL); + insert_subdev(d, s); + + buf += 2; + buf[4] = '\0'; + s->ps_vid = strtol(buf, NULL, 16); + buf += 5; + buf[4] = '\0'; + s->ps_did = strtol(buf, NULL, 16); + buf += 6; + + len = strlen(buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + (void) strlcpy(s->ps_name, buf, PCI_NAME_MAX); + + return (s); +} + +static int +readline(FILE *f, char *buf, size_t len) +{ + for (;;) { + if (fgets(buf, len, f) == NULL) + return (-1); + + if (buf[0] == 'C') + return (-1); + + if (buf[0] != '#' && buf[0] != '\n') + return (0); + } +} + +static int +parse_db(FILE *f, pcidb_hdl_t *hdl) +{ + char buf[1024]; + pcidb_vendor_t *v = NULL; + pcidb_device_t *d = NULL; + pcidb_parse_t state = PDB_VENDOR; + + for (;;) { + errno = 0; + if (readline(f, buf, sizeof (buf)) != 0) { + if (errno != 0) + return (-1); + else + return (0); + } + +newstate: + switch (state) { + case PDB_VENDOR: + v = parse_vendor(buf, hdl); + if (v == NULL) + return (NULL); + state = PDB_DEVICE; + continue; + case PDB_DEVICE: + if (buf[0] != '\t') { + state = PDB_VENDOR; + goto newstate; + } + + if (buf[1] == '\t') { + state = PDB_SUBDEV; + goto newstate; + } + + assert(v != NULL); + d = parse_device(buf, v); + if (d == NULL) + return (NULL); + continue; + case PDB_SUBDEV: + if (buf[0] != '\t') { + state = PDB_VENDOR; + goto newstate; + } + + if (buf[0] == '\t' && buf[1] != '\t') { + state = PDB_DEVICE; + goto newstate; + } + + assert(buf[0] == '\t' && buf[1] == '\t'); + assert(d != NULL); + (void) parse_subdev(buf, d); + } + } +} + +pcidb_hdl_t * +pcidb_open(int version) +{ + pcidb_hdl_t *h; + FILE *f; + + if (version != PCIDB_VERSION) { + errno = EINVAL; + return (NULL); + } + + h = malloc(sizeof (pcidb_hdl_t)); + if (h == NULL) + return (NULL); + + h->ph_vstart = NULL; + h->ph_vend = NULL; + + f = fopen(pci_db, "rF"); + if (f == NULL) { + free(h); + return (NULL); + } + + if (parse_db(f, h) < 0) { + pcidb_close(h); + free(h); + return (NULL); + } + + return (h); +} + +void +pcidb_close(pcidb_hdl_t *h) +{ + pcidb_vendor_t *v, *tv; + + pcidb_device_t *d, *td; + pcidb_subvd_t *s, *ts; + + if (h == NULL) + return; + + v = h->ph_vstart; + while (v != NULL) { + d = v->pv_dstart; + while (d != NULL) { + s = d->pd_sstart; + while (s != NULL) { + ts = s; + s = s->ps_next; + free(ts); + } + td = d; + d = d->pd_next; + free(td); + } + tv = v; + v = v->pv_next; + free(tv); + } + + free(h); +} + +pcidb_vendor_t * +pcidb_lookup_vendor(pcidb_hdl_t *hdl, uint16_t id) +{ + pcidb_vendor_t *v; + + for (v = hdl->ph_vstart; v != NULL; v = v->pv_next) { + if (v->pv_id == id) + return (v); + } + + return (NULL); +} + +const char * +pcidb_vendor_name(pcidb_vendor_t *v) +{ + return (v->pv_name); +} + +uint16_t +pcidb_vendor_id(pcidb_vendor_t *v) +{ + return (v->pv_id); +} + +pcidb_vendor_t * +pcidb_vendor_iter(pcidb_hdl_t *h) +{ + return (h->ph_vstart); +} + +pcidb_vendor_t * +pcidb_vendor_iter_next(pcidb_vendor_t *v) +{ + assert(v != NULL); + return (v->pv_next); +} + +pcidb_device_t * +pcidb_lookup_device_by_vendor(pcidb_vendor_t *v, uint16_t id) +{ + pcidb_device_t *d; + assert(v != NULL); + + for (d = v->pv_dstart; d != NULL; d = d->pd_next) + if (d->pd_id == id) + return (d); + + return (NULL); +} + +pcidb_device_t * +pcidb_lookup_device(pcidb_hdl_t *h, uint16_t vid, uint16_t did) +{ + pcidb_vendor_t *v; + + v = pcidb_lookup_vendor(h, vid); + if (v == NULL) + return (NULL); + + return (pcidb_lookup_device_by_vendor(v, did)); +} + +pcidb_device_t * +pcidb_device_iter(pcidb_vendor_t *v) +{ + return (v->pv_dstart); +} + +pcidb_device_t * +pcidb_device_iter_next(pcidb_device_t *d) +{ + return (d->pd_next); +} + +const char * +pcidb_device_name(pcidb_device_t *d) +{ + return (d->pd_name); +} + +uint16_t +pcidb_device_id(pcidb_device_t *d) +{ + return (d->pd_id); +} + +pcidb_vendor_t * +pcidb_device_vendor(pcidb_device_t *d) +{ + return (d->pd_vend); +} + +pcidb_subvd_t * +pcidb_lookup_subvd_by_device(pcidb_device_t *d, uint16_t svid, uint16_t sdid) +{ + pcidb_subvd_t *s; + + assert(d != NULL); + + for (s = d->pd_sstart; s != NULL; s = s->ps_next) + if (s->ps_vid == svid && s->ps_did == sdid) + return (s); + + return (NULL); +} + +pcidb_subvd_t * +pcidb_lookup_subvd_by_vendor(pcidb_vendor_t *v, uint16_t devid, uint16_t svid, + uint16_t sdid) +{ + pcidb_device_t *d; + + assert(v != NULL); + d = pcidb_lookup_device_by_vendor(v, devid); + if (d == NULL) + return (NULL); + + return (pcidb_lookup_subvd_by_device(d, svid, sdid)); +} + +pcidb_subvd_t * +pcidb_lookup_subvd(pcidb_hdl_t *h, uint16_t vid, uint16_t did, uint16_t svid, + uint16_t sdid) +{ + pcidb_device_t *d; + + assert(h != NULL); + d = pcidb_lookup_device(h, vid, did); + if (d == NULL) + return (NULL); + + return (pcidb_lookup_subvd_by_device(d, svid, sdid)); +} + +pcidb_subvd_t * +pcidb_subvd_iter(pcidb_device_t *d) +{ + return (d->pd_sstart); +} + +pcidb_subvd_t * +pcidb_subvd_iter_next(pcidb_subvd_t *s) +{ + return (s->ps_next); +} + +const char * +pcidb_subvd_name(pcidb_subvd_t *s) +{ + return (s->ps_name); +} + +uint16_t +pcidb_subvd_svid(pcidb_subvd_t *s) +{ + return (s->ps_vid); +} + +uint16_t +pcidb_subvd_sdid(pcidb_subvd_t *s) +{ + return (s->ps_did); +} + +pcidb_device_t * +pcidb_subvd_device(pcidb_subvd_t *s) +{ + return (s->ps_dev); +} + +pcidb_vendor_t * +pcidb_subvd_vendor(pcidb_subvd_t *s) +{ + return (s->ps_vend); +} diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/common/pcidb.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/common/pcidb.h Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,84 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ + +/* + * This header file is private to illumos and should not be shipped. + */ + +#ifndef _PCIDB_H +#define _PCIDB_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCIDB_VERSION 1 + +typedef struct pcidb_hdl pcidb_hdl_t; +typedef struct pcidb_vendor pcidb_vendor_t; +typedef struct pcidb_device pcidb_device_t; +typedef struct pcidb_subvd pcidb_subvd_t; + +extern pcidb_hdl_t *pcidb_open(int); +extern void pcidb_close(pcidb_hdl_t *); + +extern pcidb_vendor_t *pcidb_lookup_vendor(pcidb_hdl_t *, uint16_t); +extern pcidb_vendor_t *pcidb_vendor_iter(pcidb_hdl_t *); +extern pcidb_vendor_t *pcidb_vendor_iter_next(pcidb_vendor_t *); + +extern const char *pcidb_vendor_name(pcidb_vendor_t *); +extern uint16_t pcidb_vendor_id(pcidb_vendor_t *); + +extern pcidb_device_t *pcidb_lookup_device(pcidb_hdl_t *, uint16_t, uint16_t); +extern pcidb_device_t *pcidb_lookup_device_by_vendor(pcidb_vendor_t *, + uint16_t); +extern pcidb_device_t *pcidb_device_iter(pcidb_vendor_t *); +extern pcidb_device_t *pcidb_device_iter_next(pcidb_device_t *); + +extern const char *pcidb_device_name(pcidb_device_t *); +extern uint16_t pcidb_device_id(pcidb_device_t *); +extern pcidb_vendor_t *pcidb_device_vendor(pcidb_device_t *); + +extern pcidb_subvd_t *pcidb_lookup_subvd(pcidb_hdl_t *, uint16_t, uint16_t, + uint16_t, uint16_t); +extern pcidb_subvd_t *pcidb_lookup_subvd_by_vendor(pcidb_vendor_t *, uint16_t, + uint16_t, uint16_t); +extern pcidb_subvd_t *pcidb_lookup_subvd_by_device(pcidb_device_t *, uint16_t, + uint16_t); +extern pcidb_subvd_t *pcidb_subvd_iter(pcidb_device_t *); +extern pcidb_subvd_t *pcidb_subvd_iter_next(pcidb_subvd_t *); + +extern const char *pcidb_subvd_name(pcidb_subvd_t *); +extern uint16_t pcidb_subvd_svid(pcidb_subvd_t *); +extern uint16_t pcidb_subvd_sdid(pcidb_subvd_t *); +extern pcidb_device_t *pcidb_subvd_device(pcidb_subvd_t *); +extern pcidb_vendor_t *pcidb_subvd_vendor(pcidb_subvd_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _PCIDB_H */ diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/i386/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/i386/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,28 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/sparc/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/sparc/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,28 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff -r 61e74b16a691 -r 779e63d911a5 usr/src/lib/libpcidb/sparcv9/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libpcidb/sparcv9/Makefile Tue Apr 02 17:25:01 2013 -0700 @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff -r 61e74b16a691 -r 779e63d911a5 usr/src/man/man1m/prtconf.1m --- a/usr/src/man/man1m/prtconf.1m Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/man/man1m/prtconf.1m Tue Apr 02 17:25:01 2013 -0700 @@ -1,9 +1,10 @@ '\" te .\" Copyright 1989 AT&T Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved +.\" Copyright 2012, Joyent, Inc. All Rights Reserved .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. .\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the .\" fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH PRTCONF 1M "Mar 13, 2009" +.TH PRTCONF 1M "Jan 11, 2013" .SH NAME prtconf \- print system configuration .SH SYNOPSIS @@ -67,7 +68,8 @@ .ad .RS 6n Display vendor ID and device ID for PCI and PCI Express devices, in addition to -the nodename. +the nodename. If the information is known, the vendor name and device name will +also be shown. .RE .sp diff -r 61e74b16a691 -r 779e63d911a5 usr/src/pkg/manifests/system-library.mf --- a/usr/src/pkg/manifests/system-library.mf Thu Apr 11 10:46:40 2013 -0700 +++ b/usr/src/pkg/manifests/system-library.mf Tue Apr 02 17:25:01 2013 -0700 @@ -347,6 +347,7 @@ file path=usr/lib/$(ARCH64)/libmtmalloc.so.1 file path=usr/lib/$(ARCH64)/libnls.so.1 file path=usr/lib/$(ARCH64)/libpanel.so.1 +file path=usr/lib/$(ARCH64)/libpcidb.so.1 file path=usr/lib/$(ARCH64)/libpkcs11.so.1 file path=usr/lib/$(ARCH64)/libproject.so.1 file path=usr/lib/$(ARCH64)/libraidcfg.so.1 @@ -419,6 +420,7 @@ file path=usr/lib/libmtmalloc.so.1 file path=usr/lib/libnls.so.1 file path=usr/lib/libpanel.so.1 +file path=usr/lib/libpcidb.so.1 file path=usr/lib/libpkcs11.so.1 file path=usr/lib/libproject.so.1 file path=usr/lib/libraidcfg.so.1