1196200Sscottl/*- 2196200Sscottl * Copyright (c) 2008, 2009 Yahoo!, Inc. 3196200Sscottl * All rights reserved. 4196200Sscottl * 5196200Sscottl * Redistribution and use in source and binary forms, with or without 6196200Sscottl * modification, are permitted provided that the following conditions 7196200Sscottl * are met: 8196200Sscottl * 1. Redistributions of source code must retain the above copyright 9196200Sscottl * notice, this list of conditions and the following disclaimer. 10196200Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11196200Sscottl * notice, this list of conditions and the following disclaimer in the 12196200Sscottl * documentation and/or other materials provided with the distribution. 13196200Sscottl * 3. The names of the authors may not be used to endorse or promote 14196200Sscottl * products derived from this software without specific prior written 15196200Sscottl * permission. 16196200Sscottl * 17196200Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18196200Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19196200Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20196200Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21196200Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22196200Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23196200Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24196200Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25196200Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26196200Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27196200Sscottl * SUCH DAMAGE. 28196200Sscottl * 29196200Sscottl * $FreeBSD: releng/10.3/usr.sbin/mfiutil/mfi_show.c 266400 2014-05-18 15:28:25Z jhb $ 30196200Sscottl */ 31196200Sscottl 32196200Sscottl#include <sys/types.h> 33196200Sscottl#include <sys/errno.h> 34196200Sscottl#include <err.h> 35237259Seadler#include <fcntl.h> 36196200Sscottl#include <libutil.h> 37196200Sscottl#include <stdio.h> 38196200Sscottl#include <stdlib.h> 39196200Sscottl#include <string.h> 40196200Sscottl#include <unistd.h> 41196200Sscottl#include "mfiutil.h" 42196200Sscottl 43251516Ssbrunostatic const char* foreign_state = " (FOREIGN)"; 44251516Ssbruno 45196200SscottlMFI_TABLE(top, show); 46196200Sscottl 47251516Ssbrunovoid 48196200Sscottlformat_stripe(char *buf, size_t buflen, uint8_t stripe) 49196200Sscottl{ 50196200Sscottl 51196200Sscottl humanize_number(buf, buflen, (1 << stripe) * 512, "", HN_AUTOSCALE, 52196200Sscottl HN_B | HN_NOSPACE); 53196200Sscottl} 54196200Sscottl 55196200Sscottlstatic int 56237260Seadlershow_adapter(int ac, char **av __unused) 57196200Sscottl{ 58196200Sscottl struct mfi_ctrl_info info; 59196200Sscottl char stripe[5]; 60214396Sjhb int error, fd, comma; 61196200Sscottl 62196200Sscottl if (ac != 1) { 63196200Sscottl warnx("show adapter: extra arguments"); 64196200Sscottl return (EINVAL); 65196200Sscottl } 66196200Sscottl 67237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 68196200Sscottl if (fd < 0) { 69214396Sjhb error = errno; 70196200Sscottl warn("mfi_open"); 71214396Sjhb return (error); 72196200Sscottl } 73196200Sscottl 74196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 75214396Sjhb error = errno; 76196200Sscottl warn("Failed to get controller info"); 77222899Sbz close(fd); 78214396Sjhb return (error); 79196200Sscottl } 80196200Sscottl printf("mfi%d Adapter:\n", mfi_unit); 81196200Sscottl printf(" Product Name: %.80s\n", info.product_name); 82196200Sscottl printf(" Serial Number: %.32s\n", info.serial_number); 83196200Sscottl if (info.package_version[0] != '\0') 84196200Sscottl printf(" Firmware: %s\n", info.package_version); 85196200Sscottl printf(" RAID Levels:"); 86196200Sscottl#ifdef DEBUG 87196200Sscottl printf(" (%#x)", info.raid_levels); 88196200Sscottl#endif 89196200Sscottl comma = 0; 90196200Sscottl if (info.raid_levels & MFI_INFO_RAID_0) { 91196200Sscottl printf(" JBOD, RAID0"); 92196200Sscottl comma = 1; 93196200Sscottl } 94196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1) { 95196200Sscottl printf("%s RAID1", comma ? "," : ""); 96196200Sscottl comma = 1; 97196200Sscottl } 98196200Sscottl if (info.raid_levels & MFI_INFO_RAID_5) { 99196200Sscottl printf("%s RAID5", comma ? "," : ""); 100196200Sscottl comma = 1; 101196200Sscottl } 102196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1E) { 103196200Sscottl printf("%s RAID1E", comma ? "," : ""); 104196200Sscottl comma = 1; 105196200Sscottl } 106196200Sscottl if (info.raid_levels & MFI_INFO_RAID_6) { 107196200Sscottl printf("%s RAID6", comma ? "," : ""); 108196200Sscottl comma = 1; 109196200Sscottl } 110196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) == 111196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) { 112196200Sscottl printf("%s RAID10", comma ? "," : ""); 113196200Sscottl comma = 1; 114196200Sscottl } 115196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) == 116196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) { 117196200Sscottl printf("%s RAID50", comma ? "," : ""); 118196200Sscottl comma = 1; 119196200Sscottl } 120196200Sscottl printf("\n"); 121196200Sscottl printf(" Battery Backup: "); 122196200Sscottl if (info.hw_present & MFI_INFO_HW_BBU) 123196200Sscottl printf("present\n"); 124196200Sscottl else 125196200Sscottl printf("not present\n"); 126196200Sscottl if (info.hw_present & MFI_INFO_HW_NVRAM) 127196200Sscottl printf(" NVRAM: %uK\n", info.nvram_size); 128196200Sscottl printf(" Onboard Memory: %uM\n", info.memory_size); 129196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.min); 130196200Sscottl printf(" Minimum Stripe: %s\n", stripe); 131196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.max); 132196200Sscottl printf(" Maximum Stripe: %s\n", stripe); 133196200Sscottl 134196200Sscottl close(fd); 135196200Sscottl 136196200Sscottl return (0); 137196200Sscottl} 138196200SscottlMFI_COMMAND(show, adapter, show_adapter); 139196200Sscottl 140196200Sscottlstatic int 141237260Seadlershow_battery(int ac, char **av __unused) 142196200Sscottl{ 143196200Sscottl struct mfi_bbu_capacity_info cap; 144196200Sscottl struct mfi_bbu_design_info design; 145249257Smarkj struct mfi_bbu_properties props; 146219717Sjhb struct mfi_bbu_status stat; 147196200Sscottl uint8_t status; 148249257Smarkj int comma, error, fd, show_capacity, show_props; 149249257Smarkj char buf[32]; 150196200Sscottl 151196200Sscottl if (ac != 1) { 152196200Sscottl warnx("show battery: extra arguments"); 153196200Sscottl return (EINVAL); 154196200Sscottl } 155196200Sscottl 156237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 157196200Sscottl if (fd < 0) { 158214396Sjhb error = errno; 159196200Sscottl warn("mfi_open"); 160214396Sjhb return (error); 161196200Sscottl } 162196200Sscottl 163196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap, 164196200Sscottl sizeof(cap), NULL, 0, &status) < 0) { 165214396Sjhb error = errno; 166196200Sscottl warn("Failed to get capacity info"); 167222899Sbz close(fd); 168214396Sjhb return (error); 169196200Sscottl } 170225798Semaste if (status == MFI_STAT_NO_HW_PRESENT) { 171225798Semaste printf("mfi%d: No battery present\n", mfi_unit); 172225798Semaste close(fd); 173225798Semaste return (0); 174225798Semaste } 175225798Semaste show_capacity = (status == MFI_STAT_OK); 176196200Sscottl 177196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design, 178196200Sscottl sizeof(design), NULL, 0, NULL) < 0) { 179214396Sjhb error = errno; 180196200Sscottl warn("Failed to get design info"); 181222899Sbz close(fd); 182214396Sjhb return (error); 183196200Sscottl } 184196200Sscottl 185219717Sjhb if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_STATUS, &stat, sizeof(stat), 186219717Sjhb NULL, 0, NULL) < 0) { 187219722Sjhb error = errno; 188219717Sjhb warn("Failed to get status"); 189222899Sbz close(fd); 190219722Sjhb return (error); 191219717Sjhb } 192219717Sjhb 193249257Smarkj if (mfi_bbu_get_props(fd, &props, &status) < 0) { 194249257Smarkj error = errno; 195249257Smarkj warn("Failed to get properties"); 196249257Smarkj close(fd); 197249257Smarkj return (error); 198249257Smarkj } 199249257Smarkj show_props = (status == MFI_STAT_OK); 200249257Smarkj 201196200Sscottl printf("mfi%d: Battery State:\n", mfi_unit); 202219717Sjhb printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, 203196200Sscottl design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); 204219717Sjhb printf(" Serial Number: %d\n", design.serial_number); 205219717Sjhb printf(" Manufacturer: %s\n", design.mfg_name); 206219717Sjhb printf(" Model: %s\n", design.device_name); 207219717Sjhb printf(" Chemistry: %s\n", design.device_chemistry); 208219717Sjhb printf(" Design Capacity: %d mAh\n", design.design_capacity); 209225798Semaste if (show_capacity) { 210225798Semaste printf(" Full Charge Capacity: %d mAh\n", 211225798Semaste cap.full_charge_capacity); 212225798Semaste printf(" Current Capacity: %d mAh\n", 213225798Semaste cap.remaining_capacity); 214225798Semaste printf(" Charge Cycles: %d\n", cap.cycle_count); 215225798Semaste printf(" Current Charge: %d%%\n", cap.relative_charge); 216225798Semaste } 217219717Sjhb printf(" Design Voltage: %d mV\n", design.design_voltage); 218219717Sjhb printf(" Current Voltage: %d mV\n", stat.voltage); 219219717Sjhb printf(" Temperature: %d C\n", stat.temperature); 220249257Smarkj if (show_props) { 221249257Smarkj mfi_autolearn_period(props.auto_learn_period, buf, sizeof(buf)); 222249257Smarkj printf(" Autolearn period: %s\n", buf); 223249257Smarkj if (props.auto_learn_mode != 0) 224249257Smarkj snprintf(buf, sizeof(buf), "never"); 225249257Smarkj else 226249257Smarkj mfi_next_learn_time(props.next_learn_time, buf, 227249257Smarkj sizeof(buf)); 228249257Smarkj printf(" Next learn time: %s\n", buf); 229249257Smarkj printf(" Learn delay interval: %u hour%s\n", 230249257Smarkj props.learn_delay_interval, 231249257Smarkj props.learn_delay_interval != 1 ? "s" : ""); 232249257Smarkj mfi_autolearn_mode(props.auto_learn_mode, buf, sizeof(buf)); 233249257Smarkj printf(" Autolearn mode: %s\n", buf); 234249257Smarkj if (props.bbu_mode != 0) 235249257Smarkj printf(" BBU Mode: %d\n", props.bbu_mode); 236249257Smarkj } 237219717Sjhb printf(" Status:"); 238219717Sjhb comma = 0; 239219717Sjhb if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) { 240219717Sjhb printf(" PACK_MISSING"); 241219717Sjhb comma = 1; 242219717Sjhb } 243219717Sjhb if (stat.fw_status & MFI_BBU_STATE_VOLTAGE_LOW) { 244219717Sjhb printf("%s VOLTAGE_LOW", comma ? "," : ""); 245219717Sjhb comma = 1; 246219717Sjhb } 247219717Sjhb if (stat.fw_status & MFI_BBU_STATE_TEMPERATURE_HIGH) { 248219717Sjhb printf("%s TEMPERATURE_HIGH", comma ? "," : ""); 249219717Sjhb comma = 1; 250219717Sjhb } 251219717Sjhb if (stat.fw_status & MFI_BBU_STATE_CHARGE_ACTIVE) { 252219717Sjhb printf("%s CHARGING", comma ? "," : ""); 253219717Sjhb comma = 1; 254219717Sjhb } 255219717Sjhb if (stat.fw_status & MFI_BBU_STATE_DISCHARGE_ACTIVE) { 256219717Sjhb printf("%s DISCHARGING", comma ? "," : ""); 257235635Ssbruno comma = 1; 258219717Sjhb } 259235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_REQ) { 260235635Ssbruno printf("%s LEARN_CYCLE_REQUESTED", comma ? "," : ""); 261235635Ssbruno comma = 1; 262235635Ssbruno } 263235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_ACTIVE) { 264235635Ssbruno printf("%s LEARN_CYCLE_ACTIVE", comma ? "," : ""); 265235635Ssbruno comma = 1; 266235635Ssbruno } 267235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_FAIL) { 268235635Ssbruno printf("%s LEARN_CYCLE_FAIL", comma ? "," : ""); 269235635Ssbruno comma = 1; 270235635Ssbruno } 271235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_TIMEOUT) { 272235635Ssbruno printf("%s LEARN_CYCLE_TIMEOUT", comma ? "," : ""); 273235635Ssbruno comma = 1; 274235635Ssbruno } 275235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_I2C_ERR_DETECT) { 276235635Ssbruno printf("%s I2C_ERROR_DETECT", comma ? "," : ""); 277235635Ssbruno comma = 1; 278235635Ssbruno } 279235635Ssbruno 280219717Sjhb if (!comma) 281219717Sjhb printf(" normal"); 282219717Sjhb printf("\n"); 283219717Sjhb switch (stat.battery_type) { 284219717Sjhb case MFI_BBU_TYPE_BBU: 285219717Sjhb printf(" State of Health: %s\n", 286219717Sjhb stat.detail.bbu.is_SOH_good ? "good" : "bad"); 287219717Sjhb break; 288219717Sjhb } 289196200Sscottl 290196200Sscottl close(fd); 291196200Sscottl 292196200Sscottl return (0); 293196200Sscottl} 294196200SscottlMFI_COMMAND(show, battery, show_battery); 295196200Sscottl 296251516Ssbrunovoid 297196200Sscottlprint_ld(struct mfi_ld_info *info, int state_len) 298196200Sscottl{ 299196200Sscottl struct mfi_ld_params *params = &info->ld_config.params; 300196200Sscottl const char *level; 301196200Sscottl char size[6], stripe[5]; 302196200Sscottl 303196200Sscottl humanize_number(size, sizeof(size), info->size * 512, 304196200Sscottl "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 305196200Sscottl format_stripe(stripe, sizeof(stripe), 306196200Sscottl info->ld_config.params.stripe_size); 307196200Sscottl level = mfi_raid_level(params->primary_raid_level, 308196200Sscottl params->secondary_raid_level); 309196200Sscottl if (state_len > 0) 310196200Sscottl printf("(%6s) %-8s %6s %-*s", size, level, stripe, state_len, 311196200Sscottl mfi_ldstate(params->state)); 312196200Sscottl else 313196200Sscottl printf("(%s) %s %s %s", size, level, stripe, 314196200Sscottl mfi_ldstate(params->state)); 315196200Sscottl} 316196200Sscottl 317251516Ssbrunovoid 318223345Sbzprint_pd(struct mfi_pd_info *info, int state_len) 319196200Sscottl{ 320196200Sscottl const char *s; 321251516Ssbruno char buf[256]; 322196200Sscottl 323260324Ssbruno humanize_number(buf, 6, info->raw_size * 512, "", 324196200Sscottl HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 325196200Sscottl printf("(%6s) ", buf); 326251516Ssbruno if (info->state.ddf.v.pd_type.is_foreign) { 327251516Ssbruno sprintf(buf, "%s%s", mfi_pdstate(info->fw_state), foreign_state); 328251516Ssbruno s = buf; 329251516Ssbruno } else 330251516Ssbruno s = mfi_pdstate(info->fw_state); 331196200Sscottl if (state_len > 0) 332251516Ssbruno printf("%-*s", state_len, s); 333196200Sscottl else 334251516Ssbruno printf("%s",s); 335196200Sscottl s = mfi_pd_inq_string(info); 336196200Sscottl if (s != NULL) 337196200Sscottl printf(" %s", s); 338196200Sscottl} 339196200Sscottl 340196200Sscottlstatic int 341237260Seadlershow_config(int ac, char **av __unused) 342196200Sscottl{ 343196200Sscottl struct mfi_config_data *config; 344196200Sscottl struct mfi_array *ar; 345196200Sscottl struct mfi_ld_config *ld; 346196200Sscottl struct mfi_spare *sp; 347196200Sscottl struct mfi_ld_info linfo; 348196200Sscottl struct mfi_pd_info pinfo; 349196200Sscottl uint16_t device_id; 350196200Sscottl char *p; 351214396Sjhb int error, fd, i, j; 352196200Sscottl 353196200Sscottl if (ac != 1) { 354196200Sscottl warnx("show config: extra arguments"); 355196200Sscottl return (EINVAL); 356196200Sscottl } 357196200Sscottl 358237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 359196200Sscottl if (fd < 0) { 360214396Sjhb error = errno; 361196200Sscottl warn("mfi_open"); 362214396Sjhb return (error); 363196200Sscottl } 364196200Sscottl 365196200Sscottl /* Get the config from the controller. */ 366196200Sscottl if (mfi_config_read(fd, &config) < 0) { 367214396Sjhb error = errno; 368196200Sscottl warn("Failed to get config"); 369222899Sbz close(fd); 370214396Sjhb return (error); 371196200Sscottl } 372196200Sscottl 373196200Sscottl /* Dump out the configuration. */ 374196200Sscottl printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n", 375196200Sscottl mfi_unit, config->array_count, config->log_drv_count, 376196200Sscottl config->spares_count); 377196200Sscottl p = (char *)config->array; 378196200Sscottl 379196200Sscottl for (i = 0; i < config->array_count; i++) { 380196200Sscottl ar = (struct mfi_array *)p; 381196200Sscottl printf(" array %u of %u drives:\n", ar->array_ref, 382196200Sscottl ar->num_drives); 383196200Sscottl for (j = 0; j < ar->num_drives; j++) { 384196200Sscottl device_id = ar->pd[j].ref.v.device_id; 385223345Sbz printf(" drive %s ", mfi_drive_name(NULL, 386223345Sbz device_id, 387223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 388223345Sbz if (device_id != 0xffff) { 389196200Sscottl if (mfi_pd_get_info(fd, device_id, &pinfo, 390196200Sscottl NULL) < 0) 391196200Sscottl printf("%s", 392196200Sscottl mfi_pdstate(ar->pd[j].fw_state)); 393196200Sscottl else 394223345Sbz print_pd(&pinfo, -1); 395196200Sscottl } 396225168Sbz printf("\n"); 397196200Sscottl } 398196200Sscottl p += config->array_size; 399196200Sscottl } 400196200Sscottl 401196200Sscottl for (i = 0; i < config->log_drv_count; i++) { 402196200Sscottl ld = (struct mfi_ld_config *)p; 403196200Sscottl printf(" volume %s ", 404196200Sscottl mfi_volume_name(fd, ld->properties.ld.v.target_id)); 405196200Sscottl if (mfi_ld_get_info(fd, ld->properties.ld.v.target_id, &linfo, 406196200Sscottl NULL) < 0) { 407196200Sscottl printf("%s %s", 408196200Sscottl mfi_raid_level(ld->params.primary_raid_level, 409196200Sscottl ld->params.secondary_raid_level), 410196200Sscottl mfi_ldstate(ld->params.state)); 411196200Sscottl } else 412196200Sscottl print_ld(&linfo, -1); 413196200Sscottl if (ld->properties.name[0] != '\0') 414196200Sscottl printf(" <%s>", ld->properties.name); 415196200Sscottl printf(" spans:\n"); 416196200Sscottl for (j = 0; j < ld->params.span_depth; j++) 417196200Sscottl printf(" array %u\n", ld->span[j].array_ref); 418196200Sscottl p += config->log_drv_size; 419196200Sscottl } 420196200Sscottl 421196200Sscottl for (i = 0; i < config->spares_count; i++) { 422196200Sscottl sp = (struct mfi_spare *)p; 423223345Sbz printf(" %s spare %s ", 424196200Sscottl sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" : 425223345Sbz "global", mfi_drive_name(NULL, sp->ref.v.device_id, 426223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 427196200Sscottl if (mfi_pd_get_info(fd, sp->ref.v.device_id, &pinfo, NULL) < 0) 428196200Sscottl printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE)); 429196200Sscottl else 430223345Sbz print_pd(&pinfo, -1); 431196200Sscottl if (sp->spare_type & MFI_SPARE_DEDICATED) { 432196200Sscottl printf(" backs:\n"); 433196200Sscottl for (j = 0; j < sp->array_count; j++) 434196200Sscottl printf(" array %u\n", sp->array_ref[j]); 435196200Sscottl } else 436196200Sscottl printf("\n"); 437196200Sscottl p += config->spares_size; 438196200Sscottl } 439222899Sbz free(config); 440196200Sscottl close(fd); 441196200Sscottl 442196200Sscottl return (0); 443196200Sscottl} 444196200SscottlMFI_COMMAND(show, config, show_config); 445196200Sscottl 446196200Sscottlstatic int 447237260Seadlershow_volumes(int ac, char **av __unused) 448196200Sscottl{ 449196200Sscottl struct mfi_ld_list list; 450196200Sscottl struct mfi_ld_info info; 451214396Sjhb int error, fd; 452196200Sscottl u_int i, len, state_len; 453196200Sscottl 454196200Sscottl if (ac != 1) { 455196200Sscottl warnx("show volumes: extra arguments"); 456196200Sscottl return (EINVAL); 457196200Sscottl } 458196200Sscottl 459237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 460196200Sscottl if (fd < 0) { 461214396Sjhb error = errno; 462196200Sscottl warn("mfi_open"); 463214396Sjhb return (error); 464196200Sscottl } 465196200Sscottl 466196200Sscottl /* Get the logical drive list from the controller. */ 467196200Sscottl if (mfi_ld_get_list(fd, &list, NULL) < 0) { 468214396Sjhb error = errno; 469196200Sscottl warn("Failed to get volume list"); 470222899Sbz close(fd); 471214396Sjhb return (error); 472196200Sscottl } 473196200Sscottl 474196200Sscottl /* List the volumes. */ 475196200Sscottl printf("mfi%d Volumes:\n", mfi_unit); 476196200Sscottl state_len = strlen("State"); 477196200Sscottl for (i = 0; i < list.ld_count; i++) { 478196200Sscottl len = strlen(mfi_ldstate(list.ld_list[i].state)); 479196200Sscottl if (len > state_len) 480196200Sscottl state_len = len; 481196200Sscottl } 482196200Sscottl printf(" Id Size Level Stripe "); 483196200Sscottl len = state_len - strlen("State"); 484196200Sscottl for (i = 0; i < (len + 1) / 2; i++) 485196200Sscottl printf(" "); 486196200Sscottl printf("State"); 487196200Sscottl for (i = 0; i < len / 2; i++) 488196200Sscottl printf(" "); 489196200Sscottl printf(" Cache Name\n"); 490196200Sscottl for (i = 0; i < list.ld_count; i++) { 491196200Sscottl if (mfi_ld_get_info(fd, list.ld_list[i].ld.v.target_id, &info, 492196200Sscottl NULL) < 0) { 493214396Sjhb error = errno; 494196200Sscottl warn("Failed to get info for volume %d", 495196200Sscottl list.ld_list[i].ld.v.target_id); 496222899Sbz close(fd); 497214396Sjhb return (error); 498196200Sscottl } 499196200Sscottl printf("%6s ", 500196200Sscottl mfi_volume_name(fd, list.ld_list[i].ld.v.target_id)); 501196200Sscottl print_ld(&info, state_len); 502196200Sscottl switch (info.ld_config.properties.current_cache_policy & 503196200Sscottl (MR_LD_CACHE_ALLOW_WRITE_CACHE | 504196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE)) { 505196200Sscottl case 0: 506196200Sscottl printf(" Disabled"); 507196200Sscottl break; 508196200Sscottl case MR_LD_CACHE_ALLOW_READ_CACHE: 509196200Sscottl printf(" Reads "); 510196200Sscottl break; 511196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE: 512196200Sscottl printf(" Writes "); 513196200Sscottl break; 514196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE | 515196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE: 516196200Sscottl printf(" Enabled "); 517196200Sscottl break; 518196200Sscottl } 519196200Sscottl if (info.ld_config.properties.name[0] != '\0') 520196200Sscottl printf(" <%s>", info.ld_config.properties.name); 521196200Sscottl printf("\n"); 522196200Sscottl } 523196200Sscottl close(fd); 524196200Sscottl 525196200Sscottl return (0); 526196200Sscottl} 527196200SscottlMFI_COMMAND(show, volumes, show_volumes); 528196200Sscottl 529196200Sscottlstatic int 530237260Seadlershow_drives(int ac, char **av __unused) 531196200Sscottl{ 532196200Sscottl struct mfi_pd_list *list; 533196200Sscottl struct mfi_pd_info info; 534196200Sscottl u_int i, len, state_len; 535214396Sjhb int error, fd; 536196200Sscottl 537196200Sscottl if (ac != 1) { 538196200Sscottl warnx("show drives: extra arguments"); 539196200Sscottl return (EINVAL); 540196200Sscottl } 541196200Sscottl 542237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 543196200Sscottl if (fd < 0) { 544214396Sjhb error = errno; 545196200Sscottl warn("mfi_open"); 546214396Sjhb return (error); 547196200Sscottl } 548196200Sscottl 549222899Sbz list = NULL; 550196200Sscottl if (mfi_pd_get_list(fd, &list, NULL) < 0) { 551214396Sjhb error = errno; 552196200Sscottl warn("Failed to get drive list"); 553222899Sbz goto error; 554196200Sscottl } 555196200Sscottl 556196200Sscottl /* Walk the list of drives to determine width of state column. */ 557196200Sscottl state_len = 0; 558196200Sscottl for (i = 0; i < list->count; i++) { 559196200Sscottl if (list->addr[i].scsi_dev_type != 0) 560196200Sscottl continue; 561196200Sscottl 562196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 563196200Sscottl NULL) < 0) { 564214396Sjhb error = errno; 565196200Sscottl warn("Failed to fetch info for drive %u", 566196200Sscottl list->addr[i].device_id); 567222899Sbz goto error; 568196200Sscottl } 569196200Sscottl len = strlen(mfi_pdstate(info.fw_state)); 570251516Ssbruno if (info.state.ddf.v.pd_type.is_foreign) 571251516Ssbruno len += strlen(foreign_state); 572196200Sscottl if (len > state_len) 573196200Sscottl state_len = len; 574196200Sscottl } 575196200Sscottl 576196200Sscottl /* List the drives. */ 577196200Sscottl printf("mfi%d Physical Drives:\n", mfi_unit); 578196200Sscottl for (i = 0; i < list->count; i++) { 579196200Sscottl 580196200Sscottl /* Skip non-hard disks. */ 581196200Sscottl if (list->addr[i].scsi_dev_type != 0) 582196200Sscottl continue; 583196200Sscottl 584196200Sscottl /* Fetch details for this drive. */ 585196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 586196200Sscottl NULL) < 0) { 587214396Sjhb error = errno; 588196200Sscottl warn("Failed to fetch info for drive %u", 589196200Sscottl list->addr[i].device_id); 590222899Sbz goto error; 591196200Sscottl } 592196200Sscottl 593223345Sbz printf("%s ", mfi_drive_name(&info, list->addr[i].device_id, 594223345Sbz MFI_DNAME_DEVICE_ID)); 595223345Sbz print_pd(&info, state_len); 596223345Sbz printf(" %s", mfi_drive_name(&info, list->addr[i].device_id, 597223345Sbz MFI_DNAME_ES)); 598196200Sscottl printf("\n"); 599196200Sscottl } 600224495Sjhb error = 0; 601222899Sbzerror: 602222899Sbz free(list); 603196200Sscottl close(fd); 604196200Sscottl 605222899Sbz return (error); 606196200Sscottl} 607196200SscottlMFI_COMMAND(show, drives, show_drives); 608196200Sscottl 609196200Sscottlstatic int 610237260Seadlershow_firmware(int ac, char **av __unused) 611196200Sscottl{ 612196200Sscottl struct mfi_ctrl_info info; 613196200Sscottl struct mfi_info_component header; 614214396Sjhb int error, fd; 615196200Sscottl u_int i; 616196200Sscottl 617196200Sscottl if (ac != 1) { 618221208Sjhb warnx("show firmware: extra arguments"); 619196200Sscottl return (EINVAL); 620196200Sscottl } 621196200Sscottl 622237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 623196200Sscottl if (fd < 0) { 624214396Sjhb error = errno; 625196200Sscottl warn("mfi_open"); 626214396Sjhb return (error); 627196200Sscottl } 628196200Sscottl 629196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 630214396Sjhb error = errno; 631196200Sscottl warn("Failed to get controller info"); 632222899Sbz close(fd); 633214396Sjhb return (error); 634196200Sscottl } 635196200Sscottl 636196200Sscottl if (info.package_version[0] != '\0') 637196200Sscottl printf("mfi%d Firmware Package Version: %s\n", mfi_unit, 638196200Sscottl info.package_version); 639196200Sscottl printf("mfi%d Firmware Images:\n", mfi_unit); 640196200Sscottl strcpy(header.name, "Name"); 641196200Sscottl strcpy(header.version, "Version"); 642196200Sscottl strcpy(header.build_date, "Date"); 643196200Sscottl strcpy(header.build_time, "Time"); 644196200Sscottl scan_firmware(&header); 645196200Sscottl if (info.image_component_count > 8) 646196200Sscottl info.image_component_count = 8; 647196200Sscottl for (i = 0; i < info.image_component_count; i++) 648196200Sscottl scan_firmware(&info.image_component[i]); 649196200Sscottl if (info.pending_image_component_count > 8) 650196200Sscottl info.pending_image_component_count = 8; 651196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 652196200Sscottl scan_firmware(&info.pending_image_component[i]); 653196200Sscottl display_firmware(&header, "Status"); 654196200Sscottl for (i = 0; i < info.image_component_count; i++) 655196200Sscottl display_firmware(&info.image_component[i], "active"); 656196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 657196200Sscottl display_firmware(&info.pending_image_component[i], "pending"); 658196200Sscottl 659196200Sscottl close(fd); 660196200Sscottl 661196200Sscottl return (0); 662196200Sscottl} 663196200SscottlMFI_COMMAND(show, firmware, show_firmware); 664221208Sjhb 665221208Sjhbstatic int 666237260Seadlershow_progress(int ac, char **av __unused) 667221208Sjhb{ 668221208Sjhb struct mfi_ld_list llist; 669221208Sjhb struct mfi_pd_list *plist; 670221208Sjhb struct mfi_ld_info linfo; 671221208Sjhb struct mfi_pd_info pinfo; 672221208Sjhb int busy, error, fd; 673221208Sjhb u_int i; 674221208Sjhb uint16_t device_id; 675221208Sjhb uint8_t target_id; 676221208Sjhb 677221208Sjhb if (ac != 1) { 678221208Sjhb warnx("show progress: extra arguments"); 679221208Sjhb return (EINVAL); 680221208Sjhb } 681221208Sjhb 682237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 683221208Sjhb if (fd < 0) { 684221208Sjhb error = errno; 685221208Sjhb warn("mfi_open"); 686221208Sjhb return (error); 687221208Sjhb } 688221208Sjhb 689221208Sjhb if (mfi_ld_get_list(fd, &llist, NULL) < 0) { 690221208Sjhb error = errno; 691221208Sjhb warn("Failed to get volume list"); 692222899Sbz close(fd); 693221208Sjhb return (error); 694221208Sjhb } 695221208Sjhb if (mfi_pd_get_list(fd, &plist, NULL) < 0) { 696221208Sjhb error = errno; 697221208Sjhb warn("Failed to get drive list"); 698222899Sbz close(fd); 699221208Sjhb return (error); 700221208Sjhb } 701221208Sjhb 702222899Sbz busy = 0; 703221208Sjhb for (i = 0; i < llist.ld_count; i++) { 704221208Sjhb target_id = llist.ld_list[i].ld.v.target_id; 705221208Sjhb if (mfi_ld_get_info(fd, target_id, &linfo, NULL) < 0) { 706221208Sjhb error = errno; 707221208Sjhb warn("Failed to get info for volume %s", 708221208Sjhb mfi_volume_name(fd, target_id)); 709222899Sbz free(plist); 710222899Sbz close(fd); 711221208Sjhb return (error); 712221208Sjhb } 713221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_CC) { 714221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 715221208Sjhb mfi_display_progress("Consistency Check", 716221208Sjhb &linfo.progress.cc); 717221208Sjhb busy = 1; 718221208Sjhb } 719221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_BGI) { 720221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 721221208Sjhb mfi_display_progress("Background Init", 722221208Sjhb &linfo.progress.bgi); 723221208Sjhb busy = 1; 724221208Sjhb } 725221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_FGI) { 726221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 727221208Sjhb mfi_display_progress("Foreground Init", 728221208Sjhb &linfo.progress.fgi); 729221208Sjhb busy = 1; 730221208Sjhb } 731221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_RECON) { 732221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 733221208Sjhb mfi_display_progress("Reconstruction", 734221208Sjhb &linfo.progress.recon); 735221208Sjhb busy = 1; 736221208Sjhb } 737221208Sjhb } 738221208Sjhb 739221208Sjhb for (i = 0; i < plist->count; i++) { 740221208Sjhb if (plist->addr[i].scsi_dev_type != 0) 741221208Sjhb continue; 742221208Sjhb 743221208Sjhb device_id = plist->addr[i].device_id; 744221208Sjhb if (mfi_pd_get_info(fd, device_id, &pinfo, NULL) < 0) { 745221208Sjhb error = errno; 746221208Sjhb warn("Failed to fetch info for drive %u", device_id); 747222899Sbz free(plist); 748222899Sbz close(fd); 749221208Sjhb return (error); 750221208Sjhb } 751221208Sjhb 752221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_REBUILD) { 753223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 754223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 755221208Sjhb mfi_display_progress("Rebuild", &pinfo.prog_info.rbld); 756221208Sjhb busy = 1; 757221208Sjhb } 758221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_PATROL) { 759223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 760223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 761221208Sjhb mfi_display_progress("Patrol Read", 762221208Sjhb &pinfo.prog_info.patrol); 763221208Sjhb busy = 1; 764221208Sjhb } 765221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_CLEAR) { 766223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 767223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 768221208Sjhb mfi_display_progress("Clear", &pinfo.prog_info.clear); 769266400Sjhb busy = 1; 770221208Sjhb } 771221208Sjhb } 772221208Sjhb 773222899Sbz free(plist); 774221208Sjhb close(fd); 775221208Sjhb 776221208Sjhb if (!busy) 777221208Sjhb printf("No activity in progress for adapter mfi%d\n", mfi_unit); 778221208Sjhb 779221208Sjhb return (0); 780221208Sjhb} 781221208SjhbMFI_COMMAND(show, progress, show_progress); 782251516Ssbruno 783251516Ssbrunostatic int 784251516Ssbrunoshow_foreign(int ac, char **av) 785251516Ssbruno{ 786251516Ssbruno return(display_format(ac, av, 0/*normal display*/, MFI_DCMD_CFG_FOREIGN_DISPLAY)); 787251516Ssbruno} 788251516SsbrunoMFI_COMMAND(show, foreign, show_foreign); 789