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