1/*-
2 * Copyright (c) 2002-2007 Neterion, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <dev/nxge/include/xgehal-driver.h>
30#include <dev/nxge/include/xgehal-device.h>
31
32static xge_hal_driver_t g_driver;
33xge_hal_driver_t *g_xge_hal_driver = NULL;
34char *g_xge_hal_log = NULL;
35
36#ifdef XGE_OS_MEMORY_CHECK
37xge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX];
38int g_malloc_cnt = 0;
39#endif
40
41/*
42 * Runtime tracing support
43 */
44static unsigned long g_module_mask_default = 0;
45unsigned long *g_module_mask = &g_module_mask_default;
46static int g_level_default = 0;
47int *g_level = &g_level_default;
48
49#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
50static xge_os_tracebuf_t g_tracebuf;
51char *dmesg, *dmesg_start;
52
53/**
54 * xge_hal_driver_tracebuf_dump - Dump the trace buffer.
55 *
56 * Dump the trace buffer contents.
57 */
58void
59xge_hal_driver_tracebuf_dump(void)
60{
61	int i;
62	int off = 0;
63
64	if (g_xge_os_tracebuf == NULL) {
65	    return;
66	}
67
68	xge_os_printf("################ Trace dump Begin ###############");
69	if (g_xge_os_tracebuf->wrapped_once) {
70	    for (i = 0; i < g_xge_os_tracebuf->size -
71	            g_xge_os_tracebuf->offset; i += off) {
72	        if (*(dmesg_start + i))
73	            xge_os_printf(dmesg_start + i);
74	        off = xge_os_strlen(dmesg_start + i) + 1;
75	    }
76	}
77	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
78	    if (*(dmesg + i))
79	        xge_os_printf(dmesg + i);
80	    off = xge_os_strlen(dmesg + i) + 1;
81	}
82	xge_os_printf("################ Trace dump End ###############");
83}
84
85xge_hal_status_e
86xge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize)
87{
88	int i;
89	int off = 0, retbuf_off = 0;
90
91	*retsize = 0;
92	*retbuf = 0;
93
94	if (g_xge_os_tracebuf == NULL) {
95	    return XGE_HAL_FAIL;
96	}
97
98	if (g_xge_os_tracebuf->wrapped_once) {
99	    for (i = 0; i < g_xge_os_tracebuf->size -
100	            g_xge_os_tracebuf->offset; i += off) {
101	        if (*(dmesg_start + i)) {
102	            xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg_start + i);
103	            retbuf_off += xge_os_strlen(dmesg_start + i) + 1;
104	            if (retbuf_off > bufsize)
105	                return XGE_HAL_ERR_OUT_OF_MEMORY;
106	        }
107	        off = xge_os_strlen(dmesg_start + i) + 1;
108	    }
109	}
110	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
111	    if (*(dmesg + i)) {
112	        xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg + i);
113	        retbuf_off += xge_os_strlen(dmesg + i) + 1;
114	        if (retbuf_off > bufsize)
115	            return XGE_HAL_ERR_OUT_OF_MEMORY;
116	    }
117	    off = xge_os_strlen(dmesg + i) + 1;
118	}
119
120	*retsize = retbuf_off;
121	*(retbuf + retbuf_off + 1) = 0;
122
123	return XGE_HAL_OK;
124}
125#endif
126xge_os_tracebuf_t *g_xge_os_tracebuf = NULL;
127
128#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
129void
130xge_hal_driver_bar0_offset_check(void)
131{
132	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, adapter_status) ==
133	       0x108);
134	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_traffic_int) ==
135	       0x08E0);
136	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, dtx_control) ==
137	       0x09E8);
138	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_fifo_partition_0) ==
139	       0x1108);
140	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_enable) ==
141	       0x1170);
142	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, prc_rxd0_n[0]) ==
143	       0x1930);
144	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rti_command_mem) ==
145	       0x19B8);
146	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_cfg) ==
147	       0x2100);
148	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rmac_addr_cmd_mem) ==
149	       0x2128);
150	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_link_util) ==
151	       0x2170);
152	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_pause_thresh_q0q3) ==
153	       0x2918);
154	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_err_reg) ==
155	       0x1040);
156	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rxdma_int_status) ==
157	       0x1800);
158	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_tmac_err_reg) ==
159	       0x2010);
160	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_err_reg) ==
161	       0x2810);
162	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, xgxs_int_status) ==
163	       0x3000);
164}
165#endif
166
167/**
168 * xge_hal_driver_initialize - Initialize HAL.
169 * @config: HAL configuration, see xge_hal_driver_config_t{}.
170 * @uld_callbacks: Upper-layer driver callbacks, e.g. link-up.
171 *
172 * HAL initialization entry point. Not to confuse with device initialization
173 * (note that HAL "contains" zero or more Xframe devices).
174 *
175 * Returns: XGE_HAL_OK - success;
176 * XGE_HAL_ERR_BAD_DRIVER_CONFIG - Driver configuration params invalid.
177 *
178 * See also: xge_hal_device_initialize(), xge_hal_status_e{},
179 * xge_hal_uld_cbs_t{}.
180 */
181xge_hal_status_e
182xge_hal_driver_initialize(xge_hal_driver_config_t *config,
183	        xge_hal_uld_cbs_t *uld_callbacks)
184{
185	xge_hal_status_e status;
186
187	g_xge_hal_driver = &g_driver;
188
189	xge_hal_driver_debug_module_mask_set(XGE_DEBUG_MODULE_MASK_DEF);
190	xge_hal_driver_debug_level_set(XGE_DEBUG_LEVEL_DEF);
191
192#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
193	xge_hal_driver_bar0_offset_check();
194#endif
195
196#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
197	if (config->tracebuf_size == 0)
198	    /*
199	     * Trace buffer implementation is not lock protected.
200	     * The only harm to expect is memcpy() to go beyond of
201	     * allowed boundaries. To make it safe (driver-wise),
202	     * we pre-allocate needed number of extra bytes.
203	     */
204	    config->tracebuf_size = XGE_HAL_DEF_CIRCULAR_ARR +
205	                XGE_OS_TRACE_MSGBUF_MAX;
206#endif
207
208	status = __hal_driver_config_check(config);
209	if (status != XGE_HAL_OK)
210	    return status;
211
212	xge_os_memzero(g_xge_hal_driver,  sizeof(xge_hal_driver_t));
213
214	/* apply config */
215	xge_os_memcpy(&g_xge_hal_driver->config, config,
216	            sizeof(xge_hal_driver_config_t));
217
218	/* apply ULD callbacks */
219	xge_os_memcpy(&g_xge_hal_driver->uld_callbacks, uld_callbacks,
220	                sizeof(xge_hal_uld_cbs_t));
221
222	g_xge_hal_driver->is_initialized = 1;
223
224#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
225	g_tracebuf.size = config->tracebuf_size;
226	g_tracebuf.data = (char *)xge_os_malloc(NULL, g_tracebuf.size);
227	if (g_tracebuf.data == NULL) {
228	    xge_os_printf("cannot allocate trace buffer!");
229	    return XGE_HAL_ERR_OUT_OF_MEMORY;
230	}
231	/* timestamps disabled by default */
232	g_tracebuf.timestamp = config->tracebuf_timestamp_en;
233	if (g_tracebuf.timestamp) {
234	    xge_os_timestamp(g_tracebuf.msg);
235	    g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX -
236	                xge_os_strlen(g_tracebuf.msg);
237	} else
238	    g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX;
239	g_tracebuf.offset = 0;
240	*g_tracebuf.msg = 0;
241	xge_os_memzero(g_tracebuf.data, g_tracebuf.size);
242	g_xge_os_tracebuf = &g_tracebuf;
243	dmesg = g_tracebuf.data;
244	*dmesg = 0;
245#endif
246	return XGE_HAL_OK;
247}
248
249/**
250 * xge_hal_driver_terminate - Terminate HAL.
251 *
252 * HAL termination entry point.
253 *
254 * See also: xge_hal_device_terminate().
255 */
256void
257xge_hal_driver_terminate(void)
258{
259	g_xge_hal_driver->is_initialized = 0;
260
261#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
262	if (g_tracebuf.size) {
263	    xge_os_free(NULL, g_tracebuf.data, g_tracebuf.size);
264	}
265#endif
266
267	g_xge_hal_driver = NULL;
268
269#ifdef XGE_OS_MEMORY_CHECK
270	{
271	    int i, leaks=0;
272	    xge_os_printf("OSPAL: max g_malloc_cnt %d", g_malloc_cnt);
273	    for (i=0; i<g_malloc_cnt; i++) {
274	        if (g_malloc_arr[i].ptr != NULL) {
275	            xge_os_printf("OSPAL: memory leak detected at "
276	                "%s:%d:"XGE_OS_LLXFMT":%d",
277	                g_malloc_arr[i].file,
278	                g_malloc_arr[i].line,
279	                (unsigned long long)(ulong_t)
280	                    g_malloc_arr[i].ptr,
281	                g_malloc_arr[i].size);
282	            leaks++;
283	        }
284	    }
285	    if (leaks) {
286	        xge_os_printf("OSPAL: %d memory leaks detected", leaks);
287	    } else {
288	        xge_os_printf("OSPAL: no memory leaks detected");
289	    }
290	}
291#endif
292}
293