1196212Sscottl/*-
2196212Sscottl * Copyright (c) 2008 Yahoo!, Inc.
3196212Sscottl * All rights reserved.
4196212Sscottl * Written by: John Baldwin <jhb@FreeBSD.org>
5196212Sscottl *
6196212Sscottl * Redistribution and use in source and binary forms, with or without
7196212Sscottl * modification, are permitted provided that the following conditions
8196212Sscottl * are met:
9196212Sscottl * 1. Redistributions of source code must retain the above copyright
10196212Sscottl *    notice, this list of conditions and the following disclaimer.
11196212Sscottl * 2. Redistributions in binary form must reproduce the above copyright
12196212Sscottl *    notice, this list of conditions and the following disclaimer in the
13196212Sscottl *    documentation and/or other materials provided with the distribution.
14196212Sscottl * 3. Neither the name of the author nor the names of any co-contributors
15196212Sscottl *    may be used to endorse or promote products derived from this software
16196212Sscottl *    without specific prior written permission.
17196212Sscottl *
18196212Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19196212Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20196212Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21196212Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22196212Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23196212Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24196212Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25196212Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26196212Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27196212Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28196212Sscottl * SUCH DAMAGE.
29196212Sscottl */
30196212Sscottl
31196212Sscottl#include <sys/cdefs.h>
32196212Sscottl__RCSID("$FreeBSD$");
33196212Sscottl
34196212Sscottl#include <sys/param.h>
35196212Sscottl#include <sys/errno.h>
36196212Sscottl#include <sys/ioctl.h>
37196212Sscottl#include <sys/mpt_ioctl.h>
38196212Sscottl#include <sys/sysctl.h>
39196212Sscottl#include <sys/uio.h>
40196212Sscottl
41196212Sscottl#include <err.h>
42196212Sscottl#include <fcntl.h>
43196212Sscottl#include <stdio.h>
44196212Sscottl#include <stdlib.h>
45196212Sscottl#include <string.h>
46196212Sscottl#include <unistd.h>
47196212Sscottl
48196212Sscottl#include "mptutil.h"
49196212Sscottl
50196212Sscottlstatic const char *mpt_ioc_status_codes[] = {
51196212Sscottl	"Success",				/* 0x0000 */
52196212Sscottl	"Invalid function",
53196212Sscottl	"Busy",
54196212Sscottl	"Invalid scatter-gather list",
55196212Sscottl	"Internal error",
56196212Sscottl	"Reserved",
57196212Sscottl	"Insufficient resources",
58196212Sscottl	"Invalid field",
59196212Sscottl	"Invalid state",			/* 0x0008 */
60196212Sscottl	"Operation state not supported",
61196212Sscottl	NULL,
62196212Sscottl	NULL,
63196212Sscottl	NULL,
64196212Sscottl	NULL,
65196212Sscottl	NULL,
66196212Sscottl	NULL,
67196212Sscottl	NULL,					/* 0x0010 */
68196212Sscottl	NULL,
69196212Sscottl	NULL,
70196212Sscottl	NULL,
71196212Sscottl	NULL,
72196212Sscottl	NULL,
73196212Sscottl	NULL,
74196212Sscottl	NULL,
75196212Sscottl	NULL,					/* 0x0018 */
76196212Sscottl	NULL,
77196212Sscottl	NULL,
78196212Sscottl	NULL,
79196212Sscottl	NULL,
80196212Sscottl	NULL,
81196212Sscottl	NULL,
82196212Sscottl	NULL,
83196212Sscottl	"Invalid configuration action",		/* 0x0020 */
84196212Sscottl	"Invalid configuration type",
85196212Sscottl	"Invalid configuration page",
86196212Sscottl	"Invalid configuration data",
87196212Sscottl	"No configuration defaults",
88196212Sscottl	"Unable to commit configuration change",
89196212Sscottl	NULL,
90196212Sscottl	NULL,
91196212Sscottl	NULL,					/* 0x0028 */
92196212Sscottl	NULL,
93196212Sscottl	NULL,
94196212Sscottl	NULL,
95196212Sscottl	NULL,
96196212Sscottl	NULL,
97196212Sscottl	NULL,
98196212Sscottl	NULL,
99196212Sscottl	NULL,					/* 0x0030 */
100196212Sscottl	NULL,
101196212Sscottl	NULL,
102196212Sscottl	NULL,
103196212Sscottl	NULL,
104196212Sscottl	NULL,
105196212Sscottl	NULL,
106196212Sscottl	NULL,
107196212Sscottl	NULL,					/* 0x0038 */
108196212Sscottl	NULL,
109196212Sscottl	NULL,
110196212Sscottl	NULL,
111196212Sscottl	NULL,
112196212Sscottl	NULL,
113196212Sscottl	NULL,
114196212Sscottl	NULL,
115196212Sscottl	"Recovered SCSI error",			/* 0x0040 */
116196212Sscottl	"Invalid SCSI bus",
117196212Sscottl	"Invalid SCSI target ID",
118196212Sscottl	"SCSI device not there",
119196212Sscottl	"SCSI data overrun",
120196212Sscottl	"SCSI data underrun",
121196212Sscottl	"SCSI I/O error",
122196212Sscottl	"SCSI protocol error",
123196212Sscottl	"SCSI task terminated",			/* 0x0048 */
124196212Sscottl	"SCSI residual mismatch",
125196212Sscottl	"SCSI task management failed",
126196212Sscottl	"SCSI I/O controller terminated",
127196212Sscottl	"SCSI external controller terminated",
128196212Sscottl	"EEDP guard error",
129196212Sscottl	"EEDP reference tag error",
130196212Sscottl	"EEDP application tag error",
131196212Sscottl	NULL,					/* 0x0050 */
132196212Sscottl	NULL,
133196212Sscottl	NULL,
134196212Sscottl	NULL,
135196212Sscottl	NULL,
136196212Sscottl	NULL,
137196212Sscottl	NULL,
138196212Sscottl	NULL,
139196212Sscottl	NULL,					/* 0x0058 */
140196212Sscottl	NULL,
141196212Sscottl	NULL,
142196212Sscottl	NULL,
143196212Sscottl	NULL,
144196212Sscottl	NULL,
145196212Sscottl	NULL,
146196212Sscottl	NULL,
147196212Sscottl	"SCSI target priority I/O",		/* 0x0060 */
148196212Sscottl	"Invalid SCSI target port",
149196212Sscottl	"Invalid SCSI target I/O index",
150196212Sscottl	"SCSI target aborted",
151196212Sscottl	"No connection retryable",
152196212Sscottl	"No connection",
153196212Sscottl	"FC aborted",
154196212Sscottl	"Invalid FC receive ID",
155196212Sscottl	"FC did invalid",			/* 0x0068 */
156196212Sscottl	"FC node logged out",
157196212Sscottl	"Transfer count mismatch",
158196212Sscottl	"STS data not set",
159196212Sscottl	"FC exchange canceled",
160196212Sscottl	"Data offset error",
161196212Sscottl	"Too much write data",
162196212Sscottl	"IU too short",
163196212Sscottl	"ACK NAK timeout",			/* 0x0070 */
164196212Sscottl	"NAK received",
165196212Sscottl	NULL,
166196212Sscottl	NULL,
167196212Sscottl	NULL,
168196212Sscottl	NULL,
169196212Sscottl	NULL,
170196212Sscottl	NULL,
171196212Sscottl	NULL,					/* 0x0078 */
172196212Sscottl	NULL,
173196212Sscottl	NULL,
174196212Sscottl	NULL,
175196212Sscottl	NULL,
176196212Sscottl	NULL,
177196212Sscottl	NULL,
178196212Sscottl	NULL,
179196212Sscottl	"LAN device not found",			/* 0x0080 */
180196212Sscottl	"LAN device failure",
181196212Sscottl	"LAN transmit error",
182196212Sscottl	"LAN transmit aborted",
183196212Sscottl	"LAN receive error",
184196212Sscottl	"LAN receive aborted",
185196212Sscottl	"LAN partial packet",
186196212Sscottl	"LAN canceled",
187196212Sscottl	NULL,					/* 0x0088 */
188196212Sscottl	NULL,
189196212Sscottl	NULL,
190196212Sscottl	NULL,
191196212Sscottl	NULL,
192196212Sscottl	NULL,
193196212Sscottl	NULL,
194196212Sscottl	NULL,
195196212Sscottl	"SAS SMP request failed",		/* 0x0090 */
196196212Sscottl	"SAS SMP data overrun",
197196212Sscottl	NULL,
198196212Sscottl	NULL,
199196212Sscottl	NULL,
200196212Sscottl	NULL,
201196212Sscottl	NULL,
202196212Sscottl	NULL,
203196212Sscottl	"Inband aborted",			/* 0x0098 */
204196212Sscottl	"No inband connection",
205196212Sscottl	NULL,
206196212Sscottl	NULL,
207196212Sscottl	NULL,
208196212Sscottl	NULL,
209196212Sscottl	NULL,
210196212Sscottl	NULL,
211196212Sscottl	"Diagnostic released",			/* 0x00A0 */
212196212Sscottl};
213196212Sscottl
214196212Sscottlstatic const char *mpt_raid_action_status_codes[] = {
215196212Sscottl	"Success",
216196212Sscottl	"Invalid action",
217196212Sscottl	"Failure",
218196212Sscottl	"Operation in progress",
219196212Sscottl};
220196212Sscottl
221196212Sscottlconst char *
222196212Sscottlmpt_ioc_status(U16 IOCStatus)
223196212Sscottl{
224196212Sscottl	static char buffer[16];
225196212Sscottl
226196212Sscottl	IOCStatus &= MPI_IOCSTATUS_MASK;
227196212Sscottl	if (IOCStatus < sizeof(mpt_ioc_status_codes) / sizeof(char *) &&
228196212Sscottl	    mpt_ioc_status_codes[IOCStatus] != NULL)
229196212Sscottl		return (mpt_ioc_status_codes[IOCStatus]);
230196212Sscottl	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", IOCStatus);
231196212Sscottl	return (buffer);
232196212Sscottl}
233196212Sscottl
234196212Sscottlconst char *
235196212Sscottlmpt_raid_status(U16 ActionStatus)
236196212Sscottl{
237196212Sscottl	static char buffer[16];
238196212Sscottl
239196212Sscottl	if (ActionStatus < sizeof(mpt_raid_action_status_codes) /
240196212Sscottl	    sizeof(char *))
241196212Sscottl		return (mpt_raid_action_status_codes[ActionStatus]);
242196212Sscottl	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", ActionStatus);
243196212Sscottl	return (buffer);
244196212Sscottl}
245196212Sscottl
246196212Sscottlconst char *
247196212Sscottlmpt_raid_level(U8 VolumeType)
248196212Sscottl{
249196212Sscottl	static char buf[16];
250196212Sscottl
251196212Sscottl	switch (VolumeType) {
252196212Sscottl	case MPI_RAID_VOL_TYPE_IS:
253196212Sscottl		return ("RAID-0");
254196212Sscottl	case MPI_RAID_VOL_TYPE_IM:
255196212Sscottl		return ("RAID-1");
256196212Sscottl	case MPI_RAID_VOL_TYPE_IME:
257196212Sscottl		return ("RAID-1E");
258196212Sscottl	case MPI_RAID_VOL_TYPE_RAID_5:
259196212Sscottl		return ("RAID-5");
260196212Sscottl	case MPI_RAID_VOL_TYPE_RAID_6:
261196212Sscottl		return ("RAID-6");
262196212Sscottl	case MPI_RAID_VOL_TYPE_RAID_10:
263196212Sscottl		return ("RAID-10");
264196212Sscottl	case MPI_RAID_VOL_TYPE_RAID_50:
265196212Sscottl		return ("RAID-50");
266196212Sscottl	default:
267196212Sscottl		sprintf(buf, "LVL 0x%02x", VolumeType);
268196212Sscottl		return (buf);
269196212Sscottl	}
270196212Sscottl}
271196212Sscottl
272196212Sscottlconst char *
273196212Sscottlmpt_volume_name(U8 VolumeBus, U8 VolumeID)
274196212Sscottl{
275196212Sscottl	static struct mpt_query_disk info;
276196212Sscottl	static char buf[16];
277196212Sscottl
278196212Sscottl	if (mpt_query_disk(VolumeBus, VolumeID, &info) != 0) {
279196212Sscottl		/*
280196212Sscottl		 * We only print out the bus number if it is non-zero
281196212Sscottl		 * since mpt(4) only supports devices on bus zero
282196212Sscottl		 * anyway.
283196212Sscottl		 */
284196212Sscottl		if (VolumeBus == 0)
285196212Sscottl			snprintf(buf, sizeof(buf), "%d", VolumeID);
286196212Sscottl		else
287196212Sscottl			snprintf(buf, sizeof(buf), "%d:%d", VolumeBus,
288196212Sscottl			    VolumeID);
289196212Sscottl		return (buf);
290196212Sscottl	}
291196212Sscottl	return (info.devname);
292196212Sscottl}
293196212Sscottl
294196212Sscottlint
295196212Sscottlmpt_lookup_volume(int fd, const char *name, U8 *VolumeBus, U8 *VolumeID)
296196212Sscottl{
297196212Sscottl	CONFIG_PAGE_IOC_2 *ioc2;
298196212Sscottl	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
299196212Sscottl	struct mpt_query_disk info;
300196212Sscottl	char *cp;
301196212Sscottl	long bus, id;
302196212Sscottl	int i;
303196212Sscottl
304196212Sscottl	/*
305196212Sscottl	 * Check for a raw [<bus>:]<id> string.  If the bus is not
306196212Sscottl	 * specified, assume bus 0.
307196212Sscottl	 */
308196212Sscottl	bus = strtol(name, &cp, 0);
309196212Sscottl	if (*cp == ':') {
310196212Sscottl		id = strtol(cp + 1, &cp, 0);
311196212Sscottl		if (*cp == '\0') {
312196212Sscottl			if (bus < 0 || bus > 0xff || id < 0 || id > 0xff) {
313215046Sjhb				return (EINVAL);
314196212Sscottl			}
315196212Sscottl			*VolumeBus = bus;
316196212Sscottl			*VolumeID = id;
317196212Sscottl			return (0);
318196212Sscottl		}
319196212Sscottl	} else if (*cp == '\0') {
320215046Sjhb		if (bus < 0 || bus > 0xff)
321215046Sjhb			return (EINVAL);
322196212Sscottl		*VolumeBus = 0;
323196212Sscottl		*VolumeID = bus;
324196212Sscottl		return (0);
325196212Sscottl	}
326196212Sscottl
327196212Sscottl	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
328196212Sscottl	if (ioc2 == NULL)
329215046Sjhb		return (errno);
330196212Sscottl
331196212Sscottl	vol = ioc2->RaidVolume;
332196212Sscottl	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
333196212Sscottl		if (mpt_query_disk(vol->VolumeBus, vol->VolumeID, &info) != 0)
334196212Sscottl			continue;
335196212Sscottl		if (strcmp(name, info.devname) == 0) {
336196212Sscottl			*VolumeBus = vol->VolumeBus;
337196212Sscottl			*VolumeID = vol->VolumeID;
338196212Sscottl			free(ioc2);
339196212Sscottl			return (0);
340196212Sscottl		}
341196212Sscottl	}
342196212Sscottl	free(ioc2);
343215046Sjhb	return (EINVAL);
344196212Sscottl}
345196212Sscottl
346196212Sscottlint
347196212Sscottlmpt_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
348196212Sscottl    CONFIG_PAGE_HEADER *header, U16 *IOCStatus)
349196212Sscottl{
350196212Sscottl	struct mpt_cfg_page_req req;
351196212Sscottl
352196212Sscottl	if (IOCStatus != NULL)
353196212Sscottl		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
354196212Sscottl	bzero(&req, sizeof(req));
355196212Sscottl	req.header.PageType = PageType;
356196212Sscottl	req.header.PageNumber = PageNumber;
357196212Sscottl	req.page_address = PageAddress;
358196212Sscottl	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
359215046Sjhb		return (errno);
360196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
361196212Sscottl		if (IOCStatus != NULL)
362196212Sscottl			*IOCStatus = req.ioc_status;
363196212Sscottl		else
364196212Sscottl			warnx("Reading config page header failed: %s",
365196212Sscottl			    mpt_ioc_status(req.ioc_status));
366215046Sjhb		return (EIO);
367196212Sscottl	}
368196212Sscottl	*header = req.header;
369196212Sscottl	return (0);
370196212Sscottl}
371196212Sscottl
372196212Sscottlvoid *
373196212Sscottlmpt_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
374196212Sscottl    U16 *IOCStatus)
375196212Sscottl{
376196212Sscottl	struct mpt_cfg_page_req req;
377196212Sscottl	void *buf;
378215046Sjhb	int error;
379196212Sscottl
380196212Sscottl	if (IOCStatus != NULL)
381196212Sscottl		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
382196212Sscottl	bzero(&req, sizeof(req));
383196212Sscottl	req.header.PageType = PageType;
384196212Sscottl	req.header.PageNumber = PageNumber;
385196212Sscottl	req.page_address = PageAddress;
386196212Sscottl	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
387196212Sscottl		return (NULL);
388196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
389196212Sscottl		if (IOCStatus != NULL)
390196212Sscottl			*IOCStatus = req.ioc_status;
391196212Sscottl		else
392196212Sscottl			warnx("Reading config page header failed: %s",
393196212Sscottl			    mpt_ioc_status(req.ioc_status));
394196212Sscottl		errno = EIO;
395196212Sscottl		return (NULL);
396196212Sscottl	}
397196212Sscottl	req.len = req.header.PageLength * 4;
398196212Sscottl	buf = malloc(req.len);
399196212Sscottl	req.buf = buf;
400196212Sscottl	bcopy(&req.header, buf, sizeof(req.header));
401196212Sscottl	if (ioctl(fd, MPTIO_READ_CFG_PAGE, &req) < 0) {
402215046Sjhb		error = errno;
403196212Sscottl		free(buf);
404215046Sjhb		errno = error;
405196212Sscottl		return (NULL);
406196212Sscottl	}
407196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
408196212Sscottl		if (IOCStatus != NULL)
409196212Sscottl			*IOCStatus = req.ioc_status;
410196212Sscottl		else
411196212Sscottl			warnx("Reading config page failed: %s",
412196212Sscottl			    mpt_ioc_status(req.ioc_status));
413196212Sscottl		free(buf);
414196212Sscottl		errno = EIO;
415196212Sscottl		return (NULL);
416196212Sscottl	}
417196212Sscottl	return (buf);
418196212Sscottl}
419196212Sscottl
420196212Sscottlvoid *
421196212Sscottlmpt_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
422196212Sscottl    U8 PageNumber, U32 PageAddress, U16 *IOCStatus)
423196212Sscottl{
424196212Sscottl	struct mpt_ext_cfg_page_req req;
425196212Sscottl	void *buf;
426215046Sjhb	int error;
427196212Sscottl
428196212Sscottl	if (IOCStatus != NULL)
429196212Sscottl		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
430196212Sscottl	bzero(&req, sizeof(req));
431196212Sscottl	req.header.PageVersion = PageVersion;
432196212Sscottl	req.header.PageNumber = PageNumber;
433196212Sscottl	req.header.ExtPageType = ExtPageType;
434196212Sscottl	req.page_address = PageAddress;
435196212Sscottl	if (ioctl(fd, MPTIO_READ_EXT_CFG_HEADER, &req) < 0)
436196212Sscottl		return (NULL);
437196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
438196212Sscottl		if (IOCStatus != NULL)
439196212Sscottl			*IOCStatus = req.ioc_status;
440196212Sscottl		else
441196212Sscottl			warnx("Reading extended config page header failed: %s",
442196212Sscottl			    mpt_ioc_status(req.ioc_status));
443196212Sscottl		errno = EIO;
444196212Sscottl		return (NULL);
445196212Sscottl	}
446196212Sscottl	req.len = req.header.ExtPageLength * 4;
447196212Sscottl	buf = malloc(req.len);
448196212Sscottl	req.buf = buf;
449196212Sscottl	bcopy(&req.header, buf, sizeof(req.header));
450196212Sscottl	if (ioctl(fd, MPTIO_READ_EXT_CFG_PAGE, &req) < 0) {
451215046Sjhb		error = errno;
452196212Sscottl		free(buf);
453215046Sjhb		errno = error;
454196212Sscottl		return (NULL);
455196212Sscottl	}
456196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
457196212Sscottl		if (IOCStatus != NULL)
458196212Sscottl			*IOCStatus = req.ioc_status;
459196212Sscottl		else
460196212Sscottl			warnx("Reading extended config page failed: %s",
461196212Sscottl			    mpt_ioc_status(req.ioc_status));
462196212Sscottl		free(buf);
463196212Sscottl		errno = EIO;
464196212Sscottl		return (NULL);
465196212Sscottl	}
466196212Sscottl	return (buf);
467196212Sscottl}
468196212Sscottl
469196212Sscottlint
470196212Sscottlmpt_write_config_page(int fd, void *buf, U16 *IOCStatus)
471196212Sscottl{
472196212Sscottl	CONFIG_PAGE_HEADER *hdr;
473196212Sscottl	struct mpt_cfg_page_req req;
474196212Sscottl
475196212Sscottl	if (IOCStatus != NULL)
476196212Sscottl		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
477196212Sscottl	bzero(&req, sizeof(req));
478196212Sscottl	req.buf = buf;
479196212Sscottl	hdr = buf;
480196212Sscottl	req.len = hdr->PageLength * 4;
481196212Sscottl	if (ioctl(fd, MPTIO_WRITE_CFG_PAGE, &req) < 0)
482215046Sjhb		return (errno);
483196212Sscottl	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
484196212Sscottl		if (IOCStatus != NULL) {
485196212Sscottl			*IOCStatus = req.ioc_status;
486196212Sscottl			return (0);
487196212Sscottl		}
488196212Sscottl		warnx("Writing config page failed: %s",
489196212Sscottl		    mpt_ioc_status(req.ioc_status));
490215046Sjhb		return (EIO);
491196212Sscottl	}
492196212Sscottl	return (0);
493196212Sscottl}
494196212Sscottl
495196212Sscottlint
496196212Sscottlmpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID, U8 PhysDiskNum,
497196212Sscottl    U32 ActionDataWord, void *buf, int len, RAID_VOL0_STATUS *VolumeStatus,
498196212Sscottl    U32 *ActionData, int datalen, U16 *IOCStatus, U16 *ActionStatus, int write)
499196212Sscottl{
500196212Sscottl	struct mpt_raid_action raid_act;
501196212Sscottl
502196212Sscottl	if (IOCStatus != NULL)
503196212Sscottl		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
504215046Sjhb	if (datalen < 0 || (unsigned)datalen > sizeof(raid_act.action_data))
505215046Sjhb		return (EINVAL);
506196212Sscottl	bzero(&raid_act, sizeof(raid_act));
507196212Sscottl	raid_act.action = Action;
508196212Sscottl	raid_act.volume_bus = VolumeBus;
509196212Sscottl	raid_act.volume_id = VolumeID;
510196212Sscottl	raid_act.phys_disk_num = PhysDiskNum;
511196212Sscottl	raid_act.action_data_word = ActionDataWord;
512196212Sscottl	if (buf != NULL && len != 0) {
513196212Sscottl		raid_act.buf = buf;
514196212Sscottl		raid_act.len = len;
515196212Sscottl		raid_act.write = write;
516196212Sscottl	}
517196212Sscottl
518196212Sscottl	if (ioctl(fd, MPTIO_RAID_ACTION, &raid_act) < 0)
519215046Sjhb		return (errno);
520196212Sscottl
521196212Sscottl	if (!IOC_STATUS_SUCCESS(raid_act.ioc_status)) {
522196212Sscottl		if (IOCStatus != NULL) {
523196212Sscottl			*IOCStatus = raid_act.ioc_status;
524196212Sscottl			return (0);
525196212Sscottl		}
526196212Sscottl		warnx("RAID action failed: %s",
527196212Sscottl		    mpt_ioc_status(raid_act.ioc_status));
528215046Sjhb		return (EIO);
529196212Sscottl	}
530196212Sscottl
531196212Sscottl	if (ActionStatus != NULL)
532196212Sscottl		*ActionStatus = raid_act.action_status;
533196212Sscottl	if (raid_act.action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS) {
534196212Sscottl		if (ActionStatus != NULL)
535196212Sscottl			return (0);
536196212Sscottl		warnx("RAID action failed: %s",
537196212Sscottl		    mpt_raid_status(raid_act.action_status));
538215046Sjhb		return (EIO);
539196212Sscottl	}
540196212Sscottl
541196212Sscottl	if (VolumeStatus != NULL)
542196212Sscottl		*((U32 *)VolumeStatus) = raid_act.volume_status;
543196212Sscottl	if (ActionData != NULL)
544196212Sscottl		bcopy(raid_act.action_data, ActionData, datalen);
545196212Sscottl	return (0);
546196212Sscottl}
547196212Sscottl
548196212Sscottlint
549196212Sscottlmpt_open(int unit)
550196212Sscottl{
551196212Sscottl	char path[MAXPATHLEN];
552196212Sscottl
553196212Sscottl	snprintf(path, sizeof(path), "/dev/mpt%d", unit);
554196212Sscottl	return (open(path, O_RDWR));
555196212Sscottl}
556196212Sscottl
557196212Sscottlint
558196212Sscottlmpt_table_handler(struct mptutil_command **start, struct mptutil_command **end,
559196212Sscottl    int ac, char **av)
560196212Sscottl{
561196212Sscottl	struct mptutil_command **cmd;
562196212Sscottl
563196212Sscottl	if (ac < 2) {
564196212Sscottl		warnx("The %s command requires a sub-command.", av[0]);
565196212Sscottl		return (EINVAL);
566196212Sscottl	}
567196212Sscottl	for (cmd = start; cmd < end; cmd++) {
568196212Sscottl		if (strcmp((*cmd)->name, av[1]) == 0)
569196212Sscottl			return ((*cmd)->handler(ac - 1, av + 1));
570196212Sscottl	}
571196212Sscottl
572196212Sscottl	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
573196212Sscottl	return (ENOENT);
574196212Sscottl}
575196212Sscottl
576196212Sscottl#ifdef DEBUG
577196212Sscottlvoid
578196212Sscottlhexdump(const void *ptr, int length, const char *hdr, int flags)
579196212Sscottl{
580196212Sscottl	int i, j, k;
581196212Sscottl	int cols;
582196212Sscottl	const unsigned char *cp;
583196212Sscottl	char delim;
584196212Sscottl
585196212Sscottl	if ((flags & HD_DELIM_MASK) != 0)
586196212Sscottl		delim = (flags & HD_DELIM_MASK) >> 8;
587196212Sscottl	else
588196212Sscottl		delim = ' ';
589196212Sscottl
590196212Sscottl	if ((flags & HD_COLUMN_MASK) != 0)
591196212Sscottl		cols = flags & HD_COLUMN_MASK;
592196212Sscottl	else
593196212Sscottl		cols = 16;
594196212Sscottl
595196212Sscottl	cp = ptr;
596196212Sscottl	for (i = 0; i < length; i+= cols) {
597196212Sscottl		if (hdr != NULL)
598196212Sscottl			printf("%s", hdr);
599196212Sscottl
600196212Sscottl		if ((flags & HD_OMIT_COUNT) == 0)
601196212Sscottl			printf("%04x  ", i);
602196212Sscottl
603196212Sscottl		if ((flags & HD_OMIT_HEX) == 0) {
604196212Sscottl			for (j = 0; j < cols; j++) {
605196212Sscottl				k = i + j;
606196212Sscottl				if (k < length)
607196212Sscottl					printf("%c%02x", delim, cp[k]);
608196212Sscottl				else
609196212Sscottl					printf("   ");
610196212Sscottl			}
611196212Sscottl		}
612196212Sscottl
613196212Sscottl		if ((flags & HD_OMIT_CHARS) == 0) {
614196212Sscottl			printf("  |");
615196212Sscottl			for (j = 0; j < cols; j++) {
616196212Sscottl				k = i + j;
617196212Sscottl				if (k >= length)
618196212Sscottl					printf(" ");
619196212Sscottl				else if (cp[k] >= ' ' && cp[k] <= '~')
620196212Sscottl					printf("%c", cp[k]);
621196212Sscottl				else
622196212Sscottl					printf(".");
623196212Sscottl			}
624196212Sscottl			printf("|");
625196212Sscottl		}
626196212Sscottl		printf("\n");
627196212Sscottl	}
628196212Sscottl}
629196212Sscottl#endif
630