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