1196212Sscottl/*- 2196212Sscottl * Copyright (c) 2008 Yahoo!, Inc. 3196212Sscottl * All rights reserved. 4196212Sscottl * Written by: John Baldwin <jhb@FreeBSD.org> 5196212Sscottl * 6196212Sscottl * Redistribution and use in source and binary forms, with or without 7196212Sscottl * modification, are permitted provided that the following conditions 8196212Sscottl * are met: 9196212Sscottl * 1. Redistributions of source code must retain the above copyright 10196212Sscottl * notice, this list of conditions and the following disclaimer. 11196212Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12196212Sscottl * notice, this list of conditions and the following disclaimer in the 13196212Sscottl * documentation and/or other materials provided with the distribution. 14196212Sscottl * 3. Neither the name of the author nor the names of any co-contributors 15196212Sscottl * may be used to endorse or promote products derived from this software 16196212Sscottl * without specific prior written permission. 17196212Sscottl * 18196212Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19196212Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20196212Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21196212Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22196212Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23196212Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24196212Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25196212Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26196212Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27196212Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28196212Sscottl * SUCH DAMAGE. 29196212Sscottl */ 30196212Sscottl 31196212Sscottl#include <sys/cdefs.h> 32196212Sscottl__RCSID("$FreeBSD$"); 33196212Sscottl 34196212Sscottl#include <sys/param.h> 35196212Sscottl#include <sys/errno.h> 36196212Sscottl#include <err.h> 37196212Sscottl#include <libutil.h> 38196212Sscottl#include <stdio.h> 39196212Sscottl#include <stdlib.h> 40196212Sscottl#include <string.h> 41196212Sscottl#include <unistd.h> 42196212Sscottl#include "mptutil.h" 43196212Sscottl 44196212SscottlMPT_TABLE(top, show); 45196212Sscottl 46196212Sscottl#define STANDALONE_STATE "ONLINE" 47196212Sscottl 48196212Sscottlstatic void 49196212Sscottlformat_stripe(char *buf, size_t buflen, U32 stripe) 50196212Sscottl{ 51196212Sscottl 52196212Sscottl humanize_number(buf, buflen, stripe * 512, "", HN_AUTOSCALE, 53196212Sscottl HN_B | HN_NOSPACE); 54196212Sscottl} 55196212Sscottl 56196212Sscottlstatic void 57196212Sscottldisplay_stripe_map(const char *label, U32 StripeMap) 58196212Sscottl{ 59196212Sscottl char stripe[5]; 60196212Sscottl int comma, i; 61196212Sscottl 62196212Sscottl comma = 0; 63196212Sscottl printf("%s: ", label); 64196212Sscottl for (i = 0; StripeMap != 0; i++, StripeMap >>= 1) 65196212Sscottl if (StripeMap & 1) { 66196212Sscottl format_stripe(stripe, sizeof(stripe), 1 << i); 67196212Sscottl if (comma) 68196212Sscottl printf(", "); 69196212Sscottl printf("%s", stripe); 70196212Sscottl comma = 1; 71196212Sscottl } 72196212Sscottl printf("\n"); 73196212Sscottl} 74196212Sscottl 75196212Sscottlstatic int 76196212Sscottlshow_adapter(int ac, char **av) 77196212Sscottl{ 78196212Sscottl CONFIG_PAGE_MANUFACTURING_0 *man0; 79196212Sscottl CONFIG_PAGE_IOC_2 *ioc2; 80196212Sscottl CONFIG_PAGE_IOC_6 *ioc6; 81204086Sjhb U16 IOCStatus; 82215046Sjhb int comma, error, fd; 83196212Sscottl 84196212Sscottl if (ac != 1) { 85196212Sscottl warnx("show adapter: extra arguments"); 86196212Sscottl return (EINVAL); 87196212Sscottl } 88196212Sscottl 89196212Sscottl fd = mpt_open(mpt_unit); 90196212Sscottl if (fd < 0) { 91215046Sjhb error = errno; 92196212Sscottl warn("mpt_open"); 93215046Sjhb return (error); 94196212Sscottl } 95196212Sscottl 96196212Sscottl man0 = mpt_read_man_page(fd, 0, NULL); 97196212Sscottl if (man0 == NULL) { 98215046Sjhb error = errno; 99196212Sscottl warn("Failed to get controller info"); 100215046Sjhb return (error); 101196212Sscottl } 102196212Sscottl if (man0->Header.PageLength < sizeof(*man0) / 4) { 103215046Sjhb warnx("Invalid controller info"); 104196212Sscottl return (EINVAL); 105196212Sscottl } 106196212Sscottl printf("mpt%d Adapter:\n", mpt_unit); 107196212Sscottl printf(" Board Name: %.16s\n", man0->BoardName); 108196212Sscottl printf(" Board Assembly: %.16s\n", man0->BoardAssembly); 109196212Sscottl printf(" Chip Name: %.16s\n", man0->ChipName); 110196212Sscottl printf(" Chip Revision: %.16s\n", man0->ChipRevision); 111196212Sscottl 112196212Sscottl free(man0); 113196212Sscottl 114204086Sjhb ioc2 = mpt_read_ioc_page(fd, 2, &IOCStatus); 115196212Sscottl if (ioc2 != NULL) { 116196212Sscottl printf(" RAID Levels:"); 117196212Sscottl comma = 0; 118196212Sscottl if (ioc2->CapabilitiesFlags & 119196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) { 120196212Sscottl printf(" RAID0"); 121196212Sscottl comma = 1; 122196212Sscottl } 123196212Sscottl if (ioc2->CapabilitiesFlags & 124196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) { 125196212Sscottl printf("%s RAID1", comma ? "," : ""); 126196212Sscottl comma = 1; 127196212Sscottl } 128196212Sscottl if (ioc2->CapabilitiesFlags & 129196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) { 130196212Sscottl printf("%s RAID1E", comma ? "," : ""); 131196212Sscottl comma = 1; 132196212Sscottl } 133196212Sscottl if (ioc2->CapabilitiesFlags & 134196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT) { 135196212Sscottl printf("%s RAID5", comma ? "," : ""); 136196212Sscottl comma = 1; 137196212Sscottl } 138196212Sscottl if (ioc2->CapabilitiesFlags & 139196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT) { 140196212Sscottl printf("%s RAID6", comma ? "," : ""); 141196212Sscottl comma = 1; 142196212Sscottl } 143196212Sscottl if (ioc2->CapabilitiesFlags & 144196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT) { 145196212Sscottl printf("%s RAID10", comma ? "," : ""); 146196212Sscottl comma = 1; 147196212Sscottl } 148196212Sscottl if (ioc2->CapabilitiesFlags & 149196212Sscottl MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT) { 150196212Sscottl printf("%s RAID50", comma ? "," : ""); 151196212Sscottl comma = 1; 152196212Sscottl } 153196212Sscottl if (!comma) 154196212Sscottl printf(" none"); 155196212Sscottl printf("\n"); 156196212Sscottl free(ioc2); 157204086Sjhb } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 158204086Sjhb MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 159204086Sjhb warnx("mpt_read_ioc_page(2): %s", mpt_ioc_status(IOCStatus)); 160196212Sscottl 161204086Sjhb ioc6 = mpt_read_ioc_page(fd, 6, &IOCStatus); 162196212Sscottl if (ioc6 != NULL) { 163196212Sscottl display_stripe_map(" RAID0 Stripes", 164196212Sscottl ioc6->SupportedStripeSizeMapIS); 165196212Sscottl display_stripe_map(" RAID1E Stripes", 166196212Sscottl ioc6->SupportedStripeSizeMapIME); 167196212Sscottl printf(" RAID0 Drives/Vol: %u", ioc6->MinDrivesIS); 168196212Sscottl if (ioc6->MinDrivesIS != ioc6->MaxDrivesIS) 169196212Sscottl printf("-%u", ioc6->MaxDrivesIS); 170196212Sscottl printf("\n"); 171196212Sscottl printf(" RAID1 Drives/Vol: %u", ioc6->MinDrivesIM); 172196212Sscottl if (ioc6->MinDrivesIM != ioc6->MaxDrivesIM) 173196212Sscottl printf("-%u", ioc6->MaxDrivesIM); 174196212Sscottl printf("\n"); 175196212Sscottl printf("RAID1E Drives/Vol: %u", ioc6->MinDrivesIME); 176196212Sscottl if (ioc6->MinDrivesIME != ioc6->MaxDrivesIME) 177196212Sscottl printf("-%u", ioc6->MaxDrivesIME); 178196212Sscottl printf("\n"); 179196212Sscottl free(ioc6); 180204086Sjhb } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 181204086Sjhb MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 182204086Sjhb warnx("mpt_read_ioc_page(6): %s", mpt_ioc_status(IOCStatus)); 183196212Sscottl 184196212Sscottl /* TODO: Add an ioctl to fetch IOC_FACTS and print firmware version. */ 185196212Sscottl 186196212Sscottl close(fd); 187196212Sscottl 188196212Sscottl return (0); 189196212Sscottl} 190196212SscottlMPT_COMMAND(show, adapter, show_adapter); 191196212Sscottl 192196212Sscottlstatic void 193196212Sscottlprint_vol(CONFIG_PAGE_RAID_VOL_0 *info, int state_len) 194196212Sscottl{ 195196212Sscottl uint64_t size; 196196212Sscottl const char *level, *state; 197196212Sscottl char buf[6], stripe[5]; 198196212Sscottl 199196212Sscottl size = ((uint64_t)info->MaxLBAHigh << 32) | info->MaxLBA; 200196212Sscottl humanize_number(buf, sizeof(buf), (size + 1) * 512, "", HN_AUTOSCALE, 201196212Sscottl HN_B | HN_NOSPACE | HN_DECIMAL); 202196212Sscottl if (info->VolumeType == MPI_RAID_VOL_TYPE_IM) 203196212Sscottl stripe[0] = '\0'; 204196212Sscottl else 205196212Sscottl format_stripe(stripe, sizeof(stripe), info->StripeSize); 206196212Sscottl level = mpt_raid_level(info->VolumeType); 207196212Sscottl state = mpt_volstate(info->VolumeStatus.State); 208196212Sscottl if (state_len > 0) 209196212Sscottl printf("(%6s) %-8s %6s %-*s", buf, level, stripe, state_len, 210196212Sscottl state); 211196212Sscottl else if (stripe[0] != '\0') 212196212Sscottl printf("(%s) %s %s %s", buf, level, stripe, state); 213196212Sscottl else 214196212Sscottl printf("(%s) %s %s", buf, level, state); 215196212Sscottl} 216196212Sscottl 217196212Sscottlstatic void 218196212Sscottlprint_pd(CONFIG_PAGE_RAID_PHYS_DISK_0 *info, int state_len, int location) 219196212Sscottl{ 220196212Sscottl const char *inq, *state; 221196212Sscottl char buf[6]; 222196212Sscottl 223196212Sscottl humanize_number(buf, sizeof(buf), ((uint64_t)info->MaxLBA + 1) * 512, 224196212Sscottl "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 225196212Sscottl state = mpt_pdstate(info); 226196212Sscottl if (state_len > 0) 227196212Sscottl printf("(%6s) %-*s", buf, state_len, state); 228196212Sscottl else 229196212Sscottl printf("(%s) %s", buf, state); 230196212Sscottl inq = mpt_pd_inq_string(info); 231196212Sscottl if (inq != NULL) 232196212Sscottl printf(" %s", inq); 233196212Sscottl if (!location) 234196212Sscottl return; 235196212Sscottl printf(" bus %d id %d", info->PhysDiskBus, info->PhysDiskID); 236196212Sscottl} 237196212Sscottl 238196212Sscottlstatic void 239196212Sscottlprint_standalone(struct mpt_standalone_disk *disk, int state_len, int location) 240196212Sscottl{ 241196212Sscottl char buf[6]; 242196212Sscottl 243196212Sscottl humanize_number(buf, sizeof(buf), (disk->maxlba + 1) * 512, 244196212Sscottl "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 245196212Sscottl if (state_len > 0) 246196212Sscottl printf("(%6s) %-*s", buf, state_len, STANDALONE_STATE); 247196212Sscottl else 248196212Sscottl printf("(%s) %s", buf, STANDALONE_STATE); 249196212Sscottl if (disk->inqstring[0] != '\0') 250196212Sscottl printf(" %s", disk->inqstring); 251196212Sscottl if (!location) 252196212Sscottl return; 253196212Sscottl printf(" bus %d id %d", disk->bus, disk->target); 254196212Sscottl} 255196212Sscottl 256196212Sscottlstatic void 257196212Sscottlprint_spare_pools(U8 HotSparePool) 258196212Sscottl{ 259196212Sscottl int i; 260196212Sscottl 261196212Sscottl if (HotSparePool == 0) { 262196212Sscottl printf("none"); 263196212Sscottl return; 264196212Sscottl } 265196212Sscottl for (i = 0; HotSparePool != 0; i++) { 266196212Sscottl if (HotSparePool & 1) { 267196212Sscottl printf("%d", i); 268196212Sscottl if (HotSparePool == 1) 269196212Sscottl break; 270196212Sscottl printf(", "); 271196212Sscottl } 272196212Sscottl HotSparePool >>= 1; 273196212Sscottl } 274196212Sscottl} 275196212Sscottl 276196212Sscottlstatic int 277196212Sscottlshow_config(int ac, char **av) 278196212Sscottl{ 279196212Sscottl CONFIG_PAGE_IOC_2 *ioc2; 280196212Sscottl CONFIG_PAGE_IOC_2_RAID_VOL *vol; 281196212Sscottl CONFIG_PAGE_IOC_5 *ioc5; 282196212Sscottl IOC_5_HOT_SPARE *spare; 283196212Sscottl CONFIG_PAGE_RAID_VOL_0 *vinfo; 284196212Sscottl RAID_VOL0_PHYS_DISK *disk; 285196212Sscottl CONFIG_PAGE_RAID_VOL_1 *vnames; 286196212Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 287196212Sscottl struct mpt_standalone_disk *sdisks; 288215046Sjhb int error, fd, i, j, nsdisks; 289196212Sscottl 290196212Sscottl if (ac != 1) { 291196212Sscottl warnx("show config: extra arguments"); 292196212Sscottl return (EINVAL); 293196212Sscottl } 294196212Sscottl 295196212Sscottl fd = mpt_open(mpt_unit); 296196212Sscottl if (fd < 0) { 297215046Sjhb error = errno; 298196212Sscottl warn("mpt_open"); 299215046Sjhb return (error); 300196212Sscottl } 301196212Sscottl 302196212Sscottl /* Get the config from the controller. */ 303196212Sscottl ioc2 = mpt_read_ioc_page(fd, 2, NULL); 304196212Sscottl ioc5 = mpt_read_ioc_page(fd, 5, NULL); 305196212Sscottl if (ioc2 == NULL || ioc5 == NULL) { 306215046Sjhb error = errno; 307196212Sscottl warn("Failed to get config"); 308215046Sjhb return (error); 309196212Sscottl } 310196212Sscottl if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) { 311215046Sjhb error = errno; 312196212Sscottl warn("Failed to get standalone drive list"); 313215046Sjhb return (error); 314196212Sscottl } 315196212Sscottl 316196212Sscottl /* Dump out the configuration. */ 317196212Sscottl printf("mpt%d Configuration: %d volumes, %d drives\n", 318196212Sscottl mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks + 319196212Sscottl nsdisks); 320196212Sscottl vol = ioc2->RaidVolume; 321196212Sscottl for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 322196212Sscottl printf(" volume %s ", mpt_volume_name(vol->VolumeBus, 323196212Sscottl vol->VolumeID)); 324196212Sscottl vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL); 325196212Sscottl if (vinfo == NULL) { 326196212Sscottl printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType)); 327196212Sscottl } else 328196212Sscottl print_vol(vinfo, -1); 329196212Sscottl vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 330196212Sscottl if (vnames != NULL) { 331196212Sscottl if (vnames->Name[0] != '\0') 332196212Sscottl printf(" <%s>", vnames->Name); 333196212Sscottl free(vnames); 334196212Sscottl } 335196212Sscottl if (vinfo == NULL) { 336196212Sscottl printf("\n"); 337196212Sscottl continue; 338196212Sscottl } 339196212Sscottl printf(" spans:\n"); 340196212Sscottl disk = vinfo->PhysDisk; 341196212Sscottl for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) { 342196212Sscottl printf(" drive %u ", disk->PhysDiskNum); 343196212Sscottl pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL); 344196212Sscottl if (pinfo != NULL) { 345196212Sscottl print_pd(pinfo, -1, 0); 346196212Sscottl free(pinfo); 347196212Sscottl } 348196212Sscottl printf("\n"); 349196212Sscottl } 350196212Sscottl if (vinfo->VolumeSettings.HotSparePool != 0) { 351196212Sscottl printf(" spare pools: "); 352196212Sscottl print_spare_pools(vinfo->VolumeSettings.HotSparePool); 353196212Sscottl printf("\n"); 354196212Sscottl } 355196212Sscottl free(vinfo); 356196212Sscottl } 357196212Sscottl 358196212Sscottl spare = ioc5->HotSpare; 359196212Sscottl for (i = 0; i < ioc5->NumHotSpares; spare++, i++) { 360196212Sscottl printf(" spare %u ", spare->PhysDiskNum); 361196212Sscottl pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL); 362196212Sscottl if (pinfo != NULL) { 363196212Sscottl print_pd(pinfo, -1, 0); 364196212Sscottl free(pinfo); 365196212Sscottl } 366196212Sscottl printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1); 367196212Sscottl } 368196212Sscottl for (i = 0; i < nsdisks; i++) { 369196212Sscottl printf(" drive %s ", sdisks[i].devname); 370196212Sscottl print_standalone(&sdisks[i], -1, 0); 371196212Sscottl printf("\n"); 372196212Sscottl } 373196212Sscottl free(ioc2); 374196212Sscottl free(ioc5); 375196212Sscottl free(sdisks); 376196212Sscottl close(fd); 377196212Sscottl 378196212Sscottl return (0); 379196212Sscottl} 380196212SscottlMPT_COMMAND(show, config, show_config); 381196212Sscottl 382196212Sscottlstatic int 383196212Sscottlshow_volumes(int ac, char **av) 384196212Sscottl{ 385196212Sscottl CONFIG_PAGE_IOC_2 *ioc2; 386196212Sscottl CONFIG_PAGE_IOC_2_RAID_VOL *vol; 387196212Sscottl CONFIG_PAGE_RAID_VOL_0 **volumes; 388196212Sscottl CONFIG_PAGE_RAID_VOL_1 *vnames; 389215046Sjhb int error, fd, i, len, state_len; 390196212Sscottl 391196212Sscottl if (ac != 1) { 392196212Sscottl warnx("show volumes: extra arguments"); 393196212Sscottl return (EINVAL); 394196212Sscottl } 395196212Sscottl 396196212Sscottl fd = mpt_open(mpt_unit); 397196212Sscottl if (fd < 0) { 398215046Sjhb error = errno; 399196212Sscottl warn("mpt_open"); 400215046Sjhb return (error); 401196212Sscottl } 402196212Sscottl 403196212Sscottl /* Get the volume list from the controller. */ 404196212Sscottl ioc2 = mpt_read_ioc_page(fd, 2, NULL); 405196212Sscottl if (ioc2 == NULL) { 406215046Sjhb error = errno; 407196212Sscottl warn("Failed to get volume list"); 408215046Sjhb return (error); 409196212Sscottl } 410196212Sscottl 411196212Sscottl /* 412196212Sscottl * Go ahead and read the info for all the volumes and figure 413196212Sscottl * out the maximum width of the state field. 414196212Sscottl */ 415196212Sscottl volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes); 416196212Sscottl state_len = strlen("State"); 417196212Sscottl vol = ioc2->RaidVolume; 418196212Sscottl for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 419196212Sscottl volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, 420196212Sscottl NULL); 421196212Sscottl if (volumes[i] == NULL) 422196212Sscottl len = strlen("UNKNOWN"); 423196212Sscottl else 424196212Sscottl len = strlen(mpt_volstate( 425196212Sscottl volumes[i]->VolumeStatus.State)); 426196212Sscottl if (len > state_len) 427196212Sscottl state_len = len; 428196212Sscottl } 429196212Sscottl printf("mpt%d Volumes:\n", mpt_unit); 430196212Sscottl printf(" Id Size Level Stripe "); 431196212Sscottl len = state_len - strlen("State"); 432196212Sscottl for (i = 0; i < (len + 1) / 2; i++) 433196212Sscottl printf(" "); 434196212Sscottl printf("State"); 435196212Sscottl for (i = 0; i < len / 2; i++) 436196212Sscottl printf(" "); 437196212Sscottl printf(" Write-Cache Name\n"); 438196212Sscottl vol = ioc2->RaidVolume; 439196212Sscottl for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 440196212Sscottl printf("%6s ", mpt_volume_name(vol->VolumeBus, vol->VolumeID)); 441196212Sscottl if (volumes[i] != NULL) 442196212Sscottl print_vol(volumes[i], state_len); 443196212Sscottl else 444196212Sscottl printf(" %-8s %-*s", 445196212Sscottl mpt_raid_level(vol->VolumeType), state_len, 446196212Sscottl "UNKNOWN"); 447196212Sscottl if (volumes[i] != NULL) { 448196212Sscottl if (volumes[i]->VolumeSettings.Settings & 449196212Sscottl MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE) 450196212Sscottl printf(" Enabled "); 451196212Sscottl else 452196212Sscottl printf(" Disabled "); 453196212Sscottl } else 454196212Sscottl printf(" "); 455196212Sscottl free(volumes[i]); 456196212Sscottl vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 457196212Sscottl if (vnames != NULL) { 458196212Sscottl if (vnames->Name[0] != '\0') 459196212Sscottl printf(" <%s>", vnames->Name); 460196212Sscottl free(vnames); 461196212Sscottl } 462196212Sscottl printf("\n"); 463196212Sscottl } 464196212Sscottl free(ioc2); 465196212Sscottl close(fd); 466196212Sscottl 467196212Sscottl return (0); 468196212Sscottl} 469196212SscottlMPT_COMMAND(show, volumes, show_volumes); 470196212Sscottl 471196212Sscottlstatic int 472196212Sscottlshow_drives(int ac, char **av) 473196212Sscottl{ 474196212Sscottl struct mpt_drive_list *list; 475196212Sscottl struct mpt_standalone_disk *sdisks; 476215046Sjhb int error, fd, i, len, nsdisks, state_len; 477196212Sscottl 478196212Sscottl if (ac != 1) { 479196212Sscottl warnx("show drives: extra arguments"); 480196212Sscottl return (EINVAL); 481196212Sscottl } 482196212Sscottl 483196212Sscottl fd = mpt_open(mpt_unit); 484196212Sscottl if (fd < 0) { 485215046Sjhb error = errno; 486196212Sscottl warn("mpt_open"); 487215046Sjhb return (error); 488196212Sscottl } 489196212Sscottl 490196212Sscottl /* Get the drive list. */ 491196212Sscottl list = mpt_pd_list(fd); 492196212Sscottl if (list == NULL) { 493215046Sjhb error = errno; 494196212Sscottl warn("Failed to get drive list"); 495215046Sjhb return (error); 496196212Sscottl } 497196212Sscottl 498196212Sscottl /* Fetch the list of standalone disks for this controller. */ 499196212Sscottl state_len = 0; 500196212Sscottl if (mpt_fetch_disks(fd, &nsdisks, &sdisks) != 0) { 501196212Sscottl nsdisks = 0; 502196212Sscottl sdisks = NULL; 503196212Sscottl } 504196212Sscottl if (nsdisks != 0) 505196212Sscottl state_len = strlen(STANDALONE_STATE); 506196212Sscottl 507196212Sscottl /* Walk the drive list to determine width of state column. */ 508196212Sscottl for (i = 0; i < list->ndrives; i++) { 509196212Sscottl len = strlen(mpt_pdstate(list->drives[i])); 510196212Sscottl if (len > state_len) 511196212Sscottl state_len = len; 512196212Sscottl } 513196212Sscottl 514196212Sscottl /* List the drives. */ 515196212Sscottl printf("mpt%d Physical Drives:\n", mpt_unit); 516196212Sscottl for (i = 0; i < list->ndrives; i++) { 517196212Sscottl printf("%4u ", list->drives[i]->PhysDiskNum); 518196212Sscottl print_pd(list->drives[i], state_len, 1); 519196212Sscottl printf("\n"); 520196212Sscottl } 521196212Sscottl mpt_free_pd_list(list); 522196212Sscottl for (i = 0; i < nsdisks; i++) { 523196212Sscottl printf("%4s ", sdisks[i].devname); 524196212Sscottl print_standalone(&sdisks[i], state_len, 1); 525196212Sscottl printf("\n"); 526196212Sscottl } 527196212Sscottl free(sdisks); 528196212Sscottl 529196212Sscottl close(fd); 530196212Sscottl 531196212Sscottl return (0); 532196212Sscottl} 533196212SscottlMPT_COMMAND(show, drives, show_drives); 534196212Sscottl 535196212Sscottl#ifdef DEBUG 536196212Sscottlstatic int 537196212Sscottlshow_physdisks(int ac, char **av) 538196212Sscottl{ 539196212Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 540196212Sscottl U16 IOCStatus; 541236287Seadler int error, fd, i; 542196212Sscottl 543196212Sscottl if (ac != 1) { 544196212Sscottl warnx("show drives: extra arguments"); 545196212Sscottl return (EINVAL); 546196212Sscottl } 547196212Sscottl 548196212Sscottl fd = mpt_open(mpt_unit); 549196212Sscottl if (fd < 0) { 550215046Sjhb error = errno; 551196212Sscottl warn("mpt_open"); 552215046Sjhb return (error); 553196212Sscottl } 554196212Sscottl 555196212Sscottl /* Try to find each possible phys disk page. */ 556196212Sscottl for (i = 0; i <= 0xff; i++) { 557196212Sscottl pinfo = mpt_pd_info(fd, i, &IOCStatus); 558196212Sscottl if (pinfo == NULL) { 559204086Sjhb if ((IOCStatus & MPI_IOCSTATUS_MASK) != 560204086Sjhb MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 561196212Sscottl warnx("mpt_pd_info(%d): %s", i, 562196212Sscottl mpt_ioc_status(IOCStatus)); 563196212Sscottl continue; 564196212Sscottl } 565196212Sscottl printf("%3u ", i); 566196212Sscottl print_pd(pinfo, -1, 1); 567196212Sscottl printf("\n"); 568196212Sscottl } 569196212Sscottl 570196212Sscottl close(fd); 571196212Sscottl 572196212Sscottl return (0); 573196212Sscottl} 574196212SscottlMPT_COMMAND(show, pd, show_physdisks); 575196212Sscottl#endif 576