1171095Ssam/*-
2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc.
3171095Ssam * All rights reserved.
4171095Ssam *
5171095Ssam * Redistribution and use in source and binary forms, with or without
6171095Ssam * modification, are permitted provided that the following conditions
7171095Ssam * are met:
8171095Ssam * 1. Redistributions of source code must retain the above copyright
9171095Ssam *    notice, this list of conditions and the following disclaimer.
10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright
11171095Ssam *    notice, this list of conditions and the following disclaimer in the
12171095Ssam *    documentation and/or other materials provided with the distribution.
13171095Ssam *
14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171095Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171095Ssam * SUCH DAMAGE.
25171095Ssam *
26171095Ssam * $FreeBSD$
27171095Ssam */
28171095Ssam
29171095Ssam#include <dev/nxge/include/xgehal-driver.h>
30171095Ssam#include <dev/nxge/include/xgehal-device.h>
31171095Ssam
32171095Ssamstatic xge_hal_driver_t g_driver;
33171095Ssamxge_hal_driver_t *g_xge_hal_driver = NULL;
34171095Ssamchar *g_xge_hal_log = NULL;
35171095Ssam
36171095Ssam#ifdef XGE_OS_MEMORY_CHECK
37171095Ssamxge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX];
38171095Ssamint g_malloc_cnt = 0;
39171095Ssam#endif
40171095Ssam
41171095Ssam/*
42171095Ssam * Runtime tracing support
43171095Ssam */
44171095Ssamstatic unsigned long g_module_mask_default = 0;
45171095Ssamunsigned long *g_module_mask = &g_module_mask_default;
46171095Ssamstatic int g_level_default = 0;
47171095Ssamint *g_level = &g_level_default;
48171095Ssam
49171095Ssam#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
50171095Ssamstatic xge_os_tracebuf_t g_tracebuf;
51171095Ssamchar *dmesg, *dmesg_start;
52171095Ssam
53171095Ssam/**
54171095Ssam * xge_hal_driver_tracebuf_dump - Dump the trace buffer.
55171095Ssam *
56171095Ssam * Dump the trace buffer contents.
57171095Ssam */
58171095Ssamvoid
59171095Ssamxge_hal_driver_tracebuf_dump(void)
60171095Ssam{
61171095Ssam	int i;
62171095Ssam	int off = 0;
63171095Ssam
64171095Ssam	if (g_xge_os_tracebuf == NULL) {
65173139Srwatson	    return;
66171095Ssam	}
67171095Ssam
68171095Ssam	xge_os_printf("################ Trace dump Begin ###############");
69171095Ssam	if (g_xge_os_tracebuf->wrapped_once) {
70173139Srwatson	    for (i = 0; i < g_xge_os_tracebuf->size -
71173139Srwatson	            g_xge_os_tracebuf->offset; i += off) {
72173139Srwatson	        if (*(dmesg_start + i))
73173139Srwatson	            xge_os_printf(dmesg_start + i);
74173139Srwatson	        off = xge_os_strlen(dmesg_start + i) + 1;
75173139Srwatson	    }
76171095Ssam	}
77171095Ssam	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
78173139Srwatson	    if (*(dmesg + i))
79173139Srwatson	        xge_os_printf(dmesg + i);
80173139Srwatson	    off = xge_os_strlen(dmesg + i) + 1;
81171095Ssam	}
82171095Ssam	xge_os_printf("################ Trace dump End ###############");
83171095Ssam}
84171095Ssam
85171095Ssamxge_hal_status_e
86171095Ssamxge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize)
87171095Ssam{
88171095Ssam	int i;
89171095Ssam	int off = 0, retbuf_off = 0;
90171095Ssam
91171095Ssam	*retsize = 0;
92171095Ssam	*retbuf = 0;
93171095Ssam
94171095Ssam	if (g_xge_os_tracebuf == NULL) {
95173139Srwatson	    return XGE_HAL_FAIL;
96171095Ssam	}
97171095Ssam
98171095Ssam	if (g_xge_os_tracebuf->wrapped_once) {
99173139Srwatson	    for (i = 0; i < g_xge_os_tracebuf->size -
100173139Srwatson	            g_xge_os_tracebuf->offset; i += off) {
101173139Srwatson	        if (*(dmesg_start + i)) {
102173139Srwatson	            xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg_start + i);
103173139Srwatson	            retbuf_off += xge_os_strlen(dmesg_start + i) + 1;
104173139Srwatson	            if (retbuf_off > bufsize)
105173139Srwatson	                return XGE_HAL_ERR_OUT_OF_MEMORY;
106173139Srwatson	        }
107173139Srwatson	        off = xge_os_strlen(dmesg_start + i) + 1;
108173139Srwatson	    }
109171095Ssam	}
110171095Ssam	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
111173139Srwatson	    if (*(dmesg + i)) {
112173139Srwatson	        xge_os_sprintf(retbuf + retbuf_off, "%s\n", dmesg + i);
113173139Srwatson	        retbuf_off += xge_os_strlen(dmesg + i) + 1;
114173139Srwatson	        if (retbuf_off > bufsize)
115173139Srwatson	            return XGE_HAL_ERR_OUT_OF_MEMORY;
116173139Srwatson	    }
117173139Srwatson	    off = xge_os_strlen(dmesg + i) + 1;
118171095Ssam	}
119171095Ssam
120171095Ssam	*retsize = retbuf_off;
121171095Ssam	*(retbuf + retbuf_off + 1) = 0;
122171095Ssam
123171095Ssam	return XGE_HAL_OK;
124171095Ssam}
125171095Ssam#endif
126171095Ssamxge_os_tracebuf_t *g_xge_os_tracebuf = NULL;
127171095Ssam
128171095Ssam#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
129171095Ssamvoid
130171095Ssamxge_hal_driver_bar0_offset_check(void)
131171095Ssam{
132171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, adapter_status) ==
133173139Srwatson	       0x108);
134171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_traffic_int) ==
135173139Srwatson	       0x08E0);
136171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, dtx_control) ==
137173139Srwatson	       0x09E8);
138171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_fifo_partition_0) ==
139173139Srwatson	       0x1108);
140171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_enable) ==
141173139Srwatson	       0x1170);
142171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, prc_rxd0_n[0]) ==
143173139Srwatson	       0x1930);
144171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rti_command_mem) ==
145173139Srwatson	       0x19B8);
146171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_cfg) ==
147173139Srwatson	       0x2100);
148171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rmac_addr_cmd_mem) ==
149173139Srwatson	       0x2128);
150171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_link_util) ==
151173139Srwatson	       0x2170);
152171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_pause_thresh_q0q3) ==
153173139Srwatson	       0x2918);
154171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_err_reg) ==
155173139Srwatson	       0x1040);
156171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rxdma_int_status) ==
157173139Srwatson	       0x1800);
158171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_tmac_err_reg) ==
159173139Srwatson	       0x2010);
160171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_err_reg) ==
161173139Srwatson	       0x2810);
162171095Ssam	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, xgxs_int_status) ==
163173139Srwatson	       0x3000);
164171095Ssam}
165171095Ssam#endif
166171095Ssam
167171095Ssam/**
168171095Ssam * xge_hal_driver_initialize - Initialize HAL.
169171095Ssam * @config: HAL configuration, see xge_hal_driver_config_t{}.
170171095Ssam * @uld_callbacks: Upper-layer driver callbacks, e.g. link-up.
171171095Ssam *
172171095Ssam * HAL initialization entry point. Not to confuse with device initialization
173171095Ssam * (note that HAL "contains" zero or more Xframe devices).
174171095Ssam *
175171095Ssam * Returns: XGE_HAL_OK - success;
176171095Ssam * XGE_HAL_ERR_BAD_DRIVER_CONFIG - Driver configuration params invalid.
177171095Ssam *
178171095Ssam * See also: xge_hal_device_initialize(), xge_hal_status_e{},
179171095Ssam * xge_hal_uld_cbs_t{}.
180171095Ssam */
181171095Ssamxge_hal_status_e
182171095Ssamxge_hal_driver_initialize(xge_hal_driver_config_t *config,
183173139Srwatson	        xge_hal_uld_cbs_t *uld_callbacks)
184171095Ssam{
185171095Ssam	xge_hal_status_e status;
186171095Ssam
187171095Ssam	g_xge_hal_driver = &g_driver;
188171095Ssam
189171095Ssam	xge_hal_driver_debug_module_mask_set(XGE_DEBUG_MODULE_MASK_DEF);
190171095Ssam	xge_hal_driver_debug_level_set(XGE_DEBUG_LEVEL_DEF);
191171095Ssam
192171095Ssam#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
193171095Ssam	xge_hal_driver_bar0_offset_check();
194171095Ssam#endif
195171095Ssam
196171095Ssam#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
197171095Ssam	if (config->tracebuf_size == 0)
198173139Srwatson	    /*
199173139Srwatson	     * Trace buffer implementation is not lock protected.
200173139Srwatson	     * The only harm to expect is memcpy() to go beyond of
201173139Srwatson	     * allowed boundaries. To make it safe (driver-wise),
202173139Srwatson	     * we pre-allocate needed number of extra bytes.
203173139Srwatson	     */
204173139Srwatson	    config->tracebuf_size = XGE_HAL_DEF_CIRCULAR_ARR +
205173139Srwatson	                XGE_OS_TRACE_MSGBUF_MAX;
206171095Ssam#endif
207171095Ssam
208171095Ssam	status = __hal_driver_config_check(config);
209171095Ssam	if (status != XGE_HAL_OK)
210173139Srwatson	    return status;
211171095Ssam
212171095Ssam	xge_os_memzero(g_xge_hal_driver,  sizeof(xge_hal_driver_t));
213171095Ssam
214171095Ssam	/* apply config */
215171095Ssam	xge_os_memcpy(&g_xge_hal_driver->config, config,
216173139Srwatson	            sizeof(xge_hal_driver_config_t));
217171095Ssam
218171095Ssam	/* apply ULD callbacks */
219171095Ssam	xge_os_memcpy(&g_xge_hal_driver->uld_callbacks, uld_callbacks,
220173139Srwatson	                sizeof(xge_hal_uld_cbs_t));
221171095Ssam
222171095Ssam	g_xge_hal_driver->is_initialized = 1;
223171095Ssam
224171095Ssam#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
225171095Ssam	g_tracebuf.size = config->tracebuf_size;
226171095Ssam	g_tracebuf.data = (char *)xge_os_malloc(NULL, g_tracebuf.size);
227171095Ssam	if (g_tracebuf.data == NULL) {
228173139Srwatson	    xge_os_printf("cannot allocate trace buffer!");
229173139Srwatson	    return XGE_HAL_ERR_OUT_OF_MEMORY;
230171095Ssam	}
231171095Ssam	/* timestamps disabled by default */
232171095Ssam	g_tracebuf.timestamp = config->tracebuf_timestamp_en;
233171095Ssam	if (g_tracebuf.timestamp) {
234173139Srwatson	    xge_os_timestamp(g_tracebuf.msg);
235173139Srwatson	    g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX -
236173139Srwatson	                xge_os_strlen(g_tracebuf.msg);
237171095Ssam	} else
238173139Srwatson	    g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX;
239171095Ssam	g_tracebuf.offset = 0;
240171095Ssam	*g_tracebuf.msg = 0;
241171095Ssam	xge_os_memzero(g_tracebuf.data, g_tracebuf.size);
242171095Ssam	g_xge_os_tracebuf = &g_tracebuf;
243171095Ssam	dmesg = g_tracebuf.data;
244171095Ssam	*dmesg = 0;
245171095Ssam#endif
246171095Ssam	return XGE_HAL_OK;
247171095Ssam}
248171095Ssam
249171095Ssam/**
250171095Ssam * xge_hal_driver_terminate - Terminate HAL.
251171095Ssam *
252171095Ssam * HAL termination entry point.
253171095Ssam *
254171095Ssam * See also: xge_hal_device_terminate().
255171095Ssam */
256171095Ssamvoid
257171095Ssamxge_hal_driver_terminate(void)
258171095Ssam{
259171095Ssam	g_xge_hal_driver->is_initialized = 0;
260171095Ssam
261171095Ssam#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
262171095Ssam	if (g_tracebuf.size) {
263173139Srwatson	    xge_os_free(NULL, g_tracebuf.data, g_tracebuf.size);
264171095Ssam	}
265171095Ssam#endif
266171095Ssam
267171095Ssam	g_xge_hal_driver = NULL;
268171095Ssam
269171095Ssam#ifdef XGE_OS_MEMORY_CHECK
270171095Ssam	{
271173139Srwatson	    int i, leaks=0;
272173139Srwatson	    xge_os_printf("OSPAL: max g_malloc_cnt %d", g_malloc_cnt);
273173139Srwatson	    for (i=0; i<g_malloc_cnt; i++) {
274173139Srwatson	        if (g_malloc_arr[i].ptr != NULL) {
275173139Srwatson	            xge_os_printf("OSPAL: memory leak detected at "
276173139Srwatson	                "%s:%d:"XGE_OS_LLXFMT":%d",
277173139Srwatson	                g_malloc_arr[i].file,
278173139Srwatson	                g_malloc_arr[i].line,
279173139Srwatson	                (unsigned long long)(ulong_t)
280173139Srwatson	                    g_malloc_arr[i].ptr,
281173139Srwatson	                g_malloc_arr[i].size);
282173139Srwatson	            leaks++;
283173139Srwatson	        }
284173139Srwatson	    }
285173139Srwatson	    if (leaks) {
286173139Srwatson	        xge_os_printf("OSPAL: %d memory leaks detected", leaks);
287173139Srwatson	    } else {
288173139Srwatson	        xge_os_printf("OSPAL: no memory leaks detected");
289173139Srwatson	    }
290171095Ssam	}
291171095Ssam#endif
292171095Ssam}
293