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_var.h>
56 #include <net/if_types.h>
57 #include <sys/endian.h>
61 #define TCB_WORDS (TCB_SIZE / 4)
62 #define PROTO_SRAM_LINES 128
63 #define PROTO_SRAM_LINE_BITS 132
64 #define PROTO_SRAM_LINE_NIBBLES (132 / 4)
65 #define PROTO_SRAM_SIZE (PROTO_SRAM_LINE_NIBBLES * PROTO_SRAM_LINES / 2)
66 #define PROTO_SRAM_EEPROM_ADDR 4096
68 #include <cxgb_ioctl.h>
69 #include <common/cxgb_regs.h>
80 #if defined(CONFIG_T3_REGS)
81 # include "reg_defs_t3.c"
82 # include "reg_defs_t3b.c"
83 # include "reg_defs_t3c.c"
86 static const char *progname;
91 fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
93 "\tclearstats clear MAC statistics\n"
94 "\tcontext <type> <id> show an SGE context\n"
95 "\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
96 "\tfilter <idx> [<param> <val>] ... set a filter\n"
97 "\tfilter <idx> delete|clear delete a filter\n"
98 "\tfilter list list all filters\n"
99 "\tioqs dump uP IOQs\n"
100 "\tla dump uP logic analyzer info\n"
101 "\tloadboot <boot image> download boot image\n"
102 "\tloadfw <FW image> download firmware\n"
103 "\tmdio <phy_addr> <mmd_addr>\n"
104 "\t <reg_addr> [<val>] read/write MDIO register\n"
105 "\tmemdump cm|tx|rx <addr> <len> dump a mem range\n"
106 "\tmeminfo show memory info\n"
107 "\tmtus [<mtu0>...<mtuN>] read/write MTU table\n"
108 "\tpktsched port <idx> <min> <max> set TX port scheduler params\n"
109 "\tpktsched tunnelq <idx> <max>\n"
110 "\t <binding> set TX tunnelq scheduler params\n"
111 "\tpktsched tx <idx>\n"
112 "\t [<param> <val>] ... set Tx HW scheduler\n"
113 "\tpm [<TX page spec> <RX page spec>] read/write PM config\n"
114 "\tproto read proto SRAM\n"
115 "\tqset read qset parameters\n"
116 "\tqsets read # of qsets\n"
117 "\treg <address>[=<val>] read/write register\n"
118 "\tregdump [<module>] dump registers\n"
119 "\ttcamdump <address> <count> show TCAM contents\n"
120 "\ttcb <index> read TCB\n"
121 "\ttrace tx|rx|all on|off [not]\n"
122 "\t [<param> <val>[:<mask>]] ... write trace parameters\n"
124 exit(fp == stderr ? 1 : 0);
128 doit(const char *iff_name, unsigned long cmd, void *data)
134 snprintf(buf, 64, "/dev/%s", iff_name);
136 if ((fd = open(buf, O_RDWR)) < 0)
140 return ioctl(fd, cmd, data) < 0 ? -1 : 0;
144 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");
181 register_io(int argc, char *argv[], int start_arg,
182 const char *iff_name)
185 uint32_t addr, val = 0, w = 0;
187 if (argc != start_arg + 1) return -1;
189 addr = strtoul(argv[start_arg], &p, 0);
190 if (p == argv[start_arg]) return -1;
191 if (*p == '=' && p[1]) {
192 val = strtoul(p + 1, &p, 0);
196 warnx("bad parameter \"%s\"", argv[start_arg]);
201 write_reg(iff_name, addr, val);
203 val = read_reg(iff_name, addr);
204 printf("%#x [%u]\n", val, val);
210 mdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
212 struct ch_mii_data p;
213 unsigned int cmd, phy_addr, reg, mmd, val;
215 if (argc == start_arg + 3)
216 cmd = CHELSIO_GET_MIIREG;
217 else if (argc == start_arg + 4)
218 cmd = CHELSIO_SET_MIIREG;
222 if (get_int_arg(argv[start_arg], &phy_addr) ||
223 get_int_arg(argv[start_arg + 1], &mmd) ||
224 get_int_arg(argv[start_arg + 2], ®) ||
225 (cmd == CHELSIO_SET_MIIREG && get_int_arg(argv[start_arg + 3], &val)))
228 p.phy_id = phy_addr | (mmd << 8);
232 if (doit(iff_name, cmd, &p) < 0)
233 err(1, "MDIO %s", cmd == CHELSIO_GET_MIIREG ? "read" : "write");
234 if (cmd == CHELSIO_GET_MIIREG)
235 printf("%#x [%u]\n", p.val_out, p.val_out);
240 uint32_t xtract(uint32_t val, int shift, int len)
242 return (val >> shift) & ((1 << len) - 1);
246 dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
248 uint32_t reg_val = 0; // silence compiler warning
250 for ( ; reg_array->name; ++reg_array)
251 if (!reg_array->len) {
252 reg_val = regs[reg_array->addr / 4];
253 printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
254 reg_array->name, reg_val, reg_val);
256 uint32_t v = xtract(reg_val, reg_array->addr,
259 printf(" %-40s %#-10x [%u]\n", reg_array->name,
266 dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
269 char *block_name = NULL;
271 if (argc == start_arg + 1)
272 block_name = argv[start_arg];
273 else if (argc != start_arg)
276 if (!block_name || !strcmp(block_name, "sge"))
277 match += dump_block_regs(sge_regs, regs);
278 if (!block_name || !strcmp(block_name, "mc3"))
279 match += dump_block_regs(mc3_regs, regs);
280 if (!block_name || !strcmp(block_name, "mc4"))
281 match += dump_block_regs(mc4_regs, regs);
282 if (!block_name || !strcmp(block_name, "tpi"))
283 match += dump_block_regs(tpi_regs, regs);
284 if (!block_name || !strcmp(block_name, "tp"))
285 match += dump_block_regs(tp_regs, regs);
286 if (!block_name || !strcmp(block_name, "rat"))
287 match += dump_block_regs(rat_regs, regs);
288 if (!block_name || !strcmp(block_name, "cspi"))
289 match += dump_block_regs(cspi_regs, regs);
290 if (!block_name || !strcmp(block_name, "espi"))
291 match += dump_block_regs(espi_regs, regs);
292 if (!block_name || !strcmp(block_name, "ulp"))
293 match += dump_block_regs(ulp_regs, regs);
294 if (!block_name || !strcmp(block_name, "pl"))
295 match += dump_block_regs(pl_regs, regs);
296 if (!block_name || !strcmp(block_name, "mc5"))
297 match += dump_block_regs(mc5_regs, regs);
299 errx(1, "unknown block \"%s\"", block_name);
303 #if defined(CONFIG_T3_REGS)
305 dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie)
308 char *block_name = NULL;
310 if (argc == start_arg + 1)
311 block_name = argv[start_arg];
312 else if (argc != start_arg)
315 if (!block_name || !strcmp(block_name, "sge"))
316 match += dump_block_regs(sge3_regs, regs);
317 if (!block_name || !strcmp(block_name, "pci"))
318 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
320 if (!block_name || !strcmp(block_name, "t3dbg"))
321 match += dump_block_regs(t3dbg_regs, regs);
322 if (!block_name || !strcmp(block_name, "pmrx"))
323 match += dump_block_regs(mc7_pmrx_regs, regs);
324 if (!block_name || !strcmp(block_name, "pmtx"))
325 match += dump_block_regs(mc7_pmtx_regs, regs);
326 if (!block_name || !strcmp(block_name, "cm"))
327 match += dump_block_regs(mc7_cm_regs, regs);
328 if (!block_name || !strcmp(block_name, "cim"))
329 match += dump_block_regs(cim_regs, regs);
330 if (!block_name || !strcmp(block_name, "tp"))
331 match += dump_block_regs(tp1_regs, regs);
332 if (!block_name || !strcmp(block_name, "ulp_rx"))
333 match += dump_block_regs(ulp2_rx_regs, regs);
334 if (!block_name || !strcmp(block_name, "ulp_tx"))
335 match += dump_block_regs(ulp2_tx_regs, regs);
336 if (!block_name || !strcmp(block_name, "pmrx"))
337 match += dump_block_regs(pm1_rx_regs, regs);
338 if (!block_name || !strcmp(block_name, "pmtx"))
339 match += dump_block_regs(pm1_tx_regs, regs);
340 if (!block_name || !strcmp(block_name, "mps"))
341 match += dump_block_regs(mps0_regs, regs);
342 if (!block_name || !strcmp(block_name, "cplsw"))
343 match += dump_block_regs(cpl_switch_regs, regs);
344 if (!block_name || !strcmp(block_name, "smb"))
345 match += dump_block_regs(smb0_regs, regs);
346 if (!block_name || !strcmp(block_name, "i2c"))
347 match += dump_block_regs(i2cm0_regs, regs);
348 if (!block_name || !strcmp(block_name, "mi1"))
349 match += dump_block_regs(mi1_regs, regs);
350 if (!block_name || !strcmp(block_name, "sf"))
351 match += dump_block_regs(sf1_regs, regs);
352 if (!block_name || !strcmp(block_name, "pl"))
353 match += dump_block_regs(pl3_regs, regs);
354 if (!block_name || !strcmp(block_name, "mc5"))
355 match += dump_block_regs(mc5a_regs, regs);
356 if (!block_name || !strcmp(block_name, "xgmac0"))
357 match += dump_block_regs(xgmac0_0_regs, regs);
358 if (!block_name || !strcmp(block_name, "xgmac1"))
359 match += dump_block_regs(xgmac0_1_regs, regs);
361 errx(1, "unknown block \"%s\"", block_name);
366 dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
370 char *block_name = NULL;
372 if (argc == start_arg + 1)
373 block_name = argv[start_arg];
374 else if (argc != start_arg)
377 if (!block_name || !strcmp(block_name, "sge"))
378 match += dump_block_regs(t3b_sge3_regs, regs);
379 if (!block_name || !strcmp(block_name, "pci"))
380 match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
381 t3b_pcix1_regs, regs);
382 if (!block_name || !strcmp(block_name, "t3dbg"))
383 match += dump_block_regs(t3b_t3dbg_regs, regs);
384 if (!block_name || !strcmp(block_name, "pmrx"))
385 match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
386 if (!block_name || !strcmp(block_name, "pmtx"))
387 match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
388 if (!block_name || !strcmp(block_name, "cm"))
389 match += dump_block_regs(t3b_mc7_cm_regs, regs);
390 if (!block_name || !strcmp(block_name, "cim"))
391 match += dump_block_regs(t3b_cim_regs, regs);
392 if (!block_name || !strcmp(block_name, "tp"))
393 match += dump_block_regs(t3b_tp1_regs, regs);
394 if (!block_name || !strcmp(block_name, "ulp_rx"))
395 match += dump_block_regs(t3b_ulp2_rx_regs, regs);
396 if (!block_name || !strcmp(block_name, "ulp_tx"))
397 match += dump_block_regs(t3b_ulp2_tx_regs, regs);
398 if (!block_name || !strcmp(block_name, "pmrx"))
399 match += dump_block_regs(t3b_pm1_rx_regs, regs);
400 if (!block_name || !strcmp(block_name, "pmtx"))
401 match += dump_block_regs(t3b_pm1_tx_regs, regs);
402 if (!block_name || !strcmp(block_name, "mps"))
403 match += dump_block_regs(t3b_mps0_regs, regs);
404 if (!block_name || !strcmp(block_name, "cplsw"))
405 match += dump_block_regs(t3b_cpl_switch_regs, regs);
406 if (!block_name || !strcmp(block_name, "smb"))
407 match += dump_block_regs(t3b_smb0_regs, regs);
408 if (!block_name || !strcmp(block_name, "i2c"))
409 match += dump_block_regs(t3b_i2cm0_regs, regs);
410 if (!block_name || !strcmp(block_name, "mi1"))
411 match += dump_block_regs(t3b_mi1_regs, regs);
412 if (!block_name || !strcmp(block_name, "sf"))
413 match += dump_block_regs(t3b_sf1_regs, regs);
414 if (!block_name || !strcmp(block_name, "pl"))
415 match += dump_block_regs(t3b_pl3_regs, regs);
416 if (!block_name || !strcmp(block_name, "mc5"))
417 match += dump_block_regs(t3b_mc5a_regs, regs);
418 if (!block_name || !strcmp(block_name, "xgmac0"))
419 match += dump_block_regs(t3b_xgmac0_0_regs, regs);
420 if (!block_name || !strcmp(block_name, "xgmac1"))
421 match += dump_block_regs(t3b_xgmac0_1_regs, regs);
423 errx(1, "unknown block \"%s\"", block_name);
428 dump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs,
432 char *block_name = NULL;
434 if (argc == start_arg + 1)
435 block_name = argv[start_arg];
436 else if (argc != start_arg)
439 if (!block_name || !strcmp(block_name, "sge"))
440 match += dump_block_regs(t3c_sge3_regs, regs);
441 if (!block_name || !strcmp(block_name, "pci"))
442 match += dump_block_regs(is_pcie ? t3c_pcie0_regs :
443 t3c_pcix1_regs, regs);
444 if (!block_name || !strcmp(block_name, "t3dbg"))
445 match += dump_block_regs(t3c_t3dbg_regs, regs);
446 if (!block_name || !strcmp(block_name, "pmrx"))
447 match += dump_block_regs(t3c_mc7_pmrx_regs, regs);
448 if (!block_name || !strcmp(block_name, "pmtx"))
449 match += dump_block_regs(t3c_mc7_pmtx_regs, regs);
450 if (!block_name || !strcmp(block_name, "cm"))
451 match += dump_block_regs(t3c_mc7_cm_regs, regs);
452 if (!block_name || !strcmp(block_name, "cim"))
453 match += dump_block_regs(t3c_cim_regs, regs);
454 if (!block_name || !strcmp(block_name, "tp"))
455 match += dump_block_regs(t3c_tp1_regs, regs);
456 if (!block_name || !strcmp(block_name, "ulp_rx"))
457 match += dump_block_regs(t3c_ulp2_rx_regs, regs);
458 if (!block_name || !strcmp(block_name, "ulp_tx"))
459 match += dump_block_regs(t3c_ulp2_tx_regs, regs);
460 if (!block_name || !strcmp(block_name, "pmrx"))
461 match += dump_block_regs(t3c_pm1_rx_regs, regs);
462 if (!block_name || !strcmp(block_name, "pmtx"))
463 match += dump_block_regs(t3c_pm1_tx_regs, regs);
464 if (!block_name || !strcmp(block_name, "mps"))
465 match += dump_block_regs(t3c_mps0_regs, regs);
466 if (!block_name || !strcmp(block_name, "cplsw"))
467 match += dump_block_regs(t3c_cpl_switch_regs, regs);
468 if (!block_name || !strcmp(block_name, "smb"))
469 match += dump_block_regs(t3c_smb0_regs, regs);
470 if (!block_name || !strcmp(block_name, "i2c"))
471 match += dump_block_regs(t3c_i2cm0_regs, regs);
472 if (!block_name || !strcmp(block_name, "mi1"))
473 match += dump_block_regs(t3c_mi1_regs, regs);
474 if (!block_name || !strcmp(block_name, "sf"))
475 match += dump_block_regs(t3c_sf1_regs, regs);
476 if (!block_name || !strcmp(block_name, "pl"))
477 match += dump_block_regs(t3c_pl3_regs, regs);
478 if (!block_name || !strcmp(block_name, "mc5"))
479 match += dump_block_regs(t3c_mc5a_regs, regs);
480 if (!block_name || !strcmp(block_name, "xgmac0"))
481 match += dump_block_regs(t3c_xgmac0_0_regs, regs);
482 if (!block_name || !strcmp(block_name, "xgmac1"))
483 match += dump_block_regs(t3c_xgmac0_1_regs, regs);
485 errx(1, "unknown block \"%s\"", block_name);
491 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
493 int vers, revision, is_pcie;
494 struct ch_ifconf_regs regs;
496 regs.len = REGDUMP_SIZE;
498 /* XXX: This is never freed. Looks like we don't care. */
499 if ((regs.data = malloc(regs.len)) == NULL)
500 err(1, "can't malloc");
502 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
503 err(1, "can't read registers");
505 vers = regs.version & 0x3ff;
506 revision = (regs.version >> 10) & 0x3f;
507 is_pcie = (regs.version & 0x80000000) != 0;
510 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
511 #if defined(CONFIG_T3_REGS)
514 return dump_regs_t3(argc, argv, start_arg,
515 (uint32_t *)regs.data, is_pcie);
516 if (revision == 2 || revision == 3)
517 return dump_regs_t3b(argc, argv, start_arg,
518 (uint32_t *)regs.data, is_pcie);
520 return dump_regs_t3c(argc, argv, start_arg,
521 (uint32_t *)regs.data, is_pcie);
524 errx(1, "unknown card type %d.%d", vers, revision);
529 t3_meminfo(const uint32_t *regs)
532 SG_EGR_CNTX_BADDR = 0x58,
533 SG_CQ_CONTEXT_BADDR = 0x6c,
534 CIM_SDRAM_BASE_ADDR = 0x28c,
535 CIM_SDRAM_ADDR_SIZE = 0x290,
536 TP_CMM_MM_BASE = 0x314,
537 TP_CMM_TIMER_BASE = 0x318,
538 TP_CMM_MM_RX_FLST_BASE = 0x460,
539 TP_CMM_MM_TX_FLST_BASE = 0x464,
540 TP_CMM_MM_PS_FLST_BASE = 0x468,
541 ULPRX_ISCSI_LLIMIT = 0x50c,
542 ULPRX_ISCSI_ULIMIT = 0x510,
543 ULPRX_TDDP_LLIMIT = 0x51c,
544 ULPRX_TDDP_ULIMIT = 0x520,
545 ULPRX_STAG_LLIMIT = 0x52c,
546 ULPRX_STAG_ULIMIT = 0x530,
547 ULPRX_RQ_LLIMIT = 0x534,
548 ULPRX_RQ_ULIMIT = 0x538,
549 ULPRX_PBL_LLIMIT = 0x53c,
550 ULPRX_PBL_ULIMIT = 0x540,
553 unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
554 cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
555 timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
556 pstructs = regs[TP_CMM_MM_BASE / 4],
557 pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
558 rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
559 tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
560 cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
561 cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
562 unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
563 iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
564 tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
565 tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
566 stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
567 stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
568 rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
569 rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
570 pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
571 pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
573 printf("CM memory map:\n");
574 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
576 printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
577 cq_cntxt - 1, cq_cntxt - egr_cntxt);
578 printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt,
579 timers - 1, timers - cq_cntxt);
580 printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers,
581 pstructs - 1, pstructs - timers);
582 printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs,
583 pstruct_fl - 1, pstruct_fl - pstructs);
584 printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl,
585 rx_fl - 1, rx_fl - pstruct_fl);
586 printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
588 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
590 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base,
591 cim_base + cim_size - 1, cim_size);
593 printf("\nPMRX memory map:\n");
594 printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
595 iscsi_ul - iscsi_ll + 1);
596 printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
597 tddp_ul - tddp_ll + 1);
598 printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
599 stag_ul - stag_ll + 1);
600 printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
602 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
603 pbl_ul - pbl_ll + 1);
608 meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
611 struct ch_ifconf_regs regs;
617 regs.len = REGDUMP_SIZE;
618 if ((regs.data = malloc(regs.len)) == NULL)
619 err(1, "can't malloc");
621 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
622 err(1, "can't read registers");
624 vers = regs.version & 0x3ff;
626 return t3_meminfo((uint32_t *)regs.data);
628 errx(1, "unknown card type %d", vers);
633 mtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name)
638 if (argc == start_arg) {
639 if (doit(iff_name, CHELSIO_GETMTUTAB, &m) < 0)
640 err(1, "get MTU table");
641 for (i = 0; i < m.nmtus; ++i)
642 printf("%u ", m.mtus[i]);
644 } else if (argc <= start_arg + NMTUS) {
645 m.nmtus = argc - start_arg;
647 for (i = 0; i < m.nmtus; ++i) {
649 unsigned long mt = strtoul(argv[start_arg + i], &p, 0);
651 if (*p || mt > 9600) {
652 warnx("bad parameter \"%s\"",
653 argv[start_arg + i]);
656 if (i && mt < m.mtus[i - 1])
657 errx(1, "MTUs must be in ascending order");
660 if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0)
661 err(1, "set MTU table");
668 #ifdef CHELSIO_INTERNAL
670 show_egress_cntxt(uint32_t data[])
672 printf("credits: %u\n", data[0] & 0x7fff);
673 printf("GTS: %u\n", (data[0] >> 15) & 1);
674 printf("index: %u\n", data[0] >> 16);
675 printf("queue size: %u\n", data[1] & 0xffff);
676 printf("base address: 0x%" PRIx64 "\n",
677 ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
678 (((uint64_t)data[3] & 0xf) << 48)) << 12);
679 printf("rsp queue #: %u\n", (data[3] >> 4) & 7);
680 printf("cmd queue #: %u\n", (data[3] >> 7) & 1);
681 printf("TUN: %u\n", (data[3] >> 8) & 1);
682 printf("TOE: %u\n", (data[3] >> 9) & 1);
683 printf("generation: %u\n", (data[3] >> 10) & 1);
684 printf("uP token: %u\n", (data[3] >> 11) & 0xfffff);
685 printf("valid: %u\n", (data[3] >> 31) & 1);
689 show_fl_cntxt(uint32_t data[])
691 printf("base address: 0x%" PRIx64 "\n",
692 ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
693 printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
694 printf("queue size: %u\n", (data[2] >> 4) & 0xffff);
695 printf("generation: %u\n", (data[2] >> 20) & 1);
696 printf("entry size: %u\n",
697 (data[2] >> 21) | (data[3] & 0x1fffff) << 11);
698 printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff);
699 printf("GTS: %u\n", (data[3] >> 31) & 1);
703 show_response_cntxt(uint32_t data[])
705 printf("index: %u\n", data[0] & 0xffff);
706 printf("size: %u\n", data[0] >> 16);
707 printf("base address: 0x%" PRIx64 "\n",
708 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
709 printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f);
710 printf("intr enable: %u\n", (data[2] >> 26) & 1);
711 printf("intr armed: %u\n", (data[2] >> 27) & 1);
712 printf("generation: %u\n", (data[2] >> 28) & 1);
713 printf("CQ mode: %u\n", (data[2] >> 31) & 1);
714 printf("FL threshold: %u\n", data[3]);
718 show_cq_cntxt(uint32_t data[])
720 printf("index: %u\n", data[0] & 0xffff);
721 printf("size: %u\n", data[0] >> 16);
722 printf("base address: 0x%" PRIx64 "\n",
723 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
724 printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f);
725 printf("AN: %u\n", (data[2] >> 26) & 1);
726 printf("armed: %u\n", (data[2] >> 27) & 1);
727 printf("ANS: %u\n", (data[2] >> 28) & 1);
728 printf("generation: %u\n", (data[2] >> 29) & 1);
729 printf("overflow mode: %u\n", (data[2] >> 31) & 1);
730 printf("credits: %u\n", data[3] & 0xffff);
731 printf("credit threshold: %u\n", data[3] >> 16);
735 get_sge_context(int argc, char *argv[], int start_arg, const char *iff_name)
739 if (argc != start_arg + 2) return -1;
741 if (!strcmp(argv[start_arg], "egress"))
742 ctx.cntxt_type = CNTXT_TYPE_EGRESS;
743 else if (!strcmp(argv[start_arg], "fl"))
744 ctx.cntxt_type = CNTXT_TYPE_FL;
745 else if (!strcmp(argv[start_arg], "response"))
746 ctx.cntxt_type = CNTXT_TYPE_RSP;
747 else if (!strcmp(argv[start_arg], "cq"))
748 ctx.cntxt_type = CNTXT_TYPE_CQ;
750 warnx("unknown context type \"%s\"; known types are egress, "
751 "fl, cq, and response", argv[start_arg]);
755 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
758 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
759 err(1, "get SGE context");
761 if (!strcmp(argv[start_arg], "egress"))
762 show_egress_cntxt(ctx.data);
763 else if (!strcmp(argv[start_arg], "fl"))
764 show_fl_cntxt(ctx.data);
765 else if (!strcmp(argv[start_arg], "response"))
766 show_response_cntxt(ctx.data);
767 else if (!strcmp(argv[start_arg], "cq"))
768 show_cq_cntxt(ctx.data);
772 #define ntohll(x) be64toh((x))
775 get_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name)
778 unsigned int n = 1, qset, qnum;
781 if (argc != start_arg + 3 && argc != start_arg + 4)
784 if (get_int_arg(argv[start_arg], &qset) ||
785 get_int_arg(argv[start_arg + 1], &qnum) ||
786 get_int_arg(argv[start_arg + 2], &desc.idx))
789 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
793 errx(1, "invalid queue number %d, range is 0..5", qnum);
795 desc.queue_num = qset * 6 + qnum;
797 for (; n--; desc.idx++) {
798 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
799 err(1, "get SGE descriptor");
801 p = (uint64_t *)desc.data;
803 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
804 desc.idx, (unsigned int)(wr_hdr >> 56),
805 ((unsigned int)wr_hdr >> 8) & 0xfffff,
806 ((wr_hdr >> 55) & 1) ? "SOP, " : "",
807 ((wr_hdr >> 54) & 1) ? "EOP, " : "",
808 ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
809 ((wr_hdr >> 52) & 1) ? "SGL, " : "",
810 (unsigned int)wr_hdr & 0xff);
812 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
813 printf("%016" PRIx64 "%c", ntohll(*p),
814 desc.size % 32 == 8 ? '\n' : ' ');
821 get_tcb2(int argc, char *argv[], int start_arg, const char *iff_name)
825 unsigned int tcb_idx;
826 struct ch_mem_range mr;
828 if (argc != start_arg + 1)
831 if (get_int_arg(argv[start_arg], &tcb_idx))
834 mr.buf = calloc(1, TCB_SIZE);
839 mr.addr = tcb_idx * TCB_SIZE;
842 if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0)
845 for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) {
847 printf(" %08x %08x %08x %08x", (uint32_t)d[1],
848 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
849 (uint32_t)(d[0] >> 32));
851 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
852 (uint32_t)(d[1] >> 32), (uint32_t)d[0],
853 (uint32_t)(d[0] >> 32));
861 get_pm_page_spec(const char *s, unsigned int *page_size,
862 unsigned int *num_pages)
867 val = strtoul(s, &p, 0);
868 if (p == s) return -1;
869 if (*p == 'x' && p[1]) {
871 *page_size = strtoul(p + 1, &p, 0);
876 *page_size <<= 10; // KB -> bytes
881 conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
885 if (argc == start_arg) {
886 if (doit(iff_name, CHELSIO_GET_PM, &pm) < 0)
887 err(1, "read pm config");
888 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
889 pm.tx_num_pg, pm.tx_pg_sz >> 10, pm.rx_num_pg,
890 pm.rx_pg_sz >> 10, pm.pm_total >> 10);
894 if (argc != start_arg + 2) return -1;
896 if (get_pm_page_spec(argv[start_arg], &pm.tx_pg_sz, &pm.tx_num_pg)) {
897 warnx("bad parameter \"%s\"", argv[start_arg]);
900 if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz,
902 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
905 if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0)
910 #ifdef CHELSIO_INTERNAL
912 dump_tcam(int argc, char *argv[], int start_arg, const char *iff_name)
915 struct ch_tcam_word op;
917 if (argc != start_arg + 2) return -1;
919 if (get_int_arg(argv[start_arg], &op.addr) ||
920 get_int_arg(argv[start_arg + 1], &nwords))
924 if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0)
927 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
928 op.buf[0] & 0xff, op.buf[1], op.buf[2]);
935 hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
940 printf("0x%08x:", start);
941 for (i = 0; i < 4 && len; ++i, --len)
942 printf(" %016llx", (unsigned long long)*data++);
949 dump_mc7(int argc, char *argv[], int start_arg, const char *iff_name)
951 struct ch_mem_range mem;
952 unsigned int mem_id, addr, len;
954 if (argc != start_arg + 3) return -1;
956 if (!strcmp(argv[start_arg], "cm"))
958 else if (!strcmp(argv[start_arg], "rx"))
960 else if (!strcmp(argv[start_arg], "tx"))
963 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
964 " or \"rx\"", argv[start_arg]);
966 if (get_int_arg(argv[start_arg + 1], &addr) ||
967 get_int_arg(argv[start_arg + 2], &len))
970 mem.buf = malloc(len);
972 err(1, "memory dump");
978 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
979 err(1, "memory dump");
981 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
987 /* Max FW size is 64K including version, +4 bytes for the checksum. */
988 #define MAX_FW_IMAGE_SIZE (64 * 1024)
991 load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
994 struct ch_mem_range op;
995 const char *fname = argv[start_arg];
997 if (argc != start_arg + 1) return -1;
999 fd = open(fname, O_RDONLY);
1001 err(1, "load firmware");
1003 bzero(&op, sizeof(op));
1004 op.buf = malloc(MAX_FW_IMAGE_SIZE + 1);
1006 err(1, "load firmware");
1008 len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1);
1010 err(1, "load firmware");
1011 if (len > MAX_FW_IMAGE_SIZE)
1012 errx(1, "FW image too large");
1015 if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0)
1016 err(1, "load firmware");
1022 /* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */
1023 #define MAX_BOOT_IMAGE_SIZE (0xff * 512)
1026 load_boot(int argc, char *argv[], int start_arg, const char *iff_name)
1029 struct ch_mem_range op;
1030 const char *fname = argv[start_arg];
1032 if (argc != start_arg + 1) return -1;
1034 fd = open(fname, O_RDONLY);
1036 err(1, "load boot image");
1038 op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1);
1040 err(1, "load boot image");
1042 len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1);
1044 err(1, "load boot image");
1045 if (len > MAX_BOOT_IMAGE_SIZE)
1046 errx(1, "boot image too large");
1050 if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0)
1051 err(1, "load boot image");
1058 dump_proto_sram(const char *iff_name)
1061 uint8_t buf[PROTO_SRAM_SIZE];
1062 struct ch_eeprom ee;
1065 bzero(buf, sizeof(buf));
1066 ee.offset = PROTO_SRAM_EEPROM_ADDR;
1068 ee.len = sizeof(buf);
1069 if (doit(iff_name, CHELSIO_GET_EEPROM, &ee))
1070 err(1, "show protocol sram");
1072 for (i = 0; i < PROTO_SRAM_LINES; i++) {
1073 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1074 int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1075 uint8_t nibble = p[nibble_idx / 2];
1081 printf("%x", nibble);
1089 proto_sram_op(int argc, char *argv[], int start_arg,
1090 const char *iff_name)
1095 if (argc == start_arg)
1096 return dump_proto_sram(iff_name);
1101 dump_qset_params(const char *iff_name)
1103 struct ch_qset_params qp;
1107 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1109 printf("Qset TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1"
1111 printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n",
1113 qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1114 qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1115 qp.cong_thres, qp.intr_lat, qp.vector);
1118 if (!qp.qset_idx || (errno && errno != EINVAL))
1119 err(1, "get qset parameters");
1124 qset_config(int argc, char *argv[], int start_arg, const char *iff_name)
1128 if (argc == start_arg)
1129 return dump_qset_params(iff_name);
1135 qset_num_config(int argc, char *argv[], int start_arg, const char *iff_name)
1141 if (argc == start_arg) {
1142 if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0)
1143 err(1, "get qsets");
1144 printf("%u\n", reg.val);
1152 * Parse a string containing an IP address with an optional network prefix.
1155 parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1160 *mask = 0xffffffffU;
1161 slash = strchr(s, '/');
1164 if (!inet_aton(s, &ia)) {
1170 *addr = ntohl(ia.s_addr);
1172 unsigned int prefix = strtoul(slash + 1, &p, 10);
1175 if (p == slash + 1 || *p || prefix > 32)
1177 *mask <<= (32 - prefix);
1183 * Parse a string containing a value and an optional colon separated mask.
1186 parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
1187 uint32_t default_mask)
1191 *mask = default_mask;
1192 *val = strtoul(s, &p, 0);
1193 if (p == s || *val > default_mask)
1195 if (*p == ':' && p[1])
1196 *mask = strtoul(p + 1, &p, 0);
1197 return *p || *mask > default_mask ? -1 : 0;
1201 parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1203 return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1204 parse_val_mask_param(s, val, mask, 0xffffffffU);
1208 trace_config(int argc, char *argv[], int start_arg, const char *iff_name)
1211 struct ch_trace trace;
1213 if (argc == start_arg)
1216 memset(&trace, 0, sizeof(trace));
1217 if (!strcmp(argv[start_arg], "tx"))
1218 trace.config_tx = 1;
1219 else if (!strcmp(argv[start_arg], "rx"))
1220 trace.config_rx = 1;
1221 else if (!strcmp(argv[start_arg], "all"))
1222 trace.config_tx = trace.config_rx = 1;
1224 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1225 "\"tx\" or \"all\"", argv[start_arg]);
1227 if (argc == ++start_arg)
1229 if (!strcmp(argv[start_arg], "on")) {
1230 trace.trace_tx = trace.config_tx;
1231 trace.trace_rx = trace.config_rx;
1232 } else if (strcmp(argv[start_arg], "off"))
1233 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1237 if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1238 trace.invert_match = 1;
1242 while (start_arg + 2 <= argc) {
1243 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1245 if (!strcmp(argv[start_arg], "interface")) {
1247 trace.intf_mask = mask;
1248 } else if (!strcmp(argv[start_arg], "sip")) {
1250 trace.sip_mask = mask;
1251 } else if (!strcmp(argv[start_arg], "dip")) {
1253 trace.dip_mask = mask;
1254 } else if (!strcmp(argv[start_arg], "sport")) {
1256 trace.sport_mask = mask;
1257 } else if (!strcmp(argv[start_arg], "dport")) {
1259 trace.dport_mask = mask;
1260 } else if (!strcmp(argv[start_arg], "vlan")) {
1262 trace.vlan_mask = mask;
1263 } else if (!strcmp(argv[start_arg], "proto")) {
1265 trace.proto_mask = mask;
1267 errx(1, "unknown trace parameter \"%s\"\n"
1268 "known parameters are \"interface\", \"sip\", "
1269 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1270 "\"proto\"", argv[start_arg]);
1272 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1275 if (start_arg != argc)
1276 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1278 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1284 show_filters(const char *iff_name)
1286 static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
1287 struct ch_filter op;
1292 char sip[20], dip[20];
1295 bzero(&op, sizeof(op));
1296 op.filter_id = 0xffffffff;
1299 if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
1300 err(1, "list filters");
1302 if (op.filter_id == 0xffffffff)
1306 printf("index SIP DIP sport "
1307 "dport VLAN PRI P/MAC type Q\n");
1311 nsip.nip = htonl(op.val.sip);
1312 ndip.nip = htonl(op.val.dip);
1314 sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1],
1315 nsip.octet[2], nsip.octet[3],
1316 op.mask.sip ? 33 - ffs(op.mask.sip) : 0);
1317 sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1],
1318 ndip.octet[2], ndip.octet[3]);
1319 printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip);
1320 printf(op.val.sport ? "%5u " : " * ", op.val.sport);
1321 printf(op.val.dport ? "%5u " : " * ", op.val.dport);
1322 printf(op.val.vlan != 0xfff ? "%4u " : " * ", op.val.vlan);
1323 printf(op.val.vlan_prio == 7 ? " * " :
1324 "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1);
1325 if (op.mac_addr_idx == 0xffff)
1327 else if (op.mac_hit)
1328 printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
1329 (op.mac_addr_idx) & 0x7);
1331 printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1);
1332 printf("%4s ", pkt_type[op.proto]);
1338 printf("%1u\n", op.qset);
1343 filter_config(int argc, char *argv[], int start_arg, const char *iff_name)
1347 struct ch_filter op;
1349 if (argc < start_arg + 1)
1352 memset(&op, 0, sizeof(op));
1353 op.mac_addr_idx = 0xffff;
1356 if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
1357 show_filters(iff_name);
1361 if (get_int_arg(argv[start_arg++], &op.filter_id))
1363 if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") ||
1364 !strcmp(argv[start_arg], "clear"))) {
1365 if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) {
1367 err(1, "no filter support when offload in use");
1368 err(1, "delete filter");
1373 while (start_arg + 2 <= argc) {
1374 if (!strcmp(argv[start_arg], "sip")) {
1375 ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
1377 } else if (!strcmp(argv[start_arg], "dip")) {
1378 ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
1380 } else if (!strcmp(argv[start_arg], "sport")) {
1381 ret = parse_val_mask_param(argv[start_arg + 1],
1382 &val, &mask, 0xffff);
1384 op.mask.sport = mask;
1385 } else if (!strcmp(argv[start_arg], "dport")) {
1386 ret = parse_val_mask_param(argv[start_arg + 1],
1387 &val, &mask, 0xffff);
1389 op.mask.dport = mask;
1390 } else if (!strcmp(argv[start_arg], "vlan")) {
1391 ret = parse_val_mask_param(argv[start_arg + 1],
1392 &val, &mask, 0xfff);
1394 op.mask.vlan = mask;
1395 } else if (!strcmp(argv[start_arg], "prio")) {
1396 ret = parse_val_mask_param(argv[start_arg + 1],
1398 op.val.vlan_prio = val;
1399 op.mask.vlan_prio = mask;
1400 } else if (!strcmp(argv[start_arg], "mac")) {
1401 if (!strcmp(argv[start_arg + 1], "none"))
1404 ret = get_int_arg(argv[start_arg + 1], &val);
1405 op.mac_hit = val != (uint32_t)-1;
1406 op.mac_addr_idx = op.mac_hit ? val : 0;
1407 } else if (!strcmp(argv[start_arg], "type")) {
1408 if (!strcmp(argv[start_arg + 1], "tcp"))
1410 else if (!strcmp(argv[start_arg + 1], "udp"))
1412 else if (!strcmp(argv[start_arg + 1], "frag"))
1415 errx(1, "unknown type \"%s\"; must be one of "
1416 "\"tcp\", \"udp\", or \"frag\"",
1417 argv[start_arg + 1]);
1418 } else if (!strcmp(argv[start_arg], "queue")) {
1419 ret = get_int_arg(argv[start_arg + 1], &val);
1422 } else if (!strcmp(argv[start_arg], "action")) {
1423 if (!strcmp(argv[start_arg + 1], "pass"))
1425 else if (strcmp(argv[start_arg + 1], "drop"))
1426 errx(1, "unknown action \"%s\"; must be one of "
1427 "\"pass\" or \"drop\"",
1428 argv[start_arg + 1]);
1430 errx(1, "unknown filter parameter \"%s\"\n"
1431 "known parameters are \"mac\", \"sip\", "
1432 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1433 "\"prio\", \"type\", \"queue\", and \"action\"",
1436 errx(1, "bad value \"%s\" for parameter \"%s\"",
1437 argv[start_arg + 1], argv[start_arg]);
1440 if (start_arg != argc)
1441 errx(1, "no value for \"%s\"", argv[start_arg]);
1443 if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
1445 err(1, "no filter support when offload in use");
1446 err(1, "set filter");
1452 get_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
1454 if (pos + 1 >= argc)
1455 errx(1, "missing value for %s", argv[pos]);
1456 if (get_int_arg(argv[pos + 1], valp))
1462 tx_sched(int argc, char *argv[], int start_arg, const char *iff_name)
1464 struct ch_hw_sched op;
1465 unsigned int idx, val;
1467 if (argc < 5 || get_int_arg(argv[start_arg++], &idx))
1471 op.mode = op.channel = -1;
1472 op.kbps = op.class_ipg = op.flow_ipg = -1;
1474 while (argc > start_arg) {
1475 if (!strcmp(argv[start_arg], "mode")) {
1476 if (start_arg + 1 >= argc)
1477 errx(1, "missing value for mode");
1478 if (!strcmp(argv[start_arg + 1], "class"))
1480 else if (!strcmp(argv[start_arg + 1], "flow"))
1483 errx(1, "bad mode \"%s\"", argv[start_arg + 1]);
1484 } else if (!strcmp(argv[start_arg], "channel") &&
1485 !get_sched_param(argc, argv, start_arg, &val))
1487 else if (!strcmp(argv[start_arg], "rate") &&
1488 !get_sched_param(argc, argv, start_arg, &val))
1490 else if (!strcmp(argv[start_arg], "ipg") &&
1491 !get_sched_param(argc, argv, start_arg, &val))
1493 else if (!strcmp(argv[start_arg], "flowipg") &&
1494 !get_sched_param(argc, argv, start_arg, &val))
1497 errx(1, "unknown scheduler parameter \"%s\"",
1502 if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0)
1509 pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1511 struct ch_pktsched_params op;
1512 unsigned int idx, min = -1, max, binding = -1;
1515 errx(1, "no scheduler specified");
1517 if (!strcmp(argv[start_arg], "port")) {
1518 if (argc != start_arg + 4)
1520 if (get_int_arg(argv[start_arg + 1], &idx) ||
1521 get_int_arg(argv[start_arg + 2], &min) ||
1522 get_int_arg(argv[start_arg + 3], &max))
1525 } else if (!strcmp(argv[start_arg], "tunnelq")) {
1526 if (argc != start_arg + 4)
1528 if (get_int_arg(argv[start_arg + 1], &idx) ||
1529 get_int_arg(argv[start_arg + 2], &max) ||
1530 get_int_arg(argv[start_arg + 3], &binding))
1533 } else if (!strcmp(argv[start_arg], "tx"))
1534 return tx_sched(argc, argv, start_arg + 1, iff_name);
1536 errx(1, "unknown scheduler \"%s\"; must be one of \"port\", "
1537 "\"tunnelq\" or \"tx\"", argv[start_arg]);
1542 op.binding = binding;
1543 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0)
1550 clear_stats(int argc, char *argv[], int start_arg, const char *iff_name)
1556 if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0)
1557 err(1, "clearstats");
1563 get_up_la(int argc, char *argv[], int start_arg, const char *iff_name)
1566 int i, idx, max_idx, entries;
1574 la.bufsize = LA_BUFSIZE;
1575 la.data = malloc(la.bufsize);
1577 err(1, "uP_LA malloc");
1579 if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0)
1583 printf("LA is not running\n");
1585 entries = la.bufsize / 4;
1587 max_idx = (entries / 4) - 1;
1588 for (i = 0; i < max_idx; i++) {
1589 printf("%04x %08x %08x\n",
1590 la.data[idx], la.data[idx+2], la.data[idx+1]);
1591 idx = (idx + 4) & (entries - 1);
1598 get_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name)
1600 struct ch_up_ioqs ioqs;
1607 bzero(&ioqs, sizeof(ioqs));
1608 ioqs.bufsize = IOQS_BUFSIZE;
1609 ioqs.data = malloc(IOQS_BUFSIZE);
1611 err(1, "uP_IOQs malloc");
1613 if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0)
1616 printf("ioq_rx_enable : 0x%08x\n", ioqs.ioq_rx_enable);
1617 printf("ioq_tx_enable : 0x%08x\n", ioqs.ioq_tx_enable);
1618 printf("ioq_rx_status : 0x%08x\n", ioqs.ioq_rx_status);
1619 printf("ioq_tx_status : 0x%08x\n", ioqs.ioq_tx_status);
1621 entries = ioqs.bufsize / sizeof(struct t3_ioq_entry);
1622 for (i = 0; i < entries; i++) {
1623 printf("\nioq[%d].cp : 0x%08x\n", i,
1624 ioqs.data[i].ioq_cp);
1625 printf("ioq[%d].pp : 0x%08x\n", i,
1626 ioqs.data[i].ioq_pp);
1627 printf("ioq[%d].alen : 0x%08x\n", i,
1628 ioqs.data[i].ioq_alen);
1629 printf("ioq[%d].stats : 0x%08x\n", i,
1630 ioqs.data[i].ioq_stats);
1631 printf(" sop %u\n", ioqs.data[i].ioq_stats >> 16);
1632 printf(" eop %u\n", ioqs.data[i].ioq_stats & 0xFFFF);
1639 run_cmd(int argc, char *argv[], const char *iff_name)
1643 if (!strcmp(argv[2], "reg"))
1644 r = register_io(argc, argv, 3, iff_name);
1645 else if (!strcmp(argv[2], "mdio"))
1646 r = mdio_io(argc, argv, 3, iff_name);
1647 else if (!strcmp(argv[2], "mtus"))
1648 r = mtu_tab_op(argc, argv, 3, iff_name);
1649 else if (!strcmp(argv[2], "pm"))
1650 r = conf_pm(argc, argv, 3, iff_name);
1651 else if (!strcmp(argv[2], "regdump"))
1652 r = dump_regs(argc, argv, 3, iff_name);
1653 else if (!strcmp(argv[2], "tcamdump"))
1654 r = dump_tcam(argc, argv, 3, iff_name);
1655 else if (!strcmp(argv[2], "memdump"))
1656 r = dump_mc7(argc, argv, 3, iff_name);
1657 else if (!strcmp(argv[2], "meminfo"))
1658 r = meminfo(argc, argv, 3, iff_name);
1659 else if (!strcmp(argv[2], "context"))
1660 r = get_sge_context(argc, argv, 3, iff_name);
1661 else if (!strcmp(argv[2], "desc"))
1662 r = get_sge_desc(argc, argv, 3, iff_name);
1663 else if (!strcmp(argv[2], "loadfw"))
1664 r = load_fw(argc, argv, 3, iff_name);
1665 else if (!strcmp(argv[2], "loadboot"))
1666 r = load_boot(argc, argv, 3, iff_name);
1667 else if (!strcmp(argv[2], "proto"))
1668 r = proto_sram_op(argc, argv, 3, iff_name);
1669 else if (!strcmp(argv[2], "qset"))
1670 r = qset_config(argc, argv, 3, iff_name);
1671 else if (!strcmp(argv[2], "qsets"))
1672 r = qset_num_config(argc, argv, 3, iff_name);
1673 else if (!strcmp(argv[2], "trace"))
1674 r = trace_config(argc, argv, 3, iff_name);
1675 else if (!strcmp(argv[2], "pktsched"))
1676 r = pktsched(argc, argv, 3, iff_name);
1677 else if (!strcmp(argv[2], "tcb"))
1678 r = get_tcb2(argc, argv, 3, iff_name);
1679 else if (!strcmp(argv[2], "filter"))
1680 r = filter_config(argc, argv, 3, iff_name);
1681 else if (!strcmp(argv[2], "clearstats"))
1682 r = clear_stats(argc, argv, 3, iff_name);
1683 else if (!strcmp(argv[2], "la"))
1684 r = get_up_la(argc, argv, 3, iff_name);
1685 else if (!strcmp(argv[2], "ioqs"))
1686 r = get_up_ioqs(argc, argv, 3, iff_name);
1695 run_cmd_loop(int argc, char *argv[], const char *iff_name)
1707 * Fairly simplistic loop. Displays a "> " prompt and processes any
1708 * input as a cxgbtool command. You're supposed to enter only the part
1709 * after "cxgbtool cxgbX". Use "quit" or "exit" to exit. Any error in
1710 * the command will also terminate cxgbtool.
1713 fprintf(stdout, "> ");
1715 n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
1719 if (buf[--n] != '\n')
1725 for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) {
1726 while (s && (*s == ' ' || *s == '\t'))
1728 if ((args[i] = strsep(&s, " \t")) == NULL)
1731 args[sizeof(args)/sizeof(args[0]) - 1] = 0;
1733 if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit"))
1736 (void) run_cmd(i, args, iff_name);
1739 /* Can't really get here */
1744 main(int argc, char *argv[])
1747 const char *iff_name;
1752 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1754 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1755 printf("%s version %s\n", PROGNAME, VERSION);
1756 printf("%s\n", COPYRIGHT);
1761 if (argc < 3) usage(stderr);
1765 if (argc == 3 && !strcmp(argv[2], "stdio"))
1766 r = run_cmd_loop(argc, argv, iff_name);
1768 r = run_cmd(argc, argv, iff_name);