xref: /dflybsd-src/usr.sbin/mptutil/mpt_cmd.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_cmd.c,v 1.2 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 <sys/ioctl.h>
36*86d7f5d3SJohn Marino #include <sys/mpt_ioctl.h>
37*86d7f5d3SJohn Marino #include <sys/sysctl.h>
38*86d7f5d3SJohn Marino #include <sys/uio.h>
39*86d7f5d3SJohn Marino 
40*86d7f5d3SJohn Marino #include <err.h>
41*86d7f5d3SJohn Marino #include <fcntl.h>
42*86d7f5d3SJohn Marino #include <stdio.h>
43*86d7f5d3SJohn Marino #include <stdlib.h>
44*86d7f5d3SJohn Marino #include <string.h>
45*86d7f5d3SJohn Marino #include <unistd.h>
46*86d7f5d3SJohn Marino 
47*86d7f5d3SJohn Marino #include "mptutil.h"
48*86d7f5d3SJohn Marino 
49*86d7f5d3SJohn Marino static const char *mpt_ioc_status_codes[] = {
50*86d7f5d3SJohn Marino 	"Success",				/* 0x0000 */
51*86d7f5d3SJohn Marino 	"Invalid function",
52*86d7f5d3SJohn Marino 	"Busy",
53*86d7f5d3SJohn Marino 	"Invalid scatter-gather list",
54*86d7f5d3SJohn Marino 	"Internal error",
55*86d7f5d3SJohn Marino 	"Reserved",
56*86d7f5d3SJohn Marino 	"Insufficient resources",
57*86d7f5d3SJohn Marino 	"Invalid field",
58*86d7f5d3SJohn Marino 	"Invalid state",			/* 0x0008 */
59*86d7f5d3SJohn Marino 	"Operation state not supported",
60*86d7f5d3SJohn Marino 	NULL,
61*86d7f5d3SJohn Marino 	NULL,
62*86d7f5d3SJohn Marino 	NULL,
63*86d7f5d3SJohn Marino 	NULL,
64*86d7f5d3SJohn Marino 	NULL,
65*86d7f5d3SJohn Marino 	NULL,
66*86d7f5d3SJohn Marino 	NULL,					/* 0x0010 */
67*86d7f5d3SJohn Marino 	NULL,
68*86d7f5d3SJohn Marino 	NULL,
69*86d7f5d3SJohn Marino 	NULL,
70*86d7f5d3SJohn Marino 	NULL,
71*86d7f5d3SJohn Marino 	NULL,
72*86d7f5d3SJohn Marino 	NULL,
73*86d7f5d3SJohn Marino 	NULL,
74*86d7f5d3SJohn Marino 	NULL,					/* 0x0018 */
75*86d7f5d3SJohn Marino 	NULL,
76*86d7f5d3SJohn Marino 	NULL,
77*86d7f5d3SJohn Marino 	NULL,
78*86d7f5d3SJohn Marino 	NULL,
79*86d7f5d3SJohn Marino 	NULL,
80*86d7f5d3SJohn Marino 	NULL,
81*86d7f5d3SJohn Marino 	NULL,
82*86d7f5d3SJohn Marino 	"Invalid configuration action",		/* 0x0020 */
83*86d7f5d3SJohn Marino 	"Invalid configuration type",
84*86d7f5d3SJohn Marino 	"Invalid configuration page",
85*86d7f5d3SJohn Marino 	"Invalid configuration data",
86*86d7f5d3SJohn Marino 	"No configuration defaults",
87*86d7f5d3SJohn Marino 	"Unable to commit configuration change",
88*86d7f5d3SJohn Marino 	NULL,
89*86d7f5d3SJohn Marino 	NULL,
90*86d7f5d3SJohn Marino 	NULL,					/* 0x0028 */
91*86d7f5d3SJohn Marino 	NULL,
92*86d7f5d3SJohn Marino 	NULL,
93*86d7f5d3SJohn Marino 	NULL,
94*86d7f5d3SJohn Marino 	NULL,
95*86d7f5d3SJohn Marino 	NULL,
96*86d7f5d3SJohn Marino 	NULL,
97*86d7f5d3SJohn Marino 	NULL,
98*86d7f5d3SJohn Marino 	NULL,					/* 0x0030 */
99*86d7f5d3SJohn Marino 	NULL,
100*86d7f5d3SJohn Marino 	NULL,
101*86d7f5d3SJohn Marino 	NULL,
102*86d7f5d3SJohn Marino 	NULL,
103*86d7f5d3SJohn Marino 	NULL,
104*86d7f5d3SJohn Marino 	NULL,
105*86d7f5d3SJohn Marino 	NULL,
106*86d7f5d3SJohn Marino 	NULL,					/* 0x0038 */
107*86d7f5d3SJohn Marino 	NULL,
108*86d7f5d3SJohn Marino 	NULL,
109*86d7f5d3SJohn Marino 	NULL,
110*86d7f5d3SJohn Marino 	NULL,
111*86d7f5d3SJohn Marino 	NULL,
112*86d7f5d3SJohn Marino 	NULL,
113*86d7f5d3SJohn Marino 	NULL,
114*86d7f5d3SJohn Marino 	"Recovered SCSI error",			/* 0x0040 */
115*86d7f5d3SJohn Marino 	"Invalid SCSI bus",
116*86d7f5d3SJohn Marino 	"Invalid SCSI target ID",
117*86d7f5d3SJohn Marino 	"SCSI device not there",
118*86d7f5d3SJohn Marino 	"SCSI data overrun",
119*86d7f5d3SJohn Marino 	"SCSI data underrun",
120*86d7f5d3SJohn Marino 	"SCSI I/O error",
121*86d7f5d3SJohn Marino 	"SCSI protocol error",
122*86d7f5d3SJohn Marino 	"SCSI task terminated",			/* 0x0048 */
123*86d7f5d3SJohn Marino 	"SCSI residual mismatch",
124*86d7f5d3SJohn Marino 	"SCSI task management failed",
125*86d7f5d3SJohn Marino 	"SCSI I/O controller terminated",
126*86d7f5d3SJohn Marino 	"SCSI external controller terminated",
127*86d7f5d3SJohn Marino 	"EEDP guard error",
128*86d7f5d3SJohn Marino 	"EEDP reference tag error",
129*86d7f5d3SJohn Marino 	"EEDP application tag error",
130*86d7f5d3SJohn Marino 	NULL,					/* 0x0050 */
131*86d7f5d3SJohn Marino 	NULL,
132*86d7f5d3SJohn Marino 	NULL,
133*86d7f5d3SJohn Marino 	NULL,
134*86d7f5d3SJohn Marino 	NULL,
135*86d7f5d3SJohn Marino 	NULL,
136*86d7f5d3SJohn Marino 	NULL,
137*86d7f5d3SJohn Marino 	NULL,
138*86d7f5d3SJohn Marino 	NULL,					/* 0x0058 */
139*86d7f5d3SJohn Marino 	NULL,
140*86d7f5d3SJohn Marino 	NULL,
141*86d7f5d3SJohn Marino 	NULL,
142*86d7f5d3SJohn Marino 	NULL,
143*86d7f5d3SJohn Marino 	NULL,
144*86d7f5d3SJohn Marino 	NULL,
145*86d7f5d3SJohn Marino 	NULL,
146*86d7f5d3SJohn Marino 	"SCSI target priority I/O",		/* 0x0060 */
147*86d7f5d3SJohn Marino 	"Invalid SCSI target port",
148*86d7f5d3SJohn Marino 	"Invalid SCSI target I/O index",
149*86d7f5d3SJohn Marino 	"SCSI target aborted",
150*86d7f5d3SJohn Marino 	"No connection retryable",
151*86d7f5d3SJohn Marino 	"No connection",
152*86d7f5d3SJohn Marino 	"FC aborted",
153*86d7f5d3SJohn Marino 	"Invalid FC receive ID",
154*86d7f5d3SJohn Marino 	"FC did invalid",			/* 0x0068 */
155*86d7f5d3SJohn Marino 	"FC node logged out",
156*86d7f5d3SJohn Marino 	"Transfer count mismatch",
157*86d7f5d3SJohn Marino 	"STS data not set",
158*86d7f5d3SJohn Marino 	"FC exchange canceled",
159*86d7f5d3SJohn Marino 	"Data offset error",
160*86d7f5d3SJohn Marino 	"Too much write data",
161*86d7f5d3SJohn Marino 	"IU too short",
162*86d7f5d3SJohn Marino 	"ACK NAK timeout",			/* 0x0070 */
163*86d7f5d3SJohn Marino 	"NAK received",
164*86d7f5d3SJohn Marino 	NULL,
165*86d7f5d3SJohn Marino 	NULL,
166*86d7f5d3SJohn Marino 	NULL,
167*86d7f5d3SJohn Marino 	NULL,
168*86d7f5d3SJohn Marino 	NULL,
169*86d7f5d3SJohn Marino 	NULL,
170*86d7f5d3SJohn Marino 	NULL,					/* 0x0078 */
171*86d7f5d3SJohn Marino 	NULL,
172*86d7f5d3SJohn Marino 	NULL,
173*86d7f5d3SJohn Marino 	NULL,
174*86d7f5d3SJohn Marino 	NULL,
175*86d7f5d3SJohn Marino 	NULL,
176*86d7f5d3SJohn Marino 	NULL,
177*86d7f5d3SJohn Marino 	NULL,
178*86d7f5d3SJohn Marino 	"LAN device not found",			/* 0x0080 */
179*86d7f5d3SJohn Marino 	"LAN device failure",
180*86d7f5d3SJohn Marino 	"LAN transmit error",
181*86d7f5d3SJohn Marino 	"LAN transmit aborted",
182*86d7f5d3SJohn Marino 	"LAN receive error",
183*86d7f5d3SJohn Marino 	"LAN receive aborted",
184*86d7f5d3SJohn Marino 	"LAN partial packet",
185*86d7f5d3SJohn Marino 	"LAN canceled",
186*86d7f5d3SJohn Marino 	NULL,					/* 0x0088 */
187*86d7f5d3SJohn Marino 	NULL,
188*86d7f5d3SJohn Marino 	NULL,
189*86d7f5d3SJohn Marino 	NULL,
190*86d7f5d3SJohn Marino 	NULL,
191*86d7f5d3SJohn Marino 	NULL,
192*86d7f5d3SJohn Marino 	NULL,
193*86d7f5d3SJohn Marino 	NULL,
194*86d7f5d3SJohn Marino 	"SAS SMP request failed",		/* 0x0090 */
195*86d7f5d3SJohn Marino 	"SAS SMP data overrun",
196*86d7f5d3SJohn Marino 	NULL,
197*86d7f5d3SJohn Marino 	NULL,
198*86d7f5d3SJohn Marino 	NULL,
199*86d7f5d3SJohn Marino 	NULL,
200*86d7f5d3SJohn Marino 	NULL,
201*86d7f5d3SJohn Marino 	NULL,
202*86d7f5d3SJohn Marino 	"Inband aborted",			/* 0x0098 */
203*86d7f5d3SJohn Marino 	"No inband connection",
204*86d7f5d3SJohn Marino 	NULL,
205*86d7f5d3SJohn Marino 	NULL,
206*86d7f5d3SJohn Marino 	NULL,
207*86d7f5d3SJohn Marino 	NULL,
208*86d7f5d3SJohn Marino 	NULL,
209*86d7f5d3SJohn Marino 	NULL,
210*86d7f5d3SJohn Marino 	"Diagnostic released",			/* 0x00A0 */
211*86d7f5d3SJohn Marino };
212*86d7f5d3SJohn Marino 
213*86d7f5d3SJohn Marino static const char *mpt_raid_action_status_codes[] = {
214*86d7f5d3SJohn Marino 	"Success",
215*86d7f5d3SJohn Marino 	"Invalid action",
216*86d7f5d3SJohn Marino 	"Failure",
217*86d7f5d3SJohn Marino 	"Operation in progress",
218*86d7f5d3SJohn Marino };
219*86d7f5d3SJohn Marino 
220*86d7f5d3SJohn Marino const char *
mpt_ioc_status(U16 IOCStatus)221*86d7f5d3SJohn Marino mpt_ioc_status(U16 IOCStatus)
222*86d7f5d3SJohn Marino {
223*86d7f5d3SJohn Marino 	static char buffer[16];
224*86d7f5d3SJohn Marino 
225*86d7f5d3SJohn Marino 	IOCStatus &= MPI_IOCSTATUS_MASK;
226*86d7f5d3SJohn Marino 	if (IOCStatus < sizeof(mpt_ioc_status_codes) / sizeof(char *) &&
227*86d7f5d3SJohn Marino 	    mpt_ioc_status_codes[IOCStatus] != NULL)
228*86d7f5d3SJohn Marino 		return (mpt_ioc_status_codes[IOCStatus]);
229*86d7f5d3SJohn Marino 	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", IOCStatus);
230*86d7f5d3SJohn Marino 	return (buffer);
231*86d7f5d3SJohn Marino }
232*86d7f5d3SJohn Marino 
233*86d7f5d3SJohn Marino const char *
mpt_raid_status(U16 ActionStatus)234*86d7f5d3SJohn Marino mpt_raid_status(U16 ActionStatus)
235*86d7f5d3SJohn Marino {
236*86d7f5d3SJohn Marino 	static char buffer[16];
237*86d7f5d3SJohn Marino 
238*86d7f5d3SJohn Marino 	if (ActionStatus < sizeof(mpt_raid_action_status_codes) /
239*86d7f5d3SJohn Marino 	    sizeof(char *))
240*86d7f5d3SJohn Marino 		return (mpt_raid_action_status_codes[ActionStatus]);
241*86d7f5d3SJohn Marino 	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", ActionStatus);
242*86d7f5d3SJohn Marino 	return (buffer);
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino 
245*86d7f5d3SJohn Marino const char *
mpt_raid_level(U8 VolumeType)246*86d7f5d3SJohn Marino mpt_raid_level(U8 VolumeType)
247*86d7f5d3SJohn Marino {
248*86d7f5d3SJohn Marino 	static char buf[16];
249*86d7f5d3SJohn Marino 
250*86d7f5d3SJohn Marino 	switch (VolumeType) {
251*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_IS:
252*86d7f5d3SJohn Marino 		return ("RAID-0");
253*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_IM:
254*86d7f5d3SJohn Marino 		return ("RAID-1");
255*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_IME:
256*86d7f5d3SJohn Marino 		return ("RAID-1E");
257*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_RAID_5:
258*86d7f5d3SJohn Marino 		return ("RAID-5");
259*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_RAID_6:
260*86d7f5d3SJohn Marino 		return ("RAID-6");
261*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_RAID_10:
262*86d7f5d3SJohn Marino 		return ("RAID-10");
263*86d7f5d3SJohn Marino 	case MPI_RAID_VOL_TYPE_RAID_50:
264*86d7f5d3SJohn Marino 		return ("RAID-50");
265*86d7f5d3SJohn Marino 	default:
266*86d7f5d3SJohn Marino 		sprintf(buf, "LVL 0x%02x", VolumeType);
267*86d7f5d3SJohn Marino 		return (buf);
268*86d7f5d3SJohn Marino 	}
269*86d7f5d3SJohn Marino }
270*86d7f5d3SJohn Marino 
271*86d7f5d3SJohn Marino const char *
mpt_volume_name(U8 VolumeBus,U8 VolumeID)272*86d7f5d3SJohn Marino mpt_volume_name(U8 VolumeBus, U8 VolumeID)
273*86d7f5d3SJohn Marino {
274*86d7f5d3SJohn Marino 	static struct mpt_query_disk info;
275*86d7f5d3SJohn Marino 	static char buf[16];
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino 	if (mpt_query_disk(VolumeBus, VolumeID, &info) != 0) {
278*86d7f5d3SJohn Marino 		/*
279*86d7f5d3SJohn Marino 		 * We only print out the bus number if it is non-zero
280*86d7f5d3SJohn Marino 		 * since mpt(4) only supports devices on bus zero
281*86d7f5d3SJohn Marino 		 * anyway.
282*86d7f5d3SJohn Marino 		 */
283*86d7f5d3SJohn Marino 		if (VolumeBus == 0)
284*86d7f5d3SJohn Marino 			snprintf(buf, sizeof(buf), "%d", VolumeID);
285*86d7f5d3SJohn Marino 		else
286*86d7f5d3SJohn Marino 			snprintf(buf, sizeof(buf), "%d:%d", VolumeBus,
287*86d7f5d3SJohn Marino 			    VolumeID);
288*86d7f5d3SJohn Marino 		return (buf);
289*86d7f5d3SJohn Marino 	}
290*86d7f5d3SJohn Marino 	return (info.devname);
291*86d7f5d3SJohn Marino }
292*86d7f5d3SJohn Marino 
293*86d7f5d3SJohn Marino int
mpt_lookup_volume(int fd,const char * name,U8 * VolumeBus,U8 * VolumeID)294*86d7f5d3SJohn Marino mpt_lookup_volume(int fd, const char *name, U8 *VolumeBus, U8 *VolumeID)
295*86d7f5d3SJohn Marino {
296*86d7f5d3SJohn Marino 	CONFIG_PAGE_IOC_2 *ioc2;
297*86d7f5d3SJohn Marino 	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
298*86d7f5d3SJohn Marino 	struct mpt_query_disk info;
299*86d7f5d3SJohn Marino 	char *cp;
300*86d7f5d3SJohn Marino 	long bus, id;
301*86d7f5d3SJohn Marino 	int i;
302*86d7f5d3SJohn Marino 
303*86d7f5d3SJohn Marino 	/*
304*86d7f5d3SJohn Marino 	 * Check for a raw [<bus>:]<id> string.  If the bus is not
305*86d7f5d3SJohn Marino 	 * specified, assume bus 0.
306*86d7f5d3SJohn Marino 	 */
307*86d7f5d3SJohn Marino 	bus = strtol(name, &cp, 0);
308*86d7f5d3SJohn Marino 	if (*cp == ':') {
309*86d7f5d3SJohn Marino 		id = strtol(cp + 1, &cp, 0);
310*86d7f5d3SJohn Marino 		if (*cp == '\0') {
311*86d7f5d3SJohn Marino 			if (bus < 0 || bus > 0xff || id < 0 || id > 0xff) {
312*86d7f5d3SJohn Marino 				return (EINVAL);
313*86d7f5d3SJohn Marino 			}
314*86d7f5d3SJohn Marino 			*VolumeBus = bus;
315*86d7f5d3SJohn Marino 			*VolumeID = id;
316*86d7f5d3SJohn Marino 			return (0);
317*86d7f5d3SJohn Marino 		}
318*86d7f5d3SJohn Marino 	} else if (*cp == '\0') {
319*86d7f5d3SJohn Marino 		if (bus < 0 || bus > 0xff)
320*86d7f5d3SJohn Marino 			return (EINVAL);
321*86d7f5d3SJohn Marino 		*VolumeBus = 0;
322*86d7f5d3SJohn Marino 		*VolumeID = bus;
323*86d7f5d3SJohn Marino 		return (0);
324*86d7f5d3SJohn Marino 	}
325*86d7f5d3SJohn Marino 
326*86d7f5d3SJohn Marino 	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
327*86d7f5d3SJohn Marino 	if (ioc2 == NULL)
328*86d7f5d3SJohn Marino 		return (errno);
329*86d7f5d3SJohn Marino 
330*86d7f5d3SJohn Marino 	vol = ioc2->RaidVolume;
331*86d7f5d3SJohn Marino 	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
332*86d7f5d3SJohn Marino 		if (mpt_query_disk(vol->VolumeBus, vol->VolumeID, &info) != 0)
333*86d7f5d3SJohn Marino 			continue;
334*86d7f5d3SJohn Marino 		if (strcmp(name, info.devname) == 0) {
335*86d7f5d3SJohn Marino 			*VolumeBus = vol->VolumeBus;
336*86d7f5d3SJohn Marino 			*VolumeID = vol->VolumeID;
337*86d7f5d3SJohn Marino 			free(ioc2);
338*86d7f5d3SJohn Marino 			return (0);
339*86d7f5d3SJohn Marino 		}
340*86d7f5d3SJohn Marino 	}
341*86d7f5d3SJohn Marino 	free(ioc2);
342*86d7f5d3SJohn Marino 	return (EINVAL);
343*86d7f5d3SJohn Marino }
344*86d7f5d3SJohn Marino 
345*86d7f5d3SJohn Marino int
mpt_read_config_page_header(int fd,U8 PageType,U8 PageNumber,U32 PageAddress,CONFIG_PAGE_HEADER * header,U16 * IOCStatus)346*86d7f5d3SJohn Marino mpt_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
347*86d7f5d3SJohn Marino     CONFIG_PAGE_HEADER *header, U16 *IOCStatus)
348*86d7f5d3SJohn Marino {
349*86d7f5d3SJohn Marino 	struct mpt_cfg_page_req req;
350*86d7f5d3SJohn Marino 
351*86d7f5d3SJohn Marino 	if (IOCStatus != NULL)
352*86d7f5d3SJohn Marino 		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
353*86d7f5d3SJohn Marino 	bzero(&req, sizeof(req));
354*86d7f5d3SJohn Marino 	req.header.PageType = PageType;
355*86d7f5d3SJohn Marino 	req.header.PageNumber = PageNumber;
356*86d7f5d3SJohn Marino 	req.page_address = PageAddress;
357*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
358*86d7f5d3SJohn Marino 		return (errno);
359*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
360*86d7f5d3SJohn Marino 		if (IOCStatus != NULL)
361*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
362*86d7f5d3SJohn Marino 		else
363*86d7f5d3SJohn Marino 			warnx("Reading config page header failed: %s",
364*86d7f5d3SJohn Marino 			    mpt_ioc_status(req.ioc_status));
365*86d7f5d3SJohn Marino 		return (EIO);
366*86d7f5d3SJohn Marino 	}
367*86d7f5d3SJohn Marino 	*header = req.header;
368*86d7f5d3SJohn Marino 	return (0);
369*86d7f5d3SJohn Marino }
370*86d7f5d3SJohn Marino 
371*86d7f5d3SJohn Marino void *
mpt_read_config_page(int fd,U8 PageType,U8 PageNumber,U32 PageAddress,U16 * IOCStatus)372*86d7f5d3SJohn Marino mpt_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
373*86d7f5d3SJohn Marino     U16 *IOCStatus)
374*86d7f5d3SJohn Marino {
375*86d7f5d3SJohn Marino 	struct mpt_cfg_page_req req;
376*86d7f5d3SJohn Marino 	void *buf;
377*86d7f5d3SJohn Marino 	int error;
378*86d7f5d3SJohn Marino 
379*86d7f5d3SJohn Marino 	if (IOCStatus != NULL)
380*86d7f5d3SJohn Marino 		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
381*86d7f5d3SJohn Marino 	bzero(&req, sizeof(req));
382*86d7f5d3SJohn Marino 	req.header.PageType = PageType;
383*86d7f5d3SJohn Marino 	req.header.PageNumber = PageNumber;
384*86d7f5d3SJohn Marino 	req.page_address = PageAddress;
385*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
386*86d7f5d3SJohn Marino 		return (NULL);
387*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
388*86d7f5d3SJohn Marino 		if (IOCStatus != NULL)
389*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
390*86d7f5d3SJohn Marino 		else
391*86d7f5d3SJohn Marino 			warnx("Reading config page header failed: %s",
392*86d7f5d3SJohn Marino 			    mpt_ioc_status(req.ioc_status));
393*86d7f5d3SJohn Marino 		errno = EIO;
394*86d7f5d3SJohn Marino 		return (NULL);
395*86d7f5d3SJohn Marino 	}
396*86d7f5d3SJohn Marino 	req.len = req.header.PageLength * 4;
397*86d7f5d3SJohn Marino 	buf = malloc(req.len);
398*86d7f5d3SJohn Marino 	req.buf = buf;
399*86d7f5d3SJohn Marino 	bcopy(&req.header, buf, sizeof(req.header));
400*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_READ_CFG_PAGE, &req) < 0) {
401*86d7f5d3SJohn Marino 		error = errno;
402*86d7f5d3SJohn Marino 		free(buf);
403*86d7f5d3SJohn Marino 		errno = error;
404*86d7f5d3SJohn Marino 		return (NULL);
405*86d7f5d3SJohn Marino 	}
406*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
407*86d7f5d3SJohn Marino 		if (IOCStatus != NULL)
408*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
409*86d7f5d3SJohn Marino 		else
410*86d7f5d3SJohn Marino 			warnx("Reading config page failed: %s",
411*86d7f5d3SJohn Marino 			    mpt_ioc_status(req.ioc_status));
412*86d7f5d3SJohn Marino 		free(buf);
413*86d7f5d3SJohn Marino 		errno = EIO;
414*86d7f5d3SJohn Marino 		return (NULL);
415*86d7f5d3SJohn Marino 	}
416*86d7f5d3SJohn Marino 	return (buf);
417*86d7f5d3SJohn Marino }
418*86d7f5d3SJohn Marino 
419*86d7f5d3SJohn Marino void *
mpt_read_extended_config_page(int fd,U8 ExtPageType,U8 PageVersion,U8 PageNumber,U32 PageAddress,U16 * IOCStatus)420*86d7f5d3SJohn Marino mpt_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
421*86d7f5d3SJohn Marino     U8 PageNumber, U32 PageAddress, U16 *IOCStatus)
422*86d7f5d3SJohn Marino {
423*86d7f5d3SJohn Marino 	struct mpt_ext_cfg_page_req req;
424*86d7f5d3SJohn Marino 	void *buf;
425*86d7f5d3SJohn Marino 	int error;
426*86d7f5d3SJohn Marino 
427*86d7f5d3SJohn Marino 	if (IOCStatus != NULL)
428*86d7f5d3SJohn Marino 		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
429*86d7f5d3SJohn Marino 	bzero(&req, sizeof(req));
430*86d7f5d3SJohn Marino 	req.header.PageVersion = PageVersion;
431*86d7f5d3SJohn Marino 	req.header.PageNumber = PageNumber;
432*86d7f5d3SJohn Marino 	req.header.ExtPageType = ExtPageType;
433*86d7f5d3SJohn Marino 	req.page_address = PageAddress;
434*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_READ_EXT_CFG_HEADER, &req) < 0)
435*86d7f5d3SJohn Marino 		return (NULL);
436*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
437*86d7f5d3SJohn Marino 		if (IOCStatus != NULL)
438*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
439*86d7f5d3SJohn Marino 		else
440*86d7f5d3SJohn Marino 			warnx("Reading extended config page header failed: %s",
441*86d7f5d3SJohn Marino 			    mpt_ioc_status(req.ioc_status));
442*86d7f5d3SJohn Marino 		errno = EIO;
443*86d7f5d3SJohn Marino 		return (NULL);
444*86d7f5d3SJohn Marino 	}
445*86d7f5d3SJohn Marino 	req.len = req.header.ExtPageLength * 4;
446*86d7f5d3SJohn Marino 	buf = malloc(req.len);
447*86d7f5d3SJohn Marino 	req.buf = buf;
448*86d7f5d3SJohn Marino 	bcopy(&req.header, buf, sizeof(req.header));
449*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_READ_EXT_CFG_PAGE, &req) < 0) {
450*86d7f5d3SJohn Marino 		error = errno;
451*86d7f5d3SJohn Marino 		free(buf);
452*86d7f5d3SJohn Marino 		errno = error;
453*86d7f5d3SJohn Marino 		return (NULL);
454*86d7f5d3SJohn Marino 	}
455*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
456*86d7f5d3SJohn Marino 		if (IOCStatus != NULL)
457*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
458*86d7f5d3SJohn Marino 		else
459*86d7f5d3SJohn Marino 			warnx("Reading extended config page failed: %s",
460*86d7f5d3SJohn Marino 			    mpt_ioc_status(req.ioc_status));
461*86d7f5d3SJohn Marino 		free(buf);
462*86d7f5d3SJohn Marino 		errno = EIO;
463*86d7f5d3SJohn Marino 		return (NULL);
464*86d7f5d3SJohn Marino 	}
465*86d7f5d3SJohn Marino 	return (buf);
466*86d7f5d3SJohn Marino }
467*86d7f5d3SJohn Marino 
468*86d7f5d3SJohn Marino int
mpt_write_config_page(int fd,void * buf,U16 * IOCStatus)469*86d7f5d3SJohn Marino mpt_write_config_page(int fd, void *buf, U16 *IOCStatus)
470*86d7f5d3SJohn Marino {
471*86d7f5d3SJohn Marino 	CONFIG_PAGE_HEADER *hdr;
472*86d7f5d3SJohn Marino 	struct mpt_cfg_page_req req;
473*86d7f5d3SJohn Marino 
474*86d7f5d3SJohn Marino 	if (IOCStatus != NULL)
475*86d7f5d3SJohn Marino 		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
476*86d7f5d3SJohn Marino 	bzero(&req, sizeof(req));
477*86d7f5d3SJohn Marino 	req.buf = buf;
478*86d7f5d3SJohn Marino 	hdr = buf;
479*86d7f5d3SJohn Marino 	req.len = hdr->PageLength * 4;
480*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_WRITE_CFG_PAGE, &req) < 0)
481*86d7f5d3SJohn Marino 		return (errno);
482*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
483*86d7f5d3SJohn Marino 		if (IOCStatus != NULL) {
484*86d7f5d3SJohn Marino 			*IOCStatus = req.ioc_status;
485*86d7f5d3SJohn Marino 			return (0);
486*86d7f5d3SJohn Marino 		}
487*86d7f5d3SJohn Marino 		warnx("Writing config page failed: %s",
488*86d7f5d3SJohn Marino 		    mpt_ioc_status(req.ioc_status));
489*86d7f5d3SJohn Marino 		return (EIO);
490*86d7f5d3SJohn Marino 	}
491*86d7f5d3SJohn Marino 	return (0);
492*86d7f5d3SJohn Marino }
493*86d7f5d3SJohn Marino 
494*86d7f5d3SJohn Marino int
mpt_raid_action(int fd,U8 Action,U8 VolumeBus,U8 VolumeID,U8 PhysDiskNum,U32 ActionDataWord,void * buf,int len,RAID_VOL0_STATUS * VolumeStatus,U32 * ActionData,int datalen,U16 * IOCStatus,U16 * ActionStatus,int write_act)495*86d7f5d3SJohn Marino mpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID, U8 PhysDiskNum,
496*86d7f5d3SJohn Marino     U32 ActionDataWord, void *buf, int len, RAID_VOL0_STATUS *VolumeStatus,
497*86d7f5d3SJohn Marino     U32 *ActionData, int datalen, U16 *IOCStatus, U16 *ActionStatus, int write_act)
498*86d7f5d3SJohn Marino {
499*86d7f5d3SJohn Marino 	struct mpt_raid_action raid_act;
500*86d7f5d3SJohn Marino 
501*86d7f5d3SJohn Marino 	if (IOCStatus != NULL)
502*86d7f5d3SJohn Marino 		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
503*86d7f5d3SJohn Marino 	if (datalen < 0 || (unsigned)datalen > sizeof(raid_act.action_data))
504*86d7f5d3SJohn Marino 		return (EINVAL);
505*86d7f5d3SJohn Marino 	bzero(&raid_act, sizeof(raid_act));
506*86d7f5d3SJohn Marino 	raid_act.action = Action;
507*86d7f5d3SJohn Marino 	raid_act.volume_bus = VolumeBus;
508*86d7f5d3SJohn Marino 	raid_act.volume_id = VolumeID;
509*86d7f5d3SJohn Marino 	raid_act.phys_disk_num = PhysDiskNum;
510*86d7f5d3SJohn Marino 	raid_act.action_data_word = ActionDataWord;
511*86d7f5d3SJohn Marino 	if (buf != NULL && len != 0) {
512*86d7f5d3SJohn Marino 		raid_act.buf = buf;
513*86d7f5d3SJohn Marino 		raid_act.len = len;
514*86d7f5d3SJohn Marino 		raid_act.write = write_act;
515*86d7f5d3SJohn Marino 	}
516*86d7f5d3SJohn Marino 
517*86d7f5d3SJohn Marino 	if (ioctl(fd, MPTIO_RAID_ACTION, &raid_act) < 0)
518*86d7f5d3SJohn Marino 		return (errno);
519*86d7f5d3SJohn Marino 
520*86d7f5d3SJohn Marino 	if (!IOC_STATUS_SUCCESS(raid_act.ioc_status)) {
521*86d7f5d3SJohn Marino 		if (IOCStatus != NULL) {
522*86d7f5d3SJohn Marino 			*IOCStatus = raid_act.ioc_status;
523*86d7f5d3SJohn Marino 			return (0);
524*86d7f5d3SJohn Marino 		}
525*86d7f5d3SJohn Marino 		warnx("RAID action failed: %s",
526*86d7f5d3SJohn Marino 		    mpt_ioc_status(raid_act.ioc_status));
527*86d7f5d3SJohn Marino 		return (EIO);
528*86d7f5d3SJohn Marino 	}
529*86d7f5d3SJohn Marino 
530*86d7f5d3SJohn Marino 	if (ActionStatus != NULL)
531*86d7f5d3SJohn Marino 		*ActionStatus = raid_act.action_status;
532*86d7f5d3SJohn Marino 	if (raid_act.action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS) {
533*86d7f5d3SJohn Marino 		if (ActionStatus != NULL)
534*86d7f5d3SJohn Marino 			return (0);
535*86d7f5d3SJohn Marino 		warnx("RAID action failed: %s",
536*86d7f5d3SJohn Marino 		    mpt_raid_status(raid_act.action_status));
537*86d7f5d3SJohn Marino 		return (EIO);
538*86d7f5d3SJohn Marino 	}
539*86d7f5d3SJohn Marino 
540*86d7f5d3SJohn Marino 	if (VolumeStatus != NULL)
541*86d7f5d3SJohn Marino 		*((U32 *)VolumeStatus) = raid_act.volume_status;
542*86d7f5d3SJohn Marino 	if (ActionData != NULL)
543*86d7f5d3SJohn Marino 		bcopy(raid_act.action_data, ActionData, datalen);
544*86d7f5d3SJohn Marino 	return (0);
545*86d7f5d3SJohn Marino }
546*86d7f5d3SJohn Marino 
547*86d7f5d3SJohn Marino int
mpt_open(int unit)548*86d7f5d3SJohn Marino mpt_open(int unit)
549*86d7f5d3SJohn Marino {
550*86d7f5d3SJohn Marino 	char path[MAXPATHLEN];
551*86d7f5d3SJohn Marino 
552*86d7f5d3SJohn Marino 	snprintf(path, sizeof(path), "/dev/mpt%d", unit);
553*86d7f5d3SJohn Marino 	return (open(path, O_RDWR));
554*86d7f5d3SJohn Marino }
555*86d7f5d3SJohn Marino 
556*86d7f5d3SJohn Marino int
mpt_table_handler(struct mptutil_command ** start,struct mptutil_command ** end,int ac,char ** av)557*86d7f5d3SJohn Marino mpt_table_handler(struct mptutil_command **start, struct mptutil_command **end,
558*86d7f5d3SJohn Marino     int ac, char **av)
559*86d7f5d3SJohn Marino {
560*86d7f5d3SJohn Marino 	struct mptutil_command **cmd;
561*86d7f5d3SJohn Marino 
562*86d7f5d3SJohn Marino 	if (ac < 2) {
563*86d7f5d3SJohn Marino 		warnx("The %s command requires a sub-command.", av[0]);
564*86d7f5d3SJohn Marino 		return (EINVAL);
565*86d7f5d3SJohn Marino 	}
566*86d7f5d3SJohn Marino 	for (cmd = start; cmd < end; cmd++) {
567*86d7f5d3SJohn Marino 		if (strcmp((*cmd)->name, av[1]) == 0)
568*86d7f5d3SJohn Marino 			return ((*cmd)->handler(ac - 1, av + 1));
569*86d7f5d3SJohn Marino 	}
570*86d7f5d3SJohn Marino 
571*86d7f5d3SJohn Marino 	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
572*86d7f5d3SJohn Marino 	return (ENOENT);
573*86d7f5d3SJohn Marino }
574*86d7f5d3SJohn Marino 
575*86d7f5d3SJohn Marino #ifdef DEBUG
576*86d7f5d3SJohn Marino void
hexdump(const void * ptr,int length,const char * hdr,int flags)577*86d7f5d3SJohn Marino hexdump(const void *ptr, int length, const char *hdr, int flags)
578*86d7f5d3SJohn Marino {
579*86d7f5d3SJohn Marino 	int i, j, k;
580*86d7f5d3SJohn Marino 	int cols;
581*86d7f5d3SJohn Marino 	const unsigned char *cp;
582*86d7f5d3SJohn Marino 	char delim;
583*86d7f5d3SJohn Marino 
584*86d7f5d3SJohn Marino 	if ((flags & HD_DELIM_MASK) != 0)
585*86d7f5d3SJohn Marino 		delim = (flags & HD_DELIM_MASK) >> 8;
586*86d7f5d3SJohn Marino 	else
587*86d7f5d3SJohn Marino 		delim = ' ';
588*86d7f5d3SJohn Marino 
589*86d7f5d3SJohn Marino 	if ((flags & HD_COLUMN_MASK) != 0)
590*86d7f5d3SJohn Marino 		cols = flags & HD_COLUMN_MASK;
591*86d7f5d3SJohn Marino 	else
592*86d7f5d3SJohn Marino 		cols = 16;
593*86d7f5d3SJohn Marino 
594*86d7f5d3SJohn Marino 	cp = ptr;
595*86d7f5d3SJohn Marino 	for (i = 0; i < length; i+= cols) {
596*86d7f5d3SJohn Marino 		if (hdr != NULL)
597*86d7f5d3SJohn Marino 			printf("%s", hdr);
598*86d7f5d3SJohn Marino 
599*86d7f5d3SJohn Marino 		if ((flags & HD_OMIT_COUNT) == 0)
600*86d7f5d3SJohn Marino 			printf("%04x  ", i);
601*86d7f5d3SJohn Marino 
602*86d7f5d3SJohn Marino 		if ((flags & HD_OMIT_HEX) == 0) {
603*86d7f5d3SJohn Marino 			for (j = 0; j < cols; j++) {
604*86d7f5d3SJohn Marino 				k = i + j;
605*86d7f5d3SJohn Marino 				if (k < length)
606*86d7f5d3SJohn Marino 					printf("%c%02x", delim, cp[k]);
607*86d7f5d3SJohn Marino 				else
608*86d7f5d3SJohn Marino 					printf("   ");
609*86d7f5d3SJohn Marino 			}
610*86d7f5d3SJohn Marino 		}
611*86d7f5d3SJohn Marino 
612*86d7f5d3SJohn Marino 		if ((flags & HD_OMIT_CHARS) == 0) {
613*86d7f5d3SJohn Marino 			printf("  |");
614*86d7f5d3SJohn Marino 			for (j = 0; j < cols; j++) {
615*86d7f5d3SJohn Marino 				k = i + j;
616*86d7f5d3SJohn Marino 				if (k >= length)
617*86d7f5d3SJohn Marino 					printf(" ");
618*86d7f5d3SJohn Marino 				else if (cp[k] >= ' ' && cp[k] <= '~')
619*86d7f5d3SJohn Marino 					printf("%c", cp[k]);
620*86d7f5d3SJohn Marino 				else
621*86d7f5d3SJohn Marino 					printf(".");
622*86d7f5d3SJohn Marino 			}
623*86d7f5d3SJohn Marino 			printf("|");
624*86d7f5d3SJohn Marino 		}
625*86d7f5d3SJohn Marino 		printf("\n");
626*86d7f5d3SJohn Marino 	}
627*86d7f5d3SJohn Marino }
628*86d7f5d3SJohn Marino #endif
629