mfi_show.c revision 225168
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 225168 2011-08-25 08:47:38Z bz $ 30196200Sscottl */ 31196200Sscottl 32196200Sscottl#include <sys/types.h> 33196200Sscottl#include <sys/errno.h> 34196200Sscottl#include <err.h> 35196200Sscottl#include <libutil.h> 36196200Sscottl#include <stdio.h> 37196200Sscottl#include <stdlib.h> 38196200Sscottl#include <string.h> 39196200Sscottl#include <unistd.h> 40196200Sscottl#include "mfiutil.h" 41196200Sscottl 42196200SscottlMFI_TABLE(top, show); 43196200Sscottl 44196200Sscottlstatic void 45196200Sscottlformat_stripe(char *buf, size_t buflen, uint8_t stripe) 46196200Sscottl{ 47196200Sscottl 48196200Sscottl humanize_number(buf, buflen, (1 << stripe) * 512, "", HN_AUTOSCALE, 49196200Sscottl HN_B | HN_NOSPACE); 50196200Sscottl} 51196200Sscottl 52196200Sscottlstatic int 53196200Sscottlshow_adapter(int ac, char **av) 54196200Sscottl{ 55196200Sscottl struct mfi_ctrl_info info; 56196200Sscottl char stripe[5]; 57214396Sjhb int error, fd, comma; 58196200Sscottl 59196200Sscottl if (ac != 1) { 60196200Sscottl warnx("show adapter: extra arguments"); 61196200Sscottl return (EINVAL); 62196200Sscottl } 63196200Sscottl 64196200Sscottl fd = mfi_open(mfi_unit); 65196200Sscottl if (fd < 0) { 66214396Sjhb error = errno; 67196200Sscottl warn("mfi_open"); 68214396Sjhb return (error); 69196200Sscottl } 70196200Sscottl 71196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 72214396Sjhb error = errno; 73196200Sscottl warn("Failed to get controller info"); 74222899Sbz close(fd); 75214396Sjhb return (error); 76196200Sscottl } 77196200Sscottl printf("mfi%d Adapter:\n", mfi_unit); 78196200Sscottl printf(" Product Name: %.80s\n", info.product_name); 79196200Sscottl printf(" Serial Number: %.32s\n", info.serial_number); 80196200Sscottl if (info.package_version[0] != '\0') 81196200Sscottl printf(" Firmware: %s\n", info.package_version); 82196200Sscottl printf(" RAID Levels:"); 83196200Sscottl#ifdef DEBUG 84196200Sscottl printf(" (%#x)", info.raid_levels); 85196200Sscottl#endif 86196200Sscottl comma = 0; 87196200Sscottl if (info.raid_levels & MFI_INFO_RAID_0) { 88196200Sscottl printf(" JBOD, RAID0"); 89196200Sscottl comma = 1; 90196200Sscottl } 91196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1) { 92196200Sscottl printf("%s RAID1", comma ? "," : ""); 93196200Sscottl comma = 1; 94196200Sscottl } 95196200Sscottl if (info.raid_levels & MFI_INFO_RAID_5) { 96196200Sscottl printf("%s RAID5", comma ? "," : ""); 97196200Sscottl comma = 1; 98196200Sscottl } 99196200Sscottl if (info.raid_levels & MFI_INFO_RAID_1E) { 100196200Sscottl printf("%s RAID1E", comma ? "," : ""); 101196200Sscottl comma = 1; 102196200Sscottl } 103196200Sscottl if (info.raid_levels & MFI_INFO_RAID_6) { 104196200Sscottl printf("%s RAID6", comma ? "," : ""); 105196200Sscottl comma = 1; 106196200Sscottl } 107196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) == 108196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) { 109196200Sscottl printf("%s RAID10", comma ? "," : ""); 110196200Sscottl comma = 1; 111196200Sscottl } 112196200Sscottl if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) == 113196200Sscottl (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) { 114196200Sscottl printf("%s RAID50", comma ? "," : ""); 115196200Sscottl comma = 1; 116196200Sscottl } 117196200Sscottl printf("\n"); 118196200Sscottl printf(" Battery Backup: "); 119196200Sscottl if (info.hw_present & MFI_INFO_HW_BBU) 120196200Sscottl printf("present\n"); 121196200Sscottl else 122196200Sscottl printf("not present\n"); 123196200Sscottl if (info.hw_present & MFI_INFO_HW_NVRAM) 124196200Sscottl printf(" NVRAM: %uK\n", info.nvram_size); 125196200Sscottl printf(" Onboard Memory: %uM\n", info.memory_size); 126196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.min); 127196200Sscottl printf(" Minimum Stripe: %s\n", stripe); 128196200Sscottl format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.max); 129196200Sscottl printf(" Maximum Stripe: %s\n", stripe); 130196200Sscottl 131196200Sscottl close(fd); 132196200Sscottl 133196200Sscottl return (0); 134196200Sscottl} 135196200SscottlMFI_COMMAND(show, adapter, show_adapter); 136196200Sscottl 137196200Sscottlstatic int 138196200Sscottlshow_battery(int ac, char **av) 139196200Sscottl{ 140196200Sscottl struct mfi_bbu_capacity_info cap; 141196200Sscottl struct mfi_bbu_design_info design; 142219717Sjhb struct mfi_bbu_status stat; 143196200Sscottl uint8_t status; 144219717Sjhb int comma, error, fd; 145196200Sscottl 146196200Sscottl if (ac != 1) { 147196200Sscottl warnx("show battery: extra arguments"); 148196200Sscottl return (EINVAL); 149196200Sscottl } 150196200Sscottl 151196200Sscottl fd = mfi_open(mfi_unit); 152196200Sscottl if (fd < 0) { 153214396Sjhb error = errno; 154196200Sscottl warn("mfi_open"); 155214396Sjhb return (error); 156196200Sscottl } 157196200Sscottl 158196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap, 159196200Sscottl sizeof(cap), NULL, 0, &status) < 0) { 160196200Sscottl if (status == MFI_STAT_NO_HW_PRESENT) { 161196200Sscottl printf("mfi%d: No battery present\n", mfi_unit); 162222899Sbz close(fd); 163196200Sscottl return (0); 164196200Sscottl } 165214396Sjhb error = errno; 166196200Sscottl warn("Failed to get capacity info"); 167222899Sbz close(fd); 168214396Sjhb return (error); 169196200Sscottl } 170196200Sscottl 171196200Sscottl if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design, 172196200Sscottl sizeof(design), NULL, 0, NULL) < 0) { 173214396Sjhb error = errno; 174196200Sscottl warn("Failed to get design info"); 175222899Sbz close(fd); 176214396Sjhb return (error); 177196200Sscottl } 178196200Sscottl 179219717Sjhb if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_STATUS, &stat, sizeof(stat), 180219717Sjhb NULL, 0, NULL) < 0) { 181219722Sjhb error = errno; 182219717Sjhb warn("Failed to get status"); 183222899Sbz close(fd); 184219722Sjhb return (error); 185219717Sjhb } 186219717Sjhb 187196200Sscottl printf("mfi%d: Battery State:\n", mfi_unit); 188219717Sjhb printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, 189196200Sscottl design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); 190219717Sjhb printf(" Serial Number: %d\n", design.serial_number); 191219717Sjhb printf(" Manufacturer: %s\n", design.mfg_name); 192219717Sjhb printf(" Model: %s\n", design.device_name); 193219717Sjhb printf(" Chemistry: %s\n", design.device_chemistry); 194219717Sjhb printf(" Design Capacity: %d mAh\n", design.design_capacity); 195219717Sjhb printf(" Full Charge Capacity: %d mAh\n", cap.full_charge_capacity); 196219717Sjhb printf(" Current Capacity: %d mAh\n", cap.remaining_capacity); 197219717Sjhb printf(" Charge Cycles: %d\n", cap.cycle_count); 198219717Sjhb printf(" Current Charge: %d%%\n", cap.relative_charge); 199219717Sjhb printf(" Design Voltage: %d mV\n", design.design_voltage); 200219717Sjhb printf(" Current Voltage: %d mV\n", stat.voltage); 201219717Sjhb printf(" Temperature: %d C\n", stat.temperature); 202219717Sjhb printf(" Status:"); 203219717Sjhb comma = 0; 204219717Sjhb if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) { 205219717Sjhb printf(" PACK_MISSING"); 206219717Sjhb comma = 1; 207219717Sjhb } 208219717Sjhb if (stat.fw_status & MFI_BBU_STATE_VOLTAGE_LOW) { 209219717Sjhb printf("%s VOLTAGE_LOW", comma ? "," : ""); 210219717Sjhb comma = 1; 211219717Sjhb } 212219717Sjhb if (stat.fw_status & MFI_BBU_STATE_TEMPERATURE_HIGH) { 213219717Sjhb printf("%s TEMPERATURE_HIGH", comma ? "," : ""); 214219717Sjhb comma = 1; 215219717Sjhb } 216219717Sjhb if (stat.fw_status & MFI_BBU_STATE_CHARGE_ACTIVE) { 217219717Sjhb printf("%s CHARGING", comma ? "," : ""); 218219717Sjhb comma = 1; 219219717Sjhb } 220219717Sjhb if (stat.fw_status & MFI_BBU_STATE_DISCHARGE_ACTIVE) { 221219717Sjhb printf("%s DISCHARGING", comma ? "," : ""); 222219717Sjhb } 223219717Sjhb if (!comma) 224219717Sjhb printf(" normal"); 225219717Sjhb printf("\n"); 226219717Sjhb switch (stat.battery_type) { 227219717Sjhb case MFI_BBU_TYPE_BBU: 228219717Sjhb printf(" State of Health: %s\n", 229219717Sjhb stat.detail.bbu.is_SOH_good ? "good" : "bad"); 230219717Sjhb break; 231219717Sjhb } 232196200Sscottl 233196200Sscottl close(fd); 234196200Sscottl 235196200Sscottl return (0); 236196200Sscottl} 237196200SscottlMFI_COMMAND(show, battery, show_battery); 238196200Sscottl 239196200Sscottlstatic void 240196200Sscottlprint_ld(struct mfi_ld_info *info, int state_len) 241196200Sscottl{ 242196200Sscottl struct mfi_ld_params *params = &info->ld_config.params; 243196200Sscottl const char *level; 244196200Sscottl char size[6], stripe[5]; 245196200Sscottl 246196200Sscottl humanize_number(size, sizeof(size), info->size * 512, 247196200Sscottl "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 248196200Sscottl format_stripe(stripe, sizeof(stripe), 249196200Sscottl info->ld_config.params.stripe_size); 250196200Sscottl level = mfi_raid_level(params->primary_raid_level, 251196200Sscottl params->secondary_raid_level); 252196200Sscottl if (state_len > 0) 253196200Sscottl printf("(%6s) %-8s %6s %-*s", size, level, stripe, state_len, 254196200Sscottl mfi_ldstate(params->state)); 255196200Sscottl else 256196200Sscottl printf("(%s) %s %s %s", size, level, stripe, 257196200Sscottl mfi_ldstate(params->state)); 258196200Sscottl} 259196200Sscottl 260196200Sscottlstatic void 261223345Sbzprint_pd(struct mfi_pd_info *info, int state_len) 262196200Sscottl{ 263196200Sscottl const char *s; 264196200Sscottl char buf[6]; 265196200Sscottl 266196200Sscottl humanize_number(buf, sizeof(buf), info->raw_size * 512, "", 267196200Sscottl HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 268196200Sscottl printf("(%6s) ", buf); 269196200Sscottl if (state_len > 0) 270196200Sscottl printf("%-*s", state_len, mfi_pdstate(info->fw_state)); 271196200Sscottl else 272196200Sscottl printf("%s", mfi_pdstate(info->fw_state)); 273196200Sscottl s = mfi_pd_inq_string(info); 274196200Sscottl if (s != NULL) 275196200Sscottl printf(" %s", s); 276196200Sscottl} 277196200Sscottl 278196200Sscottlstatic int 279196200Sscottlshow_config(int ac, char **av) 280196200Sscottl{ 281196200Sscottl struct mfi_config_data *config; 282196200Sscottl struct mfi_array *ar; 283196200Sscottl struct mfi_ld_config *ld; 284196200Sscottl struct mfi_spare *sp; 285196200Sscottl struct mfi_ld_info linfo; 286196200Sscottl struct mfi_pd_info pinfo; 287196200Sscottl uint16_t device_id; 288196200Sscottl char *p; 289214396Sjhb int error, fd, i, j; 290196200Sscottl 291196200Sscottl if (ac != 1) { 292196200Sscottl warnx("show config: extra arguments"); 293196200Sscottl return (EINVAL); 294196200Sscottl } 295196200Sscottl 296196200Sscottl fd = mfi_open(mfi_unit); 297196200Sscottl if (fd < 0) { 298214396Sjhb error = errno; 299196200Sscottl warn("mfi_open"); 300214396Sjhb return (error); 301196200Sscottl } 302196200Sscottl 303196200Sscottl /* Get the config from the controller. */ 304196200Sscottl if (mfi_config_read(fd, &config) < 0) { 305214396Sjhb error = errno; 306196200Sscottl warn("Failed to get config"); 307222899Sbz close(fd); 308214396Sjhb return (error); 309196200Sscottl } 310196200Sscottl 311196200Sscottl /* Dump out the configuration. */ 312196200Sscottl printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n", 313196200Sscottl mfi_unit, config->array_count, config->log_drv_count, 314196200Sscottl config->spares_count); 315196200Sscottl p = (char *)config->array; 316196200Sscottl 317196200Sscottl for (i = 0; i < config->array_count; i++) { 318196200Sscottl ar = (struct mfi_array *)p; 319196200Sscottl printf(" array %u of %u drives:\n", ar->array_ref, 320196200Sscottl ar->num_drives); 321196200Sscottl for (j = 0; j < ar->num_drives; j++) { 322196200Sscottl device_id = ar->pd[j].ref.v.device_id; 323223345Sbz printf(" drive %s ", mfi_drive_name(NULL, 324223345Sbz device_id, 325223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 326223345Sbz if (device_id != 0xffff) { 327196200Sscottl if (mfi_pd_get_info(fd, device_id, &pinfo, 328196200Sscottl NULL) < 0) 329196200Sscottl printf("%s", 330196200Sscottl mfi_pdstate(ar->pd[j].fw_state)); 331196200Sscottl else 332223345Sbz print_pd(&pinfo, -1); 333196200Sscottl } 334225168Sbz printf("\n"); 335196200Sscottl } 336196200Sscottl p += config->array_size; 337196200Sscottl } 338196200Sscottl 339196200Sscottl for (i = 0; i < config->log_drv_count; i++) { 340196200Sscottl ld = (struct mfi_ld_config *)p; 341196200Sscottl printf(" volume %s ", 342196200Sscottl mfi_volume_name(fd, ld->properties.ld.v.target_id)); 343196200Sscottl if (mfi_ld_get_info(fd, ld->properties.ld.v.target_id, &linfo, 344196200Sscottl NULL) < 0) { 345196200Sscottl printf("%s %s", 346196200Sscottl mfi_raid_level(ld->params.primary_raid_level, 347196200Sscottl ld->params.secondary_raid_level), 348196200Sscottl mfi_ldstate(ld->params.state)); 349196200Sscottl } else 350196200Sscottl print_ld(&linfo, -1); 351196200Sscottl if (ld->properties.name[0] != '\0') 352196200Sscottl printf(" <%s>", ld->properties.name); 353196200Sscottl printf(" spans:\n"); 354196200Sscottl for (j = 0; j < ld->params.span_depth; j++) 355196200Sscottl printf(" array %u\n", ld->span[j].array_ref); 356196200Sscottl p += config->log_drv_size; 357196200Sscottl } 358196200Sscottl 359196200Sscottl for (i = 0; i < config->spares_count; i++) { 360196200Sscottl sp = (struct mfi_spare *)p; 361223345Sbz printf(" %s spare %s ", 362196200Sscottl sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" : 363223345Sbz "global", mfi_drive_name(NULL, sp->ref.v.device_id, 364223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 365196200Sscottl if (mfi_pd_get_info(fd, sp->ref.v.device_id, &pinfo, NULL) < 0) 366196200Sscottl printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE)); 367196200Sscottl else 368223345Sbz print_pd(&pinfo, -1); 369196200Sscottl if (sp->spare_type & MFI_SPARE_DEDICATED) { 370196200Sscottl printf(" backs:\n"); 371196200Sscottl for (j = 0; j < sp->array_count; j++) 372196200Sscottl printf(" array %u\n", sp->array_ref[j]); 373196200Sscottl } else 374196200Sscottl printf("\n"); 375196200Sscottl p += config->spares_size; 376196200Sscottl } 377222899Sbz free(config); 378196200Sscottl close(fd); 379196200Sscottl 380196200Sscottl return (0); 381196200Sscottl} 382196200SscottlMFI_COMMAND(show, config, show_config); 383196200Sscottl 384196200Sscottlstatic int 385196200Sscottlshow_volumes(int ac, char **av) 386196200Sscottl{ 387196200Sscottl struct mfi_ld_list list; 388196200Sscottl struct mfi_ld_info info; 389214396Sjhb int error, fd; 390196200Sscottl u_int i, len, state_len; 391196200Sscottl 392196200Sscottl if (ac != 1) { 393196200Sscottl warnx("show volumes: extra arguments"); 394196200Sscottl return (EINVAL); 395196200Sscottl } 396196200Sscottl 397196200Sscottl fd = mfi_open(mfi_unit); 398196200Sscottl if (fd < 0) { 399214396Sjhb error = errno; 400196200Sscottl warn("mfi_open"); 401214396Sjhb return (error); 402196200Sscottl } 403196200Sscottl 404196200Sscottl /* Get the logical drive list from the controller. */ 405196200Sscottl if (mfi_ld_get_list(fd, &list, NULL) < 0) { 406214396Sjhb error = errno; 407196200Sscottl warn("Failed to get volume list"); 408222899Sbz close(fd); 409214396Sjhb return (error); 410196200Sscottl } 411196200Sscottl 412196200Sscottl /* List the volumes. */ 413196200Sscottl printf("mfi%d Volumes:\n", mfi_unit); 414196200Sscottl state_len = strlen("State"); 415196200Sscottl for (i = 0; i < list.ld_count; i++) { 416196200Sscottl len = strlen(mfi_ldstate(list.ld_list[i].state)); 417196200Sscottl if (len > state_len) 418196200Sscottl state_len = len; 419196200Sscottl } 420196200Sscottl printf(" Id Size Level Stripe "); 421196200Sscottl len = state_len - strlen("State"); 422196200Sscottl for (i = 0; i < (len + 1) / 2; i++) 423196200Sscottl printf(" "); 424196200Sscottl printf("State"); 425196200Sscottl for (i = 0; i < len / 2; i++) 426196200Sscottl printf(" "); 427196200Sscottl printf(" Cache Name\n"); 428196200Sscottl for (i = 0; i < list.ld_count; i++) { 429196200Sscottl if (mfi_ld_get_info(fd, list.ld_list[i].ld.v.target_id, &info, 430196200Sscottl NULL) < 0) { 431214396Sjhb error = errno; 432196200Sscottl warn("Failed to get info for volume %d", 433196200Sscottl list.ld_list[i].ld.v.target_id); 434222899Sbz close(fd); 435214396Sjhb return (error); 436196200Sscottl } 437196200Sscottl printf("%6s ", 438196200Sscottl mfi_volume_name(fd, list.ld_list[i].ld.v.target_id)); 439196200Sscottl print_ld(&info, state_len); 440196200Sscottl switch (info.ld_config.properties.current_cache_policy & 441196200Sscottl (MR_LD_CACHE_ALLOW_WRITE_CACHE | 442196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE)) { 443196200Sscottl case 0: 444196200Sscottl printf(" Disabled"); 445196200Sscottl break; 446196200Sscottl case MR_LD_CACHE_ALLOW_READ_CACHE: 447196200Sscottl printf(" Reads "); 448196200Sscottl break; 449196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE: 450196200Sscottl printf(" Writes "); 451196200Sscottl break; 452196200Sscottl case MR_LD_CACHE_ALLOW_WRITE_CACHE | 453196200Sscottl MR_LD_CACHE_ALLOW_READ_CACHE: 454196200Sscottl printf(" Enabled "); 455196200Sscottl break; 456196200Sscottl } 457196200Sscottl if (info.ld_config.properties.name[0] != '\0') 458196200Sscottl printf(" <%s>", info.ld_config.properties.name); 459196200Sscottl printf("\n"); 460196200Sscottl } 461196200Sscottl close(fd); 462196200Sscottl 463196200Sscottl return (0); 464196200Sscottl} 465196200SscottlMFI_COMMAND(show, volumes, show_volumes); 466196200Sscottl 467196200Sscottlstatic int 468196200Sscottlshow_drives(int ac, char **av) 469196200Sscottl{ 470196200Sscottl struct mfi_pd_list *list; 471196200Sscottl struct mfi_pd_info info; 472196200Sscottl u_int i, len, state_len; 473214396Sjhb int error, fd; 474196200Sscottl 475196200Sscottl if (ac != 1) { 476196200Sscottl warnx("show drives: extra arguments"); 477196200Sscottl return (EINVAL); 478196200Sscottl } 479196200Sscottl 480196200Sscottl fd = mfi_open(mfi_unit); 481196200Sscottl if (fd < 0) { 482214396Sjhb error = errno; 483196200Sscottl warn("mfi_open"); 484214396Sjhb return (error); 485196200Sscottl } 486196200Sscottl 487222899Sbz list = NULL; 488196200Sscottl if (mfi_pd_get_list(fd, &list, NULL) < 0) { 489214396Sjhb error = errno; 490196200Sscottl warn("Failed to get drive list"); 491222899Sbz goto error; 492196200Sscottl } 493196200Sscottl 494196200Sscottl /* Walk the list of drives to determine width of state column. */ 495196200Sscottl state_len = 0; 496196200Sscottl for (i = 0; i < list->count; i++) { 497196200Sscottl if (list->addr[i].scsi_dev_type != 0) 498196200Sscottl continue; 499196200Sscottl 500196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 501196200Sscottl NULL) < 0) { 502214396Sjhb error = errno; 503196200Sscottl warn("Failed to fetch info for drive %u", 504196200Sscottl list->addr[i].device_id); 505222899Sbz goto error; 506196200Sscottl } 507196200Sscottl len = strlen(mfi_pdstate(info.fw_state)); 508196200Sscottl if (len > state_len) 509196200Sscottl state_len = len; 510196200Sscottl } 511196200Sscottl 512196200Sscottl /* List the drives. */ 513196200Sscottl printf("mfi%d Physical Drives:\n", mfi_unit); 514196200Sscottl for (i = 0; i < list->count; i++) { 515196200Sscottl 516196200Sscottl /* Skip non-hard disks. */ 517196200Sscottl if (list->addr[i].scsi_dev_type != 0) 518196200Sscottl continue; 519196200Sscottl 520196200Sscottl /* Fetch details for this drive. */ 521196200Sscottl if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 522196200Sscottl NULL) < 0) { 523214396Sjhb error = errno; 524196200Sscottl warn("Failed to fetch info for drive %u", 525196200Sscottl list->addr[i].device_id); 526222899Sbz goto error; 527196200Sscottl } 528196200Sscottl 529223345Sbz printf("%s ", mfi_drive_name(&info, list->addr[i].device_id, 530223345Sbz MFI_DNAME_DEVICE_ID)); 531223345Sbz print_pd(&info, state_len); 532223345Sbz printf(" %s", mfi_drive_name(&info, list->addr[i].device_id, 533223345Sbz MFI_DNAME_ES)); 534196200Sscottl printf("\n"); 535196200Sscottl } 536224495Sjhb error = 0; 537222899Sbzerror: 538222899Sbz free(list); 539196200Sscottl close(fd); 540196200Sscottl 541222899Sbz return (error); 542196200Sscottl} 543196200SscottlMFI_COMMAND(show, drives, show_drives); 544196200Sscottl 545196200Sscottlint fw_name_width, fw_version_width, fw_date_width, fw_time_width; 546196200Sscottl 547196200Sscottlstatic void 548196200Sscottlscan_firmware(struct mfi_info_component *comp) 549196200Sscottl{ 550196200Sscottl int len; 551196200Sscottl 552196200Sscottl len = strlen(comp->name); 553196200Sscottl if (fw_name_width < len) 554196200Sscottl fw_name_width = len; 555196200Sscottl len = strlen(comp->version); 556196200Sscottl if (fw_version_width < len) 557196200Sscottl fw_version_width = len; 558196200Sscottl len = strlen(comp->build_date); 559196200Sscottl if (fw_date_width < len) 560196200Sscottl fw_date_width = len; 561196200Sscottl len = strlen(comp->build_time); 562196200Sscottl if (fw_time_width < len) 563196200Sscottl fw_time_width = len; 564196200Sscottl} 565196200Sscottl 566196200Sscottlstatic void 567196200Sscottldisplay_firmware(struct mfi_info_component *comp, const char *tag) 568196200Sscottl{ 569196200Sscottl 570196200Sscottl printf("%-*s %-*s %-*s %-*s %s\n", fw_name_width, comp->name, 571196200Sscottl fw_version_width, comp->version, fw_date_width, comp->build_date, 572196200Sscottl fw_time_width, comp->build_time, tag); 573196200Sscottl} 574196200Sscottl 575196200Sscottlstatic int 576196200Sscottlshow_firmware(int ac, char **av) 577196200Sscottl{ 578196200Sscottl struct mfi_ctrl_info info; 579196200Sscottl struct mfi_info_component header; 580214396Sjhb int error, fd; 581196200Sscottl u_int i; 582196200Sscottl 583196200Sscottl if (ac != 1) { 584221208Sjhb warnx("show firmware: extra arguments"); 585196200Sscottl return (EINVAL); 586196200Sscottl } 587196200Sscottl 588196200Sscottl fd = mfi_open(mfi_unit); 589196200Sscottl if (fd < 0) { 590214396Sjhb error = errno; 591196200Sscottl warn("mfi_open"); 592214396Sjhb return (error); 593196200Sscottl } 594196200Sscottl 595196200Sscottl if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 596214396Sjhb error = errno; 597196200Sscottl warn("Failed to get controller info"); 598222899Sbz close(fd); 599214396Sjhb return (error); 600196200Sscottl } 601196200Sscottl 602196200Sscottl if (info.package_version[0] != '\0') 603196200Sscottl printf("mfi%d Firmware Package Version: %s\n", mfi_unit, 604196200Sscottl info.package_version); 605196200Sscottl printf("mfi%d Firmware Images:\n", mfi_unit); 606196200Sscottl strcpy(header.name, "Name"); 607196200Sscottl strcpy(header.version, "Version"); 608196200Sscottl strcpy(header.build_date, "Date"); 609196200Sscottl strcpy(header.build_time, "Time"); 610196200Sscottl scan_firmware(&header); 611196200Sscottl if (info.image_component_count > 8) 612196200Sscottl info.image_component_count = 8; 613196200Sscottl for (i = 0; i < info.image_component_count; i++) 614196200Sscottl scan_firmware(&info.image_component[i]); 615196200Sscottl if (info.pending_image_component_count > 8) 616196200Sscottl info.pending_image_component_count = 8; 617196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 618196200Sscottl scan_firmware(&info.pending_image_component[i]); 619196200Sscottl display_firmware(&header, "Status"); 620196200Sscottl for (i = 0; i < info.image_component_count; i++) 621196200Sscottl display_firmware(&info.image_component[i], "active"); 622196200Sscottl for (i = 0; i < info.pending_image_component_count; i++) 623196200Sscottl display_firmware(&info.pending_image_component[i], "pending"); 624196200Sscottl 625196200Sscottl close(fd); 626196200Sscottl 627196200Sscottl return (0); 628196200Sscottl} 629196200SscottlMFI_COMMAND(show, firmware, show_firmware); 630221208Sjhb 631221208Sjhbstatic int 632221208Sjhbshow_progress(int ac, char **av) 633221208Sjhb{ 634221208Sjhb struct mfi_ld_list llist; 635221208Sjhb struct mfi_pd_list *plist; 636221208Sjhb struct mfi_ld_info linfo; 637221208Sjhb struct mfi_pd_info pinfo; 638221208Sjhb int busy, error, fd; 639221208Sjhb u_int i; 640221208Sjhb uint16_t device_id; 641221208Sjhb uint8_t target_id; 642221208Sjhb 643221208Sjhb if (ac != 1) { 644221208Sjhb warnx("show progress: extra arguments"); 645221208Sjhb return (EINVAL); 646221208Sjhb } 647221208Sjhb 648221208Sjhb fd = mfi_open(mfi_unit); 649221208Sjhb if (fd < 0) { 650221208Sjhb error = errno; 651221208Sjhb warn("mfi_open"); 652221208Sjhb return (error); 653221208Sjhb } 654221208Sjhb 655221208Sjhb if (mfi_ld_get_list(fd, &llist, NULL) < 0) { 656221208Sjhb error = errno; 657221208Sjhb warn("Failed to get volume list"); 658222899Sbz close(fd); 659221208Sjhb return (error); 660221208Sjhb } 661221208Sjhb if (mfi_pd_get_list(fd, &plist, NULL) < 0) { 662221208Sjhb error = errno; 663221208Sjhb warn("Failed to get drive list"); 664222899Sbz close(fd); 665221208Sjhb return (error); 666221208Sjhb } 667221208Sjhb 668222899Sbz busy = 0; 669221208Sjhb for (i = 0; i < llist.ld_count; i++) { 670221208Sjhb target_id = llist.ld_list[i].ld.v.target_id; 671221208Sjhb if (mfi_ld_get_info(fd, target_id, &linfo, NULL) < 0) { 672221208Sjhb error = errno; 673221208Sjhb warn("Failed to get info for volume %s", 674221208Sjhb mfi_volume_name(fd, target_id)); 675222899Sbz free(plist); 676222899Sbz close(fd); 677221208Sjhb return (error); 678221208Sjhb } 679221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_CC) { 680221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 681221208Sjhb mfi_display_progress("Consistency Check", 682221208Sjhb &linfo.progress.cc); 683221208Sjhb busy = 1; 684221208Sjhb } 685221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_BGI) { 686221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 687221208Sjhb mfi_display_progress("Background Init", 688221208Sjhb &linfo.progress.bgi); 689221208Sjhb busy = 1; 690221208Sjhb } 691221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_FGI) { 692221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 693221208Sjhb mfi_display_progress("Foreground Init", 694221208Sjhb &linfo.progress.fgi); 695221208Sjhb busy = 1; 696221208Sjhb } 697221208Sjhb if (linfo.progress.active & MFI_LD_PROGRESS_RECON) { 698221208Sjhb printf("volume %s ", mfi_volume_name(fd, target_id)); 699221208Sjhb mfi_display_progress("Reconstruction", 700221208Sjhb &linfo.progress.recon); 701221208Sjhb busy = 1; 702221208Sjhb } 703221208Sjhb } 704221208Sjhb 705221208Sjhb for (i = 0; i < plist->count; i++) { 706221208Sjhb if (plist->addr[i].scsi_dev_type != 0) 707221208Sjhb continue; 708221208Sjhb 709221208Sjhb device_id = plist->addr[i].device_id; 710221208Sjhb if (mfi_pd_get_info(fd, device_id, &pinfo, NULL) < 0) { 711221208Sjhb error = errno; 712221208Sjhb warn("Failed to fetch info for drive %u", device_id); 713222899Sbz free(plist); 714222899Sbz close(fd); 715221208Sjhb return (error); 716221208Sjhb } 717221208Sjhb 718221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_REBUILD) { 719223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 720223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 721221208Sjhb mfi_display_progress("Rebuild", &pinfo.prog_info.rbld); 722221208Sjhb busy = 1; 723221208Sjhb } 724221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_PATROL) { 725223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 726223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 727221208Sjhb mfi_display_progress("Patrol Read", 728221208Sjhb &pinfo.prog_info.patrol); 729221208Sjhb busy = 1; 730221208Sjhb } 731221208Sjhb if (pinfo.prog_info.active & MFI_PD_PROGRESS_CLEAR) { 732223345Sbz printf("drive %s ", mfi_drive_name(NULL, device_id, 733223345Sbz MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 734221208Sjhb mfi_display_progress("Clear", &pinfo.prog_info.clear); 735221208Sjhb busy = 1; 736221208Sjhb } 737221208Sjhb } 738221208Sjhb 739222899Sbz free(plist); 740221208Sjhb close(fd); 741221208Sjhb 742221208Sjhb if (!busy) 743221208Sjhb printf("No activity in progress for adapter mfi%d\n", mfi_unit); 744221208Sjhb 745221208Sjhb return (0); 746221208Sjhb} 747221208SjhbMFI_COMMAND(show, progress, show_progress); 748