mfi_show.c revision 235635
1/*- 2 * Copyright (c) 2008, 2009 Yahoo!, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The names of the authors may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/usr.sbin/mfiutil/mfi_show.c 235635 2012-05-18 21:50:26Z sbruno $ 30 */ 31 32#include <sys/types.h> 33#include <sys/errno.h> 34#include <err.h> 35#include <libutil.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40#include "mfiutil.h" 41 42MFI_TABLE(top, show); 43 44static void 45format_stripe(char *buf, size_t buflen, uint8_t stripe) 46{ 47 48 humanize_number(buf, buflen, (1 << stripe) * 512, "", HN_AUTOSCALE, 49 HN_B | HN_NOSPACE); 50} 51 52static int 53show_adapter(int ac, char **av) 54{ 55 struct mfi_ctrl_info info; 56 char stripe[5]; 57 int error, fd, comma; 58 59 if (ac != 1) { 60 warnx("show adapter: extra arguments"); 61 return (EINVAL); 62 } 63 64 fd = mfi_open(mfi_unit); 65 if (fd < 0) { 66 error = errno; 67 warn("mfi_open"); 68 return (error); 69 } 70 71 if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 72 error = errno; 73 warn("Failed to get controller info"); 74 close(fd); 75 return (error); 76 } 77 printf("mfi%d Adapter:\n", mfi_unit); 78 printf(" Product Name: %.80s\n", info.product_name); 79 printf(" Serial Number: %.32s\n", info.serial_number); 80 if (info.package_version[0] != '\0') 81 printf(" Firmware: %s\n", info.package_version); 82 printf(" RAID Levels:"); 83#ifdef DEBUG 84 printf(" (%#x)", info.raid_levels); 85#endif 86 comma = 0; 87 if (info.raid_levels & MFI_INFO_RAID_0) { 88 printf(" JBOD, RAID0"); 89 comma = 1; 90 } 91 if (info.raid_levels & MFI_INFO_RAID_1) { 92 printf("%s RAID1", comma ? "," : ""); 93 comma = 1; 94 } 95 if (info.raid_levels & MFI_INFO_RAID_5) { 96 printf("%s RAID5", comma ? "," : ""); 97 comma = 1; 98 } 99 if (info.raid_levels & MFI_INFO_RAID_1E) { 100 printf("%s RAID1E", comma ? "," : ""); 101 comma = 1; 102 } 103 if (info.raid_levels & MFI_INFO_RAID_6) { 104 printf("%s RAID6", comma ? "," : ""); 105 comma = 1; 106 } 107 if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) == 108 (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) { 109 printf("%s RAID10", comma ? "," : ""); 110 comma = 1; 111 } 112 if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) == 113 (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) { 114 printf("%s RAID50", comma ? "," : ""); 115 comma = 1; 116 } 117 printf("\n"); 118 printf(" Battery Backup: "); 119 if (info.hw_present & MFI_INFO_HW_BBU) 120 printf("present\n"); 121 else 122 printf("not present\n"); 123 if (info.hw_present & MFI_INFO_HW_NVRAM) 124 printf(" NVRAM: %uK\n", info.nvram_size); 125 printf(" Onboard Memory: %uM\n", info.memory_size); 126 format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.min); 127 printf(" Minimum Stripe: %s\n", stripe); 128 format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.max); 129 printf(" Maximum Stripe: %s\n", stripe); 130 131 close(fd); 132 133 return (0); 134} 135MFI_COMMAND(show, adapter, show_adapter); 136 137static int 138show_battery(int ac, char **av) 139{ 140 struct mfi_bbu_capacity_info cap; 141 struct mfi_bbu_design_info design; 142 struct mfi_bbu_status stat; 143 uint8_t status; 144 int comma, error, fd, show_capacity; 145 146 if (ac != 1) { 147 warnx("show battery: extra arguments"); 148 return (EINVAL); 149 } 150 151 fd = mfi_open(mfi_unit); 152 if (fd < 0) { 153 error = errno; 154 warn("mfi_open"); 155 return (error); 156 } 157 158 if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap, 159 sizeof(cap), NULL, 0, &status) < 0) { 160 error = errno; 161 warn("Failed to get capacity info"); 162 close(fd); 163 return (error); 164 } 165 if (status == MFI_STAT_NO_HW_PRESENT) { 166 printf("mfi%d: No battery present\n", mfi_unit); 167 close(fd); 168 return (0); 169 } 170 show_capacity = (status == MFI_STAT_OK); 171 172 if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design, 173 sizeof(design), NULL, 0, NULL) < 0) { 174 error = errno; 175 warn("Failed to get design info"); 176 close(fd); 177 return (error); 178 } 179 180 if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_STATUS, &stat, sizeof(stat), 181 NULL, 0, NULL) < 0) { 182 error = errno; 183 warn("Failed to get status"); 184 close(fd); 185 return (error); 186 } 187 188 printf("mfi%d: Battery State:\n", mfi_unit); 189 printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, 190 design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); 191 printf(" Serial Number: %d\n", design.serial_number); 192 printf(" Manufacturer: %s\n", design.mfg_name); 193 printf(" Model: %s\n", design.device_name); 194 printf(" Chemistry: %s\n", design.device_chemistry); 195 printf(" Design Capacity: %d mAh\n", design.design_capacity); 196 if (show_capacity) { 197 printf(" Full Charge Capacity: %d mAh\n", 198 cap.full_charge_capacity); 199 printf(" Current Capacity: %d mAh\n", 200 cap.remaining_capacity); 201 printf(" Charge Cycles: %d\n", cap.cycle_count); 202 printf(" Current Charge: %d%%\n", cap.relative_charge); 203 } 204 printf(" Design Voltage: %d mV\n", design.design_voltage); 205 printf(" Current Voltage: %d mV\n", stat.voltage); 206 printf(" Temperature: %d C\n", stat.temperature); 207 printf(" Status:"); 208 comma = 0; 209 if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) { 210 printf(" PACK_MISSING"); 211 comma = 1; 212 } 213 if (stat.fw_status & MFI_BBU_STATE_VOLTAGE_LOW) { 214 printf("%s VOLTAGE_LOW", comma ? "," : ""); 215 comma = 1; 216 } 217 if (stat.fw_status & MFI_BBU_STATE_TEMPERATURE_HIGH) { 218 printf("%s TEMPERATURE_HIGH", comma ? "," : ""); 219 comma = 1; 220 } 221 if (stat.fw_status & MFI_BBU_STATE_CHARGE_ACTIVE) { 222 printf("%s CHARGING", comma ? "," : ""); 223 comma = 1; 224 } 225 if (stat.fw_status & MFI_BBU_STATE_DISCHARGE_ACTIVE) { 226 printf("%s DISCHARGING", comma ? "," : ""); 227 comma = 1; 228 } 229 if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_REQ) { 230 printf("%s LEARN_CYCLE_REQUESTED", comma ? "," : ""); 231 comma = 1; 232 } 233 if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_ACTIVE) { 234 printf("%s LEARN_CYCLE_ACTIVE", comma ? "," : ""); 235 comma = 1; 236 } 237 if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_FAIL) { 238 printf("%s LEARN_CYCLE_FAIL", comma ? "," : ""); 239 comma = 1; 240 } 241 if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_TIMEOUT) { 242 printf("%s LEARN_CYCLE_TIMEOUT", comma ? "," : ""); 243 comma = 1; 244 } 245 if (stat.fw_status & MFI_BBU_STATE_I2C_ERR_DETECT) { 246 printf("%s I2C_ERROR_DETECT", comma ? "," : ""); 247 comma = 1; 248 } 249 250 if (!comma) 251 printf(" normal"); 252 printf("\n"); 253 switch (stat.battery_type) { 254 case MFI_BBU_TYPE_BBU: 255 printf(" State of Health: %s\n", 256 stat.detail.bbu.is_SOH_good ? "good" : "bad"); 257 break; 258 } 259 260 close(fd); 261 262 return (0); 263} 264MFI_COMMAND(show, battery, show_battery); 265 266static void 267print_ld(struct mfi_ld_info *info, int state_len) 268{ 269 struct mfi_ld_params *params = &info->ld_config.params; 270 const char *level; 271 char size[6], stripe[5]; 272 273 humanize_number(size, sizeof(size), info->size * 512, 274 "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 275 format_stripe(stripe, sizeof(stripe), 276 info->ld_config.params.stripe_size); 277 level = mfi_raid_level(params->primary_raid_level, 278 params->secondary_raid_level); 279 if (state_len > 0) 280 printf("(%6s) %-8s %6s %-*s", size, level, stripe, state_len, 281 mfi_ldstate(params->state)); 282 else 283 printf("(%s) %s %s %s", size, level, stripe, 284 mfi_ldstate(params->state)); 285} 286 287static void 288print_pd(struct mfi_pd_info *info, int state_len) 289{ 290 const char *s; 291 char buf[6]; 292 293 humanize_number(buf, sizeof(buf), info->raw_size * 512, "", 294 HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 295 printf("(%6s) ", buf); 296 if (state_len > 0) 297 printf("%-*s", state_len, mfi_pdstate(info->fw_state)); 298 else 299 printf("%s", mfi_pdstate(info->fw_state)); 300 s = mfi_pd_inq_string(info); 301 if (s != NULL) 302 printf(" %s", s); 303} 304 305static int 306show_config(int ac, char **av) 307{ 308 struct mfi_config_data *config; 309 struct mfi_array *ar; 310 struct mfi_ld_config *ld; 311 struct mfi_spare *sp; 312 struct mfi_ld_info linfo; 313 struct mfi_pd_info pinfo; 314 uint16_t device_id; 315 char *p; 316 int error, fd, i, j; 317 318 if (ac != 1) { 319 warnx("show config: extra arguments"); 320 return (EINVAL); 321 } 322 323 fd = mfi_open(mfi_unit); 324 if (fd < 0) { 325 error = errno; 326 warn("mfi_open"); 327 return (error); 328 } 329 330 /* Get the config from the controller. */ 331 if (mfi_config_read(fd, &config) < 0) { 332 error = errno; 333 warn("Failed to get config"); 334 close(fd); 335 return (error); 336 } 337 338 /* Dump out the configuration. */ 339 printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n", 340 mfi_unit, config->array_count, config->log_drv_count, 341 config->spares_count); 342 p = (char *)config->array; 343 344 for (i = 0; i < config->array_count; i++) { 345 ar = (struct mfi_array *)p; 346 printf(" array %u of %u drives:\n", ar->array_ref, 347 ar->num_drives); 348 for (j = 0; j < ar->num_drives; j++) { 349 device_id = ar->pd[j].ref.v.device_id; 350 printf(" drive %s ", mfi_drive_name(NULL, 351 device_id, 352 MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 353 if (device_id != 0xffff) { 354 if (mfi_pd_get_info(fd, device_id, &pinfo, 355 NULL) < 0) 356 printf("%s", 357 mfi_pdstate(ar->pd[j].fw_state)); 358 else 359 print_pd(&pinfo, -1); 360 } 361 printf("\n"); 362 } 363 p += config->array_size; 364 } 365 366 for (i = 0; i < config->log_drv_count; i++) { 367 ld = (struct mfi_ld_config *)p; 368 printf(" volume %s ", 369 mfi_volume_name(fd, ld->properties.ld.v.target_id)); 370 if (mfi_ld_get_info(fd, ld->properties.ld.v.target_id, &linfo, 371 NULL) < 0) { 372 printf("%s %s", 373 mfi_raid_level(ld->params.primary_raid_level, 374 ld->params.secondary_raid_level), 375 mfi_ldstate(ld->params.state)); 376 } else 377 print_ld(&linfo, -1); 378 if (ld->properties.name[0] != '\0') 379 printf(" <%s>", ld->properties.name); 380 printf(" spans:\n"); 381 for (j = 0; j < ld->params.span_depth; j++) 382 printf(" array %u\n", ld->span[j].array_ref); 383 p += config->log_drv_size; 384 } 385 386 for (i = 0; i < config->spares_count; i++) { 387 sp = (struct mfi_spare *)p; 388 printf(" %s spare %s ", 389 sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" : 390 "global", mfi_drive_name(NULL, sp->ref.v.device_id, 391 MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 392 if (mfi_pd_get_info(fd, sp->ref.v.device_id, &pinfo, NULL) < 0) 393 printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE)); 394 else 395 print_pd(&pinfo, -1); 396 if (sp->spare_type & MFI_SPARE_DEDICATED) { 397 printf(" backs:\n"); 398 for (j = 0; j < sp->array_count; j++) 399 printf(" array %u\n", sp->array_ref[j]); 400 } else 401 printf("\n"); 402 p += config->spares_size; 403 } 404 free(config); 405 close(fd); 406 407 return (0); 408} 409MFI_COMMAND(show, config, show_config); 410 411static int 412show_volumes(int ac, char **av) 413{ 414 struct mfi_ld_list list; 415 struct mfi_ld_info info; 416 int error, fd; 417 u_int i, len, state_len; 418 419 if (ac != 1) { 420 warnx("show volumes: extra arguments"); 421 return (EINVAL); 422 } 423 424 fd = mfi_open(mfi_unit); 425 if (fd < 0) { 426 error = errno; 427 warn("mfi_open"); 428 return (error); 429 } 430 431 /* Get the logical drive list from the controller. */ 432 if (mfi_ld_get_list(fd, &list, NULL) < 0) { 433 error = errno; 434 warn("Failed to get volume list"); 435 close(fd); 436 return (error); 437 } 438 439 /* List the volumes. */ 440 printf("mfi%d Volumes:\n", mfi_unit); 441 state_len = strlen("State"); 442 for (i = 0; i < list.ld_count; i++) { 443 len = strlen(mfi_ldstate(list.ld_list[i].state)); 444 if (len > state_len) 445 state_len = len; 446 } 447 printf(" Id Size Level Stripe "); 448 len = state_len - strlen("State"); 449 for (i = 0; i < (len + 1) / 2; i++) 450 printf(" "); 451 printf("State"); 452 for (i = 0; i < len / 2; i++) 453 printf(" "); 454 printf(" Cache Name\n"); 455 for (i = 0; i < list.ld_count; i++) { 456 if (mfi_ld_get_info(fd, list.ld_list[i].ld.v.target_id, &info, 457 NULL) < 0) { 458 error = errno; 459 warn("Failed to get info for volume %d", 460 list.ld_list[i].ld.v.target_id); 461 close(fd); 462 return (error); 463 } 464 printf("%6s ", 465 mfi_volume_name(fd, list.ld_list[i].ld.v.target_id)); 466 print_ld(&info, state_len); 467 switch (info.ld_config.properties.current_cache_policy & 468 (MR_LD_CACHE_ALLOW_WRITE_CACHE | 469 MR_LD_CACHE_ALLOW_READ_CACHE)) { 470 case 0: 471 printf(" Disabled"); 472 break; 473 case MR_LD_CACHE_ALLOW_READ_CACHE: 474 printf(" Reads "); 475 break; 476 case MR_LD_CACHE_ALLOW_WRITE_CACHE: 477 printf(" Writes "); 478 break; 479 case MR_LD_CACHE_ALLOW_WRITE_CACHE | 480 MR_LD_CACHE_ALLOW_READ_CACHE: 481 printf(" Enabled "); 482 break; 483 } 484 if (info.ld_config.properties.name[0] != '\0') 485 printf(" <%s>", info.ld_config.properties.name); 486 printf("\n"); 487 } 488 close(fd); 489 490 return (0); 491} 492MFI_COMMAND(show, volumes, show_volumes); 493 494static int 495show_drives(int ac, char **av) 496{ 497 struct mfi_pd_list *list; 498 struct mfi_pd_info info; 499 u_int i, len, state_len; 500 int error, fd; 501 502 if (ac != 1) { 503 warnx("show drives: extra arguments"); 504 return (EINVAL); 505 } 506 507 fd = mfi_open(mfi_unit); 508 if (fd < 0) { 509 error = errno; 510 warn("mfi_open"); 511 return (error); 512 } 513 514 list = NULL; 515 if (mfi_pd_get_list(fd, &list, NULL) < 0) { 516 error = errno; 517 warn("Failed to get drive list"); 518 goto error; 519 } 520 521 /* Walk the list of drives to determine width of state column. */ 522 state_len = 0; 523 for (i = 0; i < list->count; i++) { 524 if (list->addr[i].scsi_dev_type != 0) 525 continue; 526 527 if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 528 NULL) < 0) { 529 error = errno; 530 warn("Failed to fetch info for drive %u", 531 list->addr[i].device_id); 532 goto error; 533 } 534 len = strlen(mfi_pdstate(info.fw_state)); 535 if (len > state_len) 536 state_len = len; 537 } 538 539 /* List the drives. */ 540 printf("mfi%d Physical Drives:\n", mfi_unit); 541 for (i = 0; i < list->count; i++) { 542 543 /* Skip non-hard disks. */ 544 if (list->addr[i].scsi_dev_type != 0) 545 continue; 546 547 /* Fetch details for this drive. */ 548 if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, 549 NULL) < 0) { 550 error = errno; 551 warn("Failed to fetch info for drive %u", 552 list->addr[i].device_id); 553 goto error; 554 } 555 556 printf("%s ", mfi_drive_name(&info, list->addr[i].device_id, 557 MFI_DNAME_DEVICE_ID)); 558 print_pd(&info, state_len); 559 printf(" %s", mfi_drive_name(&info, list->addr[i].device_id, 560 MFI_DNAME_ES)); 561 printf("\n"); 562 } 563 error = 0; 564error: 565 free(list); 566 close(fd); 567 568 return (error); 569} 570MFI_COMMAND(show, drives, show_drives); 571 572int fw_name_width, fw_version_width, fw_date_width, fw_time_width; 573 574static void 575scan_firmware(struct mfi_info_component *comp) 576{ 577 int len; 578 579 len = strlen(comp->name); 580 if (fw_name_width < len) 581 fw_name_width = len; 582 len = strlen(comp->version); 583 if (fw_version_width < len) 584 fw_version_width = len; 585 len = strlen(comp->build_date); 586 if (fw_date_width < len) 587 fw_date_width = len; 588 len = strlen(comp->build_time); 589 if (fw_time_width < len) 590 fw_time_width = len; 591} 592 593static void 594display_firmware(struct mfi_info_component *comp, const char *tag) 595{ 596 597 printf("%-*s %-*s %-*s %-*s %s\n", fw_name_width, comp->name, 598 fw_version_width, comp->version, fw_date_width, comp->build_date, 599 fw_time_width, comp->build_time, tag); 600} 601 602static int 603show_firmware(int ac, char **av) 604{ 605 struct mfi_ctrl_info info; 606 struct mfi_info_component header; 607 int error, fd; 608 u_int i; 609 610 if (ac != 1) { 611 warnx("show firmware: extra arguments"); 612 return (EINVAL); 613 } 614 615 fd = mfi_open(mfi_unit); 616 if (fd < 0) { 617 error = errno; 618 warn("mfi_open"); 619 return (error); 620 } 621 622 if (mfi_ctrl_get_info(fd, &info, NULL) < 0) { 623 error = errno; 624 warn("Failed to get controller info"); 625 close(fd); 626 return (error); 627 } 628 629 if (info.package_version[0] != '\0') 630 printf("mfi%d Firmware Package Version: %s\n", mfi_unit, 631 info.package_version); 632 printf("mfi%d Firmware Images:\n", mfi_unit); 633 strcpy(header.name, "Name"); 634 strcpy(header.version, "Version"); 635 strcpy(header.build_date, "Date"); 636 strcpy(header.build_time, "Time"); 637 scan_firmware(&header); 638 if (info.image_component_count > 8) 639 info.image_component_count = 8; 640 for (i = 0; i < info.image_component_count; i++) 641 scan_firmware(&info.image_component[i]); 642 if (info.pending_image_component_count > 8) 643 info.pending_image_component_count = 8; 644 for (i = 0; i < info.pending_image_component_count; i++) 645 scan_firmware(&info.pending_image_component[i]); 646 display_firmware(&header, "Status"); 647 for (i = 0; i < info.image_component_count; i++) 648 display_firmware(&info.image_component[i], "active"); 649 for (i = 0; i < info.pending_image_component_count; i++) 650 display_firmware(&info.pending_image_component[i], "pending"); 651 652 close(fd); 653 654 return (0); 655} 656MFI_COMMAND(show, firmware, show_firmware); 657 658static int 659show_progress(int ac, char **av) 660{ 661 struct mfi_ld_list llist; 662 struct mfi_pd_list *plist; 663 struct mfi_ld_info linfo; 664 struct mfi_pd_info pinfo; 665 int busy, error, fd; 666 u_int i; 667 uint16_t device_id; 668 uint8_t target_id; 669 670 if (ac != 1) { 671 warnx("show progress: extra arguments"); 672 return (EINVAL); 673 } 674 675 fd = mfi_open(mfi_unit); 676 if (fd < 0) { 677 error = errno; 678 warn("mfi_open"); 679 return (error); 680 } 681 682 if (mfi_ld_get_list(fd, &llist, NULL) < 0) { 683 error = errno; 684 warn("Failed to get volume list"); 685 close(fd); 686 return (error); 687 } 688 if (mfi_pd_get_list(fd, &plist, NULL) < 0) { 689 error = errno; 690 warn("Failed to get drive list"); 691 close(fd); 692 return (error); 693 } 694 695 busy = 0; 696 for (i = 0; i < llist.ld_count; i++) { 697 target_id = llist.ld_list[i].ld.v.target_id; 698 if (mfi_ld_get_info(fd, target_id, &linfo, NULL) < 0) { 699 error = errno; 700 warn("Failed to get info for volume %s", 701 mfi_volume_name(fd, target_id)); 702 free(plist); 703 close(fd); 704 return (error); 705 } 706 if (linfo.progress.active & MFI_LD_PROGRESS_CC) { 707 printf("volume %s ", mfi_volume_name(fd, target_id)); 708 mfi_display_progress("Consistency Check", 709 &linfo.progress.cc); 710 busy = 1; 711 } 712 if (linfo.progress.active & MFI_LD_PROGRESS_BGI) { 713 printf("volume %s ", mfi_volume_name(fd, target_id)); 714 mfi_display_progress("Background Init", 715 &linfo.progress.bgi); 716 busy = 1; 717 } 718 if (linfo.progress.active & MFI_LD_PROGRESS_FGI) { 719 printf("volume %s ", mfi_volume_name(fd, target_id)); 720 mfi_display_progress("Foreground Init", 721 &linfo.progress.fgi); 722 busy = 1; 723 } 724 if (linfo.progress.active & MFI_LD_PROGRESS_RECON) { 725 printf("volume %s ", mfi_volume_name(fd, target_id)); 726 mfi_display_progress("Reconstruction", 727 &linfo.progress.recon); 728 busy = 1; 729 } 730 } 731 732 for (i = 0; i < plist->count; i++) { 733 if (plist->addr[i].scsi_dev_type != 0) 734 continue; 735 736 device_id = plist->addr[i].device_id; 737 if (mfi_pd_get_info(fd, device_id, &pinfo, NULL) < 0) { 738 error = errno; 739 warn("Failed to fetch info for drive %u", device_id); 740 free(plist); 741 close(fd); 742 return (error); 743 } 744 745 if (pinfo.prog_info.active & MFI_PD_PROGRESS_REBUILD) { 746 printf("drive %s ", mfi_drive_name(NULL, device_id, 747 MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 748 mfi_display_progress("Rebuild", &pinfo.prog_info.rbld); 749 busy = 1; 750 } 751 if (pinfo.prog_info.active & MFI_PD_PROGRESS_PATROL) { 752 printf("drive %s ", mfi_drive_name(NULL, device_id, 753 MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 754 mfi_display_progress("Patrol Read", 755 &pinfo.prog_info.patrol); 756 busy = 1; 757 } 758 if (pinfo.prog_info.active & MFI_PD_PROGRESS_CLEAR) { 759 printf("drive %s ", mfi_drive_name(NULL, device_id, 760 MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); 761 mfi_display_progress("Clear", &pinfo.prog_info.clear); 762 busy = 1; 763 } 764 } 765 766 free(plist); 767 close(fd); 768 769 if (!busy) 770 printf("No activity in progress for adapter mfi%d\n", mfi_unit); 771 772 return (0); 773} 774MFI_COMMAND(show, progress, show_progress); 775