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