1265236Sken/*- 2283990Sslm * Copyright (c) 2011-2015 LSI Corp. 3299962Sslm * Copyright (c) 2013-2016 Avago Technologies 4265236Sken * All rights reserved. 5265236Sken * 6265236Sken * Redistribution and use in source and binary forms, with or without 7265236Sken * modification, are permitted provided that the following conditions 8265236Sken * are met: 9265236Sken * 1. Redistributions of source code must retain the above copyright 10265236Sken * notice, this list of conditions and the following disclaimer. 11265236Sken * 2. Redistributions in binary form must reproduce the above copyright 12265236Sken * notice, this list of conditions and the following disclaimer in the 13265236Sken * documentation and/or other materials provided with the distribution. 14265236Sken * 15265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18265236Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25265236Sken * SUCH DAMAGE. 26265236Sken * 27283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 28265236Sken */ 29265236Sken 30265236Sken#include <sys/cdefs.h> 31265236Sken__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr_config.c 322661 2017-08-18 15:38:08Z ken $"); 32265236Sken 33265236Sken/* TODO Move headers to mprvar */ 34265236Sken#include <sys/types.h> 35265236Sken#include <sys/param.h> 36265236Sken#include <sys/lock.h> 37265236Sken#include <sys/mutex.h> 38265236Sken#include <sys/systm.h> 39265236Sken#include <sys/kernel.h> 40265236Sken#include <sys/malloc.h> 41265236Sken#include <sys/kthread.h> 42265236Sken#include <sys/taskqueue.h> 43265236Sken#include <sys/bus.h> 44265236Sken#include <sys/endian.h> 45265236Sken#include <sys/sysctl.h> 46265236Sken#include <sys/eventhandler.h> 47265236Sken#include <sys/uio.h> 48265236Sken#include <machine/bus.h> 49265236Sken#include <machine/resource.h> 50265236Sken#include <dev/mpr/mpi/mpi2_type.h> 51265236Sken#include <dev/mpr/mpi/mpi2.h> 52265236Sken#include <dev/mpr/mpi/mpi2_ioc.h> 53265236Sken#include <dev/mpr/mpi/mpi2_sas.h> 54319436Sslm#include <dev/mpr/mpi/mpi2_pci.h> 55265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h> 56265236Sken#include <dev/mpr/mpi/mpi2_init.h> 57265236Sken#include <dev/mpr/mpi/mpi2_tool.h> 58265236Sken#include <dev/mpr/mpr_ioctl.h> 59265236Sken#include <dev/mpr/mprvar.h> 60265236Sken 61265236Sken/** 62265236Sken * mpr_config_get_ioc_pg8 - obtain ioc page 8 63265236Sken * @sc: per adapter object 64265236Sken * @mpi_reply: reply mf payload returned from firmware 65265236Sken * @config_page: contents of the config page 66265236Sken * Context: sleep. 67265236Sken * 68265236Sken * Returns 0 for success, non-zero for failure. 69265236Sken */ 70265236Skenint 71265236Skenmpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 72265236Sken Mpi2IOCPage8_t *config_page) 73265236Sken{ 74265236Sken MPI2_CONFIG_REQUEST *request; 75265236Sken MPI2_CONFIG_REPLY *reply; 76265236Sken struct mpr_command *cm; 77265236Sken MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 78265236Sken int error = 0; 79265236Sken u16 ioc_status; 80265236Sken 81265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 82265236Sken 83265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 84265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 85265236Sken __LINE__); 86265236Sken error = EBUSY; 87265236Sken goto out; 88265236Sken } 89265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 90265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 91265236Sken request->Function = MPI2_FUNCTION_CONFIG; 92265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 93265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 94265236Sken request->Header.PageNumber = 8; 95319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 96265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 97265236Sken cm->cm_data = NULL; 98322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 99322661Sken if (cm != NULL) 100322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 101265236Sken if (error || (reply == NULL)) { 102265236Sken /* FIXME */ 103265236Sken /* 104265236Sken * If the request returns an error then we need to do a diag 105265236Sken * reset 106265236Sken */ 107265236Sken printf("%s: request for header completed with error %d", 108265236Sken __func__, error); 109265236Sken error = ENXIO; 110265236Sken goto out; 111265236Sken } 112265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 113265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 114265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 115265236Sken /* FIXME */ 116265236Sken /* 117265236Sken * If the request returns an error then we need to do a diag 118265236Sken * reset 119265236Sken */ 120265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 121265236Sken __func__, ioc_status); 122265236Sken error = ENXIO; 123265236Sken goto out; 124265236Sken } 125265236Sken /* We have to do free and alloc for the reply-free and reply-post 126265236Sken * counters to match - Need to review the reply FIFO handling. 127265236Sken */ 128265236Sken mpr_free_command(sc, cm); 129265236Sken 130265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 131265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 132265236Sken __LINE__); 133265236Sken error = EBUSY; 134265236Sken goto out; 135265236Sken } 136265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 137265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 138265236Sken request->Function = MPI2_FUNCTION_CONFIG; 139265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 140265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 141265236Sken request->Header.PageNumber = 8; 142319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 143265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 144265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 145265236Sken cm->cm_sge = &request->PageBufferSGE; 146265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 147265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 148265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 149265236Sken page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 150265236Sken if (!page) { 151265236Sken printf("%s: page alloc failed\n", __func__); 152265236Sken error = ENOMEM; 153265236Sken goto out; 154265236Sken } 155265236Sken cm->cm_data = page; 156265236Sken 157322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 158322661Sken if (cm != NULL) 159322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 160265236Sken if (error || (reply == NULL)) { 161265236Sken /* FIXME */ 162265236Sken /* 163265236Sken * If the request returns an error then we need to do a diag 164265236Sken * reset 165265236Sken */ 166265236Sken printf("%s: request for page completed with error %d", 167265236Sken __func__, error); 168265236Sken error = ENXIO; 169265236Sken goto out; 170265236Sken } 171265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 172265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 173265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 174265236Sken /* FIXME */ 175265236Sken /* 176265236Sken * If the request returns an error then we need to do a diag 177265236Sken * reset 178265236Sken */ 179265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 180265236Sken __func__, ioc_status); 181265236Sken error = ENXIO; 182265236Sken goto out; 183265236Sken } 184265236Sken bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 185265236Sken 186265236Skenout: 187265236Sken free(page, M_MPR); 188265236Sken if (cm) 189265236Sken mpr_free_command(sc, cm); 190265236Sken return (error); 191265236Sken} 192265236Sken 193265236Sken/** 194265236Sken * mpr_config_get_iounit_pg8 - obtain iounit page 8 195265236Sken * @sc: per adapter object 196265236Sken * @mpi_reply: reply mf payload returned from firmware 197265236Sken * @config_page: contents of the config page 198265236Sken * Context: sleep. 199265236Sken * 200265236Sken * Returns 0 for success, non-zero for failure. 201265236Sken */ 202265236Skenint 203265236Skenmpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 204265236Sken Mpi2IOUnitPage8_t *config_page) 205265236Sken{ 206265236Sken MPI2_CONFIG_REQUEST *request; 207265236Sken MPI2_CONFIG_REPLY *reply; 208265236Sken struct mpr_command *cm; 209265236Sken MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL; 210265236Sken int error = 0; 211265236Sken u16 ioc_status; 212265236Sken 213265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 214265236Sken 215265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 216265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 217265236Sken __LINE__); 218265236Sken error = EBUSY; 219265236Sken goto out; 220265236Sken } 221265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 222265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 223265236Sken request->Function = MPI2_FUNCTION_CONFIG; 224265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 225265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 226265236Sken request->Header.PageNumber = 8; 227319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 228265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 229265236Sken cm->cm_data = NULL; 230322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 231322661Sken if (cm != NULL) 232322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 233265236Sken if (error || (reply == NULL)) { 234265236Sken /* FIXME */ 235265236Sken /* 236265236Sken * If the request returns an error then we need to do a diag 237265236Sken * reset 238265236Sken */ 239265236Sken printf("%s: request for header completed with error %d", 240265236Sken __func__, error); 241265236Sken error = ENXIO; 242265236Sken goto out; 243265236Sken } 244265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 245265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 246265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 247265236Sken /* FIXME */ 248265236Sken /* 249265236Sken * If the request returns an error then we need to do a diag 250265236Sken * reset 251265236Sken */ 252265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 253265236Sken __func__, ioc_status); 254265236Sken error = ENXIO; 255265236Sken goto out; 256265236Sken } 257265236Sken /* We have to do free and alloc for the reply-free and reply-post 258265236Sken * counters to match - Need to review the reply FIFO handling. 259265236Sken */ 260265236Sken mpr_free_command(sc, cm); 261265236Sken 262265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 263265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 264265236Sken __LINE__); 265265236Sken error = EBUSY; 266265236Sken goto out; 267265236Sken } 268265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 269265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 270265236Sken request->Function = MPI2_FUNCTION_CONFIG; 271265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 272265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 273265236Sken request->Header.PageNumber = 8; 274319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 275265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 276265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 277265236Sken cm->cm_sge = &request->PageBufferSGE; 278265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 279265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 280265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 281265236Sken page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 282265236Sken if (!page) { 283265236Sken printf("%s: page alloc failed\n", __func__); 284265236Sken error = ENOMEM; 285265236Sken goto out; 286265236Sken } 287265236Sken cm->cm_data = page; 288265236Sken 289322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 290322661Sken if (cm != NULL) 291322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 292265236Sken if (error || (reply == NULL)) { 293265236Sken /* FIXME */ 294265236Sken /* 295265236Sken * If the request returns an error then we need to do a diag 296265236Sken * reset 297265236Sken */ 298265236Sken printf("%s: request for page completed with error %d", 299265236Sken __func__, error); 300265236Sken error = ENXIO; 301265236Sken goto out; 302265236Sken } 303265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 304265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 305265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 306265236Sken /* FIXME */ 307265236Sken /* 308265236Sken * If the request returns an error then we need to do a diag 309265236Sken * reset 310265236Sken */ 311265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 312265236Sken __func__, ioc_status); 313265236Sken error = ENXIO; 314265236Sken goto out; 315265236Sken } 316265236Sken bcopy(page, config_page, MIN(cm->cm_length, 317265236Sken (sizeof(Mpi2IOUnitPage8_t)))); 318265236Sken 319265236Skenout: 320265236Sken free(page, M_MPR); 321265236Sken if (cm) 322265236Sken mpr_free_command(sc, cm); 323265236Sken return (error); 324265236Sken} 325265236Sken 326265236Sken/** 327265236Sken * mpr_base_static_config_pages - static start of day config pages. 328265236Sken * @sc: per adapter object 329265236Sken * 330265236Sken * Return nothing. 331265236Sken */ 332265236Skenvoid 333265236Skenmpr_base_static_config_pages(struct mpr_softc *sc) 334265236Sken{ 335265236Sken Mpi2ConfigReply_t mpi_reply; 336265236Sken int retry; 337265236Sken 338265236Sken retry = 0; 339265236Sken while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 340265236Sken retry++; 341265236Sken if (retry > 5) { 342265236Sken /* We need to Handle this situation */ 343265236Sken /*FIXME*/ 344265236Sken break; 345265236Sken } 346265236Sken } 347265236Sken retry = 0; 348265236Sken while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) { 349265236Sken retry++; 350265236Sken if (retry > 5) { 351265236Sken /* We need to Handle this situation */ 352265236Sken /*FIXME*/ 353265236Sken break; 354265236Sken } 355265236Sken } 356265236Sken} 357265236Sken 358265236Sken/** 359265236Sken * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0 360265236Sken * @sc: per adapter object 361265236Sken * @mpi_reply: reply mf payload returned from firmware 362265236Sken * @config_page: contents of the config page 363265236Sken * @sz: size of buffer passed in config_page 364265236Sken * Context: sleep. 365265236Sken * 366265236Sken * Returns 0 for success, non-zero for failure. 367265236Sken */ 368265236Skenint 369265236Skenmpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 370265236Sken Mpi2DriverMappingPage0_t *config_page, u16 sz) 371265236Sken{ 372265236Sken MPI2_CONFIG_REQUEST *request; 373265236Sken MPI2_CONFIG_REPLY *reply; 374265236Sken struct mpr_command *cm; 375265236Sken Mpi2DriverMappingPage0_t *page = NULL; 376265236Sken int error = 0; 377265236Sken u16 ioc_status; 378265236Sken 379265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 380265236Sken 381265236Sken memset(config_page, 0, sz); 382265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 383265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 384265236Sken __LINE__); 385265236Sken error = EBUSY; 386265236Sken goto out; 387265236Sken } 388265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 389265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 390265236Sken request->Function = MPI2_FUNCTION_CONFIG; 391265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 392265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 393265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 394265236Sken request->Header.PageNumber = 0; 395319436Sslm request->ExtPageLength = request->Header.PageVersion = 0; 396265236Sken request->PageAddress = sc->max_dpm_entries << 397265236Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 398265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 399265236Sken cm->cm_data = NULL; 400322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 401322661Sken if (cm != NULL) 402322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 403265236Sken if (error || (reply == NULL)) { 404265236Sken /* FIXME */ 405265236Sken /* 406265236Sken * If the request returns an error then we need to do a diag 407265236Sken * reset 408265236Sken */ 409265236Sken printf("%s: request for header completed with error %d", 410265236Sken __func__, error); 411265236Sken error = ENXIO; 412265236Sken goto out; 413265236Sken } 414265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 415265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 416265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 417265236Sken /* FIXME */ 418265236Sken /* 419265236Sken * If the request returns an error then we need to do a diag 420265236Sken * reset 421265236Sken */ 422265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 423265236Sken __func__, ioc_status); 424265236Sken error = ENXIO; 425265236Sken goto out; 426265236Sken } 427265236Sken /* We have to do free and alloc for the reply-free and reply-post 428265236Sken * counters to match - Need to review the reply FIFO handling. 429265236Sken */ 430265236Sken mpr_free_command(sc, cm); 431265236Sken 432265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 433265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 434265236Sken __LINE__); 435265236Sken error = EBUSY; 436265236Sken goto out; 437265236Sken } 438265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 439265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 440265236Sken request->Function = MPI2_FUNCTION_CONFIG; 441265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 442265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 443265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 444265236Sken request->Header.PageNumber = 0; 445319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 446265236Sken request->PageAddress = sc->max_dpm_entries << 447265236Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 448265236Sken request->ExtPageLength = mpi_reply->ExtPageLength; 449265236Sken cm->cm_length = le16toh(request->ExtPageLength) * 4; 450265236Sken cm->cm_sge = &request->PageBufferSGE; 451265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 452265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 453265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 454265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT); 455265236Sken if (!page) { 456265236Sken printf("%s: page alloc failed\n", __func__); 457265236Sken error = ENOMEM; 458265236Sken goto out; 459265236Sken } 460265236Sken cm->cm_data = page; 461322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 462322661Sken if (cm != NULL) 463322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 464265236Sken if (error || (reply == NULL)) { 465265236Sken /* FIXME */ 466265236Sken /* 467265236Sken * If the request returns an error then we need to do a diag 468265236Sken * reset 469265236Sken */ 470265236Sken printf("%s: request for page completed with error %d", 471265236Sken __func__, error); 472265236Sken error = ENXIO; 473265236Sken goto out; 474265236Sken } 475265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 476265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 477265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 478265236Sken /* FIXME */ 479265236Sken /* 480265236Sken * If the request returns an error then we need to do a diag 481265236Sken * reset 482265236Sken */ 483265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 484265236Sken __func__, ioc_status); 485265236Sken error = ENXIO; 486265236Sken goto out; 487265236Sken } 488265236Sken bcopy(page, config_page, MIN(cm->cm_length, sz)); 489265236Skenout: 490265236Sken free(page, M_MPR); 491265236Sken if (cm) 492265236Sken mpr_free_command(sc, cm); 493265236Sken return (error); 494265236Sken} 495265236Sken 496265236Sken/** 497265236Sken * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 498265236Sken * @sc: per adapter object 499265236Sken * @mpi_reply: reply mf payload returned from firmware 500265236Sken * @config_page: contents of the config page 501265236Sken * @entry_idx: entry index in DPM Page0 to be modified 502265236Sken * Context: sleep. 503265236Sken * 504265236Sken * Returns 0 for success, non-zero for failure. 505265236Sken */ 506265236Sken 507265236Skenint mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 508265236Sken Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 509265236Sken{ 510265236Sken MPI2_CONFIG_REQUEST *request; 511265236Sken MPI2_CONFIG_REPLY *reply; 512265236Sken struct mpr_command *cm; 513265236Sken MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 514265236Sken int error = 0; 515265236Sken u16 ioc_status; 516265236Sken 517265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 518265236Sken 519265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 520265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 521265236Sken __LINE__); 522265236Sken error = EBUSY; 523265236Sken goto out; 524265236Sken } 525265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 526265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 527265236Sken request->Function = MPI2_FUNCTION_CONFIG; 528265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 529265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 530265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 531265236Sken request->Header.PageNumber = 0; 532319436Sslm request->ExtPageLength = request->Header.PageVersion = 0; 533265236Sken /* We can remove below two lines ????*/ 534265236Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 535265236Sken request->PageAddress |= htole16(entry_idx); 536265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 537265236Sken cm->cm_data = NULL; 538322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 539322661Sken if (cm != NULL) 540322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 541265236Sken if (error || (reply == NULL)) { 542265236Sken /* FIXME */ 543265236Sken /* 544265236Sken * If the request returns an error then we need to do a diag 545265236Sken * reset 546265236Sken */ 547265236Sken printf("%s: request for header completed with error %d", 548265236Sken __func__, error); 549265236Sken error = ENXIO; 550265236Sken goto out; 551265236Sken } 552265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 553265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 554265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 555265236Sken /* FIXME */ 556265236Sken /* 557265236Sken * If the request returns an error then we need to do a diag 558265236Sken * reset 559265236Sken */ 560265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 561265236Sken __func__, ioc_status); 562265236Sken error = ENXIO; 563265236Sken goto out; 564265236Sken } 565265236Sken /* We have to do free and alloc for the reply-free and reply-post 566265236Sken * counters to match - Need to review the reply FIFO handling. 567265236Sken */ 568265236Sken mpr_free_command(sc, cm); 569265236Sken 570265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 571265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 572265236Sken __LINE__); 573265236Sken error = EBUSY; 574265236Sken goto out; 575265236Sken } 576265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 577265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 578265236Sken request->Function = MPI2_FUNCTION_CONFIG; 579265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 580265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 581265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 582265236Sken request->Header.PageNumber = 0; 583319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 584265236Sken request->ExtPageLength = mpi_reply->ExtPageLength; 585265236Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 586265236Sken request->PageAddress |= htole16(entry_idx); 587265236Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 588265236Sken cm->cm_sge = &request->PageBufferSGE; 589265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 590265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT; 591265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 592265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 593265236Sken if (!page) { 594265236Sken printf("%s: page alloc failed\n", __func__); 595265236Sken error = ENOMEM; 596265236Sken goto out; 597265236Sken } 598265236Sken bcopy(config_page, page, MIN(cm->cm_length, 599265236Sken (sizeof(Mpi2DriverMappingPage0_t)))); 600265236Sken cm->cm_data = page; 601322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 602322661Sken if (cm != NULL) 603322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 604265236Sken if (error || (reply == NULL)) { 605265236Sken /* FIXME */ 606265236Sken /* 607265236Sken * If the request returns an error then we need to do a diag 608265236Sken * reset 609265236Sken */ 610265236Sken printf("%s: request to write page completed with error %d", 611265236Sken __func__, error); 612265236Sken error = ENXIO; 613265236Sken goto out; 614265236Sken } 615265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 616265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 617265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 618265236Sken /* FIXME */ 619265236Sken /* 620265236Sken * If the request returns an error then we need to do a diag 621265236Sken * reset 622265236Sken */ 623265236Sken printf("%s: page written with error; iocstatus = 0x%x\n", 624265236Sken __func__, ioc_status); 625265236Sken error = ENXIO; 626265236Sken goto out; 627265236Sken } 628265236Skenout: 629265236Sken free(page, M_MPR); 630265236Sken if (cm) 631265236Sken mpr_free_command(sc, cm); 632265236Sken return (error); 633265236Sken} 634265236Sken 635265236Sken/** 636265236Sken * mpr_config_get_sas_device_pg0 - obtain sas device page 0 637265236Sken * @sc: per adapter object 638265236Sken * @mpi_reply: reply mf payload returned from firmware 639265236Sken * @config_page: contents of the config page 640265236Sken * @form: GET_NEXT_HANDLE or HANDLE 641265236Sken * @handle: device handle 642265236Sken * Context: sleep. 643265236Sken * 644265236Sken * Returns 0 for success, non-zero for failure. 645265236Sken */ 646265236Skenint 647265236Skenmpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 648265236Sken *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 649265236Sken{ 650265236Sken MPI2_CONFIG_REQUEST *request; 651265236Sken MPI2_CONFIG_REPLY *reply; 652265236Sken struct mpr_command *cm; 653265236Sken Mpi2SasDevicePage0_t *page = NULL; 654265236Sken int error = 0; 655265236Sken u16 ioc_status; 656265236Sken 657265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 658265236Sken 659265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 660265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 661265236Sken __LINE__); 662265236Sken error = EBUSY; 663265236Sken goto out; 664265236Sken } 665265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 666265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 667265236Sken request->Function = MPI2_FUNCTION_CONFIG; 668265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 669265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 670265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 671265236Sken request->Header.PageNumber = 0; 672319436Sslm request->ExtPageLength = request->Header.PageVersion = 0; 673265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 674265236Sken cm->cm_data = NULL; 675322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 676322661Sken if (cm != NULL) 677322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 678265236Sken if (error || (reply == NULL)) { 679265236Sken /* FIXME */ 680265236Sken /* 681265236Sken * If the request returns an error then we need to do a diag 682265236Sken * reset 683265236Sken */ 684265236Sken printf("%s: request for header completed with error %d", 685265236Sken __func__, error); 686265236Sken error = ENXIO; 687265236Sken goto out; 688265236Sken } 689265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 690265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 691265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 692265236Sken /* FIXME */ 693265236Sken /* 694265236Sken * If the request returns an error then we need to do a diag 695265236Sken * reset 696265236Sken */ 697265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 698265236Sken __func__, ioc_status); 699265236Sken error = ENXIO; 700265236Sken goto out; 701265236Sken } 702265236Sken /* We have to do free and alloc for the reply-free and reply-post 703265236Sken * counters to match - Need to review the reply FIFO handling. 704265236Sken */ 705265236Sken mpr_free_command(sc, cm); 706265236Sken 707265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 708265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 709265236Sken __LINE__); 710265236Sken error = EBUSY; 711265236Sken goto out; 712265236Sken } 713265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 714265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 715265236Sken request->Function = MPI2_FUNCTION_CONFIG; 716265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 717265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 718265236Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 719265236Sken request->Header.PageNumber = 0; 720319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 721265236Sken request->ExtPageLength = mpi_reply->ExtPageLength; 722265236Sken request->PageAddress = htole32(form | handle); 723265236Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 724265236Sken cm->cm_sge = &request->PageBufferSGE; 725265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 726265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 727265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 728265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 729265236Sken if (!page) { 730265236Sken printf("%s: page alloc failed\n", __func__); 731265236Sken error = ENOMEM; 732265236Sken goto out; 733265236Sken } 734265236Sken cm->cm_data = page; 735265236Sken 736322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 737322661Sken if (cm != NULL) 738322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 739265236Sken if (error || (reply == NULL)) { 740265236Sken /* FIXME */ 741265236Sken /* 742265236Sken * If the request returns an error then we need to do a diag 743265236Sken * reset 744265236Sken */ 745265236Sken printf("%s: request for page completed with error %d", 746265236Sken __func__, error); 747265236Sken error = ENXIO; 748265236Sken goto out; 749265236Sken } 750265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 751265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 752265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 753265236Sken /* FIXME */ 754265236Sken /* 755265236Sken * If the request returns an error then we need to do a diag 756265236Sken * reset 757265236Sken */ 758265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 759265236Sken __func__, ioc_status); 760265236Sken error = ENXIO; 761265236Sken goto out; 762265236Sken } 763265236Sken bcopy(page, config_page, MIN(cm->cm_length, 764265236Sken sizeof(Mpi2SasDevicePage0_t))); 765265236Skenout: 766265236Sken free(page, M_MPR); 767265236Sken if (cm) 768265236Sken mpr_free_command(sc, cm); 769265236Sken return (error); 770265236Sken} 771265236Sken 772265236Sken/** 773319436Sslm * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0 774319436Sslm * @sc: per adapter object 775319436Sslm * @mpi_reply: reply mf payload returned from firmware 776319436Sslm * @config_page: contents of the config page 777319436Sslm * @form: GET_NEXT_HANDLE or HANDLE 778319436Sslm * @handle: device handle 779319436Sslm * Context: sleep. 780319436Sslm * 781319436Sslm * Returns 0 for success, non-zero for failure. 782319436Sslm */ 783319436Sslmint 784319436Sslmmpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 785319436Sslm *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle) 786319436Sslm{ 787319436Sslm MPI2_CONFIG_REQUEST *request; 788319436Sslm MPI2_CONFIG_REPLY *reply; 789319436Sslm struct mpr_command *cm; 790319436Sslm Mpi26PCIeDevicePage0_t *page = NULL; 791319436Sslm int error = 0; 792319436Sslm u16 ioc_status; 793319436Sslm 794319436Sslm mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 795319436Sslm 796319436Sslm if ((cm = mpr_alloc_command(sc)) == NULL) { 797319436Sslm printf("%s: command alloc failed @ line %d\n", __func__, 798319436Sslm __LINE__); 799319436Sslm error = EBUSY; 800319436Sslm goto out; 801319436Sslm } 802319436Sslm request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 803319436Sslm bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 804319436Sslm request->Function = MPI2_FUNCTION_CONFIG; 805319436Sslm request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 806319436Sslm request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 807319436Sslm request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 808319436Sslm request->Header.PageNumber = 0; 809319436Sslm request->ExtPageLength = request->Header.PageVersion = 0; 810319436Sslm cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 811319436Sslm cm->cm_data = NULL; 812322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 813322661Sken if (cm != NULL) 814322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 815319436Sslm if (error || (reply == NULL)) { 816319436Sslm /* FIXME */ 817319436Sslm /* 818319436Sslm * If the request returns an error then we need to do a diag 819319436Sslm * reset 820319436Sslm */ 821319436Sslm printf("%s: request for header completed with error %d", 822319436Sslm __func__, error); 823319436Sslm error = ENXIO; 824319436Sslm goto out; 825319436Sslm } 826319436Sslm ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 827319436Sslm bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 828319436Sslm if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 829319436Sslm /* FIXME */ 830319436Sslm /* 831319436Sslm * If the request returns an error then we need to do a diag 832319436Sslm * reset 833319436Sslm */ 834319436Sslm printf("%s: header read with error; iocstatus = 0x%x\n", 835319436Sslm __func__, ioc_status); 836319436Sslm error = ENXIO; 837319436Sslm goto out; 838319436Sslm } 839319436Sslm /* We have to do free and alloc for the reply-free and reply-post 840319436Sslm * counters to match - Need to review the reply FIFO handling. 841319436Sslm */ 842319436Sslm mpr_free_command(sc, cm); 843319436Sslm 844319436Sslm if ((cm = mpr_alloc_command(sc)) == NULL) { 845319436Sslm printf("%s: command alloc failed @ line %d\n", __func__, 846319436Sslm __LINE__); 847319436Sslm error = EBUSY; 848319436Sslm goto out; 849319436Sslm } 850319436Sslm request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 851319436Sslm bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 852319436Sslm request->Function = MPI2_FUNCTION_CONFIG; 853319436Sslm request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 854319436Sslm request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 855319436Sslm request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 856319436Sslm request->Header.PageNumber = 0; 857319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 858319436Sslm request->ExtPageLength = mpi_reply->ExtPageLength; 859319436Sslm request->PageAddress = htole32(form | handle); 860319436Sslm cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 861319436Sslm cm->cm_sge = &request->PageBufferSGE; 862319436Sslm cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 863319436Sslm cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 864319436Sslm cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 865319436Sslm page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 866319436Sslm if (!page) { 867319436Sslm printf("%s: page alloc failed\n", __func__); 868319436Sslm error = ENOMEM; 869319436Sslm goto out; 870319436Sslm } 871319436Sslm cm->cm_data = page; 872319436Sslm 873322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 874322661Sken if (cm != NULL) 875322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 876319436Sslm if (error || (reply == NULL)) { 877319436Sslm /* FIXME */ 878319436Sslm /* 879319436Sslm * If the request returns an error then we need to do a diag 880319436Sslm * reset 881319436Sslm */ 882319436Sslm printf("%s: request for page completed with error %d", 883319436Sslm __func__, error); 884319436Sslm error = ENXIO; 885319436Sslm goto out; 886319436Sslm } 887319436Sslm ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 888319436Sslm bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 889319436Sslm if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 890319436Sslm /* FIXME */ 891319436Sslm /* 892319436Sslm * If the request returns an error then we need to do a diag 893319436Sslm * reset 894319436Sslm */ 895319436Sslm printf("%s: page read with error; iocstatus = 0x%x\n", 896319436Sslm __func__, ioc_status); 897319436Sslm error = ENXIO; 898319436Sslm goto out; 899319436Sslm } 900319436Sslm bcopy(page, config_page, MIN(cm->cm_length, 901319436Sslm sizeof(Mpi26PCIeDevicePage0_t))); 902319436Sslmout: 903319436Sslm free(page, M_MPR); 904319436Sslm if (cm) 905319436Sslm mpr_free_command(sc, cm); 906319436Sslm return (error); 907319436Sslm} 908319436Sslm 909319436Sslm/** 910319436Sslm * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2 911319436Sslm * @sc: per adapter object 912319436Sslm * @mpi_reply: reply mf payload returned from firmware 913319436Sslm * @config_page: contents of the config page 914319436Sslm * @form: GET_NEXT_HANDLE or HANDLE 915319436Sslm * @handle: device handle 916319436Sslm * Context: sleep. 917319436Sslm * 918319436Sslm * Returns 0 for success, non-zero for failure. 919319436Sslm */ 920319436Sslmint 921319436Sslmmpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t 922319436Sslm *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle) 923319436Sslm{ 924319436Sslm MPI2_CONFIG_REQUEST *request; 925319436Sslm MPI2_CONFIG_REPLY *reply; 926319436Sslm struct mpr_command *cm; 927319436Sslm Mpi26PCIeDevicePage2_t *page = NULL; 928319436Sslm int error = 0; 929319436Sslm u16 ioc_status; 930319436Sslm 931319436Sslm mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 932319436Sslm 933319436Sslm if ((cm = mpr_alloc_command(sc)) == NULL) { 934319436Sslm printf("%s: command alloc failed @ line %d\n", __func__, 935319436Sslm __LINE__); 936319436Sslm error = EBUSY; 937319436Sslm goto out; 938319436Sslm } 939319436Sslm request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 940319436Sslm bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 941319436Sslm request->Function = MPI2_FUNCTION_CONFIG; 942319436Sslm request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 943319436Sslm request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 944319436Sslm request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 945319436Sslm request->Header.PageNumber = 2; 946319436Sslm request->ExtPageLength = request->Header.PageVersion = 0; 947319436Sslm cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 948319436Sslm cm->cm_data = NULL; 949322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 950322661Sken if (cm != NULL) 951322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 952319436Sslm if (error || (reply == NULL)) { 953319436Sslm /* FIXME */ 954319436Sslm /* 955319436Sslm * If the request returns an error then we need to do a diag 956319436Sslm * reset 957319436Sslm */ 958319436Sslm printf("%s: request for header completed with error %d", 959319436Sslm __func__, error); 960319436Sslm error = ENXIO; 961319436Sslm goto out; 962319436Sslm } 963319436Sslm ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 964319436Sslm bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 965319436Sslm if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 966319436Sslm /* FIXME */ 967319436Sslm /* 968319436Sslm * If the request returns an error then we need to do a diag 969319436Sslm * reset 970319436Sslm */ 971319436Sslm printf("%s: header read with error; iocstatus = 0x%x\n", 972319436Sslm __func__, ioc_status); 973319436Sslm error = ENXIO; 974319436Sslm goto out; 975319436Sslm } 976319436Sslm /* We have to do free and alloc for the reply-free and reply-post 977319436Sslm * counters to match - Need to review the reply FIFO handling. 978319436Sslm */ 979319436Sslm mpr_free_command(sc, cm); 980319436Sslm 981319436Sslm if ((cm = mpr_alloc_command(sc)) == NULL) { 982319436Sslm printf("%s: command alloc failed @ line %d\n", __func__, 983319436Sslm __LINE__); 984319436Sslm error = EBUSY; 985319436Sslm goto out; 986319436Sslm } 987319436Sslm request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 988319436Sslm bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 989319436Sslm request->Function = MPI2_FUNCTION_CONFIG; 990319436Sslm request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 991319436Sslm request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 992319436Sslm request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 993319436Sslm request->Header.PageNumber = 2; 994319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 995319436Sslm request->ExtPageLength = mpi_reply->ExtPageLength; 996319436Sslm request->PageAddress = htole32(form | handle); 997319436Sslm cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 998319436Sslm cm->cm_sge = &request->PageBufferSGE; 999319436Sslm cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1000319436Sslm cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1001319436Sslm cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1002319436Sslm page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1003319436Sslm if (!page) { 1004319436Sslm printf("%s: page alloc failed\n", __func__); 1005319436Sslm error = ENOMEM; 1006319436Sslm goto out; 1007319436Sslm } 1008319436Sslm cm->cm_data = page; 1009319436Sslm 1010322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1011322661Sken if (cm != NULL) 1012322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1013319436Sslm if (error || (reply == NULL)) { 1014319436Sslm /* FIXME */ 1015319436Sslm /* 1016319436Sslm * If the request returns an error then we need to do a diag 1017319436Sslm * reset 1018319436Sslm */ 1019319436Sslm printf("%s: request for page completed with error %d", 1020319436Sslm __func__, error); 1021319436Sslm error = ENXIO; 1022319436Sslm goto out; 1023319436Sslm } 1024319436Sslm ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1025319436Sslm bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1026319436Sslm if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1027319436Sslm /* FIXME */ 1028319436Sslm /* 1029319436Sslm * If the request returns an error then we need to do a diag 1030319436Sslm * reset 1031319436Sslm */ 1032319436Sslm printf("%s: page read with error; iocstatus = 0x%x\n", 1033319436Sslm __func__, ioc_status); 1034319436Sslm error = ENXIO; 1035319436Sslm goto out; 1036319436Sslm } 1037319436Sslm bcopy(page, config_page, MIN(cm->cm_length, 1038319436Sslm sizeof(Mpi26PCIeDevicePage2_t))); 1039319436Sslmout: 1040319436Sslm free(page, M_MPR); 1041319436Sslm if (cm) 1042319436Sslm mpr_free_command(sc, cm); 1043319436Sslm return (error); 1044319436Sslm} 1045319436Sslm 1046319436Sslm/** 1047265236Sken * mpr_config_get_bios_pg3 - obtain BIOS page 3 1048265236Sken * @sc: per adapter object 1049265236Sken * @mpi_reply: reply mf payload returned from firmware 1050265236Sken * @config_page: contents of the config page 1051265236Sken * Context: sleep. 1052265236Sken * 1053265236Sken * Returns 0 for success, non-zero for failure. 1054265236Sken */ 1055265236Skenint 1056265236Skenmpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1057265236Sken Mpi2BiosPage3_t *config_page) 1058265236Sken{ 1059265236Sken MPI2_CONFIG_REQUEST *request; 1060265236Sken MPI2_CONFIG_REPLY *reply; 1061265236Sken struct mpr_command *cm; 1062265236Sken Mpi2BiosPage3_t *page = NULL; 1063265236Sken int error = 0; 1064265236Sken u16 ioc_status; 1065265236Sken 1066265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1067265236Sken 1068265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1069265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1070265236Sken __LINE__); 1071265236Sken error = EBUSY; 1072265236Sken goto out; 1073265236Sken } 1074265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1075265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1076265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1077265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1078265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1079265236Sken request->Header.PageNumber = 3; 1080319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 1081265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1082265236Sken cm->cm_data = NULL; 1083322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1084322661Sken if (cm != NULL) 1085322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1086265236Sken if (error || (reply == NULL)) { 1087265236Sken /* FIXME */ 1088265236Sken /* 1089265236Sken * If the request returns an error then we need to do a diag 1090265236Sken * reset 1091265236Sken */ 1092265236Sken printf("%s: request for header completed with error %d", 1093265236Sken __func__, error); 1094265236Sken error = ENXIO; 1095265236Sken goto out; 1096265236Sken } 1097265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1098265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1099265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1100265236Sken /* FIXME */ 1101265236Sken /* 1102265236Sken * If the request returns an error then we need to do a diag 1103265236Sken * reset 1104265236Sken */ 1105265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1106265236Sken __func__, ioc_status); 1107265236Sken error = ENXIO; 1108265236Sken goto out; 1109265236Sken } 1110265236Sken /* We have to do free and alloc for the reply-free and reply-post 1111265236Sken * counters to match - Need to review the reply FIFO handling. 1112265236Sken */ 1113265236Sken mpr_free_command(sc, cm); 1114265236Sken 1115265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1116265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1117265236Sken __LINE__); 1118265236Sken error = EBUSY; 1119265236Sken goto out; 1120265236Sken } 1121265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1122265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1123265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1124265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1125265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1126265236Sken request->Header.PageNumber = 3; 1127319436Sslm request->Header.PageVersion = mpi_reply->Header.PageVersion; 1128265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1129265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1130265236Sken cm->cm_sge = &request->PageBufferSGE; 1131265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1132265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1133265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1134265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1135265236Sken if (!page) { 1136265236Sken printf("%s: page alloc failed\n", __func__); 1137265236Sken error = ENOMEM; 1138265236Sken goto out; 1139265236Sken } 1140265236Sken cm->cm_data = page; 1141265236Sken 1142322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1143322661Sken if (cm != NULL) 1144322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1145265236Sken if (error || (reply == NULL)) { 1146265236Sken /* FIXME */ 1147265236Sken /* 1148265236Sken * If the request returns an error then we need to do a diag 1149265236Sken * reset 1150265236Sken */ 1151265236Sken printf("%s: request for page completed with error %d", 1152265236Sken __func__, error); 1153265236Sken error = ENXIO; 1154265236Sken goto out; 1155265236Sken } 1156265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1157265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1158265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1159265236Sken /* FIXME */ 1160265236Sken /* 1161265236Sken * If the request returns an error then we need to do a diag 1162265236Sken * reset 1163265236Sken */ 1164265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1165265236Sken __func__, ioc_status); 1166265236Sken error = ENXIO; 1167265236Sken goto out; 1168265236Sken } 1169265236Sken bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1170265236Skenout: 1171265236Sken free(page, M_MPR); 1172265236Sken if (cm) 1173265236Sken mpr_free_command(sc, cm); 1174265236Sken return (error); 1175265236Sken} 1176265236Sken 1177265236Sken/** 1178265236Sken * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0 1179265236Sken * @sc: per adapter object 1180265236Sken * @mpi_reply: reply mf payload returned from firmware 1181265236Sken * @config_page: contents of the config page 1182265236Sken * @page_address: form and handle value used to get page 1183265236Sken * Context: sleep. 1184265236Sken * 1185265236Sken * Returns 0 for success, non-zero for failure. 1186265236Sken */ 1187265236Skenint 1188265236Skenmpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 1189265236Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1190265236Sken{ 1191265236Sken MPI2_CONFIG_REQUEST *request; 1192322661Sken MPI2_CONFIG_REPLY *reply = NULL; 1193265236Sken struct mpr_command *cm; 1194265236Sken Mpi2RaidVolPage0_t *page = NULL; 1195265236Sken int error = 0; 1196265236Sken u16 ioc_status; 1197265236Sken 1198265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1199265236Sken 1200265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1201265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1202265236Sken __LINE__); 1203265236Sken error = EBUSY; 1204265236Sken goto out; 1205265236Sken } 1206265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1207265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1208265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1209265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1210265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1211265236Sken request->Header.PageNumber = 0; 1212319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 1213265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1214265236Sken cm->cm_data = NULL; 1215265236Sken 1216265236Sken /* 1217265236Sken * This page must be polled because the IOC isn't ready yet when this 1218265236Sken * page is needed. 1219265236Sken */ 1220322661Sken error = mpr_request_polled(sc, &cm); 1221322661Sken if (cm != NULL) 1222322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1223265236Sken if (error || (reply == NULL)) { 1224265236Sken /* FIXME */ 1225265236Sken /* If the poll returns error then we need to do diag reset */ 1226265236Sken printf("%s: poll for header completed with error %d", 1227265236Sken __func__, error); 1228265236Sken error = ENXIO; 1229265236Sken goto out; 1230265236Sken } 1231265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1232265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1233265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1234265236Sken /* FIXME */ 1235265236Sken /* If the poll returns error then we need to do diag reset */ 1236265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1237265236Sken __func__, ioc_status); 1238265236Sken error = ENXIO; 1239265236Sken goto out; 1240265236Sken } 1241265236Sken /* We have to do free and alloc for the reply-free and reply-post 1242265236Sken * counters to match - Need to review the reply FIFO handling. 1243265236Sken */ 1244265236Sken mpr_free_command(sc, cm); 1245265236Sken 1246265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1247265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1248265236Sken __LINE__); 1249265236Sken error = EBUSY; 1250265236Sken goto out; 1251265236Sken } 1252265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1253265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1254265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1255265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1256265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1257265236Sken request->Header.PageNumber = 0; 1258265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1259265236Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1260265236Sken request->PageAddress = page_address; 1261265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1262265236Sken cm->cm_sge = &request->PageBufferSGE; 1263265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1264265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1265265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1266265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1267265236Sken if (!page) { 1268265236Sken printf("%s: page alloc failed\n", __func__); 1269265236Sken error = ENOMEM; 1270265236Sken goto out; 1271265236Sken } 1272265236Sken cm->cm_data = page; 1273265236Sken 1274265236Sken /* 1275265236Sken * This page must be polled because the IOC isn't ready yet when this 1276265236Sken * page is needed. 1277265236Sken */ 1278322661Sken error = mpr_request_polled(sc, &cm); 1279322661Sken if (cm != NULL) 1280322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1281265236Sken if (error || (reply == NULL)) { 1282265236Sken /* FIXME */ 1283265236Sken /* If the poll returns error then we need to do diag reset */ 1284265236Sken printf("%s: poll for page completed with error %d", 1285265236Sken __func__, error); 1286265236Sken error = ENXIO; 1287265236Sken goto out; 1288265236Sken } 1289265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1290265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1291265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1292265236Sken /* FIXME */ 1293265236Sken /* If the poll returns error then we need to do diag reset */ 1294265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1295265236Sken __func__, ioc_status); 1296265236Sken error = ENXIO; 1297265236Sken goto out; 1298265236Sken } 1299265236Sken bcopy(page, config_page, cm->cm_length); 1300265236Skenout: 1301265236Sken free(page, M_MPR); 1302265236Sken if (cm) 1303265236Sken mpr_free_command(sc, cm); 1304265236Sken return (error); 1305265236Sken} 1306265236Sken 1307265236Sken/** 1308265236Sken * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1 1309265236Sken * @sc: per adapter object 1310265236Sken * @mpi_reply: reply mf payload returned from firmware 1311265236Sken * @config_page: contents of the config page 1312265236Sken * @form: GET_NEXT_HANDLE or HANDLE 1313265236Sken * @handle: volume handle 1314265236Sken * Context: sleep. 1315265236Sken * 1316265236Sken * Returns 0 for success, non-zero for failure. 1317265236Sken */ 1318265236Skenint 1319265236Skenmpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t 1320265236Sken *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1321265236Sken{ 1322265236Sken MPI2_CONFIG_REQUEST *request; 1323265236Sken MPI2_CONFIG_REPLY *reply; 1324265236Sken struct mpr_command *cm; 1325265236Sken Mpi2RaidVolPage1_t *page = NULL; 1326265236Sken int error = 0; 1327265236Sken u16 ioc_status; 1328265236Sken 1329265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1330265236Sken 1331265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1332265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1333265236Sken __LINE__); 1334265236Sken error = EBUSY; 1335265236Sken goto out; 1336265236Sken } 1337265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1338265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1339265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1340265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1341265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1342265236Sken request->Header.PageNumber = 1; 1343319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 1344265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1345265236Sken cm->cm_data = NULL; 1346322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1347322661Sken if (cm != NULL) 1348322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1349265236Sken if (error || (reply == NULL)) { 1350265236Sken /* FIXME */ 1351265236Sken /* 1352265236Sken * If the request returns an error then we need to do a diag 1353265236Sken * reset 1354265236Sken */ 1355265236Sken printf("%s: request for header completed with error %d", 1356265236Sken __func__, error); 1357265236Sken error = ENXIO; 1358265236Sken goto out; 1359265236Sken } 1360265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1361265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1362265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1363265236Sken /* FIXME */ 1364265236Sken /* 1365265236Sken * If the request returns an error then we need to do a diag 1366265236Sken * reset 1367265236Sken */ 1368265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1369265236Sken __func__, ioc_status); 1370265236Sken error = ENXIO; 1371265236Sken goto out; 1372265236Sken } 1373265236Sken /* We have to do free and alloc for the reply-free and reply-post 1374265236Sken * counters to match - Need to review the reply FIFO handling. 1375265236Sken */ 1376265236Sken mpr_free_command(sc, cm); 1377265236Sken 1378265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1379265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1380265236Sken __LINE__); 1381265236Sken error = EBUSY; 1382265236Sken goto out; 1383265236Sken } 1384265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1385265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1386265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1387265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1388265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1389265236Sken request->Header.PageNumber = 1; 1390265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1391265236Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1392265236Sken request->PageAddress = htole32(form | handle); 1393265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1394265236Sken cm->cm_sge = &request->PageBufferSGE; 1395265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1396265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1397265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1398265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1399265236Sken if (!page) { 1400265236Sken printf("%s: page alloc failed\n", __func__); 1401265236Sken error = ENOMEM; 1402265236Sken goto out; 1403265236Sken } 1404265236Sken cm->cm_data = page; 1405265236Sken 1406322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1407322661Sken if (cm != NULL) 1408322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1409265236Sken if (error || (reply == NULL)) { 1410265236Sken /* FIXME */ 1411265236Sken /* 1412265236Sken * If the request returns an error then we need to do a diag 1413265236Sken * reset 1414265236Sken */ 1415265236Sken printf("%s: request for page completed with error %d", 1416265236Sken __func__, error); 1417265236Sken error = ENXIO; 1418265236Sken goto out; 1419265236Sken } 1420265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1421265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1422265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1423265236Sken /* FIXME */ 1424265236Sken /* 1425265236Sken * If the request returns an error then we need to do a diag 1426265236Sken * reset 1427265236Sken */ 1428265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1429265236Sken __func__, ioc_status); 1430265236Sken error = ENXIO; 1431265236Sken goto out; 1432265236Sken } 1433265236Sken bcopy(page, config_page, MIN(cm->cm_length, 1434265236Sken sizeof(Mpi2RaidVolPage1_t))); 1435265236Skenout: 1436265236Sken free(page, M_MPR); 1437265236Sken if (cm) 1438265236Sken mpr_free_command(sc, cm); 1439265236Sken return (error); 1440265236Sken} 1441265236Sken 1442265236Sken/** 1443265236Sken * mpr_config_get_volume_wwid - returns wwid given the volume handle 1444265236Sken * @sc: per adapter object 1445265236Sken * @volume_handle: volume handle 1446265236Sken * @wwid: volume wwid 1447265236Sken * Context: sleep. 1448265236Sken * 1449265236Sken * Returns 0 for success, non-zero for failure. 1450265236Sken */ 1451265236Skenint 1452265236Skenmpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid) 1453265236Sken{ 1454265236Sken Mpi2ConfigReply_t mpi_reply; 1455265236Sken Mpi2RaidVolPage1_t raid_vol_pg1; 1456265236Sken 1457265236Sken *wwid = 0; 1458265236Sken if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1459265236Sken MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1460265236Sken *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1461265236Sken raid_vol_pg1.WWID.Low); 1462265236Sken return 0; 1463265236Sken } else 1464265236Sken return -1; 1465265236Sken} 1466265236Sken 1467265236Sken/** 1468265236Sken * mpr_config_get_pd_pg0 - obtain raid phys disk page 0 1469265236Sken * @sc: per adapter object 1470265236Sken * @mpi_reply: reply mf payload returned from firmware 1471265236Sken * @config_page: contents of the config page 1472265236Sken * @page_address: form and handle value used to get page 1473265236Sken * Context: sleep. 1474265236Sken * 1475265236Sken * Returns 0 for success, non-zero for failure. 1476265236Sken */ 1477265236Skenint 1478265236Skenmpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1479265236Sken Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1480265236Sken{ 1481265236Sken MPI2_CONFIG_REQUEST *request; 1482322661Sken MPI2_CONFIG_REPLY *reply = NULL; 1483265236Sken struct mpr_command *cm; 1484265236Sken Mpi2RaidPhysDiskPage0_t *page = NULL; 1485265236Sken int error = 0; 1486265236Sken u16 ioc_status; 1487265236Sken 1488265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1489265236Sken 1490265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1491265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1492265236Sken __LINE__); 1493265236Sken error = EBUSY; 1494265236Sken goto out; 1495265236Sken } 1496265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1497265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1498265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1499265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1500265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1501265236Sken request->Header.PageNumber = 0; 1502319436Sslm request->Header.PageLength = request->Header.PageVersion = 0; 1503265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1504265236Sken cm->cm_data = NULL; 1505265236Sken 1506265236Sken /* 1507265236Sken * This page must be polled because the IOC isn't ready yet when this 1508265236Sken * page is needed. 1509265236Sken */ 1510322661Sken error = mpr_request_polled(sc, &cm); 1511322661Sken if (cm != NULL) 1512322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1513265236Sken if (error || (reply == NULL)) { 1514265236Sken /* FIXME */ 1515265236Sken /* If the poll returns error then we need to do diag reset */ 1516265236Sken printf("%s: poll for header completed with error %d", 1517265236Sken __func__, error); 1518265236Sken error = ENXIO; 1519265236Sken goto out; 1520265236Sken } 1521265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1522265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1523265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1524265236Sken /* FIXME */ 1525265236Sken /* If the poll returns error then we need to do diag reset */ 1526265236Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1527265236Sken __func__, ioc_status); 1528265236Sken error = ENXIO; 1529265236Sken goto out; 1530265236Sken } 1531265236Sken /* We have to do free and alloc for the reply-free and reply-post 1532265236Sken * counters to match - Need to review the reply FIFO handling. 1533265236Sken */ 1534265236Sken mpr_free_command(sc, cm); 1535265236Sken 1536265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1537265236Sken printf("%s: command alloc failed @ line %d\n", __func__, 1538265236Sken __LINE__); 1539265236Sken error = EBUSY; 1540265236Sken goto out; 1541265236Sken } 1542265236Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1543265236Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1544265236Sken request->Function = MPI2_FUNCTION_CONFIG; 1545265236Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1546265236Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1547265236Sken request->Header.PageNumber = 0; 1548265236Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1549265236Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1550265236Sken request->PageAddress = page_address; 1551265236Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1552265236Sken cm->cm_sge = &request->PageBufferSGE; 1553265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1554265236Sken cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1555265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1556265236Sken page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1557265236Sken if (!page) { 1558265236Sken printf("%s: page alloc failed\n", __func__); 1559265236Sken error = ENOMEM; 1560265236Sken goto out; 1561265236Sken } 1562265236Sken cm->cm_data = page; 1563265236Sken 1564265236Sken /* 1565265236Sken * This page must be polled because the IOC isn't ready yet when this 1566265236Sken * page is needed. 1567265236Sken */ 1568322661Sken error = mpr_request_polled(sc, &cm); 1569322661Sken if (cm != NULL) 1570322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1571265236Sken if (error || (reply == NULL)) { 1572265236Sken /* FIXME */ 1573265236Sken /* If the poll returns error then we need to do diag reset */ 1574265236Sken printf("%s: poll for page completed with error %d", 1575265236Sken __func__, error); 1576265236Sken error = ENXIO; 1577265236Sken goto out; 1578265236Sken } 1579265236Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1580265236Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1581265236Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1582265236Sken /* FIXME */ 1583265236Sken /* If the poll returns error then we need to do diag reset */ 1584265236Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1585265236Sken __func__, ioc_status); 1586265236Sken error = ENXIO; 1587265236Sken goto out; 1588265236Sken } 1589265236Sken bcopy(page, config_page, MIN(cm->cm_length, 1590265236Sken sizeof(Mpi2RaidPhysDiskPage0_t))); 1591265236Skenout: 1592265236Sken free(page, M_MPR); 1593265236Sken if (cm) 1594265236Sken mpr_free_command(sc, cm); 1595265236Sken return (error); 1596265236Sken} 1597