1230592Sken/*- 2279253Sslm * Copyright (c) 2011-2015 LSI Corp. 3279253Sslm * Copyright (c) 2013-2015 Avago Technologies 4230592Sken * All rights reserved. 5230592Sken * 6230592Sken * Redistribution and use in source and binary forms, with or without 7230592Sken * modification, are permitted provided that the following conditions 8230592Sken * are met: 9230592Sken * 1. Redistributions of source code must retain the above copyright 10230592Sken * notice, this list of conditions and the following disclaimer. 11230592Sken * 2. Redistributions in binary form must reproduce the above copyright 12230592Sken * notice, this list of conditions and the following disclaimer in the 13230592Sken * documentation and/or other materials provided with the distribution. 14230592Sken * 15230592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16230592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17230592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18230592Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19230592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20230592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21230592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22230592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23230592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24230592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25230592Sken * SUCH DAMAGE. 26230592Sken * 27279253Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 28230592Sken */ 29230592Sken 30230592Sken#include <sys/cdefs.h> 31230592Sken__FBSDID("$FreeBSD: releng/11.0/sys/dev/mps/mps_config.c 302031 2016-06-20 18:14:51Z slm $"); 32230592Sken 33230592Sken/* TODO Move headers to mpsvar */ 34230592Sken#include <sys/types.h> 35230592Sken#include <sys/param.h> 36230592Sken#include <sys/lock.h> 37230592Sken#include <sys/mutex.h> 38230592Sken#include <sys/systm.h> 39230592Sken#include <sys/kernel.h> 40230592Sken#include <sys/malloc.h> 41230592Sken#include <sys/kthread.h> 42230592Sken#include <sys/taskqueue.h> 43230592Sken#include <sys/bus.h> 44230592Sken#include <sys/endian.h> 45230592Sken#include <sys/sysctl.h> 46230592Sken#include <sys/eventhandler.h> 47230592Sken#include <sys/uio.h> 48230592Sken#include <machine/bus.h> 49230592Sken#include <machine/resource.h> 50230592Sken#include <dev/mps/mpi/mpi2_type.h> 51230592Sken#include <dev/mps/mpi/mpi2.h> 52230592Sken#include <dev/mps/mpi/mpi2_ioc.h> 53230592Sken#include <dev/mps/mpi/mpi2_sas.h> 54230592Sken#include <dev/mps/mpi/mpi2_cnfg.h> 55230592Sken#include <dev/mps/mpi/mpi2_init.h> 56230592Sken#include <dev/mps/mpi/mpi2_tool.h> 57230592Sken#include <dev/mps/mps_ioctl.h> 58230592Sken#include <dev/mps/mpsvar.h> 59230592Sken 60230592Sken/** 61230592Sken * mps_config_get_ioc_pg8 - obtain ioc page 8 62230592Sken * @sc: per adapter object 63230592Sken * @mpi_reply: reply mf payload returned from firmware 64230592Sken * @config_page: contents of the config page 65230592Sken * Context: sleep. 66230592Sken * 67230592Sken * Returns 0 for success, non-zero for failure. 68230592Sken */ 69230592Skenint 70230592Skenmps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 71230592Sken Mpi2IOCPage8_t *config_page) 72230592Sken{ 73230592Sken MPI2_CONFIG_REQUEST *request; 74230592Sken MPI2_CONFIG_REPLY *reply; 75230592Sken struct mps_command *cm; 76230592Sken MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 77230592Sken int error = 0; 78230592Sken u16 ioc_status; 79230592Sken 80230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 81230592Sken 82230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 83230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 84230592Sken __LINE__); 85230592Sken error = EBUSY; 86230592Sken goto out; 87230592Sken } 88230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 89230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 90230592Sken request->Function = MPI2_FUNCTION_CONFIG; 91230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 92230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 93230592Sken request->Header.PageNumber = 8; 94230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 95230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 96230592Sken cm->cm_data = NULL; 97253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 98230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 99230592Sken if (error || (reply == NULL)) { 100230592Sken /* FIXME */ 101253550Sken /* 102253550Sken * If the request returns an error then we need to do a diag 103253550Sken * reset 104253550Sken */ 105253550Sken printf("%s: request for header completed with error %d", 106230592Sken __func__, error); 107230592Sken error = ENXIO; 108230592Sken goto out; 109230592Sken } 110230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 111230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 112230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 113230592Sken /* FIXME */ 114253550Sken /* 115253550Sken * If the request returns an error then we need to do a diag 116253550Sken * reset 117253550Sken */ 118230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 119230592Sken __func__, ioc_status); 120230592Sken error = ENXIO; 121230592Sken goto out; 122230592Sken } 123230592Sken /* We have to do free and alloc for the reply-free and reply-post 124230592Sken * counters to match - Need to review the reply FIFO handling. 125230592Sken */ 126230592Sken mps_free_command(sc, cm); 127230592Sken 128230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 129230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 130230592Sken __LINE__); 131230592Sken error = EBUSY; 132230592Sken goto out; 133230592Sken } 134230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 135230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 136230592Sken request->Function = MPI2_FUNCTION_CONFIG; 137230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 138230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 139230592Sken request->Header.PageNumber = 8; 140230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 141230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 142230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 143230592Sken cm->cm_sge = &request->PageBufferSGE; 144230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 145230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 146230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 147230592Sken page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT); 148230592Sken if (!page) { 149230592Sken printf("%s: page alloc failed\n", __func__); 150230592Sken error = ENOMEM; 151230592Sken goto out; 152230592Sken } 153230592Sken cm->cm_data = page; 154253550Sken 155253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 156230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 157230592Sken if (error || (reply == NULL)) { 158230592Sken /* FIXME */ 159253550Sken /* 160253550Sken * If the request returns an error then we need to do a diag 161253550Sken * reset 162253550Sken */ 163253550Sken printf("%s: request for page completed with error %d", 164230592Sken __func__, error); 165230592Sken error = ENXIO; 166230592Sken goto out; 167230592Sken } 168230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 169230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 170230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 171230592Sken /* FIXME */ 172253550Sken /* 173253550Sken * If the request returns an error then we need to do a diag 174253550Sken * reset 175253550Sken */ 176230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 177230592Sken __func__, ioc_status); 178230592Sken error = ENXIO; 179230592Sken goto out; 180230592Sken } 181230592Sken bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 182230592Sken 183230592Skenout: 184230592Sken free(page, M_MPT2); 185230592Sken if (cm) 186230592Sken mps_free_command(sc, cm); 187230592Sken return (error); 188230592Sken} 189230592Sken 190230592Sken/** 191230592Sken * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags 192230592Sken * accordingly. Currently, this page does not need to return to caller. 193230592Sken * @sc: per adapter object 194230592Sken * @mpi_reply: reply mf payload returned from firmware 195230592Sken * Context: sleep. 196230592Sken * 197230592Sken * Returns 0 for success, non-zero for failure. 198230592Sken */ 199230592Skenint 200230592Skenmps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) 201230592Sken{ 202230592Sken MPI2_CONFIG_REQUEST *request; 203230592Sken MPI2_CONFIG_REPLY *reply; 204230592Sken struct mps_command *cm; 205230592Sken pMpi2ManufacturingPagePS_t page = NULL; 206230592Sken uint32_t *pPS_info; 207230592Sken uint8_t OEM_Value = 0; 208230592Sken int error = 0; 209230592Sken u16 ioc_status; 210230592Sken 211230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 212230592Sken 213230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 214230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 215230592Sken __LINE__); 216230592Sken error = EBUSY; 217230592Sken goto out; 218230592Sken } 219230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 220230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 221230592Sken request->Function = MPI2_FUNCTION_CONFIG; 222230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 223230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 224230592Sken request->Header.PageNumber = 10; 225230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 226230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 227230592Sken cm->cm_data = NULL; 228253550Sken 229253550Sken /* 230253550Sken * This page must be polled because the IOC isn't ready yet when this 231253550Sken * page is needed. 232253550Sken */ 233286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 234230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 235230592Sken if (error || (reply == NULL)) { 236230592Sken /* FIXME */ 237230592Sken /* If the poll returns error then we need to do diag reset */ 238230592Sken printf("%s: poll for header completed with error %d", 239230592Sken __func__, error); 240230592Sken error = ENXIO; 241230592Sken goto out; 242230592Sken } 243230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 244230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 245230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 246230592Sken /* FIXME */ 247230592Sken /* If the poll returns error then we need to do diag reset */ 248230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 249230592Sken __func__, ioc_status); 250230592Sken error = ENXIO; 251230592Sken goto out; 252230592Sken } 253230592Sken /* We have to do free and alloc for the reply-free and reply-post 254230592Sken * counters to match - Need to review the reply FIFO handling. 255230592Sken */ 256230592Sken mps_free_command(sc, cm); 257230592Sken 258230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 259230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 260230592Sken __LINE__); 261230592Sken error = EBUSY; 262230592Sken goto out; 263230592Sken } 264230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 265230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 266230592Sken request->Function = MPI2_FUNCTION_CONFIG; 267230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 268230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 269230592Sken request->Header.PageNumber = 10; 270230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 271230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 272230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 273230592Sken cm->cm_sge = &request->PageBufferSGE; 274230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 275230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 276230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 277230592Sken page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT); 278230592Sken if (!page) { 279230592Sken printf("%s: page alloc failed\n", __func__); 280230592Sken error = ENOMEM; 281230592Sken goto out; 282230592Sken } 283230592Sken cm->cm_data = page; 284253550Sken 285253550Sken /* 286253550Sken * This page must be polled because the IOC isn't ready yet when this 287253550Sken * page is needed. 288253550Sken */ 289286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 290230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 291230592Sken if (error || (reply == NULL)) { 292230592Sken /* FIXME */ 293230592Sken /* If the poll returns error then we need to do diag reset */ 294230592Sken printf("%s: poll for page completed with error %d", 295230592Sken __func__, error); 296230592Sken error = ENXIO; 297230592Sken goto out; 298230592Sken } 299230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 300230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 301230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 302230592Sken /* FIXME */ 303230592Sken /* If the poll returns error then we need to do diag reset */ 304230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 305230592Sken __func__, ioc_status); 306230592Sken error = ENXIO; 307230592Sken goto out; 308230592Sken } 309230592Sken 310230592Sken /* 311230592Sken * If OEM ID is unknown, fail the request. 312230592Sken */ 313230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 314230592Sken OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF); 315230592Sken if (OEM_Value != MPS_WD_LSI_OEM) { 316230592Sken mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive " 317230592Sken "(0x%x)\n", OEM_Value); 318230592Sken error = ENXIO; 319230592Sken goto out; 320230592Sken } 321230592Sken 322230592Sken /* 323230592Sken * Set the phys disks hide/expose value. 324230592Sken */ 325230592Sken pPS_info = &page->ProductSpecificInfo; 326230592Sken sc->WD_hide_expose = (uint8_t)(pPS_info[5]); 327230592Sken sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK; 328230592Sken if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) && 329230592Sken (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) && 330230592Sken (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) { 331230592Sken mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive " 332230592Sken "hide/expose: 0x%x\n", sc->WD_hide_expose); 333230592Sken error = ENXIO; 334230592Sken goto out; 335230592Sken } 336230592Sken 337230592Skenout: 338230592Sken free(page, M_MPT2); 339230592Sken if (cm) 340230592Sken mps_free_command(sc, cm); 341230592Sken return (error); 342230592Sken} 343230592Sken 344230592Sken/** 345230592Sken * mps_base_static_config_pages - static start of day config pages. 346230592Sken * @sc: per adapter object 347230592Sken * 348230592Sken * Return nothing. 349230592Sken */ 350230592Skenvoid 351230592Skenmps_base_static_config_pages(struct mps_softc *sc) 352230592Sken{ 353230592Sken Mpi2ConfigReply_t mpi_reply; 354230592Sken int retry; 355230592Sken 356230592Sken retry = 0; 357230592Sken while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 358230592Sken retry++; 359230592Sken if (retry > 5) { 360230592Sken /* We need to Handle this situation */ 361230592Sken /*FIXME*/ 362230592Sken break; 363230592Sken } 364230592Sken } 365230592Sken} 366230592Sken 367230592Sken/** 368230592Sken * mps_wd_config_pages - get info required to support WarpDrive. This needs to 369298955Spfg * be called after discovery is complete to guarantee that IR info is there. 370230592Sken * @sc: per adapter object 371230592Sken * 372230592Sken * Return nothing. 373230592Sken */ 374230592Skenvoid 375230592Skenmps_wd_config_pages(struct mps_softc *sc) 376230592Sken{ 377230592Sken Mpi2ConfigReply_t mpi_reply; 378230592Sken pMpi2RaidVolPage0_t raid_vol_pg0 = NULL; 379230592Sken Mpi2RaidPhysDiskPage0_t phys_disk_pg0; 380230592Sken pMpi2RaidVol0PhysDisk_t pRVPD; 381230592Sken uint32_t stripe_size, phys_disk_page_address; 382230592Sken uint16_t block_size; 383230592Sken uint8_t index, stripe_exp = 0, block_exp = 0; 384230592Sken 385230592Sken /* 386230592Sken * Get the WD settings from manufacturing page 10 if using a WD HBA. 387230592Sken * This will be used to determine if phys disks should always be 388230592Sken * hidden, hidden only if part of a WD volume, or never hidden. Also, 389230592Sken * get the WD RAID Volume info and fail if volume does not exist or if 390230592Sken * volume does not meet the requirements for a WD volume. No retry 391230592Sken * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD 392230592Sken * Valid flag if Volume info fails. 393230592Sken */ 394230592Sken sc->WD_valid_config = FALSE; 395230592Sken if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { 396230592Sken if (mps_config_get_man_pg10(sc, &mpi_reply)) { 397230592Sken mps_dprint(sc, MPS_FAULT, 398230592Sken "mps_config_get_man_pg10 failed! Using 0 (Hide " 399230592Sken "Always) for WarpDrive hide/expose value.\n"); 400230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 401230592Sken } 402230592Sken 403230592Sken /* 404230592Sken * Get first RAID Volume Page0 using GET_NEXT_HANDLE. 405230592Sken */ 406230592Sken raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) + 407230592Sken (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL), 408230592Sken M_MPT2, M_ZERO | M_NOWAIT); 409230592Sken if (!raid_vol_pg0) { 410230592Sken printf("%s: page alloc failed\n", __func__); 411230592Sken goto out; 412230592Sken } 413230592Sken 414230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0, 415230592Sken 0x0000FFFF)) { 416230592Sken mps_dprint(sc, MPS_INFO, 417230592Sken "mps_config_get_raid_volume_pg0 failed! Assuming " 418230592Sken "WarpDrive IT mode.\n"); 419230592Sken goto out; 420230592Sken } 421230592Sken 422230592Sken /* 423230592Sken * Check for valid WD configuration: 424230592Sken * volume type is RAID0 425230592Sken * number of phys disks in the volume is no more than 8 426230592Sken */ 427230592Sken if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) || 428230592Sken (raid_vol_pg0->NumPhysDisks > 8)) { 429230592Sken mps_dprint(sc, MPS_FAULT, 430230592Sken "Invalid WarpDrive configuration. Direct Drive I/O " 431230592Sken "will not be used.\n"); 432230592Sken goto out; 433230592Sken } 434230592Sken 435230592Sken /* 436230592Sken * Save the WD RAID data to be used during WD I/O. 437230592Sken */ 438230592Sken sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High << 439230592Sken 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low); 440230592Sken sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks; 441230592Sken sc->DD_dev_handle = raid_vol_pg0->DevHandle; 442230592Sken sc->DD_stripe_size = raid_vol_pg0->StripeSize; 443230592Sken sc->DD_block_size = raid_vol_pg0->BlockSize; 444230592Sken 445230592Sken /* 446230592Sken * Find power of 2 of stripe size and set this as the exponent. 447230592Sken * Fail if stripe size is 0. 448230592Sken */ 449230592Sken stripe_size = raid_vol_pg0->StripeSize; 450230592Sken for (index = 0; index < 32; index++) { 451230592Sken if (stripe_size & 1) 452230592Sken break; 453230592Sken stripe_exp++; 454230592Sken stripe_size >>= 1; 455230592Sken } 456230592Sken if (index == 32) { 457230592Sken mps_dprint(sc, MPS_FAULT, 458230592Sken "RAID Volume's stripe size is 0. Direct Drive I/O " 459230592Sken "will not be used.\n"); 460230592Sken goto out; 461230592Sken } 462230592Sken sc->DD_stripe_exponent = stripe_exp; 463230592Sken 464230592Sken /* 465230592Sken * Find power of 2 of block size and set this as the exponent. 466230592Sken * Fail if block size is 0. 467230592Sken */ 468230592Sken block_size = raid_vol_pg0->BlockSize; 469230592Sken for (index = 0; index < 16; index++) { 470230592Sken if (block_size & 1) 471230592Sken break; 472230592Sken block_exp++; 473230592Sken block_size >>= 1; 474230592Sken } 475230592Sken if (index == 16) { 476230592Sken mps_dprint(sc, MPS_FAULT, 477230592Sken "RAID Volume's block size is 0. Direct Drive I/O " 478230592Sken "will not be used.\n"); 479230592Sken goto out; 480230592Sken } 481230592Sken sc->DD_block_exponent = block_exp; 482230592Sken 483230592Sken /* 484230592Sken * Loop through all of the volume's Phys Disks to map the phys 485230592Sken * disk number into the columm map. This is used during Direct 486230592Sken * Drive I/O to send the request to the correct SSD. 487230592Sken */ 488230592Sken pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk; 489230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 490230592Sken sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num = 491230592Sken pRVPD->PhysDiskNum; 492230592Sken pRVPD++; 493230592Sken } 494230592Sken 495230592Sken /* 496230592Sken * Get second RAID Volume Page0 using previous handle. This 497230592Sken * page should not exist. If it does, must not proceed with WD 498230592Sken * handling. 499230592Sken */ 500230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, 501230592Sken raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) { 502302031Sslm if ((le16toh(mpi_reply.IOCStatus) & 503302031Sslm MPI2_IOCSTATUS_MASK) != 504230592Sken MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 505230592Sken mps_dprint(sc, MPS_FAULT, 506230592Sken "Multiple RAID Volume Page0! Direct Drive " 507230592Sken "I/O will not be used.\n"); 508230592Sken goto out; 509230592Sken } 510230592Sken } else { 511230592Sken mps_dprint(sc, MPS_FAULT, 512230592Sken "Multiple volumes! Direct Drive I/O will not be " 513230592Sken "used.\n"); 514230592Sken goto out; 515230592Sken } 516230592Sken 517230592Sken /* 518230592Sken * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 519230592Sken */ 520230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 521230592Sken phys_disk_page_address = 522230592Sken MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 523230592Sken sc->DD_column_map[index].phys_disk_num; 524230592Sken if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 525230592Sken &phys_disk_pg0, phys_disk_page_address)) { 526230592Sken mps_dprint(sc, MPS_FAULT, 527230592Sken "mps_config_get_raid_pd_pg0 failed! Direct " 528230592Sken "Drive I/O will not be used.\n"); 529230592Sken goto out; 530230592Sken } 531230592Sken if (phys_disk_pg0.DevHandle == 0xFFFF) { 532230592Sken mps_dprint(sc, MPS_FAULT, 533230592Sken "Invalid Phys Disk DevHandle! Direct Drive " 534230592Sken "I/O will not be used.\n"); 535230592Sken goto out; 536230592Sken } 537230592Sken sc->DD_column_map[index].dev_handle = 538230592Sken phys_disk_pg0.DevHandle; 539230592Sken } 540230592Sken sc->WD_valid_config = TRUE; 541230592Skenout: 542230592Sken if (raid_vol_pg0) 543230592Sken free(raid_vol_pg0, M_MPT2); 544230592Sken } 545230592Sken} 546230592Sken 547230592Sken/** 548230592Sken * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 549230592Sken * @sc: per adapter object 550230592Sken * @mpi_reply: reply mf payload returned from firmware 551230592Sken * @config_page: contents of the config page 552230592Sken * @sz: size of buffer passed in config_page 553230592Sken * Context: sleep. 554230592Sken * 555230592Sken * Returns 0 for success, non-zero for failure. 556230592Sken */ 557230592Skenint 558230592Skenmps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 559230592Sken Mpi2DriverMappingPage0_t *config_page, u16 sz) 560230592Sken{ 561230592Sken MPI2_CONFIG_REQUEST *request; 562230592Sken MPI2_CONFIG_REPLY *reply; 563230592Sken struct mps_command *cm; 564230592Sken Mpi2DriverMappingPage0_t *page = NULL; 565230592Sken int error = 0; 566230592Sken u16 ioc_status; 567230592Sken 568230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 569230592Sken 570230592Sken memset(config_page, 0, sz); 571230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 572230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 573230592Sken __LINE__); 574230592Sken error = EBUSY; 575230592Sken goto out; 576230592Sken } 577230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 578230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 579230592Sken request->Function = MPI2_FUNCTION_CONFIG; 580230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 581230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 582230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 583230592Sken request->Header.PageNumber = 0; 584230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 585230592Sken request->PageAddress = sc->max_dpm_entries << 586230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 587230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 588230592Sken cm->cm_data = NULL; 589253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 590230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 591230592Sken if (error || (reply == NULL)) { 592230592Sken /* FIXME */ 593253550Sken /* 594253550Sken * If the request returns an error then we need to do a diag 595253550Sken * reset 596253550Sken */ 597253550Sken printf("%s: request for header completed with error %d", 598230592Sken __func__, error); 599230592Sken error = ENXIO; 600230592Sken goto out; 601230592Sken } 602230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 603230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 604230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 605230592Sken /* FIXME */ 606253550Sken /* 607253550Sken * If the request returns an error then we need to do a diag 608253550Sken * reset 609253550Sken */ 610230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 611230592Sken __func__, ioc_status); 612230592Sken error = ENXIO; 613230592Sken goto out; 614230592Sken } 615230592Sken /* We have to do free and alloc for the reply-free and reply-post 616230592Sken * counters to match - Need to review the reply FIFO handling. 617230592Sken */ 618230592Sken mps_free_command(sc, cm); 619230592Sken 620230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 621230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 622230592Sken __LINE__); 623230592Sken error = EBUSY; 624230592Sken goto out; 625230592Sken } 626230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 627230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 628230592Sken request->Function = MPI2_FUNCTION_CONFIG; 629230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 630230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 631230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 632230592Sken request->Header.PageNumber = 0; 633230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 634230592Sken request->PageAddress = sc->max_dpm_entries << 635230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 636230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 637230592Sken cm->cm_length = le16toh(request->ExtPageLength) * 4; 638230592Sken cm->cm_sge = &request->PageBufferSGE; 639230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 640230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 641230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 642230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 643230592Sken if (!page) { 644230592Sken printf("%s: page alloc failed\n", __func__); 645230592Sken error = ENOMEM; 646230592Sken goto out; 647230592Sken } 648230592Sken cm->cm_data = page; 649253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 650230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 651230592Sken if (error || (reply == NULL)) { 652230592Sken /* FIXME */ 653253550Sken /* 654253550Sken * If the request returns an error then we need to do a diag 655253550Sken * reset 656253550Sken */ 657253550Sken printf("%s: request for page completed with error %d", 658230592Sken __func__, error); 659230592Sken error = ENXIO; 660230592Sken goto out; 661230592Sken } 662230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 663230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 664230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 665230592Sken /* FIXME */ 666253550Sken /* 667253550Sken * If the request returns an error then we need to do a diag 668253550Sken * reset 669253550Sken */ 670230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 671230592Sken __func__, ioc_status); 672230592Sken error = ENXIO; 673230592Sken goto out; 674230592Sken } 675230592Sken bcopy(page, config_page, MIN(cm->cm_length, sz)); 676230592Skenout: 677230592Sken free(page, M_MPT2); 678230592Sken if (cm) 679230592Sken mps_free_command(sc, cm); 680230592Sken return (error); 681230592Sken} 682230592Sken 683230592Sken/** 684230592Sken * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 685230592Sken * @sc: per adapter object 686230592Sken * @mpi_reply: reply mf payload returned from firmware 687230592Sken * @config_page: contents of the config page 688230592Sken * @entry_idx: entry index in DPM Page0 to be modified 689230592Sken * Context: sleep. 690230592Sken * 691230592Sken * Returns 0 for success, non-zero for failure. 692230592Sken */ 693230592Sken 694230592Skenint mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 695230592Sken Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 696230592Sken{ 697230592Sken MPI2_CONFIG_REQUEST *request; 698230592Sken MPI2_CONFIG_REPLY *reply; 699230592Sken struct mps_command *cm; 700230592Sken MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 701230592Sken int error = 0; 702230592Sken u16 ioc_status; 703230592Sken 704230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 705230592Sken 706230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 707230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 708230592Sken __LINE__); 709230592Sken error = EBUSY; 710230592Sken goto out; 711230592Sken } 712230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 713230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 714230592Sken request->Function = MPI2_FUNCTION_CONFIG; 715230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 716230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 717230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 718230592Sken request->Header.PageNumber = 0; 719230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 720237683Sken /* We can remove below two lines ????*/ 721230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 722230592Sken request->PageAddress |= htole16(entry_idx); 723230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 724230592Sken cm->cm_data = NULL; 725253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 726230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 727230592Sken if (error || (reply == NULL)) { 728230592Sken /* FIXME */ 729253550Sken /* 730253550Sken * If the request returns an error then we need to do a diag 731253550Sken * reset 732253550Sken */ 733253550Sken printf("%s: request for header completed with error %d", 734230592Sken __func__, error); 735230592Sken error = ENXIO; 736230592Sken goto out; 737230592Sken } 738230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 739230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 740230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 741230592Sken /* FIXME */ 742253550Sken /* 743253550Sken * If the request returns an error then we need to do a diag 744253550Sken * reset 745253550Sken */ 746230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 747230592Sken __func__, ioc_status); 748230592Sken error = ENXIO; 749230592Sken goto out; 750230592Sken } 751230592Sken /* We have to do free and alloc for the reply-free and reply-post 752230592Sken * counters to match - Need to review the reply FIFO handling. 753230592Sken */ 754230592Sken mps_free_command(sc, cm); 755230592Sken 756230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 757230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 758230592Sken __LINE__); 759230592Sken error = EBUSY; 760230592Sken goto out; 761230592Sken } 762230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 763230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 764230592Sken request->Function = MPI2_FUNCTION_CONFIG; 765230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 766230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 767230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 768230592Sken request->Header.PageNumber = 0; 769230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 770230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 771230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 772230592Sken request->PageAddress |= htole16(entry_idx); 773230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 774230592Sken cm->cm_sge = &request->PageBufferSGE; 775230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 776230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 777230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 778230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 779230592Sken if (!page) { 780230592Sken printf("%s: page alloc failed\n", __func__); 781230592Sken error = ENOMEM; 782230592Sken goto out; 783230592Sken } 784230592Sken bcopy(config_page, page, MIN(cm->cm_length, 785230592Sken (sizeof(Mpi2DriverMappingPage0_t)))); 786230592Sken cm->cm_data = page; 787253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 788230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 789230592Sken if (error || (reply == NULL)) { 790230592Sken /* FIXME */ 791253550Sken /* 792253550Sken * If the request returns an error then we need to do a diag 793253550Sken * reset 794253550Sken */ 795253550Sken printf("%s: request to write page completed with error %d", 796230592Sken __func__, error); 797230592Sken error = ENXIO; 798230592Sken goto out; 799230592Sken } 800230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 801230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 802230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 803230592Sken /* FIXME */ 804253550Sken /* 805253550Sken * If the request returns an error then we need to do a diag 806253550Sken * reset 807253550Sken */ 808230592Sken printf("%s: page written with error; iocstatus = 0x%x\n", 809230592Sken __func__, ioc_status); 810230592Sken error = ENXIO; 811230592Sken goto out; 812230592Sken } 813230592Skenout: 814230592Sken free(page, M_MPT2); 815230592Sken if (cm) 816230592Sken mps_free_command(sc, cm); 817230592Sken return (error); 818230592Sken} 819230592Sken 820230592Sken/** 821230592Sken * mps_config_get_sas_device_pg0 - obtain sas device page 0 822230592Sken * @sc: per adapter object 823230592Sken * @mpi_reply: reply mf payload returned from firmware 824230592Sken * @config_page: contents of the config page 825230592Sken * @form: GET_NEXT_HANDLE or HANDLE 826230592Sken * @handle: device handle 827230592Sken * Context: sleep. 828230592Sken * 829230592Sken * Returns 0 for success, non-zero for failure. 830230592Sken */ 831230592Skenint 832230592Skenmps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 833230592Sken *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 834230592Sken{ 835230592Sken MPI2_CONFIG_REQUEST *request; 836230592Sken MPI2_CONFIG_REPLY *reply; 837230592Sken struct mps_command *cm; 838230592Sken Mpi2SasDevicePage0_t *page = NULL; 839230592Sken int error = 0; 840230592Sken u16 ioc_status; 841230592Sken 842230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 843230592Sken 844230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 845230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 846230592Sken __LINE__); 847230592Sken error = EBUSY; 848230592Sken goto out; 849230592Sken } 850230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 851230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 852230592Sken request->Function = MPI2_FUNCTION_CONFIG; 853230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 854230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 855230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 856230592Sken request->Header.PageNumber = 0; 857230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 858230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 859230592Sken cm->cm_data = NULL; 860253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 861230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 862230592Sken if (error || (reply == NULL)) { 863230592Sken /* FIXME */ 864253550Sken /* 865253550Sken * If the request returns an error then we need to do a diag 866253550Sken * reset 867253550Sken */ 868253550Sken printf("%s: request for header completed with error %d", 869230592Sken __func__, error); 870230592Sken error = ENXIO; 871230592Sken goto out; 872230592Sken } 873230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 874230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 875230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 876230592Sken /* FIXME */ 877253550Sken /* 878253550Sken * If the request returns an error then we need to do a diag 879253550Sken * reset 880253550Sken */ 881230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 882230592Sken __func__, ioc_status); 883230592Sken error = ENXIO; 884230592Sken goto out; 885230592Sken } 886230592Sken /* We have to do free and alloc for the reply-free and reply-post 887230592Sken * counters to match - Need to review the reply FIFO handling. 888230592Sken */ 889230592Sken mps_free_command(sc, cm); 890230592Sken 891230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 892230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 893230592Sken __LINE__); 894230592Sken error = EBUSY; 895230592Sken goto out; 896230592Sken } 897230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 898230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 899230592Sken request->Function = MPI2_FUNCTION_CONFIG; 900230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 901230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 902230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 903230592Sken request->Header.PageNumber = 0; 904230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 905230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 906230592Sken request->PageAddress = htole32(form | handle); 907230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 908230592Sken cm->cm_sge = &request->PageBufferSGE; 909230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 910230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 911230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 912230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 913230592Sken if (!page) { 914230592Sken printf("%s: page alloc failed\n", __func__); 915230592Sken error = ENOMEM; 916230592Sken goto out; 917230592Sken } 918230592Sken cm->cm_data = page; 919230592Sken 920253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 921230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 922230592Sken if (error || (reply == NULL)) { 923230592Sken /* FIXME */ 924253550Sken /* 925253550Sken * If the request returns an error then we need to do a diag 926253550Sken * reset 927253550Sken */ 928253550Sken printf("%s: request for page completed with error %d", 929230592Sken __func__, error); 930230592Sken error = ENXIO; 931230592Sken goto out; 932230592Sken } 933230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 934230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 935230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 936230592Sken /* FIXME */ 937253550Sken /* 938253550Sken * If the request returns an error then we need to do a diag 939253550Sken * reset 940253550Sken */ 941230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 942230592Sken __func__, ioc_status); 943230592Sken error = ENXIO; 944230592Sken goto out; 945230592Sken } 946230592Sken bcopy(page, config_page, MIN(cm->cm_length, 947230592Sken sizeof(Mpi2SasDevicePage0_t))); 948230592Skenout: 949230592Sken free(page, M_MPT2); 950230592Sken if (cm) 951230592Sken mps_free_command(sc, cm); 952230592Sken return (error); 953230592Sken} 954230592Sken 955230592Sken/** 956230592Sken * mps_config_get_bios_pg3 - obtain BIOS page 3 957230592Sken * @sc: per adapter object 958230592Sken * @mpi_reply: reply mf payload returned from firmware 959230592Sken * @config_page: contents of the config page 960230592Sken * Context: sleep. 961230592Sken * 962230592Sken * Returns 0 for success, non-zero for failure. 963230592Sken */ 964230592Skenint 965230592Skenmps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 966230592Sken Mpi2BiosPage3_t *config_page) 967230592Sken{ 968230592Sken MPI2_CONFIG_REQUEST *request; 969230592Sken MPI2_CONFIG_REPLY *reply; 970230592Sken struct mps_command *cm; 971230592Sken Mpi2BiosPage3_t *page = NULL; 972230592Sken int error = 0; 973230592Sken u16 ioc_status; 974230592Sken 975230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 976230592Sken 977230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 978230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 979230592Sken __LINE__); 980230592Sken error = EBUSY; 981230592Sken goto out; 982230592Sken } 983230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 984230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 985230592Sken request->Function = MPI2_FUNCTION_CONFIG; 986230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 987230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 988230592Sken request->Header.PageNumber = 3; 989230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 990230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 991230592Sken cm->cm_data = NULL; 992253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 993230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 994230592Sken if (error || (reply == NULL)) { 995230592Sken /* FIXME */ 996253550Sken /* 997253550Sken * If the request returns an error then we need to do a diag 998253550Sken * reset 999253550Sken */ 1000253550Sken printf("%s: request for header completed with error %d", 1001230592Sken __func__, error); 1002230592Sken error = ENXIO; 1003230592Sken goto out; 1004230592Sken } 1005230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1006230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1007230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1008230592Sken /* FIXME */ 1009253550Sken /* 1010253550Sken * If the request returns an error then we need to do a diag 1011253550Sken * reset 1012253550Sken */ 1013230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1014230592Sken __func__, ioc_status); 1015230592Sken error = ENXIO; 1016230592Sken goto out; 1017230592Sken } 1018230592Sken /* We have to do free and alloc for the reply-free and reply-post 1019230592Sken * counters to match - Need to review the reply FIFO handling. 1020230592Sken */ 1021230592Sken mps_free_command(sc, cm); 1022230592Sken 1023230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1024230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1025230592Sken __LINE__); 1026230592Sken error = EBUSY; 1027230592Sken goto out; 1028230592Sken } 1029230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1030230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1031230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1032230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1033230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1034230592Sken request->Header.PageNumber = 3; 1035230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1036230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1037230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1038230592Sken cm->cm_sge = &request->PageBufferSGE; 1039230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1040230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1041230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1042230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1043230592Sken if (!page) { 1044230592Sken printf("%s: page alloc failed\n", __func__); 1045230592Sken error = ENOMEM; 1046230592Sken goto out; 1047230592Sken } 1048230592Sken cm->cm_data = page; 1049230592Sken 1050253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1051230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1052230592Sken if (error || (reply == NULL)) { 1053230592Sken /* FIXME */ 1054253550Sken /* 1055253550Sken * If the request returns an error then we need to do a diag 1056253550Sken * reset 1057253550Sken */ 1058253550Sken printf("%s: request for page completed with error %d", 1059230592Sken __func__, error); 1060230592Sken error = ENXIO; 1061230592Sken goto out; 1062230592Sken } 1063230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1064230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1065230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1066230592Sken /* FIXME */ 1067253550Sken /* 1068253550Sken * If the request returns an error then we need to do a diag 1069253550Sken * reset 1070253550Sken */ 1071230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1072230592Sken __func__, ioc_status); 1073230592Sken error = ENXIO; 1074230592Sken goto out; 1075230592Sken } 1076230592Sken bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1077230592Skenout: 1078230592Sken free(page, M_MPT2); 1079230592Sken if (cm) 1080230592Sken mps_free_command(sc, cm); 1081230592Sken return (error); 1082230592Sken} 1083230592Sken 1084230592Sken/** 1085230592Sken * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1086230592Sken * @sc: per adapter object 1087230592Sken * @mpi_reply: reply mf payload returned from firmware 1088230592Sken * @config_page: contents of the config page 1089230592Sken * @page_address: form and handle value used to get page 1090230592Sken * Context: sleep. 1091230592Sken * 1092230592Sken * Returns 0 for success, non-zero for failure. 1093230592Sken */ 1094230592Skenint 1095230592Skenmps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1096230592Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1097230592Sken{ 1098230592Sken MPI2_CONFIG_REQUEST *request; 1099230592Sken MPI2_CONFIG_REPLY *reply; 1100230592Sken struct mps_command *cm; 1101230592Sken Mpi2RaidVolPage0_t *page = NULL; 1102230592Sken int error = 0; 1103230592Sken u16 ioc_status; 1104230592Sken 1105230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1106230592Sken 1107230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1108230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1109230592Sken __LINE__); 1110230592Sken error = EBUSY; 1111230592Sken goto out; 1112230592Sken } 1113230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1114230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1115230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1116230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1117230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1118230592Sken request->Header.PageNumber = 0; 1119230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1120230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1121230592Sken cm->cm_data = NULL; 1122253550Sken 1123253550Sken /* 1124253550Sken * This page must be polled because the IOC isn't ready yet when this 1125253550Sken * page is needed. 1126253550Sken */ 1127286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 1128230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1129230592Sken if (error || (reply == NULL)) { 1130230592Sken /* FIXME */ 1131230592Sken /* If the poll returns error then we need to do diag reset */ 1132230592Sken printf("%s: poll for header completed with error %d", 1133230592Sken __func__, error); 1134230592Sken error = ENXIO; 1135230592Sken goto out; 1136230592Sken } 1137230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1138230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1139230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1140230592Sken /* FIXME */ 1141230592Sken /* If the poll returns error then we need to do diag reset */ 1142230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1143230592Sken __func__, ioc_status); 1144230592Sken error = ENXIO; 1145230592Sken goto out; 1146230592Sken } 1147230592Sken /* We have to do free and alloc for the reply-free and reply-post 1148230592Sken * counters to match - Need to review the reply FIFO handling. 1149230592Sken */ 1150230592Sken mps_free_command(sc, cm); 1151230592Sken 1152230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1153230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1154230592Sken __LINE__); 1155230592Sken error = EBUSY; 1156230592Sken goto out; 1157230592Sken } 1158230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1159230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1160230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1161230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1162230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1163230592Sken request->Header.PageNumber = 0; 1164230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1165230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1166230592Sken request->PageAddress = page_address; 1167230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1168230592Sken cm->cm_sge = &request->PageBufferSGE; 1169230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1170230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1171230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1172230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1173230592Sken if (!page) { 1174230592Sken printf("%s: page alloc failed\n", __func__); 1175230592Sken error = ENOMEM; 1176230592Sken goto out; 1177230592Sken } 1178230592Sken cm->cm_data = page; 1179230592Sken 1180253550Sken /* 1181253550Sken * This page must be polled because the IOC isn't ready yet when this 1182253550Sken * page is needed. 1183253550Sken */ 1184286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 1185230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1186230592Sken if (error || (reply == NULL)) { 1187230592Sken /* FIXME */ 1188230592Sken /* If the poll returns error then we need to do diag reset */ 1189230592Sken printf("%s: poll for page completed with error %d", 1190230592Sken __func__, error); 1191230592Sken error = ENXIO; 1192230592Sken goto out; 1193230592Sken } 1194230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1195230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1196230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1197230592Sken /* FIXME */ 1198230592Sken /* If the poll returns error then we need to do diag reset */ 1199230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1200230592Sken __func__, ioc_status); 1201230592Sken error = ENXIO; 1202230592Sken goto out; 1203230592Sken } 1204230592Sken bcopy(page, config_page, cm->cm_length); 1205230592Skenout: 1206230592Sken free(page, M_MPT2); 1207230592Sken if (cm) 1208230592Sken mps_free_command(sc, cm); 1209230592Sken return (error); 1210230592Sken} 1211230592Sken 1212230592Sken/** 1213230592Sken * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1214230592Sken * @sc: per adapter object 1215230592Sken * @mpi_reply: reply mf payload returned from firmware 1216230592Sken * @config_page: contents of the config page 1217230592Sken * @form: GET_NEXT_HANDLE or HANDLE 1218230592Sken * @handle: volume handle 1219230592Sken * Context: sleep. 1220230592Sken * 1221230592Sken * Returns 0 for success, non-zero for failure. 1222230592Sken */ 1223230592Skenint 1224230592Skenmps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1225230592Sken *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1226230592Sken{ 1227230592Sken MPI2_CONFIG_REQUEST *request; 1228230592Sken MPI2_CONFIG_REPLY *reply; 1229230592Sken struct mps_command *cm; 1230230592Sken Mpi2RaidVolPage1_t *page = NULL; 1231230592Sken int error = 0; 1232230592Sken u16 ioc_status; 1233230592Sken 1234230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1235230592Sken 1236230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1237230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1238230592Sken __LINE__); 1239230592Sken error = EBUSY; 1240230592Sken goto out; 1241230592Sken } 1242230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1243230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1244230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1245230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1246230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1247230592Sken request->Header.PageNumber = 1; 1248230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1249230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1250230592Sken cm->cm_data = NULL; 1251253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1252230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1253230592Sken if (error || (reply == NULL)) { 1254230592Sken /* FIXME */ 1255253550Sken /* 1256253550Sken * If the request returns an error then we need to do a diag 1257253550Sken * reset 1258253550Sken */ 1259253550Sken printf("%s: request for header completed with error %d", 1260230592Sken __func__, error); 1261230592Sken error = ENXIO; 1262230592Sken goto out; 1263230592Sken } 1264230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1265230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1266230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1267230592Sken /* FIXME */ 1268253550Sken /* 1269253550Sken * If the request returns an error then we need to do a diag 1270253550Sken * reset 1271253550Sken */ 1272230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1273230592Sken __func__, ioc_status); 1274230592Sken error = ENXIO; 1275230592Sken goto out; 1276230592Sken } 1277230592Sken /* We have to do free and alloc for the reply-free and reply-post 1278230592Sken * counters to match - Need to review the reply FIFO handling. 1279230592Sken */ 1280230592Sken mps_free_command(sc, cm); 1281230592Sken 1282230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1283230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1284230592Sken __LINE__); 1285230592Sken error = EBUSY; 1286230592Sken goto out; 1287230592Sken } 1288230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1289230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1290230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1291230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1292230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1293230592Sken request->Header.PageNumber = 1; 1294230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1295230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1296230592Sken request->PageAddress = htole32(form | handle); 1297230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1298230592Sken cm->cm_sge = &request->PageBufferSGE; 1299230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1300230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1301230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1302230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1303230592Sken if (!page) { 1304230592Sken printf("%s: page alloc failed\n", __func__); 1305230592Sken error = ENOMEM; 1306230592Sken goto out; 1307230592Sken } 1308230592Sken cm->cm_data = page; 1309230592Sken 1310253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1311230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1312230592Sken if (error || (reply == NULL)) { 1313230592Sken /* FIXME */ 1314253550Sken /* 1315253550Sken * If the request returns an error then we need to do a diag 1316253550Sken * reset 1317253550Sken */ 1318253550Sken printf("%s: request for page completed with error %d", 1319230592Sken __func__, error); 1320230592Sken error = ENXIO; 1321230592Sken goto out; 1322230592Sken } 1323230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1324230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1325230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1326230592Sken /* FIXME */ 1327253550Sken /* 1328253550Sken * If the request returns an error then we need to do a diag 1329253550Sken * reset 1330253550Sken */ 1331230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1332230592Sken __func__, ioc_status); 1333230592Sken error = ENXIO; 1334230592Sken goto out; 1335230592Sken } 1336230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1337230592Sken sizeof(Mpi2RaidVolPage1_t))); 1338230592Skenout: 1339230592Sken free(page, M_MPT2); 1340230592Sken if (cm) 1341230592Sken mps_free_command(sc, cm); 1342230592Sken return (error); 1343230592Sken} 1344230592Sken 1345230592Sken/** 1346230592Sken * mps_config_get_volume_wwid - returns wwid given the volume handle 1347230592Sken * @sc: per adapter object 1348230592Sken * @volume_handle: volume handle 1349230592Sken * @wwid: volume wwid 1350230592Sken * Context: sleep. 1351230592Sken * 1352230592Sken * Returns 0 for success, non-zero for failure. 1353230592Sken */ 1354230592Skenint 1355230592Skenmps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1356230592Sken{ 1357230592Sken Mpi2ConfigReply_t mpi_reply; 1358230592Sken Mpi2RaidVolPage1_t raid_vol_pg1; 1359230592Sken 1360230592Sken *wwid = 0; 1361230592Sken if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1362230592Sken MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1363230592Sken *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1364230592Sken raid_vol_pg1.WWID.Low); 1365230592Sken return 0; 1366230592Sken } else 1367230592Sken return -1; 1368230592Sken} 1369230592Sken 1370230592Sken/** 1371230592Sken * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1372230592Sken * @sc: per adapter object 1373230592Sken * @mpi_reply: reply mf payload returned from firmware 1374230592Sken * @config_page: contents of the config page 1375230592Sken * @page_address: form and handle value used to get page 1376230592Sken * Context: sleep. 1377230592Sken * 1378230592Sken * Returns 0 for success, non-zero for failure. 1379230592Sken */ 1380230592Skenint 1381230592Skenmps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1382230592Sken Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1383230592Sken{ 1384230592Sken MPI2_CONFIG_REQUEST *request; 1385230592Sken MPI2_CONFIG_REPLY *reply; 1386230592Sken struct mps_command *cm; 1387230592Sken Mpi2RaidPhysDiskPage0_t *page = NULL; 1388230592Sken int error = 0; 1389230592Sken u16 ioc_status; 1390230592Sken 1391230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1392230592Sken 1393230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1394230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1395230592Sken __LINE__); 1396230592Sken error = EBUSY; 1397230592Sken goto out; 1398230592Sken } 1399230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1400230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1401230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1402230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1403230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1404230592Sken request->Header.PageNumber = 0; 1405230592Sken request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1406230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1407230592Sken cm->cm_data = NULL; 1408253550Sken 1409253550Sken /* 1410253550Sken * This page must be polled because the IOC isn't ready yet when this 1411253550Sken * page is needed. 1412253550Sken */ 1413286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 1414230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1415230592Sken if (error || (reply == NULL)) { 1416230592Sken /* FIXME */ 1417230592Sken /* If the poll returns error then we need to do diag reset */ 1418230592Sken printf("%s: poll for header completed with error %d", 1419230592Sken __func__, error); 1420230592Sken error = ENXIO; 1421230592Sken goto out; 1422230592Sken } 1423230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1424230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1425230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1426230592Sken /* FIXME */ 1427230592Sken /* If the poll returns error then we need to do diag reset */ 1428230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1429230592Sken __func__, ioc_status); 1430230592Sken error = ENXIO; 1431230592Sken goto out; 1432230592Sken } 1433230592Sken /* We have to do free and alloc for the reply-free and reply-post 1434230592Sken * counters to match - Need to review the reply FIFO handling. 1435230592Sken */ 1436230592Sken mps_free_command(sc, cm); 1437230592Sken 1438230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1439230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1440230592Sken __LINE__); 1441230592Sken error = EBUSY; 1442230592Sken goto out; 1443230592Sken } 1444230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1445230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1446230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1447230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1448230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1449230592Sken request->Header.PageNumber = 0; 1450230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1451230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1452230592Sken request->PageAddress = page_address; 1453230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1454230592Sken cm->cm_sge = &request->PageBufferSGE; 1455230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1456230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1457230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1458230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1459230592Sken if (!page) { 1460230592Sken printf("%s: page alloc failed\n", __func__); 1461230592Sken error = ENOMEM; 1462230592Sken goto out; 1463230592Sken } 1464230592Sken cm->cm_data = page; 1465230592Sken 1466253550Sken /* 1467253550Sken * This page must be polled because the IOC isn't ready yet when this 1468253550Sken * page is needed. 1469253550Sken */ 1470286568Sscottl error = mps_wait_command(sc, cm, 60, 0); 1471230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1472230592Sken if (error || (reply == NULL)) { 1473230592Sken /* FIXME */ 1474230592Sken /* If the poll returns error then we need to do diag reset */ 1475230592Sken printf("%s: poll for page completed with error %d", 1476230592Sken __func__, error); 1477230592Sken error = ENXIO; 1478230592Sken goto out; 1479230592Sken } 1480230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1481230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1482230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1483230592Sken /* FIXME */ 1484230592Sken /* If the poll returns error then we need to do diag reset */ 1485230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1486230592Sken __func__, ioc_status); 1487230592Sken error = ENXIO; 1488230592Sken goto out; 1489230592Sken } 1490230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1491230592Sken sizeof(Mpi2RaidPhysDiskPage0_t))); 1492230592Skenout: 1493230592Sken free(page, M_MPT2); 1494230592Sken if (cm) 1495230592Sken mps_free_command(sc, cm); 1496230592Sken return (error); 1497230592Sken} 1498