1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2002-2006 Neterion, Inc.
22 */
23
24#include "xgehal-driver.h"
25#include "xgehal-device.h"
26
27static xge_hal_driver_t g_driver;
28xge_hal_driver_t *g_xge_hal_driver = NULL;
29char *g_xge_hal_log = NULL;
30
31#ifdef XGE_OS_MEMORY_CHECK
32xge_os_malloc_t g_malloc_arr[XGE_OS_MALLOC_CNT_MAX];
33int g_malloc_cnt = 0;
34#endif
35
36/*
37 * Runtime tracing support
38 */
39static unsigned long g_module_mask_default = 0;
40unsigned long *g_module_mask = &g_module_mask_default;
41static int g_level_default = 0;
42int *g_level = &g_level_default;
43
44#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
45static xge_os_tracebuf_t g_tracebuf;
46char *dmesg, *dmesg_start;
47
48/**
49 * xge_hal_driver_tracebuf_dump - Dump the trace buffer.
50 *
51 * Dump the trace buffer contents.
52 */
53void
54xge_hal_driver_tracebuf_dump(void)
55{
56	int i;
57	int off = 0;
58
59	if (g_xge_os_tracebuf == NULL) {
60		return;
61	}
62
63	xge_os_printf("################ Trace dump Begin ###############");
64	if (g_xge_os_tracebuf->wrapped_once) {
65		for (i = 0; i < g_xge_os_tracebuf->size -
66				g_xge_os_tracebuf->offset; i += off) {
67			if (*(dmesg_start + i))
68				xge_os_printf(dmesg_start + i);
69			off = xge_os_strlen(dmesg_start + i) + 1;
70		}
71	}
72	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
73		if (*(dmesg + i))
74			xge_os_printf(dmesg + i);
75		off = xge_os_strlen(dmesg + i) + 1;
76	}
77	xge_os_printf("################ Trace dump End ###############");
78}
79
80xge_hal_status_e
81xge_hal_driver_tracebuf_read(int bufsize, char *retbuf, int *retsize)
82{
83	int i;
84	int off = 0, retbuf_off = 0;
85
86	*retsize = 0;
87	*retbuf = 0;
88
89	if (g_xge_os_tracebuf == NULL) {
90		return XGE_HAL_FAIL;
91	}
92
93	if (g_xge_os_tracebuf->wrapped_once) {
94		for (i = 0; i < g_xge_os_tracebuf->size -
95				g_xge_os_tracebuf->offset; i += off) {
96			if (*(dmesg_start + i)) {
97				xge_os_snprintf((retbuf + retbuf_off), (bufsize - retbuf_off),
98				    "%s\n", dmesg_start + i);
99				retbuf_off += xge_os_strlen(dmesg_start + i) + 1;
100				if (retbuf_off > bufsize)
101					return XGE_HAL_ERR_OUT_OF_MEMORY;
102			}
103			off = xge_os_strlen(dmesg_start + i) + 1;
104		}
105	}
106	for (i = 0; i < g_xge_os_tracebuf->offset; i += off) {
107		if (*(dmesg + i)) {
108			xge_os_snprintf((retbuf + retbuf_off), (bufsize - retbuf_off),
109			    "%s\n", dmesg + i);
110			retbuf_off += xge_os_strlen(dmesg + i) + 1;
111			if (retbuf_off > bufsize)
112				return XGE_HAL_ERR_OUT_OF_MEMORY;
113		}
114		off = xge_os_strlen(dmesg + i) + 1;
115	}
116
117	*retsize = retbuf_off;
118	*(retbuf + retbuf_off + 1) = 0;
119
120	return XGE_HAL_OK;
121}
122#endif
123xge_os_tracebuf_t *g_xge_os_tracebuf = NULL;
124
125#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
126void
127xge_hal_driver_bar0_offset_check(void)
128{
129	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, adapter_status) ==
130		   0x108);
131	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_traffic_int) ==
132		   0x08E0);
133	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, dtx_control) ==
134		   0x09E8);
135	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, tx_fifo_partition_0) ==
136		   0x1108);
137	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_enable) ==
138		   0x1170);
139	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, prc_rxd0_n[0]) ==
140		   0x1930);
141	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rti_command_mem) ==
142		   0x19B8);
143	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_cfg) ==
144		   0x2100);
145	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rmac_addr_cmd_mem) ==
146		   0x2128);
147	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_link_util) ==
148		   0x2170);
149	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_pause_thresh_q0q3) ==
150		   0x2918);
151	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, pcc_err_reg) ==
152		   0x1040);
153	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, rxdma_int_status) ==
154		   0x1800);
155	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mac_tmac_err_reg) ==
156		   0x2010);
157	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, mc_err_reg) ==
158		   0x2810);
159	xge_assert(xge_offsetof(xge_hal_pci_bar0_t, xgxs_int_status) ==
160		   0x3000);
161}
162#endif
163
164/**
165 * xge_hal_driver_initialize - Initialize HAL.
166 * @config: HAL configuration, see xge_hal_driver_config_t{}.
167 * @uld_callbacks: Upper-layer driver callbacks, e.g. link-up.
168 *
169 * HAL initialization entry point. Not to confuse with device initialization
170 * (note that HAL "contains" zero or more Xframe devices).
171 *
172 * Returns: XGE_HAL_OK - success;
173 * XGE_HAL_ERR_BAD_DRIVER_CONFIG - Driver configuration params invalid.
174 *
175 * See also: xge_hal_device_initialize(), xge_hal_status_e{},
176 * xge_hal_uld_cbs_t{}.
177 */
178xge_hal_status_e
179xge_hal_driver_initialize(xge_hal_driver_config_t *config,
180			xge_hal_uld_cbs_t *uld_callbacks)
181{
182	xge_hal_status_e status;
183
184	g_xge_hal_driver = &g_driver;
185
186	xge_hal_driver_debug_module_mask_set(XGE_DEBUG_MODULE_MASK_DEF);
187	xge_hal_driver_debug_level_set(XGE_DEBUG_LEVEL_DEF);
188
189#ifdef XGE_HAL_DEBUG_BAR0_OFFSET
190	xge_hal_driver_bar0_offset_check();
191#endif
192
193#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
194	if (config->tracebuf_size == 0)
195		/*
196		 * Trace buffer implementation is not lock protected.
197		 * The only harm to expect is memcpy() to go beyond of
198		 * allowed boundaries. To make it safe (driver-wise),
199		 * we pre-allocate needed number of extra bytes.
200		 */
201		config->tracebuf_size = XGE_HAL_DEF_CIRCULAR_ARR +
202					XGE_OS_TRACE_MSGBUF_MAX;
203#endif
204
205	status = __hal_driver_config_check(config);
206	if (status != XGE_HAL_OK)
207		return status;
208
209	xge_os_memzero(g_xge_hal_driver,  sizeof(xge_hal_driver_t));
210
211	/* apply config */
212	xge_os_memcpy(&g_xge_hal_driver->config, config,
213				sizeof(xge_hal_driver_config_t));
214
215	/* apply ULD callbacks */
216	xge_os_memcpy(&g_xge_hal_driver->uld_callbacks, uld_callbacks,
217					sizeof(xge_hal_uld_cbs_t));
218
219	g_xge_hal_driver->is_initialized = 1;
220
221#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
222	g_tracebuf.size = config->tracebuf_size;
223	g_tracebuf.data = (char *)xge_os_malloc(NULL, g_tracebuf.size);
224	if (g_tracebuf.data == NULL) {
225		xge_os_printf("cannot allocate trace buffer!");
226		return XGE_HAL_ERR_OUT_OF_MEMORY;
227	}
228	/* timestamps disabled by default */
229	g_tracebuf.timestamp = config->tracebuf_timestamp_en;
230	if (g_tracebuf.timestamp) {
231		xge_os_timestamp(g_tracebuf.msg);
232		g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX -
233					xge_os_strlen(g_tracebuf.msg);
234	} else
235		g_tracebuf.msgbuf_max = XGE_OS_TRACE_MSGBUF_MAX;
236	g_tracebuf.offset = 0;
237	*g_tracebuf.msg = 0;
238	xge_os_memzero(g_tracebuf.data, g_tracebuf.size);
239	g_xge_os_tracebuf = &g_tracebuf;
240	dmesg = g_tracebuf.data;
241	*dmesg = 0;
242#endif
243	return XGE_HAL_OK;
244}
245
246/**
247 * xge_hal_driver_terminate - Terminate HAL.
248 *
249 * HAL termination entry point.
250 *
251 * See also: xge_hal_device_terminate().
252 */
253void
254xge_hal_driver_terminate(void)
255{
256	g_xge_hal_driver->is_initialized = 0;
257
258#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
259	if (g_tracebuf.size) {
260		xge_os_free(NULL, g_tracebuf.data, g_tracebuf.size);
261	}
262#endif
263
264	g_xge_hal_driver = NULL;
265
266#ifdef XGE_OS_MEMORY_CHECK
267	{
268		int i, leaks=0;
269		xge_os_printf("OSPAL: max g_malloc_cnt %d", g_malloc_cnt);
270		for (i=0; i<g_malloc_cnt; i++) {
271			if (g_malloc_arr[i].ptr != NULL) {
272				xge_os_printf("OSPAL: memory leak detected at "
273					"%s:%d:"XGE_OS_LLXFMT":%d",
274					g_malloc_arr[i].file,
275					g_malloc_arr[i].line,
276					(unsigned long long)(ulong_t)
277						g_malloc_arr[i].ptr,
278					g_malloc_arr[i].size);
279				leaks++;
280			}
281		}
282		if (leaks) {
283			xge_os_printf("OSPAL: %d memory leaks detected", leaks);
284		} else {
285			xge_os_printf("OSPAL: no memory leaks detected");
286		}
287	}
288#endif
289}
290