1 /**************************************************************************
2 SPDX-License-Identifier: BSD-3-Clause
4 Copyright (c) 2007-2010, Chelsio Inc.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 3. Neither the name of the Chelsio Corporation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.
34 ***************************************************************************/
35 #include <sys/cdefs.h>
45 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
54 #include <net/if_types.h>
55 #include <sys/endian.h>
59 #define TCB_WORDS (TCB_SIZE / 4)
60 #define PROTO_SRAM_LINES 128
61 #define PROTO_SRAM_LINE_BITS 132
62 #define PROTO_SRAM_LINE_NIBBLES (132 / 4)
63 #define PROTO_SRAM_SIZE (PROTO_SRAM_LINE_NIBBLES * PROTO_SRAM_LINES / 2)
64 #define PROTO_SRAM_EEPROM_ADDR 4096
66 #include <cxgb_ioctl.h>
67 #include <common/cxgb_regs.h>
78 #if defined(CONFIG_T3_REGS)
79 # include "reg_defs_t3.c"
80 # include "reg_defs_t3b.c"
81 # include "reg_defs_t3c.c"
84 static const char *progname;
89 fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
91 "\tclearstats clear MAC statistics\n"
92 "\tcontext <type> <id> show an SGE context\n"
93 "\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
94 "\tfilter <idx> [<param> <val>] ... set a filter\n"
95 "\tfilter <idx> delete|clear delete a filter\n"
96 "\tfilter list list all filters\n"
97 "\tioqs dump uP IOQs\n"
98 "\tla dump uP logic analyzer info\n"
99 "\tloadboot <boot image> download boot image\n"
100 "\tloadfw <FW image> download firmware\n"
101 "\tmdio <phy_addr> <mmd_addr>\n"
102 "\t <reg_addr> [<val>] read/write MDIO register\n"
103 "\tmemdump cm|tx|rx <addr> <len> dump a mem range\n"
104 "\tmeminfo show memory info\n"
105 "\tmtus [<mtu0>...<mtuN>] read/write MTU table\n"
106 "\tpktsched port <idx> <min> <max> set TX port scheduler params\n"
107 "\tpktsched tunnelq <idx> <max>\n"
108 "\t <binding> set TX tunnelq scheduler params\n"
109 "\tpktsched tx <idx>\n"
110 "\t [<param> <val>] ... set Tx HW scheduler\n"
111 "\tpm [<TX page spec> <RX page spec>] read/write PM config\n"
112 "\tproto read proto SRAM\n"
113 "\tqset read qset parameters\n"
114 "\tqsets read # of qsets\n"
115 "\treg <address>[=<val>] read/write register\n"
116 "\tregdump [<module>] dump registers\n"
117 "\ttcamdump <address> <count> show TCAM contents\n"
118 "\ttcb <index> read TCB\n"
119 "\ttrace tx|rx|all on|off [not]\n"
120 "\t [<param> <val>[:<mask>]] ... write trace parameters\n"
122 exit(fp == stderr ? 1 : 0);
126 doit(const char *iff_name, unsigned long cmd, void *data)
132 snprintf(buf, 64, "/dev/%s", iff_name);
134 if ((fd = open(buf, O_RDWR)) < 0)
138 return ioctl(fd, cmd, data) < 0 ? -1 : 0;
142 get_int_arg(const char *s, uint32_t *valp)
146 *valp = strtoul(s, &p, 0);
148 warnx("bad parameter \"%s\"", s);
155 read_reg(const char *iff_name, uint32_t addr)
161 if (doit(iff_name, CHELSIO_GETREG, ®) < 0)
162 err(1, "register read");
167 write_reg(const char *iff_name, uint32_t addr, uint32_t val)
169 struct ch_reg ch_reg;
174 if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
175 err(1, "register write");
179 register_io(int argc, char *argv[], int start_arg,
180 const char *iff_name)
183 uint32_t addr, val = 0, w = 0;
185 if (argc != start_arg + 1) return -1;
187 addr = strtoul(argv[start_arg], &p, 0);
188 if (p == argv[start_arg]) return -1;
189 if (*p == '=' && p[1]) {
190 val = strtoul(p + 1, &p, 0);
194 warnx("bad parameter \"%s\"", argv[start_arg]);
199 write_reg(iff_name, addr, val);
201 val = read_reg(iff_name, addr);
202 printf("%#x [%u]\n", val, val);
208 mdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
210 struct ch_mii_data p;
211 unsigned int cmd, phy_addr, reg, mmd, val;
213 if (argc == start_arg + 3)
214 cmd = CHELSIO_GET_MIIREG;
215 else if (argc == start_arg + 4)
216 cmd = CHELSIO_SET_MIIREG;
220 if (get_int_arg(argv[start_arg], &phy_addr) ||
221 get_int_arg(argv[start_arg + 1], &mmd) ||
222 get_int_arg(argv[start_arg + 2], ®) ||
223 (cmd == CHELSIO_SET_MIIREG && get_int_arg(argv[start_arg + 3], &val)))
226 p.phy_id = phy_addr | (mmd << 8);
230 if (doit(iff_name, cmd, &p) < 0)
231 err(1, "MDIO %s", cmd == CHELSIO_GET_MIIREG ? "read" : "write");
232 if (cmd == CHELSIO_GET_MIIREG)
233 printf("%#x [%u]\n", p.val_out, p.val_out);
238 uint32_t xtract(uint32_t val, int shift, int len)
240 return (val >> shift) & ((1 << len) - 1);
244 dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
246 uint32_t reg_val = 0; // silence compiler warning
248 for ( ; reg_array->name; ++reg_array)
249 if (!reg_array->len) {
250 reg_val = regs[reg_array->addr / 4];
251 printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
252 reg_array->name, reg_val, reg_val);
254 uint32_t v = xtract(reg_val, reg_array->addr,
257 printf(" %-40s %#-10x [%u]\n", reg_array->name,
264 dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
267 char *block_name = NULL;
269 if (argc == start_arg + 1)
270 block_name = argv[start_arg];
271 else if (argc != start_arg)
274 if (!block_name || !strcmp(block_name, "sge"))
275 match += dump_block_regs(sge_regs, regs);
276 if (!block_name || !strcmp(block_name, "mc3"))
277 match += dump_block_regs(mc3_regs, regs);
278 if (!block_name || !strcmp(block_name, "mc4"))
279 match += dump_block_regs(mc4_regs, regs);
280 if (!block_name || !strcmp(block_name, "tpi"))
281 match += dump_block_regs(tpi_regs, regs);
282 if (!block_name || !strcmp(block_name, "tp"))
283 match += dump_block_regs(tp_regs, regs);
284 if (!block_name || !strcmp(block_name, "rat"))
285 match += dump_block_regs(rat_regs, regs);
286 if (!block_name || !strcmp(block_name, "cspi"))
287 match += dump_block_regs(cspi_regs, regs);
288 if (!block_name || !strcmp(block_name, "espi"))
289 match += dump_block_regs(espi_regs, regs);
290 if (!block_name || !strcmp(block_name, "ulp"))
291 match += dump_block_regs(ulp_regs, regs);
292 if (!block_name || !strcmp(block_name, "pl"))
293 match += dump_block_regs(pl_regs, regs);
294 if (!block_name || !strcmp(block_name, "mc5"))
295 match += dump_block_regs(mc5_regs, regs);
297 errx(1, "unknown block \"%s\"", block_name);
301 #if defined(CONFIG_T3_REGS)
303 dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie)
306 char *block_name = NULL;
308 if (argc == start_arg + 1)
309 block_name = argv[start_arg];
310 else if (argc != start_arg)
313 if (!block_name || !strcmp(block_name, "sge"))
314 match += dump_block_regs(sge3_regs, regs);
315 if (!block_name || !strcmp(block_name, "pci"))
316 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
318 if (!block_name || !strcmp(block_name, "t3dbg"))
319 match += dump_block_regs(t3dbg_regs, regs);
320 if (!block_name || !strcmp(block_name, "pmrx"))
321 match += dump_block_regs(mc7_pmrx_regs, regs);
322 if (!block_name || !strcmp(block_name, "pmtx"))
323 match += dump_block_regs(mc7_pmtx_regs, regs);
324 if (!block_name || !strcmp(block_name, "cm"))
325 match += dump_block_regs(mc7_cm_regs, regs);
326 if (!block_name || !strcmp(block_name, "cim"))
327 match += dump_block_regs(cim_regs, regs);
328 if (!block_name || !strcmp(block_name, "tp"))
329 match += dump_block_regs(tp1_regs, regs);
330 if (!block_name || !strcmp(block_name, "ulp_rx"))
331 match += dump_block_regs(ulp2_rx_regs, regs);
332 if (!block_name || !strcmp(block_name, "ulp_tx"))
333 match += dump_block_regs(ulp2_tx_regs, regs);
334 if (!block_name || !strcmp(block_name, "pmrx"))
335 match += dump_block_regs(pm1_rx_regs, regs);
336 if (!block_name || !strcmp(block_name, "pmtx"))
337 match += dump_block_regs(pm1_tx_regs, regs);
338 if (!block_name || !strcmp(block_name, "mps"))
339 match += dump_block_regs(mps0_regs, regs);
340 if (!block_name || !strcmp(block_name, "cplsw"))
341 match += dump_block_regs(cpl_switch_regs, regs);
342 if (!block_name || !strcmp(block_name, "smb"))
343 match += dump_block_regs(smb0_regs, regs);
344 if (!block_name || !strcmp(block_name, "i2c"))
345 match += dump_block_regs(i2cm0_regs, regs);
346 if (!block_name || !strcmp(block_name, "mi1"))
347 match += dump_block_regs(mi1_regs, regs);
348 if (!block_name || !strcmp(block_name, "sf"))
349 match += dump_block_regs(sf1_regs, regs);
350 if (!block_name || !strcmp(block_name, "pl"))
351 match += dump_block_regs(pl3_regs, regs);
352 if (!block_name || !strcmp(block_name, "mc5"))
353 match += dump_block_regs(mc5a_regs, regs);
354 if (!block_name || !strcmp(block_name, "xgmac0"))
355 match += dump_block_regs(xgmac0_0_regs, regs);
356 if (!block_name || !strcmp(block_name, "xgmac1"))
357 match += dump_block_regs(xgmac0_1_regs, regs);
359 errx(1, "unknown block \"%s\"", block_name);
364 dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
368 char *block_name = NULL;
370 if (argc == start_arg + 1)
371 block_name = argv[start_arg];
372 else if (argc != start_arg)
375 if (!block_name || !strcmp(block_name, "sge"))
376 match += dump_block_regs(t3b_sge3_regs, regs);
377 if (!block_name || !strcmp(block_name, "pci"))
378 match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
379 t3b_pcix1_regs, regs);
380 if (!block_name || !strcmp(block_name, "t3dbg"))
381 match += dump_block_regs(t3b_t3dbg_regs, regs);
382 if (!block_name || !strcmp(block_name, "pmrx"))
383 match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
384 if (!block_name || !strcmp(block_name, "pmtx"))
385 match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
386 if (!block_name || !strcmp(block_name, "cm"))
387 match += dump_block_regs(t3b_mc7_cm_regs, regs);
388 if (!block_name || !strcmp(block_name, "cim"))
389 match += dump_block_regs(t3b_cim_regs, regs);
390 if (!block_name || !strcmp(block_name, "tp"))
391 match += dump_block_regs(t3b_tp1_regs, regs);
392 if (!block_name || !strcmp(block_name, "ulp_rx"))
393 match += dump_block_regs(t3b_ulp2_rx_regs, regs);
394 if (!block_name || !strcmp(block_name, "ulp_tx"))
395 match += dump_block_regs(t3b_ulp2_tx_regs, regs);
396 if (!block_name || !strcmp(block_name, "pmrx"))
397 match += dump_block_regs(t3b_pm1_rx_regs, regs);
398 if (!block_name || !strcmp(block_name, "pmtx"))
399 match += dump_block_regs(t3b_pm1_tx_regs, regs);
400 if (!block_name || !strcmp(block_name, "mps"))
401 match += dump_block_regs(t3b_mps0_regs, regs);
402 if (!block_name || !strcmp(block_name, "cplsw"))
403 match += dump_block_regs(t3b_cpl_switch_regs, regs);
404 if (!block_name || !strcmp(block_name, "smb"))
405 match += dump_block_regs(t3b_smb0_regs, regs);
406 if (!block_name || !strcmp(block_name, "i2c"))
407 match += dump_block_regs(t3b_i2cm0_regs, regs);
408 if (!block_name || !strcmp(block_name, "mi1"))
409 match += dump_block_regs(t3b_mi1_regs, regs);
410 if (!block_name || !strcmp(block_name, "sf"))
411 match += dump_block_regs(t3b_sf1_regs, regs);
412 if (!block_name || !strcmp(block_name, "pl"))
413 match += dump_block_regs(t3b_pl3_regs, regs);
414 if (!block_name || !strcmp(block_name, "mc5"))
415 match += dump_block_regs(t3b_mc5a_regs, regs);
416 if (!block_name || !strcmp(block_name, "xgmac0"))
417 match += dump_block_regs(t3b_xgmac0_0_regs, regs);
418 if (!block_name || !strcmp(block_name, "xgmac1"))
419 match += dump_block_regs(t3b_xgmac0_1_regs, regs);
421 errx(1, "unknown block \"%s\"", block_name);
426 dump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs,
430 char *block_name = NULL;
432 if (argc == start_arg + 1)
433 block_name = argv[start_arg];
434 else if (argc != start_arg)
437 if (!block_name || !strcmp(block_name, "sge"))
438 match += dump_block_regs(t3c_sge3_regs, regs);
439 if (!block_name || !strcmp(block_name, "pci"))
440 match += dump_block_regs(is_pcie ? t3c_pcie0_regs :
441 t3c_pcix1_regs, regs);
442 if (!block_name || !strcmp(block_name, "t3dbg"))
443 match += dump_block_regs(t3c_t3dbg_regs, regs);
444 if (!block_name || !strcmp(block_name, "pmrx"))
445 match += dump_block_regs(t3c_mc7_pmrx_regs, regs);
446 if (!block_name || !strcmp(block_name, "pmtx"))
447 match += dump_block_regs(t3c_mc7_pmtx_regs, regs);
448 if (!block_name || !strcmp(block_name, "cm"))
449 match += dump_block_regs(t3c_mc7_cm_regs, regs);
450 if (!block_name || !strcmp(block_name, "cim"))
451 match += dump_block_regs(t3c_cim_regs, regs);
452 if (!block_name || !strcmp(block_name, "tp"))
453 match += dump_block_regs(t3c_tp1_regs, regs);
454 if (!block_name || !strcmp(block_name, "ulp_rx"))
455 match += dump_block_regs(t3c_ulp2_rx_regs, regs);
456 if (!block_name || !strcmp(block_name, "ulp_tx"))
457 match += dump_block_regs(t3c_ulp2_tx_regs, regs);
458 if (!block_name || !strcmp(block_name, "pmrx"))
459 match += dump_block_regs(t3c_pm1_rx_regs, regs);
460 if (!block_name || !strcmp(block_name, "pmtx"))
461 match += dump_block_regs(t3c_pm1_tx_regs, regs);
462 if (!block_name || !strcmp(block_name, "mps"))
463 match += dump_block_regs(t3c_mps0_regs, regs);
464 if (!block_name || !strcmp(block_name, "cplsw"))
465 match += dump_block_regs(t3c_cpl_switch_regs, regs);
466 if (!block_name || !strcmp(block_name, "smb"))
467 match += dump_block_regs(t3c_smb0_regs, regs);
468 if (!block_name || !strcmp(block_name, "i2c"))
469 match += dump_block_regs(t3c_i2cm0_regs, regs);
470 if (!block_name || !strcmp(block_name, "mi1"))
471 match += dump_block_regs(t3c_mi1_regs, regs);
472 if (!block_name || !strcmp(block_name, "sf"))
473 match += dump_block_regs(t3c_sf1_regs, regs);
474 if (!block_name || !strcmp(block_name, "pl"))
475 match += dump_block_regs(t3c_pl3_regs, regs);
476 if (!block_name || !strcmp(block_name, "mc5"))
477 match += dump_block_regs(t3c_mc5a_regs, regs);
478 if (!block_name || !strcmp(block_name, "xgmac0"))
479 match += dump_block_regs(t3c_xgmac0_0_regs, regs);
480 if (!block_name || !strcmp(block_name, "xgmac1"))
481 match += dump_block_regs(t3c_xgmac0_1_regs, regs);
483 errx(1, "unknown block \"%s\"", block_name);
489 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
491 int vers, revision, is_pcie;
492 struct ch_ifconf_regs regs;
494 regs.len = REGDUMP_SIZE;
496 /* XXX: This is never freed. Looks like we don't care. */
497 if ((regs.data = malloc(regs.len)) == NULL)
498 err(1, "can't malloc");
500 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
501 err(1, "can't read registers");
503 vers = regs.version & 0x3ff;
504 revision = (regs.version >> 10) & 0x3f;
505 is_pcie = (regs.version & 0x80000000) != 0;
508 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
509 #if defined(CONFIG_T3_REGS)
512 return dump_regs_t3(argc, argv, start_arg,
513 (uint32_t *)regs.data, is_pcie);
514 if (revision == 2 || revision == 3)
515 return dump_regs_t3b(argc, argv, start_arg,
516 (uint32_t *)regs.data, is_pcie);
518 return dump_regs_t3c(argc, argv, start_arg,
519 (uint32_t *)regs.data, is_pcie);
522 errx(1, "unknown card type %d.%d", vers, revision);
527 t3_meminfo(const uint32_t *regs)
530 SG_EGR_CNTX_BADDR = 0x58,
531 SG_CQ_CONTEXT_BADDR = 0x6c,
532 CIM_SDRAM_BASE_ADDR = 0x28c,
533 CIM_SDRAM_ADDR_SIZE = 0x290,
534 TP_CMM_MM_BASE = 0x314,
535 TP_CMM_TIMER_BASE = 0x318,
536 TP_CMM_MM_RX_FLST_BASE = 0x460,
537 TP_CMM_MM_TX_FLST_BASE = 0x464,
538 TP_CMM_MM_PS_FLST_BASE = 0x468,
539 ULPRX_ISCSI_LLIMIT = 0x50c,
540 ULPRX_ISCSI_ULIMIT = 0x510,
541 ULPRX_TDDP_LLIMIT = 0x51c,
542 ULPRX_TDDP_ULIMIT = 0x520,
543 ULPRX_STAG_LLIMIT = 0x52c,
544 ULPRX_STAG_ULIMIT = 0x530,
545 ULPRX_RQ_LLIMIT = 0x534,
546 ULPRX_RQ_ULIMIT = 0x538,
547 ULPRX_PBL_LLIMIT = 0x53c,
548 ULPRX_PBL_ULIMIT = 0x540,
551 unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
552 cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
553 timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
554 pstructs = regs[TP_CMM_MM_BASE / 4],
555 pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
556 rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
557 tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
558 cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
559 cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
560 unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
561 iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
562 tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
563 tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
564 stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
565 stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
566 rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
567 rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
568 pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
569 pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
571 printf("CM memory map:\n");
572 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
574 printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
575 cq_cntxt - 1, cq_cntxt - egr_cntxt);
576 printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt,
577 timers - 1, timers - cq_cntxt);
578 printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers,
579 pstructs - 1, pstructs - timers);
580 printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs,
581 pstruct_fl - 1, pstruct_fl - pstructs);
582 printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl,
583 rx_fl - 1, rx_fl - pstruct_fl);
584 printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
586 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
588 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base,
589 cim_base + cim_size - 1, cim_size);
591 printf("\nPMRX memory map:\n");
592 printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
593 iscsi_ul - iscsi_ll + 1);
594 printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
595 tddp_ul - tddp_ll + 1);
596 printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
597 stag_ul - stag_ll + 1);
598 printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
600 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
601 pbl_ul - pbl_ll + 1);
606 meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
609 struct ch_ifconf_regs regs;
615 regs.len = REGDUMP_SIZE;
616 if ((regs.data = malloc(regs.len)) == NULL)
617 err(1, "can't malloc");
619 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
620 err(1, "can't read registers");
622 vers = regs.version & 0x3ff;
624 return t3_meminfo((uint32_t *)regs.data);
626 errx(1, "unknown card type %d", vers);
631 mtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name)
636 if (argc == start_arg) {
637 if (doit(iff_name, CHELSIO_GETMTUTAB, &m) < 0)
638 err(1, "get MTU table");
639 for (i = 0; i < m.nmtus; ++i)
640 printf("%u ", m.mtus[i]);
642 } else if (argc <= start_arg + NMTUS) {
643 m.nmtus = argc - start_arg;
645 for (i = 0; i < m.nmtus; ++i) {
647 unsigned long mt = strtoul(argv[start_arg + i], &p, 0);
649 if (*p || mt > 9600) {
650 warnx("bad parameter \"%s\"",
651 argv[start_arg + i]);
654 if (i && mt < m.mtus[i - 1])
655 errx(1, "MTUs must be in ascending order");
658 if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0)
659 err(1, "set MTU table");
666 #ifdef CHELSIO_INTERNAL
668 show_egress_cntxt(uint32_t data[])
670 printf("credits: %u\n", data[0] & 0x7fff);
671 printf("GTS: %u\n", (data[0] >> 15) & 1);
672 printf("index: %u\n", data[0] >> 16);
673 printf("queue size: %u\n", data[1] & 0xffff);
674 printf("base address: 0x%" PRIx64 "\n",
675 ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
676 (((uint64_t)data[3] & 0xf) << 48)) << 12);
677 printf("rsp queue #: %u\n", (data[3] >> 4) & 7);
678 printf("cmd queue #: %u\n", (data[3] >> 7) & 1);
679 printf("TUN: %u\n", (data[3] >> 8) & 1);
680 printf("TOE: %u\n", (data[3] >> 9) & 1);
681 printf("generation: %u\n", (data[3] >> 10) & 1);
682 printf("uP token: %u\n", (data[3] >> 11) & 0xfffff);
683 printf("valid: %u\n", (data[3] >> 31) & 1);
687 show_fl_cntxt(uint32_t data[])
689 printf("base address: 0x%" PRIx64 "\n",
690 ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
691 printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
692 printf("queue size: %u\n", (data[2] >> 4) & 0xffff);
693 printf("generation: %u\n", (data[2] >> 20) & 1);
694 printf("entry size: %u\n",
695 (data[2] >> 21) | (data[3] & 0x1fffff) << 11);
696 printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff);
697 printf("GTS: %u\n", (data[3] >> 31) & 1);
701 show_response_cntxt(uint32_t data[])
703 printf("index: %u\n", data[0] & 0xffff);
704 printf("size: %u\n", data[0] >> 16);
705 printf("base address: 0x%" PRIx64 "\n",
706 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
707 printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f);
708 printf("intr enable: %u\n", (data[2] >> 26) & 1);
709 printf("intr armed: %u\n", (data[2] >> 27) & 1);
710 printf("generation: %u\n", (data[2] >> 28) & 1);
711 printf("CQ mode: %u\n", (data[2] >> 31) & 1);
712 printf("FL threshold: %u\n", data[3]);
716 show_cq_cntxt(uint32_t data[])
718 printf("index: %u\n", data[0] & 0xffff);
719 printf("size: %u\n", data[0] >> 16);
720 printf("base address: 0x%" PRIx64 "\n",
721 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
722 printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f);
723 printf("AN: %u\n", (data[2] >> 26) & 1);
724 printf("armed: %u\n", (data[2] >> 27) & 1);
725 printf("ANS: %u\n", (data[2] >> 28) & 1);
726 printf("generation: %u\n", (data[2] >> 29) & 1);
727 printf("overflow mode: %u\n", (data[2] >> 31) & 1);
728 printf("credits: %u\n", data[3] & 0xffff);
729 printf("credit threshold: %u\n", data[3] >> 16);
733 get_sge_context(int argc, char *argv[], int start_arg, const char *iff_name)
737 if (argc != start_arg + 2) return -1;
739 if (!strcmp(argv[start_arg], "egress"))
740 ctx.cntxt_type = CNTXT_TYPE_EGRESS;
741 else if (!strcmp(argv[start_arg], "fl"))
742 ctx.cntxt_type = CNTXT_TYPE_FL;
743 else if (!strcmp(argv[start_arg], "response"))
744 ctx.cntxt_type = CNTXT_TYPE_RSP;
745 else if (!strcmp(argv[start_arg], "cq"))
746 ctx.cntxt_type = CNTXT_TYPE_CQ;
748 warnx("unknown context type \"%s\"; known types are egress, "
749 "fl, cq, and response", argv[start_arg]);
753 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
756 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
757 err(1, "get SGE context");
759 if (!strcmp(argv[start_arg], "egress"))
760 show_egress_cntxt(ctx.data);
761 else if (!strcmp(argv[start_arg], "fl"))
762 show_fl_cntxt(ctx.data);
763 else if (!strcmp(argv[start_arg], "response"))
764 show_response_cntxt(ctx.data);
765 else if (!strcmp(argv[start_arg], "cq"))
766 show_cq_cntxt(ctx.data);
770 #define ntohll(x) be64toh((x))
773 get_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name)
776 unsigned int n = 1, qset, qnum;
779 if (argc != start_arg + 3 && argc != start_arg + 4)
782 if (get_int_arg(argv[start_arg], &qset) ||
783 get_int_arg(argv[start_arg + 1], &qnum) ||
784 get_int_arg(argv[start_arg + 2], &desc.idx))
787 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
791 errx(1, "invalid queue number %d, range is 0..5", qnum);
793 desc.queue_num = qset * 6 + qnum;
795 for (; n--; desc.idx++) {
796 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
797 err(1, "get SGE descriptor");
799 p = (uint64_t *)desc.data;
801 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
802 desc.idx, (unsigned int)(wr_hdr >> 56),
803 ((unsigned int)wr_hdr >> 8) & 0xfffff,
804 ((wr_hdr >> 55) & 1) ? "SOP, " : "",
805 ((wr_hdr >> 54) & 1) ? "EOP, " : "",
806 ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
807 ((wr_hdr >> 52) & 1) ? "SGL, " : "",
808 (unsigned int)wr_hdr & 0xff);
810 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
811 printf("%016" PRIx64 "%c", ntohll(*p),
812 desc.size % 32 == 8 ? '\n' : ' ');
819 get_tcb2(int argc, char *argv[], int start_arg, const char *iff_name)
823 unsigned int tcb_idx;
824 struct ch_mem_range mr;
826 if (argc != start_arg + 1)
829 if (get_int_arg(argv[start_arg], &tcb_idx))
832 mr.buf = calloc(1, TCB_SIZE);
837 mr.addr = tcb_idx * TCB_SIZE;
840 if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0)
843 for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) {
845 printf(" %08x %08x %08x %08x", (uint32_t)d[1],
846 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
847 (uint32_t)(d[0] >> 32));
849 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
850 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
851 (uint32_t)(d[0] >> 32));
859 get_pm_page_spec(const char *s, unsigned int *page_size,
860 unsigned int *num_pages)
865 val = strtoul(s, &p, 0);
866 if (p == s) return -1;
867 if (*p == 'x' && p[1]) {
869 *page_size = strtoul(p + 1, &p, 0);
874 *page_size <<= 10; // KB -> bytes
879 conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
883 if (argc == start_arg) {
884 if (doit(iff_name, CHELSIO_GET_PM, &pm) < 0)
885 err(1, "read pm config");
886 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
887 pm.tx_num_pg, pm.tx_pg_sz >> 10, pm.rx_num_pg,
888 pm.rx_pg_sz >> 10, pm.pm_total >> 10);
892 if (argc != start_arg + 2) return -1;
894 if (get_pm_page_spec(argv[start_arg], &pm.tx_pg_sz, &pm.tx_num_pg)) {
895 warnx("bad parameter \"%s\"", argv[start_arg]);
898 if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz,
900 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
903 if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0)
908 #ifdef CHELSIO_INTERNAL
910 dump_tcam(int argc, char *argv[], int start_arg, const char *iff_name)
913 struct ch_tcam_word op;
915 if (argc != start_arg + 2) return -1;
917 if (get_int_arg(argv[start_arg], &op.addr) ||
918 get_int_arg(argv[start_arg + 1], &nwords))
922 if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0)
925 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
926 op.buf[0] & 0xff, op.buf[1], op.buf[2]);
933 hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
938 printf("0x%08x:", start);
939 for (i = 0; i < 4 && len; ++i, --len)
940 printf(" %016llx", (unsigned long long)*data++);
947 dump_mc7(int argc, char *argv[], int start_arg, const char *iff_name)
949 struct ch_mem_range mem;
950 unsigned int mem_id, addr, len;
952 if (argc != start_arg + 3) return -1;
954 if (!strcmp(argv[start_arg], "cm"))
956 else if (!strcmp(argv[start_arg], "rx"))
958 else if (!strcmp(argv[start_arg], "tx"))
961 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
962 " or \"rx\"", argv[start_arg]);
964 if (get_int_arg(argv[start_arg + 1], &addr) ||
965 get_int_arg(argv[start_arg + 2], &len))
968 mem.buf = malloc(len);
970 err(1, "memory dump");
976 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
977 err(1, "memory dump");
979 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
985 /* Max FW size is 64K including version, +4 bytes for the checksum. */
986 #define MAX_FW_IMAGE_SIZE (64 * 1024)
989 load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
992 struct ch_mem_range op;
993 const char *fname = argv[start_arg];
995 if (argc != start_arg + 1) return -1;
997 fd = open(fname, O_RDONLY);
999 err(1, "load firmware");
1001 bzero(&op, sizeof(op));
1002 op.buf = malloc(MAX_FW_IMAGE_SIZE + 1);
1004 err(1, "load firmware");
1006 len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1);
1008 err(1, "load firmware");
1009 if (len > MAX_FW_IMAGE_SIZE)
1010 errx(1, "FW image too large");
1013 if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0)
1014 err(1, "load firmware");
1020 /* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */
1021 #define MAX_BOOT_IMAGE_SIZE (0xff * 512)
1024 load_boot(int argc, char *argv[], int start_arg, const char *iff_name)
1027 struct ch_mem_range op;
1028 const char *fname = argv[start_arg];
1030 if (argc != start_arg + 1) return -1;
1032 fd = open(fname, O_RDONLY);
1034 err(1, "load boot image");
1036 op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1);
1038 err(1, "load boot image");
1040 len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1);
1042 err(1, "load boot image");
1043 if (len > MAX_BOOT_IMAGE_SIZE)
1044 errx(1, "boot image too large");
1048 if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0)
1049 err(1, "load boot image");
1056 dump_proto_sram(const char *iff_name)
1059 uint8_t buf[PROTO_SRAM_SIZE];
1060 struct ch_eeprom ee;
1063 bzero(buf, sizeof(buf));
1064 ee.offset = PROTO_SRAM_EEPROM_ADDR;
1066 ee.len = sizeof(buf);
1067 if (doit(iff_name, CHELSIO_GET_EEPROM, &ee))
1068 err(1, "show protocol sram");
1070 for (i = 0; i < PROTO_SRAM_LINES; i++) {
1071 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1072 int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1073 uint8_t nibble = p[nibble_idx / 2];
1079 printf("%x", nibble);
1087 proto_sram_op(int argc, char *argv[], int start_arg,
1088 const char *iff_name)
1093 if (argc == start_arg)
1094 return dump_proto_sram(iff_name);
1099 dump_qset_params(const char *iff_name)
1101 struct ch_qset_params qp;
1105 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1107 printf("Qset TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1"
1109 printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n",
1111 qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1112 qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1113 qp.cong_thres, qp.intr_lat, qp.vector);
1116 if (!qp.qset_idx || (errno && errno != EINVAL))
1117 err(1, "get qset parameters");
1122 qset_config(int argc, char *argv[], int start_arg, const char *iff_name)
1126 if (argc == start_arg)
1127 return dump_qset_params(iff_name);
1133 qset_num_config(int argc, char *argv[], int start_arg, const char *iff_name)
1139 if (argc == start_arg) {
1140 if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0)
1141 err(1, "get qsets");
1142 printf("%u\n", reg.val);
1150 * Parse a string containing an IP address with an optional network prefix.
1153 parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1158 *mask = 0xffffffffU;
1159 slash = strchr(s, '/');
1162 if (!inet_aton(s, &ia)) {
1168 *addr = ntohl(ia.s_addr);
1170 unsigned int prefix = strtoul(slash + 1, &p, 10);
1173 if (p == slash + 1 || *p || prefix > 32)
1175 *mask <<= (32 - prefix);
1181 * Parse a string containing a value and an optional colon separated mask.
1184 parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
1185 uint32_t default_mask)
1189 *mask = default_mask;
1190 *val = strtoul(s, &p, 0);
1191 if (p == s || *val > default_mask)
1193 if (*p == ':' && p[1])
1194 *mask = strtoul(p + 1, &p, 0);
1195 return *p || *mask > default_mask ? -1 : 0;
1199 parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1201 return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1202 parse_val_mask_param(s, val, mask, 0xffffffffU);
1206 trace_config(int argc, char *argv[], int start_arg, const char *iff_name)
1209 struct ch_trace trace;
1211 if (argc == start_arg)
1214 memset(&trace, 0, sizeof(trace));
1215 if (!strcmp(argv[start_arg], "tx"))
1216 trace.config_tx = 1;
1217 else if (!strcmp(argv[start_arg], "rx"))
1218 trace.config_rx = 1;
1219 else if (!strcmp(argv[start_arg], "all"))
1220 trace.config_tx = trace.config_rx = 1;
1222 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1223 "\"tx\" or \"all\"", argv[start_arg]);
1225 if (argc == ++start_arg)
1227 if (!strcmp(argv[start_arg], "on")) {
1228 trace.trace_tx = trace.config_tx;
1229 trace.trace_rx = trace.config_rx;
1230 } else if (strcmp(argv[start_arg], "off"))
1231 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1235 if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1236 trace.invert_match = 1;
1240 while (start_arg + 2 <= argc) {
1241 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1243 if (!strcmp(argv[start_arg], "interface")) {
1245 trace.intf_mask = mask;
1246 } else if (!strcmp(argv[start_arg], "sip")) {
1248 trace.sip_mask = mask;
1249 } else if (!strcmp(argv[start_arg], "dip")) {
1251 trace.dip_mask = mask;
1252 } else if (!strcmp(argv[start_arg], "sport")) {
1254 trace.sport_mask = mask;
1255 } else if (!strcmp(argv[start_arg], "dport")) {
1257 trace.dport_mask = mask;
1258 } else if (!strcmp(argv[start_arg], "vlan")) {
1260 trace.vlan_mask = mask;
1261 } else if (!strcmp(argv[start_arg], "proto")) {
1263 trace.proto_mask = mask;
1265 errx(1, "unknown trace parameter \"%s\"\n"
1266 "known parameters are \"interface\", \"sip\", "
1267 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1268 "\"proto\"", argv[start_arg]);
1270 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1273 if (start_arg != argc)
1274 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1276 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1282 show_filters(const char *iff_name)
1284 static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
1285 struct ch_filter op;
1290 char sip[20], dip[20];
1293 bzero(&op, sizeof(op));
1294 op.filter_id = 0xffffffff;
1297 if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
1298 err(1, "list filters");
1300 if (op.filter_id == 0xffffffff)
1304 printf("index SIP DIP sport "
1305 "dport VLAN PRI P/MAC type Q\n");
1309 nsip.nip = htonl(op.val.sip);
1310 ndip.nip = htonl(op.val.dip);
1312 sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1],
1313 nsip.octet[2], nsip.octet[3],
1314 op.mask.sip ? 33 - ffs(op.mask.sip) : 0);
1315 sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1],
1316 ndip.octet[2], ndip.octet[3]);
1317 printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip);
1318 printf(op.val.sport ? "%5u " : " * ", op.val.sport);
1319 printf(op.val.dport ? "%5u " : " * ", op.val.dport);
1320 printf(op.val.vlan != 0xfff ? "%4u " : " * ", op.val.vlan);
1321 printf(op.val.vlan_prio == 7 ? " * " :
1322 "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1);
1323 if (op.mac_addr_idx == 0xffff)
1325 else if (op.mac_hit)
1326 printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
1327 (op.mac_addr_idx) & 0x7);
1329 printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1);
1330 printf("%4s ", pkt_type[op.proto]);
1336 printf("%1u\n", op.qset);
1341 filter_config(int argc, char *argv[], int start_arg, const char *iff_name)
1345 struct ch_filter op;
1347 if (argc < start_arg + 1)
1350 memset(&op, 0, sizeof(op));
1351 op.mac_addr_idx = 0xffff;
1354 if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
1355 show_filters(iff_name);
1359 if (get_int_arg(argv[start_arg++], &op.filter_id))
1361 if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") ||
1362 !strcmp(argv[start_arg], "clear"))) {
1363 if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) {
1365 err(1, "no filter support when offload in use");
1366 err(1, "delete filter");
1371 while (start_arg + 2 <= argc) {
1372 if (!strcmp(argv[start_arg], "sip")) {
1373 ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
1375 } else if (!strcmp(argv[start_arg], "dip")) {
1376 ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
1378 } else if (!strcmp(argv[start_arg], "sport")) {
1379 ret = parse_val_mask_param(argv[start_arg + 1],
1380 &val, &mask, 0xffff);
1382 op.mask.sport = mask;
1383 } else if (!strcmp(argv[start_arg], "dport")) {
1384 ret = parse_val_mask_param(argv[start_arg + 1],
1385 &val, &mask, 0xffff);
1387 op.mask.dport = mask;
1388 } else if (!strcmp(argv[start_arg], "vlan")) {
1389 ret = parse_val_mask_param(argv[start_arg + 1],
1390 &val, &mask, 0xfff);
1392 op.mask.vlan = mask;
1393 } else if (!strcmp(argv[start_arg], "prio")) {
1394 ret = parse_val_mask_param(argv[start_arg + 1],
1396 op.val.vlan_prio = val;
1397 op.mask.vlan_prio = mask;
1398 } else if (!strcmp(argv[start_arg], "mac")) {
1399 if (!strcmp(argv[start_arg + 1], "none"))
1402 ret = get_int_arg(argv[start_arg + 1], &val);
1403 op.mac_hit = val != (uint32_t)-1;
1404 op.mac_addr_idx = op.mac_hit ? val : 0;
1405 } else if (!strcmp(argv[start_arg], "type")) {
1406 if (!strcmp(argv[start_arg + 1], "tcp"))
1408 else if (!strcmp(argv[start_arg + 1], "udp"))
1410 else if (!strcmp(argv[start_arg + 1], "frag"))
1413 errx(1, "unknown type \"%s\"; must be one of "
1414 "\"tcp\", \"udp\", or \"frag\"",
1415 argv[start_arg + 1]);
1416 } else if (!strcmp(argv[start_arg], "queue")) {
1417 ret = get_int_arg(argv[start_arg + 1], &val);
1420 } else if (!strcmp(argv[start_arg], "action")) {
1421 if (!strcmp(argv[start_arg + 1], "pass"))
1423 else if (strcmp(argv[start_arg + 1], "drop"))
1424 errx(1, "unknown action \"%s\"; must be one of "
1425 "\"pass\" or \"drop\"",
1426 argv[start_arg + 1]);
1428 errx(1, "unknown filter parameter \"%s\"\n"
1429 "known parameters are \"mac\", \"sip\", "
1430 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1431 "\"prio\", \"type\", \"queue\", and \"action\"",
1434 errx(1, "bad value \"%s\" for parameter \"%s\"",
1435 argv[start_arg + 1], argv[start_arg]);
1438 if (start_arg != argc)
1439 errx(1, "no value for \"%s\"", argv[start_arg]);
1441 if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
1443 err(1, "no filter support when offload in use");
1444 err(1, "set filter");
1450 get_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
1452 if (pos + 1 >= argc)
1453 errx(1, "missing value for %s", argv[pos]);
1454 if (get_int_arg(argv[pos + 1], valp))
1460 tx_sched(int argc, char *argv[], int start_arg, const char *iff_name)
1462 struct ch_hw_sched op;
1463 unsigned int idx, val;
1465 if (argc < 5 || get_int_arg(argv[start_arg++], &idx))
1469 op.mode = op.channel = -1;
1470 op.kbps = op.class_ipg = op.flow_ipg = -1;
1472 while (argc > start_arg) {
1473 if (!strcmp(argv[start_arg], "mode")) {
1474 if (start_arg + 1 >= argc)
1475 errx(1, "missing value for mode");
1476 if (!strcmp(argv[start_arg + 1], "class"))
1478 else if (!strcmp(argv[start_arg + 1], "flow"))
1481 errx(1, "bad mode \"%s\"", argv[start_arg + 1]);
1482 } else if (!strcmp(argv[start_arg], "channel") &&
1483 !get_sched_param(argc, argv, start_arg, &val))
1485 else if (!strcmp(argv[start_arg], "rate") &&
1486 !get_sched_param(argc, argv, start_arg, &val))
1488 else if (!strcmp(argv[start_arg], "ipg") &&
1489 !get_sched_param(argc, argv, start_arg, &val))
1491 else if (!strcmp(argv[start_arg], "flowipg") &&
1492 !get_sched_param(argc, argv, start_arg, &val))
1495 errx(1, "unknown scheduler parameter \"%s\"",
1500 if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0)
1507 pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1509 struct ch_pktsched_params op;
1510 unsigned int idx, min = -1, max, binding = -1;
1513 errx(1, "no scheduler specified");
1515 if (!strcmp(argv[start_arg], "port")) {
1516 if (argc != start_arg + 4)
1518 if (get_int_arg(argv[start_arg + 1], &idx) ||
1519 get_int_arg(argv[start_arg + 2], &min) ||
1520 get_int_arg(argv[start_arg + 3], &max))
1523 } else if (!strcmp(argv[start_arg], "tunnelq")) {
1524 if (argc != start_arg + 4)
1526 if (get_int_arg(argv[start_arg + 1], &idx) ||
1527 get_int_arg(argv[start_arg + 2], &max) ||
1528 get_int_arg(argv[start_arg + 3], &binding))
1531 } else if (!strcmp(argv[start_arg], "tx"))
1532 return tx_sched(argc, argv, start_arg + 1, iff_name);
1534 errx(1, "unknown scheduler \"%s\"; must be one of \"port\", "
1535 "\"tunnelq\" or \"tx\"", argv[start_arg]);
1540 op.binding = binding;
1541 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0)
1548 clear_stats(int argc, char *argv[], int start_arg, const char *iff_name)
1554 if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0)
1555 err(1, "clearstats");
1561 get_up_la(int argc, char *argv[], int start_arg, const char *iff_name)
1564 int i, idx, max_idx, entries;
1572 la.bufsize = LA_BUFSIZE;
1573 la.data = malloc(la.bufsize);
1575 err(1, "uP_LA malloc");
1577 if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0)
1581 printf("LA is not running\n");
1583 entries = la.bufsize / 4;
1585 max_idx = (entries / 4) - 1;
1586 for (i = 0; i < max_idx; i++) {
1587 printf("%04x %08x %08x\n",
1588 la.data[idx], la.data[idx+2], la.data[idx+1]);
1589 idx = (idx + 4) & (entries - 1);
1596 get_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name)
1598 struct ch_up_ioqs ioqs;
1605 bzero(&ioqs, sizeof(ioqs));
1606 ioqs.bufsize = IOQS_BUFSIZE;
1607 ioqs.data = malloc(IOQS_BUFSIZE);
1609 err(1, "uP_IOQs malloc");
1611 if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0)
1614 printf("ioq_rx_enable : 0x%08x\n", ioqs.ioq_rx_enable);
1615 printf("ioq_tx_enable : 0x%08x\n", ioqs.ioq_tx_enable);
1616 printf("ioq_rx_status : 0x%08x\n", ioqs.ioq_rx_status);
1617 printf("ioq_tx_status : 0x%08x\n", ioqs.ioq_tx_status);
1619 entries = ioqs.bufsize / sizeof(struct t3_ioq_entry);
1620 for (i = 0; i < entries; i++) {
1621 printf("\nioq[%d].cp : 0x%08x\n", i,
1622 ioqs.data[i].ioq_cp);
1623 printf("ioq[%d].pp : 0x%08x\n", i,
1624 ioqs.data[i].ioq_pp);
1625 printf("ioq[%d].alen : 0x%08x\n", i,
1626 ioqs.data[i].ioq_alen);
1627 printf("ioq[%d].stats : 0x%08x\n", i,
1628 ioqs.data[i].ioq_stats);
1629 printf(" sop %u\n", ioqs.data[i].ioq_stats >> 16);
1630 printf(" eop %u\n", ioqs.data[i].ioq_stats & 0xFFFF);
1637 run_cmd(int argc, char *argv[], const char *iff_name)
1641 if (!strcmp(argv[2], "reg"))
1642 r = register_io(argc, argv, 3, iff_name);
1643 else if (!strcmp(argv[2], "mdio"))
1644 r = mdio_io(argc, argv, 3, iff_name);
1645 else if (!strcmp(argv[2], "mtus"))
1646 r = mtu_tab_op(argc, argv, 3, iff_name);
1647 else if (!strcmp(argv[2], "pm"))
1648 r = conf_pm(argc, argv, 3, iff_name);
1649 else if (!strcmp(argv[2], "regdump"))
1650 r = dump_regs(argc, argv, 3, iff_name);
1651 else if (!strcmp(argv[2], "tcamdump"))
1652 r = dump_tcam(argc, argv, 3, iff_name);
1653 else if (!strcmp(argv[2], "memdump"))
1654 r = dump_mc7(argc, argv, 3, iff_name);
1655 else if (!strcmp(argv[2], "meminfo"))
1656 r = meminfo(argc, argv, 3, iff_name);
1657 else if (!strcmp(argv[2], "context"))
1658 r = get_sge_context(argc, argv, 3, iff_name);
1659 else if (!strcmp(argv[2], "desc"))
1660 r = get_sge_desc(argc, argv, 3, iff_name);
1661 else if (!strcmp(argv[2], "loadfw"))
1662 r = load_fw(argc, argv, 3, iff_name);
1663 else if (!strcmp(argv[2], "loadboot"))
1664 r = load_boot(argc, argv, 3, iff_name);
1665 else if (!strcmp(argv[2], "proto"))
1666 r = proto_sram_op(argc, argv, 3, iff_name);
1667 else if (!strcmp(argv[2], "qset"))
1668 r = qset_config(argc, argv, 3, iff_name);
1669 else if (!strcmp(argv[2], "qsets"))
1670 r = qset_num_config(argc, argv, 3, iff_name);
1671 else if (!strcmp(argv[2], "trace"))
1672 r = trace_config(argc, argv, 3, iff_name);
1673 else if (!strcmp(argv[2], "pktsched"))
1674 r = pktsched(argc, argv, 3, iff_name);
1675 else if (!strcmp(argv[2], "tcb"))
1676 r = get_tcb2(argc, argv, 3, iff_name);
1677 else if (!strcmp(argv[2], "filter"))
1678 r = filter_config(argc, argv, 3, iff_name);
1679 else if (!strcmp(argv[2], "clearstats"))
1680 r = clear_stats(argc, argv, 3, iff_name);
1681 else if (!strcmp(argv[2], "la"))
1682 r = get_up_la(argc, argv, 3, iff_name);
1683 else if (!strcmp(argv[2], "ioqs"))
1684 r = get_up_ioqs(argc, argv, 3, iff_name);
1693 run_cmd_loop(int argc, char *argv[], const char *iff_name)
1705 * Fairly simplistic loop. Displays a "> " prompt and processes any
1706 * input as a cxgbtool command. You're supposed to enter only the part
1707 * after "cxgbtool cxgbX". Use "quit" or "exit" to exit. Any error in
1708 * the command will also terminate cxgbtool.
1711 fprintf(stdout, "> ");
1713 n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
1717 if (buf[--n] != '\n')
1723 for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) {
1724 while (s && (*s == ' ' || *s == '\t'))
1726 if ((args[i] = strsep(&s, " \t")) == NULL)
1729 args[sizeof(args)/sizeof(args[0]) - 1] = 0;
1731 if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit"))
1734 (void) run_cmd(i, args, iff_name);
1737 /* Can't really get here */
1742 main(int argc, char *argv[])
1745 const char *iff_name;
1750 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1752 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1753 printf("%s version %s\n", PROGNAME, VERSION);
1754 printf("%s\n", COPYRIGHT);
1759 if (argc < 3) usage(stderr);
1763 if (argc == 3 && !strcmp(argv[2], "stdio"))
1764 r = run_cmd_loop(argc, argv, iff_name);
1766 r = run_cmd(argc, argv, iff_name);