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