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_cnfg.h> 55 #include <dev/mpr/mpi/mpi2_init.h> 56 #include <dev/mpr/mpi/mpi2_tool.h> 57 #include <dev/mpr/mpr_ioctl.h> 58 #include <dev/mpr/mprvar.h> 59 60 /** 61 * mpr_config_get_ioc_pg8 - obtain ioc page 8 62 * @sc: per adapter object 63 * @mpi_reply: reply mf payload returned from firmware 64 * @config_page: contents of the config page 65 * Context: sleep. 66 * 67 * Returns 0 for success, non-zero for failure. 68 */ 69 int 70 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 71 Mpi2IOCPage8_t *config_page) 72 { 73 MPI2_CONFIG_REQUEST *request; 74 MPI2_CONFIG_REPLY *reply; 75 struct mpr_command *cm; 76 MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 77 int error = 0; 78 u16 ioc_status; 79 80 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 81 82 if ((cm = mpr_alloc_command(sc)) == NULL) { 83 printf("%s: command alloc failed @ line %d\n", __func__, 84 __LINE__); 85 error = EBUSY; 86 goto out; 87 } 88 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 89 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 90 request->Function = MPI2_FUNCTION_CONFIG; 91 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 92 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 93 request->Header.PageNumber = 8; 94 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 95 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 96 cm->cm_data = NULL; 97 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 98 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", 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 = MPI2_IOCPAGE8_PAGEVERSION; 141 request->Header.PageLength = mpi_reply->Header.PageLength; 142 cm->cm_length = le16toh(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 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 157 if (error || (reply == NULL)) { 158 /* FIXME */ 159 /* 160 * If the request returns an error then we need to do a diag 161 * reset 162 */ 163 printf("%s: request for page completed with error %d", 164 __func__, error); 165 error = ENXIO; 166 goto out; 167 } 168 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 169 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 170 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 171 /* FIXME */ 172 /* 173 * If the request returns an error then we need to do a diag 174 * reset 175 */ 176 printf("%s: page read with error; iocstatus = 0x%x\n", 177 __func__, ioc_status); 178 error = ENXIO; 179 goto out; 180 } 181 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 182 183 out: 184 free(page, M_MPR); 185 if (cm) 186 mpr_free_command(sc, cm); 187 return (error); 188 } 189 190 /** 191 * mpr_config_get_iounit_pg8 - obtain iounit page 8 192 * @sc: per adapter object 193 * @mpi_reply: reply mf payload returned from firmware 194 * @config_page: contents of the config page 195 * Context: sleep. 196 * 197 * Returns 0 for success, non-zero for failure. 198 */ 199 int 200 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 201 Mpi2IOUnitPage8_t *config_page) 202 { 203 MPI2_CONFIG_REQUEST *request; 204 MPI2_CONFIG_REPLY *reply; 205 struct mpr_command *cm; 206 MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL; 207 int error = 0; 208 u16 ioc_status; 209 210 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 211 212 if ((cm = mpr_alloc_command(sc)) == NULL) { 213 printf("%s: command alloc failed @ line %d\n", __func__, 214 __LINE__); 215 error = EBUSY; 216 goto out; 217 } 218 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 219 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 220 request->Function = MPI2_FUNCTION_CONFIG; 221 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 222 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 223 request->Header.PageNumber = 8; 224 request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; 225 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 226 cm->cm_data = NULL; 227 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 228 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 229 if (error || (reply == NULL)) { 230 /* FIXME */ 231 /* 232 * If the request returns an error then we need to do a diag 233 * reset 234 */ 235 printf("%s: request for header completed with error %d", 236 __func__, error); 237 error = ENXIO; 238 goto out; 239 } 240 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 241 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 242 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 243 /* FIXME */ 244 /* 245 * If the request returns an error then we need to do a diag 246 * reset 247 */ 248 printf("%s: header read with error; iocstatus = 0x%x\n", 249 __func__, ioc_status); 250 error = ENXIO; 251 goto out; 252 } 253 /* We have to do free and alloc for the reply-free and reply-post 254 * counters to match - Need to review the reply FIFO handling. 255 */ 256 mpr_free_command(sc, cm); 257 258 if ((cm = mpr_alloc_command(sc)) == NULL) { 259 printf("%s: command alloc failed @ line %d\n", __func__, 260 __LINE__); 261 error = EBUSY; 262 goto out; 263 } 264 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 265 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 266 request->Function = MPI2_FUNCTION_CONFIG; 267 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 268 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; 269 request->Header.PageNumber = 8; 270 request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; 271 request->Header.PageLength = mpi_reply->Header.PageLength; 272 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 273 cm->cm_sge = &request->PageBufferSGE; 274 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 275 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 276 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 277 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT); 278 if (!page) { 279 printf("%s: page alloc failed\n", __func__); 280 error = ENOMEM; 281 goto out; 282 } 283 cm->cm_data = page; 284 285 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 286 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 287 if (error || (reply == NULL)) { 288 /* FIXME */ 289 /* 290 * If the request returns an error then we need to do a diag 291 * reset 292 */ 293 printf("%s: request for page completed with error %d", 294 __func__, error); 295 error = ENXIO; 296 goto out; 297 } 298 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 299 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 300 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 301 /* FIXME */ 302 /* 303 * If the request returns an error then we need to do a diag 304 * reset 305 */ 306 printf("%s: page read with error; iocstatus = 0x%x\n", 307 __func__, ioc_status); 308 error = ENXIO; 309 goto out; 310 } 311 bcopy(page, config_page, MIN(cm->cm_length, 312 (sizeof(Mpi2IOUnitPage8_t)))); 313 314 out: 315 free(page, M_MPR); 316 if (cm) 317 mpr_free_command(sc, cm); 318 return (error); 319 } 320 321 /** 322 * mpr_base_static_config_pages - static start of day config pages. 323 * @sc: per adapter object 324 * 325 * Return nothing. 326 */ 327 void 328 mpr_base_static_config_pages(struct mpr_softc *sc) 329 { 330 Mpi2ConfigReply_t mpi_reply; 331 int retry; 332 333 retry = 0; 334 while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 335 retry++; 336 if (retry > 5) { 337 /* We need to Handle this situation */ 338 /*FIXME*/ 339 break; 340 } 341 } 342 retry = 0; 343 while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) { 344 retry++; 345 if (retry > 5) { 346 /* We need to Handle this situation */ 347 /*FIXME*/ 348 break; 349 } 350 } 351 } 352 353 /** 354 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0 355 * @sc: per adapter object 356 * @mpi_reply: reply mf payload returned from firmware 357 * @config_page: contents of the config page 358 * @sz: size of buffer passed in config_page 359 * Context: sleep. 360 * 361 * Returns 0 for success, non-zero for failure. 362 */ 363 int 364 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 365 Mpi2DriverMappingPage0_t *config_page, u16 sz) 366 { 367 MPI2_CONFIG_REQUEST *request; 368 MPI2_CONFIG_REPLY *reply; 369 struct mpr_command *cm; 370 Mpi2DriverMappingPage0_t *page = NULL; 371 int error = 0; 372 u16 ioc_status; 373 374 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 375 376 memset(config_page, 0, sz); 377 if ((cm = mpr_alloc_command(sc)) == NULL) { 378 printf("%s: command alloc failed @ line %d\n", __func__, 379 __LINE__); 380 error = EBUSY; 381 goto out; 382 } 383 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 384 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 385 request->Function = MPI2_FUNCTION_CONFIG; 386 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 387 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 388 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 389 request->Header.PageNumber = 0; 390 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 391 request->PageAddress = sc->max_dpm_entries << 392 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 393 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 394 cm->cm_data = NULL; 395 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 396 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 397 if (error || (reply == NULL)) { 398 /* FIXME */ 399 /* 400 * If the request returns an error then we need to do a diag 401 * reset 402 */ 403 printf("%s: request for header completed with error %d", 404 __func__, error); 405 error = ENXIO; 406 goto out; 407 } 408 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 409 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 410 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 411 /* FIXME */ 412 /* 413 * If the request returns an error then we need to do a diag 414 * reset 415 */ 416 printf("%s: header read with error; iocstatus = 0x%x\n", 417 __func__, ioc_status); 418 error = ENXIO; 419 goto out; 420 } 421 /* We have to do free and alloc for the reply-free and reply-post 422 * counters to match - Need to review the reply FIFO handling. 423 */ 424 mpr_free_command(sc, cm); 425 426 if ((cm = mpr_alloc_command(sc)) == NULL) { 427 printf("%s: command alloc failed @ line %d\n", __func__, 428 __LINE__); 429 error = EBUSY; 430 goto out; 431 } 432 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 433 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 434 request->Function = MPI2_FUNCTION_CONFIG; 435 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 436 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 437 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 438 request->Header.PageNumber = 0; 439 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 440 request->PageAddress = sc->max_dpm_entries << 441 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 442 request->ExtPageLength = mpi_reply->ExtPageLength; 443 cm->cm_length = le16toh(request->ExtPageLength) * 4; 444 cm->cm_sge = &request->PageBufferSGE; 445 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 446 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 447 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 448 page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT); 449 if (!page) { 450 printf("%s: page alloc failed\n", __func__); 451 error = ENOMEM; 452 goto out; 453 } 454 cm->cm_data = page; 455 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 456 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 457 if (error || (reply == NULL)) { 458 /* FIXME */ 459 /* 460 * If the request returns an error then we need to do a diag 461 * reset 462 */ 463 printf("%s: request for page completed with error %d", 464 __func__, error); 465 error = ENXIO; 466 goto out; 467 } 468 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 469 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 470 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 471 /* FIXME */ 472 /* 473 * If the request returns an error then we need to do a diag 474 * reset 475 */ 476 printf("%s: page read with error; iocstatus = 0x%x\n", 477 __func__, ioc_status); 478 error = ENXIO; 479 goto out; 480 } 481 bcopy(page, config_page, MIN(cm->cm_length, sz)); 482 out: 483 free(page, M_MPR); 484 if (cm) 485 mpr_free_command(sc, cm); 486 return (error); 487 } 488 489 /** 490 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 491 * @sc: per adapter object 492 * @mpi_reply: reply mf payload returned from firmware 493 * @config_page: contents of the config page 494 * @entry_idx: entry index in DPM Page0 to be modified 495 * Context: sleep. 496 * 497 * Returns 0 for success, non-zero for failure. 498 */ 499 500 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 501 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 502 { 503 MPI2_CONFIG_REQUEST *request; 504 MPI2_CONFIG_REPLY *reply; 505 struct mpr_command *cm; 506 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 507 int error = 0; 508 u16 ioc_status; 509 510 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 511 512 if ((cm = mpr_alloc_command(sc)) == NULL) { 513 printf("%s: command alloc failed @ line %d\n", __func__, 514 __LINE__); 515 error = EBUSY; 516 goto out; 517 } 518 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 519 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 520 request->Function = MPI2_FUNCTION_CONFIG; 521 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 522 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 523 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 524 request->Header.PageNumber = 0; 525 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 526 /* We can remove below two lines ????*/ 527 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 528 request->PageAddress |= htole16(entry_idx); 529 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 530 cm->cm_data = NULL; 531 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 532 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 533 if (error || (reply == NULL)) { 534 /* FIXME */ 535 /* 536 * If the request returns an error then we need to do a diag 537 * reset 538 */ 539 printf("%s: request for header completed with error %d", 540 __func__, error); 541 error = ENXIO; 542 goto out; 543 } 544 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 545 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 546 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 547 /* FIXME */ 548 /* 549 * If the request returns an error then we need to do a diag 550 * reset 551 */ 552 printf("%s: header read with error; iocstatus = 0x%x\n", 553 __func__, ioc_status); 554 error = ENXIO; 555 goto out; 556 } 557 /* We have to do free and alloc for the reply-free and reply-post 558 * counters to match - Need to review the reply FIFO handling. 559 */ 560 mpr_free_command(sc, cm); 561 562 if ((cm = mpr_alloc_command(sc)) == NULL) { 563 printf("%s: command alloc failed @ line %d\n", __func__, 564 __LINE__); 565 error = EBUSY; 566 goto out; 567 } 568 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 569 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 570 request->Function = MPI2_FUNCTION_CONFIG; 571 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 572 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 573 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 574 request->Header.PageNumber = 0; 575 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 576 request->ExtPageLength = mpi_reply->ExtPageLength; 577 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 578 request->PageAddress |= htole16(entry_idx); 579 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 580 cm->cm_sge = &request->PageBufferSGE; 581 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 582 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT; 583 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 584 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 585 if (!page) { 586 printf("%s: page alloc failed\n", __func__); 587 error = ENOMEM; 588 goto out; 589 } 590 bcopy(config_page, page, MIN(cm->cm_length, 591 (sizeof(Mpi2DriverMappingPage0_t)))); 592 cm->cm_data = page; 593 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 594 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 595 if (error || (reply == NULL)) { 596 /* FIXME */ 597 /* 598 * If the request returns an error then we need to do a diag 599 * reset 600 */ 601 printf("%s: request to write page completed with error %d", 602 __func__, error); 603 error = ENXIO; 604 goto out; 605 } 606 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 607 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 608 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 609 /* FIXME */ 610 /* 611 * If the request returns an error then we need to do a diag 612 * reset 613 */ 614 printf("%s: page written with error; iocstatus = 0x%x\n", 615 __func__, ioc_status); 616 error = ENXIO; 617 goto out; 618 } 619 out: 620 free(page, M_MPR); 621 if (cm) 622 mpr_free_command(sc, cm); 623 return (error); 624 } 625 626 /** 627 * mpr_config_get_sas_device_pg0 - obtain sas device page 0 628 * @sc: per adapter object 629 * @mpi_reply: reply mf payload returned from firmware 630 * @config_page: contents of the config page 631 * @form: GET_NEXT_HANDLE or HANDLE 632 * @handle: device handle 633 * Context: sleep. 634 * 635 * Returns 0 for success, non-zero for failure. 636 */ 637 int 638 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 639 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 640 { 641 MPI2_CONFIG_REQUEST *request; 642 MPI2_CONFIG_REPLY *reply; 643 struct mpr_command *cm; 644 Mpi2SasDevicePage0_t *page = NULL; 645 int error = 0; 646 u16 ioc_status; 647 648 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 649 650 if ((cm = mpr_alloc_command(sc)) == NULL) { 651 printf("%s: command alloc failed @ line %d\n", __func__, 652 __LINE__); 653 error = EBUSY; 654 goto out; 655 } 656 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 657 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 658 request->Function = MPI2_FUNCTION_CONFIG; 659 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 660 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 661 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 662 request->Header.PageNumber = 0; 663 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 664 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 665 cm->cm_data = NULL; 666 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 667 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 668 if (error || (reply == NULL)) { 669 /* FIXME */ 670 /* 671 * If the request returns an error then we need to do a diag 672 * reset 673 */ 674 printf("%s: request for header completed with error %d", 675 __func__, error); 676 error = ENXIO; 677 goto out; 678 } 679 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 680 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 681 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 682 /* FIXME */ 683 /* 684 * If the request returns an error then we need to do a diag 685 * reset 686 */ 687 printf("%s: header read with error; iocstatus = 0x%x\n", 688 __func__, ioc_status); 689 error = ENXIO; 690 goto out; 691 } 692 /* We have to do free and alloc for the reply-free and reply-post 693 * counters to match - Need to review the reply FIFO handling. 694 */ 695 mpr_free_command(sc, cm); 696 697 if ((cm = mpr_alloc_command(sc)) == NULL) { 698 printf("%s: command alloc failed @ line %d\n", __func__, 699 __LINE__); 700 error = EBUSY; 701 goto out; 702 } 703 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 704 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 705 request->Function = MPI2_FUNCTION_CONFIG; 706 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 707 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 708 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 709 request->Header.PageNumber = 0; 710 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 711 request->ExtPageLength = mpi_reply->ExtPageLength; 712 request->PageAddress = htole32(form | handle); 713 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 714 cm->cm_sge = &request->PageBufferSGE; 715 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 716 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 717 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 718 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 719 if (!page) { 720 printf("%s: page alloc failed\n", __func__); 721 error = ENOMEM; 722 goto out; 723 } 724 cm->cm_data = page; 725 726 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 727 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 728 if (error || (reply == NULL)) { 729 /* FIXME */ 730 /* 731 * If the request returns an error then we need to do a diag 732 * reset 733 */ 734 printf("%s: request for page completed with error %d", 735 __func__, error); 736 error = ENXIO; 737 goto out; 738 } 739 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 740 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 741 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 742 /* FIXME */ 743 /* 744 * If the request returns an error then we need to do a diag 745 * reset 746 */ 747 printf("%s: page read with error; iocstatus = 0x%x\n", 748 __func__, ioc_status); 749 error = ENXIO; 750 goto out; 751 } 752 bcopy(page, config_page, MIN(cm->cm_length, 753 sizeof(Mpi2SasDevicePage0_t))); 754 out: 755 free(page, M_MPR); 756 if (cm) 757 mpr_free_command(sc, cm); 758 return (error); 759 } 760 761 /** 762 * mpr_config_get_bios_pg3 - obtain BIOS page 3 763 * @sc: per adapter object 764 * @mpi_reply: reply mf payload returned from firmware 765 * @config_page: contents of the config page 766 * Context: sleep. 767 * 768 * Returns 0 for success, non-zero for failure. 769 */ 770 int 771 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 772 Mpi2BiosPage3_t *config_page) 773 { 774 MPI2_CONFIG_REQUEST *request; 775 MPI2_CONFIG_REPLY *reply; 776 struct mpr_command *cm; 777 Mpi2BiosPage3_t *page = NULL; 778 int error = 0; 779 u16 ioc_status; 780 781 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 782 783 if ((cm = mpr_alloc_command(sc)) == NULL) { 784 printf("%s: command alloc failed @ line %d\n", __func__, 785 __LINE__); 786 error = EBUSY; 787 goto out; 788 } 789 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 790 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 791 request->Function = MPI2_FUNCTION_CONFIG; 792 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 793 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 794 request->Header.PageNumber = 3; 795 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 796 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 797 cm->cm_data = NULL; 798 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 799 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 800 if (error || (reply == NULL)) { 801 /* FIXME */ 802 /* 803 * If the request returns an error then we need to do a diag 804 * reset 805 */ 806 printf("%s: request for header completed with error %d", 807 __func__, error); 808 error = ENXIO; 809 goto out; 810 } 811 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 812 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 813 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 814 /* FIXME */ 815 /* 816 * If the request returns an error then we need to do a diag 817 * reset 818 */ 819 printf("%s: header read with error; iocstatus = 0x%x\n", 820 __func__, ioc_status); 821 error = ENXIO; 822 goto out; 823 } 824 /* We have to do free and alloc for the reply-free and reply-post 825 * counters to match - Need to review the reply FIFO handling. 826 */ 827 mpr_free_command(sc, cm); 828 829 if ((cm = mpr_alloc_command(sc)) == NULL) { 830 printf("%s: command alloc failed @ line %d\n", __func__, 831 __LINE__); 832 error = EBUSY; 833 goto out; 834 } 835 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 836 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 837 request->Function = MPI2_FUNCTION_CONFIG; 838 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 839 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 840 request->Header.PageNumber = 3; 841 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 842 request->Header.PageLength = mpi_reply->Header.PageLength; 843 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 844 cm->cm_sge = &request->PageBufferSGE; 845 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 846 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 847 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 848 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 849 if (!page) { 850 printf("%s: page alloc failed\n", __func__); 851 error = ENOMEM; 852 goto out; 853 } 854 cm->cm_data = page; 855 856 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 857 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 858 if (error || (reply == NULL)) { 859 /* FIXME */ 860 /* 861 * If the request returns an error then we need to do a diag 862 * reset 863 */ 864 printf("%s: request for page completed with error %d", 865 __func__, error); 866 error = ENXIO; 867 goto out; 868 } 869 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 870 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 871 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 872 /* FIXME */ 873 /* 874 * If the request returns an error then we need to do a diag 875 * reset 876 */ 877 printf("%s: page read with error; iocstatus = 0x%x\n", 878 __func__, ioc_status); 879 error = ENXIO; 880 goto out; 881 } 882 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 883 out: 884 free(page, M_MPR); 885 if (cm) 886 mpr_free_command(sc, cm); 887 return (error); 888 } 889 890 /** 891 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0 892 * @sc: per adapter object 893 * @mpi_reply: reply mf payload returned from firmware 894 * @config_page: contents of the config page 895 * @page_address: form and handle value used to get page 896 * Context: sleep. 897 * 898 * Returns 0 for success, non-zero for failure. 899 */ 900 int 901 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t 902 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 903 { 904 MPI2_CONFIG_REQUEST *request; 905 MPI2_CONFIG_REPLY *reply; 906 struct mpr_command *cm; 907 Mpi2RaidVolPage0_t *page = NULL; 908 int error = 0; 909 u16 ioc_status; 910 911 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 912 913 if ((cm = mpr_alloc_command(sc)) == NULL) { 914 printf("%s: command alloc failed @ line %d\n", __func__, 915 __LINE__); 916 error = EBUSY; 917 goto out; 918 } 919 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 920 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 921 request->Function = MPI2_FUNCTION_CONFIG; 922 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 923 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 924 request->Header.PageNumber = 0; 925 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 926 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 927 cm->cm_data = NULL; 928 929 /* 930 * This page must be polled because the IOC isn't ready yet when this 931 * page is needed. 932 */ 933 error = mpr_request_polled(sc, cm); 934 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 935 if (error || (reply == NULL)) { 936 /* FIXME */ 937 /* If the poll returns error then we need to do diag reset */ 938 printf("%s: poll for header completed with error %d", 939 __func__, error); 940 error = ENXIO; 941 goto out; 942 } 943 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 944 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 945 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 946 /* FIXME */ 947 /* If the poll returns error then we need to do diag reset */ 948 printf("%s: header read with error; iocstatus = 0x%x\n", 949 __func__, ioc_status); 950 error = ENXIO; 951 goto out; 952 } 953 /* We have to do free and alloc for the reply-free and reply-post 954 * counters to match - Need to review the reply FIFO handling. 955 */ 956 mpr_free_command(sc, cm); 957 958 if ((cm = mpr_alloc_command(sc)) == NULL) { 959 printf("%s: command alloc failed @ line %d\n", __func__, 960 __LINE__); 961 error = EBUSY; 962 goto out; 963 } 964 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 965 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 966 request->Function = MPI2_FUNCTION_CONFIG; 967 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 968 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 969 request->Header.PageNumber = 0; 970 request->Header.PageLength = mpi_reply->Header.PageLength; 971 request->Header.PageVersion = mpi_reply->Header.PageVersion; 972 request->PageAddress = page_address; 973 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 974 cm->cm_sge = &request->PageBufferSGE; 975 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 976 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 977 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 978 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 979 if (!page) { 980 printf("%s: page alloc failed\n", __func__); 981 error = ENOMEM; 982 goto out; 983 } 984 cm->cm_data = page; 985 986 /* 987 * This page must be polled because the IOC isn't ready yet when this 988 * page is needed. 989 */ 990 error = mpr_request_polled(sc, cm); 991 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 992 if (error || (reply == NULL)) { 993 /* FIXME */ 994 /* If the poll returns error then we need to do diag reset */ 995 printf("%s: poll for page completed with error %d", 996 __func__, error); 997 error = ENXIO; 998 goto out; 999 } 1000 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1001 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1002 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1003 /* FIXME */ 1004 /* If the poll returns error then we need to do diag reset */ 1005 printf("%s: page read with error; iocstatus = 0x%x\n", 1006 __func__, ioc_status); 1007 error = ENXIO; 1008 goto out; 1009 } 1010 bcopy(page, config_page, cm->cm_length); 1011 out: 1012 free(page, M_MPR); 1013 if (cm) 1014 mpr_free_command(sc, cm); 1015 return (error); 1016 } 1017 1018 /** 1019 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1 1020 * @sc: per adapter object 1021 * @mpi_reply: reply mf payload returned from firmware 1022 * @config_page: contents of the config page 1023 * @form: GET_NEXT_HANDLE or HANDLE 1024 * @handle: volume handle 1025 * Context: sleep. 1026 * 1027 * Returns 0 for success, non-zero for failure. 1028 */ 1029 int 1030 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t 1031 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1032 { 1033 MPI2_CONFIG_REQUEST *request; 1034 MPI2_CONFIG_REPLY *reply; 1035 struct mpr_command *cm; 1036 Mpi2RaidVolPage1_t *page = NULL; 1037 int error = 0; 1038 u16 ioc_status; 1039 1040 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1041 1042 if ((cm = mpr_alloc_command(sc)) == NULL) { 1043 printf("%s: command alloc failed @ line %d\n", __func__, 1044 __LINE__); 1045 error = EBUSY; 1046 goto out; 1047 } 1048 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1049 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1050 request->Function = MPI2_FUNCTION_CONFIG; 1051 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1052 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1053 request->Header.PageNumber = 1; 1054 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1055 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1056 cm->cm_data = NULL; 1057 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 1058 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1059 if (error || (reply == NULL)) { 1060 /* FIXME */ 1061 /* 1062 * If the request returns an error then we need to do a diag 1063 * reset 1064 */ 1065 printf("%s: request for header completed with error %d", 1066 __func__, error); 1067 error = ENXIO; 1068 goto out; 1069 } 1070 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1071 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1072 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1073 /* FIXME */ 1074 /* 1075 * If the request returns an error then we need to do a diag 1076 * reset 1077 */ 1078 printf("%s: header read with error; iocstatus = 0x%x\n", 1079 __func__, ioc_status); 1080 error = ENXIO; 1081 goto out; 1082 } 1083 /* We have to do free and alloc for the reply-free and reply-post 1084 * counters to match - Need to review the reply FIFO handling. 1085 */ 1086 mpr_free_command(sc, cm); 1087 1088 if ((cm = mpr_alloc_command(sc)) == NULL) { 1089 printf("%s: command alloc failed @ line %d\n", __func__, 1090 __LINE__); 1091 error = EBUSY; 1092 goto out; 1093 } 1094 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1095 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1096 request->Function = MPI2_FUNCTION_CONFIG; 1097 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1098 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1099 request->Header.PageNumber = 1; 1100 request->Header.PageLength = mpi_reply->Header.PageLength; 1101 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1102 request->PageAddress = htole32(form | handle); 1103 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1104 cm->cm_sge = &request->PageBufferSGE; 1105 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1106 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1107 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1108 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1109 if (!page) { 1110 printf("%s: page alloc failed\n", __func__); 1111 error = ENOMEM; 1112 goto out; 1113 } 1114 cm->cm_data = page; 1115 1116 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 1117 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1118 if (error || (reply == NULL)) { 1119 /* FIXME */ 1120 /* 1121 * If the request returns an error then we need to do a diag 1122 * reset 1123 */ 1124 printf("%s: request for page completed with error %d", 1125 __func__, error); 1126 error = ENXIO; 1127 goto out; 1128 } 1129 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1130 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1131 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1132 /* FIXME */ 1133 /* 1134 * If the request returns an error then we need to do a diag 1135 * reset 1136 */ 1137 printf("%s: page read with error; iocstatus = 0x%x\n", 1138 __func__, ioc_status); 1139 error = ENXIO; 1140 goto out; 1141 } 1142 bcopy(page, config_page, MIN(cm->cm_length, 1143 sizeof(Mpi2RaidVolPage1_t))); 1144 out: 1145 free(page, M_MPR); 1146 if (cm) 1147 mpr_free_command(sc, cm); 1148 return (error); 1149 } 1150 1151 /** 1152 * mpr_config_get_volume_wwid - returns wwid given the volume handle 1153 * @sc: per adapter object 1154 * @volume_handle: volume handle 1155 * @wwid: volume wwid 1156 * Context: sleep. 1157 * 1158 * Returns 0 for success, non-zero for failure. 1159 */ 1160 int 1161 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid) 1162 { 1163 Mpi2ConfigReply_t mpi_reply; 1164 Mpi2RaidVolPage1_t raid_vol_pg1; 1165 1166 *wwid = 0; 1167 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1168 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1169 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1170 raid_vol_pg1.WWID.Low); 1171 return 0; 1172 } else 1173 return -1; 1174 } 1175 1176 /** 1177 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0 1178 * @sc: per adapter object 1179 * @mpi_reply: reply mf payload returned from firmware 1180 * @config_page: contents of the config page 1181 * @page_address: form and handle value used to get page 1182 * Context: sleep. 1183 * 1184 * Returns 0 for success, non-zero for failure. 1185 */ 1186 int 1187 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1188 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1189 { 1190 MPI2_CONFIG_REQUEST *request; 1191 MPI2_CONFIG_REPLY *reply; 1192 struct mpr_command *cm; 1193 Mpi2RaidPhysDiskPage0_t *page = NULL; 1194 int error = 0; 1195 u16 ioc_status; 1196 1197 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1198 1199 if ((cm = mpr_alloc_command(sc)) == NULL) { 1200 printf("%s: command alloc failed @ line %d\n", __func__, 1201 __LINE__); 1202 error = EBUSY; 1203 goto out; 1204 } 1205 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1206 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1207 request->Function = MPI2_FUNCTION_CONFIG; 1208 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1209 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1210 request->Header.PageNumber = 0; 1211 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1212 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1213 cm->cm_data = NULL; 1214 1215 /* 1216 * This page must be polled because the IOC isn't ready yet when this 1217 * page is needed. 1218 */ 1219 error = mpr_request_polled(sc, cm); 1220 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1221 if (error || (reply == NULL)) { 1222 /* FIXME */ 1223 /* If the poll returns error then we need to do diag reset */ 1224 printf("%s: poll for header completed with error %d", 1225 __func__, error); 1226 error = ENXIO; 1227 goto out; 1228 } 1229 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1230 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1231 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1232 /* FIXME */ 1233 /* If the poll returns error then we need to do diag reset */ 1234 printf("%s: header read with error; iocstatus = 0x%x\n", 1235 __func__, ioc_status); 1236 error = ENXIO; 1237 goto out; 1238 } 1239 /* We have to do free and alloc for the reply-free and reply-post 1240 * counters to match - Need to review the reply FIFO handling. 1241 */ 1242 mpr_free_command(sc, cm); 1243 1244 if ((cm = mpr_alloc_command(sc)) == NULL) { 1245 printf("%s: command alloc failed @ line %d\n", __func__, 1246 __LINE__); 1247 error = EBUSY; 1248 goto out; 1249 } 1250 request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1251 bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1252 request->Function = MPI2_FUNCTION_CONFIG; 1253 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1254 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1255 request->Header.PageNumber = 0; 1256 request->Header.PageLength = mpi_reply->Header.PageLength; 1257 request->Header.PageVersion = mpi_reply->Header.PageVersion; 1258 request->PageAddress = page_address; 1259 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1260 cm->cm_sge = &request->PageBufferSGE; 1261 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1262 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; 1263 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1264 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT); 1265 if (!page) { 1266 printf("%s: page alloc failed\n", __func__); 1267 error = ENOMEM; 1268 goto out; 1269 } 1270 cm->cm_data = page; 1271 1272 /* 1273 * This page must be polled because the IOC isn't ready yet when this 1274 * page is needed. 1275 */ 1276 error = mpr_request_polled(sc, cm); 1277 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1278 if (error || (reply == NULL)) { 1279 /* FIXME */ 1280 /* If the poll returns error then we need to do diag reset */ 1281 printf("%s: poll for page completed with error %d", 1282 __func__, error); 1283 error = ENXIO; 1284 goto out; 1285 } 1286 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1287 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1288 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1289 /* FIXME */ 1290 /* If the poll returns error then we need to do diag reset */ 1291 printf("%s: page read with error; iocstatus = 0x%x\n", 1292 __func__, ioc_status); 1293 error = ENXIO; 1294 goto out; 1295 } 1296 bcopy(page, config_page, MIN(cm->cm_length, 1297 sizeof(Mpi2RaidPhysDiskPage0_t))); 1298 out: 1299 free(page, M_MPR); 1300 if (cm) 1301 mpr_free_command(sc, cm); 1302 return (error); 1303 } 1304