1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23291a2b48SSukumar Swaminathan  * Copyright 2009 Emulex.  All rights reserved.
24*82527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27*82527734SSukumar Swaminathan 
28291a2b48SSukumar Swaminathan #define	DEF_MSG_STRUCT	/* Needed for emlxs_messages.h in emlxs_msg.h */
29291a2b48SSukumar Swaminathan #include <emlxs.h>
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
33fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_MSG_C);
34fcf3ce44SJohn Forte 
35291a2b48SSukumar Swaminathan uint32_t emlxs_log_size		= 2048;
36291a2b48SSukumar Swaminathan uint32_t emlxs_log_debugs	= 0x7FFFFFFF;
37291a2b48SSukumar Swaminathan uint32_t emlxs_log_notices	= 0xFFFFFFFF;
38291a2b48SSukumar Swaminathan uint32_t emlxs_log_warnings	= 0xFFFFFFFF;
39291a2b48SSukumar Swaminathan uint32_t emlxs_log_errors	= 0xFFFFFFFF;
40fcf3ce44SJohn Forte 
41291a2b48SSukumar Swaminathan static uint32_t	emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg);
42291a2b48SSukumar Swaminathan static uint32_t	emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg);
43291a2b48SSukumar Swaminathan static void	emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry);
44fcf3ce44SJohn Forte 
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte uint32_t
47fcf3ce44SJohn Forte emlxs_msg_log_create(emlxs_hba_t *hba)
48fcf3ce44SJohn Forte {
49fcf3ce44SJohn Forte 	emlxs_msg_log_t *log = &LOG;
50fcf3ce44SJohn Forte 	uint32_t size = sizeof (emlxs_msg_entry_t) * emlxs_log_size;
51fcf3ce44SJohn Forte 	char buf[40];
52fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
53fcf3ce44SJohn Forte 	ddi_intr_handle_t handle;
54fcf3ce44SJohn Forte 	uint32_t intr_pri;
55fcf3ce44SJohn Forte 	int32_t actual;
56fcf3ce44SJohn Forte 	uint32_t ret;
57291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
58fcf3ce44SJohn Forte 	ddi_iblock_cookie_t iblock;
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte 	/* Check if log is already created */
61fcf3ce44SJohn Forte 	if (log->entry) {
62fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "?%s%d: message log already created. log=%p",
63291a2b48SSukumar Swaminathan 		    DRIVER_NAME, hba->ddiinst, (void *)log);
64fcf3ce44SJohn Forte 		return (0);
65fcf3ce44SJohn Forte 	}
66291a2b48SSukumar Swaminathan 
67fcf3ce44SJohn Forte 	/* Clear the log */
68fcf3ce44SJohn Forte 	bzero(log, sizeof (emlxs_msg_log_t));
69fcf3ce44SJohn Forte 
70fcf3ce44SJohn Forte 	/* Allocate the memory needed for the log file */
71*82527734SSukumar Swaminathan 	log->entry = (emlxs_msg_entry_t *)kmem_zalloc(size, KM_SLEEP);
72291a2b48SSukumar Swaminathan 
73fcf3ce44SJohn Forte 	/* Initialize */
74fcf3ce44SJohn Forte 	log->size = emlxs_log_size;
75fcf3ce44SJohn Forte 	log->instance = hba->ddiinst;
76fcf3ce44SJohn Forte 	log->start_time = emlxs_device.log_timestamp;
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte 	(void) sprintf(buf, "?%s%d_log_lock mutex", DRIVER_NAME, hba->ddiinst);
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte 	if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
81fcf3ce44SJohn Forte 		/* Get the current interrupt block cookie */
82fcf3ce44SJohn Forte 		(void) ddi_get_iblock_cookie(hba->dip, (uint_t)EMLXS_INUMBER,
83fcf3ce44SJohn Forte 		    &iblock);
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte 		/* Create the log mutex lock */
86291a2b48SSukumar Swaminathan 		mutex_init(&log->lock, buf, MUTEX_DRIVER, (void *)iblock);
87fcf3ce44SJohn Forte 	}
88fcf3ce44SJohn Forte #ifdef  MSI_SUPPORT
89fcf3ce44SJohn Forte 	else {
90fcf3ce44SJohn Forte 		/* Allocate a temporary interrupt handle */
91fcf3ce44SJohn Forte 		actual = 0;
92291a2b48SSukumar Swaminathan 		ret =
93291a2b48SSukumar Swaminathan 		    ddi_intr_alloc(hba->dip, &handle, DDI_INTR_TYPE_FIXED,
94fcf3ce44SJohn Forte 		    EMLXS_MSI_INUMBER, 1, &actual, DDI_INTR_ALLOC_NORMAL);
95fcf3ce44SJohn Forte 
96fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS || actual == 0) {
97291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
98291a2b48SSukumar Swaminathan 			    "?%s%d: Unable to allocate temporary interrupt "
99291a2b48SSukumar Swaminathan 			    "handle. ret=%d actual=%d", DRIVER_NAME,
100291a2b48SSukumar Swaminathan 			    hba->ddiinst, ret, actual);
101fcf3ce44SJohn Forte 
102fcf3ce44SJohn Forte 			/* Free the log buffer */
103fcf3ce44SJohn Forte 			kmem_free(log->entry, size);
104fcf3ce44SJohn Forte 			bzero(log, sizeof (emlxs_msg_log_t));
105fcf3ce44SJohn Forte 
106fcf3ce44SJohn Forte 			return (0);
107fcf3ce44SJohn Forte 		}
108291a2b48SSukumar Swaminathan 
109fcf3ce44SJohn Forte 		/* Get the current interrupt priority */
110fcf3ce44SJohn Forte 		ret = ddi_intr_get_pri(handle, &intr_pri);
111fcf3ce44SJohn Forte 
112fcf3ce44SJohn Forte 		if (ret != DDI_SUCCESS) {
113291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
114291a2b48SSukumar Swaminathan 			    "?%s%d: Unable to get interrupt priority. ret=%d",
115291a2b48SSukumar Swaminathan 			    DRIVER_NAME, hba->ddiinst, ret);
116fcf3ce44SJohn Forte 
117fcf3ce44SJohn Forte 			/* Free the log buffer */
118fcf3ce44SJohn Forte 			kmem_free(log->entry, size);
119fcf3ce44SJohn Forte 			bzero(log, sizeof (emlxs_msg_log_t));
120fcf3ce44SJohn Forte 
121fcf3ce44SJohn Forte 			return (0);
122fcf3ce44SJohn Forte 		}
123291a2b48SSukumar Swaminathan 
124fcf3ce44SJohn Forte 		/* Create the log mutex lock */
125fcf3ce44SJohn Forte 		mutex_init(&log->lock, buf, MUTEX_DRIVER,
126291a2b48SSukumar Swaminathan 		    (void *)((unsigned long)intr_pri));
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte 		/* Free the temporary handle */
129fcf3ce44SJohn Forte 		(void) ddi_intr_free(handle);
130fcf3ce44SJohn Forte 	}
131fcf3ce44SJohn Forte #endif
132fcf3ce44SJohn Forte 
133fcf3ce44SJohn Forte 	return (1);
134fcf3ce44SJohn Forte 
135*82527734SSukumar Swaminathan } /* emlxs_msg_log_create() */
136fcf3ce44SJohn Forte 
137fcf3ce44SJohn Forte 
138fcf3ce44SJohn Forte uint32_t
139fcf3ce44SJohn Forte emlxs_msg_log_destroy(emlxs_hba_t *hba)
140fcf3ce44SJohn Forte {
141fcf3ce44SJohn Forte 	emlxs_msg_log_t *log = &LOG;
142fcf3ce44SJohn Forte 	uint32_t size;
143fcf3ce44SJohn Forte 
144fcf3ce44SJohn Forte 	/* Check if log is already destroyed */
145fcf3ce44SJohn Forte 	if (!log->entry) {
146291a2b48SSukumar Swaminathan 		cmn_err(CE_WARN,
147291a2b48SSukumar Swaminathan 		    "?%s%d: message log already destroyed. log=%p",
148291a2b48SSukumar Swaminathan 		    DRIVER_NAME, hba->ddiinst, (void *)log);
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte 		return (1);
151fcf3ce44SJohn Forte 	}
152291a2b48SSukumar Swaminathan 
153fcf3ce44SJohn Forte 	/* Destroy the lock */
154fcf3ce44SJohn Forte 	mutex_destroy(&log->lock);
155fcf3ce44SJohn Forte 
156fcf3ce44SJohn Forte 	/* Free the log buffer */
157fcf3ce44SJohn Forte 	size = sizeof (emlxs_msg_entry_t) * log->size;
158fcf3ce44SJohn Forte 	kmem_free(log->entry, size);
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 	/* Clear the log */
161fcf3ce44SJohn Forte 	bzero(log, sizeof (emlxs_msg_log_t));
162fcf3ce44SJohn Forte 
163fcf3ce44SJohn Forte 	return (1);
164fcf3ce44SJohn Forte 
165*82527734SSukumar Swaminathan } /* emlxs_msg_log_destroy() */
166291a2b48SSukumar Swaminathan 
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte uint32_t
169fcf3ce44SJohn Forte emlxs_msg_log(emlxs_port_t *port, const uint32_t fileno, const uint32_t line,
170*82527734SSukumar Swaminathan     emlxs_msg_t *msg, char *buffer)
171fcf3ce44SJohn Forte {
172fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
173fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry;
174fcf3ce44SJohn Forte 	emlxs_msg_entry_t *entry2;
175fcf3ce44SJohn Forte 	clock_t time;
176fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
177fcf3ce44SJohn Forte 	uint32_t last;
178fcf3ce44SJohn Forte 	emlxs_msg_t *msg2;
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 	/* Get the log file for this instance */
181fcf3ce44SJohn Forte 	log = &LOG;
182fcf3ce44SJohn Forte 
183fcf3ce44SJohn Forte 	/* Check if log is initialized */
184fcf3ce44SJohn Forte 	if (log->entry == NULL) {
185fcf3ce44SJohn Forte 
186fcf3ce44SJohn Forte 		if (port->vpi == 0) {
187291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
188291a2b48SSukumar Swaminathan 			    "?%s%d: message log not created. log=%p",
189291a2b48SSukumar Swaminathan 			    DRIVER_NAME, hba->ddiinst, (void *)log);
190fcf3ce44SJohn Forte 		} else {
191291a2b48SSukumar Swaminathan 			cmn_err(CE_WARN,
192291a2b48SSukumar Swaminathan 			    "?%s%d.%d: message log not created. log=%p",
193291a2b48SSukumar Swaminathan 			    DRIVER_NAME, hba->ddiinst, port->vpi,
194291a2b48SSukumar Swaminathan 			    (void *)log);
195fcf3ce44SJohn Forte 		}
196fcf3ce44SJohn Forte 
197fcf3ce44SJohn Forte 		return (1);
198fcf3ce44SJohn Forte 	}
199291a2b48SSukumar Swaminathan 
200fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 	/* Get the pointer to the last log entry */
203fcf3ce44SJohn Forte 	if (log->next == 0) {
204fcf3ce44SJohn Forte 		last = log->size - 1;
205fcf3ce44SJohn Forte 	} else {
206fcf3ce44SJohn Forte 		last = log->next - 1;
207fcf3ce44SJohn Forte 	}
208fcf3ce44SJohn Forte 	entry = &log->entry[last];
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 	/* Check if this matches the last message */
211fcf3ce44SJohn Forte 	if ((entry->instance == log->instance) &&
212fcf3ce44SJohn Forte 	    (entry->vpi == port->vpi) &&
213fcf3ce44SJohn Forte 	    (entry->fileno == fileno) &&
214fcf3ce44SJohn Forte 	    (entry->line == line) &&
215fcf3ce44SJohn Forte 	    (entry->msg == msg) &&
216fcf3ce44SJohn Forte 	    (strcmp(entry->buffer, buffer) == 0)) {
217fcf3ce44SJohn Forte 		/* If the same message is being logged then increment */
218fcf3ce44SJohn Forte 		log->repeat++;
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte 		return (0);
223fcf3ce44SJohn Forte 	} else if (log->repeat) {
224fcf3ce44SJohn Forte 		/* Get the pointer to the next log entry */
225fcf3ce44SJohn Forte 		entry2 = &log->entry[log->next];
226fcf3ce44SJohn Forte 
227fcf3ce44SJohn Forte 		/* Increment and check the next entry index */
228fcf3ce44SJohn Forte 		if (++(log->next) >= log->size) {
229fcf3ce44SJohn Forte 			log->next = 0;
230fcf3ce44SJohn Forte 		}
231291a2b48SSukumar Swaminathan 
232fcf3ce44SJohn Forte 		switch (entry->msg->level) {
233fcf3ce44SJohn Forte 		case EMLXS_DEBUG:
234fcf3ce44SJohn Forte 			msg2 = &emlxs_debug_msg;
235fcf3ce44SJohn Forte 			break;
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 		case EMLXS_NOTICE:
238fcf3ce44SJohn Forte 			msg2 = &emlxs_notice_msg;
239fcf3ce44SJohn Forte 			break;
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 		case EMLXS_WARNING:
242fcf3ce44SJohn Forte 			msg2 = &emlxs_warning_msg;
243fcf3ce44SJohn Forte 			break;
244fcf3ce44SJohn Forte 
245fcf3ce44SJohn Forte 		case EMLXS_ERROR:
246fcf3ce44SJohn Forte 			msg2 = &emlxs_error_msg;
247fcf3ce44SJohn Forte 			break;
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte 		case EMLXS_PANIC:
250fcf3ce44SJohn Forte 			msg2 = &emlxs_panic_msg;
251fcf3ce44SJohn Forte 			break;
252fcf3ce44SJohn Forte 		}
253291a2b48SSukumar Swaminathan 
254fcf3ce44SJohn Forte 		/* Initialize */
255fcf3ce44SJohn Forte 		entry2->id = log->count++;
256fcf3ce44SJohn Forte 		entry2->fileno = entry->fileno;
257fcf3ce44SJohn Forte 		entry2->line = entry->line;
258fcf3ce44SJohn Forte 		entry2->msg = msg2;
259fcf3ce44SJohn Forte 		entry2->instance = log->instance;
260fcf3ce44SJohn Forte 		entry2->vpi = port->vpi;
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 		/* Save the additional info buffer */
263fcf3ce44SJohn Forte 		(void) sprintf(entry2->buffer,
264fcf3ce44SJohn Forte 		    "Last message repeated %d time(s).",
265fcf3ce44SJohn Forte 		    log->repeat);
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 		/* Set the entry time stamp */
268fcf3ce44SJohn Forte 		(void) drv_getparm(LBOLT, &time);
269fcf3ce44SJohn Forte 		entry2->time = time - log->start_time;
270fcf3ce44SJohn Forte 
271*82527734SSukumar Swaminathan 		gethrestime(&entry2->id_time);
272*82527734SSukumar Swaminathan 
273fcf3ce44SJohn Forte 		log->repeat = 0;
274fcf3ce44SJohn Forte 	}
275291a2b48SSukumar Swaminathan 
276fcf3ce44SJohn Forte 	/* Get the pointer to the next log entry */
277fcf3ce44SJohn Forte 	entry = &log->entry[log->next];
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 	/* Increment and check the next entry index */
280fcf3ce44SJohn Forte 	if (++(log->next) >= log->size) {
281fcf3ce44SJohn Forte 		log->next = 0;
282fcf3ce44SJohn Forte 	}
283291a2b48SSukumar Swaminathan 
284fcf3ce44SJohn Forte 	/* Initialize */
285fcf3ce44SJohn Forte 	entry->id = log->count++;
286fcf3ce44SJohn Forte 	entry->fileno = fileno;
287fcf3ce44SJohn Forte 	entry->line = line;
288fcf3ce44SJohn Forte 	entry->msg = msg;
289fcf3ce44SJohn Forte 	entry->instance = log->instance;
290fcf3ce44SJohn Forte 	entry->vpi = port->vpi;
291fcf3ce44SJohn Forte 
292fcf3ce44SJohn Forte 	/* Save the additional info buffer */
293fcf3ce44SJohn Forte 	(void) strncpy(entry->buffer, buffer, (MAX_LOG_INFO_LENGTH - 1));
294fcf3ce44SJohn Forte 	entry->buffer[MAX_LOG_INFO_LENGTH - 1] = 0;
295fcf3ce44SJohn Forte 
296fcf3ce44SJohn Forte 	/* Set the entry time stamp */
297fcf3ce44SJohn Forte 	(void) drv_getparm(LBOLT, &time);
298fcf3ce44SJohn Forte 	entry->time = time - log->start_time;
299fcf3ce44SJohn Forte 
300*82527734SSukumar Swaminathan 	gethrestime(&entry->id_time);
301291a2b48SSukumar Swaminathan 
302fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte 	return (0);
305fcf3ce44SJohn Forte 
306*82527734SSukumar Swaminathan } /* emlxs_msg_log() */
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 
309*82527734SSukumar Swaminathan /*ARGSUSED*/
310fcf3ce44SJohn Forte static uint32_t
311fcf3ce44SJohn Forte emlxs_msg_log_check(emlxs_port_t *port, emlxs_msg_t *msg)
312fcf3ce44SJohn Forte {
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 	switch (msg->level) {
315fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
316fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_debugs) {
317fcf3ce44SJohn Forte 			return (1);
318fcf3ce44SJohn Forte 		}
319fcf3ce44SJohn Forte 		break;
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
322fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_notices) {
323fcf3ce44SJohn Forte 			return (1);
324fcf3ce44SJohn Forte 		}
325fcf3ce44SJohn Forte 		break;
326fcf3ce44SJohn Forte 
327fcf3ce44SJohn Forte 	case EMLXS_WARNING:
328fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_warnings) {
329fcf3ce44SJohn Forte 			return (1);
330fcf3ce44SJohn Forte 		}
331fcf3ce44SJohn Forte 		break;
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte 	case EMLXS_ERROR:
334fcf3ce44SJohn Forte 		if (msg->mask & emlxs_log_errors) {
335fcf3ce44SJohn Forte 			return (1);
336fcf3ce44SJohn Forte 		}
337fcf3ce44SJohn Forte 		break;
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte 	case EMLXS_PANIC:
340fcf3ce44SJohn Forte 		return (1);
341fcf3ce44SJohn Forte 	}
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 	return (0);
344fcf3ce44SJohn Forte 
345*82527734SSukumar Swaminathan } /* emlxs_msg_log_check() */
346fcf3ce44SJohn Forte 
347fcf3ce44SJohn Forte 
348fcf3ce44SJohn Forte static uint32_t
349fcf3ce44SJohn Forte emlxs_msg_print_check(emlxs_port_t *port, emlxs_msg_t *msg)
350fcf3ce44SJohn Forte {
351fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
352fcf3ce44SJohn Forte 	emlxs_config_t *cfg;
353fcf3ce44SJohn Forte 	uint32_t rval = 0;
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 	cfg = &CFG;
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte 	switch (msg->level) {
358fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
359fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_DEBUGS].current) {
360fcf3ce44SJohn Forte 			rval |= 2;
361fcf3ce44SJohn Forte 		}
362291a2b48SSukumar Swaminathan 
363fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_DEBUGS].current) {
364fcf3ce44SJohn Forte 			rval |= 1;
365fcf3ce44SJohn Forte 		}
366291a2b48SSukumar Swaminathan 
367fcf3ce44SJohn Forte 		break;
368fcf3ce44SJohn Forte 
369fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
370fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_NOTICES].current) {
371fcf3ce44SJohn Forte 			rval |= 2;
372fcf3ce44SJohn Forte 		}
373291a2b48SSukumar Swaminathan 
374fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_NOTICES].current) {
375fcf3ce44SJohn Forte 			rval |= 1;
376fcf3ce44SJohn Forte 		}
377291a2b48SSukumar Swaminathan 
378fcf3ce44SJohn Forte 		break;
379fcf3ce44SJohn Forte 
380fcf3ce44SJohn Forte 	case EMLXS_WARNING:
381fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_WARNINGS].current) {
382fcf3ce44SJohn Forte 			rval |= 2;
383fcf3ce44SJohn Forte 		}
384291a2b48SSukumar Swaminathan 
385fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_WARNINGS].current) {
386fcf3ce44SJohn Forte 			rval |= 1;
387fcf3ce44SJohn Forte 		}
388291a2b48SSukumar Swaminathan 
389fcf3ce44SJohn Forte 		break;
390fcf3ce44SJohn Forte 
391fcf3ce44SJohn Forte 	case EMLXS_ERROR:
392fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_CONSOLE_ERRORS].current) {
393fcf3ce44SJohn Forte 			rval |= 2;
394fcf3ce44SJohn Forte 		}
395291a2b48SSukumar Swaminathan 
396fcf3ce44SJohn Forte 		if (msg->mask & cfg[CFG_LOG_ERRORS].current) {
397fcf3ce44SJohn Forte 			rval |= 1;
398fcf3ce44SJohn Forte 		}
399fcf3ce44SJohn Forte 		break;
400fcf3ce44SJohn Forte 
401fcf3ce44SJohn Forte 	case EMLXS_PANIC:
402fcf3ce44SJohn Forte 	default:
403fcf3ce44SJohn Forte 		rval |= 1;
404fcf3ce44SJohn Forte 
405fcf3ce44SJohn Forte 	}
406fcf3ce44SJohn Forte 
407fcf3ce44SJohn Forte 	return (rval);
408fcf3ce44SJohn Forte 
409*82527734SSukumar Swaminathan } /* emlxs_msg_print_check() */
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 
412fcf3ce44SJohn Forte void
413291a2b48SSukumar Swaminathan emlxs_msg_printf(emlxs_port_t *port, const uint32_t fileno,
414*82527734SSukumar Swaminathan     const uint32_t line, emlxs_msg_t *msg,
415291a2b48SSukumar Swaminathan     const char *fmt, ...)
416fcf3ce44SJohn Forte {
417fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
418fcf3ce44SJohn Forte 	va_list valist;
419fcf3ce44SJohn Forte 	char va_str[256];
420fcf3ce44SJohn Forte 	char msg_str[512];
421fcf3ce44SJohn Forte 	char *level;
422fcf3ce44SJohn Forte 	int32_t cmn_level;
423fcf3ce44SJohn Forte 	uint32_t rval;
424fcf3ce44SJohn Forte 	char driver[32];
425fcf3ce44SJohn Forte 
426fcf3ce44SJohn Forte 	va_str[0] = 0;
427fcf3ce44SJohn Forte 
428fcf3ce44SJohn Forte 	if (fmt) {
429fcf3ce44SJohn Forte 		va_start(valist, fmt);
430fcf3ce44SJohn Forte 		(void) vsprintf(va_str, fmt, valist);
431fcf3ce44SJohn Forte 		va_end(valist);
432fcf3ce44SJohn Forte 	}
433291a2b48SSukumar Swaminathan 
434291a2b48SSukumar Swaminathan #ifdef FMA_SUPPORT
435bb63f56eSSukumar Swaminathan 	if (msg->fm_ereport_code) {
436bb63f56eSSukumar Swaminathan 		emlxs_fm_ereport(hba, msg->fm_ereport_code);
437bb63f56eSSukumar Swaminathan 	}
438291a2b48SSukumar Swaminathan 
439bb63f56eSSukumar Swaminathan 	if (msg->fm_impact_code) {
440bb63f56eSSukumar Swaminathan 		emlxs_fm_service_impact(hba, msg->fm_impact_code);
441291a2b48SSukumar Swaminathan 	}
442291a2b48SSukumar Swaminathan #endif	/* FMA_SUPPORT */
443291a2b48SSukumar Swaminathan 
444fcf3ce44SJohn Forte 	/* Check if msg should be logged */
445*82527734SSukumar Swaminathan 	if (emlxs_msg_log_check(port, msg)) {
446fcf3ce44SJohn Forte 		/* Log the message */
447*82527734SSukumar Swaminathan 		if (emlxs_msg_log(port, fileno, line, msg, va_str)) {
448fcf3ce44SJohn Forte 			return;
449fcf3ce44SJohn Forte 		}
450fcf3ce44SJohn Forte 	}
451291a2b48SSukumar Swaminathan 
452fcf3ce44SJohn Forte 	/* Check if msg should be printed */
453fcf3ce44SJohn Forte 	if (rval = emlxs_msg_print_check(port, msg)) {
454fcf3ce44SJohn Forte 		cmn_level = CE_CONT;
455fcf3ce44SJohn Forte 
456fcf3ce44SJohn Forte 		switch (msg->level) {
457fcf3ce44SJohn Forte 		case EMLXS_DEBUG:
458fcf3ce44SJohn Forte 			level = "  DEBUG";
459fcf3ce44SJohn Forte 			break;
460fcf3ce44SJohn Forte 
461fcf3ce44SJohn Forte 		case EMLXS_NOTICE:
462fcf3ce44SJohn Forte 			level = " NOTICE";
463fcf3ce44SJohn Forte 			break;
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 		case EMLXS_WARNING:
466fcf3ce44SJohn Forte 			level = "WARNING";
467fcf3ce44SJohn Forte 			break;
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 		case EMLXS_ERROR:
470fcf3ce44SJohn Forte 			level = "  ERROR";
471fcf3ce44SJohn Forte 			break;
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 		case EMLXS_PANIC:
474fcf3ce44SJohn Forte 			cmn_level = CE_PANIC;
475fcf3ce44SJohn Forte 			level = "  PANIC";
476fcf3ce44SJohn Forte 			break;
477fcf3ce44SJohn Forte 
478fcf3ce44SJohn Forte 		default:
479fcf3ce44SJohn Forte 			level = "UNKNOWN";
480fcf3ce44SJohn Forte 			break;
481fcf3ce44SJohn Forte 		}
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		if (port->vpi == 0) {
484fcf3ce44SJohn Forte 			(void) sprintf(driver, "%s%d", DRIVER_NAME,
485fcf3ce44SJohn Forte 			    hba->ddiinst);
486fcf3ce44SJohn Forte 		} else {
487fcf3ce44SJohn Forte 			(void) sprintf(driver, "%s%d.%d", DRIVER_NAME,
488fcf3ce44SJohn Forte 			    hba->ddiinst, port->vpi);
489fcf3ce44SJohn Forte 		}
490fcf3ce44SJohn Forte 
491fcf3ce44SJohn Forte 		/* Generate the message string */
492fcf3ce44SJohn Forte 		if (msg->buffer[0] != 0) {
493fcf3ce44SJohn Forte 			if (va_str[0] != 0) {
494fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
495291a2b48SSukumar Swaminathan 				    "[%2X.%04X]%s:%7s:%4d: %s (%s)\n", fileno,
496291a2b48SSukumar Swaminathan 				    line, driver, level, msg->id, msg->buffer,
497291a2b48SSukumar Swaminathan 				    va_str);
498fcf3ce44SJohn Forte 			} else {
499fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
500fcf3ce44SJohn Forte 				    "[%2X.%04X]%s:%7s:%4d: %s\n",
501fcf3ce44SJohn Forte 				    fileno, line, driver, level, msg->id,
502fcf3ce44SJohn Forte 				    msg->buffer);
503fcf3ce44SJohn Forte 			}
504fcf3ce44SJohn Forte 		} else {
505fcf3ce44SJohn Forte 			if (va_str[0] != 0) {
506fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
507291a2b48SSukumar Swaminathan 				    "[%2X.%04X]%s:%7s:%4d: (%s)\n", fileno,
508291a2b48SSukumar Swaminathan 				    line, driver, level, msg->id, va_str);
509fcf3ce44SJohn Forte 			} else {
510fcf3ce44SJohn Forte 				(void) sprintf(msg_str,
511fcf3ce44SJohn Forte 				    "[%2X.%04X]%s:%7s:%4d\n",
512fcf3ce44SJohn Forte 				    fileno, line, driver, level, msg->id);
513fcf3ce44SJohn Forte 			}
514fcf3ce44SJohn Forte 		}
515fcf3ce44SJohn Forte 
516fcf3ce44SJohn Forte 		switch (rval) {
517fcf3ce44SJohn Forte 		case 1:	/* MESSAGE LOG ONLY */
518291a2b48SSukumar Swaminathan 			/* Message log & console, if system booted in */
519291a2b48SSukumar Swaminathan 			/* verbose mode (CE_CONT only) */
520fcf3ce44SJohn Forte 			cmn_err(cmn_level, "?%s", msg_str);
521fcf3ce44SJohn Forte 			break;
522fcf3ce44SJohn Forte 
523fcf3ce44SJohn Forte 		case 2:	/* CONSOLE ONLY */
524fcf3ce44SJohn Forte 			cmn_err(cmn_level, "^%s", msg_str);
525fcf3ce44SJohn Forte 			break;
526fcf3ce44SJohn Forte 
527fcf3ce44SJohn Forte 		case 3:	/* CONSOLE AND MESSAGE LOG */
528fcf3ce44SJohn Forte 			cmn_err(cmn_level, "%s", msg_str);
529fcf3ce44SJohn Forte 			break;
530fcf3ce44SJohn Forte 
531fcf3ce44SJohn Forte 		}
532fcf3ce44SJohn Forte 
533fcf3ce44SJohn Forte 	}
534291a2b48SSukumar Swaminathan 
535fcf3ce44SJohn Forte 	return;
536fcf3ce44SJohn Forte 
537*82527734SSukumar Swaminathan } /* emlxs_msg_printf() */
538fcf3ce44SJohn Forte 
539fcf3ce44SJohn Forte 
540fcf3ce44SJohn Forte uint32_t
541fcf3ce44SJohn Forte emlxs_msg_log_get(emlxs_hba_t *hba, emlxs_log_req_t *req,
542fcf3ce44SJohn Forte     emlxs_log_resp_t *resp)
543fcf3ce44SJohn Forte {
544fcf3ce44SJohn Forte 	emlxs_msg_log_t *log;
545fcf3ce44SJohn Forte 	uint32_t first;
546fcf3ce44SJohn Forte 	uint32_t last;
547fcf3ce44SJohn Forte 	uint32_t count;
548fcf3ce44SJohn Forte 	uint32_t index;
549fcf3ce44SJohn Forte 	uint32_t i;
550fcf3ce44SJohn Forte 	char *resp_buf;
551fcf3ce44SJohn Forte 
552fcf3ce44SJohn Forte 	log = &LOG;
553fcf3ce44SJohn Forte 
554fcf3ce44SJohn Forte 	mutex_enter(&log->lock);
555fcf3ce44SJohn Forte 
556fcf3ce44SJohn Forte 	/* Check if buffer is empty */
557fcf3ce44SJohn Forte 	if (log->count == 0) {
558fcf3ce44SJohn Forte 		/* If so, exit now */
559fcf3ce44SJohn Forte 		resp->first = 0;
560fcf3ce44SJohn Forte 		resp->last = 0;
561fcf3ce44SJohn Forte 		resp->count = 0;
562fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 		return (1);
565fcf3ce44SJohn Forte 	}
566291a2b48SSukumar Swaminathan 
567fcf3ce44SJohn Forte 	/* Get current log entry ranges */
568fcf3ce44SJohn Forte 
569fcf3ce44SJohn Forte 	/* Get last entry id saved */
570fcf3ce44SJohn Forte 	last = log->count - 1;
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte 	/* Check if request is out of current range */
573fcf3ce44SJohn Forte 	if (req->first > last) {
574fcf3ce44SJohn Forte 		/* if so, exit now */
575fcf3ce44SJohn Forte 		resp->first = last;
576fcf3ce44SJohn Forte 		resp->last = last;
577fcf3ce44SJohn Forte 		resp->count = 0;
578fcf3ce44SJohn Forte 		mutex_exit(&log->lock);
579fcf3ce44SJohn Forte 
580fcf3ce44SJohn Forte 		return (0);
581fcf3ce44SJohn Forte 	}
582291a2b48SSukumar Swaminathan 
583fcf3ce44SJohn Forte 	/* Get oldest entry id and its index */
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 	/* Check if buffer has already been filled once */
586fcf3ce44SJohn Forte 	if (log->count >= log->size) {
587fcf3ce44SJohn Forte 		first = log->count - log->size;
588fcf3ce44SJohn Forte 		index = log->next;
589fcf3ce44SJohn Forte 	} else {	/* Buffer not yet filled */
590291a2b48SSukumar Swaminathan 
591fcf3ce44SJohn Forte 		first = 0;
592fcf3ce44SJohn Forte 		index = 0;
593fcf3ce44SJohn Forte 	}
594fcf3ce44SJohn Forte 
595291a2b48SSukumar Swaminathan 	/* Check if requested first message is greater than actual. */
596291a2b48SSukumar Swaminathan 	/* If so, adjust for it.  */
597fcf3ce44SJohn Forte 	if (req->first > first) {
598fcf3ce44SJohn Forte 		/* Adjust entry index to first requested message */
599fcf3ce44SJohn Forte 		index += (req->first - first);
600fcf3ce44SJohn Forte 		if (index >= log->size) {
601fcf3ce44SJohn Forte 			index -= log->size;
602fcf3ce44SJohn Forte 		}
603291a2b48SSukumar Swaminathan 
604fcf3ce44SJohn Forte 		first = req->first;
605fcf3ce44SJohn Forte 	}
606291a2b48SSukumar Swaminathan 
607fcf3ce44SJohn Forte 	/* Get the total number of messages available for return */
608fcf3ce44SJohn Forte 	count = last - first + 1;
609fcf3ce44SJohn Forte 
610fcf3ce44SJohn Forte 	/* Check if requested count is less than actual.  If so, adjust it. */
611fcf3ce44SJohn Forte 	if (req->count < count) {
612fcf3ce44SJohn Forte 		count = req->count;
613fcf3ce44SJohn Forte 	}
614291a2b48SSukumar Swaminathan 
615fcf3ce44SJohn Forte 	/* Fill in the response header */
616fcf3ce44SJohn Forte 	resp->count = count;
617fcf3ce44SJohn Forte 	resp->first = first;
618fcf3ce44SJohn Forte 	resp->last = last;
619fcf3ce44SJohn Forte 
620fcf3ce44SJohn Forte 	/* Fill the response buffer */
621fcf3ce44SJohn Forte 	resp_buf = (char *)resp + sizeof (emlxs_log_resp_t);
622fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
623fcf3ce44SJohn Forte 		emlxs_msg_sprintf(resp_buf, &log->entry[index]);
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte 		/* Increment the response buffer */
626fcf3ce44SJohn Forte 		resp_buf += MAX_LOG_MSG_LENGTH;
627fcf3ce44SJohn Forte 
628fcf3ce44SJohn Forte 		/* Increment index */
629fcf3ce44SJohn Forte 		if (++index >= log->size) {
630fcf3ce44SJohn Forte 			index = 0;
631fcf3ce44SJohn Forte 		}
632fcf3ce44SJohn Forte 	}
633fcf3ce44SJohn Forte 
634fcf3ce44SJohn Forte 	mutex_exit(&log->lock);
635fcf3ce44SJohn Forte 
636fcf3ce44SJohn Forte 	return (1);
637fcf3ce44SJohn Forte 
638*82527734SSukumar Swaminathan } /* emlxs_msg_log_get() */
639fcf3ce44SJohn Forte 
640fcf3ce44SJohn Forte 
641fcf3ce44SJohn Forte 
642fcf3ce44SJohn Forte static void
643fcf3ce44SJohn Forte emlxs_msg_sprintf(char *buffer, emlxs_msg_entry_t *entry)
644fcf3ce44SJohn Forte {
645fcf3ce44SJohn Forte 	char *level;
646fcf3ce44SJohn Forte 	emlxs_msg_t *msg;
647fcf3ce44SJohn Forte 	uint32_t secs;
648fcf3ce44SJohn Forte 	uint32_t hsecs;
649fcf3ce44SJohn Forte 	char buf[256];
650fcf3ce44SJohn Forte 	uint32_t buflen;
651fcf3ce44SJohn Forte 	char driver[32];
652fcf3ce44SJohn Forte 
653fcf3ce44SJohn Forte 	msg = entry->msg;
654*82527734SSukumar Swaminathan 
655fcf3ce44SJohn Forte 	hsecs = (entry->time % 100);
656fcf3ce44SJohn Forte 	secs = entry->time / 100;
657fcf3ce44SJohn Forte 
658fcf3ce44SJohn Forte 	switch (msg->level) {
659fcf3ce44SJohn Forte 	case EMLXS_DEBUG:
660fcf3ce44SJohn Forte 		level = "  DEBUG";
661fcf3ce44SJohn Forte 		break;
662fcf3ce44SJohn Forte 
663fcf3ce44SJohn Forte 	case EMLXS_NOTICE:
664fcf3ce44SJohn Forte 		level = " NOTICE";
665fcf3ce44SJohn Forte 		break;
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte 	case EMLXS_WARNING:
668fcf3ce44SJohn Forte 		level = "WARNING";
669fcf3ce44SJohn Forte 		break;
670fcf3ce44SJohn Forte 
671fcf3ce44SJohn Forte 	case EMLXS_ERROR:
672fcf3ce44SJohn Forte 		level = "  ERROR";
673fcf3ce44SJohn Forte 		break;
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	case EMLXS_PANIC:
676fcf3ce44SJohn Forte 		level = "  PANIC";
677fcf3ce44SJohn Forte 		break;
678fcf3ce44SJohn Forte 
679fcf3ce44SJohn Forte 	default:
680fcf3ce44SJohn Forte 		level = "UNKNOWN";
681fcf3ce44SJohn Forte 		break;
682fcf3ce44SJohn Forte 	}
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 	if (entry->vpi == 0) {
685fcf3ce44SJohn Forte 		(void) sprintf(driver, "%s%d", DRIVER_NAME, entry->instance);
686fcf3ce44SJohn Forte 	} else {
687fcf3ce44SJohn Forte 		(void) sprintf(driver, "%s%d.%d", DRIVER_NAME, entry->instance,
688fcf3ce44SJohn Forte 		    entry->vpi);
689fcf3ce44SJohn Forte 	}
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte 	/* Generate the message string */
692fcf3ce44SJohn Forte 	if (msg->buffer[0] != 0) {
693fcf3ce44SJohn Forte 		if (entry->buffer[0] != 0) {
694fcf3ce44SJohn Forte 			(void) sprintf(buf,
695fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s (%s)\n",
696291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
697291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id, msg->buffer,
698291a2b48SSukumar Swaminathan 			    entry->buffer);
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 		} else {
701fcf3ce44SJohn Forte 			(void) sprintf(buf,
702291a2b48SSukumar Swaminathan 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: %s\n", secs,
703291a2b48SSukumar Swaminathan 			    hsecs, entry->id, entry->fileno, entry->line,
704fcf3ce44SJohn Forte 			    driver, level, msg->id, msg->buffer);
705fcf3ce44SJohn Forte 		}
706fcf3ce44SJohn Forte 	} else {
707fcf3ce44SJohn Forte 		if (entry->buffer[0] != 0) {
708fcf3ce44SJohn Forte 			(void) sprintf(buf,
709fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d: (%s)\n",
710291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
711291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id,
712291a2b48SSukumar Swaminathan 			    entry->buffer);
713fcf3ce44SJohn Forte 		} else {
714fcf3ce44SJohn Forte 			(void) sprintf(buf,
715fcf3ce44SJohn Forte 			    "%8d.%02d: %6d:[%2X.%04X]%s:%7s:%4d\n",
716291a2b48SSukumar Swaminathan 			    secs, hsecs, entry->id, entry->fileno,
717291a2b48SSukumar Swaminathan 			    entry->line, driver, level, msg->id);
718fcf3ce44SJohn Forte 		}
719fcf3ce44SJohn Forte 	}
720fcf3ce44SJohn Forte 
721fcf3ce44SJohn Forte 	bzero(buffer, MAX_LOG_MSG_LENGTH);
722fcf3ce44SJohn Forte 	buflen = strlen(buf);
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	if (buflen > (MAX_LOG_MSG_LENGTH - 1)) {
725fcf3ce44SJohn Forte 		(void) strncpy(buffer, buf, (MAX_LOG_MSG_LENGTH - 2));
726fcf3ce44SJohn Forte 		buffer[MAX_LOG_MSG_LENGTH - 2] = '\n';
727fcf3ce44SJohn Forte 	} else {
728fcf3ce44SJohn Forte 		(void) strncpy(buffer, buf, buflen);
729fcf3ce44SJohn Forte 	}
730fcf3ce44SJohn Forte 
731fcf3ce44SJohn Forte 	return;
732fcf3ce44SJohn Forte 
733*82527734SSukumar Swaminathan } /* emlxs_msg_sprintf() */
734