1 /**************************************************************************
3 Copyright (c) 2007, Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Chelsio Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
33 ***************************************************************************/
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
46 #include <sys/param.h>
48 #include <sys/ioctl.h>
49 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
55 #include <net/if_var.h>
56 #include <net/if_types.h>
60 #define TCB_WORDS (TCB_SIZE / 4)
61 #define PROTO_SRAM_LINES 128
62 #define PROTO_SRAM_LINE_BITS 132
63 #define PROTO_SRAM_LINE_NIBBLES (132 / 4)
64 #define PROTO_SRAM_SIZE (PROTO_SRAM_LINE_NIBBLES * PROTO_SRAM_LINES / 2)
65 #define PROTO_SRAM_EEPROM_ADDR 4096
67 #include <cxgb_ioctl.h>
68 #include <common/cxgb_regs.h>
79 #if defined(CONFIG_T3_REGS)
80 # include "reg_defs_t3.c"
81 # include "reg_defs_t3b.c"
84 static const char *progname;
86 static void __attribute__((noreturn)) usage(FILE *fp)
88 fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
90 #ifdef CHELSIO_INTERNAL
91 "\treg <address>[=<val>] read/write register\n"
92 "\ttpi <address>[=<val>] read/write TPI register\n"
93 "\tmdio <phy_addr> <mmd_addr>\n"
94 "\t <reg_addr> [<val>] read/write MDIO register\n"
96 "\tmtus [<mtu0>...<mtuN>] read/write MTU table\n"
97 #ifdef CHELSIO_INTERNAL
98 "\tpm [<TX page spec> <RX page spec>] read/write PM config\n"
99 "\ttcam [<#serv> <#routes> <#filters>] read/write TCAM config\n"
100 "\ttcb <index> read TCB\n"
102 "\tregdump [<module>] dump registers\n"
103 #ifdef CHELSIO_INTERNAL
104 "\ttcamdump <address> <count> show TCAM contents\n"
105 "\tcontext <type> <id> show an SGE context\n"
106 "\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
107 "\tmemdump cm|tx|rx <addr> <len> dump a mem range\n"
108 "\tmeminfo show memory info\n"
110 "\tup activate TOE\n"
111 "\tproto [<protocol image>] read/write proto SRAM\n"
112 "\tloadfw <FW image> download firmware\n"
113 "\tqset [<index> [<param> <val>] ...] read/write qset parameters\n"
114 "\tqsets [<# of qsets>] read/write # of qsets\n"
115 "\ttrace tx|rx|all on|off [not]\n"
116 "\t [<param> <val>[:<mask>]] ... write trace parameters\n"
117 "\tt1powersave [on|off] enable/disable T1xx powersave mode\n"
118 "\tpktsched port <idx> <min> <max> set TX port scheduler params\n"
119 "\tpktsched tunnelq <idx> <max>\n"
120 "\t <binding> set TX tunnelq scheduler params\n"
122 exit(fp == stderr ? 1 : 0);
126 * Make a TOETOOL ioctl call.
129 doit(const char *iff_name, unsigned long cmd, void *data)
135 snprintf(buf, 64, "/dev/%s", iff_name);
137 if ((fd = open(buf, O_RDWR)) < 0)
141 return ioctl(fd, cmd, data) < 0 ? -1 : 0;
144 static int get_int_arg(const char *s, uint32_t *valp)
148 *valp = strtoul(s, &p, 0);
150 warnx("bad parameter \"%s\"", s);
157 read_reg(const char *iff_name, uint32_t addr)
163 if (doit(iff_name, CHELSIO_GETREG, ®) < 0)
164 err(1, "register read");
169 write_reg(const char *iff_name, uint32_t addr, uint32_t val)
171 struct ch_reg ch_reg;
176 if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
177 err(1, "register write");
180 static int register_io(int argc, char *argv[], int start_arg,
181 const char *iff_name)
184 uint32_t addr, val = 0, write = 0;
186 if (argc != start_arg + 1) return -1;
188 addr = strtoul(argv[start_arg], &p, 0);
189 if (p == argv[start_arg]) return -1;
190 if (*p == '=' && p[1]) {
191 val = strtoul(p + 1, &p, 0);
195 warnx("bad parameter \"%s\"", argv[start_arg]);
200 write_reg(iff_name, addr, val);
202 val = read_reg(iff_name, addr);
203 printf("%#x [%u]\n", val, val);
208 static int mdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
212 unsigned int cmd, phy_addr, reg, mmd, val;
214 if (argc == start_arg + 3)
216 else if (argc == start_arg + 4)
221 if (get_int_arg(argv[start_arg], &phy_addr) ||
222 get_int_arg(argv[start_arg + 1], &mmd) ||
223 get_int_arg(argv[start_arg + 2], ®) ||
224 (cmd == SIOCSMIIREG && get_int_arg(argv[start_arg + 3], &val)))
227 p.phy_id = phy_addr | (mmd << 8);
231 if (doit(iff_name, cmd, &p) < 0)
232 err(1, "MDIO %s", cmd == SIOCGMIIREG ? "read" : "write");
233 if (cmd == SIOCGMIIREG)
234 printf("%#x [%u]\n", p.val_out, p.val_out);
238 static inline uint32_t xtract(uint32_t val, int shift, int len)
240 return (val >> shift) & ((1 << len) - 1);
243 static int dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
245 uint32_t reg_val = 0; // silence compiler warning
247 for ( ; reg_array->name; ++reg_array)
248 if (!reg_array->len) {
249 reg_val = regs[reg_array->addr / 4];
250 printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
251 reg_array->name, reg_val, reg_val);
253 uint32_t v = xtract(reg_val, reg_array->addr,
256 printf(" %-40s %#-10x [%u]\n", reg_array->name,
262 static int dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
265 char *block_name = NULL;
267 if (argc == start_arg + 1)
268 block_name = argv[start_arg];
269 else if (argc != start_arg)
272 if (!block_name || !strcmp(block_name, "sge"))
273 match += dump_block_regs(sge_regs, regs);
274 if (!block_name || !strcmp(block_name, "mc3"))
275 match += dump_block_regs(mc3_regs, regs);
276 if (!block_name || !strcmp(block_name, "mc4"))
277 match += dump_block_regs(mc4_regs, regs);
278 if (!block_name || !strcmp(block_name, "tpi"))
279 match += dump_block_regs(tpi_regs, regs);
280 if (!block_name || !strcmp(block_name, "tp"))
281 match += dump_block_regs(tp_regs, regs);
282 if (!block_name || !strcmp(block_name, "rat"))
283 match += dump_block_regs(rat_regs, regs);
284 if (!block_name || !strcmp(block_name, "cspi"))
285 match += dump_block_regs(cspi_regs, regs);
286 if (!block_name || !strcmp(block_name, "espi"))
287 match += dump_block_regs(espi_regs, regs);
288 if (!block_name || !strcmp(block_name, "ulp"))
289 match += dump_block_regs(ulp_regs, regs);
290 if (!block_name || !strcmp(block_name, "pl"))
291 match += dump_block_regs(pl_regs, regs);
292 if (!block_name || !strcmp(block_name, "mc5"))
293 match += dump_block_regs(mc5_regs, regs);
295 errx(1, "unknown block \"%s\"", block_name);
299 #if defined(CONFIG_T3_REGS)
300 static int dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs,
304 char *block_name = NULL;
306 if (argc == start_arg + 1)
307 block_name = argv[start_arg];
308 else if (argc != start_arg)
311 if (!block_name || !strcmp(block_name, "sge"))
312 match += dump_block_regs(sge3_regs, regs);
313 if (!block_name || !strcmp(block_name, "pci"))
314 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
316 if (!block_name || !strcmp(block_name, "t3dbg"))
317 match += dump_block_regs(t3dbg_regs, regs);
318 if (!block_name || !strcmp(block_name, "pmrx"))
319 match += dump_block_regs(mc7_pmrx_regs, regs);
320 if (!block_name || !strcmp(block_name, "pmtx"))
321 match += dump_block_regs(mc7_pmtx_regs, regs);
322 if (!block_name || !strcmp(block_name, "cm"))
323 match += dump_block_regs(mc7_cm_regs, regs);
324 if (!block_name || !strcmp(block_name, "cim"))
325 match += dump_block_regs(cim_regs, regs);
326 if (!block_name || !strcmp(block_name, "tp"))
327 match += dump_block_regs(tp1_regs, regs);
328 if (!block_name || !strcmp(block_name, "ulp_rx"))
329 match += dump_block_regs(ulp2_rx_regs, regs);
330 if (!block_name || !strcmp(block_name, "ulp_tx"))
331 match += dump_block_regs(ulp2_tx_regs, regs);
332 if (!block_name || !strcmp(block_name, "pmrx"))
333 match += dump_block_regs(pm1_rx_regs, regs);
334 if (!block_name || !strcmp(block_name, "pmtx"))
335 match += dump_block_regs(pm1_tx_regs, regs);
336 if (!block_name || !strcmp(block_name, "mps"))
337 match += dump_block_regs(mps0_regs, regs);
338 if (!block_name || !strcmp(block_name, "cplsw"))
339 match += dump_block_regs(cpl_switch_regs, regs);
340 if (!block_name || !strcmp(block_name, "smb"))
341 match += dump_block_regs(smb0_regs, regs);
342 if (!block_name || !strcmp(block_name, "i2c"))
343 match += dump_block_regs(i2cm0_regs, regs);
344 if (!block_name || !strcmp(block_name, "mi1"))
345 match += dump_block_regs(mi1_regs, regs);
346 if (!block_name || !strcmp(block_name, "sf"))
347 match += dump_block_regs(sf1_regs, regs);
348 if (!block_name || !strcmp(block_name, "pl"))
349 match += dump_block_regs(pl3_regs, regs);
350 if (!block_name || !strcmp(block_name, "mc5"))
351 match += dump_block_regs(mc5a_regs, regs);
352 if (!block_name || !strcmp(block_name, "xgmac0"))
353 match += dump_block_regs(xgmac0_0_regs, regs);
354 if (!block_name || !strcmp(block_name, "xgmac1"))
355 match += dump_block_regs(xgmac0_1_regs, regs);
357 errx(1, "unknown block \"%s\"", block_name);
361 static int dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
365 char *block_name = NULL;
367 if (argc == start_arg + 1)
368 block_name = argv[start_arg];
369 else if (argc != start_arg)
372 if (!block_name || !strcmp(block_name, "sge"))
373 match += dump_block_regs(t3b_sge3_regs, regs);
374 if (!block_name || !strcmp(block_name, "pci"))
375 match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
376 t3b_pcix1_regs, regs);
377 if (!block_name || !strcmp(block_name, "t3dbg"))
378 match += dump_block_regs(t3b_t3dbg_regs, regs);
379 if (!block_name || !strcmp(block_name, "pmrx"))
380 match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
381 if (!block_name || !strcmp(block_name, "pmtx"))
382 match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
383 if (!block_name || !strcmp(block_name, "cm"))
384 match += dump_block_regs(t3b_mc7_cm_regs, regs);
385 if (!block_name || !strcmp(block_name, "cim"))
386 match += dump_block_regs(t3b_cim_regs, regs);
387 if (!block_name || !strcmp(block_name, "tp"))
388 match += dump_block_regs(t3b_tp1_regs, regs);
389 if (!block_name || !strcmp(block_name, "ulp_rx"))
390 match += dump_block_regs(t3b_ulp2_rx_regs, regs);
391 if (!block_name || !strcmp(block_name, "ulp_tx"))
392 match += dump_block_regs(t3b_ulp2_tx_regs, regs);
393 if (!block_name || !strcmp(block_name, "pmrx"))
394 match += dump_block_regs(t3b_pm1_rx_regs, regs);
395 if (!block_name || !strcmp(block_name, "pmtx"))
396 match += dump_block_regs(t3b_pm1_tx_regs, regs);
397 if (!block_name || !strcmp(block_name, "mps"))
398 match += dump_block_regs(t3b_mps0_regs, regs);
399 if (!block_name || !strcmp(block_name, "cplsw"))
400 match += dump_block_regs(t3b_cpl_switch_regs, regs);
401 if (!block_name || !strcmp(block_name, "smb"))
402 match += dump_block_regs(t3b_smb0_regs, regs);
403 if (!block_name || !strcmp(block_name, "i2c"))
404 match += dump_block_regs(t3b_i2cm0_regs, regs);
405 if (!block_name || !strcmp(block_name, "mi1"))
406 match += dump_block_regs(t3b_mi1_regs, regs);
407 if (!block_name || !strcmp(block_name, "sf"))
408 match += dump_block_regs(t3b_sf1_regs, regs);
409 if (!block_name || !strcmp(block_name, "pl"))
410 match += dump_block_regs(t3b_pl3_regs, regs);
411 if (!block_name || !strcmp(block_name, "mc5"))
412 match += dump_block_regs(t3b_mc5a_regs, regs);
413 if (!block_name || !strcmp(block_name, "xgmac0"))
414 match += dump_block_regs(t3b_xgmac0_0_regs, regs);
415 if (!block_name || !strcmp(block_name, "xgmac1"))
416 match += dump_block_regs(t3b_xgmac0_1_regs, regs);
418 errx(1, "unknown block \"%s\"", block_name);
424 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
428 int i, vers, revision, is_pcie;
429 struct ifconf_regs regs;
431 regs.len = REGDUMP_SIZE;
433 if ((regs.data = malloc(REGDUMP_SIZE)) == NULL)
434 err(1, "can't malloc");
436 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
437 err(1, "can't read registers");
439 vers = regs.version & 0x3ff;
440 revision = (regs.version >> 10) & 0x3f;
441 is_pcie = (regs.version & 0x80000000) != 0;
444 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
445 #if defined(CONFIG_T3_REGS)
448 return dump_regs_t3(argc, argv, start_arg,
449 (uint32_t *)regs.data, is_pcie);
451 return dump_regs_t3b(argc, argv, start_arg,
452 (uint32_t *)regs.data, is_pcie);
455 errx(1, "unknown card type %d", vers);
459 static int t3_meminfo(const uint32_t *regs)
462 SG_EGR_CNTX_BADDR = 0x58,
463 SG_CQ_CONTEXT_BADDR = 0x6c,
464 CIM_SDRAM_BASE_ADDR = 0x28c,
465 CIM_SDRAM_ADDR_SIZE = 0x290,
466 TP_CMM_MM_BASE = 0x314,
467 TP_CMM_TIMER_BASE = 0x318,
468 TP_CMM_MM_RX_FLST_BASE = 0x460,
469 TP_CMM_MM_TX_FLST_BASE = 0x464,
470 TP_CMM_MM_PS_FLST_BASE = 0x468,
471 ULPRX_ISCSI_LLIMIT = 0x50c,
472 ULPRX_ISCSI_ULIMIT = 0x510,
473 ULPRX_TDDP_LLIMIT = 0x51c,
474 ULPRX_TDDP_ULIMIT = 0x520,
475 ULPRX_STAG_LLIMIT = 0x52c,
476 ULPRX_STAG_ULIMIT = 0x530,
477 ULPRX_RQ_LLIMIT = 0x534,
478 ULPRX_RQ_ULIMIT = 0x538,
479 ULPRX_PBL_LLIMIT = 0x53c,
480 ULPRX_PBL_ULIMIT = 0x540,
483 unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
484 cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
485 timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
486 pstructs = regs[TP_CMM_MM_BASE / 4],
487 pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
488 rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
489 tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
490 cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
491 cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
492 unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
493 iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
494 tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
495 tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
496 stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
497 stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
498 rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
499 rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
500 pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
501 pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
503 printf("CM memory map:\n");
504 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
506 printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
507 cq_cntxt - 1, cq_cntxt - egr_cntxt);
508 printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt,
509 timers - 1, timers - cq_cntxt);
510 printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers,
511 pstructs - 1, pstructs - timers);
512 printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs,
513 pstruct_fl - 1, pstruct_fl - pstructs);
514 printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl,
515 rx_fl - 1, rx_fl - pstruct_fl);
516 printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
518 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
520 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base,
521 cim_base + cim_size - 1, cim_size);
523 printf("\nPMRX memory map:\n");
524 printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
525 iscsi_ul - iscsi_ll + 1);
526 printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
527 tddp_ul - tddp_ll + 1);
528 printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
529 stag_ul - stag_ll + 1);
530 printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
532 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
533 pbl_ul - pbl_ll + 1);
537 static int meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
540 struct ifconf_regs regs;
542 if ((regs.data = malloc(REGDUMP_SIZE)) == NULL)
543 err(1, "can't malloc");
545 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
546 err(1, "can't read registers");
548 vers = regs.version & 0x3ff;
550 return t3_meminfo((uint32_t *)regs.data);
552 errx(1, "unknown card type %d", vers);
557 static int mtu_tab_op(int argc, char *argv[], int start_arg,
558 const char *iff_name)
560 struct toetool_mtus op;
563 if (argc == start_arg) {
564 op.cmd = TOETOOL_GETMTUTAB;
565 op.nmtus = MAX_NMTUS;
567 if (doit(iff_name, &op) < 0)
568 err(1, "get MTU table");
569 for (i = 0; i < op.nmtus; ++i)
570 printf("%u ", op.mtus[i]);
572 } else if (argc <= start_arg + MAX_NMTUS) {
573 op.cmd = TOETOOL_SETMTUTAB;
574 op.nmtus = argc - start_arg;
576 for (i = 0; i < op.nmtus; ++i) {
578 unsigned long m = strtoul(argv[start_arg + i], &p, 0);
580 if (*p || m > 9600) {
581 warnx("bad parameter \"%s\"",
582 argv[start_arg + i]);
585 if (i && m < op.mtus[i - 1])
586 errx(1, "MTUs must be in ascending order");
589 if (doit(iff_name, &op) < 0)
590 err(1, "set MTU table");
598 #ifdef CHELSIO_INTERNAL
599 static void show_egress_cntxt(uint32_t data[])
601 printf("credits: %u\n", data[0] & 0x7fff);
602 printf("GTS: %u\n", (data[0] >> 15) & 1);
603 printf("index: %u\n", data[0] >> 16);
604 printf("queue size: %u\n", data[1] & 0xffff);
605 printf("base address: 0x%llx\n",
606 ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
607 (((uint64_t)data[3] & 0xf) << 48)) << 12);
608 printf("rsp queue #: %u\n", (data[3] >> 4) & 7);
609 printf("cmd queue #: %u\n", (data[3] >> 7) & 1);
610 printf("TUN: %u\n", (data[3] >> 8) & 1);
611 printf("TOE: %u\n", (data[3] >> 9) & 1);
612 printf("generation: %u\n", (data[3] >> 10) & 1);
613 printf("uP token: %u\n", (data[3] >> 11) & 0xfffff);
614 printf("valid: %u\n", (data[3] >> 31) & 1);
617 static void show_fl_cntxt(uint32_t data[])
619 printf("base address: 0x%llx\n",
620 ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
621 printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
622 printf("queue size: %u\n", (data[2] >> 4) & 0xffff);
623 printf("generation: %u\n", (data[2] >> 20) & 1);
624 printf("entry size: %u\n",
625 ((data[2] >> 21) & 0x7ff) | (data[3] & 0x1fffff));
626 printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff);
627 printf("GTS: %u\n", (data[3] >> 31) & 1);
630 static void show_response_cntxt(uint32_t data[])
632 printf("index: %u\n", data[0] & 0xffff);
633 printf("size: %u\n", data[0] >> 16);
634 printf("base address: 0x%llx\n",
635 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
636 printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f);
637 printf("intr enable: %u\n", (data[2] >> 26) & 1);
638 printf("intr armed: %u\n", (data[2] >> 27) & 1);
639 printf("generation: %u\n", (data[2] >> 28) & 1);
640 printf("CQ mode: %u\n", (data[2] >> 31) & 1);
641 printf("FL threshold: %u\n", data[3]);
644 static void show_cq_cntxt(uint32_t data[])
646 printf("index: %u\n", data[0] & 0xffff);
647 printf("size: %u\n", data[0] >> 16);
648 printf("base address: 0x%llx\n",
649 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
650 printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f);
651 printf("AN: %u\n", (data[2] >> 26) & 1);
652 printf("armed: %u\n", (data[2] >> 27) & 1);
653 printf("ANS: %u\n", (data[2] >> 28) & 1);
654 printf("generation: %u\n", (data[2] >> 29) & 1);
655 printf("overflow mode: %u\n", (data[2] >> 31) & 1);
656 printf("credits: %u\n", data[3] & 0xffff);
657 printf("credit threshold: %u\n", data[3] >> 16);
660 static int get_sge_context(int argc, char *argv[], int start_arg,
661 const char *iff_name)
665 if (argc != start_arg + 2) return -1;
667 if (!strcmp(argv[start_arg], "egress"))
668 ctx.cntxt_type = CNTXT_TYPE_EGRESS;
669 else if (!strcmp(argv[start_arg], "fl"))
670 ctx.cntxt_type = CNTXT_TYPE_FL;
671 else if (!strcmp(argv[start_arg], "response"))
672 ctx.cntxt_type = CNTXT_TYPE_RSP;
673 else if (!strcmp(argv[start_arg], "cq"))
674 ctx.cntxt_type = CNTXT_TYPE_CQ;
676 warnx("unknown context type \"%s\"; known types are egress, "
677 "fl, cq, and response", argv[start_arg]);
681 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
684 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
685 err(1, "get SGE context");
687 if (!strcmp(argv[start_arg], "egress"))
688 show_egress_cntxt(ctx.data);
689 else if (!strcmp(argv[start_arg], "fl"))
690 show_fl_cntxt(ctx.data);
691 else if (!strcmp(argv[start_arg], "response"))
692 show_response_cntxt(ctx.data);
693 else if (!strcmp(argv[start_arg], "cq"))
694 show_cq_cntxt(ctx.data);
698 #if __BYTE_ORDER == __BIG_ENDIAN
699 # define ntohll(n) (n)
701 # define ntohll(n) bswap_64(n)
704 static int get_sge_desc(int argc, char *argv[], int start_arg,
705 const char *iff_name)
708 unsigned int n = 1, qset, qnum;
711 if (argc != start_arg + 3 && argc != start_arg + 4)
714 if (get_int_arg(argv[start_arg], &qset) ||
715 get_int_arg(argv[start_arg + 1], &qnum) ||
716 get_int_arg(argv[start_arg + 2], &desc.idx))
719 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
723 errx(1, "invalid queue number %d, range is 0..5", qnum);
725 desc.queue_num = qset * 6 + qnum;
727 for (; n--; desc.idx++) {
728 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
729 err(1, "get SGE descriptor");
731 p = (uint64_t *)desc.data;
733 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
734 desc.idx, (unsigned int)(wr_hdr >> 56),
735 ((unsigned int)wr_hdr >> 8) & 0xfffff,
736 ((wr_hdr >> 55) & 1) ? "SOP, " : "",
737 ((wr_hdr >> 54) & 1) ? "EOP, " : "",
738 ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
739 ((wr_hdr >> 52) & 1) ? "SGL, " : "",
740 (unsigned int)wr_hdr & 0xff);
742 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
743 printf("%016" PRIx64 "%c", ntohll(*p),
744 desc.size % 32 == 8 ? '\n' : ' ');
751 static int get_tcb2(unsigned int tcb_idx, const char *iff_name)
755 struct toetool_mem_range *op;
757 op = malloc(sizeof(*op) + TCB_SIZE);
761 op->cmd = TOETOOL_GET_MEM;
763 op->addr = tcb_idx * TCB_SIZE;
766 if (doit(iff_name, op) < 0)
769 for (d = (uint64_t *)op->buf, i = 0; i < TCB_SIZE / 32; i++) {
771 printf(" %08x %08x %08x %08x", (uint32_t)d[1],
772 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
773 (uint32_t)(d[0] >> 32));
775 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
776 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
777 (uint32_t)(d[0] >> 32));
784 static int get_tcb(int argc, char *argv[], int start_arg, const char *iff_name)
788 struct toetool_tcb op;
790 if (argc != start_arg + 1) return -1;
792 op.cmd = TOETOOL_GET_TCB;
793 if (get_int_arg(argv[start_arg], &op.tcb_index))
797 * If this operation isn't directly supported by the driver we may
798 * still be able to read TCBs using the generic memory dump operation.
800 if (doit(iff_name, &op) < 0) {
801 if (errno != EOPNOTSUPP)
803 return get_tcb2(op.tcb_index, iff_name);
806 for (d = op.tcb_data, i = 0; i < TCB_WORDS; i += 8) {
809 printf("%2u:", 4 * i);
810 for (j = 0; j < 8; ++j)
811 printf(" %08x", *d++);
819 * The following defines, typedefs and structures are defined in the FW and
820 * should be exported instead of being redefined here (and kept up in sync).
821 * We'll fix this in the next round of FW cleanup.
823 #define CM_WRCONTEXT_BASE 0x20300000
824 #define CM_WRCONTEXT_OFFSET 0x300000
825 #define WRC_SIZE (FW_WR_SIZE * (2 + FW_WR_NUM) + 32 + 4 * 128)
826 #define FW_WR_SIZE 128
828 #define FBUF_SIZE (FW_WR_SIZE * FW_WR_NUM)
829 #define FBUF_WRAP_SIZE 128
830 #define FBUF_WRAP_FSZ (FBUF_WRAP_SZ >> 3)
831 #define MEM_CM_WRC_SIZE WRC_SIZE
834 typedef short int16_t;
836 typedef long long _s64;
837 typedef unsigned char _u8;
838 typedef unsigned short _u16;
839 typedef unsigned int _uint32_t;
840 typedef unsigned long long uint64_t;
842 enum fw_ri_mpa_attrs {
843 FW_RI_MPA_RX_MARKER_ENABLE = 0x1,
844 FW_RI_MPA_TX_MARKER_ENABLE = 0x2,
845 FW_RI_MPA_CRC_ENABLE = 0x4,
846 FW_RI_MPA_IETF_ENABLE = 0x8
847 } __attribute__ ((packed));
850 FW_RI_QP_RDMA_READ_ENABLE = 0x01,
851 FW_RI_QP_RDMA_WRITE_ENABLE = 0x02,
852 FW_RI_QP_BIND_ENABLE = 0x04,
853 FW_RI_QP_FAST_REGISTER_ENABLE = 0x08,
854 FW_RI_QP_STAG0_ENABLE = 0x10
855 } __attribute__ ((packed));
860 WRC_STATE_HALFCLOSED,
861 WRC_STATE_TOE_ESTABLISHED,
862 WRC_STATE_RDMA_TX_DATA_PEND,
864 WRC_STATE_RDMA_ESTABLISHED,
873 uint32_t pp; /* fifo producer pointer */
874 uint32_t cp; /* fifo consumer pointer */
875 int32_t num_bytes; /* num bytes stored in the fbuf */
876 char bufferb[FBUF_SIZE]; /* buffer space in bytes */
877 char _wrap[FBUF_WRAP_SIZE]; /* wrap buffer size*/
891 _u8 wrc_coherency_counter;
895 _u8 wrc_frag_credits;
903 _u8 wrc_num_tx_pages;
904 _u8 wrc_max_tx_pages;
906 uint32_t wrc_snd_nxt;
907 uint32_t wrc_snd_max;
908 uint32_t wrc_snd_una;
909 uint32_t wrc_snd_iss;
915 uint32_t wrc_rq_addr_32a;
918 enum fw_ri_mpa_attrs wrc_mpaattrs;
919 enum fw_ri_qp_caps wrc_qpcaps;
920 _u16 wrc_mulpdu_tagged;
921 _u16 wrc_mulpdu_untagged;
926 _u16 wrc_markeroffset;
927 uint32_t wrc_msn_send;
928 uint32_t wrc_msn_rdma_read;
929 uint32_t wrc_msn_rdma_read_req;
930 _u16 wrc_rdma_read_req_err;
932 _u8 wrc_sge_ec_credits;
933 _u16 wrc_maxiolen_tagged;
934 _u16 wrc_maxiolen_untagged;
943 uint32_t wrc_pad2[24];
945 } u __attribute__ ((packed));
948 struct fbuf wrc_fbuf __attribute__ ((packed));
950 #define wrc_aborted u.toe_ri.aborted
951 #define wrc_num_tx_pages u.toe_ri.wrc_num_tx_pages
952 #define wrc_max_tx_pages u.toe_ri.wrc_max_tx_pages
953 #define wrc_trace_idx u.toe_ri.wrc_trace_idx
954 #define wrc_snd_nxt u.toe_ri.wrc_snd_nxt
955 #define wrc_snd_max u.toe_ri.wrc_snd_max
956 #define wrc_snd_una u.toe_ri.wrc_snd_una
957 #define wrc_snd_iss u.toe_ri.wrc_snd_iss
958 #define wrc_pdid u.toe_ri.wrc_pdid
959 #define wrc_scqid u.toe_ri.wrc_scqid
960 #define wrc_rcqid u.toe_ri.wrc_rcqid
961 #define wrc_rq_addr_32a u.toe_ri.wrc_rq_addr_32a
962 #define wrc_rq_size u.toe_ri.wrc_rq_size
963 #define wrc_rq_wr_idx u.toe_ri.wrc_rq_wr_idx
964 #define wrc_mpaattrs u.toe_ri.wrc_mpaattrs
965 #define wrc_qpcaps u.toe_ri.wrc_qpcaps
966 #define wrc_mulpdu_tagged u.toe_ri.wrc_mulpdu_tagged
967 #define wrc_mulpdu_untagged u.toe_ri.wrc_mulpdu_untagged
968 #define wrc_ord_max u.toe_ri.wrc_ord_max
969 #define wrc_ird_max u.toe_ri.wrc_ird_max
970 #define wrc_ord u.toe_ri.wrc_ord
971 #define wrc_ird u.toe_ri.wrc_ird
972 #define wrc_markeroffset u.toe_ri.wrc_markeroffset
973 #define wrc_msn_send u.toe_ri.wrc_msn_send
974 #define wrc_msn_rdma_read u.toe_ri.wrc_msn_rdma_read
975 #define wrc_msn_rdma_read_req u.toe_ri.wrc_msn_rdma_read_req
976 #define wrc_rdma_read_req_err u.toe_ri.wrc_rdma_read_req_err
977 #define wrc_ack_mode u.toe_ri.wrc_ack_mode
978 #define wrc_sge_ec_credits u.toe_ri.wrc_sge_ec_credits
979 #define wrc_maxiolen_tagged u.toe_ri.wrc_maxiolen_tagged
980 #define wrc_maxiolen_untagged u.toe_ri.wrc_maxiolen_untagged
981 #define wrc_mo u.toe_ri.wrc_mo
983 static void print_wrc_field(char *field, unsigned int value, unsigned int size)
987 printf(" 1 %s: 0x%02x (%u)\n", field, value, value);
990 unsigned short host_value = ntohs(value);
991 printf(" 2 %s: 0x%04x (%u)\n", field, host_value, host_value);
995 unsigned int host_value = ntohl(value);
996 printf(" 4 %s: 0x%08x (%u)\n", field, host_value, host_value);
1000 printf(" unknown size %u for field %s\n", size, field);
1004 #define P(field) print_wrc_field(#field, p->wrc_ ## field, sizeof (p->wrc_ ## field))
1006 static void print_wrc(unsigned int wrc_idx, struct wrc *p)
1008 u32 *buf = (u32 *)p;
1011 printf("WRC STATE (raw)\n");
1012 for (i = 0; i < 32;) {
1013 printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4);
1014 for (j = 0; j < 8; j++) {
1015 printf(" %08x ", htonl(buf[i++]));
1019 printf("WRC BASIC\n");
1020 P(tid); P(flags); P(state); P(credits);
1022 P(sge_ec); P(sge_respQ); P(port); P(ulp); P(coherency_counter);
1023 printf("WRC REASSEMBLY\n");
1024 P(frag_len); P(frag_credits); P(frag);
1025 printf("WRC TOE\n");
1026 P(aborted); P(num_tx_pages); P(max_tx_pages); P(trace_idx); P(snd_nxt);
1027 P(snd_max); P(snd_una); P(snd_iss);
1029 P(pdid); P(scqid); P(rcqid); P(rq_addr_32a); P(rq_size); P(rq_wr_idx);
1030 P(mpaattrs); P(qpcaps); P(mulpdu_tagged); P(mulpdu_untagged); P(ord_max);
1031 P(ird_max); P(ord); P(ird); P(markeroffset); P(msn_send); P(msn_rdma_read);
1032 P(msn_rdma_read_req); P(rdma_read_req_err); P(ack_mode);
1033 P(sge_ec_credits); P(maxiolen_tagged); P(maxiolen_untagged); P(mo);
1034 printf("WRC BUFFERING\n");
1035 printf(" 4 fbuf.pp: 0x%08x (%u)\n", htonl(p->wrc_fbuf.pp), htonl(p->wrc_fbuf.pp));
1036 printf(" 4 fbuf.cp: 0x%08x (%u)\n", htonl(p->wrc_fbuf.cp), htonl(p->wrc_fbuf.cp));
1037 printf(" 4 fbuf.num_bytes: 0x%08x (%d)\n", htonl(p->wrc_fbuf.num_bytes), htonl(p->wrc_fbuf.num_bytes));
1038 printf("WRC BUFFER (raw)\n");
1039 for (i = 32; i < (FBUF_SIZE + FBUF_WRAP_SIZE) / 4;) {
1040 printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4);
1041 for (j = 0; j < 4; j++) {
1042 printf(" %08x%08x", htonl(buf[i++]), htonl(buf[i++]));
1050 #define P(field) print_sizeof(#field, ##field, sizeof (p->##field))
1060 static void print_wrc_zero(unsigned int wrc_idx, struct wrc *p)
1063 (uint32_t *)((unsigned long)p + FW_WR_SIZE * (2 + FW_WR_NUM));
1066 printf("WRC ZERO\n");
1067 printf("[%08x]:", CM_WRCONTEXT_BASE + wrc_idx * MEM_CM_WRC_SIZE +
1068 FW_WR_SIZE * (2 + FW_WR_NUM));
1070 printf(" %08x%08x", htonl(buf[i]), htonl(buf[i++]));
1074 static void print_wrc_history(struct wrc *p)
1076 unsigned int i, idx;
1077 struct history_e *e =
1078 (struct history_e *)((unsigned long)p + FW_WR_SIZE *
1079 (2 + FW_WR_NUM) + 32);
1080 printf("WRC WR HISTORY, idx %u\n", p->wrc_trace_idx);
1081 idx = p->wrc_trace_idx;
1082 for (i = 0; i < 16; i++) {
1083 printf("%02u: %08x %08x %08x%08x %08x%08x %08x%08x\n", idx,
1084 htonl(e[idx].wr_addr), htonl(e[idx].debug),
1085 htonl(e[idx].wr_flit0 & 0xFFFFFFFF),
1086 htonl(e[idx].wr_flit0 >> 32),
1087 htonl(e[idx].wr_flit1 & 0xFFFFFFFF),
1088 htonl(e[idx].wr_flit1 >> 32),
1089 htonl(e[idx].wr_flit2 & 0xFFFFFFFF),
1090 htonl(e[idx].wr_flit2 >> 32));
1091 idx = (idx - 1) & 0xF;
1095 static int get_wrc(int argc, char *argv[], int start_arg, const char *iff_name)
1097 struct toetool_mem_range *op;
1100 unsigned int idx, i = 0;
1102 if (argc != start_arg + 1)
1105 if (get_int_arg(argv[start_arg], &idx))
1108 op = malloc(sizeof(*op) + MEM_CM_WRC_SIZE);
1110 err(1, "get_wrc: malloc failed");
1112 op->cmd = TOETOOL_GET_MEM;
1113 op->mem_id = MEM_CM;
1114 op->addr = read_reg(iff_name, 0x28c) + CM_WRCONTEXT_OFFSET +
1115 idx * MEM_CM_WRC_SIZE;
1116 op->len = MEM_CM_WRC_SIZE;
1117 buf = (uint32_t *)op->buf;
1119 if (doit(iff_name, op) < 0)
1122 /* driver manges with the data... put it back into the the FW's view
1124 for (p = (uint64_t *)op->buf;
1125 p < (uint64_t *)(op->buf + MEM_CM_WRC_SIZE); p++) {
1127 buf[i++] = htonl((uint32_t)(flit >> 32));
1128 buf[i++] = htonl((uint32_t)flit);
1131 print_wrc(idx, (struct wrc *)op->buf);
1132 print_wrc_zero(idx, (struct wrc *)op->buf);
1133 print_wrc_history((struct wrc *)op->buf);
1141 static int get_pm_page_spec(const char *s, unsigned int *page_size,
1142 unsigned int *num_pages)
1147 val = strtoul(s, &p, 0);
1148 if (p == s) return -1;
1149 if (*p == 'x' && p[1]) {
1151 *page_size = strtoul(p + 1, &p, 0);
1156 *page_size <<= 10; // KB -> bytes
1160 static int conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
1162 struct toetool_pm op;
1164 if (argc == start_arg) {
1165 op.cmd = TOETOOL_GET_PM;
1166 if (doit(iff_name, &op) < 0)
1167 err(1, "read pm config");
1168 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
1169 op.tx_num_pg, op.tx_pg_sz >> 10, op.rx_num_pg,
1170 op.rx_pg_sz >> 10, op.pm_total >> 10);
1174 if (argc != start_arg + 2) return -1;
1176 if (get_pm_page_spec(argv[start_arg], &op.tx_pg_sz, &op.tx_num_pg)) {
1177 warnx("bad parameter \"%s\"", argv[start_arg]);
1180 if (get_pm_page_spec(argv[start_arg + 1], &op.rx_pg_sz,
1182 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
1185 op.cmd = TOETOOL_SET_PM;
1186 if (doit(iff_name, &op) < 0)
1187 err(1, "pm config");
1191 static int conf_tcam(int argc, char *argv[], int start_arg,
1192 const char *iff_name)
1194 struct toetool_tcam op;
1196 if (argc == start_arg) {
1197 op.cmd = TOETOOL_GET_TCAM;
1199 if (doit(iff_name, &op) < 0)
1200 err(1, "read tcam config");
1201 printf("%u total entries, %u servers, %u filters, %u routes\n",
1202 op.tcam_size, op.nservers, op.nfilters, op.nroutes);
1206 if (argc != start_arg + 3) return -1;
1208 if (get_int_arg(argv[start_arg], &op.nservers) ||
1209 get_int_arg(argv[start_arg + 1], &op.nroutes) ||
1210 get_int_arg(argv[start_arg + 2], &op.nfilters))
1212 op.cmd = TOETOOL_SET_TCAM;
1213 if (doit(iff_name, &op) < 0)
1214 err(1, "tcam config");
1219 #ifdef CHELSIO_INTERNAL
1221 static int dump_tcam(int argc, char *argv[], int start_arg,
1222 const char *iff_name)
1224 unsigned int nwords;
1225 struct toetool_tcam_word op;
1227 if (argc != start_arg + 2) return -1;
1229 if (get_int_arg(argv[start_arg], &op.addr) ||
1230 get_int_arg(argv[start_arg + 1], &nwords))
1232 op.cmd = TOETOOL_READ_TCAM_WORD;
1235 if (doit(iff_name, &op) < 0)
1236 err(1, "tcam dump");
1238 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
1239 op.buf[0] & 0xff, op.buf[1], op.buf[2]);
1245 static void hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
1250 printf("0x%08x:", start);
1251 for (i = 0; i < 4 && len; ++i, --len)
1252 printf(" %016llx", (unsigned long long)*data++);
1258 static int dump_mc7(int argc, char *argv[], int start_arg,
1259 const char *iff_name)
1261 struct ch_mem_range mem;
1262 unsigned int mem_id, addr, len;
1264 if (argc != start_arg + 3) return -1;
1266 if (!strcmp(argv[start_arg], "cm"))
1268 else if (!strcmp(argv[start_arg], "rx"))
1270 else if (!strcmp(argv[start_arg], "tx"))
1273 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
1274 " or \"rx\"", argv[start_arg]);
1276 if (get_int_arg(argv[start_arg + 1], &addr) ||
1277 get_int_arg(argv[start_arg + 2], &len))
1280 mem.buf = malloc(len);
1282 err(1, "memory dump");
1284 mem.mem_id = mem_id;
1288 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
1289 err(1, "memory dump");
1291 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
1298 /* Max FW size is 32K including version, +4 bytes for the checksum. */
1299 #define MAX_FW_IMAGE_SIZE (32768 + 4)
1301 static int load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
1304 struct toetool_mem_range *op;
1305 const char *fname = argv[start_arg];
1307 if (argc != start_arg + 1) return -1;
1309 fd = open(fname, O_RDONLY);
1311 err(1, "load firmware");
1313 op = malloc(sizeof(*op) + MAX_FW_IMAGE_SIZE + 1);
1315 err(1, "load firmware");
1317 len = read(fd, op->buf, MAX_FW_IMAGE_SIZE + 1);
1319 err(1, "load firmware");
1320 if (len > MAX_FW_IMAGE_SIZE)
1321 errx(1, "FW image too large");
1323 op->cmd = TOETOOL_LOAD_FW;
1326 if (doit(iff_name, op) < 0)
1327 err(1, "load firmware");
1332 static int write_proto_sram(const char *fname, const char *iff_name)
1336 struct toetool_proto op = { .cmd = TOETOOL_SET_PROTO };
1337 uint32_t *p = op.data;
1338 FILE *fp = fopen(fname, "r");
1341 err(1, "load protocol sram");
1343 for (i = 0; i < 128; i++, p += 5) {
1344 int n = fscanf(fp, "%1x%8x%8x%8x%8x",
1345 &p[0], &p[1], &p[2], &p[3], &p[4]);
1347 errx(1, "%s: bad line %d", fname, i);
1349 if (fscanf(fp, "%1s", &c) != EOF)
1350 errx(1, "%s: protocol sram image has too many lines", fname);
1353 if (doit(iff_name, &op) < 0)
1354 err(1, "load protocol sram");
1358 static int dump_proto_sram(const char *iff_name)
1361 u8 buf[sizeof(struct ethtool_eeprom) + PROTO_SRAM_SIZE];
1362 struct ethtool_eeprom *ee = (struct ethtool_eeprom *)buf;
1363 u8 *p = buf + sizeof(struct ethtool_eeprom);
1365 ee->cmd = ETHTOOL_GEEPROM;
1366 ee->len = PROTO_SRAM_SIZE;
1367 ee->offset = PROTO_SRAM_EEPROM_ADDR;
1368 if (ethtool_call(iff_name, ee))
1369 err(1, "show protocol sram");
1371 for (i = 0; i < PROTO_SRAM_LINES; i++) {
1372 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1373 int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1374 u8 nibble = p[nibble_idx / 2];
1380 printf("%x", nibble);
1387 static int proto_sram_op(int argc, char *argv[], int start_arg,
1388 const char *iff_name)
1390 if (argc == start_arg + 1)
1391 return write_proto_sram(argv[start_arg], iff_name);
1392 if (argc == start_arg)
1393 return dump_proto_sram(iff_name);
1398 static int dump_qset_params(const char *iff_name)
1400 struct ch_qset_params qp;
1404 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1406 printf("Qnum TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1"
1407 " Cong Intr Lat Rx Mode\n");
1408 printf("%4u %6u %6u %6u %6u %6u %6u %5u %9u %s \n",
1410 qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1411 qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1412 qp.cong_thres, qp.intr_lat,
1413 qp.polling ? "Polling" : "Interrupt");
1416 if (!qp.qset_idx || (errno && errno != EINVAL))
1417 err(1, "get qset parameters");
1421 static int qset_config(int argc, char *argv[], int start_arg,
1422 const char *iff_name)
1424 struct ch_qset_params qp;
1426 if (argc == start_arg)
1427 return dump_qset_params(iff_name);
1429 if (get_int_arg(argv[start_arg++], &qp.qset_idx))
1432 qp.txq_size[0] = qp.txq_size[1] = qp.txq_size[2] = -1;
1433 qp.fl_size[0] = qp.fl_size[1] = qp.rspq_size = -1;
1434 qp.polling = qp.intr_lat = qp.cong_thres = -1;
1436 while (start_arg + 2 <= argc) {
1437 int32_t *param = NULL;
1439 if (!strcmp(argv[start_arg], "txq0"))
1440 param = &qp.txq_size[0];
1441 else if (!strcmp(argv[start_arg], "txq1"))
1442 param = &qp.txq_size[1];
1443 else if (!strcmp(argv[start_arg], "txq2"))
1444 param = &qp.txq_size[2];
1445 else if (!strcmp(argv[start_arg], "rspq"))
1446 param = &qp.rspq_size;
1447 else if (!strcmp(argv[start_arg], "fl0"))
1448 param = &qp.fl_size[0];
1449 else if (!strcmp(argv[start_arg], "fl1"))
1450 param = &qp.fl_size[1];
1451 else if (!strcmp(argv[start_arg], "lat"))
1452 param = &qp.intr_lat;
1453 else if (!strcmp(argv[start_arg], "cong"))
1454 param = &qp.cong_thres;
1455 else if (!strcmp(argv[start_arg], "mode"))
1456 param = &qp.polling;
1458 errx(1, "unknown qset parameter \"%s\"\n"
1459 "allowed parameters are \"txq0\", \"txq1\", "
1460 "\"txq2\", \"rspq\", \"fl0\", \"fl1\", \"lat\", "
1461 "\"cong\", \"mode\' and \"lro\"", argv[start_arg]);
1465 if (param == &qp.polling) {
1466 if (!strcmp(argv[start_arg], "irq"))
1468 else if (!strcmp(argv[start_arg], "polling"))
1471 errx(1, "illegal qset mode \"%s\"\n"
1472 "known modes are \"irq\" and \"polling\"",
1474 } else if (get_int_arg(argv[start_arg], (uint32_t *)param))
1478 if (start_arg != argc)
1479 errx(1, "unknown parameter %s", argv[start_arg]);
1482 printf("%4u %6d %6d %6d %6d %6d %6d %5d %9d %d\n", op.qset_idx,
1483 op.txq_size[0], op.txq_size[1], op.txq_size[2],
1484 op.rspq_size, op.fl_size[0], op.fl_size[1], op.cong_thres,
1485 op.intr_lat, op.polling);
1487 if (doit(iff_name, CHELSIO_SET_QSET_PARAMS, &qp) < 0)
1488 err(1, "set qset parameters");
1493 static int qset_num_config(int argc, char *argv[], int start_arg,
1494 const char *iff_name)
1498 if (argc == start_arg) {
1499 if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0)
1500 err(1, "get qsets");
1501 printf("%u\n", reg.val);
1505 if (argc != start_arg + 1)
1507 if (get_int_arg(argv[start_arg], ®.val))
1510 if (doit(iff_name, CHELSIO_SET_QSET_NUM, ®) < 0)
1511 err(1, "set qsets");
1516 * Parse a string containing an IP address with an optional network prefix.
1518 static int parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1523 *mask = 0xffffffffU;
1524 slash = strchr(s, '/');
1527 if (!inet_aton(s, &ia)) {
1533 *addr = ntohl(ia.s_addr);
1535 unsigned int prefix = strtoul(slash + 1, &p, 10);
1538 if (p == slash + 1 || *p || prefix > 32)
1540 *mask <<= (32 - prefix);
1546 * Parse a string containing a value and an optional colon separated mask.
1548 static int parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask)
1552 *mask = 0xffffffffU;
1553 *val = strtoul(s, &p, 0);
1556 if (*p == ':' && p[1])
1557 *mask = strtoul(p + 1, &p, 0);
1561 static int parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1563 return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1564 parse_val_mask_param(s, val, mask);
1567 static int trace_config(int argc, char *argv[], int start_arg,
1568 const char *iff_name)
1571 struct ch_trace trace;
1573 if (argc == start_arg)
1576 memset(&trace, 0, sizeof(trace));
1577 if (!strcmp(argv[start_arg], "tx"))
1578 trace.config_tx = 1;
1579 else if (!strcmp(argv[start_arg], "rx"))
1580 trace.config_rx = 1;
1581 else if (!strcmp(argv[start_arg], "all"))
1582 trace.config_tx = trace.config_rx = 1;
1584 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1585 "\"tx\" or \"all\"", argv[start_arg]);
1587 if (argc == ++start_arg)
1589 if (!strcmp(argv[start_arg], "on")) {
1590 trace.trace_tx = trace.config_tx;
1591 trace.trace_rx = trace.config_rx;
1592 } else if (strcmp(argv[start_arg], "off"))
1593 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1597 if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1598 trace.invert_match = 1;
1602 while (start_arg + 2 <= argc) {
1603 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1605 if (!strcmp(argv[start_arg], "interface")) {
1607 trace.intf_mask = mask;
1608 } else if (!strcmp(argv[start_arg], "sip")) {
1610 trace.sip_mask = mask;
1611 } else if (!strcmp(argv[start_arg], "dip")) {
1613 trace.dip_mask = mask;
1614 } else if (!strcmp(argv[start_arg], "sport")) {
1616 trace.sport_mask = mask;
1617 } else if (!strcmp(argv[start_arg], "dport")) {
1619 trace.dport_mask = mask;
1620 } else if (!strcmp(argv[start_arg], "vlan")) {
1622 trace.vlan_mask = mask;
1623 } else if (!strcmp(argv[start_arg], "proto")) {
1625 trace.proto_mask = mask;
1627 errx(1, "unknown trace parameter \"%s\"\n"
1628 "known parameters are \"interface\", \"sip\", "
1629 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1630 "\"proto\"", argv[start_arg]);
1632 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1635 if (start_arg != argc)
1636 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1639 printf("sip: %x:%x, dip: %x:%x, sport: %x:%x, dport: %x:%x, "
1640 "interface: %x:%x, vlan: %x:%x, tx_config: %u, rx_config: %u, "
1641 "invert: %u, tx_enable: %u, rx_enable: %u\n", op.sip,
1642 op.sip_mask, op.dip, op.dip_mask, op.sport, op.sport_mask,
1643 op.dport, op.dport_mask, op.intf, op.intf_mask, op.vlan,
1644 op.vlan_mask, op.config_tx, op.config_rx, op.invert_match,
1645 op.trace_tx, op.trace_rx);
1647 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1653 static int t1_powersave(int argc, char *argv[], int start_arg,
1654 const char *iff_name)
1656 struct toetool_t1powersave op = {
1657 .cmd = TOETOOL_T1POWERSAVE,
1661 if (argc == start_arg)
1662 op.mode = 2; /* Check powersave mode */
1664 else if (argc == start_arg + 1) {
1665 if (strcmp(argv[start_arg], "on") == 0)
1667 else if (strcmp(argv[start_arg], "off") == 0)
1670 warnx("bad parameter \"%s\"", argv[start_arg]);
1674 errx(1, "too many arguments");
1678 if (doit(iff_name, &op) < 0)
1679 err(1, "t1powersave");
1682 printf("t1powersave is %s\n", (op.mode & 1) ? "on" : "off");
1688 static int pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1690 struct ch_pktsched_params pktsched;
1691 unsigned int idx, min = -1, max, binding = -1;
1693 if (!strcmp(argv[start_arg], "port")) {
1694 if (argc != start_arg + 4)
1696 if (get_int_arg(argv[start_arg + 1], &idx) ||
1697 get_int_arg(argv[start_arg + 2], &min) ||
1698 get_int_arg(argv[start_arg + 3], &max))
1701 } else if (!strcmp(argv[start_arg], "tunnelq")) {
1702 if (argc != start_arg + 4)
1704 if (get_int_arg(argv[start_arg + 1], &idx) ||
1705 get_int_arg(argv[start_arg + 2], &max) ||
1706 get_int_arg(argv[start_arg + 3], &binding))
1710 errx(1, "unknown scheduler \"%s\"; must be one of \"port\""
1711 " or \"tunnelq\"", argv[start_arg]);
1716 pktsched.binding = binding;
1717 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &pktsched) < 0)
1723 int main(int argc, char *argv[])
1726 const char *iff_name;
1731 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1733 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1734 printf("%s version %s\n", PROGNAME, VERSION);
1735 printf("%s\n", COPYRIGHT);
1740 if (argc < 3) usage(stderr);
1743 if (!strcmp(argv[2], "reg"))
1744 r = register_io(argc, argv, 3, iff_name);
1745 else if (!strcmp(argv[2], "mdio"))
1746 r = mdio_io(argc, argv, 3, iff_name);
1748 else if (!strcmp(argv[2], "tpi"))
1749 r = tpi_io(argc, argv, 3, iff_name);
1750 else if (!strcmp(argv[2], "up"))
1751 r = device_up(argc, argv, 3, iff_name);
1752 else if (!strcmp(argv[2], "mtus"))
1753 r = mtu_tab_op(argc, argv, 3, iff_name);
1754 else if (!strcmp(argv[2], "pm"))
1755 r = conf_pm(argc, argv, 3, iff_name);
1756 else if (!strcmp(argv[2], "tcam"))
1757 r = conf_tcam(argc, argv, 3, iff_name);
1758 else if (!strcmp(argv[2], "tcb"))
1759 r = get_tcb(argc, argv, 3, iff_name);
1761 else if (!strcmp(argv[2], "wrc"))
1762 r = get_wrc(argc, argv, 3, iff_name);
1765 else if (!strcmp(argv[2], "regdump"))
1766 r = dump_regs(argc, argv, 3, iff_name);
1767 #ifdef CHELSIO_INTERNAL
1768 else if (!strcmp(argv[2], "memdump"))
1769 r = dump_mc7(argc, argv, 3, iff_name);
1770 else if (!strcmp(argv[2], "meminfo"))
1771 r = meminfo(argc, argv, 3, iff_name);
1772 else if (!strcmp(argv[2], "context"))
1773 r = get_sge_context(argc, argv, 3, iff_name);
1774 else if (!strcmp(argv[2], "desc"))
1775 r = get_sge_desc(argc, argv, 3, iff_name);
1777 else if (!strcmp(argv[2], "qset"))
1778 r = qset_config(argc, argv, 3, iff_name);
1779 else if (!strcmp(argv[2], "qsets"))
1780 r = qset_num_config(argc, argv, 3, iff_name);
1781 else if (!strcmp(argv[2], "trace"))
1782 r = trace_config(argc, argv, 3, iff_name);
1784 else if (!strcmp(argv[2], "tcamdump"))
1785 r = dump_tcam(argc, argv, 3, iff_name);
1786 else if (!strcmp(argv[2], "loadfw"))
1787 r = load_fw(argc, argv, 3, iff_name);
1788 else if (!strcmp(argv[2], "proto"))
1789 r = proto_sram_op(argc, argv, 3, iff_name);
1790 else if (!strcmp(argv[2], "t1powersave"))
1791 r = t1_powersave(argc, argv, 3, iff_name);
1793 else if (!strcmp(argv[2], "pktsched"))
1794 r = pktsched(argc, argv, 3, iff_name);