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