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