1196212Sscottl/*- 2196212Sscottl * Copyright (c) 2008 Yahoo!, Inc. 3196212Sscottl * All rights reserved. 4196212Sscottl * Written by: John Baldwin <jhb@FreeBSD.org> 5196212Sscottl * 6196212Sscottl * Redistribution and use in source and binary forms, with or without 7196212Sscottl * modification, are permitted provided that the following conditions 8196212Sscottl * are met: 9196212Sscottl * 1. Redistributions of source code must retain the above copyright 10196212Sscottl * notice, this list of conditions and the following disclaimer. 11196212Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12196212Sscottl * notice, this list of conditions and the following disclaimer in the 13196212Sscottl * documentation and/or other materials provided with the distribution. 14196212Sscottl * 3. Neither the name of the author nor the names of any co-contributors 15196212Sscottl * may be used to endorse or promote products derived from this software 16196212Sscottl * without specific prior written permission. 17196212Sscottl * 18196212Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19196212Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20196212Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21196212Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22196212Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23196212Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24196212Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25196212Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26196212Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27196212Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28196212Sscottl * SUCH DAMAGE. 29196212Sscottl */ 30196212Sscottl 31196212Sscottl#include <sys/cdefs.h> 32196212Sscottl__RCSID("$FreeBSD$"); 33196212Sscottl 34196212Sscottl#include <sys/param.h> 35196212Sscottl#include <sys/errno.h> 36196212Sscottl#include <ctype.h> 37196212Sscottl#include <err.h> 38196212Sscottl#include <stdio.h> 39196212Sscottl#include <stdlib.h> 40196212Sscottl#include <unistd.h> 41196212Sscottl#include "mptutil.h" 42196212Sscottl 43196212Sscottlstatic CONFIG_PAGE_LOG_0 * 44196212Sscottlmpt_get_events(int fd, U16 *IOCStatus) 45196212Sscottl{ 46196212Sscottl 47196212Sscottl return (mpt_read_extended_config_page(fd, MPI_CONFIG_EXTPAGETYPE_LOG, 48196212Sscottl 0, 0, 0, IOCStatus)); 49196212Sscottl} 50196212Sscottl 51196212Sscottl/* 52196212Sscottl * 1 2 3 4 5 6 7 53196212Sscottl * 1234567890123456789012345678901234567890123456789012345678901234567890 54196212Sscottl * < ID> < time > <ty> <X XX XX XX XX XX XX XX XX XX XX XX XX XX |..............| 55196212Sscottl * ID Time Type Log Data 56196212Sscottl */ 57196212Sscottlstatic void 58196212Sscottlmpt_print_event(MPI_LOG_0_ENTRY *entry, int verbose) 59196212Sscottl{ 60196212Sscottl int i; 61196212Sscottl 62196212Sscottl printf("%5d %7ds %4x ", entry->LogSequence, entry->TimeStamp, 63196212Sscottl entry->LogEntryQualifier); 64196212Sscottl for (i = 0; i < 14; i++) 65196212Sscottl printf("%02x ", entry->LogData[i]); 66196212Sscottl printf("|"); 67196212Sscottl for (i = 0; i < 14; i++) 68196212Sscottl printf("%c", isprint(entry->LogData[i]) ? entry->LogData[i] : 69196212Sscottl '.'); 70196212Sscottl printf("|\n"); 71196212Sscottl printf(" "); 72196212Sscottl for (i = 0; i < 14; i++) 73196212Sscottl printf("%02x ", entry->LogData[i + 14]); 74196212Sscottl printf("|"); 75196212Sscottl for (i = 0; i < 14; i++) 76196212Sscottl printf("%c", isprint(entry->LogData[i + 14]) ? 77196212Sscottl entry->LogData[i + 14] : '.'); 78196212Sscottl printf("|\n"); 79196212Sscottl} 80196212Sscottl 81196212Sscottlstatic int 82196212Sscottlevent_compare(const void *first, const void *second) 83196212Sscottl{ 84196212Sscottl MPI_LOG_0_ENTRY * const *one; 85196212Sscottl MPI_LOG_0_ENTRY * const *two; 86196212Sscottl 87196212Sscottl one = first; 88196212Sscottl two = second; 89196212Sscottl return ((*one)->LogSequence - ((*two)->LogSequence)); 90196212Sscottl} 91196212Sscottl 92196212Sscottlstatic int 93196212Sscottlshow_events(int ac, char **av) 94196212Sscottl{ 95196212Sscottl CONFIG_PAGE_LOG_0 *log; 96196212Sscottl MPI_LOG_0_ENTRY **entries; 97215046Sjhb int ch, error, fd, i, num_events, verbose; 98196212Sscottl 99196212Sscottl fd = mpt_open(mpt_unit); 100196212Sscottl if (fd < 0) { 101215046Sjhb error = errno; 102196212Sscottl warn("mpt_open"); 103215046Sjhb return (error); 104196212Sscottl } 105196212Sscottl 106196212Sscottl log = mpt_get_events(fd, NULL); 107196212Sscottl if (log == NULL) { 108215046Sjhb error = errno; 109196212Sscottl warn("Failed to get event log info"); 110215046Sjhb return (error); 111196212Sscottl } 112196212Sscottl 113196212Sscottl /* Default settings. */ 114196212Sscottl verbose = 0; 115196212Sscottl 116196212Sscottl /* Parse any options. */ 117196212Sscottl optind = 1; 118196212Sscottl while ((ch = getopt(ac, av, "v")) != -1) { 119196212Sscottl switch (ch) { 120196212Sscottl case 'v': 121196212Sscottl verbose = 1; 122196212Sscottl break; 123196212Sscottl case '?': 124196212Sscottl default: 125196212Sscottl return (EINVAL); 126196212Sscottl } 127196212Sscottl } 128196212Sscottl ac -= optind; 129196212Sscottl av += optind; 130196212Sscottl 131196212Sscottl /* Build a list of valid entries and sort them by sequence. */ 132196212Sscottl entries = malloc(sizeof(MPI_LOG_0_ENTRY *) * log->NumLogEntries); 133215046Sjhb if (entries == NULL) 134215046Sjhb return (ENOMEM); 135196212Sscottl num_events = 0; 136196212Sscottl for (i = 0; i < log->NumLogEntries; i++) { 137196212Sscottl if (log->LogEntry[i].LogEntryQualifier == 138196212Sscottl MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED) 139196212Sscottl continue; 140196212Sscottl entries[num_events] = &log->LogEntry[i]; 141196212Sscottl num_events++; 142196212Sscottl } 143196212Sscottl 144196212Sscottl qsort(entries, num_events, sizeof(MPI_LOG_0_ENTRY *), event_compare); 145196212Sscottl 146196212Sscottl if (num_events == 0) 147196212Sscottl printf("Event log is empty\n"); 148196212Sscottl else { 149196212Sscottl printf(" ID Time Type Log Data\n"); 150196212Sscottl for (i = 0; i < num_events; i++) 151196212Sscottl mpt_print_event(entries[i], verbose); 152196212Sscottl } 153196212Sscottl 154196212Sscottl free(entries); 155196212Sscottl close(fd); 156196212Sscottl 157196212Sscottl return (0); 158196212Sscottl} 159196212SscottlMPT_COMMAND(show, events, show_events); 160