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