mpt_evt.c revision 215046
157416Smarkm/*-
257416Smarkm * Copyright (c) 2008 Yahoo!, Inc.
357416Smarkm * All rights reserved.
457416Smarkm * Written by: John Baldwin <jhb@FreeBSD.org>
557416Smarkm *
657416Smarkm * Redistribution and use in source and binary forms, with or without
757416Smarkm * modification, are permitted provided that the following conditions
857416Smarkm * are met:
957416Smarkm * 1. Redistributions of source code must retain the above copyright
1057416Smarkm *    notice, this list of conditions and the following disclaimer.
1157416Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1257416Smarkm *    notice, this list of conditions and the following disclaimer in the
1357416Smarkm *    documentation and/or other materials provided with the distribution.
1457416Smarkm * 3. Neither the name of the author nor the names of any co-contributors
1557416Smarkm *    may be used to endorse or promote products derived from this software
1657416Smarkm *    without specific prior written permission.
1757416Smarkm *
1857416Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1957416Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2057416Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2157416Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2257416Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2357416Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2457416Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2557416Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2657416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2757416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2857416Smarkm * SUCH DAMAGE.
2957416Smarkm */
3057416Smarkm
3157416Smarkm#include <sys/cdefs.h>
3257416Smarkm__RCSID("$FreeBSD: head/usr.sbin/mptutil/mpt_evt.c 215046 2010-11-09 19:28:06Z jhb $");
3357416Smarkm
3457416Smarkm#include <sys/param.h>
3557416Smarkm#include <sys/errno.h>
3657416Smarkm#include <ctype.h>
3757416Smarkm#include <err.h>
3857416Smarkm#include <stdio.h>
3990926Snectar#include <stdlib.h>
4057416Smarkm#include <unistd.h>
4157416Smarkm#include "mptutil.h"
4257416Smarkm
4357416Smarkmstatic CONFIG_PAGE_LOG_0 *
4457416Smarkmmpt_get_events(int fd, U16 *IOCStatus)
4557416Smarkm{
4657416Smarkm
4757416Smarkm	return (mpt_read_extended_config_page(fd, MPI_CONFIG_EXTPAGETYPE_LOG,
4857416Smarkm	    0, 0, 0, IOCStatus));
4957416Smarkm}
5057416Smarkm
5157416Smarkm/*
5257416Smarkm *          1         2         3         4         5         6         7
5357416Smarkm * 1234567890123456789012345678901234567890123456789012345678901234567890
5457416Smarkm * < ID> < time > <ty> <X XX XX XX XX XX XX XX XX XX XX XX XX XX |..............|
5557416Smarkm *  ID     Time   Type Log Data
5657416Smarkm */
5757416Smarkmstatic void
5857416Smarkmmpt_print_event(MPI_LOG_0_ENTRY *entry, int verbose)
5957416Smarkm{
6057416Smarkm	int i;
6157416Smarkm
6257416Smarkm	printf("%5d %7ds %4x ", entry->LogSequence, entry->TimeStamp,
6357416Smarkm	    entry->LogEntryQualifier);
6457416Smarkm	for (i = 0; i < 14; i++)
6557416Smarkm		printf("%02x ", entry->LogData[i]);
6657416Smarkm	printf("|");
6757416Smarkm	for (i = 0; i < 14; i++)
6857416Smarkm		printf("%c", isprint(entry->LogData[i]) ? entry->LogData[i] :
6957416Smarkm		    '.');
7057416Smarkm	printf("|\n");
7157416Smarkm	printf("                    ");
7257416Smarkm	for (i = 0; i < 14; i++)
7390926Snectar		printf("%02x ", entry->LogData[i + 14]);
7457416Smarkm	printf("|");
7557416Smarkm	for (i = 0; i < 14; i++)
7657416Smarkm		printf("%c", isprint(entry->LogData[i + 14]) ?
7757416Smarkm		    entry->LogData[i + 14] : '.');
7857416Smarkm	printf("|\n");
7957416Smarkm}
8057416Smarkm
8157416Smarkmstatic int
8257416Smarkmevent_compare(const void *first, const void *second)
8357416Smarkm{
8457416Smarkm	MPI_LOG_0_ENTRY * const *one;
8557416Smarkm	MPI_LOG_0_ENTRY * const *two;
8657416Smarkm
8757416Smarkm	one = first;
8890926Snectar	two = second;
8990926Snectar	return ((*one)->LogSequence - ((*two)->LogSequence));
9057416Smarkm}
9157416Smarkm
9257416Smarkmstatic int
9357416Smarkmshow_events(int ac, char **av)
9457416Smarkm{
9557416Smarkm	CONFIG_PAGE_LOG_0 *log;
9657416Smarkm	MPI_LOG_0_ENTRY **entries;
9757416Smarkm	int ch, error, fd, i, num_events, verbose;
9857416Smarkm
9957416Smarkm	fd = mpt_open(mpt_unit);
10057416Smarkm	if (fd < 0) {
10157416Smarkm		error = errno;
10257416Smarkm		warn("mpt_open");
10357416Smarkm		return (error);
10457416Smarkm	}
10557416Smarkm
10657416Smarkm	log = mpt_get_events(fd, NULL);
10757416Smarkm	if (log == NULL) {
10857416Smarkm		error = errno;
10957416Smarkm		warn("Failed to get event log info");
11057416Smarkm		return (error);
11157416Smarkm	}
11257416Smarkm
11357416Smarkm	/* Default settings. */
11457416Smarkm	verbose = 0;
11557416Smarkm
11657416Smarkm	/* Parse any options. */
11757416Smarkm	optind = 1;
11857416Smarkm	while ((ch = getopt(ac, av, "v")) != -1) {
11957416Smarkm		switch (ch) {
12057416Smarkm		case 'v':
12157416Smarkm			verbose = 1;
12257416Smarkm			break;
12357416Smarkm		case '?':
12457416Smarkm		default:
12557416Smarkm			return (EINVAL);
12657416Smarkm		}
12757416Smarkm	}
12857416Smarkm	ac -= optind;
12957416Smarkm	av += optind;
13057416Smarkm
13157416Smarkm	/* Build a list of valid entries and sort them by sequence. */
13257416Smarkm	entries = malloc(sizeof(MPI_LOG_0_ENTRY *) * log->NumLogEntries);
13357416Smarkm	if (entries == NULL)
13457416Smarkm		return (ENOMEM);
13557416Smarkm	num_events = 0;
13657416Smarkm	for (i = 0; i < log->NumLogEntries; i++) {
13757416Smarkm		if (log->LogEntry[i].LogEntryQualifier ==
13857416Smarkm		    MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED)
13957416Smarkm			continue;
14057416Smarkm		entries[num_events] = &log->LogEntry[i];
14157416Smarkm		num_events++;
14257416Smarkm	}
14357416Smarkm
14457416Smarkm	qsort(entries, num_events, sizeof(MPI_LOG_0_ENTRY *), event_compare);
14557416Smarkm
14657416Smarkm	if (num_events == 0)
14757416Smarkm		printf("Event log is empty\n");
14857416Smarkm	else {
14957416Smarkm		printf(" ID     Time   Type Log Data\n");
15057416Smarkm		for (i = 0; i < num_events; i++)
15157416Smarkm			mpt_print_event(entries[i], verbose);
15257416Smarkm	}
15357416Smarkm
15457416Smarkm	free(entries);
15557416Smarkm	close(fd);
15657416Smarkm
15757416Smarkm	return (0);
15857416Smarkm}
15957416SmarkmMPT_COMMAND(show, events, show_events);
16057416Smarkm