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