]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/cxgbtool/cxgbtool.c
This commit was generated by cvs2svn to compensate for changes in r169942,
[FreeBSD/FreeBSD.git] / usr.sbin / cxgbtool / cxgbtool.c
1 /**************************************************************************
2
3 Copyright (c) 2007, 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_var.h>
56 #include <net/if_types.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 #endif
83
84 static const char *progname;
85
86 static void __attribute__((noreturn)) usage(FILE *fp)
87 {
88         fprintf(fp, "Usage: %s <interface> [operation]\n", progname);
89         fprintf(fp,
90 #ifdef CHELSIO_INTERNAL
91                 "\treg <address>[=<val>]               read/write register\n"
92                 "\ttpi <address>[=<val>]               read/write TPI register\n"
93                 "\tmdio <phy_addr> <mmd_addr>\n"
94                 "\t     <reg_addr> [<val>]             read/write MDIO register\n"
95 #endif
96                 "\tmtus [<mtu0>...<mtuN>]              read/write MTU table\n"
97 #ifdef CHELSIO_INTERNAL
98                 "\tpm [<TX page spec> <RX page spec>]  read/write PM config\n"
99                 "\ttcam [<#serv> <#routes> <#filters>] read/write TCAM config\n"
100                 "\ttcb <index>                         read TCB\n"
101 #endif
102                 "\tregdump [<module>]                  dump registers\n"
103 #ifdef CHELSIO_INTERNAL
104                 "\ttcamdump <address> <count>          show TCAM contents\n"
105                 "\tcontext <type> <id>                 show an SGE context\n"
106                 "\tdesc <qset> <queue> <idx> [<cnt>]   dump SGE descriptors\n"
107                 "\tmemdump cm|tx|rx <addr> <len>       dump a mem range\n"
108                 "\tmeminfo                             show memory info\n"
109 #endif
110                 "\tup                                  activate TOE\n"
111                 "\tproto [<protocol image>]            read/write proto SRAM\n"
112                 "\tloadfw <FW image>                   download firmware\n"
113                 "\tqset [<index> [<param> <val>] ...]  read/write qset parameters\n"
114                 "\tqsets [<# of qsets>]                read/write # of qsets\n"
115                 "\ttrace tx|rx|all on|off [not]\n"
116                 "\t      [<param> <val>[:<mask>]] ...  write trace parameters\n"
117                 "\tt1powersave [on|off]                enable/disable T1xx powersave mode\n"
118                 "\tpktsched port <idx> <min> <max>     set TX port scheduler params\n"
119                 "\tpktsched tunnelq <idx> <max>\n"
120                 "\t         <binding>                  set TX tunnelq scheduler params\n"
121                 );
122         exit(fp == stderr ? 1 : 0);
123 }
124
125 /*
126  * Make a TOETOOL ioctl call.
127  */
128 static int
129 doit(const char *iff_name, unsigned long cmd, void *data)
130 {
131         static int fd = 0;
132         
133         if (fd == 0) {
134                 char buf[64];
135                 snprintf(buf, 64, "/dev/%s", iff_name);
136
137                 if ((fd = open(buf, O_RDWR)) < 0)
138                         return (EINVAL);
139         }
140         
141         return ioctl(fd, cmd, data) < 0 ? -1 : 0;
142 }
143
144 static int get_int_arg(const char *s, uint32_t *valp)
145 {
146         char *p;
147
148         *valp = strtoul(s, &p, 0);
149         if (*p) {
150                 warnx("bad parameter \"%s\"", s);
151                 return -1;
152         }
153         return 0;
154 }
155
156 static uint32_t
157 read_reg(const char *iff_name, uint32_t addr)
158 {
159         struct ch_reg reg;
160
161         reg.addr = addr;
162         
163         if (doit(iff_name, CHELSIO_GETREG, &reg) < 0)
164                 err(1, "register read");
165         return reg.val;
166 }
167
168 static void
169 write_reg(const char *iff_name, uint32_t addr, uint32_t val)
170 {
171         struct ch_reg ch_reg;
172
173         ch_reg.addr = addr;
174         ch_reg.val = val;
175         
176         if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0)
177                 err(1, "register write");
178 }
179
180 static int register_io(int argc, char *argv[], int start_arg,
181                        const char *iff_name)
182 {
183         char *p;
184         uint32_t addr, val = 0, write = 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                 write = 1;
193         }
194         if (*p) {
195                 warnx("bad parameter \"%s\"", argv[start_arg]);
196                 return -1;
197         }
198
199         if (write)
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
210         struct ifreq ifr; 
211         struct mii_data p;
212         unsigned int cmd, phy_addr, reg, mmd, val; 
213  
214         if (argc == start_arg + 3) 
215                 cmd = SIOCGMIIREG; 
216         else if (argc == start_arg + 4) 
217                 cmd = SIOCSMIIREG; 
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 == SIOCSMIIREG && 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 == SIOCGMIIREG ? "read" : "write"); 
233         if (cmd == SIOCGMIIREG) 
234                 printf("%#x [%u]\n", p.val_out, p.val_out); 
235         return 0; 
236
237
238 static inline uint32_t xtract(uint32_t val, int shift, int len)
239 {
240         return (val >> shift) & ((1 << len) - 1);
241 }
242
243 static int dump_block_regs(const struct reg_info *reg_array, uint32_t *regs)
244 {
245         uint32_t reg_val = 0; // silence compiler warning
246
247         for ( ; reg_array->name; ++reg_array)
248                 if (!reg_array->len) {
249                         reg_val = regs[reg_array->addr / 4];
250                         printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr,
251                                reg_array->name, reg_val, reg_val);
252                 } else {
253                         uint32_t v = xtract(reg_val, reg_array->addr,
254                                             reg_array->len);
255
256                         printf("        %-40s %#-10x [%u]\n", reg_array->name,
257                                v, v);
258                 }
259         return 1;
260 }
261
262 static int dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs)
263 {
264         int match = 0;
265         char *block_name = NULL;
266
267         if (argc == start_arg + 1)
268                 block_name = argv[start_arg];
269         else if (argc != start_arg)
270                 return -1;
271
272         if (!block_name || !strcmp(block_name, "sge"))
273                 match += dump_block_regs(sge_regs, regs);
274         if (!block_name || !strcmp(block_name, "mc3"))
275                 match += dump_block_regs(mc3_regs, regs);
276         if (!block_name || !strcmp(block_name, "mc4"))
277                 match += dump_block_regs(mc4_regs, regs);
278         if (!block_name || !strcmp(block_name, "tpi"))
279                 match += dump_block_regs(tpi_regs, regs);
280         if (!block_name || !strcmp(block_name, "tp"))
281                 match += dump_block_regs(tp_regs, regs);
282         if (!block_name || !strcmp(block_name, "rat"))
283                 match += dump_block_regs(rat_regs, regs);
284         if (!block_name || !strcmp(block_name, "cspi"))
285                 match += dump_block_regs(cspi_regs, regs);
286         if (!block_name || !strcmp(block_name, "espi"))
287                 match += dump_block_regs(espi_regs, regs);
288         if (!block_name || !strcmp(block_name, "ulp"))
289                 match += dump_block_regs(ulp_regs, regs);
290         if (!block_name || !strcmp(block_name, "pl"))
291                 match += dump_block_regs(pl_regs, regs);
292         if (!block_name || !strcmp(block_name, "mc5"))
293                 match += dump_block_regs(mc5_regs, regs);
294         if (!match)
295                 errx(1, "unknown block \"%s\"", block_name);
296         return 0;
297 }
298
299 #if defined(CONFIG_T3_REGS)
300 static int dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs,
301                         int is_pcie)
302 {
303         int match = 0;
304         char *block_name = NULL;
305
306         if (argc == start_arg + 1)
307                 block_name = argv[start_arg];
308         else if (argc != start_arg)
309                 return -1;
310
311         if (!block_name || !strcmp(block_name, "sge"))
312                 match += dump_block_regs(sge3_regs, regs);
313         if (!block_name || !strcmp(block_name, "pci"))
314                 match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs,
315                                          regs);
316         if (!block_name || !strcmp(block_name, "t3dbg"))
317                 match += dump_block_regs(t3dbg_regs, regs);
318         if (!block_name || !strcmp(block_name, "pmrx"))
319                 match += dump_block_regs(mc7_pmrx_regs, regs);
320         if (!block_name || !strcmp(block_name, "pmtx"))
321                 match += dump_block_regs(mc7_pmtx_regs, regs);
322         if (!block_name || !strcmp(block_name, "cm"))
323                 match += dump_block_regs(mc7_cm_regs, regs);
324         if (!block_name || !strcmp(block_name, "cim"))
325                 match += dump_block_regs(cim_regs, regs);
326         if (!block_name || !strcmp(block_name, "tp"))
327                 match += dump_block_regs(tp1_regs, regs);
328         if (!block_name || !strcmp(block_name, "ulp_rx"))
329                 match += dump_block_regs(ulp2_rx_regs, regs);
330         if (!block_name || !strcmp(block_name, "ulp_tx"))
331                 match += dump_block_regs(ulp2_tx_regs, regs);
332         if (!block_name || !strcmp(block_name, "pmrx"))
333                 match += dump_block_regs(pm1_rx_regs, regs);
334         if (!block_name || !strcmp(block_name, "pmtx"))
335                 match += dump_block_regs(pm1_tx_regs, regs);
336         if (!block_name || !strcmp(block_name, "mps"))
337                 match += dump_block_regs(mps0_regs, regs);
338         if (!block_name || !strcmp(block_name, "cplsw"))
339                 match += dump_block_regs(cpl_switch_regs, regs);
340         if (!block_name || !strcmp(block_name, "smb"))
341                 match += dump_block_regs(smb0_regs, regs);
342         if (!block_name || !strcmp(block_name, "i2c"))
343                 match += dump_block_regs(i2cm0_regs, regs);
344         if (!block_name || !strcmp(block_name, "mi1"))
345                 match += dump_block_regs(mi1_regs, regs);
346         if (!block_name || !strcmp(block_name, "sf"))
347                 match += dump_block_regs(sf1_regs, regs);
348         if (!block_name || !strcmp(block_name, "pl"))
349                 match += dump_block_regs(pl3_regs, regs);
350         if (!block_name || !strcmp(block_name, "mc5"))
351                 match += dump_block_regs(mc5a_regs, regs);
352         if (!block_name || !strcmp(block_name, "xgmac0"))
353                 match += dump_block_regs(xgmac0_0_regs, regs);
354         if (!block_name || !strcmp(block_name, "xgmac1"))
355                 match += dump_block_regs(xgmac0_1_regs, regs);
356         if (!match)
357                 errx(1, "unknown block \"%s\"", block_name);
358         return 0;
359 }
360
361 static int dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs,
362                          int is_pcie)
363 {
364         int match = 0;
365         char *block_name = NULL;
366
367         if (argc == start_arg + 1)
368                 block_name = argv[start_arg];
369         else if (argc != start_arg)
370                 return -1;
371
372         if (!block_name || !strcmp(block_name, "sge"))
373                 match += dump_block_regs(t3b_sge3_regs, regs);
374         if (!block_name || !strcmp(block_name, "pci"))
375                 match += dump_block_regs(is_pcie ? t3b_pcie0_regs :
376                                                    t3b_pcix1_regs, regs);
377         if (!block_name || !strcmp(block_name, "t3dbg"))
378                 match += dump_block_regs(t3b_t3dbg_regs, regs);
379         if (!block_name || !strcmp(block_name, "pmrx"))
380                 match += dump_block_regs(t3b_mc7_pmrx_regs, regs);
381         if (!block_name || !strcmp(block_name, "pmtx"))
382                 match += dump_block_regs(t3b_mc7_pmtx_regs, regs);
383         if (!block_name || !strcmp(block_name, "cm"))
384                 match += dump_block_regs(t3b_mc7_cm_regs, regs);
385         if (!block_name || !strcmp(block_name, "cim"))
386                 match += dump_block_regs(t3b_cim_regs, regs);
387         if (!block_name || !strcmp(block_name, "tp"))
388                 match += dump_block_regs(t3b_tp1_regs, regs);
389         if (!block_name || !strcmp(block_name, "ulp_rx"))
390                 match += dump_block_regs(t3b_ulp2_rx_regs, regs);
391         if (!block_name || !strcmp(block_name, "ulp_tx"))
392                 match += dump_block_regs(t3b_ulp2_tx_regs, regs);
393         if (!block_name || !strcmp(block_name, "pmrx"))
394                 match += dump_block_regs(t3b_pm1_rx_regs, regs);
395         if (!block_name || !strcmp(block_name, "pmtx"))
396                 match += dump_block_regs(t3b_pm1_tx_regs, regs);
397         if (!block_name || !strcmp(block_name, "mps"))
398                 match += dump_block_regs(t3b_mps0_regs, regs);
399         if (!block_name || !strcmp(block_name, "cplsw"))
400                 match += dump_block_regs(t3b_cpl_switch_regs, regs);
401         if (!block_name || !strcmp(block_name, "smb"))
402                 match += dump_block_regs(t3b_smb0_regs, regs);
403         if (!block_name || !strcmp(block_name, "i2c"))
404                 match += dump_block_regs(t3b_i2cm0_regs, regs);
405         if (!block_name || !strcmp(block_name, "mi1"))
406                 match += dump_block_regs(t3b_mi1_regs, regs);
407         if (!block_name || !strcmp(block_name, "sf"))
408                 match += dump_block_regs(t3b_sf1_regs, regs);
409         if (!block_name || !strcmp(block_name, "pl"))
410                 match += dump_block_regs(t3b_pl3_regs, regs);
411         if (!block_name || !strcmp(block_name, "mc5"))
412                 match += dump_block_regs(t3b_mc5a_regs, regs);
413         if (!block_name || !strcmp(block_name, "xgmac0"))
414                 match += dump_block_regs(t3b_xgmac0_0_regs, regs);
415         if (!block_name || !strcmp(block_name, "xgmac1"))
416                 match += dump_block_regs(t3b_xgmac0_1_regs, regs);
417         if (!match)
418                 errx(1, "unknown block \"%s\"", block_name);
419         return 0;
420 }
421 #endif
422
423 static int
424 dump_regs(int argc, char *argv[], int start_arg, const char *iff_name)
425 {
426
427         
428         int i, vers, revision, is_pcie;
429         struct ifconf_regs regs;
430
431         regs.len = REGDUMP_SIZE;
432
433         if ((regs.data = malloc(REGDUMP_SIZE)) == NULL)
434                 err(1, "can't malloc");
435
436         if (doit(iff_name, CHELSIO_IFCONF_GETREGS, &regs))
437                 err(1, "can't read registers");
438
439         vers = regs.version & 0x3ff;
440         revision = (regs.version >> 10) & 0x3f;
441         is_pcie = (regs.version & 0x80000000) != 0;
442
443         if (vers <= 2)
444                 return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data);
445 #if defined(CONFIG_T3_REGS)
446         if (vers == 3) {
447                 if (revision == 0)
448                         return dump_regs_t3(argc, argv, start_arg,
449                                             (uint32_t *)regs.data, is_pcie);
450                 if (revision == 2)
451                         return dump_regs_t3b(argc, argv, start_arg,
452                                              (uint32_t *)regs.data, is_pcie);
453         }
454 #endif
455         errx(1, "unknown card type %d", vers);
456         return 0;
457 }
458
459 static int t3_meminfo(const uint32_t *regs)
460 {
461         enum {
462                 SG_EGR_CNTX_BADDR       = 0x58,
463                 SG_CQ_CONTEXT_BADDR     = 0x6c,
464                 CIM_SDRAM_BASE_ADDR     = 0x28c,
465                 CIM_SDRAM_ADDR_SIZE     = 0x290,
466                 TP_CMM_MM_BASE          = 0x314,
467                 TP_CMM_TIMER_BASE       = 0x318,
468                 TP_CMM_MM_RX_FLST_BASE  = 0x460,
469                 TP_CMM_MM_TX_FLST_BASE  = 0x464,
470                 TP_CMM_MM_PS_FLST_BASE  = 0x468,
471                 ULPRX_ISCSI_LLIMIT      = 0x50c,
472                 ULPRX_ISCSI_ULIMIT      = 0x510,
473                 ULPRX_TDDP_LLIMIT       = 0x51c,
474                 ULPRX_TDDP_ULIMIT       = 0x520,
475                 ULPRX_STAG_LLIMIT       = 0x52c,
476                 ULPRX_STAG_ULIMIT       = 0x530,
477                 ULPRX_RQ_LLIMIT         = 0x534,
478                 ULPRX_RQ_ULIMIT         = 0x538,
479                 ULPRX_PBL_LLIMIT        = 0x53c,
480                 ULPRX_PBL_ULIMIT        = 0x540,
481         };
482
483         unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4],
484                      cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4],
485                      timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff,
486                      pstructs = regs[TP_CMM_MM_BASE / 4],
487                      pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4],
488                      rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4],
489                      tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4],
490                      cim_base = regs[CIM_SDRAM_BASE_ADDR / 4],
491                      cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4];
492         unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4],
493                      iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4],
494                      tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4],
495                      tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4],
496                      stag_ll = regs[ULPRX_STAG_LLIMIT / 4],
497                      stag_ul = regs[ULPRX_STAG_ULIMIT / 4],
498                      rq_ll = regs[ULPRX_RQ_LLIMIT / 4],
499                      rq_ul = regs[ULPRX_RQ_ULIMIT / 4],
500                      pbl_ll = regs[ULPRX_PBL_LLIMIT / 4],
501                      pbl_ul = regs[ULPRX_PBL_ULIMIT / 4];
502
503         printf("CM memory map:\n");
504         printf("  TCB region:      0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1,
505                egr_cntxt);
506         printf("  Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt,
507                cq_cntxt - 1, cq_cntxt - egr_cntxt);
508         printf("  CQ contexts:     0x%08x - 0x%08x [%u]\n", cq_cntxt,
509                timers - 1, timers - cq_cntxt);
510         printf("  Timers:          0x%08x - 0x%08x [%u]\n", timers,
511                pstructs - 1, pstructs - timers);
512         printf("  Pstructs:        0x%08x - 0x%08x [%u]\n", pstructs,
513                pstruct_fl - 1, pstruct_fl - pstructs);
514         printf("  Pstruct FL:      0x%08x - 0x%08x [%u]\n", pstruct_fl,
515                rx_fl - 1, rx_fl - pstruct_fl);
516         printf("  Rx FL:           0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1,
517                tx_fl - rx_fl);
518         printf("  Tx FL:           0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1,
519                cim_base - tx_fl);
520         printf("  uP RAM:          0x%08x - 0x%08x [%u]\n", cim_base,
521                cim_base + cim_size - 1, cim_size);
522
523         printf("\nPMRX memory map:\n");
524         printf("  iSCSI region:    0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul,
525                iscsi_ul - iscsi_ll + 1);
526         printf("  TCP DDP region:  0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul,
527                tddp_ul - tddp_ll + 1);
528         printf("  TPT region:      0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul,
529                stag_ul - stag_ll + 1);
530         printf("  RQ region:       0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul,
531                rq_ul - rq_ll + 1);
532         printf("  PBL region:      0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul,
533                pbl_ul - pbl_ll + 1);
534         return 0;
535 }
536
537 static int meminfo(int argc, char *argv[], int start_arg, const char *iff_name)
538 {
539         int vers;
540         struct ifconf_regs regs;
541
542         if ((regs.data = malloc(REGDUMP_SIZE)) == NULL)
543                 err(1, "can't malloc");
544         
545         if (doit(iff_name, CHELSIO_IFCONF_GETREGS, &regs))
546                 err(1, "can't read registers");
547
548         vers = regs.version & 0x3ff;
549         if (vers == 3)
550                 return t3_meminfo((uint32_t *)regs.data);
551
552         errx(1, "unknown card type %d", vers);
553         return 0;
554 }
555
556 #ifdef notyet
557 static int mtu_tab_op(int argc, char *argv[], int start_arg,
558                       const char *iff_name)
559 {
560         struct toetool_mtus op;
561         int i;
562
563         if (argc == start_arg) {
564                 op.cmd = TOETOOL_GETMTUTAB;
565                 op.nmtus = MAX_NMTUS;
566
567                 if (doit(iff_name, &op) < 0)
568                         err(1, "get MTU table");
569                 for (i = 0; i < op.nmtus; ++i)
570                         printf("%u ", op.mtus[i]);
571                 printf("\n");
572         } else if (argc <= start_arg + MAX_NMTUS) {
573                 op.cmd = TOETOOL_SETMTUTAB;
574                 op.nmtus = argc - start_arg;
575
576                 for (i = 0; i < op.nmtus; ++i) {
577                         char *p;
578                         unsigned long m = strtoul(argv[start_arg + i], &p, 0);
579
580                         if (*p || m > 9600) {
581                                 warnx("bad parameter \"%s\"",
582                                       argv[start_arg + i]);
583                                 return -1;
584                         }
585                         if (i && m < op.mtus[i - 1])
586                                 errx(1, "MTUs must be in ascending order");
587                         op.mtus[i] = m;
588                 }
589                 if (doit(iff_name, &op) < 0)
590                         err(1, "set MTU table");
591         } else
592                 return -1;
593
594         return 0;
595 }
596 #endif
597
598 #ifdef CHELSIO_INTERNAL
599 static void show_egress_cntxt(uint32_t data[])
600 {
601         printf("credits:      %u\n", data[0] & 0x7fff);
602         printf("GTS:          %u\n", (data[0] >> 15) & 1);
603         printf("index:        %u\n", data[0] >> 16);
604         printf("queue size:   %u\n", data[1] & 0xffff);
605         printf("base address: 0x%llx\n",
606                ((data[1] >> 16) | ((uint64_t)data[2] << 16) |
607                (((uint64_t)data[3] & 0xf) << 48)) << 12);
608         printf("rsp queue #:  %u\n", (data[3] >> 4) & 7);
609         printf("cmd queue #:  %u\n", (data[3] >> 7) & 1);
610         printf("TUN:          %u\n", (data[3] >> 8) & 1);
611         printf("TOE:          %u\n", (data[3] >> 9) & 1);
612         printf("generation:   %u\n", (data[3] >> 10) & 1);
613         printf("uP token:     %u\n", (data[3] >> 11) & 0xfffff);
614         printf("valid:        %u\n", (data[3] >> 31) & 1);
615 }
616
617 static void show_fl_cntxt(uint32_t data[])
618 {
619         printf("base address: 0x%llx\n",
620                ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12);
621         printf("index:        %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12));
622         printf("queue size:   %u\n", (data[2] >> 4) & 0xffff);
623         printf("generation:   %u\n", (data[2] >> 20) & 1);
624         printf("entry size:   %u\n",
625                ((data[2] >> 21) & 0x7ff) | (data[3] & 0x1fffff));
626         printf("congest thr:  %u\n", (data[3] >> 21) & 0x3ff);
627         printf("GTS:          %u\n", (data[3] >> 31) & 1);
628 }
629
630 static void show_response_cntxt(uint32_t data[])
631 {
632         printf("index:        %u\n", data[0] & 0xffff);
633         printf("size:         %u\n", data[0] >> 16);
634         printf("base address: 0x%llx\n",
635                ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
636         printf("MSI-X/RspQ:   %u\n", (data[2] >> 20) & 0x3f);
637         printf("intr enable:  %u\n", (data[2] >> 26) & 1);
638         printf("intr armed:   %u\n", (data[2] >> 27) & 1);
639         printf("generation:   %u\n", (data[2] >> 28) & 1);
640         printf("CQ mode:      %u\n", (data[2] >> 31) & 1);
641         printf("FL threshold: %u\n", data[3]);
642 }
643
644 static void show_cq_cntxt(uint32_t data[])
645 {
646         printf("index:            %u\n", data[0] & 0xffff);
647         printf("size:             %u\n", data[0] >> 16);
648         printf("base address:     0x%llx\n",
649                ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12);
650         printf("rsp queue #:      %u\n", (data[2] >> 20) & 0x3f);
651         printf("AN:               %u\n", (data[2] >> 26) & 1);
652         printf("armed:            %u\n", (data[2] >> 27) & 1);
653         printf("ANS:              %u\n", (data[2] >> 28) & 1);
654         printf("generation:       %u\n", (data[2] >> 29) & 1);
655         printf("overflow mode:    %u\n", (data[2] >> 31) & 1);
656         printf("credits:          %u\n", data[3] & 0xffff);
657         printf("credit threshold: %u\n", data[3] >> 16);
658 }
659
660 static int get_sge_context(int argc, char *argv[], int start_arg,
661                            const char *iff_name)
662 {
663         struct ch_cntxt ctx;
664
665         if (argc != start_arg + 2) return -1;
666
667         if (!strcmp(argv[start_arg], "egress"))
668                 ctx.cntxt_type = CNTXT_TYPE_EGRESS;
669         else if (!strcmp(argv[start_arg], "fl"))
670                 ctx.cntxt_type = CNTXT_TYPE_FL;
671         else if (!strcmp(argv[start_arg], "response"))
672                 ctx.cntxt_type = CNTXT_TYPE_RSP;
673         else if (!strcmp(argv[start_arg], "cq"))
674                 ctx.cntxt_type = CNTXT_TYPE_CQ;
675         else {
676                 warnx("unknown context type \"%s\"; known types are egress, "
677                       "fl, cq, and response", argv[start_arg]);
678                 return -1;
679         }
680
681         if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id))
682                 return -1;
683
684         if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0)
685                 err(1, "get SGE context");
686
687         if (!strcmp(argv[start_arg], "egress"))
688                 show_egress_cntxt(ctx.data);
689         else if (!strcmp(argv[start_arg], "fl"))
690                 show_fl_cntxt(ctx.data);
691         else if (!strcmp(argv[start_arg], "response"))
692                 show_response_cntxt(ctx.data);
693         else if (!strcmp(argv[start_arg], "cq"))
694                 show_cq_cntxt(ctx.data);
695         return 0;
696 }
697
698 #if __BYTE_ORDER == __BIG_ENDIAN
699 # define ntohll(n) (n)
700 #else
701 # define ntohll(n) bswap_64(n)
702 #endif
703
704 static int get_sge_desc(int argc, char *argv[], int start_arg,
705                         const char *iff_name)
706 {
707         uint64_t *p, wr_hdr;
708         unsigned int n = 1, qset, qnum;
709         struct ch_desc desc;
710
711         if (argc != start_arg + 3 && argc != start_arg + 4)
712                 return -1;
713
714         if (get_int_arg(argv[start_arg], &qset) ||
715             get_int_arg(argv[start_arg + 1], &qnum) ||
716             get_int_arg(argv[start_arg + 2], &desc.idx))
717                 return -1;
718
719         if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n))
720                 return -1;
721
722         if (qnum > 5)
723                 errx(1, "invalid queue number %d, range is 0..5", qnum);
724
725         desc.queue_num = qset * 6 + qnum;
726
727         for (; n--; desc.idx++) {
728                 if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0)
729                         err(1, "get SGE descriptor");
730
731                 p = (uint64_t *)desc.data;
732                 wr_hdr = ntohll(*p);
733                 printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n",
734                        desc.idx, (unsigned int)(wr_hdr >> 56),
735                        ((unsigned int)wr_hdr >> 8) & 0xfffff,
736                        ((wr_hdr >> 55) & 1) ? "SOP, " : "",
737                        ((wr_hdr >> 54) & 1) ? "EOP, " : "",
738                        ((wr_hdr >> 53) & 1) ? "COMPL, " : "",
739                        ((wr_hdr >> 52) & 1) ? "SGL, " : "",
740                        (unsigned int)wr_hdr & 0xff);
741
742                 for (; desc.size; p++, desc.size -= sizeof(uint64_t))
743                         printf("%016" PRIx64 "%c", ntohll(*p),
744                             desc.size % 32 == 8 ? '\n' : ' ');
745         }
746         return 0;
747 }
748 #endif
749
750 #ifdef notyet
751 static int get_tcb2(unsigned int tcb_idx, const char *iff_name)
752 {
753         uint64_t *d;
754         unsigned int i;
755         struct toetool_mem_range *op;
756
757         op = malloc(sizeof(*op) + TCB_SIZE);
758         if (!op)
759                 err(1, "get TCB");
760
761         op->cmd    = TOETOOL_GET_MEM;
762         op->mem_id = MEM_CM;
763         op->addr   = tcb_idx * TCB_SIZE;
764         op->len    = TCB_SIZE;
765
766         if (doit(iff_name, op) < 0)
767                 err(1, "get TCB");
768
769         for (d = (uint64_t *)op->buf, i = 0; i < TCB_SIZE / 32; i++) {
770                 printf("%2u:", i);
771                 printf(" %08x %08x %08x %08x", (uint32_t)d[1],
772                        (uint32_t)(d[1] >> 32), (uint32_t)d[0],
773                        (uint32_t)(d[0] >> 32));
774                 d += 2;
775                 printf(" %08x %08x %08x %08x\n", (uint32_t)d[1],
776                        (uint32_t)(d[1] >> 32), (uint32_t)d[0],
777                        (uint32_t)(d[0] >> 32));
778                 d += 2;
779         }
780         free(op);
781         return 0;
782 }
783
784 static int get_tcb(int argc, char *argv[], int start_arg, const char *iff_name)
785 {
786         int i;
787         uint32_t *d;
788         struct toetool_tcb op;
789
790         if (argc != start_arg + 1) return -1;
791
792         op.cmd = TOETOOL_GET_TCB;
793         if (get_int_arg(argv[start_arg], &op.tcb_index))
794                 return -1;
795
796         /*
797          * If this operation isn't directly supported by the driver we may
798          * still be able to read TCBs using the generic memory dump operation.
799          */
800         if (doit(iff_name, &op) < 0) {
801                 if (errno != EOPNOTSUPP)
802                         err(1, "get TCB");
803                 return get_tcb2(op.tcb_index, iff_name);
804         }
805
806         for (d = op.tcb_data, i = 0; i < TCB_WORDS; i += 8) {
807                 int j;
808
809                 printf("%2u:", 4 * i);
810                 for (j = 0; j < 8; ++j)
811                         printf(" %08x", *d++);
812                 printf("\n");
813         }
814         return 0;
815 }
816 #endif
817 #ifdef WRC
818 /*
819  * The following defines, typedefs and structures are defined in the FW and
820  * should be exported instead of being redefined here (and kept up in sync).
821  * We'll fix this in the next round of FW cleanup.
822  */
823 #define CM_WRCONTEXT_BASE       0x20300000
824 #define CM_WRCONTEXT_OFFSET     0x300000
825 #define WRC_SIZE                (FW_WR_SIZE * (2 + FW_WR_NUM) + 32 + 4 * 128)
826 #define FW_WR_SIZE      128
827 #define FW_WR_NUM       16
828 #define FBUF_SIZE       (FW_WR_SIZE * FW_WR_NUM)
829 #define FBUF_WRAP_SIZE  128
830 #define FBUF_WRAP_FSZ   (FBUF_WRAP_SZ >> 3)
831 #define MEM_CM_WRC_SIZE  WRC_SIZE
832
833 typedef char                    int8_t;
834 typedef short                   int16_t;
835 typedef int                     int32_t;
836 typedef long long               _s64;
837 typedef unsigned char           _u8;
838 typedef unsigned short          _u16;
839 typedef unsigned int            _uint32_t;
840 typedef unsigned long long      uint64_t;
841
842 enum fw_ri_mpa_attrs {
843         FW_RI_MPA_RX_MARKER_ENABLE = 0x1,
844         FW_RI_MPA_TX_MARKER_ENABLE = 0x2,
845         FW_RI_MPA_CRC_ENABLE    = 0x4,
846         FW_RI_MPA_IETF_ENABLE   = 0x8
847 } __attribute__ ((packed));
848
849 enum fw_ri_qp_caps {
850         FW_RI_QP_RDMA_READ_ENABLE = 0x01,
851         FW_RI_QP_RDMA_WRITE_ENABLE = 0x02,
852         FW_RI_QP_BIND_ENABLE    = 0x04,
853         FW_RI_QP_FAST_REGISTER_ENABLE = 0x08,
854         FW_RI_QP_STAG0_ENABLE   = 0x10
855 } __attribute__ ((packed));
856
857 enum wrc_state {
858         WRC_STATE_CLOSED,
859         WRC_STATE_ABORTED,
860         WRC_STATE_HALFCLOSED,
861         WRC_STATE_TOE_ESTABLISHED,
862         WRC_STATE_RDMA_TX_DATA_PEND,
863         WRC_STATE_RDMA_PEND,
864         WRC_STATE_RDMA_ESTABLISHED,
865 };
866
867 struct _wr {
868         uint32_t a;
869         uint32_t b;
870 };
871
872 struct fbuf {
873         uint32_t        pp;                     /* fifo producer pointer */
874         uint32_t        cp;                     /* fifo consumer pointer */
875         int32_t num_bytes;              /* num bytes stored in the fbuf */
876         char    bufferb[FBUF_SIZE];     /* buffer space in bytes */
877         char    _wrap[FBUF_WRAP_SIZE];  /* wrap buffer size*/
878 };
879 struct wrc {
880         uint32_t        wrc_tid;
881         _u16    wrc_flags;
882         _u8     wrc_state;
883         _u8     wrc_credits;
884
885         /* IO */
886         _u16    wrc_sge_ec;
887         _u8     wrc_sge_respQ;
888         _u8     wrc_port;
889         _u8     wrc_ulp;
890
891         _u8     wrc_coherency_counter;
892
893         /* REASSEMBLY */
894         _u8     wrc_frag_len;
895         _u8     wrc_frag_credits;
896         uint32_t        wrc_frag;
897
898         union {
899                 struct {
900
901                         /* TOE */
902                         _u8     aborted;
903                         _u8     wrc_num_tx_pages;
904                         _u8     wrc_max_tx_pages;
905                         _u8     wrc_trace_idx;
906                         uint32_t        wrc_snd_nxt;
907                         uint32_t        wrc_snd_max;
908                         uint32_t        wrc_snd_una;
909                         uint32_t        wrc_snd_iss;
910
911                         /* RI */
912                         uint32_t        wrc_pdid;
913                         uint32_t        wrc_scqid;
914                         uint32_t        wrc_rcqid;
915                         uint32_t        wrc_rq_addr_32a;
916                         _u16    wrc_rq_size;
917                         _u16    wrc_rq_wr_idx;
918                         enum fw_ri_mpa_attrs wrc_mpaattrs;
919                         enum fw_ri_qp_caps wrc_qpcaps;
920                         _u16    wrc_mulpdu_tagged;
921                         _u16    wrc_mulpdu_untagged;
922                         _u16    wrc_ord_max;
923                         _u16    wrc_ird_max;
924                         _u16    wrc_ord;
925                         _u16    wrc_ird;
926                         _u16    wrc_markeroffset;
927                         uint32_t        wrc_msn_send;
928                         uint32_t        wrc_msn_rdma_read;
929                         uint32_t        wrc_msn_rdma_read_req;
930                         _u16    wrc_rdma_read_req_err;
931                         _u8     wrc_ack_mode;
932                         _u8     wrc_sge_ec_credits;
933                         _u16    wrc_maxiolen_tagged;
934                         _u16    wrc_maxiolen_untagged;
935                         uint32_t        wrc_mo;
936                 } toe_ri;
937
938                 struct {
939
940                 } ipmi;
941
942                 struct {
943                         uint32_t        wrc_pad2[24];
944                 } pad;
945         } u __attribute__ ((packed));
946
947         /* BUFFERING */
948         struct fbuf wrc_fbuf __attribute__ ((packed));
949 };
950 #define wrc_aborted u.toe_ri.aborted
951 #define wrc_num_tx_pages u.toe_ri.wrc_num_tx_pages
952 #define wrc_max_tx_pages u.toe_ri.wrc_max_tx_pages
953 #define wrc_trace_idx u.toe_ri.wrc_trace_idx
954 #define wrc_snd_nxt u.toe_ri.wrc_snd_nxt
955 #define wrc_snd_max u.toe_ri.wrc_snd_max
956 #define wrc_snd_una u.toe_ri.wrc_snd_una
957 #define wrc_snd_iss u.toe_ri.wrc_snd_iss
958 #define wrc_pdid u.toe_ri.wrc_pdid
959 #define wrc_scqid u.toe_ri.wrc_scqid
960 #define wrc_rcqid u.toe_ri.wrc_rcqid
961 #define wrc_rq_addr_32a u.toe_ri.wrc_rq_addr_32a
962 #define wrc_rq_size u.toe_ri.wrc_rq_size
963 #define wrc_rq_wr_idx u.toe_ri.wrc_rq_wr_idx
964 #define wrc_mpaattrs u.toe_ri.wrc_mpaattrs
965 #define wrc_qpcaps u.toe_ri.wrc_qpcaps
966 #define wrc_mulpdu_tagged u.toe_ri.wrc_mulpdu_tagged
967 #define wrc_mulpdu_untagged u.toe_ri.wrc_mulpdu_untagged
968 #define wrc_ord_max u.toe_ri.wrc_ord_max
969 #define wrc_ird_max u.toe_ri.wrc_ird_max
970 #define wrc_ord u.toe_ri.wrc_ord
971 #define wrc_ird u.toe_ri.wrc_ird
972 #define wrc_markeroffset u.toe_ri.wrc_markeroffset
973 #define wrc_msn_send u.toe_ri.wrc_msn_send
974 #define wrc_msn_rdma_read u.toe_ri.wrc_msn_rdma_read
975 #define wrc_msn_rdma_read_req u.toe_ri.wrc_msn_rdma_read_req
976 #define wrc_rdma_read_req_err u.toe_ri.wrc_rdma_read_req_err
977 #define wrc_ack_mode u.toe_ri.wrc_ack_mode
978 #define wrc_sge_ec_credits u.toe_ri.wrc_sge_ec_credits
979 #define wrc_maxiolen_tagged u.toe_ri.wrc_maxiolen_tagged
980 #define wrc_maxiolen_untagged u.toe_ri.wrc_maxiolen_untagged
981 #define wrc_mo u.toe_ri.wrc_mo
982
983 static void print_wrc_field(char *field, unsigned int value, unsigned int size)
984 {
985         switch(size) {
986         case 1:
987                 printf("  1 %s: 0x%02x (%u)\n", field, value, value);
988                 break;
989         case 2: {
990                 unsigned short host_value = ntohs(value);
991                 printf("  2 %s: 0x%04x (%u)\n", field, host_value, host_value);
992                 break;
993         }
994         case 4: {
995                 unsigned int host_value = ntohl(value);
996                 printf("  4 %s: 0x%08x (%u)\n", field, host_value, host_value);
997                 break;
998         }
999         default:
1000                 printf("  unknown size %u for field %s\n", size, field);
1001         }
1002 }
1003
1004 #define P(field)  print_wrc_field(#field, p->wrc_ ## field, sizeof (p->wrc_ ## field))
1005
1006 static void print_wrc(unsigned int wrc_idx, struct wrc *p)
1007 {
1008         u32 *buf = (u32 *)p;
1009         unsigned int i, j;
1010
1011         printf("WRC STATE (raw)\n");
1012         for (i = 0; i < 32;) {
1013                 printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4);
1014                 for (j = 0; j < 8; j++) {
1015                         printf(" %08x ", htonl(buf[i++]));
1016                 }
1017                 printf("\n");
1018         }
1019         printf("WRC BASIC\n");
1020         P(tid); P(flags); P(state); P(credits);
1021         printf("WRC IO\n");
1022         P(sge_ec); P(sge_respQ); P(port); P(ulp); P(coherency_counter);
1023         printf("WRC REASSEMBLY\n");
1024         P(frag_len); P(frag_credits); P(frag);
1025         printf("WRC TOE\n");
1026         P(aborted); P(num_tx_pages); P(max_tx_pages); P(trace_idx); P(snd_nxt);
1027         P(snd_max); P(snd_una); P(snd_iss);
1028         printf("WRC RI\n");
1029         P(pdid); P(scqid); P(rcqid); P(rq_addr_32a); P(rq_size); P(rq_wr_idx);
1030         P(mpaattrs); P(qpcaps); P(mulpdu_tagged); P(mulpdu_untagged); P(ord_max);
1031         P(ird_max); P(ord); P(ird); P(markeroffset); P(msn_send); P(msn_rdma_read);
1032         P(msn_rdma_read_req); P(rdma_read_req_err); P(ack_mode);
1033         P(sge_ec_credits); P(maxiolen_tagged); P(maxiolen_untagged); P(mo);
1034         printf("WRC BUFFERING\n");
1035         printf("  4 fbuf.pp: 0x%08x (%u)\n", htonl(p->wrc_fbuf.pp),  htonl(p->wrc_fbuf.pp));
1036         printf("  4 fbuf.cp: 0x%08x (%u)\n",  htonl(p->wrc_fbuf.cp),  htonl(p->wrc_fbuf.cp));
1037         printf("  4 fbuf.num_bytes: 0x%08x (%d)\n",  htonl(p->wrc_fbuf.num_bytes),  htonl(p->wrc_fbuf.num_bytes));
1038         printf("WRC BUFFER (raw)\n");
1039         for (i = 32; i < (FBUF_SIZE + FBUF_WRAP_SIZE) / 4;) {
1040                 printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4);
1041                 for (j = 0; j < 4; j++) {
1042                         printf(" %08x%08x", htonl(buf[i++]), htonl(buf[i++]));
1043                 }
1044                 printf("\n");
1045         }
1046 }
1047
1048 #undef P
1049
1050 #define P(field)  print_sizeof(#field, ##field, sizeof (p->##field))
1051
1052 struct history_e {
1053         uint32_t wr_addr;
1054         uint32_t debug;
1055         uint64_t wr_flit0;
1056         uint64_t wr_flit1;
1057         uint64_t wr_flit2;
1058 };
1059
1060 static void print_wrc_zero(unsigned int wrc_idx, struct wrc *p)
1061 {
1062         uint32_t *buf =
1063            (uint32_t *)((unsigned long)p + FW_WR_SIZE * (2 + FW_WR_NUM));
1064         unsigned int i;
1065
1066         printf("WRC ZERO\n");
1067         printf("[%08x]:", CM_WRCONTEXT_BASE + wrc_idx * MEM_CM_WRC_SIZE +
1068                FW_WR_SIZE * (2 + FW_WR_NUM));
1069         for (i = 0; i < 4;)
1070                 printf(" %08x%08x", htonl(buf[i]), htonl(buf[i++]));
1071         printf("\n");
1072 }
1073
1074 static void print_wrc_history(struct wrc *p)
1075 {
1076         unsigned int i, idx;
1077         struct history_e *e =
1078             (struct history_e *)((unsigned long)p + FW_WR_SIZE *
1079                                  (2 + FW_WR_NUM) + 32);
1080         printf("WRC WR HISTORY, idx %u\n", p->wrc_trace_idx);
1081         idx = p->wrc_trace_idx;
1082         for (i = 0; i < 16; i++) {
1083                 printf("%02u: %08x %08x %08x%08x %08x%08x %08x%08x\n", idx,
1084                        htonl(e[idx].wr_addr), htonl(e[idx].debug),
1085                        htonl(e[idx].wr_flit0 & 0xFFFFFFFF),
1086                        htonl(e[idx].wr_flit0 >> 32),
1087                        htonl(e[idx].wr_flit1 & 0xFFFFFFFF),
1088                        htonl(e[idx].wr_flit1 >> 32),
1089                        htonl(e[idx].wr_flit2 & 0xFFFFFFFF),
1090                        htonl(e[idx].wr_flit2 >> 32));
1091                 idx = (idx - 1) & 0xF;
1092         }
1093 }
1094
1095 static int get_wrc(int argc, char *argv[], int start_arg, const char *iff_name)
1096 {
1097         struct toetool_mem_range *op;
1098         uint64_t *p;
1099         uint32_t *buf;
1100         unsigned int idx, i = 0;
1101
1102         if (argc != start_arg + 1)
1103                 return -1;
1104
1105         if (get_int_arg(argv[start_arg], &idx))
1106                 return -1;
1107
1108         op = malloc(sizeof(*op) + MEM_CM_WRC_SIZE);
1109         if (!op)
1110                 err(1, "get_wrc: malloc failed");
1111
1112         op->cmd    = TOETOOL_GET_MEM;
1113         op->mem_id = MEM_CM;
1114         op->addr   = read_reg(iff_name, 0x28c) + CM_WRCONTEXT_OFFSET +
1115                               idx * MEM_CM_WRC_SIZE;
1116         op->len    = MEM_CM_WRC_SIZE;
1117         buf = (uint32_t *)op->buf;
1118
1119         if (doit(iff_name, op) < 0)
1120                 err(1, "get_wrc");
1121
1122         /* driver manges with the data... put it back into the the FW's view
1123          */
1124         for (p = (uint64_t *)op->buf;
1125                  p < (uint64_t *)(op->buf + MEM_CM_WRC_SIZE); p++) {
1126                 uint64_t flit = *p;
1127                 buf[i++] = htonl((uint32_t)(flit >> 32));
1128                 buf[i++] = htonl((uint32_t)flit);
1129         }
1130
1131         print_wrc(idx, (struct wrc *)op->buf);
1132         print_wrc_zero(idx, (struct wrc *)op->buf);
1133         print_wrc_history((struct wrc *)op->buf);
1134
1135         free(op);
1136         return 0;
1137 }
1138 #endif
1139
1140 #ifdef notyet
1141 static int get_pm_page_spec(const char *s, unsigned int *page_size,
1142                             unsigned int *num_pages)
1143 {
1144         char *p;
1145         unsigned long val;
1146
1147         val = strtoul(s, &p, 0);
1148         if (p == s) return -1;
1149         if (*p == 'x' && p[1]) {
1150                 *num_pages = val;
1151                 *page_size = strtoul(p + 1, &p, 0);
1152         } else {
1153                 *num_pages = -1;
1154                 *page_size = val;
1155         }
1156         *page_size <<= 10;     // KB -> bytes
1157         return *p;
1158 }
1159
1160 static int conf_pm(int argc, char *argv[], int start_arg, const char *iff_name)
1161 {
1162         struct toetool_pm op;
1163
1164         if (argc == start_arg) {
1165                 op.cmd = TOETOOL_GET_PM;
1166                 if (doit(iff_name, &op) < 0)
1167                         err(1, "read pm config");
1168                 printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n",
1169                        op.tx_num_pg, op.tx_pg_sz >> 10, op.rx_num_pg,
1170                        op.rx_pg_sz >> 10, op.pm_total >> 10);
1171                 return 0;
1172         }
1173
1174         if (argc != start_arg + 2) return -1;
1175
1176         if (get_pm_page_spec(argv[start_arg], &op.tx_pg_sz, &op.tx_num_pg)) {
1177                 warnx("bad parameter \"%s\"", argv[start_arg]);
1178                 return -1;
1179         }
1180         if (get_pm_page_spec(argv[start_arg + 1], &op.rx_pg_sz,
1181                              &op.rx_num_pg)) {
1182                 warnx("bad parameter \"%s\"", argv[start_arg + 1]);
1183                 return -1;
1184         }
1185         op.cmd = TOETOOL_SET_PM;
1186         if (doit(iff_name, &op) < 0)
1187                 err(1, "pm config");
1188         return 0;
1189 }
1190
1191 static int conf_tcam(int argc, char *argv[], int start_arg,
1192                      const char *iff_name)
1193 {
1194         struct toetool_tcam op;
1195
1196         if (argc == start_arg) {
1197                 op.cmd = TOETOOL_GET_TCAM;
1198                 op.nfilters = 0;
1199                 if (doit(iff_name, &op) < 0)
1200                         err(1, "read tcam config");
1201                 printf("%u total entries, %u servers, %u filters, %u routes\n",
1202                        op.tcam_size, op.nservers, op.nfilters, op.nroutes);
1203                 return 0;
1204         }
1205
1206         if (argc != start_arg + 3) return -1;
1207
1208         if (get_int_arg(argv[start_arg], &op.nservers) ||
1209             get_int_arg(argv[start_arg + 1], &op.nroutes) ||
1210             get_int_arg(argv[start_arg + 2], &op.nfilters))
1211                 return -1;
1212         op.cmd = TOETOOL_SET_TCAM;
1213         if (doit(iff_name, &op) < 0)
1214                 err(1, "tcam config");
1215         return 0;
1216 }
1217 #endif
1218
1219 #ifdef  CHELSIO_INTERNAL
1220 #ifdef notyet
1221 static int dump_tcam(int argc, char *argv[], int start_arg,
1222                      const char *iff_name)
1223 {
1224         unsigned int nwords;
1225         struct toetool_tcam_word op;
1226
1227         if (argc != start_arg + 2) return -1;
1228
1229         if (get_int_arg(argv[start_arg], &op.addr) ||
1230             get_int_arg(argv[start_arg + 1], &nwords))
1231                 return -1;
1232         op.cmd = TOETOOL_READ_TCAM_WORD;
1233
1234         while (nwords--) {
1235                 if (doit(iff_name, &op) < 0)
1236                         err(1, "tcam dump");
1237
1238                 printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr,
1239                        op.buf[0] & 0xff, op.buf[1], op.buf[2]);
1240                 op.addr++;
1241         }
1242         return 0;
1243 }
1244 #endif
1245 static void hexdump_8b(unsigned int start, uint64_t *data, unsigned int len)
1246 {
1247         int i;
1248
1249         while (len) {
1250                 printf("0x%08x:", start);
1251                 for (i = 0; i < 4 && len; ++i, --len)
1252                         printf(" %016llx", (unsigned long long)*data++);
1253                 printf("\n");
1254                 start += 32;
1255         }
1256 }
1257
1258 static int dump_mc7(int argc, char *argv[], int start_arg,
1259                     const char *iff_name)
1260 {
1261         struct ch_mem_range mem;
1262         unsigned int mem_id, addr, len;
1263
1264         if (argc != start_arg + 3) return -1;
1265
1266         if (!strcmp(argv[start_arg], "cm"))
1267                 mem_id = MEM_CM;
1268         else if (!strcmp(argv[start_arg], "rx"))
1269                 mem_id = MEM_PMRX;
1270         else if (!strcmp(argv[start_arg], "tx"))
1271                 mem_id = MEM_PMTX;
1272         else
1273                 errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\","
1274                         " or \"rx\"", argv[start_arg]);
1275
1276         if (get_int_arg(argv[start_arg + 1], &addr) ||
1277             get_int_arg(argv[start_arg + 2], &len))
1278                 return -1;
1279
1280         mem.buf = malloc(len);
1281         if (!mem.buf)
1282                 err(1, "memory dump");
1283
1284         mem.mem_id = mem_id;
1285         mem.addr   = addr;
1286         mem.len    = len;
1287
1288         if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0)
1289                 err(1, "memory dump");
1290
1291         hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3);
1292         free(mem.buf);
1293         return 0;
1294 }
1295 #endif
1296
1297 #ifdef notyet
1298 /* Max FW size is 32K including version, +4 bytes for the checksum. */
1299 #define MAX_FW_IMAGE_SIZE (32768 + 4)
1300
1301 static int load_fw(int argc, char *argv[], int start_arg, const char *iff_name)
1302 {
1303         int fd, len;
1304         struct toetool_mem_range *op;
1305         const char *fname = argv[start_arg];
1306
1307         if (argc != start_arg + 1) return -1;
1308
1309         fd = open(fname, O_RDONLY);
1310         if (fd < 0)
1311                 err(1, "load firmware");
1312
1313         op = malloc(sizeof(*op) + MAX_FW_IMAGE_SIZE + 1);
1314         if (!op)
1315                 err(1, "load firmware");
1316
1317         len = read(fd, op->buf, MAX_FW_IMAGE_SIZE + 1);
1318         if (len < 0)
1319                 err(1, "load firmware");
1320         if (len > MAX_FW_IMAGE_SIZE)
1321                 errx(1, "FW image too large");
1322
1323         op->cmd = TOETOOL_LOAD_FW;
1324         op->len = len;
1325
1326         if (doit(iff_name, op) < 0)
1327                 err(1, "load firmware");
1328         return 0;
1329 }
1330
1331
1332 static int write_proto_sram(const char *fname, const char *iff_name)
1333 {
1334         int i;
1335         char c;
1336         struct toetool_proto op = { .cmd = TOETOOL_SET_PROTO };
1337         uint32_t *p = op.data;
1338         FILE *fp = fopen(fname, "r");
1339
1340         if (!fp)
1341                 err(1, "load protocol sram");
1342
1343         for (i = 0; i < 128; i++, p += 5) {
1344                 int n = fscanf(fp, "%1x%8x%8x%8x%8x",
1345                                &p[0], &p[1], &p[2], &p[3], &p[4]);
1346                 if (n != 5)
1347                         errx(1, "%s: bad line %d", fname, i);
1348         }
1349         if (fscanf(fp, "%1s", &c) != EOF)
1350                 errx(1, "%s: protocol sram image has too many lines", fname);
1351         fclose(fp);
1352
1353         if (doit(iff_name, &op) < 0)
1354                 err(1, "load protocol sram");
1355         return 0;
1356 }
1357
1358 static int dump_proto_sram(const char *iff_name)
1359 {
1360         int i, j;
1361         u8 buf[sizeof(struct ethtool_eeprom) + PROTO_SRAM_SIZE];
1362         struct ethtool_eeprom *ee = (struct ethtool_eeprom *)buf;
1363         u8 *p = buf + sizeof(struct ethtool_eeprom);
1364
1365         ee->cmd = ETHTOOL_GEEPROM;
1366         ee->len = PROTO_SRAM_SIZE;
1367         ee->offset = PROTO_SRAM_EEPROM_ADDR;
1368         if (ethtool_call(iff_name, ee))
1369                 err(1, "show protocol sram");
1370
1371         for (i = 0; i < PROTO_SRAM_LINES; i++) {
1372                 for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) {
1373                         int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j;
1374                         u8 nibble = p[nibble_idx / 2];
1375
1376                         if (nibble_idx & 1)
1377                                 nibble >>= 4;
1378                         else
1379                                 nibble &= 0xf;
1380                         printf("%x", nibble);
1381                 }
1382                 putchar('\n');
1383         }
1384         return 0;
1385 }
1386
1387 static int proto_sram_op(int argc, char *argv[], int start_arg,
1388                          const char *iff_name)
1389 {
1390         if (argc == start_arg + 1)
1391                 return write_proto_sram(argv[start_arg], iff_name);
1392         if (argc == start_arg)
1393                 return dump_proto_sram(iff_name);
1394         return -1;
1395 }
1396 #endif
1397
1398 static int dump_qset_params(const char *iff_name)
1399 {
1400         struct ch_qset_params qp;
1401
1402         qp.qset_idx = 0;
1403
1404         while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) {
1405                 if (!qp.qset_idx)
1406                         printf("Qnum   TxQ0   TxQ1   TxQ2   RspQ   RxQ0   RxQ1"
1407                                "  Cong  Intr Lat   Rx Mode\n");
1408                 printf("%4u %6u %6u %6u %6u %6u %6u %5u %9u   %s    \n",
1409                        qp.qset_idx,
1410                        qp.txq_size[0], qp.txq_size[1], qp.txq_size[2],
1411                        qp.rspq_size, qp.fl_size[0], qp.fl_size[1],
1412                        qp.cong_thres, qp.intr_lat,
1413                        qp.polling ? "Polling" : "Interrupt");
1414                 qp.qset_idx++;
1415         }
1416         if (!qp.qset_idx || (errno && errno != EINVAL))
1417                 err(1, "get qset parameters");
1418         return 0;
1419 }
1420
1421 static int qset_config(int argc, char *argv[], int start_arg,
1422                        const char *iff_name)
1423 {
1424         struct ch_qset_params qp;
1425
1426         if (argc == start_arg)
1427                 return dump_qset_params(iff_name);
1428
1429         if (get_int_arg(argv[start_arg++], &qp.qset_idx))
1430                 return -1;
1431
1432         qp.txq_size[0] = qp.txq_size[1] = qp.txq_size[2] = -1;
1433         qp.fl_size[0] = qp.fl_size[1] = qp.rspq_size = -1;
1434         qp.polling = qp.intr_lat = qp.cong_thres = -1;
1435
1436         while (start_arg + 2 <= argc) {
1437                 int32_t *param = NULL;
1438
1439                 if (!strcmp(argv[start_arg], "txq0"))
1440                         param = &qp.txq_size[0];
1441                 else if (!strcmp(argv[start_arg], "txq1"))
1442                         param = &qp.txq_size[1];
1443                 else if (!strcmp(argv[start_arg], "txq2"))
1444                         param = &qp.txq_size[2];
1445                 else if (!strcmp(argv[start_arg], "rspq"))
1446                         param = &qp.rspq_size;
1447                 else if (!strcmp(argv[start_arg], "fl0"))
1448                         param = &qp.fl_size[0];
1449                 else if (!strcmp(argv[start_arg], "fl1"))
1450                         param = &qp.fl_size[1];
1451                 else if (!strcmp(argv[start_arg], "lat"))
1452                         param = &qp.intr_lat;
1453                 else if (!strcmp(argv[start_arg], "cong"))
1454                         param = &qp.cong_thres;
1455                 else if (!strcmp(argv[start_arg], "mode"))
1456                         param = &qp.polling;
1457                 else
1458                         errx(1, "unknown qset parameter \"%s\"\n"
1459                              "allowed parameters are \"txq0\", \"txq1\", "
1460                              "\"txq2\", \"rspq\", \"fl0\", \"fl1\", \"lat\", "
1461                              "\"cong\", \"mode\' and \"lro\"", argv[start_arg]);
1462
1463                 start_arg++;
1464
1465                 if (param == &qp.polling) {
1466                         if (!strcmp(argv[start_arg], "irq"))
1467                                 qp.polling = 0;
1468                         else if (!strcmp(argv[start_arg], "polling"))
1469                                 qp.polling = 1;
1470                         else
1471                                 errx(1, "illegal qset mode \"%s\"\n"
1472                                      "known modes are \"irq\" and \"polling\"",
1473                                      argv[start_arg]);
1474                 } else if (get_int_arg(argv[start_arg], (uint32_t *)param))
1475                         return -1;
1476                 start_arg++;
1477         }
1478         if (start_arg != argc)
1479                 errx(1, "unknown parameter %s", argv[start_arg]);
1480
1481 #if 0
1482         printf("%4u %6d %6d %6d %6d %6d %6d %5d %9d   %d\n", op.qset_idx,
1483                op.txq_size[0], op.txq_size[1], op.txq_size[2],
1484                op.rspq_size, op.fl_size[0], op.fl_size[1], op.cong_thres,
1485                op.intr_lat, op.polling);
1486 #endif
1487         if (doit(iff_name, CHELSIO_SET_QSET_PARAMS, &qp) < 0)
1488                 err(1, "set qset parameters");
1489
1490         return 0;
1491 }
1492
1493 static int qset_num_config(int argc, char *argv[], int start_arg,
1494                            const char *iff_name)
1495 {
1496         struct ch_reg reg;
1497
1498         if (argc == start_arg) {
1499                 if (doit(iff_name, CHELSIO_GET_QSET_NUM, &reg) < 0)
1500                         err(1, "get qsets");
1501                 printf("%u\n", reg.val);
1502                 return 0;
1503         }
1504
1505         if (argc != start_arg + 1)
1506                 return -1;
1507         if (get_int_arg(argv[start_arg], &reg.val))
1508                 return -1;
1509
1510         if (doit(iff_name, CHELSIO_SET_QSET_NUM, &reg) < 0)
1511                 err(1, "set qsets");
1512         return 0;
1513 }
1514
1515 /*
1516  * Parse a string containing an IP address with an optional network prefix.
1517  */
1518 static int parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
1519 {
1520         char *p, *slash;
1521         struct in_addr ia;
1522
1523         *mask = 0xffffffffU;
1524         slash = strchr(s, '/');
1525         if (slash)
1526                 *slash = 0;
1527         if (!inet_aton(s, &ia)) {
1528                 if (slash)
1529                         *slash = '/';
1530                 *addr = 0;
1531                 return -1;
1532         }
1533         *addr = ntohl(ia.s_addr);
1534         if (slash) {
1535                 unsigned int prefix = strtoul(slash + 1, &p, 10);
1536
1537                 *slash = '/';
1538                 if (p == slash + 1 || *p || prefix > 32)
1539                         return -1;
1540                 *mask <<= (32 - prefix);
1541         }
1542         return 0;
1543 }
1544
1545 /*
1546  * Parse a string containing a value and an optional colon separated mask.
1547  */
1548 static int parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask)
1549 {
1550         char *p;
1551
1552         *mask = 0xffffffffU;
1553         *val = strtoul(s, &p, 0);
1554         if (p == s)
1555                 return -1;
1556         if (*p == ':' && p[1])
1557                 *mask = strtoul(p + 1, &p, 0);
1558         return *p ? -1 : 0;
1559 }
1560
1561 static int parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
1562 {
1563         return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
1564                                 parse_val_mask_param(s, val, mask);
1565 }
1566
1567 static int trace_config(int argc, char *argv[], int start_arg,
1568                         const char *iff_name)
1569 {
1570         uint32_t val, mask;
1571         struct ch_trace trace;
1572
1573         if (argc == start_arg)
1574                 return -1;
1575
1576         memset(&trace, 0, sizeof(trace));
1577         if (!strcmp(argv[start_arg], "tx"))
1578                 trace.config_tx = 1;
1579         else if (!strcmp(argv[start_arg], "rx"))
1580                 trace.config_rx = 1;
1581         else if (!strcmp(argv[start_arg], "all"))
1582                 trace.config_tx = trace.config_rx = 1;
1583         else
1584                 errx(1, "bad trace filter \"%s\"; must be one of \"rx\", "
1585                      "\"tx\" or \"all\"", argv[start_arg]);
1586
1587         if (argc == ++start_arg)
1588                 return -1;
1589         if (!strcmp(argv[start_arg], "on")) {
1590                 trace.trace_tx = trace.config_tx;
1591                 trace.trace_rx = trace.config_rx;
1592         } else if (strcmp(argv[start_arg], "off"))
1593                 errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"",
1594                      argv[start_arg]);
1595
1596         start_arg++;
1597         if (start_arg < argc && !strcmp(argv[start_arg], "not")) {
1598                 trace.invert_match = 1;
1599                 start_arg++;
1600         }
1601
1602         while (start_arg + 2 <= argc) {
1603                 int ret = parse_trace_param(argv[start_arg + 1], &val, &mask);
1604
1605                 if (!strcmp(argv[start_arg], "interface")) {
1606                         trace.intf = val;
1607                         trace.intf_mask = mask;
1608                 } else if (!strcmp(argv[start_arg], "sip")) {
1609                         trace.sip = val;
1610                         trace.sip_mask = mask;
1611                 } else if (!strcmp(argv[start_arg], "dip")) {
1612                         trace.dip = val;
1613                         trace.dip_mask = mask;
1614                 } else if (!strcmp(argv[start_arg], "sport")) {
1615                         trace.sport = val;
1616                         trace.sport_mask = mask;
1617                 } else if (!strcmp(argv[start_arg], "dport")) {
1618                         trace.dport = val;
1619                         trace.dport_mask = mask;
1620                 } else if (!strcmp(argv[start_arg], "vlan")) {
1621                         trace.vlan = val;
1622                         trace.vlan_mask = mask;
1623                 } else if (!strcmp(argv[start_arg], "proto")) {
1624                         trace.proto = val;
1625                         trace.proto_mask = mask;
1626                 } else
1627                         errx(1, "unknown trace parameter \"%s\"\n"
1628                              "known parameters are \"interface\", \"sip\", "
1629                              "\"dip\", \"sport\", \"dport\", \"vlan\", "
1630                              "\"proto\"", argv[start_arg]);
1631                 if (ret < 0)
1632                         errx(1, "bad parameter \"%s\"", argv[start_arg + 1]);
1633                 start_arg += 2;
1634         }
1635         if (start_arg != argc)
1636                 errx(1, "unknown parameter \"%s\"", argv[start_arg]);
1637
1638 #if 0
1639         printf("sip: %x:%x, dip: %x:%x, sport: %x:%x, dport: %x:%x, "
1640                "interface: %x:%x, vlan: %x:%x, tx_config: %u, rx_config: %u, "
1641                "invert: %u, tx_enable: %u, rx_enable: %u\n", op.sip,
1642                op.sip_mask, op.dip, op.dip_mask, op.sport, op.sport_mask,
1643                op.dport, op.dport_mask, op.intf, op.intf_mask, op.vlan,
1644                op.vlan_mask, op.config_tx, op.config_rx, op.invert_match,
1645                op.trace_tx, op.trace_rx);
1646 #endif
1647         if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0)
1648                 err(1, "trace");
1649         return 0;
1650 }
1651
1652 #ifdef notyet
1653 static int t1_powersave(int argc, char *argv[], int start_arg,
1654                      const char *iff_name)
1655 {
1656         struct toetool_t1powersave op = {
1657                 .cmd  = TOETOOL_T1POWERSAVE,
1658                 .mode = 0
1659         };
1660
1661         if (argc == start_arg)
1662                 op.mode = 2; /* Check powersave mode */
1663
1664         else if (argc == start_arg + 1) {
1665                 if (strcmp(argv[start_arg], "on") == 0)
1666                         op.mode = 1;
1667                 else if (strcmp(argv[start_arg], "off") == 0)
1668                         op.mode = 0;
1669                 else {
1670                         warnx("bad parameter \"%s\"", argv[start_arg]);
1671                         return -1;
1672                 }
1673         } else {
1674                 errx(1, "too many arguments");
1675                 return -1;
1676         }
1677
1678         if (doit(iff_name, &op) < 0)
1679                 err(1, "t1powersave");
1680
1681         if (op.mode & 2)
1682                 printf("t1powersave is %s\n", (op.mode & 1) ? "on" : "off");
1683
1684         return 0;
1685 }
1686 #endif
1687
1688 static int pktsched(int argc, char *argv[], int start_arg, const char *iff_name)
1689 {
1690         struct ch_pktsched_params pktsched;
1691         unsigned int idx, min = -1, max, binding = -1;
1692
1693         if (!strcmp(argv[start_arg], "port")) {
1694                 if (argc != start_arg + 4)
1695                         return -1;
1696                 if (get_int_arg(argv[start_arg + 1], &idx) ||
1697                     get_int_arg(argv[start_arg + 2], &min) ||
1698                     get_int_arg(argv[start_arg + 3], &max))
1699                         return -1;
1700                 pktsched.sched = 0;
1701         } else if (!strcmp(argv[start_arg], "tunnelq")) {
1702                 if (argc != start_arg + 4)
1703                         return -1;
1704                 if (get_int_arg(argv[start_arg + 1], &idx) ||
1705                     get_int_arg(argv[start_arg + 2], &max) ||
1706                     get_int_arg(argv[start_arg + 3], &binding))
1707                         return -1;
1708                 pktsched.sched = 1;
1709         } else
1710                 errx(1, "unknown scheduler \"%s\"; must be one of \"port\""
1711                         " or \"tunnelq\"", argv[start_arg]);
1712
1713         pktsched.idx = idx;
1714         pktsched.min = min;
1715         pktsched.max = max;
1716         pktsched.binding = binding;
1717         if (doit(iff_name, CHELSIO_SET_PKTSCHED, &pktsched) < 0)
1718                  err(1, "pktsched");
1719
1720         return 0;
1721 }
1722
1723 int main(int argc, char *argv[])
1724 {
1725         int r = -1;
1726         const char *iff_name;
1727
1728         progname = argv[0];
1729
1730         if (argc == 2) {
1731                 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1732                         usage(stdout);
1733                 if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
1734                         printf("%s version %s\n", PROGNAME, VERSION);
1735                         printf("%s\n", COPYRIGHT);
1736                         exit(0);
1737                 }
1738         }
1739
1740         if (argc < 3) usage(stderr);
1741
1742         iff_name = argv[1];
1743         if (!strcmp(argv[2], "reg"))
1744                 r = register_io(argc, argv, 3, iff_name);
1745         else if (!strcmp(argv[2], "mdio"))
1746                 r = mdio_io(argc, argv, 3, iff_name);
1747 #ifdef notyet   
1748         else if (!strcmp(argv[2], "tpi"))
1749                 r = tpi_io(argc, argv, 3, iff_name);
1750         else if (!strcmp(argv[2], "up"))
1751                 r = device_up(argc, argv, 3, iff_name);
1752         else if (!strcmp(argv[2], "mtus"))
1753                 r = mtu_tab_op(argc, argv, 3, iff_name);
1754         else if (!strcmp(argv[2], "pm"))
1755                 r = conf_pm(argc, argv, 3, iff_name);
1756         else if (!strcmp(argv[2], "tcam"))
1757                 r = conf_tcam(argc, argv, 3, iff_name);
1758         else if (!strcmp(argv[2], "tcb"))
1759                 r = get_tcb(argc, argv, 3, iff_name);
1760 #ifdef WRC
1761         else if (!strcmp(argv[2], "wrc"))
1762                 r = get_wrc(argc, argv, 3, iff_name);
1763 #endif
1764 #endif  
1765         else if (!strcmp(argv[2], "regdump"))
1766                 r = dump_regs(argc, argv, 3, iff_name);
1767 #ifdef CHELSIO_INTERNAL
1768         else if (!strcmp(argv[2], "memdump"))
1769                 r = dump_mc7(argc, argv, 3, iff_name);
1770         else if (!strcmp(argv[2], "meminfo"))
1771                 r = meminfo(argc, argv, 3, iff_name);
1772         else if (!strcmp(argv[2], "context"))
1773                 r = get_sge_context(argc, argv, 3, iff_name);
1774         else if (!strcmp(argv[2], "desc"))
1775                 r = get_sge_desc(argc, argv, 3, iff_name);
1776 #endif
1777         else if (!strcmp(argv[2], "qset"))
1778                 r = qset_config(argc, argv, 3, iff_name);
1779         else if (!strcmp(argv[2], "qsets"))
1780                 r = qset_num_config(argc, argv, 3, iff_name);
1781         else if (!strcmp(argv[2], "trace"))
1782                 r = trace_config(argc, argv, 3, iff_name);
1783 #ifdef notyet
1784         else if (!strcmp(argv[2], "tcamdump"))
1785                 r = dump_tcam(argc, argv, 3, iff_name);
1786         else if (!strcmp(argv[2], "loadfw"))
1787                 r = load_fw(argc, argv, 3, iff_name);
1788         else if (!strcmp(argv[2], "proto"))
1789                 r = proto_sram_op(argc, argv, 3, iff_name);
1790         else if (!strcmp(argv[2], "t1powersave"))               
1791                 r = t1_powersave(argc, argv, 3, iff_name);
1792 #endif  
1793         else if (!strcmp(argv[2], "pktsched"))
1794                 r = pktsched(argc, argv, 3, iff_name);
1795         if (r == -1)
1796                 usage(stderr);
1797         return 0;
1798 }