17687d0d8SRobert Mustacchi /*
27687d0d8SRobert Mustacchi * This file and its contents are supplied under the terms of the
37687d0d8SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
47687d0d8SRobert Mustacchi * You may only use this file in accordance with the terms of version
57687d0d8SRobert Mustacchi * 1.0 of the CDDL.
67687d0d8SRobert Mustacchi *
77687d0d8SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
87687d0d8SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
97687d0d8SRobert Mustacchi * http://www.illumos.org/license/CDDL.
107687d0d8SRobert Mustacchi */
117687d0d8SRobert Mustacchi
127687d0d8SRobert Mustacchi /*
13bd97c7ceSRobert Mustacchi * Copyright 2023 Oxide Computer Company
147687d0d8SRobert Mustacchi */
157687d0d8SRobert Mustacchi
167687d0d8SRobert Mustacchi #include <err.h>
177687d0d8SRobert Mustacchi #include <stdio.h>
187687d0d8SRobert Mustacchi #include <unistd.h>
197687d0d8SRobert Mustacchi #include <ofmt.h>
207687d0d8SRobert Mustacchi #include <strings.h>
217687d0d8SRobert Mustacchi #include <sys/pci.h>
227687d0d8SRobert Mustacchi
237687d0d8SRobert Mustacchi #include "pcieadm.h"
247687d0d8SRobert Mustacchi
257687d0d8SRobert Mustacchi typedef struct pcieadm_show_devs {
267687d0d8SRobert Mustacchi pcieadm_t *psd_pia;
277687d0d8SRobert Mustacchi ofmt_handle_t psd_ofmt;
287687d0d8SRobert Mustacchi boolean_t psd_funcs;
297687d0d8SRobert Mustacchi int psd_nfilts;
307687d0d8SRobert Mustacchi char **psd_filts;
3192f11af9SRobert Mustacchi boolean_t *psd_used;
327687d0d8SRobert Mustacchi uint_t psd_nprint;
337687d0d8SRobert Mustacchi } pcieadm_show_devs_t;
347687d0d8SRobert Mustacchi
357687d0d8SRobert Mustacchi typedef enum pcieadm_show_devs_otype {
367687d0d8SRobert Mustacchi PCIEADM_SDO_VID,
377687d0d8SRobert Mustacchi PCIEADM_SDO_DID,
38bd97c7ceSRobert Mustacchi PCIEADM_SDO_REV,
39bd97c7ceSRobert Mustacchi PCIEADM_SDO_SUBVID,
40bd97c7ceSRobert Mustacchi PCIEADM_SDO_SUBSYS,
417687d0d8SRobert Mustacchi PCIEADM_SDO_BDF,
427687d0d8SRobert Mustacchi PCIEADM_SDO_BDF_BUS,
437687d0d8SRobert Mustacchi PCIEADM_SDO_BDF_DEV,
447687d0d8SRobert Mustacchi PCIEADM_SDO_BDF_FUNC,
457687d0d8SRobert Mustacchi PCIEADM_SDO_DRIVER,
4676c08ae9SRobert Mustacchi PCIEADM_SDO_INSTANCE,
4776c08ae9SRobert Mustacchi PCIEADM_SDO_INSTNUM,
487687d0d8SRobert Mustacchi PCIEADM_SDO_TYPE,
497687d0d8SRobert Mustacchi PCIEADM_SDO_VENDOR,
507687d0d8SRobert Mustacchi PCIEADM_SDO_DEVICE,
51bd97c7ceSRobert Mustacchi PCIEADM_SDO_SUBVENDOR,
52bd97c7ceSRobert Mustacchi PCIEADM_SDO_SUBSYSTEM,
537687d0d8SRobert Mustacchi PCIEADM_SDO_PATH,
547687d0d8SRobert Mustacchi PCIEADM_SDO_MAXSPEED,
557687d0d8SRobert Mustacchi PCIEADM_SDO_MAXWIDTH,
567687d0d8SRobert Mustacchi PCIEADM_SDO_CURSPEED,
577687d0d8SRobert Mustacchi PCIEADM_SDO_CURWIDTH,
587687d0d8SRobert Mustacchi PCIEADM_SDO_SUPSPEEDS
597687d0d8SRobert Mustacchi } pcieadm_show_devs_otype_t;
607687d0d8SRobert Mustacchi
617687d0d8SRobert Mustacchi typedef struct pcieadm_show_devs_ofmt {
627687d0d8SRobert Mustacchi int psdo_vid;
637687d0d8SRobert Mustacchi int psdo_did;
64bd97c7ceSRobert Mustacchi int psdo_rev;
65bd97c7ceSRobert Mustacchi int psdo_subvid;
66bd97c7ceSRobert Mustacchi int psdo_subsys;
677687d0d8SRobert Mustacchi uint_t psdo_bus;
687687d0d8SRobert Mustacchi uint_t psdo_dev;
697687d0d8SRobert Mustacchi uint_t psdo_func;
707687d0d8SRobert Mustacchi const char *psdo_path;
717687d0d8SRobert Mustacchi const char *psdo_vendor;
727687d0d8SRobert Mustacchi const char *psdo_device;
73bd97c7ceSRobert Mustacchi const char *psdo_subvendor;
74bd97c7ceSRobert Mustacchi const char *psdo_subsystem;
757687d0d8SRobert Mustacchi const char *psdo_driver;
767687d0d8SRobert Mustacchi int psdo_instance;
777687d0d8SRobert Mustacchi int psdo_mwidth;
787687d0d8SRobert Mustacchi int psdo_cwidth;
797687d0d8SRobert Mustacchi int64_t psdo_mspeed;
807687d0d8SRobert Mustacchi int64_t psdo_cspeed;
817687d0d8SRobert Mustacchi int psdo_nspeeds;
827687d0d8SRobert Mustacchi int64_t *psdo_sspeeds;
837687d0d8SRobert Mustacchi } pcieadm_show_devs_ofmt_t;
847687d0d8SRobert Mustacchi
857687d0d8SRobert Mustacchi static uint_t
pcieadm_speed2gen(int64_t speed)867687d0d8SRobert Mustacchi pcieadm_speed2gen(int64_t speed)
877687d0d8SRobert Mustacchi {
887687d0d8SRobert Mustacchi if (speed == 2500000000LL) {
897687d0d8SRobert Mustacchi return (1);
907687d0d8SRobert Mustacchi } else if (speed == 5000000000LL) {
917687d0d8SRobert Mustacchi return (2);
927687d0d8SRobert Mustacchi } else if (speed == 8000000000LL) {
937687d0d8SRobert Mustacchi return (3);
947687d0d8SRobert Mustacchi } else if (speed == 16000000000LL) {
957687d0d8SRobert Mustacchi return (4);
967687d0d8SRobert Mustacchi } else if (speed == 32000000000LL) {
977687d0d8SRobert Mustacchi return (5);
987687d0d8SRobert Mustacchi } else {
997687d0d8SRobert Mustacchi return (0);
1007687d0d8SRobert Mustacchi }
1017687d0d8SRobert Mustacchi }
1027687d0d8SRobert Mustacchi
1037687d0d8SRobert Mustacchi static const char *
pcieadm_speed2str(int64_t speed)1047687d0d8SRobert Mustacchi pcieadm_speed2str(int64_t speed)
1057687d0d8SRobert Mustacchi {
1067687d0d8SRobert Mustacchi if (speed == 2500000000LL) {
1077687d0d8SRobert Mustacchi return ("2.5");
1087687d0d8SRobert Mustacchi } else if (speed == 5000000000LL) {
1097687d0d8SRobert Mustacchi return ("5.0");
1107687d0d8SRobert Mustacchi } else if (speed == 8000000000LL) {
1117687d0d8SRobert Mustacchi return ("8.0");
1127687d0d8SRobert Mustacchi } else if (speed == 16000000000LL) {
1137687d0d8SRobert Mustacchi return ("16.0");
1147687d0d8SRobert Mustacchi } else if (speed == 32000000000LL) {
1157687d0d8SRobert Mustacchi return ("32.0");
1167687d0d8SRobert Mustacchi } else {
1177687d0d8SRobert Mustacchi return (NULL);
1187687d0d8SRobert Mustacchi }
1197687d0d8SRobert Mustacchi }
1207687d0d8SRobert Mustacchi
1217687d0d8SRobert Mustacchi static boolean_t
pcieadm_show_devs_ofmt_cb(ofmt_arg_t * ofarg,char * buf,uint_t buflen)1227687d0d8SRobert Mustacchi pcieadm_show_devs_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t buflen)
1237687d0d8SRobert Mustacchi {
1247687d0d8SRobert Mustacchi const char *str;
1257687d0d8SRobert Mustacchi pcieadm_show_devs_ofmt_t *psdo = ofarg->ofmt_cbarg;
1267687d0d8SRobert Mustacchi boolean_t first = B_TRUE;
1277687d0d8SRobert Mustacchi
1287687d0d8SRobert Mustacchi switch (ofarg->ofmt_id) {
1297687d0d8SRobert Mustacchi case PCIEADM_SDO_BDF:
1307687d0d8SRobert Mustacchi if (snprintf(buf, buflen, "%x/%x/%x", psdo->psdo_bus,
1317687d0d8SRobert Mustacchi psdo->psdo_dev, psdo->psdo_func) >= buflen) {
1327687d0d8SRobert Mustacchi return (B_FALSE);
1337687d0d8SRobert Mustacchi }
1347687d0d8SRobert Mustacchi break;
1357687d0d8SRobert Mustacchi case PCIEADM_SDO_BDF_BUS:
1367687d0d8SRobert Mustacchi if (snprintf(buf, buflen, "%x", psdo->psdo_bus) >= buflen) {
1377687d0d8SRobert Mustacchi return (B_FALSE);
1387687d0d8SRobert Mustacchi }
1397687d0d8SRobert Mustacchi break;
1407687d0d8SRobert Mustacchi case PCIEADM_SDO_BDF_DEV:
1417687d0d8SRobert Mustacchi if (snprintf(buf, buflen, "%x", psdo->psdo_dev) >= buflen) {
1427687d0d8SRobert Mustacchi return (B_FALSE);
1437687d0d8SRobert Mustacchi }
1447687d0d8SRobert Mustacchi break;
1457687d0d8SRobert Mustacchi case PCIEADM_SDO_BDF_FUNC:
1467687d0d8SRobert Mustacchi if (snprintf(buf, buflen, "%x", psdo->psdo_func) >= buflen) {
1477687d0d8SRobert Mustacchi return (B_FALSE);
1487687d0d8SRobert Mustacchi }
1497687d0d8SRobert Mustacchi break;
15076c08ae9SRobert Mustacchi case PCIEADM_SDO_INSTANCE:
1517687d0d8SRobert Mustacchi if (psdo->psdo_driver == NULL || psdo->psdo_instance == -1) {
1527687d0d8SRobert Mustacchi (void) snprintf(buf, buflen, "--");
1537687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "%s%d", psdo->psdo_driver,
1547687d0d8SRobert Mustacchi psdo->psdo_instance) >= buflen) {
1557687d0d8SRobert Mustacchi return (B_FALSE);
1567687d0d8SRobert Mustacchi }
1577687d0d8SRobert Mustacchi break;
15876c08ae9SRobert Mustacchi case PCIEADM_SDO_DRIVER:
15976c08ae9SRobert Mustacchi if (psdo->psdo_driver == NULL) {
16076c08ae9SRobert Mustacchi (void) snprintf(buf, buflen, "--");
16176c08ae9SRobert Mustacchi } else if (strlcpy(buf, psdo->psdo_driver, buflen) >= buflen) {
16276c08ae9SRobert Mustacchi return (B_FALSE);
16376c08ae9SRobert Mustacchi }
16476c08ae9SRobert Mustacchi break;
16576c08ae9SRobert Mustacchi case PCIEADM_SDO_INSTNUM:
16676c08ae9SRobert Mustacchi if (psdo->psdo_instance == -1) {
16776c08ae9SRobert Mustacchi (void) snprintf(buf, buflen, "--");
16876c08ae9SRobert Mustacchi } else if (snprintf(buf, buflen, "%d", psdo->psdo_instance) >=
16976c08ae9SRobert Mustacchi buflen) {
17076c08ae9SRobert Mustacchi return (B_FALSE);
17176c08ae9SRobert Mustacchi }
17276c08ae9SRobert Mustacchi break;
1737687d0d8SRobert Mustacchi case PCIEADM_SDO_PATH:
1747687d0d8SRobert Mustacchi if (strlcat(buf, psdo->psdo_path, buflen) >= buflen) {
1757687d0d8SRobert Mustacchi return (B_TRUE);
1767687d0d8SRobert Mustacchi }
1777687d0d8SRobert Mustacchi break;
1787687d0d8SRobert Mustacchi case PCIEADM_SDO_VID:
1797687d0d8SRobert Mustacchi if (psdo->psdo_vid == -1) {
1807687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
1817687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "%x", psdo->psdo_vid) >=
1827687d0d8SRobert Mustacchi buflen) {
1837687d0d8SRobert Mustacchi return (B_FALSE);
1847687d0d8SRobert Mustacchi }
1857687d0d8SRobert Mustacchi break;
1867687d0d8SRobert Mustacchi case PCIEADM_SDO_DID:
1877687d0d8SRobert Mustacchi if (psdo->psdo_did == -1) {
1887687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
1897687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "%x", psdo->psdo_did) >=
1907687d0d8SRobert Mustacchi buflen) {
1917687d0d8SRobert Mustacchi return (B_FALSE);
1927687d0d8SRobert Mustacchi }
1937687d0d8SRobert Mustacchi break;
194bd97c7ceSRobert Mustacchi case PCIEADM_SDO_REV:
195bd97c7ceSRobert Mustacchi if (psdo->psdo_rev == -1) {
196bd97c7ceSRobert Mustacchi (void) strlcat(buf, "--", buflen);
197bd97c7ceSRobert Mustacchi } else if (snprintf(buf, buflen, "%x", psdo->psdo_rev) >=
198bd97c7ceSRobert Mustacchi buflen) {
199bd97c7ceSRobert Mustacchi return (B_FALSE);
200bd97c7ceSRobert Mustacchi }
201bd97c7ceSRobert Mustacchi break;
202bd97c7ceSRobert Mustacchi case PCIEADM_SDO_SUBVID:
203bd97c7ceSRobert Mustacchi if (psdo->psdo_subvid == -1) {
204bd97c7ceSRobert Mustacchi (void) strlcat(buf, "--", buflen);
205bd97c7ceSRobert Mustacchi } else if (snprintf(buf, buflen, "%x", psdo->psdo_subvid) >=
206bd97c7ceSRobert Mustacchi buflen) {
207bd97c7ceSRobert Mustacchi return (B_FALSE);
208bd97c7ceSRobert Mustacchi }
209bd97c7ceSRobert Mustacchi break;
210bd97c7ceSRobert Mustacchi case PCIEADM_SDO_SUBSYS:
211bd97c7ceSRobert Mustacchi if (psdo->psdo_subsys == -1) {
212bd97c7ceSRobert Mustacchi (void) strlcat(buf, "--", buflen);
213bd97c7ceSRobert Mustacchi } else if (snprintf(buf, buflen, "%x", psdo->psdo_subsys) >=
214bd97c7ceSRobert Mustacchi buflen) {
215bd97c7ceSRobert Mustacchi return (B_FALSE);
216bd97c7ceSRobert Mustacchi }
217bd97c7ceSRobert Mustacchi break;
2187687d0d8SRobert Mustacchi case PCIEADM_SDO_VENDOR:
2197687d0d8SRobert Mustacchi if (strlcat(buf, psdo->psdo_vendor, buflen) >= buflen) {
2207687d0d8SRobert Mustacchi return (B_FALSE);
2217687d0d8SRobert Mustacchi }
2227687d0d8SRobert Mustacchi break;
2237687d0d8SRobert Mustacchi case PCIEADM_SDO_DEVICE:
2247687d0d8SRobert Mustacchi if (strlcat(buf, psdo->psdo_device, buflen) >= buflen) {
2257687d0d8SRobert Mustacchi return (B_FALSE);
2267687d0d8SRobert Mustacchi }
2277687d0d8SRobert Mustacchi break;
228bd97c7ceSRobert Mustacchi case PCIEADM_SDO_SUBVENDOR:
229bd97c7ceSRobert Mustacchi if (strlcat(buf, psdo->psdo_subvendor, buflen) >= buflen) {
230bd97c7ceSRobert Mustacchi return (B_FALSE);
231bd97c7ceSRobert Mustacchi }
232bd97c7ceSRobert Mustacchi break;
233bd97c7ceSRobert Mustacchi case PCIEADM_SDO_SUBSYSTEM:
234bd97c7ceSRobert Mustacchi if (strlcat(buf, psdo->psdo_subsystem, buflen) >= buflen) {
235bd97c7ceSRobert Mustacchi return (B_FALSE);
236bd97c7ceSRobert Mustacchi }
237bd97c7ceSRobert Mustacchi break;
2387687d0d8SRobert Mustacchi case PCIEADM_SDO_MAXWIDTH:
2397687d0d8SRobert Mustacchi if (psdo->psdo_mwidth <= 0) {
2407687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
2417687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "x%u", psdo->psdo_mwidth) >=
2427687d0d8SRobert Mustacchi buflen) {
2437687d0d8SRobert Mustacchi return (B_FALSE);
2447687d0d8SRobert Mustacchi }
2457687d0d8SRobert Mustacchi break;
2467687d0d8SRobert Mustacchi case PCIEADM_SDO_CURWIDTH:
2477687d0d8SRobert Mustacchi if (psdo->psdo_cwidth <= 0) {
2487687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
2497687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "x%u", psdo->psdo_cwidth) >=
2507687d0d8SRobert Mustacchi buflen) {
2517687d0d8SRobert Mustacchi return (B_FALSE);
2527687d0d8SRobert Mustacchi }
2537687d0d8SRobert Mustacchi break;
2547687d0d8SRobert Mustacchi case PCIEADM_SDO_MAXSPEED:
2557687d0d8SRobert Mustacchi str = pcieadm_speed2str(psdo->psdo_mspeed);
2567687d0d8SRobert Mustacchi if (str == NULL) {
2577687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
2587687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "%s GT/s", str) >= buflen) {
2597687d0d8SRobert Mustacchi return (B_FALSE);
2607687d0d8SRobert Mustacchi }
2617687d0d8SRobert Mustacchi break;
2627687d0d8SRobert Mustacchi case PCIEADM_SDO_CURSPEED:
2637687d0d8SRobert Mustacchi str = pcieadm_speed2str(psdo->psdo_cspeed);
2647687d0d8SRobert Mustacchi if (str == NULL) {
2657687d0d8SRobert Mustacchi (void) strlcat(buf, "--", buflen);
2667687d0d8SRobert Mustacchi } else if (snprintf(buf, buflen, "%s GT/s", str) >= buflen) {
2677687d0d8SRobert Mustacchi return (B_FALSE);
2687687d0d8SRobert Mustacchi }
2697687d0d8SRobert Mustacchi break;
2707687d0d8SRobert Mustacchi case PCIEADM_SDO_SUPSPEEDS:
2717687d0d8SRobert Mustacchi buf[0] = 0;
2727687d0d8SRobert Mustacchi for (int i = 0; i < psdo->psdo_nspeeds; i++) {
2737687d0d8SRobert Mustacchi const char *str;
2747687d0d8SRobert Mustacchi
2757687d0d8SRobert Mustacchi str = pcieadm_speed2str(psdo->psdo_sspeeds[i]);
2767687d0d8SRobert Mustacchi if (str == NULL) {
2777687d0d8SRobert Mustacchi continue;
2787687d0d8SRobert Mustacchi }
2797687d0d8SRobert Mustacchi
2807687d0d8SRobert Mustacchi if (!first) {
2817687d0d8SRobert Mustacchi if (strlcat(buf, ",", buflen) >= buflen) {
2827687d0d8SRobert Mustacchi return (B_FALSE);
2837687d0d8SRobert Mustacchi }
2847687d0d8SRobert Mustacchi }
2857687d0d8SRobert Mustacchi first = B_FALSE;
2867687d0d8SRobert Mustacchi
2877687d0d8SRobert Mustacchi if (strlcat(buf, str, buflen) >= buflen) {
2887687d0d8SRobert Mustacchi return (B_FALSE);
2897687d0d8SRobert Mustacchi }
2907687d0d8SRobert Mustacchi }
2917687d0d8SRobert Mustacchi break;
2927687d0d8SRobert Mustacchi case PCIEADM_SDO_TYPE:
293a68304ebSRobert Mustacchi if (pcieadm_speed2gen(psdo->psdo_cspeed) == 0 ||
2947687d0d8SRobert Mustacchi psdo->psdo_mwidth == -1) {
2957687d0d8SRobert Mustacchi if (strlcat(buf, "PCI", buflen) >= buflen) {
2967687d0d8SRobert Mustacchi return (B_FALSE);
2977687d0d8SRobert Mustacchi }
2987687d0d8SRobert Mustacchi } else {
2997687d0d8SRobert Mustacchi if (snprintf(buf, buflen, "PCIe Gen %ux%u",
300a68304ebSRobert Mustacchi pcieadm_speed2gen(psdo->psdo_cspeed),
301a68304ebSRobert Mustacchi psdo->psdo_cwidth) >= buflen) {
3027687d0d8SRobert Mustacchi return (B_FALSE);
3037687d0d8SRobert Mustacchi }
3047687d0d8SRobert Mustacchi }
3057687d0d8SRobert Mustacchi break;
3067687d0d8SRobert Mustacchi default:
3077687d0d8SRobert Mustacchi abort();
3087687d0d8SRobert Mustacchi }
3097687d0d8SRobert Mustacchi return (B_TRUE);
3107687d0d8SRobert Mustacchi }
3117687d0d8SRobert Mustacchi
31276c08ae9SRobert Mustacchi static const char *pcieadm_show_dev_fields = "bdf,type,instance,device";
3137687d0d8SRobert Mustacchi static const char *pcieadm_show_dev_speeds =
3147687d0d8SRobert Mustacchi "bdf,driver,maxspeed,curspeed,maxwidth,curwidth,supspeeds";
3157687d0d8SRobert Mustacchi static const ofmt_field_t pcieadm_show_dev_ofmt[] = {
3167687d0d8SRobert Mustacchi { "VID", 6, PCIEADM_SDO_VID, pcieadm_show_devs_ofmt_cb },
3177687d0d8SRobert Mustacchi { "DID", 6, PCIEADM_SDO_DID, pcieadm_show_devs_ofmt_cb },
318bd97c7ceSRobert Mustacchi { "REV", 6, PCIEADM_SDO_REV, pcieadm_show_devs_ofmt_cb },
319bd97c7ceSRobert Mustacchi { "SUBVID", 6, PCIEADM_SDO_SUBVID, pcieadm_show_devs_ofmt_cb },
320bd97c7ceSRobert Mustacchi { "SUBSYS", 6, PCIEADM_SDO_SUBSYS, pcieadm_show_devs_ofmt_cb },
3217687d0d8SRobert Mustacchi { "BDF", 8, PCIEADM_SDO_BDF, pcieadm_show_devs_ofmt_cb },
3227687d0d8SRobert Mustacchi { "DRIVER", 15, PCIEADM_SDO_DRIVER, pcieadm_show_devs_ofmt_cb },
32376c08ae9SRobert Mustacchi { "INSTANCE", 15, PCIEADM_SDO_INSTANCE, pcieadm_show_devs_ofmt_cb },
32476c08ae9SRobert Mustacchi { "INSTNUM", 8, PCIEADM_SDO_INSTNUM, pcieadm_show_devs_ofmt_cb },
3257687d0d8SRobert Mustacchi { "TYPE", 15, PCIEADM_SDO_TYPE, pcieadm_show_devs_ofmt_cb },
3267687d0d8SRobert Mustacchi { "VENDOR", 30, PCIEADM_SDO_VENDOR, pcieadm_show_devs_ofmt_cb },
3277687d0d8SRobert Mustacchi { "DEVICE", 30, PCIEADM_SDO_DEVICE, pcieadm_show_devs_ofmt_cb },
328bd97c7ceSRobert Mustacchi { "SUBVENDOR", 30, PCIEADM_SDO_SUBVENDOR, pcieadm_show_devs_ofmt_cb },
329bd97c7ceSRobert Mustacchi { "SUBSYSTEM", 30, PCIEADM_SDO_SUBSYSTEM, pcieadm_show_devs_ofmt_cb },
3307687d0d8SRobert Mustacchi { "PATH", 30, PCIEADM_SDO_PATH, pcieadm_show_devs_ofmt_cb },
3317687d0d8SRobert Mustacchi { "BUS", 4, PCIEADM_SDO_BDF_BUS, pcieadm_show_devs_ofmt_cb },
3327687d0d8SRobert Mustacchi { "DEV", 4, PCIEADM_SDO_BDF_DEV, pcieadm_show_devs_ofmt_cb },
3337687d0d8SRobert Mustacchi { "FUNC", 4, PCIEADM_SDO_BDF_FUNC, pcieadm_show_devs_ofmt_cb },
3347687d0d8SRobert Mustacchi { "MAXSPEED", 10, PCIEADM_SDO_MAXSPEED, pcieadm_show_devs_ofmt_cb },
3357687d0d8SRobert Mustacchi { "MAXWIDTH", 10, PCIEADM_SDO_MAXWIDTH, pcieadm_show_devs_ofmt_cb },
3367687d0d8SRobert Mustacchi { "CURSPEED", 10, PCIEADM_SDO_CURSPEED, pcieadm_show_devs_ofmt_cb },
3377687d0d8SRobert Mustacchi { "CURWIDTH", 10, PCIEADM_SDO_CURWIDTH, pcieadm_show_devs_ofmt_cb },
3387687d0d8SRobert Mustacchi { "SUPSPEEDS", 20, PCIEADM_SDO_SUPSPEEDS, pcieadm_show_devs_ofmt_cb },
3397687d0d8SRobert Mustacchi { NULL, 0, 0, NULL }
3407687d0d8SRobert Mustacchi };
3417687d0d8SRobert Mustacchi
3427687d0d8SRobert Mustacchi static boolean_t
pcieadm_show_devs_match(pcieadm_show_devs_t * psd,pcieadm_show_devs_ofmt_t * psdo)3437687d0d8SRobert Mustacchi pcieadm_show_devs_match(pcieadm_show_devs_t *psd,
3447687d0d8SRobert Mustacchi pcieadm_show_devs_ofmt_t *psdo)
3457687d0d8SRobert Mustacchi {
3467687d0d8SRobert Mustacchi char dinst[128], bdf[128];
3477687d0d8SRobert Mustacchi
3487687d0d8SRobert Mustacchi if (psd->psd_nfilts == 0) {
3497687d0d8SRobert Mustacchi return (B_TRUE);
3507687d0d8SRobert Mustacchi }
3517687d0d8SRobert Mustacchi
3527687d0d8SRobert Mustacchi if (psdo->psdo_driver != NULL && psdo->psdo_instance != -1) {
3537687d0d8SRobert Mustacchi (void) snprintf(dinst, sizeof (dinst), "%s%d",
3547687d0d8SRobert Mustacchi psdo->psdo_driver, psdo->psdo_instance);
3557687d0d8SRobert Mustacchi }
3567687d0d8SRobert Mustacchi (void) snprintf(bdf, sizeof (bdf), "%x/%x/%x", psdo->psdo_bus,
3577687d0d8SRobert Mustacchi psdo->psdo_dev, psdo->psdo_func);
3587687d0d8SRobert Mustacchi
3597687d0d8SRobert Mustacchi for (uint_t i = 0; i < psd->psd_nfilts; i++) {
3607687d0d8SRobert Mustacchi const char *filt = psd->psd_filts[i];
3617687d0d8SRobert Mustacchi
3627687d0d8SRobert Mustacchi if (strcmp(filt, psdo->psdo_path) == 0) {
36392f11af9SRobert Mustacchi psd->psd_used[i] = B_TRUE;
3647687d0d8SRobert Mustacchi return (B_TRUE);
3657687d0d8SRobert Mustacchi }
3667687d0d8SRobert Mustacchi
3677687d0d8SRobert Mustacchi if (strcmp(filt, bdf) == 0) {
36892f11af9SRobert Mustacchi psd->psd_used[i] = B_TRUE;
3697687d0d8SRobert Mustacchi return (B_TRUE);
3707687d0d8SRobert Mustacchi }
3717687d0d8SRobert Mustacchi
3727687d0d8SRobert Mustacchi if (psdo->psdo_driver != NULL &&
3737687d0d8SRobert Mustacchi strcmp(filt, psdo->psdo_driver) == 0) {
37492f11af9SRobert Mustacchi psd->psd_used[i] = B_TRUE;
3757687d0d8SRobert Mustacchi return (B_TRUE);
3767687d0d8SRobert Mustacchi }
3777687d0d8SRobert Mustacchi
3787687d0d8SRobert Mustacchi if (psdo->psdo_driver != NULL && psdo->psdo_instance != -1 &&
3797687d0d8SRobert Mustacchi strcmp(filt, dinst) == 0) {
38092f11af9SRobert Mustacchi psd->psd_used[i] = B_TRUE;
3817687d0d8SRobert Mustacchi return (B_TRUE);
3827687d0d8SRobert Mustacchi }
3837687d0d8SRobert Mustacchi
3847687d0d8SRobert Mustacchi if (strncmp("/devices", filt, strlen("/devices")) == 0) {
3857687d0d8SRobert Mustacchi filt += strlen("/devices");
3867687d0d8SRobert Mustacchi }
3877687d0d8SRobert Mustacchi
3887687d0d8SRobert Mustacchi if (strcmp(filt, psdo->psdo_path) == 0) {
38992f11af9SRobert Mustacchi psd->psd_used[i] = B_TRUE;
3907687d0d8SRobert Mustacchi return (B_TRUE);
3917687d0d8SRobert Mustacchi }
3927687d0d8SRobert Mustacchi }
3937687d0d8SRobert Mustacchi return (B_FALSE);
3947687d0d8SRobert Mustacchi }
3957687d0d8SRobert Mustacchi
3967687d0d8SRobert Mustacchi static int
pcieadm_show_devs_walk_cb(di_node_t node,void * arg)3977687d0d8SRobert Mustacchi pcieadm_show_devs_walk_cb(di_node_t node, void *arg)
3987687d0d8SRobert Mustacchi {
399bd97c7ceSRobert Mustacchi int nprop, *regs = NULL, *did, *vid, *mwidth, *cwidth, *rev;
400bd97c7ceSRobert Mustacchi int *subvid, *subsys;
4017687d0d8SRobert Mustacchi int64_t *mspeed, *cspeed, *sspeeds;
4027687d0d8SRobert Mustacchi char *path = NULL;
4037687d0d8SRobert Mustacchi pcieadm_show_devs_t *psd = arg;
4047687d0d8SRobert Mustacchi int ret = DI_WALK_CONTINUE;
405bd97c7ceSRobert Mustacchi char venstr[64], devstr[64], subvenstr[64], subsysstr[64];
4067687d0d8SRobert Mustacchi pcieadm_show_devs_ofmt_t oarg;
4077687d0d8SRobert Mustacchi pcidb_hdl_t *pcidb = psd->psd_pia->pia_pcidb;
4087687d0d8SRobert Mustacchi
4097687d0d8SRobert Mustacchi bzero(&oarg, sizeof (oarg));
4107687d0d8SRobert Mustacchi
4117687d0d8SRobert Mustacchi path = di_devfs_path(node);
4127687d0d8SRobert Mustacchi if (path == NULL) {
4137687d0d8SRobert Mustacchi err(EXIT_FAILURE, "failed to construct devfs path for node: "
414*6b1325cfSRobert Mustacchi "%s", di_node_name(node));
4157687d0d8SRobert Mustacchi }
4167687d0d8SRobert Mustacchi
4177687d0d8SRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", ®s);
4187687d0d8SRobert Mustacchi if (nprop <= 0) {
4197687d0d8SRobert Mustacchi errx(EXIT_FAILURE, "failed to lookup regs array for %s",
4207687d0d8SRobert Mustacchi path);
4217687d0d8SRobert Mustacchi }
4227687d0d8SRobert Mustacchi
4237687d0d8SRobert Mustacchi oarg.psdo_path = path;
4247687d0d8SRobert Mustacchi oarg.psdo_bus = PCI_REG_BUS_G(regs[0]);
4257687d0d8SRobert Mustacchi oarg.psdo_dev = PCI_REG_DEV_G(regs[0]);
4267687d0d8SRobert Mustacchi oarg.psdo_func = PCI_REG_FUNC_G(regs[0]);
4277687d0d8SRobert Mustacchi
4287687d0d8SRobert Mustacchi if (oarg.psdo_func != 0 && !psd->psd_funcs) {
4297687d0d8SRobert Mustacchi goto done;
4307687d0d8SRobert Mustacchi }
4317687d0d8SRobert Mustacchi
4327687d0d8SRobert Mustacchi oarg.psdo_driver = di_driver_name(node);
4337687d0d8SRobert Mustacchi oarg.psdo_instance = di_instance(node);
4347687d0d8SRobert Mustacchi
4357687d0d8SRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &did);
4367687d0d8SRobert Mustacchi if (nprop != 1) {
4377687d0d8SRobert Mustacchi oarg.psdo_did = -1;
4387687d0d8SRobert Mustacchi } else {
4397687d0d8SRobert Mustacchi oarg.psdo_did = (uint16_t)*did;
4407687d0d8SRobert Mustacchi }
4417687d0d8SRobert Mustacchi
4427687d0d8SRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vid);
4437687d0d8SRobert Mustacchi if (nprop != 1) {
4447687d0d8SRobert Mustacchi oarg.psdo_vid = -1;
4457687d0d8SRobert Mustacchi } else {
4467687d0d8SRobert Mustacchi oarg.psdo_vid = (uint16_t)*vid;
4477687d0d8SRobert Mustacchi }
4487687d0d8SRobert Mustacchi
449bd97c7ceSRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "revision-id", &rev);
450bd97c7ceSRobert Mustacchi if (nprop != 1) {
451bd97c7ceSRobert Mustacchi oarg.psdo_rev = -1;
452bd97c7ceSRobert Mustacchi } else {
453bd97c7ceSRobert Mustacchi oarg.psdo_rev = (uint16_t)*rev;
454bd97c7ceSRobert Mustacchi }
455bd97c7ceSRobert Mustacchi
456bd97c7ceSRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "subsystem-vendor-id",
457bd97c7ceSRobert Mustacchi &subvid);
458bd97c7ceSRobert Mustacchi if (nprop != 1) {
459bd97c7ceSRobert Mustacchi oarg.psdo_subvid = -1;
460bd97c7ceSRobert Mustacchi } else {
461bd97c7ceSRobert Mustacchi oarg.psdo_subvid = (uint16_t)*subvid;
462bd97c7ceSRobert Mustacchi }
463bd97c7ceSRobert Mustacchi
464bd97c7ceSRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "subsystem-id",
465bd97c7ceSRobert Mustacchi &subsys);
466bd97c7ceSRobert Mustacchi if (nprop != 1) {
467bd97c7ceSRobert Mustacchi oarg.psdo_subsys = -1;
468bd97c7ceSRobert Mustacchi } else {
469bd97c7ceSRobert Mustacchi oarg.psdo_subsys = (uint16_t)*subsys;
470bd97c7ceSRobert Mustacchi }
471bd97c7ceSRobert Mustacchi
4727687d0d8SRobert Mustacchi oarg.psdo_vendor = "--";
4737687d0d8SRobert Mustacchi if (oarg.psdo_vid != -1) {
4747687d0d8SRobert Mustacchi pcidb_vendor_t *vend = pcidb_lookup_vendor(pcidb,
4757687d0d8SRobert Mustacchi oarg.psdo_vid);
4767687d0d8SRobert Mustacchi if (vend != NULL) {
4777687d0d8SRobert Mustacchi oarg.psdo_vendor = pcidb_vendor_name(vend);
478bc729d49SRobert Mustacchi } else {
479bc729d49SRobert Mustacchi (void) snprintf(venstr, sizeof (venstr),
480bc729d49SRobert Mustacchi "Unknown vendor: 0x%x", oarg.psdo_vid);
481bc729d49SRobert Mustacchi oarg.psdo_vendor = venstr;
4827687d0d8SRobert Mustacchi }
4837687d0d8SRobert Mustacchi }
4847687d0d8SRobert Mustacchi
4857687d0d8SRobert Mustacchi oarg.psdo_device = "--";
4867687d0d8SRobert Mustacchi if (oarg.psdo_vid != -1 && oarg.psdo_did != -1) {
4877687d0d8SRobert Mustacchi pcidb_device_t *dev = pcidb_lookup_device(pcidb,
4887687d0d8SRobert Mustacchi oarg.psdo_vid, oarg.psdo_did);
4897687d0d8SRobert Mustacchi if (dev != NULL) {
4907687d0d8SRobert Mustacchi oarg.psdo_device = pcidb_device_name(dev);
491bc729d49SRobert Mustacchi } else {
492bc729d49SRobert Mustacchi (void) snprintf(devstr, sizeof (devstr),
493bc729d49SRobert Mustacchi "Unknown device: 0x%x", oarg.psdo_did);
494bc729d49SRobert Mustacchi oarg.psdo_device = devstr;
4957687d0d8SRobert Mustacchi }
4967687d0d8SRobert Mustacchi }
4977687d0d8SRobert Mustacchi
498bd97c7ceSRobert Mustacchi /*
499bd97c7ceSRobert Mustacchi * The pci.ids database organizes subsystems under devices. We look at
500bd97c7ceSRobert Mustacchi * the subsystem vendor separately because even if the device or other
501bd97c7ceSRobert Mustacchi * information is not known, we may still be able to figure out what it
502bd97c7ceSRobert Mustacchi * is.
503bd97c7ceSRobert Mustacchi */
504bd97c7ceSRobert Mustacchi oarg.psdo_subvendor = "--";
505bd97c7ceSRobert Mustacchi oarg.psdo_subsystem = "--";
506bd97c7ceSRobert Mustacchi if (oarg.psdo_subvid != -1) {
507bd97c7ceSRobert Mustacchi pcidb_vendor_t *vend = pcidb_lookup_vendor(pcidb,
508bd97c7ceSRobert Mustacchi oarg.psdo_subvid);
509bd97c7ceSRobert Mustacchi if (vend != NULL) {
510bd97c7ceSRobert Mustacchi oarg.psdo_subvendor = pcidb_vendor_name(vend);
511bd97c7ceSRobert Mustacchi } else {
512bd97c7ceSRobert Mustacchi (void) snprintf(subvenstr, sizeof (subvenstr),
513bd97c7ceSRobert Mustacchi "Unknown vendor: 0x%x", oarg.psdo_vid);
514bd97c7ceSRobert Mustacchi oarg.psdo_subvendor = subvenstr;
515bd97c7ceSRobert Mustacchi }
516bd97c7ceSRobert Mustacchi }
517bd97c7ceSRobert Mustacchi
518bd97c7ceSRobert Mustacchi if (oarg.psdo_vid != -1 && oarg.psdo_did != -1 &&
519bd97c7ceSRobert Mustacchi oarg.psdo_subvid != -1 && oarg.psdo_subsys != -1) {
520bd97c7ceSRobert Mustacchi pcidb_subvd_t *subvd = pcidb_lookup_subvd(pcidb, oarg.psdo_vid,
521bd97c7ceSRobert Mustacchi oarg.psdo_did, oarg.psdo_subvid, oarg.psdo_subsys);
522bd97c7ceSRobert Mustacchi if (subvd != NULL) {
523bd97c7ceSRobert Mustacchi oarg.psdo_subsystem = pcidb_subvd_name(subvd);
524bd97c7ceSRobert Mustacchi } else {
525bd97c7ceSRobert Mustacchi (void) snprintf(subsysstr, sizeof (subsysstr),
526bd97c7ceSRobert Mustacchi "Unknown subsystem: 0x%x", oarg.psdo_subsys);
527bd97c7ceSRobert Mustacchi oarg.psdo_subsystem = subsysstr;
528bd97c7ceSRobert Mustacchi }
529bd97c7ceSRobert Mustacchi }
530bd97c7ceSRobert Mustacchi
531bd97c7ceSRobert Mustacchi
5327687d0d8SRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
5337687d0d8SRobert Mustacchi "pcie-link-maximum-width", &mwidth);
5347687d0d8SRobert Mustacchi if (nprop != 1) {
5357687d0d8SRobert Mustacchi oarg.psdo_mwidth = -1;
5367687d0d8SRobert Mustacchi } else {
5377687d0d8SRobert Mustacchi oarg.psdo_mwidth = *mwidth;
5387687d0d8SRobert Mustacchi }
5397687d0d8SRobert Mustacchi
5407687d0d8SRobert Mustacchi nprop = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
5417687d0d8SRobert Mustacchi "pcie-link-current-width", &cwidth);
5427687d0d8SRobert Mustacchi if (nprop != 1) {
5437687d0d8SRobert Mustacchi oarg.psdo_cwidth = -1;
5447687d0d8SRobert Mustacchi } else {
5457687d0d8SRobert Mustacchi oarg.psdo_cwidth = *cwidth;
5467687d0d8SRobert Mustacchi }
5477687d0d8SRobert Mustacchi
5487687d0d8SRobert Mustacchi nprop = di_prop_lookup_int64(DDI_DEV_T_ANY, node,
5497687d0d8SRobert Mustacchi "pcie-link-maximum-speed", &mspeed);
5507687d0d8SRobert Mustacchi if (nprop != 1) {
5517687d0d8SRobert Mustacchi oarg.psdo_mspeed = -1;
5527687d0d8SRobert Mustacchi } else {
5537687d0d8SRobert Mustacchi oarg.psdo_mspeed = *mspeed;
5547687d0d8SRobert Mustacchi }
5557687d0d8SRobert Mustacchi
5567687d0d8SRobert Mustacchi nprop = di_prop_lookup_int64(DDI_DEV_T_ANY, node,
5577687d0d8SRobert Mustacchi "pcie-link-current-speed", &cspeed);
5587687d0d8SRobert Mustacchi if (nprop != 1) {
5597687d0d8SRobert Mustacchi oarg.psdo_cspeed = -1;
5607687d0d8SRobert Mustacchi } else {
5617687d0d8SRobert Mustacchi oarg.psdo_cspeed = *cspeed;
5627687d0d8SRobert Mustacchi }
5637687d0d8SRobert Mustacchi
5647687d0d8SRobert Mustacchi nprop = di_prop_lookup_int64(DDI_DEV_T_ANY, node,
5657687d0d8SRobert Mustacchi "pcie-link-supported-speeds", &sspeeds);
5667687d0d8SRobert Mustacchi if (nprop > 0) {
5677687d0d8SRobert Mustacchi oarg.psdo_nspeeds = nprop;
5687687d0d8SRobert Mustacchi oarg.psdo_sspeeds = sspeeds;
5697687d0d8SRobert Mustacchi } else {
5707687d0d8SRobert Mustacchi oarg.psdo_nspeeds = 0;
5717687d0d8SRobert Mustacchi oarg.psdo_sspeeds = NULL;
5727687d0d8SRobert Mustacchi }
5737687d0d8SRobert Mustacchi
5747687d0d8SRobert Mustacchi if (pcieadm_show_devs_match(psd, &oarg)) {
5757687d0d8SRobert Mustacchi ofmt_print(psd->psd_ofmt, &oarg);
5767687d0d8SRobert Mustacchi psd->psd_nprint++;
5777687d0d8SRobert Mustacchi }
5787687d0d8SRobert Mustacchi
5797687d0d8SRobert Mustacchi done:
5807687d0d8SRobert Mustacchi if (path != NULL) {
5817687d0d8SRobert Mustacchi di_devfs_path_free(path);
5827687d0d8SRobert Mustacchi }
5837687d0d8SRobert Mustacchi
5847687d0d8SRobert Mustacchi return (ret);
5857687d0d8SRobert Mustacchi }
5867687d0d8SRobert Mustacchi
5877687d0d8SRobert Mustacchi void
pcieadm_show_devs_usage(FILE * f)5887687d0d8SRobert Mustacchi pcieadm_show_devs_usage(FILE *f)
5897687d0d8SRobert Mustacchi {
5907687d0d8SRobert Mustacchi (void) fprintf(f, "\tshow-devs\t[-F] [-H] [-s | -o field[,...] [-p]] "
5917687d0d8SRobert Mustacchi "[filter...]\n");
5927687d0d8SRobert Mustacchi }
5937687d0d8SRobert Mustacchi
5947687d0d8SRobert Mustacchi static void
pcieadm_show_devs_help(const char * fmt,...)5957687d0d8SRobert Mustacchi pcieadm_show_devs_help(const char *fmt, ...)
5967687d0d8SRobert Mustacchi {
5977687d0d8SRobert Mustacchi if (fmt != NULL) {
5987687d0d8SRobert Mustacchi va_list ap;
5997687d0d8SRobert Mustacchi
6007687d0d8SRobert Mustacchi va_start(ap, fmt);
6017687d0d8SRobert Mustacchi vwarnx(fmt, ap);
6027687d0d8SRobert Mustacchi va_end(ap);
6037687d0d8SRobert Mustacchi (void) fprintf(stderr, "\n");
6047687d0d8SRobert Mustacchi }
6057687d0d8SRobert Mustacchi
6067687d0d8SRobert Mustacchi (void) fprintf(stderr, "Usage: %s show-devs [-F] [-H] [-s | -o "
6077687d0d8SRobert Mustacchi "field[,...] [-p]] [filter...]\n", pcieadm_progname);
6087687d0d8SRobert Mustacchi
6097687d0d8SRobert Mustacchi (void) fprintf(stderr, "\nList PCI devices and functions in the "
6107687d0d8SRobert Mustacchi "system. Each <filter> selects a set\nof devices to show and "
6117687d0d8SRobert Mustacchi "can be a driver name, instance, /devices path, or\nb/d/f.\n\n"
6127687d0d8SRobert Mustacchi "\t-F\t\tdo not display PCI functions\n"
6137687d0d8SRobert Mustacchi "\t-H\t\tomit the column header\n"
6147687d0d8SRobert Mustacchi "\t-o field\toutput fields to print\n"
6157687d0d8SRobert Mustacchi "\t-p\t\tparsable output (requires -o)\n"
61676c08ae9SRobert Mustacchi "\t-s\t\tlist speeds and widths\n\n"
61776c08ae9SRobert Mustacchi "The following fields are supported:\n"
61876c08ae9SRobert Mustacchi "\tvid\t\tthe PCI vendor ID in hex\n"
61976c08ae9SRobert Mustacchi "\tdid\t\tthe PCI device ID in hex\n"
620bd97c7ceSRobert Mustacchi "\trev\t\tthe PCI device revision in hex\n"
621bd97c7ceSRobert Mustacchi "\tsubvid\t\tthe PCI subsystem vendor ID in hex\n"
622bd97c7ceSRobert Mustacchi "\tsubsys\t\tthe PCI subsystem ID in hex\n"
62376c08ae9SRobert Mustacchi "\tvendor\t\tthe name of the PCI vendor\n"
62476c08ae9SRobert Mustacchi "\tdevice\t\tthe name of the PCI device\n"
625bd97c7ceSRobert Mustacchi "\tsubvendor\t\tthe name of the PCI subsystem vendor\n"
626bd97c7ceSRobert Mustacchi "\tsubsystem\t\tthe name of the PCI subsystem\n"
62776c08ae9SRobert Mustacchi "\tinstance\tthe name of this particular instance, e.g. igb0\n"
62876c08ae9SRobert Mustacchi "\tdriver\t\tthe name of the driver attached to the device\n"
62976c08ae9SRobert Mustacchi "\tinstnum\t\tthe instance number of a device, e.g. 2 for nvme2\n"
63076c08ae9SRobert Mustacchi "\tpath\t\tthe /devices path of the device\n"
63176c08ae9SRobert Mustacchi "\tbdf\t\tthe PCI bus/device/function, with values in hex\n"
63276c08ae9SRobert Mustacchi "\tbus\t\tthe PCI bus number of the device in hex\n"
63376c08ae9SRobert Mustacchi "\tdev\t\tthe PCI device number of the device in hex\n"
63476c08ae9SRobert Mustacchi "\tfunc\t\tthe PCI function number of the device in hex\n"
63576c08ae9SRobert Mustacchi "\ttype\t\ta string describing the PCIe generation and width\n"
63676c08ae9SRobert Mustacchi "\tmaxspeed\tthe maximum supported PCIe speed of the device\n"
63776c08ae9SRobert Mustacchi "\tcurspeed\tthe current PCIe speed of the device\n"
63876c08ae9SRobert Mustacchi "\tmaxwidth\tthe maximum supported PCIe lane count of the device\n"
63976c08ae9SRobert Mustacchi "\tcurwidth\tthe current lane count of the PCIe device\n"
64076c08ae9SRobert Mustacchi "\tsupspeeds\tthe list of speeds the device supports\n");
6417687d0d8SRobert Mustacchi }
6427687d0d8SRobert Mustacchi
6437687d0d8SRobert Mustacchi int
pcieadm_show_devs(pcieadm_t * pcip,int argc,char * argv[])6447687d0d8SRobert Mustacchi pcieadm_show_devs(pcieadm_t *pcip, int argc, char *argv[])
6457687d0d8SRobert Mustacchi {
64692f11af9SRobert Mustacchi int c, ret;
6477687d0d8SRobert Mustacchi uint_t flags = 0;
6487687d0d8SRobert Mustacchi const char *fields = NULL;
6497687d0d8SRobert Mustacchi pcieadm_show_devs_t psd;
6507687d0d8SRobert Mustacchi pcieadm_di_walk_t walk;
6517687d0d8SRobert Mustacchi ofmt_status_t oferr;
6527687d0d8SRobert Mustacchi boolean_t parse = B_FALSE;
6537687d0d8SRobert Mustacchi boolean_t speeds = B_FALSE;
6547687d0d8SRobert Mustacchi
6557687d0d8SRobert Mustacchi /*
6567687d0d8SRobert Mustacchi * show-devs relies solely on the devinfo snapshot we already took.
6577687d0d8SRobert Mustacchi * Formalize our privs immediately.
6587687d0d8SRobert Mustacchi */
6597687d0d8SRobert Mustacchi pcieadm_init_privs(pcip);
6607687d0d8SRobert Mustacchi
6617687d0d8SRobert Mustacchi bzero(&psd, sizeof (psd));
6627687d0d8SRobert Mustacchi psd.psd_pia = pcip;
6637687d0d8SRobert Mustacchi psd.psd_funcs = B_TRUE;
6647687d0d8SRobert Mustacchi
6657687d0d8SRobert Mustacchi while ((c = getopt(argc, argv, ":FHo:ps")) != -1) {
6667687d0d8SRobert Mustacchi switch (c) {
6677687d0d8SRobert Mustacchi case 'F':
6687687d0d8SRobert Mustacchi psd.psd_funcs = B_FALSE;
6697687d0d8SRobert Mustacchi break;
6707687d0d8SRobert Mustacchi case 'p':
6717687d0d8SRobert Mustacchi parse = B_TRUE;
6727687d0d8SRobert Mustacchi flags |= OFMT_PARSABLE;
6737687d0d8SRobert Mustacchi break;
6747687d0d8SRobert Mustacchi case 'H':
6757687d0d8SRobert Mustacchi flags |= OFMT_NOHEADER;
6767687d0d8SRobert Mustacchi break;
6777687d0d8SRobert Mustacchi case 's':
6787687d0d8SRobert Mustacchi speeds = B_TRUE;
6797687d0d8SRobert Mustacchi break;
6807687d0d8SRobert Mustacchi case 'o':
6817687d0d8SRobert Mustacchi fields = optarg;
6827687d0d8SRobert Mustacchi break;
6837687d0d8SRobert Mustacchi case ':':
6847687d0d8SRobert Mustacchi pcieadm_show_devs_help("option -%c requires an "
6857687d0d8SRobert Mustacchi "argument", optopt);
6867687d0d8SRobert Mustacchi exit(EXIT_USAGE);
6877687d0d8SRobert Mustacchi case '?':
6887687d0d8SRobert Mustacchi pcieadm_show_devs_help("unknown option: -%c", optopt);
6897687d0d8SRobert Mustacchi exit(EXIT_USAGE);
6907687d0d8SRobert Mustacchi }
6917687d0d8SRobert Mustacchi }
6927687d0d8SRobert Mustacchi
6937687d0d8SRobert Mustacchi if (parse && fields == NULL) {
6947687d0d8SRobert Mustacchi errx(EXIT_USAGE, "-p requires fields specified with -o");
6957687d0d8SRobert Mustacchi }
6967687d0d8SRobert Mustacchi
6977687d0d8SRobert Mustacchi if (fields != NULL && speeds) {
6987687d0d8SRobert Mustacchi errx(EXIT_USAGE, "-s cannot be used with with -o");
6997687d0d8SRobert Mustacchi }
7007687d0d8SRobert Mustacchi
7017687d0d8SRobert Mustacchi if (fields == NULL) {
7027687d0d8SRobert Mustacchi if (speeds) {
7037687d0d8SRobert Mustacchi fields = pcieadm_show_dev_speeds;
7047687d0d8SRobert Mustacchi } else {
7057687d0d8SRobert Mustacchi fields = pcieadm_show_dev_fields;
7067687d0d8SRobert Mustacchi }
7077687d0d8SRobert Mustacchi }
7087687d0d8SRobert Mustacchi
7097687d0d8SRobert Mustacchi argc -= optind;
7107687d0d8SRobert Mustacchi argv += optind;
7117687d0d8SRobert Mustacchi
7127687d0d8SRobert Mustacchi if (argc > 0) {
7137687d0d8SRobert Mustacchi psd.psd_nfilts = argc;
7147687d0d8SRobert Mustacchi psd.psd_filts = argv;
71592f11af9SRobert Mustacchi psd.psd_used = calloc(argc, sizeof (boolean_t));
71692f11af9SRobert Mustacchi if (psd.psd_used == NULL) {
71792f11af9SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate filter tracking "
71892f11af9SRobert Mustacchi "memory");
71992f11af9SRobert Mustacchi }
7207687d0d8SRobert Mustacchi }
7217687d0d8SRobert Mustacchi
7227687d0d8SRobert Mustacchi oferr = ofmt_open(fields, pcieadm_show_dev_ofmt, flags, 0,
7237687d0d8SRobert Mustacchi &psd.psd_ofmt);
7247687d0d8SRobert Mustacchi ofmt_check(oferr, parse, psd.psd_ofmt, pcieadm_ofmt_errx, warnx);
7257687d0d8SRobert Mustacchi
7267687d0d8SRobert Mustacchi walk.pdw_arg = &psd;
7277687d0d8SRobert Mustacchi walk.pdw_func = pcieadm_show_devs_walk_cb;
7287687d0d8SRobert Mustacchi
7297687d0d8SRobert Mustacchi pcieadm_di_walk(pcip, &walk);
7307687d0d8SRobert Mustacchi
73192f11af9SRobert Mustacchi ret = EXIT_SUCCESS;
73292f11af9SRobert Mustacchi for (int i = 0; i < psd.psd_nfilts; i++) {
73392f11af9SRobert Mustacchi if (!psd.psd_used[i]) {
73492f11af9SRobert Mustacchi warnx("filter '%s' did not match any devices",
73592f11af9SRobert Mustacchi psd.psd_filts[i]);
73692f11af9SRobert Mustacchi ret = EXIT_FAILURE;
73792f11af9SRobert Mustacchi }
7387687d0d8SRobert Mustacchi }
73992f11af9SRobert Mustacchi
74092f11af9SRobert Mustacchi if (psd.psd_nprint == 0) {
74192f11af9SRobert Mustacchi ret = EXIT_FAILURE;
74292f11af9SRobert Mustacchi }
74392f11af9SRobert Mustacchi
74492f11af9SRobert Mustacchi return (ret);
7457687d0d8SRobert Mustacchi }
746