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