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