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