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