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"
44*fcabbd87SPotnuri Bharat Teja #include "cudbg_entity.h"
457e6ad469SVishal Kulkarni
467e6ad469SVishal Kulkarni #define CUDBG_SIZE (32 * 1024 * 1024)
477e6ad469SVishal Kulkarni #define CUDBG_MAX_ENTITY_STR_LEN 4096
487e6ad469SVishal Kulkarni #define MAX_PARAM_LEN 4096
49*fcabbd87SPotnuri Bharat Teja #ifndef MAX
50*fcabbd87SPotnuri Bharat Teja #define MAX(x, y) ((x) > (y) ? (x) : (y))
51*fcabbd87SPotnuri Bharat Teja #endif
52*fcabbd87SPotnuri Bharat Teja
53*fcabbd87SPotnuri Bharat Teja struct reg_info {
54*fcabbd87SPotnuri Bharat Teja const char *name;
55*fcabbd87SPotnuri Bharat Teja uint32_t addr;
56*fcabbd87SPotnuri Bharat Teja uint32_t len;
57*fcabbd87SPotnuri Bharat Teja };
58*fcabbd87SPotnuri Bharat Teja
59*fcabbd87SPotnuri Bharat Teja struct mod_regs {
60*fcabbd87SPotnuri Bharat Teja const char *name;
61*fcabbd87SPotnuri Bharat Teja const struct reg_info *ri;
62*fcabbd87SPotnuri Bharat Teja unsigned int offset;
63*fcabbd87SPotnuri Bharat Teja };
64*fcabbd87SPotnuri Bharat Teja
65*fcabbd87SPotnuri Bharat Teja #include "reg_defs.h"
667e6ad469SVishal Kulkarni
67d81537f4SRobert Mustacchi static char cxgbetool_nexus[PATH_MAX];
68d81537f4SRobert Mustacchi
697e6ad469SVishal Kulkarni char *option_list[] = {
707e6ad469SVishal Kulkarni "--collect",
717e6ad469SVishal Kulkarni "--view",
727e6ad469SVishal Kulkarni "--version",
737e6ad469SVishal Kulkarni };
747e6ad469SVishal Kulkarni
757e6ad469SVishal Kulkarni enum {
767e6ad469SVishal Kulkarni CUDBG_OPT_COLLECT,
777e6ad469SVishal Kulkarni CUDBG_OPT_VIEW,
787e6ad469SVishal Kulkarni CUDBG_OPT_VERSION,
797e6ad469SVishal Kulkarni };
805a9113e7SVishal Kulkarni
815a9113e7SVishal Kulkarni /*
825a9113e7SVishal Kulkarni * Firmware Device Log Dumping
835a9113e7SVishal Kulkarni */
845a9113e7SVishal Kulkarni
855a9113e7SVishal Kulkarni static const char * const devlog_level_strings[] = {
865a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_EMERG] = "EMERG",
875a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_CRIT] = "CRIT",
885a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_ERR] = "ERR",
895a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE",
905a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_INFO] = "INFO",
915a9113e7SVishal Kulkarni [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG"
925a9113e7SVishal Kulkarni };
935a9113e7SVishal Kulkarni
945a9113e7SVishal Kulkarni static const char * const devlog_facility_strings[] = {
955a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CORE] = "CORE",
965a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CF] = "CF",
975a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_SCHED] = "SCHED",
985a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_TIMER] = "TIMER",
995a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_RES] = "RES",
1005a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_HW] = "HW",
1015a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FLR] = "FLR",
1025a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ",
1035a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_PHY] = "PHY",
1045a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_MAC] = "MAC",
1055a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_PORT] = "PORT",
1065a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_VI] = "VI",
1075a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FILTER] = "FILTER",
1085a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ACL] = "ACL",
1095a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_TM] = "TM",
1105a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_QFC] = "QFC",
1115a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_DCB] = "DCB",
1125a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ETH] = "ETH",
1135a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_OFLD] = "OFLD",
1145a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_RI] = "RI",
1155a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI",
1165a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FCOE] = "FCOE",
1175a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI",
1185a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE",
1195a9113e7SVishal Kulkarni [FW_DEVLOG_FACILITY_CHNET] = "CHNET",
1205a9113e7SVishal Kulkarni };
1215a9113e7SVishal Kulkarni
1225a9113e7SVishal Kulkarni static const char *progname;
1237e6ad469SVishal Kulkarni int set_dbg_entity(u8 *dbg_bitmap, char *dbg_entity_list);
1247e6ad469SVishal Kulkarni
check_option(char * opt)1257e6ad469SVishal Kulkarni static int check_option(char *opt)
1267e6ad469SVishal Kulkarni {
1277e6ad469SVishal Kulkarni int i;
1287e6ad469SVishal Kulkarni
1297e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(option_list); i++) {
1307e6ad469SVishal Kulkarni if (!strcmp(opt, option_list[i]))
1317e6ad469SVishal Kulkarni return i;
1327e6ad469SVishal Kulkarni }
1337e6ad469SVishal Kulkarni return -1;
1347e6ad469SVishal Kulkarni }
1355a9113e7SVishal Kulkarni
usage(FILE * fp)1365a9113e7SVishal Kulkarni static void usage(FILE *fp)
1375a9113e7SVishal Kulkarni {
138d81537f4SRobert Mustacchi fprintf(fp, "Usage: %s <t4nex# | cxgbe#> [operation]\n", progname);
1395a9113e7SVishal Kulkarni fprintf(fp,
1405a9113e7SVishal Kulkarni "\tdevlog show device log\n"
1417e6ad469SVishal Kulkarni "\tloadfw <FW image> Flash the FW image\n"
142*fcabbd87SPotnuri Bharat Teja "\tcudbg <option> [<args>] Chelsio Unified Debugger\n"
143*fcabbd87SPotnuri Bharat Teja "\tregdump [<module>] Dump registers\n"
144*fcabbd87SPotnuri Bharat Teja "\treg <address>[=<val>] Read or write the registers\n");
1455a9113e7SVishal Kulkarni exit(fp == stderr ? 1 : 0);
1465a9113e7SVishal Kulkarni }
1475a9113e7SVishal Kulkarni
1485a9113e7SVishal Kulkarni static int
doit(const char * iff_name,unsigned long cmd,void * data)1495a9113e7SVishal Kulkarni doit(const char *iff_name, unsigned long cmd, void *data)
1505a9113e7SVishal Kulkarni {
1515a9113e7SVishal Kulkarni int fd = 0;
1525a9113e7SVishal Kulkarni int rc = 0;
1535a9113e7SVishal Kulkarni
1545a9113e7SVishal Kulkarni if ((fd = open(iff_name, O_RDWR)) < 0)
1555a9113e7SVishal Kulkarni return (-1);
1565a9113e7SVishal Kulkarni
1575a9113e7SVishal Kulkarni rc = (ioctl(fd, cmd, data) < 0) ? errno : rc;
1585a9113e7SVishal Kulkarni close(fd);
1595a9113e7SVishal Kulkarni return (rc);
1605a9113e7SVishal Kulkarni }
1615a9113e7SVishal Kulkarni
1625a9113e7SVishal Kulkarni static void
get_devlog(int argc,char * argv[],int start_arg,const char * iff_name)1635a9113e7SVishal Kulkarni get_devlog(int argc, char *argv[], int start_arg, const char *iff_name)
1645a9113e7SVishal Kulkarni {
1655a9113e7SVishal Kulkarni struct t4_devlog *devlog;
1665a9113e7SVishal Kulkarni struct fw_devlog_e *entry, *buf;
1675a9113e7SVishal Kulkarni int rc = 0, first = 0, nentries, i, j, len;
1685a9113e7SVishal Kulkarni uint64_t ftstamp = UINT64_MAX;
1695a9113e7SVishal Kulkarni
1705a9113e7SVishal Kulkarni devlog = malloc(T4_DEVLOG_SIZE + sizeof (struct t4_devlog));
1715a9113e7SVishal Kulkarni if (!devlog)
1725a9113e7SVishal Kulkarni err(1, "%s: can't allocate devlog buffer", __func__);
1735a9113e7SVishal Kulkarni
1745a9113e7SVishal Kulkarni devlog->len = T4_DEVLOG_SIZE;
1755a9113e7SVishal Kulkarni /* Get device log */
1765a9113e7SVishal Kulkarni rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog);
1775a9113e7SVishal Kulkarni if (rc == ENOBUFS) {
1785a9113e7SVishal Kulkarni /*
1795a9113e7SVishal Kulkarni * Default buffer size is not sufficient to hold device log.
1805a9113e7SVishal Kulkarni * Driver has updated the devlog.len to indicate the expected
1815a9113e7SVishal Kulkarni * size. Free the currently allocated devlog.data, allocate
1825a9113e7SVishal Kulkarni * again with right size and retry.
1835a9113e7SVishal Kulkarni */
1845a9113e7SVishal Kulkarni len = devlog->len;
1855a9113e7SVishal Kulkarni free(devlog);
1865a9113e7SVishal Kulkarni
1875a9113e7SVishal Kulkarni if ((devlog = malloc(len + sizeof (struct t4_devlog))) == NULL)
1885a9113e7SVishal Kulkarni err(1, "%s: can't reallocate devlog buffer", __func__);
1895a9113e7SVishal Kulkarni
1905a9113e7SVishal Kulkarni rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog);
1915a9113e7SVishal Kulkarni }
1925a9113e7SVishal Kulkarni if (rc) {
1935a9113e7SVishal Kulkarni free(devlog);
19465ecf399SYuri Pankov errx(1, "%s: can't get device log", __func__);
1955a9113e7SVishal Kulkarni }
1965a9113e7SVishal Kulkarni
1975a9113e7SVishal Kulkarni /* There are nentries number of entries in the buffer */
1985a9113e7SVishal Kulkarni nentries = (devlog->len / sizeof (struct fw_devlog_e));
1995a9113e7SVishal Kulkarni
2005a9113e7SVishal Kulkarni buf = (struct fw_devlog_e *)devlog->data;
2015a9113e7SVishal Kulkarni
2025a9113e7SVishal Kulkarni /* Find the first entry */
2035a9113e7SVishal Kulkarni for (i = 0; i < nentries; i++) {
2045a9113e7SVishal Kulkarni entry = &buf[i];
2055a9113e7SVishal Kulkarni
2065a9113e7SVishal Kulkarni if (entry->timestamp == 0)
2075a9113e7SVishal Kulkarni break;
2085a9113e7SVishal Kulkarni
2095a9113e7SVishal Kulkarni entry->timestamp = BE_64(entry->timestamp);
2105a9113e7SVishal Kulkarni entry->seqno = BE_32(entry->seqno);
2115a9113e7SVishal Kulkarni for (j = 0; j < 8; j++)
2125a9113e7SVishal Kulkarni entry->params[j] = BE_32(entry->params[j]);
2135a9113e7SVishal Kulkarni
2145a9113e7SVishal Kulkarni if (entry->timestamp < ftstamp) {
2155a9113e7SVishal Kulkarni ftstamp = entry->timestamp;
2165a9113e7SVishal Kulkarni first = i;
2175a9113e7SVishal Kulkarni }
2185a9113e7SVishal Kulkarni }
2195a9113e7SVishal Kulkarni
2205a9113e7SVishal Kulkarni printf("%10s %15s %8s %8s %s\n", "Seq#", "Tstamp", "Level",
2215a9113e7SVishal Kulkarni "Facility", "Message");
2225a9113e7SVishal Kulkarni
2235a9113e7SVishal Kulkarni i = first;
2245a9113e7SVishal Kulkarni
2255a9113e7SVishal Kulkarni do {
2265a9113e7SVishal Kulkarni entry = &buf[i];
2275a9113e7SVishal Kulkarni
2285a9113e7SVishal Kulkarni if (entry->timestamp == 0)
2295a9113e7SVishal Kulkarni break;
2305a9113e7SVishal Kulkarni
2315a9113e7SVishal Kulkarni printf("%10d %15llu %8s %8s ", entry->seqno,
2325a9113e7SVishal Kulkarni entry->timestamp,
2335a9113e7SVishal Kulkarni (entry->level < ARRAY_SIZE(devlog_level_strings) ?
2345a9113e7SVishal Kulkarni devlog_level_strings[entry->level] : "UNKNOWN"),
2355a9113e7SVishal Kulkarni (entry->facility < ARRAY_SIZE(devlog_facility_strings) ?
2365a9113e7SVishal Kulkarni devlog_facility_strings[entry->facility] : "UNKNOWN"));
2375a9113e7SVishal Kulkarni
2385a9113e7SVishal Kulkarni printf((const char *)entry->fmt, entry->params[0],
2395a9113e7SVishal Kulkarni entry->params[1], entry->params[2], entry->params[3],
2405a9113e7SVishal Kulkarni entry->params[4], entry->params[5], entry->params[6],
2415a9113e7SVishal Kulkarni entry->params[7]);
2425a9113e7SVishal Kulkarni
2435a9113e7SVishal Kulkarni if (++i == nentries)
2445a9113e7SVishal Kulkarni i = 0;
2455a9113e7SVishal Kulkarni
2465a9113e7SVishal Kulkarni } while (i != first);
2475a9113e7SVishal Kulkarni
2485a9113e7SVishal Kulkarni free(devlog);
2495a9113e7SVishal Kulkarni }
2505a9113e7SVishal Kulkarni
xtract(uint32_t val,int shift,int len)251*fcabbd87SPotnuri Bharat Teja static uint32_t xtract(uint32_t val, int shift, int len)
252*fcabbd87SPotnuri Bharat Teja {
253*fcabbd87SPotnuri Bharat Teja return (val >> shift) & ((1 << len) - 1);
254*fcabbd87SPotnuri Bharat Teja }
255*fcabbd87SPotnuri Bharat Teja
dump_block_regs(const struct reg_info * reg_array,const u32 * regs)256*fcabbd87SPotnuri Bharat Teja int dump_block_regs(const struct reg_info *reg_array, const u32 *regs)
257*fcabbd87SPotnuri Bharat Teja {
258*fcabbd87SPotnuri Bharat Teja uint32_t reg_val = 0;
259*fcabbd87SPotnuri Bharat Teja
260*fcabbd87SPotnuri Bharat Teja for ( ; reg_array->name; ++reg_array) {
261*fcabbd87SPotnuri Bharat Teja if (!reg_array->len) {
262*fcabbd87SPotnuri Bharat Teja reg_val = regs[reg_array->addr / 4];
263*fcabbd87SPotnuri Bharat Teja printf("[%#7x] %-47s %#-10x %u\n", reg_array->addr,
264*fcabbd87SPotnuri Bharat Teja reg_array->name, reg_val, reg_val);
265*fcabbd87SPotnuri Bharat Teja } else {
266*fcabbd87SPotnuri Bharat Teja uint32_t v = xtract(reg_val, reg_array->addr,
267*fcabbd87SPotnuri Bharat Teja reg_array->len);
268*fcabbd87SPotnuri Bharat Teja printf(" %*u:%u %-47s %#-10x %u\n",
269*fcabbd87SPotnuri Bharat Teja reg_array->addr < 10 ? 3 : 2,
270*fcabbd87SPotnuri Bharat Teja reg_array->addr + reg_array->len - 1,
271*fcabbd87SPotnuri Bharat Teja reg_array->addr, reg_array->name, v, v);
272*fcabbd87SPotnuri Bharat Teja }
273*fcabbd87SPotnuri Bharat Teja }
274*fcabbd87SPotnuri Bharat Teja return 1;
275*fcabbd87SPotnuri Bharat Teja }
276*fcabbd87SPotnuri Bharat Teja
dump_regs_table(int argc,char * argv[],int start_arg,const u32 * regs,const struct mod_regs * modtab,int nmodules,const char * modnames)277*fcabbd87SPotnuri Bharat Teja int dump_regs_table(int argc, char *argv[], int start_arg,
278*fcabbd87SPotnuri Bharat Teja const u32 *regs, const struct mod_regs *modtab,
279*fcabbd87SPotnuri Bharat Teja int nmodules, const char *modnames)
280*fcabbd87SPotnuri Bharat Teja {
281*fcabbd87SPotnuri Bharat Teja int match = 0;
282*fcabbd87SPotnuri Bharat Teja const char *block_name = NULL;
283*fcabbd87SPotnuri Bharat Teja
284*fcabbd87SPotnuri Bharat Teja if (argc == start_arg + 1)
285*fcabbd87SPotnuri Bharat Teja block_name = argv[start_arg];
286*fcabbd87SPotnuri Bharat Teja else if (argc != start_arg)
287*fcabbd87SPotnuri Bharat Teja return -1;
288*fcabbd87SPotnuri Bharat Teja
289*fcabbd87SPotnuri Bharat Teja for ( ; nmodules; nmodules--, modtab++) {
290*fcabbd87SPotnuri Bharat Teja if (!block_name || !strcmp(block_name, modtab->name))
291*fcabbd87SPotnuri Bharat Teja match += dump_block_regs(modtab->ri,
292*fcabbd87SPotnuri Bharat Teja regs + modtab->offset);
293*fcabbd87SPotnuri Bharat Teja }
294*fcabbd87SPotnuri Bharat Teja if (!match)
295*fcabbd87SPotnuri Bharat Teja errx(1, "unknown block \"%s\"\navailable: %s", block_name,
296*fcabbd87SPotnuri Bharat Teja modnames);
297*fcabbd87SPotnuri Bharat Teja return 0;
298*fcabbd87SPotnuri Bharat Teja }
299*fcabbd87SPotnuri Bharat Teja
300*fcabbd87SPotnuri Bharat Teja #define T5_MODREGS(name) { #name, t5_##name##_regs }
301*fcabbd87SPotnuri Bharat Teja static int
dump_regs_t5(int argc,char * argv[],int start_arg,uint32_t * regs)302*fcabbd87SPotnuri Bharat Teja dump_regs_t5(int argc, char *argv[], int start_arg, uint32_t *regs)
303*fcabbd87SPotnuri Bharat Teja {
304*fcabbd87SPotnuri Bharat Teja static struct mod_regs t5_mod[] = {
305*fcabbd87SPotnuri Bharat Teja T5_MODREGS(sge),
306*fcabbd87SPotnuri Bharat Teja { "pci", t5_pcie_regs },
307*fcabbd87SPotnuri Bharat Teja T5_MODREGS(dbg),
308*fcabbd87SPotnuri Bharat Teja { "mc0", t5_mc_0_regs },
309*fcabbd87SPotnuri Bharat Teja { "mc1", t5_mc_1_regs },
310*fcabbd87SPotnuri Bharat Teja T5_MODREGS(ma),
311*fcabbd87SPotnuri Bharat Teja { "edc0", t5_edc_t50_regs },
312*fcabbd87SPotnuri Bharat Teja { "edc1", t5_edc_t51_regs },
313*fcabbd87SPotnuri Bharat Teja T5_MODREGS(cim),
314*fcabbd87SPotnuri Bharat Teja T5_MODREGS(tp),
315*fcabbd87SPotnuri Bharat Teja { "ulprx", t5_ulp_rx_regs },
316*fcabbd87SPotnuri Bharat Teja { "ulptx", t5_ulp_tx_regs },
317*fcabbd87SPotnuri Bharat Teja { "pmrx", t5_pm_rx_regs },
318*fcabbd87SPotnuri Bharat Teja { "pmtx", t5_pm_tx_regs },
319*fcabbd87SPotnuri Bharat Teja T5_MODREGS(mps),
320*fcabbd87SPotnuri Bharat Teja { "cplsw", t5_cpl_switch_regs },
321*fcabbd87SPotnuri Bharat Teja T5_MODREGS(smb),
322*fcabbd87SPotnuri Bharat Teja { "i2c", t5_i2cm_regs },
323*fcabbd87SPotnuri Bharat Teja T5_MODREGS(mi),
324*fcabbd87SPotnuri Bharat Teja T5_MODREGS(uart),
325*fcabbd87SPotnuri Bharat Teja T5_MODREGS(pmu),
326*fcabbd87SPotnuri Bharat Teja T5_MODREGS(sf),
327*fcabbd87SPotnuri Bharat Teja T5_MODREGS(pl),
328*fcabbd87SPotnuri Bharat Teja T5_MODREGS(le),
329*fcabbd87SPotnuri Bharat Teja T5_MODREGS(ncsi),
330*fcabbd87SPotnuri Bharat Teja T5_MODREGS(mac),
331*fcabbd87SPotnuri Bharat Teja { "hma", t5_hma_t5_regs }
332*fcabbd87SPotnuri Bharat Teja };
333*fcabbd87SPotnuri Bharat Teja
334*fcabbd87SPotnuri Bharat Teja return dump_regs_table(argc, argv, start_arg, regs, t5_mod,
335*fcabbd87SPotnuri Bharat Teja ARRAY_SIZE(t5_mod),
336*fcabbd87SPotnuri Bharat Teja "sge, pci, dbg, mc0, mc1, ma, edc0, edc1, cim, "
337*fcabbd87SPotnuri Bharat Teja "tp, ulprx, ulptx, pmrx, pmtx, mps, cplsw, smb, "
338*fcabbd87SPotnuri Bharat Teja "i2c, mi, uart, pmu, sf, pl, le, ncsi, "
339*fcabbd87SPotnuri Bharat Teja "mac, hma");
340*fcabbd87SPotnuri Bharat Teja }
341*fcabbd87SPotnuri Bharat Teja
342*fcabbd87SPotnuri Bharat Teja #undef T5_MODREGS
343*fcabbd87SPotnuri Bharat Teja
344*fcabbd87SPotnuri Bharat Teja #define T6_MODREGS(name) { #name, t6_##name##_regs }
dump_regs_t6(int argc,char * argv[],int start_arg,const u32 * regs)345*fcabbd87SPotnuri Bharat Teja static int dump_regs_t6(int argc, char *argv[], int start_arg, const u32 *regs)
346*fcabbd87SPotnuri Bharat Teja {
347*fcabbd87SPotnuri Bharat Teja static struct mod_regs t6_mod[] = {
348*fcabbd87SPotnuri Bharat Teja T6_MODREGS(sge),
349*fcabbd87SPotnuri Bharat Teja { "pci", t6_pcie_regs },
350*fcabbd87SPotnuri Bharat Teja T6_MODREGS(dbg),
351*fcabbd87SPotnuri Bharat Teja { "mc0", t6_mc_0_regs },
352*fcabbd87SPotnuri Bharat Teja T6_MODREGS(ma),
353*fcabbd87SPotnuri Bharat Teja { "edc0", t6_edc_t60_regs },
354*fcabbd87SPotnuri Bharat Teja { "edc1", t6_edc_t61_regs },
355*fcabbd87SPotnuri Bharat Teja T6_MODREGS(cim),
356*fcabbd87SPotnuri Bharat Teja T6_MODREGS(tp),
357*fcabbd87SPotnuri Bharat Teja { "ulprx", t6_ulp_rx_regs },
358*fcabbd87SPotnuri Bharat Teja { "ulptx", t6_ulp_tx_regs },
359*fcabbd87SPotnuri Bharat Teja { "pmrx", t6_pm_rx_regs },
360*fcabbd87SPotnuri Bharat Teja { "pmtx", t6_pm_tx_regs },
361*fcabbd87SPotnuri Bharat Teja T6_MODREGS(mps),
362*fcabbd87SPotnuri Bharat Teja { "cplsw", t6_cpl_switch_regs },
363*fcabbd87SPotnuri Bharat Teja T6_MODREGS(smb),
364*fcabbd87SPotnuri Bharat Teja { "i2c", t6_i2cm_regs },
365*fcabbd87SPotnuri Bharat Teja T6_MODREGS(mi),
366*fcabbd87SPotnuri Bharat Teja T6_MODREGS(uart),
367*fcabbd87SPotnuri Bharat Teja T6_MODREGS(pmu),
368*fcabbd87SPotnuri Bharat Teja T6_MODREGS(sf),
369*fcabbd87SPotnuri Bharat Teja T6_MODREGS(pl),
370*fcabbd87SPotnuri Bharat Teja T6_MODREGS(le),
371*fcabbd87SPotnuri Bharat Teja T6_MODREGS(ncsi),
372*fcabbd87SPotnuri Bharat Teja T6_MODREGS(mac),
373*fcabbd87SPotnuri Bharat Teja { "hma", t6_hma_t6_regs }
374*fcabbd87SPotnuri Bharat Teja };
375*fcabbd87SPotnuri Bharat Teja
376*fcabbd87SPotnuri Bharat Teja return dump_regs_table(argc, argv, start_arg, regs, t6_mod,
377*fcabbd87SPotnuri Bharat Teja ARRAY_SIZE(t6_mod),
378*fcabbd87SPotnuri Bharat Teja "sge, pci, dbg, mc0, ma, edc0, edc1, cim, "
379*fcabbd87SPotnuri Bharat Teja "tp, ulprx, ulptx, pmrx, pmtx, mps, cplsw, smb, "
380*fcabbd87SPotnuri Bharat Teja "i2c, mi, uart, pmu, sf, pl, le, ncsi, "
381*fcabbd87SPotnuri Bharat Teja "mac, hma");
382*fcabbd87SPotnuri Bharat Teja }
383*fcabbd87SPotnuri Bharat Teja #undef T6_MODREGS
384*fcabbd87SPotnuri Bharat Teja
385*fcabbd87SPotnuri Bharat Teja static int
get_regdump(int argc,char * argv[],int start_arg,const char * iff_name)386*fcabbd87SPotnuri Bharat Teja get_regdump(int argc, char *argv[], int start_arg, const char *iff_name)
387*fcabbd87SPotnuri Bharat Teja {
388*fcabbd87SPotnuri Bharat Teja int rc, vers, revision, is_pcie;
389*fcabbd87SPotnuri Bharat Teja uint32_t len, length;
390*fcabbd87SPotnuri Bharat Teja struct t4_regdump *regs;
391*fcabbd87SPotnuri Bharat Teja
392*fcabbd87SPotnuri Bharat Teja len = MAX(T5_REGDUMP_SIZE, T6_REGDUMP_SIZE);
393*fcabbd87SPotnuri Bharat Teja
394*fcabbd87SPotnuri Bharat Teja regs = malloc(len + sizeof(struct t4_regdump));
395*fcabbd87SPotnuri Bharat Teja if (!regs)
396*fcabbd87SPotnuri Bharat Teja err(1, "%s: can't allocate reg dump buffer", __func__);
397*fcabbd87SPotnuri Bharat Teja
398*fcabbd87SPotnuri Bharat Teja regs->len = len;
399*fcabbd87SPotnuri Bharat Teja
400*fcabbd87SPotnuri Bharat Teja rc = doit(iff_name, T4_IOCTL_REGDUMP, regs);
401*fcabbd87SPotnuri Bharat Teja
402*fcabbd87SPotnuri Bharat Teja if (rc == ENOBUFS) {
403*fcabbd87SPotnuri Bharat Teja length = regs->len;
404*fcabbd87SPotnuri Bharat Teja free(regs);
405*fcabbd87SPotnuri Bharat Teja
406*fcabbd87SPotnuri Bharat Teja regs = malloc(length + sizeof(struct t4_regdump));
407*fcabbd87SPotnuri Bharat Teja if (regs == NULL)
408*fcabbd87SPotnuri Bharat Teja err(1, "%s: can't reallocate regs buffer", __func__);
409*fcabbd87SPotnuri Bharat Teja
410*fcabbd87SPotnuri Bharat Teja rc = doit(iff_name, T4_IOCTL_REGDUMP, regs);
411*fcabbd87SPotnuri Bharat Teja }
412*fcabbd87SPotnuri Bharat Teja
413*fcabbd87SPotnuri Bharat Teja if (rc) {
414*fcabbd87SPotnuri Bharat Teja free(regs);
415*fcabbd87SPotnuri Bharat Teja errx(1, "%s: can't get register dumps", __func__);
416*fcabbd87SPotnuri Bharat Teja }
417*fcabbd87SPotnuri Bharat Teja
418*fcabbd87SPotnuri Bharat Teja vers = regs->version & 0x3ff;
419*fcabbd87SPotnuri Bharat Teja revision = (regs->version >> 10) & 0x3f;
420*fcabbd87SPotnuri Bharat Teja is_pcie = (regs->version & 0x80000000) != 0;
421*fcabbd87SPotnuri Bharat Teja
422*fcabbd87SPotnuri Bharat Teja if (vers == 5) {
423*fcabbd87SPotnuri Bharat Teja return dump_regs_t5(argc, argv, start_arg,
424*fcabbd87SPotnuri Bharat Teja (uint32_t *)regs->data);
425*fcabbd87SPotnuri Bharat Teja } else if (vers == 6) {
426*fcabbd87SPotnuri Bharat Teja return dump_regs_t6(argc, argv, start_arg,
427*fcabbd87SPotnuri Bharat Teja (uint32_t *)regs->data);
428*fcabbd87SPotnuri Bharat Teja } else {
429*fcabbd87SPotnuri Bharat Teja errx(1, "unknown card type %d.%d.%d", vers, revision, is_pcie);
430*fcabbd87SPotnuri Bharat Teja }
431*fcabbd87SPotnuri Bharat Teja
432*fcabbd87SPotnuri Bharat Teja return 0;
433*fcabbd87SPotnuri Bharat Teja }
434*fcabbd87SPotnuri Bharat Teja
435*fcabbd87SPotnuri Bharat Teja static void
write_reg(const char * iff_name,uint32_t addr,uint32_t val)436*fcabbd87SPotnuri Bharat Teja write_reg(const char *iff_name, uint32_t addr, uint32_t val)
437*fcabbd87SPotnuri Bharat Teja {
438*fcabbd87SPotnuri Bharat Teja struct t4_reg32_cmd reg;
439*fcabbd87SPotnuri Bharat Teja
440*fcabbd87SPotnuri Bharat Teja reg.reg = addr;
441*fcabbd87SPotnuri Bharat Teja reg.value = val;
442*fcabbd87SPotnuri Bharat Teja
443*fcabbd87SPotnuri Bharat Teja if (doit(iff_name, T4_IOCTL_PUT32, ®) < 0)
444*fcabbd87SPotnuri Bharat Teja err(1, "register write");
445*fcabbd87SPotnuri Bharat Teja }
446*fcabbd87SPotnuri Bharat Teja
447*fcabbd87SPotnuri Bharat Teja static uint32_t
read_reg(const char * iff_name,uint32_t addr)448*fcabbd87SPotnuri Bharat Teja read_reg(const char *iff_name, uint32_t addr)
449*fcabbd87SPotnuri Bharat Teja {
450*fcabbd87SPotnuri Bharat Teja struct t4_reg32_cmd reg;
451*fcabbd87SPotnuri Bharat Teja
452*fcabbd87SPotnuri Bharat Teja reg.reg = addr;
453*fcabbd87SPotnuri Bharat Teja
454*fcabbd87SPotnuri Bharat Teja if (doit(iff_name, T4_IOCTL_GET32, ®) < 0)
455*fcabbd87SPotnuri Bharat Teja err(1, "register read");
456*fcabbd87SPotnuri Bharat Teja return reg.value;
457*fcabbd87SPotnuri Bharat Teja }
458*fcabbd87SPotnuri Bharat Teja
register_io(int argc,char * argv[],int start_arg,const char * iff_name)459*fcabbd87SPotnuri Bharat Teja static void register_io(int argc, char *argv[], int start_arg,
460*fcabbd87SPotnuri Bharat Teja const char *iff_name)
461*fcabbd87SPotnuri Bharat Teja {
462*fcabbd87SPotnuri Bharat Teja char *p;
463*fcabbd87SPotnuri Bharat Teja uint32_t addr = 0, val = 0, write = 0;
464*fcabbd87SPotnuri Bharat Teja
465*fcabbd87SPotnuri Bharat Teja if (argc != start_arg + 1) {
466*fcabbd87SPotnuri Bharat Teja errx(1, "incorrect number of arguments");
467*fcabbd87SPotnuri Bharat Teja }
468*fcabbd87SPotnuri Bharat Teja errno = 0;
469*fcabbd87SPotnuri Bharat Teja addr = strtoul(argv[start_arg], &p, 0);
470*fcabbd87SPotnuri Bharat Teja if (addr == 0 || errno != 0) {
471*fcabbd87SPotnuri Bharat Teja errx(1, "invalid arguments");
472*fcabbd87SPotnuri Bharat Teja }
473*fcabbd87SPotnuri Bharat Teja
474*fcabbd87SPotnuri Bharat Teja if (p == argv[start_arg])
475*fcabbd87SPotnuri Bharat Teja return;
476*fcabbd87SPotnuri Bharat Teja if (*p == '=' && p[1]) {
477*fcabbd87SPotnuri Bharat Teja val = strtoul(p + 1, &p, 0);
478*fcabbd87SPotnuri Bharat Teja write = 1;
479*fcabbd87SPotnuri Bharat Teja }
480*fcabbd87SPotnuri Bharat Teja if (*p) {
481*fcabbd87SPotnuri Bharat Teja errx(1, "bad parameter \"%s\"", argv[start_arg]);
482*fcabbd87SPotnuri Bharat Teja }
483*fcabbd87SPotnuri Bharat Teja
484*fcabbd87SPotnuri Bharat Teja if (write) {
485*fcabbd87SPotnuri Bharat Teja write_reg(iff_name, addr, val);
486*fcabbd87SPotnuri Bharat Teja } else {
487*fcabbd87SPotnuri Bharat Teja val = read_reg(iff_name, addr);
488*fcabbd87SPotnuri Bharat Teja printf("%#x [%u]\n", val, val);
489*fcabbd87SPotnuri Bharat Teja }
490*fcabbd87SPotnuri Bharat Teja }
491*fcabbd87SPotnuri Bharat Teja
4925a9113e7SVishal Kulkarni static void
load_fw(int argc,char * argv[],int start_arg,const char * iff_name)4935a9113e7SVishal Kulkarni load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
4945a9113e7SVishal Kulkarni {
4955a9113e7SVishal Kulkarni const char *fname = argv[start_arg];
4965a9113e7SVishal Kulkarni struct t4_ldfw *fw;
4975a9113e7SVishal Kulkarni struct stat sb;
4985a9113e7SVishal Kulkarni size_t len;
4995a9113e7SVishal Kulkarni int fd;
5005a9113e7SVishal Kulkarni
5015a9113e7SVishal Kulkarni if (argc != 4)
50265ecf399SYuri Pankov errx(1, "incorrect number of arguments");
5035a9113e7SVishal Kulkarni
5045a9113e7SVishal Kulkarni fd = open(fname, O_RDONLY);
5055a9113e7SVishal Kulkarni if (fd < 0)
5065a9113e7SVishal Kulkarni err(1, "%s: opening %s failed", __func__, fname);
5075a9113e7SVishal Kulkarni if (fstat(fd, &sb) < 0) {
50865ecf399SYuri Pankov warn("%s: fstat %s failed", __func__, fname);
5095a9113e7SVishal Kulkarni close(fd);
51065ecf399SYuri Pankov exit(1);
5115a9113e7SVishal Kulkarni }
5125a9113e7SVishal Kulkarni len = (size_t)sb.st_size;
5135a9113e7SVishal Kulkarni
5145a9113e7SVishal Kulkarni fw = malloc(sizeof (struct t4_ldfw) + len);
5155a9113e7SVishal Kulkarni if (!fw) {
5166b1325cfSRobert Mustacchi warn("%s: %s allocate %zu bytes failed",
5175a9113e7SVishal Kulkarni __func__, fname, sizeof (struct t4_ldfw) + len);
51865ecf399SYuri Pankov close(fd);
51965ecf399SYuri Pankov exit(1);
5205a9113e7SVishal Kulkarni }
5215a9113e7SVishal Kulkarni
5225a9113e7SVishal Kulkarni if (read(fd, fw->data, len) < len) {
52365ecf399SYuri Pankov warn("%s: %s read failed", __func__, fname);
5245a9113e7SVishal Kulkarni close(fd);
5255a9113e7SVishal Kulkarni free(fw);
52665ecf399SYuri Pankov exit(1);
5275a9113e7SVishal Kulkarni }
5285a9113e7SVishal Kulkarni
5295a9113e7SVishal Kulkarni close(fd);
5305a9113e7SVishal Kulkarni
5315a9113e7SVishal Kulkarni fw->len = len;
5325a9113e7SVishal Kulkarni
5335a9113e7SVishal Kulkarni if (doit(iff_name, T4_IOCTL_LOAD_FW, fw)) {
5345a9113e7SVishal Kulkarni free(fw);
5355a9113e7SVishal Kulkarni err(1, "%s: IOCTL failed", __func__);
5365a9113e7SVishal Kulkarni } else {
5375a9113e7SVishal Kulkarni printf("FW flash success, reload driver/reboot to take "
5385a9113e7SVishal Kulkarni "effect\n");
5395a9113e7SVishal Kulkarni }
5405a9113e7SVishal Kulkarni
5415a9113e7SVishal Kulkarni free(fw);
5425a9113e7SVishal Kulkarni }
5435a9113e7SVishal Kulkarni
read_input_file(char * in_file,void ** buf,int * buf_size)5447e6ad469SVishal Kulkarni int read_input_file(char *in_file, void **buf, int *buf_size)
5457e6ad469SVishal Kulkarni {
5467e6ad469SVishal Kulkarni FILE *fptr = NULL;
5477e6ad469SVishal Kulkarni size_t count;
5487e6ad469SVishal Kulkarni int rc = 0;
5497e6ad469SVishal Kulkarni
5507e6ad469SVishal Kulkarni fptr = fopen(in_file, "rb");
5517e6ad469SVishal Kulkarni if (!fptr) {
5527e6ad469SVishal Kulkarni perror("error in opening file ");
5537e6ad469SVishal Kulkarni rc = -1;
5547e6ad469SVishal Kulkarni goto out;
5557e6ad469SVishal Kulkarni }
5567e6ad469SVishal Kulkarni rc = fseek(fptr, 0, SEEK_END);
5577e6ad469SVishal Kulkarni if (rc < 0) {
5587e6ad469SVishal Kulkarni perror("error in seeking file ");
5597e6ad469SVishal Kulkarni rc = -1;
5607e6ad469SVishal Kulkarni goto out;
5617e6ad469SVishal Kulkarni }
5627e6ad469SVishal Kulkarni *buf_size = ftell(fptr);
5637e6ad469SVishal Kulkarni rc = fseek(fptr, 0, SEEK_SET);
5647e6ad469SVishal Kulkarni if (rc < 0) {
5657e6ad469SVishal Kulkarni perror("error in seeking file ");
5667e6ad469SVishal Kulkarni rc = -1;
5677e6ad469SVishal Kulkarni goto out;
5687e6ad469SVishal Kulkarni }
5697e6ad469SVishal Kulkarni *buf = (void *) malloc(*buf_size);
5707e6ad469SVishal Kulkarni if (*buf == NULL) {
5717e6ad469SVishal Kulkarni rc = CUDBG_STATUS_NOSPACE;
5727e6ad469SVishal Kulkarni goto out;
5737e6ad469SVishal Kulkarni }
5747e6ad469SVishal Kulkarni memset(*buf, 0, *buf_size);
5757e6ad469SVishal Kulkarni
5767e6ad469SVishal Kulkarni count = fread(*buf, 1, *buf_size, fptr);
5777e6ad469SVishal Kulkarni if (count != *buf_size) {
5787e6ad469SVishal Kulkarni perror("error in reading from file ");
5797e6ad469SVishal Kulkarni goto out;
5807e6ad469SVishal Kulkarni }
5817e6ad469SVishal Kulkarni
5827e6ad469SVishal Kulkarni out:
5837e6ad469SVishal Kulkarni if (fptr)
5847e6ad469SVishal Kulkarni fclose(fptr);
5857e6ad469SVishal Kulkarni
5867e6ad469SVishal Kulkarni return rc;
5877e6ad469SVishal Kulkarni }
5887e6ad469SVishal Kulkarni
5897e6ad469SVishal Kulkarni static void
do_collect(char * dbg_entity_list,const char * iff_name,const char * fname)5907e6ad469SVishal Kulkarni do_collect(char *dbg_entity_list, const char *iff_name, const char *fname)
5917e6ad469SVishal Kulkarni {
5927e6ad469SVishal Kulkarni struct t4_cudbg_dump *cudbg;
5937e6ad469SVishal Kulkarni int fd;
5947e6ad469SVishal Kulkarni
5957e6ad469SVishal Kulkarni cudbg = malloc(sizeof(struct t4_cudbg_dump) + CUDBG_SIZE);
5967e6ad469SVishal Kulkarni if (!cudbg) {
5976b1325cfSRobert Mustacchi err(1, "%s:allocate %d bytes failed", __func__, CUDBG_SIZE);
5987e6ad469SVishal Kulkarni }
5997e6ad469SVishal Kulkarni
6007e6ad469SVishal Kulkarni memset(cudbg, 0, sizeof(struct t4_cudbg_dump) + CUDBG_SIZE);
6017e6ad469SVishal Kulkarni
6027e6ad469SVishal Kulkarni cudbg->len = CUDBG_SIZE;
6037e6ad469SVishal Kulkarni
6047e6ad469SVishal Kulkarni set_dbg_entity(cudbg->bitmap, dbg_entity_list);
6057e6ad469SVishal Kulkarni
6067e6ad469SVishal Kulkarni if (doit(iff_name, T4_IOCTL_GET_CUDBG, cudbg)) {
6077e6ad469SVishal Kulkarni free(cudbg);
6087e6ad469SVishal Kulkarni err(1, "%s: IOCTL failed", __func__);
6097e6ad469SVishal Kulkarni }
6107e6ad469SVishal Kulkarni
6117e6ad469SVishal Kulkarni fd = open(fname, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY,
6127e6ad469SVishal Kulkarni S_IRUSR | S_IRGRP | S_IROTH);
6137e6ad469SVishal Kulkarni if (fd < 0) {
6147e6ad469SVishal Kulkarni err(1, "%s: file open failed", __func__);
6157e6ad469SVishal Kulkarni }
6167e6ad469SVishal Kulkarni
6177e6ad469SVishal Kulkarni write(fd, cudbg->data, cudbg->len);
6187e6ad469SVishal Kulkarni close(fd);
6197e6ad469SVishal Kulkarni free(cudbg);
6207e6ad469SVishal Kulkarni }
6217e6ad469SVishal Kulkarni
6227e6ad469SVishal Kulkarni static void
do_view(char * dbg_entity_list,char * in_file)6237e6ad469SVishal Kulkarni do_view(char *dbg_entity_list, char *in_file)
6247e6ad469SVishal Kulkarni {
6257e6ad469SVishal Kulkarni void *handle = NULL;
6267e6ad469SVishal Kulkarni void *buf = NULL;
6277e6ad469SVishal Kulkarni int buf_size = 32 * 1024 * 1024;
6287e6ad469SVishal Kulkarni int next_offset = 0;
6297e6ad469SVishal Kulkarni int data_len;
6307e6ad469SVishal Kulkarni int rc = 0;
6317e6ad469SVishal Kulkarni
6327e6ad469SVishal Kulkarni handle = cudbg_alloc_handle();
6337e6ad469SVishal Kulkarni if (!handle)
6347e6ad469SVishal Kulkarni goto out;
6357e6ad469SVishal Kulkarni /* rcad from file */
6367e6ad469SVishal Kulkarni rc = read_input_file(in_file, &buf, &buf_size);
6377e6ad469SVishal Kulkarni if (rc < 0) {
6387e6ad469SVishal Kulkarni goto out;
6397e6ad469SVishal Kulkarni }
6407e6ad469SVishal Kulkarni
6417e6ad469SVishal Kulkarni set_dbg_entity(((struct cudbg_private *)handle)->dbg_init.dbg_bitmap,
6427e6ad469SVishal Kulkarni dbg_entity_list);
6437e6ad469SVishal Kulkarni do {
6447e6ad469SVishal Kulkarni if (buf_size - next_offset <= 0)
6457e6ad469SVishal Kulkarni break;
6467e6ad469SVishal Kulkarni
6477e6ad469SVishal Kulkarni data_len = cudbg_view(handle, buf+next_offset,
6487e6ad469SVishal Kulkarni buf_size-next_offset, NULL, 0);
6497e6ad469SVishal Kulkarni next_offset += data_len;
6507e6ad469SVishal Kulkarni if (data_len > 0)
6517e6ad469SVishal Kulkarni printf("\n\t\t<========================END============="\
6527e6ad469SVishal Kulkarni "===========>\t\t\n\n\n");
6537e6ad469SVishal Kulkarni } while (data_len > 0);
6547e6ad469SVishal Kulkarni
6557e6ad469SVishal Kulkarni out:
6567e6ad469SVishal Kulkarni if (buf)
6577e6ad469SVishal Kulkarni free(buf);
6587e6ad469SVishal Kulkarni if (handle)
6597e6ad469SVishal Kulkarni cudbg_free_handle(handle);
6607e6ad469SVishal Kulkarni return;
6617e6ad469SVishal Kulkarni }
6627e6ad469SVishal Kulkarni
6637e6ad469SVishal Kulkarni typedef void (*cudbg_alias_get_entities_cb)(char *dst, u32 dst_size);
6647e6ad469SVishal Kulkarni
6657e6ad469SVishal Kulkarni struct entity_access_list {
6667e6ad469SVishal Kulkarni const char *name;
6677e6ad469SVishal Kulkarni cudbg_alias_get_entities_cb get_entities_cb;
6687e6ad469SVishal Kulkarni };
6697e6ad469SVishal Kulkarni
6707e6ad469SVishal Kulkarni void
cudbg_append_string(char * dst,u32 dst_size,char * src)6717e6ad469SVishal Kulkarni cudbg_append_string(char *dst, u32 dst_size, char *src)
6727e6ad469SVishal Kulkarni {
6737e6ad469SVishal Kulkarni strlcat(dst, src, dst_size);
6747e6ad469SVishal Kulkarni strlcat(dst, ",", dst_size);
6757e6ad469SVishal Kulkarni }
6767e6ad469SVishal Kulkarni
6777e6ad469SVishal Kulkarni static void
cudbg_alias_get_allregs(char * dst,u32 dst_size)6787e6ad469SVishal Kulkarni cudbg_alias_get_allregs(char *dst, u32 dst_size)
6797e6ad469SVishal Kulkarni {
6807e6ad469SVishal Kulkarni u32 i;
6817e6ad469SVishal Kulkarni
6827e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_list); i++)
6837e6ad469SVishal Kulkarni if (entity_list[i].flag & (1 << ENTITY_FLAG_REGISTER))
6847e6ad469SVishal Kulkarni cudbg_append_string(dst, dst_size, entity_list[i].name);
6857e6ad469SVishal Kulkarni }
6867e6ad469SVishal Kulkarni
6877e6ad469SVishal Kulkarni static struct entity_access_list ATTRIBUTE_UNUSED entity_alias_list[] = {
6887e6ad469SVishal Kulkarni {"allregs", cudbg_alias_get_allregs},
6897e6ad469SVishal Kulkarni };
6907e6ad469SVishal Kulkarni
6917e6ad469SVishal Kulkarni static int
check_dbg_entity(char * entity)6927e6ad469SVishal Kulkarni check_dbg_entity(char *entity)
6937e6ad469SVishal Kulkarni {
6947e6ad469SVishal Kulkarni u32 i;
6957e6ad469SVishal Kulkarni
6967e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_list); i++)
6977e6ad469SVishal Kulkarni if (!strcmp(entity, entity_list[i].name))
6987e6ad469SVishal Kulkarni return entity_list[i].bit;
6997e6ad469SVishal Kulkarni return -1;
7007e6ad469SVishal Kulkarni }
7017e6ad469SVishal Kulkarni
7027e6ad469SVishal Kulkarni /* Get matching alias index from entity_alias_list[] */
7037e6ad469SVishal Kulkarni static
get_alias(const char * entity)7047e6ad469SVishal Kulkarni int get_alias(const char *entity)
7057e6ad469SVishal Kulkarni {
7067e6ad469SVishal Kulkarni u32 i;
7077e6ad469SVishal Kulkarni
7087e6ad469SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(entity_alias_list); i++)
7097e6ad469SVishal Kulkarni if (!strcmp(entity, entity_alias_list[i].name))
7107e6ad469SVishal Kulkarni return i;
7117e6ad469SVishal Kulkarni return -1;
7127e6ad469SVishal Kulkarni }
7137e6ad469SVishal Kulkarni
7147e6ad469SVishal Kulkarni static int
parse_entity_list(const char * dbg_entity_list,char * dst,u32 dst_size)7157e6ad469SVishal Kulkarni parse_entity_list(const char *dbg_entity_list, char *dst,
7167e6ad469SVishal Kulkarni u32 dst_size)
7177e6ad469SVishal Kulkarni {
7187e6ad469SVishal Kulkarni char *tmp_dbg_entity_list;
7197e6ad469SVishal Kulkarni char *dbg_entity;
7207e6ad469SVishal Kulkarni int rc, i;
7217e6ad469SVishal Kulkarni
7227e6ad469SVishal Kulkarni /* Holds single entity name de-limited by comma */
7237e6ad469SVishal Kulkarni tmp_dbg_entity_list = malloc(CUDBG_MAX_ENTITY_STR_LEN);
7247e6ad469SVishal Kulkarni if (!tmp_dbg_entity_list)
7257e6ad469SVishal Kulkarni return ENOMEM;
7267e6ad469SVishal Kulkarni
7277e6ad469SVishal Kulkarni strlcpy(tmp_dbg_entity_list, dbg_entity_list, CUDBG_MAX_ENTITY_STR_LEN);
7287e6ad469SVishal Kulkarni dbg_entity = strtok(tmp_dbg_entity_list, ",");
7297e6ad469SVishal Kulkarni while (dbg_entity != NULL) {
7307e6ad469SVishal Kulkarni /* See if specified entity name exists. If it doesn't
7317e6ad469SVishal Kulkarni * exist, see if the entity name is an alias.
7327e6ad469SVishal Kulkarni * If it's not a valid entity name, bail with error.
7337e6ad469SVishal Kulkarni */
7347e6ad469SVishal Kulkarni rc = check_dbg_entity(dbg_entity);
7357e6ad469SVishal Kulkarni if (rc < 0) {
7367e6ad469SVishal Kulkarni i = get_alias(dbg_entity);
7377e6ad469SVishal Kulkarni if (i < 0) {
7387e6ad469SVishal Kulkarni /* Not an alias, and not a valid entity name */
7397e6ad469SVishal Kulkarni printf("\nUnknown entity: %s\n", dbg_entity);
7407e6ad469SVishal Kulkarni rc = CUDBG_STATUS_ENTITY_NOT_FOUND;
7417e6ad469SVishal Kulkarni goto out_err;
7427e6ad469SVishal Kulkarni } else {
7437e6ad469SVishal Kulkarni /* If alias is found, get all the corresponding
7447e6ad469SVishal Kulkarni * debug entities related to the alias.
7457e6ad469SVishal Kulkarni */
7467e6ad469SVishal Kulkarni entity_alias_list[i].get_entities_cb(dst, dst_size);
7477e6ad469SVishal Kulkarni }
7487e6ad469SVishal Kulkarni } else {
7497e6ad469SVishal Kulkarni /* Not an alias, but is a valid entity name.
7507e6ad469SVishal Kulkarni * So, append the corresponding debug entity.
7517e6ad469SVishal Kulkarni */
7527e6ad469SVishal Kulkarni cudbg_append_string(dst, dst_size, entity_list[rc].name);
7537e6ad469SVishal Kulkarni }
7547e6ad469SVishal Kulkarni dbg_entity = strtok(NULL, ",");
7557e6ad469SVishal Kulkarni }
7567e6ad469SVishal Kulkarni
7577e6ad469SVishal Kulkarni rc = 0;
7587e6ad469SVishal Kulkarni
7597e6ad469SVishal Kulkarni out_err:
7607e6ad469SVishal Kulkarni free(tmp_dbg_entity_list);
7617e6ad469SVishal Kulkarni return rc;
7627e6ad469SVishal Kulkarni }
7637e6ad469SVishal Kulkarni
7647e6ad469SVishal Kulkarni static
get_entity_list(const char * in_buff,char ** out_buff)7657e6ad469SVishal Kulkarni int get_entity_list(const char *in_buff, char **out_buff)
7667e6ad469SVishal Kulkarni {
7677e6ad469SVishal Kulkarni char *dbg_entity_list;
7687e6ad469SVishal Kulkarni int rc;
7697e6ad469SVishal Kulkarni
7707e6ad469SVishal Kulkarni /* Allocate enough to hold converted alias string.
7717e6ad469SVishal Kulkarni * Must be freed by caller
7727e6ad469SVishal Kulkarni */
7737e6ad469SVishal Kulkarni dbg_entity_list = malloc(CUDBG_MAX_ENTITY_STR_LEN);
7747e6ad469SVishal Kulkarni if (!dbg_entity_list)
7757e6ad469SVishal Kulkarni return ENOMEM;
7767e6ad469SVishal Kulkarni
7777e6ad469SVishal Kulkarni memset(dbg_entity_list, 0, CUDBG_MAX_ENTITY_STR_LEN);
7787e6ad469SVishal Kulkarni rc = parse_entity_list(in_buff, dbg_entity_list,
7797e6ad469SVishal Kulkarni CUDBG_MAX_ENTITY_STR_LEN);
7807e6ad469SVishal Kulkarni if (rc) {
7817e6ad469SVishal Kulkarni free(dbg_entity_list);
7827e6ad469SVishal Kulkarni return rc;
7837e6ad469SVishal Kulkarni }
7847e6ad469SVishal Kulkarni
7857e6ad469SVishal Kulkarni /* Remove the last comma */
7867e6ad469SVishal Kulkarni dbg_entity_list[strlen(dbg_entity_list) - 1] = '\0';
7877e6ad469SVishal Kulkarni *out_buff = dbg_entity_list;
7887e6ad469SVishal Kulkarni return 0;
7897e6ad469SVishal Kulkarni }
7907e6ad469SVishal Kulkarni
7917e6ad469SVishal Kulkarni static void
put_entity_list(char * buf)7927e6ad469SVishal Kulkarni put_entity_list(char *buf)
7937e6ad469SVishal Kulkarni {
7947e6ad469SVishal Kulkarni if (buf)
7957e6ad469SVishal Kulkarni free(buf);
7967e6ad469SVishal Kulkarni }
7977e6ad469SVishal Kulkarni
7987e6ad469SVishal Kulkarni int
set_dbg_entity(u8 * dbg_bitmap,char * dbg_entity_list)7997e6ad469SVishal Kulkarni set_dbg_entity(u8 *dbg_bitmap, char *dbg_entity_list)
8007e6ad469SVishal Kulkarni {
8017e6ad469SVishal Kulkarni int i, dbg_entity_bit, rc = 0;
8027e6ad469SVishal Kulkarni char *dbg_entity;
8037e6ad469SVishal Kulkarni char *dbg_entity_list_tmp;
8047e6ad469SVishal Kulkarni
8057e6ad469SVishal Kulkarni dbg_entity_list_tmp = malloc(MAX_PARAM_LEN);
8067e6ad469SVishal Kulkarni if (!dbg_entity_list_tmp) {
8077e6ad469SVishal Kulkarni rc = CUDBG_STATUS_NOSPACE;
8087e6ad469SVishal Kulkarni return rc;
8097e6ad469SVishal Kulkarni }
8107e6ad469SVishal Kulkarni
8117e6ad469SVishal Kulkarni if (dbg_entity_list != NULL) {
8127e6ad469SVishal Kulkarni strlcpy(dbg_entity_list_tmp, dbg_entity_list, MAX_PARAM_LEN);
8137e6ad469SVishal Kulkarni dbg_entity = strtok(dbg_entity_list_tmp, ",");
8147e6ad469SVishal Kulkarni }
8157e6ad469SVishal Kulkarni else
8167e6ad469SVishal Kulkarni dbg_entity = NULL;
8177e6ad469SVishal Kulkarni
8187e6ad469SVishal Kulkarni while (dbg_entity != NULL) {
8197e6ad469SVishal Kulkarni rc = check_dbg_entity(dbg_entity);
8207e6ad469SVishal Kulkarni if (rc < 0) {
8217e6ad469SVishal Kulkarni printf("\n\tInvalid debug entity: %s\n", dbg_entity);
8227e6ad469SVishal Kulkarni //Vishal cudbg_usage();
8237e6ad469SVishal Kulkarni goto out_free;
8247e6ad469SVishal Kulkarni }
8257e6ad469SVishal Kulkarni
8267e6ad469SVishal Kulkarni dbg_entity_bit = rc;
8277e6ad469SVishal Kulkarni
8287e6ad469SVishal Kulkarni if (dbg_entity_bit == CUDBG_ALL) {
8297e6ad469SVishal Kulkarni for (i = 1; i < CUDBG_MAX_ENTITY; i++)
8307e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, i);
8317e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, CUDBG_ALL);
8327e6ad469SVishal Kulkarni break;
8337e6ad469SVishal Kulkarni } else {
8347e6ad469SVishal Kulkarni set_dbg_bitmap(dbg_bitmap, dbg_entity_bit);
8357e6ad469SVishal Kulkarni }
8367e6ad469SVishal Kulkarni
8377e6ad469SVishal Kulkarni dbg_entity = strtok(NULL, ",");
8387e6ad469SVishal Kulkarni }
8397e6ad469SVishal Kulkarni
8407e6ad469SVishal Kulkarni rc = 0;
8417e6ad469SVishal Kulkarni
8427e6ad469SVishal Kulkarni out_free:
8437e6ad469SVishal Kulkarni free(dbg_entity_list_tmp);
8447e6ad469SVishal Kulkarni return rc;
8457e6ad469SVishal Kulkarni }
8467e6ad469SVishal Kulkarni
8477e6ad469SVishal Kulkarni
8487e6ad469SVishal Kulkarni static void
get_cudbg(int argc,char * argv[],int start_arg,const char * iff_name)8497e6ad469SVishal Kulkarni get_cudbg(int argc, char *argv[], int start_arg, const char *iff_name)
8507e6ad469SVishal Kulkarni {
8517e6ad469SVishal Kulkarni char *dbg_entity_list = NULL;
8527e6ad469SVishal Kulkarni int rc = 0, option;
85365ecf399SYuri Pankov
85465ecf399SYuri Pankov if (start_arg >= argc)
85565ecf399SYuri Pankov errx(1, "no option provided");
85665ecf399SYuri Pankov
8577e6ad469SVishal Kulkarni rc = check_option(argv[start_arg++]);
8587e6ad469SVishal Kulkarni if (rc < 0) {
85965ecf399SYuri Pankov errx(1, "%s:Invalid option provided", __func__);
8607e6ad469SVishal Kulkarni }
8617e6ad469SVishal Kulkarni option = rc;
8627e6ad469SVishal Kulkarni
8637e6ad469SVishal Kulkarni if (option == CUDBG_OPT_VERSION) {
8647e6ad469SVishal Kulkarni printf("Library Version %d.%d.%d\n", CUDBG_MAJOR_VERSION,
8657e6ad469SVishal Kulkarni CUDBG_MINOR_VERSION, CUDBG_BUILD_VERSION);
8667e6ad469SVishal Kulkarni return;
8677e6ad469SVishal Kulkarni }
8687e6ad469SVishal Kulkarni
8697e6ad469SVishal Kulkarni if (argc < 5) {
87065ecf399SYuri Pankov errx(1, "Invalid number of arguments\n");
8717e6ad469SVishal Kulkarni }
8727e6ad469SVishal Kulkarni rc = get_entity_list(argv[start_arg++],
8737e6ad469SVishal Kulkarni &dbg_entity_list);
8747e6ad469SVishal Kulkarni if (rc) {
87565ecf399SYuri Pankov errx(1, "Error in parsing entity\n");
8767e6ad469SVishal Kulkarni }
8777e6ad469SVishal Kulkarni
8787e6ad469SVishal Kulkarni if (argc < 6) {
87965ecf399SYuri Pankov errx(1, "File name is missing\n");
8807e6ad469SVishal Kulkarni }
8817e6ad469SVishal Kulkarni
8827e6ad469SVishal Kulkarni switch (option) {
8837e6ad469SVishal Kulkarni case CUDBG_OPT_COLLECT:
8847e6ad469SVishal Kulkarni do_collect(dbg_entity_list, iff_name, argv[start_arg]);
8857e6ad469SVishal Kulkarni break;
8867e6ad469SVishal Kulkarni case CUDBG_OPT_VIEW:
8877e6ad469SVishal Kulkarni do_view(dbg_entity_list, argv[start_arg]);
8887e6ad469SVishal Kulkarni break;
8897e6ad469SVishal Kulkarni default:
89065ecf399SYuri Pankov errx(1, "Wrong option provided\n");
8917e6ad469SVishal Kulkarni }
8927e6ad469SVishal Kulkarni
8937e6ad469SVishal Kulkarni put_entity_list(dbg_entity_list);
8947e6ad469SVishal Kulkarni }
8957e6ad469SVishal Kulkarni
8965a9113e7SVishal Kulkarni static void
run_cmd(int argc,char * argv[],const char * iff_name)8975a9113e7SVishal Kulkarni run_cmd(int argc, char *argv[], const char *iff_name)
8985a9113e7SVishal Kulkarni {
8995a9113e7SVishal Kulkarni if (strcmp(argv[2], "devlog") == 0)
9005a9113e7SVishal Kulkarni get_devlog(argc, argv, 3, iff_name);
9015a9113e7SVishal Kulkarni else if (strcmp(argv[2], "loadfw") == 0)
9025a9113e7SVishal Kulkarni load_fw(argc, argv, 3, iff_name);
9037e6ad469SVishal Kulkarni else if (strcmp(argv[2], "cudbg") == 0)
9047e6ad469SVishal Kulkarni get_cudbg(argc, argv, 3, iff_name);
905*fcabbd87SPotnuri Bharat Teja else if (strcmp(argv[2], "regdump") == 0)
906*fcabbd87SPotnuri Bharat Teja get_regdump(argc, argv, 3, iff_name);
907*fcabbd87SPotnuri Bharat Teja else if (strcmp(argv[2], "reg") == 0)
908*fcabbd87SPotnuri Bharat Teja register_io(argc, argv, 3, iff_name);
9095a9113e7SVishal Kulkarni else
9105a9113e7SVishal Kulkarni usage(stderr);
9115a9113e7SVishal Kulkarni }
9125a9113e7SVishal Kulkarni
913d81537f4SRobert Mustacchi /*
914d81537f4SRobert Mustacchi * Traditionally we expect to be given a path to the t4nex device control file
915d81537f4SRobert Mustacchi * hidden in /devices. To make life easier, we want to also support folks using
916d81537f4SRobert Mustacchi * the driver instance numbers for either a given t4nex%d or cxgbe%d. We check
917d81537f4SRobert Mustacchi * to see if we've been given a path to a character device and if so, just
918d81537f4SRobert Mustacchi * continue straight on with the given argument. Otherwise we attempt to map it
919d81537f4SRobert Mustacchi * to something known.
920d81537f4SRobert Mustacchi */
921d81537f4SRobert Mustacchi static const char *
cxgbetool_parse_path(char * arg)922d81537f4SRobert Mustacchi cxgbetool_parse_path(char *arg)
923d81537f4SRobert Mustacchi {
924d81537f4SRobert Mustacchi struct stat st;
925d81537f4SRobert Mustacchi di_node_t root, node;
926d81537f4SRobert Mustacchi const char *numptr, *errstr;
927d81537f4SRobert Mustacchi size_t drvlen;
928d81537f4SRobert Mustacchi int inst;
929d81537f4SRobert Mustacchi boolean_t is_t4nex = B_TRUE;
930d81537f4SRobert Mustacchi char mname[64];
931d81537f4SRobert Mustacchi
932d81537f4SRobert Mustacchi if (stat(arg, &st) == 0) {
933d81537f4SRobert Mustacchi if (S_ISCHR(st.st_mode)) {
934d81537f4SRobert Mustacchi return (arg);
935d81537f4SRobert Mustacchi }
936d81537f4SRobert Mustacchi }
937d81537f4SRobert Mustacchi
938d81537f4SRobert Mustacchi if (strncmp(arg, T4_NEXUS_NAME, sizeof (T4_NEXUS_NAME) - 1) == 0) {
939d81537f4SRobert Mustacchi drvlen = sizeof (T4_NEXUS_NAME) - 1;
940d81537f4SRobert Mustacchi } else if (strncmp(arg, T4_PORT_NAME, sizeof (T4_PORT_NAME) - 1) == 0) {
941d81537f4SRobert Mustacchi is_t4nex = B_FALSE;
942d81537f4SRobert Mustacchi drvlen = sizeof (T4_PORT_NAME) - 1;
943d81537f4SRobert Mustacchi } else {
944d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "cannot use device %s: not a character "
945d81537f4SRobert Mustacchi "device or a %s/%s device instance", arg, T4_PORT_NAME,
946d81537f4SRobert Mustacchi T4_NEXUS_NAME);
947d81537f4SRobert Mustacchi }
948d81537f4SRobert Mustacchi
949d81537f4SRobert Mustacchi numptr = arg + drvlen;
950d81537f4SRobert Mustacchi inst = (int)strtonum(numptr, 0, INT_MAX, &errstr);
951d81537f4SRobert Mustacchi if (errstr != NULL) {
952d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to parse instance number '%s': %s",
953d81537f4SRobert Mustacchi numptr, errstr);
954d81537f4SRobert Mustacchi }
955d81537f4SRobert Mustacchi
956d81537f4SRobert Mustacchi /*
957d81537f4SRobert Mustacchi * Now that we have the instance here, we need to truncate the string at
958d81537f4SRobert Mustacchi * the end of the driver name otherwise di_drv_first_node() will be very
959d81537f4SRobert Mustacchi * confused as there is no driver called say 't4nex0'.
960d81537f4SRobert Mustacchi */
961d81537f4SRobert Mustacchi arg[drvlen] = '\0';
962d81537f4SRobert Mustacchi root = di_init("/", DINFOCPYALL);
963d81537f4SRobert Mustacchi if (root == DI_NODE_NIL) {
964d81537f4SRobert Mustacchi err(EXIT_FAILURE, "failed to initialize libdevinfo while "
965d81537f4SRobert Mustacchi "trying to map device name %s", arg);
966d81537f4SRobert Mustacchi }
967d81537f4SRobert Mustacchi
968d81537f4SRobert Mustacchi for (node = di_drv_first_node(arg, root); node != DI_NODE_NIL;
969d81537f4SRobert Mustacchi node = di_drv_next_node(node)) {
970d81537f4SRobert Mustacchi char *bpath;
971d81537f4SRobert Mustacchi di_minor_t minor = DI_MINOR_NIL;
972d81537f4SRobert Mustacchi
973d81537f4SRobert Mustacchi if (di_instance(node) != inst) {
974d81537f4SRobert Mustacchi continue;
975d81537f4SRobert Mustacchi }
976d81537f4SRobert Mustacchi
977d81537f4SRobert Mustacchi if (!is_t4nex) {
978d81537f4SRobert Mustacchi const char *pdrv;
979d81537f4SRobert Mustacchi node = di_parent_node(node);
980d81537f4SRobert Mustacchi pdrv = di_driver_name(node);
981d81537f4SRobert Mustacchi if (pdrv == NULL || strcmp(pdrv, T4_NEXUS_NAME) != 0) {
982d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "%s does not have %s "
983d81537f4SRobert Mustacchi "parent, found %s%d", arg, T4_NEXUS_NAME,
984d81537f4SRobert Mustacchi pdrv != NULL ? pdrv : "unknown",
985d81537f4SRobert Mustacchi pdrv != NULL ? di_instance(node) : -1);
986d81537f4SRobert Mustacchi }
987d81537f4SRobert Mustacchi }
988d81537f4SRobert Mustacchi
989d81537f4SRobert Mustacchi (void) snprintf(mname, sizeof (mname), "%s,%d", T4_NEXUS_NAME,
990d81537f4SRobert Mustacchi di_instance(node));
991d81537f4SRobert Mustacchi
992d81537f4SRobert Mustacchi while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
993d81537f4SRobert Mustacchi if (strcmp(di_minor_name(minor), mname) == 0) {
994d81537f4SRobert Mustacchi break;
995d81537f4SRobert Mustacchi }
996d81537f4SRobert Mustacchi }
997d81537f4SRobert Mustacchi
998d81537f4SRobert Mustacchi if (minor == DI_MINOR_NIL) {
999d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to find minor %s on %s%d",
1000d81537f4SRobert Mustacchi mname, di_driver_name(node), di_instance(node));
1001d81537f4SRobert Mustacchi }
1002d81537f4SRobert Mustacchi
1003d81537f4SRobert Mustacchi bpath = di_devfs_minor_path(minor);
1004d81537f4SRobert Mustacchi if (bpath == NULL) {
1005d81537f4SRobert Mustacchi err(EXIT_FAILURE, "failed to get minor path for "
1006d81537f4SRobert Mustacchi "%s%d:%s", di_driver_name(node), di_instance(node),
1007d81537f4SRobert Mustacchi di_minor_name(minor));
1008d81537f4SRobert Mustacchi }
1009d81537f4SRobert Mustacchi if (snprintf(cxgbetool_nexus, sizeof (cxgbetool_nexus),
1010d81537f4SRobert Mustacchi "/devices%s", bpath) >= sizeof (cxgbetool_nexus)) {
1011d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to construct full /devices "
1012d81537f4SRobert Mustacchi "path for %s: internal path buffer would have "
10136b1325cfSRobert Mustacchi "overflowed", bpath);
1014d81537f4SRobert Mustacchi }
1015d81537f4SRobert Mustacchi di_devfs_path_free(bpath);
1016d81537f4SRobert Mustacchi
1017d81537f4SRobert Mustacchi di_fini(root);
1018d81537f4SRobert Mustacchi return (cxgbetool_nexus);
1019d81537f4SRobert Mustacchi }
1020d81537f4SRobert Mustacchi
1021d81537f4SRobert Mustacchi errx(EXIT_FAILURE, "failed to map %s%d to a %s or %s instance",
1022d81537f4SRobert Mustacchi arg, inst, T4_PORT_NAME, T4_NEXUS_NAME);
1023d81537f4SRobert Mustacchi }
1024d81537f4SRobert Mustacchi
10255a9113e7SVishal Kulkarni int
main(int argc,char * argv[])10265a9113e7SVishal Kulkarni main(int argc, char *argv[])
10275a9113e7SVishal Kulkarni {
10285a9113e7SVishal Kulkarni const char *iff_name;
10295a9113e7SVishal Kulkarni
10305a9113e7SVishal Kulkarni progname = argv[0];
10315a9113e7SVishal Kulkarni
10325a9113e7SVishal Kulkarni if (argc == 2) {
10335a9113e7SVishal Kulkarni if (strcmp(argv[1], "-h") == 0 ||
10345a9113e7SVishal Kulkarni strcmp(argv[1], "--help") == 0) {
10355a9113e7SVishal Kulkarni usage(stdout);
10365a9113e7SVishal Kulkarni }
10375a9113e7SVishal Kulkarni
10385a9113e7SVishal Kulkarni if (strcmp(argv[1], "-v") == 0 ||
10395a9113e7SVishal Kulkarni strcmp(argv[1], "--version") == 0) {
10405a9113e7SVishal Kulkarni printf("cxgbetool version %s\n", DRV_VERSION);
10415a9113e7SVishal Kulkarni exit(0);
10425a9113e7SVishal Kulkarni }
10435a9113e7SVishal Kulkarni }
10445a9113e7SVishal Kulkarni
10455a9113e7SVishal Kulkarni if (argc < 3)
10465a9113e7SVishal Kulkarni usage(stderr);
10475a9113e7SVishal Kulkarni
1048d81537f4SRobert Mustacchi iff_name = cxgbetool_parse_path(argv[1]);
10495a9113e7SVishal Kulkarni
10505a9113e7SVishal Kulkarni run_cmd(argc, argv, iff_name);
10515a9113e7SVishal Kulkarni
10525a9113e7SVishal Kulkarni return (0);
10535a9113e7SVishal Kulkarni }
1054