2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 2N/A * SES Log reader library 2N/A * This library is responsible for accessing the SES log at the target address, 2N/A * formatting and returning any log entries found. 2N/A * The data will be returned in an nvlist_t structure allocated here. 2N/A * open the device with given device name 2N/A * Initialize scsi struct 2N/A * set control cdb of scsi structure 2N/A * initialize sense data 2N/A * Initialize data going to device 2N/A * Executes SCSI command(or at least forwards it to lower layers). 2N/A * Read log from device 2N/A * Invokes a SCSI LOG SENSE command. 2N/A * SG_LIB_CAT_INVALID_OP -> Log Sense not supported, 2N/A * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 2N/A * SG_LIB_CAT_NOT_READY -> device not ready, 2N/A * -1 -> other failure 2N/A /* pc = 1, pg_code = 0x7 (logs page) */ 2N/A /* (((pc << 6) & 0xc0) | (pg_code & 0x3f)) = 0x47; */ 2N/A /* pc = 1 current values */ 2N/A * Save the logs by walking through the entries in the response buffer. 2N/A * resp buffer looks like: 2N/A * +=====-========-========-========-========-========-========-========-=====+ 2N/A * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 2N/A * |Byte | | | | | | | | | 2N/A * |=====+====================================================================| 2N/A * | 0 | reserved | page code | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * |-----+--------------------------------------------------------------------| 2N/A * | 2 |(MSB) Page Length(n-3) | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * | 4 | Log Parameter (First)(Length X) | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * |n-y+1| Log Parameter (Last)(Length y) | 2N/A * +==========================================================================+ 2N/A * Log parameter field looks like: 2N/A * +=====-========-========-========-========-========-========-========-=====+ 2N/A * | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 2N/A * |Byte | | | | | | | | | 2N/A * |=====+====================================================================| 2N/A * | 0 |(MSB) Parameter Code | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * | 2 | DU | DS | TSD | ETC | TMC | LBIN | LP | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * | 3 | Parameter Length(n-3) | 2N/A * |-----+--------------------------------------------------------------------| 2N/A * | 4 | Parameter Values | 2N/A * |-----+--------------------------------------------------------------------| 2N/A unsigned char *
log_str_ptr;
/* ptr to ascii str returend by expander */ 2N/A * Bytes 2 and 3 of response buffer contain the page length of 2N/A * the log entries returned. 2N/A * Initialize log parameter pointer to point to first log entry. 2N/A * The resp includes 4 bytes of header info and then log entries 2N/A * If multiple heads are reading the logs, it is possible that we 2N/A * could be re-reading some of the same log entries plus some 2N/A * new additional entries. Check to see if any entries in this read 2N/A * contain the same log entry as the last entry we read last time. 2N/A * We have a valid log entry from a previous read log 2N/A * Start walking each log entry in response buffer looking for 2N/A * a duplicate entry. 2N/A * Calculate log entry length 2N/A * Log param ptr [3] contains the log length minus the 2N/A * header info which is 4 bytes so add that in. 2N/A * Only header information in this entry 2N/A * process next log entry 2N/A * initialize log_str_ptr to point to string info 2N/A * returned by expander 2N/A * first 4 bytes of log parameter contains 2N/A * 2 bytes of parameter code, 1 byte of Control data 2N/A * and 1 byte for parameter length. Log string begins 2N/A * after that so add 4 to log param ptr. 2N/A * Check to see if this is the 2N/A /* Found an exact match */ 2N/A * Either there was no log data or we have 2N/A * already read these log entries. 2N/A /* Grab memory to return logs with */ 2N/A /* Couldn't alloc memory for nvlist */ 2N/A * Start saving new log entries 2N/A * Walk the log data adding any new entries 2N/A * Calculate log entry length 2N/A * Log ptr [3] contains the log length minus the header info 2N/A * which is 4 bytes so add that in 2N/A /* Only header information in this entry */ 2N/A /* process next log entry */ 2N/A * initialize log_str_ptr to point to string info of the log 2N/A * entry. First 4 bytes of log entry contains param code, 2N/A * control byte, and length. Log string starts after that. 2N/A * Format of log str is as follows 2N/A * "%8x %8x %8x %8x %8x %8x %8x %8x", 2N/A * log_entry.log_word3, log_entry.log_word4 2N/A * following example has extra spaces removed to fit in 80 char 2N/A * 40004 0 42d5f5fe 185b 630002 fd0800 50800207 e482813 2N/A /* Add this entry to the nvlist log data */ 2N/A /* Couldn't alloc space, return error */ 2N/A /* Error adding string, return error */ 2N/A /* Error adding string, return error */ 2N/A /* Error adding srtring, return error */ 2N/A /* Error adding nvlist, return error */ 2N/A /* Update the last log entry string with last one read */ 2N/A/* Setup struct to send command to device */ 2N/A * Invokes a SCSI MODE SENSE(10) command. 2N/A * SG_LIB_CAT_INVALID_OP -> invalid opcode 2N/A * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb 2N/A * SG_LIB_CAT_NOT_READY -> device not ready 2N/A * -1 -> other failure 2N/A * Invokes a SCSI MODE SELECT(10) command. 2N/A * SG_LIB_CAT_INVALID_OP for invalid opcode 2N/A * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 2N/A * SG_LIB_CAT_NOT_READY -> device not ready, 2N/A * -1 -> other failure 2N/A * modesCmdBlk 2 equal 0 PC 0 return current page code 0 return 2N/A * MODE SENSE 10 commands yield a response that has block descriptors followed 2N/A * by mode pages. In most cases users are interested in the first mode page. 2N/A * This function returns the(byte) offset of the start of the first mode page. 2N/A * Returns >= 0 is successful or -1 if failure. If there is a failure 2N/A * a message is written to err_buff. 2N/A * return data looks like: 2N/A * Table 92 - Mode parameter header(10) 2N/A * ---------------------------------------------------------- 2N/A * ---------------------------------------------------------- 2N/A * ---------------------------------------------------------- 2N/A * 3 Device-specific parameter 2N/A * ---------------------------------------------------------- 2N/A * ---------------------------------------------------------- 2N/A * ---------------------------------------------------------- 2N/A * 6 MSB block descriptor length 2N/A * 7 LSB block descriptor length 2N/A * ---------------------------------------------------------- 2N/A * block desciptors.... 2N/A * ----------------------- 2N/A * 0 : ps Reserved : page Code 2N/A * 1 : Page Length(n-1) 2N/A * 2-N Mode parameters 2N/A /* Too short of a response buffer */ 2N/A /* LongLBA doesn't change this calculation */ 2N/A /* Given response length to small */ 2N/A /* Calculated response length too small */ 2N/A/* fill in unique host id */ 2N/A * The appliance kit contains all the information for the AK systems. 2N/A * To see the values run: 2N/A /* If here, didn't get unique host id from AK */ 2N/A * convert nanosecond time to seconds 2N/A /* Add 5 minutes to poll time to allow for data retrieval time */ 2N/A * retrieve the last read sequence number from the last 2N/A * We have a valid log entry from a previous read log 2N/A /* do MODE SENSE to fetch current values */ 2N/A /* Error during mode sense */ 2N/A /* Setup mode Select to clear logs */ 2N/A /* Mode page offset error */ 2N/A /* Data length to large */ 2N/A /* Content length not correct */ 2N/A /* reference model doesn't have use subpage format bit set */ 2N/A /* Even though it should have */ 2N/A /* don't send the command */ 2N/A * Gather data from given device. 2N/A /* Failed to open device */ 2N/A resp_len =
0x8000;
/* Maximum size available to read */ 2N/A /* Some sort of Error during read of logs */ 2N/A /* Clear the logs */ 2N/A * Access the SES target identified by the indicated path. Read the logs 2N/A * and return them in a nvlist. 2N/A /* Initialize return data */ 2N/A /* NULL Target path, return error */ 2N/A /* Try to find a valid path */ 2N/A /* Couldn't find a path that exists */ 2N/A /* Update the size of log entries being returned */