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
22/*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include <sys/types.h>
27#include <sys/kmem.h>
28#include <sys/cmn_err.h>
29#include <sys/conf.h>
30#include <sys/ddi.h>
31#include <sys/sunddi.h>
32#include <sys/ksynch.h>
33#include <sys/varargs.h>
34
35#include <sys/ib/clients/eoib/eib_impl.h>
36
37/*
38 * Defaults
39 */
40uint_t eib_log_size = EIB_LOGSZ_DEFAULT;
41int eib_log_level = EIB_MSGS_DEFAULT | EIB_MSGS_DEBUG;
42int eib_log_timestamps = 0;
43
44/*
45 * Debug variables, should not be tunables so allocated debug buffer
46 * and its size remain consistent.
47 */
48static kmutex_t eib_debug_buf_lock;
49static uint8_t *eib_debug_buf;
50static uint32_t eib_debug_buf_ndx;
51static uint_t eib_debug_buf_sz = 0;
52
53/*
54 * Local declarations
55 */
56static void eib_log(char *);
57
58void
59eib_debug_init(void)
60{
61	eib_debug_buf_ndx = 0;
62	eib_debug_buf_sz = eib_log_size;
63	eib_debug_buf = kmem_zalloc(eib_debug_buf_sz, KM_SLEEP);
64
65	mutex_init(&eib_debug_buf_lock, NULL, MUTEX_DRIVER, NULL);
66}
67
68void
69eib_debug_fini(void)
70{
71	mutex_destroy(&eib_debug_buf_lock);
72
73	if (eib_debug_buf && eib_debug_buf_sz) {
74		kmem_free(eib_debug_buf, eib_debug_buf_sz);
75		eib_debug_buf = NULL;
76	}
77	eib_debug_buf_sz = 0;
78	eib_debug_buf_ndx = 0;
79}
80
81void
82eib_log(char *msg)
83{
84	uint32_t off;
85	int msglen;
86	char msgbuf[EIB_MAX_LINE];
87
88	if (eib_debug_buf == NULL)
89		return;
90
91	if (eib_log_timestamps) {
92		msglen = snprintf(msgbuf, EIB_MAX_LINE, "%llx: %s",
93		    (unsigned long long)ddi_get_lbolt64(), msg);
94	} else {
95		msglen = snprintf(msgbuf, EIB_MAX_LINE, "%s", msg);
96	}
97
98	if (msglen < 0)
99		return;
100	else if (msglen >= EIB_MAX_LINE)
101		msglen = EIB_MAX_LINE - 1;
102
103	mutex_enter(&eib_debug_buf_lock);
104	if ((eib_debug_buf_ndx == 0) ||
105	    (eib_debug_buf[eib_debug_buf_ndx-1] != '\n')) {
106		eib_debug_buf[eib_debug_buf_ndx] = '\n';
107		eib_debug_buf_ndx++;
108	}
109
110	off = eib_debug_buf_ndx;	/* current msg should go here */
111
112	eib_debug_buf_ndx += msglen;	/* next msg should start here */
113	eib_debug_buf[eib_debug_buf_ndx] = 0;	/* terminate current msg */
114
115	if (eib_debug_buf_ndx >= (eib_debug_buf_sz - 2 * EIB_MAX_LINE))
116		eib_debug_buf_ndx = 0;
117
118	mutex_exit(&eib_debug_buf_lock);
119
120	bcopy(msgbuf, eib_debug_buf+off, msglen);    /* no lock needed */
121}
122
123#ifdef EIB_DEBUG
124void
125eib_dprintf_verbose(int inst, const char *fmt, ...)
126{
127	va_list ap;
128	int msglen;
129	char msgbuf[EIB_MAX_LINE];
130	char newfmt[EIB_MAX_LINE];
131
132	if ((eib_log_level & EIB_MSGS_VERBOSE) != EIB_MSGS_VERBOSE)
133		return;
134
135	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
136
137	va_start(ap, fmt);
138	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
139	va_end(ap);
140
141	if (msglen > 0) {
142		eib_log(msgbuf);
143	}
144}
145
146void
147eib_dprintf_pkt(int inst, uint8_t *pkt, uint_t sz)
148{
149	char msgbuf[EIB_MAX_LINE];
150	char *bufp;
151	uint8_t *p = pkt;
152	uint_t len;
153	uint_t i;
154
155	if ((eib_log_level & EIB_MSGS_PKT) != EIB_MSGS_PKT)
156		return;
157
158	while (sz >= 16) {
159		(void) snprintf(msgbuf, EIB_MAX_LINE,
160		    "eoib%02d__%02x %02x %02x %02x %02x %02x %02x %02x "
161		    "%02x %02x %02x %02x %02x %02x %02x %02x\n", inst,
162		    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
163		    p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
164
165		eib_log(msgbuf);
166
167		p += 16;
168		sz -= 16;
169	}
170
171	len = EIB_MAX_LINE;
172	bufp = msgbuf;
173	for (i = 0; i < sz; i++) {
174		if (i == 0) {
175			(void) snprintf(bufp, len, "eoib%02d__%02x ",
176			    inst, p[i]);
177			len -= 11;
178			bufp += 11;
179		} else if (i < (sz - 1)) {
180			(void) snprintf(bufp, len, "%02x ", p[i]);
181			len -= 3;
182			bufp += 3;
183		} else {
184			(void) snprintf(bufp, len, "%02x\n", p[i]);
185			len -= 3;
186			bufp += 3;
187		}
188	}
189
190	eib_log(msgbuf);
191}
192
193void
194eib_dprintf_args(int inst, const char *fmt, ...)
195{
196	va_list ap;
197	int msglen;
198	char msgbuf[EIB_MAX_LINE];
199	char newfmt[EIB_MAX_LINE];
200
201	if ((eib_log_level & EIB_MSGS_ARGS) != EIB_MSGS_ARGS)
202		return;
203
204	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
205
206	va_start(ap, fmt);
207	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
208	va_end(ap);
209
210	if (msglen > 0) {
211		eib_log(msgbuf);
212	}
213}
214
215void
216eib_dprintf_debug(int inst, const char *fmt, ...)
217{
218	va_list ap;
219	int msglen;
220	char msgbuf[EIB_MAX_LINE];
221	char newfmt[EIB_MAX_LINE];
222
223	if ((eib_log_level & EIB_MSGS_DEBUG) != EIB_MSGS_DEBUG)
224		return;
225
226	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
227
228	va_start(ap, fmt);
229	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
230	va_end(ap);
231
232	if (msglen > 0) {
233		eib_log(msgbuf);
234	}
235}
236#endif
237
238void
239eib_dprintf_warn(int inst, const char *fmt, ...)
240{
241	va_list ap;
242	int msglen;
243	char msgbuf[EIB_MAX_LINE];
244	char newfmt[EIB_MAX_LINE];
245
246	if ((eib_log_level & EIB_MSGS_WARN) != EIB_MSGS_WARN)
247		return;
248
249	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
250
251	va_start(ap, fmt);
252	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
253	va_end(ap);
254
255	if (msglen > 0) {
256		eib_log(msgbuf);
257	}
258}
259
260void
261eib_dprintf_err(int inst, const char *fmt, ...)
262{
263	va_list ap;
264	int msglen;
265	char msgbuf[EIB_MAX_LINE];
266	char newfmt[EIB_MAX_LINE];
267
268	if ((eib_log_level & EIB_MSGS_ERR) != EIB_MSGS_ERR)
269		return;
270
271	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
272
273	va_start(ap, fmt);
274	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
275	va_end(ap);
276
277	if (msglen > 0) {
278		eib_log(msgbuf);
279		cmn_err(CE_WARN, "!%s\n", msgbuf);
280	}
281}
282
283void
284eib_dprintf_crit(int inst, const char *fmt, ...)
285{
286	va_list ap;
287	int msglen;
288	char msgbuf[EIB_MAX_LINE];
289	char newfmt[EIB_MAX_LINE];
290
291	if ((eib_log_level & EIB_MSGS_CRIT) != EIB_MSGS_CRIT)
292		return;
293
294	(void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
295
296	va_start(ap, fmt);
297	msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
298	va_end(ap);
299
300	if (msglen > 0) {
301		eib_log(msgbuf);
302		cmn_err(CE_PANIC, "!%s\n", msgbuf);
303	}
304}
305