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