scsi_ctl.c revision 236426
1229997Sken/*- 2229997Sken * Copyright (c) 2008, 2009 Silicon Graphics International Corp. 3229997Sken * All rights reserved. 4229997Sken * 5229997Sken * Redistribution and use in source and binary forms, with or without 6229997Sken * modification, are permitted provided that the following conditions 7229997Sken * are met: 8229997Sken * 1. Redistributions of source code must retain the above copyright 9229997Sken * notice, this list of conditions, and the following disclaimer, 10229997Sken * without modification. 11229997Sken * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12229997Sken * substantially similar to the "NO WARRANTY" disclaimer below 13229997Sken * ("Disclaimer") and any redistribution must be conditioned upon 14229997Sken * including a substantially similar Disclaimer requirement for further 15229997Sken * binary redistribution. 16229997Sken * 17229997Sken * NO WARRANTY 18229997Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19229997Sken * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20229997Sken * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21229997Sken * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22229997Sken * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26229997Sken * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27229997Sken * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28229997Sken * POSSIBILITY OF SUCH DAMAGES. 29229997Sken * 30229997Sken * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/scsi_ctl.c#4 $ 31229997Sken */ 32229997Sken/* 33229997Sken * Peripheral driver interface between CAM and CTL (CAM Target Layer). 34229997Sken * 35229997Sken * Author: Ken Merry <ken@FreeBSD.org> 36229997Sken */ 37229997Sken 38229997Sken#include <sys/cdefs.h> 39229997Sken__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 236426 2012-06-01 23:24:56Z mjacob $"); 40229997Sken 41229997Sken#include <sys/param.h> 42229997Sken#include <sys/queue.h> 43229997Sken#include <sys/systm.h> 44229997Sken#include <sys/kernel.h> 45229997Sken#include <sys/lock.h> 46229997Sken#include <sys/mutex.h> 47229997Sken#include <sys/condvar.h> 48229997Sken#include <sys/malloc.h> 49229997Sken#include <sys/bus.h> 50229997Sken#include <sys/endian.h> 51229997Sken#include <sys/sbuf.h> 52229997Sken#include <sys/sysctl.h> 53229997Sken#include <sys/types.h> 54229997Sken#include <sys/systm.h> 55229997Sken#include <machine/bus.h> 56229997Sken 57229997Sken#include <cam/cam.h> 58229997Sken#include <cam/cam_ccb.h> 59229997Sken#include <cam/cam_periph.h> 60229997Sken#include <cam/cam_queue.h> 61229997Sken#include <cam/cam_xpt_periph.h> 62229997Sken#include <cam/cam_debug.h> 63229997Sken#include <cam/cam_sim.h> 64229997Sken#include <cam/cam_xpt.h> 65229997Sken 66229997Sken#include <cam/scsi/scsi_all.h> 67229997Sken#include <cam/scsi/scsi_message.h> 68229997Sken 69229997Sken#include <cam/ctl/ctl_io.h> 70229997Sken#include <cam/ctl/ctl.h> 71229997Sken#include <cam/ctl/ctl_frontend.h> 72229997Sken#include <cam/ctl/ctl_util.h> 73229997Sken#include <cam/ctl/ctl_error.h> 74229997Sken 75229997Skentypedef enum { 76229997Sken CTLFE_CCB_WAITING = 0x01 77229997Sken} ctlfe_ccb_types; 78229997Sken 79229997Skenstruct ctlfe_softc { 80229997Sken struct ctl_frontend fe; 81229997Sken path_id_t path_id; 82229997Sken struct cam_sim *sim; 83229997Sken char port_name[DEV_IDLEN]; 84229997Sken STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list; 85229997Sken STAILQ_ENTRY(ctlfe_softc) links; 86229997Sken}; 87229997Sken 88229997SkenSTAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list; 89229997Skenstruct mtx ctlfe_list_mtx; 90229997Skenstatic char ctlfe_mtx_desc[] = "ctlfelist"; 91229997Skenstatic int ctlfe_dma_enabled = 1; 92229997Sken#ifdef CTLFE_INIT_ENABLE 93229997Skenstatic int ctlfe_max_targets = 1; 94229997Skenstatic int ctlfe_num_targets = 0; 95229997Sken#endif 96229997Sken 97229997Skentypedef enum { 98229997Sken CTLFE_LUN_NONE = 0x00, 99229997Sken CTLFE_LUN_WILDCARD = 0x01 100229997Sken} ctlfe_lun_flags; 101229997Sken 102229997Skenstruct ctlfe_lun_softc { 103229997Sken struct ctlfe_softc *parent_softc; 104229997Sken struct cam_periph *periph; 105229997Sken ctlfe_lun_flags flags; 106229997Sken struct callout dma_callout; 107229997Sken uint64_t ccbs_alloced; 108229997Sken uint64_t ccbs_freed; 109229997Sken uint64_t ctios_sent; 110229997Sken uint64_t ctios_returned; 111229997Sken uint64_t atios_sent; 112229997Sken uint64_t atios_returned; 113229997Sken uint64_t inots_sent; 114229997Sken uint64_t inots_returned; 115229997Sken /* bus_dma_tag_t dma_tag; */ 116229997Sken TAILQ_HEAD(, ccb_hdr) work_queue; 117229997Sken STAILQ_ENTRY(ctlfe_lun_softc) links; 118229997Sken}; 119229997Sken 120229997Skentypedef enum { 121229997Sken CTLFE_CMD_NONE = 0x00, 122229997Sken CTLFE_CMD_PIECEWISE = 0x01 123229997Sken} ctlfe_cmd_flags; 124229997Sken 125229997Sken/* 126229997Sken * The size limit of this structure is CTL_PORT_PRIV_SIZE, from ctl_io.h. 127229997Sken * Currently that is 600 bytes. 128229997Sken */ 129229997Skenstruct ctlfe_lun_cmd_info { 130229997Sken int cur_transfer_index; 131229997Sken ctlfe_cmd_flags flags; 132229997Sken /* 133229997Sken * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16 134229997Sken * bytes on amd64. So with 32 elements, this is 256 bytes on 135229997Sken * i386 and 512 bytes on amd64. 136229997Sken */ 137229997Sken bus_dma_segment_t cam_sglist[32]; 138229997Sken}; 139229997Sken 140229997Sken/* 141229997Sken * When we register the adapter/bus, request that this many ctl_ios be 142229997Sken * allocated. This should be the maximum supported by the adapter, but we 143229997Sken * currently don't have a way to get that back from the path inquiry. 144229997Sken * XXX KDM add that to the path inquiry. 145229997Sken */ 146229997Sken#define CTLFE_REQ_CTL_IO 4096 147229997Sken/* 148229997Sken * Number of Accept Target I/O CCBs to allocate and queue down to the 149229997Sken * adapter per LUN. 150229997Sken * XXX KDM should this be controlled by CTL? 151229997Sken */ 152229997Sken#define CTLFE_ATIO_PER_LUN 1024 153229997Sken/* 154229997Sken * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to 155229997Sken * allocate and queue down to the adapter per LUN. 156229997Sken * XXX KDM should this be controlled by CTL? 157229997Sken */ 158229997Sken#define CTLFE_IN_PER_LUN 1024 159229997Sken 160229997Sken/* 161229997Sken * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending 162229997Sken * status to the initiator. The SIM is expected to have its own timeouts, 163229997Sken * so we're not putting this timeout around the CCB execution time. The 164229997Sken * SIM should timeout and let us know if it has an issue. 165229997Sken */ 166229997Sken#define CTLFE_DMA_TIMEOUT 60 167229997Sken 168229997Sken/* 169229997Sken * Turn this on to enable extra debugging prints. 170229997Sken */ 171229997Sken#if 0 172229997Sken#define CTLFE_DEBUG 173229997Sken#endif 174229997Sken 175229997Sken/* 176229997Sken * Use randomly assigned WWNN/WWPN values. This is to work around an issue 177229997Sken * in the FreeBSD initiator that makes it unable to rescan the target if 178229997Sken * the target gets rebooted and the WWNN/WWPN stay the same. 179229997Sken */ 180229997Sken#if 0 181229997Sken#define RANDOM_WWNN 182229997Sken#endif 183229997Sken 184229997SkenSYSCTL_INT(_kern_cam_ctl, OID_AUTO, dma_enabled, CTLFLAG_RW, 185229997Sken &ctlfe_dma_enabled, 0, "DMA enabled"); 186229997SkenMALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface"); 187229997Sken 188229997Sken#define ccb_type ppriv_field0 189229997Sken/* This is only used in the ATIO */ 190229997Sken#define io_ptr ppriv_ptr1 191229997Sken 192229997Sken/* This is only used in the CTIO */ 193229997Sken#define ccb_atio ppriv_ptr1 194229997Sken 195229997Skenint ctlfeinitialize(void); 196229997Skenvoid ctlfeshutdown(void); 197229997Skenstatic periph_init_t ctlfeinit; 198229997Skenstatic void ctlfeasync(void *callback_arg, uint32_t code, 199229997Sken struct cam_path *path, void *arg); 200229997Skenstatic periph_ctor_t ctlferegister; 201229997Skenstatic periph_oninv_t ctlfeoninvalidate; 202229997Skenstatic periph_dtor_t ctlfecleanup; 203229997Skenstatic periph_start_t ctlfestart; 204229997Skenstatic void ctlfedone(struct cam_periph *periph, 205229997Sken union ccb *done_ccb); 206229997Sken 207229997Skenstatic void ctlfe_onoffline(void *arg, int online); 208229997Skenstatic void ctlfe_online(void *arg); 209229997Skenstatic void ctlfe_offline(void *arg); 210229997Skenstatic int ctlfe_targ_enable(void *arg, struct ctl_id targ_id); 211229997Skenstatic int ctlfe_targ_disable(void *arg, struct ctl_id targ_id); 212229997Skenstatic int ctlfe_lun_enable(void *arg, struct ctl_id targ_id, 213229997Sken int lun_id); 214229997Skenstatic int ctlfe_lun_disable(void *arg, struct ctl_id targ_id, 215229997Sken int lun_id); 216229997Skenstatic void ctlfe_dump_sim(struct cam_sim *sim); 217229997Skenstatic void ctlfe_dump_queue(struct ctlfe_lun_softc *softc); 218229997Skenstatic void ctlfe_dma_timeout(void *arg); 219229997Skenstatic void ctlfe_datamove_done(union ctl_io *io); 220229997Skenstatic void ctlfe_dump(void); 221229997Sken 222229997Skenstatic struct periph_driver ctlfe_driver = 223229997Sken{ 224229997Sken ctlfeinit, "ctl", 225229997Sken TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0 226229997Sken}; 227229997SkenPERIPHDRIVER_DECLARE(ctl, ctlfe_driver); 228229997Sken 229229997Skenextern struct ctl_softc *control_softc; 230229997Sken 231229997Skenint 232229997Skenctlfeinitialize(void) 233229997Sken{ 234229997Sken cam_status status; 235229997Sken 236229997Sken STAILQ_INIT(&ctlfe_softc_list); 237229997Sken 238229997Sken mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF); 239229997Sken 240229997Sken xpt_lock_buses(); 241229997Sken periphdriver_register(&ctlfe_driver); 242229997Sken xpt_unlock_buses(); 243229997Sken 244229997Sken status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED | 245229997Sken AC_CONTRACT, ctlfeasync, NULL, NULL); 246229997Sken 247229997Sken if (status != CAM_REQ_CMP) { 248229997Sken printf("ctl: Failed to attach async callback due to CAM " 249229997Sken "status 0x%x!\n", status); 250229997Sken } 251229997Sken 252229997Sken return (0); 253229997Sken} 254229997Sken 255229997Skenvoid 256229997Skenctlfeshutdown(void) 257229997Sken{ 258229997Sken return; 259229997Sken} 260229997Sken 261229997Skenvoid 262229997Skenctlfeinit(void) 263229997Sken{ 264229997Sken cam_status status; 265229997Sken 266229997Sken STAILQ_INIT(&ctlfe_softc_list); 267229997Sken 268229997Sken mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF); 269229997Sken 270229997Sken KASSERT(control_softc != NULL, ("CTL is not initialized!")); 271229997Sken 272229997Sken status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED | 273229997Sken AC_CONTRACT, ctlfeasync, NULL, NULL); 274229997Sken 275229997Sken if (status != CAM_REQ_CMP) { 276229997Sken printf("ctl: Failed to attach async callback due to CAM " 277229997Sken "status 0x%x!\n", status); 278229997Sken } 279229997Sken} 280229997Sken 281229997Skenstatic void 282229997Skenctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 283229997Sken{ 284229997Sken 285229997Sken#ifdef CTLFEDEBUG 286229997Sken printf("%s: entered\n", __func__); 287229997Sken#endif 288229997Sken 289229997Sken /* 290229997Sken * When a new path gets registered, and it is capable of target 291229997Sken * mode, go ahead and attach. Later on, we may need to be more 292229997Sken * selective, but for now this will be sufficient. 293229997Sken */ 294229997Sken switch (code) { 295229997Sken case AC_PATH_REGISTERED: { 296229997Sken struct ctl_frontend *fe; 297229997Sken struct ctlfe_softc *bus_softc; 298229997Sken struct ctlfe_lun_softc *lun_softc; 299229997Sken struct cam_path *path; 300229997Sken struct ccb_pathinq *cpi; 301229997Sken cam_status status; 302229997Sken int retval; 303229997Sken 304229997Sken cpi = (struct ccb_pathinq *)arg; 305229997Sken 306229997Sken /* Don't attach if it doesn't support target mode */ 307229997Sken if ((cpi->target_sprt & PIT_PROCESSOR) == 0) { 308230033Sken#ifdef CTLFEDEBUG 309229997Sken printf("%s: SIM %s%d doesn't support target mode\n", 310229997Sken __func__, cpi->dev_name, cpi->unit_number); 311230033Sken#endif 312229997Sken break; 313229997Sken } 314229997Sken 315229997Sken#ifdef CTLFE_INIT_ENABLE 316229997Sken if (ctlfe_num_targets >= ctlfe_max_targets) { 317229997Sken union ccb *ccb; 318229997Sken struct cam_sim *sim; 319229997Sken 320229997Sken ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, 321229997Sken M_NOWAIT | M_ZERO); 322229997Sken if (ccb == NULL) { 323229997Sken printf("%s: unable to malloc CCB!\n", __func__); 324229997Sken xpt_free_path(path); 325229997Sken return; 326229997Sken } 327229997Sken xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path, 328229997Sken /*priority*/ 1); 329229997Sken 330229997Sken sim = xpt_path_sim(cpi->ccb_h.path); 331229997Sken 332229997Sken ccb->ccb_h.func_code = XPT_SET_SIM_KNOB; 333229997Sken ccb->knob.xport_specific.valid = KNOB_VALID_ROLE; 334229997Sken ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR; 335229997Sken 336229997Sken /* We should hold the SIM lock here */ 337229997Sken mtx_assert(sim->mtx, MA_OWNED); 338229997Sken 339229997Sken xpt_action(ccb); 340229997Sken 341229997Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != 342229997Sken CAM_REQ_CMP) { 343229997Sken printf("%s: SIM %s%d (path id %d) initiator " 344229997Sken "enable failed with status %#x\n", 345229997Sken __func__, cpi->dev_name, 346229997Sken cpi->unit_number, cpi->ccb_h.path_id, 347229997Sken ccb->ccb_h.status); 348229997Sken } else { 349229997Sken printf("%s: SIM %s%d (path id %d) initiator " 350229997Sken "enable succeeded\n", 351229997Sken __func__, cpi->dev_name, 352229997Sken cpi->unit_number, cpi->ccb_h.path_id); 353229997Sken } 354229997Sken 355229997Sken free(ccb, M_TEMP); 356229997Sken 357229997Sken break; 358229997Sken } else { 359229997Sken ctlfe_num_targets++; 360229997Sken } 361229997Sken 362229997Sken printf("%s: ctlfe_num_targets = %d\n", __func__, 363229997Sken ctlfe_num_targets); 364229997Sken#endif /* CTLFE_INIT_ENABLE */ 365229997Sken 366229997Sken /* 367229997Sken * We're in an interrupt context here, so we have to 368229997Sken * use M_NOWAIT. Of course this means trouble if we 369229997Sken * can't allocate memory. 370229997Sken */ 371229997Sken bus_softc = malloc(sizeof(*bus_softc), M_CTLFE, 372229997Sken M_NOWAIT | M_ZERO); 373229997Sken if (bus_softc == NULL) { 374229997Sken printf("%s: unable to malloc %zd bytes for softc\n", 375229997Sken __func__, sizeof(*bus_softc)); 376229997Sken return; 377229997Sken } 378229997Sken 379229997Sken bus_softc->path_id = cpi->ccb_h.path_id; 380229997Sken bus_softc->sim = xpt_path_sim(cpi->ccb_h.path); 381229997Sken STAILQ_INIT(&bus_softc->lun_softc_list); 382229997Sken 383229997Sken fe = &bus_softc->fe; 384229997Sken 385229997Sken /* 386229997Sken * XXX KDM should we be more accurate here ? 387229997Sken */ 388229997Sken if (cpi->transport == XPORT_FC) 389229997Sken fe->port_type = CTL_PORT_FC; 390229997Sken else 391229997Sken fe->port_type = CTL_PORT_SCSI; 392229997Sken 393229997Sken /* XXX KDM what should the real number be here? */ 394229997Sken fe->num_requested_ctl_io = 4096; 395229997Sken snprintf(bus_softc->port_name, sizeof(bus_softc->port_name), 396229997Sken "%s%d", cpi->dev_name, cpi->unit_number); 397229997Sken /* 398229997Sken * XXX KDM it would be nice to allocate storage in the 399229997Sken * frontend structure itself. 400229997Sken */ 401229997Sken fe->port_name = bus_softc->port_name; 402229997Sken fe->physical_port = cpi->unit_number; 403229997Sken fe->virtual_port = cpi->bus_id; 404229997Sken fe->port_online = ctlfe_online; 405229997Sken fe->port_offline = ctlfe_offline; 406229997Sken fe->onoff_arg = bus_softc; 407229997Sken fe->targ_enable = ctlfe_targ_enable; 408229997Sken fe->targ_disable = ctlfe_targ_disable; 409229997Sken fe->lun_enable = ctlfe_lun_enable; 410229997Sken fe->lun_disable = ctlfe_lun_disable; 411229997Sken fe->targ_lun_arg = bus_softc; 412229997Sken fe->fe_datamove = ctlfe_datamove_done; 413229997Sken fe->fe_done = ctlfe_datamove_done; 414229997Sken fe->fe_dump = ctlfe_dump; 415229997Sken /* 416229997Sken * XXX KDM the path inquiry doesn't give us the maximum 417229997Sken * number of targets supported. 418229997Sken */ 419229997Sken fe->max_targets = cpi->max_target; 420229997Sken fe->max_target_id = cpi->max_target; 421229997Sken 422229997Sken /* 423229997Sken * XXX KDM need to figure out whether we're the master or 424229997Sken * slave. 425229997Sken */ 426230033Sken#ifdef CTLFEDEBUG 427229997Sken printf("%s: calling ctl_frontend_register() for %s%d\n", 428229997Sken __func__, cpi->dev_name, cpi->unit_number); 429230033Sken#endif 430229997Sken retval = ctl_frontend_register(fe, /*master_SC*/ 1); 431229997Sken if (retval != 0) { 432229997Sken printf("%s: ctl_frontend_register() failed with " 433229997Sken "error %d!\n", __func__, retval); 434229997Sken free(bus_softc, M_CTLFE); 435229997Sken break; 436229997Sken } else { 437229997Sken mtx_lock(&ctlfe_list_mtx); 438229997Sken STAILQ_INSERT_TAIL(&ctlfe_softc_list, bus_softc, links); 439229997Sken mtx_unlock(&ctlfe_list_mtx); 440229997Sken } 441229997Sken 442229997Sken status = xpt_create_path(&path, /*periph*/ NULL, 443229997Sken bus_softc->path_id,CAM_TARGET_WILDCARD, 444229997Sken CAM_LUN_WILDCARD); 445229997Sken if (status != CAM_REQ_CMP) { 446229997Sken printf("%s: unable to create path for wildcard " 447229997Sken "periph\n", __func__); 448229997Sken break; 449229997Sken } 450229997Sken lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, 451229997Sken M_NOWAIT | M_ZERO); 452229997Sken if (lun_softc == NULL) { 453229997Sken xpt_print(path, "%s: unable to allocate softc for " 454229997Sken "wildcard periph\n", __func__); 455229997Sken xpt_free_path(path); 456229997Sken break; 457229997Sken } 458229997Sken 459229997Sken lun_softc->parent_softc = bus_softc; 460229997Sken lun_softc->flags |= CTLFE_LUN_WILDCARD; 461229997Sken 462229997Sken status = cam_periph_alloc(ctlferegister, 463229997Sken ctlfeoninvalidate, 464229997Sken ctlfecleanup, 465229997Sken ctlfestart, 466229997Sken "ctl", 467229997Sken CAM_PERIPH_BIO, 468229997Sken path, 469229997Sken ctlfeasync, 470229997Sken 0, 471229997Sken lun_softc); 472229997Sken 473229997Sken xpt_free_path(path); 474229997Sken 475229997Sken break; 476229997Sken } 477229997Sken case AC_PATH_DEREGISTERED: 478229997Sken /* ctl_frontend_deregister() */ 479229997Sken break; 480229997Sken case AC_CONTRACT: { 481229997Sken struct ac_contract *ac; 482229997Sken 483229997Sken ac = (struct ac_contract *)arg; 484229997Sken 485229997Sken switch (ac->contract_number) { 486229997Sken case AC_CONTRACT_DEV_CHG: { 487229997Sken struct ac_device_changed *dev_chg; 488229997Sken struct ctlfe_softc *softc; 489229997Sken int retval, found; 490229997Sken 491229997Sken dev_chg = (struct ac_device_changed *)ac->contract_data; 492229997Sken 493236426Smjacob printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n", 494229997Sken __func__, dev_chg->wwpn, dev_chg->port, 495229997Sken xpt_path_path_id(path), dev_chg->target, 496229997Sken (dev_chg->arrived == 0) ? "left" : "arrived"); 497229997Sken 498229997Sken found = 0; 499229997Sken 500229997Sken mtx_lock(&ctlfe_list_mtx); 501229997Sken STAILQ_FOREACH(softc, &ctlfe_softc_list, links) { 502229997Sken if (softc->path_id == xpt_path_path_id(path)) { 503229997Sken found = 1; 504229997Sken break; 505229997Sken } 506229997Sken } 507229997Sken mtx_unlock(&ctlfe_list_mtx); 508229997Sken 509229997Sken if (found == 0) { 510229997Sken printf("%s: CTL port for CAM path %u not " 511229997Sken "found!\n", __func__, 512229997Sken xpt_path_path_id(path)); 513229997Sken break; 514229997Sken } 515229997Sken if (dev_chg->arrived != 0) { 516229997Sken retval = ctl_add_initiator(dev_chg->wwpn, 517229997Sken softc->fe.targ_port, dev_chg->target); 518229997Sken } else { 519229997Sken retval = ctl_remove_initiator( 520229997Sken softc->fe.targ_port, dev_chg->target); 521229997Sken } 522229997Sken 523229997Sken if (retval != 0) { 524229997Sken printf("%s: could not %s port %d iid %u " 525229997Sken "WWPN %#jx!\n", __func__, 526229997Sken (dev_chg->arrived != 0) ? "add" : 527229997Sken "remove", softc->fe.targ_port, 528229997Sken dev_chg->target, 529229997Sken (uintmax_t)dev_chg->wwpn); 530229997Sken } 531229997Sken break; 532229997Sken } 533229997Sken default: 534229997Sken printf("%s: unsupported contract number %ju\n", 535229997Sken __func__, (uintmax_t)ac->contract_number); 536229997Sken break; 537229997Sken } 538229997Sken break; 539229997Sken } 540229997Sken default: 541229997Sken break; 542229997Sken } 543229997Sken} 544229997Sken 545229997Skenstatic cam_status 546229997Skenctlferegister(struct cam_periph *periph, void *arg) 547229997Sken{ 548229997Sken struct ctlfe_softc *bus_softc; 549229997Sken struct ctlfe_lun_softc *softc; 550229997Sken struct cam_sim *sim; 551229997Sken union ccb en_lun_ccb; 552229997Sken cam_status status; 553229997Sken int i; 554229997Sken 555229997Sken softc = (struct ctlfe_lun_softc *)arg; 556229997Sken bus_softc = softc->parent_softc; 557229997Sken sim = xpt_path_sim(periph->path); 558229997Sken 559229997Sken TAILQ_INIT(&softc->work_queue); 560229997Sken softc->periph = periph; 561229997Sken softc->parent_softc = bus_softc; 562229997Sken 563229997Sken callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0); 564229997Sken periph->softc = softc; 565229997Sken 566229997Sken xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, /*priority*/ 1); 567229997Sken en_lun_ccb.ccb_h.func_code = XPT_EN_LUN; 568229997Sken en_lun_ccb.cel.grp6_len = 0; 569229997Sken en_lun_ccb.cel.grp7_len = 0; 570229997Sken en_lun_ccb.cel.enable = 1; 571229997Sken xpt_action(&en_lun_ccb); 572229997Sken status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK); 573229997Sken if (status != CAM_REQ_CMP) { 574229997Sken xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n", 575229997Sken __func__, en_lun_ccb.ccb_h.status); 576229997Sken return (status); 577229997Sken } 578229997Sken 579229997Sken status = CAM_REQ_CMP; 580229997Sken 581229997Sken for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) { 582229997Sken union ccb *new_ccb; 583229997Sken 584229997Sken new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE, 585236426Smjacob M_ZERO|M_NOWAIT); 586229997Sken if (new_ccb == NULL) { 587229997Sken status = CAM_RESRC_UNAVAIL; 588229997Sken break; 589229997Sken } 590229997Sken xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); 591229997Sken new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO; 592229997Sken new_ccb->ccb_h.cbfcnp = ctlfedone; 593229997Sken xpt_action(new_ccb); 594229997Sken softc->atios_sent++; 595229997Sken status = new_ccb->ccb_h.status; 596229997Sken if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 597229997Sken free(new_ccb, M_CTLFE); 598229997Sken break; 599229997Sken } 600229997Sken } 601229997Sken 602229997Sken status = cam_periph_acquire(periph); 603229997Sken if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 604229997Sken xpt_print(periph->path, "%s: could not acquire reference " 605229997Sken "count, status = %#x\n", __func__, status); 606229997Sken return (status); 607229997Sken } 608229997Sken 609229997Sken if (i == 0) { 610229997Sken xpt_print(periph->path, "%s: could not allocate ATIO CCBs, " 611229997Sken "status 0x%x\n", __func__, status); 612229997Sken return (CAM_REQ_CMP_ERR); 613229997Sken } 614229997Sken 615229997Sken for (i = 0; i < CTLFE_IN_PER_LUN; i++) { 616229997Sken union ccb *new_ccb; 617229997Sken 618229997Sken new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE, 619236426Smjacob M_ZERO|M_NOWAIT); 620229997Sken if (new_ccb == NULL) { 621229997Sken status = CAM_RESRC_UNAVAIL; 622229997Sken break; 623229997Sken } 624229997Sken 625229997Sken xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1); 626229997Sken new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; 627229997Sken new_ccb->ccb_h.cbfcnp = ctlfedone; 628229997Sken xpt_action(new_ccb); 629229997Sken softc->inots_sent++; 630229997Sken status = new_ccb->ccb_h.status; 631229997Sken if (status != CAM_REQ_INPROG) { 632229997Sken free(new_ccb, M_CTLFE); 633229997Sken break; 634229997Sken } 635229997Sken } 636229997Sken if (i == 0) { 637229997Sken xpt_print(periph->path, "%s: could not allocate immediate " 638229997Sken "notify CCBs, status 0x%x\n", __func__, status); 639229997Sken return (CAM_REQ_CMP_ERR); 640229997Sken } 641229997Sken return (CAM_REQ_CMP); 642229997Sken} 643229997Sken 644229997Skenstatic void 645229997Skenctlfeoninvalidate(struct cam_periph *periph) 646229997Sken{ 647229997Sken union ccb en_lun_ccb; 648229997Sken cam_status status; 649229997Sken struct ctlfe_lun_softc *softc; 650229997Sken 651229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 652229997Sken 653229997Sken xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, /*priority*/ 1); 654229997Sken en_lun_ccb.ccb_h.func_code = XPT_EN_LUN; 655229997Sken en_lun_ccb.cel.grp6_len = 0; 656229997Sken en_lun_ccb.cel.grp7_len = 0; 657229997Sken en_lun_ccb.cel.enable = 0; 658229997Sken xpt_action(&en_lun_ccb); 659229997Sken status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK); 660229997Sken if (status != CAM_REQ_CMP) { 661229997Sken xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n", 662229997Sken __func__, en_lun_ccb.ccb_h.status); 663229997Sken /* 664229997Sken * XXX KDM what do we do now? 665229997Sken */ 666229997Sken } 667229997Sken xpt_print(periph->path, "LUN removed, %ju ATIOs outstanding, %ju " 668229997Sken "INOTs outstanding, %d refs\n", softc->atios_sent - 669229997Sken softc->atios_returned, softc->inots_sent - 670229997Sken softc->inots_returned, periph->refcount); 671229997Sken} 672229997Sken 673229997Skenstatic void 674229997Skenctlfecleanup(struct cam_periph *periph) 675229997Sken{ 676229997Sken struct ctlfe_lun_softc *softc; 677229997Sken struct ctlfe_softc *bus_softc; 678229997Sken 679229997Sken xpt_print(periph->path, "%s: Called\n", __func__); 680229997Sken 681229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 682229997Sken bus_softc = softc->parent_softc; 683229997Sken 684229997Sken STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc,links); 685229997Sken 686229997Sken /* 687229997Sken * XXX KDM is there anything else that needs to be done here? 688229997Sken */ 689229997Sken free(softc, M_CTLFE); 690229997Sken} 691229997Sken 692229997Skenstatic void 693229997Skenctlfestart(struct cam_periph *periph, union ccb *start_ccb) 694229997Sken{ 695229997Sken struct ctlfe_lun_softc *softc; 696229997Sken struct ccb_hdr *ccb_h; 697229997Sken 698229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 699229997Sken 700229997Sken softc->ccbs_alloced++; 701229997Sken 702229997Sken ccb_h = TAILQ_FIRST(&softc->work_queue); 703229997Sken if (periph->immediate_priority <= periph->pinfo.priority) { 704229997Sken panic("shouldn't get to the CCB waiting case!"); 705229997Sken start_ccb->ccb_h.ccb_type = CTLFE_CCB_WAITING; 706229997Sken SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 707229997Sken periph_links.sle); 708229997Sken periph->immediate_priority = CAM_PRIORITY_NONE; 709229997Sken wakeup(&periph->ccb_list); 710229997Sken } else if (ccb_h == NULL) { 711229997Sken softc->ccbs_freed++; 712229997Sken xpt_release_ccb(start_ccb); 713229997Sken } else { 714229997Sken struct ccb_accept_tio *atio; 715229997Sken struct ccb_scsiio *csio; 716229997Sken uint8_t *data_ptr; 717229997Sken uint32_t dxfer_len; 718229997Sken ccb_flags flags; 719229997Sken union ctl_io *io; 720229997Sken uint8_t scsi_status; 721229997Sken 722229997Sken /* Take the ATIO off the work queue */ 723229997Sken TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe); 724229997Sken atio = (struct ccb_accept_tio *)ccb_h; 725229997Sken io = (union ctl_io *)ccb_h->io_ptr; 726229997Sken csio = &start_ccb->csio; 727229997Sken 728229997Sken flags = atio->ccb_h.flags & 729229997Sken (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); 730229997Sken 731229997Sken if ((io == NULL) 732229997Sken || (io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) { 733229997Sken /* 734229997Sken * We're done, send status back. 735229997Sken */ 736229997Sken flags |= CAM_SEND_STATUS; 737229997Sken if (io == NULL) { 738229997Sken scsi_status = SCSI_STATUS_BUSY; 739229997Sken csio->sense_len = 0; 740229997Sken } else if ((io->io_hdr.status & CTL_STATUS_MASK) == 741229997Sken CTL_CMD_ABORTED) { 742229997Sken io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; 743229997Sken 744229997Sken /* 745229997Sken * If this command was aborted, we don't 746229997Sken * need to send status back to the SIM. 747229997Sken * Just free the CTIO and ctl_io, and 748229997Sken * recycle the ATIO back to the SIM. 749229997Sken */ 750229997Sken xpt_print(periph->path, "%s: aborted " 751229997Sken "command 0x%04x discarded\n", 752229997Sken __func__, io->scsiio.tag_num); 753229997Sken ctl_free_io(io); 754229997Sken /* 755229997Sken * For a wildcard attachment, commands can 756229997Sken * come in with a specific target/lun. Reset 757229997Sken * the target and LUN fields back to the 758229997Sken * wildcard values before we send them back 759229997Sken * down to the SIM. The SIM has a wildcard 760229997Sken * LUN enabled, not whatever target/lun 761229997Sken * these happened to be. 762229997Sken */ 763229997Sken if (softc->flags & CTLFE_LUN_WILDCARD) { 764229997Sken atio->ccb_h.target_id = 765229997Sken CAM_TARGET_WILDCARD; 766229997Sken atio->ccb_h.target_lun = 767229997Sken CAM_LUN_WILDCARD; 768229997Sken } 769229997Sken 770229997Sken if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { 771229997Sken cam_release_devq(periph->path, 772229997Sken /*relsim_flags*/0, 773229997Sken /*reduction*/0, 774229997Sken /*timeout*/0, 775229997Sken /*getcount_only*/0); 776229997Sken atio->ccb_h.status &= ~CAM_DEV_QFRZN; 777229997Sken } 778229997Sken 779229997Sken ccb_h = TAILQ_FIRST(&softc->work_queue); 780229997Sken 781229997Sken if (atio->ccb_h.func_code != 782229997Sken XPT_ACCEPT_TARGET_IO) { 783229997Sken xpt_print(periph->path, "%s: func_code " 784229997Sken "is %#x\n", __func__, 785229997Sken atio->ccb_h.func_code); 786229997Sken } 787229997Sken start_ccb->ccb_h.func_code = XPT_ABORT; 788229997Sken start_ccb->cab.abort_ccb = (union ccb *)atio; 789229997Sken start_ccb->ccb_h.cbfcnp = ctlfedone; 790229997Sken 791229997Sken /* Tell the SIM that we've aborted this ATIO */ 792229997Sken xpt_action(start_ccb); 793229997Sken softc->ccbs_freed++; 794229997Sken xpt_release_ccb(start_ccb); 795229997Sken 796229997Sken /* 797229997Sken * Send the ATIO back down to the SIM. 798229997Sken */ 799229997Sken xpt_action((union ccb *)atio); 800229997Sken softc->atios_sent++; 801229997Sken 802229997Sken /* 803229997Sken * If we still have work to do, ask for 804229997Sken * another CCB. Otherwise, deactivate our 805229997Sken * callout. 806229997Sken */ 807229997Sken if (ccb_h != NULL) 808229997Sken xpt_schedule(periph, /*priority*/ 1); 809229997Sken else 810229997Sken callout_stop(&softc->dma_callout); 811229997Sken 812229997Sken return; 813229997Sken } else { 814229997Sken io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; 815229997Sken scsi_status = io->scsiio.scsi_status; 816229997Sken csio->sense_len = io->scsiio.sense_len; 817229997Sken } 818229997Sken data_ptr = NULL; 819229997Sken dxfer_len = 0; 820229997Sken if (io == NULL) { 821229997Sken printf("%s: tag %04x io is NULL\n", __func__, 822229997Sken atio->tag_id); 823229997Sken } else { 824229997Sken#ifdef CTLFEDEBUG 825229997Sken printf("%s: tag %04x status %x\n", __func__, 826229997Sken atio->tag_id, io->io_hdr.status); 827229997Sken#endif 828229997Sken } 829229997Sken csio->sglist_cnt = 0; 830229997Sken if (csio->sense_len != 0) { 831229997Sken csio->sense_data = io->scsiio.sense_data; 832229997Sken flags |= CAM_SEND_SENSE; 833229997Sken } else if (scsi_status == SCSI_STATUS_CHECK_COND) { 834229997Sken xpt_print(periph->path, "%s: check condition " 835229997Sken "with no sense\n", __func__); 836229997Sken } 837229997Sken } else { 838229997Sken struct ctlfe_lun_cmd_info *cmd_info; 839229997Sken 840229997Sken /* 841229997Sken * Datamove call, we need to setup the S/G list. 842229997Sken * If we pass in a S/G list, the isp(4) driver at 843229997Sken * least expects physical/bus addresses. 844229997Sken */ 845229997Sken 846229997Sken cmd_info = (struct ctlfe_lun_cmd_info *) 847229997Sken io->io_hdr.port_priv; 848229997Sken 849229997Sken KASSERT(sizeof(*cmd_info) < CTL_PORT_PRIV_SIZE, 850229997Sken ("%s: sizeof(struct ctlfe_lun_cmd_info) %zd < " 851229997Sken "CTL_PORT_PRIV_SIZE %d", __func__, 852229997Sken sizeof(*cmd_info), CTL_PORT_PRIV_SIZE)); 853229997Sken io->io_hdr.flags &= ~CTL_FLAG_DMA_QUEUED; 854229997Sken 855229997Sken /* 856229997Sken * Need to zero this, in case it has been used for 857229997Sken * a previous datamove for this particular I/O. 858229997Sken */ 859229997Sken bzero(cmd_info, sizeof(*cmd_info)); 860229997Sken scsi_status = 0; 861229997Sken 862229997Sken /* 863229997Sken * Set the direction, relative to the initiator. 864229997Sken */ 865229997Sken flags &= ~CAM_DIR_MASK; 866229997Sken if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == 867229997Sken CTL_FLAG_DATA_IN) 868229997Sken flags |= CAM_DIR_IN; 869229997Sken else 870229997Sken flags |= CAM_DIR_OUT; 871229997Sken 872229997Sken csio->cdb_len = atio->cdb_len; 873229997Sken 874229997Sken if (io->scsiio.kern_sg_entries == 0) { 875229997Sken /* No S/G list */ 876229997Sken data_ptr = io->scsiio.kern_data_ptr; 877229997Sken dxfer_len = io->scsiio.kern_data_len; 878229997Sken csio->sglist_cnt = 0; 879229997Sken 880229997Sken if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) 881229997Sken flags |= CAM_DATA_PHYS; 882229997Sken } else if (io->scsiio.kern_sg_entries <= 883229997Sken (sizeof(cmd_info->cam_sglist)/ 884229997Sken sizeof(cmd_info->cam_sglist[0]))) { 885229997Sken /* 886229997Sken * S/G list with physical or virtual pointers. 887229997Sken * Just populate the CAM S/G list with the 888229997Sken * pointers. 889229997Sken */ 890229997Sken int i; 891229997Sken struct ctl_sg_entry *ctl_sglist; 892229997Sken bus_dma_segment_t *cam_sglist; 893229997Sken 894229997Sken ctl_sglist = (struct ctl_sg_entry *) 895229997Sken io->scsiio.kern_data_ptr; 896229997Sken cam_sglist = cmd_info->cam_sglist; 897229997Sken 898229997Sken for (i = 0; i < io->scsiio.kern_sg_entries;i++){ 899229997Sken cam_sglist[i].ds_addr = 900229997Sken (bus_addr_t)ctl_sglist[i].addr; 901229997Sken cam_sglist[i].ds_len = 902229997Sken ctl_sglist[i].len; 903229997Sken } 904229997Sken csio->sglist_cnt = io->scsiio.kern_sg_entries; 905229997Sken flags |= CAM_SCATTER_VALID; 906229997Sken if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) 907229997Sken flags |= CAM_SG_LIST_PHYS; 908229997Sken else 909229997Sken flags &= ~CAM_SG_LIST_PHYS; 910229997Sken data_ptr = (uint8_t *)cam_sglist; 911229997Sken dxfer_len = io->scsiio.kern_data_len; 912229997Sken } else { 913229997Sken /* S/G list with virtual pointers */ 914229997Sken struct ctl_sg_entry *sglist; 915229997Sken int *ti; 916229997Sken 917229997Sken /* 918229997Sken * XXX KDM this is a temporary hack. The 919229997Sken * isp(4) driver can't deal with S/G lists 920229997Sken * with virtual pointers, so we need to 921229997Sken * go through and send down one virtual 922229997Sken * pointer at a time. 923229997Sken */ 924229997Sken sglist = (struct ctl_sg_entry *) 925229997Sken io->scsiio.kern_data_ptr; 926229997Sken ti = &cmd_info->cur_transfer_index; 927229997Sken data_ptr = sglist[*ti].addr; 928229997Sken dxfer_len = sglist[*ti].len; 929229997Sken csio->sglist_cnt = 0; 930229997Sken cmd_info->flags |= CTLFE_CMD_PIECEWISE; 931229997Sken (*ti)++; 932229997Sken } 933229997Sken 934229997Sken io->scsiio.ext_data_filled += dxfer_len; 935229997Sken 936229997Sken if (io->scsiio.ext_data_filled > 937229997Sken io->scsiio.kern_total_len) { 938229997Sken xpt_print(periph->path, "%s: tag 0x%04x " 939229997Sken "fill len %u > total %u\n", 940229997Sken __func__, io->scsiio.tag_num, 941229997Sken io->scsiio.ext_data_filled, 942229997Sken io->scsiio.kern_total_len); 943229997Sken } 944229997Sken } 945229997Sken 946229997Sken#ifdef CTLFEDEBUG 947229997Sken printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__, 948229997Sken (flags & CAM_SEND_STATUS) ? "done" : "datamove", 949229997Sken atio->tag_id, flags, data_ptr, dxfer_len); 950229997Sken#endif 951229997Sken 952229997Sken /* 953229997Sken * Valid combinations: 954229997Sken * - CAM_SEND_STATUS, SCATTER_VALID = 0, dxfer_len = 0, 955229997Sken * sglist_cnt = 0 956229997Sken * - CAM_SEND_STATUS = 0, SCATTER_VALID = 0, dxfer_len != 0, 957229997Sken * sglist_cnt = 0 958229997Sken * - CAM_SEND_STATUS = 0, SCATTER_VALID, dxfer_len != 0, 959229997Sken * sglist_cnt != 0 960229997Sken */ 961229997Sken#ifdef CTLFEDEBUG 962229997Sken if (((flags & CAM_SEND_STATUS) 963229997Sken && (((flags & CAM_SCATTER_VALID) != 0) 964229997Sken || (dxfer_len != 0) 965229997Sken || (csio->sglist_cnt != 0))) 966229997Sken || (((flags & CAM_SEND_STATUS) == 0) 967229997Sken && (dxfer_len == 0)) 968229997Sken || ((flags & CAM_SCATTER_VALID) 969229997Sken && (csio->sglist_cnt == 0)) 970229997Sken || (((flags & CAM_SCATTER_VALID) == 0) 971229997Sken && (csio->sglist_cnt != 0))) { 972229997Sken printf("%s: tag %04x cdb %02x flags %#x dxfer_len " 973229997Sken "%d sg %u\n", __func__, atio->tag_id, 974229997Sken atio->cdb_io.cdb_bytes[0], flags, dxfer_len, 975229997Sken csio->sglist_cnt); 976229997Sken if (io != NULL) { 977229997Sken printf("%s: tag %04x io status %#x\n", __func__, 978229997Sken atio->tag_id, io->io_hdr.status); 979229997Sken } else { 980229997Sken printf("%s: tag %04x no associated io\n", 981229997Sken __func__, atio->tag_id); 982229997Sken } 983229997Sken } 984229997Sken#endif 985229997Sken cam_fill_ctio(csio, 986229997Sken /*retries*/ 2, 987229997Sken ctlfedone, 988229997Sken flags, 989229997Sken (flags & CAM_TAG_ACTION_VALID) ? 990229997Sken MSG_SIMPLE_Q_TAG : 0, 991229997Sken atio->tag_id, 992229997Sken atio->init_id, 993229997Sken scsi_status, 994229997Sken /*data_ptr*/ data_ptr, 995229997Sken /*dxfer_len*/ dxfer_len, 996229997Sken /*timeout*/ 5 * 1000); 997229997Sken start_ccb->ccb_h.ccb_atio = atio; 998229997Sken if (((flags & CAM_SEND_STATUS) == 0) 999229997Sken && (io != NULL)) 1000229997Sken io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; 1001229997Sken 1002229997Sken softc->ctios_sent++; 1003229997Sken 1004229997Sken xpt_action(start_ccb); 1005229997Sken 1006229997Sken if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { 1007229997Sken cam_release_devq(periph->path, 1008229997Sken /*relsim_flags*/0, 1009229997Sken /*reduction*/0, 1010229997Sken /*timeout*/0, 1011229997Sken /*getcount_only*/0); 1012229997Sken atio->ccb_h.status &= ~CAM_DEV_QFRZN; 1013229997Sken } 1014229997Sken 1015229997Sken ccb_h = TAILQ_FIRST(&softc->work_queue); 1016229997Sken } 1017229997Sken /* 1018229997Sken * If we still have work to do, ask for another CCB. Otherwise, 1019229997Sken * deactivate our callout. 1020229997Sken */ 1021229997Sken if (ccb_h != NULL) 1022229997Sken xpt_schedule(periph, /*priority*/ 1); 1023229997Sken else 1024229997Sken callout_stop(&softc->dma_callout); 1025229997Sken} 1026229997Sken 1027229997Skenstatic void 1028229997Skenctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb) 1029229997Sken{ 1030229997Sken struct ctlfe_lun_softc *softc; 1031229997Sken 1032229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 1033229997Sken 1034229997Sken switch (ccb->ccb_h.func_code) { 1035229997Sken case XPT_ACCEPT_TARGET_IO: 1036229997Sken softc->atios_returned++; 1037229997Sken break; 1038229997Sken case XPT_IMMEDIATE_NOTIFY: 1039229997Sken case XPT_NOTIFY_ACKNOWLEDGE: 1040229997Sken softc->inots_returned++; 1041229997Sken break; 1042229997Sken default: 1043229997Sken break; 1044229997Sken } 1045229997Sken 1046229997Sken free(ccb, M_CTLFE); 1047229997Sken 1048229997Sken KASSERT(softc->atios_returned <= softc->atios_sent, ("%s: " 1049229997Sken "atios_returned %ju > atios_sent %ju", __func__, 1050229997Sken softc->atios_returned, softc->atios_sent)); 1051229997Sken KASSERT(softc->inots_returned <= softc->inots_sent, ("%s: " 1052229997Sken "inots_returned %ju > inots_sent %ju", __func__, 1053229997Sken softc->inots_returned, softc->inots_sent)); 1054229997Sken 1055229997Sken /* 1056229997Sken * If we have received all of our CCBs, we can release our 1057229997Sken * reference on the peripheral driver. It will probably go away 1058229997Sken * now. 1059229997Sken */ 1060229997Sken if ((softc->atios_returned == softc->atios_sent) 1061229997Sken && (softc->inots_returned == softc->inots_sent)) { 1062229997Sken cam_periph_release_locked(periph); 1063229997Sken } 1064229997Sken} 1065229997Sken 1066229997Skenstatic void 1067229997Skenctlfedone(struct cam_periph *periph, union ccb *done_ccb) 1068229997Sken{ 1069229997Sken struct ctlfe_lun_softc *softc; 1070229997Sken struct ctlfe_softc *bus_softc; 1071229997Sken 1072229997Sken#ifdef CTLFE_DEBUG 1073229997Sken printf("%s: entered, func_code = %#x, type = %#lx\n", __func__, 1074229997Sken done_ccb->ccb_h.func_code, done_ccb->ccb_h.ccb_type); 1075229997Sken#endif 1076229997Sken 1077229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 1078229997Sken bus_softc = softc->parent_softc; 1079229997Sken 1080229997Sken if (done_ccb->ccb_h.ccb_type == CTLFE_CCB_WAITING) { 1081229997Sken panic("shouldn't get to the CCB waiting case!"); 1082229997Sken wakeup(&done_ccb->ccb_h.cbfcnp); 1083229997Sken return; 1084229997Sken } 1085229997Sken 1086229997Sken /* 1087229997Sken * If the peripheral is invalid, ATIOs and immediate notify CCBs 1088229997Sken * need to be freed. Most of the ATIOs and INOTs that come back 1089229997Sken * will be CCBs that are being returned from the SIM as a result of 1090229997Sken * our disabling the LUN. 1091229997Sken * 1092229997Sken * Other CCB types are handled in their respective cases below. 1093229997Sken */ 1094229997Sken if (periph->flags & CAM_PERIPH_INVALID) { 1095229997Sken switch (done_ccb->ccb_h.func_code) { 1096229997Sken case XPT_ACCEPT_TARGET_IO: 1097229997Sken case XPT_IMMEDIATE_NOTIFY: 1098229997Sken case XPT_NOTIFY_ACKNOWLEDGE: 1099229997Sken ctlfe_free_ccb(periph, done_ccb); 1100229997Sken return; 1101229997Sken default: 1102229997Sken break; 1103229997Sken } 1104229997Sken 1105229997Sken } 1106229997Sken switch (done_ccb->ccb_h.func_code) { 1107229997Sken case XPT_ACCEPT_TARGET_IO: { 1108229997Sken union ctl_io *io; 1109229997Sken struct ccb_accept_tio *atio; 1110229997Sken 1111229997Sken atio = &done_ccb->atio; 1112229997Sken 1113229997Sken softc->atios_returned++; 1114229997Sken 1115229997Sken /* 1116229997Sken * Allocate a ctl_io, pass it to CTL, and wait for the 1117229997Sken * datamove or done. 1118229997Sken */ 1119229997Sken io = ctl_alloc_io(bus_softc->fe.ctl_pool_ref); 1120229997Sken if (io == NULL) { 1121229997Sken atio->ccb_h.flags &= ~CAM_DIR_MASK; 1122229997Sken atio->ccb_h.flags |= CAM_DIR_NONE; 1123229997Sken 1124229997Sken printf("%s: ctl_alloc_io failed!\n", __func__); 1125229997Sken 1126229997Sken /* 1127229997Sken * XXX KDM need to set SCSI_STATUS_BUSY, but there 1128229997Sken * is no field in the ATIO structure to do that, 1129229997Sken * and we aren't able to allocate a ctl_io here. 1130229997Sken * What to do? 1131229997Sken */ 1132229997Sken atio->sense_len = 0; 1133229997Sken done_ccb->ccb_h.io_ptr = NULL; 1134229997Sken TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h, 1135229997Sken periph_links.tqe); 1136229997Sken xpt_schedule(periph, /*priority*/ 1); 1137229997Sken break; 1138229997Sken } 1139229997Sken ctl_zero_io(io); 1140229997Sken 1141229997Sken /* Save pointers on both sides */ 1142229997Sken io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = done_ccb; 1143229997Sken done_ccb->ccb_h.io_ptr = io; 1144229997Sken 1145229997Sken /* 1146229997Sken * Only SCSI I/O comes down this path, resets, etc. come 1147229997Sken * down the immediate notify path below. 1148229997Sken */ 1149229997Sken io->io_hdr.io_type = CTL_IO_SCSI; 1150229997Sken io->io_hdr.nexus.initid.id = atio->init_id; 1151229997Sken io->io_hdr.nexus.targ_port = bus_softc->fe.targ_port; 1152229997Sken io->io_hdr.nexus.targ_target.id = atio->ccb_h.target_id; 1153229997Sken io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun; 1154229997Sken io->scsiio.tag_num = atio->tag_id; 1155229997Sken switch (atio->tag_action) { 1156229997Sken case CAM_TAG_ACTION_NONE: 1157229997Sken io->scsiio.tag_type = CTL_TAG_UNTAGGED; 1158229997Sken break; 1159229997Sken case MSG_SIMPLE_TASK: 1160229997Sken io->scsiio.tag_type = CTL_TAG_SIMPLE; 1161229997Sken break; 1162229997Sken case MSG_HEAD_OF_QUEUE_TASK: 1163229997Sken io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE; 1164229997Sken break; 1165229997Sken case MSG_ORDERED_TASK: 1166229997Sken io->scsiio.tag_type = CTL_TAG_ORDERED; 1167229997Sken break; 1168229997Sken case MSG_ACA_TASK: 1169229997Sken io->scsiio.tag_type = CTL_TAG_ACA; 1170229997Sken break; 1171229997Sken default: 1172229997Sken io->scsiio.tag_type = CTL_TAG_UNTAGGED; 1173229997Sken printf("%s: unhandled tag type %#x!!\n", __func__, 1174229997Sken atio->tag_action); 1175229997Sken break; 1176229997Sken } 1177229997Sken if (atio->cdb_len > sizeof(io->scsiio.cdb)) { 1178229997Sken printf("%s: WARNING: CDB len %d > ctl_io space %zd\n", 1179229997Sken __func__, atio->cdb_len, sizeof(io->scsiio.cdb)); 1180229997Sken } 1181229997Sken io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb)); 1182229997Sken bcopy(atio->cdb_io.cdb_bytes, io->scsiio.cdb, 1183229997Sken io->scsiio.cdb_len); 1184229997Sken 1185229997Sken#ifdef CTLFEDEBUG 1186229997Sken printf("%s: %ju:%d:%ju:%d: tag %04x CDB %02x\n", __func__, 1187229997Sken (uintmax_t)io->io_hdr.nexus.initid.id, 1188229997Sken io->io_hdr.nexus.targ_port, 1189229997Sken (uintmax_t)io->io_hdr.nexus.targ_target.id, 1190229997Sken io->io_hdr.nexus.targ_lun, 1191229997Sken io->scsiio.tag_num, io->scsiio.cdb[0]); 1192229997Sken#endif 1193229997Sken 1194229997Sken ctl_queue(io); 1195229997Sken break; 1196229997Sken } 1197229997Sken case XPT_CONT_TARGET_IO: { 1198229997Sken struct ccb_accept_tio *atio; 1199229997Sken union ctl_io *io; 1200229997Sken 1201229997Sken atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio; 1202229997Sken io = (union ctl_io *)atio->ccb_h.io_ptr; 1203229997Sken 1204229997Sken softc->ctios_returned++; 1205229997Sken#ifdef CTLFEDEBUG 1206229997Sken printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n", 1207229997Sken __func__, atio->tag_id, done_ccb->ccb_h.flags); 1208229997Sken#endif 1209229997Sken /* 1210229997Sken * If we were sending status back to the initiator, free up 1211229997Sken * resources. If we were doing a datamove, call the 1212229997Sken * datamove done routine. 1213229997Sken */ 1214229997Sken if (done_ccb->ccb_h.flags & CAM_SEND_STATUS) { 1215229997Sken softc->ccbs_freed++; 1216229997Sken xpt_release_ccb(done_ccb); 1217229997Sken ctl_free_io(io); 1218229997Sken /* 1219229997Sken * For a wildcard attachment, commands can come in 1220229997Sken * with a specific target/lun. Reset the target 1221229997Sken * and LUN fields back to the wildcard values before 1222229997Sken * we send them back down to the SIM. The SIM has 1223229997Sken * a wildcard LUN enabled, not whatever target/lun 1224229997Sken * these happened to be. 1225229997Sken */ 1226229997Sken if (softc->flags & CTLFE_LUN_WILDCARD) { 1227229997Sken atio->ccb_h.target_id = CAM_TARGET_WILDCARD; 1228229997Sken atio->ccb_h.target_lun = CAM_LUN_WILDCARD; 1229229997Sken } 1230229997Sken if (periph->flags & CAM_PERIPH_INVALID) { 1231229997Sken ctlfe_free_ccb(periph, (union ccb *)atio); 1232229997Sken return; 1233229997Sken } else { 1234229997Sken xpt_action((union ccb *)atio); 1235229997Sken softc->atios_sent++; 1236229997Sken } 1237229997Sken } else { 1238229997Sken struct ctlfe_lun_cmd_info *cmd_info; 1239229997Sken struct ccb_scsiio *csio; 1240229997Sken 1241229997Sken csio = &done_ccb->csio; 1242229997Sken cmd_info = (struct ctlfe_lun_cmd_info *) 1243229997Sken io->io_hdr.port_priv; 1244229997Sken 1245229997Sken io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; 1246229997Sken 1247229997Sken io->scsiio.ext_data_len += csio->dxfer_len; 1248229997Sken if (io->scsiio.ext_data_len > 1249229997Sken io->scsiio.kern_total_len) { 1250229997Sken xpt_print(periph->path, "%s: tag 0x%04x " 1251229997Sken "done len %u > total %u sent %u\n", 1252229997Sken __func__, io->scsiio.tag_num, 1253229997Sken io->scsiio.ext_data_len, 1254229997Sken io->scsiio.kern_total_len, 1255229997Sken io->scsiio.ext_data_filled); 1256229997Sken } 1257229997Sken /* 1258229997Sken * Translate CAM status to CTL status. Success 1259229997Sken * does not change the overall, ctl_io status. In 1260229997Sken * that case we just set port_status to 0. If we 1261229997Sken * have a failure, though, set a data phase error 1262229997Sken * for the overall ctl_io. 1263229997Sken */ 1264229997Sken switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) { 1265229997Sken case CAM_REQ_CMP: 1266229997Sken io->io_hdr.port_status = 0; 1267229997Sken break; 1268229997Sken default: 1269229997Sken /* 1270229997Sken * XXX KDM the isp(4) driver doesn't really 1271229997Sken * seem to send errors back for data 1272229997Sken * transfers that I can tell. There is one 1273229997Sken * case where it'll send CAM_REQ_CMP_ERR, 1274229997Sken * but probably not that many more cases. 1275229997Sken * So set a generic data phase error here, 1276229997Sken * like the SXP driver sets. 1277229997Sken */ 1278229997Sken io->io_hdr.port_status = 0xbad1; 1279229997Sken ctl_set_data_phase_error(&io->scsiio); 1280229997Sken /* 1281229997Sken * XXX KDM figure out residual. 1282229997Sken */ 1283229997Sken break; 1284229997Sken } 1285229997Sken /* 1286229997Sken * If we had to break this S/G list into multiple 1287229997Sken * pieces, figure out where we are in the list, and 1288229997Sken * continue sending pieces if necessary. 1289229997Sken */ 1290229997Sken if ((cmd_info->flags & CTLFE_CMD_PIECEWISE) 1291229997Sken && (io->io_hdr.port_status == 0) 1292229997Sken && (cmd_info->cur_transfer_index < 1293229997Sken io->scsiio.kern_sg_entries)) { 1294229997Sken struct ctl_sg_entry *sglist; 1295229997Sken ccb_flags flags; 1296229997Sken uint8_t scsi_status; 1297229997Sken uint8_t *data_ptr; 1298229997Sken uint32_t dxfer_len; 1299229997Sken int *ti; 1300229997Sken 1301229997Sken sglist = (struct ctl_sg_entry *) 1302229997Sken io->scsiio.kern_data_ptr; 1303229997Sken ti = &cmd_info->cur_transfer_index; 1304229997Sken flags = atio->ccb_h.flags & 1305229997Sken (CAM_DIS_DISCONNECT| 1306229997Sken CAM_TAG_ACTION_VALID| 1307229997Sken CAM_DIR_MASK); 1308229997Sken 1309229997Sken /* 1310229997Sken * Set the direction, relative to the initiator. 1311229997Sken */ 1312229997Sken flags &= ~CAM_DIR_MASK; 1313229997Sken if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == 1314229997Sken CTL_FLAG_DATA_IN) 1315229997Sken flags |= CAM_DIR_IN; 1316229997Sken else 1317229997Sken flags |= CAM_DIR_OUT; 1318229997Sken 1319229997Sken data_ptr = sglist[*ti].addr; 1320229997Sken dxfer_len = sglist[*ti].len; 1321229997Sken (*ti)++; 1322229997Sken 1323229997Sken scsi_status = 0; 1324229997Sken 1325229997Sken if (((flags & CAM_SEND_STATUS) == 0) 1326229997Sken && (dxfer_len == 0)) { 1327229997Sken printf("%s: tag %04x no status or " 1328229997Sken "len cdb = %02x\n", __func__, 1329229997Sken atio->tag_id, 1330229997Sken atio->cdb_io.cdb_bytes[0]); 1331229997Sken printf("%s: tag %04x io status %#x\n", 1332229997Sken __func__, atio->tag_id, 1333229997Sken io->io_hdr.status); 1334229997Sken } 1335229997Sken 1336229997Sken cam_fill_ctio(csio, 1337229997Sken /*retries*/ 2, 1338229997Sken ctlfedone, 1339229997Sken flags, 1340229997Sken (flags & CAM_TAG_ACTION_VALID) ? 1341229997Sken MSG_SIMPLE_Q_TAG : 0, 1342229997Sken atio->tag_id, 1343229997Sken atio->init_id, 1344229997Sken scsi_status, 1345229997Sken /*data_ptr*/ data_ptr, 1346229997Sken /*dxfer_len*/ dxfer_len, 1347229997Sken /*timeout*/ 5 * 1000); 1348229997Sken 1349229997Sken csio->resid = 0; 1350229997Sken csio->ccb_h.ccb_atio = atio; 1351229997Sken io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; 1352229997Sken softc->ctios_sent++; 1353229997Sken xpt_action((union ccb *)csio); 1354229997Sken } else { 1355229997Sken /* 1356229997Sken * Release the CTIO. The ATIO will be sent back 1357229997Sken * down to the SIM once we send status. 1358229997Sken */ 1359229997Sken softc->ccbs_freed++; 1360229997Sken xpt_release_ccb(done_ccb); 1361229997Sken 1362229997Sken /* Call the backend move done callback */ 1363229997Sken io->scsiio.be_move_done(io); 1364229997Sken } 1365229997Sken } 1366229997Sken break; 1367229997Sken } 1368229997Sken case XPT_IMMEDIATE_NOTIFY: { 1369229997Sken union ctl_io *io; 1370229997Sken struct ccb_immediate_notify *inot; 1371229997Sken cam_status status; 1372229997Sken int frozen; 1373229997Sken 1374229997Sken inot = &done_ccb->cin1; 1375229997Sken 1376229997Sken softc->inots_returned++; 1377229997Sken 1378229997Sken frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0; 1379229997Sken 1380229997Sken printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x " 1381229997Sken "seq %#x\n", __func__, inot->ccb_h.status, 1382229997Sken inot->tag_id, inot->seq_id); 1383229997Sken 1384229997Sken io = ctl_alloc_io(bus_softc->fe.ctl_pool_ref); 1385229997Sken if (io != NULL) { 1386229997Sken int send_ctl_io; 1387229997Sken 1388229997Sken send_ctl_io = 1; 1389229997Sken 1390229997Sken ctl_zero_io(io); 1391229997Sken io->io_hdr.io_type = CTL_IO_TASK; 1392229997Sken io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr =done_ccb; 1393229997Sken inot->ccb_h.io_ptr = io; 1394229997Sken io->io_hdr.nexus.initid.id = inot->initiator_id; 1395229997Sken io->io_hdr.nexus.targ_port = bus_softc->fe.targ_port; 1396229997Sken io->io_hdr.nexus.targ_target.id = inot->ccb_h.target_id; 1397229997Sken io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun; 1398229997Sken /* XXX KDM should this be the tag_id? */ 1399229997Sken io->taskio.tag_num = inot->seq_id; 1400229997Sken 1401229997Sken status = inot->ccb_h.status & CAM_STATUS_MASK; 1402229997Sken switch (status) { 1403229997Sken case CAM_SCSI_BUS_RESET: 1404229997Sken io->taskio.task_action = CTL_TASK_BUS_RESET; 1405229997Sken break; 1406229997Sken case CAM_BDR_SENT: 1407229997Sken io->taskio.task_action = CTL_TASK_TARGET_RESET; 1408229997Sken break; 1409229997Sken case CAM_MESSAGE_RECV: 1410229997Sken switch (inot->arg) { 1411229997Sken case MSG_ABORT_TASK_SET: 1412229997Sken /* 1413229997Sken * XXX KDM this isn't currently 1414229997Sken * supported by CTL. It ends up 1415229997Sken * being a no-op. 1416229997Sken */ 1417229997Sken io->taskio.task_action = 1418229997Sken CTL_TASK_ABORT_TASK_SET; 1419229997Sken break; 1420229997Sken case MSG_TARGET_RESET: 1421229997Sken io->taskio.task_action = 1422229997Sken CTL_TASK_TARGET_RESET; 1423229997Sken break; 1424229997Sken case MSG_ABORT_TASK: 1425229997Sken io->taskio.task_action = 1426229997Sken CTL_TASK_ABORT_TASK; 1427229997Sken break; 1428229997Sken case MSG_LOGICAL_UNIT_RESET: 1429229997Sken io->taskio.task_action = 1430229997Sken CTL_TASK_LUN_RESET; 1431229997Sken break; 1432229997Sken case MSG_CLEAR_TASK_SET: 1433229997Sken /* 1434229997Sken * XXX KDM this isn't currently 1435229997Sken * supported by CTL. It ends up 1436229997Sken * being a no-op. 1437229997Sken */ 1438229997Sken io->taskio.task_action = 1439229997Sken CTL_TASK_CLEAR_TASK_SET; 1440229997Sken break; 1441229997Sken case MSG_CLEAR_ACA: 1442229997Sken io->taskio.task_action = 1443229997Sken CTL_TASK_CLEAR_ACA; 1444229997Sken break; 1445229997Sken case MSG_NOOP: 1446229997Sken send_ctl_io = 0; 1447229997Sken break; 1448229997Sken default: 1449229997Sken xpt_print(periph->path, "%s: " 1450229997Sken "unsupported message 0x%x\n", 1451229997Sken __func__, inot->arg); 1452229997Sken send_ctl_io = 0; 1453229997Sken break; 1454229997Sken } 1455229997Sken break; 1456229997Sken case CAM_REQ_ABORTED: 1457229997Sken /* 1458229997Sken * This request was sent back by the driver. 1459229997Sken * XXX KDM what do we do here? 1460229997Sken */ 1461229997Sken send_ctl_io = 0; 1462229997Sken break; 1463229997Sken default: 1464229997Sken xpt_print(periph->path, "%s: " 1465229997Sken "unsupported CAM status 0x%x\n", 1466229997Sken __func__, status); 1467229997Sken send_ctl_io = 0; 1468229997Sken break; 1469229997Sken } 1470229997Sken if (send_ctl_io != 0) { 1471229997Sken ctl_queue(io); 1472229997Sken } else { 1473229997Sken ctl_free_io(io); 1474229997Sken done_ccb->ccb_h.status = CAM_REQ_INPROG; 1475229997Sken done_ccb->ccb_h.func_code = 1476229997Sken XPT_NOTIFY_ACKNOWLEDGE; 1477229997Sken xpt_action(done_ccb); 1478229997Sken } 1479229997Sken } else { 1480229997Sken xpt_print(periph->path, "%s: could not allocate " 1481229997Sken "ctl_io for immediate notify!\n", __func__); 1482229997Sken /* requeue this to the adapter */ 1483229997Sken done_ccb->ccb_h.status = CAM_REQ_INPROG; 1484229997Sken done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; 1485229997Sken xpt_action(done_ccb); 1486229997Sken } 1487229997Sken 1488229997Sken if (frozen != 0) { 1489229997Sken cam_release_devq(periph->path, 1490229997Sken /*relsim_flags*/ 0, 1491229997Sken /*opening reduction*/ 0, 1492229997Sken /*timeout*/ 0, 1493229997Sken /*getcount_only*/ 0); 1494229997Sken } 1495229997Sken break; 1496229997Sken } 1497229997Sken case XPT_NOTIFY_ACKNOWLEDGE: 1498229997Sken /* 1499229997Sken * Queue this back down to the SIM as an immediate notify. 1500229997Sken */ 1501229997Sken done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; 1502229997Sken xpt_action(done_ccb); 1503229997Sken softc->inots_sent++; 1504229997Sken break; 1505229997Sken case XPT_ABORT: 1506229997Sken /* 1507229997Sken * XPT_ABORT is an immediate CCB, we shouldn't get here. 1508229997Sken */ 1509229997Sken panic("%s: XPT_ABORT CCB returned!", __func__); 1510229997Sken break; 1511229997Sken case XPT_SET_SIM_KNOB: 1512229997Sken case XPT_GET_SIM_KNOB: 1513229997Sken break; 1514229997Sken default: 1515229997Sken panic("%s: unexpected CCB type %#x", __func__, 1516229997Sken done_ccb->ccb_h.func_code); 1517229997Sken break; 1518229997Sken } 1519229997Sken} 1520229997Sken 1521229997Skenstatic void 1522229997Skenctlfe_onoffline(void *arg, int online) 1523229997Sken{ 1524229997Sken struct ctlfe_softc *bus_softc; 1525229997Sken union ccb *ccb; 1526229997Sken cam_status status; 1527229997Sken struct cam_path *path; 1528229997Sken struct cam_sim *sim; 1529229997Sken int set_wwnn; 1530229997Sken 1531229997Sken bus_softc = (struct ctlfe_softc *)arg; 1532229997Sken 1533229997Sken set_wwnn = 0; 1534229997Sken 1535229997Sken status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id, 1536229997Sken CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 1537229997Sken if (status != CAM_REQ_CMP) { 1538229997Sken printf("%s: unable to create path!\n", __func__); 1539229997Sken return; 1540229997Sken } 1541229997Sken ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO); 1542229997Sken if (ccb == NULL) { 1543229997Sken printf("%s: unable to malloc CCB!\n", __func__); 1544229997Sken xpt_free_path(path); 1545229997Sken return; 1546229997Sken } 1547229997Sken xpt_setup_ccb(&ccb->ccb_h, path, /*priority*/ 1); 1548229997Sken 1549229997Sken sim = xpt_path_sim(path); 1550229997Sken 1551229997Sken /* 1552229997Sken * Copan WWN format: 1553229997Sken * 1554229997Sken * Bits 63-60: 0x5 NAA, IEEE registered name 1555229997Sken * Bits 59-36: 0x000ED5 IEEE Company name assigned to Copan 1556229997Sken * Bits 35-12: Copan SSN (Sequential Serial Number) 1557229997Sken * Bits 11-8: Type of port: 1558229997Sken * 1 == N-Port 1559229997Sken * 2 == F-Port 1560229997Sken * 3 == NL-Port 1561229997Sken * Bits 7-0: 0 == Node Name, >0 == Port Number 1562229997Sken */ 1563229997Sken 1564229997Sken if (online != 0) { 1565229997Sken 1566229997Sken ccb->ccb_h.func_code = XPT_GET_SIM_KNOB; 1567229997Sken 1568229997Sken CAM_SIM_LOCK(sim); 1569229997Sken 1570229997Sken xpt_action(ccb); 1571229997Sken 1572229997Sken CAM_SIM_UNLOCK(sim); 1573229997Sken 1574229997Sken if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){ 1575229997Sken#ifdef RANDOM_WWNN 1576229997Sken uint64_t random_bits; 1577229997Sken#endif 1578229997Sken 1579229997Sken printf("%s: %s current WWNN %#jx\n", __func__, 1580229997Sken bus_softc->port_name, 1581229997Sken ccb->knob.xport_specific.fc.wwnn); 1582229997Sken printf("%s: %s current WWPN %#jx\n", __func__, 1583229997Sken bus_softc->port_name, 1584229997Sken ccb->knob.xport_specific.fc.wwpn); 1585229997Sken 1586229997Sken#ifdef RANDOM_WWNN 1587229997Sken arc4rand(&random_bits, sizeof(random_bits), 0); 1588229997Sken#endif 1589229997Sken 1590229997Sken /* 1591229997Sken * XXX KDM this is a bit of a kludge for now. We 1592229997Sken * take the current WWNN/WWPN from the card, and 1593229997Sken * replace the company identifier and the NL-Port 1594229997Sken * indicator and the port number (for the WWPN). 1595229997Sken * This should be replaced later with ddb_GetWWNN, 1596229997Sken * or possibly a more centralized scheme. (It 1597229997Sken * would be nice to have the WWNN/WWPN for each 1598229997Sken * port stored in the ctl_frontend structure.) 1599229997Sken */ 1600229997Sken#ifdef RANDOM_WWNN 1601229997Sken ccb->knob.xport_specific.fc.wwnn = 1602229997Sken (random_bits & 1603229997Sken 0x0000000fffffff00ULL) | 1604229997Sken /* Company ID */ 0x5000ED5000000000ULL | 1605229997Sken /* NL-Port */ 0x0300; 1606229997Sken ccb->knob.xport_specific.fc.wwpn = 1607229997Sken (random_bits & 1608229997Sken 0x0000000fffffff00ULL) | 1609229997Sken /* Company ID */ 0x5000ED5000000000ULL | 1610229997Sken /* NL-Port */ 0x3000 | 1611229997Sken /* Port Num */ (bus_softc->fe.targ_port & 0xff); 1612229997Sken 1613229997Sken /* 1614229997Sken * This is a bit of an API break/reversal, but if 1615229997Sken * we're doing the random WWNN that's a little 1616229997Sken * different anyway. So record what we're actually 1617229997Sken * using with the frontend code so it's reported 1618229997Sken * accurately. 1619229997Sken */ 1620229997Sken bus_softc->fe.wwnn = 1621229997Sken ccb->knob.xport_specific.fc.wwnn; 1622229997Sken bus_softc->fe.wwpn = 1623229997Sken ccb->knob.xport_specific.fc.wwpn; 1624229997Sken set_wwnn = 1; 1625229997Sken#else /* RANDOM_WWNN */ 1626229997Sken /* 1627229997Sken * If the user has specified a WWNN/WWPN, send them 1628229997Sken * down to the SIM. Otherwise, record what the SIM 1629229997Sken * has reported. 1630229997Sken */ 1631229997Sken if ((bus_softc->fe.wwnn != 0) 1632229997Sken && (bus_softc->fe.wwpn != 0)) { 1633229997Sken ccb->knob.xport_specific.fc.wwnn = 1634229997Sken bus_softc->fe.wwnn; 1635229997Sken ccb->knob.xport_specific.fc.wwpn = 1636229997Sken bus_softc->fe.wwpn; 1637229997Sken set_wwnn = 1; 1638229997Sken } else { 1639229997Sken bus_softc->fe.wwnn = 1640229997Sken ccb->knob.xport_specific.fc.wwnn; 1641229997Sken bus_softc->fe.wwpn = 1642229997Sken ccb->knob.xport_specific.fc.wwpn; 1643229997Sken } 1644229997Sken#endif /* RANDOM_WWNN */ 1645229997Sken 1646229997Sken 1647229997Sken if (set_wwnn != 0) { 1648229997Sken printf("%s: %s new WWNN %#jx\n", __func__, 1649229997Sken bus_softc->port_name, 1650229997Sken ccb->knob.xport_specific.fc.wwnn); 1651229997Sken printf("%s: %s new WWPN %#jx\n", __func__, 1652229997Sken bus_softc->port_name, 1653229997Sken ccb->knob.xport_specific.fc.wwpn); 1654229997Sken } 1655229997Sken } else { 1656229997Sken printf("%s: %s has no valid WWNN/WWPN\n", __func__, 1657229997Sken bus_softc->port_name); 1658229997Sken } 1659229997Sken } 1660229997Sken ccb->ccb_h.func_code = XPT_SET_SIM_KNOB; 1661229997Sken ccb->knob.xport_specific.valid = KNOB_VALID_ROLE; 1662229997Sken if (set_wwnn != 0) 1663229997Sken ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS; 1664229997Sken 1665229997Sken if (online != 0) 1666229997Sken ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET; 1667229997Sken else 1668229997Sken ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE; 1669229997Sken 1670229997Sken 1671229997Sken CAM_SIM_LOCK(sim); 1672229997Sken 1673229997Sken xpt_action(ccb); 1674229997Sken 1675229997Sken CAM_SIM_UNLOCK(sim); 1676229997Sken 1677229997Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1678229997Sken printf("%s: SIM %s (path id %d) target %s failed with " 1679229997Sken "status %#x\n", 1680229997Sken __func__, bus_softc->port_name, bus_softc->path_id, 1681229997Sken (online != 0) ? "enable" : "disable", 1682229997Sken ccb->ccb_h.status); 1683229997Sken } else { 1684229997Sken printf("%s: SIM %s (path id %d) target %s succeeded\n", 1685229997Sken __func__, bus_softc->port_name, bus_softc->path_id, 1686229997Sken (online != 0) ? "enable" : "disable"); 1687229997Sken } 1688229997Sken 1689229997Sken free(ccb, M_TEMP); 1690229997Sken xpt_free_path(path); 1691229997Sken 1692229997Sken return; 1693229997Sken} 1694229997Sken 1695229997Skenstatic void 1696229997Skenctlfe_online(void *arg) 1697229997Sken{ 1698229997Sken ctlfe_onoffline(arg, /*online*/ 1); 1699229997Sken} 1700229997Sken 1701229997Skenstatic void 1702229997Skenctlfe_offline(void *arg) 1703229997Sken{ 1704229997Sken ctlfe_onoffline(arg, /*online*/ 0); 1705229997Sken} 1706229997Sken 1707229997Skenstatic int 1708229997Skenctlfe_targ_enable(void *arg, struct ctl_id targ_id) 1709229997Sken{ 1710229997Sken return (0); 1711229997Sken} 1712229997Sken 1713229997Skenstatic int 1714229997Skenctlfe_targ_disable(void *arg, struct ctl_id targ_id) 1715229997Sken{ 1716229997Sken return (0); 1717229997Sken} 1718229997Sken 1719229997Sken/* 1720229997Sken * This will get called to enable a LUN on every bus that is attached to 1721229997Sken * CTL. So we only need to create a path/periph for this particular bus. 1722229997Sken */ 1723229997Skenstatic int 1724229997Skenctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id) 1725229997Sken{ 1726229997Sken struct ctlfe_softc *bus_softc; 1727229997Sken struct ctlfe_lun_softc *softc; 1728229997Sken struct cam_path *path; 1729229997Sken struct cam_periph *periph; 1730229997Sken struct cam_sim *sim; 1731229997Sken cam_status status; 1732229997Sken 1733229997Sken 1734229997Sken bus_softc = (struct ctlfe_softc *)arg; 1735229997Sken 1736229997Sken status = xpt_create_path_unlocked(&path, /*periph*/ NULL, 1737229997Sken bus_softc->path_id, 1738229997Sken targ_id.id, 1739229997Sken lun_id); 1740229997Sken /* XXX KDM need some way to return status to CTL here? */ 1741229997Sken if (status != CAM_REQ_CMP) { 1742229997Sken printf("%s: could not create path, status %#x\n", __func__, 1743229997Sken status); 1744229997Sken return (1); 1745229997Sken } 1746229997Sken 1747229997Sken softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO); 1748229997Sken if (softc == NULL) { 1749229997Sken printf("%s: could not allocate %zd bytes for softc\n", 1750229997Sken __func__, sizeof(*softc)); 1751229997Sken xpt_free_path(path); 1752229997Sken return (1); 1753229997Sken } 1754229997Sken sim = xpt_path_sim(path); 1755229997Sken mtx_lock(sim->mtx); 1756229997Sken periph = cam_periph_find(path, "ctl"); 1757229997Sken if (periph != NULL) { 1758229997Sken /* We've already got a periph, no need to alloc a new one. */ 1759229997Sken xpt_free_path(path); 1760229997Sken free(softc, M_CTLFE); 1761229997Sken mtx_unlock(sim->mtx); 1762229997Sken return (0); 1763229997Sken } 1764229997Sken 1765229997Sken softc->parent_softc = bus_softc; 1766229997Sken STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links); 1767229997Sken 1768229997Sken status = cam_periph_alloc(ctlferegister, 1769229997Sken ctlfeoninvalidate, 1770229997Sken ctlfecleanup, 1771229997Sken ctlfestart, 1772229997Sken "ctl", 1773229997Sken CAM_PERIPH_BIO, 1774229997Sken path, 1775229997Sken ctlfeasync, 1776229997Sken 0, 1777229997Sken softc); 1778229997Sken 1779229997Sken mtx_unlock(sim->mtx); 1780229997Sken 1781229997Sken xpt_free_path(path); 1782229997Sken 1783229997Sken return (0); 1784229997Sken} 1785229997Sken 1786229997Sken/* 1787229997Sken * XXX KDM we disable LUN removal here. The problem is that the isp(4) 1788229997Sken * driver doesn't currently handle LUN removal properly. We need to keep 1789229997Sken * enough state here at the peripheral level even after LUNs have been 1790229997Sken * removed inside CTL. 1791229997Sken * 1792229997Sken * Once the isp(4) driver is fixed, this can be re-enabled. 1793229997Sken */ 1794229997Skenstatic int 1795229997Skenctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id) 1796229997Sken{ 1797229997Sken#ifdef NOTYET 1798229997Sken struct ctlfe_softc *softc; 1799229997Sken struct ctlfe_lun_softc *lun_softc; 1800229997Sken 1801229997Sken softc = (struct ctlfe_softc *)arg; 1802229997Sken 1803229997Sken mtx_lock(softc->sim->mtx); 1804229997Sken STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) { 1805229997Sken struct cam_path *path; 1806229997Sken 1807229997Sken path = lun_softc->periph->path; 1808229997Sken 1809229997Sken if ((xpt_path_target_id(path) == targ_id.id) 1810229997Sken && (xpt_path_lun_id(path) == lun_id)) { 1811229997Sken break; 1812229997Sken } 1813229997Sken } 1814229997Sken if (lun_softc == NULL) { 1815229997Sken mtx_unlock(softc->sim->mtx); 1816229997Sken printf("%s: can't find target %d lun %d\n", __func__, 1817229997Sken targ_id.id, lun_id); 1818229997Sken return (1); 1819229997Sken } 1820229997Sken 1821229997Sken cam_periph_invalidate(lun_softc->periph); 1822229997Sken 1823229997Sken mtx_unlock(softc->sim->mtx); 1824229997Sken#endif 1825229997Sken 1826229997Sken return (0); 1827229997Sken} 1828229997Sken 1829229997Skenstatic void 1830229997Skenctlfe_dump_sim(struct cam_sim *sim) 1831229997Sken{ 1832229997Sken int i; 1833229997Sken 1834229997Sken printf("%s%d: max tagged openings: %d, max dev openings: %d\n", 1835229997Sken sim->sim_name, sim->unit_number, 1836229997Sken sim->max_tagged_dev_openings, sim->max_dev_openings); 1837229997Sken printf("%s%d: max_ccbs: %u, ccb_count: %u\n", 1838229997Sken sim->sim_name, sim->unit_number, 1839229997Sken sim->max_ccbs, sim->ccb_count); 1840229997Sken printf("%s%d: ccb_freeq is %sempty\n", 1841229997Sken sim->sim_name, sim->unit_number, 1842229997Sken (SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT "); 1843229997Sken printf("%s%d: alloc_queue.entries %d, alloc_openings %d\n", 1844229997Sken sim->sim_name, sim->unit_number, 1845229997Sken sim->devq->alloc_queue.entries, sim->devq->alloc_openings); 1846229997Sken printf("%s%d: qfrozen_cnt:", sim->sim_name, sim->unit_number); 1847229997Sken for (i = 0; i < CAM_RL_VALUES; i++) { 1848229997Sken printf("%s%u", (i != 0) ? ":" : "", 1849229997Sken sim->devq->alloc_queue.qfrozen_cnt[i]); 1850229997Sken } 1851229997Sken printf("\n"); 1852229997Sken} 1853229997Sken 1854229997Sken/* 1855229997Sken * Assumes that the SIM lock is held. 1856229997Sken */ 1857229997Skenstatic void 1858229997Skenctlfe_dump_queue(struct ctlfe_lun_softc *softc) 1859229997Sken{ 1860229997Sken struct ccb_hdr *hdr; 1861229997Sken struct cam_periph *periph; 1862229997Sken int num_items; 1863229997Sken 1864229997Sken periph = softc->periph; 1865229997Sken num_items = 0; 1866229997Sken 1867229997Sken TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) { 1868229997Sken union ctl_io *io; 1869229997Sken 1870229997Sken io = hdr->io_ptr; 1871229997Sken 1872229997Sken num_items++; 1873229997Sken 1874229997Sken /* 1875229997Sken * This can happen when we get an ATIO but can't allocate 1876229997Sken * a ctl_io. See the XPT_ACCEPT_TARGET_IO case in ctlfedone(). 1877229997Sken */ 1878229997Sken if (io == NULL) { 1879229997Sken struct ccb_scsiio *csio; 1880229997Sken 1881229997Sken csio = (struct ccb_scsiio *)hdr; 1882229997Sken 1883229997Sken xpt_print(periph->path, "CCB %#x ctl_io allocation " 1884229997Sken "failed\n", csio->tag_id); 1885229997Sken continue; 1886229997Sken } 1887229997Sken 1888229997Sken /* 1889229997Sken * Only regular SCSI I/O is put on the work 1890229997Sken * queue, so we can print sense here. There may be no 1891229997Sken * sense if it's no the queue for a DMA, but this serves to 1892229997Sken * print out the CCB as well. 1893229997Sken * 1894229997Sken * XXX KDM switch this over to scsi_sense_print() when 1895229997Sken * CTL is merged in with CAM. 1896229997Sken */ 1897229997Sken ctl_io_error_print(io, NULL); 1898229997Sken 1899229997Sken /* 1900229997Sken * We're sending status back to the 1901229997Sken * initiator, so we're on the queue waiting 1902229997Sken * for a CTIO to do that. 1903229997Sken */ 1904229997Sken if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) 1905229997Sken continue; 1906229997Sken 1907229997Sken /* 1908229997Sken * Otherwise, we're on the queue waiting to 1909229997Sken * do a data transfer. 1910229997Sken */ 1911229997Sken xpt_print(periph->path, "Total %u, Current %u, Resid %u\n", 1912229997Sken io->scsiio.kern_total_len, io->scsiio.kern_data_len, 1913229997Sken io->scsiio.kern_data_resid); 1914229997Sken } 1915229997Sken 1916229997Sken xpt_print(periph->path, "%d requests total waiting for CCBs\n", 1917229997Sken num_items); 1918229997Sken xpt_print(periph->path, "%ju CCBs oustanding (%ju allocated, %ju " 1919229997Sken "freed)\n", (uintmax_t)(softc->ccbs_alloced - 1920229997Sken softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced, 1921229997Sken (uintmax_t)softc->ccbs_freed); 1922229997Sken xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju " 1923229997Sken "returned\n", (uintmax_t)(softc->ctios_sent - 1924229997Sken softc->ctios_returned), softc->ctios_sent, 1925229997Sken softc->ctios_returned); 1926229997Sken} 1927229997Sken 1928229997Sken/* 1929229997Sken * This function is called when we fail to get a CCB for a DMA or status return 1930229997Sken * to the initiator within the specified time period. 1931229997Sken * 1932229997Sken * The callout code should insure that we hold the sim mutex here. 1933229997Sken */ 1934229997Skenstatic void 1935229997Skenctlfe_dma_timeout(void *arg) 1936229997Sken{ 1937229997Sken struct ctlfe_lun_softc *softc; 1938229997Sken struct cam_periph *periph; 1939229997Sken struct cam_sim *sim; 1940229997Sken int num_queued; 1941229997Sken 1942229997Sken softc = (struct ctlfe_lun_softc *)arg; 1943229997Sken periph = softc->periph; 1944229997Sken sim = xpt_path_sim(periph->path); 1945229997Sken num_queued = 0; 1946229997Sken 1947229997Sken /* 1948229997Sken * Nothing to do... 1949229997Sken */ 1950229997Sken if (TAILQ_FIRST(&softc->work_queue) == NULL) { 1951229997Sken xpt_print(periph->path, "TIMEOUT triggered after %d " 1952229997Sken "seconds, but nothing on work queue??\n", 1953229997Sken CTLFE_DMA_TIMEOUT); 1954229997Sken return; 1955229997Sken } 1956229997Sken 1957229997Sken xpt_print(periph->path, "TIMEOUT (%d seconds) waiting for DMA to " 1958229997Sken "start\n", CTLFE_DMA_TIMEOUT); 1959229997Sken 1960229997Sken ctlfe_dump_queue(softc); 1961229997Sken 1962229997Sken ctlfe_dump_sim(sim); 1963229997Sken 1964229997Sken xpt_print(periph->path, "calling xpt_schedule() to attempt to " 1965229997Sken "unstick our queue\n"); 1966229997Sken 1967229997Sken xpt_schedule(periph, /*priority*/ 1); 1968229997Sken 1969229997Sken xpt_print(periph->path, "xpt_schedule() call complete\n"); 1970229997Sken} 1971229997Sken 1972229997Sken/* 1973229997Sken * Datamove/done routine called by CTL. Put ourselves on the queue to 1974229997Sken * receive a CCB from CAM so we can queue the continue I/O request down 1975229997Sken * to the adapter. 1976229997Sken */ 1977229997Skenstatic void 1978229997Skenctlfe_datamove_done(union ctl_io *io) 1979229997Sken{ 1980229997Sken union ccb *ccb; 1981229997Sken struct cam_sim *sim; 1982229997Sken struct cam_periph *periph; 1983229997Sken struct ctlfe_lun_softc *softc; 1984229997Sken 1985229997Sken ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 1986229997Sken 1987229997Sken sim = xpt_path_sim(ccb->ccb_h.path); 1988229997Sken 1989229997Sken mtx_lock(sim->mtx); 1990229997Sken 1991229997Sken periph = xpt_path_periph(ccb->ccb_h.path); 1992229997Sken 1993229997Sken softc = (struct ctlfe_lun_softc *)periph->softc; 1994229997Sken 1995229997Sken if (io->io_hdr.io_type == CTL_IO_TASK) { 1996229997Sken /* 1997229997Sken * Task management commands don't require any further 1998229997Sken * communication back to the adapter. Requeue the CCB 1999229997Sken * to the adapter, and free the CTL I/O. 2000229997Sken */ 2001229997Sken xpt_print(ccb->ccb_h.path, "%s: returning task I/O " 2002229997Sken "tag %#x seq %#x\n", __func__, 2003229997Sken ccb->cin1.tag_id, ccb->cin1.seq_id); 2004229997Sken /* 2005229997Sken * Send the notify acknowledge down to the SIM, to let it 2006229997Sken * know we processed the task management command. 2007229997Sken */ 2008229997Sken ccb->ccb_h.status = CAM_REQ_INPROG; 2009229997Sken ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; 2010229997Sken xpt_action(ccb); 2011229997Sken ctl_free_io(io); 2012229997Sken } else { 2013229997Sken if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) 2014229997Sken io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; 2015229997Sken else 2016229997Sken io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED; 2017229997Sken 2018229997Sken TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, 2019229997Sken periph_links.tqe); 2020229997Sken 2021229997Sken /* 2022229997Sken * Reset the timeout for our latest active DMA. 2023229997Sken */ 2024229997Sken callout_reset(&softc->dma_callout, 2025229997Sken CTLFE_DMA_TIMEOUT * hz, 2026229997Sken ctlfe_dma_timeout, softc); 2027229997Sken /* 2028229997Sken * Ask for the CAM transport layer to send us a CCB to do 2029229997Sken * the DMA or send status, unless ctlfe_dma_enabled is set 2030229997Sken * to 0. 2031229997Sken */ 2032229997Sken if (ctlfe_dma_enabled != 0) 2033229997Sken xpt_schedule(periph, /*priority*/ 1); 2034229997Sken } 2035229997Sken 2036229997Sken mtx_unlock(sim->mtx); 2037229997Sken} 2038229997Sken 2039229997Skenstatic void 2040229997Skenctlfe_dump(void) 2041229997Sken{ 2042229997Sken struct ctlfe_softc *bus_softc; 2043229997Sken 2044229997Sken STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) { 2045229997Sken struct ctlfe_lun_softc *lun_softc; 2046229997Sken 2047229997Sken ctlfe_dump_sim(bus_softc->sim); 2048229997Sken 2049229997Sken STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links) { 2050229997Sken ctlfe_dump_queue(lun_softc); 2051229997Sken } 2052229997Sken } 2053229997Sken} 2054