1 /*- 2 * Copyright (c) 2008 Yahoo!, Inc. 3 * All rights reserved. 4 * Written by: John Baldwin <jhb@FreeBSD.org> 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 * 3. Neither the name of the author nor the names of any co-contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface 31 */ 32 /*- 33 * Copyright (c) 2011-2015 LSI Corp. 34 * Copyright (c) 2013-2015 Avago Technologies 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 * 58 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 59 * 60 * $FreeBSD$ 61 */ 62 63 #include <sys/cdefs.h> 64 __FBSDID("$FreeBSD$"); 65 66 #include "opt_compat.h" 67 68 /* TODO Move headers to mprvar */ 69 #include <sys/types.h> 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/kernel.h> 73 #include <sys/selinfo.h> 74 #include <sys/module.h> 75 #include <sys/bus.h> 76 #include <sys/conf.h> 77 #include <sys/bio.h> 78 #include <sys/malloc.h> 79 #include <sys/uio.h> 80 #include <sys/sysctl.h> 81 #include <sys/ioccom.h> 82 #include <sys/endian.h> 83 #include <sys/queue.h> 84 #include <sys/kthread.h> 85 #include <sys/taskqueue.h> 86 #include <sys/proc.h> 87 #include <sys/sysent.h> 88 89 #include <machine/bus.h> 90 #include <machine/resource.h> 91 #include <sys/rman.h> 92 93 #include <cam/cam.h> 94 #include <cam/cam_ccb.h> 95 96 #include <dev/mpr/mpi/mpi2_type.h> 97 #include <dev/mpr/mpi/mpi2.h> 98 #include <dev/mpr/mpi/mpi2_ioc.h> 99 #include <dev/mpr/mpi/mpi2_cnfg.h> 100 #include <dev/mpr/mpi/mpi2_init.h> 101 #include <dev/mpr/mpi/mpi2_tool.h> 102 #include <dev/mpr/mpr_ioctl.h> 103 #include <dev/mpr/mprvar.h> 104 #include <dev/mpr/mpr_table.h> 105 #include <dev/mpr/mpr_sas.h> 106 #include <dev/pci/pcivar.h> 107 #include <dev/pci/pcireg.h> 108 109 static d_open_t mpr_open; 110 static d_close_t mpr_close; 111 static d_ioctl_t mpr_ioctl_devsw; 112 113 static struct cdevsw mpr_cdevsw = { 114 .d_version = D_VERSION, 115 .d_flags = 0, 116 .d_open = mpr_open, 117 .d_close = mpr_close, 118 .d_ioctl = mpr_ioctl_devsw, 119 .d_name = "mpr", 120 }; 121 122 typedef int (mpr_user_f)(struct mpr_command *, struct mpr_usr_command *); 123 static mpr_user_f mpi_pre_ioc_facts; 124 static mpr_user_f mpi_pre_port_facts; 125 static mpr_user_f mpi_pre_fw_download; 126 static mpr_user_f mpi_pre_fw_upload; 127 static mpr_user_f mpi_pre_sata_passthrough; 128 static mpr_user_f mpi_pre_smp_passthrough; 129 static mpr_user_f mpi_pre_config; 130 static mpr_user_f mpi_pre_sas_io_unit_control; 131 132 static int mpr_user_read_cfg_header(struct mpr_softc *, 133 struct mpr_cfg_page_req *); 134 static int mpr_user_read_cfg_page(struct mpr_softc *, 135 struct mpr_cfg_page_req *, void *); 136 static int mpr_user_read_extcfg_header(struct mpr_softc *, 137 struct mpr_ext_cfg_page_req *); 138 static int mpr_user_read_extcfg_page(struct mpr_softc *, 139 struct mpr_ext_cfg_page_req *, void *); 140 static int mpr_user_write_cfg_page(struct mpr_softc *, 141 struct mpr_cfg_page_req *, void *); 142 static int mpr_user_setup_request(struct mpr_command *, 143 struct mpr_usr_command *); 144 static int mpr_user_command(struct mpr_softc *, struct mpr_usr_command *); 145 146 static int mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data); 147 static void mpr_user_get_adapter_data(struct mpr_softc *sc, 148 mpr_adapter_data_t *data); 149 static void mpr_user_read_pci_info(struct mpr_softc *sc, 150 mpr_pci_info_t *data); 151 static uint8_t mpr_get_fw_diag_buffer_number(struct mpr_softc *sc, 152 uint32_t unique_id); 153 static int mpr_post_fw_diag_buffer(struct mpr_softc *sc, 154 mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code); 155 static int mpr_release_fw_diag_buffer(struct mpr_softc *sc, 156 mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code, 157 uint32_t diag_type); 158 static int mpr_diag_register(struct mpr_softc *sc, 159 mpr_fw_diag_register_t *diag_register, uint32_t *return_code); 160 static int mpr_diag_unregister(struct mpr_softc *sc, 161 mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code); 162 static int mpr_diag_query(struct mpr_softc *sc, 163 mpr_fw_diag_query_t *diag_query, uint32_t *return_code); 164 static int mpr_diag_read_buffer(struct mpr_softc *sc, 165 mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf, 166 uint32_t *return_code); 167 static int mpr_diag_release(struct mpr_softc *sc, 168 mpr_fw_diag_release_t *diag_release, uint32_t *return_code); 169 static int mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, 170 uint8_t *diag_action, uint32_t length, uint32_t *return_code); 171 static int mpr_user_diag_action(struct mpr_softc *sc, 172 mpr_diag_action_t *data); 173 static void mpr_user_event_query(struct mpr_softc *sc, 174 mpr_event_query_t *data); 175 static void mpr_user_event_enable(struct mpr_softc *sc, 176 mpr_event_enable_t *data); 177 static int mpr_user_event_report(struct mpr_softc *sc, 178 mpr_event_report_t *data); 179 static int mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data); 180 static int mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data); 181 182 static MALLOC_DEFINE(M_MPRUSER, "mpr_user", "Buffers for mpr(4) ioctls"); 183 184 /* Macros from compat/freebsd32/freebsd32.h */ 185 #define PTRIN(v) (void *)(uintptr_t)(v) 186 #define PTROUT(v) (uint32_t)(uintptr_t)(v) 187 188 #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) 189 #define PTRIN_CP(src,dst,fld) \ 190 do { (dst).fld = PTRIN((src).fld); } while (0) 191 #define PTROUT_CP(src,dst,fld) \ 192 do { (dst).fld = PTROUT((src).fld); } while (0) 193 194 /* 195 * MPI functions that support IEEE SGLs for SAS3. 196 */ 197 static uint8_t ieee_sgl_func_list[] = { 198 MPI2_FUNCTION_SCSI_IO_REQUEST, 199 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH, 200 MPI2_FUNCTION_SMP_PASSTHROUGH, 201 MPI2_FUNCTION_SATA_PASSTHROUGH, 202 MPI2_FUNCTION_FW_UPLOAD, 203 MPI2_FUNCTION_FW_DOWNLOAD, 204 MPI2_FUNCTION_TARGET_ASSIST, 205 MPI2_FUNCTION_TARGET_STATUS_SEND, 206 MPI2_FUNCTION_TOOLBOX 207 }; 208 209 int 210 mpr_attach_user(struct mpr_softc *sc) 211 { 212 int unit; 213 214 unit = device_get_unit(sc->mpr_dev); 215 sc->mpr_cdev = make_dev(&mpr_cdevsw, unit, UID_ROOT, GID_OPERATOR, 216 0640, "mpr%d", unit); 217 if (sc->mpr_cdev == NULL) { 218 return (ENOMEM); 219 } 220 sc->mpr_cdev->si_drv1 = sc; 221 return (0); 222 } 223 224 void 225 mpr_detach_user(struct mpr_softc *sc) 226 { 227 228 /* XXX: do a purge of pending requests? */ 229 if (sc->mpr_cdev != NULL) 230 destroy_dev(sc->mpr_cdev); 231 } 232 233 static int 234 mpr_open(struct cdev *dev, int flags, int fmt, struct thread *td) 235 { 236 237 return (0); 238 } 239 240 static int 241 mpr_close(struct cdev *dev, int flags, int fmt, struct thread *td) 242 { 243 244 return (0); 245 } 246 247 static int 248 mpr_user_read_cfg_header(struct mpr_softc *sc, 249 struct mpr_cfg_page_req *page_req) 250 { 251 MPI2_CONFIG_PAGE_HEADER *hdr; 252 struct mpr_config_params params; 253 int error; 254 255 hdr = ¶ms.hdr.Struct; 256 params.action = MPI2_CONFIG_ACTION_PAGE_HEADER; 257 params.page_address = le32toh(page_req->page_address); 258 hdr->PageVersion = 0; 259 hdr->PageLength = 0; 260 hdr->PageNumber = page_req->header.PageNumber; 261 hdr->PageType = page_req->header.PageType; 262 params.buffer = NULL; 263 params.length = 0; 264 params.callback = NULL; 265 266 if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { 267 /* 268 * Leave the request. Without resetting the chip, it's 269 * still owned by it and we'll just get into trouble 270 * freeing it now. Mark it as abandoned so that if it 271 * shows up later it can be freed. 272 */ 273 mpr_printf(sc, "read_cfg_header timed out\n"); 274 return (ETIMEDOUT); 275 } 276 277 page_req->ioc_status = htole16(params.status); 278 if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) == 279 MPI2_IOCSTATUS_SUCCESS) { 280 bcopy(hdr, &page_req->header, sizeof(page_req->header)); 281 } 282 283 return (0); 284 } 285 286 static int 287 mpr_user_read_cfg_page(struct mpr_softc *sc, 288 struct mpr_cfg_page_req *page_req, void *buf) 289 { 290 MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; 291 struct mpr_config_params params; 292 int error; 293 294 reqhdr = buf; 295 hdr = ¶ms.hdr.Struct; 296 hdr->PageVersion = reqhdr->PageVersion; 297 hdr->PageLength = reqhdr->PageLength; 298 hdr->PageNumber = reqhdr->PageNumber; 299 hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK; 300 params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 301 params.page_address = le32toh(page_req->page_address); 302 params.buffer = buf; 303 params.length = le32toh(page_req->len); 304 params.callback = NULL; 305 306 if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { 307 mpr_printf(sc, "mpr_user_read_cfg_page timed out\n"); 308 return (ETIMEDOUT); 309 } 310 311 page_req->ioc_status = htole16(params.status); 312 return (0); 313 } 314 315 static int 316 mpr_user_read_extcfg_header(struct mpr_softc *sc, 317 struct mpr_ext_cfg_page_req *ext_page_req) 318 { 319 MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr; 320 struct mpr_config_params params; 321 int error; 322 323 hdr = ¶ms.hdr.Ext; 324 params.action = MPI2_CONFIG_ACTION_PAGE_HEADER; 325 hdr->PageVersion = ext_page_req->header.PageVersion; 326 hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 327 hdr->ExtPageLength = 0; 328 hdr->PageNumber = ext_page_req->header.PageNumber; 329 hdr->ExtPageType = ext_page_req->header.ExtPageType; 330 params.page_address = le32toh(ext_page_req->page_address); 331 params.buffer = NULL; 332 params.length = 0; 333 params.callback = NULL; 334 335 if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { 336 /* 337 * Leave the request. Without resetting the chip, it's 338 * still owned by it and we'll just get into trouble 339 * freeing it now. Mark it as abandoned so that if it 340 * shows up later it can be freed. 341 */ 342 mpr_printf(sc, "mpr_user_read_extcfg_header timed out\n"); 343 return (ETIMEDOUT); 344 } 345 346 ext_page_req->ioc_status = htole16(params.status); 347 if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) == 348 MPI2_IOCSTATUS_SUCCESS) { 349 ext_page_req->header.PageVersion = hdr->PageVersion; 350 ext_page_req->header.PageNumber = hdr->PageNumber; 351 ext_page_req->header.PageType = hdr->PageType; 352 ext_page_req->header.ExtPageLength = hdr->ExtPageLength; 353 ext_page_req->header.ExtPageType = hdr->ExtPageType; 354 } 355 356 return (0); 357 } 358 359 static int 360 mpr_user_read_extcfg_page(struct mpr_softc *sc, 361 struct mpr_ext_cfg_page_req *ext_page_req, void *buf) 362 { 363 MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr; 364 struct mpr_config_params params; 365 int error; 366 367 reqhdr = buf; 368 hdr = ¶ms.hdr.Ext; 369 params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 370 params.page_address = le32toh(ext_page_req->page_address); 371 hdr->PageVersion = reqhdr->PageVersion; 372 hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 373 hdr->PageNumber = reqhdr->PageNumber; 374 hdr->ExtPageType = reqhdr->ExtPageType; 375 hdr->ExtPageLength = reqhdr->ExtPageLength; 376 params.buffer = buf; 377 params.length = le32toh(ext_page_req->len); 378 params.callback = NULL; 379 380 if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { 381 mpr_printf(sc, "mpr_user_read_extcfg_page timed out\n"); 382 return (ETIMEDOUT); 383 } 384 385 ext_page_req->ioc_status = htole16(params.status); 386 return (0); 387 } 388 389 static int 390 mpr_user_write_cfg_page(struct mpr_softc *sc, 391 struct mpr_cfg_page_req *page_req, void *buf) 392 { 393 MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; 394 struct mpr_config_params params; 395 u_int hdr_attr; 396 int error; 397 398 reqhdr = buf; 399 hdr = ¶ms.hdr.Struct; 400 hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK; 401 if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE && 402 hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) { 403 mpr_printf(sc, "page type 0x%x not changeable\n", 404 reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK); 405 return (EINVAL); 406 } 407 408 /* 409 * There isn't any point in restoring stripped out attributes 410 * if you then mask them going down to issue the request. 411 */ 412 413 hdr->PageVersion = reqhdr->PageVersion; 414 hdr->PageLength = reqhdr->PageLength; 415 hdr->PageNumber = reqhdr->PageNumber; 416 hdr->PageType = reqhdr->PageType; 417 params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; 418 params.page_address = le32toh(page_req->page_address); 419 params.buffer = buf; 420 params.length = le32toh(page_req->len); 421 params.callback = NULL; 422 423 if ((error = mpr_write_config_page(sc, ¶ms)) != 0) { 424 mpr_printf(sc, "mpr_write_cfg_page timed out\n"); 425 return (ETIMEDOUT); 426 } 427 428 page_req->ioc_status = htole16(params.status); 429 return (0); 430 } 431 432 void 433 mpr_init_sge(struct mpr_command *cm, void *req, void *sge) 434 { 435 int off, space; 436 437 space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4; 438 off = (uintptr_t)sge - (uintptr_t)req; 439 440 KASSERT(off < space, ("bad pointers %p %p, off %d, space %d", 441 req, sge, off, space)); 442 443 cm->cm_sge = sge; 444 cm->cm_sglsize = space - off; 445 } 446 447 /* 448 * Prepare the mpr_command for an IOC_FACTS request. 449 */ 450 static int 451 mpi_pre_ioc_facts(struct mpr_command *cm, struct mpr_usr_command *cmd) 452 { 453 MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req; 454 MPI2_IOC_FACTS_REPLY *rpl; 455 456 if (cmd->req_len != sizeof *req) 457 return (EINVAL); 458 if (cmd->rpl_len != sizeof *rpl) 459 return (EINVAL); 460 461 cm->cm_sge = NULL; 462 cm->cm_sglsize = 0; 463 return (0); 464 } 465 466 /* 467 * Prepare the mpr_command for a PORT_FACTS request. 468 */ 469 static int 470 mpi_pre_port_facts(struct mpr_command *cm, struct mpr_usr_command *cmd) 471 { 472 MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req; 473 MPI2_PORT_FACTS_REPLY *rpl; 474 475 if (cmd->req_len != sizeof *req) 476 return (EINVAL); 477 if (cmd->rpl_len != sizeof *rpl) 478 return (EINVAL); 479 480 cm->cm_sge = NULL; 481 cm->cm_sglsize = 0; 482 return (0); 483 } 484 485 /* 486 * Prepare the mpr_command for a FW_DOWNLOAD request. 487 */ 488 static int 489 mpi_pre_fw_download(struct mpr_command *cm, struct mpr_usr_command *cmd) 490 { 491 MPI25_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req; 492 MPI2_FW_DOWNLOAD_REPLY *rpl; 493 int error; 494 495 if (cmd->req_len != sizeof *req) 496 return (EINVAL); 497 if (cmd->rpl_len != sizeof *rpl) 498 return (EINVAL); 499 500 if (cmd->len == 0) 501 return (EINVAL); 502 503 error = copyin(cmd->buf, cm->cm_data, cmd->len); 504 if (error != 0) 505 return (error); 506 507 mpr_init_sge(cm, req, &req->SGL); 508 509 /* 510 * For now, the F/W image must be provided in a single request. 511 */ 512 if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0) 513 return (EINVAL); 514 if (req->TotalImageSize != cmd->len) 515 return (EINVAL); 516 517 req->ImageOffset = 0; 518 req->ImageSize = cmd->len; 519 520 cm->cm_flags |= MPR_CM_FLAGS_DATAOUT; 521 522 return (mpr_push_ieee_sge(cm, &req->SGL, 0)); 523 } 524 525 /* 526 * Prepare the mpr_command for a FW_UPLOAD request. 527 */ 528 static int 529 mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd) 530 { 531 MPI25_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req; 532 MPI2_FW_UPLOAD_REPLY *rpl; 533 534 if (cmd->req_len != sizeof *req) 535 return (EINVAL); 536 if (cmd->rpl_len != sizeof *rpl) 537 return (EINVAL); 538 539 mpr_init_sge(cm, req, &req->SGL); 540 if (cmd->len == 0) { 541 /* Perhaps just asking what the size of the fw is? */ 542 return (0); 543 } 544 545 req->ImageOffset = 0; 546 req->ImageSize = cmd->len; 547 548 cm->cm_flags |= MPR_CM_FLAGS_DATAIN; 549 550 return (mpr_push_ieee_sge(cm, &req->SGL, 0)); 551 } 552 553 /* 554 * Prepare the mpr_command for a SATA_PASSTHROUGH request. 555 */ 556 static int 557 mpi_pre_sata_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd) 558 { 559 MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req; 560 MPI2_SATA_PASSTHROUGH_REPLY *rpl; 561 562 if (cmd->req_len != sizeof *req) 563 return (EINVAL); 564 if (cmd->rpl_len != sizeof *rpl) 565 return (EINVAL); 566 567 mpr_init_sge(cm, req, &req->SGL); 568 return (0); 569 } 570 571 /* 572 * Prepare the mpr_command for a SMP_PASSTHROUGH request. 573 */ 574 static int 575 mpi_pre_smp_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd) 576 { 577 MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req; 578 MPI2_SMP_PASSTHROUGH_REPLY *rpl; 579 580 if (cmd->req_len != sizeof *req) 581 return (EINVAL); 582 if (cmd->rpl_len != sizeof *rpl) 583 return (EINVAL); 584 585 mpr_init_sge(cm, req, &req->SGL); 586 return (0); 587 } 588 589 /* 590 * Prepare the mpr_command for a CONFIG request. 591 */ 592 static int 593 mpi_pre_config(struct mpr_command *cm, struct mpr_usr_command *cmd) 594 { 595 MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req; 596 MPI2_CONFIG_REPLY *rpl; 597 598 if (cmd->req_len != sizeof *req) 599 return (EINVAL); 600 if (cmd->rpl_len != sizeof *rpl) 601 return (EINVAL); 602 603 mpr_init_sge(cm, req, &req->PageBufferSGE); 604 return (0); 605 } 606 607 /* 608 * Prepare the mpr_command for a SAS_IO_UNIT_CONTROL request. 609 */ 610 static int 611 mpi_pre_sas_io_unit_control(struct mpr_command *cm, 612 struct mpr_usr_command *cmd) 613 { 614 615 cm->cm_sge = NULL; 616 cm->cm_sglsize = 0; 617 return (0); 618 } 619 620 /* 621 * A set of functions to prepare an mpr_command for the various 622 * supported requests. 623 */ 624 struct mpr_user_func { 625 U8 Function; 626 mpr_user_f *f_pre; 627 } mpr_user_func_list[] = { 628 { MPI2_FUNCTION_IOC_FACTS, mpi_pre_ioc_facts }, 629 { MPI2_FUNCTION_PORT_FACTS, mpi_pre_port_facts }, 630 { MPI2_FUNCTION_FW_DOWNLOAD, mpi_pre_fw_download }, 631 { MPI2_FUNCTION_FW_UPLOAD, mpi_pre_fw_upload }, 632 { MPI2_FUNCTION_SATA_PASSTHROUGH, mpi_pre_sata_passthrough }, 633 { MPI2_FUNCTION_SMP_PASSTHROUGH, mpi_pre_smp_passthrough}, 634 { MPI2_FUNCTION_CONFIG, mpi_pre_config}, 635 { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, mpi_pre_sas_io_unit_control }, 636 { 0xFF, NULL } /* list end */ 637 }; 638 639 static int 640 mpr_user_setup_request(struct mpr_command *cm, struct mpr_usr_command *cmd) 641 { 642 MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; 643 struct mpr_user_func *f; 644 645 for (f = mpr_user_func_list; f->f_pre != NULL; f++) { 646 if (hdr->Function == f->Function) 647 return (f->f_pre(cm, cmd)); 648 } 649 return (EINVAL); 650 } 651 652 static int 653 mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd) 654 { 655 MPI2_REQUEST_HEADER *hdr; 656 MPI2_DEFAULT_REPLY *rpl; 657 void *buf = NULL; 658 struct mpr_command *cm = NULL; 659 int err = 0; 660 int sz; 661 662 mpr_lock(sc); 663 cm = mpr_alloc_command(sc); 664 665 if (cm == NULL) { 666 mpr_printf(sc, "%s: no mpr requests\n", __func__); 667 err = ENOMEM; 668 goto Ret; 669 } 670 mpr_unlock(sc); 671 672 hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; 673 674 mpr_dprint(sc, MPR_USER, "%s: req %p %d rpl %p %d\n", __func__, 675 cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len); 676 677 if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) { 678 err = EINVAL; 679 goto RetFreeUnlocked; 680 } 681 err = copyin(cmd->req, hdr, cmd->req_len); 682 if (err != 0) 683 goto RetFreeUnlocked; 684 685 mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__, 686 hdr->Function, hdr->MsgFlags); 687 688 if (cmd->len > 0) { 689 buf = malloc(cmd->len, M_MPRUSER, M_WAITOK|M_ZERO); 690 if (!buf) { 691 mpr_printf(sc, "Cannot allocate memory %s %d\n", 692 __func__, __LINE__); 693 return (ENOMEM); 694 } 695 cm->cm_data = buf; 696 cm->cm_length = cmd->len; 697 } else { 698 cm->cm_data = NULL; 699 cm->cm_length = 0; 700 } 701 702 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE; 703 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 704 705 err = mpr_user_setup_request(cm, cmd); 706 if (err == EINVAL) { 707 mpr_printf(sc, "%s: unsupported parameter or unsupported " 708 "function in request (function = 0x%X)\n", __func__, 709 hdr->Function); 710 } 711 if (err != 0) 712 goto RetFreeUnlocked; 713 714 mpr_lock(sc); 715 err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); 716 717 if (err) { 718 mpr_printf(sc, "%s: invalid request: error %d\n", 719 __func__, err); 720 goto Ret; 721 } 722 723 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; 724 if (rpl != NULL) 725 sz = rpl->MsgLength * 4; 726 else 727 sz = 0; 728 729 if (sz > cmd->rpl_len) { 730 mpr_printf(sc, "%s: user reply buffer (%d) smaller than " 731 "returned buffer (%d)\n", __func__, cmd->rpl_len, sz); 732 sz = cmd->rpl_len; 733 } 734 735 mpr_unlock(sc); 736 copyout(rpl, cmd->rpl, sz); 737 if (buf != NULL) 738 copyout(buf, cmd->buf, cmd->len); 739 mpr_dprint(sc, MPR_USER, "%s: reply size %d\n", __func__, sz); 740 741 RetFreeUnlocked: 742 mpr_lock(sc); 743 if (cm != NULL) 744 mpr_free_command(sc, cm); 745 Ret: 746 mpr_unlock(sc); 747 if (buf != NULL) 748 free(buf, M_MPRUSER); 749 return (err); 750 } 751 752 static int 753 mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) 754 { 755 MPI2_REQUEST_HEADER *hdr, tmphdr; 756 MPI2_DEFAULT_REPLY *rpl; 757 struct mpr_command *cm = NULL; 758 int i, err = 0, dir = 0, sz; 759 uint8_t tool, function = 0; 760 u_int sense_len; 761 struct mprsas_target *targ = NULL; 762 763 /* 764 * Only allow one passthru command at a time. Use the MPR_FLAGS_BUSY 765 * bit to denote that a passthru is being processed. 766 */ 767 mpr_lock(sc); 768 if (sc->mpr_flags & MPR_FLAGS_BUSY) { 769 mpr_dprint(sc, MPR_USER, "%s: Only one passthru command " 770 "allowed at a single time.", __func__); 771 mpr_unlock(sc); 772 return (EBUSY); 773 } 774 sc->mpr_flags |= MPR_FLAGS_BUSY; 775 mpr_unlock(sc); 776 777 /* 778 * Do some validation on data direction. Valid cases are: 779 * 1) DataSize is 0 and direction is NONE 780 * 2) DataSize is non-zero and one of: 781 * a) direction is READ or 782 * b) direction is WRITE or 783 * c) direction is BOTH and DataOutSize is non-zero 784 * If valid and the direction is BOTH, change the direction to READ. 785 * if valid and the direction is not BOTH, make sure DataOutSize is 0. 786 */ 787 if (((data->DataSize == 0) && 788 (data->DataDirection == MPR_PASS_THRU_DIRECTION_NONE)) || 789 ((data->DataSize != 0) && 790 ((data->DataDirection == MPR_PASS_THRU_DIRECTION_READ) || 791 (data->DataDirection == MPR_PASS_THRU_DIRECTION_WRITE) || 792 ((data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH) && 793 (data->DataOutSize != 0))))) { 794 if (data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH) 795 data->DataDirection = MPR_PASS_THRU_DIRECTION_READ; 796 else 797 data->DataOutSize = 0; 798 } else 799 return (EINVAL); 800 801 mpr_dprint(sc, MPR_USER, "%s: req 0x%jx %d rpl 0x%jx %d " 802 "data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__, 803 data->PtrRequest, data->RequestSize, data->PtrReply, 804 data->ReplySize, data->PtrData, data->DataSize, 805 data->PtrDataOut, data->DataOutSize, data->DataDirection); 806 807 /* 808 * copy in the header so we know what we're dealing with before we 809 * commit to allocating a command for it. 810 */ 811 err = copyin(PTRIN(data->PtrRequest), &tmphdr, data->RequestSize); 812 if (err != 0) 813 goto RetFreeUnlocked; 814 815 if (data->RequestSize > (int)sc->facts->IOCRequestFrameSize * 4) { 816 err = EINVAL; 817 goto RetFreeUnlocked; 818 } 819 820 function = tmphdr.Function; 821 mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__, 822 function, tmphdr.MsgFlags); 823 824 /* 825 * Handle a passthru TM request. 826 */ 827 if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) { 828 MPI2_SCSI_TASK_MANAGE_REQUEST *task; 829 830 mpr_lock(sc); 831 cm = mprsas_alloc_tm(sc); 832 if (cm == NULL) { 833 err = EINVAL; 834 goto Ret; 835 } 836 837 /* Copy the header in. Only a small fixup is needed. */ 838 task = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 839 bcopy(&tmphdr, task, data->RequestSize); 840 task->TaskMID = cm->cm_desc.Default.SMID; 841 842 cm->cm_data = NULL; 843 cm->cm_desc.HighPriority.RequestFlags = 844 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 845 cm->cm_complete = NULL; 846 cm->cm_complete_data = NULL; 847 848 targ = mprsas_find_target_by_handle(sc->sassc, 0, 849 task->DevHandle); 850 if (targ == NULL) { 851 mpr_dprint(sc, MPR_INFO, 852 "%s %d : invalid handle for requested TM 0x%x \n", 853 __func__, __LINE__, task->DevHandle); 854 err = 1; 855 } else { 856 mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); 857 err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); 858 } 859 860 if (err != 0) { 861 err = EIO; 862 mpr_dprint(sc, MPR_FAULT, "%s: task management failed", 863 __func__); 864 } 865 /* 866 * Copy the reply data and sense data to user space. 867 */ 868 if (cm->cm_reply != NULL) { 869 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; 870 sz = rpl->MsgLength * 4; 871 872 if (sz > data->ReplySize) { 873 mpr_printf(sc, "%s: user reply buffer (%d) " 874 "smaller than returned buffer (%d)\n", 875 __func__, data->ReplySize, sz); 876 } 877 mpr_unlock(sc); 878 copyout(cm->cm_reply, PTRIN(data->PtrReply), 879 data->ReplySize); 880 mpr_lock(sc); 881 } 882 mprsas_free_tm(sc, cm); 883 goto Ret; 884 } 885 886 mpr_lock(sc); 887 cm = mpr_alloc_command(sc); 888 889 if (cm == NULL) { 890 mpr_printf(sc, "%s: no mpr requests\n", __func__); 891 err = ENOMEM; 892 goto Ret; 893 } 894 mpr_unlock(sc); 895 896 hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; 897 bcopy(&tmphdr, hdr, data->RequestSize); 898 899 /* 900 * Do some checking to make sure the IOCTL request contains a valid 901 * request. Then set the SGL info. 902 */ 903 mpr_init_sge(cm, hdr, (void *)((uint8_t *)hdr + data->RequestSize)); 904 905 /* 906 * Set up for read, write or both. From check above, DataOutSize will 907 * be 0 if direction is READ or WRITE, but it will have some non-zero 908 * value if the direction is BOTH. So, just use the biggest size to get 909 * the cm_data buffer size. If direction is BOTH, 2 SGLs need to be set 910 * up; the first is for the request and the second will contain the 911 * response data. cm_out_len needs to be set here and this will be used 912 * when the SGLs are set up. 913 */ 914 cm->cm_data = NULL; 915 cm->cm_length = MAX(data->DataSize, data->DataOutSize); 916 cm->cm_out_len = data->DataOutSize; 917 cm->cm_flags = 0; 918 if (cm->cm_length != 0) { 919 cm->cm_data = malloc(cm->cm_length, M_MPRUSER, M_WAITOK | 920 M_ZERO); 921 if (cm->cm_data == NULL) { 922 mpr_dprint(sc, MPR_FAULT, "%s: alloc failed for IOCTL " 923 "passthru length %d\n", __func__, cm->cm_length); 924 } else { 925 cm->cm_flags = MPR_CM_FLAGS_DATAIN; 926 if (data->DataOutSize) { 927 cm->cm_flags |= MPR_CM_FLAGS_DATAOUT; 928 err = copyin(PTRIN(data->PtrDataOut), 929 cm->cm_data, data->DataOutSize); 930 } else if (data->DataDirection == 931 MPR_PASS_THRU_DIRECTION_WRITE) { 932 cm->cm_flags = MPR_CM_FLAGS_DATAOUT; 933 err = copyin(PTRIN(data->PtrData), 934 cm->cm_data, data->DataSize); 935 } 936 if (err != 0) 937 mpr_dprint(sc, MPR_FAULT, "%s: failed to copy " 938 "IOCTL data from user space\n", __func__); 939 } 940 } 941 /* 942 * Set this flag only if processing a command that does not need an 943 * IEEE SGL. The CLI Tool within the Toolbox uses IEEE SGLs, so clear 944 * the flag only for that tool if processing a Toolbox function. 945 */ 946 cm->cm_flags |= MPR_CM_FLAGS_SGE_SIMPLE; 947 for (i = 0; i < sizeof (ieee_sgl_func_list); i++) { 948 if (function == ieee_sgl_func_list[i]) { 949 if (function == MPI2_FUNCTION_TOOLBOX) 950 { 951 tool = (uint8_t)hdr->FunctionDependent1; 952 if (tool != MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) 953 break; 954 } 955 cm->cm_flags &= ~MPR_CM_FLAGS_SGE_SIMPLE; 956 break; 957 } 958 } 959 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 960 961 /* 962 * Set up Sense buffer and SGL offset for IO passthru. SCSI IO request 963 * uses SCSI IO or Fast Path SCSI IO descriptor. 964 */ 965 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) || 966 (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { 967 MPI2_SCSI_IO_REQUEST *scsi_io_req; 968 969 scsi_io_req = (MPI2_SCSI_IO_REQUEST *)hdr; 970 /* 971 * Put SGE for data and data_out buffer at the end of 972 * scsi_io_request message header (64 bytes in total). 973 * Following above SGEs, the residual space will be used by 974 * sense data. 975 */ 976 scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize - 977 64); 978 scsi_io_req->SenseBufferLowAddress = 979 htole32(cm->cm_sense_busaddr); 980 981 /* 982 * Set SGLOffset0 value. This is the number of dwords that SGL 983 * is offset from the beginning of MPI2_SCSI_IO_REQUEST struct. 984 */ 985 scsi_io_req->SGLOffset0 = 24; 986 987 /* 988 * Setup descriptor info. RAID passthrough must use the 989 * default request descriptor which is already set, so if this 990 * is a SCSI IO request, change the descriptor to SCSI IO or 991 * Fast Path SCSI IO. Also, if this is a SCSI IO request, 992 * handle the reply in the mprsas_scsio_complete function. 993 */ 994 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) { 995 targ = mprsas_find_target_by_handle(sc->sassc, 0, 996 scsi_io_req->DevHandle); 997 998 if (!targ) { 999 printf("No Target found for handle %d\n", 1000 scsi_io_req->DevHandle); 1001 err = EINVAL; 1002 goto RetFreeUnlocked; 1003 } 1004 1005 if (targ->scsi_req_desc_type == 1006 MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) { 1007 cm->cm_desc.FastPathSCSIIO.RequestFlags = 1008 MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 1009 cm->cm_desc.FastPathSCSIIO.DevHandle = 1010 scsi_io_req->DevHandle; 1011 scsi_io_req->IoFlags |= 1012 MPI25_SCSIIO_IOFLAGS_FAST_PATH; 1013 } else { 1014 cm->cm_desc.SCSIIO.RequestFlags = 1015 MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; 1016 cm->cm_desc.SCSIIO.DevHandle = 1017 scsi_io_req->DevHandle; 1018 } 1019 1020 /* 1021 * Make sure the DevHandle is not 0 because this is a 1022 * likely error. 1023 */ 1024 if (scsi_io_req->DevHandle == 0) { 1025 err = EINVAL; 1026 goto RetFreeUnlocked; 1027 } 1028 } 1029 } 1030 1031 mpr_lock(sc); 1032 1033 err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); 1034 1035 if (err) { 1036 mpr_printf(sc, "%s: invalid request: error %d\n", __func__, 1037 err); 1038 mpr_unlock(sc); 1039 goto RetFreeUnlocked; 1040 } 1041 1042 /* 1043 * Sync the DMA data, if any. Then copy the data to user space. 1044 */ 1045 if (cm->cm_data != NULL) { 1046 if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) 1047 dir = BUS_DMASYNC_POSTREAD; 1048 else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) 1049 dir = BUS_DMASYNC_POSTWRITE; 1050 bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); 1051 bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 1052 1053 if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) { 1054 mpr_unlock(sc); 1055 err = copyout(cm->cm_data, 1056 PTRIN(data->PtrData), data->DataSize); 1057 mpr_lock(sc); 1058 if (err != 0) 1059 mpr_dprint(sc, MPR_FAULT, "%s: failed to copy " 1060 "IOCTL data to user space\n", __func__); 1061 } 1062 } 1063 1064 /* 1065 * Copy the reply data and sense data to user space. 1066 */ 1067 if (cm->cm_reply != NULL) { 1068 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply; 1069 sz = rpl->MsgLength * 4; 1070 1071 if (sz > data->ReplySize) { 1072 mpr_printf(sc, "%s: user reply buffer (%d) smaller " 1073 "than returned buffer (%d)\n", __func__, 1074 data->ReplySize, sz); 1075 } 1076 mpr_unlock(sc); 1077 copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize); 1078 mpr_lock(sc); 1079 1080 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) || 1081 (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { 1082 if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState & 1083 MPI2_SCSI_STATE_AUTOSENSE_VALID) { 1084 sense_len = 1085 MIN((le32toh(((MPI2_SCSI_IO_REPLY *)rpl)-> 1086 SenseCount)), sizeof(struct 1087 scsi_sense_data)); 1088 mpr_unlock(sc); 1089 copyout(cm->cm_sense, cm->cm_req + 64, 1090 sense_len); 1091 mpr_lock(sc); 1092 } 1093 } 1094 } 1095 mpr_unlock(sc); 1096 1097 RetFreeUnlocked: 1098 mpr_lock(sc); 1099 1100 if (cm != NULL) { 1101 if (cm->cm_data) 1102 free(cm->cm_data, M_MPRUSER); 1103 mpr_free_command(sc, cm); 1104 } 1105 Ret: 1106 sc->mpr_flags &= ~MPR_FLAGS_BUSY; 1107 mpr_unlock(sc); 1108 1109 return (err); 1110 } 1111 1112 static void 1113 mpr_user_get_adapter_data(struct mpr_softc *sc, mpr_adapter_data_t *data) 1114 { 1115 Mpi2ConfigReply_t mpi_reply; 1116 Mpi2BiosPage3_t config_page; 1117 1118 /* 1119 * Use the PCI interface functions to get the Bus, Device, and Function 1120 * information. 1121 */ 1122 data->PciInformation.u.bits.BusNumber = pci_get_bus(sc->mpr_dev); 1123 data->PciInformation.u.bits.DeviceNumber = pci_get_slot(sc->mpr_dev); 1124 data->PciInformation.u.bits.FunctionNumber = 1125 pci_get_function(sc->mpr_dev); 1126 1127 /* 1128 * Get the FW version that should already be saved in IOC Facts. 1129 */ 1130 data->MpiFirmwareVersion = sc->facts->FWVersion.Word; 1131 1132 /* 1133 * General device info. 1134 */ 1135 data->AdapterType = MPRIOCTL_ADAPTER_TYPE_SAS3; 1136 data->PCIDeviceHwId = pci_get_device(sc->mpr_dev); 1137 data->PCIDeviceHwRev = pci_read_config(sc->mpr_dev, PCIR_REVID, 1); 1138 data->SubSystemId = pci_get_subdevice(sc->mpr_dev); 1139 data->SubsystemVendorId = pci_get_subvendor(sc->mpr_dev); 1140 1141 /* 1142 * Get the driver version. 1143 */ 1144 strcpy((char *)&data->DriverVersion[0], MPR_DRIVER_VERSION); 1145 1146 /* 1147 * Need to get BIOS Config Page 3 for the BIOS Version. 1148 */ 1149 data->BiosVersion = 0; 1150 mpr_lock(sc); 1151 if (mpr_config_get_bios_pg3(sc, &mpi_reply, &config_page)) 1152 printf("%s: Error while retrieving BIOS Version\n", __func__); 1153 else 1154 data->BiosVersion = config_page.BiosVersion; 1155 mpr_unlock(sc); 1156 } 1157 1158 static void 1159 mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data) 1160 { 1161 int i; 1162 1163 /* 1164 * Use the PCI interface functions to get the Bus, Device, and Function 1165 * information. 1166 */ 1167 data->BusNumber = pci_get_bus(sc->mpr_dev); 1168 data->DeviceNumber = pci_get_slot(sc->mpr_dev); 1169 data->FunctionNumber = pci_get_function(sc->mpr_dev); 1170 1171 /* 1172 * Now get the interrupt vector and the pci header. The vector can 1173 * only be 0 right now. The header is the first 256 bytes of config 1174 * space. 1175 */ 1176 data->InterruptVector = 0; 1177 for (i = 0; i < sizeof (data->PciHeader); i++) { 1178 data->PciHeader[i] = pci_read_config(sc->mpr_dev, i, 1); 1179 } 1180 } 1181 1182 static uint8_t 1183 mpr_get_fw_diag_buffer_number(struct mpr_softc *sc, uint32_t unique_id) 1184 { 1185 uint8_t index; 1186 1187 for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) { 1188 if (sc->fw_diag_buffer_list[index].unique_id == unique_id) { 1189 return (index); 1190 } 1191 } 1192 1193 return (MPR_FW_DIAGNOSTIC_UID_NOT_FOUND); 1194 } 1195 1196 static int 1197 mpr_post_fw_diag_buffer(struct mpr_softc *sc, 1198 mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code) 1199 { 1200 MPI2_DIAG_BUFFER_POST_REQUEST *req; 1201 MPI2_DIAG_BUFFER_POST_REPLY *reply; 1202 struct mpr_command *cm = NULL; 1203 int i, status; 1204 1205 /* 1206 * If buffer is not enabled, just leave. 1207 */ 1208 *return_code = MPR_FW_DIAG_ERROR_POST_FAILED; 1209 if (!pBuffer->enabled) { 1210 return (MPR_DIAG_FAILURE); 1211 } 1212 1213 /* 1214 * Clear some flags initially. 1215 */ 1216 pBuffer->force_release = FALSE; 1217 pBuffer->valid_data = FALSE; 1218 pBuffer->owned_by_firmware = FALSE; 1219 1220 /* 1221 * Get a command. 1222 */ 1223 cm = mpr_alloc_command(sc); 1224 if (cm == NULL) { 1225 mpr_printf(sc, "%s: no mpr requests\n", __func__); 1226 return (MPR_DIAG_FAILURE); 1227 } 1228 1229 /* 1230 * Build the request for releasing the FW Diag Buffer and send it. 1231 */ 1232 req = (MPI2_DIAG_BUFFER_POST_REQUEST *)cm->cm_req; 1233 req->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; 1234 req->BufferType = pBuffer->buffer_type; 1235 req->ExtendedType = pBuffer->extended_type; 1236 req->BufferLength = pBuffer->size; 1237 for (i = 0; i < (sizeof(req->ProductSpecific) / 4); i++) 1238 req->ProductSpecific[i] = pBuffer->product_specific[i]; 1239 mpr_from_u64(sc->fw_diag_busaddr, &req->BufferAddress); 1240 cm->cm_data = NULL; 1241 cm->cm_length = 0; 1242 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1243 cm->cm_complete_data = NULL; 1244 1245 /* 1246 * Send command synchronously. 1247 */ 1248 status = mpr_wait_command(sc, cm, 30, CAN_SLEEP); 1249 if (status) { 1250 mpr_printf(sc, "%s: invalid request: error %d\n", __func__, 1251 status); 1252 status = MPR_DIAG_FAILURE; 1253 goto done; 1254 } 1255 1256 /* 1257 * Process POST reply. 1258 */ 1259 reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply; 1260 if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { 1261 status = MPR_DIAG_FAILURE; 1262 mpr_dprint(sc, MPR_FAULT, "%s: post of FW Diag Buffer failed " 1263 "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and " 1264 "TransferLength = 0x%x\n", __func__, reply->IOCStatus, 1265 reply->IOCLogInfo, reply->TransferLength); 1266 goto done; 1267 } 1268 1269 /* 1270 * Post was successful. 1271 */ 1272 pBuffer->valid_data = TRUE; 1273 pBuffer->owned_by_firmware = TRUE; 1274 *return_code = MPR_FW_DIAG_ERROR_SUCCESS; 1275 status = MPR_DIAG_SUCCESS; 1276 1277 done: 1278 mpr_free_command(sc, cm); 1279 return (status); 1280 } 1281 1282 static int 1283 mpr_release_fw_diag_buffer(struct mpr_softc *sc, 1284 mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code, 1285 uint32_t diag_type) 1286 { 1287 MPI2_DIAG_RELEASE_REQUEST *req; 1288 MPI2_DIAG_RELEASE_REPLY *reply; 1289 struct mpr_command *cm = NULL; 1290 int status; 1291 1292 /* 1293 * If buffer is not enabled, just leave. 1294 */ 1295 *return_code = MPR_FW_DIAG_ERROR_RELEASE_FAILED; 1296 if (!pBuffer->enabled) { 1297 mpr_dprint(sc, MPR_USER, "%s: This buffer type is not " 1298 "supported by the IOC", __func__); 1299 return (MPR_DIAG_FAILURE); 1300 } 1301 1302 /* 1303 * Clear some flags initially. 1304 */ 1305 pBuffer->force_release = FALSE; 1306 pBuffer->valid_data = FALSE; 1307 pBuffer->owned_by_firmware = FALSE; 1308 1309 /* 1310 * Get a command. 1311 */ 1312 cm = mpr_alloc_command(sc); 1313 if (cm == NULL) { 1314 mpr_printf(sc, "%s: no mpr requests\n", __func__); 1315 return (MPR_DIAG_FAILURE); 1316 } 1317 1318 /* 1319 * Build the request for releasing the FW Diag Buffer and send it. 1320 */ 1321 req = (MPI2_DIAG_RELEASE_REQUEST *)cm->cm_req; 1322 req->Function = MPI2_FUNCTION_DIAG_RELEASE; 1323 req->BufferType = pBuffer->buffer_type; 1324 cm->cm_data = NULL; 1325 cm->cm_length = 0; 1326 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1327 cm->cm_complete_data = NULL; 1328 1329 /* 1330 * Send command synchronously. 1331 */ 1332 status = mpr_wait_command(sc, cm, 30, CAN_SLEEP); 1333 if (status) { 1334 mpr_printf(sc, "%s: invalid request: error %d\n", __func__, 1335 status); 1336 status = MPR_DIAG_FAILURE; 1337 goto done; 1338 } 1339 1340 /* 1341 * Process RELEASE reply. 1342 */ 1343 reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply; 1344 if ((reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) || 1345 pBuffer->owned_by_firmware) { 1346 status = MPR_DIAG_FAILURE; 1347 mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer " 1348 "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n", 1349 __func__, reply->IOCStatus, reply->IOCLogInfo); 1350 goto done; 1351 } 1352 1353 /* 1354 * Release was successful. 1355 */ 1356 *return_code = MPR_FW_DIAG_ERROR_SUCCESS; 1357 status = MPR_DIAG_SUCCESS; 1358 1359 /* 1360 * If this was for an UNREGISTER diag type command, clear the unique ID. 1361 */ 1362 if (diag_type == MPR_FW_DIAG_TYPE_UNREGISTER) { 1363 pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID; 1364 } 1365 1366 done: 1367 return (status); 1368 } 1369 1370 static int 1371 mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, 1372 uint32_t *return_code) 1373 { 1374 mpr_fw_diagnostic_buffer_t *pBuffer; 1375 uint8_t extended_type, buffer_type, i; 1376 uint32_t buffer_size; 1377 uint32_t unique_id; 1378 int status; 1379 1380 extended_type = diag_register->ExtendedType; 1381 buffer_type = diag_register->BufferType; 1382 buffer_size = diag_register->RequestedBufferSize; 1383 unique_id = diag_register->UniqueId; 1384 1385 /* 1386 * Check for valid buffer type 1387 */ 1388 if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) { 1389 *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1390 return (MPR_DIAG_FAILURE); 1391 } 1392 1393 /* 1394 * Get the current buffer and look up the unique ID. The unique ID 1395 * should not be found. If it is, the ID is already in use. 1396 */ 1397 i = mpr_get_fw_diag_buffer_number(sc, unique_id); 1398 pBuffer = &sc->fw_diag_buffer_list[buffer_type]; 1399 if (i != MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) { 1400 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1401 return (MPR_DIAG_FAILURE); 1402 } 1403 1404 /* 1405 * The buffer's unique ID should not be registered yet, and the given 1406 * unique ID cannot be 0. 1407 */ 1408 if ((pBuffer->unique_id != MPR_FW_DIAG_INVALID_UID) || 1409 (unique_id == MPR_FW_DIAG_INVALID_UID)) { 1410 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1411 return (MPR_DIAG_FAILURE); 1412 } 1413 1414 /* 1415 * If this buffer is already posted as immediate, just change owner. 1416 */ 1417 if (pBuffer->immediate && pBuffer->owned_by_firmware && 1418 (pBuffer->unique_id == MPR_FW_DIAG_INVALID_UID)) { 1419 pBuffer->immediate = FALSE; 1420 pBuffer->unique_id = unique_id; 1421 return (MPR_DIAG_SUCCESS); 1422 } 1423 1424 /* 1425 * Post a new buffer after checking if it's enabled. The DMA buffer 1426 * that is allocated will be contiguous (nsegments = 1). 1427 */ 1428 if (!pBuffer->enabled) { 1429 *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER; 1430 return (MPR_DIAG_FAILURE); 1431 } 1432 if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */ 1433 1, 0, /* algnmnt, boundary */ 1434 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 1435 BUS_SPACE_MAXADDR, /* highaddr */ 1436 NULL, NULL, /* filter, filterarg */ 1437 buffer_size, /* maxsize */ 1438 1, /* nsegments */ 1439 buffer_size, /* maxsegsize */ 1440 0, /* flags */ 1441 NULL, NULL, /* lockfunc, lockarg */ 1442 &sc->fw_diag_dmat)) { 1443 device_printf(sc->mpr_dev, "Cannot allocate FW diag buffer DMA " 1444 "tag\n"); 1445 return (ENOMEM); 1446 } 1447 if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer, 1448 BUS_DMA_NOWAIT, &sc->fw_diag_map)) { 1449 device_printf(sc->mpr_dev, "Cannot allocate FW diag buffer " 1450 "memory\n"); 1451 return (ENOMEM); 1452 } 1453 bzero(sc->fw_diag_buffer, buffer_size); 1454 bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map, sc->fw_diag_buffer, 1455 buffer_size, mpr_memaddr_cb, &sc->fw_diag_busaddr, 0); 1456 pBuffer->size = buffer_size; 1457 1458 /* 1459 * Copy the given info to the diag buffer and post the buffer. 1460 */ 1461 pBuffer->buffer_type = buffer_type; 1462 pBuffer->immediate = FALSE; 1463 if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) { 1464 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4); 1465 i++) { 1466 pBuffer->product_specific[i] = 1467 diag_register->ProductSpecific[i]; 1468 } 1469 } 1470 pBuffer->extended_type = extended_type; 1471 pBuffer->unique_id = unique_id; 1472 status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code); 1473 1474 /* 1475 * In case there was a failure, free the DMA buffer. 1476 */ 1477 if (status == MPR_DIAG_FAILURE) { 1478 if (sc->fw_diag_busaddr != 0) 1479 bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map); 1480 if (sc->fw_diag_buffer != NULL) 1481 bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer, 1482 sc->fw_diag_map); 1483 if (sc->fw_diag_dmat != NULL) 1484 bus_dma_tag_destroy(sc->fw_diag_dmat); 1485 } 1486 1487 return (status); 1488 } 1489 1490 static int 1491 mpr_diag_unregister(struct mpr_softc *sc, 1492 mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code) 1493 { 1494 mpr_fw_diagnostic_buffer_t *pBuffer; 1495 uint8_t i; 1496 uint32_t unique_id; 1497 int status; 1498 1499 unique_id = diag_unregister->UniqueId; 1500 1501 /* 1502 * Get the current buffer and look up the unique ID. The unique ID 1503 * should be there. 1504 */ 1505 i = mpr_get_fw_diag_buffer_number(sc, unique_id); 1506 if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) { 1507 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1508 return (MPR_DIAG_FAILURE); 1509 } 1510 1511 pBuffer = &sc->fw_diag_buffer_list[i]; 1512 1513 /* 1514 * Try to release the buffer from FW before freeing it. If release 1515 * fails, don't free the DMA buffer in case FW tries to access it 1516 * later. If buffer is not owned by firmware, can't release it. 1517 */ 1518 if (!pBuffer->owned_by_firmware) { 1519 status = MPR_DIAG_SUCCESS; 1520 } else { 1521 status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code, 1522 MPR_FW_DIAG_TYPE_UNREGISTER); 1523 } 1524 1525 /* 1526 * At this point, return the current status no matter what happens with 1527 * the DMA buffer. 1528 */ 1529 pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID; 1530 if (status == MPR_DIAG_SUCCESS) { 1531 if (sc->fw_diag_busaddr != 0) 1532 bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map); 1533 if (sc->fw_diag_buffer != NULL) 1534 bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer, 1535 sc->fw_diag_map); 1536 if (sc->fw_diag_dmat != NULL) 1537 bus_dma_tag_destroy(sc->fw_diag_dmat); 1538 } 1539 1540 return (status); 1541 } 1542 1543 static int 1544 mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query, 1545 uint32_t *return_code) 1546 { 1547 mpr_fw_diagnostic_buffer_t *pBuffer; 1548 uint8_t i; 1549 uint32_t unique_id; 1550 1551 unique_id = diag_query->UniqueId; 1552 1553 /* 1554 * If ID is valid, query on ID. 1555 * If ID is invalid, query on buffer type. 1556 */ 1557 if (unique_id == MPR_FW_DIAG_INVALID_UID) { 1558 i = diag_query->BufferType; 1559 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) { 1560 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1561 return (MPR_DIAG_FAILURE); 1562 } 1563 } else { 1564 i = mpr_get_fw_diag_buffer_number(sc, unique_id); 1565 if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) { 1566 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1567 return (MPR_DIAG_FAILURE); 1568 } 1569 } 1570 1571 /* 1572 * Fill query structure with the diag buffer info. 1573 */ 1574 pBuffer = &sc->fw_diag_buffer_list[i]; 1575 diag_query->BufferType = pBuffer->buffer_type; 1576 diag_query->ExtendedType = pBuffer->extended_type; 1577 if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) { 1578 for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4); 1579 i++) { 1580 diag_query->ProductSpecific[i] = 1581 pBuffer->product_specific[i]; 1582 } 1583 } 1584 diag_query->TotalBufferSize = pBuffer->size; 1585 diag_query->DriverAddedBufferSize = 0; 1586 diag_query->UniqueId = pBuffer->unique_id; 1587 diag_query->ApplicationFlags = 0; 1588 diag_query->DiagnosticFlags = 0; 1589 1590 /* 1591 * Set/Clear application flags 1592 */ 1593 if (pBuffer->immediate) { 1594 diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_APP_OWNED; 1595 } else { 1596 diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_APP_OWNED; 1597 } 1598 if (pBuffer->valid_data || pBuffer->owned_by_firmware) { 1599 diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_BUFFER_VALID; 1600 } else { 1601 diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_BUFFER_VALID; 1602 } 1603 if (pBuffer->owned_by_firmware) { 1604 diag_query->ApplicationFlags |= 1605 MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS; 1606 } else { 1607 diag_query->ApplicationFlags &= 1608 ~MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS; 1609 } 1610 1611 return (MPR_DIAG_SUCCESS); 1612 } 1613 1614 static int 1615 mpr_diag_read_buffer(struct mpr_softc *sc, 1616 mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf, 1617 uint32_t *return_code) 1618 { 1619 mpr_fw_diagnostic_buffer_t *pBuffer; 1620 uint8_t i, *pData; 1621 uint32_t unique_id; 1622 int status; 1623 1624 unique_id = diag_read_buffer->UniqueId; 1625 1626 /* 1627 * Get the current buffer and look up the unique ID. The unique ID 1628 * should be there. 1629 */ 1630 i = mpr_get_fw_diag_buffer_number(sc, unique_id); 1631 if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) { 1632 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1633 return (MPR_DIAG_FAILURE); 1634 } 1635 1636 pBuffer = &sc->fw_diag_buffer_list[i]; 1637 1638 /* 1639 * Make sure requested read is within limits 1640 */ 1641 if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead > 1642 pBuffer->size) { 1643 *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1644 return (MPR_DIAG_FAILURE); 1645 } 1646 1647 /* 1648 * Copy the requested data from DMA to the diag_read_buffer. The DMA 1649 * buffer that was allocated is one contiguous buffer. 1650 */ 1651 pData = (uint8_t *)(sc->fw_diag_buffer + 1652 diag_read_buffer->StartingOffset); 1653 if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0) 1654 return (MPR_DIAG_FAILURE); 1655 diag_read_buffer->Status = 0; 1656 1657 /* 1658 * Set or clear the Force Release flag. 1659 */ 1660 if (pBuffer->force_release) { 1661 diag_read_buffer->Flags |= MPR_FW_DIAG_FLAG_FORCE_RELEASE; 1662 } else { 1663 diag_read_buffer->Flags &= ~MPR_FW_DIAG_FLAG_FORCE_RELEASE; 1664 } 1665 1666 /* 1667 * If buffer is to be reregistered, make sure it's not already owned by 1668 * firmware first. 1669 */ 1670 status = MPR_DIAG_SUCCESS; 1671 if (!pBuffer->owned_by_firmware) { 1672 if (diag_read_buffer->Flags & MPR_FW_DIAG_FLAG_REREGISTER) { 1673 status = mpr_post_fw_diag_buffer(sc, pBuffer, 1674 return_code); 1675 } 1676 } 1677 1678 return (status); 1679 } 1680 1681 static int 1682 mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release, 1683 uint32_t *return_code) 1684 { 1685 mpr_fw_diagnostic_buffer_t *pBuffer; 1686 uint8_t i; 1687 uint32_t unique_id; 1688 int status; 1689 1690 unique_id = diag_release->UniqueId; 1691 1692 /* 1693 * Get the current buffer and look up the unique ID. The unique ID 1694 * should be there. 1695 */ 1696 i = mpr_get_fw_diag_buffer_number(sc, unique_id); 1697 if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) { 1698 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID; 1699 return (MPR_DIAG_FAILURE); 1700 } 1701 1702 pBuffer = &sc->fw_diag_buffer_list[i]; 1703 1704 /* 1705 * If buffer is not owned by firmware, it's already been released. 1706 */ 1707 if (!pBuffer->owned_by_firmware) { 1708 *return_code = MPR_FW_DIAG_ERROR_ALREADY_RELEASED; 1709 return (MPR_DIAG_FAILURE); 1710 } 1711 1712 /* 1713 * Release the buffer. 1714 */ 1715 status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code, 1716 MPR_FW_DIAG_TYPE_RELEASE); 1717 return (status); 1718 } 1719 1720 static int 1721 mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, 1722 uint8_t *diag_action, uint32_t length, uint32_t *return_code) 1723 { 1724 mpr_fw_diag_register_t diag_register; 1725 mpr_fw_diag_unregister_t diag_unregister; 1726 mpr_fw_diag_query_t diag_query; 1727 mpr_diag_read_buffer_t diag_read_buffer; 1728 mpr_fw_diag_release_t diag_release; 1729 int status = MPR_DIAG_SUCCESS; 1730 uint32_t original_return_code; 1731 1732 original_return_code = *return_code; 1733 *return_code = MPR_FW_DIAG_ERROR_SUCCESS; 1734 1735 switch (action) { 1736 case MPR_FW_DIAG_TYPE_REGISTER: 1737 if (!length) { 1738 *return_code = 1739 MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1740 status = MPR_DIAG_FAILURE; 1741 break; 1742 } 1743 if (copyin(diag_action, &diag_register, 1744 sizeof(diag_register)) != 0) 1745 return (MPR_DIAG_FAILURE); 1746 status = mpr_diag_register(sc, &diag_register, 1747 return_code); 1748 break; 1749 1750 case MPR_FW_DIAG_TYPE_UNREGISTER: 1751 if (length < sizeof(diag_unregister)) { 1752 *return_code = 1753 MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1754 status = MPR_DIAG_FAILURE; 1755 break; 1756 } 1757 if (copyin(diag_action, &diag_unregister, 1758 sizeof(diag_unregister)) != 0) 1759 return (MPR_DIAG_FAILURE); 1760 status = mpr_diag_unregister(sc, &diag_unregister, 1761 return_code); 1762 break; 1763 1764 case MPR_FW_DIAG_TYPE_QUERY: 1765 if (length < sizeof (diag_query)) { 1766 *return_code = 1767 MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1768 status = MPR_DIAG_FAILURE; 1769 break; 1770 } 1771 if (copyin(diag_action, &diag_query, sizeof(diag_query)) 1772 != 0) 1773 return (MPR_DIAG_FAILURE); 1774 status = mpr_diag_query(sc, &diag_query, return_code); 1775 if (status == MPR_DIAG_SUCCESS) 1776 if (copyout(&diag_query, diag_action, 1777 sizeof (diag_query)) != 0) 1778 return (MPR_DIAG_FAILURE); 1779 break; 1780 1781 case MPR_FW_DIAG_TYPE_READ_BUFFER: 1782 if (copyin(diag_action, &diag_read_buffer, 1783 sizeof(diag_read_buffer)) != 0) 1784 return (MPR_DIAG_FAILURE); 1785 if (length < diag_read_buffer.BytesToRead) { 1786 *return_code = 1787 MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1788 status = MPR_DIAG_FAILURE; 1789 break; 1790 } 1791 status = mpr_diag_read_buffer(sc, &diag_read_buffer, 1792 PTRIN(diag_read_buffer.PtrDataBuffer), 1793 return_code); 1794 if (status == MPR_DIAG_SUCCESS) { 1795 if (copyout(&diag_read_buffer, diag_action, 1796 sizeof(diag_read_buffer) - 1797 sizeof(diag_read_buffer.PtrDataBuffer)) != 1798 0) 1799 return (MPR_DIAG_FAILURE); 1800 } 1801 break; 1802 1803 case MPR_FW_DIAG_TYPE_RELEASE: 1804 if (length < sizeof(diag_release)) { 1805 *return_code = 1806 MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1807 status = MPR_DIAG_FAILURE; 1808 break; 1809 } 1810 if (copyin(diag_action, &diag_release, 1811 sizeof(diag_release)) != 0) 1812 return (MPR_DIAG_FAILURE); 1813 status = mpr_diag_release(sc, &diag_release, 1814 return_code); 1815 break; 1816 1817 default: 1818 *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER; 1819 status = MPR_DIAG_FAILURE; 1820 break; 1821 } 1822 1823 if ((status == MPR_DIAG_FAILURE) && 1824 (original_return_code == MPR_FW_DIAG_NEW) && 1825 (*return_code != MPR_FW_DIAG_ERROR_SUCCESS)) 1826 status = MPR_DIAG_SUCCESS; 1827 1828 return (status); 1829 } 1830 1831 static int 1832 mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data) 1833 { 1834 int status; 1835 1836 /* 1837 * Only allow one diag action at one time. 1838 */ 1839 if (sc->mpr_flags & MPR_FLAGS_BUSY) { 1840 mpr_dprint(sc, MPR_USER, "%s: Only one FW diag command " 1841 "allowed at a single time.", __func__); 1842 return (EBUSY); 1843 } 1844 sc->mpr_flags |= MPR_FLAGS_BUSY; 1845 1846 /* 1847 * Send diag action request 1848 */ 1849 if (data->Action == MPR_FW_DIAG_TYPE_REGISTER || 1850 data->Action == MPR_FW_DIAG_TYPE_UNREGISTER || 1851 data->Action == MPR_FW_DIAG_TYPE_QUERY || 1852 data->Action == MPR_FW_DIAG_TYPE_READ_BUFFER || 1853 data->Action == MPR_FW_DIAG_TYPE_RELEASE) { 1854 status = mpr_do_diag_action(sc, data->Action, 1855 PTRIN(data->PtrDiagAction), data->Length, 1856 &data->ReturnCode); 1857 } else 1858 status = EINVAL; 1859 1860 sc->mpr_flags &= ~MPR_FLAGS_BUSY; 1861 return (status); 1862 } 1863 1864 /* 1865 * Copy the event recording mask and the event queue size out. For 1866 * clarification, the event recording mask (events_to_record) is not the same 1867 * thing as the event mask (event_mask). events_to_record has a bit set for 1868 * every event type that is to be recorded by the driver, and event_mask has a 1869 * bit cleared for every event that is allowed into the driver from the IOC. 1870 * They really have nothing to do with each other. 1871 */ 1872 static void 1873 mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data) 1874 { 1875 uint8_t i; 1876 1877 mpr_lock(sc); 1878 data->Entries = MPR_EVENT_QUEUE_SIZE; 1879 1880 for (i = 0; i < 4; i++) { 1881 data->Types[i] = sc->events_to_record[i]; 1882 } 1883 mpr_unlock(sc); 1884 } 1885 1886 /* 1887 * Set the driver's event mask according to what's been given. See 1888 * mpr_user_event_query for explanation of the event recording mask and the IOC 1889 * event mask. It's the app's responsibility to enable event logging by setting 1890 * the bits in events_to_record. Initially, no events will be logged. 1891 */ 1892 static void 1893 mpr_user_event_enable(struct mpr_softc *sc, mpr_event_enable_t *data) 1894 { 1895 uint8_t i; 1896 1897 mpr_lock(sc); 1898 for (i = 0; i < 4; i++) { 1899 sc->events_to_record[i] = data->Types[i]; 1900 } 1901 mpr_unlock(sc); 1902 } 1903 1904 /* 1905 * Copy out the events that have been recorded, up to the max events allowed. 1906 */ 1907 static int 1908 mpr_user_event_report(struct mpr_softc *sc, mpr_event_report_t *data) 1909 { 1910 int status = 0; 1911 uint32_t size; 1912 1913 mpr_lock(sc); 1914 size = data->Size; 1915 if ((size >= sizeof(sc->recorded_events)) && (status == 0)) { 1916 mpr_unlock(sc); 1917 if (copyout((void *)sc->recorded_events, 1918 PTRIN(data->PtrEvents), size) != 0) 1919 status = EFAULT; 1920 mpr_lock(sc); 1921 } else { 1922 /* 1923 * data->Size value is not large enough to copy event data. 1924 */ 1925 status = EFAULT; 1926 } 1927 1928 /* 1929 * Change size value to match the number of bytes that were copied. 1930 */ 1931 if (status == 0) 1932 data->Size = sizeof(sc->recorded_events); 1933 mpr_unlock(sc); 1934 1935 return (status); 1936 } 1937 1938 /* 1939 * Record events into the driver from the IOC if they are not masked. 1940 */ 1941 void 1942 mprsas_record_event(struct mpr_softc *sc, 1943 MPI2_EVENT_NOTIFICATION_REPLY *event_reply) 1944 { 1945 uint32_t event; 1946 int i, j; 1947 uint16_t event_data_len; 1948 boolean_t sendAEN = FALSE; 1949 1950 event = event_reply->Event; 1951 1952 /* 1953 * Generate a system event to let anyone who cares know that a 1954 * LOG_ENTRY_ADDED event has occurred. This is sent no matter what the 1955 * event mask is set to. 1956 */ 1957 if (event == MPI2_EVENT_LOG_ENTRY_ADDED) { 1958 sendAEN = TRUE; 1959 } 1960 1961 /* 1962 * Record the event only if its corresponding bit is set in 1963 * events_to_record. event_index is the index into recorded_events and 1964 * event_number is the overall number of an event being recorded since 1965 * start-of-day. event_index will roll over; event_number will never 1966 * roll over. 1967 */ 1968 i = (uint8_t)(event / 32); 1969 j = (uint8_t)(event % 32); 1970 if ((i < 4) && ((1 << j) & sc->events_to_record[i])) { 1971 i = sc->event_index; 1972 sc->recorded_events[i].Type = event; 1973 sc->recorded_events[i].Number = ++sc->event_number; 1974 bzero(sc->recorded_events[i].Data, MPR_MAX_EVENT_DATA_LENGTH * 1975 4); 1976 event_data_len = event_reply->EventDataLength; 1977 1978 if (event_data_len > 0) { 1979 /* 1980 * Limit data to size in m_event entry 1981 */ 1982 if (event_data_len > MPR_MAX_EVENT_DATA_LENGTH) { 1983 event_data_len = MPR_MAX_EVENT_DATA_LENGTH; 1984 } 1985 for (j = 0; j < event_data_len; j++) { 1986 sc->recorded_events[i].Data[j] = 1987 event_reply->EventData[j]; 1988 } 1989 1990 /* 1991 * check for index wrap-around 1992 */ 1993 if (++i == MPR_EVENT_QUEUE_SIZE) { 1994 i = 0; 1995 } 1996 sc->event_index = (uint8_t)i; 1997 1998 /* 1999 * Set flag to send the event. 2000 */ 2001 sendAEN = TRUE; 2002 } 2003 } 2004 2005 /* 2006 * Generate a system event if flag is set to let anyone who cares know 2007 * that an event has occurred. 2008 */ 2009 if (sendAEN) { 2010 //SLM-how to send a system event (see kqueue, kevent) 2011 // (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS", 2012 // "SAS", NULL, NULL, DDI_NOSLEEP); 2013 } 2014 } 2015 2016 static int 2017 mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data) 2018 { 2019 int status = 0; 2020 2021 switch (data->Command) { 2022 /* 2023 * IO access is not supported. 2024 */ 2025 case REG_IO_READ: 2026 case REG_IO_WRITE: 2027 mpr_dprint(sc, MPR_USER, "IO access is not supported. " 2028 "Use memory access."); 2029 status = EINVAL; 2030 break; 2031 2032 case REG_MEM_READ: 2033 data->RegData = mpr_regread(sc, data->RegOffset); 2034 break; 2035 2036 case REG_MEM_WRITE: 2037 mpr_regwrite(sc, data->RegOffset, data->RegData); 2038 break; 2039 2040 default: 2041 status = EINVAL; 2042 break; 2043 } 2044 2045 return (status); 2046 } 2047 2048 static int 2049 mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data) 2050 { 2051 uint8_t bt2dh = FALSE; 2052 uint8_t dh2bt = FALSE; 2053 uint16_t dev_handle, bus, target; 2054 2055 bus = data->Bus; 2056 target = data->TargetID; 2057 dev_handle = data->DevHandle; 2058 2059 /* 2060 * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/ 2061 * Target to get DevHandle. When Bus/Target are 0xFFFF and DevHandle is 2062 * not 0xFFFF, use DevHandle to get Bus/Target. Anything else is 2063 * invalid. 2064 */ 2065 if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF)) 2066 dh2bt = TRUE; 2067 if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF)) 2068 bt2dh = TRUE; 2069 if (!dh2bt && !bt2dh) 2070 return (EINVAL); 2071 2072 /* 2073 * Only handle bus of 0. Make sure target is within range. 2074 */ 2075 if (bt2dh) { 2076 if (bus != 0) 2077 return (EINVAL); 2078 2079 if (target > sc->max_devices) { 2080 mpr_dprint(sc, MPR_FAULT, "Target ID is out of range " 2081 "for Bus/Target to DevHandle mapping."); 2082 return (EINVAL); 2083 } 2084 dev_handle = sc->mapping_table[target].dev_handle; 2085 if (dev_handle) 2086 data->DevHandle = dev_handle; 2087 } else { 2088 bus = 0; 2089 target = mpr_mapping_get_sas_id_from_handle(sc, dev_handle); 2090 data->Bus = bus; 2091 data->TargetID = target; 2092 } 2093 2094 return (0); 2095 } 2096 2097 static int 2098 mpr_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag, 2099 struct thread *td) 2100 { 2101 struct mpr_softc *sc; 2102 struct mpr_cfg_page_req *page_req; 2103 struct mpr_ext_cfg_page_req *ext_page_req; 2104 void *mpr_page; 2105 int error, msleep_ret; 2106 2107 mpr_page = NULL; 2108 sc = dev->si_drv1; 2109 page_req = (void *)arg; 2110 ext_page_req = (void *)arg; 2111 2112 switch (cmd) { 2113 case MPRIO_READ_CFG_HEADER: 2114 mpr_lock(sc); 2115 error = mpr_user_read_cfg_header(sc, page_req); 2116 mpr_unlock(sc); 2117 break; 2118 case MPRIO_READ_CFG_PAGE: 2119 mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK | M_ZERO); 2120 if (!mpr_page) { 2121 mpr_printf(sc, "Cannot allocate memory %s %d\n", 2122 __func__, __LINE__); 2123 return (ENOMEM); 2124 } 2125 error = copyin(page_req->buf, mpr_page, 2126 sizeof(MPI2_CONFIG_PAGE_HEADER)); 2127 if (error) 2128 break; 2129 mpr_lock(sc); 2130 error = mpr_user_read_cfg_page(sc, page_req, mpr_page); 2131 mpr_unlock(sc); 2132 if (error) 2133 break; 2134 error = copyout(mpr_page, page_req->buf, page_req->len); 2135 break; 2136 case MPRIO_READ_EXT_CFG_HEADER: 2137 mpr_lock(sc); 2138 error = mpr_user_read_extcfg_header(sc, ext_page_req); 2139 mpr_unlock(sc); 2140 break; 2141 case MPRIO_READ_EXT_CFG_PAGE: 2142 mpr_page = malloc(ext_page_req->len, M_MPRUSER, 2143 M_WAITOK | M_ZERO); 2144 if (!mpr_page) { 2145 mpr_printf(sc, "Cannot allocate memory %s %d\n", 2146 __func__, __LINE__); 2147 return (ENOMEM); 2148 } 2149 error = copyin(ext_page_req->buf, mpr_page, 2150 sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)); 2151 if (error) 2152 break; 2153 mpr_lock(sc); 2154 error = mpr_user_read_extcfg_page(sc, ext_page_req, mpr_page); 2155 mpr_unlock(sc); 2156 if (error) 2157 break; 2158 error = copyout(mpr_page, ext_page_req->buf, ext_page_req->len); 2159 break; 2160 case MPRIO_WRITE_CFG_PAGE: 2161 mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK|M_ZERO); 2162 if (!mpr_page) { 2163 mpr_printf(sc, "Cannot allocate memory %s %d\n", 2164 __func__, __LINE__); 2165 return (ENOMEM); 2166 } 2167 error = copyin(page_req->buf, mpr_page, page_req->len); 2168 if (error) 2169 break; 2170 mpr_lock(sc); 2171 error = mpr_user_write_cfg_page(sc, page_req, mpr_page); 2172 mpr_unlock(sc); 2173 break; 2174 case MPRIO_MPR_COMMAND: 2175 error = mpr_user_command(sc, (struct mpr_usr_command *)arg); 2176 break; 2177 case MPTIOCTL_PASS_THRU: 2178 /* 2179 * The user has requested to pass through a command to be 2180 * executed by the MPT firmware. Call our routine which does 2181 * this. Only allow one passthru IOCTL at one time. 2182 */ 2183 error = mpr_user_pass_thru(sc, (mpr_pass_thru_t *)arg); 2184 break; 2185 case MPTIOCTL_GET_ADAPTER_DATA: 2186 /* 2187 * The user has requested to read adapter data. Call our 2188 * routine which does this. 2189 */ 2190 error = 0; 2191 mpr_user_get_adapter_data(sc, (mpr_adapter_data_t *)arg); 2192 break; 2193 case MPTIOCTL_GET_PCI_INFO: 2194 /* 2195 * The user has requested to read pci info. Call 2196 * our routine which does this. 2197 */ 2198 mpr_lock(sc); 2199 error = 0; 2200 mpr_user_read_pci_info(sc, (mpr_pci_info_t *)arg); 2201 mpr_unlock(sc); 2202 break; 2203 case MPTIOCTL_RESET_ADAPTER: 2204 mpr_lock(sc); 2205 sc->port_enable_complete = 0; 2206 uint32_t reinit_start = time_uptime; 2207 error = mpr_reinit(sc); 2208 /* Sleep for 300 second. */ 2209 msleep_ret = msleep(&sc->port_enable_complete, &sc->mpr_mtx, 2210 PRIBIO, "mpr_porten", 300 * hz); 2211 mpr_unlock(sc); 2212 if (msleep_ret) 2213 printf("Port Enable did not complete after Diag " 2214 "Reset msleep error %d.\n", msleep_ret); 2215 else 2216 mpr_dprint(sc, MPR_USER, "Hard Reset with Port Enable " 2217 "completed in %d seconds.\n", 2218 (uint32_t)(time_uptime - reinit_start)); 2219 break; 2220 case MPTIOCTL_DIAG_ACTION: 2221 /* 2222 * The user has done a diag buffer action. Call our routine 2223 * which does this. Only allow one diag action at one time. 2224 */ 2225 mpr_lock(sc); 2226 error = mpr_user_diag_action(sc, (mpr_diag_action_t *)arg); 2227 mpr_unlock(sc); 2228 break; 2229 case MPTIOCTL_EVENT_QUERY: 2230 /* 2231 * The user has done an event query. Call our routine which does 2232 * this. 2233 */ 2234 error = 0; 2235 mpr_user_event_query(sc, (mpr_event_query_t *)arg); 2236 break; 2237 case MPTIOCTL_EVENT_ENABLE: 2238 /* 2239 * The user has done an event enable. Call our routine which 2240 * does this. 2241 */ 2242 error = 0; 2243 mpr_user_event_enable(sc, (mpr_event_enable_t *)arg); 2244 break; 2245 case MPTIOCTL_EVENT_REPORT: 2246 /* 2247 * The user has done an event report. Call our routine which 2248 * does this. 2249 */ 2250 error = mpr_user_event_report(sc, (mpr_event_report_t *)arg); 2251 break; 2252 case MPTIOCTL_REG_ACCESS: 2253 /* 2254 * The user has requested register access. Call our routine 2255 * which does this. 2256 */ 2257 mpr_lock(sc); 2258 error = mpr_user_reg_access(sc, (mpr_reg_access_t *)arg); 2259 mpr_unlock(sc); 2260 break; 2261 case MPTIOCTL_BTDH_MAPPING: 2262 /* 2263 * The user has requested to translate a bus/target to a 2264 * DevHandle or a DevHandle to a bus/target. Call our routine 2265 * which does this. 2266 */ 2267 error = mpr_user_btdh(sc, (mpr_btdh_mapping_t *)arg); 2268 break; 2269 default: 2270 error = ENOIOCTL; 2271 break; 2272 } 2273 2274 if (mpr_page != NULL) 2275 free(mpr_page, M_MPRUSER); 2276 2277 return (error); 2278 } 2279 2280 #ifdef COMPAT_FREEBSD32 2281 2282 struct mpr_cfg_page_req32 { 2283 MPI2_CONFIG_PAGE_HEADER header; 2284 uint32_t page_address; 2285 uint32_t buf; 2286 int len; 2287 uint16_t ioc_status; 2288 }; 2289 2290 struct mpr_ext_cfg_page_req32 { 2291 MPI2_CONFIG_EXTENDED_PAGE_HEADER header; 2292 uint32_t page_address; 2293 uint32_t buf; 2294 int len; 2295 uint16_t ioc_status; 2296 }; 2297 2298 struct mpr_raid_action32 { 2299 uint8_t action; 2300 uint8_t volume_bus; 2301 uint8_t volume_id; 2302 uint8_t phys_disk_num; 2303 uint32_t action_data_word; 2304 uint32_t buf; 2305 int len; 2306 uint32_t volume_status; 2307 uint32_t action_data[4]; 2308 uint16_t action_status; 2309 uint16_t ioc_status; 2310 uint8_t write; 2311 }; 2312 2313 struct mpr_usr_command32 { 2314 uint32_t req; 2315 uint32_t req_len; 2316 uint32_t rpl; 2317 uint32_t rpl_len; 2318 uint32_t buf; 2319 int len; 2320 uint32_t flags; 2321 }; 2322 2323 #define MPRIO_READ_CFG_HEADER32 _IOWR('M', 200, struct mpr_cfg_page_req32) 2324 #define MPRIO_READ_CFG_PAGE32 _IOWR('M', 201, struct mpr_cfg_page_req32) 2325 #define MPRIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mpr_ext_cfg_page_req32) 2326 #define MPRIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mpr_ext_cfg_page_req32) 2327 #define MPRIO_WRITE_CFG_PAGE32 _IOWR('M', 204, struct mpr_cfg_page_req32) 2328 #define MPRIO_RAID_ACTION32 _IOWR('M', 205, struct mpr_raid_action32) 2329 #define MPRIO_MPR_COMMAND32 _IOWR('M', 210, struct mpr_usr_command32) 2330 2331 static int 2332 mpr_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag, 2333 struct thread *td) 2334 { 2335 struct mpr_cfg_page_req32 *page32 = _arg; 2336 struct mpr_ext_cfg_page_req32 *ext32 = _arg; 2337 struct mpr_raid_action32 *raid32 = _arg; 2338 struct mpr_usr_command32 *user32 = _arg; 2339 union { 2340 struct mpr_cfg_page_req page; 2341 struct mpr_ext_cfg_page_req ext; 2342 struct mpr_raid_action raid; 2343 struct mpr_usr_command user; 2344 } arg; 2345 u_long cmd; 2346 int error; 2347 2348 switch (cmd32) { 2349 case MPRIO_READ_CFG_HEADER32: 2350 case MPRIO_READ_CFG_PAGE32: 2351 case MPRIO_WRITE_CFG_PAGE32: 2352 if (cmd32 == MPRIO_READ_CFG_HEADER32) 2353 cmd = MPRIO_READ_CFG_HEADER; 2354 else if (cmd32 == MPRIO_READ_CFG_PAGE32) 2355 cmd = MPRIO_READ_CFG_PAGE; 2356 else 2357 cmd = MPRIO_WRITE_CFG_PAGE; 2358 CP(*page32, arg.page, header); 2359 CP(*page32, arg.page, page_address); 2360 PTRIN_CP(*page32, arg.page, buf); 2361 CP(*page32, arg.page, len); 2362 CP(*page32, arg.page, ioc_status); 2363 break; 2364 2365 case MPRIO_READ_EXT_CFG_HEADER32: 2366 case MPRIO_READ_EXT_CFG_PAGE32: 2367 if (cmd32 == MPRIO_READ_EXT_CFG_HEADER32) 2368 cmd = MPRIO_READ_EXT_CFG_HEADER; 2369 else 2370 cmd = MPRIO_READ_EXT_CFG_PAGE; 2371 CP(*ext32, arg.ext, header); 2372 CP(*ext32, arg.ext, page_address); 2373 PTRIN_CP(*ext32, arg.ext, buf); 2374 CP(*ext32, arg.ext, len); 2375 CP(*ext32, arg.ext, ioc_status); 2376 break; 2377 2378 case MPRIO_RAID_ACTION32: 2379 cmd = MPRIO_RAID_ACTION; 2380 CP(*raid32, arg.raid, action); 2381 CP(*raid32, arg.raid, volume_bus); 2382 CP(*raid32, arg.raid, volume_id); 2383 CP(*raid32, arg.raid, phys_disk_num); 2384 CP(*raid32, arg.raid, action_data_word); 2385 PTRIN_CP(*raid32, arg.raid, buf); 2386 CP(*raid32, arg.raid, len); 2387 CP(*raid32, arg.raid, volume_status); 2388 bcopy(raid32->action_data, arg.raid.action_data, 2389 sizeof arg.raid.action_data); 2390 CP(*raid32, arg.raid, ioc_status); 2391 CP(*raid32, arg.raid, write); 2392 break; 2393 2394 case MPRIO_MPR_COMMAND32: 2395 cmd = MPRIO_MPR_COMMAND; 2396 PTRIN_CP(*user32, arg.user, req); 2397 CP(*user32, arg.user, req_len); 2398 PTRIN_CP(*user32, arg.user, rpl); 2399 CP(*user32, arg.user, rpl_len); 2400 PTRIN_CP(*user32, arg.user, buf); 2401 CP(*user32, arg.user, len); 2402 CP(*user32, arg.user, flags); 2403 break; 2404 default: 2405 return (ENOIOCTL); 2406 } 2407 2408 error = mpr_ioctl(dev, cmd, &arg, flag, td); 2409 if (error == 0 && (cmd32 & IOC_OUT) != 0) { 2410 switch (cmd32) { 2411 case MPRIO_READ_CFG_HEADER32: 2412 case MPRIO_READ_CFG_PAGE32: 2413 case MPRIO_WRITE_CFG_PAGE32: 2414 CP(arg.page, *page32, header); 2415 CP(arg.page, *page32, page_address); 2416 PTROUT_CP(arg.page, *page32, buf); 2417 CP(arg.page, *page32, len); 2418 CP(arg.page, *page32, ioc_status); 2419 break; 2420 2421 case MPRIO_READ_EXT_CFG_HEADER32: 2422 case MPRIO_READ_EXT_CFG_PAGE32: 2423 CP(arg.ext, *ext32, header); 2424 CP(arg.ext, *ext32, page_address); 2425 PTROUT_CP(arg.ext, *ext32, buf); 2426 CP(arg.ext, *ext32, len); 2427 CP(arg.ext, *ext32, ioc_status); 2428 break; 2429 2430 case MPRIO_RAID_ACTION32: 2431 CP(arg.raid, *raid32, action); 2432 CP(arg.raid, *raid32, volume_bus); 2433 CP(arg.raid, *raid32, volume_id); 2434 CP(arg.raid, *raid32, phys_disk_num); 2435 CP(arg.raid, *raid32, action_data_word); 2436 PTROUT_CP(arg.raid, *raid32, buf); 2437 CP(arg.raid, *raid32, len); 2438 CP(arg.raid, *raid32, volume_status); 2439 bcopy(arg.raid.action_data, raid32->action_data, 2440 sizeof arg.raid.action_data); 2441 CP(arg.raid, *raid32, ioc_status); 2442 CP(arg.raid, *raid32, write); 2443 break; 2444 2445 case MPRIO_MPR_COMMAND32: 2446 PTROUT_CP(arg.user, *user32, req); 2447 CP(arg.user, *user32, req_len); 2448 PTROUT_CP(arg.user, *user32, rpl); 2449 CP(arg.user, *user32, rpl_len); 2450 PTROUT_CP(arg.user, *user32, buf); 2451 CP(arg.user, *user32, len); 2452 CP(arg.user, *user32, flags); 2453 break; 2454 } 2455 } 2456 2457 return (error); 2458 } 2459 #endif /* COMPAT_FREEBSD32 */ 2460 2461 static int 2462 mpr_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag, 2463 struct thread *td) 2464 { 2465 #ifdef COMPAT_FREEBSD32 2466 if (SV_CURPROC_FLAG(SV_ILP32)) 2467 return (mpr_ioctl32(dev, com, arg, flag, td)); 2468 #endif 2469 return (mpr_ioctl(dev, com, arg, flag, td)); 2470 } 2471