1 /*- 2 * Copyright (c) 2011, 2012 LSI Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * LSI MPT-Fusion Host Adapter FreeBSD 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 /* TODO Move headers to mpsvar */ 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/lock.h> 36 #include <sys/mutex.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/malloc.h> 40 #include <sys/kthread.h> 41 #include <sys/taskqueue.h> 42 #include <sys/bus.h> 43 #include <sys/endian.h> 44 #include <sys/sysctl.h> 45 #include <sys/eventhandler.h> 46 #include <sys/uio.h> 47 #include <machine/bus.h> 48 #include <machine/resource.h> 49 #include <dev/mps/mpi/mpi2_type.h> 50 #include <dev/mps/mpi/mpi2.h> 51 #include <dev/mps/mpi/mpi2_ioc.h> 52 #include <dev/mps/mpi/mpi2_sas.h> 53 #include <dev/mps/mpi/mpi2_cnfg.h> 54 #include <dev/mps/mpi/mpi2_init.h> 55 #include <dev/mps/mpi/mpi2_tool.h> 56 #include <dev/mps/mps_ioctl.h> 57 #include <dev/mps/mpsvar.h> 58 59 /** 60 * mps_config_get_ioc_pg8 - obtain ioc page 8 61 * @sc: per adapter object 62 * @mpi_reply: reply mf payload returned from firmware 63 * @config_page: contents of the config page 64 * Context: sleep. 65 * 66 * Returns 0 for success, non-zero for failure. 67 */ 68 int 69 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 70 Mpi2IOCPage8_t *config_page) 71 { 72 MPI2_CONFIG_REQUEST *request; 73 MPI2_CONFIG_REPLY *reply; 74 struct mps_command *cm; 75 MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 76 int error = 0; 77 u16 ioc_status; 78 79 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 80 81 if ((cm = mps_alloc_command(sc)) == NULL) { 82 printf("%s: command alloc failed @ line %d\n", __func__, 83 __LINE__); 84 error = EBUSY; 85 goto out; 86 } 87 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 88 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 89 request->Function = MPI2_FUNCTION_CONFIG; 90 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 91 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 92 request->Header.PageNumber = 8; 93 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 94 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 95 cm->cm_data = NULL; 96 error = mps_request_polled(sc, cm); 97 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 98 if (error || (reply == NULL)) { 99 /* FIXME */ 100 /* If the poll returns error then we need to do diag reset */ 101 printf("%s: poll for header completed with error %d", 102 __func__, error); 103 error = ENXIO; 104 goto out; 105 } 106 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 107 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 108 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 109 /* FIXME */ 110 /* If the poll returns error then we need to do diag reset */ 111 printf("%s: header read with error; iocstatus = 0x%x\n", 112 __func__, ioc_status); 113 error = ENXIO; 114 goto out; 115 } 116 /* We have to do free and alloc for the reply-free and reply-post 117 * counters to match - Need to review the reply FIFO handling. 118 */ 119 mps_free_command(sc, cm); 120 121 if ((cm = mps_alloc_command(sc)) == NULL) { 122 printf("%s: command alloc failed @ line %d\n", __func__, 123 __LINE__); 124 error = EBUSY; 125 goto out; 126 } 127 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 128 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 129 request->Function = MPI2_FUNCTION_CONFIG; 130 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 131 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 132 request->Header.PageNumber = 8; 133 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 134 request->Header.PageLength = mpi_reply->Header.PageLength; 135 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 136 cm->cm_sge = &request->PageBufferSGE; 137 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 138 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 139 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 140 page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT); 141 if (!page) { 142 printf("%s: page alloc failed\n", __func__); 143 error = ENOMEM; 144 goto out; 145 } 146 cm->cm_data = page; 147 error = mps_request_polled(sc, cm); 148 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 149 if (error || (reply == NULL)) { 150 /* FIXME */ 151 /* If the poll returns error then we need to do diag reset */ 152 printf("%s: poll for page completed with error %d", 153 __func__, error); 154 error = ENXIO; 155 goto out; 156 } 157 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 158 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 159 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 160 /* FIXME */ 161 /* If the poll returns error then we need to do diag reset */ 162 printf("%s: page read with error; iocstatus = 0x%x\n", 163 __func__, ioc_status); 164 error = ENXIO; 165 goto out; 166 } 167 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 168 169 out: 170 free(page, M_MPT2); 171 if (cm) 172 mps_free_command(sc, cm); 173 return (error); 174 } 175 176 /** 177 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags 178 * accordingly. Currently, this page does not need to return to caller. 179 * @sc: per adapter object 180 * @mpi_reply: reply mf payload returned from firmware 181 * Context: sleep. 182 * 183 * Returns 0 for success, non-zero for failure. 184 */ 185 int 186 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) 187 { 188 MPI2_CONFIG_REQUEST *request; 189 MPI2_CONFIG_REPLY *reply; 190 struct mps_command *cm; 191 pMpi2ManufacturingPagePS_t page = NULL; 192 uint32_t *pPS_info; 193 uint8_t OEM_Value = 0; 194 int error = 0; 195 u16 ioc_status; 196 197 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 198 199 if ((cm = mps_alloc_command(sc)) == NULL) { 200 printf("%s: command alloc failed @ line %d\n", __func__, 201 __LINE__); 202 error = EBUSY; 203 goto out; 204 } 205 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 206 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 207 request->Function = MPI2_FUNCTION_CONFIG; 208 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 209 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 210 request->Header.PageNumber = 10; 211 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 212 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 213 cm->cm_data = NULL; 214 error = mps_request_polled(sc, cm); 215 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 216 if (error || (reply == NULL)) { 217 /* FIXME */ 218 /* If the poll returns error then we need to do diag reset */ 219 printf("%s: poll for header completed with error %d", 220 __func__, error); 221 error = ENXIO; 222 goto out; 223 } 224 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 225 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 226 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 227 /* FIXME */ 228 /* If the poll returns error then we need to do diag reset */ 229 printf("%s: header read with error; iocstatus = 0x%x\n", 230 __func__, ioc_status); 231 error = ENXIO; 232 goto out; 233 } 234 /* We have to do free and alloc for the reply-free and reply-post 235 * counters to match - Need to review the reply FIFO handling. 236 */ 237 mps_free_command(sc, cm); 238 239 if ((cm = mps_alloc_command(sc)) == NULL) { 240 printf("%s: command alloc failed @ line %d\n", __func__, 241 __LINE__); 242 error = EBUSY; 243 goto out; 244 } 245 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 246 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 247 request->Function = MPI2_FUNCTION_CONFIG; 248 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 249 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 250 request->Header.PageNumber = 10; 251 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 252 request->Header.PageLength = mpi_reply->Header.PageLength; 253 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 254 cm->cm_sge = &request->PageBufferSGE; 255 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 256 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 257 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 258 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT); 259 if (!page) { 260 printf("%s: page alloc failed\n", __func__); 261 error = ENOMEM; 262 goto out; 263 } 264 cm->cm_data = page; 265 error = mps_request_polled(sc, cm); 266 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 267 if (error || (reply == NULL)) { 268 /* FIXME */ 269 /* If the poll returns error then we need to do diag reset */ 270 printf("%s: poll for page completed with error %d", 271 __func__, error); 272 error = ENXIO; 273 goto out; 274 } 275 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 276 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 277 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 278 /* FIXME */ 279 /* If the poll returns error then we need to do diag reset */ 280 printf("%s: page read with error; iocstatus = 0x%x\n", 281 __func__, ioc_status); 282 error = ENXIO; 283 goto out; 284 } 285 286 /* 287 * If OEM ID is unknown, fail the request. 288 */ 289 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 290 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF); 291 if (OEM_Value != MPS_WD_LSI_OEM) { 292 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive " 293 "(0x%x)\n", OEM_Value); 294 error = ENXIO; 295 goto out; 296 } 297 298 /* 299 * Set the phys disks hide/expose value. 300 */ 301 pPS_info = &page->ProductSpecificInfo; 302 sc->WD_hide_expose = (uint8_t)(pPS_info[5]); 303 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK; 304 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) && 305 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) && 306 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) { 307 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive " 308 "hide/expose: 0x%x\n", sc->WD_hide_expose); 309 error = ENXIO; 310 goto out; 311 } 312 313 out: 314 free(page, M_MPT2); 315 if (cm) 316 mps_free_command(sc, cm); 317 return (error); 318 } 319 320 /** 321 * mps_base_static_config_pages - static start of day config pages. 322 * @sc: per adapter object 323 * 324 * Return nothing. 325 */ 326 void 327 mps_base_static_config_pages(struct mps_softc *sc) 328 { 329 Mpi2ConfigReply_t mpi_reply; 330 int retry; 331 332 retry = 0; 333 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 334 retry++; 335 if (retry > 5) { 336 /* We need to Handle this situation */ 337 /*FIXME*/ 338 break; 339 } 340 } 341 } 342 343 /** 344 * mps_wd_config_pages - get info required to support WarpDrive. This needs to 345 * be called after discovery is complete to guarentee that IR info is there. 346 * @sc: per adapter object 347 * 348 * Return nothing. 349 */ 350 void 351 mps_wd_config_pages(struct mps_softc *sc) 352 { 353 Mpi2ConfigReply_t mpi_reply; 354 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL; 355 Mpi2RaidPhysDiskPage0_t phys_disk_pg0; 356 pMpi2RaidVol0PhysDisk_t pRVPD; 357 uint32_t stripe_size, phys_disk_page_address; 358 uint16_t block_size; 359 uint8_t index, stripe_exp = 0, block_exp = 0; 360 361 /* 362 * Get the WD settings from manufacturing page 10 if using a WD HBA. 363 * This will be used to determine if phys disks should always be 364 * hidden, hidden only if part of a WD volume, or never hidden. Also, 365 * get the WD RAID Volume info and fail if volume does not exist or if 366 * volume does not meet the requirements for a WD volume. No retry 367 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD 368 * Valid flag if Volume info fails. 369 */ 370 sc->WD_valid_config = FALSE; 371 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { 372 if (mps_config_get_man_pg10(sc, &mpi_reply)) { 373 mps_dprint(sc, MPS_FAULT, 374 "mps_config_get_man_pg10 failed! Using 0 (Hide " 375 "Always) for WarpDrive hide/expose value.\n"); 376 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 377 } 378 379 /* 380 * Get first RAID Volume Page0 using GET_NEXT_HANDLE. 381 */ 382 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) + 383 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL), 384 M_MPT2, M_ZERO | M_NOWAIT); 385 if (!raid_vol_pg0) { 386 printf("%s: page alloc failed\n", __func__); 387 goto out; 388 } 389 390 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0, 391 0x0000FFFF)) { 392 mps_dprint(sc, MPS_INFO, 393 "mps_config_get_raid_volume_pg0 failed! Assuming " 394 "WarpDrive IT mode.\n"); 395 goto out; 396 } 397 398 /* 399 * Check for valid WD configuration: 400 * volume type is RAID0 401 * number of phys disks in the volume is no more than 8 402 */ 403 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) || 404 (raid_vol_pg0->NumPhysDisks > 8)) { 405 mps_dprint(sc, MPS_FAULT, 406 "Invalid WarpDrive configuration. Direct Drive I/O " 407 "will not be used.\n"); 408 goto out; 409 } 410 411 /* 412 * Save the WD RAID data to be used during WD I/O. 413 */ 414 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High << 415 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low); 416 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks; 417 sc->DD_dev_handle = raid_vol_pg0->DevHandle; 418 sc->DD_stripe_size = raid_vol_pg0->StripeSize; 419 sc->DD_block_size = raid_vol_pg0->BlockSize; 420 421 /* 422 * Find power of 2 of stripe size and set this as the exponent. 423 * Fail if stripe size is 0. 424 */ 425 stripe_size = raid_vol_pg0->StripeSize; 426 for (index = 0; index < 32; index++) { 427 if (stripe_size & 1) 428 break; 429 stripe_exp++; 430 stripe_size >>= 1; 431 } 432 if (index == 32) { 433 mps_dprint(sc, MPS_FAULT, 434 "RAID Volume's stripe size is 0. Direct Drive I/O " 435 "will not be used.\n"); 436 goto out; 437 } 438 sc->DD_stripe_exponent = stripe_exp; 439 440 /* 441 * Find power of 2 of block size and set this as the exponent. 442 * Fail if block size is 0. 443 */ 444 block_size = raid_vol_pg0->BlockSize; 445 for (index = 0; index < 16; index++) { 446 if (block_size & 1) 447 break; 448 block_exp++; 449 block_size >>= 1; 450 } 451 if (index == 16) { 452 mps_dprint(sc, MPS_FAULT, 453 "RAID Volume's block size is 0. Direct Drive I/O " 454 "will not be used.\n"); 455 goto out; 456 } 457 sc->DD_block_exponent = block_exp; 458 459 /* 460 * Loop through all of the volume's Phys Disks to map the phys 461 * disk number into the columm map. This is used during Direct 462 * Drive I/O to send the request to the correct SSD. 463 */ 464 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk; 465 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 466 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num = 467 pRVPD->PhysDiskNum; 468 pRVPD++; 469 } 470 471 /* 472 * Get second RAID Volume Page0 using previous handle. This 473 * page should not exist. If it does, must not proceed with WD 474 * handling. 475 */ 476 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, 477 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) { 478 if (mpi_reply.IOCStatus != 479 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 480 mps_dprint(sc, MPS_FAULT, 481 "Multiple RAID Volume Page0! Direct Drive " 482 "I/O will not be used.\n"); 483 goto out; 484 } 485 } else { 486 mps_dprint(sc, MPS_FAULT, 487 "Multiple volumes! Direct Drive I/O will not be " 488 "used.\n"); 489 goto out; 490 } 491 492 /* 493 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 494 */ 495 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 496 phys_disk_page_address = 497 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 498 sc->DD_column_map[index].phys_disk_num; 499 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 500 &phys_disk_pg0, phys_disk_page_address)) { 501 mps_dprint(sc, MPS_FAULT, 502 "mps_config_get_raid_pd_pg0 failed! Direct " 503 "Drive I/O will not be used.\n"); 504 goto out; 505 } 506 if (phys_disk_pg0.DevHandle == 0xFFFF) { 507 mps_dprint(sc, MPS_FAULT, 508 "Invalid Phys Disk DevHandle! Direct Drive " 509 "I/O will not be used.\n"); 510 goto out; 511 } 512 sc->DD_column_map[index].dev_handle = 513 phys_disk_pg0.DevHandle; 514 } 515 sc->WD_valid_config = TRUE; 516 out: 517 if (raid_vol_pg0) 518 free(raid_vol_pg0, M_MPT2); 519 } 520 } 521 522 /** 523 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 524 * @sc: per adapter object 525 * @mpi_reply: reply mf payload returned from firmware 526 * @config_page: contents of the config page 527 * @sz: size of buffer passed in config_page 528 * Context: sleep. 529 * 530 * Returns 0 for success, non-zero for failure. 531 */ 532 int 533 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 534 Mpi2DriverMappingPage0_t *config_page, u16 sz) 535 { 536 MPI2_CONFIG_REQUEST *request; 537 MPI2_CONFIG_REPLY *reply; 538 struct mps_command *cm; 539 Mpi2DriverMappingPage0_t *page = NULL; 540 int error = 0; 541 u16 ioc_status; 542 543 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 544 545 memset(config_page, 0, sz); 546 if ((cm = mps_alloc_command(sc)) == NULL) { 547 printf("%s: command alloc failed @ line %d\n", __func__, 548 __LINE__); 549 error = EBUSY; 550 goto out; 551 } 552 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 553 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 554 request->Function = MPI2_FUNCTION_CONFIG; 555 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 556 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 557 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 558 request->Header.PageNumber = 0; 559 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 560 request->PageAddress = sc->max_dpm_entries << 561 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 562 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 563 cm->cm_data = NULL; 564 error = mps_request_polled(sc, cm); 565 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 566 if (error || (reply == NULL)) { 567 /* FIXME */ 568 /* If the poll returns error then we need to do diag reset */ 569 printf("%s: poll for header completed with error %d", 570 __func__, error); 571 error = ENXIO; 572 goto out; 573 } 574 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 575 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 576 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 577 /* FIXME */ 578 /* If the poll returns error then we need to do diag reset */ 579 printf("%s: header read with error; iocstatus = 0x%x\n", 580 __func__, ioc_status); 581 error = ENXIO; 582 goto out; 583 } 584 /* We have to do free and alloc for the reply-free and reply-post 585 * counters to match - Need to review the reply FIFO handling. 586 */ 587 mps_free_command(sc, cm); 588 589 if ((cm = mps_alloc_command(sc)) == NULL) { 590 printf("%s: command alloc failed @ line %d\n", __func__, 591 __LINE__); 592 error = EBUSY; 593 goto out; 594 } 595 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 596 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 597 request->Function = MPI2_FUNCTION_CONFIG; 598 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 599 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 600 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 601 request->Header.PageNumber = 0; 602 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 603 request->PageAddress = sc->max_dpm_entries << 604 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 605 request->ExtPageLength = mpi_reply->ExtPageLength; 606 cm->cm_length = le16toh(request->ExtPageLength) * 4; 607 cm->cm_sge = &request->PageBufferSGE; 608 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 609 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 610 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 611 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 612 if (!page) { 613 printf("%s: page alloc failed\n", __func__); 614 error = ENOMEM; 615 goto out; 616 } 617 cm->cm_data = page; 618 error = mps_request_polled(sc, cm); 619 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 620 if (error || (reply == NULL)) { 621 /* FIXME */ 622 /* If the poll returns error then we need to do diag reset */ 623 printf("%s: poll for page completed with error %d", 624 __func__, error); 625 error = ENXIO; 626 goto out; 627 } 628 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 629 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 630 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 631 /* FIXME */ 632 /* If the poll returns error then we need to do diag reset */ 633 printf("%s: page read with error; iocstatus = 0x%x\n", 634 __func__, ioc_status); 635 error = ENXIO; 636 goto out; 637 } 638 bcopy(page, config_page, MIN(cm->cm_length, sz)); 639 out: 640 free(page, M_MPT2); 641 if (cm) 642 mps_free_command(sc, cm); 643 return (error); 644 } 645 646 /** 647 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 648 * @sc: per adapter object 649 * @mpi_reply: reply mf payload returned from firmware 650 * @config_page: contents of the config page 651 * @entry_idx: entry index in DPM Page0 to be modified 652 * Context: sleep. 653 * 654 * Returns 0 for success, non-zero for failure. 655 */ 656 657 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 658 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 659 { 660 MPI2_CONFIG_REQUEST *request; 661 MPI2_CONFIG_REPLY *reply; 662 struct mps_command *cm; 663 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 664 int error = 0; 665 u16 ioc_status; 666 667 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 668 669 if ((cm = mps_alloc_command(sc)) == NULL) { 670 printf("%s: command alloc failed @ line %d\n", __func__, 671 __LINE__); 672 error = EBUSY; 673 goto out; 674 } 675 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 676 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 677 request->Function = MPI2_FUNCTION_CONFIG; 678 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 679 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 680 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 681 request->Header.PageNumber = 0; 682 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 683 /* We can remove below two lines ????*/ 684 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 685 request->PageAddress |= htole16(entry_idx); 686 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 687 cm->cm_data = NULL; 688 error = mps_request_polled(sc, cm); 689 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 690 if (error || (reply == NULL)) { 691 /* FIXME */ 692 /* If the poll returns error then we need to do diag reset */ 693 printf("%s: poll for header completed with error %d", 694 __func__, error); 695 error = ENXIO; 696 goto out; 697 } 698 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 699 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 700 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 701 /* FIXME */ 702 /* If the poll returns error then we need to do diag reset */ 703 printf("%s: header read with error; iocstatus = 0x%x\n", 704 __func__, ioc_status); 705 error = ENXIO; 706 goto out; 707 } 708 /* We have to do free and alloc for the reply-free and reply-post 709 * counters to match - Need to review the reply FIFO handling. 710 */ 711 mps_free_command(sc, cm); 712 713 if ((cm = mps_alloc_command(sc)) == NULL) { 714 printf("%s: command alloc failed @ line %d\n", __func__, 715 __LINE__); 716 error = EBUSY; 717 goto out; 718 } 719 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 720 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 721 request->Function = MPI2_FUNCTION_CONFIG; 722 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 723 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 724 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 725 request->Header.PageNumber = 0; 726 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 727 request->ExtPageLength = mpi_reply->ExtPageLength; 728 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 729 request->PageAddress |= htole16(entry_idx); 730 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 731 cm->cm_sge = &request->PageBufferSGE; 732 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 733 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 734 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 735 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 736 if (!page) { 737 printf("%s: page alloc failed\n", __func__); 738 error = ENOMEM; 739 goto out; 740 } 741 bcopy(config_page, page, MIN(cm->cm_length, 742 (sizeof(Mpi2DriverMappingPage0_t)))); 743 cm->cm_data = page; 744 error = mps_request_polled(sc, cm); 745 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 746 if (error || (reply == NULL)) { 747 /* FIXME */ 748 /* If the poll returns error then we need to do diag reset */ 749 printf("%s: poll for page completed with error %d", 750 __func__, error); 751 error = ENXIO; 752 goto out; 753 } 754 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 755 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 756 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 757 /* FIXME */ 758 /* If the poll returns error then we need to do diag reset */ 759 printf("%s: page written with error; iocstatus = 0x%x\n", 760 __func__, ioc_status); 761 error = ENXIO; 762 goto out; 763 } 764 out: 765 free(page, M_MPT2); 766 if (cm) 767 mps_free_command(sc, cm); 768 return (error); 769 } 770 771 /** 772 * mps_config_get_sas_device_pg0 - obtain sas device page 0 773 * @sc: per adapter object 774 * @mpi_reply: reply mf payload returned from firmware 775 * @config_page: contents of the config page 776 * @form: GET_NEXT_HANDLE or HANDLE 777 * @handle: device handle 778 * Context: sleep. 779 * 780 * Returns 0 for success, non-zero for failure. 781 */ 782 int 783 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 784 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 785 { 786 MPI2_CONFIG_REQUEST *request; 787 MPI2_CONFIG_REPLY *reply; 788 struct mps_command *cm; 789 Mpi2SasDevicePage0_t *page = NULL; 790 int error = 0; 791 u16 ioc_status; 792 793 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 794 795 if ((cm = mps_alloc_command(sc)) == NULL) { 796 printf("%s: command alloc failed @ line %d\n", __func__, 797 __LINE__); 798 error = EBUSY; 799 goto out; 800 } 801 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 802 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 803 request->Function = MPI2_FUNCTION_CONFIG; 804 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 805 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 806 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 807 request->Header.PageNumber = 0; 808 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 809 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 810 cm->cm_data = NULL; 811 error = mps_request_polled(sc, cm); 812 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 813 if (error || (reply == NULL)) { 814 /* FIXME */ 815 /* If the poll returns error then we need to do diag reset */ 816 printf("%s: poll for header completed with error %d", 817 __func__, error); 818 error = ENXIO; 819 goto out; 820 } 821 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 822 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 823 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 824 /* FIXME */ 825 /* If the poll returns error then we need to do diag reset */ 826 printf("%s: header read with error; iocstatus = 0x%x\n", 827 __func__, ioc_status); 828 error = ENXIO; 829 goto out; 830 } 831 /* We have to do free and alloc for the reply-free and reply-post 832 * counters to match - Need to review the reply FIFO handling. 833 */ 834 mps_free_command(sc, cm); 835 836 if ((cm = mps_alloc_command(sc)) == NULL) { 837 printf("%s: command alloc failed @ line %d\n", __func__, 838 __LINE__); 839 error = EBUSY; 840 goto out; 841 } 842 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 843 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 844 request->Function = MPI2_FUNCTION_CONFIG; 845 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 846 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 847 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 848 request->Header.PageNumber = 0; 849 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 850 request->ExtPageLength = mpi_reply->ExtPageLength; 851 request->PageAddress = htole32(form | handle); 852 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 853 cm->cm_sge = &request->PageBufferSGE; 854 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 855 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 856 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 857 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 858 if (!page) { 859 printf("%s: page alloc failed\n", __func__); 860 error = ENOMEM; 861 goto out; 862 } 863 cm->cm_data = page; 864 865 error = mps_request_polled(sc, cm); 866 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 867 if (error || (reply == NULL)) { 868 /* FIXME */ 869 /* If the poll returns error then we need to do diag reset */ 870 printf("%s: poll for page completed with error %d", 871 __func__, error); 872 error = ENXIO; 873 goto out; 874 } 875 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 876 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 877 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 878 /* FIXME */ 879 /* If the poll returns error then we need to do diag reset */ 880 printf("%s: page read with error; iocstatus = 0x%x\n", 881 __func__, ioc_status); 882 error = ENXIO; 883 goto out; 884 } 885 bcopy(page, config_page, MIN(cm->cm_length, 886 sizeof(Mpi2SasDevicePage0_t))); 887 out: 888 free(page, M_MPT2); 889 if (cm) 890 mps_free_command(sc, cm); 891 return (error); 892 } 893 894 /** 895 * mps_config_get_bios_pg3 - obtain BIOS page 3 896 * @sc: per adapter object 897 * @mpi_reply: reply mf payload returned from firmware 898 * @config_page: contents of the config page 899 * Context: sleep. 900 * 901 * Returns 0 for success, non-zero for failure. 902 */ 903 int 904 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 905 Mpi2BiosPage3_t *config_page) 906 { 907 MPI2_CONFIG_REQUEST *request; 908 MPI2_CONFIG_REPLY *reply; 909 struct mps_command *cm; 910 Mpi2BiosPage3_t *page = NULL; 911 int error = 0; 912 u16 ioc_status; 913 914 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 915 916 if ((cm = mps_alloc_command(sc)) == NULL) { 917 printf("%s: command alloc failed @ line %d\n", __func__, 918 __LINE__); 919 error = EBUSY; 920 goto out; 921 } 922 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 923 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 924 request->Function = MPI2_FUNCTION_CONFIG; 925 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 926 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 927 request->Header.PageNumber = 3; 928 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 929 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 930 cm->cm_data = NULL; 931 error = mps_request_polled(sc, cm); 932 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 933 if (error || (reply == NULL)) { 934 /* FIXME */ 935 /* If the poll returns error then we need to do diag reset */ 936 printf("%s: poll for header completed with error %d", 937 __func__, error); 938 error = ENXIO; 939 goto out; 940 } 941 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 942 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 943 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 944 /* FIXME */ 945 /* If the poll returns error then we need to do diag reset */ 946 printf("%s: header read with error; iocstatus = 0x%x\n", 947 __func__, ioc_status); 948 error = ENXIO; 949 goto out; 950 } 951 /* We have to do free and alloc for the reply-free and reply-post 952 * counters to match - Need to review the reply FIFO handling. 953 */ 954 mps_free_command(sc, cm); 955 956 if ((cm = mps_alloc_command(sc)) == NULL) { 957 printf("%s: command alloc failed @ line %d\n", __func__, 958 __LINE__); 959 error = EBUSY; 960 goto out; 961 } 962 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 963 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 964 request->Function = MPI2_FUNCTION_CONFIG; 965 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 966 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 967 request->Header.PageNumber = 3; 968 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 969 request->Header.PageLength = mpi_reply->Header.PageLength; 970 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 971 cm->cm_sge = &request->PageBufferSGE; 972 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 973 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 974 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 975 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 976 if (!page) { 977 printf("%s: page alloc failed\n", __func__); 978 error = ENOMEM; 979 goto out; 980 } 981 cm->cm_data = page; 982 983 error = mps_request_polled(sc, cm); 984 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 985 if (error || (reply == NULL)) { 986 /* FIXME */ 987 /* If the poll returns error then we need to do diag reset */ 988 printf("%s: poll for page completed with error %d", 989 __func__, error); 990 error = ENXIO; 991 goto out; 992 } 993 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 994 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 995 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 996 /* FIXME */ 997 /* If the poll returns error then we need to do diag reset */ 998 printf("%s: page read with error; iocstatus = 0x%x\n", 999 __func__, ioc_status); 1000 error = ENXIO; 1001 goto out; 1002 } 1003 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1004 out: 1005 free(page, M_MPT2); 1006 if (cm) 1007 mps_free_command(sc, cm); 1008 return (error); 1009 } 1010 1011 /** 1012 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1013 * @sc: per adapter object 1014 * @mpi_reply: reply mf payload returned from firmware 1015 * @config_page: contents of the config page 1016 * @page_address: form and handle value used to get page 1017 * Context: sleep. 1018 * 1019 * Returns 0 for success, non-zero for failure. 1020 */ 1021 int 1022 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1023 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1024 { 1025 MPI2_CONFIG_REQUEST *request; 1026 MPI2_CONFIG_REPLY *reply; 1027 struct mps_command *cm; 1028 Mpi2RaidVolPage0_t *page = NULL; 1029 int error = 0; 1030 u16 ioc_status; 1031 1032 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1033 1034 if ((cm = mps_alloc_command(sc)) == NULL) { 1035 printf("%s: command alloc failed @ line %d\n", __func__, 1036 __LINE__); 1037 error = EBUSY; 1038 goto out; 1039 } 1040 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1041 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1042 request->Function = MPI2_FUNCTION_CONFIG; 1043 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1044 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1045 request->Header.PageNumber = 0; 1046 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1047 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1048 cm->cm_data = NULL; 1049 error = mps_request_polled(sc, cm); 1050 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1051 if (error || (reply == NULL)) { 1052 /* FIXME */ 1053 /* If the poll returns error then we need to do diag reset */ 1054 printf("%s: poll for header completed with error %d", 1055 __func__, error); 1056 error = ENXIO; 1057 goto out; 1058 } 1059 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1060 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1061 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1062 /* FIXME */ 1063 /* If the poll returns error then we need to do diag reset */ 1064 printf("%s: header read with error; iocstatus = 0x%x\n", 1065 __func__, ioc_status); 1066 error = ENXIO; 1067 goto out; 1068 } 1069 /* We have to do free and alloc for the reply-free and reply-post 1070 * counters to match - Need to review the reply FIFO handling. 1071 */ 1072 mps_free_command(sc, cm); 1073 1074 if ((cm = mps_alloc_command(sc)) == NULL) { 1075 printf("%s: command alloc failed @ line %d\n", __func__, 1076 __LINE__); 1077 error = EBUSY; 1078 goto out; 1079 } 1080 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1081 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1082 request->Function = MPI2_FUNCTION_CONFIG; 1083 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1084 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1085 request->Header.PageNumber = 0; 1086 request->Header.PageLength = mpi_reply->Header.PageLength; 1087 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1088 request->PageAddress = page_address; 1089 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1090 cm->cm_sge = &request->PageBufferSGE; 1091 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1092 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1093 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1094 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1095 if (!page) { 1096 printf("%s: page alloc failed\n", __func__); 1097 error = ENOMEM; 1098 goto out; 1099 } 1100 cm->cm_data = page; 1101 1102 error = mps_request_polled(sc, cm); 1103 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1104 if (error || (reply == NULL)) { 1105 /* FIXME */ 1106 /* If the poll returns error then we need to do diag reset */ 1107 printf("%s: poll for page completed with error %d", 1108 __func__, error); 1109 error = ENXIO; 1110 goto out; 1111 } 1112 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1113 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1114 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1115 /* FIXME */ 1116 /* If the poll returns error then we need to do diag reset */ 1117 printf("%s: page read with error; iocstatus = 0x%x\n", 1118 __func__, ioc_status); 1119 error = ENXIO; 1120 goto out; 1121 } 1122 bcopy(page, config_page, cm->cm_length); 1123 out: 1124 free(page, M_MPT2); 1125 if (cm) 1126 mps_free_command(sc, cm); 1127 return (error); 1128 } 1129 1130 /** 1131 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1132 * @sc: per adapter object 1133 * @mpi_reply: reply mf payload returned from firmware 1134 * @config_page: contents of the config page 1135 * @form: GET_NEXT_HANDLE or HANDLE 1136 * @handle: volume handle 1137 * Context: sleep. 1138 * 1139 * Returns 0 for success, non-zero for failure. 1140 */ 1141 int 1142 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1143 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1144 { 1145 MPI2_CONFIG_REQUEST *request; 1146 MPI2_CONFIG_REPLY *reply; 1147 struct mps_command *cm; 1148 Mpi2RaidVolPage1_t *page = NULL; 1149 int error = 0; 1150 u16 ioc_status; 1151 1152 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1153 1154 if ((cm = mps_alloc_command(sc)) == NULL) { 1155 printf("%s: command alloc failed @ line %d\n", __func__, 1156 __LINE__); 1157 error = EBUSY; 1158 goto out; 1159 } 1160 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1161 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1162 request->Function = MPI2_FUNCTION_CONFIG; 1163 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1164 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1165 request->Header.PageNumber = 1; 1166 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1167 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1168 cm->cm_data = NULL; 1169 error = mps_request_polled(sc, cm); 1170 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1171 if (error || (reply == NULL)) { 1172 /* FIXME */ 1173 /* If the poll returns error then we need to do diag reset */ 1174 printf("%s: poll for header completed with error %d", 1175 __func__, error); 1176 error = ENXIO; 1177 goto out; 1178 } 1179 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1180 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1181 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1182 /* FIXME */ 1183 /* If the poll returns error then we need to do diag reset */ 1184 printf("%s: header read with error; iocstatus = 0x%x\n", 1185 __func__, ioc_status); 1186 error = ENXIO; 1187 goto out; 1188 } 1189 /* We have to do free and alloc for the reply-free and reply-post 1190 * counters to match - Need to review the reply FIFO handling. 1191 */ 1192 mps_free_command(sc, cm); 1193 1194 if ((cm = mps_alloc_command(sc)) == NULL) { 1195 printf("%s: command alloc failed @ line %d\n", __func__, 1196 __LINE__); 1197 error = EBUSY; 1198 goto out; 1199 } 1200 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1201 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1202 request->Function = MPI2_FUNCTION_CONFIG; 1203 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1204 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1205 request->Header.PageNumber = 1; 1206 request->Header.PageLength = mpi_reply->Header.PageLength; 1207 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1208 request->PageAddress = htole32(form | handle); 1209 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1210 cm->cm_sge = &request->PageBufferSGE; 1211 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1212 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1213 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1214 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1215 if (!page) { 1216 printf("%s: page alloc failed\n", __func__); 1217 error = ENOMEM; 1218 goto out; 1219 } 1220 cm->cm_data = page; 1221 1222 error = mps_request_polled(sc, cm); 1223 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1224 if (error || (reply == NULL)) { 1225 /* FIXME */ 1226 /* If the poll returns error then we need to do diag reset */ 1227 printf("%s: poll for page completed with error %d", 1228 __func__, error); 1229 error = ENXIO; 1230 goto out; 1231 } 1232 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1233 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1234 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1235 /* FIXME */ 1236 /* If the poll returns error then we need to do diag reset */ 1237 printf("%s: page read with error; iocstatus = 0x%x\n", 1238 __func__, ioc_status); 1239 error = ENXIO; 1240 goto out; 1241 } 1242 bcopy(page, config_page, MIN(cm->cm_length, 1243 sizeof(Mpi2RaidVolPage1_t))); 1244 out: 1245 free(page, M_MPT2); 1246 if (cm) 1247 mps_free_command(sc, cm); 1248 return (error); 1249 } 1250 1251 /** 1252 * mps_config_get_volume_wwid - returns wwid given the volume handle 1253 * @sc: per adapter object 1254 * @volume_handle: volume handle 1255 * @wwid: volume wwid 1256 * Context: sleep. 1257 * 1258 * Returns 0 for success, non-zero for failure. 1259 */ 1260 int 1261 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1262 { 1263 Mpi2ConfigReply_t mpi_reply; 1264 Mpi2RaidVolPage1_t raid_vol_pg1; 1265 1266 *wwid = 0; 1267 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1268 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1269 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1270 raid_vol_pg1.WWID.Low); 1271 return 0; 1272 } else 1273 return -1; 1274 } 1275 1276 /** 1277 * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1278 * @sc: per adapter object 1279 * @mpi_reply: reply mf payload returned from firmware 1280 * @config_page: contents of the config page 1281 * @page_address: form and handle value used to get page 1282 * Context: sleep. 1283 * 1284 * Returns 0 for success, non-zero for failure. 1285 */ 1286 int 1287 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1288 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1289 { 1290 MPI2_CONFIG_REQUEST *request; 1291 MPI2_CONFIG_REPLY *reply; 1292 struct mps_command *cm; 1293 Mpi2RaidPhysDiskPage0_t *page = NULL; 1294 int error = 0; 1295 u16 ioc_status; 1296 1297 mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1298 1299 if ((cm = mps_alloc_command(sc)) == NULL) { 1300 printf("%s: command alloc failed @ line %d\n", __func__, 1301 __LINE__); 1302 error = EBUSY; 1303 goto out; 1304 } 1305 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1306 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1307 request->Function = MPI2_FUNCTION_CONFIG; 1308 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1309 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1310 request->Header.PageNumber = 0; 1311 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1312 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1313 cm->cm_data = NULL; 1314 error = mps_request_polled(sc, cm); 1315 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1316 if (error || (reply == NULL)) { 1317 /* FIXME */ 1318 /* If the poll returns error then we need to do diag reset */ 1319 printf("%s: poll for header completed with error %d", 1320 __func__, error); 1321 error = ENXIO; 1322 goto out; 1323 } 1324 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1325 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1326 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1327 /* FIXME */ 1328 /* If the poll returns error then we need to do diag reset */ 1329 printf("%s: header read with error; iocstatus = 0x%x\n", 1330 __func__, ioc_status); 1331 error = ENXIO; 1332 goto out; 1333 } 1334 /* We have to do free and alloc for the reply-free and reply-post 1335 * counters to match - Need to review the reply FIFO handling. 1336 */ 1337 mps_free_command(sc, cm); 1338 1339 if ((cm = mps_alloc_command(sc)) == NULL) { 1340 printf("%s: command alloc failed @ line %d\n", __func__, 1341 __LINE__); 1342 error = EBUSY; 1343 goto out; 1344 } 1345 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1346 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1347 request->Function = MPI2_FUNCTION_CONFIG; 1348 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1349 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1350 request->Header.PageNumber = 0; 1351 request->Header.PageLength = mpi_reply->Header.PageLength; 1352 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1353 request->PageAddress = page_address; 1354 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1355 cm->cm_sge = &request->PageBufferSGE; 1356 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1357 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1358 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1359 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1360 if (!page) { 1361 printf("%s: page alloc failed\n", __func__); 1362 error = ENOMEM; 1363 goto out; 1364 } 1365 cm->cm_data = page; 1366 1367 error = mps_request_polled(sc, cm); 1368 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1369 if (error || (reply == NULL)) { 1370 /* FIXME */ 1371 /* If the poll returns error then we need to do diag reset */ 1372 printf("%s: poll for page completed with error %d", 1373 __func__, error); 1374 error = ENXIO; 1375 goto out; 1376 } 1377 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1378 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1379 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1380 /* FIXME */ 1381 /* If the poll returns error then we need to do diag reset */ 1382 printf("%s: page read with error; iocstatus = 0x%x\n", 1383 __func__, ioc_status); 1384 error = ENXIO; 1385 goto out; 1386 } 1387 bcopy(page, config_page, MIN(cm->cm_length, 1388 sizeof(Mpi2RaidPhysDiskPage0_t))); 1389 out: 1390 free(page, M_MPT2); 1391 if (cm) 1392 mps_free_command(sc, cm); 1393 return (error); 1394 } 1395