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 = 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 = 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 /* We can remove below two lines ????*/ 688 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 689 request->PageAddress |= htole16(entry_idx); 690 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 691 cm->cm_data = NULL; 692 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 693 if (cm != NULL) 694 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 695 if (error || (reply == NULL)) { 696 /* FIXME */ 697 /* 698 * If the request returns an error then we need to do a diag 699 * reset 700 */ 701 printf("%s: request for header completed with error %d\n", 702 __func__, error); 703 error = ENXIO; 704 goto out; 705 } 706 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 707 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 708 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 709 /* FIXME */ 710 /* 711 * If the request returns an error then we need to do a diag 712 * reset 713 */ 714 printf("%s: header read with error; iocstatus = 0x%x\n", 715 __func__, ioc_status); 716 error = ENXIO; 717 goto out; 718 } 719 /* We have to do free and alloc for the reply-free and reply-post 720 * counters to match - Need to review the reply FIFO handling. 721 */ 722 mpr_free_command(sc, cm); 723 724 if ((cm = mpr_alloc_command(sc)) == NULL) { 725 printf("%s: command alloc failed @ line %d\n", __func__, 726 __LINE__); 727 error = EBUSY; 728 goto out; 729 } 730 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 731 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 732 request->Function = MPI2_FUNCTION_CONFIG; 733 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 734 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 735 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 736 request->Header.PageNumber = 0; 737 request->Header.PageVersion = mpi_reply->Header.PageVersion; 738 request->ExtPageLength = mpi_reply->ExtPageLength; 739 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 740 request->PageAddress |= htole16(entry_idx); 741 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 742 cm->cm_sge = &request->PageBufferSGE; 743 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 744 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT; 745 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 746 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 747 if (!page) { 748 printf("%s: page alloc failed\n", __func__); 749 error = ENOMEM; 750 goto out; 751 } 752 bcopy(config_page, page, MIN(cm->cm_length, 753 (sizeof(Mpi2DriverMappingPage0_t)))); 754 cm->cm_data = page; 755 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 756 if (cm != NULL) 757 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 758 if (error || (reply == NULL)) { 759 /* FIXME */ 760 /* 761 * If the request returns an error then we need to do a diag 762 * reset 763 */ 764 printf("%s: request to write page completed with error %d\n", 765 __func__, error); 766 error = ENXIO; 767 goto out; 768 } 769 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 770 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 771 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 772 /* FIXME */ 773 /* 774 * If the request returns an error then we need to do a diag 775 * reset 776 */ 777 printf("%s: page written with error; iocstatus = 0x%x\n", 778 __func__, ioc_status); 779 error = ENXIO; 780 goto out; 781 } 782 out: 783 free(page, M_MPR); 784 if (cm) 785 mpr_free_command(sc, cm); 786 return (error); 787 } 788 789 /** 790 * mpr_config_get_sas_device_pg0 - obtain sas device page 0 791 * @sc: per adapter object 792 * @mpi_reply: reply mf payload returned from firmware 793 * @config_page: contents of the config page 794 * @form: GET_NEXT_HANDLE or HANDLE 795 * @handle: device handle 796 * Context: sleep. 797 * 798 * Returns 0 for success, non-zero for failure. 799 */ 800 int 801 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 802 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 803 { 804 MPI2_CONFIG_REQUEST *request; 805 MPI2_CONFIG_REPLY *reply; 806 struct mpr_command *cm; 807 Mpi2SasDevicePage0_t *page = NULL; 808 int error = 0; 809 u16 ioc_status; 810 811 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 812 813 if ((cm = mpr_alloc_command(sc)) == NULL) { 814 printf("%s: command alloc failed @ line %d\n", __func__, 815 __LINE__); 816 error = EBUSY; 817 goto out; 818 } 819 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 820 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 821 request->Function = MPI2_FUNCTION_CONFIG; 822 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 823 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 824 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 825 request->Header.PageNumber = 0; 826 request->ExtPageLength = request->Header.PageVersion = 0; 827 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 828 cm->cm_data = NULL; 829 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 830 if (cm != NULL) 831 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 832 if (error || (reply == NULL)) { 833 /* FIXME */ 834 /* 835 * If the request returns an error then we need to do a diag 836 * reset 837 */ 838 printf("%s: request for header completed with error %d\n", 839 __func__, error); 840 error = ENXIO; 841 goto out; 842 } 843 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 844 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 845 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 846 /* FIXME */ 847 /* 848 * If the request returns an error then we need to do a diag 849 * reset 850 */ 851 printf("%s: header read with error; iocstatus = 0x%x\n", 852 __func__, ioc_status); 853 error = ENXIO; 854 goto out; 855 } 856 /* We have to do free and alloc for the reply-free and reply-post 857 * counters to match - Need to review the reply FIFO handling. 858 */ 859 mpr_free_command(sc, cm); 860 861 if ((cm = mpr_alloc_command(sc)) == NULL) { 862 printf("%s: command alloc failed @ line %d\n", __func__, 863 __LINE__); 864 error = EBUSY; 865 goto out; 866 } 867 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 868 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 869 request->Function = MPI2_FUNCTION_CONFIG; 870 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 871 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 872 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 873 request->Header.PageNumber = 0; 874 request->Header.PageVersion = mpi_reply->Header.PageVersion; 875 request->ExtPageLength = mpi_reply->ExtPageLength; 876 request->PageAddress = htole32(form | handle); 877 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 878 cm->cm_sge = &request->PageBufferSGE; 879 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 880 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 881 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 882 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 883 if (!page) { 884 printf("%s: page alloc failed\n", __func__); 885 error = ENOMEM; 886 goto out; 887 } 888 cm->cm_data = page; 889 890 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 891 if (cm != NULL) 892 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 893 if (error || (reply == NULL)) { 894 /* FIXME */ 895 /* 896 * If the request returns an error then we need to do a diag 897 * reset 898 */ 899 printf("%s: request for page completed with error %d\n", 900 __func__, error); 901 error = ENXIO; 902 goto out; 903 } 904 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 905 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 906 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 907 /* FIXME */ 908 /* 909 * If the request returns an error then we need to do a diag 910 * reset 911 */ 912 printf("%s: page read with error; iocstatus = 0x%x\n", 913 __func__, ioc_status); 914 error = ENXIO; 915 goto out; 916 } 917 bcopy(page, config_page, MIN(cm->cm_length, 918 sizeof(Mpi2SasDevicePage0_t))); 919 out: 920 free(page, M_MPR); 921 if (cm) 922 mpr_free_command(sc, cm); 923 return (error); 924 } 925 926 /** 927 * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0 928 * @sc: per adapter object 929 * @mpi_reply: reply mf payload returned from firmware 930 * @config_page: contents of the config page 931 * @form: GET_NEXT_HANDLE or HANDLE 932 * @handle: device handle 933 * Context: sleep. 934 * 935 * Returns 0 for success, non-zero for failure. 936 */ 937 int 938 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 939 *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle) 940 { 941 MPI2_CONFIG_REQUEST *request; 942 MPI2_CONFIG_REPLY *reply; 943 struct mpr_command *cm; 944 Mpi26PCIeDevicePage0_t *page = NULL; 945 int error = 0; 946 u16 ioc_status; 947 948 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 949 950 if ((cm = mpr_alloc_command(sc)) == NULL) { 951 printf("%s: command alloc failed @ line %d\n", __func__, 952 __LINE__); 953 error = EBUSY; 954 goto out; 955 } 956 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 957 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 958 request->Function = MPI2_FUNCTION_CONFIG; 959 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 960 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 961 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 962 request->Header.PageNumber = 0; 963 request->ExtPageLength = request->Header.PageVersion = 0; 964 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 965 cm->cm_data = NULL; 966 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 967 if (cm != NULL) 968 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 969 if (error || (reply == NULL)) { 970 /* FIXME */ 971 /* 972 * If the request returns an error then we need to do a diag 973 * reset 974 */ 975 printf("%s: request for header completed with error %d\n", 976 __func__, error); 977 error = ENXIO; 978 goto out; 979 } 980 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 981 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 982 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 983 /* FIXME */ 984 /* 985 * If the request returns an error then we need to do a diag 986 * reset 987 */ 988 printf("%s: header read with error; iocstatus = 0x%x\n", 989 __func__, ioc_status); 990 error = ENXIO; 991 goto out; 992 } 993 /* We have to do free and alloc for the reply-free and reply-post 994 * counters to match - Need to review the reply FIFO handling. 995 */ 996 mpr_free_command(sc, cm); 997 998 if ((cm = mpr_alloc_command(sc)) == NULL) { 999 printf("%s: command alloc failed @ line %d\n", __func__, 1000 __LINE__); 1001 error = EBUSY; 1002 goto out; 1003 } 1004 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1005 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1006 request->Function = MPI2_FUNCTION_CONFIG; 1007 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1008 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1009 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1010 request->Header.PageNumber = 0; 1011 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1012 request->ExtPageLength = mpi_reply->ExtPageLength; 1013 request->PageAddress = htole32(form | handle); 1014 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 1015 cm->cm_sge = &request->PageBufferSGE; 1016 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1017 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1018 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1019 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1020 if (!page) { 1021 printf("%s: page alloc failed\n", __func__); 1022 error = ENOMEM; 1023 goto out; 1024 } 1025 cm->cm_data = page; 1026 1027 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1028 if (cm != NULL) 1029 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1030 if (error || (reply == NULL)) { 1031 /* FIXME */ 1032 /* 1033 * If the request returns an error then we need to do a diag 1034 * reset 1035 */ 1036 printf("%s: request for page completed with error %d\n", 1037 __func__, error); 1038 error = ENXIO; 1039 goto out; 1040 } 1041 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1042 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1043 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1044 /* FIXME */ 1045 /* 1046 * If the request returns an error then we need to do a diag 1047 * reset 1048 */ 1049 printf("%s: page read with error; iocstatus = 0x%x\n", 1050 __func__, ioc_status); 1051 error = ENXIO; 1052 goto out; 1053 } 1054 bcopy(page, config_page, MIN(cm->cm_length, 1055 sizeof(Mpi26PCIeDevicePage0_t))); 1056 out: 1057 free(page, M_MPR); 1058 if (cm) 1059 mpr_free_command(sc, cm); 1060 return (error); 1061 } 1062 1063 /** 1064 * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2 1065 * @sc: per adapter object 1066 * @mpi_reply: reply mf payload returned from firmware 1067 * @config_page: contents of the config page 1068 * @form: GET_NEXT_HANDLE or HANDLE 1069 * @handle: device handle 1070 * Context: sleep. 1071 * 1072 * Returns 0 for success, non-zero for failure. 1073 */ 1074 int 1075 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t 1076 *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle) 1077 { 1078 MPI2_CONFIG_REQUEST *request; 1079 MPI2_CONFIG_REPLY *reply; 1080 struct mpr_command *cm; 1081 Mpi26PCIeDevicePage2_t *page = NULL; 1082 int error = 0; 1083 u16 ioc_status; 1084 1085 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1086 1087 if ((cm = mpr_alloc_command(sc)) == NULL) { 1088 printf("%s: command alloc failed @ line %d\n", __func__, 1089 __LINE__); 1090 error = EBUSY; 1091 goto out; 1092 } 1093 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1094 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1095 request->Function = MPI2_FUNCTION_CONFIG; 1096 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1097 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1098 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1099 request->Header.PageNumber = 2; 1100 request->ExtPageLength = request->Header.PageVersion = 0; 1101 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1102 cm->cm_data = NULL; 1103 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1104 if (cm != NULL) 1105 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1106 if (error || (reply == NULL)) { 1107 /* FIXME */ 1108 /* 1109 * If the request returns an error then we need to do a diag 1110 * reset 1111 */ 1112 printf("%s: request for header completed with error %d\n", 1113 __func__, error); 1114 error = ENXIO; 1115 goto out; 1116 } 1117 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1118 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1119 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1120 /* FIXME */ 1121 /* 1122 * If the request returns an error then we need to do a diag 1123 * reset 1124 */ 1125 printf("%s: header read with error; iocstatus = 0x%x\n", 1126 __func__, ioc_status); 1127 error = ENXIO; 1128 goto out; 1129 } 1130 /* We have to do free and alloc for the reply-free and reply-post 1131 * counters to match - Need to review the reply FIFO handling. 1132 */ 1133 mpr_free_command(sc, cm); 1134 1135 if ((cm = mpr_alloc_command(sc)) == NULL) { 1136 printf("%s: command alloc failed @ line %d\n", __func__, 1137 __LINE__); 1138 error = EBUSY; 1139 goto out; 1140 } 1141 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1142 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1143 request->Function = MPI2_FUNCTION_CONFIG; 1144 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1145 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 1146 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; 1147 request->Header.PageNumber = 2; 1148 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1149 request->ExtPageLength = mpi_reply->ExtPageLength; 1150 request->PageAddress = htole32(form | handle); 1151 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 1152 cm->cm_sge = &request->PageBufferSGE; 1153 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1154 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1155 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1156 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1157 if (!page) { 1158 printf("%s: page alloc failed\n", __func__); 1159 error = ENOMEM; 1160 goto out; 1161 } 1162 cm->cm_data = page; 1163 1164 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1165 if (cm != NULL) 1166 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1167 if (error || (reply == NULL)) { 1168 /* FIXME */ 1169 /* 1170 * If the request returns an error then we need to do a diag 1171 * reset 1172 */ 1173 printf("%s: request for page completed with error %d\n", 1174 __func__, error); 1175 error = ENXIO; 1176 goto out; 1177 } 1178 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1179 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1180 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1181 /* FIXME */ 1182 /* 1183 * If the request returns an error then we need to do a diag 1184 * reset 1185 */ 1186 printf("%s: page read with error; iocstatus = 0x%x\n", 1187 __func__, ioc_status); 1188 error = ENXIO; 1189 goto out; 1190 } 1191 bcopy(page, config_page, MIN(cm->cm_length, 1192 sizeof(Mpi26PCIeDevicePage2_t))); 1193 out: 1194 free(page, M_MPR); 1195 if (cm) 1196 mpr_free_command(sc, cm); 1197 return (error); 1198 } 1199 1200 /** 1201 * mpr_config_get_bios_pg3 - obtain BIOS page 3 1202 * @sc: per adapter object 1203 * @mpi_reply: reply mf payload returned from firmware 1204 * @config_page: contents of the config page 1205 * Context: sleep. 1206 * 1207 * Returns 0 for success, non-zero for failure. 1208 */ 1209 int 1210 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1211 Mpi2BiosPage3_t *config_page) 1212 { 1213 MPI2_CONFIG_REQUEST *request; 1214 MPI2_CONFIG_REPLY *reply; 1215 struct mpr_command *cm; 1216 Mpi2BiosPage3_t *page = NULL; 1217 int error = 0; 1218 u16 ioc_status; 1219 1220 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1221 1222 if ((cm = mpr_alloc_command(sc)) == NULL) { 1223 printf("%s: command alloc failed @ line %d\n", __func__, 1224 __LINE__); 1225 error = EBUSY; 1226 goto out; 1227 } 1228 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1229 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1230 request->Function = MPI2_FUNCTION_CONFIG; 1231 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1232 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1233 request->Header.PageNumber = 3; 1234 request->Header.PageLength = request->Header.PageVersion = 0; 1235 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1236 cm->cm_data = NULL; 1237 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1238 if (cm != NULL) 1239 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1240 if (error || (reply == NULL)) { 1241 /* FIXME */ 1242 /* 1243 * If the request returns an error then we need to do a diag 1244 * reset 1245 */ 1246 printf("%s: request for header completed with error %d\n", 1247 __func__, error); 1248 error = ENXIO; 1249 goto out; 1250 } 1251 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1252 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1253 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1254 /* FIXME */ 1255 /* 1256 * If the request returns an error then we need to do a diag 1257 * reset 1258 */ 1259 printf("%s: header read with error; iocstatus = 0x%x\n", 1260 __func__, ioc_status); 1261 error = ENXIO; 1262 goto out; 1263 } 1264 /* We have to do free and alloc for the reply-free and reply-post 1265 * counters to match - Need to review the reply FIFO handling. 1266 */ 1267 mpr_free_command(sc, cm); 1268 1269 if ((cm = mpr_alloc_command(sc)) == NULL) { 1270 printf("%s: command alloc failed @ line %d\n", __func__, 1271 __LINE__); 1272 error = EBUSY; 1273 goto out; 1274 } 1275 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1276 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1277 request->Function = MPI2_FUNCTION_CONFIG; 1278 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1279 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1280 request->Header.PageNumber = 3; 1281 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1282 request->Header.PageLength = mpi_reply->Header.PageLength; 1283 cm->cm_length = mpi_reply->Header.PageLength * 4; 1284 cm->cm_sge = &request->PageBufferSGE; 1285 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1286 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1287 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1288 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1289 if (!page) { 1290 printf("%s: page alloc failed\n", __func__); 1291 error = ENOMEM; 1292 goto out; 1293 } 1294 cm->cm_data = page; 1295 1296 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1297 if (cm != NULL) 1298 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1299 if (error || (reply == NULL)) { 1300 /* FIXME */ 1301 /* 1302 * If the request returns an error then we need to do a diag 1303 * reset 1304 */ 1305 printf("%s: request for page completed with error %d\n", 1306 __func__, error); 1307 error = ENXIO; 1308 goto out; 1309 } 1310 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1311 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1312 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1313 /* FIXME */ 1314 /* 1315 * If the request returns an error then we need to do a diag 1316 * reset 1317 */ 1318 printf("%s: page read with error; iocstatus = 0x%x\n", 1319 __func__, ioc_status); 1320 error = ENXIO; 1321 goto out; 1322 } 1323 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1324 out: 1325 free(page, M_MPR); 1326 if (cm) 1327 mpr_free_command(sc, cm); 1328 return (error); 1329 } 1330 1331 /** 1332 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0 1333 * @sc: per adapter object 1334 * @mpi_reply: reply mf payload returned from firmware 1335 * @config_page: contents of the config page 1336 * @page_address: form and handle value used to get page 1337 * Context: sleep. 1338 * 1339 * Returns 0 for success, non-zero for failure. 1340 */ 1341 int 1342 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 1343 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1344 { 1345 MPI2_CONFIG_REQUEST *request; 1346 MPI2_CONFIG_REPLY *reply = NULL; 1347 struct mpr_command *cm; 1348 Mpi2RaidVolPage0_t *page = NULL; 1349 int error = 0; 1350 u16 ioc_status; 1351 1352 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1353 1354 if ((cm = mpr_alloc_command(sc)) == NULL) { 1355 printf("%s: command alloc failed @ line %d\n", __func__, 1356 __LINE__); 1357 error = EBUSY; 1358 goto out; 1359 } 1360 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1361 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1362 request->Function = MPI2_FUNCTION_CONFIG; 1363 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1364 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1365 request->Header.PageNumber = 0; 1366 request->Header.PageLength = request->Header.PageVersion = 0; 1367 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1368 cm->cm_data = NULL; 1369 1370 /* 1371 * This page must be polled because the IOC isn't ready yet when this 1372 * page is needed. 1373 */ 1374 error = mpr_request_polled(sc, &cm); 1375 if (cm != NULL) 1376 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1377 if (error || (reply == NULL)) { 1378 /* FIXME */ 1379 /* If the poll returns error then we need to do diag reset */ 1380 printf("%s: poll for header completed with error %d\n", 1381 __func__, error); 1382 error = ENXIO; 1383 goto out; 1384 } 1385 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1386 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1387 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1388 /* FIXME */ 1389 /* If the poll returns error then we need to do diag reset */ 1390 printf("%s: header read with error; iocstatus = 0x%x\n", 1391 __func__, ioc_status); 1392 error = ENXIO; 1393 goto out; 1394 } 1395 /* We have to do free and alloc for the reply-free and reply-post 1396 * counters to match - Need to review the reply FIFO handling. 1397 */ 1398 mpr_free_command(sc, cm); 1399 1400 if ((cm = mpr_alloc_command(sc)) == NULL) { 1401 printf("%s: command alloc failed @ line %d\n", __func__, 1402 __LINE__); 1403 error = EBUSY; 1404 goto out; 1405 } 1406 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1407 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1408 request->Function = MPI2_FUNCTION_CONFIG; 1409 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1410 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1411 request->Header.PageNumber = 0; 1412 request->Header.PageLength = mpi_reply->Header.PageLength; 1413 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1414 request->PageAddress = page_address; 1415 cm->cm_length = mpi_reply->Header.PageLength * 4; 1416 cm->cm_sge = &request->PageBufferSGE; 1417 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1418 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1419 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1420 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1421 if (!page) { 1422 printf("%s: page alloc failed\n", __func__); 1423 error = ENOMEM; 1424 goto out; 1425 } 1426 cm->cm_data = page; 1427 1428 /* 1429 * This page must be polled because the IOC isn't ready yet when this 1430 * page is needed. 1431 */ 1432 error = mpr_request_polled(sc, &cm); 1433 if (cm != NULL) 1434 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1435 if (error || (reply == NULL)) { 1436 /* FIXME */ 1437 /* If the poll returns error then we need to do diag reset */ 1438 printf("%s: poll for page completed with error %d\n", 1439 __func__, error); 1440 error = ENXIO; 1441 goto out; 1442 } 1443 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1444 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1445 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1446 /* FIXME */ 1447 /* If the poll returns error then we need to do diag reset */ 1448 printf("%s: page read with error; iocstatus = 0x%x\n", 1449 __func__, ioc_status); 1450 error = ENXIO; 1451 goto out; 1452 } 1453 bcopy(page, config_page, cm->cm_length); 1454 out: 1455 free(page, M_MPR); 1456 if (cm) 1457 mpr_free_command(sc, cm); 1458 return (error); 1459 } 1460 1461 /** 1462 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1 1463 * @sc: per adapter object 1464 * @mpi_reply: reply mf payload returned from firmware 1465 * @config_page: contents of the config page 1466 * @form: GET_NEXT_HANDLE or HANDLE 1467 * @handle: volume handle 1468 * Context: sleep. 1469 * 1470 * Returns 0 for success, non-zero for failure. 1471 */ 1472 int 1473 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t 1474 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1475 { 1476 MPI2_CONFIG_REQUEST *request; 1477 MPI2_CONFIG_REPLY *reply; 1478 struct mpr_command *cm; 1479 Mpi2RaidVolPage1_t *page = NULL; 1480 int error = 0; 1481 u16 ioc_status; 1482 1483 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1484 1485 if ((cm = mpr_alloc_command(sc)) == NULL) { 1486 printf("%s: command alloc failed @ line %d\n", __func__, 1487 __LINE__); 1488 error = EBUSY; 1489 goto out; 1490 } 1491 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1492 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1493 request->Function = MPI2_FUNCTION_CONFIG; 1494 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1495 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1496 request->Header.PageNumber = 1; 1497 request->Header.PageLength = request->Header.PageVersion = 0; 1498 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1499 cm->cm_data = NULL; 1500 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1501 if (cm != NULL) 1502 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1503 if (error || (reply == NULL)) { 1504 /* FIXME */ 1505 /* 1506 * If the request returns an error then we need to do a diag 1507 * reset 1508 */ 1509 printf("%s: request for header completed with error %d\n", 1510 __func__, error); 1511 error = ENXIO; 1512 goto out; 1513 } 1514 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1515 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1516 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1517 /* FIXME */ 1518 /* 1519 * If the request returns an error then we need to do a diag 1520 * reset 1521 */ 1522 printf("%s: header read with error; iocstatus = 0x%x\n", 1523 __func__, ioc_status); 1524 error = ENXIO; 1525 goto out; 1526 } 1527 /* We have to do free and alloc for the reply-free and reply-post 1528 * counters to match - Need to review the reply FIFO handling. 1529 */ 1530 mpr_free_command(sc, cm); 1531 1532 if ((cm = mpr_alloc_command(sc)) == NULL) { 1533 printf("%s: command alloc failed @ line %d\n", __func__, 1534 __LINE__); 1535 error = EBUSY; 1536 goto out; 1537 } 1538 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1539 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1540 request->Function = MPI2_FUNCTION_CONFIG; 1541 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1542 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1543 request->Header.PageNumber = 1; 1544 request->Header.PageLength = mpi_reply->Header.PageLength; 1545 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1546 request->PageAddress = htole32(form | handle); 1547 cm->cm_length = mpi_reply->Header.PageLength * 4; 1548 cm->cm_sge = &request->PageBufferSGE; 1549 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1550 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1551 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1552 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1553 if (!page) { 1554 printf("%s: page alloc failed\n", __func__); 1555 error = ENOMEM; 1556 goto out; 1557 } 1558 cm->cm_data = page; 1559 1560 error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1561 if (cm != NULL) 1562 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1563 if (error || (reply == NULL)) { 1564 /* FIXME */ 1565 /* 1566 * If the request returns an error then we need to do a diag 1567 * reset 1568 */ 1569 printf("%s: request for page completed with error %d\n", 1570 __func__, error); 1571 error = ENXIO; 1572 goto out; 1573 } 1574 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1575 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1576 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1577 /* FIXME */ 1578 /* 1579 * If the request returns an error then we need to do a diag 1580 * reset 1581 */ 1582 printf("%s: page read with error; iocstatus = 0x%x\n", 1583 __func__, ioc_status); 1584 error = ENXIO; 1585 goto out; 1586 } 1587 bcopy(page, config_page, MIN(cm->cm_length, 1588 sizeof(Mpi2RaidVolPage1_t))); 1589 out: 1590 free(page, M_MPR); 1591 if (cm) 1592 mpr_free_command(sc, cm); 1593 return (error); 1594 } 1595 1596 /** 1597 * mpr_config_get_volume_wwid - returns wwid given the volume handle 1598 * @sc: per adapter object 1599 * @volume_handle: volume handle 1600 * @wwid: volume wwid 1601 * Context: sleep. 1602 * 1603 * Returns 0 for success, non-zero for failure. 1604 */ 1605 int 1606 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid) 1607 { 1608 Mpi2ConfigReply_t mpi_reply; 1609 Mpi2RaidVolPage1_t raid_vol_pg1; 1610 1611 *wwid = 0; 1612 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1613 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1614 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1615 raid_vol_pg1.WWID.Low); 1616 return 0; 1617 } else 1618 return -1; 1619 } 1620 1621 /** 1622 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0 1623 * @sc: per adapter object 1624 * @mpi_reply: reply mf payload returned from firmware 1625 * @config_page: contents of the config page 1626 * @page_address: form and handle value used to get page 1627 * Context: sleep. 1628 * 1629 * Returns 0 for success, non-zero for failure. 1630 */ 1631 int 1632 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1633 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1634 { 1635 MPI2_CONFIG_REQUEST *request; 1636 MPI2_CONFIG_REPLY *reply = NULL; 1637 struct mpr_command *cm; 1638 Mpi2RaidPhysDiskPage0_t *page = NULL; 1639 int error = 0; 1640 u16 ioc_status; 1641 1642 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1643 1644 if ((cm = mpr_alloc_command(sc)) == NULL) { 1645 printf("%s: command alloc failed @ line %d\n", __func__, 1646 __LINE__); 1647 error = EBUSY; 1648 goto out; 1649 } 1650 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1651 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1652 request->Function = MPI2_FUNCTION_CONFIG; 1653 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1654 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1655 request->Header.PageNumber = 0; 1656 request->Header.PageLength = request->Header.PageVersion = 0; 1657 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1658 cm->cm_data = NULL; 1659 1660 /* 1661 * This page must be polled because the IOC isn't ready yet when this 1662 * page is needed. 1663 */ 1664 error = mpr_request_polled(sc, &cm); 1665 if (cm != NULL) 1666 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1667 if (error || (reply == NULL)) { 1668 /* FIXME */ 1669 /* If the poll returns error then we need to do diag reset */ 1670 printf("%s: poll for header completed with error %d\n", 1671 __func__, error); 1672 error = ENXIO; 1673 goto out; 1674 } 1675 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1676 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1677 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1678 /* FIXME */ 1679 /* If the poll returns error then we need to do diag reset */ 1680 printf("%s: header read with error; iocstatus = 0x%x\n", 1681 __func__, ioc_status); 1682 error = ENXIO; 1683 goto out; 1684 } 1685 /* We have to do free and alloc for the reply-free and reply-post 1686 * counters to match - Need to review the reply FIFO handling. 1687 */ 1688 mpr_free_command(sc, cm); 1689 1690 if ((cm = mpr_alloc_command(sc)) == NULL) { 1691 printf("%s: command alloc failed @ line %d\n", __func__, 1692 __LINE__); 1693 error = EBUSY; 1694 goto out; 1695 } 1696 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1697 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1698 request->Function = MPI2_FUNCTION_CONFIG; 1699 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1700 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1701 request->Header.PageNumber = 0; 1702 request->Header.PageLength = mpi_reply->Header.PageLength; 1703 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1704 request->PageAddress = page_address; 1705 cm->cm_length = mpi_reply->Header.PageLength * 4; 1706 cm->cm_sge = &request->PageBufferSGE; 1707 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1708 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1709 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1710 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1711 if (!page) { 1712 printf("%s: page alloc failed\n", __func__); 1713 error = ENOMEM; 1714 goto out; 1715 } 1716 cm->cm_data = page; 1717 1718 /* 1719 * This page must be polled because the IOC isn't ready yet when this 1720 * page is needed. 1721 */ 1722 error = mpr_request_polled(sc, &cm); 1723 if (cm != NULL) 1724 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1725 if (error || (reply == NULL)) { 1726 /* FIXME */ 1727 /* If the poll returns error then we need to do diag reset */ 1728 printf("%s: poll for page completed with error %d\n", 1729 __func__, error); 1730 error = ENXIO; 1731 goto out; 1732 } 1733 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1734 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1735 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1736 /* FIXME */ 1737 /* If the poll returns error then we need to do diag reset */ 1738 printf("%s: page read with error; iocstatus = 0x%x\n", 1739 __func__, ioc_status); 1740 error = ENXIO; 1741 goto out; 1742 } 1743 bcopy(page, config_page, MIN(cm->cm_length, 1744 sizeof(Mpi2RaidPhysDiskPage0_t))); 1745 out: 1746 free(page, M_MPR); 1747 if (cm) 1748 mpr_free_command(sc, cm); 1749 return (error); 1750 } 1751