1 /*- 2 * Copyright (c) 2011-2015 LSI Corp. 3 * Copyright (c) 2013-2016 Avago Technologies 4 * Copyright 2000-2020 Broadcom Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD 29 */ 30 31 #include <sys/cdefs.h> 32 /* TODO Move headers to mprvar */ 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/mpr/mpi/mpi2_type.h> 50 #include <dev/mpr/mpi/mpi2.h> 51 #include <dev/mpr/mpi/mpi2_ioc.h> 52 #include <dev/mpr/mpi/mpi2_sas.h> 53 #include <dev/mpr/mpi/mpi2_pci.h> 54 #include <dev/mpr/mpi/mpi2_cnfg.h> 55 #include <dev/mpr/mpi/mpi2_init.h> 56 #include <dev/mpr/mpi/mpi2_tool.h> 57 #include <dev/mpr/mpr_ioctl.h> 58 #include <dev/mpr/mprvar.h> 59 60 /** 61 * mpr_config_get_ioc_pg8 - obtain ioc page 8 62 * @sc: per adapter object 63 * @mpi_reply: reply mf payload returned from firmware 64 * @config_page: contents of the config page 65 * Context: sleep. 66 * 67 * Returns 0 for success, non-zero for failure. 68 */ 69 int 70 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 71 Mpi2IOCPage8_t *config_page) 72 { 73 MPI2_CONFIG_REQUEST *request; 74 MPI2_CONFIG_REPLY *reply; 75 struct mpr_command *cm; 76 MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 77 int error = 0; 78 u16 ioc_status; 79 80 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 81 82 if ((cm = mpr_alloc_command(sc)) == NULL) { 83 printf("%s: command alloc failed @ line %d\n", __func__, 84 __LINE__); 85 error = EBUSY; 86 goto out; 87 } 88 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 89 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 90 request->Function = MPI2_FUNCTION_CONFIG; 91 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 92 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 93 request->Header.PageNumber = 8; 94 request->Header.PageLength = request->Header.PageVersion = 0; 95 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 96 cm->cm_data = NULL; 97 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 98 if (cm != NULL) 99 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 100 if (error || (reply == NULL)) { 101 /* FIXME */ 102 /* 103 * If the request returns an error then we need to do a diag 104 * reset 105 */ 106 printf("%s: request for header completed with error %d\n", 107 __func__, error); 108 error = ENXIO; 109 goto out; 110 } 111 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 112 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 113 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 114 /* FIXME */ 115 /* 116 * If the request returns an error then we need to do a diag 117 * reset 118 */ 119 printf("%s: header read with error; iocstatus = 0x%x\n", 120 __func__, ioc_status); 121 error = ENXIO; 122 goto out; 123 } 124 /* We have to do free and alloc for the reply-free and reply-post 125 * counters to match - Need to review the reply FIFO handling. 126 */ 127 mpr_free_command(sc, cm); 128 129 if ((cm = mpr_alloc_command(sc)) == NULL) { 130 printf("%s: command alloc failed @ line %d\n", __func__, 131 __LINE__); 132 error = EBUSY; 133 goto out; 134 } 135 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 136 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 137 request->Function = MPI2_FUNCTION_CONFIG; 138 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 139 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 140 request->Header.PageNumber = 8; 141 request->Header.PageVersion = mpi_reply->Header.PageVersion; 142 request->Header.PageLength = mpi_reply->Header.PageLength; 143 cm->cm_length = mpi_reply->Header.PageLength * 4; 144 cm->cm_sge = &request->PageBufferSGE; 145 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 146 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 147 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 148 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 149 if (!page) { 150 printf("%s: page alloc failed\n", __func__); 151 error = ENOMEM; 152 goto out; 153 } 154 cm->cm_data = page; 155 156 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 157 if (cm != NULL) 158 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 159 if (error || (reply == NULL)) { 160 /* FIXME */ 161 /* 162 * If the request returns an error then we need to do a diag 163 * reset 164 */ 165 printf("%s: request for page completed with error %d\n", 166 __func__, error); 167 error = ENXIO; 168 goto out; 169 } 170 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 171 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 172 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 173 /* FIXME */ 174 /* 175 * If the request returns an error then we need to do a diag 176 * reset 177 */ 178 printf("%s: page read with error; iocstatus = 0x%x\n", 179 __func__, ioc_status); 180 error = ENXIO; 181 goto out; 182 } 183 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 184 185 out: 186 free(page, M_MPR); 187 if (cm) 188 mpr_free_command(sc, cm); 189 return (error); 190 } 191 192 /** 193 * mpr_config_get_iounit_pg8 - obtain iounit page 8 194 * @sc: per adapter object 195 * @mpi_reply: reply mf payload returned from firmware 196 * @config_page: contents of the config page 197 * Context: sleep. 198 * 199 * Returns 0 for success, non-zero for failure. 200 */ 201 int 202 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 203 Mpi2IOUnitPage8_t *config_page) 204 { 205 MPI2_CONFIG_REQUEST *request; 206 MPI2_CONFIG_REPLY *reply; 207 struct mpr_command *cm; 208 MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL; 209 int error = 0; 210 u16 ioc_status; 211 212 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 213 214 if ((cm = mpr_alloc_command(sc)) == NULL) { 215 printf("%s: command alloc failed @ line %d\n", __func__, 216 __LINE__); 217 error = EBUSY; 218 goto out; 219 } 220 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 221 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 222 request->Function = MPI2_FUNCTION_CONFIG; 223 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 224 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 225 request->Header.PageNumber = 8; 226 request->Header.PageLength = request->Header.PageVersion = 0; 227 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 228 cm->cm_data = NULL; 229 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 230 if (cm != NULL) 231 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 232 if (error || (reply == NULL)) { 233 /* FIXME */ 234 /* 235 * If the request returns an error then we need to do a diag 236 * reset 237 */ 238 printf("%s: request for header completed with error %d\n", 239 __func__, error); 240 error = ENXIO; 241 goto out; 242 } 243 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 244 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 245 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 246 /* FIXME */ 247 /* 248 * If the request returns an error then we need to do a diag 249 * reset 250 */ 251 printf("%s: header read with error; iocstatus = 0x%x\n", 252 __func__, ioc_status); 253 error = ENXIO; 254 goto out; 255 } 256 /* We have to do free and alloc for the reply-free and reply-post 257 * counters to match - Need to review the reply FIFO handling. 258 */ 259 mpr_free_command(sc, cm); 260 261 if ((cm = mpr_alloc_command(sc)) == NULL) { 262 printf("%s: command alloc failed @ line %d\n", __func__, 263 __LINE__); 264 error = EBUSY; 265 goto out; 266 } 267 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 268 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 269 request->Function = MPI2_FUNCTION_CONFIG; 270 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 271 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 272 request->Header.PageNumber = 8; 273 request->Header.PageVersion = mpi_reply->Header.PageVersion; 274 request->Header.PageLength = mpi_reply->Header.PageLength; 275 cm->cm_length = mpi_reply->Header.PageLength * 4; 276 cm->cm_sge = &request->PageBufferSGE; 277 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 278 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 279 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 280 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 281 if (!page) { 282 printf("%s: page alloc failed\n", __func__); 283 error = ENOMEM; 284 goto out; 285 } 286 cm->cm_data = page; 287 288 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 289 if (cm != NULL) 290 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 291 if (error || (reply == NULL)) { 292 /* FIXME */ 293 /* 294 * If the request returns an error then we need to do a diag 295 * reset 296 */ 297 printf("%s: request for page completed with error %d\n", 298 __func__, error); 299 error = ENXIO; 300 goto out; 301 } 302 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 303 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 304 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 305 /* FIXME */ 306 /* 307 * If the request returns an error then we need to do a diag 308 * reset 309 */ 310 printf("%s: page read with error; iocstatus = 0x%x\n", 311 __func__, ioc_status); 312 error = ENXIO; 313 goto out; 314 } 315 bcopy(page, config_page, MIN(cm->cm_length, 316 (sizeof(Mpi2IOUnitPage8_t)))); 317 318 out: 319 free(page, M_MPR); 320 if (cm) 321 mpr_free_command(sc, cm); 322 return (error); 323 } 324 325 /** 326 * mpr_config_get_man_pg11 - obtain manufacturing page 11 327 * @sc: per adapter object 328 * @mpi_reply: reply mf payload returned from firmware 329 * @config_page: contents of the config page 330 * Context: sleep. 331 * 332 * Returns 0 for success, non-zero for failure. 333 */ 334 int 335 mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 336 Mpi2ManufacturingPage11_t *config_page) 337 { 338 MPI2_CONFIG_REQUEST *request; 339 MPI2_CONFIG_REPLY *reply; 340 struct mpr_command *cm; 341 MPI2_CONFIG_PAGE_MAN_11 *page = NULL; 342 int error = 0; 343 u16 ioc_status; 344 345 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 346 347 if ((cm = mpr_alloc_command(sc)) == NULL) { 348 printf("%s: command alloc failed @ line %d\n", __func__, 349 __LINE__); 350 error = EBUSY; 351 goto out; 352 } 353 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 354 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 355 request->Function = MPI2_FUNCTION_CONFIG; 356 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 357 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 358 request->Header.PageNumber = 11; 359 request->Header.PageLength = request->Header.PageVersion = 0; 360 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 361 cm->cm_data = NULL; 362 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 363 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 364 if (error || (reply == NULL)) { 365 /* FIXME */ 366 /* 367 * If the request returns an error then we need to do a diag 368 * reset 369 */ 370 printf("%s: request for header completed with error %d\n", 371 __func__, error); 372 error = ENXIO; 373 goto out; 374 } 375 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 376 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 377 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 378 /* FIXME */ 379 /* 380 * If the request returns an error then we need to do a diag 381 * reset 382 */ 383 printf("%s: header read with error; iocstatus = 0x%x\n", 384 __func__, ioc_status); 385 error = ENXIO; 386 goto out; 387 } 388 /* We have to do free and alloc for the reply-free and reply-post 389 * counters to match - Need to review the reply FIFO handling. 390 */ 391 mpr_free_command(sc, cm); 392 393 if ((cm = mpr_alloc_command(sc)) == NULL) { 394 printf("%s: command alloc failed @ line %d\n", __func__, 395 __LINE__); 396 error = EBUSY; 397 goto out; 398 } 399 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 400 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 401 request->Function = MPI2_FUNCTION_CONFIG; 402 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 403 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 404 request->Header.PageNumber = 11; 405 request->Header.PageVersion = mpi_reply->Header.PageVersion; 406 request->Header.PageLength = mpi_reply->Header.PageLength; 407 cm->cm_length = mpi_reply->Header.PageLength * 4; 408 cm->cm_sge = &request->PageBufferSGE; 409 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 410 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 411 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 412 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 413 if (!page) { 414 printf("%s: page alloc failed\n", __func__); 415 error = ENOMEM; 416 goto out; 417 } 418 cm->cm_data = page; 419 420 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 421 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 422 if (error || (reply == NULL)) { 423 /* FIXME */ 424 /* 425 * If the request returns an error then we need to do a diag 426 * reset 427 */ 428 printf("%s: request for page completed with error %d\n", 429 __func__, error); 430 error = ENXIO; 431 goto out; 432 } 433 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 434 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 435 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 436 /* FIXME */ 437 /* 438 * If the request returns an error then we need to do a diag 439 * reset 440 */ 441 printf("%s: page read with error; iocstatus = 0x%x\n", 442 __func__, ioc_status); 443 error = ENXIO; 444 goto out; 445 } 446 bcopy(page, config_page, MIN(cm->cm_length, 447 (sizeof(Mpi2ManufacturingPage11_t)))); 448 449 out: 450 free(page, M_MPR); 451 if (cm) 452 mpr_free_command(sc, cm); 453 return (error); 454 } 455 456 /** 457 * mpr_base_static_config_pages - static start of day config pages. 458 * @sc: per adapter object 459 * 460 * Return nothing. 461 */ 462 void 463 mpr_base_static_config_pages(struct mpr_softc *sc) 464 { 465 Mpi2ConfigReply_t mpi_reply; 466 Mpi2ManufacturingPage11_t man_pg11; 467 int retry, rc; 468 469 retry = 0; 470 while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 471 retry++; 472 if (retry > 5) { 473 /* We need to Handle this situation */ 474 /*FIXME*/ 475 break; 476 } 477 } 478 retry = 0; 479 while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) { 480 retry++; 481 if (retry > 5) { 482 /* We need to Handle this situation */ 483 /*FIXME*/ 484 break; 485 } 486 } 487 retry = 0; 488 while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) { 489 retry++; 490 if (retry > 5) { 491 /* We need to Handle this situation */ 492 /*FIXME*/ 493 break; 494 } 495 } 496 497 if (!rc) { 498 sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) & 499 MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK); 500 sc->nvme_abort_timeout = man_pg11.NVMeAbortTO; 501 502 /* Minimum NVMe Abort timeout value should be 6 seconds & 503 * maximum value should be 60 seconds. 504 */ 505 if (sc->nvme_abort_timeout < 6) 506 sc->nvme_abort_timeout = 6; 507 if (sc->nvme_abort_timeout > 60) 508 sc->nvme_abort_timeout = 60; 509 } 510 } 511 512 /** 513 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0 514 * @sc: per adapter object 515 * @mpi_reply: reply mf payload returned from firmware 516 * @config_page: contents of the config page 517 * @sz: size of buffer passed in config_page 518 * Context: sleep. 519 * 520 * Returns 0 for success, non-zero for failure. 521 */ 522 int 523 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 524 Mpi2DriverMappingPage0_t *config_page, u16 sz) 525 { 526 MPI2_CONFIG_REQUEST *request; 527 MPI2_CONFIG_REPLY *reply; 528 struct mpr_command *cm; 529 Mpi2DriverMappingPage0_t *page = NULL; 530 int error = 0; 531 u16 ioc_status; 532 533 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 534 535 memset(config_page, 0, sz); 536 if ((cm = mpr_alloc_command(sc)) == NULL) { 537 printf("%s: command alloc failed @ line %d\n", __func__, 538 __LINE__); 539 error = EBUSY; 540 goto out; 541 } 542 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 543 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 544 request->Function = MPI2_FUNCTION_CONFIG; 545 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 546 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 547 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 548 request->Header.PageNumber = 0; 549 request->ExtPageLength = request->Header.PageVersion = 0; 550 request->PageAddress = htole32(sc->max_dpm_entries << 551 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT); 552 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 553 cm->cm_data = NULL; 554 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 555 if (cm != NULL) 556 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 557 if (error || (reply == NULL)) { 558 /* FIXME */ 559 /* 560 * If the request returns an error then we need to do a diag 561 * reset 562 */ 563 printf("%s: request for header completed with error %d\n", 564 __func__, error); 565 error = ENXIO; 566 goto out; 567 } 568 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 569 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 570 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 571 /* FIXME */ 572 /* 573 * If the request returns an error then we need to do a diag 574 * reset 575 */ 576 printf("%s: header read with error; iocstatus = 0x%x\n", 577 __func__, ioc_status); 578 error = ENXIO; 579 goto out; 580 } 581 /* We have to do free and alloc for the reply-free and reply-post 582 * counters to match - Need to review the reply FIFO handling. 583 */ 584 mpr_free_command(sc, cm); 585 586 if ((cm = mpr_alloc_command(sc)) == NULL) { 587 printf("%s: command alloc failed @ line %d\n", __func__, 588 __LINE__); 589 error = EBUSY; 590 goto out; 591 } 592 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 593 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 594 request->Function = MPI2_FUNCTION_CONFIG; 595 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 596 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 597 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 598 request->Header.PageNumber = 0; 599 request->Header.PageVersion = mpi_reply->Header.PageVersion; 600 request->PageAddress = htole32(sc->max_dpm_entries << 601 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT); 602 request->ExtPageLength = mpi_reply->ExtPageLength; 603 cm->cm_length = le16toh(request->ExtPageLength) * 4; 604 cm->cm_sge = &request->PageBufferSGE; 605 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 606 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 607 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 608 page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT); 609 if (!page) { 610 printf("%s: page alloc failed\n", __func__); 611 error = ENOMEM; 612 goto out; 613 } 614 cm->cm_data = page; 615 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 616 if (cm != NULL) 617 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 618 if (error || (reply == NULL)) { 619 /* FIXME */ 620 /* 621 * If the request returns an error then we need to do a diag 622 * reset 623 */ 624 printf("%s: request for page completed with error %d\n", 625 __func__, error); 626 error = ENXIO; 627 goto out; 628 } 629 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 630 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 631 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 632 /* FIXME */ 633 /* 634 * If the request returns an error then we need to do a diag 635 * reset 636 */ 637 printf("%s: page read with error; iocstatus = 0x%x\n", 638 __func__, ioc_status); 639 error = ENXIO; 640 goto out; 641 } 642 bcopy(page, config_page, MIN(cm->cm_length, sz)); 643 out: 644 free(page, M_MPR); 645 if (cm) 646 mpr_free_command(sc, cm); 647 return (error); 648 } 649 650 /** 651 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 652 * @sc: per adapter object 653 * @mpi_reply: reply mf payload returned from firmware 654 * @config_page: contents of the config page 655 * @entry_idx: entry index in DPM Page0 to be modified 656 * Context: sleep. 657 * 658 * Returns 0 for success, non-zero for failure. 659 */ 660 661 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 662 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 663 { 664 MPI2_CONFIG_REQUEST *request; 665 MPI2_CONFIG_REPLY *reply; 666 struct mpr_command *cm; 667 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 668 int error = 0; 669 u16 ioc_status; 670 671 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 672 673 if ((cm = mpr_alloc_command(sc)) == NULL) { 674 printf("%s: command alloc failed @ line %d\n", __func__, 675 __LINE__); 676 error = EBUSY; 677 goto out; 678 } 679 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 680 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 681 request->Function = MPI2_FUNCTION_CONFIG; 682 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 683 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 684 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 685 request->Header.PageNumber = 0; 686 request->ExtPageLength = request->Header.PageVersion = 0; 687 request->PageAddress = htole32( 688 (1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx); 689 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 690 cm->cm_data = NULL; 691 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 692 if (cm != NULL) 693 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 694 if (error || (reply == NULL)) { 695 /* FIXME */ 696 /* 697 * If the request returns an error then we need to do a diag 698 * reset 699 */ 700 printf("%s: request for header completed with error %d\n", 701 __func__, error); 702 error = ENXIO; 703 goto out; 704 } 705 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 706 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 707 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 708 /* FIXME */ 709 /* 710 * If the request returns an error then we need to do a diag 711 * reset 712 */ 713 printf("%s: header read with error; iocstatus = 0x%x\n", 714 __func__, ioc_status); 715 error = ENXIO; 716 goto out; 717 } 718 /* We have to do free and alloc for the reply-free and reply-post 719 * counters to match - Need to review the reply FIFO handling. 720 */ 721 mpr_free_command(sc, cm); 722 723 if ((cm = mpr_alloc_command(sc)) == NULL) { 724 printf("%s: command alloc failed @ line %d\n", __func__, 725 __LINE__); 726 error = EBUSY; 727 goto out; 728 } 729 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 730 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 731 request->Function = MPI2_FUNCTION_CONFIG; 732 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 733 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 734 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 735 request->Header.PageNumber = 0; 736 request->Header.PageVersion = mpi_reply->Header.PageVersion; 737 request->ExtPageLength = mpi_reply->ExtPageLength; 738 request->PageAddress = htole32( 739 (1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx); 740 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 741 cm->cm_sge = &request->PageBufferSGE; 742 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 743 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT; 744 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 745 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 746 if (!page) { 747 printf("%s: page alloc failed\n", __func__); 748 error = ENOMEM; 749 goto out; 750 } 751 bcopy(config_page, page, MIN(cm->cm_length, 752 (sizeof(Mpi2DriverMappingPage0_t)))); 753 cm->cm_data = page; 754 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 755 if (cm != NULL) 756 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 757 if (error || (reply == NULL)) { 758 /* FIXME */ 759 /* 760 * If the request returns an error then we need to do a diag 761 * reset 762 */ 763 printf("%s: request to write page completed with error %d\n", 764 __func__, error); 765 error = ENXIO; 766 goto out; 767 } 768 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 769 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 770 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 771 /* FIXME */ 772 /* 773 * If the request returns an error then we need to do a diag 774 * reset 775 */ 776 printf("%s: page written with error; iocstatus = 0x%x\n", 777 __func__, ioc_status); 778 error = ENXIO; 779 goto out; 780 } 781 out: 782 free(page, M_MPR); 783 if (cm) 784 mpr_free_command(sc, cm); 785 return (error); 786 } 787 788 /** 789 * mpr_config_get_sas_device_pg0 - obtain sas device page 0 790 * @sc: per adapter object 791 * @mpi_reply: reply mf payload returned from firmware 792 * @config_page: contents of the config page 793 * @form: GET_NEXT_HANDLE or HANDLE 794 * @handle: device handle 795 * Context: sleep. 796 * 797 * Returns 0 for success, non-zero for failure. 798 */ 799 int 800 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 801 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 802 { 803 MPI2_CONFIG_REQUEST *request; 804 MPI2_CONFIG_REPLY *reply; 805 struct mpr_command *cm; 806 Mpi2SasDevicePage0_t *page = NULL; 807 int error = 0; 808 u16 ioc_status; 809 810 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 811 812 if ((cm = mpr_alloc_command(sc)) == NULL) { 813 printf("%s: command alloc failed @ line %d\n", __func__, 814 __LINE__); 815 error = EBUSY; 816 goto out; 817 } 818 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 819 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 820 request->Function = MPI2_FUNCTION_CONFIG; 821 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 822 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 823 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 824 request->Header.PageNumber = 0; 825 request->ExtPageLength = request->Header.PageVersion = 0; 826 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 827 cm->cm_data = NULL; 828 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 829 if (cm != NULL) 830 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 831 if (error || (reply == NULL)) { 832 /* FIXME */ 833 /* 834 * If the request returns an error then we need to do a diag 835 * reset 836 */ 837 printf("%s: request for header completed with error %d\n", 838 __func__, error); 839 error = ENXIO; 840 goto out; 841 } 842 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 843 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 844 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 845 /* FIXME */ 846 /* 847 * If the request returns an error then we need to do a diag 848 * reset 849 */ 850 printf("%s: header read with error; iocstatus = 0x%x\n", 851 __func__, ioc_status); 852 error = ENXIO; 853 goto out; 854 } 855 /* We have to do free and alloc for the reply-free and reply-post 856 * counters to match - Need to review the reply FIFO handling. 857 */ 858 mpr_free_command(sc, cm); 859 860 if ((cm = mpr_alloc_command(sc)) == NULL) { 861 printf("%s: command alloc failed @ line %d\n", __func__, 862 __LINE__); 863 error = EBUSY; 864 goto out; 865 } 866 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 867 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 868 request->Function = MPI2_FUNCTION_CONFIG; 869 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 870 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 871 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 872 request->Header.PageNumber = 0; 873 request->Header.PageVersion = mpi_reply->Header.PageVersion; 874 request->ExtPageLength = mpi_reply->ExtPageLength; 875 request->PageAddress = htole32(form | handle); 876 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 877 cm->cm_sge = &request->PageBufferSGE; 878 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 879 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 880 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 881 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 882 if (!page) { 883 printf("%s: page alloc failed\n", __func__); 884 error = ENOMEM; 885 goto out; 886 } 887 cm->cm_data = page; 888 889 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 890 if (cm != NULL) 891 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 892 if (error || (reply == NULL)) { 893 /* FIXME */ 894 /* 895 * If the request returns an error then we need to do a diag 896 * reset 897 */ 898 printf("%s: request for page completed with error %d\n", 899 __func__, error); 900 error = ENXIO; 901 goto out; 902 } 903 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 904 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 905 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 906 /* FIXME */ 907 /* 908 * If the request returns an error then we need to do a diag 909 * reset 910 */ 911 printf("%s: page read with error; iocstatus = 0x%x\n", 912 __func__, ioc_status); 913 error = ENXIO; 914 goto out; 915 } 916 bcopy(page, config_page, MIN(cm->cm_length, 917 sizeof(Mpi2SasDevicePage0_t))); 918 out: 919 free(page, M_MPR); 920 if (cm) 921 mpr_free_command(sc, cm); 922 return (error); 923 } 924 925 /** 926 * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0 927 * @sc: per adapter object 928 * @mpi_reply: reply mf payload returned from firmware 929 * @config_page: contents of the config page 930 * @form: GET_NEXT_HANDLE or HANDLE 931 * @handle: device handle 932 * Context: sleep. 933 * 934 * Returns 0 for success, non-zero for failure. 935 */ 936 int 937 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 938 *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle) 939 { 940 MPI2_CONFIG_REQUEST *request; 941 MPI2_CONFIG_REPLY *reply; 942 struct mpr_command *cm; 943 Mpi26PCIeDevicePage0_t *page = NULL; 944 int error = 0; 945 u16 ioc_status; 946 947 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 948 949 if ((cm = mpr_alloc_command(sc)) == NULL) { 950 printf("%s: command alloc failed @ line %d\n", __func__, 951 __LINE__); 952 error = EBUSY; 953 goto out; 954 } 955 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 956 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 957 request->Function = MPI2_FUNCTION_CONFIG; 958 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 959 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 960 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 961 request->Header.PageNumber = 0; 962 request->ExtPageLength = request->Header.PageVersion = 0; 963 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 964 cm->cm_data = NULL; 965 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 966 if (cm != NULL) 967 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 968 if (error || (reply == NULL)) { 969 /* FIXME */ 970 /* 971 * If the request returns an error then we need to do a diag 972 * reset 973 */ 974 printf("%s: request for header completed with error %d\n", 975 __func__, error); 976 error = ENXIO; 977 goto out; 978 } 979 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 980 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 981 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 982 /* FIXME */ 983 /* 984 * If the request returns an error then we need to do a diag 985 * reset 986 */ 987 printf("%s: header read with error; iocstatus = 0x%x\n", 988 __func__, ioc_status); 989 error = ENXIO; 990 goto out; 991 } 992 /* We have to do free and alloc for the reply-free and reply-post 993 * counters to match - Need to review the reply FIFO handling. 994 */ 995 mpr_free_command(sc, cm); 996 997 if ((cm = mpr_alloc_command(sc)) == NULL) { 998 printf("%s: command alloc failed @ line %d\n", __func__, 999 __LINE__); 1000 error = EBUSY; 1001 goto out; 1002 } 1003 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1004 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1005 request->Function = MPI2_FUNCTION_CONFIG; 1006 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1007 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1008 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1009 request->Header.PageNumber = 0; 1010 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1011 request->ExtPageLength = mpi_reply->ExtPageLength; 1012 request->PageAddress = htole32(form | handle); 1013 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 1014 cm->cm_sge = &request->PageBufferSGE; 1015 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1016 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1017 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1018 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1019 if (!page) { 1020 printf("%s: page alloc failed\n", __func__); 1021 error = ENOMEM; 1022 goto out; 1023 } 1024 cm->cm_data = page; 1025 1026 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1027 if (cm != NULL) 1028 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1029 if (error || (reply == NULL)) { 1030 /* FIXME */ 1031 /* 1032 * If the request returns an error then we need to do a diag 1033 * reset 1034 */ 1035 printf("%s: request for page completed with error %d\n", 1036 __func__, error); 1037 error = ENXIO; 1038 goto out; 1039 } 1040 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1041 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1042 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1043 /* FIXME */ 1044 /* 1045 * If the request returns an error then we need to do a diag 1046 * reset 1047 */ 1048 printf("%s: page read with error; iocstatus = 0x%x\n", 1049 __func__, ioc_status); 1050 error = ENXIO; 1051 goto out; 1052 } 1053 bcopy(page, config_page, MIN(cm->cm_length, 1054 sizeof(Mpi26PCIeDevicePage0_t))); 1055 out: 1056 free(page, M_MPR); 1057 if (cm) 1058 mpr_free_command(sc, cm); 1059 return (error); 1060 } 1061 1062 /** 1063 * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2 1064 * @sc: per adapter object 1065 * @mpi_reply: reply mf payload returned from firmware 1066 * @config_page: contents of the config page 1067 * @form: GET_NEXT_HANDLE or HANDLE 1068 * @handle: device handle 1069 * Context: sleep. 1070 * 1071 * Returns 0 for success, non-zero for failure. 1072 */ 1073 int 1074 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t 1075 *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle) 1076 { 1077 MPI2_CONFIG_REQUEST *request; 1078 MPI2_CONFIG_REPLY *reply; 1079 struct mpr_command *cm; 1080 Mpi26PCIeDevicePage2_t *page = NULL; 1081 int error = 0; 1082 u16 ioc_status; 1083 1084 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1085 1086 if ((cm = mpr_alloc_command(sc)) == NULL) { 1087 printf("%s: command alloc failed @ line %d\n", __func__, 1088 __LINE__); 1089 error = EBUSY; 1090 goto out; 1091 } 1092 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1093 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1094 request->Function = MPI2_FUNCTION_CONFIG; 1095 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1096 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1097 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1098 request->Header.PageNumber = 2; 1099 request->ExtPageLength = request->Header.PageVersion = 0; 1100 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1101 cm->cm_data = NULL; 1102 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1103 if (cm != NULL) 1104 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1105 if (error || (reply == NULL)) { 1106 /* FIXME */ 1107 /* 1108 * If the request returns an error then we need to do a diag 1109 * reset 1110 */ 1111 printf("%s: request for header completed with error %d\n", 1112 __func__, error); 1113 error = ENXIO; 1114 goto out; 1115 } 1116 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1117 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1118 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1119 /* FIXME */ 1120 /* 1121 * If the request returns an error then we need to do a diag 1122 * reset 1123 */ 1124 printf("%s: header read with error; iocstatus = 0x%x\n", 1125 __func__, ioc_status); 1126 error = ENXIO; 1127 goto out; 1128 } 1129 /* We have to do free and alloc for the reply-free and reply-post 1130 * counters to match - Need to review the reply FIFO handling. 1131 */ 1132 mpr_free_command(sc, cm); 1133 1134 if ((cm = mpr_alloc_command(sc)) == NULL) { 1135 printf("%s: command alloc failed @ line %d\n", __func__, 1136 __LINE__); 1137 error = EBUSY; 1138 goto out; 1139 } 1140 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1141 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1142 request->Function = MPI2_FUNCTION_CONFIG; 1143 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1144 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1145 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1146 request->Header.PageNumber = 2; 1147 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1148 request->ExtPageLength = mpi_reply->ExtPageLength; 1149 request->PageAddress = htole32(form | handle); 1150 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 1151 cm->cm_sge = &request->PageBufferSGE; 1152 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1153 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1154 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1155 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1156 if (!page) { 1157 printf("%s: page alloc failed\n", __func__); 1158 error = ENOMEM; 1159 goto out; 1160 } 1161 cm->cm_data = page; 1162 1163 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1164 if (cm != NULL) 1165 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1166 if (error || (reply == NULL)) { 1167 /* FIXME */ 1168 /* 1169 * If the request returns an error then we need to do a diag 1170 * reset 1171 */ 1172 printf("%s: request for page completed with error %d\n", 1173 __func__, error); 1174 error = ENXIO; 1175 goto out; 1176 } 1177 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1178 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1179 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1180 /* FIXME */ 1181 /* 1182 * If the request returns an error then we need to do a diag 1183 * reset 1184 */ 1185 printf("%s: page read with error; iocstatus = 0x%x\n", 1186 __func__, ioc_status); 1187 error = ENXIO; 1188 goto out; 1189 } 1190 bcopy(page, config_page, MIN(cm->cm_length, 1191 sizeof(Mpi26PCIeDevicePage2_t))); 1192 out: 1193 free(page, M_MPR); 1194 if (cm) 1195 mpr_free_command(sc, cm); 1196 return (error); 1197 } 1198 1199 /** 1200 * mpr_config_get_bios_pg3 - obtain BIOS page 3 1201 * @sc: per adapter object 1202 * @mpi_reply: reply mf payload returned from firmware 1203 * @config_page: contents of the config page 1204 * Context: sleep. 1205 * 1206 * Returns 0 for success, non-zero for failure. 1207 */ 1208 int 1209 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1210 Mpi2BiosPage3_t *config_page) 1211 { 1212 MPI2_CONFIG_REQUEST *request; 1213 MPI2_CONFIG_REPLY *reply; 1214 struct mpr_command *cm; 1215 Mpi2BiosPage3_t *page = NULL; 1216 int error = 0; 1217 u16 ioc_status; 1218 1219 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1220 1221 if ((cm = mpr_alloc_command(sc)) == NULL) { 1222 printf("%s: command alloc failed @ line %d\n", __func__, 1223 __LINE__); 1224 error = EBUSY; 1225 goto out; 1226 } 1227 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1228 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1229 request->Function = MPI2_FUNCTION_CONFIG; 1230 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1231 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1232 request->Header.PageNumber = 3; 1233 request->Header.PageLength = request->Header.PageVersion = 0; 1234 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1235 cm->cm_data = NULL; 1236 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1237 if (cm != NULL) 1238 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1239 if (error || (reply == NULL)) { 1240 /* FIXME */ 1241 /* 1242 * If the request returns an error then we need to do a diag 1243 * reset 1244 */ 1245 printf("%s: request for header completed with error %d\n", 1246 __func__, error); 1247 error = ENXIO; 1248 goto out; 1249 } 1250 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1251 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1252 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1253 /* FIXME */ 1254 /* 1255 * If the request returns an error then we need to do a diag 1256 * reset 1257 */ 1258 printf("%s: header read with error; iocstatus = 0x%x\n", 1259 __func__, ioc_status); 1260 error = ENXIO; 1261 goto out; 1262 } 1263 /* We have to do free and alloc for the reply-free and reply-post 1264 * counters to match - Need to review the reply FIFO handling. 1265 */ 1266 mpr_free_command(sc, cm); 1267 1268 if ((cm = mpr_alloc_command(sc)) == NULL) { 1269 printf("%s: command alloc failed @ line %d\n", __func__, 1270 __LINE__); 1271 error = EBUSY; 1272 goto out; 1273 } 1274 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1275 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1276 request->Function = MPI2_FUNCTION_CONFIG; 1277 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1278 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1279 request->Header.PageNumber = 3; 1280 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1281 request->Header.PageLength = mpi_reply->Header.PageLength; 1282 cm->cm_length = mpi_reply->Header.PageLength * 4; 1283 cm->cm_sge = &request->PageBufferSGE; 1284 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1285 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1286 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1287 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1288 if (!page) { 1289 printf("%s: page alloc failed\n", __func__); 1290 error = ENOMEM; 1291 goto out; 1292 } 1293 cm->cm_data = page; 1294 1295 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1296 if (cm != NULL) 1297 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1298 if (error || (reply == NULL)) { 1299 /* FIXME */ 1300 /* 1301 * If the request returns an error then we need to do a diag 1302 * reset 1303 */ 1304 printf("%s: request for page completed with error %d\n", 1305 __func__, error); 1306 error = ENXIO; 1307 goto out; 1308 } 1309 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1310 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1311 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1312 /* FIXME */ 1313 /* 1314 * If the request returns an error then we need to do a diag 1315 * reset 1316 */ 1317 printf("%s: page read with error; iocstatus = 0x%x\n", 1318 __func__, ioc_status); 1319 error = ENXIO; 1320 goto out; 1321 } 1322 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1323 out: 1324 free(page, M_MPR); 1325 if (cm) 1326 mpr_free_command(sc, cm); 1327 return (error); 1328 } 1329 1330 /** 1331 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0 1332 * @sc: per adapter object 1333 * @mpi_reply: reply mf payload returned from firmware 1334 * @config_page: contents of the config page 1335 * @page_address: form and handle value used to get page 1336 * Context: sleep. 1337 * 1338 * Returns 0 for success, non-zero for failure. 1339 */ 1340 int 1341 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 1342 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1343 { 1344 MPI2_CONFIG_REQUEST *request; 1345 MPI2_CONFIG_REPLY *reply = NULL; 1346 struct mpr_command *cm; 1347 Mpi2RaidVolPage0_t *page = NULL; 1348 int error = 0; 1349 u16 ioc_status; 1350 1351 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1352 1353 if ((cm = mpr_alloc_command(sc)) == NULL) { 1354 printf("%s: command alloc failed @ line %d\n", __func__, 1355 __LINE__); 1356 error = EBUSY; 1357 goto out; 1358 } 1359 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1360 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1361 request->Function = MPI2_FUNCTION_CONFIG; 1362 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1363 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1364 request->Header.PageNumber = 0; 1365 request->Header.PageLength = request->Header.PageVersion = 0; 1366 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1367 cm->cm_data = NULL; 1368 1369 /* 1370 * This page must be polled because the IOC isn't ready yet when this 1371 * page is needed. 1372 */ 1373 error = mpr_request_polled(sc, &cm); 1374 if (cm != NULL) 1375 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1376 if (error || (reply == NULL)) { 1377 /* FIXME */ 1378 /* If the poll returns error then we need to do diag reset */ 1379 printf("%s: poll for header completed with error %d\n", 1380 __func__, error); 1381 error = ENXIO; 1382 goto out; 1383 } 1384 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1385 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1386 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1387 /* FIXME */ 1388 /* If the poll returns error then we need to do diag reset */ 1389 printf("%s: header read with error; iocstatus = 0x%x\n", 1390 __func__, ioc_status); 1391 error = ENXIO; 1392 goto out; 1393 } 1394 /* We have to do free and alloc for the reply-free and reply-post 1395 * counters to match - Need to review the reply FIFO handling. 1396 */ 1397 mpr_free_command(sc, cm); 1398 1399 if ((cm = mpr_alloc_command(sc)) == NULL) { 1400 printf("%s: command alloc failed @ line %d\n", __func__, 1401 __LINE__); 1402 error = EBUSY; 1403 goto out; 1404 } 1405 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1406 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1407 request->Function = MPI2_FUNCTION_CONFIG; 1408 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1409 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1410 request->Header.PageNumber = 0; 1411 request->Header.PageLength = mpi_reply->Header.PageLength; 1412 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1413 request->PageAddress = page_address; 1414 cm->cm_length = mpi_reply->Header.PageLength * 4; 1415 cm->cm_sge = &request->PageBufferSGE; 1416 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1417 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1418 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1419 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1420 if (!page) { 1421 printf("%s: page alloc failed\n", __func__); 1422 error = ENOMEM; 1423 goto out; 1424 } 1425 cm->cm_data = page; 1426 1427 /* 1428 * This page must be polled because the IOC isn't ready yet when this 1429 * page is needed. 1430 */ 1431 error = mpr_request_polled(sc, &cm); 1432 if (cm != NULL) 1433 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1434 if (error || (reply == NULL)) { 1435 /* FIXME */ 1436 /* If the poll returns error then we need to do diag reset */ 1437 printf("%s: poll for page completed with error %d\n", 1438 __func__, error); 1439 error = ENXIO; 1440 goto out; 1441 } 1442 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1443 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1444 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1445 /* FIXME */ 1446 /* If the poll returns error then we need to do diag reset */ 1447 printf("%s: page read with error; iocstatus = 0x%x\n", 1448 __func__, ioc_status); 1449 error = ENXIO; 1450 goto out; 1451 } 1452 bcopy(page, config_page, cm->cm_length); 1453 out: 1454 free(page, M_MPR); 1455 if (cm) 1456 mpr_free_command(sc, cm); 1457 return (error); 1458 } 1459 1460 /** 1461 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1 1462 * @sc: per adapter object 1463 * @mpi_reply: reply mf payload returned from firmware 1464 * @config_page: contents of the config page 1465 * @form: GET_NEXT_HANDLE or HANDLE 1466 * @handle: volume handle 1467 * Context: sleep. 1468 * 1469 * Returns 0 for success, non-zero for failure. 1470 */ 1471 int 1472 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t 1473 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1474 { 1475 MPI2_CONFIG_REQUEST *request; 1476 MPI2_CONFIG_REPLY *reply; 1477 struct mpr_command *cm; 1478 Mpi2RaidVolPage1_t *page = NULL; 1479 int error = 0; 1480 u16 ioc_status; 1481 1482 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1483 1484 if ((cm = mpr_alloc_command(sc)) == NULL) { 1485 printf("%s: command alloc failed @ line %d\n", __func__, 1486 __LINE__); 1487 error = EBUSY; 1488 goto out; 1489 } 1490 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1491 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1492 request->Function = MPI2_FUNCTION_CONFIG; 1493 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1494 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1495 request->Header.PageNumber = 1; 1496 request->Header.PageLength = request->Header.PageVersion = 0; 1497 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1498 cm->cm_data = NULL; 1499 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1500 if (cm != NULL) 1501 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1502 if (error || (reply == NULL)) { 1503 /* FIXME */ 1504 /* 1505 * If the request returns an error then we need to do a diag 1506 * reset 1507 */ 1508 printf("%s: request for header completed with error %d\n", 1509 __func__, error); 1510 error = ENXIO; 1511 goto out; 1512 } 1513 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1514 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1515 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1516 /* FIXME */ 1517 /* 1518 * If the request returns an error then we need to do a diag 1519 * reset 1520 */ 1521 printf("%s: header read with error; iocstatus = 0x%x\n", 1522 __func__, ioc_status); 1523 error = ENXIO; 1524 goto out; 1525 } 1526 /* We have to do free and alloc for the reply-free and reply-post 1527 * counters to match - Need to review the reply FIFO handling. 1528 */ 1529 mpr_free_command(sc, cm); 1530 1531 if ((cm = mpr_alloc_command(sc)) == NULL) { 1532 printf("%s: command alloc failed @ line %d\n", __func__, 1533 __LINE__); 1534 error = EBUSY; 1535 goto out; 1536 } 1537 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1538 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1539 request->Function = MPI2_FUNCTION_CONFIG; 1540 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1541 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1542 request->Header.PageNumber = 1; 1543 request->Header.PageLength = mpi_reply->Header.PageLength; 1544 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1545 request->PageAddress = htole32(form | handle); 1546 cm->cm_length = mpi_reply->Header.PageLength * 4; 1547 cm->cm_sge = &request->PageBufferSGE; 1548 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1549 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1550 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1551 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1552 if (!page) { 1553 printf("%s: page alloc failed\n", __func__); 1554 error = ENOMEM; 1555 goto out; 1556 } 1557 cm->cm_data = page; 1558 1559 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1560 if (cm != NULL) 1561 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1562 if (error || (reply == NULL)) { 1563 /* FIXME */ 1564 /* 1565 * If the request returns an error then we need to do a diag 1566 * reset 1567 */ 1568 printf("%s: request for page completed with error %d\n", 1569 __func__, error); 1570 error = ENXIO; 1571 goto out; 1572 } 1573 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1574 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1575 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1576 /* FIXME */ 1577 /* 1578 * If the request returns an error then we need to do a diag 1579 * reset 1580 */ 1581 printf("%s: page read with error; iocstatus = 0x%x\n", 1582 __func__, ioc_status); 1583 error = ENXIO; 1584 goto out; 1585 } 1586 bcopy(page, config_page, MIN(cm->cm_length, 1587 sizeof(Mpi2RaidVolPage1_t))); 1588 out: 1589 free(page, M_MPR); 1590 if (cm) 1591 mpr_free_command(sc, cm); 1592 return (error); 1593 } 1594 1595 /** 1596 * mpr_config_get_volume_wwid - returns wwid given the volume handle 1597 * @sc: per adapter object 1598 * @volume_handle: volume handle 1599 * @wwid: volume wwid 1600 * Context: sleep. 1601 * 1602 * Returns 0 for success, non-zero for failure. 1603 */ 1604 int 1605 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid) 1606 { 1607 Mpi2ConfigReply_t mpi_reply; 1608 Mpi2RaidVolPage1_t raid_vol_pg1; 1609 1610 *wwid = 0; 1611 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1612 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1613 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1614 raid_vol_pg1.WWID.Low); 1615 return 0; 1616 } else 1617 return -1; 1618 } 1619 1620 /** 1621 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0 1622 * @sc: per adapter object 1623 * @mpi_reply: reply mf payload returned from firmware 1624 * @config_page: contents of the config page 1625 * @page_address: form and handle value used to get page 1626 * Context: sleep. 1627 * 1628 * Returns 0 for success, non-zero for failure. 1629 */ 1630 int 1631 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1632 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1633 { 1634 MPI2_CONFIG_REQUEST *request; 1635 MPI2_CONFIG_REPLY *reply = NULL; 1636 struct mpr_command *cm; 1637 Mpi2RaidPhysDiskPage0_t *page = NULL; 1638 int error = 0; 1639 u16 ioc_status; 1640 1641 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1642 1643 if ((cm = mpr_alloc_command(sc)) == NULL) { 1644 printf("%s: command alloc failed @ line %d\n", __func__, 1645 __LINE__); 1646 error = EBUSY; 1647 goto out; 1648 } 1649 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1650 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1651 request->Function = MPI2_FUNCTION_CONFIG; 1652 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1653 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1654 request->Header.PageNumber = 0; 1655 request->Header.PageLength = request->Header.PageVersion = 0; 1656 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1657 cm->cm_data = NULL; 1658 1659 /* 1660 * This page must be polled because the IOC isn't ready yet when this 1661 * page is needed. 1662 */ 1663 error = mpr_request_polled(sc, &cm); 1664 if (cm != NULL) 1665 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1666 if (error || (reply == NULL)) { 1667 /* FIXME */ 1668 /* If the poll returns error then we need to do diag reset */ 1669 printf("%s: poll for header completed with error %d\n", 1670 __func__, error); 1671 error = ENXIO; 1672 goto out; 1673 } 1674 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1675 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1676 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1677 /* FIXME */ 1678 /* If the poll returns error then we need to do diag reset */ 1679 printf("%s: header read with error; iocstatus = 0x%x\n", 1680 __func__, ioc_status); 1681 error = ENXIO; 1682 goto out; 1683 } 1684 /* We have to do free and alloc for the reply-free and reply-post 1685 * counters to match - Need to review the reply FIFO handling. 1686 */ 1687 mpr_free_command(sc, cm); 1688 1689 if ((cm = mpr_alloc_command(sc)) == NULL) { 1690 printf("%s: command alloc failed @ line %d\n", __func__, 1691 __LINE__); 1692 error = EBUSY; 1693 goto out; 1694 } 1695 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1696 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1697 request->Function = MPI2_FUNCTION_CONFIG; 1698 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1699 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1700 request->Header.PageNumber = 0; 1701 request->Header.PageLength = mpi_reply->Header.PageLength; 1702 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1703 request->PageAddress = page_address; 1704 cm->cm_length = mpi_reply->Header.PageLength * 4; 1705 cm->cm_sge = &request->PageBufferSGE; 1706 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1707 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1708 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1709 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1710 if (!page) { 1711 printf("%s: page alloc failed\n", __func__); 1712 error = ENOMEM; 1713 goto out; 1714 } 1715 cm->cm_data = page; 1716 1717 /* 1718 * This page must be polled because the IOC isn't ready yet when this 1719 * page is needed. 1720 */ 1721 error = mpr_request_polled(sc, &cm); 1722 if (cm != NULL) 1723 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1724 if (error || (reply == NULL)) { 1725 /* FIXME */ 1726 /* If the poll returns error then we need to do diag reset */ 1727 printf("%s: poll for page completed with error %d\n", 1728 __func__, error); 1729 error = ENXIO; 1730 goto out; 1731 } 1732 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1733 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1734 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1735 /* FIXME */ 1736 /* If the poll returns error then we need to do diag reset */ 1737 printf("%s: page read with error; iocstatus = 0x%x\n", 1738 __func__, ioc_status); 1739 error = ENXIO; 1740 goto out; 1741 } 1742 bcopy(page, config_page, MIN(cm->cm_length, 1743 sizeof(Mpi2RaidPhysDiskPage0_t))); 1744 out: 1745 free(page, M_MPR); 1746 if (cm) 1747 mpr_free_command(sc, cm); 1748 return (error); 1749 } 1750