mfi_show.c revision 237259
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: head/usr.sbin/mfiutil/mfi_show.c 237259 2012-06-19 06:18:37Z eadler $ 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 43196200SscottlMFI_TABLE(top, show); 44196200Sscottl 45196200Sscottlstatic void 46196200Sscottlformat_stripe(char *buf, size_t buflen, uint8_t stripe) 47196200Sscottl{ 48196200Sscottl 49196200Sscottl humanize_number(buf, buflen, (1 << stripe) * 512, "", HN_AUTOSCALE, 50196200Sscottl HN_B | HN_NOSPACE); 51196200Sscottl} 52196200Sscottl 53196200Sscottlstatic int 54196200Sscottlshow_adapter(int ac, char **av) 55196200Sscottl{ 56196200Sscottl struct mfi_ctrl_info info; 57196200Sscottl char stripe[5]; 58214396Sjhb int error, fd, comma; 59196200Sscottl 60196200Sscottl if (ac != 1) { 61196200Sscottl warnx("show adapter: extra arguments"); 62196200Sscottl return (EINVAL); 63196200Sscottl } 64196200Sscottl 65237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 66196200Sscottl if (fd < 0) { 67214396Sjhb error = errno; 68196200Sscottl warn("mfi_open"); 69214396Sjhb return (error); 70196200Sscottl } 71196200Sscottl 72196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 73214396Sjhb error = errno; 74196200Sscottl warn("Failed to get controller info"); 75222899Sbz close(fd); 76214396Sjhb return (error); 77196200Sscottl } 78196200Sscottl printf("mfi%d Adapter:\n", mfi_unit); 79196200Sscottl printf(" Product Name: %.80s\n", info.product_name); 80196200Sscottl printf(" Serial Number: %.32s\n", info.serial_number); 81196200Sscottl if (info.package_version[0] != '\0') 82196200Sscottl printf(" Firmware: %s\n", info.package_version); 83196200Sscottl printf(" RAID Levels:"); 84196200Sscottl#ifdef DEBUG 85196200Sscottl printf(" (%#x)", info.raid_levels); 86196200Sscottl#endif 87196200Sscottl comma = 0; 88196200Sscottl if (info.raid_levels & MFI_INFO_RAID_0) { 89196200Sscottl printf(" JBOD, RAID0"); 90196200Sscottl comma = 1; 91196200Sscottl } 92196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1) { 93196200Sscottl printf("%s RAID1", comma ? "," : ""); 94196200Sscottl comma = 1; 95196200Sscottl } 96196200Sscottl if (info.raid_levels & MFI_INFO_RAID_5) { 97196200Sscottl printf("%s RAID5", comma ? "," : ""); 98196200Sscottl comma = 1; 99196200Sscottl } 100196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1E) { 101196200Sscottl printf("%s RAID1E", comma ? "," : ""); 102196200Sscottl comma = 1; 103196200Sscottl } 104196200Sscottl if (info.raid_levels & MFI_INFO_RAID_6) { 105196200Sscottl printf("%s RAID6", comma ? "," : ""); 106196200Sscottl comma = 1; 107196200Sscottl } 108196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) == 109196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) { 110196200Sscottl printf("%s RAID10", comma ? "," : ""); 111196200Sscottl comma = 1; 112196200Sscottl } 113196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) == 114196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) { 115196200Sscottl printf("%s RAID50", comma ? "," : ""); 116196200Sscottl comma = 1; 117196200Sscottl } 118196200Sscottl printf("\n"); 119196200Sscottl printf(" Battery Backup: "); 120196200Sscottl if (info.hw_present & MFI_INFO_HW_BBU) 121196200Sscottl printf("present\n"); 122196200Sscottl else 123196200Sscottl printf("not present\n"); 124196200Sscottl if (info.hw_present & MFI_INFO_HW_NVRAM) 125196200Sscottl printf(" NVRAM: %uK\n", info.nvram_size); 126196200Sscottl printf(" Onboard Memory: %uM\n", info.memory_size); 127196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.min); 128196200Sscottl printf(" Minimum Stripe: %s\n", stripe); 129196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.max); 130196200Sscottl printf(" Maximum Stripe: %s\n", stripe); 131196200Sscottl 132196200Sscottl close(fd); 133196200Sscottl 134196200Sscottl return (0); 135196200Sscottl} 136196200SscottlMFI_COMMAND(show, adapter, show_adapter); 137196200Sscottl 138196200Sscottlstatic int 139196200Sscottlshow_battery(int ac, char **av) 140196200Sscottl{ 141196200Sscottl struct mfi_bbu_capacity_info cap; 142196200Sscottl struct mfi_bbu_design_info design; 143219717Sjhb struct mfi_bbu_status stat; 144196200Sscottl uint8_t status; 145225798Semaste int comma, error, fd, show_capacity; 146196200Sscottl 147196200Sscottl if (ac != 1) { 148196200Sscottl warnx("show battery: extra arguments"); 149196200Sscottl return (EINVAL); 150196200Sscottl } 151196200Sscottl 152237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 153196200Sscottl if (fd < 0) { 154214396Sjhb error = errno; 155196200Sscottl warn("mfi_open"); 156214396Sjhb return (error); 157196200Sscottl } 158196200Sscottl 159196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap, 160196200Sscottl sizeof(cap), NULL, 0, &status) < 0) { 161214396Sjhb error = errno; 162196200Sscottl warn("Failed to get capacity info"); 163222899Sbz close(fd); 164214396Sjhb return (error); 165196200Sscottl } 166225798Semaste if (status == MFI_STAT_NO_HW_PRESENT) { 167225798Semaste printf("mfi%d: No battery present\n", mfi_unit); 168225798Semaste close(fd); 169225798Semaste return (0); 170225798Semaste } 171225798Semaste show_capacity = (status == MFI_STAT_OK); 172196200Sscottl 173196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design, 174196200Sscottl sizeof(design), NULL, 0, NULL) < 0) { 175214396Sjhb error = errno; 176196200Sscottl warn("Failed to get design info"); 177222899Sbz close(fd); 178214396Sjhb return (error); 179196200Sscottl } 180196200Sscottl 181219717Sjhb if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_STATUS, &stat, sizeof(stat), 182219717Sjhb NULL, 0, NULL) < 0) { 183219722Sjhb error = errno; 184219717Sjhb warn("Failed to get status"); 185222899Sbz close(fd); 186219722Sjhb return (error); 187219717Sjhb } 188219717Sjhb 189196200Sscottl printf("mfi%d: Battery State:\n", mfi_unit); 190219717Sjhb printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, 191196200Sscottl design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); 192219717Sjhb printf(" Serial Number: %d\n", design.serial_number); 193219717Sjhb printf(" Manufacturer: %s\n", design.mfg_name); 194219717Sjhb printf(" Model: %s\n", design.device_name); 195219717Sjhb printf(" Chemistry: %s\n", design.device_chemistry); 196219717Sjhb printf(" Design Capacity: %d mAh\n", design.design_capacity); 197225798Semaste if (show_capacity) { 198225798Semaste printf(" Full Charge Capacity: %d mAh\n", 199225798Semaste cap.full_charge_capacity); 200225798Semaste printf(" Current Capacity: %d mAh\n", 201225798Semaste cap.remaining_capacity); 202225798Semaste printf(" Charge Cycles: %d\n", cap.cycle_count); 203225798Semaste printf(" Current Charge: %d%%\n", cap.relative_charge); 204225798Semaste } 205219717Sjhb printf(" Design Voltage: %d mV\n", design.design_voltage); 206219717Sjhb printf(" Current Voltage: %d mV\n", stat.voltage); 207219717Sjhb printf(" Temperature: %d C\n", stat.temperature); 208219717Sjhb printf(" Status:"); 209219717Sjhb comma = 0; 210219717Sjhb if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) { 211219717Sjhb printf(" PACK_MISSING"); 212219717Sjhb comma = 1; 213219717Sjhb } 214219717Sjhb if (stat.fw_status & MFI_BBU_STATE_VOLTAGE_LOW) { 215219717Sjhb printf("%s VOLTAGE_LOW", comma ? "," : ""); 216219717Sjhb comma = 1; 217219717Sjhb } 218219717Sjhb if (stat.fw_status & MFI_BBU_STATE_TEMPERATURE_HIGH) { 219219717Sjhb printf("%s TEMPERATURE_HIGH", comma ? "," : ""); 220219717Sjhb comma = 1; 221219717Sjhb } 222219717Sjhb if (stat.fw_status & MFI_BBU_STATE_CHARGE_ACTIVE) { 223219717Sjhb printf("%s CHARGING", comma ? "," : ""); 224219717Sjhb comma = 1; 225219717Sjhb } 226219717Sjhb if (stat.fw_status & MFI_BBU_STATE_DISCHARGE_ACTIVE) { 227219717Sjhb printf("%s DISCHARGING", comma ? "," : ""); 228235635Ssbruno comma = 1; 229219717Sjhb } 230235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_REQ) { 231235635Ssbruno printf("%s LEARN_CYCLE_REQUESTED", comma ? "," : ""); 232235635Ssbruno comma = 1; 233235635Ssbruno } 234235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_ACTIVE) { 235235635Ssbruno printf("%s LEARN_CYCLE_ACTIVE", comma ? "," : ""); 236235635Ssbruno comma = 1; 237235635Ssbruno } 238235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_FAIL) { 239235635Ssbruno printf("%s LEARN_CYCLE_FAIL", comma ? "," : ""); 240235635Ssbruno comma = 1; 241235635Ssbruno } 242235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_TIMEOUT) { 243235635Ssbruno printf("%s LEARN_CYCLE_TIMEOUT", comma ? "," : ""); 244235635Ssbruno comma = 1; 245235635Ssbruno } 246235635Ssbruno if (stat.fw_status & MFI_BBU_STATE_I2C_ERR_DETECT) { 247235635Ssbruno printf("%s I2C_ERROR_DETECT", comma ? "," : ""); 248235635Ssbruno comma = 1; 249235635Ssbruno } 250235635Ssbruno 251219717Sjhb if (!comma) 252219717Sjhb printf(" normal"); 253219717Sjhb printf("\n"); 254219717Sjhb switch (stat.battery_type) { 255219717Sjhb case MFI_BBU_TYPE_BBU: 256219717Sjhb printf(" State of Health: %s\n", 257219717Sjhb stat.detail.bbu.is_SOH_good ? "good" : "bad"); 258219717Sjhb break; 259219717Sjhb } 260196200Sscottl 261196200Sscottl close(fd); 262196200Sscottl 263196200Sscottl return (0); 264196200Sscottl} 265196200SscottlMFI_COMMAND(show, battery, show_battery); 266196200Sscottl 267196200Sscottlstatic void 268196200Sscottlprint_ld(struct mfi_ld_info *info, int state_len) 269196200Sscottl{ 270196200Sscottl struct mfi_ld_params *params = &info->ld_config.params; 271196200Sscottl const char *level; 272196200Sscottl char size[6], stripe[5]; 273196200Sscottl 274196200Sscottl humanize_number(size, sizeof(size), info->size * 512, 275196200Sscottl "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 276196200Sscottl format_stripe(stripe, sizeof(stripe), 277196200Sscottl info->ld_config.params.stripe_size); 278196200Sscottl level = mfi_raid_level(params->primary_raid_level, 279196200Sscottl params->secondary_raid_level); 280196200Sscottl if (state_len > 0) 281196200Sscottl printf("(%6s) %-8s %6s %-*s", size, level, stripe, state_len, 282196200Sscottl mfi_ldstate(params->state)); 283196200Sscottl else 284196200Sscottl printf("(%s) %s %s %s", size, level, stripe, 285196200Sscottl mfi_ldstate(params->state)); 286196200Sscottl} 287196200Sscottl 288196200Sscottlstatic void 289223345Sbzprint_pd(struct mfi_pd_info *info, int state_len) 290196200Sscottl{ 291196200Sscottl const char *s; 292196200Sscottl char buf[6]; 293196200Sscottl 294196200Sscottl humanize_number(buf, sizeof(buf), info->raw_size * 512, "", 295196200Sscottl HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 296196200Sscottl printf("(%6s) ", buf); 297196200Sscottl if (state_len > 0) 298196200Sscottl printf("%-*s", state_len, mfi_pdstate(info->fw_state)); 299196200Sscottl else 300196200Sscottl printf("%s", mfi_pdstate(info->fw_state)); 301196200Sscottl s = mfi_pd_inq_string(info); 302196200Sscottl if (s != NULL) 303196200Sscottl printf(" %s", s); 304196200Sscottl} 305196200Sscottl 306196200Sscottlstatic int 307196200Sscottlshow_config(int ac, char **av) 308196200Sscottl{ 309196200Sscottl struct mfi_config_data *config; 310196200Sscottl struct mfi_array *ar; 311196200Sscottl struct mfi_ld_config *ld; 312196200Sscottl struct mfi_spare *sp; 313196200Sscottl struct mfi_ld_info linfo; 314196200Sscottl struct mfi_pd_info pinfo; 315196200Sscottl uint16_t device_id; 316196200Sscottl char *p; 317214396Sjhb int error, fd, i, j; 318196200Sscottl 319196200Sscottl if (ac != 1) { 320196200Sscottl warnx("show config: extra arguments"); 321196200Sscottl return (EINVAL); 322196200Sscottl } 323196200Sscottl 324237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 325196200Sscottl if (fd < 0) { 326214396Sjhb error = errno; 327196200Sscottl warn("mfi_open"); 328214396Sjhb return (error); 329196200Sscottl } 330196200Sscottl 331196200Sscottl /* Get the config from the controller. */ 332196200Sscottl if (mfi_config_read(fd, &config) < 0) { 333214396Sjhb error = errno; 334196200Sscottl warn("Failed to get config"); 335222899Sbz close(fd); 336214396Sjhb return (error); 337196200Sscottl } 338196200Sscottl 339196200Sscottl /* Dump out the configuration. */ 340196200Sscottl printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n", 341196200Sscottl mfi_unit, config->array_count, config->log_drv_count, 342196200Sscottl config->spares_count); 343196200Sscottl p = (char *)config->array; 344196200Sscottl 345196200Sscottl for (i = 0; i < config->array_count; i++) { 346196200Sscottl ar = (struct mfi_array *)p; 347196200Sscottl printf(" array %u of %u drives:\n", ar->array_ref, 348196200Sscottl ar->num_drives); 349196200Sscottl for (j = 0; j < ar->num_drives; j++) { 350196200Sscottl device_id = ar->pd[j].ref.v.device_id; 351223345Sbz printf(" drive %s ", mfi_drive_name(NULL, 352223345Sbz device_id, 353223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 354223345Sbz if (device_id != 0xffff) { 355196200Sscottl if (mfi_pd_get_info(fd, device_id, &pinfo, 356196200Sscottl NULL) < 0) 357196200Sscottl printf("%s", 358196200Sscottl mfi_pdstate(ar->pd[j].fw_state)); 359196200Sscottl else 360223345Sbz print_pd(&pinfo, -1); 361196200Sscottl } 362225168Sbz printf("\n"); 363196200Sscottl } 364196200Sscottl p += config->array_size; 365196200Sscottl } 366196200Sscottl 367196200Sscottl for (i = 0; i < config->log_drv_count; i++) { 368196200Sscottl ld = (struct mfi_ld_config *)p; 369196200Sscottl printf(" volume %s ", 370196200Sscottl mfi_volume_name(fd, ld->properties.ld.v.target_id)); 371196200Sscottl if (mfi_ld_get_info(fd, ld->properties.ld.v.target_id, &linfo, 372196200Sscottl NULL) < 0) { 373196200Sscottl printf("%s %s", 374196200Sscottl mfi_raid_level(ld->params.primary_raid_level, 375196200Sscottl ld->params.secondary_raid_level), 376196200Sscottl mfi_ldstate(ld->params.state)); 377196200Sscottl } else 378196200Sscottl print_ld(&linfo, -1); 379196200Sscottl if (ld->properties.name[0] != '\0') 380196200Sscottl printf(" <%s>", ld->properties.name); 381196200Sscottl printf(" spans:\n"); 382196200Sscottl for (j = 0; j < ld->params.span_depth; j++) 383196200Sscottl printf(" array %u\n", ld->span[j].array_ref); 384196200Sscottl p += config->log_drv_size; 385196200Sscottl } 386196200Sscottl 387196200Sscottl for (i = 0; i < config->spares_count; i++) { 388196200Sscottl sp = (struct mfi_spare *)p; 389223345Sbz printf(" %s spare %s ", 390196200Sscottl sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" : 391223345Sbz "global", mfi_drive_name(NULL, sp->ref.v.device_id, 392223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 393196200Sscottl if (mfi_pd_get_info(fd, sp->ref.v.device_id, &pinfo, NULL) < 0) 394196200Sscottl printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE)); 395196200Sscottl else 396223345Sbz print_pd(&pinfo, -1); 397196200Sscottl if (sp->spare_type & MFI_SPARE_DEDICATED) { 398196200Sscottl printf(" backs:\n"); 399196200Sscottl for (j = 0; j < sp->array_count; j++) 400196200Sscottl printf(" array %u\n", sp->array_ref[j]); 401196200Sscottl } else 402196200Sscottl printf("\n"); 403196200Sscottl p += config->spares_size; 404196200Sscottl } 405222899Sbz free(config); 406196200Sscottl close(fd); 407196200Sscottl 408196200Sscottl return (0); 409196200Sscottl} 410196200SscottlMFI_COMMAND(show, config, show_config); 411196200Sscottl 412196200Sscottlstatic int 413196200Sscottlshow_volumes(int ac, char **av) 414196200Sscottl{ 415196200Sscottl struct mfi_ld_list list; 416196200Sscottl struct mfi_ld_info info; 417214396Sjhb int error, fd; 418196200Sscottl u_int i, len, state_len; 419196200Sscottl 420196200Sscottl if (ac != 1) { 421196200Sscottl warnx("show volumes: extra arguments"); 422196200Sscottl return (EINVAL); 423196200Sscottl } 424196200Sscottl 425237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 426196200Sscottl if (fd < 0) { 427214396Sjhb error = errno; 428196200Sscottl warn("mfi_open"); 429214396Sjhb return (error); 430196200Sscottl } 431196200Sscottl 432196200Sscottl /* Get the logical drive list from the controller. */ 433196200Sscottl if (mfi_ld_get_list(fd, &list, NULL) < 0) { 434214396Sjhb error = errno; 435196200Sscottl warn("Failed to get volume list"); 436222899Sbz close(fd); 437214396Sjhb return (error); 438196200Sscottl } 439196200Sscottl 440196200Sscottl /* List the volumes. */ 441196200Sscottl printf("mfi%d Volumes:\n", mfi_unit); 442196200Sscottl state_len = strlen("State"); 443196200Sscottl for (i = 0; i < list.ld_count; i++) { 444196200Sscottl len = strlen(mfi_ldstate(list.ld_list[i].state)); 445196200Sscottl if (len > state_len) 446196200Sscottl state_len = len; 447196200Sscottl } 448196200Sscottl printf(" Id Size Level Stripe "); 449196200Sscottl len = state_len - strlen("State"); 450196200Sscottl for (i = 0; i < (len + 1) / 2; i++) 451196200Sscottl printf(" "); 452196200Sscottl printf("State"); 453196200Sscottl for (i = 0; i < len / 2; i++) 454196200Sscottl printf(" "); 455196200Sscottl printf(" Cache Name\n"); 456196200Sscottl for (i = 0; i < list.ld_count; i++) { 457196200Sscottl if (mfi_ld_get_info(fd, list.ld_list[i].ld.v.target_id, &info, 458196200Sscottl NULL) < 0) { 459214396Sjhb error = errno; 460196200Sscottl warn("Failed to get info for volume %d", 461196200Sscottl list.ld_list[i].ld.v.target_id); 462222899Sbz close(fd); 463214396Sjhb return (error); 464196200Sscottl } 465196200Sscottl printf("%6s ", 466196200Sscottl mfi_volume_name(fd, list.ld_list[i].ld.v.target_id)); 467196200Sscottl print_ld(&info, state_len); 468196200Sscottl switch (info.ld_config.properties.current_cache_policy & 469196200Sscottl (MR_LD_CACHE_ALLOW_WRITE_CACHE | 470196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE)) { 471196200Sscottl case 0: 472196200Sscottl printf(" Disabled"); 473196200Sscottl break; 474196200Sscottl case MR_LD_CACHE_ALLOW_READ_CACHE: 475196200Sscottl printf(" Reads "); 476196200Sscottl break; 477196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE: 478196200Sscottl printf(" Writes "); 479196200Sscottl break; 480196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE | 481196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE: 482196200Sscottl printf(" Enabled "); 483196200Sscottl break; 484196200Sscottl } 485196200Sscottl if (info.ld_config.properties.name[0] != '\0') 486196200Sscottl printf(" <%s>", info.ld_config.properties.name); 487196200Sscottl printf("\n"); 488196200Sscottl } 489196200Sscottl close(fd); 490196200Sscottl 491196200Sscottl return (0); 492196200Sscottl} 493196200SscottlMFI_COMMAND(show, volumes, show_volumes); 494196200Sscottl 495196200Sscottlstatic int 496196200Sscottlshow_drives(int ac, char **av) 497196200Sscottl{ 498196200Sscottl struct mfi_pd_list *list; 499196200Sscottl struct mfi_pd_info info; 500196200Sscottl u_int i, len, state_len; 501214396Sjhb int error, fd; 502196200Sscottl 503196200Sscottl if (ac != 1) { 504196200Sscottl warnx("show drives: extra arguments"); 505196200Sscottl return (EINVAL); 506196200Sscottl } 507196200Sscottl 508237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 509196200Sscottl if (fd < 0) { 510214396Sjhb error = errno; 511196200Sscottl warn("mfi_open"); 512214396Sjhb return (error); 513196200Sscottl } 514196200Sscottl 515222899Sbz list = NULL; 516196200Sscottl if (mfi_pd_get_list(fd, &list, NULL) < 0) { 517214396Sjhb error = errno; 518196200Sscottl warn("Failed to get drive list"); 519222899Sbz goto error; 520196200Sscottl } 521196200Sscottl 522196200Sscottl /* Walk the list of drives to determine width of state column. */ 523196200Sscottl state_len = 0; 524196200Sscottl for (i = 0; i < list->count; i++) { 525196200Sscottl if (list->addr[i].scsi_dev_type != 0) 526196200Sscottl continue; 527196200Sscottl 528196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 529196200Sscottl NULL) < 0) { 530214396Sjhb error = errno; 531196200Sscottl warn("Failed to fetch info for drive %u", 532196200Sscottl list->addr[i].device_id); 533222899Sbz goto error; 534196200Sscottl } 535196200Sscottl len = strlen(mfi_pdstate(info.fw_state)); 536196200Sscottl if (len > state_len) 537196200Sscottl state_len = len; 538196200Sscottl } 539196200Sscottl 540196200Sscottl /* List the drives. */ 541196200Sscottl printf("mfi%d Physical Drives:\n", mfi_unit); 542196200Sscottl for (i = 0; i < list->count; i++) { 543196200Sscottl 544196200Sscottl /* Skip non-hard disks. */ 545196200Sscottl if (list->addr[i].scsi_dev_type != 0) 546196200Sscottl continue; 547196200Sscottl 548196200Sscottl /* Fetch details for this drive. */ 549196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 550196200Sscottl NULL) < 0) { 551214396Sjhb error = errno; 552196200Sscottl warn("Failed to fetch info for drive %u", 553196200Sscottl list->addr[i].device_id); 554222899Sbz goto error; 555196200Sscottl } 556196200Sscottl 557223345Sbz printf("%s ", mfi_drive_name(&info, list->addr[i].device_id, 558223345Sbz MFI_DNAME_DEVICE_ID)); 559223345Sbz print_pd(&info, state_len); 560223345Sbz printf(" %s", mfi_drive_name(&info, list->addr[i].device_id, 561223345Sbz MFI_DNAME_ES)); 562196200Sscottl printf("\n"); 563196200Sscottl } 564224495Sjhb error = 0; 565222899Sbzerror: 566222899Sbz free(list); 567196200Sscottl close(fd); 568196200Sscottl 569222899Sbz return (error); 570196200Sscottl} 571196200SscottlMFI_COMMAND(show, drives, show_drives); 572196200Sscottl 573196200Sscottlint fw_name_width, fw_version_width, fw_date_width, fw_time_width; 574196200Sscottl 575196200Sscottlstatic void 576196200Sscottlscan_firmware(struct mfi_info_component *comp) 577196200Sscottl{ 578196200Sscottl int len; 579196200Sscottl 580196200Sscottl len = strlen(comp->name); 581196200Sscottl if (fw_name_width < len) 582196200Sscottl fw_name_width = len; 583196200Sscottl len = strlen(comp->version); 584196200Sscottl if (fw_version_width < len) 585196200Sscottl fw_version_width = len; 586196200Sscottl len = strlen(comp->build_date); 587196200Sscottl if (fw_date_width < len) 588196200Sscottl fw_date_width = len; 589196200Sscottl len = strlen(comp->build_time); 590196200Sscottl if (fw_time_width < len) 591196200Sscottl fw_time_width = len; 592196200Sscottl} 593196200Sscottl 594196200Sscottlstatic void 595196200Sscottldisplay_firmware(struct mfi_info_component *comp, const char *tag) 596196200Sscottl{ 597196200Sscottl 598196200Sscottl printf("%-*s %-*s %-*s %-*s %s\n", fw_name_width, comp->name, 599196200Sscottl fw_version_width, comp->version, fw_date_width, comp->build_date, 600196200Sscottl fw_time_width, comp->build_time, tag); 601196200Sscottl} 602196200Sscottl 603196200Sscottlstatic int 604196200Sscottlshow_firmware(int ac, char **av) 605196200Sscottl{ 606196200Sscottl struct mfi_ctrl_info info; 607196200Sscottl struct mfi_info_component header; 608214396Sjhb int error, fd; 609196200Sscottl u_int i; 610196200Sscottl 611196200Sscottl if (ac != 1) { 612221208Sjhb warnx("show firmware: extra arguments"); 613196200Sscottl return (EINVAL); 614196200Sscottl } 615196200Sscottl 616237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 617196200Sscottl if (fd < 0) { 618214396Sjhb error = errno; 619196200Sscottl warn("mfi_open"); 620214396Sjhb return (error); 621196200Sscottl } 622196200Sscottl 623196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 624214396Sjhb error = errno; 625196200Sscottl warn("Failed to get controller info"); 626222899Sbz close(fd); 627214396Sjhb return (error); 628196200Sscottl } 629196200Sscottl 630196200Sscottl if (info.package_version[0] != '\0') 631196200Sscottl printf("mfi%d Firmware Package Version: %s\n", mfi_unit, 632196200Sscottl info.package_version); 633196200Sscottl printf("mfi%d Firmware Images:\n", mfi_unit); 634196200Sscottl strcpy(header.name, "Name"); 635196200Sscottl strcpy(header.version, "Version"); 636196200Sscottl strcpy(header.build_date, "Date"); 637196200Sscottl strcpy(header.build_time, "Time"); 638196200Sscottl scan_firmware(&header); 639196200Sscottl if (info.image_component_count > 8) 640196200Sscottl info.image_component_count = 8; 641196200Sscottl for (i = 0; i < info.image_component_count; i++) 642196200Sscottl scan_firmware(&info.image_component[i]); 643196200Sscottl if (info.pending_image_component_count > 8) 644196200Sscottl info.pending_image_component_count = 8; 645196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 646196200Sscottl scan_firmware(&info.pending_image_component[i]); 647196200Sscottl display_firmware(&header, "Status"); 648196200Sscottl for (i = 0; i < info.image_component_count; i++) 649196200Sscottl display_firmware(&info.image_component[i], "active"); 650196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 651196200Sscottl display_firmware(&info.pending_image_component[i], "pending"); 652196200Sscottl 653196200Sscottl close(fd); 654196200Sscottl 655196200Sscottl return (0); 656196200Sscottl} 657196200SscottlMFI_COMMAND(show, firmware, show_firmware); 658221208Sjhb 659221208Sjhbstatic int 660221208Sjhbshow_progress(int ac, char **av) 661221208Sjhb{ 662221208Sjhb struct mfi_ld_list llist; 663221208Sjhb struct mfi_pd_list *plist; 664221208Sjhb struct mfi_ld_info linfo; 665221208Sjhb struct mfi_pd_info pinfo; 666221208Sjhb int busy, error, fd; 667221208Sjhb u_int i; 668221208Sjhb uint16_t device_id; 669221208Sjhb uint8_t target_id; 670221208Sjhb 671221208Sjhb if (ac != 1) { 672221208Sjhb warnx("show progress: extra arguments"); 673221208Sjhb return (EINVAL); 674221208Sjhb } 675221208Sjhb 676237259Seadler fd = mfi_open(mfi_unit, O_RDONLY); 677221208Sjhb if (fd < 0) { 678221208Sjhb error = errno; 679221208Sjhb warn("mfi_open"); 680221208Sjhb return (error); 681221208Sjhb } 682221208Sjhb 683221208Sjhb if (mfi_ld_get_list(fd, &llist, NULL) < 0) { 684221208Sjhb error = errno; 685221208Sjhb warn("Failed to get volume list"); 686222899Sbz close(fd); 687221208Sjhb return (error); 688221208Sjhb } 689221208Sjhb if (mfi_pd_get_list(fd, &plist, NULL) < 0) { 690221208Sjhb error = errno; 691221208Sjhb warn("Failed to get drive list"); 692222899Sbz close(fd); 693221208Sjhb return (error); 694221208Sjhb } 695221208Sjhb 696222899Sbz busy = 0; 697221208Sjhb for (i = 0; i < llist.ld_count; i++) { 698221208Sjhb target_id = llist.ld_list[i].ld.v.target_id; 699221208Sjhb if (mfi_ld_get_info(fd, target_id, &linfo, NULL) < 0) { 700221208Sjhb error = errno; 701221208Sjhb warn("Failed to get info for volume %s", 702221208Sjhb mfi_volume_name(fd, target_id)); 703222899Sbz free(plist); 704222899Sbz close(fd); 705221208Sjhb return (error); 706221208Sjhb } 707221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_CC) { 708221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 709221208Sjhb mfi_display_progress("Consistency Check", 710221208Sjhb &linfo.progress.cc); 711221208Sjhb busy = 1; 712221208Sjhb } 713221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_BGI) { 714221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 715221208Sjhb mfi_display_progress("Background Init", 716221208Sjhb &linfo.progress.bgi); 717221208Sjhb busy = 1; 718221208Sjhb } 719221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_FGI) { 720221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 721221208Sjhb mfi_display_progress("Foreground Init", 722221208Sjhb &linfo.progress.fgi); 723221208Sjhb busy = 1; 724221208Sjhb } 725221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_RECON) { 726221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 727221208Sjhb mfi_display_progress("Reconstruction", 728221208Sjhb &linfo.progress.recon); 729221208Sjhb busy = 1; 730221208Sjhb } 731221208Sjhb } 732221208Sjhb 733221208Sjhb for (i = 0; i < plist->count; i++) { 734221208Sjhb if (plist->addr[i].scsi_dev_type != 0) 735221208Sjhb continue; 736221208Sjhb 737221208Sjhb device_id = plist->addr[i].device_id; 738221208Sjhb if (mfi_pd_get_info(fd, device_id, &pinfo, NULL) < 0) { 739221208Sjhb error = errno; 740221208Sjhb warn("Failed to fetch info for drive %u", device_id); 741222899Sbz free(plist); 742222899Sbz close(fd); 743221208Sjhb return (error); 744221208Sjhb } 745221208Sjhb 746221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_REBUILD) { 747223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 748223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 749221208Sjhb mfi_display_progress("Rebuild", &pinfo.prog_info.rbld); 750221208Sjhb busy = 1; 751221208Sjhb } 752221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_PATROL) { 753223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 754223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 755221208Sjhb mfi_display_progress("Patrol Read", 756221208Sjhb &pinfo.prog_info.patrol); 757221208Sjhb busy = 1; 758221208Sjhb } 759221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_CLEAR) { 760223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 761223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 762221208Sjhb mfi_display_progress("Clear", &pinfo.prog_info.clear); 763221208Sjhb busy = 1; 764221208Sjhb } 765221208Sjhb } 766221208Sjhb 767222899Sbz free(plist); 768221208Sjhb close(fd); 769221208Sjhb 770221208Sjhb if (!busy) 771221208Sjhb printf("No activity in progress for adapter mfi%d\n", mfi_unit); 772221208Sjhb 773221208Sjhb return (0); 774221208Sjhb} 775221208SjhbMFI_COMMAND(show, progress, show_progress); 776