1258945Sroberto/*- 2280849Scy * Copyright (c) 2008 Yahoo!, Inc. 3258945Sroberto * All rights reserved. 4258945Sroberto * Written by: John Baldwin <jhb@FreeBSD.org> 5258945Sroberto * 6258945Sroberto * Redistribution and use in source and binary forms, with or without 7258945Sroberto * modification, are permitted provided that the following conditions 8258945Sroberto * are met: 9258945Sroberto * 1. Redistributions of source code must retain the above copyright 10258945Sroberto * notice, this list of conditions and the following disclaimer. 11258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright 12258945Sroberto * notice, this list of conditions and the following disclaimer in the 13258945Sroberto * documentation and/or other materials provided with the distribution. 14258945Sroberto * 3. Neither the name of the author nor the names of any co-contributors 15258945Sroberto * may be used to endorse or promote products derived from this software 16258945Sroberto * without specific prior written permission. 17258945Sroberto * 18280849Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20258945Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21258945Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22258945Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25258945Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26258945Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27258945Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28258945Sroberto * SUCH DAMAGE. 29258945Sroberto */ 30258945Sroberto 31258945Sroberto#include <sys/cdefs.h> 32258945Sroberto__RCSID("$FreeBSD$"); 33258945Sroberto 34280849Scy#include <sys/param.h> 35258945Sroberto#include <sys/errno.h> 36258945Sroberto#include <err.h> 37258945Sroberto#include <libutil.h> 38258945Sroberto#include <stdio.h> 39280849Scy#include <stdlib.h> 40258945Sroberto#include <string.h> 41258945Sroberto#include <unistd.h> 42258945Sroberto#include "mptutil.h" 43258945Sroberto 44258945SrobertoMPT_TABLE(top, show); 45258945Sroberto 46258945Sroberto#define STANDALONE_STATE "ONLINE" 47258945Sroberto 48258945Srobertostatic void 49258945Srobertoformat_stripe(char *buf, size_t buflen, U32 stripe) 50258945Sroberto{ 51258945Sroberto 52258945Sroberto humanize_number(buf, buflen, stripe * 512, "", HN_AUTOSCALE, 53258945Sroberto HN_B | HN_NOSPACE); 54258945Sroberto} 55258945Sroberto 56258945Srobertostatic void 57258945Srobertodisplay_stripe_map(const char *label, U32 StripeMap) 58258945Sroberto{ 59258945Sroberto char stripe[5]; 60258945Sroberto int comma, i; 61258945Sroberto 62258945Sroberto comma = 0; 63258945Sroberto printf("%s: ", label); 64258945Sroberto for (i = 0; StripeMap != 0; i++, StripeMap >>= 1) 65258945Sroberto if (StripeMap & 1) { 66258945Sroberto format_stripe(stripe, sizeof(stripe), 1 << i); 67258945Sroberto if (comma) 68258945Sroberto printf(", "); 69258945Sroberto printf("%s", stripe); 70258945Sroberto comma = 1; 71258945Sroberto } 72258945Sroberto printf("\n"); 73258945Sroberto} 74258945Sroberto 75258945Srobertostatic int 76258945Srobertoshow_adapter(int ac, char **av) 77258945Sroberto{ 78258945Sroberto CONFIG_PAGE_MANUFACTURING_0 *man0; 79258945Sroberto CONFIG_PAGE_IOC_2 *ioc2; 80258945Sroberto CONFIG_PAGE_IOC_6 *ioc6; 81258945Sroberto U16 IOCStatus; 82258945Sroberto int comma, error, fd; 83258945Sroberto 84258945Sroberto if (ac != 1) { 85258945Sroberto warnx("show adapter: extra arguments"); 86258945Sroberto return (EINVAL); 87258945Sroberto } 88258945Sroberto 89258945Sroberto fd = mpt_open(mpt_unit); 90258945Sroberto if (fd < 0) { 91258945Sroberto error = errno; 92258945Sroberto warn("mpt_open"); 93258945Sroberto return (error); 94258945Sroberto } 95258945Sroberto 96258945Sroberto man0 = mpt_read_man_page(fd, 0, NULL); 97258945Sroberto if (man0 == NULL) { 98258945Sroberto error = errno; 99258945Sroberto warn("Failed to get controller info"); 100258945Sroberto return (error); 101258945Sroberto } 102258945Sroberto if (man0->Header.PageLength < sizeof(*man0) / 4) { 103258945Sroberto warnx("Invalid controller info"); 104258945Sroberto return (EINVAL); 105258945Sroberto } 106258945Sroberto printf("mpt%d Adapter:\n", mpt_unit); 107258945Sroberto printf(" Board Name: %.16s\n", man0->BoardName); 108258945Sroberto printf(" Board Assembly: %.16s\n", man0->BoardAssembly); 109258945Sroberto printf(" Chip Name: %.16s\n", man0->ChipName); 110258945Sroberto printf(" Chip Revision: %.16s\n", man0->ChipRevision); 111258945Sroberto 112258945Sroberto free(man0); 113258945Sroberto 114258945Sroberto ioc2 = mpt_read_ioc_page(fd, 2, &IOCStatus); 115258945Sroberto if (ioc2 != NULL) { 116258945Sroberto printf(" RAID Levels:"); 117258945Sroberto comma = 0; 118258945Sroberto if (ioc2->CapabilitiesFlags & 119258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) { 120258945Sroberto printf(" RAID0"); 121258945Sroberto comma = 1; 122258945Sroberto } 123258945Sroberto if (ioc2->CapabilitiesFlags & 124258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) { 125258945Sroberto printf("%s RAID1", comma ? "," : ""); 126258945Sroberto comma = 1; 127258945Sroberto } 128258945Sroberto if (ioc2->CapabilitiesFlags & 129258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) { 130258945Sroberto printf("%s RAID1E", comma ? "," : ""); 131258945Sroberto comma = 1; 132258945Sroberto } 133258945Sroberto if (ioc2->CapabilitiesFlags & 134258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT) { 135258945Sroberto printf("%s RAID5", comma ? "," : ""); 136258945Sroberto comma = 1; 137258945Sroberto } 138258945Sroberto if (ioc2->CapabilitiesFlags & 139258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT) { 140258945Sroberto printf("%s RAID6", comma ? "," : ""); 141258945Sroberto comma = 1; 142258945Sroberto } 143258945Sroberto if (ioc2->CapabilitiesFlags & 144258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT) { 145258945Sroberto printf("%s RAID10", comma ? "," : ""); 146258945Sroberto comma = 1; 147258945Sroberto } 148258945Sroberto if (ioc2->CapabilitiesFlags & 149258945Sroberto MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT) { 150258945Sroberto printf("%s RAID50", comma ? "," : ""); 151258945Sroberto comma = 1; 152258945Sroberto } 153258945Sroberto if (!comma) 154258945Sroberto printf(" none"); 155258945Sroberto printf("\n"); 156258945Sroberto free(ioc2); 157258945Sroberto } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 158258945Sroberto MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 159258945Sroberto warnx("mpt_read_ioc_page(2): %s", mpt_ioc_status(IOCStatus)); 160258945Sroberto 161258945Sroberto ioc6 = mpt_read_ioc_page(fd, 6, &IOCStatus); 162258945Sroberto if (ioc6 != NULL) { 163258945Sroberto display_stripe_map(" RAID0 Stripes", 164258945Sroberto ioc6->SupportedStripeSizeMapIS); 165258945Sroberto display_stripe_map(" RAID1E Stripes", 166258945Sroberto ioc6->SupportedStripeSizeMapIME); 167258945Sroberto printf(" RAID0 Drives/Vol: %u", ioc6->MinDrivesIS); 168258945Sroberto if (ioc6->MinDrivesIS != ioc6->MaxDrivesIS) 169258945Sroberto printf("-%u", ioc6->MaxDrivesIS); 170258945Sroberto printf("\n"); 171258945Sroberto printf(" RAID1 Drives/Vol: %u", ioc6->MinDrivesIM); 172258945Sroberto if (ioc6->MinDrivesIM != ioc6->MaxDrivesIM) 173258945Sroberto printf("-%u", ioc6->MaxDrivesIM); 174258945Sroberto printf("\n"); 175258945Sroberto printf("RAID1E Drives/Vol: %u", ioc6->MinDrivesIME); 176258945Sroberto if (ioc6->MinDrivesIME != ioc6->MaxDrivesIME) 177258945Sroberto printf("-%u", ioc6->MaxDrivesIME); 178258945Sroberto printf("\n"); 179258945Sroberto free(ioc6); 180258945Sroberto } else if ((IOCStatus & MPI_IOCSTATUS_MASK) != 181258945Sroberto MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 182258945Sroberto warnx("mpt_read_ioc_page(6): %s", mpt_ioc_status(IOCStatus)); 183258945Sroberto 184258945Sroberto /* TODO: Add an ioctl to fetch IOC_FACTS and print firmware version. */ 185258945Sroberto 186258945Sroberto close(fd); 187258945Sroberto 188258945Sroberto return (0); 189258945Sroberto} 190258945SrobertoMPT_COMMAND(show, adapter, show_adapter); 191258945Sroberto 192258945Srobertostatic void 193258945Srobertoprint_vol(CONFIG_PAGE_RAID_VOL_0 *info, int state_len) 194258945Sroberto{ 195258945Sroberto uint64_t size; 196258945Sroberto const char *level, *state; 197258945Sroberto char buf[6], stripe[5]; 198258945Sroberto 199258945Sroberto size = ((uint64_t)info->MaxLBAHigh << 32) | info->MaxLBA; 200258945Sroberto humanize_number(buf, sizeof(buf), (size + 1) * 512, "", HN_AUTOSCALE, 201258945Sroberto HN_B | HN_NOSPACE | HN_DECIMAL); 202258945Sroberto if (info->VolumeType == MPI_RAID_VOL_TYPE_IM) 203258945Sroberto stripe[0] = '\0'; 204258945Sroberto else 205258945Sroberto format_stripe(stripe, sizeof(stripe), info->StripeSize); 206258945Sroberto level = mpt_raid_level(info->VolumeType); 207258945Sroberto state = mpt_volstate(info->VolumeStatus.State); 208258945Sroberto if (state_len > 0) 209258945Sroberto printf("(%6s) %-8s %6s %-*s", buf, level, stripe, state_len, 210258945Sroberto state); 211258945Sroberto else if (stripe[0] != '\0') 212258945Sroberto printf("(%s) %s %s %s", buf, level, stripe, state); 213258945Sroberto else 214258945Sroberto printf("(%s) %s %s", buf, level, state); 215258945Sroberto} 216258945Sroberto 217258945Srobertostatic void 218280849Scyprint_pd(CONFIG_PAGE_RAID_PHYS_DISK_0 *info, int state_len, int location) 219280849Scy{ 220280849Scy const char *inq, *state; 221258945Sroberto char buf[6]; 222258945Sroberto 223258945Sroberto humanize_number(buf, sizeof(buf), ((uint64_t)info->MaxLBA + 1) * 512, 224258945Sroberto "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 225258945Sroberto state = mpt_pdstate(info); 226258945Sroberto if (state_len > 0) 227258945Sroberto printf("(%6s) %-*s", buf, state_len, state); 228258945Sroberto else 229258945Sroberto printf("(%s) %s", buf, state); 230258945Sroberto inq = mpt_pd_inq_string(info); 231258945Sroberto if (inq != NULL) 232258945Sroberto printf(" %s", inq); 233258945Sroberto if (!location) 234280849Scy return; 235258945Sroberto printf(" bus %d id %d", info->PhysDiskBus, info->PhysDiskID); 236280849Scy} 237280849Scy 238280849Scystatic void 239258945Srobertoprint_standalone(struct mpt_standalone_disk *disk, int state_len, int location) 240258945Sroberto{ 241258945Sroberto char buf[6]; 242258945Sroberto 243258945Sroberto humanize_number(buf, sizeof(buf), (disk->maxlba + 1) * 512, 244258945Sroberto "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); 245280849Scy if (state_len > 0) 246280849Scy printf("(%6s) %-*s", buf, state_len, STANDALONE_STATE); 247280849Scy else 248258945Sroberto printf("(%s) %s", buf, STANDALONE_STATE); 249258945Sroberto if (disk->inqstring[0] != '\0') 250280849Scy printf(" %s", disk->inqstring); 251258945Sroberto if (!location) 252258945Sroberto return; 253258945Sroberto printf(" bus %d id %d", disk->bus, disk->target); 254258945Sroberto} 255258945Sroberto 256258945Srobertostatic void 257258945Srobertoprint_spare_pools(U8 HotSparePool) 258258945Sroberto{ 259258945Sroberto int i; 260258945Sroberto 261258945Sroberto if (HotSparePool == 0) { 262258945Sroberto printf("none"); 263258945Sroberto return; 264258945Sroberto } 265258945Sroberto for (i = 0; HotSparePool != 0; i++) { 266258945Sroberto if (HotSparePool & 1) { 267258945Sroberto printf("%d", i); 268258945Sroberto if (HotSparePool == 1) 269258945Sroberto break; 270258945Sroberto printf(", "); 271258945Sroberto } 272258945Sroberto HotSparePool >>= 1; 273258945Sroberto } 274258945Sroberto} 275258945Sroberto 276258945Srobertostatic int 277258945Srobertoshow_config(int ac, char **av) 278258945Sroberto{ 279258945Sroberto CONFIG_PAGE_IOC_2 *ioc2; 280258945Sroberto CONFIG_PAGE_IOC_2_RAID_VOL *vol; 281258945Sroberto CONFIG_PAGE_IOC_5 *ioc5; 282258945Sroberto IOC_5_HOT_SPARE *spare; 283258945Sroberto CONFIG_PAGE_RAID_VOL_0 *vinfo; 284258945Sroberto RAID_VOL0_PHYS_DISK *disk; 285258945Sroberto CONFIG_PAGE_RAID_VOL_1 *vnames; 286258945Sroberto CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 287258945Sroberto struct mpt_standalone_disk *sdisks; 288258945Sroberto int error, fd, i, j, nsdisks; 289258945Sroberto 290258945Sroberto if (ac != 1) { 291258945Sroberto warnx("show config: extra arguments"); 292258945Sroberto return (EINVAL); 293258945Sroberto } 294258945Sroberto 295258945Sroberto fd = mpt_open(mpt_unit); 296258945Sroberto if (fd < 0) { 297258945Sroberto error = errno; 298258945Sroberto warn("mpt_open"); 299258945Sroberto return (error); 300258945Sroberto } 301258945Sroberto 302258945Sroberto /* Get the config from the controller. */ 303258945Sroberto ioc2 = mpt_read_ioc_page(fd, 2, NULL); 304258945Sroberto ioc5 = mpt_read_ioc_page(fd, 5, NULL); 305258945Sroberto if (ioc2 == NULL || ioc5 == NULL) { 306258945Sroberto error = errno; 307258945Sroberto warn("Failed to get config"); 308258945Sroberto return (error); 309258945Sroberto } 310258945Sroberto if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) { 311258945Sroberto error = errno; 312258945Sroberto warn("Failed to get standalone drive list"); 313258945Sroberto return (error); 314258945Sroberto } 315258945Sroberto 316258945Sroberto /* Dump out the configuration. */ 317258945Sroberto printf("mpt%d Configuration: %d volumes, %d drives\n", 318258945Sroberto mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks + 319258945Sroberto nsdisks); 320280849Scy vol = ioc2->RaidVolume; 321280849Scy for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 322280849Scy printf(" volume %s ", mpt_volume_name(vol->VolumeBus, 323280849Scy vol->VolumeID)); 324280849Scy vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL); 325280849Scy if (vinfo == NULL) { 326258945Sroberto printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType)); 327280849Scy } else 328280849Scy print_vol(vinfo, -1); 329280849Scy vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 330280849Scy if (vnames != NULL) { 331280849Scy if (vnames->Name[0] != '\0') 332280849Scy printf(" <%s>", vnames->Name); 333258945Sroberto free(vnames); 334258945Sroberto } 335258945Sroberto if (vinfo == NULL) { 336258945Sroberto printf("\n"); 337258945Sroberto continue; 338258945Sroberto } 339258945Sroberto printf(" spans:\n"); 340258945Sroberto disk = vinfo->PhysDisk; 341258945Sroberto for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) { 342258945Sroberto printf(" drive %u ", disk->PhysDiskNum); 343258945Sroberto pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL); 344258945Sroberto if (pinfo != NULL) { 345258945Sroberto print_pd(pinfo, -1, 0); 346258945Sroberto free(pinfo); 347258945Sroberto } 348280849Scy printf("\n"); 349280849Scy } 350280849Scy if (vinfo->VolumeSettings.HotSparePool != 0) { 351280849Scy printf(" spare pools: "); 352280849Scy print_spare_pools(vinfo->VolumeSettings.HotSparePool); 353258945Sroberto printf("\n"); 354258945Sroberto } 355258945Sroberto free(vinfo); 356258945Sroberto } 357258945Sroberto 358258945Sroberto spare = ioc5->HotSpare; 359258945Sroberto for (i = 0; i < ioc5->NumHotSpares; spare++, i++) { 360258945Sroberto printf(" spare %u ", spare->PhysDiskNum); 361258945Sroberto pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL); 362258945Sroberto if (pinfo != NULL) { 363258945Sroberto print_pd(pinfo, -1, 0); 364258945Sroberto free(pinfo); 365258945Sroberto } 366258945Sroberto printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1); 367258945Sroberto } 368258945Sroberto for (i = 0; i < nsdisks; i++) { 369258945Sroberto printf(" drive %s ", sdisks[i].devname); 370258945Sroberto print_standalone(&sdisks[i], -1, 0); 371258945Sroberto printf("\n"); 372258945Sroberto } 373258945Sroberto free(ioc2); 374258945Sroberto free(ioc5); 375258945Sroberto free(sdisks); 376258945Sroberto close(fd); 377258945Sroberto 378258945Sroberto return (0); 379258945Sroberto} 380258945SrobertoMPT_COMMAND(show, config, show_config); 381258945Sroberto 382258945Srobertostatic int 383258945Srobertoshow_volumes(int ac, char **av) 384258945Sroberto{ 385258945Sroberto CONFIG_PAGE_IOC_2 *ioc2; 386258945Sroberto CONFIG_PAGE_IOC_2_RAID_VOL *vol; 387258945Sroberto CONFIG_PAGE_RAID_VOL_0 **volumes; 388258945Sroberto CONFIG_PAGE_RAID_VOL_1 *vnames; 389258945Sroberto int error, fd, i, len, state_len; 390258945Sroberto 391258945Sroberto if (ac != 1) { 392258945Sroberto warnx("show volumes: extra arguments"); 393258945Sroberto return (EINVAL); 394258945Sroberto } 395258945Sroberto 396258945Sroberto fd = mpt_open(mpt_unit); 397258945Sroberto if (fd < 0) { 398258945Sroberto error = errno; 399258945Sroberto warn("mpt_open"); 400258945Sroberto return (error); 401280849Scy } 402280849Scy 403280849Scy /* Get the volume list from the controller. */ 404280849Scy ioc2 = mpt_read_ioc_page(fd, 2, NULL); 405280849Scy if (ioc2 == NULL) { 406280849Scy error = errno; 407280849Scy warn("Failed to get volume list"); 408280849Scy return (error); 409280849Scy } 410280849Scy 411280849Scy /* 412280849Scy * Go ahead and read the info for all the volumes and figure 413280849Scy * out the maximum width of the state field. 414280849Scy */ 415280849Scy volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes); 416280849Scy state_len = strlen("State"); 417280849Scy vol = ioc2->RaidVolume; 418258945Sroberto for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 419258945Sroberto volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, 420258945Sroberto NULL); 421258945Sroberto if (volumes[i] == NULL) 422258945Sroberto len = strlen("UNKNOWN"); 423258945Sroberto else 424258945Sroberto len = strlen(mpt_volstate( 425258945Sroberto volumes[i]->VolumeStatus.State)); 426258945Sroberto if (len > state_len) 427258945Sroberto state_len = len; 428258945Sroberto } 429258945Sroberto printf("mpt%d Volumes:\n", mpt_unit); 430258945Sroberto printf(" Id Size Level Stripe "); 431258945Sroberto len = state_len - strlen("State"); 432258945Sroberto for (i = 0; i < (len + 1) / 2; i++) 433258945Sroberto printf(" "); 434258945Sroberto printf("State"); 435258945Sroberto for (i = 0; i < len / 2; i++) 436258945Sroberto printf(" "); 437258945Sroberto printf(" Write-Cache Name\n"); 438258945Sroberto vol = ioc2->RaidVolume; 439258945Sroberto for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { 440258945Sroberto printf("%6s ", mpt_volume_name(vol->VolumeBus, vol->VolumeID)); 441258945Sroberto if (volumes[i] != NULL) 442258945Sroberto print_vol(volumes[i], state_len); 443258945Sroberto else 444258945Sroberto printf(" %-8s %-*s", 445258945Sroberto mpt_raid_level(vol->VolumeType), state_len, 446258945Sroberto "UNKNOWN"); 447258945Sroberto if (volumes[i] != NULL) { 448258945Sroberto if (volumes[i]->VolumeSettings.Settings & 449258945Sroberto MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE) 450258945Sroberto printf(" Enabled "); 451258945Sroberto else 452258945Sroberto printf(" Disabled "); 453258945Sroberto } else 454258945Sroberto printf(" "); 455258945Sroberto free(volumes[i]); 456258945Sroberto vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL); 457258945Sroberto if (vnames != NULL) { 458258945Sroberto if (vnames->Name[0] != '\0') 459258945Sroberto printf(" <%s>", vnames->Name); 460258945Sroberto free(vnames); 461258945Sroberto } 462258945Sroberto printf("\n"); 463258945Sroberto } 464258945Sroberto free(ioc2); 465258945Sroberto close(fd); 466258945Sroberto 467258945Sroberto return (0); 468258945Sroberto} 469258945SrobertoMPT_COMMAND(show, volumes, show_volumes); 470258945Sroberto 471258945Srobertostatic int 472258945Srobertoshow_drives(int ac, char **av) 473258945Sroberto{ 474258945Sroberto struct mpt_drive_list *list; 475258945Sroberto struct mpt_standalone_disk *sdisks; 476258945Sroberto int error, fd, i, len, nsdisks, state_len; 477258945Sroberto 478258945Sroberto if (ac != 1) { 479258945Sroberto warnx("show drives: extra arguments"); 480258945Sroberto return (EINVAL); 481258945Sroberto } 482258945Sroberto 483258945Sroberto fd = mpt_open(mpt_unit); 484258945Sroberto if (fd < 0) { 485258945Sroberto error = errno; 486258945Sroberto warn("mpt_open"); 487258945Sroberto return (error); 488258945Sroberto } 489258945Sroberto 490258945Sroberto /* Get the drive list. */ 491258945Sroberto list = mpt_pd_list(fd); 492258945Sroberto if (list == NULL) { 493258945Sroberto error = errno; 494258945Sroberto warn("Failed to get drive list"); 495258945Sroberto return (error); 496280849Scy } 497258945Sroberto 498258945Sroberto /* Fetch the list of standalone disks for this controller. */ 499258945Sroberto state_len = 0; 500258945Sroberto if (mpt_fetch_disks(fd, &nsdisks, &sdisks) != 0) { 501258945Sroberto nsdisks = 0; 502258945Sroberto sdisks = NULL; 503258945Sroberto } 504258945Sroberto if (nsdisks != 0) 505258945Sroberto state_len = strlen(STANDALONE_STATE); 506258945Sroberto 507258945Sroberto /* Walk the drive list to determine width of state column. */ 508258945Sroberto for (i = 0; i < list->ndrives; i++) { 509258945Sroberto len = strlen(mpt_pdstate(list->drives[i])); 510258945Sroberto if (len > state_len) 511258945Sroberto state_len = len; 512258945Sroberto } 513258945Sroberto 514258945Sroberto /* List the drives. */ 515258945Sroberto printf("mpt%d Physical Drives:\n", mpt_unit); 516258945Sroberto for (i = 0; i < list->ndrives; i++) { 517258945Sroberto printf("%4u ", list->drives[i]->PhysDiskNum); 518258945Sroberto print_pd(list->drives[i], state_len, 1); 519258945Sroberto printf("\n"); 520258945Sroberto } 521258945Sroberto mpt_free_pd_list(list); 522258945Sroberto for (i = 0; i < nsdisks; i++) { 523258945Sroberto printf("%4s ", sdisks[i].devname); 524258945Sroberto print_standalone(&sdisks[i], state_len, 1); 525258945Sroberto printf("\n"); 526258945Sroberto } 527258945Sroberto free(sdisks); 528258945Sroberto 529258945Sroberto close(fd); 530258945Sroberto 531258945Sroberto return (0); 532258945Sroberto} 533258945SrobertoMPT_COMMAND(show, drives, show_drives); 534258945Sroberto 535258945Sroberto#ifdef DEBUG 536258945Srobertostatic int 537258945Srobertoshow_physdisks(int ac, char **av) 538258945Sroberto{ 539258945Sroberto CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo; 540258945Sroberto U16 IOCStatus; 541258945Sroberto int error, fd, i; 542258945Sroberto 543258945Sroberto if (ac != 1) { 544280849Scy warnx("show drives: extra arguments"); 545280849Scy return (EINVAL); 546280849Scy } 547280849Scy 548280849Scy fd = mpt_open(mpt_unit); 549280849Scy if (fd < 0) { 550280849Scy error = errno; 551280849Scy warn("mpt_open"); 552280849Scy return (error); 553280849Scy } 554280849Scy 555280849Scy /* Try to find each possible phys disk page. */ 556280849Scy for (i = 0; i <= 0xff; i++) { 557280849Scy pinfo = mpt_pd_info(fd, i, &IOCStatus); 558280849Scy if (pinfo == NULL) { 559280849Scy if ((IOCStatus & MPI_IOCSTATUS_MASK) != 560280849Scy MPI_IOCSTATUS_CONFIG_INVALID_PAGE) 561280849Scy warnx("mpt_pd_info(%d): %s", i, 562280849Scy mpt_ioc_status(IOCStatus)); 563280849Scy continue; 564280849Scy } 565280849Scy printf("%3u ", i); 566280849Scy print_pd(pinfo, -1, 1); 567280849Scy printf("\n"); 568280849Scy } 569280849Scy 570280849Scy close(fd); 571280849Scy 572280849Scy return (0); 573280849Scy} 574280849ScyMPT_COMMAND(show, pd, show_physdisks); 575280849Scy#endif 576280849Scy