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