15a9113e7SVishal Kulkarni /*
25a9113e7SVishal Kulkarni * This file and its contents are supplied under the terms of the
35a9113e7SVishal Kulkarni * Common Development and Distribution License ("CDDL"), version 1.0.
45a9113e7SVishal Kulkarni * You may only use this file in accordance with the terms of version
55a9113e7SVishal Kulkarni * 1.0 of the CDDL.
65a9113e7SVishal Kulkarni *
75a9113e7SVishal Kulkarni * A full copy of the text of the CDDL should have accompanied this
85a9113e7SVishal Kulkarni * source. A copy of the CDDL is also available via the Internet at
95a9113e7SVishal Kulkarni * http://www.illumos.org/license/CDDL.
105a9113e7SVishal Kulkarni */
115a9113e7SVishal Kulkarni
125a9113e7SVishal Kulkarni /*
135a9113e7SVishal Kulkarni * Copyright (c) 2018 by Chelsio Communications, Inc.
145a9113e7SVishal Kulkarni */
155a9113e7SVishal Kulkarni
1644bf619dSJohn Levon /*
1744bf619dSJohn Levon * Copyright 2019 Joyent, Inc.
18d81537f4SRobert Mustacchi * Copyright 2023 Oxide Computer Company
1944bf619dSJohn Levon */
2044bf619dSJohn Levon
215a9113e7SVishal Kulkarni #include <stdio.h>
225a9113e7SVishal Kulkarni #include <stdlib.h>
235a9113e7SVishal Kulkarni #include <unistd.h>
245a9113e7SVishal Kulkarni #include <stropts.h>
255a9113e7SVishal Kulkarni #include <sys/types.h>
265a9113e7SVishal Kulkarni #include <sys/stat.h>
275a9113e7SVishal Kulkarni #include <fcntl.h>
285a9113e7SVishal Kulkarni #include <sys/socket.h>
295a9113e7SVishal Kulkarni #include <strings.h>
305a9113e7SVishal Kulkarni #include <sys/varargs.h>
315a9113e7SVishal Kulkarni #include <errno.h>
325a9113e7SVishal Kulkarni #include <sys/byteorder.h>
335a9113e7SVishal Kulkarni #include <inttypes.h>
345a9113e7SVishal Kulkarni #include <sys/sysmacros.h>
3565ecf399SYuri Pankov #include <err.h>
36d81537f4SRobert Mustacchi #include <libdevinfo.h>
375a9113e7SVishal Kulkarni
385a9113e7SVishal Kulkarni #include "t4nex.h"
395a9113e7SVishal Kulkarni #include "version.h"
405a9113e7SVishal Kulkarni #include "osdep.h"
415a9113e7SVishal Kulkarni #include "t4fw_interface.h"
427e6ad469SVishal Kulkarni #include "cudbg.h"
437e6ad469SVishal Kulkarni #include "cudbg_lib_common.h"
447e6ad469SVishal Kulkarni
457e6ad469SVishal Kulkarni #define CUDBG_SIZE (32 * 1024 * 1024)
467e6ad469SVishal Kulkarni #define CUDBG_MAX_ENTITY_STR_LEN 4096
477e6ad469SVishal Kulkarni #define MAX_PARAM_LEN 4096
487e6ad469SVishal Kulkarni
49d81537f4SRobert Mustacchi static char cxgbetool_nexus[PATH_MAX];
50d81537f4SRobert Mustacchi
517e6ad469SVishal Kulkarni char *option_list[] = {
527e6ad469SVishal Kulkarni "--collect",
537e6ad469SVishal Kulkarni "--view",
547e6ad469SVishal Kulkarni "--version",
557e6ad469SVishal Kulkarni };
567e6ad469SVishal Kulkarni
577e6ad469SVishal Kulkarni enum {
587e6ad469SVishal Kulkarni CUDBG_OPT_COLLECT,
597e6ad469SVishal Kulkarni CUDBG_OPT_VIEW,
607e6ad469SVishal Kulkarni CUDBG_OPT_VERSION,
617e6ad469SVishal Kulkarni };
625a9113e7SVishal Kulkarni
635a9113e7SVishal Kulkarni /*
645a9113e7SVishal Kulkarni * Firmware Device Log Dumping
655a9113e7SVishal Kulkarni */
665a9113e7SVishal Kulkarni
675a9113e7SVishal Kulkarni static const char * const devlog_level_strings[] = {
685a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_EMERG] = "EMERG",
695a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_CRIT] = "CRIT",
705a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_ERR] = "ERR",
715a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE",
725a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_INFO] = "INFO",
735a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG"
745a9113e7SVishal Kulkarni };
755a9113e7SVishal Kulkarni
765a9113e7SVishal Kulkarni static const char * const devlog_facility_strings[] = {
775a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CORE] = "CORE",
785a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CF] = "CF",
795a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_SCHED] = "SCHED",
805a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_TIMER] = "TIMER",
815a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_RES] = "RES",
825a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_HW] = "HW",
835a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FLR] = "FLR",
845a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ",
855a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_PHY] = "PHY",
865a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_MAC] = "MAC",
875a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_PORT] = "PORT",
885a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_VI] = "VI",
895a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FILTER] = "FILTER",
905a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ACL] = "ACL",
915a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_TM] = "TM",
925a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_QFC] = "QFC",
935a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_DCB] = "DCB",
945a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ETH] = "ETH",
955a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_OFLD] = "OFLD",
965a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_RI] = "RI",
975a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI",
985a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FCOE] = "FCOE",
995a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI",
1005a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE",
1015a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CHNET] = "CHNET",
1025a9113e7SVishal Kulkarni };
1035a9113e7SVishal Kulkarni
1045a9113e7SVishal Kulkarni static const char *progname;
1057e6ad469SVishal Kulkarni int set_dbg_entity(u8 *dbg_bitmap, char *dbg_entity_list);
1067e6ad469SVishal Kulkarni
check_option(char * opt)1077e6ad469SVishal Kulkarni static int check_option(char *opt)
1087e6ad469SVishal Kulkarni {
1097e6ad469SVishal Kulkarni int i;
1107e6ad469SVishal Kulkarni
1117e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(option_list); i++) {
1127e6ad469SVishal Kulkarni if (!strcmp(opt, option_list[i]))
1137e6ad469SVishal Kulkarni return i;
1147e6ad469SVishal Kulkarni }
1157e6ad469SVishal Kulkarni return -1;
1167e6ad469SVishal Kulkarni }
1175a9113e7SVishal Kulkarni
usage(FILE * fp)1185a9113e7SVishal Kulkarni static void usage(FILE *fp)
1195a9113e7SVishal Kulkarni {
120d81537f4SRobert Mustacchi fprintf(fp, "Usage: %s <t4nex# | cxgbe#> [operation]\n", progname);
1215a9113e7SVishal Kulkarni fprintf(fp,
1225a9113e7SVishal Kulkarni "\tdevlog show device log\n"
1237e6ad469SVishal Kulkarni "\tloadfw <FW image> Flash the FW image\n"
12465ecf399SYuri Pankov "\tcudbg <option> [<args>] Chelsio Unified Debugger\n");
1255a9113e7SVishal Kulkarni exit(fp == stderr ? 1 : 0);
1265a9113e7SVishal Kulkarni }
1275a9113e7SVishal Kulkarni
1285a9113e7SVishal Kulkarni static int
doit(const char * iff_name,unsigned long cmd,void * data)1295a9113e7SVishal Kulkarni doit(const char *iff_name, unsigned long cmd, void *data)
1305a9113e7SVishal Kulkarni {
1315a9113e7SVishal Kulkarni int fd = 0;
1325a9113e7SVishal Kulkarni int rc = 0;
1335a9113e7SVishal Kulkarni
1345a9113e7SVishal Kulkarni if ((fd = open(iff_name, O_RDWR)) < 0)
1355a9113e7SVishal Kulkarni return (-1);
1365a9113e7SVishal Kulkarni
1375a9113e7SVishal Kulkarni rc = (ioctl(fd, cmd, data) < 0) ? errno : rc;
1385a9113e7SVishal Kulkarni close(fd);
1395a9113e7SVishal Kulkarni return (rc);
1405a9113e7SVishal Kulkarni }
1415a9113e7SVishal Kulkarni
1425a9113e7SVishal Kulkarni static void
get_devlog(int argc,char * argv[],int start_arg,const char * iff_name)1435a9113e7SVishal Kulkarni get_devlog(int argc, char *argv[], int start_arg, const char *iff_name)
1445a9113e7SVishal Kulkarni {
1455a9113e7SVishal Kulkarni struct t4_devlog *devlog;
1465a9113e7SVishal Kulkarni struct fw_devlog_e *entry, *buf;
1475a9113e7SVishal Kulkarni int rc = 0, first = 0, nentries, i, j, len;
1485a9113e7SVishal Kulkarni uint64_t ftstamp = UINT64_MAX;
1495a9113e7SVishal Kulkarni
1505a9113e7SVishal Kulkarni devlog = malloc(T4_DEVLOG_SIZE + sizeof (struct t4_devlog));
1515a9113e7SVishal Kulkarni if (!devlog)
1525a9113e7SVishal Kulkarni err(1, "%s: can't allocate devlog buffer", __func__);
1535a9113e7SVishal Kulkarni
1545a9113e7SVishal Kulkarni devlog->len = T4_DEVLOG_SIZE;
1555a9113e7SVishal Kulkarni /* Get device log */
1565a9113e7SVishal Kulkarni rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog);
1575a9113e7SVishal Kulkarni if (rc == ENOBUFS) {
1585a9113e7SVishal Kulkarni /*
1595a9113e7SVishal Kulkarni * Default buffer size is not sufficient to hold device log.
1605a9113e7SVishal Kulkarni * Driver has updated the devlog.len to indicate the expected
1615a9113e7SVishal Kulkarni * size. Free the currently allocated devlog.data, allocate
1625a9113e7SVishal Kulkarni * again with right size and retry.
1635a9113e7SVishal Kulkarni */
1645a9113e7SVishal Kulkarni len = devlog->len;
1655a9113e7SVishal Kulkarni free(devlog);
1665a9113e7SVishal Kulkarni
1675a9113e7SVishal Kulkarni if ((devlog = malloc(len + sizeof (struct t4_devlog))) == NULL)
1685a9113e7SVishal Kulkarni err(1, "%s: can't reallocate devlog buffer", __func__);
1695a9113e7SVishal Kulkarni
1705a9113e7SVishal Kulkarni rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog);
1715a9113e7SVishal Kulkarni }
1725a9113e7SVishal Kulkarni if (rc) {
1735a9113e7SVishal Kulkarni free(devlog);
17465ecf399SYuri Pankov errx(1, "%s: can't get device log", __func__);
1755a9113e7SVishal Kulkarni }
1765a9113e7SVishal Kulkarni
1775a9113e7SVishal Kulkarni /* There are nentries number of entries in the buffer */
1785a9113e7SVishal Kulkarni nentries = (devlog->len / sizeof (struct fw_devlog_e));
1795a9113e7SVishal Kulkarni
1805a9113e7SVishal Kulkarni buf = (struct fw_devlog_e *)devlog->data;
1815a9113e7SVishal Kulkarni
1825a9113e7SVishal Kulkarni /* Find the first entry */
1835a9113e7SVishal Kulkarni for (i = 0; i < nentries; i++) {
1845a9113e7SVishal Kulkarni entry = &buf[i];
1855a9113e7SVishal Kulkarni
1865a9113e7SVishal Kulkarni if (entry->timestamp == 0)
1875a9113e7SVishal Kulkarni break;
1885a9113e7SVishal Kulkarni
1895a9113e7SVishal Kulkarni entry->timestamp = BE_64(entry->timestamp);
1905a9113e7SVishal Kulkarni entry->seqno = BE_32(entry->seqno);
1915a9113e7SVishal Kulkarni for (j = 0; j < 8; j++)
1925a9113e7SVishal Kulkarni entry->params[j] = BE_32(entry->params[j]);
1935a9113e7SVishal Kulkarni
1945a9113e7SVishal Kulkarni if (entry->timestamp < ftstamp) {
1955a9113e7SVishal Kulkarni ftstamp = entry->timestamp;
1965a9113e7SVishal Kulkarni first = i;
1975a9113e7SVishal Kulkarni }
1985a9113e7SVishal Kulkarni }
1995a9113e7SVishal Kulkarni
2005a9113e7SVishal Kulkarni printf("%10s %15s %8s %8s %s\n", "Seq#", "Tstamp", "Level",
2015a9113e7SVishal Kulkarni "Facility", "Message");
2025a9113e7SVishal Kulkarni
2035a9113e7SVishal Kulkarni i = first;
2045a9113e7SVishal Kulkarni
2055a9113e7SVishal Kulkarni do {
2065a9113e7SVishal Kulkarni entry = &buf[i];
2075a9113e7SVishal Kulkarni
2085a9113e7SVishal Kulkarni if (entry->timestamp == 0)
2095a9113e7SVishal Kulkarni break;
2105a9113e7SVishal Kulkarni
2115a9113e7SVishal Kulkarni printf("%10d %15llu %8s %8s ", entry->seqno,
2125a9113e7SVishal Kulkarni entry->timestamp,
2135a9113e7SVishal Kulkarni (entry->level < ARRAY_SIZE(devlog_level_strings) ?
2145a9113e7SVishal Kulkarni devlog_level_strings[entry->level] : "UNKNOWN"),
2155a9113e7SVishal Kulkarni (entry->facility < ARRAY_SIZE(devlog_facility_strings) ?
2165a9113e7SVishal Kulkarni devlog_facility_strings[entry->facility] : "UNKNOWN"));
2175a9113e7SVishal Kulkarni
2185a9113e7SVishal Kulkarni printf((const char *)entry->fmt, entry->params[0],
2195a9113e7SVishal Kulkarni entry->params[1], entry->params[2], entry->params[3],
2205a9113e7SVishal Kulkarni entry->params[4], entry->params[5], entry->params[6],
2215a9113e7SVishal Kulkarni entry->params[7]);
2225a9113e7SVishal Kulkarni
2235a9113e7SVishal Kulkarni if (++i == nentries)
2245a9113e7SVishal Kulkarni i = 0;
2255a9113e7SVishal Kulkarni
2265a9113e7SVishal Kulkarni } while (i != first);
2275a9113e7SVishal Kulkarni
2285a9113e7SVishal Kulkarni free(devlog);
2295a9113e7SVishal Kulkarni }
2305a9113e7SVishal Kulkarni
2315a9113e7SVishal Kulkarni static void
load_fw(int argc,char * argv[],int start_arg,const char * iff_name)2325a9113e7SVishal Kulkarni load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
2335a9113e7SVishal Kulkarni {
2345a9113e7SVishal Kulkarni const char *fname = argv[start_arg];
2355a9113e7SVishal Kulkarni struct t4_ldfw *fw;
2365a9113e7SVishal Kulkarni struct stat sb;
2375a9113e7SVishal Kulkarni size_t len;
2385a9113e7SVishal Kulkarni int fd;
2395a9113e7SVishal Kulkarni
2405a9113e7SVishal Kulkarni if (argc != 4)
24165ecf399SYuri Pankov errx(1, "incorrect number of arguments");
2425a9113e7SVishal Kulkarni
2435a9113e7SVishal Kulkarni fd = open(fname, O_RDONLY);
2445a9113e7SVishal Kulkarni if (fd < 0)
2455a9113e7SVishal Kulkarni err(1, "%s: opening %s failed", __func__, fname);
2465a9113e7SVishal Kulkarni if (fstat(fd, &sb) < 0) {
24765ecf399SYuri Pankov warn("%s: fstat %s failed", __func__, fname);
2485a9113e7SVishal Kulkarni close(fd);
24965ecf399SYuri Pankov exit(1);
2505a9113e7SVishal Kulkarni }
2515a9113e7SVishal Kulkarni len = (size_t)sb.st_size;
2525a9113e7SVishal Kulkarni
2535a9113e7SVishal Kulkarni fw = malloc(sizeof (struct t4_ldfw) + len);
2545a9113e7SVishal Kulkarni if (!fw) {
255*6b1325cfSRobert Mustacchi warn("%s: %s allocate %zu bytes failed",
2565a9113e7SVishal Kulkarni __func__, fname, sizeof (struct t4_ldfw) + len);
25765ecf399SYuri Pankov close(fd);
25865ecf399SYuri Pankov exit(1);
2595a9113e7SVishal Kulkarni }
2605a9113e7SVishal Kulkarni
2615a9113e7SVishal Kulkarni if (read(fd, fw->data, len) < len) {
26265ecf399SYuri Pankov warn("%s: %s read failed", __func__, fname);
2635a9113e7SVishal Kulkarni close(fd);
2645a9113e7SVishal Kulkarni free(fw);
26565ecf399SYuri Pankov exit(1);
2665a9113e7SVishal Kulkarni }
2675a9113e7SVishal Kulkarni
2685a9113e7SVishal Kulkarni close(fd);
2695a9113e7SVishal Kulkarni
2705a9113e7SVishal Kulkarni fw->len = len;
2715a9113e7SVishal Kulkarni
2725a9113e7SVishal Kulkarni if (doit(iff_name, T4_IOCTL_LOAD_FW, fw)) {
2735a9113e7SVishal Kulkarni free(fw);
2745a9113e7SVishal Kulkarni err(1, "%s: IOCTL failed", __func__);
2755a9113e7SVishal Kulkarni } else {
2765a9113e7SVishal Kulkarni printf("FW flash success, reload driver/reboot to take "
2775a9113e7SVishal Kulkarni "effect\n");
2785a9113e7SVishal Kulkarni }
2795a9113e7SVishal Kulkarni
2805a9113e7SVishal Kulkarni free(fw);
2815a9113e7SVishal Kulkarni }
2825a9113e7SVishal Kulkarni
read_input_file(char * in_file,void ** buf,int * buf_size)2837e6ad469SVishal Kulkarni int read_input_file(char *in_file, void **buf, int *buf_size)
2847e6ad469SVishal Kulkarni {
2857e6ad469SVishal Kulkarni FILE *fptr = NULL;
2867e6ad469SVishal Kulkarni size_t count;
2877e6ad469SVishal Kulkarni int rc = 0;
2887e6ad469SVishal Kulkarni
2897e6ad469SVishal Kulkarni fptr = fopen(in_file, "rb");
2907e6ad469SVishal Kulkarni if (!fptr) {
2917e6ad469SVishal Kulkarni perror("error in opening file ");
2927e6ad469SVishal Kulkarni rc = -1;
2937e6ad469SVishal Kulkarni goto out;
2947e6ad469SVishal Kulkarni }
2957e6ad469SVishal Kulkarni rc = fseek(fptr, 0, SEEK_END);
2967e6ad469SVishal Kulkarni if (rc < 0) {
2977e6ad469SVishal Kulkarni perror("error in seeking file ");
2987e6ad469SVishal Kulkarni rc = -1;
2997e6ad469SVishal Kulkarni goto out;
3007e6ad469SVishal Kulkarni }
3017e6ad469SVishal Kulkarni *buf_size = ftell(fptr);
3027e6ad469SVishal Kulkarni rc = fseek(fptr, 0, SEEK_SET);
3037e6ad469SVishal Kulkarni if (rc < 0) {
3047e6ad469SVishal Kulkarni perror("error in seeking file ");
3057e6ad469SVishal Kulkarni rc = -1;
3067e6ad469SVishal Kulkarni goto out;
3077e6ad469SVishal Kulkarni }
3087e6ad469SVishal Kulkarni *buf = (void *) malloc(*buf_size);
3097e6ad469SVishal Kulkarni if (*buf == NULL) {
3107e6ad469SVishal Kulkarni rc = CUDBG_STATUS_NOSPACE;
3117e6ad469SVishal Kulkarni goto out;
3127e6ad469SVishal Kulkarni }
3137e6ad469SVishal Kulkarni memset(*buf, 0, *buf_size);
3147e6ad469SVishal Kulkarni
3157e6ad469SVishal Kulkarni count = fread(*buf, 1, *buf_size, fptr);
3167e6ad469SVishal Kulkarni if (count != *buf_size) {
3177e6ad469SVishal Kulkarni perror("error in reading from file ");
3187e6ad469SVishal Kulkarni goto out;
3197e6ad469SVishal Kulkarni }
3207e6ad469SVishal Kulkarni
3217e6ad469SVishal Kulkarni out:
3227e6ad469SVishal Kulkarni if (fptr)
3237e6ad469SVishal Kulkarni fclose(fptr);
3247e6ad469SVishal Kulkarni
3257e6ad469SVishal Kulkarni return rc;
3267e6ad469SVishal Kulkarni }
3277e6ad469SVishal Kulkarni
3287e6ad469SVishal Kulkarni static void
do_collect(char * dbg_entity_list,const char * iff_name,const char * fname)3297e6ad469SVishal Kulkarni do_collect(char *dbg_entity_list, const char *iff_name, const char *fname)
3307e6ad469SVishal Kulkarni {
3317e6ad469SVishal Kulkarni struct t4_cudbg_dump *cudbg;
3327e6ad469SVishal Kulkarni int fd;
3337e6ad469SVishal Kulkarni
3347e6ad469SVishal Kulkarni cudbg = malloc(sizeof(struct t4_cudbg_dump) + CUDBG_SIZE);
3357e6ad469SVishal Kulkarni if (!cudbg) {
336*6b1325cfSRobert Mustacchi err(1, "%s:allocate %d bytes failed", __func__, CUDBG_SIZE);
3377e6ad469SVishal Kulkarni }
3387e6ad469SVishal Kulkarni
3397e6ad469SVishal Kulkarni memset(cudbg, 0, sizeof(struct t4_cudbg_dump) + CUDBG_SIZE);
3407e6ad469SVishal Kulkarni
3417e6ad469SVishal Kulkarni cudbg->len = CUDBG_SIZE;
3427e6ad469SVishal Kulkarni
3437e6ad469SVishal Kulkarni set_dbg_entity(cudbg->bitmap, dbg_entity_list);
3447e6ad469SVishal Kulkarni
3457e6ad469SVishal Kulkarni if (doit(iff_name, T4_IOCTL_GET_CUDBG, cudbg)) {
3467e6ad469SVishal Kulkarni free(cudbg);
3477e6ad469SVishal Kulkarni err(1, "%s: IOCTL failed", __func__);
3487e6ad469SVishal Kulkarni }
3497e6ad469SVishal Kulkarni
3507e6ad469SVishal Kulkarni fd = open(fname, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY,
3517e6ad469SVishal Kulkarni S_IRUSR | S_IRGRP | S_IROTH);
3527e6ad469SVishal Kulkarni if (fd < 0) {
35365ecf399SYuri Pankov err(1, "%s: file open failed", __func__);
3547e6ad469SVishal Kulkarni }
3557e6ad469SVishal Kulkarni
3567e6ad469SVishal Kulkarni write(fd, cudbg->data, cudbg->len);
3577e6ad469SVishal Kulkarni close(fd);
3587e6ad469SVishal Kulkarni free(cudbg);
3597e6ad469SVishal Kulkarni }
3607e6ad469SVishal Kulkarni
3617e6ad469SVishal Kulkarni static void
do_view(char * dbg_entity_list,char * in_file)3627e6ad469SVishal Kulkarni do_view(char *dbg_entity_list, char *in_file)
3637e6ad469SVishal Kulkarni {
3647e6ad469SVishal Kulkarni void *handle = NULL;
3657e6ad469SVishal Kulkarni void *buf = NULL;
3667e6ad469SVishal Kulkarni int buf_size = 32 * 1024 * 1024;
3677e6ad469SVishal Kulkarni int next_offset = 0;
3687e6ad469SVishal Kulkarni int data_len;
3697e6ad469SVishal Kulkarni int rc = 0;
3707e6ad469SVishal Kulkarni
3717e6ad469SVishal Kulkarni handle = cudbg_alloc_handle();
3727e6ad469SVishal Kulkarni if (!handle)
3737e6ad469SVishal Kulkarni goto out;
3747e6ad469SVishal Kulkarni /* rcad from file */
3757e6ad469SVishal Kulkarni rc = read_input_file(in_file, &buf, &buf_size);
3767e6ad469SVishal Kulkarni if (rc < 0) {
3777e6ad469SVishal Kulkarni goto out;
3787e6ad469SVishal Kulkarni }
3797e6ad469SVishal Kulkarni
3807e6ad469SVishal Kulkarni set_dbg_entity(((struct cudbg_private *)handle)->dbg_init.dbg_bitmap,
3817e6ad469SVishal Kulkarni dbg_entity_list);
3827e6ad469SVishal Kulkarni do {
3837e6ad469SVishal Kulkarni if (buf_size - next_offset <= 0)
3847e6ad469SVishal Kulkarni break;
3857e6ad469SVishal Kulkarni
3867e6ad469SVishal Kulkarni data_len = cudbg_view(handle, buf+next_offset,
3877e6ad469SVishal Kulkarni buf_size-next_offset, NULL, 0);
3887e6ad469SVishal Kulkarni next_offset += data_len;
3897e6ad469SVishal Kulkarni if (data_len > 0)
3907e6ad469SVishal Kulkarni printf("\n\t\t<========================END============="\
3917e6ad469SVishal Kulkarni "===========>\t\t\n\n\n");
3927e6ad469SVishal Kulkarni } while (data_len > 0);
3937e6ad469SVishal Kulkarni
3947e6ad469SVishal Kulkarni out:
3957e6ad469SVishal Kulkarni if (buf)
3967e6ad469SVishal Kulkarni free(buf);
3977e6ad469SVishal Kulkarni if (handle)
3987e6ad469SVishal Kulkarni cudbg_free_handle(handle);
3997e6ad469SVishal Kulkarni return;
4007e6ad469SVishal Kulkarni }
4017e6ad469SVishal Kulkarni
4027e6ad469SVishal Kulkarni typedef void (*cudbg_alias_get_entities_cb)(char *dst, u32 dst_size);
4037e6ad469SVishal Kulkarni
4047e6ad469SVishal Kulkarni struct entity_access_list {
4057e6ad469SVishal Kulkarni const char *name;
4067e6ad469SVishal Kulkarni cudbg_alias_get_entities_cb get_entities_cb;
4077e6ad469SVishal Kulkarni };
4087e6ad469SVishal Kulkarni
4097e6ad469SVishal Kulkarni void
cudbg_append_string(char * dst,u32 dst_size,char * src)4107e6ad469SVishal Kulkarni cudbg_append_string(char *dst, u32 dst_size, char *src)
4117e6ad469SVishal Kulkarni {
4127e6ad469SVishal Kulkarni strlcat(dst, src, dst_size);
4137e6ad469SVishal Kulkarni strlcat(dst, ",", dst_size);
4147e6ad469SVishal Kulkarni }
4157e6ad469SVishal Kulkarni
4167e6ad469SVishal Kulkarni static void
cudbg_alias_get_allregs(char * dst,u32 dst_size)4177e6ad469SVishal Kulkarni cudbg_alias_get_allregs(char *dst, u32 dst_size)
4187e6ad469SVishal Kulkarni {
4197e6ad469SVishal Kulkarni u32 i;
4207e6ad469SVishal Kulkarni
4217e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_list); i++)
4227e6ad469SVishal Kulkarni if (entity_list[i].flag & (1 << ENTITY_FLAG_REGISTER))
4237e6ad469SVishal Kulkarni cudbg_append_string(dst, dst_size, entity_list[i].name);
4247e6ad469SVishal Kulkarni }
4257e6ad469SVishal Kulkarni
4267e6ad469SVishal Kulkarni static struct entity_access_list ATTRIBUTE_UNUSED entity_alias_list[] = {
4277e6ad469SVishal Kulkarni {"allregs", cudbg_alias_get_allregs},
4287e6ad469SVishal Kulkarni };
4297e6ad469SVishal Kulkarni
4307e6ad469SVishal Kulkarni static int
check_dbg_entity(char * entity)4317e6ad469SVishal Kulkarni check_dbg_entity(char *entity)
4327e6ad469SVishal Kulkarni {
4337e6ad469SVishal Kulkarni u32 i;
4347e6ad469SVishal Kulkarni
4357e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_list); i++)
4367e6ad469SVishal Kulkarni if (!strcmp(entity, entity_list[i].name))
4377e6ad469SVishal Kulkarni return entity_list[i].bit;
4387e6ad469SVishal Kulkarni return -1;
4397e6ad469SVishal Kulkarni }
4407e6ad469SVishal Kulkarni
4417e6ad469SVishal Kulkarni /* Get matching alias index from entity_alias_list[] */
4427e6ad469SVishal Kulkarni static
get_alias(const char * entity)4437e6ad469SVishal Kulkarni int get_alias(const char *entity)
4447e6ad469SVishal Kulkarni {
4457e6ad469SVishal Kulkarni u32 i;
4467e6ad469SVishal Kulkarni
4477e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_alias_list); i++)
4487e6ad469SVishal Kulkarni if (!strcmp(entity, entity_alias_list[i].name))
4497e6ad469SVishal Kulkarni return i;
4507e6ad469SVishal Kulkarni return -1;
4517e6ad469SVishal Kulkarni }
4527e6ad469SVishal Kulkarni
4537e6ad469SVishal Kulkarni static int
parse_entity_list(const char * dbg_entity_list,char * dst,u32 dst_size)4547e6ad469SVishal Kulkarni parse_entity_list(const char *dbg_entity_list, char *dst,
4557e6ad469SVishal Kulkarni u32 dst_size)
4567e6ad469SVishal Kulkarni {
4577e6ad469SVishal Kulkarni char *tmp_dbg_entity_list;
4587e6ad469SVishal Kulkarni char *dbg_entity;
4597e6ad469SVishal Kulkarni int rc, i;
4607e6ad469SVishal Kulkarni
4617e6ad469SVishal Kulkarni /* Holds single entity name de-limited by comma */
4627e6ad469SVishal Kulkarni tmp_dbg_entity_list = malloc(CUDBG_MAX_ENTITY_STR_LEN);
4637e6ad469SVishal Kulkarni if (!tmp_dbg_entity_list)
4647e6ad469SVishal Kulkarni return ENOMEM;
4657e6ad469SVishal Kulkarni
4667e6ad469SVishal Kulkarni strlcpy(tmp_dbg_entity_list, dbg_entity_list, CUDBG_MAX_ENTITY_STR_LEN);
4677e6ad469SVishal Kulkarni dbg_entity = strtok(tmp_dbg_entity_list, ",");
4687e6ad469SVishal Kulkarni while (dbg_entity != NULL) {
4697e6ad469SVishal Kulkarni /* See if specified entity name exists. If it doesn't
4707e6ad469SVishal Kulkarni * exist, see if the entity name is an alias.
4717e6ad469SVishal Kulkarni * If it's not a valid entity name, bail with error.
4727e6ad469SVishal Kulkarni */
4737e6ad469SVishal Kulkarni rc = check_dbg_entity(dbg_entity);
4747e6ad469SVishal Kulkarni if (rc < 0) {
4757e6ad469SVishal Kulkarni i = get_alias(dbg_entity);
4767e6ad469SVishal Kulkarni if (i < 0) {
4777e6ad469SVishal Kulkarni /* Not an alias, and not a valid entity name */
4787e6ad469SVishal Kulkarni printf("\nUnknown entity: %s\n", dbg_entity);
4797e6ad469SVishal Kulkarni rc = CUDBG_STATUS_ENTITY_NOT_FOUND;
4807e6ad469SVishal Kulkarni goto out_err;
4817e6ad469SVishal Kulkarni } else {
4827e6ad469SVishal Kulkarni /* If alias is found, get all the corresponding
4837e6ad469SVishal Kulkarni * debug entities related to the alias.
4847e6ad469SVishal Kulkarni */
4857e6ad469SVishal Kulkarni entity_alias_list[i].get_entities_cb(dst, dst_size);
4867e6ad469SVishal Kulkarni }
4877e6ad469SVishal Kulkarni } else {
4887e6ad469SVishal Kulkarni /* Not an alias, but is a valid entity name.
4897e6ad469SVishal Kulkarni * So, append the corresponding debug entity.
4907e6ad469SVishal Kulkarni */
4917e6ad469SVishal Kulkarni cudbg_append_string(dst, dst_size, entity_list[rc].name);
4927e6ad469SVishal Kulkarni }
4937e6ad469SVishal Kulkarni dbg_entity = strtok(NULL, ",");
4947e6ad469SVishal Kulkarni }
4957e6ad469SVishal Kulkarni
4967e6ad469SVishal Kulkarni rc = 0;
4977e6ad469SVishal Kulkarni
4987e6ad469SVishal Kulkarni out_err:
4997e6ad469SVishal Kulkarni free(tmp_dbg_entity_list);
5007e6ad469SVishal Kulkarni return rc;
5017e6ad469SVishal Kulkarni }
5027e6ad469SVishal Kulkarni
5037e6ad469SVishal Kulkarni static
get_entity_list(const char * in_buff,char ** out_buff)5047e6ad469SVishal Kulkarni int get_entity_list(const char *in_buff, char **out_buff)
5057e6ad469SVishal Kulkarni {
5067e6ad469SVishal Kulkarni char *dbg_entity_list;
5077e6ad469SVishal Kulkarni int rc;
5087e6ad469SVishal Kulkarni
5097e6ad469SVishal Kulkarni /* Allocate enough to hold converted alias string.
5107e6ad469SVishal Kulkarni * Must be freed by caller
5117e6ad469SVishal Kulkarni */
5127e6ad469SVishal Kulkarni dbg_entity_list = malloc(CUDBG_MAX_ENTITY_STR_LEN);
5137e6ad469SVishal Kulkarni if (!dbg_entity_list)
5147e6ad469SVishal Kulkarni return ENOMEM;
5157e6ad469SVishal Kulkarni
5167e6ad469SVishal Kulkarni memset(dbg_entity_list, 0, CUDBG_MAX_ENTITY_STR_LEN);
5177e6ad469SVishal Kulkarni rc = parse_entity_list(in_buff, dbg_entity_list,
5187e6ad469SVishal Kulkarni CUDBG_MAX_ENTITY_STR_LEN);
5197e6ad469SVishal Kulkarni if (rc) {
5207e6ad469SVishal Kulkarni free(dbg_entity_list);
5217e6ad469SVishal Kulkarni return rc;
5227e6ad469SVishal Kulkarni }
5237e6ad469SVishal Kulkarni
5247e6ad469SVishal Kulkarni /* Remove the last comma */
5257e6ad469SVishal Kulkarni dbg_entity_list[strlen(dbg_entity_list) - 1] = '\0';
5267e6ad469SVishal Kulkarni *out_buff = dbg_entity_list;
5277e6ad469SVishal Kulkarni return 0;
5287e6ad469SVishal Kulkarni }
5297e6ad469SVishal Kulkarni
5307e6ad469SVishal Kulkarni static void
put_entity_list(char * buf)5317e6ad469SVishal Kulkarni put_entity_list(char *buf)
5327e6ad469SVishal Kulkarni {
5337e6ad469SVishal Kulkarni if (buf)
5347e6ad469SVishal Kulkarni free(buf);
5357e6ad469SVishal Kulkarni }
5367e6ad469SVishal Kulkarni
5377e6ad469SVishal Kulkarni int
set_dbg_entity(u8 * dbg_bitmap,char * dbg_entity_list)5387e6ad469SVishal Kulkarni set_dbg_entity(u8 *dbg_bitmap, char *dbg_entity_list)
5397e6ad469SVishal Kulkarni {
5407e6ad469SVishal Kulkarni int i, dbg_entity_bit, rc = 0;
5417e6ad469SVishal Kulkarni char *dbg_entity;
5427e6ad469SVishal Kulkarni char *dbg_entity_list_tmp;
5437e6ad469SVishal Kulkarni
5447e6ad469SVishal Kulkarni dbg_entity_list_tmp = malloc(MAX_PARAM_LEN);
5457e6ad469SVishal Kulkarni if (!dbg_entity_list_tmp) {
5467e6ad469SVishal Kulkarni rc = CUDBG_STATUS_NOSPACE;
5477e6ad469SVishal Kulkarni return rc;
5487e6ad469SVishal Kulkarni }
5497e6ad469SVishal Kulkarni
5507e6ad469SVishal Kulkarni if (dbg_entity_list != NULL) {
5517e6ad469SVishal Kulkarni strlcpy(dbg_entity_list_tmp, dbg_entity_list, MAX_PARAM_LEN);
5527e6ad469SVishal Kulkarni dbg_entity = strtok(dbg_entity_list_tmp, ",");
5537e6ad469SVishal Kulkarni }
5547e6ad469SVishal Kulkarni else
5557e6ad469SVishal Kulkarni dbg_entity = NULL;
5567e6ad469SVishal Kulkarni
5577e6ad469SVishal Kulkarni while (dbg_entity != NULL) {
5587e6ad469SVishal Kulkarni rc = check_dbg_entity(dbg_entity);
5597e6ad469SVishal Kulkarni if (rc < 0) {
5607e6ad469SVishal Kulkarni printf("\n\tInvalid debug entity: %s\n", dbg_entity);
5617e6ad469SVishal Kulkarni //Vishal cudbg_usage();
5627e6ad469SVishal Kulkarni goto out_free;
5637e6ad469SVishal Kulkarni }
5647e6ad469SVishal Kulkarni
5657e6ad469SVishal Kulkarni dbg_entity_bit = rc;
5667e6ad469SVishal Kulkarni
5677e6ad469SVishal Kulkarni if (dbg_entity_bit == CUDBG_ALL) {
5687e6ad469SVishal Kulkarni for (i = 1; i < CUDBG_MAX_ENTITY; i++)
5697e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, i);
5707e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, CUDBG_ALL);
5717e6ad469SVishal Kulkarni break;
5727e6ad469SVishal Kulkarni } else {
5737e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, dbg_entity_bit);
5747e6ad469SVishal Kulkarni }
5757e6ad469SVishal Kulkarni
5767e6ad469SVishal Kulkarni dbg_entity = strtok(NULL, ",");
5777e6ad469SVishal Kulkarni }
5787e6ad469SVishal Kulkarni
5797e6ad469SVishal Kulkarni rc = 0;
5807e6ad469SVishal Kulkarni
5817e6ad469SVishal Kulkarni out_free:
5827e6ad469SVishal Kulkarni free(dbg_entity_list_tmp);
5837e6ad469SVishal Kulkarni return rc;
5847e6ad469SVishal Kulkarni }
5857e6ad469SVishal Kulkarni
5867e6ad469SVishal Kulkarni
5877e6ad469SVishal Kulkarni static void
get_cudbg(int argc,char * argv[],int start_arg,const char * iff_name)5887e6ad469SVishal Kulkarni get_cudbg(int argc, char *argv[], int start_arg, const char *iff_name)
5897e6ad469SVishal Kulkarni {
5907e6ad469SVishal Kulkarni char *dbg_entity_list = NULL;
5917e6ad469SVishal Kulkarni int rc = 0, option;
59265ecf399SYuri Pankov
59365ecf399SYuri Pankov if (start_arg >= argc)
59465ecf399SYuri Pankov errx(1, "no option provided");
59565ecf399SYuri Pankov
5967e6ad469SVishal Kulkarni rc = check_option(argv[start_arg++]);
5977e6ad469SVishal Kulkarni if (rc < 0) {
59865ecf399SYuri Pankov errx(1, "%s:Invalid option provided", __func__);
5997e6ad469SVishal Kulkarni }
6007e6ad469SVishal Kulkarni option = rc;
6017e6ad469SVishal Kulkarni
6027e6ad469SVishal Kulkarni if (option == CUDBG_OPT_VERSION) {
6037e6ad469SVishal Kulkarni printf("Library Version %d.%d.%d\n", CUDBG_MAJOR_VERSION,
6047e6ad469SVishal Kulkarni CUDBG_MINOR_VERSION, CUDBG_BUILD_VERSION);
6057e6ad469SVishal Kulkarni return;
6067e6ad469SVishal Kulkarni }
6077e6ad469SVishal Kulkarni
6087e6ad469SVishal Kulkarni if (argc < 5) {
60965ecf399SYuri Pankov errx(1, "Invalid number of arguments\n");
6107e6ad469SVishal Kulkarni }
6117e6ad469SVishal Kulkarni rc = get_entity_list(argv[start_arg++],
6127e6ad469SVishal Kulkarni &dbg_entity_list);
6137e6ad469SVishal Kulkarni if (rc) {
61465ecf399SYuri Pankov errx(1, "Error in parsing entity\n");
6157e6ad469SVishal Kulkarni }
6167e6ad469SVishal Kulkarni
6177e6ad469SVishal Kulkarni if (argc < 6) {
61865ecf399SYuri Pankov errx(1, "File name is missing\n");
6197e6ad469SVishal Kulkarni }
6207e6ad469SVishal Kulkarni
6217e6ad469SVishal Kulkarni switch (option) {
6227e6ad469SVishal Kulkarni case CUDBG_OPT_COLLECT:
6237e6ad469SVishal Kulkarni do_collect(dbg_entity_list, iff_name, argv[start_arg]);
6247e6ad469SVishal Kulkarni break;
6257e6ad469SVishal Kulkarni case CUDBG_OPT_VIEW:
6267e6ad469SVishal Kulkarni do_view(dbg_entity_list, argv[start_arg]);
6277e6ad469SVishal Kulkarni break;
6287e6ad469SVishal Kulkarni default:
62965ecf399SYuri Pankov errx(1, "Wrong option provided\n");
6307e6ad469SVishal Kulkarni }
6317e6ad469SVishal Kulkarni
6327e6ad469SVishal Kulkarni put_entity_list(dbg_entity_list);
6337e6ad469SVishal Kulkarni }
6347e6ad469SVishal Kulkarni
6355a9113e7SVishal Kulkarni static void
run_cmd(int argc,char * argv[],const char * iff_name)6365a9113e7SVishal Kulkarni run_cmd(int argc, char *argv[], const char *iff_name)
6375a9113e7SVishal Kulkarni {
6385a9113e7SVishal Kulkarni if (strcmp(argv[2], "devlog") == 0)
6395a9113e7SVishal Kulkarni get_devlog(argc, argv, 3, iff_name);
6405a9113e7SVishal Kulkarni else if (strcmp(argv[2], "loadfw") == 0)
6415a9113e7SVishal Kulkarni load_fw(argc, argv, 3, iff_name);
6427e6ad469SVishal Kulkarni else if (strcmp(argv[2], "cudbg") == 0)
6437e6ad469SVishal Kulkarni get_cudbg(argc, argv, 3, iff_name);
6445a9113e7SVishal Kulkarni else
6455a9113e7SVishal Kulkarni usage(stderr);
6465a9113e7SVishal Kulkarni }
6475a9113e7SVishal Kulkarni
648d81537f4SRobert Mustacchi /*
649d81537f4SRobert Mustacchi * Traditionally we expect to be given a path to the t4nex device control file
650d81537f4SRobert Mustacchi * hidden in /devices. To make life easier, we want to also support folks using
651d81537f4SRobert Mustacchi * the driver instance numbers for either a given t4nex%d or cxgbe%d. We check
652d81537f4SRobert Mustacchi * to see if we've been given a path to a character device and if so, just
653d81537f4SRobert Mustacchi * continue straight on with the given argument. Otherwise we attempt to map it
654d81537f4SRobert Mustacchi * to something known.
655d81537f4SRobert Mustacchi */
656d81537f4SRobert Mustacchi static const char *
cxgbetool_parse_path(char * arg)657d81537f4SRobert Mustacchi cxgbetool_parse_path(char *arg)
658d81537f4SRobert Mustacchi {
659d81537f4SRobert Mustacchi struct stat st;
660d81537f4SRobert Mustacchi di_node_t root, node;
661d81537f4SRobert Mustacchi const char *numptr, *errstr;
662d81537f4SRobert Mustacchi size_t drvlen;
663d81537f4SRobert Mustacchi int inst;
664d81537f4SRobert Mustacchi boolean_t is_t4nex = B_TRUE;
665d81537f4SRobert Mustacchi char mname[64];
666d81537f4SRobert Mustacchi
667d81537f4SRobert Mustacchi if (stat(arg, &st) == 0) {
668d81537f4SRobert Mustacchi if (S_ISCHR(st.st_mode)) {
669d81537f4SRobert Mustacchi return (arg);
670d81537f4SRobert Mustacchi }
671d81537f4SRobert Mustacchi }
672d81537f4SRobert Mustacchi
673d81537f4SRobert Mustacchi if (strncmp(arg, T4_NEXUS_NAME, sizeof (T4_NEXUS_NAME) - 1) == 0) {
674d81537f4SRobert Mustacchi drvlen = sizeof (T4_NEXUS_NAME) - 1;
675d81537f4SRobert Mustacchi } else if (strncmp(arg, T4_PORT_NAME, sizeof (T4_PORT_NAME) - 1) == 0) {
676d81537f4SRobert Mustacchi is_t4nex = B_FALSE;
677d81537f4SRobert Mustacchi drvlen = sizeof (T4_PORT_NAME) - 1;
678d81537f4SRobert Mustacchi } else {
679d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "cannot use device %s: not a character "
680d81537f4SRobert Mustacchi "device or a %s/%s device instance", arg, T4_PORT_NAME,
681d81537f4SRobert Mustacchi T4_NEXUS_NAME);
682d81537f4SRobert Mustacchi }
683d81537f4SRobert Mustacchi
684d81537f4SRobert Mustacchi numptr = arg + drvlen;
685d81537f4SRobert Mustacchi inst = (int)strtonum(numptr, 0, INT_MAX, &errstr);
686d81537f4SRobert Mustacchi if (errstr != NULL) {
687d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse instance number '%s': %s",
688d81537f4SRobert Mustacchi numptr, errstr);
689d81537f4SRobert Mustacchi }
690d81537f4SRobert Mustacchi
691d81537f4SRobert Mustacchi /*
692d81537f4SRobert Mustacchi * Now that we have the instance here, we need to truncate the string at
693d81537f4SRobert Mustacchi * the end of the driver name otherwise di_drv_first_node() will be very
694d81537f4SRobert Mustacchi * confused as there is no driver called say 't4nex0'.
695d81537f4SRobert Mustacchi */
696d81537f4SRobert Mustacchi arg[drvlen] = '\0';
697d81537f4SRobert Mustacchi root = di_init("/", DINFOCPYALL);
698d81537f4SRobert Mustacchi if (root == DI_NODE_NIL) {
699d81537f4SRobert Mustacchi err(EXIT_FAILURE, "failed to initialize libdevinfo while "
700d81537f4SRobert Mustacchi "trying to map device name %s", arg);
701d81537f4SRobert Mustacchi }
702d81537f4SRobert Mustacchi
703d81537f4SRobert Mustacchi for (node = di_drv_first_node(arg, root); node != DI_NODE_NIL;
704d81537f4SRobert Mustacchi node = di_drv_next_node(node)) {
705d81537f4SRobert Mustacchi char *bpath;
706d81537f4SRobert Mustacchi di_minor_t minor = DI_MINOR_NIL;
707d81537f4SRobert Mustacchi
708d81537f4SRobert Mustacchi if (di_instance(node) != inst) {
709d81537f4SRobert Mustacchi continue;
710d81537f4SRobert Mustacchi }
711d81537f4SRobert Mustacchi
712d81537f4SRobert Mustacchi if (!is_t4nex) {
713d81537f4SRobert Mustacchi const char *pdrv;
714d81537f4SRobert Mustacchi node = di_parent_node(node);
715d81537f4SRobert Mustacchi pdrv = di_driver_name(node);
716d81537f4SRobert Mustacchi if (pdrv == NULL || strcmp(pdrv, T4_NEXUS_NAME) != 0) {
717d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "%s does not have %s "
718d81537f4SRobert Mustacchi "parent, found %s%d", arg, T4_NEXUS_NAME,
719d81537f4SRobert Mustacchi pdrv != NULL ? pdrv : "unknown",
720d81537f4SRobert Mustacchi pdrv != NULL ? di_instance(node) : -1);
721d81537f4SRobert Mustacchi }
722d81537f4SRobert Mustacchi }
723d81537f4SRobert Mustacchi
724d81537f4SRobert Mustacchi (void) snprintf(mname, sizeof (mname), "%s,%d", T4_NEXUS_NAME,
725d81537f4SRobert Mustacchi di_instance(node));
726d81537f4SRobert Mustacchi
727d81537f4SRobert Mustacchi while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
728d81537f4SRobert Mustacchi if (strcmp(di_minor_name(minor), mname) == 0) {
729d81537f4SRobert Mustacchi break;
730d81537f4SRobert Mustacchi }
731d81537f4SRobert Mustacchi }
732d81537f4SRobert Mustacchi
733d81537f4SRobert Mustacchi if (minor == DI_MINOR_NIL) {
734d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to find minor %s on %s%d",
735d81537f4SRobert Mustacchi mname, di_driver_name(node), di_instance(node));
736d81537f4SRobert Mustacchi }
737d81537f4SRobert Mustacchi
738d81537f4SRobert Mustacchi bpath = di_devfs_minor_path(minor);
739d81537f4SRobert Mustacchi if (bpath == NULL) {
740d81537f4SRobert Mustacchi err(EXIT_FAILURE, "failed to get minor path for "
741d81537f4SRobert Mustacchi "%s%d:%s", di_driver_name(node), di_instance(node),
742d81537f4SRobert Mustacchi di_minor_name(minor));
743d81537f4SRobert Mustacchi }
744d81537f4SRobert Mustacchi if (snprintf(cxgbetool_nexus, sizeof (cxgbetool_nexus),
745d81537f4SRobert Mustacchi "/devices%s", bpath) >= sizeof (cxgbetool_nexus)) {
746d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to construct full /devices "
747d81537f4SRobert Mustacchi "path for %s: internal path buffer would have "
748*6b1325cfSRobert Mustacchi "overflowed", bpath);
749d81537f4SRobert Mustacchi }
750d81537f4SRobert Mustacchi di_devfs_path_free(bpath);
751d81537f4SRobert Mustacchi
752d81537f4SRobert Mustacchi di_fini(root);
753d81537f4SRobert Mustacchi return (cxgbetool_nexus);
754d81537f4SRobert Mustacchi }
755d81537f4SRobert Mustacchi
756d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to map %s%d to a %s or %s instance",
757d81537f4SRobert Mustacchi arg, inst, T4_PORT_NAME, T4_NEXUS_NAME);
758d81537f4SRobert Mustacchi }
759d81537f4SRobert Mustacchi
7605a9113e7SVishal Kulkarni int
main(int argc,char * argv[])7615a9113e7SVishal Kulkarni main(int argc, char *argv[])
7625a9113e7SVishal Kulkarni {
7635a9113e7SVishal Kulkarni const char *iff_name;
7645a9113e7SVishal Kulkarni
7655a9113e7SVishal Kulkarni progname = argv[0];
7665a9113e7SVishal Kulkarni
7675a9113e7SVishal Kulkarni if (argc == 2) {
7685a9113e7SVishal Kulkarni if (strcmp(argv[1], "-h") == 0 ||
7695a9113e7SVishal Kulkarni strcmp(argv[1], "--help") == 0) {
7705a9113e7SVishal Kulkarni usage(stdout);
7715a9113e7SVishal Kulkarni }
7725a9113e7SVishal Kulkarni
7735a9113e7SVishal Kulkarni if (strcmp(argv[1], "-v") == 0 ||
7745a9113e7SVishal Kulkarni strcmp(argv[1], "--version") == 0) {
7755a9113e7SVishal Kulkarni printf("cxgbetool version %s\n", DRV_VERSION);
7765a9113e7SVishal Kulkarni exit(0);
7775a9113e7SVishal Kulkarni }
7785a9113e7SVishal Kulkarni }
7795a9113e7SVishal Kulkarni
7805a9113e7SVishal Kulkarni if (argc < 3)
7815a9113e7SVishal Kulkarni usage(stderr);
7825a9113e7SVishal Kulkarni
783d81537f4SRobert Mustacchi iff_name = cxgbetool_parse_path(argv[1]);
7845a9113e7SVishal Kulkarni
7855a9113e7SVishal Kulkarni run_cmd(argc, argv, iff_name);
7865a9113e7SVishal Kulkarni
7875a9113e7SVishal Kulkarni return (0);
7885a9113e7SVishal Kulkarni }
789