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