mps_cmd.c revision 290061
1286180Sscottl/*- 2290061Sscottl * Copyright (c) 2015 Netflix, Inc. 3290061Sscottl * All rights reserved. 4290061Sscottl * Written by: Scott Long <scottl@freebsd.org> 5290061Sscottl * 6286180Sscottl * Copyright (c) 2008 Yahoo!, Inc. 7286180Sscottl * All rights reserved. 8286180Sscottl * Written by: John Baldwin <jhb@FreeBSD.org> 9286180Sscottl * 10286180Sscottl * Redistribution and use in source and binary forms, with or without 11286180Sscottl * modification, are permitted provided that the following conditions 12286180Sscottl * are met: 13286180Sscottl * 1. Redistributions of source code must retain the above copyright 14286180Sscottl * notice, this list of conditions and the following disclaimer. 15286180Sscottl * 2. Redistributions in binary form must reproduce the above copyright 16286180Sscottl * notice, this list of conditions and the following disclaimer in the 17286180Sscottl * documentation and/or other materials provided with the distribution. 18286180Sscottl * 3. Neither the name of the author nor the names of any co-contributors 19286180Sscottl * may be used to endorse or promote products derived from this software 20286180Sscottl * without specific prior written permission. 21286180Sscottl * 22286180Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23286180Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24286180Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25286180Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26286180Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27286180Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28286180Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29286180Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30286180Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31286180Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32286180Sscottl * SUCH DAMAGE. 33286180Sscottl */ 34286180Sscottl 35286180Sscottl#include <sys/cdefs.h> 36286180Sscottl__RCSID("$FreeBSD: projects/mpsutil/usr.sbin/mpsutil/mps_cmd.c 290061 2015-10-27 20:56:57Z scottl $"); 37286180Sscottl 38286180Sscottl#include <sys/param.h> 39286180Sscottl#include <sys/errno.h> 40286180Sscottl#include <sys/ioctl.h> 41286180Sscottl#if 0 42286180Sscottl#include <sys/mps_ioctl.h> 43286180Sscottl#else 44286180Sscottl#include "mps_ioctl.h" 45289366Sbapt#include "mpr_ioctl.h" 46286180Sscottl#endif 47286180Sscottl#include <sys/sysctl.h> 48286180Sscottl#include <sys/uio.h> 49286180Sscottl 50286180Sscottl#include <err.h> 51286180Sscottl#include <fcntl.h> 52286180Sscottl#include <stdio.h> 53286180Sscottl#include <stdlib.h> 54286180Sscottl#include <string.h> 55286180Sscottl#include <unistd.h> 56286180Sscottl 57286180Sscottl#include "mpsutil.h" 58286180Sscottl 59286180Sscottl#ifndef USE_MPT_IOCTLS 60286180Sscottl#define USE_MPT_IOCTLS 61286180Sscottl#endif 62286180Sscottl 63286180Sscottlstatic const char *mps_ioc_status_codes[] = { 64286180Sscottl "Success", /* 0x0000 */ 65286180Sscottl "Invalid function", 66286180Sscottl "Busy", 67286180Sscottl "Invalid scatter-gather list", 68286180Sscottl "Internal error", 69286180Sscottl "Reserved", 70286180Sscottl "Insufficient resources", 71286180Sscottl "Invalid field", 72286180Sscottl "Invalid state", /* 0x0008 */ 73286180Sscottl "Operation state not supported", 74286180Sscottl NULL, 75286180Sscottl NULL, 76286180Sscottl NULL, 77286180Sscottl NULL, 78286180Sscottl NULL, 79286180Sscottl NULL, 80286180Sscottl NULL, /* 0x0010 */ 81286180Sscottl NULL, 82286180Sscottl NULL, 83286180Sscottl NULL, 84286180Sscottl NULL, 85286180Sscottl NULL, 86286180Sscottl NULL, 87286180Sscottl NULL, 88286180Sscottl NULL, /* 0x0018 */ 89286180Sscottl NULL, 90286180Sscottl NULL, 91286180Sscottl NULL, 92286180Sscottl NULL, 93286180Sscottl NULL, 94286180Sscottl NULL, 95286180Sscottl NULL, 96286180Sscottl "Invalid configuration action", /* 0x0020 */ 97286180Sscottl "Invalid configuration type", 98286180Sscottl "Invalid configuration page", 99286180Sscottl "Invalid configuration data", 100286180Sscottl "No configuration defaults", 101286180Sscottl "Unable to commit configuration change", 102286180Sscottl NULL, 103286180Sscottl NULL, 104286180Sscottl NULL, /* 0x0028 */ 105286180Sscottl NULL, 106286180Sscottl NULL, 107286180Sscottl NULL, 108286180Sscottl NULL, 109286180Sscottl NULL, 110286180Sscottl NULL, 111286180Sscottl NULL, 112286180Sscottl NULL, /* 0x0030 */ 113286180Sscottl NULL, 114286180Sscottl NULL, 115286180Sscottl NULL, 116286180Sscottl NULL, 117286180Sscottl NULL, 118286180Sscottl NULL, 119286180Sscottl NULL, 120286180Sscottl NULL, /* 0x0038 */ 121286180Sscottl NULL, 122286180Sscottl NULL, 123286180Sscottl NULL, 124286180Sscottl NULL, 125286180Sscottl NULL, 126286180Sscottl NULL, 127286180Sscottl NULL, 128286180Sscottl "Recovered SCSI error", /* 0x0040 */ 129286180Sscottl "Invalid SCSI bus", 130286180Sscottl "Invalid SCSI target ID", 131286180Sscottl "SCSI device not there", 132286180Sscottl "SCSI data overrun", 133286180Sscottl "SCSI data underrun", 134286180Sscottl "SCSI I/O error", 135286180Sscottl "SCSI protocol error", 136286180Sscottl "SCSI task terminated", /* 0x0048 */ 137286180Sscottl "SCSI residual mismatch", 138286180Sscottl "SCSI task management failed", 139286180Sscottl "SCSI I/O controller terminated", 140286180Sscottl "SCSI external controller terminated", 141286180Sscottl "EEDP guard error", 142286180Sscottl "EEDP reference tag error", 143286180Sscottl "EEDP application tag error", 144286180Sscottl NULL, /* 0x0050 */ 145286180Sscottl NULL, 146286180Sscottl NULL, 147286180Sscottl NULL, 148286180Sscottl NULL, 149286180Sscottl NULL, 150286180Sscottl NULL, 151286180Sscottl NULL, 152286180Sscottl NULL, /* 0x0058 */ 153286180Sscottl NULL, 154286180Sscottl NULL, 155286180Sscottl NULL, 156286180Sscottl NULL, 157286180Sscottl NULL, 158286180Sscottl NULL, 159286180Sscottl NULL, 160286180Sscottl "SCSI target priority I/O", /* 0x0060 */ 161286180Sscottl "Invalid SCSI target port", 162286180Sscottl "Invalid SCSI target I/O index", 163286180Sscottl "SCSI target aborted", 164286180Sscottl "No connection retryable", 165286180Sscottl "No connection", 166286180Sscottl "FC aborted", 167286180Sscottl "Invalid FC receive ID", 168286180Sscottl "FC did invalid", /* 0x0068 */ 169286180Sscottl "FC node logged out", 170286180Sscottl "Transfer count mismatch", 171286180Sscottl "STS data not set", 172286180Sscottl "FC exchange canceled", 173286180Sscottl "Data offset error", 174286180Sscottl "Too much write data", 175286180Sscottl "IU too short", 176286180Sscottl "ACK NAK timeout", /* 0x0070 */ 177286180Sscottl "NAK received", 178286180Sscottl NULL, 179286180Sscottl NULL, 180286180Sscottl NULL, 181286180Sscottl NULL, 182286180Sscottl NULL, 183286180Sscottl NULL, 184286180Sscottl NULL, /* 0x0078 */ 185286180Sscottl NULL, 186286180Sscottl NULL, 187286180Sscottl NULL, 188286180Sscottl NULL, 189286180Sscottl NULL, 190286180Sscottl NULL, 191286180Sscottl NULL, 192286180Sscottl "LAN device not found", /* 0x0080 */ 193286180Sscottl "LAN device failure", 194286180Sscottl "LAN transmit error", 195286180Sscottl "LAN transmit aborted", 196286180Sscottl "LAN receive error", 197286180Sscottl "LAN receive aborted", 198286180Sscottl "LAN partial packet", 199286180Sscottl "LAN canceled", 200286180Sscottl NULL, /* 0x0088 */ 201286180Sscottl NULL, 202286180Sscottl NULL, 203286180Sscottl NULL, 204286180Sscottl NULL, 205286180Sscottl NULL, 206286180Sscottl NULL, 207286180Sscottl NULL, 208286180Sscottl "SAS SMP request failed", /* 0x0090 */ 209286180Sscottl "SAS SMP data overrun", 210286180Sscottl NULL, 211286180Sscottl NULL, 212286180Sscottl NULL, 213286180Sscottl NULL, 214286180Sscottl NULL, 215286180Sscottl NULL, 216286180Sscottl "Inband aborted", /* 0x0098 */ 217286180Sscottl "No inband connection", 218286180Sscottl NULL, 219286180Sscottl NULL, 220286180Sscottl NULL, 221286180Sscottl NULL, 222286180Sscottl NULL, 223286180Sscottl NULL, 224286180Sscottl "Diagnostic released", /* 0x00A0 */ 225286180Sscottl}; 226286180Sscottl 227289366Sbaptstruct mprs_pass_thru { 228289366Sbapt uint64_t PtrRequest; 229289366Sbapt uint64_t PtrReply; 230289366Sbapt uint64_t PtrData; 231289366Sbapt uint32_t RequestSize; 232289366Sbapt uint32_t ReplySize; 233289366Sbapt uint32_t DataSize; 234289366Sbapt uint32_t DataDirection; 235289366Sbapt uint64_t PtrDataOut; 236289366Sbapt uint32_t DataOutSize; 237289366Sbapt uint32_t Timeout; 238289366Sbapt}; 239289366Sbapt 240289366Sbaptstruct mprs_btdh_mapping { 241289366Sbapt uint16_t TargetID; 242289366Sbapt uint16_t Bus; 243289366Sbapt uint16_t DevHandle; 244289366Sbapt uint16_t Reserved; 245289366Sbapt}; 246289366Sbapt 247286180Sscottlconst char * 248286180Sscottlmps_ioc_status(U16 IOCStatus) 249286180Sscottl{ 250286180Sscottl static char buffer[16]; 251286180Sscottl 252286180Sscottl IOCStatus &= MPI2_IOCSTATUS_MASK; 253286180Sscottl if (IOCStatus < sizeof(mps_ioc_status_codes) / sizeof(char *) && 254286180Sscottl mps_ioc_status_codes[IOCStatus] != NULL) 255286180Sscottl return (mps_ioc_status_codes[IOCStatus]); 256286180Sscottl snprintf(buffer, sizeof(buffer), "Status: 0x%04x", IOCStatus); 257286180Sscottl return (buffer); 258286180Sscottl} 259286180Sscottl 260286180Sscottl#ifdef USE_MPT_IOCTLS 261286180Sscottlint 262286180Sscottlmps_map_btdh(int fd, uint16_t *devhandle, uint16_t *bus, uint16_t *target) 263286180Sscottl{ 264286180Sscottl int error; 265289366Sbapt struct mprs_btdh_mapping map; 266286180Sscottl 267286180Sscottl map.Bus = *bus; 268286180Sscottl map.TargetID = *target; 269286180Sscottl map.DevHandle = *devhandle; 270286180Sscottl 271286180Sscottl if ((error = ioctl(fd, MPTIOCTL_BTDH_MAPPING, &map)) != 0) { 272286180Sscottl error = errno; 273286180Sscottl warn("Failed to map bus/target/device"); 274286180Sscottl return (error); 275286180Sscottl } 276286180Sscottl 277286180Sscottl *bus = map.Bus; 278286180Sscottl *target = map.TargetID; 279286180Sscottl *devhandle = map.DevHandle; 280286180Sscottl 281286180Sscottl return (0); 282286180Sscottl} 283286180Sscottl 284286180Sscottlint 285286180Sscottlmps_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, 286286180Sscottl MPI2_CONFIG_PAGE_HEADER *header, U16 *IOCStatus) 287286180Sscottl{ 288286180Sscottl MPI2_CONFIG_REQUEST req; 289286180Sscottl MPI2_CONFIG_REPLY reply; 290286180Sscottl 291286180Sscottl bzero(&req, sizeof(req)); 292286180Sscottl req.Function = MPI2_FUNCTION_CONFIG; 293286180Sscottl req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 294286180Sscottl req.Header.PageType = PageType; 295286180Sscottl req.Header.PageNumber = PageNumber; 296286180Sscottl req.PageAddress = PageAddress; 297286180Sscottl 298286180Sscottl if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), 299286180Sscottl NULL, 0, NULL, 0, 30)) 300286180Sscottl return (errno); 301286180Sscottl 302286180Sscottl if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { 303286180Sscottl if (IOCStatus != NULL) 304286180Sscottl *IOCStatus = reply.IOCStatus; 305286180Sscottl return (EIO); 306286180Sscottl } 307286180Sscottl if (header == NULL) 308286180Sscottl return (EINVAL); 309286180Sscottl *header = reply.Header; 310286180Sscottl return (0); 311286180Sscottl} 312286180Sscottl 313286180Sscottlint 314286180Sscottlmps_read_ext_config_page_header(int fd, U8 ExtPageType, U8 PageNumber, U32 PageAddress, MPI2_CONFIG_PAGE_HEADER *header, U16 *ExtPageLength, U16 *IOCStatus) 315286180Sscottl{ 316286180Sscottl MPI2_CONFIG_REQUEST req; 317286180Sscottl MPI2_CONFIG_REPLY reply; 318286180Sscottl 319286180Sscottl bzero(&req, sizeof(req)); 320286180Sscottl req.Function = MPI2_FUNCTION_CONFIG; 321286180Sscottl req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 322286180Sscottl req.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 323286180Sscottl req.ExtPageType = ExtPageType; 324286180Sscottl req.Header.PageNumber = PageNumber; 325286180Sscottl req.PageAddress = PageAddress; 326286180Sscottl 327286180Sscottl if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), 328286180Sscottl NULL, 0, NULL, 0, 30)) 329286180Sscottl return (errno); 330286180Sscottl 331286180Sscottl if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { 332286180Sscottl if (IOCStatus != NULL) 333286180Sscottl *IOCStatus = reply.IOCStatus; 334286180Sscottl return (EIO); 335286180Sscottl } 336286180Sscottl if ((header == NULL) || (ExtPageLength == NULL)) 337286180Sscottl return (EINVAL); 338286180Sscottl *header = reply.Header; 339286180Sscottl *ExtPageLength = reply.ExtPageLength; 340286180Sscottl return (0); 341286180Sscottl} 342286180Sscottl 343286180Sscottlvoid * 344286180Sscottlmps_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, 345286180Sscottl U16 *IOCStatus) 346286180Sscottl{ 347286180Sscottl MPI2_CONFIG_REQUEST req; 348286180Sscottl MPI2_CONFIG_PAGE_HEADER header; 349286180Sscottl MPI2_CONFIG_REPLY reply; 350286180Sscottl void *buf; 351286180Sscottl int error, len; 352286180Sscottl 353286180Sscottl bzero(&header, sizeof(header)); 354286180Sscottl error = mps_read_config_page_header(fd, PageType, PageNumber, 355286180Sscottl PageAddress, &header, IOCStatus); 356286180Sscottl if (error) { 357286180Sscottl errno = error; 358286180Sscottl return (NULL); 359286180Sscottl } 360286180Sscottl 361286180Sscottl bzero(&req, sizeof(req)); 362286180Sscottl req.Function = MPI2_FUNCTION_CONFIG; 363286180Sscottl req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 364286180Sscottl req.PageAddress = PageAddress; 365286180Sscottl req.Header = header; 366286180Sscottl req.Header.PageLength = reply.Header.PageLength; 367286180Sscottl if (reply.Header.PageLength == 0) 368286180Sscottl req.Header.PageLength = 4; 369286180Sscottl 370286180Sscottl len = req.Header.PageLength * 4; 371286180Sscottl buf = malloc(len); 372286180Sscottl if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), 373286180Sscottl buf, len, NULL, 0, 30)) { 374286180Sscottl error = errno; 375286180Sscottl free(buf); 376286180Sscottl errno = error; 377286180Sscottl return (NULL); 378286180Sscottl } 379286180Sscottl if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { 380286180Sscottl if (IOCStatus != NULL) 381286180Sscottl *IOCStatus = reply.IOCStatus; 382286180Sscottl else 383286180Sscottl warnx("Reading config page failed: 0x%x %s", 384286180Sscottl reply.IOCStatus, mps_ioc_status(reply.IOCStatus)); 385286180Sscottl free(buf); 386286180Sscottl errno = EIO; 387286180Sscottl return (NULL); 388286180Sscottl } 389286180Sscottl return (buf); 390286180Sscottl} 391286180Sscottl 392286180Sscottlvoid * 393286180Sscottlmps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion, 394286180Sscottl U8 PageNumber, U32 PageAddress, U16 *IOCStatus) 395286180Sscottl{ 396286180Sscottl MPI2_CONFIG_REQUEST req; 397286180Sscottl MPI2_CONFIG_PAGE_HEADER header; 398286180Sscottl MPI2_CONFIG_REPLY reply; 399286180Sscottl U16 pagelen; 400286180Sscottl void *buf; 401286180Sscottl int error, len; 402286180Sscottl 403286180Sscottl if (IOCStatus != NULL) 404286180Sscottl *IOCStatus = MPI2_IOCSTATUS_SUCCESS; 405286180Sscottl bzero(&header, sizeof(header)); 406286180Sscottl error = mps_read_ext_config_page_header(fd, ExtPageType, PageNumber, 407286180Sscottl PageAddress, &header, &pagelen, IOCStatus); 408286180Sscottl if (error) { 409286180Sscottl errno = error; 410286180Sscottl return (NULL); 411286180Sscottl } 412286180Sscottl 413286180Sscottl bzero(&req, sizeof(req)); 414286180Sscottl req.Function = MPI2_FUNCTION_CONFIG; 415286180Sscottl req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 416286180Sscottl req.PageAddress = PageAddress; 417286180Sscottl req.Header = header; 418286180Sscottl if (pagelen == 0) 419286180Sscottl pagelen = 4; 420286180Sscottl req.ExtPageLength = pagelen; 421286180Sscottl req.ExtPageType = ExtPageType; 422286180Sscottl 423286180Sscottl len = pagelen * 4; 424286180Sscottl buf = malloc(len); 425286180Sscottl if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), 426286180Sscottl buf, len, NULL, 0, 30)) { 427286180Sscottl error = errno; 428286180Sscottl free(buf); 429286180Sscottl errno = error; 430286180Sscottl return (NULL); 431286180Sscottl } 432286180Sscottl if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { 433286180Sscottl if (IOCStatus != NULL) 434286180Sscottl *IOCStatus = reply.IOCStatus; 435286180Sscottl else 436286180Sscottl warnx("Reading extended config page failed: %s", 437286180Sscottl mps_ioc_status(reply.IOCStatus)); 438286180Sscottl free(buf); 439286180Sscottl errno = EIO; 440286180Sscottl return (NULL); 441286180Sscottl } 442286180Sscottl return (buf); 443286180Sscottl} 444286180Sscottl 445286180Sscottl#else 446286180Sscottl 447286180Sscottlint 448286180Sscottlmps_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, 449286180Sscottl MPI2_CONFIG_PAGE_HEADER *header, U16 *IOCStatus) 450286180Sscottl{ 451286180Sscottl struct mps_cfg_page_req req; 452286180Sscottl 453286180Sscottl if (IOCStatus != NULL) 454286180Sscottl *IOCStatus = MPI2_IOCSTATUS_SUCCESS; 455286180Sscottl if (header == NULL) 456286180Sscottl return (EINVAL); 457286180Sscottl bzero(&req, sizeof(req)); 458286180Sscottl req.header.PageType = PageType; 459286180Sscottl req.header.PageNumber = PageNumber; 460286180Sscottl req.page_address = PageAddress; 461286180Sscottl if (ioctl(fd, MPSIO_READ_CFG_HEADER, &req) < 0) 462286180Sscottl return (errno); 463286180Sscottl if (!IOC_STATUS_SUCCESS(req.ioc_status)) { 464286180Sscottl if (IOCStatus != NULL) 465286180Sscottl *IOCStatus = req.ioc_status; 466286180Sscottl return (EIO); 467286180Sscottl } 468286180Sscottl bcopy(&req.header, header, sizeof(*header)); 469286180Sscottl return (0); 470286180Sscottl} 471286180Sscottl 472286180Sscottlvoid * 473286180Sscottlmps_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, 474286180Sscottl U16 *IOCStatus) 475286180Sscottl{ 476286180Sscottl struct mps_cfg_page_req req; 477286180Sscottl void *buf; 478286180Sscottl int error; 479286180Sscottl 480286180Sscottl error = mps_read_config_page_header(fd, PageType, PageNumber, 481286180Sscottl PageAddress, &req.header, IOCStatus); 482286180Sscottl if (error) { 483286180Sscottl errno = error; 484286180Sscottl return (NULL); 485286180Sscottl } 486286180Sscottl 487286180Sscottl if (req.header.PageLength == 0) 488286180Sscottl req.header.PageLength = 4; 489286180Sscottl req.len = req.header.PageLength * 4; 490286180Sscottl buf = malloc(req.len); 491286180Sscottl req.buf = buf; 492286180Sscottl bcopy(&req.header, buf, sizeof(req.header)); 493286180Sscottl if (ioctl(fd, MPSIO_READ_CFG_PAGE, &req) < 0) { 494286180Sscottl error = errno; 495286180Sscottl free(buf); 496286180Sscottl errno = error; 497286180Sscottl return (NULL); 498286180Sscottl } 499286180Sscottl if (!IOC_STATUS_SUCCESS(req.ioc_status)) { 500286180Sscottl if (IOCStatus != NULL) 501286180Sscottl *IOCStatus = req.ioc_status; 502286180Sscottl else 503286180Sscottl warnx("Reading config page failed: 0x%x %s", 504286180Sscottl req.ioc_status, mps_ioc_status(req.ioc_status)); 505286180Sscottl free(buf); 506286180Sscottl errno = EIO; 507286180Sscottl return (NULL); 508286180Sscottl } 509286180Sscottl return (buf); 510286180Sscottl} 511286180Sscottl 512286180Sscottlvoid * 513286180Sscottlmps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion, 514286180Sscottl U8 PageNumber, U32 PageAddress, U16 *IOCStatus) 515286180Sscottl{ 516286180Sscottl struct mps_ext_cfg_page_req req; 517286180Sscottl void *buf; 518286180Sscottl int error; 519286180Sscottl 520286180Sscottl if (IOCStatus != NULL) 521286180Sscottl *IOCStatus = MPI2_IOCSTATUS_SUCCESS; 522286180Sscottl bzero(&req, sizeof(req)); 523286180Sscottl req.header.PageVersion = PageVersion; 524286180Sscottl req.header.PageNumber = PageNumber; 525286180Sscottl req.header.ExtPageType = ExtPageType; 526286180Sscottl req.page_address = PageAddress; 527286180Sscottl if (ioctl(fd, MPSIO_READ_EXT_CFG_HEADER, &req) < 0) 528286180Sscottl return (NULL); 529286180Sscottl if (!IOC_STATUS_SUCCESS(req.ioc_status)) { 530286180Sscottl if (IOCStatus != NULL) 531286180Sscottl *IOCStatus = req.ioc_status; 532286180Sscottl else 533286180Sscottl warnx("Reading extended config page header failed: %s", 534286180Sscottl mps_ioc_status(req.ioc_status)); 535286180Sscottl errno = EIO; 536286180Sscottl return (NULL); 537286180Sscottl } 538286180Sscottl req.len = req.header.ExtPageLength * 4; 539286180Sscottl buf = malloc(req.len); 540286180Sscottl req.buf = buf; 541286180Sscottl bcopy(&req.header, buf, sizeof(req.header)); 542286180Sscottl if (ioctl(fd, MPSIO_READ_EXT_CFG_PAGE, &req) < 0) { 543286180Sscottl error = errno; 544286180Sscottl free(buf); 545286180Sscottl errno = error; 546286180Sscottl return (NULL); 547286180Sscottl } 548286180Sscottl if (!IOC_STATUS_SUCCESS(req.ioc_status)) { 549286180Sscottl if (IOCStatus != NULL) 550286180Sscottl *IOCStatus = req.ioc_status; 551286180Sscottl else 552286180Sscottl warnx("Reading extended config page failed: %s", 553286180Sscottl mps_ioc_status(req.ioc_status)); 554286180Sscottl free(buf); 555286180Sscottl errno = EIO; 556286180Sscottl return (NULL); 557286180Sscottl } 558286180Sscottl return (buf); 559286180Sscottl} 560286180Sscottl#endif 561286180Sscottl 562286180Sscottl#if 0 563286180Sscottlint 564286180Sscottlmpt_write_config_page(int fd, void *buf, U16 *IOCStatus) 565286180Sscottl{ 566286180Sscottl CONFIG_PAGE_HEADER *hdr; 567286180Sscottl struct mpt_cfg_page_req req; 568286180Sscottl 569286180Sscottl if (IOCStatus != NULL) 570286180Sscottl *IOCStatus = MPI_IOCSTATUS_SUCCESS; 571286180Sscottl bzero(&req, sizeof(req)); 572286180Sscottl req.buf = buf; 573286180Sscottl hdr = buf; 574286180Sscottl req.len = hdr->PageLength * 4; 575286180Sscottl if (ioctl(fd, MPTIO_WRITE_CFG_PAGE, &req) < 0) 576286180Sscottl return (errno); 577286180Sscottl if (!IOC_STATUS_SUCCESS(req.ioc_status)) { 578286180Sscottl if (IOCStatus != NULL) { 579286180Sscottl *IOCStatus = req.ioc_status; 580286180Sscottl return (0); 581286180Sscottl } 582286180Sscottl warnx("Writing config page failed: %s", 583286180Sscottl mpt_ioc_status(req.ioc_status)); 584286180Sscottl return (EIO); 585286180Sscottl } 586286180Sscottl return (0); 587286180Sscottl} 588286180Sscottl 589286180Sscottlint 590286180Sscottlmpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID, U8 PhysDiskNum, 591286180Sscottl U32 ActionDataWord, void *buf, int len, RAID_VOL0_STATUS *VolumeStatus, 592286180Sscottl U32 *ActionData, int datalen, U16 *IOCStatus, U16 *ActionStatus, int write) 593286180Sscottl{ 594286180Sscottl struct mpt_raid_action raid_act; 595286180Sscottl 596286180Sscottl if (IOCStatus != NULL) 597286180Sscottl *IOCStatus = MPI_IOCSTATUS_SUCCESS; 598286180Sscottl if (datalen < 0 || (unsigned)datalen > sizeof(raid_act.action_data)) 599286180Sscottl return (EINVAL); 600286180Sscottl bzero(&raid_act, sizeof(raid_act)); 601286180Sscottl raid_act.action = Action; 602286180Sscottl raid_act.volume_bus = VolumeBus; 603286180Sscottl raid_act.volume_id = VolumeID; 604286180Sscottl raid_act.phys_disk_num = PhysDiskNum; 605286180Sscottl raid_act.action_data_word = ActionDataWord; 606286180Sscottl if (buf != NULL && len != 0) { 607286180Sscottl raid_act.buf = buf; 608286180Sscottl raid_act.len = len; 609286180Sscottl raid_act.write = write; 610286180Sscottl } 611286180Sscottl 612286180Sscottl if (ioctl(fd, MPTIO_RAID_ACTION, &raid_act) < 0) 613286180Sscottl return (errno); 614286180Sscottl 615286180Sscottl if (!IOC_STATUS_SUCCESS(raid_act.ioc_status)) { 616286180Sscottl if (IOCStatus != NULL) { 617286180Sscottl *IOCStatus = raid_act.ioc_status; 618286180Sscottl return (0); 619286180Sscottl } 620286180Sscottl warnx("RAID action failed: %s", 621286180Sscottl mpt_ioc_status(raid_act.ioc_status)); 622286180Sscottl return (EIO); 623286180Sscottl } 624286180Sscottl 625286180Sscottl if (ActionStatus != NULL) 626286180Sscottl *ActionStatus = raid_act.action_status; 627286180Sscottl if (raid_act.action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS) { 628286180Sscottl if (ActionStatus != NULL) 629286180Sscottl return (0); 630286180Sscottl warnx("RAID action failed: %s", 631286180Sscottl mpt_raid_status(raid_act.action_status)); 632286180Sscottl return (EIO); 633286180Sscottl } 634286180Sscottl 635286180Sscottl if (VolumeStatus != NULL) 636286180Sscottl *((U32 *)VolumeStatus) = raid_act.volume_status; 637286180Sscottl if (ActionData != NULL) 638286180Sscottl bcopy(raid_act.action_data, ActionData, datalen); 639286180Sscottl return (0); 640286180Sscottl} 641286180Sscottl#endif 642286180Sscottl 643286180Sscottlint 644286180Sscottlmps_open(int unit) 645286180Sscottl{ 646286180Sscottl char path[MAXPATHLEN]; 647286180Sscottl 648289364Sbapt snprintf(path, sizeof(path), "/dev/mp%s%d", is_mps ? "s": "r", unit); 649286180Sscottl return (open(path, O_RDWR)); 650286180Sscottl} 651286180Sscottl 652286180Sscottlint 653286180Sscottlmps_user_command(int fd, void *req, uint32_t req_len, void *reply, 654286180Sscottl uint32_t reply_len, void *buffer, int len, uint32_t flags) 655286180Sscottl{ 656286180Sscottl struct mps_usr_command cmd; 657286180Sscottl 658286180Sscottl bzero(&cmd, sizeof(struct mps_usr_command)); 659286180Sscottl cmd.req = req; 660286180Sscottl cmd.req_len = req_len; 661286180Sscottl cmd.rpl = reply; 662286180Sscottl cmd.rpl_len = reply_len; 663286180Sscottl cmd.buf = buffer; 664286180Sscottl cmd.len = len; 665286180Sscottl cmd.flags = flags; 666286180Sscottl 667289366Sbapt if (ioctl(fd, is_mps ? MPSIO_MPS_COMMAND : MPRIO_MPR_COMMAND, &cmd) < 0) 668286180Sscottl return (errno); 669286180Sscottl return (0); 670286180Sscottl} 671286180Sscottl 672286180Sscottlint 673286180Sscottlmps_pass_command(int fd, void *req, uint32_t req_len, void *reply, 674286180Sscottl uint32_t reply_len, void *data_in, uint32_t datain_len, void *data_out, 675286180Sscottl uint32_t dataout_len, uint32_t timeout) 676286180Sscottl{ 677289366Sbapt struct mprs_pass_thru pass; 678286180Sscottl 679286180Sscottl pass.PtrRequest = (uint64_t)(uintptr_t)req; 680286180Sscottl pass.PtrReply = (uint64_t)(uintptr_t)reply; 681286180Sscottl pass.PtrData = (uint64_t)(uintptr_t)data_in; 682286180Sscottl pass.PtrDataOut = (uint64_t)(uintptr_t)data_out; 683286180Sscottl pass.RequestSize = req_len; 684286180Sscottl pass.ReplySize = reply_len; 685286180Sscottl pass.DataSize = datain_len; 686286180Sscottl pass.DataOutSize = dataout_len; 687289366Sbapt if (datain_len && dataout_len) { 688289366Sbapt if (is_mps) { 689289366Sbapt pass.DataDirection = MPS_PASS_THRU_DIRECTION_BOTH; 690289366Sbapt } else { 691289366Sbapt pass.DataDirection = MPR_PASS_THRU_DIRECTION_BOTH; 692289366Sbapt } 693289366Sbapt } else if (datain_len) { 694289366Sbapt if (is_mps) { 695289366Sbapt pass.DataDirection = MPS_PASS_THRU_DIRECTION_READ; 696289366Sbapt } else { 697289366Sbapt pass.DataDirection = MPR_PASS_THRU_DIRECTION_READ; 698289366Sbapt } 699289366Sbapt } else if (dataout_len) { 700289366Sbapt if (is_mps) { 701289366Sbapt pass.DataDirection = MPS_PASS_THRU_DIRECTION_WRITE; 702289366Sbapt } else { 703289366Sbapt pass.DataDirection = MPR_PASS_THRU_DIRECTION_WRITE; 704289366Sbapt } 705289366Sbapt } else { 706289366Sbapt if (is_mps) { 707289366Sbapt pass.DataDirection = MPS_PASS_THRU_DIRECTION_NONE; 708289366Sbapt } else { 709289366Sbapt pass.DataDirection = MPR_PASS_THRU_DIRECTION_NONE; 710289366Sbapt } 711289366Sbapt } 712286180Sscottl pass.Timeout = timeout; 713286180Sscottl 714286180Sscottl if (ioctl(fd, MPTIOCTL_PASS_THRU, &pass) < 0) 715286180Sscottl return (errno); 716286180Sscottl return (0); 717286180Sscottl} 718286180Sscottl 719286180SscottlMPI2_IOC_FACTS_REPLY * 720286180Sscottlmps_get_iocfacts(int fd) 721286180Sscottl{ 722286180Sscottl MPI2_IOC_FACTS_REPLY *facts; 723286180Sscottl MPI2_IOC_FACTS_REQUEST req; 724286180Sscottl int error; 725286180Sscottl 726286180Sscottl facts = malloc(sizeof(MPI2_IOC_FACTS_REPLY)); 727286180Sscottl if (facts == NULL) { 728286180Sscottl errno = ENOMEM; 729286180Sscottl return (NULL); 730286180Sscottl } 731286180Sscottl 732286180Sscottl bzero(&req, sizeof(MPI2_IOC_FACTS_REQUEST)); 733286180Sscottl req.Function = MPI2_FUNCTION_IOC_FACTS; 734286180Sscottl 735286180Sscottl#if 1 736286180Sscottl error = mps_pass_command(fd, &req, sizeof(MPI2_IOC_FACTS_REQUEST), 737286180Sscottl facts, sizeof(MPI2_IOC_FACTS_REPLY), NULL, 0, NULL, 0, 10); 738286180Sscottl#else 739286180Sscottl error = mps_user_command(fd, &req, sizeof(MPI2_IOC_FACTS_REQUEST), 740286180Sscottl facts, sizeof(MPI2_IOC_FACTS_REPLY), NULL, 0, 0); 741286180Sscottl#endif 742286180Sscottl if (error) { 743286180Sscottl free(facts); 744286180Sscottl return (NULL); 745286180Sscottl } 746286180Sscottl 747286180Sscottl if (!IOC_STATUS_SUCCESS(facts->IOCStatus)) { 748286180Sscottl free(facts); 749286180Sscottl errno = EINVAL; 750286180Sscottl return (NULL); 751286180Sscottl } 752286180Sscottl return (facts); 753286180Sscottl} 754286180Sscottl 755