1 /**************************************************************************
3 Copyright (c) 2007-2010, 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_types.h>
56 #include <sys/endian.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"
82 # include "reg_defs_t3c.c"
85 static const char *progname;
90 fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
92 "\tclearstats clear MAC statistics\n"
93 "\tcontext <type> <id> show an SGE context\n"
94 "\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
95 "\tfilter <idx> [<param> <val>] ... set a filter\n"
96 "\tfilter <idx> delete|clear delete a filter\n"
97 "\tfilter list list all filters\n"
98 "\tioqs dump uP IOQs\n"
99 "\tla dump uP logic analyzer info\n"
100 "\tloadboot <boot image> download boot image\n"
101 "\tloadfw <FW image> download firmware\n"
102 "\tmdio <phy_addr> <mmd_addr>\n"
103 "\t <reg_addr> [<val>] read/write MDIO register\n"
104 "\tmemdump cm|tx|rx <addr> <len> dump a mem range\n"
105 "\tmeminfo show memory info\n"
106 "\tmtus [<mtu0>...<mtuN>] read/write MTU table\n"
107 "\tpktsched port <idx> <min> <max> set TX port scheduler params\n"
108 "\tpktsched tunnelq <idx> <max>\n"
109 "\t <binding> set TX tunnelq scheduler params\n"
110 "\tpktsched tx <idx>\n"
111 "\t [<param> <val>] ... set Tx HW scheduler\n"
112 "\tpm [<TX page spec> <RX page spec>] read/write PM config\n"
113 "\tproto read proto SRAM\n"
114 "\tqset read qset parameters\n"
115 "\tqsets read # of qsets\n"
116 "\treg <address>[=<val>] read/write register\n"
117 "\tregdump [<module>] dump registers\n"
118 "\ttcamdump <address> <count> show TCAM contents\n"
119 "\ttcb <index> read TCB\n"
120 "\ttrace tx|rx|all on|off [not]\n"
121 "\t [<param> <val>[:<mask>]] ... write trace parameters\n"
123 exit(fp == stderr ? 1 : 0);
127 doit(const char *iff_name, unsigned long cmd, void *data)
133 snprintf(buf, 64, "/dev/%s", iff_name);
135 if ((fd = open(buf, O_RDWR)) < 0)
139 return ioctl(fd, cmd, data) < 0 ? -1 : 0;
143 get_int_arg(const char *s, uint32_t *valp)
147 *valp = strtoul(s, &p, 0);
149 warnx("bad parameter \"%s\"", s);
156 read_reg(const char *iff_name, uint32_t addr)
162 if (doit(iff_name, CHELSIO_GETREG, ®) < 0)
163 err(1, "register read");
168 write_reg(const char *iff_name, uint32_t addr, uint32_t val)
170 struct ch_reg ch_reg;
175 if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
176 err(1, "register write");
180 register_io(int argc, char *argv[], int start_arg,
181 const char *iff_name)
184 uint32_t addr, val = 0, w = 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);
209 mdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
211 struct ch_mii_data p;
212 unsigned int cmd, phy_addr, reg, mmd, val;
214 if (argc == start_arg + 3)
215 cmd = CHELSIO_GET_MIIREG;
216 else if (argc == start_arg + 4)
217 cmd = CHELSIO_SET_MIIREG;
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 == CHELSIO_SET_MIIREG && 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 == CHELSIO_GET_MIIREG ? "read" : "write");
233 if (cmd == CHELSIO_GET_MIIREG)
234 printf("%#x [%u]\n", p.val_out, p.val_out);
239 uint32_t xtract(uint32_t val, int shift, int len)
241 return (val >> shift) & ((1 << len) - 1);
245 dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
247 uint32_t reg_val = 0; // silence compiler warning
249 for ( ; reg_array->name; ++reg_array)
250 if (!reg_array->len) {
251 reg_val = regs[reg_array->addr / 4];
252 printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
253 reg_array->name, reg_val, reg_val);
255 uint32_t v = xtract(reg_val, reg_array->addr,
258 printf(" %-40s %#-10x [%u]\n", reg_array->name,
265 dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
268 char *block_name = NULL;
270 if (argc == start_arg + 1)
271 block_name = argv[start_arg];
272 else if (argc != start_arg)
275 if (!block_name || !strcmp(block_name, "sge"))
276 match += dump_block_regs(sge_regs, regs);
277 if (!block_name || !strcmp(block_name, "mc3"))
278 match += dump_block_regs(mc3_regs, regs);
279 if (!block_name || !strcmp(block_name, "mc4"))
280 match += dump_block_regs(mc4_regs, regs);
281 if (!block_name || !strcmp(block_name, "tpi"))
282 match += dump_block_regs(tpi_regs, regs);
283 if (!block_name || !strcmp(block_name, "tp"))
284 match += dump_block_regs(tp_regs, regs);
285 if (!block_name || !strcmp(block_name, "rat"))
286 match += dump_block_regs(rat_regs, regs);
287 if (!block_name || !strcmp(block_name, "cspi"))
288 match += dump_block_regs(cspi_regs, regs);
289 if (!block_name || !strcmp(block_name, "espi"))
290 match += dump_block_regs(espi_regs, regs);
291 if (!block_name || !strcmp(block_name, "ulp"))
292 match += dump_block_regs(ulp_regs, regs);
293 if (!block_name || !strcmp(block_name, "pl"))
294 match += dump_block_regs(pl_regs, regs);
295 if (!block_name || !strcmp(block_name, "mc5"))
296 match += dump_block_regs(mc5_regs, regs);
298 errx(1, "unknown block \"%s\"", block_name);
302 #if defined(CONFIG_T3_REGS)
304 dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie)
307 char *block_name = NULL;
309 if (argc == start_arg + 1)
310 block_name = argv[start_arg];
311 else if (argc != start_arg)
314 if (!block_name || !strcmp(block_name, "sge"))
315 match += dump_block_regs(sge3_regs, regs);
316 if (!block_name || !strcmp(block_name, "pci"))
317 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
319 if (!block_name || !strcmp(block_name, "t3dbg"))
320 match += dump_block_regs(t3dbg_regs, regs);
321 if (!block_name || !strcmp(block_name, "pmrx"))
322 match += dump_block_regs(mc7_pmrx_regs, regs);
323 if (!block_name || !strcmp(block_name, "pmtx"))
324 match += dump_block_regs(mc7_pmtx_regs, regs);
325 if (!block_name || !strcmp(block_name, "cm"))
326 match += dump_block_regs(mc7_cm_regs, regs);
327 if (!block_name || !strcmp(block_name, "cim"))
328 match += dump_block_regs(cim_regs, regs);
329 if (!block_name || !strcmp(block_name, "tp"))
330 match += dump_block_regs(tp1_regs, regs);
331 if (!block_name || !strcmp(block_name, "ulp_rx"))
332 match += dump_block_regs(ulp2_rx_regs, regs);
333 if (!block_name || !strcmp(block_name, "ulp_tx"))
334 match += dump_block_regs(ulp2_tx_regs, regs);
335 if (!block_name || !strcmp(block_name, "pmrx"))
336 match += dump_block_regs(pm1_rx_regs, regs);
337 if (!block_name || !strcmp(block_name, "pmtx"))
338 match += dump_block_regs(pm1_tx_regs, regs);
339 if (!block_name || !strcmp(block_name, "mps"))
340 match += dump_block_regs(mps0_regs, regs);
341 if (!block_name || !strcmp(block_name, "cplsw"))
342 match += dump_block_regs(cpl_switch_regs, regs);
343 if (!block_name || !strcmp(block_name, "smb"))
344 match += dump_block_regs(smb0_regs, regs);
345 if (!block_name || !strcmp(block_name, "i2c"))
346 match += dump_block_regs(i2cm0_regs, regs);
347 if (!block_name || !strcmp(block_name, "mi1"))
348 match += dump_block_regs(mi1_regs, regs);
349 if (!block_name || !strcmp(block_name, "sf"))
350 match += dump_block_regs(sf1_regs, regs);
351 if (!block_name || !strcmp(block_name, "pl"))
352 match += dump_block_regs(pl3_regs, regs);
353 if (!block_name || !strcmp(block_name, "mc5"))
354 match += dump_block_regs(mc5a_regs, regs);
355 if (!block_name || !strcmp(block_name, "xgmac0"))
356 match += dump_block_regs(xgmac0_0_regs, regs);
357 if (!block_name || !strcmp(block_name, "xgmac1"))
358 match += dump_block_regs(xgmac0_1_regs, regs);
360 errx(1, "unknown block \"%s\"", block_name);
365 dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
369 char *block_name = NULL;
371 if (argc == start_arg + 1)
372 block_name = argv[start_arg];
373 else if (argc != start_arg)
376 if (!block_name || !strcmp(block_name, "sge"))
377 match += dump_block_regs(t3b_sge3_regs, regs);
378 if (!block_name || !strcmp(block_name, "pci"))
379 match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
380 t3b_pcix1_regs, regs);
381 if (!block_name || !strcmp(block_name, "t3dbg"))
382 match += dump_block_regs(t3b_t3dbg_regs, regs);
383 if (!block_name || !strcmp(block_name, "pmrx"))
384 match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
385 if (!block_name || !strcmp(block_name, "pmtx"))
386 match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
387 if (!block_name || !strcmp(block_name, "cm"))
388 match += dump_block_regs(t3b_mc7_cm_regs, regs);
389 if (!block_name || !strcmp(block_name, "cim"))
390 match += dump_block_regs(t3b_cim_regs, regs);
391 if (!block_name || !strcmp(block_name, "tp"))
392 match += dump_block_regs(t3b_tp1_regs, regs);
393 if (!block_name || !strcmp(block_name, "ulp_rx"))
394 match += dump_block_regs(t3b_ulp2_rx_regs, regs);
395 if (!block_name || !strcmp(block_name, "ulp_tx"))
396 match += dump_block_regs(t3b_ulp2_tx_regs, regs);
397 if (!block_name || !strcmp(block_name, "pmrx"))
398 match += dump_block_regs(t3b_pm1_rx_regs, regs);
399 if (!block_name || !strcmp(block_name, "pmtx"))
400 match += dump_block_regs(t3b_pm1_tx_regs, regs);
401 if (!block_name || !strcmp(block_name, "mps"))
402 match += dump_block_regs(t3b_mps0_regs, regs);
403 if (!block_name || !strcmp(block_name, "cplsw"))
404 match += dump_block_regs(t3b_cpl_switch_regs, regs);
405 if (!block_name || !strcmp(block_name, "smb"))
406 match += dump_block_regs(t3b_smb0_regs, regs);
407 if (!block_name || !strcmp(block_name, "i2c"))
408 match += dump_block_regs(t3b_i2cm0_regs, regs);
409 if (!block_name || !strcmp(block_name, "mi1"))
410 match += dump_block_regs(t3b_mi1_regs, regs);
411 if (!block_name || !strcmp(block_name, "sf"))
412 match += dump_block_regs(t3b_sf1_regs, regs);
413 if (!block_name || !strcmp(block_name, "pl"))
414 match += dump_block_regs(t3b_pl3_regs, regs);
415 if (!block_name || !strcmp(block_name, "mc5"))
416 match += dump_block_regs(t3b_mc5a_regs, regs);
417 if (!block_name || !strcmp(block_name, "xgmac0"))
418 match += dump_block_regs(t3b_xgmac0_0_regs, regs);
419 if (!block_name || !strcmp(block_name, "xgmac1"))
420 match += dump_block_regs(t3b_xgmac0_1_regs, regs);
422 errx(1, "unknown block \"%s\"", block_name);
427 dump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs,
431 char *block_name = NULL;
433 if (argc == start_arg + 1)
434 block_name = argv[start_arg];
435 else if (argc != start_arg)
438 if (!block_name || !strcmp(block_name, "sge"))
439 match += dump_block_regs(t3c_sge3_regs, regs);
440 if (!block_name || !strcmp(block_name, "pci"))
441 match += dump_block_regs(is_pcie ? t3c_pcie0_regs :
442 t3c_pcix1_regs, regs);
443 if (!block_name || !strcmp(block_name, "t3dbg"))
444 match += dump_block_regs(t3c_t3dbg_regs, regs);
445 if (!block_name || !strcmp(block_name, "pmrx"))
446 match += dump_block_regs(t3c_mc7_pmrx_regs, regs);
447 if (!block_name || !strcmp(block_name, "pmtx"))
448 match += dump_block_regs(t3c_mc7_pmtx_regs, regs);
449 if (!block_name || !strcmp(block_name, "cm"))
450 match += dump_block_regs(t3c_mc7_cm_regs, regs);
451 if (!block_name || !strcmp(block_name, "cim"))
452 match += dump_block_regs(t3c_cim_regs, regs);
453 if (!block_name || !strcmp(block_name, "tp"))
454 match += dump_block_regs(t3c_tp1_regs, regs);
455 if (!block_name || !strcmp(block_name, "ulp_rx"))
456 match += dump_block_regs(t3c_ulp2_rx_regs, regs);
457 if (!block_name || !strcmp(block_name, "ulp_tx"))
458 match += dump_block_regs(t3c_ulp2_tx_regs, regs);
459 if (!block_name || !strcmp(block_name, "pmrx"))
460 match += dump_block_regs(t3c_pm1_rx_regs, regs);
461 if (!block_name || !strcmp(block_name, "pmtx"))
462 match += dump_block_regs(t3c_pm1_tx_regs, regs);
463 if (!block_name || !strcmp(block_name, "mps"))
464 match += dump_block_regs(t3c_mps0_regs, regs);
465 if (!block_name || !strcmp(block_name, "cplsw"))
466 match += dump_block_regs(t3c_cpl_switch_regs, regs);
467 if (!block_name || !strcmp(block_name, "smb"))
468 match += dump_block_regs(t3c_smb0_regs, regs);
469 if (!block_name || !strcmp(block_name, "i2c"))
470 match += dump_block_regs(t3c_i2cm0_regs, regs);
471 if (!block_name || !strcmp(block_name, "mi1"))
472 match += dump_block_regs(t3c_mi1_regs, regs);
473 if (!block_name || !strcmp(block_name, "sf"))
474 match += dump_block_regs(t3c_sf1_regs, regs);
475 if (!block_name || !strcmp(block_name, "pl"))
476 match += dump_block_regs(t3c_pl3_regs, regs);
477 if (!block_name || !strcmp(block_name, "mc5"))
478 match += dump_block_regs(t3c_mc5a_regs, regs);
479 if (!block_name || !strcmp(block_name, "xgmac0"))
480 match += dump_block_regs(t3c_xgmac0_0_regs, regs);
481 if (!block_name || !strcmp(block_name, "xgmac1"))
482 match += dump_block_regs(t3c_xgmac0_1_regs, regs);
484 errx(1, "unknown block \"%s\"", block_name);
490 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
492 int vers, revision, is_pcie;
493 struct ch_ifconf_regs regs;
495 regs.len = REGDUMP_SIZE;
497 /* XXX: This is never freed. Looks like we don't care. */
498 if ((regs.data = malloc(regs.len)) == NULL)
499 err(1, "can't malloc");
501 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
502 err(1, "can't read registers");
504 vers = regs.version & 0x3ff;
505 revision = (regs.version >> 10) & 0x3f;
506 is_pcie = (regs.version & 0x80000000) != 0;
509 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
510 #if defined(CONFIG_T3_REGS)
513 return dump_regs_t3(argc, argv, start_arg,
514 (uint32_t *)regs.data, is_pcie);
515 if (revision == 2 || revision == 3)
516 return dump_regs_t3b(argc, argv, start_arg,
517 (uint32_t *)regs.data, is_pcie);
519 return dump_regs_t3c(argc, argv, start_arg,
520 (uint32_t *)regs.data, is_pcie);
523 errx(1, "unknown card type %d.%d", vers, revision);
528 t3_meminfo(const uint32_t *regs)
531 SG_EGR_CNTX_BADDR = 0x58,
532 SG_CQ_CONTEXT_BADDR = 0x6c,
533 CIM_SDRAM_BASE_ADDR = 0x28c,
534 CIM_SDRAM_ADDR_SIZE = 0x290,
535 TP_CMM_MM_BASE = 0x314,
536 TP_CMM_TIMER_BASE = 0x318,
537 TP_CMM_MM_RX_FLST_BASE = 0x460,
538 TP_CMM_MM_TX_FLST_BASE = 0x464,
539 TP_CMM_MM_PS_FLST_BASE = 0x468,
540 ULPRX_ISCSI_LLIMIT = 0x50c,
541 ULPRX_ISCSI_ULIMIT = 0x510,
542 ULPRX_TDDP_LLIMIT = 0x51c,
543 ULPRX_TDDP_ULIMIT = 0x520,
544 ULPRX_STAG_LLIMIT = 0x52c,
545 ULPRX_STAG_ULIMIT = 0x530,
546 ULPRX_RQ_LLIMIT = 0x534,
547 ULPRX_RQ_ULIMIT = 0x538,
548 ULPRX_PBL_LLIMIT = 0x53c,
549 ULPRX_PBL_ULIMIT = 0x540,
552 unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
553 cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
554 timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
555 pstructs = regs[TP_CMM_MM_BASE / 4],
556 pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
557 rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
558 tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
559 cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
560 cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
561 unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
562 iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
563 tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
564 tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
565 stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
566 stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
567 rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
568 rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
569 pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
570 pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
572 printf("CM memory map:\n");
573 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
575 printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
576 cq_cntxt - 1, cq_cntxt - egr_cntxt);
577 printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt,
578 timers - 1, timers - cq_cntxt);
579 printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers,
580 pstructs - 1, pstructs - timers);
581 printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs,
582 pstruct_fl - 1, pstruct_fl - pstructs);
583 printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl,
584 rx_fl - 1, rx_fl - pstruct_fl);
585 printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
587 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
589 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base,
590 cim_base + cim_size - 1, cim_size);
592 printf("\nPMRX memory map:\n");
593 printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
594 iscsi_ul - iscsi_ll + 1);
595 printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
596 tddp_ul - tddp_ll + 1);
597 printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
598 stag_ul - stag_ll + 1);
599 printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
601 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
602 pbl_ul - pbl_ll + 1);
607 meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
610 struct ch_ifconf_regs regs;
616 regs.len = REGDUMP_SIZE;
617 if ((regs.data = malloc(regs.len)) == NULL)
618 err(1, "can't malloc");
620 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
621 err(1, "can't read registers");
623 vers = regs.version & 0x3ff;
625 return t3_meminfo((uint32_t *)regs.data);
627 errx(1, "unknown card type %d", vers);
632 mtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name)
637 if (argc == start_arg) {
638 if (doit(iff_name, CHELSIO_GETMTUTAB, &m) < 0)
639 err(1, "get MTU table");
640 for (i = 0; i < m.nmtus; ++i)
641 printf("%u ", m.mtus[i]);
643 } else if (argc <= start_arg + NMTUS) {
644 m.nmtus = argc - start_arg;
646 for (i = 0; i < m.nmtus; ++i) {
648 unsigned long mt = strtoul(argv[start_arg + i], &p, 0);
650 if (*p || mt > 9600) {
651 warnx("bad parameter \"%s\"",
652 argv[start_arg + i]);
655 if (i && mt < m.mtus[i - 1])
656 errx(1, "MTUs must be in ascending order");
659 if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0)
660 err(1, "set MTU table");
667 #ifdef CHELSIO_INTERNAL
669 show_egress_cntxt(uint32_t data[])
671 printf("credits: %u\n", data[0] & 0x7fff);
672 printf("GTS: %u\n", (data[0] >> 15) & 1);
673 printf("index: %u\n", data[0] >> 16);
674 printf("queue size: %u\n", data[1] & 0xffff);
675 printf("base address: 0x%" PRIx64 "\n",
676 ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
677 (((uint64_t)data[3] & 0xf) << 48)) << 12);
678 printf("rsp queue #: %u\n", (data[3] >> 4) & 7);
679 printf("cmd queue #: %u\n", (data[3] >> 7) & 1);
680 printf("TUN: %u\n", (data[3] >> 8) & 1);
681 printf("TOE: %u\n", (data[3] >> 9) & 1);
682 printf("generation: %u\n", (data[3] >> 10) & 1);
683 printf("uP token: %u\n", (data[3] >> 11) & 0xfffff);
684 printf("valid: %u\n", (data[3] >> 31) & 1);
688 show_fl_cntxt(uint32_t data[])
690 printf("base address: 0x%" PRIx64 "\n",
691 ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
692 printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
693 printf("queue size: %u\n", (data[2] >> 4) & 0xffff);
694 printf("generation: %u\n", (data[2] >> 20) & 1);
695 printf("entry size: %u\n",
696 (data[2] >> 21) | (data[3] & 0x1fffff) << 11);
697 printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff);
698 printf("GTS: %u\n", (data[3] >> 31) & 1);
702 show_response_cntxt(uint32_t data[])
704 printf("index: %u\n", data[0] & 0xffff);
705 printf("size: %u\n", data[0] >> 16);
706 printf("base address: 0x%" PRIx64 "\n",
707 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
708 printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f);
709 printf("intr enable: %u\n", (data[2] >> 26) & 1);
710 printf("intr armed: %u\n", (data[2] >> 27) & 1);
711 printf("generation: %u\n", (data[2] >> 28) & 1);
712 printf("CQ mode: %u\n", (data[2] >> 31) & 1);
713 printf("FL threshold: %u\n", data[3]);
717 show_cq_cntxt(uint32_t data[])
719 printf("index: %u\n", data[0] & 0xffff);
720 printf("size: %u\n", data[0] >> 16);
721 printf("base address: 0x%" PRIx64 "\n",
722 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
723 printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f);
724 printf("AN: %u\n", (data[2] >> 26) & 1);
725 printf("armed: %u\n", (data[2] >> 27) & 1);
726 printf("ANS: %u\n", (data[2] >> 28) & 1);
727 printf("generation: %u\n", (data[2] >> 29) & 1);
728 printf("overflow mode: %u\n", (data[2] >> 31) & 1);
729 printf("credits: %u\n", data[3] & 0xffff);
730 printf("credit threshold: %u\n", data[3] >> 16);
734 get_sge_context(int argc, char *argv[], int start_arg, const char *iff_name)
738 if (argc != start_arg + 2) return -1;
740 if (!strcmp(argv[start_arg], "egress"))
741 ctx.cntxt_type = CNTXT_TYPE_EGRESS;
742 else if (!strcmp(argv[start_arg], "fl"))
743 ctx.cntxt_type = CNTXT_TYPE_FL;
744 else if (!strcmp(argv[start_arg], "response"))
745 ctx.cntxt_type = CNTXT_TYPE_RSP;
746 else if (!strcmp(argv[start_arg], "cq"))
747 ctx.cntxt_type = CNTXT_TYPE_CQ;
749 warnx("unknown context type \"%s\"; known types are egress, "
750 "fl, cq, and response", argv[start_arg]);
754 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
757 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
758 err(1, "get SGE context");
760 if (!strcmp(argv[start_arg], "egress"))
761 show_egress_cntxt(ctx.data);
762 else if (!strcmp(argv[start_arg], "fl"))
763 show_fl_cntxt(ctx.data);
764 else if (!strcmp(argv[start_arg], "response"))
765 show_response_cntxt(ctx.data);
766 else if (!strcmp(argv[start_arg], "cq"))
767 show_cq_cntxt(ctx.data);
771 #define ntohll(x) be64toh((x))
774 get_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name)
777 unsigned int n = 1, qset, qnum;
780 if (argc != start_arg + 3 && argc != start_arg + 4)
783 if (get_int_arg(argv[start_arg], &qset) ||
784 get_int_arg(argv[start_arg + 1], &qnum) ||
785 get_int_arg(argv[start_arg + 2], &desc.idx))
788 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
792 errx(1, "invalid queue number %d, range is 0..5", qnum);
794 desc.queue_num = qset * 6 + qnum;
796 for (; n--; desc.idx++) {
797 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
798 err(1, "get SGE descriptor");
800 p = (uint64_t *)desc.data;
802 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
803 desc.idx, (unsigned int)(wr_hdr >> 56),
804 ((unsigned int)wr_hdr >> 8) & 0xfffff,
805 ((wr_hdr >> 55) & 1) ? "SOP, " : "",
806 ((wr_hdr >> 54) & 1) ? "EOP, " : "",
807 ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
808 ((wr_hdr >> 52) & 1) ? "SGL, " : "",
809 (unsigned int)wr_hdr & 0xff);
811 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
812 printf("%016" PRIx64 "%c", ntohll(*p),
813 desc.size % 32 == 8 ? '\n' : ' ');
820 get_tcb2(int argc, char *argv[], int start_arg, const char *iff_name)
824 unsigned int tcb_idx;
825 struct ch_mem_range mr;
827 if (argc != start_arg + 1)
830 if (get_int_arg(argv[start_arg], &tcb_idx))
833 mr.buf = calloc(1, TCB_SIZE);
838 mr.addr = tcb_idx * TCB_SIZE;
841 if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0)
844 for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) {
846 printf(" %08x %08x %08x %08x", (uint32_t)d[1],
847 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
848 (uint32_t)(d[0] >> 32));
850 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
851 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
852 (uint32_t)(d[0] >> 32));
860 get_pm_page_spec(const char *s, unsigned int *page_size,
861 unsigned int *num_pages)
866 val = strtoul(s, &p, 0);
867 if (p == s) return -1;
868 if (*p == 'x' && p[1]) {
870 *page_size = strtoul(p + 1, &p, 0);
875 *page_size <<= 10; // KB -> bytes
880 conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
884 if (argc == start_arg) {
885 if (doit(iff_name, CHELSIO_GET_PM, &pm) < 0)
886 err(1, "read pm config");
887 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
888 pm.tx_num_pg, pm.tx_pg_sz >> 10, pm.rx_num_pg,
889 pm.rx_pg_sz >> 10, pm.pm_total >> 10);
893 if (argc != start_arg + 2) return -1;
895 if (get_pm_page_spec(argv[start_arg], &pm.tx_pg_sz, &pm.tx_num_pg)) {
896 warnx("bad parameter \"%s\"", argv[start_arg]);
899 if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz,
901 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
904 if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0)
909 #ifdef CHELSIO_INTERNAL
911 dump_tcam(int argc, char *argv[], int start_arg, const char *iff_name)
914 struct ch_tcam_word op;
916 if (argc != start_arg + 2) return -1;
918 if (get_int_arg(argv[start_arg], &op.addr) ||
919 get_int_arg(argv[start_arg + 1], &nwords))
923 if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0)
926 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
927 op.buf[0] & 0xff, op.buf[1], op.buf[2]);
934 hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
939 printf("0x%08x:", start);
940 for (i = 0; i < 4 && len; ++i, --len)
941 printf(" %016llx", (unsigned long long)*data++);
948 dump_mc7(int argc, char *argv[], int start_arg, const char *iff_name)
950 struct ch_mem_range mem;
951 unsigned int mem_id, addr, len;
953 if (argc != start_arg + 3) return -1;
955 if (!strcmp(argv[start_arg], "cm"))
957 else if (!strcmp(argv[start_arg], "rx"))
959 else if (!strcmp(argv[start_arg], "tx"))
962 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
963 " or \"rx\"", argv[start_arg]);
965 if (get_int_arg(argv[start_arg + 1], &addr) ||
966 get_int_arg(argv[start_arg + 2], &len))
969 mem.buf = malloc(len);
971 err(1, "memory dump");
977 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
978 err(1, "memory dump");
980 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
986 /* Max FW size is 64K including version, +4 bytes for the checksum. */
987 #define MAX_FW_IMAGE_SIZE (64 * 1024)
990 load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
993 struct ch_mem_range op;
994 const char *fname = argv[start_arg];
996 if (argc != start_arg + 1) return -1;
998 fd = open(fname, O_RDONLY);
1000 err(1, "load firmware");
1002 bzero(&op, sizeof(op));
1003 op.buf = malloc(MAX_FW_IMAGE_SIZE + 1);
1005 err(1, "load firmware");
1007 len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1);
1009 err(1, "load firmware");
1010 if (len > MAX_FW_IMAGE_SIZE)
1011 errx(1, "FW image too large");
1014 if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0)
1015 err(1, "load firmware");
1021 /* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */
1022 #define MAX_BOOT_IMAGE_SIZE (0xff * 512)
1025 load_boot(int argc, char *argv[], int start_arg, const char *iff_name)
1028 struct ch_mem_range op;
1029 const char *fname = argv[start_arg];
1031 if (argc != start_arg + 1) return -1;
1033 fd = open(fname, O_RDONLY);
1035 err(1, "load boot image");
1037 op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1);
1039 err(1, "load boot image");
1041 len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1);
1043 err(1, "load boot image");
1044 if (len > MAX_BOOT_IMAGE_SIZE)
1045 errx(1, "boot image too large");
1049 if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0)
1050 err(1, "load boot image");
1057 dump_proto_sram(const char *iff_name)
1060 uint8_t buf[PROTO_SRAM_SIZE];
1061 struct ch_eeprom ee;
1064 bzero(buf, sizeof(buf));
1065 ee.offset = PROTO_SRAM_EEPROM_ADDR;
1067 ee.len = sizeof(buf);
1068 if (doit(iff_name, CHELSIO_GET_EEPROM, &ee))
1069 err(1, "show protocol sram");
1071 for (i = 0; i < PROTO_SRAM_LINES; i++) {
1072 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1073 int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1074 uint8_t nibble = p[nibble_idx / 2];
1080 printf("%x", nibble);
1088 proto_sram_op(int argc, char *argv[], int start_arg,
1089 const char *iff_name)
1094 if (argc == start_arg)
1095 return dump_proto_sram(iff_name);
1100 dump_qset_params(const char *iff_name)
1102 struct ch_qset_params qp;
1106 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1108 printf("Qset TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1"
1110 printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n",
1112 qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1113 qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1114 qp.cong_thres, qp.intr_lat, qp.vector);
1117 if (!qp.qset_idx || (errno && errno != EINVAL))
1118 err(1, "get qset parameters");
1123 qset_config(int argc, char *argv[], int start_arg, const char *iff_name)
1127 if (argc == start_arg)
1128 return dump_qset_params(iff_name);
1134 qset_num_config(int argc, char *argv[], int start_arg, const char *iff_name)
1140 if (argc == start_arg) {
1141 if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0)
1142 err(1, "get qsets");
1143 printf("%u\n", reg.val);
1151 * Parse a string containing an IP address with an optional network prefix.
1154 parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1159 *mask = 0xffffffffU;
1160 slash = strchr(s, '/');
1163 if (!inet_aton(s, &ia)) {
1169 *addr = ntohl(ia.s_addr);
1171 unsigned int prefix = strtoul(slash + 1, &p, 10);
1174 if (p == slash + 1 || *p || prefix > 32)
1176 *mask <<= (32 - prefix);
1182 * Parse a string containing a value and an optional colon separated mask.
1185 parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
1186 uint32_t default_mask)
1190 *mask = default_mask;
1191 *val = strtoul(s, &p, 0);
1192 if (p == s || *val > default_mask)
1194 if (*p == ':' && p[1])
1195 *mask = strtoul(p + 1, &p, 0);
1196 return *p || *mask > default_mask ? -1 : 0;
1200 parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1202 return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1203 parse_val_mask_param(s, val, mask, 0xffffffffU);
1207 trace_config(int argc, char *argv[], int start_arg, const char *iff_name)
1210 struct ch_trace trace;
1212 if (argc == start_arg)
1215 memset(&trace, 0, sizeof(trace));
1216 if (!strcmp(argv[start_arg], "tx"))
1217 trace.config_tx = 1;
1218 else if (!strcmp(argv[start_arg], "rx"))
1219 trace.config_rx = 1;
1220 else if (!strcmp(argv[start_arg], "all"))
1221 trace.config_tx = trace.config_rx = 1;
1223 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1224 "\"tx\" or \"all\"", argv[start_arg]);
1226 if (argc == ++start_arg)
1228 if (!strcmp(argv[start_arg], "on")) {
1229 trace.trace_tx = trace.config_tx;
1230 trace.trace_rx = trace.config_rx;
1231 } else if (strcmp(argv[start_arg], "off"))
1232 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1236 if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1237 trace.invert_match = 1;
1241 while (start_arg + 2 <= argc) {
1242 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1244 if (!strcmp(argv[start_arg], "interface")) {
1246 trace.intf_mask = mask;
1247 } else if (!strcmp(argv[start_arg], "sip")) {
1249 trace.sip_mask = mask;
1250 } else if (!strcmp(argv[start_arg], "dip")) {
1252 trace.dip_mask = mask;
1253 } else if (!strcmp(argv[start_arg], "sport")) {
1255 trace.sport_mask = mask;
1256 } else if (!strcmp(argv[start_arg], "dport")) {
1258 trace.dport_mask = mask;
1259 } else if (!strcmp(argv[start_arg], "vlan")) {
1261 trace.vlan_mask = mask;
1262 } else if (!strcmp(argv[start_arg], "proto")) {
1264 trace.proto_mask = mask;
1266 errx(1, "unknown trace parameter \"%s\"\n"
1267 "known parameters are \"interface\", \"sip\", "
1268 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1269 "\"proto\"", argv[start_arg]);
1271 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1274 if (start_arg != argc)
1275 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1277 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1283 show_filters(const char *iff_name)
1285 static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
1286 struct ch_filter op;
1291 char sip[20], dip[20];
1294 bzero(&op, sizeof(op));
1295 op.filter_id = 0xffffffff;
1298 if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
1299 err(1, "list filters");
1301 if (op.filter_id == 0xffffffff)
1305 printf("index SIP DIP sport "
1306 "dport VLAN PRI P/MAC type Q\n");
1310 nsip.nip = htonl(op.val.sip);
1311 ndip.nip = htonl(op.val.dip);
1313 sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1],
1314 nsip.octet[2], nsip.octet[3],
1315 op.mask.sip ? 33 - ffs(op.mask.sip) : 0);
1316 sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1],
1317 ndip.octet[2], ndip.octet[3]);
1318 printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip);
1319 printf(op.val.sport ? "%5u " : " * ", op.val.sport);
1320 printf(op.val.dport ? "%5u " : " * ", op.val.dport);
1321 printf(op.val.vlan != 0xfff ? "%4u " : " * ", op.val.vlan);
1322 printf(op.val.vlan_prio == 7 ? " * " :
1323 "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1);
1324 if (op.mac_addr_idx == 0xffff)
1326 else if (op.mac_hit)
1327 printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
1328 (op.mac_addr_idx) & 0x7);
1330 printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1);
1331 printf("%4s ", pkt_type[op.proto]);
1337 printf("%1u\n", op.qset);
1342 filter_config(int argc, char *argv[], int start_arg, const char *iff_name)
1346 struct ch_filter op;
1348 if (argc < start_arg + 1)
1351 memset(&op, 0, sizeof(op));
1352 op.mac_addr_idx = 0xffff;
1355 if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
1356 show_filters(iff_name);
1360 if (get_int_arg(argv[start_arg++], &op.filter_id))
1362 if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") ||
1363 !strcmp(argv[start_arg], "clear"))) {
1364 if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) {
1366 err(1, "no filter support when offload in use");
1367 err(1, "delete filter");
1372 while (start_arg + 2 <= argc) {
1373 if (!strcmp(argv[start_arg], "sip")) {
1374 ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
1376 } else if (!strcmp(argv[start_arg], "dip")) {
1377 ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
1379 } else if (!strcmp(argv[start_arg], "sport")) {
1380 ret = parse_val_mask_param(argv[start_arg + 1],
1381 &val, &mask, 0xffff);
1383 op.mask.sport = mask;
1384 } else if (!strcmp(argv[start_arg], "dport")) {
1385 ret = parse_val_mask_param(argv[start_arg + 1],
1386 &val, &mask, 0xffff);
1388 op.mask.dport = mask;
1389 } else if (!strcmp(argv[start_arg], "vlan")) {
1390 ret = parse_val_mask_param(argv[start_arg + 1],
1391 &val, &mask, 0xfff);
1393 op.mask.vlan = mask;
1394 } else if (!strcmp(argv[start_arg], "prio")) {
1395 ret = parse_val_mask_param(argv[start_arg + 1],
1397 op.val.vlan_prio = val;
1398 op.mask.vlan_prio = mask;
1399 } else if (!strcmp(argv[start_arg], "mac")) {
1400 if (!strcmp(argv[start_arg + 1], "none"))
1403 ret = get_int_arg(argv[start_arg + 1], &val);
1404 op.mac_hit = val != (uint32_t)-1;
1405 op.mac_addr_idx = op.mac_hit ? val : 0;
1406 } else if (!strcmp(argv[start_arg], "type")) {
1407 if (!strcmp(argv[start_arg + 1], "tcp"))
1409 else if (!strcmp(argv[start_arg + 1], "udp"))
1411 else if (!strcmp(argv[start_arg + 1], "frag"))
1414 errx(1, "unknown type \"%s\"; must be one of "
1415 "\"tcp\", \"udp\", or \"frag\"",
1416 argv[start_arg + 1]);
1417 } else if (!strcmp(argv[start_arg], "queue")) {
1418 ret = get_int_arg(argv[start_arg + 1], &val);
1421 } else if (!strcmp(argv[start_arg], "action")) {
1422 if (!strcmp(argv[start_arg + 1], "pass"))
1424 else if (strcmp(argv[start_arg + 1], "drop"))
1425 errx(1, "unknown action \"%s\"; must be one of "
1426 "\"pass\" or \"drop\"",
1427 argv[start_arg + 1]);
1429 errx(1, "unknown filter parameter \"%s\"\n"
1430 "known parameters are \"mac\", \"sip\", "
1431 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1432 "\"prio\", \"type\", \"queue\", and \"action\"",
1435 errx(1, "bad value \"%s\" for parameter \"%s\"",
1436 argv[start_arg + 1], argv[start_arg]);
1439 if (start_arg != argc)
1440 errx(1, "no value for \"%s\"", argv[start_arg]);
1442 if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
1444 err(1, "no filter support when offload in use");
1445 err(1, "set filter");
1451 get_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
1453 if (pos + 1 >= argc)
1454 errx(1, "missing value for %s", argv[pos]);
1455 if (get_int_arg(argv[pos + 1], valp))
1461 tx_sched(int argc, char *argv[], int start_arg, const char *iff_name)
1463 struct ch_hw_sched op;
1464 unsigned int idx, val;
1466 if (argc < 5 || get_int_arg(argv[start_arg++], &idx))
1470 op.mode = op.channel = -1;
1471 op.kbps = op.class_ipg = op.flow_ipg = -1;
1473 while (argc > start_arg) {
1474 if (!strcmp(argv[start_arg], "mode")) {
1475 if (start_arg + 1 >= argc)
1476 errx(1, "missing value for mode");
1477 if (!strcmp(argv[start_arg + 1], "class"))
1479 else if (!strcmp(argv[start_arg + 1], "flow"))
1482 errx(1, "bad mode \"%s\"", argv[start_arg + 1]);
1483 } else if (!strcmp(argv[start_arg], "channel") &&
1484 !get_sched_param(argc, argv, start_arg, &val))
1486 else if (!strcmp(argv[start_arg], "rate") &&
1487 !get_sched_param(argc, argv, start_arg, &val))
1489 else if (!strcmp(argv[start_arg], "ipg") &&
1490 !get_sched_param(argc, argv, start_arg, &val))
1492 else if (!strcmp(argv[start_arg], "flowipg") &&
1493 !get_sched_param(argc, argv, start_arg, &val))
1496 errx(1, "unknown scheduler parameter \"%s\"",
1501 if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0)
1508 pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1510 struct ch_pktsched_params op;
1511 unsigned int idx, min = -1, max, binding = -1;
1514 errx(1, "no scheduler specified");
1516 if (!strcmp(argv[start_arg], "port")) {
1517 if (argc != start_arg + 4)
1519 if (get_int_arg(argv[start_arg + 1], &idx) ||
1520 get_int_arg(argv[start_arg + 2], &min) ||
1521 get_int_arg(argv[start_arg + 3], &max))
1524 } else if (!strcmp(argv[start_arg], "tunnelq")) {
1525 if (argc != start_arg + 4)
1527 if (get_int_arg(argv[start_arg + 1], &idx) ||
1528 get_int_arg(argv[start_arg + 2], &max) ||
1529 get_int_arg(argv[start_arg + 3], &binding))
1532 } else if (!strcmp(argv[start_arg], "tx"))
1533 return tx_sched(argc, argv, start_arg + 1, iff_name);
1535 errx(1, "unknown scheduler \"%s\"; must be one of \"port\", "
1536 "\"tunnelq\" or \"tx\"", argv[start_arg]);
1541 op.binding = binding;
1542 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0)
1549 clear_stats(int argc, char *argv[], int start_arg, const char *iff_name)
1555 if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0)
1556 err(1, "clearstats");
1562 get_up_la(int argc, char *argv[], int start_arg, const char *iff_name)
1565 int i, idx, max_idx, entries;
1573 la.bufsize = LA_BUFSIZE;
1574 la.data = malloc(la.bufsize);
1576 err(1, "uP_LA malloc");
1578 if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0)
1582 printf("LA is not running\n");
1584 entries = la.bufsize / 4;
1586 max_idx = (entries / 4) - 1;
1587 for (i = 0; i < max_idx; i++) {
1588 printf("%04x %08x %08x\n",
1589 la.data[idx], la.data[idx+2], la.data[idx+1]);
1590 idx = (idx + 4) & (entries - 1);
1597 get_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name)
1599 struct ch_up_ioqs ioqs;
1606 bzero(&ioqs, sizeof(ioqs));
1607 ioqs.bufsize = IOQS_BUFSIZE;
1608 ioqs.data = malloc(IOQS_BUFSIZE);
1610 err(1, "uP_IOQs malloc");
1612 if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0)
1615 printf("ioq_rx_enable : 0x%08x\n", ioqs.ioq_rx_enable);
1616 printf("ioq_tx_enable : 0x%08x\n", ioqs.ioq_tx_enable);
1617 printf("ioq_rx_status : 0x%08x\n", ioqs.ioq_rx_status);
1618 printf("ioq_tx_status : 0x%08x\n", ioqs.ioq_tx_status);
1620 entries = ioqs.bufsize / sizeof(struct t3_ioq_entry);
1621 for (i = 0; i < entries; i++) {
1622 printf("\nioq[%d].cp : 0x%08x\n", i,
1623 ioqs.data[i].ioq_cp);
1624 printf("ioq[%d].pp : 0x%08x\n", i,
1625 ioqs.data[i].ioq_pp);
1626 printf("ioq[%d].alen : 0x%08x\n", i,
1627 ioqs.data[i].ioq_alen);
1628 printf("ioq[%d].stats : 0x%08x\n", i,
1629 ioqs.data[i].ioq_stats);
1630 printf(" sop %u\n", ioqs.data[i].ioq_stats >> 16);
1631 printf(" eop %u\n", ioqs.data[i].ioq_stats & 0xFFFF);
1638 run_cmd(int argc, char *argv[], const char *iff_name)
1642 if (!strcmp(argv[2], "reg"))
1643 r = register_io(argc, argv, 3, iff_name);
1644 else if (!strcmp(argv[2], "mdio"))
1645 r = mdio_io(argc, argv, 3, iff_name);
1646 else if (!strcmp(argv[2], "mtus"))
1647 r = mtu_tab_op(argc, argv, 3, iff_name);
1648 else if (!strcmp(argv[2], "pm"))
1649 r = conf_pm(argc, argv, 3, iff_name);
1650 else if (!strcmp(argv[2], "regdump"))
1651 r = dump_regs(argc, argv, 3, iff_name);
1652 else if (!strcmp(argv[2], "tcamdump"))
1653 r = dump_tcam(argc, argv, 3, iff_name);
1654 else if (!strcmp(argv[2], "memdump"))
1655 r = dump_mc7(argc, argv, 3, iff_name);
1656 else if (!strcmp(argv[2], "meminfo"))
1657 r = meminfo(argc, argv, 3, iff_name);
1658 else if (!strcmp(argv[2], "context"))
1659 r = get_sge_context(argc, argv, 3, iff_name);
1660 else if (!strcmp(argv[2], "desc"))
1661 r = get_sge_desc(argc, argv, 3, iff_name);
1662 else if (!strcmp(argv[2], "loadfw"))
1663 r = load_fw(argc, argv, 3, iff_name);
1664 else if (!strcmp(argv[2], "loadboot"))
1665 r = load_boot(argc, argv, 3, iff_name);
1666 else if (!strcmp(argv[2], "proto"))
1667 r = proto_sram_op(argc, argv, 3, iff_name);
1668 else if (!strcmp(argv[2], "qset"))
1669 r = qset_config(argc, argv, 3, iff_name);
1670 else if (!strcmp(argv[2], "qsets"))
1671 r = qset_num_config(argc, argv, 3, iff_name);
1672 else if (!strcmp(argv[2], "trace"))
1673 r = trace_config(argc, argv, 3, iff_name);
1674 else if (!strcmp(argv[2], "pktsched"))
1675 r = pktsched(argc, argv, 3, iff_name);
1676 else if (!strcmp(argv[2], "tcb"))
1677 r = get_tcb2(argc, argv, 3, iff_name);
1678 else if (!strcmp(argv[2], "filter"))
1679 r = filter_config(argc, argv, 3, iff_name);
1680 else if (!strcmp(argv[2], "clearstats"))
1681 r = clear_stats(argc, argv, 3, iff_name);
1682 else if (!strcmp(argv[2], "la"))
1683 r = get_up_la(argc, argv, 3, iff_name);
1684 else if (!strcmp(argv[2], "ioqs"))
1685 r = get_up_ioqs(argc, argv, 3, iff_name);
1694 run_cmd_loop(int argc, char *argv[], const char *iff_name)
1706 * Fairly simplistic loop. Displays a "> " prompt and processes any
1707 * input as a cxgbtool command. You're supposed to enter only the part
1708 * after "cxgbtool cxgbX". Use "quit" or "exit" to exit. Any error in
1709 * the command will also terminate cxgbtool.
1712 fprintf(stdout, "> ");
1714 n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
1718 if (buf[--n] != '\n')
1724 for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) {
1725 while (s && (*s == ' ' || *s == '\t'))
1727 if ((args[i] = strsep(&s, " \t")) == NULL)
1730 args[sizeof(args)/sizeof(args[0]) - 1] = 0;
1732 if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit"))
1735 (void) run_cmd(i, args, iff_name);
1738 /* Can't really get here */
1743 main(int argc, char *argv[])
1746 const char *iff_name;
1751 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1753 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1754 printf("%s version %s\n", PROGNAME, VERSION);
1755 printf("%s\n", COPYRIGHT);
1760 if (argc < 3) usage(stderr);
1764 if (argc == 3 && !strcmp(argv[2], "stdio"))
1765 r = run_cmd_loop(argc, argv, iff_name);
1767 r = run_cmd(argc, argv, iff_name);