1fc58801cSScott Long /*- 2fc58801cSScott Long * Copyright (c) 2008 Yahoo!, Inc. 3fc58801cSScott Long * All rights reserved. 4fc58801cSScott Long * Written by: John Baldwin <jhb@FreeBSD.org> 5fc58801cSScott Long * 6fc58801cSScott Long * Redistribution and use in source and binary forms, with or without 7fc58801cSScott Long * modification, are permitted provided that the following conditions 8fc58801cSScott Long * are met: 9fc58801cSScott Long * 1. Redistributions of source code must retain the above copyright 10fc58801cSScott Long * notice, this list of conditions and the following disclaimer. 11fc58801cSScott Long * 2. Redistributions in binary form must reproduce the above copyright 12fc58801cSScott Long * notice, this list of conditions and the following disclaimer in the 13fc58801cSScott Long * documentation and/or other materials provided with the distribution. 14fc58801cSScott Long * 3. Neither the name of the author nor the names of any co-contributors 15fc58801cSScott Long * may be used to endorse or promote products derived from this software 16fc58801cSScott Long * without specific prior written permission. 17fc58801cSScott Long * 18fc58801cSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19fc58801cSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20fc58801cSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21fc58801cSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22fc58801cSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23fc58801cSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24fc58801cSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25fc58801cSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26fc58801cSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27fc58801cSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28fc58801cSScott Long * SUCH DAMAGE. 29fc58801cSScott Long */ 30fc58801cSScott Long 31fc58801cSScott Long #include <sys/cdefs.h> 32fc58801cSScott Long __RCSID("$FreeBSD$"); 33fc58801cSScott Long 34fc58801cSScott Long #include <sys/param.h> 35fc58801cSScott Long #include <sys/errno.h> 36fc58801cSScott Long #include <err.h> 37fc58801cSScott Long #include <libutil.h> 38fc58801cSScott Long #include <stdio.h> 39fc58801cSScott Long #include <stdlib.h> 40fc58801cSScott Long #include <string.h> 41fc58801cSScott Long #include <unistd.h> 42fc58801cSScott Long #include "mptutil.h" 43fc58801cSScott Long 44fc58801cSScott Long MPT_TABLE(top, show); 45fc58801cSScott Long 46fc58801cSScott Long #define STANDALONE_STATE "ONLINE" 47fc58801cSScott Long 48fc58801cSScott Long static void 49fc58801cSScott Long format_stripe(char *buf, size_t buflen, U32 stripe) 50fc58801cSScott Long { 51fc58801cSScott Long 52fc58801cSScott Long humanize_number(buf, buflen, stripe * 512, "", HN_AUTOSCALE, 53fc58801cSScott Long HN_B | HN_NOSPACE); 54fc58801cSScott Long } 55fc58801cSScott Long 56fc58801cSScott Long static void 57fc58801cSScott Long display_stripe_map(const char *label, U32 StripeMap) 58fc58801cSScott Long { 59fc58801cSScott Long char stripe[5]; 60fc58801cSScott Long int comma, i; 61fc58801cSScott Long 62fc58801cSScott Long comma = 0; 63fc58801cSScott Long printf("%s: ", label); 64fc58801cSScott Long for (i = 0; StripeMap != 0; i++, StripeMap >>= 1) 65fc58801cSScott Long if (StripeMap & 1) { 66fc58801cSScott Long format_stripe(stripe, sizeof(stripe), 1 << i); 67fc58801cSScott Long if (comma) 68fc58801cSScott Long printf(", "); 69fc58801cSScott Long printf("%s", stripe); 70fc58801cSScott Long comma = 1; 71fc58801cSScott Long } 72fc58801cSScott Long printf("\n"); 73fc58801cSScott Long } 74fc58801cSScott Long 75fc58801cSScott Long static int 76fc58801cSScott Long show_adapter(int ac, char **av) 77fc58801cSScott Long { 78fc58801cSScott Long CONFIG_PAGE_MANUFACTURING_0 *man0; 79fc58801cSScott Long CONFIG_PAGE_IOC_2 *ioc2; 80fc58801cSScott Long CONFIG_PAGE_IOC_6 *ioc6; 81fc58801cSScott Long int fd, comma; 82fc58801cSScott Long 83fc58801cSScott Long if (ac != 1) { 84fc58801cSScott Long warnx("show adapter: extra arguments"); 85fc58801cSScott Long return (EINVAL); 86fc58801cSScott Long } 87fc58801cSScott Long 88fc58801cSScott Long fd = mpt_open(mpt_unit); 89fc58801cSScott Long if (fd < 0) { 90fc58801cSScott Long warn("mpt_open"); 91fc58801cSScott Long return (errno); 92fc58801cSScott Long } 93fc58801cSScott Long 94fc58801cSScott Long man0 = mpt_read_man_page(fd, 0, NULL); 95fc58801cSScott Long if (man0 == NULL) { 96fc58801cSScott Long warn("Failed to get controller info"); 97fc58801cSScott Long return (errno); 98fc58801cSScott Long } 99fc58801cSScott Long if (man0->Header.PageLength < sizeof(*man0) / 4) { 100fc58801cSScott Long warn("Invalid controller info"); 101fc58801cSScott Long return (EINVAL); 102fc58801cSScott Long } 103fc58801cSScott Long printf("mpt%d Adapter:\n", mpt_unit); 104fc58801cSScott Long printf(" Board Name: %.16s\n", man0->BoardName); 105fc58801cSScott Long printf(" Board Assembly: %.16s\n", man0->BoardAssembly); 106fc58801cSScott Long printf(" Chip Name: %.16s\n", man0->ChipName); 107fc58801cSScott Long printf(" Chip Revision: %.16s\n", man0->ChipRevision); 108fc58801cSScott Long 109fc58801cSScott Long free(man0); 110fc58801cSScott Long 111fc58801cSScott Long ioc2 = mpt_read_ioc_page(fd, 2, NULL); 112fc58801cSScott Long if (ioc2 != NULL) { 113fc58801cSScott Long printf(" RAID Levels:"); 114fc58801cSScott Long comma = 0; 115fc58801cSScott Long if (ioc2->CapabilitiesFlags & 116fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) { 117fc58801cSScott Long printf(" RAID0"); 118fc58801cSScott Long comma = 1; 119fc58801cSScott Long } 120fc58801cSScott Long if (ioc2->CapabilitiesFlags & 121fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) { 122fc58801cSScott Long printf("%s RAID1", comma ? "," : ""); 123fc58801cSScott Long comma = 1; 124fc58801cSScott Long } 125fc58801cSScott Long if (ioc2->CapabilitiesFlags & 126fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) { 127fc58801cSScott Long printf("%s RAID1E", comma ? "," : ""); 128fc58801cSScott Long comma = 1; 129fc58801cSScott Long } 130fc58801cSScott Long if (ioc2->CapabilitiesFlags & 131fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT) { 132fc58801cSScott Long printf("%s RAID5", comma ? "," : ""); 133fc58801cSScott Long comma = 1; 134fc58801cSScott Long } 135fc58801cSScott Long if (ioc2->CapabilitiesFlags & 136fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT) { 137fc58801cSScott Long printf("%s RAID6", comma ? "," : ""); 138fc58801cSScott Long comma = 1; 139fc58801cSScott Long } 140fc58801cSScott Long if (ioc2->CapabilitiesFlags & 141fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT) { 142fc58801cSScott Long printf("%s RAID10", comma ? "," : ""); 143fc58801cSScott Long comma = 1; 144fc58801cSScott Long } 145fc58801cSScott Long if (ioc2->CapabilitiesFlags & 146fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT) { 147fc58801cSScott Long printf("%s RAID50", comma ? "," : ""); 148fc58801cSScott Long comma = 1; 149fc58801cSScott Long } 150fc58801cSScott Long if (!comma) 151fc58801cSScott Long printf(" none"); 152fc58801cSScott Long printf("\n"); 153fc58801cSScott Long free(ioc2); 154fc58801cSScott Long } 155fc58801cSScott Long 156fc58801cSScott Long ioc6 = mpt_read_ioc_page(fd, 6, NULL); 157fc58801cSScott Long if (ioc6 != NULL) { 158fc58801cSScott Long display_stripe_map(" RAID0 Stripes", 159fc58801cSScott Long ioc6->SupportedStripeSizeMapIS); 160fc58801cSScott Long display_stripe_map(" RAID1E Stripes", 161fc58801cSScott Long ioc6->SupportedStripeSizeMapIME); 162fc58801cSScott Long printf(" RAID0 Drives/Vol: %u", ioc6->MinDrivesIS); 163fc58801cSScott Long if (ioc6->MinDrivesIS != ioc6->MaxDrivesIS) 164fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIS); 165fc58801cSScott Long printf("\n"); 166fc58801cSScott Long printf(" RAID1 Drives/Vol: %u", ioc6->MinDrivesIM); 167fc58801cSScott Long if (ioc6->MinDrivesIM != ioc6->MaxDrivesIM) 168fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIM); 169fc58801cSScott Long printf("\n"); 170fc58801cSScott Long printf("RAID1E Drives/Vol: %u", ioc6->MinDrivesIME); 171fc58801cSScott Long if (ioc6->MinDrivesIME != ioc6->MaxDrivesIME) 172fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIME); 173fc58801cSScott Long printf("\n"); 174fc58801cSScott Long free(ioc6); 175fc58801cSScott Long } 176fc58801cSScott Long 177fc58801cSScott Long /* TODO: Add an ioctl to fetch IOC_FACTS and print firmware version. */ 178fc58801cSScott Long 179fc58801cSScott Long close(fd); 180fc58801cSScott Long 181fc58801cSScott Long return (0); 182fc58801cSScott Long } 183fc58801cSScott Long MPT_COMMAND(show, adapter, show_adapter); 184fc58801cSScott Long 185fc58801cSScott Long static void 186fc58801cSScott Long print_vol(CONFIG_PAGE_RAID_VOL_0 *info, int state_len) 187fc58801cSScott Long { 188fc58801cSScott Long uint64_t size; 189fc58801cSScott Long const char *level, *state; 190fc58801cSScott Long char buf[6], stripe[5]; 191fc58801cSScott Long 192fc58801cSScott Long size = ((uint64_t)info->MaxLBAHigh << 32) | info->MaxLBA; 193fc58801cSScott Long humanize_number(buf, sizeof(buf), (size + 1) * 512, "", HN_AUTOSCALE, 194fc58801cSScott Long HN_B | HN_NOSPACE | HN_DECIMAL); 195fc58801cSScott Long if (info->VolumeType == MPI_RAID_VOL_TYPE_IM) 196fc58801cSScott Long stripe[0] = '\0'; 197fc58801cSScott Long else 198fc58801cSScott Long format_stripe(stripe, sizeof(stripe), info->StripeSize); 199fc58801cSScott Long level = mpt_raid_level(info->VolumeType); 200fc58801cSScott Long state = mpt_volstate(info->VolumeStatus.State); 201fc58801cSScott Long if (state_len > 0) 202fc58801cSScott Long printf("(%6s) %-8s %6s %-*s", buf, level, stripe, state_len, 203fc58801cSScott Long state); 204fc58801cSScott Long else if (stripe[0] != '\0') 205fc58801cSScott Long printf("(%s) %s %s %s", buf, level, stripe, state); 206fc58801cSScott Long else 207fc58801cSScott Long printf("(%s) %s %s", buf, level, state); 208fc58801cSScott Long } 209fc58801cSScott Long 210fc58801cSScott Long static void 211fc58801cSScott Long print_pd(CONFIG_PAGE_RAID_PHYS_DISK_0 *info, int state_len, int location) 212fc58801cSScott Long { 213fc58801cSScott Long const char *inq, *state; 214fc58801cSScott Long char buf[6]; 215fc58801cSScott Long 216fc58801cSScott Long humanize_number(buf, sizeof(buf), ((uint64_t)info->MaxLBA + 1) * 512, 217fc58801cSScott Long "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 218fc58801cSScott Long state = mpt_pdstate(info); 219fc58801cSScott Long if (state_len > 0) 220fc58801cSScott Long printf("(%6s) %-*s", buf, state_len, state); 221fc58801cSScott Long else 222fc58801cSScott Long printf("(%s) %s", buf, state); 223fc58801cSScott Long inq = mpt_pd_inq_string(info); 224fc58801cSScott Long if (inq != NULL) 225fc58801cSScott Long printf(" %s", inq); 226fc58801cSScott Long if (!location) 227fc58801cSScott Long return; 228fc58801cSScott Long printf(" bus %d id %d", info->PhysDiskBus, info->PhysDiskID); 229fc58801cSScott Long } 230fc58801cSScott Long 231fc58801cSScott Long static void 232fc58801cSScott Long print_standalone(struct mpt_standalone_disk *disk, int state_len, int location) 233fc58801cSScott Long { 234fc58801cSScott Long char buf[6]; 235fc58801cSScott Long 236fc58801cSScott Long humanize_number(buf, sizeof(buf), (disk->maxlba + 1) * 512, 237fc58801cSScott Long "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 238fc58801cSScott Long if (state_len > 0) 239fc58801cSScott Long printf("(%6s) %-*s", buf, state_len, STANDALONE_STATE); 240fc58801cSScott Long else 241fc58801cSScott Long printf("(%s) %s", buf, STANDALONE_STATE); 242fc58801cSScott Long if (disk->inqstring[0] != '\0') 243fc58801cSScott Long printf(" %s", disk->inqstring); 244fc58801cSScott Long if (!location) 245fc58801cSScott Long return; 246fc58801cSScott Long printf(" bus %d id %d", disk->bus, disk->target); 247fc58801cSScott Long } 248fc58801cSScott Long 249fc58801cSScott Long static void 250fc58801cSScott Long print_spare_pools(U8 HotSparePool) 251fc58801cSScott Long { 252fc58801cSScott Long int i; 253fc58801cSScott Long 254fc58801cSScott Long if (HotSparePool == 0) { 255fc58801cSScott Long printf("none"); 256fc58801cSScott Long return; 257fc58801cSScott Long } 258fc58801cSScott Long for (i = 0; HotSparePool != 0; i++) { 259fc58801cSScott Long if (HotSparePool & 1) { 260fc58801cSScott Long printf("%d", i); 261fc58801cSScott Long if (HotSparePool == 1) 262fc58801cSScott Long break; 263fc58801cSScott Long printf(", "); 264fc58801cSScott Long } 265fc58801cSScott Long HotSparePool >>= 1; 266fc58801cSScott Long } 267fc58801cSScott Long } 268fc58801cSScott Long 269fc58801cSScott Long static int 270fc58801cSScott Long show_config(int ac, char **av) 271fc58801cSScott Long { 272fc58801cSScott Long CONFIG_PAGE_IOC_2 *ioc2; 273fc58801cSScott Long CONFIG_PAGE_IOC_2_RAID_VOL *vol; 274fc58801cSScott Long CONFIG_PAGE_IOC_5 *ioc5; 275fc58801cSScott Long IOC_5_HOT_SPARE *spare; 276fc58801cSScott Long CONFIG_PAGE_RAID_VOL_0 *vinfo; 277fc58801cSScott Long RAID_VOL0_PHYS_DISK *disk; 278fc58801cSScott Long CONFIG_PAGE_RAID_VOL_1 *vnames; 279fc58801cSScott Long CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 280fc58801cSScott Long struct mpt_standalone_disk *sdisks; 281fc58801cSScott Long int fd, i, j, nsdisks; 282fc58801cSScott Long 283fc58801cSScott Long if (ac != 1) { 284fc58801cSScott Long warnx("show config: extra arguments"); 285fc58801cSScott Long return (EINVAL); 286fc58801cSScott Long } 287fc58801cSScott Long 288fc58801cSScott Long fd = mpt_open(mpt_unit); 289fc58801cSScott Long if (fd < 0) { 290fc58801cSScott Long warn("mpt_open"); 291fc58801cSScott Long return (errno); 292fc58801cSScott Long } 293fc58801cSScott Long 294fc58801cSScott Long /* Get the config from the controller. */ 295fc58801cSScott Long ioc2 = mpt_read_ioc_page(fd, 2, NULL); 296fc58801cSScott Long ioc5 = mpt_read_ioc_page(fd, 5, NULL); 297fc58801cSScott Long if (ioc2 == NULL || ioc5 == NULL) { 298fc58801cSScott Long warn("Failed to get config"); 299fc58801cSScott Long return (errno); 300fc58801cSScott Long } 301fc58801cSScott Long if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) { 302fc58801cSScott Long warn("Failed to get standalone drive list"); 303fc58801cSScott Long return (errno); 304fc58801cSScott Long } 305fc58801cSScott Long 306fc58801cSScott Long /* Dump out the configuration. */ 307fc58801cSScott Long printf("mpt%d Configuration: %d volumes, %d drives\n", 308fc58801cSScott Long mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks + 309fc58801cSScott Long nsdisks); 310fc58801cSScott Long vol = ioc2->RaidVolume; 311fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 312fc58801cSScott Long printf(" volume %s ", mpt_volume_name(vol->VolumeBus, 313fc58801cSScott Long vol->VolumeID)); 314fc58801cSScott Long vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL); 315fc58801cSScott Long if (vinfo == NULL) { 316fc58801cSScott Long printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType)); 317fc58801cSScott Long } else 318fc58801cSScott Long print_vol(vinfo, -1); 319fc58801cSScott Long vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 320fc58801cSScott Long if (vnames != NULL) { 321fc58801cSScott Long if (vnames->Name[0] != '\0') 322fc58801cSScott Long printf(" <%s>", vnames->Name); 323fc58801cSScott Long free(vnames); 324fc58801cSScott Long } 325fc58801cSScott Long if (vinfo == NULL) { 326fc58801cSScott Long printf("\n"); 327fc58801cSScott Long continue; 328fc58801cSScott Long } 329fc58801cSScott Long printf(" spans:\n"); 330fc58801cSScott Long disk = vinfo->PhysDisk; 331fc58801cSScott Long for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) { 332fc58801cSScott Long printf(" drive %u ", disk->PhysDiskNum); 333fc58801cSScott Long pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL); 334fc58801cSScott Long if (pinfo != NULL) { 335fc58801cSScott Long print_pd(pinfo, -1, 0); 336fc58801cSScott Long free(pinfo); 337fc58801cSScott Long } 338fc58801cSScott Long printf("\n"); 339fc58801cSScott Long } 340fc58801cSScott Long if (vinfo->VolumeSettings.HotSparePool != 0) { 341fc58801cSScott Long printf(" spare pools: "); 342fc58801cSScott Long print_spare_pools(vinfo->VolumeSettings.HotSparePool); 343fc58801cSScott Long printf("\n"); 344fc58801cSScott Long } 345fc58801cSScott Long free(vinfo); 346fc58801cSScott Long } 347fc58801cSScott Long 348fc58801cSScott Long spare = ioc5->HotSpare; 349fc58801cSScott Long for (i = 0; i < ioc5->NumHotSpares; spare++, i++) { 350fc58801cSScott Long printf(" spare %u ", spare->PhysDiskNum); 351fc58801cSScott Long pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL); 352fc58801cSScott Long if (pinfo != NULL) { 353fc58801cSScott Long print_pd(pinfo, -1, 0); 354fc58801cSScott Long free(pinfo); 355fc58801cSScott Long } 356fc58801cSScott Long printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1); 357fc58801cSScott Long } 358fc58801cSScott Long for (i = 0; i < nsdisks; i++) { 359fc58801cSScott Long printf(" drive %s ", sdisks[i].devname); 360fc58801cSScott Long print_standalone(&sdisks[i], -1, 0); 361fc58801cSScott Long printf("\n"); 362fc58801cSScott Long } 363fc58801cSScott Long free(ioc2); 364fc58801cSScott Long free(ioc5); 365fc58801cSScott Long free(sdisks); 366fc58801cSScott Long close(fd); 367fc58801cSScott Long 368fc58801cSScott Long return (0); 369fc58801cSScott Long } 370fc58801cSScott Long MPT_COMMAND(show, config, show_config); 371fc58801cSScott Long 372fc58801cSScott Long static int 373fc58801cSScott Long show_volumes(int ac, char **av) 374fc58801cSScott Long { 375fc58801cSScott Long CONFIG_PAGE_IOC_2 *ioc2; 376fc58801cSScott Long CONFIG_PAGE_IOC_2_RAID_VOL *vol; 377fc58801cSScott Long CONFIG_PAGE_RAID_VOL_0 **volumes; 378fc58801cSScott Long CONFIG_PAGE_RAID_VOL_1 *vnames; 379fc58801cSScott Long int fd, i, len, state_len; 380fc58801cSScott Long 381fc58801cSScott Long if (ac != 1) { 382fc58801cSScott Long warnx("show volumes: extra arguments"); 383fc58801cSScott Long return (EINVAL); 384fc58801cSScott Long } 385fc58801cSScott Long 386fc58801cSScott Long fd = mpt_open(mpt_unit); 387fc58801cSScott Long if (fd < 0) { 388fc58801cSScott Long warn("mpt_open"); 389fc58801cSScott Long return (errno); 390fc58801cSScott Long } 391fc58801cSScott Long 392fc58801cSScott Long /* Get the volume list from the controller. */ 393fc58801cSScott Long ioc2 = mpt_read_ioc_page(fd, 2, NULL); 394fc58801cSScott Long if (ioc2 == NULL) { 395fc58801cSScott Long warn("Failed to get volume list"); 396fc58801cSScott Long return (errno); 397fc58801cSScott Long } 398fc58801cSScott Long 399fc58801cSScott Long /* 400fc58801cSScott Long * Go ahead and read the info for all the volumes and figure 401fc58801cSScott Long * out the maximum width of the state field. 402fc58801cSScott Long */ 403fc58801cSScott Long volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes); 404fc58801cSScott Long state_len = strlen("State"); 405fc58801cSScott Long vol = ioc2->RaidVolume; 406fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 407fc58801cSScott Long volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, 408fc58801cSScott Long NULL); 409fc58801cSScott Long if (volumes[i] == NULL) 410fc58801cSScott Long len = strlen("UNKNOWN"); 411fc58801cSScott Long else 412fc58801cSScott Long len = strlen(mpt_volstate( 413fc58801cSScott Long volumes[i]->VolumeStatus.State)); 414fc58801cSScott Long if (len > state_len) 415fc58801cSScott Long state_len = len; 416fc58801cSScott Long } 417fc58801cSScott Long printf("mpt%d Volumes:\n", mpt_unit); 418fc58801cSScott Long printf(" Id Size Level Stripe "); 419fc58801cSScott Long len = state_len - strlen("State"); 420fc58801cSScott Long for (i = 0; i < (len + 1) / 2; i++) 421fc58801cSScott Long printf(" "); 422fc58801cSScott Long printf("State"); 423fc58801cSScott Long for (i = 0; i < len / 2; i++) 424fc58801cSScott Long printf(" "); 425fc58801cSScott Long printf(" Write-Cache Name\n"); 426fc58801cSScott Long vol = ioc2->RaidVolume; 427fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 428fc58801cSScott Long printf("%6s ", mpt_volume_name(vol->VolumeBus, vol->VolumeID)); 429fc58801cSScott Long if (volumes[i] != NULL) 430fc58801cSScott Long print_vol(volumes[i], state_len); 431fc58801cSScott Long else 432fc58801cSScott Long printf(" %-8s %-*s", 433fc58801cSScott Long mpt_raid_level(vol->VolumeType), state_len, 434fc58801cSScott Long "UNKNOWN"); 435fc58801cSScott Long if (volumes[i] != NULL) { 436fc58801cSScott Long if (volumes[i]->VolumeSettings.Settings & 437fc58801cSScott Long MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE) 438fc58801cSScott Long printf(" Enabled "); 439fc58801cSScott Long else 440fc58801cSScott Long printf(" Disabled "); 441fc58801cSScott Long } else 442fc58801cSScott Long printf(" "); 443fc58801cSScott Long free(volumes[i]); 444fc58801cSScott Long vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 445fc58801cSScott Long if (vnames != NULL) { 446fc58801cSScott Long if (vnames->Name[0] != '\0') 447fc58801cSScott Long printf(" <%s>", vnames->Name); 448fc58801cSScott Long free(vnames); 449fc58801cSScott Long } 450fc58801cSScott Long printf("\n"); 451fc58801cSScott Long } 452fc58801cSScott Long free(ioc2); 453fc58801cSScott Long close(fd); 454fc58801cSScott Long 455fc58801cSScott Long return (0); 456fc58801cSScott Long } 457fc58801cSScott Long MPT_COMMAND(show, volumes, show_volumes); 458fc58801cSScott Long 459fc58801cSScott Long static int 460fc58801cSScott Long show_drives(int ac, char **av) 461fc58801cSScott Long { 462fc58801cSScott Long struct mpt_drive_list *list; 463fc58801cSScott Long struct mpt_standalone_disk *sdisks; 464fc58801cSScott Long int fd, i, len, nsdisks, state_len; 465fc58801cSScott Long 466fc58801cSScott Long if (ac != 1) { 467fc58801cSScott Long warnx("show drives: extra arguments"); 468fc58801cSScott Long return (EINVAL); 469fc58801cSScott Long } 470fc58801cSScott Long 471fc58801cSScott Long fd = mpt_open(mpt_unit); 472fc58801cSScott Long if (fd < 0) { 473fc58801cSScott Long warn("mpt_open"); 474fc58801cSScott Long return (errno); 475fc58801cSScott Long } 476fc58801cSScott Long 477fc58801cSScott Long /* Get the drive list. */ 478fc58801cSScott Long list = mpt_pd_list(fd); 479fc58801cSScott Long if (list == NULL) { 480fc58801cSScott Long warn("Failed to get drive list"); 481fc58801cSScott Long return (errno); 482fc58801cSScott Long } 483fc58801cSScott Long 484fc58801cSScott Long /* Fetch the list of standalone disks for this controller. */ 485fc58801cSScott Long state_len = 0; 486fc58801cSScott Long if (mpt_fetch_disks(fd, &nsdisks, &sdisks) != 0) { 487fc58801cSScott Long nsdisks = 0; 488fc58801cSScott Long sdisks = NULL; 489fc58801cSScott Long } 490fc58801cSScott Long if (nsdisks != 0) 491fc58801cSScott Long state_len = strlen(STANDALONE_STATE); 492fc58801cSScott Long 493fc58801cSScott Long /* Walk the drive list to determine width of state column. */ 494fc58801cSScott Long for (i = 0; i < list->ndrives; i++) { 495fc58801cSScott Long len = strlen(mpt_pdstate(list->drives[i])); 496fc58801cSScott Long if (len > state_len) 497fc58801cSScott Long state_len = len; 498fc58801cSScott Long } 499fc58801cSScott Long 500fc58801cSScott Long /* List the drives. */ 501fc58801cSScott Long printf("mpt%d Physical Drives:\n", mpt_unit); 502fc58801cSScott Long for (i = 0; i < list->ndrives; i++) { 503fc58801cSScott Long printf("%4u ", list->drives[i]->PhysDiskNum); 504fc58801cSScott Long print_pd(list->drives[i], state_len, 1); 505fc58801cSScott Long printf("\n"); 506fc58801cSScott Long } 507fc58801cSScott Long mpt_free_pd_list(list); 508fc58801cSScott Long for (i = 0; i < nsdisks; i++) { 509fc58801cSScott Long printf("%4s ", sdisks[i].devname); 510fc58801cSScott Long print_standalone(&sdisks[i], state_len, 1); 511fc58801cSScott Long printf("\n"); 512fc58801cSScott Long } 513fc58801cSScott Long free(sdisks); 514fc58801cSScott Long 515fc58801cSScott Long close(fd); 516fc58801cSScott Long 517fc58801cSScott Long return (0); 518fc58801cSScott Long } 519fc58801cSScott Long MPT_COMMAND(show, drives, show_drives); 520fc58801cSScott Long 521fc58801cSScott Long #ifdef DEBUG 522fc58801cSScott Long static int 523fc58801cSScott Long show_physdisks(int ac, char **av) 524fc58801cSScott Long { 525fc58801cSScott Long CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 526fc58801cSScott Long U16 IOCStatus; 527fc58801cSScott Long int fd, i; 528fc58801cSScott Long 529fc58801cSScott Long if (ac != 1) { 530fc58801cSScott Long warnx("show drives: extra arguments"); 531fc58801cSScott Long return (EINVAL); 532fc58801cSScott Long } 533fc58801cSScott Long 534fc58801cSScott Long fd = mpt_open(mpt_unit); 535fc58801cSScott Long if (fd < 0) { 536fc58801cSScott Long warn("mpt_open"); 537fc58801cSScott Long return (errno); 538fc58801cSScott Long } 539fc58801cSScott Long 540fc58801cSScott Long /* Try to find each possible phys disk page. */ 541fc58801cSScott Long for (i = 0; i <= 0xff; i++) { 542fc58801cSScott Long pinfo = mpt_pd_info(fd, i, &IOCStatus); 543fc58801cSScott Long if (pinfo == NULL) { 544fc58801cSScott Long if (IOCStatus != MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 545fc58801cSScott Long warnx("mpt_pd_info(%d): %s", i, 546fc58801cSScott Long mpt_ioc_status(IOCStatus)); 547fc58801cSScott Long continue; 548fc58801cSScott Long } 549fc58801cSScott Long printf("%3u ", i); 550fc58801cSScott Long print_pd(pinfo, -1, 1); 551fc58801cSScott Long printf("\n"); 552fc58801cSScott Long } 553fc58801cSScott Long 554fc58801cSScott Long close(fd); 555fc58801cSScott Long 556fc58801cSScott Long return (0); 557fc58801cSScott Long } 558fc58801cSScott Long MPT_COMMAND(show, pd, show_physdisks); 559fc58801cSScott Long #endif 560