2 * Copyright (c) 2008, 2009 Yahoo!, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
29 * $FreeBSD: src/usr.sbin/mfiutil/mfi_show.c,v 1.10 2011/09/27 14:28:07 emaste Exp $
32 #include <sys/types.h>
33 #include <sys/errno.h>
45 format_stripe(char *buf
, size_t buflen
, uint8_t stripe
)
48 humanize_number(buf
, buflen
, (1 << stripe
) * 512, "", HN_AUTOSCALE
,
53 show_adapter(int ac
, char **av
)
55 struct mfi_ctrl_info info
;
60 warnx("show adapter: extra arguments");
64 fd
= mfi_open(mfi_unit
);
71 if (mfi_ctrl_get_info(fd
, &info
, NULL
) < 0) {
73 warn("Failed to get controller info");
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:");
84 printf(" (%#x)", info
.raid_levels
);
87 if (info
.raid_levels
& MFI_INFO_RAID_0
) {
88 printf(" JBOD, RAID0");
91 if (info
.raid_levels
& MFI_INFO_RAID_1
) {
92 printf("%s RAID1", comma
? "," : "");
95 if (info
.raid_levels
& MFI_INFO_RAID_5
) {
96 printf("%s RAID5", comma
? "," : "");
99 if (info
.raid_levels
& MFI_INFO_RAID_1E
) {
100 printf("%s RAID1E", comma
? "," : "");
103 if (info
.raid_levels
& MFI_INFO_RAID_6
) {
104 printf("%s RAID6", comma
? "," : "");
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
? "," : "");
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
? "," : "");
118 printf(" Battery Backup: ");
119 if (info
.hw_present
& MFI_INFO_HW_BBU
)
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
);
135 MFI_COMMAND(show
, adapter
, show_adapter
);
138 show_battery(int ac
, char **av
)
140 struct mfi_bbu_capacity_info cap
;
141 struct mfi_bbu_design_info design
;
142 struct mfi_bbu_status stat
;
144 int comma
, error
, fd
, show_capacity
;
147 warnx("show battery: extra arguments");
151 fd
= mfi_open(mfi_unit
);
158 if (mfi_dcmd_command(fd
, MFI_DCMD_BBU_GET_CAPACITY_INFO
, &cap
,
159 sizeof(cap
), NULL
, 0, &status
) < 0) {
161 warn("Failed to get capacity info");
165 if (status
== MFI_STAT_NO_HW_PRESENT
) {
166 printf("mfi%d: No battery present\n", mfi_unit
);
170 show_capacity
= (status
== MFI_STAT_OK
);
172 if (mfi_dcmd_command(fd
, MFI_DCMD_BBU_GET_DESIGN_INFO
, &design
,
173 sizeof(design
), NULL
, 0, NULL
) < 0) {
175 warn("Failed to get design info");
180 if (mfi_dcmd_command(fd
, MFI_DCMD_BBU_GET_STATUS
, &stat
, sizeof(stat
),
181 NULL
, 0, NULL
) < 0) {
183 warn("Failed to get status");
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
);
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
);
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
);
209 if (stat
.fw_status
& MFI_BBU_STATE_PACK_MISSING
) {
210 printf(" PACK_MISSING");
213 if (stat
.fw_status
& MFI_BBU_STATE_VOLTAGE_LOW
) {
214 printf("%s VOLTAGE_LOW", comma
? "," : "");
217 if (stat
.fw_status
& MFI_BBU_STATE_TEMPERATURE_HIGH
) {
218 printf("%s TEMPERATURE_HIGH", comma
? "," : "");
221 if (stat
.fw_status
& MFI_BBU_STATE_CHARGE_ACTIVE
) {
222 printf("%s CHARGING", comma
? "," : "");
225 if (stat
.fw_status
& MFI_BBU_STATE_DISCHARGE_ACTIVE
) {
226 printf("%s DISCHARGING", comma
? "," : "");
231 switch (stat
.battery_type
) {
232 case MFI_BBU_TYPE_BBU
:
233 printf(" State of Health: %s\n",
234 stat
.detail
.bbu
.is_SOH_good
? "good" : "bad");
242 MFI_COMMAND(show
, battery
, show_battery
);
245 print_ld(struct mfi_ld_info
*info
, int state_len
)
247 struct mfi_ld_params
*params
= &info
->ld_config
.params
;
249 char size
[6], stripe
[5];
251 humanize_number(size
, sizeof(size
), info
->size
* 512,
252 "", HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
);
253 format_stripe(stripe
, sizeof(stripe
),
254 info
->ld_config
.params
.stripe_size
);
255 level
= mfi_raid_level(params
->primary_raid_level
,
256 params
->secondary_raid_level
);
258 printf("(%6s) %-8s %6s %-*s", size
, level
, stripe
, state_len
,
259 mfi_ldstate(params
->state
));
261 printf("(%s) %s %s %s", size
, level
, stripe
,
262 mfi_ldstate(params
->state
));
266 print_pd(struct mfi_pd_info
*info
, int state_len
)
271 humanize_number(buf
, sizeof(buf
), info
->raw_size
* 512, "",
272 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
|HN_DECIMAL
);
273 printf("(%6s) ", buf
);
275 printf("%-*s", state_len
, mfi_pdstate(info
->fw_state
));
277 printf("%s", mfi_pdstate(info
->fw_state
));
278 s
= mfi_pd_inq_string(info
);
284 show_config(int ac
, char **av
)
286 struct mfi_config_data
*config
;
287 struct mfi_array
*ar
;
288 struct mfi_ld_config
*ld
;
289 struct mfi_spare
*sp
;
290 struct mfi_ld_info linfo
;
291 struct mfi_pd_info pinfo
;
297 warnx("show config: extra arguments");
301 fd
= mfi_open(mfi_unit
);
308 /* Get the config from the controller. */
309 if (mfi_config_read(fd
, &config
) < 0) {
311 warn("Failed to get config");
316 /* Dump out the configuration. */
317 printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n",
318 mfi_unit
, config
->array_count
, config
->log_drv_count
,
319 config
->spares_count
);
320 p
= (char *)config
->array
;
322 for (i
= 0; i
< config
->array_count
; i
++) {
323 ar
= (struct mfi_array
*)p
;
324 printf(" array %u of %u drives:\n", ar
->array_ref
,
326 for (j
= 0; j
< ar
->num_drives
; j
++) {
327 device_id
= ar
->pd
[j
].ref
.v
.device_id
;
328 printf(" drive %s ", mfi_drive_name(NULL
,
330 MFI_DNAME_DEVICE_ID
|MFI_DNAME_HONOR_OPTS
));
331 if (device_id
!= 0xffff) {
332 if (mfi_pd_get_info(fd
, device_id
, &pinfo
,
335 mfi_pdstate(ar
->pd
[j
].fw_state
));
337 print_pd(&pinfo
, -1);
341 p
+= config
->array_size
;
344 for (i
= 0; i
< config
->log_drv_count
; i
++) {
345 ld
= (struct mfi_ld_config
*)p
;
346 printf(" volume %s ",
347 mfi_volume_name(fd
, ld
->properties
.ld
.v
.target_id
));
348 if (mfi_ld_get_info(fd
, ld
->properties
.ld
.v
.target_id
, &linfo
,
351 mfi_raid_level(ld
->params
.primary_raid_level
,
352 ld
->params
.secondary_raid_level
),
353 mfi_ldstate(ld
->params
.state
));
355 print_ld(&linfo
, -1);
356 if (ld
->properties
.name
[0] != '\0')
357 printf(" <%s>", ld
->properties
.name
);
359 for (j
= 0; j
< ld
->params
.span_depth
; j
++)
360 printf(" array %u\n", ld
->span
[j
].array_ref
);
361 p
+= config
->log_drv_size
;
364 for (i
= 0; i
< config
->spares_count
; i
++) {
365 sp
= (struct mfi_spare
*)p
;
366 printf(" %s spare %s ",
367 sp
->spare_type
& MFI_SPARE_DEDICATED
? "dedicated" :
368 "global", mfi_drive_name(NULL
, sp
->ref
.v
.device_id
,
369 MFI_DNAME_DEVICE_ID
|MFI_DNAME_HONOR_OPTS
));
370 if (mfi_pd_get_info(fd
, sp
->ref
.v
.device_id
, &pinfo
, NULL
) < 0)
371 printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE
));
373 print_pd(&pinfo
, -1);
374 if (sp
->spare_type
& MFI_SPARE_DEDICATED
) {
376 for (j
= 0; j
< sp
->array_count
; j
++)
377 printf(" array %u\n", sp
->array_ref
[j
]);
380 p
+= config
->spares_size
;
387 MFI_COMMAND(show
, config
, show_config
);
390 show_volumes(int ac
, char **av
)
392 struct mfi_ld_list list
;
393 struct mfi_ld_info info
;
395 u_int i
, len
, state_len
;
398 warnx("show volumes: extra arguments");
402 fd
= mfi_open(mfi_unit
);
409 /* Get the logical drive list from the controller. */
410 if (mfi_ld_get_list(fd
, &list
, NULL
) < 0) {
412 warn("Failed to get volume list");
417 /* List the volumes. */
418 printf("mfi%d Volumes:\n", mfi_unit
);
419 state_len
= strlen("State");
420 for (i
= 0; i
< list
.ld_count
; i
++) {
421 len
= strlen(mfi_ldstate(list
.ld_list
[i
].state
));
425 printf(" Id Size Level Stripe ");
426 len
= state_len
- strlen("State");
427 for (i
= 0; i
< (len
+ 1) / 2; i
++)
430 for (i
= 0; i
< len
/ 2; i
++)
432 printf(" Cache Name\n");
433 for (i
= 0; i
< list
.ld_count
; i
++) {
434 if (mfi_ld_get_info(fd
, list
.ld_list
[i
].ld
.v
.target_id
, &info
,
437 warn("Failed to get info for volume %d",
438 list
.ld_list
[i
].ld
.v
.target_id
);
443 mfi_volume_name(fd
, list
.ld_list
[i
].ld
.v
.target_id
));
444 print_ld(&info
, state_len
);
445 switch (info
.ld_config
.properties
.current_cache_policy
&
446 (MR_LD_CACHE_ALLOW_WRITE_CACHE
|
447 MR_LD_CACHE_ALLOW_READ_CACHE
)) {
451 case MR_LD_CACHE_ALLOW_READ_CACHE
:
454 case MR_LD_CACHE_ALLOW_WRITE_CACHE
:
457 case MR_LD_CACHE_ALLOW_WRITE_CACHE
|
458 MR_LD_CACHE_ALLOW_READ_CACHE
:
462 if (info
.ld_config
.properties
.name
[0] != '\0')
463 printf(" <%s>", info
.ld_config
.properties
.name
);
470 MFI_COMMAND(show
, volumes
, show_volumes
);
473 show_drives(int ac
, char **av
)
475 struct mfi_pd_list
*list
;
476 struct mfi_pd_info info
;
477 u_int i
, len
, state_len
;
481 warnx("show drives: extra arguments");
485 fd
= mfi_open(mfi_unit
);
493 if (mfi_pd_get_list(fd
, &list
, NULL
) < 0) {
495 warn("Failed to get drive list");
499 /* Walk the list of drives to determine width of state column. */
501 for (i
= 0; i
< list
->count
; i
++) {
502 if (list
->addr
[i
].scsi_dev_type
!= 0)
505 if (mfi_pd_get_info(fd
, list
->addr
[i
].device_id
, &info
,
508 warn("Failed to fetch info for drive %u",
509 list
->addr
[i
].device_id
);
512 len
= strlen(mfi_pdstate(info
.fw_state
));
517 /* List the drives. */
518 printf("mfi%d Physical Drives:\n", mfi_unit
);
519 for (i
= 0; i
< list
->count
; i
++) {
521 /* Skip non-hard disks. */
522 if (list
->addr
[i
].scsi_dev_type
!= 0)
525 /* Fetch details for this drive. */
526 if (mfi_pd_get_info(fd
, list
->addr
[i
].device_id
, &info
,
529 warn("Failed to fetch info for drive %u",
530 list
->addr
[i
].device_id
);
534 printf("%s ", mfi_drive_name(&info
, list
->addr
[i
].device_id
,
535 MFI_DNAME_DEVICE_ID
));
536 print_pd(&info
, state_len
);
537 printf(" %s", mfi_drive_name(&info
, list
->addr
[i
].device_id
,
548 MFI_COMMAND(show
, drives
, show_drives
);
550 int fw_name_width
, fw_version_width
, fw_date_width
, fw_time_width
;
553 scan_firmware(struct mfi_info_component
*comp
)
557 len
= strlen(comp
->name
);
558 if (fw_name_width
< len
)
560 len
= strlen(comp
->version
);
561 if (fw_version_width
< len
)
562 fw_version_width
= len
;
563 len
= strlen(comp
->build_date
);
564 if (fw_date_width
< len
)
566 len
= strlen(comp
->build_time
);
567 if (fw_time_width
< len
)
572 display_firmware(struct mfi_info_component
*comp
, const char *tag
)
575 printf("%-*s %-*s %-*s %-*s %s\n", fw_name_width
, comp
->name
,
576 fw_version_width
, comp
->version
, fw_date_width
, comp
->build_date
,
577 fw_time_width
, comp
->build_time
, tag
);
581 show_firmware(int ac
, char **av
)
583 struct mfi_ctrl_info info
;
584 struct mfi_info_component header
;
589 warnx("show firmware: extra arguments");
593 fd
= mfi_open(mfi_unit
);
600 if (mfi_ctrl_get_info(fd
, &info
, NULL
) < 0) {
602 warn("Failed to get controller info");
607 if (info
.package_version
[0] != '\0')
608 printf("mfi%d Firmware Package Version: %s\n", mfi_unit
,
609 info
.package_version
);
610 printf("mfi%d Firmware Images:\n", mfi_unit
);
611 strcpy(header
.name
, "Name");
612 strcpy(header
.version
, "Version");
613 strcpy(header
.build_date
, "Date");
614 strcpy(header
.build_time
, "Time");
615 scan_firmware(&header
);
616 if (info
.image_component_count
> 8)
617 info
.image_component_count
= 8;
618 for (i
= 0; i
< info
.image_component_count
; i
++)
619 scan_firmware(&info
.image_component
[i
]);
620 if (info
.pending_image_component_count
> 8)
621 info
.pending_image_component_count
= 8;
622 for (i
= 0; i
< info
.pending_image_component_count
; i
++)
623 scan_firmware(&info
.pending_image_component
[i
]);
624 display_firmware(&header
, "Status");
625 for (i
= 0; i
< info
.image_component_count
; i
++)
626 display_firmware(&info
.image_component
[i
], "active");
627 for (i
= 0; i
< info
.pending_image_component_count
; i
++)
628 display_firmware(&info
.pending_image_component
[i
], "pending");
634 MFI_COMMAND(show
, firmware
, show_firmware
);
637 show_progress(int ac
, char **av
)
639 struct mfi_ld_list llist
;
640 struct mfi_pd_list
*plist
;
641 struct mfi_ld_info linfo
;
642 struct mfi_pd_info pinfo
;
649 warnx("show progress: extra arguments");
653 fd
= mfi_open(mfi_unit
);
660 if (mfi_ld_get_list(fd
, &llist
, NULL
) < 0) {
662 warn("Failed to get volume list");
666 if (mfi_pd_get_list(fd
, &plist
, NULL
) < 0) {
668 warn("Failed to get drive list");
674 for (i
= 0; i
< llist
.ld_count
; i
++) {
675 target_id
= llist
.ld_list
[i
].ld
.v
.target_id
;
676 if (mfi_ld_get_info(fd
, target_id
, &linfo
, NULL
) < 0) {
678 warn("Failed to get info for volume %s",
679 mfi_volume_name(fd
, target_id
));
684 if (linfo
.progress
.active
& MFI_LD_PROGRESS_CC
) {
685 printf("volume %s ", mfi_volume_name(fd
, target_id
));
686 mfi_display_progress("Consistency Check",
690 if (linfo
.progress
.active
& MFI_LD_PROGRESS_BGI
) {
691 printf("volume %s ", mfi_volume_name(fd
, target_id
));
692 mfi_display_progress("Background Init",
693 &linfo
.progress
.bgi
);
696 if (linfo
.progress
.active
& MFI_LD_PROGRESS_FGI
) {
697 printf("volume %s ", mfi_volume_name(fd
, target_id
));
698 mfi_display_progress("Foreground Init",
699 &linfo
.progress
.fgi
);
702 if (linfo
.progress
.active
& MFI_LD_PROGRESS_RECON
) {
703 printf("volume %s ", mfi_volume_name(fd
, target_id
));
704 mfi_display_progress("Reconstruction",
705 &linfo
.progress
.recon
);
710 for (i
= 0; i
< plist
->count
; i
++) {
711 if (plist
->addr
[i
].scsi_dev_type
!= 0)
714 device_id
= plist
->addr
[i
].device_id
;
715 if (mfi_pd_get_info(fd
, device_id
, &pinfo
, NULL
) < 0) {
717 warn("Failed to fetch info for drive %u", device_id
);
723 if (pinfo
.prog_info
.active
& MFI_PD_PROGRESS_REBUILD
) {
724 printf("drive %s ", mfi_drive_name(NULL
, device_id
,
725 MFI_DNAME_DEVICE_ID
|MFI_DNAME_HONOR_OPTS
));
726 mfi_display_progress("Rebuild", &pinfo
.prog_info
.rbld
);
729 if (pinfo
.prog_info
.active
& MFI_PD_PROGRESS_PATROL
) {
730 printf("drive %s ", mfi_drive_name(NULL
, device_id
,
731 MFI_DNAME_DEVICE_ID
|MFI_DNAME_HONOR_OPTS
));
732 mfi_display_progress("Patrol Read",
733 &pinfo
.prog_info
.patrol
);
736 if (pinfo
.prog_info
.active
& MFI_PD_PROGRESS_CLEAR
) {
737 printf("drive %s ", mfi_drive_name(NULL
, device_id
,
738 MFI_DNAME_DEVICE_ID
|MFI_DNAME_HONOR_OPTS
));
739 mfi_display_progress("Clear", &pinfo
.prog_info
.clear
);
748 printf("No activity in progress for adapter mfi%d\n", mfi_unit
);
752 MFI_COMMAND(show
, progress
, show_progress
);