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