1230592Sken/*- 2237876Sken * Copyright (c) 2011, 2012 LSI Corp. 3230592Sken * All rights reserved. 4230592Sken * 5230592Sken * Redistribution and use in source and binary forms, with or without 6230592Sken * modification, are permitted provided that the following conditions 7230592Sken * are met: 8230592Sken * 1. Redistributions of source code must retain the above copyright 9230592Sken * notice, this list of conditions and the following disclaimer. 10230592Sken * 2. Redistributions in binary form must reproduce the above copyright 11230592Sken * notice, this list of conditions and the following disclaimer in the 12230592Sken * documentation and/or other materials provided with the distribution. 13230592Sken * 14230592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15230592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16230592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17230592Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18230592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19230592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20230592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21230592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22230592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23230592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24230592Sken * SUCH DAMAGE. 25230592Sken * 26230592Sken * LSI MPT-Fusion Host Adapter FreeBSD 27230592Sken */ 28230592Sken 29230592Sken#include <sys/cdefs.h> 30230592Sken__FBSDID("$FreeBSD$"); 31230592Sken 32230592Sken/* TODO Move headers to mpsvar */ 33230592Sken#include <sys/types.h> 34230592Sken#include <sys/param.h> 35230592Sken#include <sys/lock.h> 36230592Sken#include <sys/mutex.h> 37230592Sken#include <sys/systm.h> 38230592Sken#include <sys/kernel.h> 39230592Sken#include <sys/malloc.h> 40230592Sken#include <sys/kthread.h> 41230592Sken#include <sys/taskqueue.h> 42230592Sken#include <sys/bus.h> 43230592Sken#include <sys/endian.h> 44230592Sken#include <sys/sysctl.h> 45230592Sken#include <sys/eventhandler.h> 46230592Sken#include <sys/uio.h> 47230592Sken#include <machine/bus.h> 48230592Sken#include <machine/resource.h> 49230592Sken#include <dev/mps/mpi/mpi2_type.h> 50230592Sken#include <dev/mps/mpi/mpi2.h> 51230592Sken#include <dev/mps/mpi/mpi2_ioc.h> 52230592Sken#include <dev/mps/mpi/mpi2_sas.h> 53230592Sken#include <dev/mps/mpi/mpi2_cnfg.h> 54230592Sken#include <dev/mps/mpi/mpi2_init.h> 55230592Sken#include <dev/mps/mpi/mpi2_tool.h> 56230592Sken#include <dev/mps/mps_ioctl.h> 57230592Sken#include <dev/mps/mpsvar.h> 58230592Sken 59230592Sken/** 60230592Sken * mps_config_get_ioc_pg8 - obtain ioc page 8 61230592Sken * @sc: per adapter object 62230592Sken * @mpi_reply: reply mf payload returned from firmware 63230592Sken * @config_page: contents of the config page 64230592Sken * Context: sleep. 65230592Sken * 66230592Sken * Returns 0 for success, non-zero for failure. 67230592Sken */ 68230592Skenint 69230592Skenmps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 70230592Sken Mpi2IOCPage8_t *config_page) 71230592Sken{ 72230592Sken MPI2_CONFIG_REQUEST *request; 73230592Sken MPI2_CONFIG_REPLY *reply; 74230592Sken struct mps_command *cm; 75230592Sken MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 76230592Sken int error = 0; 77230592Sken u16 ioc_status; 78230592Sken 79230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 80230592Sken 81230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 82230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 83230592Sken __LINE__); 84230592Sken error = EBUSY; 85230592Sken goto out; 86230592Sken } 87230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 88230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 89230592Sken request->Function = MPI2_FUNCTION_CONFIG; 90230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 91230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 92230592Sken request->Header.PageNumber = 8; 93230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 94230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 95230592Sken cm->cm_data = NULL; 96254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 97230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 98230592Sken if (error || (reply == NULL)) { 99230592Sken /* FIXME */ 100254938Sken /* 101254938Sken * If the request returns an error then we need to do a diag 102254938Sken * reset 103254938Sken */ 104254938Sken printf("%s: request for header completed with error %d", 105230592Sken __func__, error); 106230592Sken error = ENXIO; 107230592Sken goto out; 108230592Sken } 109230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 110230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 111230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 112230592Sken /* FIXME */ 113254938Sken /* 114254938Sken * If the request returns an error then we need to do a diag 115254938Sken * reset 116254938Sken */ 117230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 118230592Sken __func__, ioc_status); 119230592Sken error = ENXIO; 120230592Sken goto out; 121230592Sken } 122230592Sken /* We have to do free and alloc for the reply-free and reply-post 123230592Sken * counters to match - Need to review the reply FIFO handling. 124230592Sken */ 125230592Sken mps_free_command(sc, cm); 126230592Sken 127230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 128230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 129230592Sken __LINE__); 130230592Sken error = EBUSY; 131230592Sken goto out; 132230592Sken } 133230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 134230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 135230592Sken request->Function = MPI2_FUNCTION_CONFIG; 136230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 137230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 138230592Sken request->Header.PageNumber = 8; 139230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 140230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 141230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 142230592Sken cm->cm_sge = &request->PageBufferSGE; 143230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 144230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 145230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 146230592Sken page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT); 147230592Sken if (!page) { 148230592Sken printf("%s: page alloc failed\n", __func__); 149230592Sken error = ENOMEM; 150230592Sken goto out; 151230592Sken } 152230592Sken cm->cm_data = page; 153254938Sken 154254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 155230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 156230592Sken if (error || (reply == NULL)) { 157230592Sken /* FIXME */ 158254938Sken /* 159254938Sken * If the request returns an error then we need to do a diag 160254938Sken * reset 161254938Sken */ 162254938Sken printf("%s: request for page completed with error %d", 163230592Sken __func__, error); 164230592Sken error = ENXIO; 165230592Sken goto out; 166230592Sken } 167230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 168230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 169230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 170230592Sken /* FIXME */ 171254938Sken /* 172254938Sken * If the request returns an error then we need to do a diag 173254938Sken * reset 174254938Sken */ 175230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 176230592Sken __func__, ioc_status); 177230592Sken error = ENXIO; 178230592Sken goto out; 179230592Sken } 180230592Sken bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 181230592Sken 182230592Skenout: 183230592Sken free(page, M_MPT2); 184230592Sken if (cm) 185230592Sken mps_free_command(sc, cm); 186230592Sken return (error); 187230592Sken} 188230592Sken 189230592Sken/** 190230592Sken * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags 191230592Sken * accordingly. Currently, this page does not need to return to caller. 192230592Sken * @sc: per adapter object 193230592Sken * @mpi_reply: reply mf payload returned from firmware 194230592Sken * Context: sleep. 195230592Sken * 196230592Sken * Returns 0 for success, non-zero for failure. 197230592Sken */ 198230592Skenint 199230592Skenmps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) 200230592Sken{ 201230592Sken MPI2_CONFIG_REQUEST *request; 202230592Sken MPI2_CONFIG_REPLY *reply; 203230592Sken struct mps_command *cm; 204230592Sken pMpi2ManufacturingPagePS_t page = NULL; 205230592Sken uint32_t *pPS_info; 206230592Sken uint8_t OEM_Value = 0; 207230592Sken int error = 0; 208230592Sken u16 ioc_status; 209230592Sken 210230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 211230592Sken 212230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 213230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 214230592Sken __LINE__); 215230592Sken error = EBUSY; 216230592Sken goto out; 217230592Sken } 218230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 219230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 220230592Sken request->Function = MPI2_FUNCTION_CONFIG; 221230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 222230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 223230592Sken request->Header.PageNumber = 10; 224230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 225230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 226230592Sken cm->cm_data = NULL; 227254938Sken 228254938Sken /* 229254938Sken * This page must be polled because the IOC isn't ready yet when this 230254938Sken * page is needed. 231254938Sken */ 232230592Sken error = mps_request_polled(sc, cm); 233230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 234230592Sken if (error || (reply == NULL)) { 235230592Sken /* FIXME */ 236230592Sken /* If the poll returns error then we need to do diag reset */ 237230592Sken printf("%s: poll for header completed with error %d", 238230592Sken __func__, error); 239230592Sken error = ENXIO; 240230592Sken goto out; 241230592Sken } 242230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 243230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 244230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 245230592Sken /* FIXME */ 246230592Sken /* If the poll returns error then we need to do diag reset */ 247230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 248230592Sken __func__, ioc_status); 249230592Sken error = ENXIO; 250230592Sken goto out; 251230592Sken } 252230592Sken /* We have to do free and alloc for the reply-free and reply-post 253230592Sken * counters to match - Need to review the reply FIFO handling. 254230592Sken */ 255230592Sken mps_free_command(sc, cm); 256230592Sken 257230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 258230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 259230592Sken __LINE__); 260230592Sken error = EBUSY; 261230592Sken goto out; 262230592Sken } 263230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 264230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 265230592Sken request->Function = MPI2_FUNCTION_CONFIG; 266230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 267230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 268230592Sken request->Header.PageNumber = 10; 269230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 270230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 271230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 272230592Sken cm->cm_sge = &request->PageBufferSGE; 273230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 274230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 275230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 276230592Sken page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT); 277230592Sken if (!page) { 278230592Sken printf("%s: page alloc failed\n", __func__); 279230592Sken error = ENOMEM; 280230592Sken goto out; 281230592Sken } 282230592Sken cm->cm_data = page; 283254938Sken 284254938Sken /* 285254938Sken * This page must be polled because the IOC isn't ready yet when this 286254938Sken * page is needed. 287254938Sken */ 288230592Sken error = mps_request_polled(sc, cm); 289230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 290230592Sken if (error || (reply == NULL)) { 291230592Sken /* FIXME */ 292230592Sken /* If the poll returns error then we need to do diag reset */ 293230592Sken printf("%s: poll for page completed with error %d", 294230592Sken __func__, error); 295230592Sken error = ENXIO; 296230592Sken goto out; 297230592Sken } 298230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 299230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 300230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 301230592Sken /* FIXME */ 302230592Sken /* If the poll returns error then we need to do diag reset */ 303230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 304230592Sken __func__, ioc_status); 305230592Sken error = ENXIO; 306230592Sken goto out; 307230592Sken } 308230592Sken 309230592Sken /* 310230592Sken * If OEM ID is unknown, fail the request. 311230592Sken */ 312230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 313230592Sken OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF); 314230592Sken if (OEM_Value != MPS_WD_LSI_OEM) { 315230592Sken mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive " 316230592Sken "(0x%x)\n", OEM_Value); 317230592Sken error = ENXIO; 318230592Sken goto out; 319230592Sken } 320230592Sken 321230592Sken /* 322230592Sken * Set the phys disks hide/expose value. 323230592Sken */ 324230592Sken pPS_info = &page->ProductSpecificInfo; 325230592Sken sc->WD_hide_expose = (uint8_t)(pPS_info[5]); 326230592Sken sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK; 327230592Sken if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) && 328230592Sken (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) && 329230592Sken (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) { 330230592Sken mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive " 331230592Sken "hide/expose: 0x%x\n", sc->WD_hide_expose); 332230592Sken error = ENXIO; 333230592Sken goto out; 334230592Sken } 335230592Sken 336230592Skenout: 337230592Sken free(page, M_MPT2); 338230592Sken if (cm) 339230592Sken mps_free_command(sc, cm); 340230592Sken return (error); 341230592Sken} 342230592Sken 343230592Sken/** 344230592Sken * mps_base_static_config_pages - static start of day config pages. 345230592Sken * @sc: per adapter object 346230592Sken * 347230592Sken * Return nothing. 348230592Sken */ 349230592Skenvoid 350230592Skenmps_base_static_config_pages(struct mps_softc *sc) 351230592Sken{ 352230592Sken Mpi2ConfigReply_t mpi_reply; 353230592Sken int retry; 354230592Sken 355230592Sken retry = 0; 356230592Sken while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 357230592Sken retry++; 358230592Sken if (retry > 5) { 359230592Sken /* We need to Handle this situation */ 360230592Sken /*FIXME*/ 361230592Sken break; 362230592Sken } 363230592Sken } 364230592Sken} 365230592Sken 366230592Sken/** 367230592Sken * mps_wd_config_pages - get info required to support WarpDrive. This needs to 368230592Sken * be called after discovery is complete to guarentee that IR info is there. 369230592Sken * @sc: per adapter object 370230592Sken * 371230592Sken * Return nothing. 372230592Sken */ 373230592Skenvoid 374230592Skenmps_wd_config_pages(struct mps_softc *sc) 375230592Sken{ 376230592Sken Mpi2ConfigReply_t mpi_reply; 377230592Sken pMpi2RaidVolPage0_t raid_vol_pg0 = NULL; 378230592Sken Mpi2RaidPhysDiskPage0_t phys_disk_pg0; 379230592Sken pMpi2RaidVol0PhysDisk_t pRVPD; 380230592Sken uint32_t stripe_size, phys_disk_page_address; 381230592Sken uint16_t block_size; 382230592Sken uint8_t index, stripe_exp = 0, block_exp = 0; 383230592Sken 384230592Sken /* 385230592Sken * Get the WD settings from manufacturing page 10 if using a WD HBA. 386230592Sken * This will be used to determine if phys disks should always be 387230592Sken * hidden, hidden only if part of a WD volume, or never hidden. Also, 388230592Sken * get the WD RAID Volume info and fail if volume does not exist or if 389230592Sken * volume does not meet the requirements for a WD volume. No retry 390230592Sken * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD 391230592Sken * Valid flag if Volume info fails. 392230592Sken */ 393230592Sken sc->WD_valid_config = FALSE; 394230592Sken if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { 395230592Sken if (mps_config_get_man_pg10(sc, &mpi_reply)) { 396230592Sken mps_dprint(sc, MPS_FAULT, 397230592Sken "mps_config_get_man_pg10 failed! Using 0 (Hide " 398230592Sken "Always) for WarpDrive hide/expose value.\n"); 399230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 400230592Sken } 401230592Sken 402230592Sken /* 403230592Sken * Get first RAID Volume Page0 using GET_NEXT_HANDLE. 404230592Sken */ 405230592Sken raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) + 406230592Sken (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL), 407230592Sken M_MPT2, M_ZERO | M_NOWAIT); 408230592Sken if (!raid_vol_pg0) { 409230592Sken printf("%s: page alloc failed\n", __func__); 410230592Sken goto out; 411230592Sken } 412230592Sken 413230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0, 414230592Sken 0x0000FFFF)) { 415230592Sken mps_dprint(sc, MPS_INFO, 416230592Sken "mps_config_get_raid_volume_pg0 failed! Assuming " 417230592Sken "WarpDrive IT mode.\n"); 418230592Sken goto out; 419230592Sken } 420230592Sken 421230592Sken /* 422230592Sken * Check for valid WD configuration: 423230592Sken * volume type is RAID0 424230592Sken * number of phys disks in the volume is no more than 8 425230592Sken */ 426230592Sken if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) || 427230592Sken (raid_vol_pg0->NumPhysDisks > 8)) { 428230592Sken mps_dprint(sc, MPS_FAULT, 429230592Sken "Invalid WarpDrive configuration. Direct Drive I/O " 430230592Sken "will not be used.\n"); 431230592Sken goto out; 432230592Sken } 433230592Sken 434230592Sken /* 435230592Sken * Save the WD RAID data to be used during WD I/O. 436230592Sken */ 437230592Sken sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High << 438230592Sken 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low); 439230592Sken sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks; 440230592Sken sc->DD_dev_handle = raid_vol_pg0->DevHandle; 441230592Sken sc->DD_stripe_size = raid_vol_pg0->StripeSize; 442230592Sken sc->DD_block_size = raid_vol_pg0->BlockSize; 443230592Sken 444230592Sken /* 445230592Sken * Find power of 2 of stripe size and set this as the exponent. 446230592Sken * Fail if stripe size is 0. 447230592Sken */ 448230592Sken stripe_size = raid_vol_pg0->StripeSize; 449230592Sken for (index = 0; index < 32; index++) { 450230592Sken if (stripe_size & 1) 451230592Sken break; 452230592Sken stripe_exp++; 453230592Sken stripe_size >>= 1; 454230592Sken } 455230592Sken if (index == 32) { 456230592Sken mps_dprint(sc, MPS_FAULT, 457230592Sken "RAID Volume's stripe size is 0. Direct Drive I/O " 458230592Sken "will not be used.\n"); 459230592Sken goto out; 460230592Sken } 461230592Sken sc->DD_stripe_exponent = stripe_exp; 462230592Sken 463230592Sken /* 464230592Sken * Find power of 2 of block size and set this as the exponent. 465230592Sken * Fail if block size is 0. 466230592Sken */ 467230592Sken block_size = raid_vol_pg0->BlockSize; 468230592Sken for (index = 0; index < 16; index++) { 469230592Sken if (block_size & 1) 470230592Sken break; 471230592Sken block_exp++; 472230592Sken block_size >>= 1; 473230592Sken } 474230592Sken if (index == 16) { 475230592Sken mps_dprint(sc, MPS_FAULT, 476230592Sken "RAID Volume's block size is 0. Direct Drive I/O " 477230592Sken "will not be used.\n"); 478230592Sken goto out; 479230592Sken } 480230592Sken sc->DD_block_exponent = block_exp; 481230592Sken 482230592Sken /* 483230592Sken * Loop through all of the volume's Phys Disks to map the phys 484230592Sken * disk number into the columm map. This is used during Direct 485230592Sken * Drive I/O to send the request to the correct SSD. 486230592Sken */ 487230592Sken pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk; 488230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 489230592Sken sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num = 490230592Sken pRVPD->PhysDiskNum; 491230592Sken pRVPD++; 492230592Sken } 493230592Sken 494230592Sken /* 495230592Sken * Get second RAID Volume Page0 using previous handle. This 496230592Sken * page should not exist. If it does, must not proceed with WD 497230592Sken * handling. 498230592Sken */ 499230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, 500230592Sken raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) { 501230592Sken if (mpi_reply.IOCStatus != 502230592Sken MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 503230592Sken mps_dprint(sc, MPS_FAULT, 504230592Sken "Multiple RAID Volume Page0! Direct Drive " 505230592Sken "I/O will not be used.\n"); 506230592Sken goto out; 507230592Sken } 508230592Sken } else { 509230592Sken mps_dprint(sc, MPS_FAULT, 510230592Sken "Multiple volumes! Direct Drive I/O will not be " 511230592Sken "used.\n"); 512230592Sken goto out; 513230592Sken } 514230592Sken 515230592Sken /* 516230592Sken * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 517230592Sken */ 518230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 519230592Sken phys_disk_page_address = 520230592Sken MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 521230592Sken sc->DD_column_map[index].phys_disk_num; 522230592Sken if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 523230592Sken &phys_disk_pg0, phys_disk_page_address)) { 524230592Sken mps_dprint(sc, MPS_FAULT, 525230592Sken "mps_config_get_raid_pd_pg0 failed! Direct " 526230592Sken "Drive I/O will not be used.\n"); 527230592Sken goto out; 528230592Sken } 529230592Sken if (phys_disk_pg0.DevHandle == 0xFFFF) { 530230592Sken mps_dprint(sc, MPS_FAULT, 531230592Sken "Invalid Phys Disk DevHandle! Direct Drive " 532230592Sken "I/O will not be used.\n"); 533230592Sken goto out; 534230592Sken } 535230592Sken sc->DD_column_map[index].dev_handle = 536230592Sken phys_disk_pg0.DevHandle; 537230592Sken } 538230592Sken sc->WD_valid_config = TRUE; 539230592Skenout: 540230592Sken if (raid_vol_pg0) 541230592Sken free(raid_vol_pg0, M_MPT2); 542230592Sken } 543230592Sken} 544230592Sken 545230592Sken/** 546230592Sken * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 547230592Sken * @sc: per adapter object 548230592Sken * @mpi_reply: reply mf payload returned from firmware 549230592Sken * @config_page: contents of the config page 550230592Sken * @sz: size of buffer passed in config_page 551230592Sken * Context: sleep. 552230592Sken * 553230592Sken * Returns 0 for success, non-zero for failure. 554230592Sken */ 555230592Skenint 556230592Skenmps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 557230592Sken Mpi2DriverMappingPage0_t *config_page, u16 sz) 558230592Sken{ 559230592Sken MPI2_CONFIG_REQUEST *request; 560230592Sken MPI2_CONFIG_REPLY *reply; 561230592Sken struct mps_command *cm; 562230592Sken Mpi2DriverMappingPage0_t *page = NULL; 563230592Sken int error = 0; 564230592Sken u16 ioc_status; 565230592Sken 566230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 567230592Sken 568230592Sken memset(config_page, 0, sz); 569230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 570230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 571230592Sken __LINE__); 572230592Sken error = EBUSY; 573230592Sken goto out; 574230592Sken } 575230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 576230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 577230592Sken request->Function = MPI2_FUNCTION_CONFIG; 578230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 579230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 580230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 581230592Sken request->Header.PageNumber = 0; 582230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 583230592Sken request->PageAddress = sc->max_dpm_entries << 584230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 585230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 586230592Sken cm->cm_data = NULL; 587254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 588230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 589230592Sken if (error || (reply == NULL)) { 590230592Sken /* FIXME */ 591254938Sken /* 592254938Sken * If the request returns an error then we need to do a diag 593254938Sken * reset 594254938Sken */ 595254938Sken printf("%s: request for header completed with error %d", 596230592Sken __func__, error); 597230592Sken error = ENXIO; 598230592Sken goto out; 599230592Sken } 600230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 601230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 602230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 603230592Sken /* FIXME */ 604254938Sken /* 605254938Sken * If the request returns an error then we need to do a diag 606254938Sken * reset 607254938Sken */ 608230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 609230592Sken __func__, ioc_status); 610230592Sken error = ENXIO; 611230592Sken goto out; 612230592Sken } 613230592Sken /* We have to do free and alloc for the reply-free and reply-post 614230592Sken * counters to match - Need to review the reply FIFO handling. 615230592Sken */ 616230592Sken mps_free_command(sc, cm); 617230592Sken 618230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 619230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 620230592Sken __LINE__); 621230592Sken error = EBUSY; 622230592Sken goto out; 623230592Sken } 624230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 625230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 626230592Sken request->Function = MPI2_FUNCTION_CONFIG; 627230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 628230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 629230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 630230592Sken request->Header.PageNumber = 0; 631230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 632230592Sken request->PageAddress = sc->max_dpm_entries << 633230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 634230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 635230592Sken cm->cm_length = le16toh(request->ExtPageLength) * 4; 636230592Sken cm->cm_sge = &request->PageBufferSGE; 637230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 638230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 639230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 640230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 641230592Sken if (!page) { 642230592Sken printf("%s: page alloc failed\n", __func__); 643230592Sken error = ENOMEM; 644230592Sken goto out; 645230592Sken } 646230592Sken cm->cm_data = page; 647254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 648230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 649230592Sken if (error || (reply == NULL)) { 650230592Sken /* FIXME */ 651254938Sken /* 652254938Sken * If the request returns an error then we need to do a diag 653254938Sken * reset 654254938Sken */ 655254938Sken printf("%s: request for page completed with error %d", 656230592Sken __func__, error); 657230592Sken error = ENXIO; 658230592Sken goto out; 659230592Sken } 660230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 661230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 662230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 663230592Sken /* FIXME */ 664254938Sken /* 665254938Sken * If the request returns an error then we need to do a diag 666254938Sken * reset 667254938Sken */ 668230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 669230592Sken __func__, ioc_status); 670230592Sken error = ENXIO; 671230592Sken goto out; 672230592Sken } 673230592Sken bcopy(page, config_page, MIN(cm->cm_length, sz)); 674230592Skenout: 675230592Sken free(page, M_MPT2); 676230592Sken if (cm) 677230592Sken mps_free_command(sc, cm); 678230592Sken return (error); 679230592Sken} 680230592Sken 681230592Sken/** 682230592Sken * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 683230592Sken * @sc: per adapter object 684230592Sken * @mpi_reply: reply mf payload returned from firmware 685230592Sken * @config_page: contents of the config page 686230592Sken * @entry_idx: entry index in DPM Page0 to be modified 687230592Sken * Context: sleep. 688230592Sken * 689230592Sken * Returns 0 for success, non-zero for failure. 690230592Sken */ 691230592Sken 692230592Skenint mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 693230592Sken Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 694230592Sken{ 695230592Sken MPI2_CONFIG_REQUEST *request; 696230592Sken MPI2_CONFIG_REPLY *reply; 697230592Sken struct mps_command *cm; 698230592Sken MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 699230592Sken int error = 0; 700230592Sken u16 ioc_status; 701230592Sken 702230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 703230592Sken 704230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 705230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 706230592Sken __LINE__); 707230592Sken error = EBUSY; 708230592Sken goto out; 709230592Sken } 710230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 711230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 712230592Sken request->Function = MPI2_FUNCTION_CONFIG; 713230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 714230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 715230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 716230592Sken request->Header.PageNumber = 0; 717230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 718237876Sken /* We can remove below two lines ????*/ 719230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 720230592Sken request->PageAddress |= htole16(entry_idx); 721230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 722230592Sken cm->cm_data = NULL; 723254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 724230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 725230592Sken if (error || (reply == NULL)) { 726230592Sken /* FIXME */ 727254938Sken /* 728254938Sken * If the request returns an error then we need to do a diag 729254938Sken * reset 730254938Sken */ 731254938Sken printf("%s: request for header completed with error %d", 732230592Sken __func__, error); 733230592Sken error = ENXIO; 734230592Sken goto out; 735230592Sken } 736230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 737230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 738230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 739230592Sken /* FIXME */ 740254938Sken /* 741254938Sken * If the request returns an error then we need to do a diag 742254938Sken * reset 743254938Sken */ 744230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 745230592Sken __func__, ioc_status); 746230592Sken error = ENXIO; 747230592Sken goto out; 748230592Sken } 749230592Sken /* We have to do free and alloc for the reply-free and reply-post 750230592Sken * counters to match - Need to review the reply FIFO handling. 751230592Sken */ 752230592Sken mps_free_command(sc, cm); 753230592Sken 754230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 755230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 756230592Sken __LINE__); 757230592Sken error = EBUSY; 758230592Sken goto out; 759230592Sken } 760230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 761230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 762230592Sken request->Function = MPI2_FUNCTION_CONFIG; 763230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 764230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 765230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 766230592Sken request->Header.PageNumber = 0; 767230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 768230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 769230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 770230592Sken request->PageAddress |= htole16(entry_idx); 771230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 772230592Sken cm->cm_sge = &request->PageBufferSGE; 773230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 774230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 775230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 776230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 777230592Sken if (!page) { 778230592Sken printf("%s: page alloc failed\n", __func__); 779230592Sken error = ENOMEM; 780230592Sken goto out; 781230592Sken } 782230592Sken bcopy(config_page, page, MIN(cm->cm_length, 783230592Sken (sizeof(Mpi2DriverMappingPage0_t)))); 784230592Sken cm->cm_data = page; 785254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 786230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 787230592Sken if (error || (reply == NULL)) { 788230592Sken /* FIXME */ 789254938Sken /* 790254938Sken * If the request returns an error then we need to do a diag 791254938Sken * reset 792254938Sken */ 793254938Sken printf("%s: request to write page completed with error %d", 794230592Sken __func__, error); 795230592Sken error = ENXIO; 796230592Sken goto out; 797230592Sken } 798230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 799230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 800230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 801230592Sken /* FIXME */ 802254938Sken /* 803254938Sken * If the request returns an error then we need to do a diag 804254938Sken * reset 805254938Sken */ 806230592Sken printf("%s: page written with error; iocstatus = 0x%x\n", 807230592Sken __func__, ioc_status); 808230592Sken error = ENXIO; 809230592Sken goto out; 810230592Sken } 811230592Skenout: 812230592Sken free(page, M_MPT2); 813230592Sken if (cm) 814230592Sken mps_free_command(sc, cm); 815230592Sken return (error); 816230592Sken} 817230592Sken 818230592Sken/** 819230592Sken * mps_config_get_sas_device_pg0 - obtain sas device page 0 820230592Sken * @sc: per adapter object 821230592Sken * @mpi_reply: reply mf payload returned from firmware 822230592Sken * @config_page: contents of the config page 823230592Sken * @form: GET_NEXT_HANDLE or HANDLE 824230592Sken * @handle: device handle 825230592Sken * Context: sleep. 826230592Sken * 827230592Sken * Returns 0 for success, non-zero for failure. 828230592Sken */ 829230592Skenint 830230592Skenmps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 831230592Sken *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 832230592Sken{ 833230592Sken MPI2_CONFIG_REQUEST *request; 834230592Sken MPI2_CONFIG_REPLY *reply; 835230592Sken struct mps_command *cm; 836230592Sken Mpi2SasDevicePage0_t *page = NULL; 837230592Sken int error = 0; 838230592Sken u16 ioc_status; 839230592Sken 840230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 841230592Sken 842230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 843230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 844230592Sken __LINE__); 845230592Sken error = EBUSY; 846230592Sken goto out; 847230592Sken } 848230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 849230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 850230592Sken request->Function = MPI2_FUNCTION_CONFIG; 851230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 852230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 853230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 854230592Sken request->Header.PageNumber = 0; 855230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 856230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 857230592Sken cm->cm_data = NULL; 858254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 859230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 860230592Sken if (error || (reply == NULL)) { 861230592Sken /* FIXME */ 862254938Sken /* 863254938Sken * If the request returns an error then we need to do a diag 864254938Sken * reset 865254938Sken */ 866254938Sken printf("%s: request for header completed with error %d", 867230592Sken __func__, error); 868230592Sken error = ENXIO; 869230592Sken goto out; 870230592Sken } 871230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 872230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 873230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 874230592Sken /* FIXME */ 875254938Sken /* 876254938Sken * If the request returns an error then we need to do a diag 877254938Sken * reset 878254938Sken */ 879230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 880230592Sken __func__, ioc_status); 881230592Sken error = ENXIO; 882230592Sken goto out; 883230592Sken } 884230592Sken /* We have to do free and alloc for the reply-free and reply-post 885230592Sken * counters to match - Need to review the reply FIFO handling. 886230592Sken */ 887230592Sken mps_free_command(sc, cm); 888230592Sken 889230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 890230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 891230592Sken __LINE__); 892230592Sken error = EBUSY; 893230592Sken goto out; 894230592Sken } 895230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 896230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 897230592Sken request->Function = MPI2_FUNCTION_CONFIG; 898230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 899230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 900230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 901230592Sken request->Header.PageNumber = 0; 902230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 903230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 904230592Sken request->PageAddress = htole32(form | handle); 905230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 906230592Sken cm->cm_sge = &request->PageBufferSGE; 907230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 908230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 909230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 910230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 911230592Sken if (!page) { 912230592Sken printf("%s: page alloc failed\n", __func__); 913230592Sken error = ENOMEM; 914230592Sken goto out; 915230592Sken } 916230592Sken cm->cm_data = page; 917230592Sken 918254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 919230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 920230592Sken if (error || (reply == NULL)) { 921230592Sken /* FIXME */ 922254938Sken /* 923254938Sken * If the request returns an error then we need to do a diag 924254938Sken * reset 925254938Sken */ 926254938Sken printf("%s: request for page completed with error %d", 927230592Sken __func__, error); 928230592Sken error = ENXIO; 929230592Sken goto out; 930230592Sken } 931230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 932230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 933230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 934230592Sken /* FIXME */ 935254938Sken /* 936254938Sken * If the request returns an error then we need to do a diag 937254938Sken * reset 938254938Sken */ 939230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 940230592Sken __func__, ioc_status); 941230592Sken error = ENXIO; 942230592Sken goto out; 943230592Sken } 944230592Sken bcopy(page, config_page, MIN(cm->cm_length, 945230592Sken sizeof(Mpi2SasDevicePage0_t))); 946230592Skenout: 947230592Sken free(page, M_MPT2); 948230592Sken if (cm) 949230592Sken mps_free_command(sc, cm); 950230592Sken return (error); 951230592Sken} 952230592Sken 953230592Sken/** 954230592Sken * mps_config_get_bios_pg3 - obtain BIOS page 3 955230592Sken * @sc: per adapter object 956230592Sken * @mpi_reply: reply mf payload returned from firmware 957230592Sken * @config_page: contents of the config page 958230592Sken * Context: sleep. 959230592Sken * 960230592Sken * Returns 0 for success, non-zero for failure. 961230592Sken */ 962230592Skenint 963230592Skenmps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 964230592Sken Mpi2BiosPage3_t *config_page) 965230592Sken{ 966230592Sken MPI2_CONFIG_REQUEST *request; 967230592Sken MPI2_CONFIG_REPLY *reply; 968230592Sken struct mps_command *cm; 969230592Sken Mpi2BiosPage3_t *page = NULL; 970230592Sken int error = 0; 971230592Sken u16 ioc_status; 972230592Sken 973230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 974230592Sken 975230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 976230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 977230592Sken __LINE__); 978230592Sken error = EBUSY; 979230592Sken goto out; 980230592Sken } 981230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 982230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 983230592Sken request->Function = MPI2_FUNCTION_CONFIG; 984230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 985230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 986230592Sken request->Header.PageNumber = 3; 987230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 988230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 989230592Sken cm->cm_data = NULL; 990254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 991230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 992230592Sken if (error || (reply == NULL)) { 993230592Sken /* FIXME */ 994254938Sken /* 995254938Sken * If the request returns an error then we need to do a diag 996254938Sken * reset 997254938Sken */ 998254938Sken printf("%s: request for header completed with error %d", 999230592Sken __func__, error); 1000230592Sken error = ENXIO; 1001230592Sken goto out; 1002230592Sken } 1003230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1004230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1005230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1006230592Sken /* FIXME */ 1007254938Sken /* 1008254938Sken * If the request returns an error then we need to do a diag 1009254938Sken * reset 1010254938Sken */ 1011230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1012230592Sken __func__, ioc_status); 1013230592Sken error = ENXIO; 1014230592Sken goto out; 1015230592Sken } 1016230592Sken /* We have to do free and alloc for the reply-free and reply-post 1017230592Sken * counters to match - Need to review the reply FIFO handling. 1018230592Sken */ 1019230592Sken mps_free_command(sc, cm); 1020230592Sken 1021230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1022230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1023230592Sken __LINE__); 1024230592Sken error = EBUSY; 1025230592Sken goto out; 1026230592Sken } 1027230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1028230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1029230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1030230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1031230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1032230592Sken request->Header.PageNumber = 3; 1033230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1034230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1035230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1036230592Sken cm->cm_sge = &request->PageBufferSGE; 1037230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1038230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1039230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1040230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1041230592Sken if (!page) { 1042230592Sken printf("%s: page alloc failed\n", __func__); 1043230592Sken error = ENOMEM; 1044230592Sken goto out; 1045230592Sken } 1046230592Sken cm->cm_data = page; 1047230592Sken 1048254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1049230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1050230592Sken if (error || (reply == NULL)) { 1051230592Sken /* FIXME */ 1052254938Sken /* 1053254938Sken * If the request returns an error then we need to do a diag 1054254938Sken * reset 1055254938Sken */ 1056254938Sken printf("%s: request for page completed with error %d", 1057230592Sken __func__, error); 1058230592Sken error = ENXIO; 1059230592Sken goto out; 1060230592Sken } 1061230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1062230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1063230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1064230592Sken /* FIXME */ 1065254938Sken /* 1066254938Sken * If the request returns an error then we need to do a diag 1067254938Sken * reset 1068254938Sken */ 1069230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1070230592Sken __func__, ioc_status); 1071230592Sken error = ENXIO; 1072230592Sken goto out; 1073230592Sken } 1074230592Sken bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1075230592Skenout: 1076230592Sken free(page, M_MPT2); 1077230592Sken if (cm) 1078230592Sken mps_free_command(sc, cm); 1079230592Sken return (error); 1080230592Sken} 1081230592Sken 1082230592Sken/** 1083230592Sken * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1084230592Sken * @sc: per adapter object 1085230592Sken * @mpi_reply: reply mf payload returned from firmware 1086230592Sken * @config_page: contents of the config page 1087230592Sken * @page_address: form and handle value used to get page 1088230592Sken * Context: sleep. 1089230592Sken * 1090230592Sken * Returns 0 for success, non-zero for failure. 1091230592Sken */ 1092230592Skenint 1093230592Skenmps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1094230592Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1095230592Sken{ 1096230592Sken MPI2_CONFIG_REQUEST *request; 1097230592Sken MPI2_CONFIG_REPLY *reply; 1098230592Sken struct mps_command *cm; 1099230592Sken Mpi2RaidVolPage0_t *page = NULL; 1100230592Sken int error = 0; 1101230592Sken u16 ioc_status; 1102230592Sken 1103230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1104230592Sken 1105230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1106230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1107230592Sken __LINE__); 1108230592Sken error = EBUSY; 1109230592Sken goto out; 1110230592Sken } 1111230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1112230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1113230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1114230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1115230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1116230592Sken request->Header.PageNumber = 0; 1117230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1118230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1119230592Sken cm->cm_data = NULL; 1120254938Sken 1121254938Sken /* 1122254938Sken * This page must be polled because the IOC isn't ready yet when this 1123254938Sken * page is needed. 1124254938Sken */ 1125230592Sken error = mps_request_polled(sc, cm); 1126230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1127230592Sken if (error || (reply == NULL)) { 1128230592Sken /* FIXME */ 1129230592Sken /* If the poll returns error then we need to do diag reset */ 1130230592Sken printf("%s: poll for header completed with error %d", 1131230592Sken __func__, error); 1132230592Sken error = ENXIO; 1133230592Sken goto out; 1134230592Sken } 1135230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1136230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1137230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1138230592Sken /* FIXME */ 1139230592Sken /* If the poll returns error then we need to do diag reset */ 1140230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1141230592Sken __func__, ioc_status); 1142230592Sken error = ENXIO; 1143230592Sken goto out; 1144230592Sken } 1145230592Sken /* We have to do free and alloc for the reply-free and reply-post 1146230592Sken * counters to match - Need to review the reply FIFO handling. 1147230592Sken */ 1148230592Sken mps_free_command(sc, cm); 1149230592Sken 1150230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1151230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1152230592Sken __LINE__); 1153230592Sken error = EBUSY; 1154230592Sken goto out; 1155230592Sken } 1156230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1157230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1158230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1159230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1160230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1161230592Sken request->Header.PageNumber = 0; 1162230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1163230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1164230592Sken request->PageAddress = page_address; 1165230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1166230592Sken cm->cm_sge = &request->PageBufferSGE; 1167230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1168230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1169230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1170230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1171230592Sken if (!page) { 1172230592Sken printf("%s: page alloc failed\n", __func__); 1173230592Sken error = ENOMEM; 1174230592Sken goto out; 1175230592Sken } 1176230592Sken cm->cm_data = page; 1177230592Sken 1178254938Sken /* 1179254938Sken * This page must be polled because the IOC isn't ready yet when this 1180254938Sken * page is needed. 1181254938Sken */ 1182230592Sken error = mps_request_polled(sc, cm); 1183230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1184230592Sken if (error || (reply == NULL)) { 1185230592Sken /* FIXME */ 1186230592Sken /* If the poll returns error then we need to do diag reset */ 1187230592Sken printf("%s: poll for page completed with error %d", 1188230592Sken __func__, error); 1189230592Sken error = ENXIO; 1190230592Sken goto out; 1191230592Sken } 1192230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1193230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1194230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1195230592Sken /* FIXME */ 1196230592Sken /* If the poll returns error then we need to do diag reset */ 1197230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1198230592Sken __func__, ioc_status); 1199230592Sken error = ENXIO; 1200230592Sken goto out; 1201230592Sken } 1202230592Sken bcopy(page, config_page, cm->cm_length); 1203230592Skenout: 1204230592Sken free(page, M_MPT2); 1205230592Sken if (cm) 1206230592Sken mps_free_command(sc, cm); 1207230592Sken return (error); 1208230592Sken} 1209230592Sken 1210230592Sken/** 1211230592Sken * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1212230592Sken * @sc: per adapter object 1213230592Sken * @mpi_reply: reply mf payload returned from firmware 1214230592Sken * @config_page: contents of the config page 1215230592Sken * @form: GET_NEXT_HANDLE or HANDLE 1216230592Sken * @handle: volume handle 1217230592Sken * Context: sleep. 1218230592Sken * 1219230592Sken * Returns 0 for success, non-zero for failure. 1220230592Sken */ 1221230592Skenint 1222230592Skenmps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1223230592Sken *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1224230592Sken{ 1225230592Sken MPI2_CONFIG_REQUEST *request; 1226230592Sken MPI2_CONFIG_REPLY *reply; 1227230592Sken struct mps_command *cm; 1228230592Sken Mpi2RaidVolPage1_t *page = NULL; 1229230592Sken int error = 0; 1230230592Sken u16 ioc_status; 1231230592Sken 1232230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1233230592Sken 1234230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1235230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1236230592Sken __LINE__); 1237230592Sken error = EBUSY; 1238230592Sken goto out; 1239230592Sken } 1240230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1241230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1242230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1243230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1244230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1245230592Sken request->Header.PageNumber = 1; 1246230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1247230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1248230592Sken cm->cm_data = NULL; 1249254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1250230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1251230592Sken if (error || (reply == NULL)) { 1252230592Sken /* FIXME */ 1253254938Sken /* 1254254938Sken * If the request returns an error then we need to do a diag 1255254938Sken * reset 1256254938Sken */ 1257254938Sken printf("%s: request for header completed with error %d", 1258230592Sken __func__, error); 1259230592Sken error = ENXIO; 1260230592Sken goto out; 1261230592Sken } 1262230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1263230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1264230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1265230592Sken /* FIXME */ 1266254938Sken /* 1267254938Sken * If the request returns an error then we need to do a diag 1268254938Sken * reset 1269254938Sken */ 1270230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1271230592Sken __func__, ioc_status); 1272230592Sken error = ENXIO; 1273230592Sken goto out; 1274230592Sken } 1275230592Sken /* We have to do free and alloc for the reply-free and reply-post 1276230592Sken * counters to match - Need to review the reply FIFO handling. 1277230592Sken */ 1278230592Sken mps_free_command(sc, cm); 1279230592Sken 1280230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1281230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1282230592Sken __LINE__); 1283230592Sken error = EBUSY; 1284230592Sken goto out; 1285230592Sken } 1286230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1287230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1288230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1289230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1290230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1291230592Sken request->Header.PageNumber = 1; 1292230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1293230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1294230592Sken request->PageAddress = htole32(form | handle); 1295230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1296230592Sken cm->cm_sge = &request->PageBufferSGE; 1297230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1298230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1299230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1300230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1301230592Sken if (!page) { 1302230592Sken printf("%s: page alloc failed\n", __func__); 1303230592Sken error = ENOMEM; 1304230592Sken goto out; 1305230592Sken } 1306230592Sken cm->cm_data = page; 1307230592Sken 1308254938Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1309230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1310230592Sken if (error || (reply == NULL)) { 1311230592Sken /* FIXME */ 1312254938Sken /* 1313254938Sken * If the request returns an error then we need to do a diag 1314254938Sken * reset 1315254938Sken */ 1316254938Sken printf("%s: request for page completed with error %d", 1317230592Sken __func__, error); 1318230592Sken error = ENXIO; 1319230592Sken goto out; 1320230592Sken } 1321230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1322230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1323230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1324230592Sken /* FIXME */ 1325254938Sken /* 1326254938Sken * If the request returns an error then we need to do a diag 1327254938Sken * reset 1328254938Sken */ 1329230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1330230592Sken __func__, ioc_status); 1331230592Sken error = ENXIO; 1332230592Sken goto out; 1333230592Sken } 1334230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1335230592Sken sizeof(Mpi2RaidVolPage1_t))); 1336230592Skenout: 1337230592Sken free(page, M_MPT2); 1338230592Sken if (cm) 1339230592Sken mps_free_command(sc, cm); 1340230592Sken return (error); 1341230592Sken} 1342230592Sken 1343230592Sken/** 1344230592Sken * mps_config_get_volume_wwid - returns wwid given the volume handle 1345230592Sken * @sc: per adapter object 1346230592Sken * @volume_handle: volume handle 1347230592Sken * @wwid: volume wwid 1348230592Sken * Context: sleep. 1349230592Sken * 1350230592Sken * Returns 0 for success, non-zero for failure. 1351230592Sken */ 1352230592Skenint 1353230592Skenmps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1354230592Sken{ 1355230592Sken Mpi2ConfigReply_t mpi_reply; 1356230592Sken Mpi2RaidVolPage1_t raid_vol_pg1; 1357230592Sken 1358230592Sken *wwid = 0; 1359230592Sken if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1360230592Sken MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1361230592Sken *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1362230592Sken raid_vol_pg1.WWID.Low); 1363230592Sken return 0; 1364230592Sken } else 1365230592Sken return -1; 1366230592Sken} 1367230592Sken 1368230592Sken/** 1369230592Sken * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1370230592Sken * @sc: per adapter object 1371230592Sken * @mpi_reply: reply mf payload returned from firmware 1372230592Sken * @config_page: contents of the config page 1373230592Sken * @page_address: form and handle value used to get page 1374230592Sken * Context: sleep. 1375230592Sken * 1376230592Sken * Returns 0 for success, non-zero for failure. 1377230592Sken */ 1378230592Skenint 1379230592Skenmps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1380230592Sken Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1381230592Sken{ 1382230592Sken MPI2_CONFIG_REQUEST *request; 1383230592Sken MPI2_CONFIG_REPLY *reply; 1384230592Sken struct mps_command *cm; 1385230592Sken Mpi2RaidPhysDiskPage0_t *page = NULL; 1386230592Sken int error = 0; 1387230592Sken u16 ioc_status; 1388230592Sken 1389230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1390230592Sken 1391230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1392230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1393230592Sken __LINE__); 1394230592Sken error = EBUSY; 1395230592Sken goto out; 1396230592Sken } 1397230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1398230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1399230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1400230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1401230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1402230592Sken request->Header.PageNumber = 0; 1403230592Sken request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1404230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1405230592Sken cm->cm_data = NULL; 1406254938Sken 1407254938Sken /* 1408254938Sken * This page must be polled because the IOC isn't ready yet when this 1409254938Sken * page is needed. 1410254938Sken */ 1411230592Sken error = mps_request_polled(sc, cm); 1412230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1413230592Sken if (error || (reply == NULL)) { 1414230592Sken /* FIXME */ 1415230592Sken /* If the poll returns error then we need to do diag reset */ 1416230592Sken printf("%s: poll for header completed with error %d", 1417230592Sken __func__, error); 1418230592Sken error = ENXIO; 1419230592Sken goto out; 1420230592Sken } 1421230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1422230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1423230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1424230592Sken /* FIXME */ 1425230592Sken /* If the poll returns error then we need to do diag reset */ 1426230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1427230592Sken __func__, ioc_status); 1428230592Sken error = ENXIO; 1429230592Sken goto out; 1430230592Sken } 1431230592Sken /* We have to do free and alloc for the reply-free and reply-post 1432230592Sken * counters to match - Need to review the reply FIFO handling. 1433230592Sken */ 1434230592Sken mps_free_command(sc, cm); 1435230592Sken 1436230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1437230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1438230592Sken __LINE__); 1439230592Sken error = EBUSY; 1440230592Sken goto out; 1441230592Sken } 1442230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1443230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1444230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1445230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1446230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1447230592Sken request->Header.PageNumber = 0; 1448230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1449230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1450230592Sken request->PageAddress = page_address; 1451230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1452230592Sken cm->cm_sge = &request->PageBufferSGE; 1453230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1454230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1455230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1456230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1457230592Sken if (!page) { 1458230592Sken printf("%s: page alloc failed\n", __func__); 1459230592Sken error = ENOMEM; 1460230592Sken goto out; 1461230592Sken } 1462230592Sken cm->cm_data = page; 1463230592Sken 1464254938Sken /* 1465254938Sken * This page must be polled because the IOC isn't ready yet when this 1466254938Sken * page is needed. 1467254938Sken */ 1468230592Sken error = mps_request_polled(sc, cm); 1469230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1470230592Sken if (error || (reply == NULL)) { 1471230592Sken /* FIXME */ 1472230592Sken /* If the poll returns error then we need to do diag reset */ 1473230592Sken printf("%s: poll for page completed with error %d", 1474230592Sken __func__, error); 1475230592Sken error = ENXIO; 1476230592Sken goto out; 1477230592Sken } 1478230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1479230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1480230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1481230592Sken /* FIXME */ 1482230592Sken /* If the poll returns error then we need to do diag reset */ 1483230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1484230592Sken __func__, ioc_status); 1485230592Sken error = ENXIO; 1486230592Sken goto out; 1487230592Sken } 1488230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1489230592Sken sizeof(Mpi2RaidPhysDiskPage0_t))); 1490230592Skenout: 1491230592Sken free(page, M_MPT2); 1492230592Sken if (cm) 1493230592Sken mps_free_command(sc, cm); 1494230592Sken return (error); 1495230592Sken} 1496