1167518Skmacy/**************************************************************************
2167518Skmacy
3207643SnpCopyright (c) 2007-2010, Chelsio Inc.
4167518SkmacyAll rights reserved.
5167518Skmacy
6167518SkmacyRedistribution and use in source and binary forms, with or without
7167518Skmacymodification, are permitted provided that the following conditions are met:
8167518Skmacy
9167518Skmacy 1. Redistributions of source code must retain the above copyright notice,
10167518Skmacy    this list of conditions and the following disclaimer.
11167518Skmacy
12167518Skmacy 2. Redistributions in binary form must reproduce the above copyright
13167518Skmacy    notice, this list of conditions and the following disclaimer in the
14167518Skmacy    documentation and/or other materials provided with the distribution.
15167518Skmacy
16167518Skmacy 3. Neither the name of the Chelsio Corporation nor the names of its
17167518Skmacy    contributors may be used to endorse or promote products derived from
18167518Skmacy    this software without specific prior written permission.
19167518Skmacy
20167518SkmacyTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21167518SkmacyAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22167518SkmacyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23167518SkmacyARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24167518SkmacyLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25167518SkmacyCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26167518SkmacySUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27167518SkmacyINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28167518SkmacyCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29167518SkmacyARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30167518SkmacyPOSSIBILITY OF SUCH DAMAGE.
31167518Skmacy
32167518Skmacy
33167518Skmacy***************************************************************************/
34167518Skmacy#include <sys/cdefs.h>
35167518Skmacy__FBSDID("$FreeBSD$");
36167518Skmacy
37167518Skmacy#include <stdlib.h>
38167518Skmacy#include <stdio.h>
39167518Skmacy#include <stdint.h>
40167518Skmacy#include <string.h>
41167518Skmacy#include <unistd.h>
42167518Skmacy#include <fcntl.h>
43167518Skmacy#include <err.h>
44167518Skmacy#include <errno.h>
45167518Skmacy#include <inttypes.h>
46167518Skmacy#include <sys/param.h>
47167518Skmacy#include <sys/time.h>
48167518Skmacy#include <sys/ioctl.h>
49167518Skmacy#include <sys/socket.h>
50167518Skmacy
51167518Skmacy#include <netinet/in.h>
52167518Skmacy#include <arpa/inet.h>
53167518Skmacy
54167518Skmacy#include <net/if.h>
55167518Skmacy#include <net/if_var.h>
56167518Skmacy#include <net/if_types.h>
57182899Skmacy#include <sys/endian.h>
58167518Skmacy
59167518Skmacy#define NMTUS 16
60167518Skmacy#define TCB_SIZE 128
61167518Skmacy#define TCB_WORDS (TCB_SIZE / 4)
62167518Skmacy#define PROTO_SRAM_LINES 128
63167518Skmacy#define PROTO_SRAM_LINE_BITS 132
64167518Skmacy#define PROTO_SRAM_LINE_NIBBLES (132 / 4)
65167518Skmacy#define PROTO_SRAM_SIZE (PROTO_SRAM_LINE_NIBBLES * PROTO_SRAM_LINES / 2)
66167518Skmacy#define PROTO_SRAM_EEPROM_ADDR 4096
67167518Skmacy
68167589Skmacy#include <cxgb_ioctl.h>
69167589Skmacy#include <common/cxgb_regs.h>
70167518Skmacy#include "version.h"
71167518Skmacy
72167518Skmacystruct reg_info {
73167518Skmacy        const char *name;
74167518Skmacy        uint16_t addr;
75167518Skmacy        uint16_t len;
76167518Skmacy};
77167518Skmacy
78167518Skmacy
79167518Skmacy#include "reg_defs.c"
80167518Skmacy#if defined(CONFIG_T3_REGS)
81167518Skmacy# include "reg_defs_t3.c"
82167518Skmacy# include "reg_defs_t3b.c"
83182594Skmacy# include "reg_defs_t3c.c"
84167518Skmacy#endif
85167518Skmacy
86167518Skmacystatic const char *progname;
87167518Skmacy
88204267Snpstatic void
89204267Snpusage(FILE *fp)
90167518Skmacy{
91167518Skmacy	fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
92167518Skmacy	fprintf(fp,
93182594Skmacy	    	"\tclearstats                          clear MAC statistics\n"
94182594Skmacy		"\tcontext <type> <id>                 show an SGE context\n"
95182594Skmacy		"\tdesc <qset> <queue> <idx> [<cnt>]   dump SGE descriptors\n"
96207643Snp		"\tfilter <idx> [<param> <val>] ...    set a filter\n"
97207643Snp		"\tfilter <idx> delete|clear           delete a filter\n"
98207643Snp		"\tfilter list                         list all filters\n"
99189643Sgnn		"\tioqs                                dump uP IOQs\n"
100189643Sgnn		"\tla                                  dump uP logic analyzer info\n"
101182594Skmacy		"\tloadboot <boot image>               download boot image\n"
102182594Skmacy		"\tloadfw <FW image>                   download firmware\n"
103167518Skmacy		"\tmdio <phy_addr> <mmd_addr>\n"
104167518Skmacy	        "\t     <reg_addr> [<val>]             read/write MDIO register\n"
105182594Skmacy		"\tmemdump cm|tx|rx <addr> <len>       dump a mem range\n"
106182594Skmacy		"\tmeminfo                             show memory info\n"
107167518Skmacy		"\tmtus [<mtu0>...<mtuN>]              read/write MTU table\n"
108182594Skmacy		"\tpktsched port <idx> <min> <max>     set TX port scheduler params\n"
109182594Skmacy		"\tpktsched tunnelq <idx> <max>\n"
110182594Skmacy		"\t         <binding>                  set TX tunnelq scheduler params\n"
111182594Skmacy		"\tpktsched tx <idx>\n"
112182594Skmacy	        "\t         [<param> <val>] ...        set Tx HW scheduler\n"
113167518Skmacy		"\tpm [<TX page spec> <RX page spec>]  read/write PM config\n"
114182594Skmacy		"\tproto                               read proto SRAM\n"
115182594Skmacy		"\tqset                                read qset parameters\n"
116182594Skmacy		"\tqsets                               read # of qsets\n"
117182594Skmacy		"\treg <address>[=<val>]               read/write register\n"
118167518Skmacy		"\tregdump [<module>]                  dump registers\n"
119167518Skmacy		"\ttcamdump <address> <count>          show TCAM contents\n"
120182594Skmacy		"\ttcb <index>                         read TCB\n"
121167518Skmacy		"\ttrace tx|rx|all on|off [not]\n"
122167518Skmacy	        "\t      [<param> <val>[:<mask>]] ...  write trace parameters\n"
123167518Skmacy		);
124167518Skmacy	exit(fp == stderr ? 1 : 0);
125167518Skmacy}
126167518Skmacy
127167518Skmacystatic int
128167518Skmacydoit(const char *iff_name, unsigned long cmd, void *data)
129167518Skmacy{
130167518Skmacy	static int fd = 0;
131167518Skmacy
132167518Skmacy	if (fd == 0) {
133167518Skmacy		char buf[64];
134167518Skmacy		snprintf(buf, 64, "/dev/%s", iff_name);
135167518Skmacy
136167518Skmacy		if ((fd = open(buf, O_RDWR)) < 0)
137182594Skmacy			return -1;
138167518Skmacy	}
139167518Skmacy
140167518Skmacy	return ioctl(fd, cmd, data) < 0 ? -1 : 0;
141167518Skmacy}
142167518Skmacy
143204267Snpstatic int
144204267Snpget_int_arg(const char *s, uint32_t *valp)
145167518Skmacy{
146167518Skmacy	char *p;
147167518Skmacy
148167518Skmacy	*valp = strtoul(s, &p, 0);
149167518Skmacy	if (*p) {
150167518Skmacy		warnx("bad parameter \"%s\"", s);
151167518Skmacy		return -1;
152167518Skmacy	}
153167518Skmacy	return 0;
154167518Skmacy}
155167518Skmacy
156167518Skmacystatic uint32_t
157167518Skmacyread_reg(const char *iff_name, uint32_t addr)
158167518Skmacy{
159167518Skmacy	struct ch_reg reg;
160167518Skmacy
161167518Skmacy	reg.addr = addr;
162167518Skmacy
163167518Skmacy	if (doit(iff_name, CHELSIO_GETREG, &reg) < 0)
164167518Skmacy		err(1, "register read");
165167518Skmacy	return reg.val;
166167518Skmacy}
167167518Skmacy
168167518Skmacystatic void
169167518Skmacywrite_reg(const char *iff_name, uint32_t addr, uint32_t val)
170167518Skmacy{
171167518Skmacy	struct ch_reg ch_reg;
172167518Skmacy
173167518Skmacy	ch_reg.addr = addr;
174167518Skmacy	ch_reg.val = val;
175167518Skmacy
176167518Skmacy	if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
177167518Skmacy		err(1, "register write");
178167518Skmacy}
179167518Skmacy
180204267Snpstatic int
181204267Snpregister_io(int argc, char *argv[], int start_arg,
182167518Skmacy		       const char *iff_name)
183167518Skmacy{
184167518Skmacy	char *p;
185204267Snp	uint32_t addr, val = 0, w = 0;
186167518Skmacy
187167518Skmacy	if (argc != start_arg + 1) return -1;
188167518Skmacy
189167518Skmacy	addr = strtoul(argv[start_arg], &p, 0);
190167518Skmacy	if (p == argv[start_arg]) return -1;
191167518Skmacy	if (*p == '=' && p[1]) {
192167518Skmacy		val = strtoul(p + 1, &p, 0);
193204267Snp		w = 1;
194167518Skmacy	}
195167518Skmacy	if (*p) {
196167518Skmacy		warnx("bad parameter \"%s\"", argv[start_arg]);
197167518Skmacy		return -1;
198167518Skmacy	}
199167518Skmacy
200204267Snp	if (w)
201167518Skmacy		write_reg(iff_name, addr, val);
202167518Skmacy	else {
203167518Skmacy		val = read_reg(iff_name, addr);
204167518Skmacy		printf("%#x [%u]\n", val, val);
205167518Skmacy	}
206167518Skmacy	return 0;
207167518Skmacy}
208167518Skmacy
209204267Snpstatic int
210204267Snpmdio_io(int argc, char *argv[], int start_arg, const char *iff_name)
211167518Skmacy{
212182594Skmacy        struct ch_mii_data p;
213167518Skmacy        unsigned int cmd, phy_addr, reg, mmd, val;
214167518Skmacy
215167518Skmacy        if (argc == start_arg + 3)
216182594Skmacy                cmd = CHELSIO_GET_MIIREG;
217167518Skmacy        else if (argc == start_arg + 4)
218182594Skmacy                cmd = CHELSIO_SET_MIIREG;
219167518Skmacy        else
220167518Skmacy                return -1;
221167518Skmacy
222167518Skmacy        if (get_int_arg(argv[start_arg], &phy_addr) ||
223167518Skmacy            get_int_arg(argv[start_arg + 1], &mmd) ||
224167518Skmacy            get_int_arg(argv[start_arg + 2], &reg) ||
225182594Skmacy            (cmd == CHELSIO_SET_MIIREG && get_int_arg(argv[start_arg + 3], &val)))
226167518Skmacy                return -1;
227167518Skmacy
228167518Skmacy        p.phy_id  = phy_addr | (mmd << 8);
229167518Skmacy        p.reg_num = reg;
230167518Skmacy        p.val_in  = val;
231167518Skmacy
232167518Skmacy        if (doit(iff_name, cmd, &p) < 0)
233182594Skmacy                err(1, "MDIO %s", cmd == CHELSIO_GET_MIIREG ? "read" : "write");
234182594Skmacy        if (cmd == CHELSIO_GET_MIIREG)
235167518Skmacy                printf("%#x [%u]\n", p.val_out, p.val_out);
236167518Skmacy        return 0;
237167518Skmacy}
238167518Skmacy
239204267Snpstatic inline
240204267Snpuint32_t xtract(uint32_t val, int shift, int len)
241167518Skmacy{
242167518Skmacy	return (val >> shift) & ((1 << len) - 1);
243167518Skmacy}
244167518Skmacy
245204267Snpstatic int
246204267Snpdump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
247167518Skmacy{
248167518Skmacy	uint32_t reg_val = 0; // silence compiler warning
249167518Skmacy
250167518Skmacy	for ( ; reg_array->name; ++reg_array)
251167518Skmacy		if (!reg_array->len) {
252167518Skmacy			reg_val = regs[reg_array->addr / 4];
253167518Skmacy			printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
254167518Skmacy			       reg_array->name, reg_val, reg_val);
255167518Skmacy		} else {
256167518Skmacy			uint32_t v = xtract(reg_val, reg_array->addr,
257167518Skmacy					    reg_array->len);
258167518Skmacy
259167518Skmacy			printf("        %-40s %#-10x [%u]\n", reg_array->name,
260167518Skmacy			       v, v);
261167518Skmacy		}
262167518Skmacy	return 1;
263167518Skmacy}
264167518Skmacy
265204267Snpstatic int
266204267Snpdump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
267167518Skmacy{
268167518Skmacy	int match = 0;
269167518Skmacy	char *block_name = NULL;
270167518Skmacy
271167518Skmacy	if (argc == start_arg + 1)
272167518Skmacy		block_name = argv[start_arg];
273167518Skmacy	else if (argc != start_arg)
274167518Skmacy		return -1;
275167518Skmacy
276167518Skmacy	if (!block_name || !strcmp(block_name, "sge"))
277167518Skmacy		match += dump_block_regs(sge_regs, regs);
278167518Skmacy	if (!block_name || !strcmp(block_name, "mc3"))
279167518Skmacy		match += dump_block_regs(mc3_regs, regs);
280167518Skmacy	if (!block_name || !strcmp(block_name, "mc4"))
281167518Skmacy		match += dump_block_regs(mc4_regs, regs);
282167518Skmacy	if (!block_name || !strcmp(block_name, "tpi"))
283167518Skmacy		match += dump_block_regs(tpi_regs, regs);
284167518Skmacy	if (!block_name || !strcmp(block_name, "tp"))
285167518Skmacy		match += dump_block_regs(tp_regs, regs);
286167518Skmacy	if (!block_name || !strcmp(block_name, "rat"))
287167518Skmacy		match += dump_block_regs(rat_regs, regs);
288167518Skmacy	if (!block_name || !strcmp(block_name, "cspi"))
289167518Skmacy		match += dump_block_regs(cspi_regs, regs);
290167518Skmacy	if (!block_name || !strcmp(block_name, "espi"))
291167518Skmacy		match += dump_block_regs(espi_regs, regs);
292167518Skmacy	if (!block_name || !strcmp(block_name, "ulp"))
293167518Skmacy		match += dump_block_regs(ulp_regs, regs);
294167518Skmacy	if (!block_name || !strcmp(block_name, "pl"))
295167518Skmacy		match += dump_block_regs(pl_regs, regs);
296167518Skmacy	if (!block_name || !strcmp(block_name, "mc5"))
297167518Skmacy		match += dump_block_regs(mc5_regs, regs);
298167518Skmacy	if (!match)
299167518Skmacy		errx(1, "unknown block \"%s\"", block_name);
300167518Skmacy	return 0;
301167518Skmacy}
302167518Skmacy
303167518Skmacy#if defined(CONFIG_T3_REGS)
304204267Snpstatic int
305204267Snpdump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie)
306167518Skmacy{
307167518Skmacy	int match = 0;
308167518Skmacy	char *block_name = NULL;
309167518Skmacy
310167518Skmacy	if (argc == start_arg + 1)
311167518Skmacy		block_name = argv[start_arg];
312167518Skmacy	else if (argc != start_arg)
313167518Skmacy		return -1;
314167518Skmacy
315167518Skmacy	if (!block_name || !strcmp(block_name, "sge"))
316167518Skmacy		match += dump_block_regs(sge3_regs, regs);
317167518Skmacy	if (!block_name || !strcmp(block_name, "pci"))
318167518Skmacy		match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
319167518Skmacy					 regs);
320167518Skmacy	if (!block_name || !strcmp(block_name, "t3dbg"))
321167518Skmacy		match += dump_block_regs(t3dbg_regs, regs);
322167518Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
323167518Skmacy		match += dump_block_regs(mc7_pmrx_regs, regs);
324167518Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
325167518Skmacy		match += dump_block_regs(mc7_pmtx_regs, regs);
326167518Skmacy	if (!block_name || !strcmp(block_name, "cm"))
327167518Skmacy		match += dump_block_regs(mc7_cm_regs, regs);
328167518Skmacy	if (!block_name || !strcmp(block_name, "cim"))
329167518Skmacy		match += dump_block_regs(cim_regs, regs);
330167518Skmacy	if (!block_name || !strcmp(block_name, "tp"))
331167518Skmacy		match += dump_block_regs(tp1_regs, regs);
332167518Skmacy	if (!block_name || !strcmp(block_name, "ulp_rx"))
333167518Skmacy		match += dump_block_regs(ulp2_rx_regs, regs);
334167518Skmacy	if (!block_name || !strcmp(block_name, "ulp_tx"))
335167518Skmacy		match += dump_block_regs(ulp2_tx_regs, regs);
336167518Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
337167518Skmacy		match += dump_block_regs(pm1_rx_regs, regs);
338167518Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
339167518Skmacy		match += dump_block_regs(pm1_tx_regs, regs);
340167518Skmacy	if (!block_name || !strcmp(block_name, "mps"))
341167518Skmacy		match += dump_block_regs(mps0_regs, regs);
342167518Skmacy	if (!block_name || !strcmp(block_name, "cplsw"))
343167518Skmacy		match += dump_block_regs(cpl_switch_regs, regs);
344167518Skmacy	if (!block_name || !strcmp(block_name, "smb"))
345167518Skmacy		match += dump_block_regs(smb0_regs, regs);
346167518Skmacy	if (!block_name || !strcmp(block_name, "i2c"))
347167518Skmacy		match += dump_block_regs(i2cm0_regs, regs);
348167518Skmacy	if (!block_name || !strcmp(block_name, "mi1"))
349167518Skmacy		match += dump_block_regs(mi1_regs, regs);
350167518Skmacy	if (!block_name || !strcmp(block_name, "sf"))
351167518Skmacy		match += dump_block_regs(sf1_regs, regs);
352167518Skmacy	if (!block_name || !strcmp(block_name, "pl"))
353167518Skmacy		match += dump_block_regs(pl3_regs, regs);
354167518Skmacy	if (!block_name || !strcmp(block_name, "mc5"))
355167518Skmacy		match += dump_block_regs(mc5a_regs, regs);
356167518Skmacy	if (!block_name || !strcmp(block_name, "xgmac0"))
357167518Skmacy		match += dump_block_regs(xgmac0_0_regs, regs);
358167518Skmacy	if (!block_name || !strcmp(block_name, "xgmac1"))
359167518Skmacy		match += dump_block_regs(xgmac0_1_regs, regs);
360167518Skmacy	if (!match)
361167518Skmacy		errx(1, "unknown block \"%s\"", block_name);
362167518Skmacy	return 0;
363167518Skmacy}
364167518Skmacy
365204267Snpstatic int
366204267Snpdump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
367204267Snp    int is_pcie)
368167518Skmacy{
369167518Skmacy	int match = 0;
370167518Skmacy	char *block_name = NULL;
371167518Skmacy
372167518Skmacy	if (argc == start_arg + 1)
373167518Skmacy		block_name = argv[start_arg];
374167518Skmacy	else if (argc != start_arg)
375167518Skmacy		return -1;
376167518Skmacy
377167518Skmacy	if (!block_name || !strcmp(block_name, "sge"))
378167518Skmacy		match += dump_block_regs(t3b_sge3_regs, regs);
379167518Skmacy	if (!block_name || !strcmp(block_name, "pci"))
380167518Skmacy		match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
381167518Skmacy						   t3b_pcix1_regs, regs);
382167518Skmacy	if (!block_name || !strcmp(block_name, "t3dbg"))
383167518Skmacy		match += dump_block_regs(t3b_t3dbg_regs, regs);
384167518Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
385167518Skmacy		match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
386167518Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
387167518Skmacy		match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
388167518Skmacy	if (!block_name || !strcmp(block_name, "cm"))
389167518Skmacy		match += dump_block_regs(t3b_mc7_cm_regs, regs);
390167518Skmacy	if (!block_name || !strcmp(block_name, "cim"))
391167518Skmacy		match += dump_block_regs(t3b_cim_regs, regs);
392167518Skmacy	if (!block_name || !strcmp(block_name, "tp"))
393167518Skmacy		match += dump_block_regs(t3b_tp1_regs, regs);
394167518Skmacy	if (!block_name || !strcmp(block_name, "ulp_rx"))
395167518Skmacy		match += dump_block_regs(t3b_ulp2_rx_regs, regs);
396167518Skmacy	if (!block_name || !strcmp(block_name, "ulp_tx"))
397167518Skmacy		match += dump_block_regs(t3b_ulp2_tx_regs, regs);
398167518Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
399167518Skmacy		match += dump_block_regs(t3b_pm1_rx_regs, regs);
400167518Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
401167518Skmacy		match += dump_block_regs(t3b_pm1_tx_regs, regs);
402167518Skmacy	if (!block_name || !strcmp(block_name, "mps"))
403167518Skmacy		match += dump_block_regs(t3b_mps0_regs, regs);
404167518Skmacy	if (!block_name || !strcmp(block_name, "cplsw"))
405167518Skmacy		match += dump_block_regs(t3b_cpl_switch_regs, regs);
406167518Skmacy	if (!block_name || !strcmp(block_name, "smb"))
407167518Skmacy		match += dump_block_regs(t3b_smb0_regs, regs);
408167518Skmacy	if (!block_name || !strcmp(block_name, "i2c"))
409167518Skmacy		match += dump_block_regs(t3b_i2cm0_regs, regs);
410167518Skmacy	if (!block_name || !strcmp(block_name, "mi1"))
411167518Skmacy		match += dump_block_regs(t3b_mi1_regs, regs);
412167518Skmacy	if (!block_name || !strcmp(block_name, "sf"))
413167518Skmacy		match += dump_block_regs(t3b_sf1_regs, regs);
414167518Skmacy	if (!block_name || !strcmp(block_name, "pl"))
415167518Skmacy		match += dump_block_regs(t3b_pl3_regs, regs);
416167518Skmacy	if (!block_name || !strcmp(block_name, "mc5"))
417167518Skmacy		match += dump_block_regs(t3b_mc5a_regs, regs);
418167518Skmacy	if (!block_name || !strcmp(block_name, "xgmac0"))
419167518Skmacy		match += dump_block_regs(t3b_xgmac0_0_regs, regs);
420167518Skmacy	if (!block_name || !strcmp(block_name, "xgmac1"))
421167518Skmacy		match += dump_block_regs(t3b_xgmac0_1_regs, regs);
422167518Skmacy	if (!match)
423167518Skmacy		errx(1, "unknown block \"%s\"", block_name);
424167518Skmacy	return 0;
425167518Skmacy}
426182594Skmacy
427204267Snpstatic int
428204267Snpdump_regs_t3c(int argc, char *argv[], int start_arg, uint32_t *regs,
429204267Snp    int is_pcie)
430182594Skmacy{
431182594Skmacy	int match = 0;
432182594Skmacy	char *block_name = NULL;
433182594Skmacy
434182594Skmacy	if (argc == start_arg + 1)
435182594Skmacy		block_name = argv[start_arg];
436182594Skmacy	else if (argc != start_arg)
437182594Skmacy		return -1;
438182594Skmacy
439182594Skmacy	if (!block_name || !strcmp(block_name, "sge"))
440182594Skmacy		match += dump_block_regs(t3c_sge3_regs, regs);
441182594Skmacy	if (!block_name || !strcmp(block_name, "pci"))
442182594Skmacy		match += dump_block_regs(is_pcie ? t3c_pcie0_regs :
443182594Skmacy						   t3c_pcix1_regs, regs);
444182594Skmacy	if (!block_name || !strcmp(block_name, "t3dbg"))
445182594Skmacy		match += dump_block_regs(t3c_t3dbg_regs, regs);
446182594Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
447182594Skmacy		match += dump_block_regs(t3c_mc7_pmrx_regs, regs);
448182594Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
449182594Skmacy		match += dump_block_regs(t3c_mc7_pmtx_regs, regs);
450182594Skmacy	if (!block_name || !strcmp(block_name, "cm"))
451182594Skmacy		match += dump_block_regs(t3c_mc7_cm_regs, regs);
452182594Skmacy	if (!block_name || !strcmp(block_name, "cim"))
453182594Skmacy		match += dump_block_regs(t3c_cim_regs, regs);
454182594Skmacy	if (!block_name || !strcmp(block_name, "tp"))
455182594Skmacy		match += dump_block_regs(t3c_tp1_regs, regs);
456182594Skmacy	if (!block_name || !strcmp(block_name, "ulp_rx"))
457182594Skmacy		match += dump_block_regs(t3c_ulp2_rx_regs, regs);
458182594Skmacy	if (!block_name || !strcmp(block_name, "ulp_tx"))
459182594Skmacy		match += dump_block_regs(t3c_ulp2_tx_regs, regs);
460182594Skmacy	if (!block_name || !strcmp(block_name, "pmrx"))
461182594Skmacy		match += dump_block_regs(t3c_pm1_rx_regs, regs);
462182594Skmacy	if (!block_name || !strcmp(block_name, "pmtx"))
463182594Skmacy		match += dump_block_regs(t3c_pm1_tx_regs, regs);
464182594Skmacy	if (!block_name || !strcmp(block_name, "mps"))
465182594Skmacy		match += dump_block_regs(t3c_mps0_regs, regs);
466182594Skmacy	if (!block_name || !strcmp(block_name, "cplsw"))
467182594Skmacy		match += dump_block_regs(t3c_cpl_switch_regs, regs);
468182594Skmacy	if (!block_name || !strcmp(block_name, "smb"))
469182594Skmacy		match += dump_block_regs(t3c_smb0_regs, regs);
470182594Skmacy	if (!block_name || !strcmp(block_name, "i2c"))
471182594Skmacy		match += dump_block_regs(t3c_i2cm0_regs, regs);
472182594Skmacy	if (!block_name || !strcmp(block_name, "mi1"))
473182594Skmacy		match += dump_block_regs(t3c_mi1_regs, regs);
474182594Skmacy	if (!block_name || !strcmp(block_name, "sf"))
475182594Skmacy		match += dump_block_regs(t3c_sf1_regs, regs);
476182594Skmacy	if (!block_name || !strcmp(block_name, "pl"))
477182594Skmacy		match += dump_block_regs(t3c_pl3_regs, regs);
478182594Skmacy	if (!block_name || !strcmp(block_name, "mc5"))
479182594Skmacy		match += dump_block_regs(t3c_mc5a_regs, regs);
480182594Skmacy	if (!block_name || !strcmp(block_name, "xgmac0"))
481182594Skmacy		match += dump_block_regs(t3c_xgmac0_0_regs, regs);
482182594Skmacy	if (!block_name || !strcmp(block_name, "xgmac1"))
483182594Skmacy		match += dump_block_regs(t3c_xgmac0_1_regs, regs);
484182594Skmacy	if (!match)
485182594Skmacy		errx(1, "unknown block \"%s\"", block_name);
486182594Skmacy	return 0;
487182594Skmacy}
488167518Skmacy#endif
489167518Skmacy
490167518Skmacystatic int
491167518Skmacydump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
492167518Skmacy{
493204267Snp	int vers, revision, is_pcie;
494182594Skmacy	struct ch_ifconf_regs regs;
495167518Skmacy
496167518Skmacy	regs.len = REGDUMP_SIZE;
497167518Skmacy
498182594Skmacy	/* XXX: This is never freed.  Looks like we don't care. */
499182594Skmacy	if ((regs.data = malloc(regs.len)) == NULL)
500167518Skmacy		err(1, "can't malloc");
501167518Skmacy
502167518Skmacy	if (doit(iff_name, CHELSIO_IFCONF_GETREGS, &regs))
503167518Skmacy		err(1, "can't read registers");
504167518Skmacy
505167518Skmacy	vers = regs.version & 0x3ff;
506167518Skmacy	revision = (regs.version >> 10) & 0x3f;
507167518Skmacy	is_pcie = (regs.version & 0x80000000) != 0;
508167518Skmacy
509167518Skmacy	if (vers <= 2)
510167518Skmacy		return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
511167518Skmacy#if defined(CONFIG_T3_REGS)
512167518Skmacy	if (vers == 3) {
513167518Skmacy		if (revision == 0)
514167518Skmacy			return dump_regs_t3(argc, argv, start_arg,
515167518Skmacy					    (uint32_t *)regs.data, is_pcie);
516182899Skmacy		if (revision == 2 || revision == 3)
517167518Skmacy			return dump_regs_t3b(argc, argv, start_arg,
518167518Skmacy					     (uint32_t *)regs.data, is_pcie);
519182594Skmacy		if (revision == 4)
520182594Skmacy			return dump_regs_t3c(argc, argv, start_arg,
521182594Skmacy			    		     (uint32_t *)regs.data, is_pcie);
522167518Skmacy	}
523167518Skmacy#endif
524182594Skmacy	errx(1, "unknown card type %d.%d", vers, revision);
525167518Skmacy	return 0;
526167518Skmacy}
527167518Skmacy
528204267Snpstatic int
529204267Snpt3_meminfo(const uint32_t *regs)
530167518Skmacy{
531167518Skmacy	enum {
532167518Skmacy		SG_EGR_CNTX_BADDR       = 0x58,
533167518Skmacy		SG_CQ_CONTEXT_BADDR     = 0x6c,
534167518Skmacy		CIM_SDRAM_BASE_ADDR     = 0x28c,
535167518Skmacy		CIM_SDRAM_ADDR_SIZE     = 0x290,
536167518Skmacy		TP_CMM_MM_BASE          = 0x314,
537167518Skmacy		TP_CMM_TIMER_BASE       = 0x318,
538167518Skmacy		TP_CMM_MM_RX_FLST_BASE  = 0x460,
539167518Skmacy		TP_CMM_MM_TX_FLST_BASE  = 0x464,
540167518Skmacy		TP_CMM_MM_PS_FLST_BASE  = 0x468,
541167518Skmacy		ULPRX_ISCSI_LLIMIT      = 0x50c,
542167518Skmacy		ULPRX_ISCSI_ULIMIT      = 0x510,
543167518Skmacy		ULPRX_TDDP_LLIMIT       = 0x51c,
544167518Skmacy		ULPRX_TDDP_ULIMIT       = 0x520,
545167518Skmacy		ULPRX_STAG_LLIMIT       = 0x52c,
546167518Skmacy		ULPRX_STAG_ULIMIT       = 0x530,
547167518Skmacy		ULPRX_RQ_LLIMIT         = 0x534,
548167518Skmacy		ULPRX_RQ_ULIMIT         = 0x538,
549167518Skmacy		ULPRX_PBL_LLIMIT        = 0x53c,
550167518Skmacy		ULPRX_PBL_ULIMIT        = 0x540,
551167518Skmacy	};
552167518Skmacy
553167518Skmacy	unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
554167518Skmacy		     cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
555167518Skmacy		     timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
556167518Skmacy		     pstructs = regs[TP_CMM_MM_BASE / 4],
557167518Skmacy		     pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
558167518Skmacy		     rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
559167518Skmacy		     tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
560167518Skmacy		     cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
561167518Skmacy		     cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
562167518Skmacy	unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
563167518Skmacy		     iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
564167518Skmacy		     tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
565167518Skmacy		     tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
566167518Skmacy		     stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
567167518Skmacy		     stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
568167518Skmacy		     rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
569167518Skmacy		     rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
570167518Skmacy		     pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
571167518Skmacy		     pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
572167518Skmacy
573167518Skmacy	printf("CM memory map:\n");
574167518Skmacy	printf("  TCB region:      0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
575167518Skmacy	       egr_cntxt);
576167518Skmacy	printf("  Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
577167518Skmacy	       cq_cntxt - 1, cq_cntxt - egr_cntxt);
578167518Skmacy	printf("  CQ contexts:     0x%08x - 0x%08x [%u]\n", cq_cntxt,
579167518Skmacy	       timers - 1, timers - cq_cntxt);
580167518Skmacy	printf("  Timers:          0x%08x - 0x%08x [%u]\n", timers,
581167518Skmacy	       pstructs - 1, pstructs - timers);
582167518Skmacy	printf("  Pstructs:        0x%08x - 0x%08x [%u]\n", pstructs,
583167518Skmacy	       pstruct_fl - 1, pstruct_fl - pstructs);
584167518Skmacy	printf("  Pstruct FL:      0x%08x - 0x%08x [%u]\n", pstruct_fl,
585167518Skmacy	       rx_fl - 1, rx_fl - pstruct_fl);
586167518Skmacy	printf("  Rx FL:           0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
587167518Skmacy	       tx_fl - rx_fl);
588167518Skmacy	printf("  Tx FL:           0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
589167518Skmacy	       cim_base - tx_fl);
590167518Skmacy	printf("  uP RAM:          0x%08x - 0x%08x [%u]\n", cim_base,
591167518Skmacy	       cim_base + cim_size - 1, cim_size);
592167518Skmacy
593167518Skmacy	printf("\nPMRX memory map:\n");
594167518Skmacy	printf("  iSCSI region:    0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
595167518Skmacy	       iscsi_ul - iscsi_ll + 1);
596167518Skmacy	printf("  TCP DDP region:  0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
597167518Skmacy	       tddp_ul - tddp_ll + 1);
598167518Skmacy	printf("  TPT region:      0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
599167518Skmacy	       stag_ul - stag_ll + 1);
600167518Skmacy	printf("  RQ region:       0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
601167518Skmacy	       rq_ul - rq_ll + 1);
602167518Skmacy	printf("  PBL region:      0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
603167518Skmacy	       pbl_ul - pbl_ll + 1);
604167518Skmacy	return 0;
605167518Skmacy}
606167518Skmacy
607204267Snpstatic int
608204267Snpmeminfo(int argc, char *argv[], int start_arg, const char *iff_name)
609167518Skmacy{
610167518Skmacy	int vers;
611182594Skmacy	struct ch_ifconf_regs regs;
612167518Skmacy
613204267Snp	(void) argc;
614204267Snp	(void) argv;
615204267Snp	(void) start_arg;
616204267Snp
617182594Skmacy	regs.len = REGDUMP_SIZE;
618182594Skmacy	if ((regs.data = malloc(regs.len)) == NULL)
619167518Skmacy		err(1, "can't malloc");
620167518Skmacy
621167518Skmacy	if (doit(iff_name, CHELSIO_IFCONF_GETREGS, &regs))
622167518Skmacy		err(1, "can't read registers");
623167518Skmacy
624167518Skmacy	vers = regs.version & 0x3ff;
625167518Skmacy	if (vers == 3)
626167518Skmacy		return t3_meminfo((uint32_t *)regs.data);
627167518Skmacy
628167518Skmacy	errx(1, "unknown card type %d", vers);
629167518Skmacy	return 0;
630167518Skmacy}
631167518Skmacy
632204267Snpstatic int
633204267Snpmtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name)
634167518Skmacy{
635182594Skmacy	struct ch_mtus m;
636204267Snp	unsigned int i;
637167518Skmacy
638167518Skmacy	if (argc == start_arg) {
639182594Skmacy		if (doit(iff_name, CHELSIO_GETMTUTAB, &m) < 0)
640167518Skmacy			err(1, "get MTU table");
641182594Skmacy		for (i = 0; i < m.nmtus; ++i)
642182594Skmacy			printf("%u ", m.mtus[i]);
643167518Skmacy		printf("\n");
644182594Skmacy	} else if (argc <= start_arg + NMTUS) {
645182594Skmacy		m.nmtus = argc - start_arg;
646167518Skmacy
647182594Skmacy		for (i = 0; i < m.nmtus; ++i) {
648167518Skmacy			char *p;
649182594Skmacy			unsigned long mt = strtoul(argv[start_arg + i], &p, 0);
650167518Skmacy
651182594Skmacy			if (*p || mt > 9600) {
652167518Skmacy				warnx("bad parameter \"%s\"",
653167518Skmacy				      argv[start_arg + i]);
654167518Skmacy				return -1;
655167518Skmacy			}
656182594Skmacy			if (i && mt < m.mtus[i - 1])
657167518Skmacy				errx(1, "MTUs must be in ascending order");
658182594Skmacy			m.mtus[i] = mt;
659167518Skmacy		}
660182594Skmacy		if (doit(iff_name, CHELSIO_SETMTUTAB, &m) < 0)
661167518Skmacy			err(1, "set MTU table");
662167518Skmacy	} else
663167518Skmacy		return -1;
664167518Skmacy
665167518Skmacy	return 0;
666167518Skmacy}
667167518Skmacy
668167518Skmacy#ifdef CHELSIO_INTERNAL
669204267Snpstatic void
670204267Snpshow_egress_cntxt(uint32_t data[])
671167518Skmacy{
672167518Skmacy	printf("credits:      %u\n", data[0] & 0x7fff);
673167518Skmacy	printf("GTS:          %u\n", (data[0] >> 15) & 1);
674167518Skmacy	printf("index:        %u\n", data[0] >> 16);
675167518Skmacy	printf("queue size:   %u\n", data[1] & 0xffff);
676204267Snp	printf("base address: 0x%" PRIx64 "\n",
677167518Skmacy	       ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
678167518Skmacy	       (((uint64_t)data[3] & 0xf) << 48)) << 12);
679167518Skmacy	printf("rsp queue #:  %u\n", (data[3] >> 4) & 7);
680167518Skmacy	printf("cmd queue #:  %u\n", (data[3] >> 7) & 1);
681167518Skmacy	printf("TUN:          %u\n", (data[3] >> 8) & 1);
682167518Skmacy	printf("TOE:          %u\n", (data[3] >> 9) & 1);
683167518Skmacy	printf("generation:   %u\n", (data[3] >> 10) & 1);
684167518Skmacy	printf("uP token:     %u\n", (data[3] >> 11) & 0xfffff);
685167518Skmacy	printf("valid:        %u\n", (data[3] >> 31) & 1);
686167518Skmacy}
687167518Skmacy
688204267Snpstatic void
689204267Snpshow_fl_cntxt(uint32_t data[])
690167518Skmacy{
691204267Snp	printf("base address: 0x%" PRIx64 "\n",
692167518Skmacy	       ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
693167518Skmacy	printf("index:        %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
694167518Skmacy	printf("queue size:   %u\n", (data[2] >> 4) & 0xffff);
695167518Skmacy	printf("generation:   %u\n", (data[2] >> 20) & 1);
696167518Skmacy	printf("entry size:   %u\n",
697189643Sgnn	       (data[2] >> 21) | (data[3] & 0x1fffff) << 11);
698167518Skmacy	printf("congest thr:  %u\n", (data[3] >> 21) & 0x3ff);
699167518Skmacy	printf("GTS:          %u\n", (data[3] >> 31) & 1);
700167518Skmacy}
701167518Skmacy
702204267Snpstatic void
703204267Snpshow_response_cntxt(uint32_t data[])
704167518Skmacy{
705167518Skmacy	printf("index:        %u\n", data[0] & 0xffff);
706167518Skmacy	printf("size:         %u\n", data[0] >> 16);
707204267Snp	printf("base address: 0x%" PRIx64 "\n",
708167518Skmacy	       ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
709167518Skmacy	printf("MSI-X/RspQ:   %u\n", (data[2] >> 20) & 0x3f);
710167518Skmacy	printf("intr enable:  %u\n", (data[2] >> 26) & 1);
711167518Skmacy	printf("intr armed:   %u\n", (data[2] >> 27) & 1);
712167518Skmacy	printf("generation:   %u\n", (data[2] >> 28) & 1);
713167518Skmacy	printf("CQ mode:      %u\n", (data[2] >> 31) & 1);
714167518Skmacy	printf("FL threshold: %u\n", data[3]);
715167518Skmacy}
716167518Skmacy
717204267Snpstatic void
718204267Snpshow_cq_cntxt(uint32_t data[])
719167518Skmacy{
720167518Skmacy	printf("index:            %u\n", data[0] & 0xffff);
721167518Skmacy	printf("size:             %u\n", data[0] >> 16);
722204267Snp	printf("base address:     0x%" PRIx64 "\n",
723167518Skmacy	       ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
724167518Skmacy	printf("rsp queue #:      %u\n", (data[2] >> 20) & 0x3f);
725167518Skmacy	printf("AN:               %u\n", (data[2] >> 26) & 1);
726167518Skmacy	printf("armed:            %u\n", (data[2] >> 27) & 1);
727167518Skmacy	printf("ANS:              %u\n", (data[2] >> 28) & 1);
728167518Skmacy	printf("generation:       %u\n", (data[2] >> 29) & 1);
729167518Skmacy	printf("overflow mode:    %u\n", (data[2] >> 31) & 1);
730167518Skmacy	printf("credits:          %u\n", data[3] & 0xffff);
731167518Skmacy	printf("credit threshold: %u\n", data[3] >> 16);
732167518Skmacy}
733167518Skmacy
734204267Snpstatic int
735204267Snpget_sge_context(int argc, char *argv[], int start_arg, const char *iff_name)
736167518Skmacy{
737167518Skmacy	struct ch_cntxt ctx;
738167518Skmacy
739167518Skmacy	if (argc != start_arg + 2) return -1;
740167518Skmacy
741167518Skmacy	if (!strcmp(argv[start_arg], "egress"))
742167518Skmacy		ctx.cntxt_type = CNTXT_TYPE_EGRESS;
743167518Skmacy	else if (!strcmp(argv[start_arg], "fl"))
744167518Skmacy		ctx.cntxt_type = CNTXT_TYPE_FL;
745167518Skmacy	else if (!strcmp(argv[start_arg], "response"))
746167518Skmacy		ctx.cntxt_type = CNTXT_TYPE_RSP;
747167518Skmacy	else if (!strcmp(argv[start_arg], "cq"))
748167518Skmacy		ctx.cntxt_type = CNTXT_TYPE_CQ;
749167518Skmacy	else {
750167518Skmacy		warnx("unknown context type \"%s\"; known types are egress, "
751167518Skmacy		      "fl, cq, and response", argv[start_arg]);
752167518Skmacy		return -1;
753167518Skmacy	}
754167518Skmacy
755167518Skmacy	if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
756167518Skmacy		return -1;
757167518Skmacy
758167518Skmacy	if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
759167518Skmacy		err(1, "get SGE context");
760167518Skmacy
761167518Skmacy	if (!strcmp(argv[start_arg], "egress"))
762167518Skmacy		show_egress_cntxt(ctx.data);
763167518Skmacy	else if (!strcmp(argv[start_arg], "fl"))
764167518Skmacy		show_fl_cntxt(ctx.data);
765167518Skmacy	else if (!strcmp(argv[start_arg], "response"))
766167518Skmacy		show_response_cntxt(ctx.data);
767167518Skmacy	else if (!strcmp(argv[start_arg], "cq"))
768167518Skmacy		show_cq_cntxt(ctx.data);
769167518Skmacy	return 0;
770167518Skmacy}
771167518Skmacy
772182899Skmacy#define ntohll(x) be64toh((x))
773167518Skmacy
774204267Snpstatic int
775204267Snpget_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name)
776167518Skmacy{
777167518Skmacy	uint64_t *p, wr_hdr;
778167518Skmacy	unsigned int n = 1, qset, qnum;
779167518Skmacy	struct ch_desc desc;
780167518Skmacy
781167518Skmacy	if (argc != start_arg + 3 && argc != start_arg + 4)
782167518Skmacy		return -1;
783167518Skmacy
784167518Skmacy	if (get_int_arg(argv[start_arg], &qset) ||
785167518Skmacy	    get_int_arg(argv[start_arg + 1], &qnum) ||
786167518Skmacy	    get_int_arg(argv[start_arg + 2], &desc.idx))
787167518Skmacy		return -1;
788167518Skmacy
789167518Skmacy	if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
790167518Skmacy		return -1;
791167518Skmacy
792167518Skmacy	if (qnum > 5)
793167518Skmacy		errx(1, "invalid queue number %d, range is 0..5", qnum);
794167518Skmacy
795167518Skmacy	desc.queue_num = qset * 6 + qnum;
796167518Skmacy
797167518Skmacy	for (; n--; desc.idx++) {
798167518Skmacy		if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
799167518Skmacy			err(1, "get SGE descriptor");
800167518Skmacy
801167518Skmacy		p = (uint64_t *)desc.data;
802167518Skmacy		wr_hdr = ntohll(*p);
803167518Skmacy		printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
804167518Skmacy		       desc.idx, (unsigned int)(wr_hdr >> 56),
805167518Skmacy		       ((unsigned int)wr_hdr >> 8) & 0xfffff,
806167518Skmacy		       ((wr_hdr >> 55) & 1) ? "SOP, " : "",
807167518Skmacy		       ((wr_hdr >> 54) & 1) ? "EOP, " : "",
808167518Skmacy		       ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
809167518Skmacy		       ((wr_hdr >> 52) & 1) ? "SGL, " : "",
810167518Skmacy		       (unsigned int)wr_hdr & 0xff);
811167518Skmacy
812167518Skmacy		for (; desc.size; p++, desc.size -= sizeof(uint64_t))
813167518Skmacy			printf("%016" PRIx64 "%c", ntohll(*p),
814167518Skmacy			    desc.size % 32 == 8 ? '\n' : ' ');
815167518Skmacy	}
816167518Skmacy	return 0;
817167518Skmacy}
818167518Skmacy#endif
819167518Skmacy
820204267Snpstatic int
821204267Snpget_tcb2(int argc, char *argv[], int start_arg, const char *iff_name)
822167518Skmacy{
823167518Skmacy	uint64_t *d;
824167518Skmacy	unsigned int i;
825182594Skmacy	unsigned int tcb_idx;
826182594Skmacy	struct ch_mem_range mr;
827167518Skmacy
828182594Skmacy	if (argc != start_arg + 1)
829182594Skmacy		return -1;
830182594Skmacy
831182594Skmacy	if (get_int_arg(argv[start_arg], &tcb_idx))
832182594Skmacy		return -1;
833182594Skmacy
834182594Skmacy	mr.buf = calloc(1, TCB_SIZE);
835182594Skmacy	if (!mr.buf)
836167518Skmacy		err(1, "get TCB");
837167518Skmacy
838182594Skmacy	mr.mem_id = MEM_CM;
839182594Skmacy	mr.addr   = tcb_idx * TCB_SIZE;
840182594Skmacy	mr.len    = TCB_SIZE;
841167518Skmacy
842182594Skmacy	if (doit(iff_name, CHELSIO_GET_MEM, &mr) < 0)
843167518Skmacy		err(1, "get TCB");
844167518Skmacy
845182899Skmacy	for (d = (uint64_t *)mr.buf, i = 0; i < TCB_SIZE / 32; i++) {
846167518Skmacy		printf("%2u:", i);
847167518Skmacy		printf(" %08x %08x %08x %08x", (uint32_t)d[1],
848167518Skmacy		       (uint32_t)(d[1] >> 32), (uint32_t)d[0],
849167518Skmacy		       (uint32_t)(d[0] >> 32));
850167518Skmacy		d += 2;
851167518Skmacy		printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
852167518Skmacy		       (uint32_t)(d[1] >> 32), (uint32_t)d[0],
853167518Skmacy		       (uint32_t)(d[0] >> 32));
854167518Skmacy		d += 2;
855167518Skmacy	}
856182594Skmacy	free(mr.buf);
857167518Skmacy	return 0;
858167518Skmacy}
859167518Skmacy
860204267Snpstatic int
861204267Snpget_pm_page_spec(const char *s, unsigned int *page_size,
862204267Snp    unsigned int *num_pages)
863167518Skmacy{
864167518Skmacy	char *p;
865167518Skmacy	unsigned long val;
866167518Skmacy
867167518Skmacy	val = strtoul(s, &p, 0);
868167518Skmacy	if (p == s) return -1;
869167518Skmacy	if (*p == 'x' && p[1]) {
870167518Skmacy		*num_pages = val;
871167518Skmacy		*page_size = strtoul(p + 1, &p, 0);
872167518Skmacy	} else {
873167518Skmacy		*num_pages = -1;
874167518Skmacy		*page_size = val;
875167518Skmacy	}
876167518Skmacy	*page_size <<= 10;     // KB -> bytes
877167518Skmacy	return *p;
878167518Skmacy}
879167518Skmacy
880204267Snpstatic int
881204267Snpconf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
882167518Skmacy{
883182594Skmacy	struct ch_pm pm;
884167518Skmacy
885167518Skmacy	if (argc == start_arg) {
886182594Skmacy		if (doit(iff_name, CHELSIO_GET_PM, &pm) < 0)
887167518Skmacy			err(1, "read pm config");
888167518Skmacy		printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
889182594Skmacy		       pm.tx_num_pg, pm.tx_pg_sz >> 10, pm.rx_num_pg,
890182594Skmacy		       pm.rx_pg_sz >> 10, pm.pm_total >> 10);
891167518Skmacy		return 0;
892167518Skmacy	}
893167518Skmacy
894167518Skmacy	if (argc != start_arg + 2) return -1;
895167518Skmacy
896182594Skmacy	if (get_pm_page_spec(argv[start_arg], &pm.tx_pg_sz, &pm.tx_num_pg)) {
897167518Skmacy		warnx("bad parameter \"%s\"", argv[start_arg]);
898167518Skmacy		return -1;
899167518Skmacy	}
900182594Skmacy	if (get_pm_page_spec(argv[start_arg + 1], &pm.rx_pg_sz,
901182594Skmacy			     &pm.rx_num_pg)) {
902167518Skmacy		warnx("bad parameter \"%s\"", argv[start_arg + 1]);
903167518Skmacy		return -1;
904167518Skmacy	}
905182594Skmacy	if (doit(iff_name, CHELSIO_SET_PM, &pm) < 0)
906167518Skmacy		err(1, "pm config");
907167518Skmacy	return 0;
908167518Skmacy}
909167518Skmacy
910167518Skmacy#ifdef	CHELSIO_INTERNAL
911204267Snpstatic int
912204267Snpdump_tcam(int argc, char *argv[], int start_arg, const char *iff_name)
913167518Skmacy{
914167518Skmacy	unsigned int nwords;
915182594Skmacy	struct ch_tcam_word op;
916167518Skmacy
917167518Skmacy	if (argc != start_arg + 2) return -1;
918167518Skmacy
919167518Skmacy	if (get_int_arg(argv[start_arg], &op.addr) ||
920167518Skmacy	    get_int_arg(argv[start_arg + 1], &nwords))
921167518Skmacy		return -1;
922167518Skmacy
923167518Skmacy	while (nwords--) {
924182594Skmacy		if (doit(iff_name, CHELSIO_READ_TCAM_WORD, &op) < 0)
925167518Skmacy			err(1, "tcam dump");
926167518Skmacy
927167518Skmacy		printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
928167518Skmacy		       op.buf[0] & 0xff, op.buf[1], op.buf[2]);
929167518Skmacy		op.addr++;
930167518Skmacy	}
931167518Skmacy	return 0;
932167518Skmacy}
933182594Skmacy
934204267Snpstatic void
935204267Snphexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
936167518Skmacy{
937167518Skmacy	int i;
938167518Skmacy
939167518Skmacy	while (len) {
940167518Skmacy		printf("0x%08x:", start);
941167518Skmacy		for (i = 0; i < 4 && len; ++i, --len)
942167518Skmacy			printf(" %016llx", (unsigned long long)*data++);
943167518Skmacy		printf("\n");
944167518Skmacy		start += 32;
945167518Skmacy	}
946167518Skmacy}
947167518Skmacy
948204267Snpstatic int
949204267Snpdump_mc7(int argc, char *argv[], int start_arg, const char *iff_name)
950167518Skmacy{
951167518Skmacy	struct ch_mem_range mem;
952167518Skmacy	unsigned int mem_id, addr, len;
953167518Skmacy
954167518Skmacy	if (argc != start_arg + 3) return -1;
955167518Skmacy
956167518Skmacy	if (!strcmp(argv[start_arg], "cm"))
957167518Skmacy		mem_id = MEM_CM;
958167518Skmacy	else if (!strcmp(argv[start_arg], "rx"))
959167518Skmacy		mem_id = MEM_PMRX;
960167518Skmacy	else if (!strcmp(argv[start_arg], "tx"))
961167518Skmacy		mem_id = MEM_PMTX;
962167518Skmacy	else
963167518Skmacy		errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
964167518Skmacy			" or \"rx\"", argv[start_arg]);
965167518Skmacy
966167518Skmacy	if (get_int_arg(argv[start_arg + 1], &addr) ||
967167518Skmacy	    get_int_arg(argv[start_arg + 2], &len))
968167518Skmacy		return -1;
969167518Skmacy
970167518Skmacy	mem.buf = malloc(len);
971167518Skmacy	if (!mem.buf)
972167518Skmacy		err(1, "memory dump");
973167518Skmacy
974167518Skmacy	mem.mem_id = mem_id;
975167518Skmacy	mem.addr   = addr;
976167518Skmacy	mem.len    = len;
977167518Skmacy
978167518Skmacy	if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
979167518Skmacy		err(1, "memory dump");
980167518Skmacy
981167518Skmacy	hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
982167518Skmacy	free(mem.buf);
983167518Skmacy	return 0;
984167518Skmacy}
985167518Skmacy#endif
986167518Skmacy
987204267Snp/* Max FW size is 64K including version, +4 bytes for the checksum. */
988189643Sgnn#define MAX_FW_IMAGE_SIZE (64 * 1024)
989167518Skmacy
990204267Snpstatic int
991204267Snpload_fw(int argc, char *argv[], int start_arg, const char *iff_name)
992167518Skmacy{
993167518Skmacy	int fd, len;
994182594Skmacy	struct ch_mem_range op;
995167518Skmacy	const char *fname = argv[start_arg];
996167518Skmacy
997167518Skmacy	if (argc != start_arg + 1) return -1;
998167518Skmacy
999167518Skmacy	fd = open(fname, O_RDONLY);
1000167518Skmacy	if (fd < 0)
1001167518Skmacy		err(1, "load firmware");
1002167518Skmacy
1003182594Skmacy	bzero(&op, sizeof(op));
1004182594Skmacy	op.buf = malloc(MAX_FW_IMAGE_SIZE + 1);
1005182594Skmacy	if (!op.buf)
1006167518Skmacy		err(1, "load firmware");
1007167518Skmacy
1008204267Snp	len = read(fd, op.buf, MAX_FW_IMAGE_SIZE + 1);
1009204267Snp	if (len < 0)
1010167518Skmacy		err(1, "load firmware");
1011204267Snp 	if (len > MAX_FW_IMAGE_SIZE)
1012167518Skmacy		errx(1, "FW image too large");
1013167518Skmacy
1014204267Snp	op.len = len;
1015182594Skmacy	if (doit(iff_name, CHELSIO_LOAD_FW, &op) < 0)
1016167518Skmacy		err(1, "load firmware");
1017216285Skevlo
1018216285Skevlo	close(fd);
1019167518Skmacy	return 0;
1020167518Skmacy}
1021167518Skmacy
1022182594Skmacy/* Max BOOT size is 255*512 bytes including the BIOS boot ROM basic header */
1023182594Skmacy#define MAX_BOOT_IMAGE_SIZE (0xff * 512)
1024167518Skmacy
1025204267Snpstatic int
1026204267Snpload_boot(int argc, char *argv[], int start_arg, const char *iff_name)
1027167518Skmacy{
1028182594Skmacy	int fd, len;
1029182594Skmacy	struct ch_mem_range op;
1030182594Skmacy	const char *fname = argv[start_arg];
1031167518Skmacy
1032182594Skmacy	if (argc != start_arg + 1) return -1;
1033167518Skmacy
1034182594Skmacy	fd = open(fname, O_RDONLY);
1035182594Skmacy	if (fd < 0)
1036182594Skmacy		err(1, "load boot image");
1037167518Skmacy
1038182594Skmacy	op.buf = malloc(MAX_BOOT_IMAGE_SIZE + 1);
1039182594Skmacy	if (!op.buf)
1040182594Skmacy		err(1, "load boot image");
1041182594Skmacy
1042182594Skmacy	len = read(fd, op.buf, MAX_BOOT_IMAGE_SIZE + 1);
1043182594Skmacy	if (len < 0)
1044182594Skmacy		err(1, "load boot image");
1045182594Skmacy 	if (len > MAX_BOOT_IMAGE_SIZE)
1046182594Skmacy		errx(1, "boot image too large");
1047182594Skmacy
1048182594Skmacy	op.len = len;
1049182594Skmacy
1050182594Skmacy	if (doit(iff_name, CHELSIO_LOAD_BOOT, &op) < 0)
1051182594Skmacy		err(1, "load boot image");
1052182594Skmacy
1053216285Skevlo	close(fd);
1054167518Skmacy	return 0;
1055167518Skmacy}
1056167518Skmacy
1057204267Snpstatic int
1058204267Snpdump_proto_sram(const char *iff_name)
1059167518Skmacy{
1060167518Skmacy	int i, j;
1061182594Skmacy	uint8_t buf[PROTO_SRAM_SIZE];
1062182594Skmacy	struct ch_eeprom ee;
1063182594Skmacy	uint8_t *p = buf;
1064167518Skmacy
1065182594Skmacy	bzero(buf, sizeof(buf));
1066182594Skmacy	ee.offset = PROTO_SRAM_EEPROM_ADDR;
1067182594Skmacy	ee.data = p;
1068182594Skmacy	ee.len = sizeof(buf);
1069182594Skmacy	if (doit(iff_name, CHELSIO_GET_EEPROM, &ee))
1070167518Skmacy		err(1, "show protocol sram");
1071167518Skmacy
1072167518Skmacy	for (i = 0; i < PROTO_SRAM_LINES; i++) {
1073167518Skmacy		for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1074167518Skmacy			int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1075182594Skmacy			uint8_t nibble = p[nibble_idx / 2];
1076167518Skmacy
1077167518Skmacy			if (nibble_idx & 1)
1078167518Skmacy				nibble >>= 4;
1079167518Skmacy			else
1080167518Skmacy				nibble &= 0xf;
1081167518Skmacy			printf("%x", nibble);
1082167518Skmacy		}
1083167518Skmacy		putchar('\n');
1084167518Skmacy	}
1085167518Skmacy	return 0;
1086167518Skmacy}
1087167518Skmacy
1088204267Snpstatic int
1089204267Snpproto_sram_op(int argc, char *argv[], int start_arg,
1090167518Skmacy			 const char *iff_name)
1091167518Skmacy{
1092204267Snp	(void) argv;
1093204267Snp	(void) start_arg;
1094204267Snp
1095167518Skmacy	if (argc == start_arg)
1096167518Skmacy		return dump_proto_sram(iff_name);
1097167518Skmacy	return -1;
1098167518Skmacy}
1099167518Skmacy
1100204267Snpstatic int
1101204267Snpdump_qset_params(const char *iff_name)
1102167518Skmacy{
1103167518Skmacy	struct ch_qset_params qp;
1104167518Skmacy
1105167518Skmacy	qp.qset_idx = 0;
1106167518Skmacy
1107167518Skmacy	while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1108167518Skmacy		if (!qp.qset_idx)
1109182594Skmacy			printf("Qset   TxQ0   TxQ1   TxQ2   RspQ   RxQ0   RxQ1"
1110182594Skmacy			       "  Cong  Lat   IRQ\n");
1111182594Skmacy		printf("%4u %6u %6u %6u %6u %6u %6u %5u %4u %5d\n",
1112182594Skmacy		       qp.qnum,
1113167518Skmacy		       qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1114167518Skmacy		       qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1115182594Skmacy		       qp.cong_thres, qp.intr_lat, qp.vector);
1116167518Skmacy		qp.qset_idx++;
1117167518Skmacy	}
1118167518Skmacy	if (!qp.qset_idx || (errno && errno != EINVAL))
1119167518Skmacy		err(1, "get qset parameters");
1120167518Skmacy	return 0;
1121167518Skmacy}
1122167518Skmacy
1123204267Snpstatic int
1124204267Snpqset_config(int argc, char *argv[], int start_arg, const char *iff_name)
1125167518Skmacy{
1126204267Snp	(void) argv;
1127167518Skmacy
1128167518Skmacy	if (argc == start_arg)
1129167518Skmacy		return dump_qset_params(iff_name);
1130167518Skmacy
1131182594Skmacy	return -1;
1132167518Skmacy}
1133167518Skmacy
1134204267Snpstatic int
1135204267Snpqset_num_config(int argc, char *argv[], int start_arg, const char *iff_name)
1136167518Skmacy{
1137167518Skmacy	struct ch_reg reg;
1138167518Skmacy
1139204267Snp	(void) argv;
1140204267Snp
1141167518Skmacy	if (argc == start_arg) {
1142167518Skmacy		if (doit(iff_name, CHELSIO_GET_QSET_NUM, &reg) < 0)
1143167518Skmacy			err(1, "get qsets");
1144167518Skmacy		printf("%u\n", reg.val);
1145167518Skmacy		return 0;
1146167518Skmacy	}
1147167518Skmacy
1148182594Skmacy	return -1;
1149167518Skmacy}
1150167518Skmacy
1151167518Skmacy/*
1152167518Skmacy * Parse a string containing an IP address with an optional network prefix.
1153167518Skmacy */
1154204267Snpstatic int
1155204267Snpparse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1156167518Skmacy{
1157167518Skmacy	char *p, *slash;
1158167518Skmacy	struct in_addr ia;
1159167518Skmacy
1160167518Skmacy	*mask = 0xffffffffU;
1161167518Skmacy	slash = strchr(s, '/');
1162167518Skmacy	if (slash)
1163167518Skmacy		*slash = 0;
1164167518Skmacy	if (!inet_aton(s, &ia)) {
1165167518Skmacy		if (slash)
1166167518Skmacy			*slash = '/';
1167167518Skmacy		*addr = 0;
1168167518Skmacy		return -1;
1169167518Skmacy	}
1170167518Skmacy	*addr = ntohl(ia.s_addr);
1171167518Skmacy	if (slash) {
1172167518Skmacy		unsigned int prefix = strtoul(slash + 1, &p, 10);
1173167518Skmacy
1174167518Skmacy		*slash = '/';
1175167518Skmacy		if (p == slash + 1 || *p || prefix > 32)
1176167518Skmacy			return -1;
1177167518Skmacy		*mask <<= (32 - prefix);
1178167518Skmacy	}
1179167518Skmacy	return 0;
1180167518Skmacy}
1181167518Skmacy
1182167518Skmacy/*
1183167518Skmacy * Parse a string containing a value and an optional colon separated mask.
1184167518Skmacy */
1185204267Snpstatic int
1186207643Snpparse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
1187207643Snp    uint32_t default_mask)
1188167518Skmacy{
1189167518Skmacy	char *p;
1190167518Skmacy
1191207643Snp	*mask = default_mask;
1192167518Skmacy	*val = strtoul(s, &p, 0);
1193207643Snp	if (p == s || *val > default_mask)
1194167518Skmacy		return -1;
1195167518Skmacy	if (*p == ':' && p[1])
1196167518Skmacy		*mask = strtoul(p + 1, &p, 0);
1197207643Snp	return *p || *mask > default_mask ? -1 : 0;
1198167518Skmacy}
1199167518Skmacy
1200204267Snpstatic int
1201204267Snpparse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1202167518Skmacy{
1203167518Skmacy	return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1204207643Snp				parse_val_mask_param(s, val, mask, 0xffffffffU);
1205167518Skmacy}
1206167518Skmacy
1207204267Snpstatic int
1208204267Snptrace_config(int argc, char *argv[], int start_arg, const char *iff_name)
1209167518Skmacy{
1210167518Skmacy	uint32_t val, mask;
1211167518Skmacy	struct ch_trace trace;
1212167518Skmacy
1213167518Skmacy	if (argc == start_arg)
1214167518Skmacy		return -1;
1215167518Skmacy
1216167518Skmacy	memset(&trace, 0, sizeof(trace));
1217167518Skmacy	if (!strcmp(argv[start_arg], "tx"))
1218167518Skmacy		trace.config_tx = 1;
1219167518Skmacy	else if (!strcmp(argv[start_arg], "rx"))
1220167518Skmacy		trace.config_rx = 1;
1221167518Skmacy	else if (!strcmp(argv[start_arg], "all"))
1222167518Skmacy		trace.config_tx = trace.config_rx = 1;
1223167518Skmacy	else
1224167518Skmacy		errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1225167518Skmacy		     "\"tx\" or \"all\"", argv[start_arg]);
1226167518Skmacy
1227167518Skmacy	if (argc == ++start_arg)
1228167518Skmacy		return -1;
1229167518Skmacy	if (!strcmp(argv[start_arg], "on")) {
1230167518Skmacy		trace.trace_tx = trace.config_tx;
1231167518Skmacy		trace.trace_rx = trace.config_rx;
1232167518Skmacy	} else if (strcmp(argv[start_arg], "off"))
1233167518Skmacy		errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1234167518Skmacy		     argv[start_arg]);
1235167518Skmacy
1236167518Skmacy	start_arg++;
1237167518Skmacy	if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1238167518Skmacy		trace.invert_match = 1;
1239167518Skmacy		start_arg++;
1240167518Skmacy	}
1241167518Skmacy
1242167518Skmacy	while (start_arg + 2 <= argc) {
1243167518Skmacy		int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1244167518Skmacy
1245167518Skmacy		if (!strcmp(argv[start_arg], "interface")) {
1246167518Skmacy			trace.intf = val;
1247167518Skmacy			trace.intf_mask = mask;
1248167518Skmacy		} else if (!strcmp(argv[start_arg], "sip")) {
1249167518Skmacy			trace.sip = val;
1250167518Skmacy			trace.sip_mask = mask;
1251167518Skmacy		} else if (!strcmp(argv[start_arg], "dip")) {
1252167518Skmacy			trace.dip = val;
1253167518Skmacy			trace.dip_mask = mask;
1254167518Skmacy		} else if (!strcmp(argv[start_arg], "sport")) {
1255167518Skmacy			trace.sport = val;
1256167518Skmacy			trace.sport_mask = mask;
1257167518Skmacy		} else if (!strcmp(argv[start_arg], "dport")) {
1258167518Skmacy			trace.dport = val;
1259167518Skmacy			trace.dport_mask = mask;
1260167518Skmacy		} else if (!strcmp(argv[start_arg], "vlan")) {
1261167518Skmacy			trace.vlan = val;
1262167518Skmacy			trace.vlan_mask = mask;
1263167518Skmacy		} else if (!strcmp(argv[start_arg], "proto")) {
1264167518Skmacy			trace.proto = val;
1265167518Skmacy			trace.proto_mask = mask;
1266167518Skmacy		} else
1267167518Skmacy			errx(1, "unknown trace parameter \"%s\"\n"
1268167518Skmacy			     "known parameters are \"interface\", \"sip\", "
1269167518Skmacy			     "\"dip\", \"sport\", \"dport\", \"vlan\", "
1270167518Skmacy			     "\"proto\"", argv[start_arg]);
1271167518Skmacy		if (ret < 0)
1272167518Skmacy			errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1273167518Skmacy		start_arg += 2;
1274167518Skmacy	}
1275167518Skmacy	if (start_arg != argc)
1276167518Skmacy		errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1277167518Skmacy
1278167518Skmacy	if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1279167518Skmacy		err(1, "trace");
1280167518Skmacy	return 0;
1281167518Skmacy}
1282167518Skmacy
1283207643Snpstatic void
1284207643Snpshow_filters(const char *iff_name)
1285207643Snp{
1286207643Snp	static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
1287207643Snp	struct ch_filter op;
1288207643Snp	union {
1289207643Snp		uint32_t nip;
1290207643Snp		uint8_t octet[4];
1291207643Snp	} nsip, ndip;
1292207643Snp	char sip[20], dip[20];
1293207643Snp	int header = 0;
1294207643Snp
1295207643Snp	bzero(&op, sizeof(op));
1296207643Snp	op.filter_id = 0xffffffff;
1297207643Snp
1298207643Snp	do {
1299207643Snp		if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
1300207643Snp			err(1, "list filters");
1301207643Snp
1302207643Snp		if (op.filter_id == 0xffffffff)
1303207643Snp			break;
1304207643Snp
1305207643Snp		if (!header) {
1306207643Snp			printf("index         SIP                DIP     sport "
1307207643Snp			    "dport VLAN PRI P/MAC type Q\n");
1308207643Snp			header = 1;
1309207643Snp		}
1310207643Snp
1311207643Snp		nsip.nip = htonl(op.val.sip);
1312207643Snp		ndip.nip = htonl(op.val.dip);
1313207643Snp
1314207643Snp		sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1],
1315207643Snp		    nsip.octet[2], nsip.octet[3],
1316207643Snp		    op.mask.sip ? 33 - ffs(op.mask.sip) : 0);
1317207643Snp		sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1],
1318207643Snp		    ndip.octet[2], ndip.octet[3]);
1319207643Snp		printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip);
1320207643Snp		printf(op.val.sport ? "%5u " : "    * ", op.val.sport);
1321207643Snp		printf(op.val.dport ? "%5u " : "    * ", op.val.dport);
1322207643Snp		printf(op.val.vlan != 0xfff ? "%4u " : "   * ", op.val.vlan);
1323207643Snp		printf(op.val.vlan_prio == 7 ?  "  * " :
1324207643Snp		    "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1);
1325207643Snp		if (op.mac_addr_idx == 0xffff)
1326207643Snp			printf("*/*   ");
1327207643Snp		else if (op.mac_hit)
1328207643Snp			printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
1329207643Snp			    (op.mac_addr_idx) & 0x7);
1330207643Snp		else
1331207643Snp			printf("%1u/  * ", (op.mac_addr_idx >> 3) & 0x1);
1332207643Snp		printf("%4s ", pkt_type[op.proto]);
1333207643Snp		if (!op.pass)
1334207643Snp			printf("-\n");
1335207643Snp		else if (op.rss)
1336207643Snp			printf("*\n");
1337207643Snp		else
1338207643Snp			printf("%1u\n", op.qset);
1339207643Snp	} while (1);
1340207643Snp}
1341207643Snp
1342204267Snpstatic int
1343207643Snpfilter_config(int argc, char *argv[], int start_arg, const char *iff_name)
1344207643Snp{
1345207643Snp	int ret = 0;
1346207643Snp	uint32_t val, mask;
1347207643Snp	struct ch_filter op;
1348207643Snp
1349207643Snp	if (argc < start_arg + 1)
1350207643Snp		return -1;
1351207643Snp
1352207643Snp	memset(&op, 0, sizeof(op));
1353207643Snp	op.mac_addr_idx = 0xffff;
1354207643Snp	op.rss = 1;
1355207643Snp
1356207643Snp	if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
1357207643Snp		show_filters(iff_name);
1358207643Snp		return 0;
1359207643Snp	}
1360207643Snp
1361207643Snp	if (get_int_arg(argv[start_arg++], &op.filter_id))
1362207643Snp		return -1;
1363207643Snp	if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") ||
1364207643Snp				      !strcmp(argv[start_arg], "clear"))) {
1365207643Snp		if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) {
1366207643Snp			if (errno == EBUSY)
1367207643Snp				err(1, "no filter support when offload in use");
1368207643Snp			err(1, "delete filter");
1369207643Snp		}
1370207643Snp		return 0;
1371207643Snp	}
1372207643Snp
1373207643Snp	while (start_arg + 2 <= argc) {
1374207643Snp		if (!strcmp(argv[start_arg], "sip")) {
1375207643Snp			ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
1376207643Snp					   &op.mask.sip);
1377207643Snp		} else if (!strcmp(argv[start_arg], "dip")) {
1378207643Snp			ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
1379207643Snp					   &op.mask.dip);
1380207643Snp		} else if (!strcmp(argv[start_arg], "sport")) {
1381207643Snp			ret = parse_val_mask_param(argv[start_arg + 1],
1382207643Snp						   &val, &mask, 0xffff);
1383207643Snp			op.val.sport = val;
1384207643Snp			op.mask.sport = mask;
1385207643Snp		} else if (!strcmp(argv[start_arg], "dport")) {
1386207643Snp			ret = parse_val_mask_param(argv[start_arg + 1],
1387207643Snp						   &val, &mask, 0xffff);
1388207643Snp			op.val.dport = val;
1389207643Snp			op.mask.dport = mask;
1390207643Snp		} else if (!strcmp(argv[start_arg], "vlan")) {
1391207643Snp			ret = parse_val_mask_param(argv[start_arg + 1],
1392207643Snp						   &val, &mask, 0xfff);
1393207643Snp			op.val.vlan = val;
1394207643Snp			op.mask.vlan = mask;
1395207643Snp		} else if (!strcmp(argv[start_arg], "prio")) {
1396207643Snp			ret = parse_val_mask_param(argv[start_arg + 1],
1397207643Snp						   &val, &mask, 7);
1398207643Snp			op.val.vlan_prio = val;
1399207643Snp			op.mask.vlan_prio = mask;
1400207643Snp		} else if (!strcmp(argv[start_arg], "mac")) {
1401207643Snp			if (!strcmp(argv[start_arg + 1], "none"))
1402207643Snp				val = -1;
1403207643Snp			else
1404207643Snp				ret = get_int_arg(argv[start_arg + 1], &val);
1405207643Snp			op.mac_hit = val != (uint32_t)-1;
1406207643Snp			op.mac_addr_idx = op.mac_hit ? val : 0;
1407207643Snp		} else if (!strcmp(argv[start_arg], "type")) {
1408207643Snp			if (!strcmp(argv[start_arg + 1], "tcp"))
1409207643Snp				op.proto = 1;
1410207643Snp			else if (!strcmp(argv[start_arg + 1], "udp"))
1411207643Snp				op.proto = 2;
1412207643Snp			else if (!strcmp(argv[start_arg + 1], "frag"))
1413207643Snp				op.proto = 3;
1414207643Snp			else
1415207643Snp				errx(1, "unknown type \"%s\"; must be one of "
1416207643Snp				     "\"tcp\", \"udp\", or \"frag\"",
1417207643Snp				     argv[start_arg + 1]);
1418207643Snp		} else if (!strcmp(argv[start_arg], "queue")) {
1419207643Snp			ret = get_int_arg(argv[start_arg + 1], &val);
1420207643Snp			op.qset = val;
1421207643Snp			op.rss = 0;
1422207643Snp		} else if (!strcmp(argv[start_arg], "action")) {
1423207643Snp			if (!strcmp(argv[start_arg + 1], "pass"))
1424207643Snp				op.pass = 1;
1425207643Snp			else if (strcmp(argv[start_arg + 1], "drop"))
1426207643Snp				errx(1, "unknown action \"%s\"; must be one of "
1427207643Snp				     "\"pass\" or \"drop\"",
1428207643Snp				     argv[start_arg + 1]);
1429207643Snp		} else
1430207643Snp 			errx(1, "unknown filter parameter \"%s\"\n"
1431207643Snp			     "known parameters are \"mac\", \"sip\", "
1432207643Snp			     "\"dip\", \"sport\", \"dport\", \"vlan\", "
1433207643Snp			     "\"prio\", \"type\", \"queue\", and \"action\"",
1434207643Snp			     argv[start_arg]);
1435207643Snp		if (ret < 0)
1436207643Snp			errx(1, "bad value \"%s\" for parameter \"%s\"",
1437207643Snp			     argv[start_arg + 1], argv[start_arg]);
1438207643Snp		start_arg += 2;
1439207643Snp	}
1440207643Snp	if (start_arg != argc)
1441207643Snp		errx(1, "no value for \"%s\"", argv[start_arg]);
1442207643Snp
1443207643Snp	if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
1444207643Snp		if (errno == EBUSY)
1445207643Snp			err(1, "no filter support when offload in use");
1446207643Snp		err(1, "set filter");
1447207643Snp	}
1448207643Snp
1449207643Snp	return 0;
1450207643Snp}
1451207643Snpstatic int
1452204267Snpget_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
1453167518Skmacy{
1454182594Skmacy	if (pos + 1 >= argc)
1455182594Skmacy		errx(1, "missing value for %s", argv[pos]);
1456182594Skmacy	if (get_int_arg(argv[pos + 1], valp))
1457182594Skmacy		exit(1);
1458182594Skmacy	return 0;
1459182594Skmacy}
1460167518Skmacy
1461204267Snpstatic int
1462204267Snptx_sched(int argc, char *argv[], int start_arg, const char *iff_name)
1463182594Skmacy{
1464182594Skmacy	struct ch_hw_sched op;
1465182594Skmacy	unsigned int idx, val;
1466167518Skmacy
1467182594Skmacy	if (argc < 5 || get_int_arg(argv[start_arg++], &idx))
1468167518Skmacy		return -1;
1469182594Skmacy
1470182594Skmacy	op.sched = idx;
1471182594Skmacy	op.mode = op.channel = -1;
1472182594Skmacy	op.kbps = op.class_ipg = op.flow_ipg = -1;
1473182594Skmacy
1474182594Skmacy	while (argc > start_arg) {
1475182594Skmacy		if (!strcmp(argv[start_arg], "mode")) {
1476182594Skmacy			if (start_arg + 1 >= argc)
1477182594Skmacy				errx(1, "missing value for mode");
1478182594Skmacy			if (!strcmp(argv[start_arg + 1], "class"))
1479182594Skmacy				op.mode = 0;
1480182594Skmacy			else if (!strcmp(argv[start_arg + 1], "flow"))
1481182594Skmacy				op.mode = 1;
1482182594Skmacy			else
1483182594Skmacy				errx(1, "bad mode \"%s\"", argv[start_arg + 1]);
1484182594Skmacy		} else if (!strcmp(argv[start_arg], "channel") &&
1485182594Skmacy			 !get_sched_param(argc, argv, start_arg, &val))
1486182594Skmacy			op.channel = val;
1487182594Skmacy		else if (!strcmp(argv[start_arg], "rate") &&
1488182594Skmacy			 !get_sched_param(argc, argv, start_arg, &val))
1489182594Skmacy			op.kbps = val;
1490182594Skmacy		else if (!strcmp(argv[start_arg], "ipg") &&
1491182594Skmacy			 !get_sched_param(argc, argv, start_arg, &val))
1492182594Skmacy			op.class_ipg = val;
1493182594Skmacy		else if (!strcmp(argv[start_arg], "flowipg") &&
1494182594Skmacy			 !get_sched_param(argc, argv, start_arg, &val))
1495182594Skmacy			op.flow_ipg = val;
1496182594Skmacy		else
1497182594Skmacy			errx(1, "unknown scheduler parameter \"%s\"",
1498182594Skmacy			     argv[start_arg]);
1499182594Skmacy		start_arg += 2;
1500167518Skmacy	}
1501167518Skmacy
1502182594Skmacy	if (doit(iff_name, CHELSIO_SET_HW_SCHED, &op) < 0)
1503182594Skmacy		 err(1, "pktsched");
1504167518Skmacy
1505167518Skmacy	return 0;
1506167518Skmacy}
1507167518Skmacy
1508204267Snpstatic int
1509204267Snppktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1510167518Skmacy{
1511182594Skmacy	struct ch_pktsched_params op;
1512167518Skmacy	unsigned int idx, min = -1, max, binding = -1;
1513167518Skmacy
1514182594Skmacy	if (argc < 4)
1515182594Skmacy		errx(1, "no scheduler specified");
1516182594Skmacy
1517167518Skmacy	if (!strcmp(argv[start_arg], "port")) {
1518167518Skmacy		if (argc != start_arg + 4)
1519167518Skmacy			return -1;
1520167518Skmacy		if (get_int_arg(argv[start_arg + 1], &idx) ||
1521167518Skmacy		    get_int_arg(argv[start_arg + 2], &min) ||
1522167518Skmacy		    get_int_arg(argv[start_arg + 3], &max))
1523167518Skmacy			return -1;
1524182594Skmacy		op.sched = 0;
1525167518Skmacy	} else if (!strcmp(argv[start_arg], "tunnelq")) {
1526167518Skmacy		if (argc != start_arg + 4)
1527167518Skmacy			return -1;
1528167518Skmacy		if (get_int_arg(argv[start_arg + 1], &idx) ||
1529167518Skmacy		    get_int_arg(argv[start_arg + 2], &max) ||
1530167518Skmacy		    get_int_arg(argv[start_arg + 3], &binding))
1531167518Skmacy			return -1;
1532182594Skmacy		op.sched = 1;
1533182594Skmacy	} else if (!strcmp(argv[start_arg], "tx"))
1534182594Skmacy		return tx_sched(argc, argv, start_arg + 1, iff_name);
1535182594Skmacy	else
1536182594Skmacy		errx(1, "unknown scheduler \"%s\"; must be one of \"port\", "
1537182594Skmacy			"\"tunnelq\" or \"tx\"", argv[start_arg]);
1538182594Skmacy
1539182594Skmacy	op.idx = idx;
1540182594Skmacy	op.min = min;
1541182594Skmacy	op.max = max;
1542182594Skmacy	op.binding = binding;
1543182594Skmacy	if (doit(iff_name, CHELSIO_SET_PKTSCHED, &op) < 0)
1544167518Skmacy		 err(1, "pktsched");
1545167518Skmacy
1546167518Skmacy	return 0;
1547167518Skmacy}
1548189643Sgnn
1549204267Snpstatic int
1550204267Snpclear_stats(int argc, char *argv[], int start_arg, const char *iff_name)
1551182594Skmacy{
1552204267Snp	(void) argc;
1553204267Snp	(void) argv;
1554204267Snp	(void) start_arg;
1555204267Snp
1556182594Skmacy	if (doit(iff_name, CHELSIO_CLEAR_STATS, NULL) < 0)
1557182594Skmacy		 err(1, "clearstats");
1558167518Skmacy
1559182594Skmacy	return 0;
1560182594Skmacy}
1561182594Skmacy
1562204267Snpstatic int
1563204267Snpget_up_la(int argc, char *argv[], int start_arg, const char *iff_name)
1564189643Sgnn{
1565189643Sgnn	struct ch_up_la la;
1566189643Sgnn	int i, idx, max_idx, entries;
1567189643Sgnn
1568204267Snp	(void) argc;
1569204267Snp	(void) argv;
1570204267Snp	(void) start_arg;
1571204267Snp
1572189643Sgnn	la.stopped = 0;
1573189643Sgnn	la.idx = -1;
1574189643Sgnn	la.bufsize = LA_BUFSIZE;
1575189643Sgnn	la.data = malloc(la.bufsize);
1576189643Sgnn	if (!la.data)
1577189643Sgnn		err(1, "uP_LA malloc");
1578189643Sgnn
1579189643Sgnn	if (doit(iff_name, CHELSIO_GET_UP_LA, &la) < 0)
1580189643Sgnn		 err(1, "uP_LA");
1581189643Sgnn
1582189643Sgnn	if (la.stopped)
1583189643Sgnn		printf("LA is not running\n");
1584189643Sgnn
1585189643Sgnn	entries = la.bufsize / 4;
1586189643Sgnn	idx = (int)la.idx;
1587189643Sgnn	max_idx = (entries / 4) - 1;
1588189643Sgnn	for (i = 0; i < max_idx; i++) {
1589189643Sgnn		printf("%04x %08x %08x\n",
1590189643Sgnn		       la.data[idx], la.data[idx+2], la.data[idx+1]);
1591189643Sgnn		idx = (idx + 4) & (entries - 1);
1592189643Sgnn	}
1593189643Sgnn
1594189643Sgnn	return 0;
1595189643Sgnn}
1596189643Sgnn
1597204267Snpstatic int
1598204267Snpget_up_ioqs(int argc, char *argv[], int start_arg, const char *iff_name)
1599189643Sgnn{
1600189643Sgnn	struct ch_up_ioqs ioqs;
1601189643Sgnn	int i, entries;
1602189643Sgnn
1603204267Snp	(void) argc;
1604204267Snp	(void) argv;
1605204267Snp	(void) start_arg;
1606204267Snp
1607189643Sgnn	bzero(&ioqs, sizeof(ioqs));
1608189643Sgnn	ioqs.bufsize = IOQS_BUFSIZE;
1609189643Sgnn	ioqs.data = malloc(IOQS_BUFSIZE);
1610189643Sgnn	if (!ioqs.data)
1611189643Sgnn		err(1, "uP_IOQs malloc");
1612189643Sgnn
1613189643Sgnn	if (doit(iff_name, CHELSIO_GET_UP_IOQS, &ioqs) < 0)
1614189643Sgnn		 err(1, "uP_IOQs");
1615189643Sgnn
1616189643Sgnn	printf("ioq_rx_enable   : 0x%08x\n", ioqs.ioq_rx_enable);
1617189643Sgnn	printf("ioq_tx_enable   : 0x%08x\n", ioqs.ioq_tx_enable);
1618189643Sgnn	printf("ioq_rx_status   : 0x%08x\n", ioqs.ioq_rx_status);
1619189643Sgnn	printf("ioq_tx_status   : 0x%08x\n", ioqs.ioq_tx_status);
1620189643Sgnn
1621189643Sgnn	entries = ioqs.bufsize / sizeof(struct t3_ioq_entry);
1622189643Sgnn	for (i = 0; i < entries; i++) {
1623189643Sgnn		printf("\nioq[%d].cp       : 0x%08x\n", i,
1624189643Sgnn		       ioqs.data[i].ioq_cp);
1625189643Sgnn		printf("ioq[%d].pp       : 0x%08x\n", i,
1626189643Sgnn		       ioqs.data[i].ioq_pp);
1627189643Sgnn		printf("ioq[%d].alen     : 0x%08x\n", i,
1628189643Sgnn		       ioqs.data[i].ioq_alen);
1629189643Sgnn		printf("ioq[%d].stats    : 0x%08x\n", i,
1630189643Sgnn		       ioqs.data[i].ioq_stats);
1631189643Sgnn		printf("  sop %u\n", ioqs.data[i].ioq_stats >> 16);
1632189643Sgnn		printf("  eop %u\n", ioqs.data[i].ioq_stats  & 0xFFFF);
1633189643Sgnn	}
1634189643Sgnn
1635189643Sgnn	return 0;
1636189643Sgnn}
1637189643Sgnn
1638194928Snpstatic int
1639194928Snprun_cmd(int argc, char *argv[], const char *iff_name)
1640167518Skmacy{
1641167518Skmacy	int r = -1;
1642167518Skmacy
1643167518Skmacy	if (!strcmp(argv[2], "reg"))
1644167518Skmacy		r = register_io(argc, argv, 3, iff_name);
1645167518Skmacy	else if (!strcmp(argv[2], "mdio"))
1646167518Skmacy		r = mdio_io(argc, argv, 3, iff_name);
1647167518Skmacy	else if (!strcmp(argv[2], "mtus"))
1648167518Skmacy		r = mtu_tab_op(argc, argv, 3, iff_name);
1649167518Skmacy	else if (!strcmp(argv[2], "pm"))
1650167518Skmacy		r = conf_pm(argc, argv, 3, iff_name);
1651167518Skmacy	else if (!strcmp(argv[2], "regdump"))
1652167518Skmacy		r = dump_regs(argc, argv, 3, iff_name);
1653182594Skmacy	else if (!strcmp(argv[2], "tcamdump"))
1654182594Skmacy		r = dump_tcam(argc, argv, 3, iff_name);
1655167518Skmacy	else if (!strcmp(argv[2], "memdump"))
1656167518Skmacy		r = dump_mc7(argc, argv, 3, iff_name);
1657167518Skmacy	else if (!strcmp(argv[2], "meminfo"))
1658167518Skmacy		r = meminfo(argc, argv, 3, iff_name);
1659167518Skmacy	else if (!strcmp(argv[2], "context"))
1660167518Skmacy		r = get_sge_context(argc, argv, 3, iff_name);
1661167518Skmacy	else if (!strcmp(argv[2], "desc"))
1662167518Skmacy		r = get_sge_desc(argc, argv, 3, iff_name);
1663182594Skmacy	else if (!strcmp(argv[2], "loadfw"))
1664182594Skmacy		r = load_fw(argc, argv, 3, iff_name);
1665182594Skmacy	else if (!strcmp(argv[2], "loadboot"))
1666182594Skmacy		r = load_boot(argc, argv, 3, iff_name);
1667182594Skmacy	else if (!strcmp(argv[2], "proto"))
1668182594Skmacy		r = proto_sram_op(argc, argv, 3, iff_name);
1669167518Skmacy	else if (!strcmp(argv[2], "qset"))
1670167518Skmacy		r = qset_config(argc, argv, 3, iff_name);
1671167518Skmacy	else if (!strcmp(argv[2], "qsets"))
1672167518Skmacy		r = qset_num_config(argc, argv, 3, iff_name);
1673167518Skmacy	else if (!strcmp(argv[2], "trace"))
1674167518Skmacy		r = trace_config(argc, argv, 3, iff_name);
1675167518Skmacy	else if (!strcmp(argv[2], "pktsched"))
1676167518Skmacy		r = pktsched(argc, argv, 3, iff_name);
1677182594Skmacy	else if (!strcmp(argv[2], "tcb"))
1678182594Skmacy		r = get_tcb2(argc, argv, 3, iff_name);
1679207643Snp	else if (!strcmp(argv[2], "filter"))
1680207643Snp		r = filter_config(argc, argv, 3, iff_name);
1681182594Skmacy	else if (!strcmp(argv[2], "clearstats"))
1682182594Skmacy		r = clear_stats(argc, argv, 3, iff_name);
1683189643Sgnn	else if (!strcmp(argv[2], "la"))
1684189643Sgnn		r = get_up_la(argc, argv, 3, iff_name);
1685189643Sgnn	else if (!strcmp(argv[2], "ioqs"))
1686189643Sgnn		r = get_up_ioqs(argc, argv, 3, iff_name);
1687182594Skmacy
1688167518Skmacy	if (r == -1)
1689167518Skmacy		usage(stderr);
1690182594Skmacy
1691194928Snp	return (0);
1692167518Skmacy}
1693194928Snp
1694194928Snpstatic int
1695194928Snprun_cmd_loop(int argc, char *argv[], const char *iff_name)
1696194928Snp{
1697204267Snp	int n;
1698204267Snp	unsigned int i;
1699194928Snp	char buf[64];
1700194928Snp	char *args[8], *s;
1701194928Snp
1702204267Snp	(void) argc;
1703194928Snp	args[0] = argv[0];
1704194928Snp	args[1] = argv[1];
1705194928Snp
1706194928Snp	/*
1707194928Snp	 * Fairly simplistic loop.  Displays a "> " prompt and processes any
1708194928Snp	 * input as a cxgbtool command.  You're supposed to enter only the part
1709194928Snp	 * after "cxgbtool cxgbX".  Use "quit" or "exit" to exit.  Any error in
1710194928Snp	 * the command will also terminate cxgbtool.
1711194928Snp	 */
1712194928Snp	for (;;) {
1713194928Snp		fprintf(stdout, "> ");
1714194928Snp		fflush(stdout);
1715204267Snp		n = read(STDIN_FILENO, buf, sizeof(buf) - 1);
1716204267Snp		if (n <= 0)
1717194928Snp			return (0);
1718194928Snp
1719194928Snp		if (buf[--n] != '\n')
1720194928Snp			continue;
1721194928Snp		else
1722194928Snp			buf[n] = 0;
1723194928Snp
1724194928Snp		s = &buf[0];
1725194928Snp		for (i = 2; i < sizeof(args)/sizeof(args[0]) - 1; i++) {
1726194928Snp			while (s && (*s == ' ' || *s == '\t'))
1727194928Snp				s++;
1728194928Snp			if ((args[i] = strsep(&s, " \t")) == NULL)
1729194928Snp				break;
1730194928Snp		}
1731194928Snp		args[sizeof(args)/sizeof(args[0]) - 1] = 0;
1732194928Snp
1733194928Snp		if (!strcmp(args[2], "quit") || !strcmp(args[2], "exit"))
1734194928Snp			return (0);
1735194928Snp
1736194928Snp		(void) run_cmd(i, args, iff_name);
1737194928Snp	}
1738194928Snp
1739194928Snp	/* Can't really get here */
1740194928Snp	return (0);
1741194928Snp}
1742194928Snp
1743194928Snpint
1744194928Snpmain(int argc, char *argv[])
1745194928Snp{
1746194928Snp	int r = -1;
1747194928Snp	const char *iff_name;
1748194928Snp
1749194928Snp	progname = argv[0];
1750194928Snp
1751194928Snp	if (argc == 2) {
1752194928Snp		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1753194928Snp			usage(stdout);
1754194928Snp		if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1755194928Snp			printf("%s version %s\n", PROGNAME, VERSION);
1756194928Snp			printf("%s\n", COPYRIGHT);
1757194928Snp			exit(0);
1758194928Snp		}
1759194928Snp	}
1760194928Snp
1761194928Snp	if (argc < 3) usage(stderr);
1762194928Snp
1763194928Snp	iff_name = argv[1];
1764194928Snp
1765194928Snp	if (argc == 3 && !strcmp(argv[2], "stdio"))
1766194928Snp		r = run_cmd_loop(argc, argv, iff_name);
1767194928Snp	else
1768194928Snp		r = run_cmd(argc, argv, iff_name);
1769194928Snp
1770194928Snp	return (r);
1771194928Snp}
1772