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