xref: /freebsd-11-stable/tools/tools/cxgbtool/cxgbtool.c (revision 4ab2e064d7950be84256d671a7ae93f87cc6aa36)
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, &reg) < 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], &reg) ||
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, &regs))
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, &regs))
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, &reg) < 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