cxgbtool.c revision 194928
1/************************************************************************** 2 3Copyright (c) 2007-2009, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, are permitted provided that the following conditions are met: 8 9 1. Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 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. 15 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. 19 20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30POSSIBILITY OF SUCH DAMAGE. 31 32 33***************************************************************************/ 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: head/usr.sbin/cxgbtool/cxgbtool.c 194928 2009-06-24 22:28:48Z np $"); 36 37#include <stdlib.h> 38#include <stdio.h> 39#include <stdint.h> 40#include <string.h> 41#include <unistd.h> 42#include <fcntl.h> 43#include <err.h> 44#include <errno.h> 45#include <inttypes.h> 46#include <sys/param.h> 47#include <sys/time.h> 48#include <sys/ioctl.h> 49#include <sys/socket.h> 50 51#include <netinet/in.h> 52#include <arpa/inet.h> 53 54#include <net/if.h> 55#include <net/if_var.h> 56#include <net/if_types.h> 57#include <sys/endian.h> 58 59#define NMTUS 16 60#define TCB_SIZE 128 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 67 68#include <cxgb_ioctl.h> 69#include <common/cxgb_regs.h> 70#include "version.h" 71 72struct reg_info { 73 const char *name; 74 uint16_t addr; 75 uint16_t len; 76}; 77 78 79#include "reg_defs.c" 80#if defined(CONFIG_T3_REGS) 81# include "reg_defs_t3.c" 82# include "reg_defs_t3b.c" 83# include "reg_defs_t3c.c" 84#endif 85 86static const char *progname; 87 88static void __attribute__((noreturn)) usage(FILE *fp) 89{ 90 fprintf(fp, "Usage: %s <interface> [operation]\n", progname); 91 fprintf(fp, 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 "\tioqs dump uP IOQs\n" 96 "\tla dump uP logic analyzer info\n" 97 "\tloadboot <boot image> download boot image\n" 98 "\tloadfw <FW image> download firmware\n" 99 "\tmdio <phy_addr> <mmd_addr>\n" 100 "\t <reg_addr> [<val>] read/write MDIO register\n" 101 "\tmemdump cm|tx|rx <addr> <len> dump a mem range\n" 102 "\tmeminfo show memory info\n" 103 "\tmtus [<mtu0>...<mtuN>] read/write MTU table\n" 104 "\tpktsched port <idx> <min> <max> set TX port scheduler params\n" 105 "\tpktsched tunnelq <idx> <max>\n" 106 "\t <binding> set TX tunnelq scheduler params\n" 107 "\tpktsched tx <idx>\n" 108 "\t [<param> <val>] ... set Tx HW scheduler\n" 109 "\tpm [<TX page spec> <RX page spec>] read/write PM config\n" 110 "\tproto read proto SRAM\n" 111 "\tqset read qset parameters\n" 112 "\tqsets read # of qsets\n" 113 "\treg <address>[=<val>] read/write register\n" 114 "\tregdump [<module>] dump registers\n" 115 "\ttcamdump <address> <count> show TCAM contents\n" 116 "\ttcb <index> read TCB\n" 117 "\ttrace tx|rx|all on|off [not]\n" 118 "\t [<param> <val>[:<mask>]] ... write trace parameters\n" 119 ); 120 exit(fp == stderr ? 1 : 0); 121} 122 123static int 124doit(const char *iff_name, unsigned long cmd, void *data) 125{ 126 static int fd = 0; 127 128 if (fd == 0) { 129 char buf[64]; 130 snprintf(buf, 64, "/dev/%s", iff_name); 131 132 if ((fd = open(buf, O_RDWR)) < 0) 133 return -1; 134 } 135 136 return ioctl(fd, cmd, data) < 0 ? -1 : 0; 137} 138 139static int get_int_arg(const char *s, uint32_t *valp) 140{ 141 char *p; 142 143 *valp = strtoul(s, &p, 0); 144 if (*p) { 145 warnx("bad parameter \"%s\"", s); 146 return -1; 147 } 148 return 0; 149} 150 151static uint32_t 152read_reg(const char *iff_name, uint32_t addr) 153{ 154 struct ch_reg reg; 155 156 reg.addr = addr; 157 158 if (doit(iff_name, CHELSIO_GETREG, ®) < 0) 159 err(1, "register read"); 160 return reg.val; 161} 162 163static void 164write_reg(const char *iff_name, uint32_t addr, uint32_t val) 165{ 166 struct ch_reg ch_reg; 167 168 ch_reg.addr = addr; 169 ch_reg.val = val; 170 171 if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0) 172 err(1, "register write"); 173} 174 175static int register_io(int argc, char *argv[], int start_arg, 176 const char *iff_name) 177{ 178 char *p; 179 uint32_t addr, val = 0, write = 0; 180 181 if (argc != start_arg + 1) return -1; 182 183 addr = strtoul(argv[start_arg], &p, 0); 184 if (p == argv[start_arg]) return -1; 185 if (*p == '=' && p[1]) { 186 val = strtoul(p + 1, &p, 0); 187 write = 1; 188 } 189 if (*p) { 190 warnx("bad parameter \"%s\"", argv[start_arg]); 191 return -1; 192 } 193 194 if (write) 195 write_reg(iff_name, addr, val); 196 else { 197 val = read_reg(iff_name, addr); 198 printf("%#x [%u]\n", val, val); 199 } 200 return 0; 201} 202 203static int mdio_io(int argc, char *argv[], int start_arg, const char *iff_name) 204{ 205 struct ifreq ifr; 206 struct ch_mii_data p; 207 unsigned int cmd, phy_addr, reg, mmd, val; 208 209 if (argc == start_arg + 3) 210 cmd = CHELSIO_GET_MIIREG; 211 else if (argc == start_arg + 4) 212 cmd = CHELSIO_SET_MIIREG; 213 else 214 return -1; 215 216 if (get_int_arg(argv[start_arg], &phy_addr) || 217 get_int_arg(argv[start_arg + 1], &mmd) || 218 get_int_arg(argv[start_arg + 2], ®) || 219 (cmd == CHELSIO_SET_MIIREG && get_int_arg(argv[start_arg + 3], &val))) 220 return -1; 221 222 p.phy_id = phy_addr | (mmd << 8); 223 p.reg_num = reg; 224 p.val_in = val; 225 226 if (doit(iff_name, cmd, &p) < 0) 227 err(1, "MDIO %s", cmd == CHELSIO_GET_MIIREG ? "read" : "write"); 228 if (cmd == CHELSIO_GET_MIIREG) 229 printf("%#x [%u]\n", p.val_out, p.val_out); 230 return 0; 231} 232 233static inline uint32_t xtract(uint32_t val, int shift, int len) 234{ 235 return (val >> shift) & ((1 << len) - 1); 236} 237 238static int dump_block_regs(const struct reg_info *reg_array, uint32_t *regs) 239{ 240 uint32_t reg_val = 0; // silence compiler warning 241 242 for ( ; reg_array->name; ++reg_array) 243 if (!reg_array->len) { 244 reg_val = regs[reg_array->addr / 4]; 245 printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr, 246 reg_array->name, reg_val, reg_val); 247 } else { 248 uint32_t v = xtract(reg_val, reg_array->addr, 249 reg_array->len); 250 251 printf(" %-40s %#-10x [%u]\n", reg_array->name, 252 v, v); 253 } 254 return 1; 255} 256 257static int dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs) 258{ 259 int match = 0; 260 char *block_name = NULL; 261 262 if (argc == start_arg + 1) 263 block_name = argv[start_arg]; 264 else if (argc != start_arg) 265 return -1; 266 267 if (!block_name || !strcmp(block_name, "sge")) 268 match += dump_block_regs(sge_regs, regs); 269 if (!block_name || !strcmp(block_name, "mc3")) 270 match += dump_block_regs(mc3_regs, regs); 271 if (!block_name || !strcmp(block_name, "mc4")) 272 match += dump_block_regs(mc4_regs, regs); 273 if (!block_name || !strcmp(block_name, "tpi")) 274 match += dump_block_regs(tpi_regs, regs); 275 if (!block_name || !strcmp(block_name, "tp")) 276 match += dump_block_regs(tp_regs, regs); 277 if (!block_name || !strcmp(block_name, "rat")) 278 match += dump_block_regs(rat_regs, regs); 279 if (!block_name || !strcmp(block_name, "cspi")) 280 match += dump_block_regs(cspi_regs, regs); 281 if (!block_name || !strcmp(block_name, "espi")) 282 match += dump_block_regs(espi_regs, regs); 283 if (!block_name || !strcmp(block_name, "ulp")) 284 match += dump_block_regs(ulp_regs, regs); 285 if (!block_name || !strcmp(block_name, "pl")) 286 match += dump_block_regs(pl_regs, regs); 287 if (!block_name || !strcmp(block_name, "mc5")) 288 match += dump_block_regs(mc5_regs, regs); 289 if (!match) 290 errx(1, "unknown block \"%s\"", block_name); 291 return 0; 292} 293 294#if defined(CONFIG_T3_REGS) 295static int dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, 296 int is_pcie) 297{ 298 int match = 0; 299 char *block_name = NULL; 300 301 if (argc == start_arg + 1) 302 block_name = argv[start_arg]; 303 else if (argc != start_arg) 304 return -1; 305 306 if (!block_name || !strcmp(block_name, "sge")) 307 match += dump_block_regs(sge3_regs, regs); 308 if (!block_name || !strcmp(block_name, "pci")) 309 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs, 310 regs); 311 if (!block_name || !strcmp(block_name, "t3dbg")) 312 match += dump_block_regs(t3dbg_regs, regs); 313 if (!block_name || !strcmp(block_name, "pmrx")) 314 match += dump_block_regs(mc7_pmrx_regs, regs); 315 if (!block_name || !strcmp(block_name, "pmtx")) 316 match += dump_block_regs(mc7_pmtx_regs, regs); 317 if (!block_name || !strcmp(block_name, "cm")) 318 match += dump_block_regs(mc7_cm_regs, regs); 319 if (!block_name || !strcmp(block_name, "cim")) 320 match += dump_block_regs(cim_regs, regs); 321 if (!block_name || !strcmp(block_name, "tp")) 322 match += dump_block_regs(tp1_regs, regs); 323 if (!block_name || !strcmp(block_name, "ulp_rx")) 324 match += dump_block_regs(ulp2_rx_regs, regs); 325 if (!block_name || !strcmp(block_name, "ulp_tx")) 326 match += dump_block_regs(ulp2_tx_regs, regs); 327 if (!block_name || !strcmp(block_name, "pmrx")) 328 match += dump_block_regs(pm1_rx_regs, regs); 329 if (!block_name || !strcmp(block_name, "pmtx")) 330 match += dump_block_regs(pm1_tx_regs, regs); 331 if (!block_name || !strcmp(block_name, "mps")) 332 match += dump_block_regs(mps0_regs, regs); 333 if (!block_name || !strcmp(block_name, "cplsw")) 334 match += dump_block_regs(cpl_switch_regs, regs); 335 if (!block_name || !strcmp(block_name, "smb")) 336 match += dump_block_regs(smb0_regs, regs); 337 if (!block_name || !strcmp(block_name, "i2c")) 338 match += dump_block_regs(i2cm0_regs, regs); 339 if (!block_name || !strcmp(block_name, "mi1")) 340 match += dump_block_regs(mi1_regs, regs); 341 if (!block_name || !strcmp(block_name, "sf")) 342 match += dump_block_regs(sf1_regs, regs); 343 if (!block_name || !strcmp(block_name, "pl")) 344 match += dump_block_regs(pl3_regs, regs); 345 if (!block_name || !strcmp(block_name, "mc5")) 346 match += dump_block_regs(mc5a_regs, regs); 347 if (!block_name || !strcmp(block_name, "xgmac0")) 348 match += dump_block_regs(xgmac0_0_regs, regs); 349 if (!block_name || !strcmp(block_name, "xgmac1")) 350 match += dump_block_regs(xgmac0_1_regs, regs); 351 if (!match) 352 errx(1, "unknown block \"%s\"", block_name); 353 return 0; 354} 355 356static int dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs, 357 int is_pcie) 358{ 359 int match = 0; 360 char *block_name = NULL; 361 362 if (argc == start_arg + 1) 363 block_name = argv[start_arg]; 364 else if (argc != start_arg) 365 return -1; 366 367 if (!block_name || !strcmp(block_name, "sge")) 368 match += dump_block_regs(t3b_sge3_regs, regs); 369 if (!block_name || !strcmp(block_name, "pci")) 370 match += dump_block_regs(is_pcie ? t3b_pcie0_regs : 371 t3b_pcix1_regs, regs); 372 if (!block_name || !strcmp(block_name, "t3dbg")) 373 match += dump_block_regs(t3b_t3dbg_regs, regs); 374 if (!block_name || !strcmp(block_name, "pmrx")) 375 match += dump_block_regs(t3b_mc7_pmrx_regs, regs); 376 if (!block_name || !strcmp(block_name, "pmtx")) 377 match += dump_block_regs(t3b_mc7_pmtx_regs, regs); 378 if (!block_name || !strcmp(block_name, "cm")) 379 match += dump_block_regs(t3b_mc7_cm_regs, regs); 380 if (!block_name || !strcmp(block_name, "cim")) 381 match += dump_block_regs(t3b_cim_regs, regs); 382 if (!block_name || !strcmp(block_name, "tp")) 383 match += dump_block_regs(t3b_tp1_regs, regs); 384 if (!block_name || !strcmp(block_name, "ulp_rx")) 385 match += dump_block_regs(t3b_ulp2_rx_regs, regs); 386 if (!block_name || !strcmp(block_name, "ulp_tx")) 387 match += dump_block_regs(t3b_ulp2_tx_regs, regs); 388 if (!block_name || !strcmp(block_name, "pmrx")) 389 match += dump_block_regs(t3b_pm1_rx_regs, regs); 390 if (!block_name || !strcmp(block_name, "pmtx")) 391 match += dump_block_regs(t3b_pm1_tx_regs, regs); 392 if (!block_name || !strcmp(block_name, "mps")) 393 match += dump_block_regs(t3b_mps0_regs, regs); 394 if (!block_name || !strcmp(block_name, "cplsw")) 395 match += dump_block_regs(t3b_cpl_switch_regs, regs); 396 if (!block_name || !strcmp(block_name, "smb")) 397 match += dump_block_regs(t3b_smb0_regs, regs); 398 if (!block_name || !strcmp(block_name, "i2c")) 399 match += dump_block_regs(t3b_i2cm0_regs, regs); 400 if (!block_name || !strcmp(block_name, "mi1")) 401 match += dump_block_regs(t3b_mi1_regs, regs); 402 if (!block_name || !strcmp(block_name, "sf")) 403 match += dump_block_regs(t3b_sf1_regs, regs); 404 if (!block_name || !strcmp(block_name, "pl")) 405 match += dump_block_regs(t3b_pl3_regs, regs); 406 if (!block_name || !strcmp(block_name, "mc5")) 407 match += dump_block_regs(t3b_mc5a_regs, regs); 408 if (!block_name || !strcmp(block_name, "xgmac0")) 409 match += dump_block_regs(t3b_xgmac0_0_regs, regs); 410 if (!block_name || !strcmp(block_name, "xgmac1")) 411 match += dump_block_regs(t3b_xgmac0_1_regs, regs); 412 if (!match) 413 errx(1, "unknown block \"%s\"", block_name); 414 return 0; 415} 416 417static int dump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs, 418 int is_pcie) 419{ 420 int match = 0; 421 char *block_name = NULL; 422 423 if (argc == start_arg + 1) 424 block_name = argv[start_arg]; 425 else if (argc != start_arg) 426 return -1; 427 428 if (!block_name || !strcmp(block_name, "sge")) 429 match += dump_block_regs(t3c_sge3_regs, regs); 430 if (!block_name || !strcmp(block_name, "pci")) 431 match += dump_block_regs(is_pcie ? t3c_pcie0_regs : 432 t3c_pcix1_regs, regs); 433 if (!block_name || !strcmp(block_name, "t3dbg")) 434 match += dump_block_regs(t3c_t3dbg_regs, regs); 435 if (!block_name || !strcmp(block_name, "pmrx")) 436 match += dump_block_regs(t3c_mc7_pmrx_regs, regs); 437 if (!block_name || !strcmp(block_name, "pmtx")) 438 match += dump_block_regs(t3c_mc7_pmtx_regs, regs); 439 if (!block_name || !strcmp(block_name, "cm")) 440 match += dump_block_regs(t3c_mc7_cm_regs, regs); 441 if (!block_name || !strcmp(block_name, "cim")) 442 match += dump_block_regs(t3c_cim_regs, regs); 443 if (!block_name || !strcmp(block_name, "tp")) 444 match += dump_block_regs(t3c_tp1_regs, regs); 445 if (!block_name || !strcmp(block_name, "ulp_rx")) 446 match += dump_block_regs(t3c_ulp2_rx_regs, regs); 447 if (!block_name || !strcmp(block_name, "ulp_tx")) 448 match += dump_block_regs(t3c_ulp2_tx_regs, regs); 449 if (!block_name || !strcmp(block_name, "pmrx")) 450 match += dump_block_regs(t3c_pm1_rx_regs, regs); 451 if (!block_name || !strcmp(block_name, "pmtx")) 452 match += dump_block_regs(t3c_pm1_tx_regs, regs); 453 if (!block_name || !strcmp(block_name, "mps")) 454 match += dump_block_regs(t3c_mps0_regs, regs); 455 if (!block_name || !strcmp(block_name, "cplsw")) 456 match += dump_block_regs(t3c_cpl_switch_regs, regs); 457 if (!block_name || !strcmp(block_name, "smb")) 458 match += dump_block_regs(t3c_smb0_regs, regs); 459 if (!block_name || !strcmp(block_name, "i2c")) 460 match += dump_block_regs(t3c_i2cm0_regs, regs); 461 if (!block_name || !strcmp(block_name, "mi1")) 462 match += dump_block_regs(t3c_mi1_regs, regs); 463 if (!block_name || !strcmp(block_name, "sf")) 464 match += dump_block_regs(t3c_sf1_regs, regs); 465 if (!block_name || !strcmp(block_name, "pl")) 466 match += dump_block_regs(t3c_pl3_regs, regs); 467 if (!block_name || !strcmp(block_name, "mc5")) 468 match += dump_block_regs(t3c_mc5a_regs, regs); 469 if (!block_name || !strcmp(block_name, "xgmac0")) 470 match += dump_block_regs(t3c_xgmac0_0_regs, regs); 471 if (!block_name || !strcmp(block_name, "xgmac1")) 472 match += dump_block_regs(t3c_xgmac0_1_regs, regs); 473 if (!match) 474 errx(1, "unknown block \"%s\"", block_name); 475 return 0; 476} 477#endif 478 479static int 480dump_regs(int argc, char *argv[], int start_arg, const char *iff_name) 481{ 482 int i, vers, revision, is_pcie; 483 struct ch_ifconf_regs regs; 484 485 regs.len = REGDUMP_SIZE; 486 487 /* XXX: This is never freed. Looks like we don't care. */ 488 if ((regs.data = malloc(regs.len)) == NULL) 489 err(1, "can't malloc"); 490 491 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s)) 492 err(1, "can't read registers"); 493 494 vers = regs.version & 0x3ff; 495 revision = (regs.version >> 10) & 0x3f; 496 is_pcie = (regs.version & 0x80000000) != 0; 497 498 if (vers <= 2) 499 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data); 500#if defined(CONFIG_T3_REGS) 501 if (vers == 3) { 502 if (revision == 0) 503 return dump_regs_t3(argc, argv, start_arg, 504 (uint32_t *)regs.data, is_pcie); 505 if (revision == 2 || revision == 3) 506 return dump_regs_t3b(argc, argv, start_arg, 507 (uint32_t *)regs.data, is_pcie); 508 if (revision == 4) 509 return dump_regs_t3c(argc, argv, start_arg, 510 (uint32_t *)regs.data, is_pcie); 511 } 512#endif 513 errx(1, "unknown card type %d.%d", vers, revision); 514 return 0; 515} 516 517static int t3_meminfo(const uint32_t *regs) 518{ 519 enum { 520 SG_EGR_CNTX_BADDR = 0x58, 521 SG_CQ_CONTEXT_BADDR = 0x6c, 522 CIM_SDRAM_BASE_ADDR = 0x28c, 523 CIM_SDRAM_ADDR_SIZE = 0x290, 524 TP_CMM_MM_BASE = 0x314, 525 TP_CMM_TIMER_BASE = 0x318, 526 TP_CMM_MM_RX_FLST_BASE = 0x460, 527 TP_CMM_MM_TX_FLST_BASE = 0x464, 528 TP_CMM_MM_PS_FLST_BASE = 0x468, 529 ULPRX_ISCSI_LLIMIT = 0x50c, 530 ULPRX_ISCSI_ULIMIT = 0x510, 531 ULPRX_TDDP_LLIMIT = 0x51c, 532 ULPRX_TDDP_ULIMIT = 0x520, 533 ULPRX_STAG_LLIMIT = 0x52c, 534 ULPRX_STAG_ULIMIT = 0x530, 535 ULPRX_RQ_LLIMIT = 0x534, 536 ULPRX_RQ_ULIMIT = 0x538, 537 ULPRX_PBL_LLIMIT = 0x53c, 538 ULPRX_PBL_ULIMIT = 0x540, 539 }; 540 541 unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4], 542 cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4], 543 timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff, 544 pstructs = regs[TP_CMM_MM_BASE / 4], 545 pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4], 546 rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4], 547 tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4], 548 cim_base = regs[CIM_SDRAM_BASE_ADDR / 4], 549 cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4]; 550 unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4], 551 iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4], 552 tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4], 553 tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4], 554 stag_ll = regs[ULPRX_STAG_LLIMIT / 4], 555 stag_ul = regs[ULPRX_STAG_ULIMIT / 4], 556 rq_ll = regs[ULPRX_RQ_LLIMIT / 4], 557 rq_ul = regs[ULPRX_RQ_ULIMIT / 4], 558 pbl_ll = regs[ULPRX_PBL_LLIMIT / 4], 559 pbl_ul = regs[ULPRX_PBL_ULIMIT / 4]; 560 561 printf("CM memory map:\n"); 562 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1, 563 egr_cntxt); 564 printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt, 565 cq_cntxt - 1, cq_cntxt - egr_cntxt); 566 printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt, 567 timers - 1, timers - cq_cntxt); 568 printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers, 569 pstructs - 1, pstructs - timers); 570 printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs, 571 pstruct_fl - 1, pstruct_fl - pstructs); 572 printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl, 573 rx_fl - 1, rx_fl - pstruct_fl); 574 printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1, 575 tx_fl - rx_fl); 576 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1, 577 cim_base - tx_fl); 578 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base, 579 cim_base + cim_size - 1, cim_size); 580 581 printf("\nPMRX memory map:\n"); 582 printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul, 583 iscsi_ul - iscsi_ll + 1); 584 printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul, 585 tddp_ul - tddp_ll + 1); 586 printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul, 587 stag_ul - stag_ll + 1); 588 printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul, 589 rq_ul - rq_ll + 1); 590 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul, 591 pbl_ul - pbl_ll + 1); 592 return 0; 593} 594 595static int meminfo(int argc, char *argv[], int start_arg, const char *iff_name) 596{ 597 int vers; 598 struct ch_ifconf_regs regs; 599 600 regs.len = REGDUMP_SIZE; 601 if ((regs.data = malloc(regs.len)) == NULL) 602 err(1, "can't malloc"); 603 604 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s)) 605 err(1, "can't read registers"); 606 607 vers = regs.version & 0x3ff; 608 if (vers == 3) 609 return t3_meminfo((uint32_t *)regs.data); 610 611 errx(1, "unknown card type %d", vers); 612 return 0; 613} 614 615static int mtu_tab_op(int argc, char *argv[], int start_arg, 616 const char *iff_name) 617{ 618 struct ch_mtus m; 619 int i; 620 621 if (argc == start_arg) { 622 if (doit(iff_name, CHELSIO_GETMTUTAB, &m) < 0) 623 err(1, "get MTU table"); 624 for (i = 0; i < m.nmtus; ++i) 625 printf("%u ", m.mtus[i]); 626 printf("\n"); 627 } else if (argc <= start_arg + NMTUS) { 628 m.nmtus = argc - start_arg; 629 630 for (i = 0; i < m.nmtus; ++i) { 631 char *p; 632 unsigned long mt = strtoul(argv[start_arg + i], &p, 0); 633 634 if (*p || mt > 9600) { 635 warnx("bad parameter \"%s\"", 636 argv[start_arg + i]); 637 return -1; 638 } 639 if (i && mt < m.mtus[i - 1]) 640 errx(1, "MTUs must be in ascending order"); 641 m.mtus[i] = mt; 642 } 643 if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0) 644 err(1, "set MTU table"); 645 } else 646 return -1; 647 648 return 0; 649} 650 651#ifdef CHELSIO_INTERNAL 652static void show_egress_cntxt(uint32_t data[]) 653{ 654 printf("credits: %u\n", data[0] & 0x7fff); 655 printf("GTS: %u\n", (data[0] >> 15) & 1); 656 printf("index: %u\n", data[0] >> 16); 657 printf("queue size: %u\n", data[1] & 0xffff); 658 printf("base address: 0x%llx\n", 659 ((data[1] >> 16) | ((uint64_t)data[2] << 16) | 660 (((uint64_t)data[3] & 0xf) << 48)) << 12); 661 printf("rsp queue #: %u\n", (data[3] >> 4) & 7); 662 printf("cmd queue #: %u\n", (data[3] >> 7) & 1); 663 printf("TUN: %u\n", (data[3] >> 8) & 1); 664 printf("TOE: %u\n", (data[3] >> 9) & 1); 665 printf("generation: %u\n", (data[3] >> 10) & 1); 666 printf("uP token: %u\n", (data[3] >> 11) & 0xfffff); 667 printf("valid: %u\n", (data[3] >> 31) & 1); 668} 669 670static void show_fl_cntxt(uint32_t data[]) 671{ 672 printf("base address: 0x%llx\n", 673 ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12); 674 printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12)); 675 printf("queue size: %u\n", (data[2] >> 4) & 0xffff); 676 printf("generation: %u\n", (data[2] >> 20) & 1); 677 printf("entry size: %u\n", 678 (data[2] >> 21) | (data[3] & 0x1fffff) << 11); 679 printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff); 680 printf("GTS: %u\n", (data[3] >> 31) & 1); 681} 682 683static void show_response_cntxt(uint32_t data[]) 684{ 685 printf("index: %u\n", data[0] & 0xffff); 686 printf("size: %u\n", data[0] >> 16); 687 printf("base address: 0x%llx\n", 688 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12); 689 printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f); 690 printf("intr enable: %u\n", (data[2] >> 26) & 1); 691 printf("intr armed: %u\n", (data[2] >> 27) & 1); 692 printf("generation: %u\n", (data[2] >> 28) & 1); 693 printf("CQ mode: %u\n", (data[2] >> 31) & 1); 694 printf("FL threshold: %u\n", data[3]); 695} 696 697static void show_cq_cntxt(uint32_t data[]) 698{ 699 printf("index: %u\n", data[0] & 0xffff); 700 printf("size: %u\n", data[0] >> 16); 701 printf("base address: 0x%llx\n", 702 ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12); 703 printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f); 704 printf("AN: %u\n", (data[2] >> 26) & 1); 705 printf("armed: %u\n", (data[2] >> 27) & 1); 706 printf("ANS: %u\n", (data[2] >> 28) & 1); 707 printf("generation: %u\n", (data[2] >> 29) & 1); 708 printf("overflow mode: %u\n", (data[2] >> 31) & 1); 709 printf("credits: %u\n", data[3] & 0xffff); 710 printf("credit threshold: %u\n", data[3] >> 16); 711} 712 713static int get_sge_context(int argc, char *argv[], int start_arg, 714 const char *iff_name) 715{ 716 struct ch_cntxt ctx; 717 718 if (argc != start_arg + 2) return -1; 719 720 if (!strcmp(argv[start_arg], "egress")) 721 ctx.cntxt_type = CNTXT_TYPE_EGRESS; 722 else if (!strcmp(argv[start_arg], "fl")) 723 ctx.cntxt_type = CNTXT_TYPE_FL; 724 else if (!strcmp(argv[start_arg], "response")) 725 ctx.cntxt_type = CNTXT_TYPE_RSP; 726 else if (!strcmp(argv[start_arg], "cq")) 727 ctx.cntxt_type = CNTXT_TYPE_CQ; 728 else { 729 warnx("unknown context type \"%s\"; known types are egress, " 730 "fl, cq, and response", argv[start_arg]); 731 return -1; 732 } 733 734 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id)) 735 return -1; 736 737 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0) 738 err(1, "get SGE context"); 739 740 if (!strcmp(argv[start_arg], "egress")) 741 show_egress_cntxt(ctx.data); 742 else if (!strcmp(argv[start_arg], "fl")) 743 show_fl_cntxt(ctx.data); 744 else if (!strcmp(argv[start_arg], "response")) 745 show_response_cntxt(ctx.data); 746 else if (!strcmp(argv[start_arg], "cq")) 747 show_cq_cntxt(ctx.data); 748 return 0; 749} 750 751#define ntohll(x) be64toh((x)) 752 753static int get_sge_desc(int argc, char *argv[], int start_arg, 754 const char *iff_name) 755{ 756 uint64_t *p, wr_hdr; 757 unsigned int n = 1, qset, qnum; 758 struct ch_desc desc; 759 760 if (argc != start_arg + 3 && argc != start_arg + 4) 761 return -1; 762 763 if (get_int_arg(argv[start_arg], &qset) || 764 get_int_arg(argv[start_arg + 1], &qnum) || 765 get_int_arg(argv[start_arg + 2], &desc.idx)) 766 return -1; 767 768 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n)) 769 return -1; 770 771 if (qnum > 5) 772 errx(1, "invalid queue number %d, range is 0..5", qnum); 773 774 desc.queue_num = qset * 6 + qnum; 775 776 for (; n--; desc.idx++) { 777 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0) 778 err(1, "get SGE descriptor"); 779 780 p = (uint64_t *)desc.data; 781 wr_hdr = ntohll(*p); 782 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n", 783 desc.idx, (unsigned int)(wr_hdr >> 56), 784 ((unsigned int)wr_hdr >> 8) & 0xfffff, 785 ((wr_hdr >> 55) & 1) ? "SOP, " : "", 786 ((wr_hdr >> 54) & 1) ? "EOP, " : "", 787 ((wr_hdr >> 53) & 1) ? "COMPL, " : "", 788 ((wr_hdr >> 52) & 1) ? "SGL, " : "", 789 (unsigned int)wr_hdr & 0xff); 790 791 for (; desc.size; p++, desc.size -= sizeof(uint64_t)) 792 printf("%016" PRIx64 "%c", ntohll(*p), 793 desc.size % 32 == 8 ? '\n' : ' '); 794 } 795 return 0; 796} 797#endif 798 799static int get_tcb2(int argc, char *argv[], int start_arg, const char *iff_name) 800{ 801 uint64_t *d; 802 unsigned int i; 803 unsigned int tcb_idx; 804 struct ch_mem_range mr; 805 806 if (argc != start_arg + 1) 807 return -1; 808 809 if (get_int_arg(argv[start_arg], &tcb_idx)) 810 return -1; 811 812 mr.buf = calloc(1, TCB_SIZE); 813 if (!mr.buf) 814 err(1, "get TCB"); 815 816 mr.mem_id = MEM_CM; 817 mr.addr = tcb_idx * TCB_SIZE; 818 mr.len = TCB_SIZE; 819 820 if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0) 821 err(1, "get TCB"); 822 823 for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) { 824 printf("%2u:", i); 825 printf(" %08x %08x %08x %08x", (uint32_t)d[1], 826 (uint32_t)(d[1] >> 32), (uint32_t)d[0], 827 (uint32_t)(d[0] >> 32)); 828 d += 2; 829 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1], 830 (uint32_t)(d[1] >> 32), (uint32_t)d[0], 831 (uint32_t)(d[0] >> 32)); 832 d += 2; 833 } 834 free(mr.buf); 835 return 0; 836} 837 838static int get_pm_page_spec(const char *s, unsigned int *page_size, 839 unsigned int *num_pages) 840{ 841 char *p; 842 unsigned long val; 843 844 val = strtoul(s, &p, 0); 845 if (p == s) return -1; 846 if (*p == 'x' && p[1]) { 847 *num_pages = val; 848 *page_size = strtoul(p + 1, &p, 0); 849 } else { 850 *num_pages = -1; 851 *page_size = val; 852 } 853 *page_size <<= 10; // KB -> bytes 854 return *p; 855} 856 857static int conf_pm(int argc, char *argv[], int start_arg, const char *iff_name) 858{ 859 struct ch_pm pm; 860 861 if (argc == start_arg) { 862 if (doit(iff_name, CHELSIO_GET_PM, &pm) < 0) 863 err(1, "read pm config"); 864 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n", 865 pm.tx_num_pg, pm.tx_pg_sz >> 10, pm.rx_num_pg, 866 pm.rx_pg_sz >> 10, pm.pm_total >> 10); 867 return 0; 868 } 869 870 if (argc != start_arg + 2) return -1; 871 872 if (get_pm_page_spec(argv[start_arg], &pm.tx_pg_sz, &pm.tx_num_pg)) { 873 warnx("bad parameter \"%s\"", argv[start_arg]); 874 return -1; 875 } 876 if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz, 877 &pm.rx_num_pg)) { 878 warnx("bad parameter \"%s\"", argv[start_arg + 1]); 879 return -1; 880 } 881 if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0) 882 err(1, "pm config"); 883 return 0; 884} 885 886#ifdef CHELSIO_INTERNAL 887static int dump_tcam(int argc, char *argv[], int start_arg, 888 const char *iff_name) 889{ 890 unsigned int nwords; 891 struct ch_tcam_word op; 892 893 if (argc != start_arg + 2) return -1; 894 895 if (get_int_arg(argv[start_arg], &op.addr) || 896 get_int_arg(argv[start_arg + 1], &nwords)) 897 return -1; 898 899 while (nwords--) { 900 if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0) 901 err(1, "tcam dump"); 902 903 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr, 904 op.buf[0] & 0xff, op.buf[1], op.buf[2]); 905 op.addr++; 906 } 907 return 0; 908} 909 910static void hexdump_8b(unsigned int start, uint64_t *data, unsigned int len) 911{ 912 int i; 913 914 while (len) { 915 printf("0x%08x:", start); 916 for (i = 0; i < 4 && len; ++i, --len) 917 printf(" %016llx", (unsigned long long)*data++); 918 printf("\n"); 919 start += 32; 920 } 921} 922 923static int dump_mc7(int argc, char *argv[], int start_arg, 924 const char *iff_name) 925{ 926 struct ch_mem_range mem; 927 unsigned int mem_id, addr, len; 928 929 if (argc != start_arg + 3) return -1; 930 931 if (!strcmp(argv[start_arg], "cm")) 932 mem_id = MEM_CM; 933 else if (!strcmp(argv[start_arg], "rx")) 934 mem_id = MEM_PMRX; 935 else if (!strcmp(argv[start_arg], "tx")) 936 mem_id = MEM_PMTX; 937 else 938 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\"," 939 " or \"rx\"", argv[start_arg]); 940 941 if (get_int_arg(argv[start_arg + 1], &addr) || 942 get_int_arg(argv[start_arg + 2], &len)) 943 return -1; 944 945 mem.buf = malloc(len); 946 if (!mem.buf) 947 err(1, "memory dump"); 948 949 mem.mem_id = mem_id; 950 mem.addr = addr; 951 mem.len = len; 952 953 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0) 954 err(1, "memory dump"); 955 956 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3); 957 free(mem.buf); 958 return 0; 959} 960#endif 961 962/* Max FW size is 32K including version, +4 bytes for the checksum. */ 963#define MAX_FW_IMAGE_SIZE (64 * 1024) 964 965static int load_fw(int argc, char *argv[], int start_arg, const char *iff_name) 966{ 967 int fd, len; 968 struct ch_mem_range op; 969 const char *fname = argv[start_arg]; 970 971 if (argc != start_arg + 1) return -1; 972 973 fd = open(fname, O_RDONLY); 974 if (fd < 0) 975 err(1, "load firmware"); 976 977 bzero(&op, sizeof(op)); 978 op.buf = malloc(MAX_FW_IMAGE_SIZE + 1); 979 if (!op.buf) 980 err(1, "load firmware"); 981 982 op.len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1); 983 if (op.len < 0) 984 err(1, "load firmware"); 985 if (op.len > MAX_FW_IMAGE_SIZE) 986 errx(1, "FW image too large"); 987 988 if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0) 989 err(1, "load firmware"); 990 return 0; 991} 992 993/* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */ 994#define MAX_BOOT_IMAGE_SIZE (0xff * 512) 995 996static int load_boot(int argc, char *argv[], 997 int start_arg, const char *iff_name) 998{ 999 int fd, len; 1000 struct ch_mem_range op; 1001 const char *fname = argv[start_arg]; 1002 1003 if (argc != start_arg + 1) return -1; 1004 1005 fd = open(fname, O_RDONLY); 1006 if (fd < 0) 1007 err(1, "load boot image"); 1008 1009 op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1); 1010 if (!op.buf) 1011 err(1, "load boot image"); 1012 1013 len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1); 1014 if (len < 0) 1015 err(1, "load boot image"); 1016 if (len > MAX_BOOT_IMAGE_SIZE) 1017 errx(1, "boot image too large"); 1018 1019 op.len = len; 1020 1021 if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0) 1022 err(1, "load boot image"); 1023 1024 return 0; 1025} 1026 1027static int dump_proto_sram(const char *iff_name) 1028{ 1029 int i, j; 1030 uint8_t buf[PROTO_SRAM_SIZE]; 1031 struct ch_eeprom ee; 1032 uint8_t *p = buf; 1033 1034 bzero(buf, sizeof(buf)); 1035 ee.offset = PROTO_SRAM_EEPROM_ADDR; 1036 ee.data = p; 1037 ee.len = sizeof(buf); 1038 if (doit(iff_name, CHELSIO_GET_EEPROM, &ee)) 1039 err(1, "show protocol sram"); 1040 1041 for (i = 0; i < PROTO_SRAM_LINES; i++) { 1042 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) { 1043 int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j; 1044 uint8_t nibble = p[nibble_idx / 2]; 1045 1046 if (nibble_idx & 1) 1047 nibble >>= 4; 1048 else 1049 nibble &= 0xf; 1050 printf("%x", nibble); 1051 } 1052 putchar('\n'); 1053 } 1054 return 0; 1055} 1056 1057static int proto_sram_op(int argc, char *argv[], int start_arg, 1058 const char *iff_name) 1059{ 1060 if (argc == start_arg) 1061 return dump_proto_sram(iff_name); 1062 return -1; 1063} 1064 1065static int dump_qset_params(const char *iff_name) 1066{ 1067 struct ch_qset_params qp; 1068 1069 qp.qset_idx = 0; 1070 1071 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) { 1072 if (!qp.qset_idx) 1073 printf("Qset TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1" 1074 " Cong Lat IRQ\n"); 1075 printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n", 1076 qp.qnum, 1077 qp.txq_size[0], qp.txq_size[1], qp.txq_size[2], 1078 qp.rspq_size, qp.fl_size[0], qp.fl_size[1], 1079 qp.cong_thres, qp.intr_lat, qp.vector); 1080 qp.qset_idx++; 1081 } 1082 if (!qp.qset_idx || (errno && errno != EINVAL)) 1083 err(1, "get qset parameters"); 1084 return 0; 1085} 1086 1087static int qset_config(int argc, char *argv[], int start_arg, 1088 const char *iff_name) 1089{ 1090 struct ch_qset_params qp; 1091 1092 if (argc == start_arg) 1093 return dump_qset_params(iff_name); 1094 1095 return -1; 1096} 1097 1098static int qset_num_config(int argc, char *argv[], int start_arg, 1099 const char *iff_name) 1100{ 1101 struct ch_reg reg; 1102 1103 if (argc == start_arg) { 1104 if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0) 1105 err(1, "get qsets"); 1106 printf("%u\n", reg.val); 1107 return 0; 1108 } 1109 1110 return -1; 1111} 1112 1113/* 1114 * Parse a string containing an IP address with an optional network prefix. 1115 */ 1116static int parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask) 1117{ 1118 char *p, *slash; 1119 struct in_addr ia; 1120 1121 *mask = 0xffffffffU; 1122 slash = strchr(s, '/'); 1123 if (slash) 1124 *slash = 0; 1125 if (!inet_aton(s, &ia)) { 1126 if (slash) 1127 *slash = '/'; 1128 *addr = 0; 1129 return -1; 1130 } 1131 *addr = ntohl(ia.s_addr); 1132 if (slash) { 1133 unsigned int prefix = strtoul(slash + 1, &p, 10); 1134 1135 *slash = '/'; 1136 if (p == slash + 1 || *p || prefix > 32) 1137 return -1; 1138 *mask <<= (32 - prefix); 1139 } 1140 return 0; 1141} 1142 1143/* 1144 * Parse a string containing a value and an optional colon separated mask. 1145 */ 1146static int parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask) 1147{ 1148 char *p; 1149 1150 *mask = 0xffffffffU; 1151 *val = strtoul(s, &p, 0); 1152 if (p == s) 1153 return -1; 1154 if (*p == ':' && p[1]) 1155 *mask = strtoul(p + 1, &p, 0); 1156 return *p ? -1 : 0; 1157} 1158 1159static int parse_trace_param(const char *s, uint32_t *val, uint32_t *mask) 1160{ 1161 return strchr(s, '.') ? parse_ipaddr(s, val, mask) : 1162 parse_val_mask_param(s, val, mask); 1163} 1164 1165static int trace_config(int argc, char *argv[], int start_arg, 1166 const char *iff_name) 1167{ 1168 uint32_t val, mask; 1169 struct ch_trace trace; 1170 1171 if (argc == start_arg) 1172 return -1; 1173 1174 memset(&trace, 0, sizeof(trace)); 1175 if (!strcmp(argv[start_arg], "tx")) 1176 trace.config_tx = 1; 1177 else if (!strcmp(argv[start_arg], "rx")) 1178 trace.config_rx = 1; 1179 else if (!strcmp(argv[start_arg], "all")) 1180 trace.config_tx = trace.config_rx = 1; 1181 else 1182 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", " 1183 "\"tx\" or \"all\"", argv[start_arg]); 1184 1185 if (argc == ++start_arg) 1186 return -1; 1187 if (!strcmp(argv[start_arg], "on")) { 1188 trace.trace_tx = trace.config_tx; 1189 trace.trace_rx = trace.config_rx; 1190 } else if (strcmp(argv[start_arg], "off")) 1191 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"", 1192 argv[start_arg]); 1193 1194 start_arg++; 1195 if (start_arg < argc && !strcmp(argv[start_arg], "not")) { 1196 trace.invert_match = 1; 1197 start_arg++; 1198 } 1199 1200 while (start_arg + 2 <= argc) { 1201 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask); 1202 1203 if (!strcmp(argv[start_arg], "interface")) { 1204 trace.intf = val; 1205 trace.intf_mask = mask; 1206 } else if (!strcmp(argv[start_arg], "sip")) { 1207 trace.sip = val; 1208 trace.sip_mask = mask; 1209 } else if (!strcmp(argv[start_arg], "dip")) { 1210 trace.dip = val; 1211 trace.dip_mask = mask; 1212 } else if (!strcmp(argv[start_arg], "sport")) { 1213 trace.sport = val; 1214 trace.sport_mask = mask; 1215 } else if (!strcmp(argv[start_arg], "dport")) { 1216 trace.dport = val; 1217 trace.dport_mask = mask; 1218 } else if (!strcmp(argv[start_arg], "vlan")) { 1219 trace.vlan = val; 1220 trace.vlan_mask = mask; 1221 } else if (!strcmp(argv[start_arg], "proto")) { 1222 trace.proto = val; 1223 trace.proto_mask = mask; 1224 } else 1225 errx(1, "unknown trace parameter \"%s\"\n" 1226 "known parameters are \"interface\", \"sip\", " 1227 "\"dip\", \"sport\", \"dport\", \"vlan\", " 1228 "\"proto\"", argv[start_arg]); 1229 if (ret < 0) 1230 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]); 1231 start_arg += 2; 1232 } 1233 if (start_arg != argc) 1234 errx(1, "unknown parameter \"%s\"", argv[start_arg]); 1235 1236 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0) 1237 err(1, "trace"); 1238 return 0; 1239} 1240 1241static int get_sched_param(int argc, char *argv[], int pos, unsigned int *valp) 1242{ 1243 if (pos + 1 >= argc) 1244 errx(1, "missing value for %s", argv[pos]); 1245 if (get_int_arg(argv[pos + 1], valp)) 1246 exit(1); 1247 return 0; 1248} 1249 1250static int tx_sched(int argc, char *argv[], int start_arg, const char *iff_name) 1251{ 1252 struct ch_hw_sched op; 1253 unsigned int idx, val; 1254 1255 if (argc < 5 || get_int_arg(argv[start_arg++], &idx)) 1256 return -1; 1257 1258 op.sched = idx; 1259 op.mode = op.channel = -1; 1260 op.kbps = op.class_ipg = op.flow_ipg = -1; 1261 1262 while (argc > start_arg) { 1263 if (!strcmp(argv[start_arg], "mode")) { 1264 if (start_arg + 1 >= argc) 1265 errx(1, "missing value for mode"); 1266 if (!strcmp(argv[start_arg + 1], "class")) 1267 op.mode = 0; 1268 else if (!strcmp(argv[start_arg + 1], "flow")) 1269 op.mode = 1; 1270 else 1271 errx(1, "bad mode \"%s\"", argv[start_arg + 1]); 1272 } else if (!strcmp(argv[start_arg], "channel") && 1273 !get_sched_param(argc, argv, start_arg, &val)) 1274 op.channel = val; 1275 else if (!strcmp(argv[start_arg], "rate") && 1276 !get_sched_param(argc, argv, start_arg, &val)) 1277 op.kbps = val; 1278 else if (!strcmp(argv[start_arg], "ipg") && 1279 !get_sched_param(argc, argv, start_arg, &val)) 1280 op.class_ipg = val; 1281 else if (!strcmp(argv[start_arg], "flowipg") && 1282 !get_sched_param(argc, argv, start_arg, &val)) 1283 op.flow_ipg = val; 1284 else 1285 errx(1, "unknown scheduler parameter \"%s\"", 1286 argv[start_arg]); 1287 start_arg += 2; 1288 } 1289 1290 if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0) 1291 err(1, "pktsched"); 1292 1293 return 0; 1294} 1295 1296static int pktsched(int argc, char *argv[], int start_arg, const char *iff_name) 1297{ 1298 struct ch_pktsched_params op; 1299 unsigned int idx, min = -1, max, binding = -1; 1300 1301 if (argc < 4) 1302 errx(1, "no scheduler specified"); 1303 1304 if (!strcmp(argv[start_arg], "port")) { 1305 if (argc != start_arg + 4) 1306 return -1; 1307 if (get_int_arg(argv[start_arg + 1], &idx) || 1308 get_int_arg(argv[start_arg + 2], &min) || 1309 get_int_arg(argv[start_arg + 3], &max)) 1310 return -1; 1311 op.sched = 0; 1312 } else if (!strcmp(argv[start_arg], "tunnelq")) { 1313 if (argc != start_arg + 4) 1314 return -1; 1315 if (get_int_arg(argv[start_arg + 1], &idx) || 1316 get_int_arg(argv[start_arg + 2], &max) || 1317 get_int_arg(argv[start_arg + 3], &binding)) 1318 return -1; 1319 op.sched = 1; 1320 } else if (!strcmp(argv[start_arg], "tx")) 1321 return tx_sched(argc, argv, start_arg + 1, iff_name); 1322 else 1323 errx(1, "unknown scheduler \"%s\"; must be one of \"port\", " 1324 "\"tunnelq\" or \"tx\"", argv[start_arg]); 1325 1326 op.idx = idx; 1327 op.min = min; 1328 op.max = max; 1329 op.binding = binding; 1330 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0) 1331 err(1, "pktsched"); 1332 1333 return 0; 1334} 1335 1336static int clear_stats(int argc, char *argv[], int start_arg, 1337 const char *iff_name) 1338{ 1339 if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0) 1340 err(1, "clearstats"); 1341 1342 return 0; 1343} 1344 1345static int get_up_la(int argc, char *argv[], int start_arg, const char *iff_name) 1346{ 1347 struct ch_up_la la; 1348 int i, idx, max_idx, entries; 1349 1350 la.stopped = 0; 1351 la.idx = -1; 1352 la.bufsize = LA_BUFSIZE; 1353 la.data = malloc(la.bufsize); 1354 if (!la.data) 1355 err(1, "uP_LA malloc"); 1356 1357 if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0) 1358 err(1, "uP_LA"); 1359 1360 if (la.stopped) 1361 printf("LA is not running\n"); 1362 1363 entries = la.bufsize / 4; 1364 idx = (int)la.idx; 1365 max_idx = (entries / 4) - 1; 1366 for (i = 0; i < max_idx; i++) { 1367 printf("%04x %08x %08x\n", 1368 la.data[idx], la.data[idx+2], la.data[idx+1]); 1369 idx = (idx + 4) & (entries - 1); 1370 } 1371 1372 return 0; 1373} 1374 1375static int get_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name) 1376{ 1377 struct ch_up_ioqs ioqs; 1378 int i, entries; 1379 1380 bzero(&ioqs, sizeof(ioqs)); 1381 ioqs.bufsize = IOQS_BUFSIZE; 1382 ioqs.data = malloc(IOQS_BUFSIZE); 1383 if (!ioqs.data) 1384 err(1, "uP_IOQs malloc"); 1385 1386 if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0) 1387 err(1, "uP_IOQs"); 1388 1389 printf("ioq_rx_enable : 0x%08x\n", ioqs.ioq_rx_enable); 1390 printf("ioq_tx_enable : 0x%08x\n", ioqs.ioq_tx_enable); 1391 printf("ioq_rx_status : 0x%08x\n", ioqs.ioq_rx_status); 1392 printf("ioq_tx_status : 0x%08x\n", ioqs.ioq_tx_status); 1393 1394 entries = ioqs.bufsize / sizeof(struct t3_ioq_entry); 1395 for (i = 0; i < entries; i++) { 1396 printf("\nioq[%d].cp : 0x%08x\n", i, 1397 ioqs.data[i].ioq_cp); 1398 printf("ioq[%d].pp : 0x%08x\n", i, 1399 ioqs.data[i].ioq_pp); 1400 printf("ioq[%d].alen : 0x%08x\n", i, 1401 ioqs.data[i].ioq_alen); 1402 printf("ioq[%d].stats : 0x%08x\n", i, 1403 ioqs.data[i].ioq_stats); 1404 printf(" sop %u\n", ioqs.data[i].ioq_stats >> 16); 1405 printf(" eop %u\n", ioqs.data[i].ioq_stats & 0xFFFF); 1406 } 1407 1408 return 0; 1409} 1410 1411static int 1412run_cmd(int argc, char *argv[], const char *iff_name) 1413{ 1414 int r = -1; 1415 1416 if (!strcmp(argv[2], "reg")) 1417 r = register_io(argc, argv, 3, iff_name); 1418 else if (!strcmp(argv[2], "mdio")) 1419 r = mdio_io(argc, argv, 3, iff_name); 1420 else if (!strcmp(argv[2], "mtus")) 1421 r = mtu_tab_op(argc, argv, 3, iff_name); 1422 else if (!strcmp(argv[2], "pm")) 1423 r = conf_pm(argc, argv, 3, iff_name); 1424 else if (!strcmp(argv[2], "regdump")) 1425 r = dump_regs(argc, argv, 3, iff_name); 1426 else if (!strcmp(argv[2], "tcamdump")) 1427 r = dump_tcam(argc, argv, 3, iff_name); 1428 else if (!strcmp(argv[2], "memdump")) 1429 r = dump_mc7(argc, argv, 3, iff_name); 1430 else if (!strcmp(argv[2], "meminfo")) 1431 r = meminfo(argc, argv, 3, iff_name); 1432 else if (!strcmp(argv[2], "context")) 1433 r = get_sge_context(argc, argv, 3, iff_name); 1434 else if (!strcmp(argv[2], "desc")) 1435 r = get_sge_desc(argc, argv, 3, iff_name); 1436 else if (!strcmp(argv[2], "loadfw")) 1437 r = load_fw(argc, argv, 3, iff_name); 1438 else if (!strcmp(argv[2], "loadboot")) 1439 r = load_boot(argc, argv, 3, iff_name); 1440 else if (!strcmp(argv[2], "proto")) 1441 r = proto_sram_op(argc, argv, 3, iff_name); 1442 else if (!strcmp(argv[2], "qset")) 1443 r = qset_config(argc, argv, 3, iff_name); 1444 else if (!strcmp(argv[2], "qsets")) 1445 r = qset_num_config(argc, argv, 3, iff_name); 1446 else if (!strcmp(argv[2], "trace")) 1447 r = trace_config(argc, argv, 3, iff_name); 1448 else if (!strcmp(argv[2], "pktsched")) 1449 r = pktsched(argc, argv, 3, iff_name); 1450 else if (!strcmp(argv[2], "tcb")) 1451 r = get_tcb2(argc, argv, 3, iff_name); 1452 else if (!strcmp(argv[2], "clearstats")) 1453 r = clear_stats(argc, argv, 3, iff_name); 1454 else if (!strcmp(argv[2], "la")) 1455 r = get_up_la(argc, argv, 3, iff_name); 1456 else if (!strcmp(argv[2], "ioqs")) 1457 r = get_up_ioqs(argc, argv, 3, iff_name); 1458 1459 if (r == -1) 1460 usage(stderr); 1461 1462 return (0); 1463} 1464 1465static int 1466run_cmd_loop(int argc, char *argv[], const char *iff_name) 1467{ 1468 int n, i; 1469 char buf[64]; 1470 char *args[8], *s; 1471 1472 args[0] = argv[0]; 1473 args[1] = argv[1]; 1474 1475 /* 1476 * Fairly simplistic loop. Displays a "> " prompt and processes any 1477 * input as a cxgbtool command. You're supposed to enter only the part 1478 * after "cxgbtool cxgbX". Use "quit" or "exit" to exit. Any error in 1479 * the command will also terminate cxgbtool. 1480 */ 1481 for (;;) { 1482 fprintf(stdout, "> "); 1483 fflush(stdout); 1484 n = read(STDIN_FILENO, buf, sizeof(buf)); 1485 if (n > sizeof(buf) - 1) { 1486 fprintf(stdout, "too much input.\n"); 1487 return (0); 1488 } else if (n <= 0) 1489 return (0); 1490 1491 if (buf[--n] != '\n') 1492 continue; 1493 else 1494 buf[n] = 0; 1495 1496 s = &buf[0]; 1497 for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) { 1498 while (s && (*s == ' ' || *s == '\t')) 1499 s++; 1500 if ((args[i] = strsep(&s, " \t")) == NULL) 1501 break; 1502 } 1503 args[sizeof(args)/sizeof(args[0]) - 1] = 0; 1504 1505 if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit")) 1506 return (0); 1507 1508 (void) run_cmd(i, args, iff_name); 1509 } 1510 1511 /* Can't really get here */ 1512 return (0); 1513} 1514 1515int 1516main(int argc, char *argv[]) 1517{ 1518 int r = -1; 1519 const char *iff_name; 1520 1521 progname = argv[0]; 1522 1523 if (argc == 2) { 1524 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) 1525 usage(stdout); 1526 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) { 1527 printf("%s version %s\n", PROGNAME, VERSION); 1528 printf("%s\n", COPYRIGHT); 1529 exit(0); 1530 } 1531 } 1532 1533 if (argc < 3) usage(stderr); 1534 1535 iff_name = argv[1]; 1536 1537 if (argc == 3 && !strcmp(argv[2], "stdio")) 1538 r = run_cmd_loop(argc, argv, iff_name); 1539 else 1540 r = run_cmd(argc, argv, iff_name); 1541 1542 return (r); 1543} 1544