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