xref: /freebsd/sys/dev/bxe/bxe_debug.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*-
2  * Copyright (c) 2007-2013 Broadcom Corporation. All rights reserved.
3  *
4  * Eric Davis        <edavis@broadcom.com>
5  * David Christensen <davidch@broadcom.com>
6  * Gary Zambrano     <zambrano@broadcom.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of Broadcom Corporation nor the name of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written consent.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include "bxe.h"
38 
39 #include "ddb/ddb.h"
40 #include "ddb/db_sym.h"
41 #include "ddb/db_lex.h"
42 
43 #ifdef BXE_REG_NO_INLINE
44 
45 /*
46  * Debug versions of the 8/16/32 bit OS register read/write functions to
47  * capture/display values read/written from/to the controller.
48  */
49 
50 void
51 bxe_reg_write8(struct bxe_softc *sc, bus_size_t offset, uint8_t val)
52 {
53     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
54     bus_space_write_1(sc->bar[BAR0].tag,
55                       sc->bar[BAR0].handle,
56                       offset,
57                       val);
58 }
59 
60 void
61 bxe_reg_write16(struct bxe_softc *sc, bus_size_t offset, uint16_t val)
62 {
63     if ((offset % 2) != 0) {
64         BLOGD(sc, DBG_REGS, "Unaligned 16-bit write to 0x%08lx\n", offset);
65     }
66 
67     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%04x\n", offset, val);
68     bus_space_write_2(sc->bar[BAR0].tag,
69                       sc->bar[BAR0].handle,
70                       offset,
71                       val);
72 }
73 
74 void
75 bxe_reg_write32(struct bxe_softc *sc, bus_size_t offset, uint32_t val)
76 {
77     if ((offset % 4) != 0) {
78         BLOGD(sc, DBG_REGS, "Unaligned 32-bit write to 0x%08lx\n", offset);
79     }
80 
81     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
82     bus_space_write_4(sc->bar[BAR0].tag,
83                       sc->bar[BAR0].handle,
84                       offset,
85                       val);
86 }
87 
88 uint8_t
89 bxe_reg_read8(struct bxe_softc *sc, bus_size_t offset)
90 {
91     uint8_t val;
92 
93     val = bus_space_read_1(sc->bar[BAR0].tag,
94                            sc->bar[BAR0].handle,
95                            offset);
96     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
97 
98     return (val);
99 }
100 
101 uint16_t
102 bxe_reg_read16(struct bxe_softc *sc, bus_size_t offset)
103 {
104     uint16_t val;
105 
106     if ((offset % 2) != 0) {
107         BLOGD(sc, DBG_REGS, "Unaligned 16-bit read from 0x%08lx\n", offset);
108     }
109 
110     val = bus_space_read_2(sc->bar[BAR0].tag,
111                            sc->bar[BAR0].handle,
112                            offset);
113     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
114 
115     return (val);
116 }
117 
118 uint32_t
119 bxe_reg_read32(struct bxe_softc *sc, bus_size_t offset)
120 {
121     uint32_t val;
122 
123     if ((offset % 4) != 0) {
124         BLOGD(sc, DBG_REGS, "Unaligned 32-bit read from 0x%08lx\n", offset);
125     }
126 
127     val = bus_space_read_4(sc->bar[BAR0].tag,
128                            sc->bar[BAR0].handle,
129                            offset);
130     BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
131 
132     return (val);
133 }
134 
135 #endif /* BXE_REG_NO_INLINE */
136 
137 #ifdef ELINK_DEBUG
138 
139 void
140 elink_cb_dbg(struct bxe_softc *sc,
141              char             *fmt)
142 {
143     char buf[128];
144     if (__predict_false(sc->debug & DBG_PHY)) {
145         snprintf(buf, sizeof(buf), "ELINK: %s", fmt);
146         device_printf(sc->dev, "%s", buf);
147     }
148 }
149 
150 void
151 elink_cb_dbg1(struct bxe_softc *sc,
152               char             *fmt,
153               uint32_t         arg1)
154 {
155     char tmp[128], buf[128];
156     if (__predict_false(sc->debug & DBG_PHY)) {
157         snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
158         snprintf(buf, sizeof(buf), tmp, arg1);
159         device_printf(sc->dev, "%s", buf);
160     }
161 }
162 
163 void
164 elink_cb_dbg2(struct bxe_softc *sc,
165               char             *fmt,
166               uint32_t         arg1,
167               uint32_t         arg2)
168 {
169     char tmp[128], buf[128];
170     if (__predict_false(sc->debug & DBG_PHY)) {
171         snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
172         snprintf(buf, sizeof(buf), tmp, arg1, arg2);
173         device_printf(sc->dev, "%s", buf);
174     }
175 }
176 
177 void
178 elink_cb_dbg3(struct bxe_softc *sc,
179               char             *fmt,
180               uint32_t         arg1,
181               uint32_t         arg2,
182               uint32_t         arg3)
183 {
184     char tmp[128], buf[128];
185     if (__predict_false(sc->debug & DBG_PHY)) {
186         snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
187         snprintf(buf, sizeof(buf), tmp, arg1, arg2, arg3);
188         device_printf(sc->dev, "%s", buf);
189     }
190 }
191 
192 #endif /* ELINK_DEBUG */
193 
194 extern struct mtx bxe_prev_mtx;
195 
196 void
197 bxe_dump_mem(struct bxe_softc *sc,
198              char             *tag,
199              uint8_t          *mem,
200              uint32_t         len)
201 {
202     char buf[256];
203     char c[32];
204     int  xx;
205 
206     mtx_lock(&bxe_prev_mtx);
207 
208     BLOGI(sc, "++++++++++++ %s\n", tag);
209     strcpy(buf, "** 000: ");
210 
211     for (xx = 0; xx < len; xx++)
212     {
213         if ((xx != 0) && (xx % 16 == 0))
214         {
215             BLOGI(sc, "%s\n", buf);
216             strcpy(buf, "** ");
217             snprintf(c, sizeof(c), "%03x", xx);
218             strcat(buf, c);
219             strcat(buf, ": ");
220         }
221 
222         snprintf(c, sizeof(c), "%02x ", *mem);
223         strcat(buf, c);
224 
225         mem++;
226     }
227 
228     BLOGI(sc, "%s\n", buf);
229     BLOGI(sc, "------------ %s\n", tag);
230 
231     mtx_unlock(&bxe_prev_mtx);
232 }
233 
234 void
235 bxe_dump_mbuf_data(struct bxe_softc *sc,
236                    char             *tag,
237                    struct mbuf      *m,
238                    uint8_t          contents)
239 {
240     char buf[256];
241     char c[32];
242     uint8_t *memp;
243     int i, xx = 0;
244 
245     mtx_lock(&bxe_prev_mtx);
246 
247     BLOGI(sc, "++++++++++++ %s\n", tag);
248 
249     while (m)
250     {
251         memp = m->m_data;
252         strcpy(buf, "** > ");
253         snprintf(c, sizeof(c), "%03x", xx);
254         strcat(buf, c);
255         strcat(buf, ": ");
256 
257         if (contents)
258         {
259             for (i = 0; i < m->m_len; i++)
260             {
261                 if ((xx != 0) && (xx % 16 == 0))
262                 {
263                     BLOGI(sc, "%s\n", buf);
264                     strcpy(buf, "**   ");
265                     snprintf(c, sizeof(c), "%03x", xx);
266                     strcat(buf, c);
267                     strcat(buf, ": ");
268                 }
269 
270                 snprintf(c, sizeof(c), "%02x ", *memp);
271                 strcat(buf, c);
272 
273                 memp++;
274                 xx++;
275             }
276         }
277         else
278         {
279             snprintf(c, sizeof(c), "%d", m->m_len);
280             strcat(buf, c);
281             xx += m->m_len;
282         }
283 
284         BLOGI(sc, "%s\n", buf);
285         m = m->m_next;
286     }
287 
288     BLOGI(sc, "------------ %s\n", tag);
289 
290     mtx_unlock(&bxe_prev_mtx);
291 }
292 
293 #ifdef DDB
294 
295 static void bxe_ddb_usage()
296 {
297     db_printf("Usage: bxe[/hpv] <instance> [<address>]\n");
298 }
299 
300 static db_cmdfcn_t bxe_ddb;
301 _DB_SET(_cmd, bxe, bxe_ddb, db_cmd_table, CS_OWN, NULL);
302 
303 static void bxe_ddb(db_expr_t blah1,
304                     boolean_t blah2,
305                     db_expr_t blah3,
306                     char      *blah4)
307 {
308     char if_xname[IFNAMSIZ];
309     struct ifnet *ifp = NULL;
310     struct bxe_softc *sc;
311     db_expr_t next_arg;
312     int index;
313     int tok;
314     int mod_phys_addr = FALSE;
315     int mod_virt_addr = FALSE;
316     db_addr_t addr;
317 
318     tok = db_read_token();
319     if (tok == tSLASH) {
320         tok = db_read_token();
321         if (tok != tIDENT) {
322             db_printf("ERROR: bad modifier\n");
323             bxe_ddb_usage();
324             goto bxe_ddb_done;
325         }
326         if (strcmp(db_tok_string, "h") == 0) {
327             bxe_ddb_usage();
328             goto bxe_ddb_done;
329         } else if (strcmp(db_tok_string, "p") == 0) {
330             mod_phys_addr = TRUE;
331         } else if (strcmp(db_tok_string, "v") == 0) {
332             mod_virt_addr = TRUE;
333         }
334     } else {
335         db_unread_token(tok);
336     }
337 
338     if (!db_expression((db_expr_t *)&index)) {
339         db_printf("ERROR: bxe index missing\n");
340         bxe_ddb_usage();
341         goto bxe_ddb_done;
342     }
343 
344     snprintf(if_xname, sizeof(if_xname), "bxe%d", index);
345     if ((ifp = ifunit_ref(if_xname)) == NULL)
346     {
347         db_printf("ERROR: Invalid interface %s\n", if_xname);
348         goto bxe_ddb_done;
349     }
350 
351     sc = (struct bxe_softc *)ifp->if_softc;
352     db_printf("ifnet=%p (%s)\n", ifp, if_xname);
353     db_printf("softc=%p\n", sc);
354     db_printf("  dev=%p\n", sc->dev);
355     db_printf("  BDF=%d:%d:%d\n",
356               sc->pcie_bus, sc->pcie_device, sc->pcie_func);
357 
358     if (mod_phys_addr || mod_virt_addr) {
359         if (!db_expression((db_addr_t *)&addr)) {
360             db_printf("ERROR: Invalid address\n");
361             bxe_ddb_usage();
362             goto bxe_ddb_done;
363         }
364 
365         db_printf("addr=%p", addr);
366     }
367 
368 bxe_ddb_done:
369 
370     db_flush_lex();
371     if (ifp) if_rele(ifp);
372 }
373 
374 #endif /* DDB */
375 
376