186d7f5d3SJohn Marino /*-
286d7f5d3SJohn Marino * Copyright (c) 2008 Yahoo!, Inc.
386d7f5d3SJohn Marino * All rights reserved.
486d7f5d3SJohn Marino * Written by: John Baldwin <jhb@FreeBSD.org>
586d7f5d3SJohn Marino *
686d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
786d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
886d7f5d3SJohn Marino * are met:
986d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
1086d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
1186d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
1386d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
1486d7f5d3SJohn Marino * 3. Neither the name of the author nor the names of any co-contributors
1586d7f5d3SJohn Marino * may be used to endorse or promote products derived from this software
1686d7f5d3SJohn Marino * without specific prior written permission.
1786d7f5d3SJohn Marino *
1886d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1986d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2086d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2186d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2286d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2386d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2486d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2586d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2686d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2786d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2886d7f5d3SJohn Marino * SUCH DAMAGE.
2986d7f5d3SJohn Marino *
3086d7f5d3SJohn Marino * $FreeBSD: src/usr.sbin/mptutil/mpt_cmd.c,v 1.2 2010/11/09 19:28:06 jhb Exp $
3186d7f5d3SJohn Marino */
3286d7f5d3SJohn Marino
3386d7f5d3SJohn Marino #include <sys/param.h>
3486d7f5d3SJohn Marino #include <sys/errno.h>
3586d7f5d3SJohn Marino #include <sys/ioctl.h>
3686d7f5d3SJohn Marino #include <sys/mpt_ioctl.h>
3786d7f5d3SJohn Marino #include <sys/sysctl.h>
3886d7f5d3SJohn Marino #include <sys/uio.h>
3986d7f5d3SJohn Marino
4086d7f5d3SJohn Marino #include <err.h>
4186d7f5d3SJohn Marino #include <fcntl.h>
4286d7f5d3SJohn Marino #include <stdio.h>
4386d7f5d3SJohn Marino #include <stdlib.h>
4486d7f5d3SJohn Marino #include <string.h>
4586d7f5d3SJohn Marino #include <unistd.h>
4686d7f5d3SJohn Marino
4786d7f5d3SJohn Marino #include "mptutil.h"
4886d7f5d3SJohn Marino
4986d7f5d3SJohn Marino static const char *mpt_ioc_status_codes[] = {
5086d7f5d3SJohn Marino "Success", /* 0x0000 */
5186d7f5d3SJohn Marino "Invalid function",
5286d7f5d3SJohn Marino "Busy",
5386d7f5d3SJohn Marino "Invalid scatter-gather list",
5486d7f5d3SJohn Marino "Internal error",
5586d7f5d3SJohn Marino "Reserved",
5686d7f5d3SJohn Marino "Insufficient resources",
5786d7f5d3SJohn Marino "Invalid field",
5886d7f5d3SJohn Marino "Invalid state", /* 0x0008 */
5986d7f5d3SJohn Marino "Operation state not supported",
6086d7f5d3SJohn Marino NULL,
6186d7f5d3SJohn Marino NULL,
6286d7f5d3SJohn Marino NULL,
6386d7f5d3SJohn Marino NULL,
6486d7f5d3SJohn Marino NULL,
6586d7f5d3SJohn Marino NULL,
6686d7f5d3SJohn Marino NULL, /* 0x0010 */
6786d7f5d3SJohn Marino NULL,
6886d7f5d3SJohn Marino NULL,
6986d7f5d3SJohn Marino NULL,
7086d7f5d3SJohn Marino NULL,
7186d7f5d3SJohn Marino NULL,
7286d7f5d3SJohn Marino NULL,
7386d7f5d3SJohn Marino NULL,
7486d7f5d3SJohn Marino NULL, /* 0x0018 */
7586d7f5d3SJohn Marino NULL,
7686d7f5d3SJohn Marino NULL,
7786d7f5d3SJohn Marino NULL,
7886d7f5d3SJohn Marino NULL,
7986d7f5d3SJohn Marino NULL,
8086d7f5d3SJohn Marino NULL,
8186d7f5d3SJohn Marino NULL,
8286d7f5d3SJohn Marino "Invalid configuration action", /* 0x0020 */
8386d7f5d3SJohn Marino "Invalid configuration type",
8486d7f5d3SJohn Marino "Invalid configuration page",
8586d7f5d3SJohn Marino "Invalid configuration data",
8686d7f5d3SJohn Marino "No configuration defaults",
8786d7f5d3SJohn Marino "Unable to commit configuration change",
8886d7f5d3SJohn Marino NULL,
8986d7f5d3SJohn Marino NULL,
9086d7f5d3SJohn Marino NULL, /* 0x0028 */
9186d7f5d3SJohn Marino NULL,
9286d7f5d3SJohn Marino NULL,
9386d7f5d3SJohn Marino NULL,
9486d7f5d3SJohn Marino NULL,
9586d7f5d3SJohn Marino NULL,
9686d7f5d3SJohn Marino NULL,
9786d7f5d3SJohn Marino NULL,
9886d7f5d3SJohn Marino NULL, /* 0x0030 */
9986d7f5d3SJohn Marino NULL,
10086d7f5d3SJohn Marino NULL,
10186d7f5d3SJohn Marino NULL,
10286d7f5d3SJohn Marino NULL,
10386d7f5d3SJohn Marino NULL,
10486d7f5d3SJohn Marino NULL,
10586d7f5d3SJohn Marino NULL,
10686d7f5d3SJohn Marino NULL, /* 0x0038 */
10786d7f5d3SJohn Marino NULL,
10886d7f5d3SJohn Marino NULL,
10986d7f5d3SJohn Marino NULL,
11086d7f5d3SJohn Marino NULL,
11186d7f5d3SJohn Marino NULL,
11286d7f5d3SJohn Marino NULL,
11386d7f5d3SJohn Marino NULL,
11486d7f5d3SJohn Marino "Recovered SCSI error", /* 0x0040 */
11586d7f5d3SJohn Marino "Invalid SCSI bus",
11686d7f5d3SJohn Marino "Invalid SCSI target ID",
11786d7f5d3SJohn Marino "SCSI device not there",
11886d7f5d3SJohn Marino "SCSI data overrun",
11986d7f5d3SJohn Marino "SCSI data underrun",
12086d7f5d3SJohn Marino "SCSI I/O error",
12186d7f5d3SJohn Marino "SCSI protocol error",
12286d7f5d3SJohn Marino "SCSI task terminated", /* 0x0048 */
12386d7f5d3SJohn Marino "SCSI residual mismatch",
12486d7f5d3SJohn Marino "SCSI task management failed",
12586d7f5d3SJohn Marino "SCSI I/O controller terminated",
12686d7f5d3SJohn Marino "SCSI external controller terminated",
12786d7f5d3SJohn Marino "EEDP guard error",
12886d7f5d3SJohn Marino "EEDP reference tag error",
12986d7f5d3SJohn Marino "EEDP application tag error",
13086d7f5d3SJohn Marino NULL, /* 0x0050 */
13186d7f5d3SJohn Marino NULL,
13286d7f5d3SJohn Marino NULL,
13386d7f5d3SJohn Marino NULL,
13486d7f5d3SJohn Marino NULL,
13586d7f5d3SJohn Marino NULL,
13686d7f5d3SJohn Marino NULL,
13786d7f5d3SJohn Marino NULL,
13886d7f5d3SJohn Marino NULL, /* 0x0058 */
13986d7f5d3SJohn Marino NULL,
14086d7f5d3SJohn Marino NULL,
14186d7f5d3SJohn Marino NULL,
14286d7f5d3SJohn Marino NULL,
14386d7f5d3SJohn Marino NULL,
14486d7f5d3SJohn Marino NULL,
14586d7f5d3SJohn Marino NULL,
14686d7f5d3SJohn Marino "SCSI target priority I/O", /* 0x0060 */
14786d7f5d3SJohn Marino "Invalid SCSI target port",
14886d7f5d3SJohn Marino "Invalid SCSI target I/O index",
14986d7f5d3SJohn Marino "SCSI target aborted",
15086d7f5d3SJohn Marino "No connection retryable",
15186d7f5d3SJohn Marino "No connection",
15286d7f5d3SJohn Marino "FC aborted",
15386d7f5d3SJohn Marino "Invalid FC receive ID",
15486d7f5d3SJohn Marino "FC did invalid", /* 0x0068 */
15586d7f5d3SJohn Marino "FC node logged out",
15686d7f5d3SJohn Marino "Transfer count mismatch",
15786d7f5d3SJohn Marino "STS data not set",
15886d7f5d3SJohn Marino "FC exchange canceled",
15986d7f5d3SJohn Marino "Data offset error",
16086d7f5d3SJohn Marino "Too much write data",
16186d7f5d3SJohn Marino "IU too short",
16286d7f5d3SJohn Marino "ACK NAK timeout", /* 0x0070 */
16386d7f5d3SJohn Marino "NAK received",
16486d7f5d3SJohn Marino NULL,
16586d7f5d3SJohn Marino NULL,
16686d7f5d3SJohn Marino NULL,
16786d7f5d3SJohn Marino NULL,
16886d7f5d3SJohn Marino NULL,
16986d7f5d3SJohn Marino NULL,
17086d7f5d3SJohn Marino NULL, /* 0x0078 */
17186d7f5d3SJohn Marino NULL,
17286d7f5d3SJohn Marino NULL,
17386d7f5d3SJohn Marino NULL,
17486d7f5d3SJohn Marino NULL,
17586d7f5d3SJohn Marino NULL,
17686d7f5d3SJohn Marino NULL,
17786d7f5d3SJohn Marino NULL,
17886d7f5d3SJohn Marino "LAN device not found", /* 0x0080 */
17986d7f5d3SJohn Marino "LAN device failure",
18086d7f5d3SJohn Marino "LAN transmit error",
18186d7f5d3SJohn Marino "LAN transmit aborted",
18286d7f5d3SJohn Marino "LAN receive error",
18386d7f5d3SJohn Marino "LAN receive aborted",
18486d7f5d3SJohn Marino "LAN partial packet",
18586d7f5d3SJohn Marino "LAN canceled",
18686d7f5d3SJohn Marino NULL, /* 0x0088 */
18786d7f5d3SJohn Marino NULL,
18886d7f5d3SJohn Marino NULL,
18986d7f5d3SJohn Marino NULL,
19086d7f5d3SJohn Marino NULL,
19186d7f5d3SJohn Marino NULL,
19286d7f5d3SJohn Marino NULL,
19386d7f5d3SJohn Marino NULL,
19486d7f5d3SJohn Marino "SAS SMP request failed", /* 0x0090 */
19586d7f5d3SJohn Marino "SAS SMP data overrun",
19686d7f5d3SJohn Marino NULL,
19786d7f5d3SJohn Marino NULL,
19886d7f5d3SJohn Marino NULL,
19986d7f5d3SJohn Marino NULL,
20086d7f5d3SJohn Marino NULL,
20186d7f5d3SJohn Marino NULL,
20286d7f5d3SJohn Marino "Inband aborted", /* 0x0098 */
20386d7f5d3SJohn Marino "No inband connection",
20486d7f5d3SJohn Marino NULL,
20586d7f5d3SJohn Marino NULL,
20686d7f5d3SJohn Marino NULL,
20786d7f5d3SJohn Marino NULL,
20886d7f5d3SJohn Marino NULL,
20986d7f5d3SJohn Marino NULL,
21086d7f5d3SJohn Marino "Diagnostic released", /* 0x00A0 */
21186d7f5d3SJohn Marino };
21286d7f5d3SJohn Marino
21386d7f5d3SJohn Marino static const char *mpt_raid_action_status_codes[] = {
21486d7f5d3SJohn Marino "Success",
21586d7f5d3SJohn Marino "Invalid action",
21686d7f5d3SJohn Marino "Failure",
21786d7f5d3SJohn Marino "Operation in progress",
21886d7f5d3SJohn Marino };
21986d7f5d3SJohn Marino
22086d7f5d3SJohn Marino const char *
mpt_ioc_status(U16 IOCStatus)22186d7f5d3SJohn Marino mpt_ioc_status(U16 IOCStatus)
22286d7f5d3SJohn Marino {
22386d7f5d3SJohn Marino static char buffer[16];
22486d7f5d3SJohn Marino
22586d7f5d3SJohn Marino IOCStatus &= MPI_IOCSTATUS_MASK;
22686d7f5d3SJohn Marino if (IOCStatus < sizeof(mpt_ioc_status_codes) / sizeof(char *) &&
22786d7f5d3SJohn Marino mpt_ioc_status_codes[IOCStatus] != NULL)
22886d7f5d3SJohn Marino return (mpt_ioc_status_codes[IOCStatus]);
22986d7f5d3SJohn Marino snprintf(buffer, sizeof(buffer), "Status: 0x%04x", IOCStatus);
23086d7f5d3SJohn Marino return (buffer);
23186d7f5d3SJohn Marino }
23286d7f5d3SJohn Marino
23386d7f5d3SJohn Marino const char *
mpt_raid_status(U16 ActionStatus)23486d7f5d3SJohn Marino mpt_raid_status(U16 ActionStatus)
23586d7f5d3SJohn Marino {
23686d7f5d3SJohn Marino static char buffer[16];
23786d7f5d3SJohn Marino
23886d7f5d3SJohn Marino if (ActionStatus < sizeof(mpt_raid_action_status_codes) /
23986d7f5d3SJohn Marino sizeof(char *))
24086d7f5d3SJohn Marino return (mpt_raid_action_status_codes[ActionStatus]);
24186d7f5d3SJohn Marino snprintf(buffer, sizeof(buffer), "Status: 0x%04x", ActionStatus);
24286d7f5d3SJohn Marino return (buffer);
24386d7f5d3SJohn Marino }
24486d7f5d3SJohn Marino
24586d7f5d3SJohn Marino const char *
mpt_raid_level(U8 VolumeType)24686d7f5d3SJohn Marino mpt_raid_level(U8 VolumeType)
24786d7f5d3SJohn Marino {
24886d7f5d3SJohn Marino static char buf[16];
24986d7f5d3SJohn Marino
25086d7f5d3SJohn Marino switch (VolumeType) {
25186d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_IS:
25286d7f5d3SJohn Marino return ("RAID-0");
25386d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_IM:
25486d7f5d3SJohn Marino return ("RAID-1");
25586d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_IME:
25686d7f5d3SJohn Marino return ("RAID-1E");
25786d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_RAID_5:
25886d7f5d3SJohn Marino return ("RAID-5");
25986d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_RAID_6:
26086d7f5d3SJohn Marino return ("RAID-6");
26186d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_RAID_10:
26286d7f5d3SJohn Marino return ("RAID-10");
26386d7f5d3SJohn Marino case MPI_RAID_VOL_TYPE_RAID_50:
26486d7f5d3SJohn Marino return ("RAID-50");
26586d7f5d3SJohn Marino default:
26686d7f5d3SJohn Marino sprintf(buf, "LVL 0x%02x", VolumeType);
26786d7f5d3SJohn Marino return (buf);
26886d7f5d3SJohn Marino }
26986d7f5d3SJohn Marino }
27086d7f5d3SJohn Marino
27186d7f5d3SJohn Marino const char *
mpt_volume_name(U8 VolumeBus,U8 VolumeID)27286d7f5d3SJohn Marino mpt_volume_name(U8 VolumeBus, U8 VolumeID)
27386d7f5d3SJohn Marino {
27486d7f5d3SJohn Marino static struct mpt_query_disk info;
27586d7f5d3SJohn Marino static char buf[16];
27686d7f5d3SJohn Marino
27786d7f5d3SJohn Marino if (mpt_query_disk(VolumeBus, VolumeID, &info) != 0) {
27886d7f5d3SJohn Marino /*
27986d7f5d3SJohn Marino * We only print out the bus number if it is non-zero
28086d7f5d3SJohn Marino * since mpt(4) only supports devices on bus zero
28186d7f5d3SJohn Marino * anyway.
28286d7f5d3SJohn Marino */
28386d7f5d3SJohn Marino if (VolumeBus == 0)
28486d7f5d3SJohn Marino snprintf(buf, sizeof(buf), "%d", VolumeID);
28586d7f5d3SJohn Marino else
28686d7f5d3SJohn Marino snprintf(buf, sizeof(buf), "%d:%d", VolumeBus,
28786d7f5d3SJohn Marino VolumeID);
28886d7f5d3SJohn Marino return (buf);
28986d7f5d3SJohn Marino }
29086d7f5d3SJohn Marino return (info.devname);
29186d7f5d3SJohn Marino }
29286d7f5d3SJohn Marino
29386d7f5d3SJohn Marino int
mpt_lookup_volume(int fd,const char * name,U8 * VolumeBus,U8 * VolumeID)29486d7f5d3SJohn Marino mpt_lookup_volume(int fd, const char *name, U8 *VolumeBus, U8 *VolumeID)
29586d7f5d3SJohn Marino {
29686d7f5d3SJohn Marino CONFIG_PAGE_IOC_2 *ioc2;
29786d7f5d3SJohn Marino CONFIG_PAGE_IOC_2_RAID_VOL *vol;
29886d7f5d3SJohn Marino struct mpt_query_disk info;
29986d7f5d3SJohn Marino char *cp;
30086d7f5d3SJohn Marino long bus, id;
30186d7f5d3SJohn Marino int i;
30286d7f5d3SJohn Marino
30386d7f5d3SJohn Marino /*
30486d7f5d3SJohn Marino * Check for a raw [<bus>:]<id> string. If the bus is not
30586d7f5d3SJohn Marino * specified, assume bus 0.
30686d7f5d3SJohn Marino */
30786d7f5d3SJohn Marino bus = strtol(name, &cp, 0);
30886d7f5d3SJohn Marino if (*cp == ':') {
30986d7f5d3SJohn Marino id = strtol(cp + 1, &cp, 0);
31086d7f5d3SJohn Marino if (*cp == '\0') {
31186d7f5d3SJohn Marino if (bus < 0 || bus > 0xff || id < 0 || id > 0xff) {
31286d7f5d3SJohn Marino return (EINVAL);
31386d7f5d3SJohn Marino }
31486d7f5d3SJohn Marino *VolumeBus = bus;
31586d7f5d3SJohn Marino *VolumeID = id;
31686d7f5d3SJohn Marino return (0);
31786d7f5d3SJohn Marino }
31886d7f5d3SJohn Marino } else if (*cp == '\0') {
31986d7f5d3SJohn Marino if (bus < 0 || bus > 0xff)
32086d7f5d3SJohn Marino return (EINVAL);
32186d7f5d3SJohn Marino *VolumeBus = 0;
32286d7f5d3SJohn Marino *VolumeID = bus;
32386d7f5d3SJohn Marino return (0);
32486d7f5d3SJohn Marino }
32586d7f5d3SJohn Marino
32686d7f5d3SJohn Marino ioc2 = mpt_read_ioc_page(fd, 2, NULL);
32786d7f5d3SJohn Marino if (ioc2 == NULL)
32886d7f5d3SJohn Marino return (errno);
32986d7f5d3SJohn Marino
33086d7f5d3SJohn Marino vol = ioc2->RaidVolume;
33186d7f5d3SJohn Marino for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
33286d7f5d3SJohn Marino if (mpt_query_disk(vol->VolumeBus, vol->VolumeID, &info) != 0)
33386d7f5d3SJohn Marino continue;
33486d7f5d3SJohn Marino if (strcmp(name, info.devname) == 0) {
33586d7f5d3SJohn Marino *VolumeBus = vol->VolumeBus;
33686d7f5d3SJohn Marino *VolumeID = vol->VolumeID;
33786d7f5d3SJohn Marino free(ioc2);
33886d7f5d3SJohn Marino return (0);
33986d7f5d3SJohn Marino }
34086d7f5d3SJohn Marino }
34186d7f5d3SJohn Marino free(ioc2);
34286d7f5d3SJohn Marino return (EINVAL);
34386d7f5d3SJohn Marino }
34486d7f5d3SJohn Marino
34586d7f5d3SJohn Marino int
mpt_read_config_page_header(int fd,U8 PageType,U8 PageNumber,U32 PageAddress,CONFIG_PAGE_HEADER * header,U16 * IOCStatus)34686d7f5d3SJohn Marino mpt_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
34786d7f5d3SJohn Marino CONFIG_PAGE_HEADER *header, U16 *IOCStatus)
34886d7f5d3SJohn Marino {
34986d7f5d3SJohn Marino struct mpt_cfg_page_req req;
35086d7f5d3SJohn Marino
35186d7f5d3SJohn Marino if (IOCStatus != NULL)
35286d7f5d3SJohn Marino *IOCStatus = MPI_IOCSTATUS_SUCCESS;
35386d7f5d3SJohn Marino bzero(&req, sizeof(req));
35486d7f5d3SJohn Marino req.header.PageType = PageType;
35586d7f5d3SJohn Marino req.header.PageNumber = PageNumber;
35686d7f5d3SJohn Marino req.page_address = PageAddress;
35786d7f5d3SJohn Marino if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
35886d7f5d3SJohn Marino return (errno);
35986d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
36086d7f5d3SJohn Marino if (IOCStatus != NULL)
36186d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
36286d7f5d3SJohn Marino else
36386d7f5d3SJohn Marino warnx("Reading config page header failed: %s",
36486d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
36586d7f5d3SJohn Marino return (EIO);
36686d7f5d3SJohn Marino }
36786d7f5d3SJohn Marino *header = req.header;
36886d7f5d3SJohn Marino return (0);
36986d7f5d3SJohn Marino }
37086d7f5d3SJohn Marino
37186d7f5d3SJohn Marino void *
mpt_read_config_page(int fd,U8 PageType,U8 PageNumber,U32 PageAddress,U16 * IOCStatus)37286d7f5d3SJohn Marino mpt_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
37386d7f5d3SJohn Marino U16 *IOCStatus)
37486d7f5d3SJohn Marino {
37586d7f5d3SJohn Marino struct mpt_cfg_page_req req;
37686d7f5d3SJohn Marino void *buf;
37786d7f5d3SJohn Marino int error;
37886d7f5d3SJohn Marino
37986d7f5d3SJohn Marino if (IOCStatus != NULL)
38086d7f5d3SJohn Marino *IOCStatus = MPI_IOCSTATUS_SUCCESS;
38186d7f5d3SJohn Marino bzero(&req, sizeof(req));
38286d7f5d3SJohn Marino req.header.PageType = PageType;
38386d7f5d3SJohn Marino req.header.PageNumber = PageNumber;
38486d7f5d3SJohn Marino req.page_address = PageAddress;
38586d7f5d3SJohn Marino if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
38686d7f5d3SJohn Marino return (NULL);
38786d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
38886d7f5d3SJohn Marino if (IOCStatus != NULL)
38986d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
39086d7f5d3SJohn Marino else
39186d7f5d3SJohn Marino warnx("Reading config page header failed: %s",
39286d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
39386d7f5d3SJohn Marino errno = EIO;
39486d7f5d3SJohn Marino return (NULL);
39586d7f5d3SJohn Marino }
39686d7f5d3SJohn Marino req.len = req.header.PageLength * 4;
39786d7f5d3SJohn Marino buf = malloc(req.len);
39886d7f5d3SJohn Marino req.buf = buf;
39986d7f5d3SJohn Marino bcopy(&req.header, buf, sizeof(req.header));
40086d7f5d3SJohn Marino if (ioctl(fd, MPTIO_READ_CFG_PAGE, &req) < 0) {
40186d7f5d3SJohn Marino error = errno;
40286d7f5d3SJohn Marino free(buf);
40386d7f5d3SJohn Marino errno = error;
40486d7f5d3SJohn Marino return (NULL);
40586d7f5d3SJohn Marino }
40686d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
40786d7f5d3SJohn Marino if (IOCStatus != NULL)
40886d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
40986d7f5d3SJohn Marino else
41086d7f5d3SJohn Marino warnx("Reading config page failed: %s",
41186d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
41286d7f5d3SJohn Marino free(buf);
41386d7f5d3SJohn Marino errno = EIO;
41486d7f5d3SJohn Marino return (NULL);
41586d7f5d3SJohn Marino }
41686d7f5d3SJohn Marino return (buf);
41786d7f5d3SJohn Marino }
41886d7f5d3SJohn Marino
41986d7f5d3SJohn Marino void *
mpt_read_extended_config_page(int fd,U8 ExtPageType,U8 PageVersion,U8 PageNumber,U32 PageAddress,U16 * IOCStatus)42086d7f5d3SJohn Marino mpt_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
42186d7f5d3SJohn Marino U8 PageNumber, U32 PageAddress, U16 *IOCStatus)
42286d7f5d3SJohn Marino {
42386d7f5d3SJohn Marino struct mpt_ext_cfg_page_req req;
42486d7f5d3SJohn Marino void *buf;
42586d7f5d3SJohn Marino int error;
42686d7f5d3SJohn Marino
42786d7f5d3SJohn Marino if (IOCStatus != NULL)
42886d7f5d3SJohn Marino *IOCStatus = MPI_IOCSTATUS_SUCCESS;
42986d7f5d3SJohn Marino bzero(&req, sizeof(req));
43086d7f5d3SJohn Marino req.header.PageVersion = PageVersion;
43186d7f5d3SJohn Marino req.header.PageNumber = PageNumber;
43286d7f5d3SJohn Marino req.header.ExtPageType = ExtPageType;
43386d7f5d3SJohn Marino req.page_address = PageAddress;
43486d7f5d3SJohn Marino if (ioctl(fd, MPTIO_READ_EXT_CFG_HEADER, &req) < 0)
43586d7f5d3SJohn Marino return (NULL);
43686d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
43786d7f5d3SJohn Marino if (IOCStatus != NULL)
43886d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
43986d7f5d3SJohn Marino else
44086d7f5d3SJohn Marino warnx("Reading extended config page header failed: %s",
44186d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
44286d7f5d3SJohn Marino errno = EIO;
44386d7f5d3SJohn Marino return (NULL);
44486d7f5d3SJohn Marino }
44586d7f5d3SJohn Marino req.len = req.header.ExtPageLength * 4;
44686d7f5d3SJohn Marino buf = malloc(req.len);
44786d7f5d3SJohn Marino req.buf = buf;
44886d7f5d3SJohn Marino bcopy(&req.header, buf, sizeof(req.header));
44986d7f5d3SJohn Marino if (ioctl(fd, MPTIO_READ_EXT_CFG_PAGE, &req) < 0) {
45086d7f5d3SJohn Marino error = errno;
45186d7f5d3SJohn Marino free(buf);
45286d7f5d3SJohn Marino errno = error;
45386d7f5d3SJohn Marino return (NULL);
45486d7f5d3SJohn Marino }
45586d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
45686d7f5d3SJohn Marino if (IOCStatus != NULL)
45786d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
45886d7f5d3SJohn Marino else
45986d7f5d3SJohn Marino warnx("Reading extended config page failed: %s",
46086d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
46186d7f5d3SJohn Marino free(buf);
46286d7f5d3SJohn Marino errno = EIO;
46386d7f5d3SJohn Marino return (NULL);
46486d7f5d3SJohn Marino }
46586d7f5d3SJohn Marino return (buf);
46686d7f5d3SJohn Marino }
46786d7f5d3SJohn Marino
46886d7f5d3SJohn Marino int
mpt_write_config_page(int fd,void * buf,U16 * IOCStatus)46986d7f5d3SJohn Marino mpt_write_config_page(int fd, void *buf, U16 *IOCStatus)
47086d7f5d3SJohn Marino {
47186d7f5d3SJohn Marino CONFIG_PAGE_HEADER *hdr;
47286d7f5d3SJohn Marino struct mpt_cfg_page_req req;
47386d7f5d3SJohn Marino
47486d7f5d3SJohn Marino if (IOCStatus != NULL)
47586d7f5d3SJohn Marino *IOCStatus = MPI_IOCSTATUS_SUCCESS;
47686d7f5d3SJohn Marino bzero(&req, sizeof(req));
47786d7f5d3SJohn Marino req.buf = buf;
47886d7f5d3SJohn Marino hdr = buf;
47986d7f5d3SJohn Marino req.len = hdr->PageLength * 4;
48086d7f5d3SJohn Marino if (ioctl(fd, MPTIO_WRITE_CFG_PAGE, &req) < 0)
48186d7f5d3SJohn Marino return (errno);
48286d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
48386d7f5d3SJohn Marino if (IOCStatus != NULL) {
48486d7f5d3SJohn Marino *IOCStatus = req.ioc_status;
48586d7f5d3SJohn Marino return (0);
48686d7f5d3SJohn Marino }
48786d7f5d3SJohn Marino warnx("Writing config page failed: %s",
48886d7f5d3SJohn Marino mpt_ioc_status(req.ioc_status));
48986d7f5d3SJohn Marino return (EIO);
49086d7f5d3SJohn Marino }
49186d7f5d3SJohn Marino return (0);
49286d7f5d3SJohn Marino }
49386d7f5d3SJohn Marino
49486d7f5d3SJohn 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)49586d7f5d3SJohn Marino mpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID, U8 PhysDiskNum,
49686d7f5d3SJohn Marino U32 ActionDataWord, void *buf, int len, RAID_VOL0_STATUS *VolumeStatus,
49786d7f5d3SJohn Marino U32 *ActionData, int datalen, U16 *IOCStatus, U16 *ActionStatus, int write_act)
49886d7f5d3SJohn Marino {
49986d7f5d3SJohn Marino struct mpt_raid_action raid_act;
50086d7f5d3SJohn Marino
50186d7f5d3SJohn Marino if (IOCStatus != NULL)
50286d7f5d3SJohn Marino *IOCStatus = MPI_IOCSTATUS_SUCCESS;
50386d7f5d3SJohn Marino if (datalen < 0 || (unsigned)datalen > sizeof(raid_act.action_data))
50486d7f5d3SJohn Marino return (EINVAL);
50586d7f5d3SJohn Marino bzero(&raid_act, sizeof(raid_act));
50686d7f5d3SJohn Marino raid_act.action = Action;
50786d7f5d3SJohn Marino raid_act.volume_bus = VolumeBus;
50886d7f5d3SJohn Marino raid_act.volume_id = VolumeID;
50986d7f5d3SJohn Marino raid_act.phys_disk_num = PhysDiskNum;
51086d7f5d3SJohn Marino raid_act.action_data_word = ActionDataWord;
51186d7f5d3SJohn Marino if (buf != NULL && len != 0) {
51286d7f5d3SJohn Marino raid_act.buf = buf;
51386d7f5d3SJohn Marino raid_act.len = len;
51486d7f5d3SJohn Marino raid_act.write = write_act;
51586d7f5d3SJohn Marino }
51686d7f5d3SJohn Marino
51786d7f5d3SJohn Marino if (ioctl(fd, MPTIO_RAID_ACTION, &raid_act) < 0)
51886d7f5d3SJohn Marino return (errno);
51986d7f5d3SJohn Marino
52086d7f5d3SJohn Marino if (!IOC_STATUS_SUCCESS(raid_act.ioc_status)) {
52186d7f5d3SJohn Marino if (IOCStatus != NULL) {
52286d7f5d3SJohn Marino *IOCStatus = raid_act.ioc_status;
52386d7f5d3SJohn Marino return (0);
52486d7f5d3SJohn Marino }
52586d7f5d3SJohn Marino warnx("RAID action failed: %s",
52686d7f5d3SJohn Marino mpt_ioc_status(raid_act.ioc_status));
52786d7f5d3SJohn Marino return (EIO);
52886d7f5d3SJohn Marino }
52986d7f5d3SJohn Marino
53086d7f5d3SJohn Marino if (ActionStatus != NULL)
53186d7f5d3SJohn Marino *ActionStatus = raid_act.action_status;
53286d7f5d3SJohn Marino if (raid_act.action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS) {
53386d7f5d3SJohn Marino if (ActionStatus != NULL)
53486d7f5d3SJohn Marino return (0);
53586d7f5d3SJohn Marino warnx("RAID action failed: %s",
53686d7f5d3SJohn Marino mpt_raid_status(raid_act.action_status));
53786d7f5d3SJohn Marino return (EIO);
53886d7f5d3SJohn Marino }
53986d7f5d3SJohn Marino
54086d7f5d3SJohn Marino if (VolumeStatus != NULL)
54186d7f5d3SJohn Marino *((U32 *)VolumeStatus) = raid_act.volume_status;
54286d7f5d3SJohn Marino if (ActionData != NULL)
54386d7f5d3SJohn Marino bcopy(raid_act.action_data, ActionData, datalen);
54486d7f5d3SJohn Marino return (0);
54586d7f5d3SJohn Marino }
54686d7f5d3SJohn Marino
54786d7f5d3SJohn Marino int
mpt_open(int unit)54886d7f5d3SJohn Marino mpt_open(int unit)
54986d7f5d3SJohn Marino {
55086d7f5d3SJohn Marino char path[MAXPATHLEN];
55186d7f5d3SJohn Marino
55286d7f5d3SJohn Marino snprintf(path, sizeof(path), "/dev/mpt%d", unit);
55386d7f5d3SJohn Marino return (open(path, O_RDWR));
55486d7f5d3SJohn Marino }
55586d7f5d3SJohn Marino
55686d7f5d3SJohn Marino int
mpt_table_handler(struct mptutil_command ** start,struct mptutil_command ** end,int ac,char ** av)55786d7f5d3SJohn Marino mpt_table_handler(struct mptutil_command **start, struct mptutil_command **end,
55886d7f5d3SJohn Marino int ac, char **av)
55986d7f5d3SJohn Marino {
56086d7f5d3SJohn Marino struct mptutil_command **cmd;
56186d7f5d3SJohn Marino
56286d7f5d3SJohn Marino if (ac < 2) {
56386d7f5d3SJohn Marino warnx("The %s command requires a sub-command.", av[0]);
56486d7f5d3SJohn Marino return (EINVAL);
56586d7f5d3SJohn Marino }
56686d7f5d3SJohn Marino for (cmd = start; cmd < end; cmd++) {
56786d7f5d3SJohn Marino if (strcmp((*cmd)->name, av[1]) == 0)
56886d7f5d3SJohn Marino return ((*cmd)->handler(ac - 1, av + 1));
56986d7f5d3SJohn Marino }
57086d7f5d3SJohn Marino
57186d7f5d3SJohn Marino warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
57286d7f5d3SJohn Marino return (ENOENT);
57386d7f5d3SJohn Marino }
57486d7f5d3SJohn Marino
57586d7f5d3SJohn Marino #ifdef DEBUG
57686d7f5d3SJohn Marino void
hexdump(const void * ptr,int length,const char * hdr,int flags)57786d7f5d3SJohn Marino hexdump(const void *ptr, int length, const char *hdr, int flags)
57886d7f5d3SJohn Marino {
57986d7f5d3SJohn Marino int i, j, k;
58086d7f5d3SJohn Marino int cols;
58186d7f5d3SJohn Marino const unsigned char *cp;
58286d7f5d3SJohn Marino char delim;
58386d7f5d3SJohn Marino
58486d7f5d3SJohn Marino if ((flags & HD_DELIM_MASK) != 0)
58586d7f5d3SJohn Marino delim = (flags & HD_DELIM_MASK) >> 8;
58686d7f5d3SJohn Marino else
58786d7f5d3SJohn Marino delim = ' ';
58886d7f5d3SJohn Marino
58986d7f5d3SJohn Marino if ((flags & HD_COLUMN_MASK) != 0)
59086d7f5d3SJohn Marino cols = flags & HD_COLUMN_MASK;
59186d7f5d3SJohn Marino else
59286d7f5d3SJohn Marino cols = 16;
59386d7f5d3SJohn Marino
59486d7f5d3SJohn Marino cp = ptr;
59586d7f5d3SJohn Marino for (i = 0; i < length; i+= cols) {
59686d7f5d3SJohn Marino if (hdr != NULL)
59786d7f5d3SJohn Marino printf("%s", hdr);
59886d7f5d3SJohn Marino
59986d7f5d3SJohn Marino if ((flags & HD_OMIT_COUNT) == 0)
60086d7f5d3SJohn Marino printf("%04x ", i);
60186d7f5d3SJohn Marino
60286d7f5d3SJohn Marino if ((flags & HD_OMIT_HEX) == 0) {
60386d7f5d3SJohn Marino for (j = 0; j < cols; j++) {
60486d7f5d3SJohn Marino k = i + j;
60586d7f5d3SJohn Marino if (k < length)
60686d7f5d3SJohn Marino printf("%c%02x", delim, cp[k]);
60786d7f5d3SJohn Marino else
60886d7f5d3SJohn Marino printf(" ");
60986d7f5d3SJohn Marino }
61086d7f5d3SJohn Marino }
61186d7f5d3SJohn Marino
61286d7f5d3SJohn Marino if ((flags & HD_OMIT_CHARS) == 0) {
61386d7f5d3SJohn Marino printf(" |");
61486d7f5d3SJohn Marino for (j = 0; j < cols; j++) {
61586d7f5d3SJohn Marino k = i + j;
61686d7f5d3SJohn Marino if (k >= length)
61786d7f5d3SJohn Marino printf(" ");
61886d7f5d3SJohn Marino else if (cp[k] >= ' ' && cp[k] <= '~')
61986d7f5d3SJohn Marino printf("%c", cp[k]);
62086d7f5d3SJohn Marino else
62186d7f5d3SJohn Marino printf(".");
62286d7f5d3SJohn Marino }
62386d7f5d3SJohn Marino printf("|");
62486d7f5d3SJohn Marino }
62586d7f5d3SJohn Marino printf("\n");
62686d7f5d3SJohn Marino }
62786d7f5d3SJohn Marino }
62886d7f5d3SJohn Marino #endif
629