1 /**************************************************************************
2 SPDX-License-Identifier: BSD-3-Clause
3
4 Copyright (c) 2007-2010, Chelsio Inc.
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 3. Neither the name of the Chelsio Corporation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.
32
33
34 ***************************************************************************/
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <stdint.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <err.h>
45 #include <errno.h>
46 #include <inttypes.h>
47 #include <sys/param.h>
48 #include <sys/time.h>
49 #include <sys/ioctl.h>
50 #include <sys/socket.h>
51
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54
55 #include <net/if.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
72 struct 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
86 static const char *progname;
87
88 static void
usage(FILE * fp)89 usage(FILE *fp)
90 {
91 fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
92 fprintf(fp,
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"
123 );
124 exit(fp == stderr ? 1 : 0);
125 }
126
127 static int
doit(const char * iff_name,unsigned long cmd,void * data)128 doit(const char *iff_name, unsigned long cmd, void *data)
129 {
130 static int fd = 0;
131
132 if (fd == 0) {
133 char buf[64];
134 snprintf(buf, 64, "/dev/%s", iff_name);
135
136 if ((fd = open(buf, O_RDWR)) < 0)
137 return -1;
138 }
139
140 return ioctl(fd, cmd, data) < 0 ? -1 : 0;
141 }
142
143 static int
get_int_arg(const char * s,uint32_t * valp)144 get_int_arg(const char *s, uint32_t *valp)
145 {
146 char *p;
147
148 *valp = strtoul(s, &p, 0);
149 if (*p) {
150 warnx("bad parameter \"%s\"", s);
151 return -1;
152 }
153 return 0;
154 }
155
156 static uint32_t
read_reg(const char * iff_name,uint32_t addr)157 read_reg(const char *iff_name, uint32_t addr)
158 {
159 struct ch_reg reg;
160
161 reg.addr = addr;
162
163 if (doit(iff_name, CHELSIO_GETREG, ®) < 0)
164 err(1, "register read");
165 return reg.val;
166 }
167
168 static void
write_reg(const char * iff_name,uint32_t addr,uint32_t val)169 write_reg(const char *iff_name, uint32_t addr, uint32_t val)
170 {
171 struct ch_reg ch_reg;
172
173 ch_reg.addr = addr;
174 ch_reg.val = val;
175
176 if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
177 err(1, "register write");
178 }
179
180 static int
register_io(int argc,char * argv[],int start_arg,const char * iff_name)181 register_io(int argc, char *argv[], int start_arg,
182 const char *iff_name)
183 {
184 char *p;
185 uint32_t addr, val = 0, w = 0;
186
187 if (argc != start_arg + 1) return -1;
188
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);
193 w = 1;
194 }
195 if (*p) {
196 warnx("bad parameter \"%s\"", argv[start_arg]);
197 return -1;
198 }
199
200 if (w)
201 write_reg(iff_name, addr, val);
202 else {
203 val = read_reg(iff_name, addr);
204 printf("%#x [%u]\n", val, val);
205 }
206 return 0;
207 }
208
209 static int
mdio_io(int argc,char * argv[],int start_arg,const char * iff_name)210 mdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
211 {
212 struct ch_mii_data p;
213 unsigned int cmd, phy_addr, reg, mmd, val;
214
215 if (argc == start_arg + 3)
216 cmd = CHELSIO_GET_MIIREG;
217 else if (argc == start_arg + 4)
218 cmd = CHELSIO_SET_MIIREG;
219 else
220 return -1;
221
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)))
226 return -1;
227
228 p.phy_id = phy_addr | (mmd << 8);
229 p.reg_num = reg;
230 p.val_in = val;
231
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);
236 return 0;
237 }
238
239 static inline
xtract(uint32_t val,int shift,int len)240 uint32_t xtract(uint32_t val, int shift, int len)
241 {
242 return (val >> shift) & ((1 << len) - 1);
243 }
244
245 static int
dump_block_regs(const struct reg_info * reg_array,uint32_t * regs)246 dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
247 {
248 uint32_t reg_val = 0; // silence compiler warning
249
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);
255 } else {
256 uint32_t v = xtract(reg_val, reg_array->addr,
257 reg_array->len);
258
259 printf(" %-40s %#-10x [%u]\n", reg_array->name,
260 v, v);
261 }
262 return 1;
263 }
264
265 static int
dump_regs_t2(int argc,char * argv[],int start_arg,uint32_t * regs)266 dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
267 {
268 int match = 0;
269 char *block_name = NULL;
270
271 if (argc == start_arg + 1)
272 block_name = argv[start_arg];
273 else if (argc != start_arg)
274 return -1;
275
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);
298 if (!match)
299 errx(1, "unknown block \"%s\"", block_name);
300 return 0;
301 }
302
303 #if defined(CONFIG_T3_REGS)
304 static int
dump_regs_t3(int argc,char * argv[],int start_arg,uint32_t * regs,int is_pcie)305 dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie)
306 {
307 int match = 0;
308 char *block_name = NULL;
309
310 if (argc == start_arg + 1)
311 block_name = argv[start_arg];
312 else if (argc != start_arg)
313 return -1;
314
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,
319 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);
360 if (!match)
361 errx(1, "unknown block \"%s\"", block_name);
362 return 0;
363 }
364
365 static int
dump_regs_t3b(int argc,char * argv[],int start_arg,uint32_t * regs,int is_pcie)366 dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
367 int is_pcie)
368 {
369 int match = 0;
370 char *block_name = NULL;
371
372 if (argc == start_arg + 1)
373 block_name = argv[start_arg];
374 else if (argc != start_arg)
375 return -1;
376
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);
422 if (!match)
423 errx(1, "unknown block \"%s\"", block_name);
424 return 0;
425 }
426
427 static int
dump_regs_t3c(int argc,char * argv[],int start_arg,uint32_t * regs,int is_pcie)428 dump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs,
429 int is_pcie)
430 {
431 int match = 0;
432 char *block_name = NULL;
433
434 if (argc == start_arg + 1)
435 block_name = argv[start_arg];
436 else if (argc != start_arg)
437 return -1;
438
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);
484 if (!match)
485 errx(1, "unknown block \"%s\"", block_name);
486 return 0;
487 }
488 #endif
489
490 static int
dump_regs(int argc,char * argv[],int start_arg,const char * iff_name)491 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
492 {
493 int vers, revision, is_pcie;
494 struct ch_ifconf_regs regs;
495
496 regs.len = REGDUMP_SIZE;
497
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");
501
502 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
503 err(1, "can't read registers");
504
505 vers = regs.version & 0x3ff;
506 revision = (regs.version >> 10) & 0x3f;
507 is_pcie = (regs.version & 0x80000000) != 0;
508
509 if (vers <= 2)
510 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
511 #if defined(CONFIG_T3_REGS)
512 if (vers == 3) {
513 if (revision == 0)
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);
519 if (revision == 4)
520 return dump_regs_t3c(argc, argv, start_arg,
521 (uint32_t *)regs.data, is_pcie);
522 }
523 #endif
524 errx(1, "unknown card type %d.%d", vers, revision);
525 return 0;
526 }
527
528 static int
t3_meminfo(const uint32_t * regs)529 t3_meminfo(const uint32_t *regs)
530 {
531 enum {
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,
551 };
552
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];
572
573 printf("CM memory map:\n");
574 printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
575 egr_cntxt);
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,
587 tx_fl - rx_fl);
588 printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
589 cim_base - tx_fl);
590 printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base,
591 cim_base + cim_size - 1, cim_size);
592
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,
601 rq_ul - rq_ll + 1);
602 printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
603 pbl_ul - pbl_ll + 1);
604 return 0;
605 }
606
607 static int
meminfo(int argc,char * argv[],int start_arg,const char * iff_name)608 meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
609 {
610 int vers;
611 struct ch_ifconf_regs regs;
612
613 (void) argc;
614 (void) argv;
615 (void) start_arg;
616
617 regs.len = REGDUMP_SIZE;
618 if ((regs.data = malloc(regs.len)) == NULL)
619 err(1, "can't malloc");
620
621 if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s))
622 err(1, "can't read registers");
623
624 vers = regs.version & 0x3ff;
625 if (vers == 3)
626 return t3_meminfo((uint32_t *)regs.data);
627
628 errx(1, "unknown card type %d", vers);
629 return 0;
630 }
631
632 static int
mtu_tab_op(int argc,char * argv[],int start_arg,const char * iff_name)633 mtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name)
634 {
635 struct ch_mtus m;
636 unsigned int i;
637
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]);
643 printf("\n");
644 } else if (argc <= start_arg + NMTUS) {
645 m.nmtus = argc - start_arg;
646
647 for (i = 0; i < m.nmtus; ++i) {
648 char *p;
649 unsigned long mt = strtoul(argv[start_arg + i], &p, 0);
650
651 if (*p || mt > 9600) {
652 warnx("bad parameter \"%s\"",
653 argv[start_arg + i]);
654 return -1;
655 }
656 if (i && mt < m.mtus[i - 1])
657 errx(1, "MTUs must be in ascending order");
658 m.mtus[i] = mt;
659 }
660 if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0)
661 err(1, "set MTU table");
662 } else
663 return -1;
664
665 return 0;
666 }
667
668 #ifdef CHELSIO_INTERNAL
669 static void
show_egress_cntxt(uint32_t data[])670 show_egress_cntxt(uint32_t data[])
671 {
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);
686 }
687
688 static void
show_fl_cntxt(uint32_t data[])689 show_fl_cntxt(uint32_t data[])
690 {
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);
700 }
701
702 static void
show_response_cntxt(uint32_t data[])703 show_response_cntxt(uint32_t data[])
704 {
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]);
715 }
716
717 static void
show_cq_cntxt(uint32_t data[])718 show_cq_cntxt(uint32_t data[])
719 {
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);
732 }
733
734 static int
get_sge_context(int argc,char * argv[],int start_arg,const char * iff_name)735 get_sge_context(int argc, char *argv[], int start_arg, const char *iff_name)
736 {
737 struct ch_cntxt ctx;
738
739 if (argc != start_arg + 2) return -1;
740
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;
749 else {
750 warnx("unknown context type \"%s\"; known types are egress, "
751 "fl, cq, and response", argv[start_arg]);
752 return -1;
753 }
754
755 if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
756 return -1;
757
758 if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
759 err(1, "get SGE context");
760
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);
769 return 0;
770 }
771
772 #define ntohll(x) be64toh((x))
773
774 static int
get_sge_desc(int argc,char * argv[],int start_arg,const char * iff_name)775 get_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name)
776 {
777 uint64_t *p, wr_hdr;
778 unsigned int n = 1, qset, qnum;
779 struct ch_desc desc;
780
781 if (argc != start_arg + 3 && argc != start_arg + 4)
782 return -1;
783
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))
787 return -1;
788
789 if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
790 return -1;
791
792 if (qnum > 5)
793 errx(1, "invalid queue number %d, range is 0..5", qnum);
794
795 desc.queue_num = qset * 6 + qnum;
796
797 for (; n--; desc.idx++) {
798 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
799 err(1, "get SGE descriptor");
800
801 p = (uint64_t *)desc.data;
802 wr_hdr = ntohll(*p);
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);
811
812 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
813 printf("%016" PRIx64 "%c", ntohll(*p),
814 desc.size % 32 == 8 ? '\n' : ' ');
815 }
816 return 0;
817 }
818 #endif
819
820 static int
get_tcb2(int argc,char * argv[],int start_arg,const char * iff_name)821 get_tcb2(int argc, char *argv[], int start_arg, const char *iff_name)
822 {
823 uint64_t *d;
824 unsigned int i;
825 unsigned int tcb_idx;
826 struct ch_mem_range mr;
827
828 if (argc != start_arg + 1)
829 return -1;
830
831 if (get_int_arg(argv[start_arg], &tcb_idx))
832 return -1;
833
834 mr.buf = calloc(1, TCB_SIZE);
835 if (!mr.buf)
836 err(1, "get TCB");
837
838 mr.mem_id = MEM_CM;
839 mr.addr = tcb_idx * TCB_SIZE;
840 mr.len = TCB_SIZE;
841
842 if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0)
843 err(1, "get TCB");
844
845 for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) {
846 printf("%2u:", 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));
850 d += 2;
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));
854 d += 2;
855 }
856 free(mr.buf);
857 return 0;
858 }
859
860 static int
get_pm_page_spec(const char * s,unsigned int * page_size,unsigned int * num_pages)861 get_pm_page_spec(const char *s, unsigned int *page_size,
862 unsigned int *num_pages)
863 {
864 char *p;
865 unsigned long val;
866
867 val = strtoul(s, &p, 0);
868 if (p == s) return -1;
869 if (*p == 'x' && p[1]) {
870 *num_pages = val;
871 *page_size = strtoul(p + 1, &p, 0);
872 } else {
873 *num_pages = -1;
874 *page_size = val;
875 }
876 *page_size <<= 10; // KB -> bytes
877 return *p;
878 }
879
880 static int
conf_pm(int argc,char * argv[],int start_arg,const char * iff_name)881 conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
882 {
883 struct ch_pm pm;
884
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);
891 return 0;
892 }
893
894 if (argc != start_arg + 2) return -1;
895
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]);
898 return -1;
899 }
900 if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz,
901 &pm.rx_num_pg)) {
902 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
903 return -1;
904 }
905 if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0)
906 err(1, "pm config");
907 return 0;
908 }
909
910 #ifdef CHELSIO_INTERNAL
911 static int
dump_tcam(int argc,char * argv[],int start_arg,const char * iff_name)912 dump_tcam(int argc, char *argv[], int start_arg, const char *iff_name)
913 {
914 unsigned int nwords;
915 struct ch_tcam_word op;
916
917 if (argc != start_arg + 2) return -1;
918
919 if (get_int_arg(argv[start_arg], &op.addr) ||
920 get_int_arg(argv[start_arg + 1], &nwords))
921 return -1;
922
923 while (nwords--) {
924 if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0)
925 err(1, "tcam dump");
926
927 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
928 op.buf[0] & 0xff, op.buf[1], op.buf[2]);
929 op.addr++;
930 }
931 return 0;
932 }
933
934 static void
hexdump_8b(unsigned int start,uint64_t * data,unsigned int len)935 hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
936 {
937 int i;
938
939 while (len) {
940 printf("0x%08x:", start);
941 for (i = 0; i < 4 && len; ++i, --len)
942 printf(" %016llx", (unsigned long long)*data++);
943 printf("\n");
944 start += 32;
945 }
946 }
947
948 static int
dump_mc7(int argc,char * argv[],int start_arg,const char * iff_name)949 dump_mc7(int argc, char *argv[], int start_arg, const char *iff_name)
950 {
951 struct ch_mem_range mem;
952 unsigned int mem_id, addr, len;
953
954 if (argc != start_arg + 3) return -1;
955
956 if (!strcmp(argv[start_arg], "cm"))
957 mem_id = MEM_CM;
958 else if (!strcmp(argv[start_arg], "rx"))
959 mem_id = MEM_PMRX;
960 else if (!strcmp(argv[start_arg], "tx"))
961 mem_id = MEM_PMTX;
962 else
963 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
964 " or \"rx\"", argv[start_arg]);
965
966 if (get_int_arg(argv[start_arg + 1], &addr) ||
967 get_int_arg(argv[start_arg + 2], &len))
968 return -1;
969
970 mem.buf = malloc(len);
971 if (!mem.buf)
972 err(1, "memory dump");
973
974 mem.mem_id = mem_id;
975 mem.addr = addr;
976 mem.len = len;
977
978 if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
979 err(1, "memory dump");
980
981 hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
982 free(mem.buf);
983 return 0;
984 }
985 #endif
986
987 /* Max FW size is 64K including version, +4 bytes for the checksum. */
988 #define MAX_FW_IMAGE_SIZE (64 * 1024)
989
990 static int
load_fw(int argc,char * argv[],int start_arg,const char * iff_name)991 load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
992 {
993 int fd, len;
994 struct ch_mem_range op;
995 const char *fname = argv[start_arg];
996
997 if (argc != start_arg + 1) return -1;
998
999 fd = open(fname, O_RDONLY);
1000 if (fd < 0)
1001 err(1, "load firmware");
1002
1003 bzero(&op, sizeof(op));
1004 op.buf = malloc(MAX_FW_IMAGE_SIZE + 1);
1005 if (!op.buf)
1006 err(1, "load firmware");
1007
1008 len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1);
1009 if (len < 0)
1010 err(1, "load firmware");
1011 if (len > MAX_FW_IMAGE_SIZE)
1012 errx(1, "FW image too large");
1013
1014 op.len = len;
1015 if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0)
1016 err(1, "load firmware");
1017
1018 close(fd);
1019 return 0;
1020 }
1021
1022 /* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */
1023 #define MAX_BOOT_IMAGE_SIZE (0xff * 512)
1024
1025 static int
load_boot(int argc,char * argv[],int start_arg,const char * iff_name)1026 load_boot(int argc, char *argv[], int start_arg, const char *iff_name)
1027 {
1028 int fd, len;
1029 struct ch_mem_range op;
1030 const char *fname = argv[start_arg];
1031
1032 if (argc != start_arg + 1) return -1;
1033
1034 fd = open(fname, O_RDONLY);
1035 if (fd < 0)
1036 err(1, "load boot image");
1037
1038 op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1);
1039 if (!op.buf)
1040 err(1, "load boot image");
1041
1042 len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1);
1043 if (len < 0)
1044 err(1, "load boot image");
1045 if (len > MAX_BOOT_IMAGE_SIZE)
1046 errx(1, "boot image too large");
1047
1048 op.len = len;
1049
1050 if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0)
1051 err(1, "load boot image");
1052
1053 close(fd);
1054 return 0;
1055 }
1056
1057 static int
dump_proto_sram(const char * iff_name)1058 dump_proto_sram(const char *iff_name)
1059 {
1060 int i, j;
1061 uint8_t buf[PROTO_SRAM_SIZE];
1062 struct ch_eeprom ee;
1063 uint8_t *p = buf;
1064
1065 bzero(buf, sizeof(buf));
1066 ee.offset = PROTO_SRAM_EEPROM_ADDR;
1067 ee.data = p;
1068 ee.len = sizeof(buf);
1069 if (doit(iff_name, CHELSIO_GET_EEPROM, &ee))
1070 err(1, "show protocol sram");
1071
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];
1076
1077 if (nibble_idx & 1)
1078 nibble >>= 4;
1079 else
1080 nibble &= 0xf;
1081 printf("%x", nibble);
1082 }
1083 putchar('\n');
1084 }
1085 return 0;
1086 }
1087
1088 static int
proto_sram_op(int argc,char * argv[],int start_arg,const char * iff_name)1089 proto_sram_op(int argc, char *argv[], int start_arg,
1090 const char *iff_name)
1091 {
1092 (void) argv;
1093 (void) start_arg;
1094
1095 if (argc == start_arg)
1096 return dump_proto_sram(iff_name);
1097 return -1;
1098 }
1099
1100 static int
dump_qset_params(const char * iff_name)1101 dump_qset_params(const char *iff_name)
1102 {
1103 struct ch_qset_params qp;
1104
1105 qp.qset_idx = 0;
1106
1107 while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1108 if (!qp.qset_idx)
1109 printf("Qset TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1"
1110 " Cong Lat IRQ\n");
1111 printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n",
1112 qp.qnum,
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);
1116 qp.qset_idx++;
1117 }
1118 if (!qp.qset_idx || (errno && errno != EINVAL))
1119 err(1, "get qset parameters");
1120 return 0;
1121 }
1122
1123 static int
qset_config(int argc,char * argv[],int start_arg,const char * iff_name)1124 qset_config(int argc, char *argv[], int start_arg, const char *iff_name)
1125 {
1126 (void) argv;
1127
1128 if (argc == start_arg)
1129 return dump_qset_params(iff_name);
1130
1131 return -1;
1132 }
1133
1134 static int
qset_num_config(int argc,char * argv[],int start_arg,const char * iff_name)1135 qset_num_config(int argc, char *argv[], int start_arg, const char *iff_name)
1136 {
1137 struct ch_reg reg;
1138
1139 (void) argv;
1140
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);
1145 return 0;
1146 }
1147
1148 return -1;
1149 }
1150
1151 /*
1152 * Parse a string containing an IP address with an optional network prefix.
1153 */
1154 static int
parse_ipaddr(const char * s,uint32_t * addr,uint32_t * mask)1155 parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1156 {
1157 char *p, *slash;
1158 struct in_addr ia;
1159
1160 *mask = 0xffffffffU;
1161 slash = strchr(s, '/');
1162 if (slash)
1163 *slash = 0;
1164 if (!inet_aton(s, &ia)) {
1165 if (slash)
1166 *slash = '/';
1167 *addr = 0;
1168 return -1;
1169 }
1170 *addr = ntohl(ia.s_addr);
1171 if (slash) {
1172 unsigned int prefix = strtoul(slash + 1, &p, 10);
1173
1174 *slash = '/';
1175 if (p == slash + 1 || *p || prefix > 32)
1176 return -1;
1177 *mask <<= (32 - prefix);
1178 }
1179 return 0;
1180 }
1181
1182 /*
1183 * Parse a string containing a value and an optional colon separated mask.
1184 */
1185 static int
parse_val_mask_param(const char * s,uint32_t * val,uint32_t * mask,uint32_t default_mask)1186 parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
1187 uint32_t default_mask)
1188 {
1189 char *p;
1190
1191 *mask = default_mask;
1192 *val = strtoul(s, &p, 0);
1193 if (p == s || *val > default_mask)
1194 return -1;
1195 if (*p == ':' && p[1])
1196 *mask = strtoul(p + 1, &p, 0);
1197 return *p || *mask > default_mask ? -1 : 0;
1198 }
1199
1200 static int
parse_trace_param(const char * s,uint32_t * val,uint32_t * mask)1201 parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1202 {
1203 return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1204 parse_val_mask_param(s, val, mask, 0xffffffffU);
1205 }
1206
1207 static int
trace_config(int argc,char * argv[],int start_arg,const char * iff_name)1208 trace_config(int argc, char *argv[], int start_arg, const char *iff_name)
1209 {
1210 uint32_t val, mask;
1211 struct ch_trace trace;
1212
1213 if (argc == start_arg)
1214 return -1;
1215
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;
1223 else
1224 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1225 "\"tx\" or \"all\"", argv[start_arg]);
1226
1227 if (argc == ++start_arg)
1228 return -1;
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\"",
1234 argv[start_arg]);
1235
1236 start_arg++;
1237 if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1238 trace.invert_match = 1;
1239 start_arg++;
1240 }
1241
1242 while (start_arg + 2 <= argc) {
1243 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1244
1245 if (!strcmp(argv[start_arg], "interface")) {
1246 trace.intf = val;
1247 trace.intf_mask = mask;
1248 } else if (!strcmp(argv[start_arg], "sip")) {
1249 trace.sip = val;
1250 trace.sip_mask = mask;
1251 } else if (!strcmp(argv[start_arg], "dip")) {
1252 trace.dip = val;
1253 trace.dip_mask = mask;
1254 } else if (!strcmp(argv[start_arg], "sport")) {
1255 trace.sport = val;
1256 trace.sport_mask = mask;
1257 } else if (!strcmp(argv[start_arg], "dport")) {
1258 trace.dport = val;
1259 trace.dport_mask = mask;
1260 } else if (!strcmp(argv[start_arg], "vlan")) {
1261 trace.vlan = val;
1262 trace.vlan_mask = mask;
1263 } else if (!strcmp(argv[start_arg], "proto")) {
1264 trace.proto = val;
1265 trace.proto_mask = mask;
1266 } else
1267 errx(1, "unknown trace parameter \"%s\"\n"
1268 "known parameters are \"interface\", \"sip\", "
1269 "\"dip\", \"sport\", \"dport\", \"vlan\", "
1270 "\"proto\"", argv[start_arg]);
1271 if (ret < 0)
1272 errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1273 start_arg += 2;
1274 }
1275 if (start_arg != argc)
1276 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1277
1278 if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1279 err(1, "trace");
1280 return 0;
1281 }
1282
1283 static void
show_filters(const char * iff_name)1284 show_filters(const char *iff_name)
1285 {
1286 static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
1287 struct ch_filter op;
1288 union {
1289 uint32_t nip;
1290 uint8_t octet[4];
1291 } nsip, ndip;
1292 char sip[20], dip[20];
1293 int header = 0;
1294
1295 bzero(&op, sizeof(op));
1296 op.filter_id = 0xffffffff;
1297
1298 do {
1299 if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
1300 err(1, "list filters");
1301
1302 if (op.filter_id == 0xffffffff)
1303 break;
1304
1305 if (!header) {
1306 printf("index SIP DIP sport "
1307 "dport VLAN PRI P/MAC type Q\n");
1308 header = 1;
1309 }
1310
1311 nsip.nip = htonl(op.val.sip);
1312 ndip.nip = htonl(op.val.dip);
1313
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)
1326 printf("*/* ");
1327 else if (op.mac_hit)
1328 printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
1329 (op.mac_addr_idx) & 0x7);
1330 else
1331 printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1);
1332 printf("%4s ", pkt_type[op.proto]);
1333 if (!op.pass)
1334 printf("-\n");
1335 else if (op.rss)
1336 printf("*\n");
1337 else
1338 printf("%1u\n", op.qset);
1339 } while (1);
1340 }
1341
1342 static int
filter_config(int argc,char * argv[],int start_arg,const char * iff_name)1343 filter_config(int argc, char *argv[], int start_arg, const char *iff_name)
1344 {
1345 int ret = 0;
1346 uint32_t val, mask;
1347 struct ch_filter op;
1348
1349 if (argc < start_arg + 1)
1350 return -1;
1351
1352 memset(&op, 0, sizeof(op));
1353 op.mac_addr_idx = 0xffff;
1354 op.rss = 1;
1355
1356 if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
1357 show_filters(iff_name);
1358 return 0;
1359 }
1360
1361 if (get_int_arg(argv[start_arg++], &op.filter_id))
1362 return -1;
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) {
1366 if (errno == EBUSY)
1367 err(1, "no filter support when offload in use");
1368 err(1, "delete filter");
1369 }
1370 return 0;
1371 }
1372
1373 while (start_arg + 2 <= argc) {
1374 if (!strcmp(argv[start_arg], "sip")) {
1375 ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
1376 &op.mask.sip);
1377 } else if (!strcmp(argv[start_arg], "dip")) {
1378 ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
1379 &op.mask.dip);
1380 } else if (!strcmp(argv[start_arg], "sport")) {
1381 ret = parse_val_mask_param(argv[start_arg + 1],
1382 &val, &mask, 0xffff);
1383 op.val.sport = val;
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);
1388 op.val.dport = val;
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);
1393 op.val.vlan = val;
1394 op.mask.vlan = mask;
1395 } else if (!strcmp(argv[start_arg], "prio")) {
1396 ret = parse_val_mask_param(argv[start_arg + 1],
1397 &val, &mask, 7);
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"))
1402 val = -1;
1403 else
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"))
1409 op.proto = 1;
1410 else if (!strcmp(argv[start_arg + 1], "udp"))
1411 op.proto = 2;
1412 else if (!strcmp(argv[start_arg + 1], "frag"))
1413 op.proto = 3;
1414 else
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);
1420 op.qset = val;
1421 op.rss = 0;
1422 } else if (!strcmp(argv[start_arg], "action")) {
1423 if (!strcmp(argv[start_arg + 1], "pass"))
1424 op.pass = 1;
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]);
1429 } else
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\"",
1434 argv[start_arg]);
1435 if (ret < 0)
1436 errx(1, "bad value \"%s\" for parameter \"%s\"",
1437 argv[start_arg + 1], argv[start_arg]);
1438 start_arg += 2;
1439 }
1440 if (start_arg != argc)
1441 errx(1, "no value for \"%s\"", argv[start_arg]);
1442
1443 if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
1444 if (errno == EBUSY)
1445 err(1, "no filter support when offload in use");
1446 err(1, "set filter");
1447 }
1448
1449 return 0;
1450 }
1451 static int
get_sched_param(int argc,char * argv[],int pos,unsigned int * valp)1452 get_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
1453 {
1454 if (pos + 1 >= argc)
1455 errx(1, "missing value for %s", argv[pos]);
1456 if (get_int_arg(argv[pos + 1], valp))
1457 exit(1);
1458 return 0;
1459 }
1460
1461 static int
tx_sched(int argc,char * argv[],int start_arg,const char * iff_name)1462 tx_sched(int argc, char *argv[], int start_arg, const char *iff_name)
1463 {
1464 struct ch_hw_sched op;
1465 unsigned int idx, val;
1466
1467 if (argc < 5 || get_int_arg(argv[start_arg++], &idx))
1468 return -1;
1469
1470 op.sched = idx;
1471 op.mode = op.channel = -1;
1472 op.kbps = op.class_ipg = op.flow_ipg = -1;
1473
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"))
1479 op.mode = 0;
1480 else if (!strcmp(argv[start_arg + 1], "flow"))
1481 op.mode = 1;
1482 else
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))
1486 op.channel = val;
1487 else if (!strcmp(argv[start_arg], "rate") &&
1488 !get_sched_param(argc, argv, start_arg, &val))
1489 op.kbps = val;
1490 else if (!strcmp(argv[start_arg], "ipg") &&
1491 !get_sched_param(argc, argv, start_arg, &val))
1492 op.class_ipg = val;
1493 else if (!strcmp(argv[start_arg], "flowipg") &&
1494 !get_sched_param(argc, argv, start_arg, &val))
1495 op.flow_ipg = val;
1496 else
1497 errx(1, "unknown scheduler parameter \"%s\"",
1498 argv[start_arg]);
1499 start_arg += 2;
1500 }
1501
1502 if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0)
1503 err(1, "pktsched");
1504
1505 return 0;
1506 }
1507
1508 static int
pktsched(int argc,char * argv[],int start_arg,const char * iff_name)1509 pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1510 {
1511 struct ch_pktsched_params op;
1512 unsigned int idx, min = -1, max, binding = -1;
1513
1514 if (argc < 4)
1515 errx(1, "no scheduler specified");
1516
1517 if (!strcmp(argv[start_arg], "port")) {
1518 if (argc != start_arg + 4)
1519 return -1;
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))
1523 return -1;
1524 op.sched = 0;
1525 } else if (!strcmp(argv[start_arg], "tunnelq")) {
1526 if (argc != start_arg + 4)
1527 return -1;
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))
1531 return -1;
1532 op.sched = 1;
1533 } else if (!strcmp(argv[start_arg], "tx"))
1534 return tx_sched(argc, argv, start_arg + 1, iff_name);
1535 else
1536 errx(1, "unknown scheduler \"%s\"; must be one of \"port\", "
1537 "\"tunnelq\" or \"tx\"", argv[start_arg]);
1538
1539 op.idx = idx;
1540 op.min = min;
1541 op.max = max;
1542 op.binding = binding;
1543 if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0)
1544 err(1, "pktsched");
1545
1546 return 0;
1547 }
1548
1549 static int
clear_stats(int argc,char * argv[],int start_arg,const char * iff_name)1550 clear_stats(int argc, char *argv[], int start_arg, const char *iff_name)
1551 {
1552 (void) argc;
1553 (void) argv;
1554 (void) start_arg;
1555
1556 if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0)
1557 err(1, "clearstats");
1558
1559 return 0;
1560 }
1561
1562 static int
get_up_la(int argc,char * argv[],int start_arg,const char * iff_name)1563 get_up_la(int argc, char *argv[], int start_arg, const char *iff_name)
1564 {
1565 struct ch_up_la la;
1566 int i, idx, max_idx, entries;
1567
1568 (void) argc;
1569 (void) argv;
1570 (void) start_arg;
1571
1572 la.stopped = 0;
1573 la.idx = -1;
1574 la.bufsize = LA_BUFSIZE;
1575 la.data = malloc(la.bufsize);
1576 if (!la.data)
1577 err(1, "uP_LA malloc");
1578
1579 if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0)
1580 err(1, "uP_LA");
1581
1582 if (la.stopped)
1583 printf("LA is not running\n");
1584
1585 entries = la.bufsize / 4;
1586 idx = (int)la.idx;
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);
1592 }
1593
1594 return 0;
1595 }
1596
1597 static int
get_up_ioqs(int argc,char * argv[],int start_arg,const char * iff_name)1598 get_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name)
1599 {
1600 struct ch_up_ioqs ioqs;
1601 int i, entries;
1602
1603 (void) argc;
1604 (void) argv;
1605 (void) start_arg;
1606
1607 bzero(&ioqs, sizeof(ioqs));
1608 ioqs.bufsize = IOQS_BUFSIZE;
1609 ioqs.data = malloc(IOQS_BUFSIZE);
1610 if (!ioqs.data)
1611 err(1, "uP_IOQs malloc");
1612
1613 if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0)
1614 err(1, "uP_IOQs");
1615
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);
1620
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);
1633 }
1634
1635 return 0;
1636 }
1637
1638 static int
run_cmd(int argc,char * argv[],const char * iff_name)1639 run_cmd(int argc, char *argv[], const char *iff_name)
1640 {
1641 int r = -1;
1642
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);
1687
1688 if (r == -1)
1689 usage(stderr);
1690
1691 return (0);
1692 }
1693
1694 static int
run_cmd_loop(int argc,char * argv[],const char * iff_name)1695 run_cmd_loop(int argc, char *argv[], const char *iff_name)
1696 {
1697 int n;
1698 unsigned int i;
1699 char buf[64];
1700 char *args[8], *s;
1701
1702 (void) argc;
1703 args[0] = argv[0];
1704 args[1] = argv[1];
1705
1706 /*
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.
1711 */
1712 for (;;) {
1713 fprintf(stdout, "> ");
1714 fflush(stdout);
1715 n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
1716 if (n <= 0)
1717 return (0);
1718
1719 if (buf[--n] != '\n')
1720 continue;
1721 else
1722 buf[n] = 0;
1723
1724 s = &buf[0];
1725 for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) {
1726 while (s && (*s == ' ' || *s == '\t'))
1727 s++;
1728 if ((args[i] = strsep(&s, " \t")) == NULL)
1729 break;
1730 }
1731 args[sizeof(args)/sizeof(args[0]) - 1] = 0;
1732
1733 if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit"))
1734 return (0);
1735
1736 (void) run_cmd(i, args, iff_name);
1737 }
1738
1739 /* Can't really get here */
1740 return (0);
1741 }
1742
1743 int
main(int argc,char * argv[])1744 main(int argc, char *argv[])
1745 {
1746 int r = -1;
1747 const char *iff_name;
1748
1749 progname = argv[0];
1750
1751 if (argc == 2) {
1752 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1753 usage(stdout);
1754 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1755 printf("%s version %s\n", PROGNAME, VERSION);
1756 printf("%s\n", COPYRIGHT);
1757 exit(0);
1758 }
1759 }
1760
1761 if (argc < 3) usage(stderr);
1762
1763 iff_name = argv[1];
1764
1765 if (argc == 3 && !strcmp(argv[2], "stdio"))
1766 r = run_cmd_loop(argc, argv, iff_name);
1767 else
1768 r = run_cmd(argc, argv, iff_name);
1769
1770 return (r);
1771 }
1772