scsi_ctl.c revision 314737
1/*- 2 * Copyright (c) 2008, 2009 Silicon Graphics International Corp. 3 * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer, 11 * without modification. 12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13 * substantially similar to the "NO WARRANTY" disclaimer below 14 * ("Disclaimer") and any redistribution must be conditioned upon 15 * including a substantially similar Disclaimer requirement for further 16 * binary redistribution. 17 * 18 * NO WARRANTY 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGES. 30 * 31 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/scsi_ctl.c#4 $ 32 */ 33/* 34 * Peripheral driver interface between CAM and CTL (CAM Target Layer). 35 * 36 * Author: Ken Merry <ken@FreeBSD.org> 37 */ 38 39#include <sys/cdefs.h> 40__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/scsi_ctl.c 314737 2017-03-06 06:24:53Z mav $"); 41 42#include <sys/param.h> 43#include <sys/queue.h> 44#include <sys/systm.h> 45#include <sys/kernel.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> 48#include <sys/condvar.h> 49#include <sys/malloc.h> 50#include <sys/bus.h> 51#include <sys/endian.h> 52#include <sys/sbuf.h> 53#include <sys/sysctl.h> 54#include <sys/types.h> 55#include <sys/systm.h> 56#include <machine/bus.h> 57 58#include <cam/cam.h> 59#include <cam/cam_ccb.h> 60#include <cam/cam_periph.h> 61#include <cam/cam_queue.h> 62#include <cam/cam_xpt_periph.h> 63#include <cam/cam_debug.h> 64#include <cam/cam_sim.h> 65#include <cam/cam_xpt.h> 66 67#include <cam/scsi/scsi_all.h> 68#include <cam/scsi/scsi_message.h> 69 70#include <cam/ctl/ctl_io.h> 71#include <cam/ctl/ctl.h> 72#include <cam/ctl/ctl_frontend.h> 73#include <cam/ctl/ctl_util.h> 74#include <cam/ctl/ctl_error.h> 75 76struct ctlfe_softc { 77 struct ctl_port port; 78 path_id_t path_id; 79 target_id_t target_id; 80 uint32_t hba_misc; 81 u_int maxio; 82 struct cam_sim *sim; 83 char port_name[DEV_IDLEN]; 84 struct mtx lun_softc_mtx; 85 STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list; 86 STAILQ_ENTRY(ctlfe_softc) links; 87}; 88 89STAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list; 90struct mtx ctlfe_list_mtx; 91static char ctlfe_mtx_desc[] = "ctlfelist"; 92#ifdef CTLFE_INIT_ENABLE 93static int ctlfe_max_targets = 1; 94static int ctlfe_num_targets = 0; 95#endif 96 97typedef enum { 98 CTLFE_LUN_NONE = 0x00, 99 CTLFE_LUN_WILDCARD = 0x01 100} ctlfe_lun_flags; 101 102struct ctlfe_lun_softc { 103 struct ctlfe_softc *parent_softc; 104 struct cam_periph *periph; 105 ctlfe_lun_flags flags; 106 uint64_t ccbs_alloced; 107 uint64_t ccbs_freed; 108 uint64_t ctios_sent; 109 uint64_t ctios_returned; 110 uint64_t atios_alloced; 111 uint64_t atios_freed; 112 uint64_t inots_alloced; 113 uint64_t inots_freed; 114 /* bus_dma_tag_t dma_tag; */ 115 TAILQ_HEAD(, ccb_hdr) work_queue; 116 STAILQ_ENTRY(ctlfe_lun_softc) links; 117}; 118 119typedef enum { 120 CTLFE_CMD_NONE = 0x00, 121 CTLFE_CMD_PIECEWISE = 0x01 122} ctlfe_cmd_flags; 123 124struct ctlfe_cmd_info { 125 int cur_transfer_index; 126 size_t cur_transfer_off; 127 ctlfe_cmd_flags flags; 128 /* 129 * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16 130 * bytes on amd64. So with 32 elements, this is 256 bytes on 131 * i386 and 512 bytes on amd64. 132 */ 133#define CTLFE_MAX_SEGS 32 134 bus_dma_segment_t cam_sglist[CTLFE_MAX_SEGS]; 135}; 136 137/* 138 * When we register the adapter/bus, request that this many ctl_ios be 139 * allocated. This should be the maximum supported by the adapter, but we 140 * currently don't have a way to get that back from the path inquiry. 141 * XXX KDM add that to the path inquiry. 142 */ 143#define CTLFE_REQ_CTL_IO 4096 144/* 145 * Number of Accept Target I/O CCBs to allocate and queue down to the 146 * adapter per LUN. 147 * XXX KDM should this be controlled by CTL? 148 */ 149#define CTLFE_ATIO_PER_LUN 1024 150/* 151 * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to 152 * allocate and queue down to the adapter per LUN. 153 * XXX KDM should this be controlled by CTL? 154 */ 155#define CTLFE_IN_PER_LUN 1024 156 157/* 158 * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending 159 * status to the initiator. The SIM is expected to have its own timeouts, 160 * so we're not putting this timeout around the CCB execution time. The 161 * SIM should timeout and let us know if it has an issue. 162 */ 163#define CTLFE_DMA_TIMEOUT 60 164 165/* 166 * Turn this on to enable extra debugging prints. 167 */ 168#if 0 169#define CTLFE_DEBUG 170#endif 171 172/* 173 * Use randomly assigned WWNN/WWPN values. This is to work around an issue 174 * in the FreeBSD initiator that makes it unable to rescan the target if 175 * the target gets rebooted and the WWNN/WWPN stay the same. 176 */ 177#if 0 178#define RANDOM_WWNN 179#endif 180 181MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface"); 182 183#define io_ptr ppriv_ptr0 184 185/* This is only used in the CTIO */ 186#define ccb_atio ppriv_ptr1 187 188#define PRIV_CCB(io) ((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptrs[0]) 189#define PRIV_INFO(io) ((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptrs[1]) 190 191static int ctlfeinitialize(void); 192static int ctlfeshutdown(void); 193static periph_init_t ctlfeperiphinit; 194static void ctlfeasync(void *callback_arg, uint32_t code, 195 struct cam_path *path, void *arg); 196static periph_ctor_t ctlferegister; 197static periph_oninv_t ctlfeoninvalidate; 198static periph_dtor_t ctlfecleanup; 199static periph_start_t ctlfestart; 200static void ctlfedone(struct cam_periph *periph, 201 union ccb *done_ccb); 202 203static void ctlfe_onoffline(void *arg, int online); 204static void ctlfe_online(void *arg); 205static void ctlfe_offline(void *arg); 206static int ctlfe_lun_enable(void *arg, int lun_id); 207static int ctlfe_lun_disable(void *arg, int lun_id); 208static void ctlfe_dump_sim(struct cam_sim *sim); 209static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc); 210static void ctlfe_datamove(union ctl_io *io); 211static void ctlfe_done(union ctl_io *io); 212static void ctlfe_dump(void); 213 214static struct periph_driver ctlfe_driver = 215{ 216 ctlfeperiphinit, "ctl", 217 TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0, 218 CAM_PERIPH_DRV_EARLY 219}; 220 221static struct ctl_frontend ctlfe_frontend = 222{ 223 .name = "camtgt", 224 .init = ctlfeinitialize, 225 .fe_dump = ctlfe_dump, 226 .shutdown = ctlfeshutdown, 227}; 228CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend); 229 230static int 231ctlfeshutdown(void) 232{ 233 234 /* CAM does not support periph driver unregister now. */ 235 return (EBUSY); 236} 237 238static int 239ctlfeinitialize(void) 240{ 241 242 STAILQ_INIT(&ctlfe_softc_list); 243 mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF); 244 periphdriver_register(&ctlfe_driver); 245 return (0); 246} 247 248static void 249ctlfeperiphinit(void) 250{ 251 cam_status status; 252 253 status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED | 254 AC_CONTRACT, ctlfeasync, NULL, NULL); 255 if (status != CAM_REQ_CMP) { 256 printf("ctl: Failed to attach async callback due to CAM " 257 "status 0x%x!\n", status); 258 } 259} 260 261static void 262ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 263{ 264 struct ctlfe_softc *softc; 265 266#ifdef CTLFEDEBUG 267 printf("%s: entered\n", __func__); 268#endif 269 270 mtx_lock(&ctlfe_list_mtx); 271 STAILQ_FOREACH(softc, &ctlfe_softc_list, links) { 272 if (softc->path_id == xpt_path_path_id(path)) 273 break; 274 } 275 mtx_unlock(&ctlfe_list_mtx); 276 277 /* 278 * When a new path gets registered, and it is capable of target 279 * mode, go ahead and attach. Later on, we may need to be more 280 * selective, but for now this will be sufficient. 281 */ 282 switch (code) { 283 case AC_PATH_REGISTERED: { 284 struct ctl_port *port; 285 struct ccb_pathinq *cpi; 286 int retval; 287 288 cpi = (struct ccb_pathinq *)arg; 289 290 /* Don't attach if it doesn't support target mode */ 291 if ((cpi->target_sprt & PIT_PROCESSOR) == 0) { 292#ifdef CTLFEDEBUG 293 printf("%s: SIM %s%d doesn't support target mode\n", 294 __func__, cpi->dev_name, cpi->unit_number); 295#endif 296 break; 297 } 298 299 if (softc != NULL) { 300#ifdef CTLFEDEBUG 301 printf("%s: CTL port for CAM path %u already exists\n", 302 __func__, xpt_path_path_id(path)); 303#endif 304 break; 305 } 306 307#ifdef CTLFE_INIT_ENABLE 308 if (ctlfe_num_targets >= ctlfe_max_targets) { 309 union ccb *ccb; 310 311 ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, 312 M_NOWAIT | M_ZERO); 313 if (ccb == NULL) { 314 printf("%s: unable to malloc CCB!\n", __func__); 315 return; 316 } 317 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE); 318 319 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB; 320 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE; 321 ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR; 322 323 xpt_action(ccb); 324 325 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != 326 CAM_REQ_CMP) { 327 printf("%s: SIM %s%d (path id %d) initiator " 328 "enable failed with status %#x\n", 329 __func__, cpi->dev_name, 330 cpi->unit_number, cpi->ccb_h.path_id, 331 ccb->ccb_h.status); 332 } else { 333 printf("%s: SIM %s%d (path id %d) initiator " 334 "enable succeeded\n", 335 __func__, cpi->dev_name, 336 cpi->unit_number, cpi->ccb_h.path_id); 337 } 338 339 free(ccb, M_TEMP); 340 341 break; 342 } else { 343 ctlfe_num_targets++; 344 } 345 346 printf("%s: ctlfe_num_targets = %d\n", __func__, 347 ctlfe_num_targets); 348#endif /* CTLFE_INIT_ENABLE */ 349 350 /* 351 * We're in an interrupt context here, so we have to 352 * use M_NOWAIT. Of course this means trouble if we 353 * can't allocate memory. 354 */ 355 softc = malloc(sizeof(*softc), M_CTLFE, M_NOWAIT | M_ZERO); 356 if (softc == NULL) { 357 printf("%s: unable to malloc %zd bytes for softc\n", 358 __func__, sizeof(*softc)); 359 return; 360 } 361 362 softc->path_id = cpi->ccb_h.path_id; 363 softc->target_id = cpi->initiator_id; 364 softc->sim = xpt_path_sim(path); 365 softc->hba_misc = cpi->hba_misc; 366 if (cpi->maxio != 0) 367 softc->maxio = cpi->maxio; 368 else 369 softc->maxio = DFLTPHYS; 370 mtx_init(&softc->lun_softc_mtx, "LUN softc mtx", NULL, MTX_DEF); 371 STAILQ_INIT(&softc->lun_softc_list); 372 373 port = &softc->port; 374 port->frontend = &ctlfe_frontend; 375 376 /* 377 * XXX KDM should we be more accurate here ? 378 */ 379 if (cpi->transport == XPORT_FC) 380 port->port_type = CTL_PORT_FC; 381 else if (cpi->transport == XPORT_SAS) 382 port->port_type = CTL_PORT_SAS; 383 else 384 port->port_type = CTL_PORT_SCSI; 385 386 /* XXX KDM what should the real number be here? */ 387 port->num_requested_ctl_io = 4096; 388 snprintf(softc->port_name, sizeof(softc->port_name), 389 "%s%d", cpi->dev_name, cpi->unit_number); 390 /* 391 * XXX KDM it would be nice to allocate storage in the 392 * frontend structure itself. 393 */ 394 port->port_name = softc->port_name; 395 port->physical_port = cpi->bus_id; 396 port->virtual_port = 0; 397 port->port_online = ctlfe_online; 398 port->port_offline = ctlfe_offline; 399 port->onoff_arg = softc; 400 port->lun_enable = ctlfe_lun_enable; 401 port->lun_disable = ctlfe_lun_disable; 402 port->targ_lun_arg = softc; 403 port->fe_datamove = ctlfe_datamove; 404 port->fe_done = ctlfe_done; 405 /* 406 * XXX KDM the path inquiry doesn't give us the maximum 407 * number of targets supported. 408 */ 409 port->max_targets = cpi->max_target; 410 port->max_target_id = cpi->max_target; 411 port->targ_port = -1; 412 413 /* 414 * XXX KDM need to figure out whether we're the master or 415 * slave. 416 */ 417#ifdef CTLFEDEBUG 418 printf("%s: calling ctl_port_register() for %s%d\n", 419 __func__, cpi->dev_name, cpi->unit_number); 420#endif 421 retval = ctl_port_register(port); 422 if (retval != 0) { 423 printf("%s: ctl_port_register() failed with " 424 "error %d!\n", __func__, retval); 425 mtx_destroy(&softc->lun_softc_mtx); 426 free(softc, M_CTLFE); 427 break; 428 } else { 429 mtx_lock(&ctlfe_list_mtx); 430 STAILQ_INSERT_TAIL(&ctlfe_softc_list, softc, links); 431 mtx_unlock(&ctlfe_list_mtx); 432 } 433 434 break; 435 } 436 case AC_PATH_DEREGISTERED: { 437 438 if (softc != NULL) { 439 /* 440 * XXX KDM are we certain at this point that there 441 * are no outstanding commands for this frontend? 442 */ 443 mtx_lock(&ctlfe_list_mtx); 444 STAILQ_REMOVE(&ctlfe_softc_list, softc, ctlfe_softc, 445 links); 446 mtx_unlock(&ctlfe_list_mtx); 447 ctl_port_deregister(&softc->port); 448 mtx_destroy(&softc->lun_softc_mtx); 449 free(softc, M_CTLFE); 450 } 451 break; 452 } 453 case AC_CONTRACT: { 454 struct ac_contract *ac; 455 456 ac = (struct ac_contract *)arg; 457 458 switch (ac->contract_number) { 459 case AC_CONTRACT_DEV_CHG: { 460 struct ac_device_changed *dev_chg; 461 int retval; 462 463 dev_chg = (struct ac_device_changed *)ac->contract_data; 464 465 printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n", 466 __func__, dev_chg->wwpn, dev_chg->port, 467 xpt_path_path_id(path), dev_chg->target, 468 (dev_chg->arrived == 0) ? "left" : "arrived"); 469 470 if (softc == NULL) { 471 printf("%s: CTL port for CAM path %u not " 472 "found!\n", __func__, 473 xpt_path_path_id(path)); 474 break; 475 } 476 if (dev_chg->arrived != 0) { 477 retval = ctl_add_initiator(&softc->port, 478 dev_chg->target, dev_chg->wwpn, NULL); 479 } else { 480 retval = ctl_remove_initiator(&softc->port, 481 dev_chg->target); 482 } 483 484 if (retval < 0) { 485 printf("%s: could not %s port %d iid %u " 486 "WWPN %#jx!\n", __func__, 487 (dev_chg->arrived != 0) ? "add" : 488 "remove", softc->port.targ_port, 489 dev_chg->target, 490 (uintmax_t)dev_chg->wwpn); 491 } 492 break; 493 } 494 default: 495 printf("%s: unsupported contract number %ju\n", 496 __func__, (uintmax_t)ac->contract_number); 497 break; 498 } 499 break; 500 } 501 default: 502 break; 503 } 504} 505 506static cam_status 507ctlferegister(struct cam_periph *periph, void *arg) 508{ 509 struct ctlfe_softc *bus_softc; 510 struct ctlfe_lun_softc *softc; 511 union ccb en_lun_ccb; 512 cam_status status; 513 int i; 514 515 softc = (struct ctlfe_lun_softc *)arg; 516 bus_softc = softc->parent_softc; 517 518 TAILQ_INIT(&softc->work_queue); 519 softc->periph = periph; 520 periph->softc = softc; 521 522 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE); 523 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN; 524 en_lun_ccb.cel.grp6_len = 0; 525 en_lun_ccb.cel.grp7_len = 0; 526 en_lun_ccb.cel.enable = 1; 527 xpt_action(&en_lun_ccb); 528 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK); 529 if (status != CAM_REQ_CMP) { 530 xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n", 531 __func__, en_lun_ccb.ccb_h.status); 532 return (status); 533 } 534 535 status = CAM_REQ_CMP; 536 537 for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) { 538 union ccb *new_ccb; 539 union ctl_io *new_io; 540 struct ctlfe_cmd_info *cmd_info; 541 542 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE, 543 M_ZERO|M_NOWAIT); 544 if (new_ccb == NULL) { 545 status = CAM_RESRC_UNAVAIL; 546 break; 547 } 548 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref); 549 if (new_io == NULL) { 550 free(new_ccb, M_CTLFE); 551 status = CAM_RESRC_UNAVAIL; 552 break; 553 } 554 cmd_info = malloc(sizeof(*cmd_info), M_CTLFE, 555 M_ZERO | M_NOWAIT); 556 if (cmd_info == NULL) { 557 ctl_free_io(new_io); 558 free(new_ccb, M_CTLFE); 559 status = CAM_RESRC_UNAVAIL; 560 break; 561 } 562 PRIV_INFO(new_io) = cmd_info; 563 softc->atios_alloced++; 564 new_ccb->ccb_h.io_ptr = new_io; 565 566 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); 567 new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO; 568 new_ccb->ccb_h.cbfcnp = ctlfedone; 569 new_ccb->ccb_h.flags |= CAM_UNLOCKED; 570 xpt_action(new_ccb); 571 status = new_ccb->ccb_h.status; 572 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 573 free(cmd_info, M_CTLFE); 574 ctl_free_io(new_io); 575 free(new_ccb, M_CTLFE); 576 break; 577 } 578 } 579 580 status = cam_periph_acquire(periph); 581 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 582 xpt_print(periph->path, "%s: could not acquire reference " 583 "count, status = %#x\n", __func__, status); 584 return (status); 585 } 586 587 if (i == 0) { 588 xpt_print(periph->path, "%s: could not allocate ATIO CCBs, " 589 "status 0x%x\n", __func__, status); 590 return (CAM_REQ_CMP_ERR); 591 } 592 593 for (i = 0; i < CTLFE_IN_PER_LUN; i++) { 594 union ccb *new_ccb; 595 union ctl_io *new_io; 596 597 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE, 598 M_ZERO|M_NOWAIT); 599 if (new_ccb == NULL) { 600 status = CAM_RESRC_UNAVAIL; 601 break; 602 } 603 new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref); 604 if (new_io == NULL) { 605 free(new_ccb, M_CTLFE); 606 status = CAM_RESRC_UNAVAIL; 607 break; 608 } 609 softc->inots_alloced++; 610 new_ccb->ccb_h.io_ptr = new_io; 611 612 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); 613 new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; 614 new_ccb->ccb_h.cbfcnp = ctlfedone; 615 new_ccb->ccb_h.flags |= CAM_UNLOCKED; 616 xpt_action(new_ccb); 617 status = new_ccb->ccb_h.status; 618 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 619 /* 620 * Note that we don't free the CCB here. If the 621 * status is not CAM_REQ_INPROG, then we're 622 * probably talking to a SIM that says it is 623 * target-capable but doesn't support the 624 * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the 625 * older API. In that case, it'll call xpt_done() 626 * on the CCB, and we need to free it in our done 627 * routine as a result. 628 */ 629 break; 630 } 631 } 632 if ((i == 0) 633 || (status != CAM_REQ_INPROG)) { 634 xpt_print(periph->path, "%s: could not allocate immediate " 635 "notify CCBs, status 0x%x\n", __func__, status); 636 return (CAM_REQ_CMP_ERR); 637 } 638 mtx_lock(&bus_softc->lun_softc_mtx); 639 STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links); 640 mtx_unlock(&bus_softc->lun_softc_mtx); 641 return (CAM_REQ_CMP); 642} 643 644static void 645ctlfeoninvalidate(struct cam_periph *periph) 646{ 647 union ccb en_lun_ccb; 648 cam_status status; 649 struct ctlfe_softc *bus_softc; 650 struct ctlfe_lun_softc *softc; 651 652 softc = (struct ctlfe_lun_softc *)periph->softc; 653 654 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE); 655 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN; 656 en_lun_ccb.cel.grp6_len = 0; 657 en_lun_ccb.cel.grp7_len = 0; 658 en_lun_ccb.cel.enable = 0; 659 xpt_action(&en_lun_ccb); 660 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK); 661 if (status != CAM_REQ_CMP) { 662 xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n", 663 __func__, en_lun_ccb.ccb_h.status); 664 /* 665 * XXX KDM what do we do now? 666 */ 667 } 668 669 bus_softc = softc->parent_softc; 670 mtx_lock(&bus_softc->lun_softc_mtx); 671 STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links); 672 mtx_unlock(&bus_softc->lun_softc_mtx); 673} 674 675static void 676ctlfecleanup(struct cam_periph *periph) 677{ 678 struct ctlfe_lun_softc *softc; 679 680 softc = (struct ctlfe_lun_softc *)periph->softc; 681 682 KASSERT(softc->ccbs_freed == softc->ccbs_alloced, ("%s: " 683 "ccbs_freed %ju != ccbs_alloced %ju", __func__, 684 softc->ccbs_freed, softc->ccbs_alloced)); 685 KASSERT(softc->ctios_returned == softc->ctios_sent, ("%s: " 686 "ctios_returned %ju != ctios_sent %ju", __func__, 687 softc->ctios_returned, softc->ctios_sent)); 688 KASSERT(softc->atios_freed == softc->atios_alloced, ("%s: " 689 "atios_freed %ju != atios_alloced %ju", __func__, 690 softc->atios_freed, softc->atios_alloced)); 691 KASSERT(softc->inots_freed == softc->inots_alloced, ("%s: " 692 "inots_freed %ju != inots_alloced %ju", __func__, 693 softc->inots_freed, softc->inots_alloced)); 694 695 free(softc, M_CTLFE); 696} 697 698static void 699ctlfedata(struct ctlfe_lun_softc *softc, union ctl_io *io, 700 ccb_flags *flags, uint8_t **data_ptr, uint32_t *dxfer_len, 701 u_int16_t *sglist_cnt) 702{ 703 struct ctlfe_softc *bus_softc; 704 struct ctlfe_cmd_info *cmd_info; 705 struct ctl_sg_entry *ctl_sglist; 706 bus_dma_segment_t *cam_sglist; 707 size_t off; 708 int i, idx; 709 710 cmd_info = PRIV_INFO(io); 711 bus_softc = softc->parent_softc; 712 713 /* 714 * Set the direction, relative to the initiator. 715 */ 716 *flags &= ~CAM_DIR_MASK; 717 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) 718 *flags |= CAM_DIR_IN; 719 else 720 *flags |= CAM_DIR_OUT; 721 722 *flags &= ~CAM_DATA_MASK; 723 idx = cmd_info->cur_transfer_index; 724 off = cmd_info->cur_transfer_off; 725 cmd_info->flags &= ~CTLFE_CMD_PIECEWISE; 726 if (io->scsiio.kern_sg_entries == 0) { /* No S/G list. */ 727 728 /* One time shift for SRR offset. */ 729 off += io->scsiio.ext_data_filled; 730 io->scsiio.ext_data_filled = 0; 731 732 *data_ptr = io->scsiio.kern_data_ptr + off; 733 if (io->scsiio.kern_data_len - off <= bus_softc->maxio) { 734 *dxfer_len = io->scsiio.kern_data_len - off; 735 } else { 736 *dxfer_len = bus_softc->maxio; 737 cmd_info->cur_transfer_off += bus_softc->maxio; 738 cmd_info->flags |= CTLFE_CMD_PIECEWISE; 739 } 740 *sglist_cnt = 0; 741 742 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) 743 *flags |= CAM_DATA_PADDR; 744 else 745 *flags |= CAM_DATA_VADDR; 746 } else { /* S/G list with physical or virtual pointers. */ 747 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 748 749 /* One time shift for SRR offset. */ 750 while (io->scsiio.ext_data_filled >= ctl_sglist[idx].len - off) { 751 io->scsiio.ext_data_filled -= ctl_sglist[idx].len - off; 752 idx++; 753 off = 0; 754 } 755 off += io->scsiio.ext_data_filled; 756 io->scsiio.ext_data_filled = 0; 757 758 cam_sglist = cmd_info->cam_sglist; 759 *dxfer_len = 0; 760 for (i = 0; i < io->scsiio.kern_sg_entries - idx; i++) { 761 cam_sglist[i].ds_addr = (bus_addr_t)ctl_sglist[i + idx].addr + off; 762 if (ctl_sglist[i + idx].len - off <= bus_softc->maxio - *dxfer_len) { 763 cam_sglist[i].ds_len = ctl_sglist[idx + i].len - off; 764 *dxfer_len += cam_sglist[i].ds_len; 765 } else { 766 cam_sglist[i].ds_len = bus_softc->maxio - *dxfer_len; 767 cmd_info->cur_transfer_index = idx + i; 768 cmd_info->cur_transfer_off = cam_sglist[i].ds_len + off; 769 cmd_info->flags |= CTLFE_CMD_PIECEWISE; 770 *dxfer_len += cam_sglist[i].ds_len; 771 if (ctl_sglist[i].len != 0) 772 i++; 773 break; 774 } 775 if (i == (CTLFE_MAX_SEGS - 1) && 776 idx + i < (io->scsiio.kern_sg_entries - 1)) { 777 cmd_info->cur_transfer_index = idx + i + 1; 778 cmd_info->cur_transfer_off = 0; 779 cmd_info->flags |= CTLFE_CMD_PIECEWISE; 780 i++; 781 break; 782 } 783 off = 0; 784 } 785 *sglist_cnt = i; 786 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) 787 *flags |= CAM_DATA_SG_PADDR; 788 else 789 *flags |= CAM_DATA_SG; 790 *data_ptr = (uint8_t *)cam_sglist; 791 } 792} 793 794static void 795ctlfestart(struct cam_periph *periph, union ccb *start_ccb) 796{ 797 struct ctlfe_lun_softc *softc; 798 struct ctlfe_cmd_info *cmd_info; 799 struct ccb_hdr *ccb_h; 800 struct ccb_accept_tio *atio; 801 struct ccb_scsiio *csio; 802 uint8_t *data_ptr; 803 uint32_t dxfer_len; 804 ccb_flags flags; 805 union ctl_io *io; 806 uint8_t scsi_status; 807 808 softc = (struct ctlfe_lun_softc *)periph->softc; 809 softc->ccbs_alloced++; 810 811 ccb_h = TAILQ_FIRST(&softc->work_queue); 812 if (ccb_h == NULL) { 813 softc->ccbs_freed++; 814 xpt_release_ccb(start_ccb); 815 return; 816 } 817 818 /* Take the ATIO off the work queue */ 819 TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe); 820 atio = (struct ccb_accept_tio *)ccb_h; 821 io = (union ctl_io *)ccb_h->io_ptr; 822 csio = &start_ccb->csio; 823 824 flags = atio->ccb_h.flags & 825 (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); 826 cmd_info = PRIV_INFO(io); 827 cmd_info->cur_transfer_index = 0; 828 cmd_info->cur_transfer_off = 0; 829 cmd_info->flags = 0; 830 831 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) { 832 /* 833 * Datamove call, we need to setup the S/G list. 834 */ 835 ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len, 836 &csio->sglist_cnt); 837 } else { 838 /* 839 * We're done, send status back. 840 */ 841 if ((io->io_hdr.flags & CTL_FLAG_ABORT) && 842 (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) { 843 io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; 844 845 /* Tell the SIM that we've aborted this ATIO */ 846#ifdef CTLFEDEBUG 847 printf("%s: tag %04x abort\n", __func__, atio->tag_id); 848#endif 849 KASSERT(atio->ccb_h.func_code == XPT_ACCEPT_TARGET_IO, 850 ("func_code %#x is not ATIO", atio->ccb_h.func_code)); 851 start_ccb->ccb_h.func_code = XPT_ABORT; 852 start_ccb->cab.abort_ccb = (union ccb *)atio; 853 xpt_action(start_ccb); 854 softc->ccbs_freed++; 855 xpt_release_ccb(start_ccb); 856 857 /* 858 * Send the ATIO back down to the SIM. 859 * For a wildcard attachment, commands can come in 860 * with a specific target/lun. Reset the target and 861 * LUN fields back to the wildcard values before we 862 * send them back down to the SIM. 863 */ 864 if (softc->flags & CTLFE_LUN_WILDCARD) { 865 atio->ccb_h.target_id = CAM_TARGET_WILDCARD; 866 atio->ccb_h.target_lun = CAM_LUN_WILDCARD; 867 } 868 xpt_action((union ccb *)atio); 869 870 /* If we still have work to do, ask for another CCB. */ 871 if (!TAILQ_EMPTY(&softc->work_queue)) 872 xpt_schedule(periph, /*priority*/ 1); 873 return; 874 } 875 data_ptr = NULL; 876 dxfer_len = 0; 877 csio->sglist_cnt = 0; 878 } 879 scsi_status = 0; 880 if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) && 881 (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 && 882 ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 || 883 io->io_hdr.status == CTL_SUCCESS)) { 884 flags |= CAM_SEND_STATUS; 885 scsi_status = io->scsiio.scsi_status; 886 csio->sense_len = io->scsiio.sense_len; 887#ifdef CTLFEDEBUG 888 printf("%s: tag %04x status %x\n", __func__, 889 atio->tag_id, io->io_hdr.status); 890#endif 891 if (csio->sense_len != 0) { 892 csio->sense_data = io->scsiio.sense_data; 893 flags |= CAM_SEND_SENSE; 894 } 895 } 896 897#ifdef CTLFEDEBUG 898 printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__, 899 (flags & CAM_SEND_STATUS) ? "done" : "datamove", 900 atio->tag_id, flags, data_ptr, dxfer_len); 901#endif 902 903 /* 904 * Valid combinations: 905 * - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0, 906 * sglist_cnt = 0 907 * - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0, 908 * sglist_cnt = 0 909 * - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0, 910 * sglist_cnt != 0 911 */ 912#ifdef CTLFEDEBUG 913 if (((flags & CAM_SEND_STATUS) 914 && (((flags & CAM_DATA_SG) != 0) 915 || (dxfer_len != 0) 916 || (csio->sglist_cnt != 0))) 917 || (((flags & CAM_SEND_STATUS) == 0) 918 && (dxfer_len == 0)) 919 || ((flags & CAM_DATA_SG) 920 && (csio->sglist_cnt == 0)) 921 || (((flags & CAM_DATA_SG) == 0) 922 && (csio->sglist_cnt != 0))) { 923 printf("%s: tag %04x cdb %02x flags %#x dxfer_len " 924 "%d sg %u\n", __func__, atio->tag_id, 925 atio_cdb_ptr(atio)[0], flags, dxfer_len, 926 csio->sglist_cnt); 927 printf("%s: tag %04x io status %#x\n", __func__, 928 atio->tag_id, io->io_hdr.status); 929 } 930#endif 931 cam_fill_ctio(csio, 932 /*retries*/ 2, 933 ctlfedone, 934 flags, 935 (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0, 936 atio->tag_id, 937 atio->init_id, 938 scsi_status, 939 /*data_ptr*/ data_ptr, 940 /*dxfer_len*/ dxfer_len, 941 /*timeout*/ 5 * 1000); 942 start_ccb->ccb_h.flags |= CAM_UNLOCKED; 943 start_ccb->ccb_h.ccb_atio = atio; 944 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) 945 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; 946 io->io_hdr.flags &= ~(CTL_FLAG_DMA_QUEUED | CTL_FLAG_STATUS_QUEUED); 947 948 softc->ctios_sent++; 949 950 cam_periph_unlock(periph); 951 xpt_action(start_ccb); 952 cam_periph_lock(periph); 953 954 /* 955 * If we still have work to do, ask for another CCB. 956 */ 957 if (!TAILQ_EMPTY(&softc->work_queue)) 958 xpt_schedule(periph, /*priority*/ 1); 959} 960 961static void 962ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb) 963{ 964 struct ctlfe_lun_softc *softc; 965 union ctl_io *io; 966 struct ctlfe_cmd_info *cmd_info; 967 968 softc = (struct ctlfe_lun_softc *)periph->softc; 969 io = ccb->ccb_h.io_ptr; 970 971 switch (ccb->ccb_h.func_code) { 972 case XPT_ACCEPT_TARGET_IO: 973 softc->atios_freed++; 974 cmd_info = PRIV_INFO(io); 975 free(cmd_info, M_CTLFE); 976 break; 977 case XPT_IMMEDIATE_NOTIFY: 978 case XPT_NOTIFY_ACKNOWLEDGE: 979 softc->inots_freed++; 980 break; 981 default: 982 break; 983 } 984 985 ctl_free_io(io); 986 free(ccb, M_CTLFE); 987 988 KASSERT(softc->atios_freed <= softc->atios_alloced, ("%s: " 989 "atios_freed %ju > atios_alloced %ju", __func__, 990 softc->atios_freed, softc->atios_alloced)); 991 KASSERT(softc->inots_freed <= softc->inots_alloced, ("%s: " 992 "inots_freed %ju > inots_alloced %ju", __func__, 993 softc->inots_freed, softc->inots_alloced)); 994 995 /* 996 * If we have received all of our CCBs, we can release our 997 * reference on the peripheral driver. It will probably go away 998 * now. 999 */ 1000 if ((softc->atios_freed == softc->atios_alloced) 1001 && (softc->inots_freed == softc->inots_alloced)) { 1002 cam_periph_release_locked(periph); 1003 } 1004} 1005 1006static int 1007ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset) 1008{ 1009 uint64_t lba; 1010 uint32_t num_blocks, nbc; 1011 uint8_t *cmdbyt = atio_cdb_ptr(atio); 1012 1013 nbc = offset >> 9; /* ASSUMING 512 BYTE BLOCKS */ 1014 1015 switch (cmdbyt[0]) { 1016 case READ_6: 1017 case WRITE_6: 1018 { 1019 struct scsi_rw_6 *cdb = (struct scsi_rw_6 *)cmdbyt; 1020 lba = scsi_3btoul(cdb->addr); 1021 lba &= 0x1fffff; 1022 num_blocks = cdb->length; 1023 if (num_blocks == 0) 1024 num_blocks = 256; 1025 lba += nbc; 1026 num_blocks -= nbc; 1027 scsi_ulto3b(lba, cdb->addr); 1028 cdb->length = num_blocks; 1029 break; 1030 } 1031 case READ_10: 1032 case WRITE_10: 1033 { 1034 struct scsi_rw_10 *cdb = (struct scsi_rw_10 *)cmdbyt; 1035 lba = scsi_4btoul(cdb->addr); 1036 num_blocks = scsi_2btoul(cdb->length); 1037 lba += nbc; 1038 num_blocks -= nbc; 1039 scsi_ulto4b(lba, cdb->addr); 1040 scsi_ulto2b(num_blocks, cdb->length); 1041 break; 1042 } 1043 case READ_12: 1044 case WRITE_12: 1045 { 1046 struct scsi_rw_12 *cdb = (struct scsi_rw_12 *)cmdbyt; 1047 lba = scsi_4btoul(cdb->addr); 1048 num_blocks = scsi_4btoul(cdb->length); 1049 lba += nbc; 1050 num_blocks -= nbc; 1051 scsi_ulto4b(lba, cdb->addr); 1052 scsi_ulto4b(num_blocks, cdb->length); 1053 break; 1054 } 1055 case READ_16: 1056 case WRITE_16: 1057 { 1058 struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt; 1059 lba = scsi_8btou64(cdb->addr); 1060 num_blocks = scsi_4btoul(cdb->length); 1061 lba += nbc; 1062 num_blocks -= nbc; 1063 scsi_u64to8b(lba, cdb->addr); 1064 scsi_ulto4b(num_blocks, cdb->length); 1065 break; 1066 } 1067 default: 1068 return -1; 1069 } 1070 return (0); 1071} 1072 1073static void 1074ctlfedone(struct cam_periph *periph, union ccb *done_ccb) 1075{ 1076 struct ctlfe_lun_softc *softc; 1077 struct ctlfe_softc *bus_softc; 1078 struct ctlfe_cmd_info *cmd_info; 1079 struct ccb_accept_tio *atio = NULL; 1080 union ctl_io *io = NULL; 1081 struct mtx *mtx; 1082 cam_status status; 1083 1084 KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0, 1085 ("CCB in ctlfedone() without CAM_UNLOCKED flag")); 1086#ifdef CTLFE_DEBUG 1087 printf("%s: entered, func_code = %#x\n", __func__, 1088 done_ccb->ccb_h.func_code); 1089#endif 1090 1091 /* 1092 * At this point CTL has no known use case for device queue freezes. 1093 * In case some SIM think different -- drop its freeze right here. 1094 */ 1095 if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1096 cam_release_devq(periph->path, 1097 /*relsim_flags*/0, 1098 /*reduction*/0, 1099 /*timeout*/0, 1100 /*getcount_only*/0); 1101 done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 1102 } 1103 1104 softc = (struct ctlfe_lun_softc *)periph->softc; 1105 bus_softc = softc->parent_softc; 1106 mtx = cam_periph_mtx(periph); 1107 mtx_lock(mtx); 1108 1109 switch (done_ccb->ccb_h.func_code) { 1110 case XPT_ACCEPT_TARGET_IO: { 1111 1112 atio = &done_ccb->atio; 1113 status = atio->ccb_h.status & CAM_STATUS_MASK; 1114 if (status != CAM_CDB_RECVD) { 1115 ctlfe_free_ccb(periph, done_ccb); 1116 goto out; 1117 } 1118 1119 resubmit: 1120 /* 1121 * Allocate a ctl_io, pass it to CTL, and wait for the 1122 * datamove or done. 1123 */ 1124 mtx_unlock(mtx); 1125 io = done_ccb->ccb_h.io_ptr; 1126 cmd_info = PRIV_INFO(io); 1127 ctl_zero_io(io); 1128 1129 /* Save pointers on both sides */ 1130 PRIV_CCB(io) = done_ccb; 1131 PRIV_INFO(io) = cmd_info; 1132 done_ccb->ccb_h.io_ptr = io; 1133 1134 /* 1135 * Only SCSI I/O comes down this path, resets, etc. come 1136 * down the immediate notify path below. 1137 */ 1138 io->io_hdr.io_type = CTL_IO_SCSI; 1139 io->io_hdr.nexus.initid = atio->init_id; 1140 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port; 1141 if (bus_softc->hba_misc & PIM_EXTLUNS) { 1142 io->io_hdr.nexus.targ_lun = ctl_decode_lun( 1143 CAM_EXTLUN_BYTE_SWIZZLE(atio->ccb_h.target_lun)); 1144 } else { 1145 io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun; 1146 } 1147 io->scsiio.tag_num = atio->tag_id; 1148 switch (atio->tag_action) { 1149 case CAM_TAG_ACTION_NONE: 1150 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 1151 break; 1152 case MSG_SIMPLE_TASK: 1153 io->scsiio.tag_type = CTL_TAG_SIMPLE; 1154 break; 1155 case MSG_HEAD_OF_QUEUE_TASK: 1156 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE; 1157 break; 1158 case MSG_ORDERED_TASK: 1159 io->scsiio.tag_type = CTL_TAG_ORDERED; 1160 break; 1161 case MSG_ACA_TASK: 1162 io->scsiio.tag_type = CTL_TAG_ACA; 1163 break; 1164 default: 1165 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 1166 printf("%s: unhandled tag type %#x!!\n", __func__, 1167 atio->tag_action); 1168 break; 1169 } 1170 if (atio->cdb_len > sizeof(io->scsiio.cdb)) { 1171 printf("%s: WARNING: CDB len %d > ctl_io space %zd\n", 1172 __func__, atio->cdb_len, sizeof(io->scsiio.cdb)); 1173 } 1174 io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb)); 1175 bcopy(atio_cdb_ptr(atio), io->scsiio.cdb, io->scsiio.cdb_len); 1176 1177#ifdef CTLFEDEBUG 1178 printf("%s: %u:%u:%u: tag %04x CDB %02x\n", __func__, 1179 io->io_hdr.nexus.initid, 1180 io->io_hdr.nexus.targ_port, 1181 io->io_hdr.nexus.targ_lun, 1182 io->scsiio.tag_num, io->scsiio.cdb[0]); 1183#endif 1184 1185 ctl_queue(io); 1186 return; 1187 } 1188 case XPT_CONT_TARGET_IO: { 1189 int srr = 0; 1190 uint32_t srr_off = 0; 1191 1192 atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio; 1193 io = (union ctl_io *)atio->ccb_h.io_ptr; 1194 1195 softc->ctios_returned++; 1196#ifdef CTLFEDEBUG 1197 printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n", 1198 __func__, atio->tag_id, done_ccb->ccb_h.flags); 1199#endif 1200 /* 1201 * Handle SRR case were the data pointer is pushed back hack 1202 */ 1203 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_MESSAGE_RECV 1204 && done_ccb->csio.msg_ptr != NULL 1205 && done_ccb->csio.msg_ptr[0] == MSG_EXTENDED 1206 && done_ccb->csio.msg_ptr[1] == 5 1207 && done_ccb->csio.msg_ptr[2] == 0) { 1208 srr = 1; 1209 srr_off = 1210 (done_ccb->csio.msg_ptr[3] << 24) 1211 | (done_ccb->csio.msg_ptr[4] << 16) 1212 | (done_ccb->csio.msg_ptr[5] << 8) 1213 | (done_ccb->csio.msg_ptr[6]); 1214 } 1215 1216 /* 1217 * If we have an SRR and we're still sending data, we 1218 * should be able to adjust offsets and cycle again. 1219 * It is possible only if offset is from this datamove. 1220 */ 1221 if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) && 1222 srr_off >= io->scsiio.kern_rel_offset && 1223 srr_off < io->scsiio.kern_rel_offset + 1224 io->scsiio.kern_data_len) { 1225 io->scsiio.kern_data_resid = 1226 io->scsiio.kern_rel_offset + 1227 io->scsiio.kern_data_len - srr_off; 1228 io->scsiio.ext_data_filled = srr_off; 1229 io->scsiio.io_hdr.status = CTL_STATUS_NONE; 1230 io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED; 1231 softc->ccbs_freed++; 1232 xpt_release_ccb(done_ccb); 1233 TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h, 1234 periph_links.tqe); 1235 xpt_schedule(periph, /*priority*/ 1); 1236 break; 1237 } 1238 1239 /* 1240 * If status was being sent, the back end data is now history. 1241 * Hack it up and resubmit a new command with the CDB adjusted. 1242 * If the SIM does the right thing, all of the resid math 1243 * should work. 1244 */ 1245 if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) { 1246 softc->ccbs_freed++; 1247 xpt_release_ccb(done_ccb); 1248 if (ctlfe_adjust_cdb(atio, srr_off) == 0) { 1249 done_ccb = (union ccb *)atio; 1250 goto resubmit; 1251 } 1252 /* 1253 * Fall through to doom.... 1254 */ 1255 } 1256 1257 if ((done_ccb->ccb_h.flags & CAM_SEND_STATUS) && 1258 (done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1259 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; 1260 1261 /* 1262 * If we were sending status back to the initiator, free up 1263 * resources. If we were doing a datamove, call the 1264 * datamove done routine. 1265 */ 1266 if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) { 1267 softc->ccbs_freed++; 1268 xpt_release_ccb(done_ccb); 1269 /* 1270 * For a wildcard attachment, commands can come in 1271 * with a specific target/lun. Reset the target 1272 * and LUN fields back to the wildcard values before 1273 * we send them back down to the SIM. The SIM has 1274 * a wildcard LUN enabled, not whatever target/lun 1275 * these happened to be. 1276 */ 1277 if (softc->flags & CTLFE_LUN_WILDCARD) { 1278 atio->ccb_h.target_id = CAM_TARGET_WILDCARD; 1279 atio->ccb_h.target_lun = CAM_LUN_WILDCARD; 1280 } 1281 if (periph->flags & CAM_PERIPH_INVALID) { 1282 ctlfe_free_ccb(periph, (union ccb *)atio); 1283 } else { 1284 mtx_unlock(mtx); 1285 xpt_action((union ccb *)atio); 1286 return; 1287 } 1288 } else { 1289 struct ctlfe_cmd_info *cmd_info; 1290 struct ccb_scsiio *csio; 1291 1292 csio = &done_ccb->csio; 1293 cmd_info = PRIV_INFO(io); 1294 1295 io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; 1296 1297 /* 1298 * Translate CAM status to CTL status. Success 1299 * does not change the overall, ctl_io status. In 1300 * that case we just set port_status to 0. If we 1301 * have a failure, though, set a data phase error 1302 * for the overall ctl_io. 1303 */ 1304 switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) { 1305 case CAM_REQ_CMP: 1306 io->scsiio.kern_data_resid -= csio->dxfer_len; 1307 io->io_hdr.port_status = 0; 1308 break; 1309 default: 1310 /* 1311 * XXX KDM we probably need to figure out a 1312 * standard set of errors that the SIM 1313 * drivers should return in the event of a 1314 * data transfer failure. A data phase 1315 * error will at least point the user to a 1316 * data transfer error of some sort. 1317 * Hopefully the SIM printed out some 1318 * additional information to give the user 1319 * a clue what happened. 1320 */ 1321 io->io_hdr.port_status = 0xbad1; 1322 ctl_set_data_phase_error(&io->scsiio); 1323 /* 1324 * XXX KDM figure out residual. 1325 */ 1326 break; 1327 } 1328 /* 1329 * If we had to break this S/G list into multiple 1330 * pieces, figure out where we are in the list, and 1331 * continue sending pieces if necessary. 1332 */ 1333 if ((cmd_info->flags & CTLFE_CMD_PIECEWISE) 1334 && (io->io_hdr.port_status == 0)) { 1335 ccb_flags flags; 1336 uint8_t *data_ptr; 1337 uint32_t dxfer_len; 1338 1339 flags = atio->ccb_h.flags & 1340 (CAM_DIS_DISCONNECT| 1341 CAM_TAG_ACTION_VALID); 1342 1343 ctlfedata(softc, io, &flags, &data_ptr, 1344 &dxfer_len, &csio->sglist_cnt); 1345 1346 if (((flags & CAM_SEND_STATUS) == 0) 1347 && (dxfer_len == 0)) { 1348 printf("%s: tag %04x no status or " 1349 "len cdb = %02x\n", __func__, 1350 atio->tag_id, 1351 atio_cdb_ptr(atio)[0]); 1352 printf("%s: tag %04x io status %#x\n", 1353 __func__, atio->tag_id, 1354 io->io_hdr.status); 1355 } 1356 1357 cam_fill_ctio(csio, 1358 /*retries*/ 2, 1359 ctlfedone, 1360 flags, 1361 (flags & CAM_TAG_ACTION_VALID) ? 1362 MSG_SIMPLE_Q_TAG : 0, 1363 atio->tag_id, 1364 atio->init_id, 1365 0, 1366 /*data_ptr*/ data_ptr, 1367 /*dxfer_len*/ dxfer_len, 1368 /*timeout*/ 5 * 1000); 1369 1370 csio->ccb_h.flags |= CAM_UNLOCKED; 1371 csio->resid = 0; 1372 csio->ccb_h.ccb_atio = atio; 1373 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; 1374 softc->ctios_sent++; 1375 mtx_unlock(mtx); 1376 xpt_action((union ccb *)csio); 1377 } else { 1378 /* 1379 * Release the CTIO. The ATIO will be sent back 1380 * down to the SIM once we send status. 1381 */ 1382 softc->ccbs_freed++; 1383 xpt_release_ccb(done_ccb); 1384 mtx_unlock(mtx); 1385 1386 /* Call the backend move done callback */ 1387 io->scsiio.be_move_done(io); 1388 } 1389 return; 1390 } 1391 break; 1392 } 1393 case XPT_IMMEDIATE_NOTIFY: { 1394 union ctl_io *io; 1395 struct ccb_immediate_notify *inot; 1396 int send_ctl_io; 1397 1398 inot = &done_ccb->cin1; 1399 io = done_ccb->ccb_h.io_ptr; 1400 ctl_zero_io(io); 1401 1402 send_ctl_io = 1; 1403 1404 io->io_hdr.io_type = CTL_IO_TASK; 1405 PRIV_CCB(io) = done_ccb; 1406 inot->ccb_h.io_ptr = io; 1407 io->io_hdr.nexus.initid = inot->initiator_id; 1408 io->io_hdr.nexus.targ_port = bus_softc->port.targ_port; 1409 if (bus_softc->hba_misc & PIM_EXTLUNS) { 1410 io->io_hdr.nexus.targ_lun = ctl_decode_lun( 1411 CAM_EXTLUN_BYTE_SWIZZLE(inot->ccb_h.target_lun)); 1412 } else { 1413 io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun; 1414 } 1415 /* XXX KDM should this be the tag_id? */ 1416 io->taskio.tag_num = inot->seq_id; 1417 1418 status = inot->ccb_h.status & CAM_STATUS_MASK; 1419 switch (status) { 1420 case CAM_SCSI_BUS_RESET: 1421 io->taskio.task_action = CTL_TASK_BUS_RESET; 1422 break; 1423 case CAM_BDR_SENT: 1424 io->taskio.task_action = CTL_TASK_TARGET_RESET; 1425 break; 1426 case CAM_MESSAGE_RECV: 1427 switch (inot->arg) { 1428 case MSG_ABORT_TASK_SET: 1429 io->taskio.task_action = 1430 CTL_TASK_ABORT_TASK_SET; 1431 break; 1432 case MSG_TARGET_RESET: 1433 io->taskio.task_action = CTL_TASK_TARGET_RESET; 1434 break; 1435 case MSG_ABORT_TASK: 1436 io->taskio.task_action = CTL_TASK_ABORT_TASK; 1437 break; 1438 case MSG_LOGICAL_UNIT_RESET: 1439 io->taskio.task_action = CTL_TASK_LUN_RESET; 1440 break; 1441 case MSG_CLEAR_TASK_SET: 1442 io->taskio.task_action = 1443 CTL_TASK_CLEAR_TASK_SET; 1444 break; 1445 case MSG_CLEAR_ACA: 1446 io->taskio.task_action = CTL_TASK_CLEAR_ACA; 1447 break; 1448 case MSG_QUERY_TASK: 1449 io->taskio.task_action = CTL_TASK_QUERY_TASK; 1450 break; 1451 case MSG_QUERY_TASK_SET: 1452 io->taskio.task_action = 1453 CTL_TASK_QUERY_TASK_SET; 1454 break; 1455 case MSG_QUERY_ASYNC_EVENT: 1456 io->taskio.task_action = 1457 CTL_TASK_QUERY_ASYNC_EVENT; 1458 break; 1459 case MSG_NOOP: 1460 send_ctl_io = 0; 1461 break; 1462 default: 1463 xpt_print(periph->path, 1464 "%s: unsupported INOT message 0x%x\n", 1465 __func__, inot->arg); 1466 send_ctl_io = 0; 1467 break; 1468 } 1469 break; 1470 default: 1471 xpt_print(periph->path, 1472 "%s: unsupported INOT status 0x%x\n", 1473 __func__, status); 1474 /* FALLTHROUGH */ 1475 case CAM_REQ_ABORTED: 1476 case CAM_REQ_INVALID: 1477 case CAM_DEV_NOT_THERE: 1478 case CAM_PROVIDE_FAIL: 1479 ctlfe_free_ccb(periph, done_ccb); 1480 goto out; 1481 } 1482 if (send_ctl_io != 0) { 1483 ctl_queue(io); 1484 } else { 1485 done_ccb->ccb_h.status = CAM_REQ_INPROG; 1486 done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; 1487 xpt_action(done_ccb); 1488 } 1489 break; 1490 } 1491 case XPT_NOTIFY_ACKNOWLEDGE: 1492 if (periph->flags & CAM_PERIPH_INVALID) { 1493 ctlfe_free_ccb(periph, done_ccb); 1494 goto out; 1495 } 1496 1497 /* 1498 * Queue this back down to the SIM as an immediate notify. 1499 */ 1500 done_ccb->ccb_h.status = CAM_REQ_INPROG; 1501 done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; 1502 xpt_action(done_ccb); 1503 break; 1504 case XPT_SET_SIM_KNOB: 1505 case XPT_GET_SIM_KNOB: 1506 break; 1507 default: 1508 panic("%s: unexpected CCB type %#x", __func__, 1509 done_ccb->ccb_h.func_code); 1510 break; 1511 } 1512 1513out: 1514 mtx_unlock(mtx); 1515} 1516 1517static void 1518ctlfe_onoffline(void *arg, int online) 1519{ 1520 struct ctlfe_softc *bus_softc; 1521 union ccb *ccb; 1522 cam_status status; 1523 struct cam_path *path; 1524 int set_wwnn; 1525 1526 bus_softc = (struct ctlfe_softc *)arg; 1527 1528 set_wwnn = 0; 1529 1530 status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id, 1531 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 1532 if (status != CAM_REQ_CMP) { 1533 printf("%s: unable to create path!\n", __func__); 1534 return; 1535 } 1536 ccb = xpt_alloc_ccb(); 1537 xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE); 1538 ccb->ccb_h.func_code = XPT_GET_SIM_KNOB; 1539 xpt_action(ccb); 1540 1541 /* 1542 * Copan WWN format: 1543 * 1544 * Bits 63-60: 0x5 NAA, IEEE registered name 1545 * Bits 59-36: 0x000ED5 IEEE Company name assigned to Copan 1546 * Bits 35-12: Copan SSN (Sequential Serial Number) 1547 * Bits 11-8: Type of port: 1548 * 1 == N-Port 1549 * 2 == F-Port 1550 * 3 == NL-Port 1551 * Bits 7-0: 0 == Node Name, >0 == Port Number 1552 */ 1553 if (online != 0) { 1554 if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){ 1555#ifdef RANDOM_WWNN 1556 uint64_t random_bits; 1557#endif 1558 1559 printf("%s: %s current WWNN %#jx\n", __func__, 1560 bus_softc->port_name, 1561 ccb->knob.xport_specific.fc.wwnn); 1562 printf("%s: %s current WWPN %#jx\n", __func__, 1563 bus_softc->port_name, 1564 ccb->knob.xport_specific.fc.wwpn); 1565 1566#ifdef RANDOM_WWNN 1567 arc4rand(&random_bits, sizeof(random_bits), 0); 1568#endif 1569 1570 /* 1571 * XXX KDM this is a bit of a kludge for now. We 1572 * take the current WWNN/WWPN from the card, and 1573 * replace the company identifier and the NL-Port 1574 * indicator and the port number (for the WWPN). 1575 * This should be replaced later with ddb_GetWWNN, 1576 * or possibly a more centralized scheme. (It 1577 * would be nice to have the WWNN/WWPN for each 1578 * port stored in the ctl_port structure.) 1579 */ 1580#ifdef RANDOM_WWNN 1581 ccb->knob.xport_specific.fc.wwnn = 1582 (random_bits & 1583 0x0000000fffffff00ULL) | 1584 /* Company ID */ 0x5000ED5000000000ULL | 1585 /* NL-Port */ 0x0300; 1586 ccb->knob.xport_specific.fc.wwpn = 1587 (random_bits & 1588 0x0000000fffffff00ULL) | 1589 /* Company ID */ 0x5000ED5000000000ULL | 1590 /* NL-Port */ 0x3000 | 1591 /* Port Num */ (bus_softc->port.targ_port & 0xff); 1592 1593 /* 1594 * This is a bit of an API break/reversal, but if 1595 * we're doing the random WWNN that's a little 1596 * different anyway. So record what we're actually 1597 * using with the frontend code so it's reported 1598 * accurately. 1599 */ 1600 ctl_port_set_wwns(&bus_softc->port, 1601 true, ccb->knob.xport_specific.fc.wwnn, 1602 true, ccb->knob.xport_specific.fc.wwpn); 1603 set_wwnn = 1; 1604#else /* RANDOM_WWNN */ 1605 /* 1606 * If the user has specified a WWNN/WWPN, send them 1607 * down to the SIM. Otherwise, record what the SIM 1608 * has reported. 1609 */ 1610 if (bus_softc->port.wwnn != 0 && bus_softc->port.wwnn 1611 != ccb->knob.xport_specific.fc.wwnn) { 1612 ccb->knob.xport_specific.fc.wwnn = 1613 bus_softc->port.wwnn; 1614 set_wwnn = 1; 1615 } else { 1616 ctl_port_set_wwns(&bus_softc->port, 1617 true, ccb->knob.xport_specific.fc.wwnn, 1618 false, 0); 1619 } 1620 if (bus_softc->port.wwpn != 0 && bus_softc->port.wwpn 1621 != ccb->knob.xport_specific.fc.wwpn) { 1622 ccb->knob.xport_specific.fc.wwpn = 1623 bus_softc->port.wwpn; 1624 set_wwnn = 1; 1625 } else { 1626 ctl_port_set_wwns(&bus_softc->port, 1627 false, 0, 1628 true, ccb->knob.xport_specific.fc.wwpn); 1629 } 1630#endif /* RANDOM_WWNN */ 1631 1632 1633 if (set_wwnn != 0) { 1634 printf("%s: %s new WWNN %#jx\n", __func__, 1635 bus_softc->port_name, 1636 ccb->knob.xport_specific.fc.wwnn); 1637 printf("%s: %s new WWPN %#jx\n", __func__, 1638 bus_softc->port_name, 1639 ccb->knob.xport_specific.fc.wwpn); 1640 } 1641 } else { 1642 printf("%s: %s has no valid WWNN/WWPN\n", __func__, 1643 bus_softc->port_name); 1644 } 1645 } 1646 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB; 1647 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE; 1648 if (set_wwnn != 0) 1649 ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS; 1650 1651 if (online != 0) 1652 ccb->knob.xport_specific.fc.role |= KNOB_ROLE_TARGET; 1653 else 1654 ccb->knob.xport_specific.fc.role &= ~KNOB_ROLE_TARGET; 1655 1656 xpt_action(ccb); 1657 1658 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1659 printf("%s: SIM %s (path id %d) target %s failed with " 1660 "status %#x\n", 1661 __func__, bus_softc->port_name, bus_softc->path_id, 1662 (online != 0) ? "enable" : "disable", 1663 ccb->ccb_h.status); 1664 } else { 1665 printf("%s: SIM %s (path id %d) target %s succeeded\n", 1666 __func__, bus_softc->port_name, bus_softc->path_id, 1667 (online != 0) ? "enable" : "disable"); 1668 } 1669 1670 xpt_free_path(path); 1671 xpt_free_ccb(ccb); 1672} 1673 1674static void 1675ctlfe_online(void *arg) 1676{ 1677 struct ctlfe_softc *bus_softc; 1678 struct cam_path *path; 1679 cam_status status; 1680 struct ctlfe_lun_softc *lun_softc; 1681 struct cam_periph *periph; 1682 1683 bus_softc = (struct ctlfe_softc *)arg; 1684 1685 /* 1686 * Create the wildcard LUN before bringing the port online. 1687 */ 1688 status = xpt_create_path(&path, /*periph*/ NULL, 1689 bus_softc->path_id, CAM_TARGET_WILDCARD, 1690 CAM_LUN_WILDCARD); 1691 if (status != CAM_REQ_CMP) { 1692 printf("%s: unable to create path for wildcard periph\n", 1693 __func__); 1694 return; 1695 } 1696 1697 lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, M_WAITOK | M_ZERO); 1698 1699 xpt_path_lock(path); 1700 periph = cam_periph_find(path, "ctl"); 1701 if (periph != NULL) { 1702 /* We've already got a periph, no need to alloc a new one. */ 1703 xpt_path_unlock(path); 1704 xpt_free_path(path); 1705 free(lun_softc, M_CTLFE); 1706 return; 1707 } 1708 lun_softc->parent_softc = bus_softc; 1709 lun_softc->flags |= CTLFE_LUN_WILDCARD; 1710 1711 status = cam_periph_alloc(ctlferegister, 1712 ctlfeoninvalidate, 1713 ctlfecleanup, 1714 ctlfestart, 1715 "ctl", 1716 CAM_PERIPH_BIO, 1717 path, 1718 ctlfeasync, 1719 0, 1720 lun_softc); 1721 1722 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1723 const struct cam_status_entry *entry; 1724 1725 entry = cam_fetch_status_entry(status); 1726 printf("%s: CAM error %s (%#x) returned from " 1727 "cam_periph_alloc()\n", __func__, (entry != NULL) ? 1728 entry->status_text : "Unknown", status); 1729 free(lun_softc, M_CTLFE); 1730 } 1731 1732 xpt_path_unlock(path); 1733 ctlfe_onoffline(arg, /*online*/ 1); 1734 xpt_free_path(path); 1735} 1736 1737static void 1738ctlfe_offline(void *arg) 1739{ 1740 struct ctlfe_softc *bus_softc; 1741 struct cam_path *path; 1742 cam_status status; 1743 struct cam_periph *periph; 1744 1745 bus_softc = (struct ctlfe_softc *)arg; 1746 1747 ctlfe_onoffline(arg, /*online*/ 0); 1748 1749 /* 1750 * Disable the wildcard LUN for this port now that we have taken 1751 * the port offline. 1752 */ 1753 status = xpt_create_path(&path, /*periph*/ NULL, 1754 bus_softc->path_id, CAM_TARGET_WILDCARD, 1755 CAM_LUN_WILDCARD); 1756 if (status != CAM_REQ_CMP) { 1757 printf("%s: unable to create path for wildcard periph\n", 1758 __func__); 1759 return; 1760 } 1761 xpt_path_lock(path); 1762 if ((periph = cam_periph_find(path, "ctl")) != NULL) 1763 cam_periph_invalidate(periph); 1764 xpt_path_unlock(path); 1765 xpt_free_path(path); 1766} 1767 1768/* 1769 * This will get called to enable a LUN on every bus that is attached to 1770 * CTL. So we only need to create a path/periph for this particular bus. 1771 */ 1772static int 1773ctlfe_lun_enable(void *arg, int lun_id) 1774{ 1775 struct ctlfe_softc *bus_softc; 1776 struct ctlfe_lun_softc *softc; 1777 struct cam_path *path; 1778 struct cam_periph *periph; 1779 cam_status status; 1780 1781 bus_softc = (struct ctlfe_softc *)arg; 1782 if (bus_softc->hba_misc & PIM_EXTLUNS) 1783 lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id)); 1784 1785 status = xpt_create_path(&path, /*periph*/ NULL, 1786 bus_softc->path_id, bus_softc->target_id, lun_id); 1787 /* XXX KDM need some way to return status to CTL here? */ 1788 if (status != CAM_REQ_CMP) { 1789 printf("%s: could not create path, status %#x\n", __func__, 1790 status); 1791 return (1); 1792 } 1793 1794 softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO); 1795 xpt_path_lock(path); 1796 periph = cam_periph_find(path, "ctl"); 1797 if (periph != NULL) { 1798 /* We've already got a periph, no need to alloc a new one. */ 1799 xpt_path_unlock(path); 1800 xpt_free_path(path); 1801 free(softc, M_CTLFE); 1802 return (0); 1803 } 1804 softc->parent_softc = bus_softc; 1805 1806 status = cam_periph_alloc(ctlferegister, 1807 ctlfeoninvalidate, 1808 ctlfecleanup, 1809 ctlfestart, 1810 "ctl", 1811 CAM_PERIPH_BIO, 1812 path, 1813 ctlfeasync, 1814 0, 1815 softc); 1816 1817 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1818 const struct cam_status_entry *entry; 1819 1820 entry = cam_fetch_status_entry(status); 1821 printf("%s: CAM error %s (%#x) returned from " 1822 "cam_periph_alloc()\n", __func__, (entry != NULL) ? 1823 entry->status_text : "Unknown", status); 1824 free(softc, M_CTLFE); 1825 } 1826 1827 xpt_path_unlock(path); 1828 xpt_free_path(path); 1829 return (0); 1830} 1831 1832/* 1833 * This will get called when the user removes a LUN to disable that LUN 1834 * on every bus that is attached to CTL. 1835 */ 1836static int 1837ctlfe_lun_disable(void *arg, int lun_id) 1838{ 1839 struct ctlfe_softc *softc; 1840 struct ctlfe_lun_softc *lun_softc; 1841 1842 softc = (struct ctlfe_softc *)arg; 1843 if (softc->hba_misc & PIM_EXTLUNS) 1844 lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id)); 1845 1846 mtx_lock(&softc->lun_softc_mtx); 1847 STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) { 1848 struct cam_path *path; 1849 1850 path = lun_softc->periph->path; 1851 1852 if ((xpt_path_target_id(path) == softc->target_id) 1853 && (xpt_path_lun_id(path) == lun_id)) { 1854 break; 1855 } 1856 } 1857 if (lun_softc == NULL) { 1858 mtx_unlock(&softc->lun_softc_mtx); 1859 printf("%s: can't find lun %d\n", __func__, lun_id); 1860 return (1); 1861 } 1862 cam_periph_acquire(lun_softc->periph); 1863 mtx_unlock(&softc->lun_softc_mtx); 1864 1865 cam_periph_lock(lun_softc->periph); 1866 cam_periph_invalidate(lun_softc->periph); 1867 cam_periph_unlock(lun_softc->periph); 1868 cam_periph_release(lun_softc->periph); 1869 return (0); 1870} 1871 1872static void 1873ctlfe_dump_sim(struct cam_sim *sim) 1874{ 1875 1876 printf("%s%d: max tagged openings: %d, max dev openings: %d\n", 1877 sim->sim_name, sim->unit_number, 1878 sim->max_tagged_dev_openings, sim->max_dev_openings); 1879} 1880 1881/* 1882 * Assumes that the SIM lock is held. 1883 */ 1884static void 1885ctlfe_dump_queue(struct ctlfe_lun_softc *softc) 1886{ 1887 struct ccb_hdr *hdr; 1888 struct cam_periph *periph; 1889 int num_items; 1890 1891 periph = softc->periph; 1892 num_items = 0; 1893 1894 TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) { 1895 union ctl_io *io = hdr->io_ptr; 1896 1897 num_items++; 1898 1899 /* 1900 * Only regular SCSI I/O is put on the work 1901 * queue, so we can print sense here. There may be no 1902 * sense if it's no the queue for a DMA, but this serves to 1903 * print out the CCB as well. 1904 * 1905 * XXX KDM switch this over to scsi_sense_print() when 1906 * CTL is merged in with CAM. 1907 */ 1908 ctl_io_error_print(io, NULL); 1909 1910 /* 1911 * Print DMA status if we are DMA_QUEUED. 1912 */ 1913 if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) { 1914 xpt_print(periph->path, 1915 "Total %u, Current %u, Resid %u\n", 1916 io->scsiio.kern_total_len, 1917 io->scsiio.kern_data_len, 1918 io->scsiio.kern_data_resid); 1919 } 1920 } 1921 1922 xpt_print(periph->path, "%d requests total waiting for CCBs\n", 1923 num_items); 1924 xpt_print(periph->path, "%ju CCBs outstanding (%ju allocated, %ju " 1925 "freed)\n", (uintmax_t)(softc->ccbs_alloced - 1926 softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced, 1927 (uintmax_t)softc->ccbs_freed); 1928 xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju " 1929 "returned\n", (uintmax_t)(softc->ctios_sent - 1930 softc->ctios_returned), softc->ctios_sent, 1931 softc->ctios_returned); 1932} 1933 1934/* 1935 * Datamove/done routine called by CTL. Put ourselves on the queue to 1936 * receive a CCB from CAM so we can queue the continue I/O request down 1937 * to the adapter. 1938 */ 1939static void 1940ctlfe_datamove(union ctl_io *io) 1941{ 1942 union ccb *ccb; 1943 struct cam_periph *periph; 1944 struct ctlfe_lun_softc *softc; 1945 1946 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, 1947 ("Unexpected io_type (%d) in ctlfe_datamove", io->io_hdr.io_type)); 1948 1949 io->scsiio.ext_data_filled = 0; 1950 ccb = PRIV_CCB(io); 1951 periph = xpt_path_periph(ccb->ccb_h.path); 1952 cam_periph_lock(periph); 1953 softc = (struct ctlfe_lun_softc *)periph->softc; 1954 io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED; 1955 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) 1956 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; 1957 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, 1958 periph_links.tqe); 1959 xpt_schedule(periph, /*priority*/ 1); 1960 cam_periph_unlock(periph); 1961} 1962 1963static void 1964ctlfe_done(union ctl_io *io) 1965{ 1966 union ccb *ccb; 1967 struct cam_periph *periph; 1968 struct ctlfe_lun_softc *softc; 1969 1970 ccb = PRIV_CCB(io); 1971 periph = xpt_path_periph(ccb->ccb_h.path); 1972 cam_periph_lock(periph); 1973 softc = (struct ctlfe_lun_softc *)periph->softc; 1974 1975 if (io->io_hdr.io_type == CTL_IO_TASK) { 1976 /* 1977 * Send the notify acknowledge down to the SIM, to let it 1978 * know we processed the task management command. 1979 */ 1980 ccb->ccb_h.status = CAM_REQ_INPROG; 1981 ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; 1982 switch (io->taskio.task_status) { 1983 case CTL_TASK_FUNCTION_COMPLETE: 1984 ccb->cna2.arg = CAM_RSP_TMF_COMPLETE; 1985 break; 1986 case CTL_TASK_FUNCTION_SUCCEEDED: 1987 ccb->cna2.arg = CAM_RSP_TMF_SUCCEEDED; 1988 ccb->ccb_h.flags |= CAM_SEND_STATUS; 1989 break; 1990 case CTL_TASK_FUNCTION_REJECTED: 1991 ccb->cna2.arg = CAM_RSP_TMF_REJECTED; 1992 ccb->ccb_h.flags |= CAM_SEND_STATUS; 1993 break; 1994 case CTL_TASK_LUN_DOES_NOT_EXIST: 1995 ccb->cna2.arg = CAM_RSP_TMF_INCORRECT_LUN; 1996 ccb->ccb_h.flags |= CAM_SEND_STATUS; 1997 break; 1998 case CTL_TASK_FUNCTION_NOT_SUPPORTED: 1999 ccb->cna2.arg = CAM_RSP_TMF_FAILED; 2000 ccb->ccb_h.flags |= CAM_SEND_STATUS; 2001 break; 2002 } 2003 ccb->cna2.arg |= scsi_3btoul(io->taskio.task_resp) << 8; 2004 xpt_action(ccb); 2005 } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) { 2006 if (softc->flags & CTLFE_LUN_WILDCARD) { 2007 ccb->ccb_h.target_id = CAM_TARGET_WILDCARD; 2008 ccb->ccb_h.target_lun = CAM_LUN_WILDCARD; 2009 } 2010 if (periph->flags & CAM_PERIPH_INVALID) { 2011 ctlfe_free_ccb(periph, ccb); 2012 } else { 2013 cam_periph_unlock(periph); 2014 xpt_action(ccb); 2015 return; 2016 } 2017 } else { 2018 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; 2019 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, 2020 periph_links.tqe); 2021 xpt_schedule(periph, /*priority*/ 1); 2022 } 2023 2024 cam_periph_unlock(periph); 2025} 2026 2027static void 2028ctlfe_dump(void) 2029{ 2030 struct ctlfe_softc *bus_softc; 2031 struct ctlfe_lun_softc *lun_softc; 2032 2033 STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) { 2034 ctlfe_dump_sim(bus_softc->sim); 2035 STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links) 2036 ctlfe_dump_queue(lun_softc); 2037 } 2038} 2039