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 #include "bxe.h"
31
32 #include "ddb/ddb.h"
33 #include "ddb/db_sym.h"
34 #include "ddb/db_lex.h"
35
36 #ifdef BXE_REG_NO_INLINE
37
38 /*
39 * Debug versions of the 8/16/32 bit OS register read/write functions to
40 * capture/display values read/written from/to the controller.
41 */
42
43 void
bxe_reg_write8(struct bxe_softc * sc,bus_size_t offset,uint8_t val)44 bxe_reg_write8(struct bxe_softc *sc, bus_size_t offset, uint8_t val)
45 {
46 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
47 bus_space_write_1(sc->bar[BAR0].tag,
48 sc->bar[BAR0].handle,
49 offset,
50 val);
51 }
52
53 void
bxe_reg_write16(struct bxe_softc * sc,bus_size_t offset,uint16_t val)54 bxe_reg_write16(struct bxe_softc *sc, bus_size_t offset, uint16_t val)
55 {
56 if ((offset % 2) != 0) {
57 BLOGD(sc, DBG_REGS, "Unaligned 16-bit write to 0x%08lx\n", offset);
58 }
59
60 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%04x\n", offset, val);
61 bus_space_write_2(sc->bar[BAR0].tag,
62 sc->bar[BAR0].handle,
63 offset,
64 val);
65 }
66
67 void
bxe_reg_write32(struct bxe_softc * sc,bus_size_t offset,uint32_t val)68 bxe_reg_write32(struct bxe_softc *sc, bus_size_t offset, uint32_t val)
69 {
70 if ((offset % 4) != 0) {
71 BLOGD(sc, DBG_REGS, "Unaligned 32-bit write to 0x%08lx\n", offset);
72 }
73
74 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
75 bus_space_write_4(sc->bar[BAR0].tag,
76 sc->bar[BAR0].handle,
77 offset,
78 val);
79 }
80
81 uint8_t
bxe_reg_read8(struct bxe_softc * sc,bus_size_t offset)82 bxe_reg_read8(struct bxe_softc *sc, bus_size_t offset)
83 {
84 uint8_t val;
85
86 val = bus_space_read_1(sc->bar[BAR0].tag,
87 sc->bar[BAR0].handle,
88 offset);
89 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
90
91 return (val);
92 }
93
94 uint16_t
bxe_reg_read16(struct bxe_softc * sc,bus_size_t offset)95 bxe_reg_read16(struct bxe_softc *sc, bus_size_t offset)
96 {
97 uint16_t val;
98
99 if ((offset % 2) != 0) {
100 BLOGD(sc, DBG_REGS, "Unaligned 16-bit read from 0x%08lx\n", offset);
101 }
102
103 val = bus_space_read_2(sc->bar[BAR0].tag,
104 sc->bar[BAR0].handle,
105 offset);
106 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
107
108 return (val);
109 }
110
111 uint32_t
bxe_reg_read32(struct bxe_softc * sc,bus_size_t offset)112 bxe_reg_read32(struct bxe_softc *sc, bus_size_t offset)
113 {
114 uint32_t val;
115
116 if ((offset % 4) != 0) {
117 BLOGD(sc, DBG_REGS, "Unaligned 32-bit read from 0x%08lx\n", offset);
118 }
119
120 val = bus_space_read_4(sc->bar[BAR0].tag,
121 sc->bar[BAR0].handle,
122 offset);
123 BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
124
125 return (val);
126 }
127
128 #endif /* BXE_REG_NO_INLINE */
129
130 #ifdef ELINK_DEBUG
131
132 void
elink_cb_dbg(struct bxe_softc * sc,char * fmt)133 elink_cb_dbg(struct bxe_softc *sc,
134 char *fmt)
135 {
136 char buf[128];
137 if (__predict_false(sc->debug & DBG_PHY)) {
138 snprintf(buf, sizeof(buf), "ELINK: %s", fmt);
139 device_printf(sc->dev, "%s", buf);
140 }
141 }
142
143 void
elink_cb_dbg1(struct bxe_softc * sc,char * fmt,uint32_t arg1)144 elink_cb_dbg1(struct bxe_softc *sc,
145 char *fmt,
146 uint32_t arg1)
147 {
148 char tmp[128], buf[128];
149 if (__predict_false(sc->debug & DBG_PHY)) {
150 snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
151 snprintf(buf, sizeof(buf), tmp, arg1);
152 device_printf(sc->dev, "%s", buf);
153 }
154 }
155
156 void
elink_cb_dbg2(struct bxe_softc * sc,char * fmt,uint32_t arg1,uint32_t arg2)157 elink_cb_dbg2(struct bxe_softc *sc,
158 char *fmt,
159 uint32_t arg1,
160 uint32_t arg2)
161 {
162 char tmp[128], buf[128];
163 if (__predict_false(sc->debug & DBG_PHY)) {
164 snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
165 snprintf(buf, sizeof(buf), tmp, arg1, arg2);
166 device_printf(sc->dev, "%s", buf);
167 }
168 }
169
170 void
elink_cb_dbg3(struct bxe_softc * sc,char * fmt,uint32_t arg1,uint32_t arg2,uint32_t arg3)171 elink_cb_dbg3(struct bxe_softc *sc,
172 char *fmt,
173 uint32_t arg1,
174 uint32_t arg2,
175 uint32_t arg3)
176 {
177 char tmp[128], buf[128];
178 if (__predict_false(sc->debug & DBG_PHY)) {
179 snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
180 snprintf(buf, sizeof(buf), tmp, arg1, arg2, arg3);
181 device_printf(sc->dev, "%s", buf);
182 }
183 }
184
185 #endif /* ELINK_DEBUG */
186
187 extern struct mtx bxe_prev_mtx;
188
189 void
bxe_dump_mem(struct bxe_softc * sc,char * tag,uint8_t * mem,uint32_t len)190 bxe_dump_mem(struct bxe_softc *sc,
191 char *tag,
192 uint8_t *mem,
193 uint32_t len)
194 {
195 char buf[256];
196 char c[32];
197 int xx;
198
199 mtx_lock(&bxe_prev_mtx);
200
201 BLOGI(sc, "++++++++++++ %s\n", tag);
202 strcpy(buf, "** 000: ");
203
204 for (xx = 0; xx < len; xx++)
205 {
206 if ((xx != 0) && (xx % 16 == 0))
207 {
208 BLOGI(sc, "%s\n", buf);
209 strcpy(buf, "** ");
210 snprintf(c, sizeof(c), "%03x", xx);
211 strcat(buf, c);
212 strcat(buf, ": ");
213 }
214
215 snprintf(c, sizeof(c), "%02x ", *mem);
216 strcat(buf, c);
217
218 mem++;
219 }
220
221 BLOGI(sc, "%s\n", buf);
222 BLOGI(sc, "------------ %s\n", tag);
223
224 mtx_unlock(&bxe_prev_mtx);
225 }
226
227 void
bxe_dump_mbuf_data(struct bxe_softc * sc,char * tag,struct mbuf * m,uint8_t contents)228 bxe_dump_mbuf_data(struct bxe_softc *sc,
229 char *tag,
230 struct mbuf *m,
231 uint8_t contents)
232 {
233 char buf[256];
234 char c[32];
235 uint8_t *memp;
236 int i, xx = 0;
237
238 mtx_lock(&bxe_prev_mtx);
239
240 BLOGI(sc, "++++++++++++ %s\n", tag);
241
242 while (m)
243 {
244 memp = m->m_data;
245 strcpy(buf, "** > ");
246 snprintf(c, sizeof(c), "%03x", xx);
247 strcat(buf, c);
248 strcat(buf, ": ");
249
250 if (contents)
251 {
252 for (i = 0; i < m->m_len; i++)
253 {
254 if ((xx != 0) && (xx % 16 == 0))
255 {
256 BLOGI(sc, "%s\n", buf);
257 strcpy(buf, "** ");
258 snprintf(c, sizeof(c), "%03x", xx);
259 strcat(buf, c);
260 strcat(buf, ": ");
261 }
262
263 snprintf(c, sizeof(c), "%02x ", *memp);
264 strcat(buf, c);
265
266 memp++;
267 xx++;
268 }
269 }
270 else
271 {
272 snprintf(c, sizeof(c), "%d", m->m_len);
273 strcat(buf, c);
274 xx += m->m_len;
275 }
276
277 BLOGI(sc, "%s\n", buf);
278 m = m->m_next;
279 }
280
281 BLOGI(sc, "------------ %s\n", tag);
282
283 mtx_unlock(&bxe_prev_mtx);
284 }
285
286 #ifdef DDB
287
bxe_ddb_usage()288 static void bxe_ddb_usage()
289 {
290 db_printf("Usage: bxe[/hpv] <instance> [<address>]\n");
291 }
292
DB_COMMAND_FLAGS(bxe,bxe_ddb,CS_OWN)293 DB_COMMAND_FLAGS(bxe, bxe_ddb, CS_OWN)
294 {
295 char if_xname[IFNAMSIZ];
296 if_t ifp = NULL;
297 struct bxe_softc *sc;
298 db_expr_t next_arg;
299 int index;
300 int tok;
301 int mod_phys_addr = FALSE;
302 int mod_virt_addr = FALSE;
303 db_addr_t addr;
304
305 tok = db_read_token();
306 if (tok == tSLASH) {
307 tok = db_read_token();
308 if (tok != tIDENT) {
309 db_printf("ERROR: bad modifier\n");
310 bxe_ddb_usage();
311 goto bxe_ddb_done;
312 }
313 if (strcmp(db_tok_string, "h") == 0) {
314 bxe_ddb_usage();
315 goto bxe_ddb_done;
316 } else if (strcmp(db_tok_string, "p") == 0) {
317 mod_phys_addr = TRUE;
318 } else if (strcmp(db_tok_string, "v") == 0) {
319 mod_virt_addr = TRUE;
320 }
321 } else {
322 db_unread_token(tok);
323 }
324
325 if (!db_expression((db_expr_t *)&index)) {
326 db_printf("ERROR: bxe index missing\n");
327 bxe_ddb_usage();
328 goto bxe_ddb_done;
329 }
330
331 snprintf(if_xname, sizeof(if_xname), "bxe%d", index);
332 if ((ifp = ifunit_ref(if_xname)) == NULL) /* XXX */
333 {
334 db_printf("ERROR: Invalid interface %s\n", if_xname);
335 goto bxe_ddb_done;
336 }
337
338 sc = (struct bxe_softc *)if_getsoftc(ifp);
339 db_printf("ifnet=%p (%s)\n", ifp, if_xname);
340 db_printf("softc=%p\n", sc);
341 db_printf(" dev=%p\n", sc->dev);
342 db_printf(" BDF=%d:%d:%d\n",
343 sc->pcie_bus, sc->pcie_device, sc->pcie_func);
344
345 if (mod_phys_addr || mod_virt_addr) {
346 if (!db_expression((db_addr_t *)&addr)) {
347 db_printf("ERROR: Invalid address\n");
348 bxe_ddb_usage();
349 goto bxe_ddb_done;
350 }
351
352 db_printf("addr=%p", addr);
353 }
354
355 bxe_ddb_done:
356
357 db_flush_lex();
358 if (ifp) if_rele(ifp);
359 }
360
361 #endif /* DDB */
362
363