1255736Sdavidch/*-
2255736Sdavidch * Copyright (c) 2007-2013 Broadcom Corporation. All rights reserved.
3255736Sdavidch *
4255736Sdavidch * Eric Davis        <edavis@broadcom.com>
5255736Sdavidch * David Christensen <davidch@broadcom.com>
6255736Sdavidch * Gary Zambrano     <zambrano@broadcom.com>
7255736Sdavidch *
8255736Sdavidch * Redistribution and use in source and binary forms, with or without
9255736Sdavidch * modification, are permitted provided that the following conditions
10255736Sdavidch * are met:
11255736Sdavidch *
12255736Sdavidch * 1. Redistributions of source code must retain the above copyright
13255736Sdavidch *    notice, this list of conditions and the following disclaimer.
14255736Sdavidch * 2. Redistributions in binary form must reproduce the above copyright
15255736Sdavidch *    notice, this list of conditions and the following disclaimer in the
16255736Sdavidch *    documentation and/or other materials provided with the distribution.
17255736Sdavidch * 3. Neither the name of Broadcom Corporation nor the name of its contributors
18255736Sdavidch *    may be used to endorse or promote products derived from this software
19255736Sdavidch *    without specific prior written consent.
20255736Sdavidch *
21255736Sdavidch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
22255736Sdavidch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23255736Sdavidch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24255736Sdavidch * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25255736Sdavidch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26255736Sdavidch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27255736Sdavidch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28255736Sdavidch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29255736Sdavidch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30255736Sdavidch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31255736Sdavidch * THE POSSIBILITY OF SUCH DAMAGE.
32255736Sdavidch */
33255736Sdavidch
34255736Sdavidch#include <sys/cdefs.h>
35255736Sdavidch__FBSDID("$FreeBSD$");
36255736Sdavidch
37255736Sdavidch#include "bxe.h"
38255736Sdavidch
39255736Sdavidch#include "ddb/ddb.h"
40255736Sdavidch#include "ddb/db_sym.h"
41255736Sdavidch#include "ddb/db_lex.h"
42255736Sdavidch
43255736Sdavidch#ifdef BXE_REG_NO_INLINE
44255736Sdavidch
45255736Sdavidch/*
46255736Sdavidch * Debug versions of the 8/16/32 bit OS register read/write functions to
47255736Sdavidch * capture/display values read/written from/to the controller.
48255736Sdavidch */
49255736Sdavidch
50255736Sdavidchvoid
51255736Sdavidchbxe_reg_write8(struct bxe_softc *sc, bus_size_t offset, uint8_t val)
52255736Sdavidch{
53255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
54255736Sdavidch    bus_space_write_1(sc->bar[BAR0].tag,
55255736Sdavidch                      sc->bar[BAR0].handle,
56255736Sdavidch                      offset,
57255736Sdavidch                      val);
58255736Sdavidch}
59255736Sdavidch
60255736Sdavidchvoid
61255736Sdavidchbxe_reg_write16(struct bxe_softc *sc, bus_size_t offset, uint16_t val)
62255736Sdavidch{
63255736Sdavidch    if ((offset % 2) != 0) {
64255736Sdavidch        BLOGD(sc, DBG_REGS, "Unaligned 16-bit write to 0x%08lx\n", offset);
65255736Sdavidch    }
66255736Sdavidch
67255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%04x\n", offset, val);
68255736Sdavidch    bus_space_write_2(sc->bar[BAR0].tag,
69255736Sdavidch                      sc->bar[BAR0].handle,
70255736Sdavidch                      offset,
71255736Sdavidch                      val);
72255736Sdavidch}
73255736Sdavidch
74255736Sdavidchvoid
75255736Sdavidchbxe_reg_write32(struct bxe_softc *sc, bus_size_t offset, uint32_t val)
76255736Sdavidch{
77255736Sdavidch    if ((offset % 4) != 0) {
78255736Sdavidch        BLOGD(sc, DBG_REGS, "Unaligned 32-bit write to 0x%08lx\n", offset);
79255736Sdavidch    }
80255736Sdavidch
81255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
82255736Sdavidch    bus_space_write_4(sc->bar[BAR0].tag,
83255736Sdavidch                      sc->bar[BAR0].handle,
84255736Sdavidch                      offset,
85255736Sdavidch                      val);
86255736Sdavidch}
87255736Sdavidch
88255736Sdavidchuint8_t
89255736Sdavidchbxe_reg_read8(struct bxe_softc *sc, bus_size_t offset)
90255736Sdavidch{
91255736Sdavidch    uint8_t val;
92255736Sdavidch
93255736Sdavidch    val = bus_space_read_1(sc->bar[BAR0].tag,
94255736Sdavidch                           sc->bar[BAR0].handle,
95255736Sdavidch                           offset);
96255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%02x\n", offset, val);
97255736Sdavidch
98255736Sdavidch    return (val);
99255736Sdavidch}
100255736Sdavidch
101255736Sdavidchuint16_t
102255736Sdavidchbxe_reg_read16(struct bxe_softc *sc, bus_size_t offset)
103255736Sdavidch{
104255736Sdavidch    uint16_t val;
105255736Sdavidch
106255736Sdavidch    if ((offset % 2) != 0) {
107255736Sdavidch        BLOGD(sc, DBG_REGS, "Unaligned 16-bit read from 0x%08lx\n", offset);
108255736Sdavidch    }
109255736Sdavidch
110255736Sdavidch    val = bus_space_read_2(sc->bar[BAR0].tag,
111255736Sdavidch                           sc->bar[BAR0].handle,
112255736Sdavidch                           offset);
113255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
114255736Sdavidch
115255736Sdavidch    return (val);
116255736Sdavidch}
117255736Sdavidch
118255736Sdavidchuint32_t
119255736Sdavidchbxe_reg_read32(struct bxe_softc *sc, bus_size_t offset)
120255736Sdavidch{
121255736Sdavidch    uint32_t val;
122255736Sdavidch
123255736Sdavidch    if ((offset % 4) != 0) {
124255736Sdavidch        BLOGD(sc, DBG_REGS, "Unaligned 32-bit read from 0x%08lx\n", offset);
125255736Sdavidch    }
126255736Sdavidch
127255736Sdavidch    val = bus_space_read_4(sc->bar[BAR0].tag,
128255736Sdavidch                           sc->bar[BAR0].handle,
129255736Sdavidch                           offset);
130255736Sdavidch    BLOGD(sc, DBG_REGS, "offset=0x%08lx val=0x%08x\n", offset, val);
131255736Sdavidch
132255736Sdavidch    return (val);
133255736Sdavidch}
134255736Sdavidch
135255736Sdavidch#endif /* BXE_REG_NO_INLINE */
136255736Sdavidch
137255736Sdavidch#ifdef ELINK_DEBUG
138255736Sdavidch
139255736Sdavidchvoid
140255736Sdavidchelink_cb_dbg(struct bxe_softc *sc,
141255736Sdavidch             char             *fmt)
142255736Sdavidch{
143255736Sdavidch    char buf[128];
144255736Sdavidch    if (__predict_false(sc->debug & DBG_PHY)) {
145255736Sdavidch        snprintf(buf, sizeof(buf), "ELINK: %s", fmt);
146255736Sdavidch        device_printf(sc->dev, "%s", buf);
147255736Sdavidch    }
148255736Sdavidch}
149255736Sdavidch
150255736Sdavidchvoid
151255736Sdavidchelink_cb_dbg1(struct bxe_softc *sc,
152255736Sdavidch              char             *fmt,
153255736Sdavidch              uint32_t         arg1)
154255736Sdavidch{
155255736Sdavidch    char tmp[128], buf[128];
156255736Sdavidch    if (__predict_false(sc->debug & DBG_PHY)) {
157255736Sdavidch        snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
158255736Sdavidch        snprintf(buf, sizeof(buf), tmp, arg1);
159255736Sdavidch        device_printf(sc->dev, "%s", buf);
160255736Sdavidch    }
161255736Sdavidch}
162255736Sdavidch
163255736Sdavidchvoid
164255736Sdavidchelink_cb_dbg2(struct bxe_softc *sc,
165255736Sdavidch              char             *fmt,
166255736Sdavidch              uint32_t         arg1,
167255736Sdavidch              uint32_t         arg2)
168255736Sdavidch{
169255736Sdavidch    char tmp[128], buf[128];
170255736Sdavidch    if (__predict_false(sc->debug & DBG_PHY)) {
171255736Sdavidch        snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
172255736Sdavidch        snprintf(buf, sizeof(buf), tmp, arg1, arg2);
173255736Sdavidch        device_printf(sc->dev, "%s", buf);
174255736Sdavidch    }
175255736Sdavidch}
176255736Sdavidch
177255736Sdavidchvoid
178255736Sdavidchelink_cb_dbg3(struct bxe_softc *sc,
179255736Sdavidch              char             *fmt,
180255736Sdavidch              uint32_t         arg1,
181255736Sdavidch              uint32_t         arg2,
182255736Sdavidch              uint32_t         arg3)
183255736Sdavidch{
184255736Sdavidch    char tmp[128], buf[128];
185255736Sdavidch    if (__predict_false(sc->debug & DBG_PHY)) {
186255736Sdavidch        snprintf(tmp, sizeof(tmp), "ELINK: %s", fmt);
187255736Sdavidch        snprintf(buf, sizeof(buf), tmp, arg1, arg2, arg3);
188255736Sdavidch        device_printf(sc->dev, "%s", buf);
189255736Sdavidch    }
190255736Sdavidch}
191255736Sdavidch
192255736Sdavidch#endif /* ELINK_DEBUG */
193255736Sdavidch
194255736Sdavidchextern struct mtx bxe_prev_mtx;
195255736Sdavidch
196255736Sdavidchvoid
197255736Sdavidchbxe_dump_mem(struct bxe_softc *sc,
198255736Sdavidch             char             *tag,
199255736Sdavidch             uint8_t          *mem,
200255736Sdavidch             uint32_t         len)
201255736Sdavidch{
202255736Sdavidch    char buf[256];
203255736Sdavidch    char c[32];
204255736Sdavidch    int  xx;
205255736Sdavidch
206255736Sdavidch    mtx_lock(&bxe_prev_mtx);
207255736Sdavidch
208255736Sdavidch    BLOGI(sc, "++++++++++++ %s\n", tag);
209255736Sdavidch    strcpy(buf, "** 000: ");
210255736Sdavidch
211255736Sdavidch    for (xx = 0; xx < len; xx++)
212255736Sdavidch    {
213255736Sdavidch        if ((xx != 0) && (xx % 16 == 0))
214255736Sdavidch        {
215255736Sdavidch            BLOGI(sc, "%s\n", buf);
216255736Sdavidch            strcpy(buf, "** ");
217255736Sdavidch            snprintf(c, sizeof(c), "%03x", xx);
218255736Sdavidch            strcat(buf, c);
219255736Sdavidch            strcat(buf, ": ");
220255736Sdavidch        }
221255736Sdavidch
222255736Sdavidch        snprintf(c, sizeof(c), "%02x ", *mem);
223255736Sdavidch        strcat(buf, c);
224255736Sdavidch
225255736Sdavidch        mem++;
226255736Sdavidch    }
227255736Sdavidch
228255736Sdavidch    BLOGI(sc, "%s\n", buf);
229255736Sdavidch    BLOGI(sc, "------------ %s\n", tag);
230255736Sdavidch
231255736Sdavidch    mtx_unlock(&bxe_prev_mtx);
232255736Sdavidch}
233255736Sdavidch
234255736Sdavidchvoid
235255736Sdavidchbxe_dump_mbuf_data(struct bxe_softc *sc,
236255736Sdavidch                   char             *tag,
237255736Sdavidch                   struct mbuf      *m,
238255736Sdavidch                   uint8_t          contents)
239255736Sdavidch{
240255736Sdavidch    char buf[256];
241255736Sdavidch    char c[32];
242255736Sdavidch    uint8_t *memp;
243255736Sdavidch    int i, xx = 0;
244255736Sdavidch
245255736Sdavidch    mtx_lock(&bxe_prev_mtx);
246255736Sdavidch
247255736Sdavidch    BLOGI(sc, "++++++++++++ %s\n", tag);
248255736Sdavidch
249255736Sdavidch    while (m)
250255736Sdavidch    {
251255736Sdavidch        memp = m->m_data;
252255736Sdavidch        strcpy(buf, "** > ");
253255736Sdavidch        snprintf(c, sizeof(c), "%03x", xx);
254255736Sdavidch        strcat(buf, c);
255255736Sdavidch        strcat(buf, ": ");
256255736Sdavidch
257255736Sdavidch        if (contents)
258255736Sdavidch        {
259255736Sdavidch            for (i = 0; i < m->m_len; i++)
260255736Sdavidch            {
261255736Sdavidch                if ((xx != 0) && (xx % 16 == 0))
262255736Sdavidch                {
263255736Sdavidch                    BLOGI(sc, "%s\n", buf);
264255736Sdavidch                    strcpy(buf, "**   ");
265255736Sdavidch                    snprintf(c, sizeof(c), "%03x", xx);
266255736Sdavidch                    strcat(buf, c);
267255736Sdavidch                    strcat(buf, ": ");
268255736Sdavidch                }
269255736Sdavidch
270255736Sdavidch                snprintf(c, sizeof(c), "%02x ", *memp);
271255736Sdavidch                strcat(buf, c);
272255736Sdavidch
273255736Sdavidch                memp++;
274255736Sdavidch                xx++;
275255736Sdavidch            }
276255736Sdavidch        }
277255736Sdavidch        else
278255736Sdavidch        {
279255736Sdavidch            snprintf(c, sizeof(c), "%d", m->m_len);
280255736Sdavidch            strcat(buf, c);
281255736Sdavidch            xx += m->m_len;
282255736Sdavidch        }
283255736Sdavidch
284255736Sdavidch        BLOGI(sc, "%s\n", buf);
285255736Sdavidch        m = m->m_next;
286255736Sdavidch    }
287255736Sdavidch
288255736Sdavidch    BLOGI(sc, "------------ %s\n", tag);
289255736Sdavidch
290255736Sdavidch    mtx_unlock(&bxe_prev_mtx);
291255736Sdavidch}
292255736Sdavidch
293255736Sdavidch#ifdef DDB
294255736Sdavidch
295255736Sdavidchstatic void bxe_ddb_usage()
296255736Sdavidch{
297255736Sdavidch    db_printf("Usage: bxe[/hpv] <instance> [<address>]\n");
298255736Sdavidch}
299255736Sdavidch
300255736Sdavidchstatic db_cmdfcn_t bxe_ddb;
301255736Sdavidch_DB_SET(_cmd, bxe, bxe_ddb, db_cmd_table, CS_OWN, NULL);
302255736Sdavidch
303255736Sdavidchstatic void bxe_ddb(db_expr_t blah1,
304255736Sdavidch                    boolean_t blah2,
305255736Sdavidch                    db_expr_t blah3,
306255736Sdavidch                    char      *blah4)
307255736Sdavidch{
308255736Sdavidch    char if_xname[IFNAMSIZ];
309255736Sdavidch    struct ifnet *ifp = NULL;
310255736Sdavidch    struct bxe_softc *sc;
311255736Sdavidch    db_expr_t next_arg;
312255736Sdavidch    int index;
313255736Sdavidch    int tok;
314255736Sdavidch    int mod_phys_addr = FALSE;
315255736Sdavidch    int mod_virt_addr = FALSE;
316255736Sdavidch    db_addr_t addr;
317255736Sdavidch
318255736Sdavidch    tok = db_read_token();
319255736Sdavidch    if (tok == tSLASH) {
320255736Sdavidch        tok = db_read_token();
321255736Sdavidch        if (tok != tIDENT) {
322255736Sdavidch            db_printf("ERROR: bad modifier\n");
323255736Sdavidch            bxe_ddb_usage();
324255736Sdavidch            goto bxe_ddb_done;
325255736Sdavidch        }
326255736Sdavidch        if (strcmp(db_tok_string, "h") == 0) {
327255736Sdavidch            bxe_ddb_usage();
328255736Sdavidch            goto bxe_ddb_done;
329255736Sdavidch        } else if (strcmp(db_tok_string, "p") == 0) {
330255736Sdavidch            mod_phys_addr = TRUE;
331255736Sdavidch        } else if (strcmp(db_tok_string, "v") == 0) {
332255736Sdavidch            mod_virt_addr = TRUE;
333255736Sdavidch        }
334255736Sdavidch    } else {
335255736Sdavidch        db_unread_token(tok);
336255736Sdavidch    }
337255736Sdavidch
338255736Sdavidch    if (!db_expression((db_expr_t *)&index)) {
339255736Sdavidch        db_printf("ERROR: bxe index missing\n");
340255736Sdavidch        bxe_ddb_usage();
341255736Sdavidch        goto bxe_ddb_done;
342255736Sdavidch    }
343255736Sdavidch
344255736Sdavidch    snprintf(if_xname, sizeof(if_xname), "bxe%d", index);
345255736Sdavidch    if ((ifp = ifunit_ref(if_xname)) == NULL)
346255736Sdavidch    {
347255736Sdavidch        db_printf("ERROR: Invalid interface %s\n", if_xname);
348255736Sdavidch        goto bxe_ddb_done;
349255736Sdavidch    }
350255736Sdavidch
351255736Sdavidch    sc = (struct bxe_softc *)ifp->if_softc;
352255736Sdavidch    db_printf("ifnet=%p (%s)\n", ifp, if_xname);
353255736Sdavidch    db_printf("softc=%p\n", sc);
354255736Sdavidch    db_printf("  dev=%p\n", sc->dev);
355255736Sdavidch    db_printf("  BDF=%d:%d:%d\n",
356255736Sdavidch              sc->pcie_bus, sc->pcie_device, sc->pcie_func);
357255736Sdavidch
358255736Sdavidch    if (mod_phys_addr || mod_virt_addr) {
359255736Sdavidch        if (!db_expression((db_addr_t *)&addr)) {
360255736Sdavidch            db_printf("ERROR: Invalid address\n");
361255736Sdavidch            bxe_ddb_usage();
362255736Sdavidch            goto bxe_ddb_done;
363255736Sdavidch        }
364255736Sdavidch
365255736Sdavidch        db_printf("addr=%p", addr);
366255736Sdavidch    }
367255736Sdavidch
368255736Sdavidchbxe_ddb_done:
369255736Sdavidch
370255736Sdavidch    db_flush_lex();
371255736Sdavidch    if (ifp) if_rele(ifp);
372255736Sdavidch}
373255736Sdavidch
374255736Sdavidch#endif /* DDB */
375255736Sdavidch
376