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; 815f1f6da8SJohn Baldwin U16 IOCStatus; 82fc58801cSScott Long int fd, comma; 83fc58801cSScott Long 84fc58801cSScott Long if (ac != 1) { 85fc58801cSScott Long warnx("show adapter: extra arguments"); 86fc58801cSScott Long return (EINVAL); 87fc58801cSScott Long } 88fc58801cSScott Long 89fc58801cSScott Long fd = mpt_open(mpt_unit); 90fc58801cSScott Long if (fd < 0) { 91fc58801cSScott Long warn("mpt_open"); 92fc58801cSScott Long return (errno); 93fc58801cSScott Long } 94fc58801cSScott Long 95fc58801cSScott Long man0 = mpt_read_man_page(fd, 0, NULL); 96fc58801cSScott Long if (man0 == NULL) { 97fc58801cSScott Long warn("Failed to get controller info"); 98fc58801cSScott Long return (errno); 99fc58801cSScott Long } 100fc58801cSScott Long if (man0->Header.PageLength < sizeof(*man0) / 4) { 101fc58801cSScott Long warn("Invalid controller info"); 102fc58801cSScott Long return (EINVAL); 103fc58801cSScott Long } 104fc58801cSScott Long printf("mpt%d Adapter:\n", mpt_unit); 105fc58801cSScott Long printf(" Board Name: %.16s\n", man0->BoardName); 106fc58801cSScott Long printf(" Board Assembly: %.16s\n", man0->BoardAssembly); 107fc58801cSScott Long printf(" Chip Name: %.16s\n", man0->ChipName); 108fc58801cSScott Long printf(" Chip Revision: %.16s\n", man0->ChipRevision); 109fc58801cSScott Long 110fc58801cSScott Long free(man0); 111fc58801cSScott Long 1125f1f6da8SJohn Baldwin ioc2 = mpt_read_ioc_page(fd, 2, &IOCStatus); 113fc58801cSScott Long if (ioc2 != NULL) { 114fc58801cSScott Long printf(" RAID Levels:"); 115fc58801cSScott Long comma = 0; 116fc58801cSScott Long if (ioc2->CapabilitiesFlags & 117fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) { 118fc58801cSScott Long printf(" RAID0"); 119fc58801cSScott Long comma = 1; 120fc58801cSScott Long } 121fc58801cSScott Long if (ioc2->CapabilitiesFlags & 122fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) { 123fc58801cSScott Long printf("%s RAID1", comma ? "," : ""); 124fc58801cSScott Long comma = 1; 125fc58801cSScott Long } 126fc58801cSScott Long if (ioc2->CapabilitiesFlags & 127fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) { 128fc58801cSScott Long printf("%s RAID1E", comma ? "," : ""); 129fc58801cSScott Long comma = 1; 130fc58801cSScott Long } 131fc58801cSScott Long if (ioc2->CapabilitiesFlags & 132fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT) { 133fc58801cSScott Long printf("%s RAID5", comma ? "," : ""); 134fc58801cSScott Long comma = 1; 135fc58801cSScott Long } 136fc58801cSScott Long if (ioc2->CapabilitiesFlags & 137fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT) { 138fc58801cSScott Long printf("%s RAID6", comma ? "," : ""); 139fc58801cSScott Long comma = 1; 140fc58801cSScott Long } 141fc58801cSScott Long if (ioc2->CapabilitiesFlags & 142fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT) { 143fc58801cSScott Long printf("%s RAID10", comma ? "," : ""); 144fc58801cSScott Long comma = 1; 145fc58801cSScott Long } 146fc58801cSScott Long if (ioc2->CapabilitiesFlags & 147fc58801cSScott Long MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT) { 148fc58801cSScott Long printf("%s RAID50", comma ? "," : ""); 149fc58801cSScott Long comma = 1; 150fc58801cSScott Long } 151fc58801cSScott Long if (!comma) 152fc58801cSScott Long printf(" none"); 153fc58801cSScott Long printf("\n"); 154fc58801cSScott Long free(ioc2); 1555f1f6da8SJohn Baldwin } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 1565f1f6da8SJohn Baldwin MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 1575f1f6da8SJohn Baldwin warnx("mpt_read_ioc_page(2): %s", mpt_ioc_status(IOCStatus)); 158fc58801cSScott Long 1595f1f6da8SJohn Baldwin ioc6 = mpt_read_ioc_page(fd, 6, &IOCStatus); 160fc58801cSScott Long if (ioc6 != NULL) { 161fc58801cSScott Long display_stripe_map(" RAID0 Stripes", 162fc58801cSScott Long ioc6->SupportedStripeSizeMapIS); 163fc58801cSScott Long display_stripe_map(" RAID1E Stripes", 164fc58801cSScott Long ioc6->SupportedStripeSizeMapIME); 165fc58801cSScott Long printf(" RAID0 Drives/Vol: %u", ioc6->MinDrivesIS); 166fc58801cSScott Long if (ioc6->MinDrivesIS != ioc6->MaxDrivesIS) 167fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIS); 168fc58801cSScott Long printf("\n"); 169fc58801cSScott Long printf(" RAID1 Drives/Vol: %u", ioc6->MinDrivesIM); 170fc58801cSScott Long if (ioc6->MinDrivesIM != ioc6->MaxDrivesIM) 171fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIM); 172fc58801cSScott Long printf("\n"); 173fc58801cSScott Long printf("RAID1E Drives/Vol: %u", ioc6->MinDrivesIME); 174fc58801cSScott Long if (ioc6->MinDrivesIME != ioc6->MaxDrivesIME) 175fc58801cSScott Long printf("-%u", ioc6->MaxDrivesIME); 176fc58801cSScott Long printf("\n"); 177fc58801cSScott Long free(ioc6); 1785f1f6da8SJohn Baldwin } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 1795f1f6da8SJohn Baldwin MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 1805f1f6da8SJohn Baldwin warnx("mpt_read_ioc_page(6): %s", mpt_ioc_status(IOCStatus)); 181fc58801cSScott Long 182fc58801cSScott Long /* TODO: Add an ioctl to fetch IOC_FACTS and print firmware version. */ 183fc58801cSScott Long 184fc58801cSScott Long close(fd); 185fc58801cSScott Long 186fc58801cSScott Long return (0); 187fc58801cSScott Long } 188fc58801cSScott Long MPT_COMMAND(show, adapter, show_adapter); 189fc58801cSScott Long 190fc58801cSScott Long static void 191fc58801cSScott Long print_vol(CONFIG_PAGE_RAID_VOL_0 *info, int state_len) 192fc58801cSScott Long { 193fc58801cSScott Long uint64_t size; 194fc58801cSScott Long const char *level, *state; 195fc58801cSScott Long char buf[6], stripe[5]; 196fc58801cSScott Long 197fc58801cSScott Long size = ((uint64_t)info->MaxLBAHigh << 32) | info->MaxLBA; 198fc58801cSScott Long humanize_number(buf, sizeof(buf), (size + 1) * 512, "", HN_AUTOSCALE, 199fc58801cSScott Long HN_B | HN_NOSPACE | HN_DECIMAL); 200fc58801cSScott Long if (info->VolumeType == MPI_RAID_VOL_TYPE_IM) 201fc58801cSScott Long stripe[0] = '\0'; 202fc58801cSScott Long else 203fc58801cSScott Long format_stripe(stripe, sizeof(stripe), info->StripeSize); 204fc58801cSScott Long level = mpt_raid_level(info->VolumeType); 205fc58801cSScott Long state = mpt_volstate(info->VolumeStatus.State); 206fc58801cSScott Long if (state_len > 0) 207fc58801cSScott Long printf("(%6s) %-8s %6s %-*s", buf, level, stripe, state_len, 208fc58801cSScott Long state); 209fc58801cSScott Long else if (stripe[0] != '\0') 210fc58801cSScott Long printf("(%s) %s %s %s", buf, level, stripe, state); 211fc58801cSScott Long else 212fc58801cSScott Long printf("(%s) %s %s", buf, level, state); 213fc58801cSScott Long } 214fc58801cSScott Long 215fc58801cSScott Long static void 216fc58801cSScott Long print_pd(CONFIG_PAGE_RAID_PHYS_DISK_0 *info, int state_len, int location) 217fc58801cSScott Long { 218fc58801cSScott Long const char *inq, *state; 219fc58801cSScott Long char buf[6]; 220fc58801cSScott Long 221fc58801cSScott Long humanize_number(buf, sizeof(buf), ((uint64_t)info->MaxLBA + 1) * 512, 222fc58801cSScott Long "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 223fc58801cSScott Long state = mpt_pdstate(info); 224fc58801cSScott Long if (state_len > 0) 225fc58801cSScott Long printf("(%6s) %-*s", buf, state_len, state); 226fc58801cSScott Long else 227fc58801cSScott Long printf("(%s) %s", buf, state); 228fc58801cSScott Long inq = mpt_pd_inq_string(info); 229fc58801cSScott Long if (inq != NULL) 230fc58801cSScott Long printf(" %s", inq); 231fc58801cSScott Long if (!location) 232fc58801cSScott Long return; 233fc58801cSScott Long printf(" bus %d id %d", info->PhysDiskBus, info->PhysDiskID); 234fc58801cSScott Long } 235fc58801cSScott Long 236fc58801cSScott Long static void 237fc58801cSScott Long print_standalone(struct mpt_standalone_disk *disk, int state_len, int location) 238fc58801cSScott Long { 239fc58801cSScott Long char buf[6]; 240fc58801cSScott Long 241fc58801cSScott Long humanize_number(buf, sizeof(buf), (disk->maxlba + 1) * 512, 242fc58801cSScott Long "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 243fc58801cSScott Long if (state_len > 0) 244fc58801cSScott Long printf("(%6s) %-*s", buf, state_len, STANDALONE_STATE); 245fc58801cSScott Long else 246fc58801cSScott Long printf("(%s) %s", buf, STANDALONE_STATE); 247fc58801cSScott Long if (disk->inqstring[0] != '\0') 248fc58801cSScott Long printf(" %s", disk->inqstring); 249fc58801cSScott Long if (!location) 250fc58801cSScott Long return; 251fc58801cSScott Long printf(" bus %d id %d", disk->bus, disk->target); 252fc58801cSScott Long } 253fc58801cSScott Long 254fc58801cSScott Long static void 255fc58801cSScott Long print_spare_pools(U8 HotSparePool) 256fc58801cSScott Long { 257fc58801cSScott Long int i; 258fc58801cSScott Long 259fc58801cSScott Long if (HotSparePool == 0) { 260fc58801cSScott Long printf("none"); 261fc58801cSScott Long return; 262fc58801cSScott Long } 263fc58801cSScott Long for (i = 0; HotSparePool != 0; i++) { 264fc58801cSScott Long if (HotSparePool & 1) { 265fc58801cSScott Long printf("%d", i); 266fc58801cSScott Long if (HotSparePool == 1) 267fc58801cSScott Long break; 268fc58801cSScott Long printf(", "); 269fc58801cSScott Long } 270fc58801cSScott Long HotSparePool >>= 1; 271fc58801cSScott Long } 272fc58801cSScott Long } 273fc58801cSScott Long 274fc58801cSScott Long static int 275fc58801cSScott Long show_config(int ac, char **av) 276fc58801cSScott Long { 277fc58801cSScott Long CONFIG_PAGE_IOC_2 *ioc2; 278fc58801cSScott Long CONFIG_PAGE_IOC_2_RAID_VOL *vol; 279fc58801cSScott Long CONFIG_PAGE_IOC_5 *ioc5; 280fc58801cSScott Long IOC_5_HOT_SPARE *spare; 281fc58801cSScott Long CONFIG_PAGE_RAID_VOL_0 *vinfo; 282fc58801cSScott Long RAID_VOL0_PHYS_DISK *disk; 283fc58801cSScott Long CONFIG_PAGE_RAID_VOL_1 *vnames; 284fc58801cSScott Long CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 285fc58801cSScott Long struct mpt_standalone_disk *sdisks; 286fc58801cSScott Long int fd, i, j, nsdisks; 287fc58801cSScott Long 288fc58801cSScott Long if (ac != 1) { 289fc58801cSScott Long warnx("show config: extra arguments"); 290fc58801cSScott Long return (EINVAL); 291fc58801cSScott Long } 292fc58801cSScott Long 293fc58801cSScott Long fd = mpt_open(mpt_unit); 294fc58801cSScott Long if (fd < 0) { 295fc58801cSScott Long warn("mpt_open"); 296fc58801cSScott Long return (errno); 297fc58801cSScott Long } 298fc58801cSScott Long 299fc58801cSScott Long /* Get the config from the controller. */ 300fc58801cSScott Long ioc2 = mpt_read_ioc_page(fd, 2, NULL); 301fc58801cSScott Long ioc5 = mpt_read_ioc_page(fd, 5, NULL); 302fc58801cSScott Long if (ioc2 == NULL || ioc5 == NULL) { 303fc58801cSScott Long warn("Failed to get config"); 304fc58801cSScott Long return (errno); 305fc58801cSScott Long } 306fc58801cSScott Long if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) { 307fc58801cSScott Long warn("Failed to get standalone drive list"); 308fc58801cSScott Long return (errno); 309fc58801cSScott Long } 310fc58801cSScott Long 311fc58801cSScott Long /* Dump out the configuration. */ 312fc58801cSScott Long printf("mpt%d Configuration: %d volumes, %d drives\n", 313fc58801cSScott Long mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks + 314fc58801cSScott Long nsdisks); 315fc58801cSScott Long vol = ioc2->RaidVolume; 316fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 317fc58801cSScott Long printf(" volume %s ", mpt_volume_name(vol->VolumeBus, 318fc58801cSScott Long vol->VolumeID)); 319fc58801cSScott Long vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL); 320fc58801cSScott Long if (vinfo == NULL) { 321fc58801cSScott Long printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType)); 322fc58801cSScott Long } else 323fc58801cSScott Long print_vol(vinfo, -1); 324fc58801cSScott Long vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 325fc58801cSScott Long if (vnames != NULL) { 326fc58801cSScott Long if (vnames->Name[0] != '\0') 327fc58801cSScott Long printf(" <%s>", vnames->Name); 328fc58801cSScott Long free(vnames); 329fc58801cSScott Long } 330fc58801cSScott Long if (vinfo == NULL) { 331fc58801cSScott Long printf("\n"); 332fc58801cSScott Long continue; 333fc58801cSScott Long } 334fc58801cSScott Long printf(" spans:\n"); 335fc58801cSScott Long disk = vinfo->PhysDisk; 336fc58801cSScott Long for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) { 337fc58801cSScott Long printf(" drive %u ", disk->PhysDiskNum); 338fc58801cSScott Long pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL); 339fc58801cSScott Long if (pinfo != NULL) { 340fc58801cSScott Long print_pd(pinfo, -1, 0); 341fc58801cSScott Long free(pinfo); 342fc58801cSScott Long } 343fc58801cSScott Long printf("\n"); 344fc58801cSScott Long } 345fc58801cSScott Long if (vinfo->VolumeSettings.HotSparePool != 0) { 346fc58801cSScott Long printf(" spare pools: "); 347fc58801cSScott Long print_spare_pools(vinfo->VolumeSettings.HotSparePool); 348fc58801cSScott Long printf("\n"); 349fc58801cSScott Long } 350fc58801cSScott Long free(vinfo); 351fc58801cSScott Long } 352fc58801cSScott Long 353fc58801cSScott Long spare = ioc5->HotSpare; 354fc58801cSScott Long for (i = 0; i < ioc5->NumHotSpares; spare++, i++) { 355fc58801cSScott Long printf(" spare %u ", spare->PhysDiskNum); 356fc58801cSScott Long pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL); 357fc58801cSScott Long if (pinfo != NULL) { 358fc58801cSScott Long print_pd(pinfo, -1, 0); 359fc58801cSScott Long free(pinfo); 360fc58801cSScott Long } 361fc58801cSScott Long printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1); 362fc58801cSScott Long } 363fc58801cSScott Long for (i = 0; i < nsdisks; i++) { 364fc58801cSScott Long printf(" drive %s ", sdisks[i].devname); 365fc58801cSScott Long print_standalone(&sdisks[i], -1, 0); 366fc58801cSScott Long printf("\n"); 367fc58801cSScott Long } 368fc58801cSScott Long free(ioc2); 369fc58801cSScott Long free(ioc5); 370fc58801cSScott Long free(sdisks); 371fc58801cSScott Long close(fd); 372fc58801cSScott Long 373fc58801cSScott Long return (0); 374fc58801cSScott Long } 375fc58801cSScott Long MPT_COMMAND(show, config, show_config); 376fc58801cSScott Long 377fc58801cSScott Long static int 378fc58801cSScott Long show_volumes(int ac, char **av) 379fc58801cSScott Long { 380fc58801cSScott Long CONFIG_PAGE_IOC_2 *ioc2; 381fc58801cSScott Long CONFIG_PAGE_IOC_2_RAID_VOL *vol; 382fc58801cSScott Long CONFIG_PAGE_RAID_VOL_0 **volumes; 383fc58801cSScott Long CONFIG_PAGE_RAID_VOL_1 *vnames; 384fc58801cSScott Long int fd, i, len, state_len; 385fc58801cSScott Long 386fc58801cSScott Long if (ac != 1) { 387fc58801cSScott Long warnx("show volumes: extra arguments"); 388fc58801cSScott Long return (EINVAL); 389fc58801cSScott Long } 390fc58801cSScott Long 391fc58801cSScott Long fd = mpt_open(mpt_unit); 392fc58801cSScott Long if (fd < 0) { 393fc58801cSScott Long warn("mpt_open"); 394fc58801cSScott Long return (errno); 395fc58801cSScott Long } 396fc58801cSScott Long 397fc58801cSScott Long /* Get the volume list from the controller. */ 398fc58801cSScott Long ioc2 = mpt_read_ioc_page(fd, 2, NULL); 399fc58801cSScott Long if (ioc2 == NULL) { 400fc58801cSScott Long warn("Failed to get volume list"); 401fc58801cSScott Long return (errno); 402fc58801cSScott Long } 403fc58801cSScott Long 404fc58801cSScott Long /* 405fc58801cSScott Long * Go ahead and read the info for all the volumes and figure 406fc58801cSScott Long * out the maximum width of the state field. 407fc58801cSScott Long */ 408fc58801cSScott Long volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes); 409fc58801cSScott Long state_len = strlen("State"); 410fc58801cSScott Long vol = ioc2->RaidVolume; 411fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 412fc58801cSScott Long volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, 413fc58801cSScott Long NULL); 414fc58801cSScott Long if (volumes[i] == NULL) 415fc58801cSScott Long len = strlen("UNKNOWN"); 416fc58801cSScott Long else 417fc58801cSScott Long len = strlen(mpt_volstate( 418fc58801cSScott Long volumes[i]->VolumeStatus.State)); 419fc58801cSScott Long if (len > state_len) 420fc58801cSScott Long state_len = len; 421fc58801cSScott Long } 422fc58801cSScott Long printf("mpt%d Volumes:\n", mpt_unit); 423fc58801cSScott Long printf(" Id Size Level Stripe "); 424fc58801cSScott Long len = state_len - strlen("State"); 425fc58801cSScott Long for (i = 0; i < (len + 1) / 2; i++) 426fc58801cSScott Long printf(" "); 427fc58801cSScott Long printf("State"); 428fc58801cSScott Long for (i = 0; i < len / 2; i++) 429fc58801cSScott Long printf(" "); 430fc58801cSScott Long printf(" Write-Cache Name\n"); 431fc58801cSScott Long vol = ioc2->RaidVolume; 432fc58801cSScott Long for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 433fc58801cSScott Long printf("%6s ", mpt_volume_name(vol->VolumeBus, vol->VolumeID)); 434fc58801cSScott Long if (volumes[i] != NULL) 435fc58801cSScott Long print_vol(volumes[i], state_len); 436fc58801cSScott Long else 437fc58801cSScott Long printf(" %-8s %-*s", 438fc58801cSScott Long mpt_raid_level(vol->VolumeType), state_len, 439fc58801cSScott Long "UNKNOWN"); 440fc58801cSScott Long if (volumes[i] != NULL) { 441fc58801cSScott Long if (volumes[i]->VolumeSettings.Settings & 442fc58801cSScott Long MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE) 443fc58801cSScott Long printf(" Enabled "); 444fc58801cSScott Long else 445fc58801cSScott Long printf(" Disabled "); 446fc58801cSScott Long } else 447fc58801cSScott Long printf(" "); 448fc58801cSScott Long free(volumes[i]); 449fc58801cSScott Long vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 450fc58801cSScott Long if (vnames != NULL) { 451fc58801cSScott Long if (vnames->Name[0] != '\0') 452fc58801cSScott Long printf(" <%s>", vnames->Name); 453fc58801cSScott Long free(vnames); 454fc58801cSScott Long } 455fc58801cSScott Long printf("\n"); 456fc58801cSScott Long } 457fc58801cSScott Long free(ioc2); 458fc58801cSScott Long close(fd); 459fc58801cSScott Long 460fc58801cSScott Long return (0); 461fc58801cSScott Long } 462fc58801cSScott Long MPT_COMMAND(show, volumes, show_volumes); 463fc58801cSScott Long 464fc58801cSScott Long static int 465fc58801cSScott Long show_drives(int ac, char **av) 466fc58801cSScott Long { 467fc58801cSScott Long struct mpt_drive_list *list; 468fc58801cSScott Long struct mpt_standalone_disk *sdisks; 469fc58801cSScott Long int fd, i, len, nsdisks, state_len; 470fc58801cSScott Long 471fc58801cSScott Long if (ac != 1) { 472fc58801cSScott Long warnx("show drives: extra arguments"); 473fc58801cSScott Long return (EINVAL); 474fc58801cSScott Long } 475fc58801cSScott Long 476fc58801cSScott Long fd = mpt_open(mpt_unit); 477fc58801cSScott Long if (fd < 0) { 478fc58801cSScott Long warn("mpt_open"); 479fc58801cSScott Long return (errno); 480fc58801cSScott Long } 481fc58801cSScott Long 482fc58801cSScott Long /* Get the drive list. */ 483fc58801cSScott Long list = mpt_pd_list(fd); 484fc58801cSScott Long if (list == NULL) { 485fc58801cSScott Long warn("Failed to get drive list"); 486fc58801cSScott Long return (errno); 487fc58801cSScott Long } 488fc58801cSScott Long 489fc58801cSScott Long /* Fetch the list of standalone disks for this controller. */ 490fc58801cSScott Long state_len = 0; 491fc58801cSScott Long if (mpt_fetch_disks(fd, &nsdisks, &sdisks) != 0) { 492fc58801cSScott Long nsdisks = 0; 493fc58801cSScott Long sdisks = NULL; 494fc58801cSScott Long } 495fc58801cSScott Long if (nsdisks != 0) 496fc58801cSScott Long state_len = strlen(STANDALONE_STATE); 497fc58801cSScott Long 498fc58801cSScott Long /* Walk the drive list to determine width of state column. */ 499fc58801cSScott Long for (i = 0; i < list->ndrives; i++) { 500fc58801cSScott Long len = strlen(mpt_pdstate(list->drives[i])); 501fc58801cSScott Long if (len > state_len) 502fc58801cSScott Long state_len = len; 503fc58801cSScott Long } 504fc58801cSScott Long 505fc58801cSScott Long /* List the drives. */ 506fc58801cSScott Long printf("mpt%d Physical Drives:\n", mpt_unit); 507fc58801cSScott Long for (i = 0; i < list->ndrives; i++) { 508fc58801cSScott Long printf("%4u ", list->drives[i]->PhysDiskNum); 509fc58801cSScott Long print_pd(list->drives[i], state_len, 1); 510fc58801cSScott Long printf("\n"); 511fc58801cSScott Long } 512fc58801cSScott Long mpt_free_pd_list(list); 513fc58801cSScott Long for (i = 0; i < nsdisks; i++) { 514fc58801cSScott Long printf("%4s ", sdisks[i].devname); 515fc58801cSScott Long print_standalone(&sdisks[i], state_len, 1); 516fc58801cSScott Long printf("\n"); 517fc58801cSScott Long } 518fc58801cSScott Long free(sdisks); 519fc58801cSScott Long 520fc58801cSScott Long close(fd); 521fc58801cSScott Long 522fc58801cSScott Long return (0); 523fc58801cSScott Long } 524fc58801cSScott Long MPT_COMMAND(show, drives, show_drives); 525fc58801cSScott Long 526fc58801cSScott Long #ifdef DEBUG 527fc58801cSScott Long static int 528fc58801cSScott Long show_physdisks(int ac, char **av) 529fc58801cSScott Long { 530fc58801cSScott Long CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 531fc58801cSScott Long U16 IOCStatus; 532fc58801cSScott Long int fd, i; 533fc58801cSScott Long 534fc58801cSScott Long if (ac != 1) { 535fc58801cSScott Long warnx("show drives: extra arguments"); 536fc58801cSScott Long return (EINVAL); 537fc58801cSScott Long } 538fc58801cSScott Long 539fc58801cSScott Long fd = mpt_open(mpt_unit); 540fc58801cSScott Long if (fd < 0) { 541fc58801cSScott Long warn("mpt_open"); 542fc58801cSScott Long return (errno); 543fc58801cSScott Long } 544fc58801cSScott Long 545fc58801cSScott Long /* Try to find each possible phys disk page. */ 546fc58801cSScott Long for (i = 0; i <= 0xff; i++) { 547fc58801cSScott Long pinfo = mpt_pd_info(fd, i, &IOCStatus); 548fc58801cSScott Long if (pinfo == NULL) { 5495f1f6da8SJohn Baldwin if ((IOCStatus & MPI_IOCSTATUS_MASK) != 5505f1f6da8SJohn Baldwin MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 551fc58801cSScott Long warnx("mpt_pd_info(%d): %s", i, 552fc58801cSScott Long mpt_ioc_status(IOCStatus)); 553fc58801cSScott Long continue; 554fc58801cSScott Long } 555fc58801cSScott Long printf("%3u ", i); 556fc58801cSScott Long print_pd(pinfo, -1, 1); 557fc58801cSScott Long printf("\n"); 558fc58801cSScott Long } 559fc58801cSScott Long 560fc58801cSScott Long close(fd); 561fc58801cSScott Long 562fc58801cSScott Long return (0); 563fc58801cSScott Long } 564fc58801cSScott Long MPT_COMMAND(show, pd, show_physdisks); 565fc58801cSScott Long #endif 566