File:  [DragonFly] / src / sys / bus / cam / scsi / scsi_target.c
Revision 1.6: download - view: text, annotated - select for diffs
Fri Mar 12 03:23:19 2004 UTC (10 years, 9 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Change M_NOWAIT to M_INTWAIT or M_WAITOK.  CAM does a mediocre job checking
for NULL returns from malloc() and even when it does it generally causes
the device operation to fail instead of retrying, resulting in unacceptable
behavior.  M_NOWAIT semantics allow NULL to be returned during normal system
operation.  This is especially true in DragonFly.

Also remove much of the code that previously checked for NULL.  By using
M_INTWAIT or M_WAITOK, malloc() will panic rather then return NULL.  Only
the addition of M_NULLOK allows a blocking malloc() to return NULL, and we
do not use that flag in CAM.

Add M_ZERO to a number of malloc()'s and remove subsequent bzero()'s, and
add M_ZERO to a few mallocs (primarily for the read capacity data structure)
that did not bother zeroing out the structure before.  While the data is
supposed to be overwritten read-capacity is often quite fragile due to the
SCSI simulation layer, so we do not take any chances.

    1: /*
    2:  * Generic SCSI Target Kernel Mode Driver
    3:  *
    4:  * Copyright (c) 2002 Nate Lawson.
    5:  * Copyright (c) 1998, 1999, 2001, 2002 Justin T. Gibbs.
    6:  * All rights reserved.
    7:  *
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions
   10:  * are met:
   11:  * 1. Redistributions of source code must retain the above copyright
   12:  *    notice, this list of conditions, and the following disclaimer,
   13:  *    without modification, immediately at the beginning of the file.
   14:  * 2. The name of the author may not be used to endorse or promote products
   15:  *    derived from this software without specific prior written permission.
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27:  * SUCH DAMAGE.
   28:  *
   29:  * $FreeBSD: src/sys/cam/scsi/scsi_target.c,v 1.22.2.7 2003/02/18 22:07:10 njl Exp $
   30:  * $DragonFly: src/sys/bus/cam/scsi/scsi_target.c,v 1.6 2004/03/12 03:23:19 dillon Exp $
   31:  */
   32: 
   33: #include <sys/param.h>
   34: #include <sys/systm.h>
   35: #include <sys/kernel.h>
   36: #include <sys/conf.h>
   37: #include <sys/malloc.h>
   38: #include <sys/poll.h>
   39: #include <sys/vnode.h>
   40: #include <sys/devicestat.h>
   41: 
   42: #include "../cam.h"
   43: #include "../cam_ccb.h"
   44: #include "../cam_periph.h"
   45: #include "../cam_xpt_periph.h"
   46: #include "scsi_targetio.h"
   47: 
   48: /* Transaction information attached to each CCB sent by the user */
   49: struct targ_cmd_descr {
   50: 	struct cam_periph_map_info  mapinfo;
   51: 	TAILQ_ENTRY(targ_cmd_descr) tqe;
   52: 	union ccb *user_ccb;
   53: 	int	   priority;
   54: 	int	   func_code;
   55: };
   56: 
   57: /* Offset into the private CCB area for storing our descriptor */
   58: #define targ_descr	periph_priv.entries[1].ptr
   59: 
   60: TAILQ_HEAD(descr_queue, targ_cmd_descr);
   61: 
   62: typedef enum {
   63: 	TARG_STATE_RESV		= 0x00, /* Invalid state */
   64: 	TARG_STATE_OPENED	= 0x01, /* Device opened, softc initialized */
   65: 	TARG_STATE_LUN_ENABLED	= 0x02  /* Device enabled for a path */
   66: } targ_state;
   67: 
   68: /* Per-instance device software context */
   69: struct targ_softc {
   70: 	/* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
   71: 	struct ccb_queue	 pending_ccb_queue;
   72: 
   73: 	/* Command descriptors awaiting CTIO resources from the XPT */
   74: 	struct descr_queue	 work_queue;
   75: 
   76: 	/* Command descriptors that have been aborted back to the user. */
   77: 	struct descr_queue	 abort_queue;
   78: 
   79: 	/*
   80: 	 * Queue of CCBs that have been copied out to userland, but our
   81: 	 * userland daemon has not yet seen.
   82: 	 */
   83: 	struct ccb_queue	 user_ccb_queue;
   84: 
   85: 	struct cam_periph	*periph;
   86: 	struct cam_path		*path;
   87: 	targ_state		 state;
   88: 	struct selinfo		 read_select;
   89: 	struct devstat		 device_stats;
   90: };
   91: 
   92: static d_open_t		targopen;
   93: static d_close_t	targclose;
   94: static d_read_t		targread;
   95: static d_write_t	targwrite;
   96: static d_ioctl_t	targioctl;
   97: static d_poll_t		targpoll;
   98: static d_kqfilter_t	targkqfilter;
   99: static void		targreadfiltdetach(struct knote *kn);
  100: static int		targreadfilt(struct knote *kn, long hint);
  101: static struct filterops targread_filtops =
  102: 	{ 1, NULL, targreadfiltdetach, targreadfilt };
  103: 
  104: #define TARG_CDEV_MAJOR 65
  105: static struct cdevsw targ_cdevsw = {
  106: 	/* name */	"targ",
  107: 	/* maj */	TARG_CDEV_MAJOR,
  108: 	/* flags */	D_KQFILTER,
  109: 	/* port */      NULL,
  110: 	/* autoq */	0,
  111: 
  112: 	/* open */	targopen,
  113: 	/* close */	targclose,
  114: 	/* read */	targread,
  115: 	/* write */	targwrite,
  116: 	/* ioctl */	targioctl,
  117: 	/* poll */	targpoll,
  118: 	/* mmap */	nommap,
  119: 	/* strategy */	nostrategy,
  120: 	/* dump */	nodump,
  121: 	/* psize */	nopsize,
  122: 	/* kqfilter */	targkqfilter
  123: };
  124: 
  125: static cam_status	targendislun(struct cam_path *path, int enable,
  126: 				     int grp6_len, int grp7_len);
  127: static cam_status	targenable(struct targ_softc *softc,
  128: 				   struct cam_path *path,
  129: 				   int grp6_len, int grp7_len);
  130: static cam_status	targdisable(struct targ_softc *softc);
  131: static periph_ctor_t    targctor;
  132: static periph_dtor_t    targdtor;
  133: static periph_start_t   targstart;
  134: static int		targusermerge(struct targ_softc *softc,
  135: 				      struct targ_cmd_descr *descr,
  136: 				      union ccb *ccb);
  137: static int		targsendccb(struct targ_softc *softc, union ccb *ccb,
  138: 				    struct targ_cmd_descr *descr);
  139: static void		targdone(struct cam_periph *periph,
  140: 				 union  ccb *done_ccb);
  141: static int		targreturnccb(struct targ_softc *softc,
  142: 				      union  ccb *ccb);
  143: static union ccb *	targgetccb(struct targ_softc *softc, xpt_opcode type,
  144: 				   int priority);
  145: static void		targfreeccb(struct targ_softc *softc, union ccb *ccb);
  146: static struct targ_cmd_descr *
  147: 			targgetdescr(struct targ_softc *softc);
  148: static periph_init_t	targinit;
  149: static void		targasync(void *callback_arg, u_int32_t code,
  150: 				  struct cam_path *path, void *arg);
  151: static void		abort_all_pending(struct targ_softc *softc);
  152: static void		notify_user(struct targ_softc *softc);
  153: static int		targcamstatus(cam_status status);
  154: static size_t		targccblen(xpt_opcode func_code);
  155: 
  156: static struct periph_driver targdriver =
  157: {
  158: 	targinit, "targ",
  159: 	TAILQ_HEAD_INITIALIZER(targdriver.units), /* generation */ 0
  160: };
  161: DATA_SET(periphdriver_set, targdriver);
  162: 
  163: static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
  164: 
  165: /* Create softc and initialize it. Only one proc can open each targ device. */
  166: static int
  167: targopen(dev_t dev, int flags, int fmt, struct proc *p)
  168: {
  169: 	struct targ_softc *softc;
  170: 
  171: 	if (dev->si_drv1 != 0) {
  172: 		return (EBUSY);
  173: 	}
  174: 	
  175: 	/* Mark device busy before any potentially blocking operations */
  176: 	dev->si_drv1 = (void *)~0;
  177: 
  178: 	/* Create the targ device, allocate its softc, initialize it */
  179: 	make_dev(&targ_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 0600,
  180: 			 "targ%d", lminor(dev));
  181: 	MALLOC(softc, struct targ_softc *, sizeof(*softc), M_TARG,
  182: 	       M_WAITOK | M_ZERO);
  183: 	dev->si_drv1 = softc;
  184: 	softc->state = TARG_STATE_OPENED;
  185: 	softc->periph = NULL;
  186: 	softc->path = NULL;
  187: 
  188: 	TAILQ_INIT(&softc->pending_ccb_queue);
  189: 	TAILQ_INIT(&softc->work_queue);
  190: 	TAILQ_INIT(&softc->abort_queue);
  191: 	TAILQ_INIT(&softc->user_ccb_queue);
  192: 
  193: 	return (0);
  194: }
  195: 
  196: /* Disable LUN if enabled and teardown softc */
  197: static int
  198: targclose(dev_t dev, int flag, int fmt, struct proc *p)
  199: {
  200: 	struct targ_softc     *softc;
  201: 	int    error;
  202: 
  203: 	softc = (struct targ_softc *)dev->si_drv1;
  204: 	error = targdisable(softc);
  205: 	if (error == CAM_REQ_CMP) {
  206: 		dev->si_drv1 = 0;
  207: 		if (softc->periph != NULL) {
  208: 			cam_periph_invalidate(softc->periph);
  209: 			softc->periph = NULL;
  210: 		}
  211: 		destroy_dev(dev);
  212: 		FREE(softc, M_TARG);
  213: 	}
  214: 	return (error);
  215: }
  216: 
  217: /* Enable/disable LUNs, set debugging level */
  218: static int
  219: targioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  220: {
  221: 	struct targ_softc *softc;
  222: 	cam_status	   status;
  223: 
  224: 	softc = (struct targ_softc *)dev->si_drv1;
  225: 
  226: 	switch (cmd) {
  227: 	case TARGIOCENABLE:
  228: 	{
  229: 		struct ioc_enable_lun	*new_lun;
  230: 		struct cam_path		*path;
  231: 
  232: 		new_lun = (struct ioc_enable_lun *)addr;
  233: 		status = xpt_create_path(&path, /*periph*/NULL,
  234: 					 new_lun->path_id,
  235: 					 new_lun->target_id,
  236: 					 new_lun->lun_id);
  237: 		if (status != CAM_REQ_CMP) {
  238: 			printf("Couldn't create path, status %#x\n", status);
  239: 			break;
  240: 		}
  241: 		status = targenable(softc, path, new_lun->grp6_len,
  242: 				    new_lun->grp7_len);
  243: 		xpt_free_path(path);
  244: 		break;
  245: 	}
  246: 	case TARGIOCDISABLE:
  247: 		status = targdisable(softc);
  248: 		break;
  249: 	case TARGIOCDEBUG:
  250: 	{
  251: #ifdef	CAMDEBUG
  252: 		struct ccb_debug cdbg;
  253: 
  254: 		bzero(&cdbg, sizeof cdbg);
  255: 		if (*((int *)addr) != 0)
  256: 			cdbg.flags = CAM_DEBUG_PERIPH;
  257: 		else
  258: 			cdbg.flags = CAM_DEBUG_NONE;
  259: 		xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
  260: 		cdbg.ccb_h.func_code = XPT_DEBUG;
  261: 		cdbg.ccb_h.cbfcnp = targdone;
  262: 
  263: 		/* If no periph available, disallow debugging changes */
  264: 		if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
  265: 			status = CAM_DEV_NOT_THERE;
  266: 			break;
  267: 		}
  268: 		xpt_action((union ccb *)&cdbg);
  269: 		status = cdbg.ccb_h.status & CAM_STATUS_MASK;
  270: #else
  271: 		status = CAM_FUNC_NOTAVAIL;
  272: #endif
  273: 		break;
  274: 	}
  275: 	default:
  276: 		status = CAM_PROVIDE_FAIL;
  277: 		break;
  278: 	}
  279: 
  280: 	return (targcamstatus(status));
  281: }
  282: 
  283: /* Writes are always ready, reads wait for user_ccb_queue or abort_queue */
  284: static int
  285: targpoll(dev_t dev, int poll_events, struct proc *p)
  286: {
  287: 	struct targ_softc *softc;
  288: 	int	revents, s;
  289: 
  290: 	softc = (struct targ_softc *)dev->si_drv1;
  291: 
  292: 	/* Poll for write() is always ok. */
  293: 	revents = poll_events & (POLLOUT | POLLWRNORM);
  294: 	if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
  295: 		s = splsoftcam();
  296: 		/* Poll for read() depends on user and abort queues. */
  297: 		if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
  298: 		    !TAILQ_EMPTY(&softc->abort_queue)) {
  299: 			revents |= poll_events & (POLLIN | POLLRDNORM);
  300: 		}
  301: 		/* Only sleep if the user didn't poll for write. */
  302: 		if (revents == 0)
  303: 			selrecord(p, &softc->read_select);
  304: 		splx(s);
  305: 	}
  306: 
  307: 	return (revents);
  308: }
  309: 
  310: static int
  311: targkqfilter(dev_t dev, struct knote *kn)
  312: {
  313: 	struct  targ_softc *softc;
  314: 	int	s;
  315: 
  316: 	softc = (struct targ_softc *)dev->si_drv1;
  317: 	kn->kn_hook = (caddr_t)softc;
  318: 	kn->kn_fop = &targread_filtops;
  319: 	s = splsoftcam();
  320: 	SLIST_INSERT_HEAD(&softc->read_select.si_note, kn, kn_selnext);
  321: 	splx(s);
  322: 	return (0);
  323: }
  324: 
  325: static void
  326: targreadfiltdetach(struct knote *kn)
  327: {
  328: 	struct  targ_softc *softc;
  329: 	int	s;
  330: 
  331: 	softc = (struct targ_softc *)kn->kn_hook;
  332: 	s = splsoftcam();
  333: 	SLIST_REMOVE(&softc->read_select.si_note, kn, knote, kn_selnext);
  334: 	splx(s);
  335: }
  336: 
  337: /* Notify the user's kqueue when the user queue or abort queue gets a CCB */
  338: static int
  339: targreadfilt(struct knote *kn, long hint)
  340: {
  341: 	struct targ_softc *softc;
  342: 	int	retval, s;
  343: 
  344: 	softc = (struct targ_softc *)kn->kn_hook;
  345: 	s = splsoftcam();
  346: 	retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
  347: 		 !TAILQ_EMPTY(&softc->abort_queue);
  348: 	splx(s);
  349: 	return (retval);
  350: }
  351: 
  352: /* Send the HBA the enable/disable message */
  353: static cam_status
  354: targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
  355: {
  356: 	struct ccb_en_lun en_ccb;
  357: 	cam_status	  status;
  358: 
  359: 	/* Tell the lun to begin answering selects */
  360: 	xpt_setup_ccb(&en_ccb.ccb_h, path, /*priority*/1);
  361: 	en_ccb.ccb_h.func_code = XPT_EN_LUN;
  362: 	/* Don't need support for any vendor specific commands */
  363: 	en_ccb.grp6_len = grp6_len;
  364: 	en_ccb.grp7_len = grp7_len;
  365: 	en_ccb.enable = enable ? 1 : 0;
  366: 	xpt_action((union ccb *)&en_ccb);
  367: 	status = en_ccb.ccb_h.status & CAM_STATUS_MASK;
  368: 	if (status != CAM_REQ_CMP) {
  369: 		xpt_print_path(path);
  370: 		printf("%sable lun CCB rejected, status %#x\n",
  371: 		       enable ? "en" : "dis", status);
  372: 	}
  373: 	return (status);
  374: }
  375: 
  376: /* Enable target mode on a LUN, given its path */
  377: static cam_status
  378: targenable(struct targ_softc *softc, struct cam_path *path, int grp6_len,
  379: 	   int grp7_len)
  380: {
  381: 	struct cam_periph *periph;
  382: 	struct ccb_pathinq cpi;
  383: 	cam_status	   status;
  384: 
  385: 	if ((softc->state & TARG_STATE_LUN_ENABLED) != 0)
  386: 		return (CAM_LUN_ALRDY_ENA);
  387: 
  388: 	/* Make sure SIM supports target mode */
  389: 	xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
  390: 	cpi.ccb_h.func_code = XPT_PATH_INQ;
  391: 	xpt_action((union ccb *)&cpi);
  392: 	status = cpi.ccb_h.status & CAM_STATUS_MASK;
  393: 	if (status != CAM_REQ_CMP) {
  394: 		printf("pathinq failed, status %#x\n", status);
  395: 		goto enable_fail;
  396: 	}
  397: 	if ((cpi.target_sprt & PIT_PROCESSOR) == 0) {
  398: 		printf("controller does not support target mode\n");
  399: 		status = CAM_FUNC_NOTAVAIL;
  400: 		goto enable_fail;
  401: 	}
  402: 
  403: 	/* Destroy any periph on our path if it is disabled */
  404: 	periph = cam_periph_find(path, "targ");
  405: 	if (periph != NULL) {
  406: 		struct targ_softc *del_softc;
  407: 
  408: 		del_softc = (struct targ_softc *)periph->softc;
  409: 		if ((del_softc->state & TARG_STATE_LUN_ENABLED) == 0) {
  410: 			cam_periph_invalidate(del_softc->periph);
  411: 			del_softc->periph = NULL;
  412: 		} else {
  413: 			printf("Requested path still in use by targ%d\n",
  414: 			       periph->unit_number);
  415: 			status = CAM_LUN_ALRDY_ENA;
  416: 			goto enable_fail;
  417: 		}
  418: 	}
  419: 
  420: 	/* Create a periph instance attached to this path */
  421: 	status = cam_periph_alloc(targctor, NULL, targdtor, targstart,
  422: 			"targ", CAM_PERIPH_BIO, path, targasync, 0, softc);
  423: 	if (status != CAM_REQ_CMP) {
  424: 		printf("cam_periph_alloc failed, status %#x\n", status);
  425: 		goto enable_fail;
  426: 	}
  427: 
  428: 	/* Ensure that the periph now exists. */
  429: 	if (cam_periph_find(path, "targ") == NULL) {
  430: 		panic("targenable: succeeded but no periph?");
  431: 		/* NOTREACHED */
  432: 	}
  433: 
  434: 	/* Send the enable lun message */
  435: 	status = targendislun(path, /*enable*/1, grp6_len, grp7_len);
  436: 	if (status != CAM_REQ_CMP) {
  437: 		printf("enable lun failed, status %#x\n", status);
  438: 		goto enable_fail;
  439: 	}
  440: 	softc->state |= TARG_STATE_LUN_ENABLED;
  441: 
  442: enable_fail:
  443: 	return (status);
  444: }
  445: 
  446: /* Disable this softc's target instance if enabled */
  447: static cam_status
  448: targdisable(struct targ_softc *softc)
  449: {
  450: 	cam_status status;
  451: 	int s;
  452: 
  453: 	if ((softc->state & TARG_STATE_LUN_ENABLED) == 0)
  454: 		return (CAM_REQ_CMP);
  455: 
  456: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targdisable\n"));
  457: 
  458: 	/* Abort any ccbs pending on the controller */
  459: 	s = splcam();
  460: 	abort_all_pending(softc);
  461: 	splx(s);
  462: 
  463: 	/* Disable this lun */
  464: 	status = targendislun(softc->path, /*enable*/0,
  465: 			      /*grp6_len*/0, /*grp7_len*/0);
  466: 	if (status == CAM_REQ_CMP)
  467: 		softc->state &= ~TARG_STATE_LUN_ENABLED;
  468: 	else
  469: 		printf("Disable lun failed, status %#x\n", status);
  470: 
  471: 	return (status);
  472: }
  473: 
  474: /* Initialize a periph (called from cam_periph_alloc) */
  475: static cam_status
  476: targctor(struct cam_periph *periph, void *arg)
  477: {
  478: 	struct targ_softc *softc;
  479: 
  480: 	/* Store pointer to softc for periph-driven routines */
  481: 	softc = (struct targ_softc *)arg;
  482: 	periph->softc = softc;
  483: 	softc->periph = periph;
  484: 	softc->path = periph->path;
  485: 	return (CAM_REQ_CMP);
  486: }
  487: 
  488: static void
  489: targdtor(struct cam_periph *periph)
  490: {
  491: 	struct targ_softc     *softc;
  492: 	struct ccb_hdr	      *ccb_h;
  493: 	struct targ_cmd_descr *descr;
  494: 
  495: 	softc = (struct targ_softc *)periph->softc;
  496: 
  497: 	/* 
  498: 	 * targdisable() aborts CCBs back to the user and leaves them
  499: 	 * on user_ccb_queue and abort_queue in case the user is still
  500: 	 * interested in them.  We free them now.
  501: 	 */
  502: 	while ((ccb_h = TAILQ_FIRST(&softc->user_ccb_queue)) != NULL) {
  503: 		TAILQ_REMOVE(&softc->user_ccb_queue, ccb_h, periph_links.tqe);
  504: 		targfreeccb(softc, (union ccb *)ccb_h);
  505: 	}
  506: 	while ((descr = TAILQ_FIRST(&softc->abort_queue)) != NULL) {
  507: 		TAILQ_REMOVE(&softc->abort_queue, descr, tqe);
  508: 		FREE(descr, M_TARG);
  509: 	}
  510: 
  511: 	softc->periph = NULL;
  512: 	softc->path = NULL;
  513: 	periph->softc = NULL;
  514: }
  515: 
  516: /* Receive CCBs from user mode proc and send them to the HBA */
  517: static int
  518: targwrite(dev_t dev, struct uio *uio, int ioflag)
  519: {
  520: 	union ccb *user_ccb;
  521: 	struct targ_softc *softc;
  522: 	struct targ_cmd_descr *descr;
  523: 	int write_len, error, s;
  524: 	int func_code, priority;
  525: 
  526: 	softc = (struct targ_softc *)dev->si_drv1;
  527: 	write_len = error = 0;
  528: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  529: 		  ("write - uio_resid %d\n", uio->uio_resid));
  530: 	while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
  531: 		union ccb *ccb;
  532: 		int error;
  533: 
  534: 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
  535: 		if (error != 0) {
  536: 			CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  537: 				  ("write - uiomove failed (%d)\n", error));
  538: 			break;
  539: 		}
  540: 		priority = fuword(&user_ccb->ccb_h.pinfo.priority);
  541: 		if (priority == -1) {
  542: 			error = EINVAL;
  543: 			break;
  544: 		}
  545: 		func_code = fuword(&user_ccb->ccb_h.func_code);
  546: 		switch (func_code) {
  547: 		case XPT_ACCEPT_TARGET_IO:
  548: 		case XPT_IMMED_NOTIFY:
  549: 			ccb = targgetccb(softc, func_code, priority);
  550: 			descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
  551: 			descr->user_ccb = user_ccb;
  552: 			descr->func_code = func_code;
  553: 			CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  554: 				  ("Sent ATIO/INOT (%p)\n", user_ccb));
  555: 			xpt_action(ccb);
  556: 			s = splsoftcam();
  557: 			TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
  558: 					  &ccb->ccb_h,
  559: 					  periph_links.tqe);
  560: 			splx(s);
  561: 			break;
  562: 		default:
  563: 			if ((func_code & XPT_FC_QUEUED) != 0) {
  564: 				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  565: 					  ("Sending queued ccb %#x (%p)\n",
  566: 					  func_code, user_ccb));
  567: 				descr = targgetdescr(softc);
  568: 				descr->user_ccb = user_ccb;
  569: 				descr->priority = priority;
  570: 				descr->func_code = func_code;
  571: 				s = splsoftcam();
  572: 				TAILQ_INSERT_TAIL(&softc->work_queue,
  573: 						  descr, tqe);
  574: 				splx(s);
  575: 				xpt_schedule(softc->periph, priority);
  576: 			} else {
  577: 				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  578: 					  ("Sending inline ccb %#x (%p)\n",
  579: 					  func_code, user_ccb));
  580: 				ccb = targgetccb(softc, func_code, priority);
  581: 				descr = (struct targ_cmd_descr *)
  582: 					 ccb->ccb_h.targ_descr;
  583: 				descr->user_ccb = user_ccb;
  584: 				descr->priority = priority;
  585: 				descr->func_code = func_code;
  586: 				if (targusermerge(softc, descr, ccb) != EFAULT)
  587: 					targsendccb(softc, ccb, descr);
  588: 				targreturnccb(softc, ccb);
  589: 			}
  590: 			break;
  591: 		}
  592: 		write_len += sizeof(user_ccb);
  593: 	}
  594: 	
  595: 	/*
  596: 	 * If we've successfully taken in some amount of
  597: 	 * data, return success for that data first.  If
  598: 	 * an error is persistent, it will be reported
  599: 	 * on the next write.
  600: 	 */
  601: 	if (error != 0 && write_len == 0)
  602: 		return (error);
  603: 	if (write_len == 0 && uio->uio_resid != 0)
  604: 		return (ENOSPC);
  605: 	return (0);
  606: }
  607: 
  608: /* Process requests (descrs) via the periph-supplied CCBs */
  609: static void
  610: targstart(struct cam_periph *periph, union ccb *start_ccb)
  611: {
  612: 	struct targ_softc *softc;
  613: 	struct targ_cmd_descr *descr, *next_descr;
  614: 	int s, error;
  615: 
  616: 	softc = (struct targ_softc *)periph->softc;
  617: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targstart %p\n", start_ccb));
  618: 
  619: 	s = splsoftcam();
  620: 	descr = TAILQ_FIRST(&softc->work_queue);
  621: 	if (descr == NULL) {
  622: 		splx(s);
  623: 		xpt_release_ccb(start_ccb);
  624: 	} else {
  625: 		TAILQ_REMOVE(&softc->work_queue, descr, tqe);
  626: 		next_descr = TAILQ_FIRST(&softc->work_queue);
  627: 		splx(s);
  628: 
  629: 		/* Initiate a transaction using the descr and supplied CCB */
  630: 		error = targusermerge(softc, descr, start_ccb);
  631: 		if (error == 0)
  632: 			error = targsendccb(softc, start_ccb, descr);
  633: 		if (error != 0) {
  634: 			xpt_print_path(periph->path);
  635: 			printf("targsendccb failed, err %d\n", error);
  636: 			xpt_release_ccb(start_ccb);
  637: 			suword(&descr->user_ccb->ccb_h.status,
  638: 			       CAM_REQ_CMP_ERR);
  639: 			s = splsoftcam();
  640: 			TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
  641: 			splx(s);
  642: 			notify_user(softc);
  643: 		}
  644: 
  645: 		/* If we have more work to do, stay scheduled */
  646: 		if (next_descr != NULL)
  647: 			xpt_schedule(periph, next_descr->priority);
  648: 	}
  649: }
  650: 
  651: static int
  652: targusermerge(struct targ_softc *softc, struct targ_cmd_descr *descr,
  653: 	      union ccb *ccb)
  654: {
  655: 	struct ccb_hdr *u_ccbh, *k_ccbh;
  656: 	size_t ccb_len;
  657: 	int error;
  658: 
  659: 	u_ccbh = &descr->user_ccb->ccb_h;
  660: 	k_ccbh = &ccb->ccb_h;
  661: 
  662: 	/*
  663: 	 * There are some fields in the CCB header that need to be
  664: 	 * preserved, the rest we get from the user ccb. (See xpt_merge_ccb)
  665: 	 */
  666: 	xpt_setup_ccb(k_ccbh, softc->path, descr->priority);
  667: 	k_ccbh->retry_count = fuword(&u_ccbh->retry_count);
  668: 	k_ccbh->func_code = descr->func_code;
  669: 	k_ccbh->flags = fuword(&u_ccbh->flags);
  670: 	k_ccbh->timeout = fuword(&u_ccbh->timeout);
  671: 	ccb_len = targccblen(k_ccbh->func_code) - sizeof(struct ccb_hdr);
  672: 	error = copyin(u_ccbh + 1, k_ccbh + 1, ccb_len);
  673: 	if (error != 0) {
  674: 		k_ccbh->status = CAM_REQ_CMP_ERR;
  675: 		return (error);
  676: 	}
  677: 
  678: 	/* Translate usermode abort_ccb pointer to its kernel counterpart */
  679: 	if (k_ccbh->func_code == XPT_ABORT) {
  680: 		struct ccb_abort *cab;
  681: 		struct ccb_hdr *ccb_h;
  682: 		int s;
  683: 
  684: 		cab = (struct ccb_abort *)ccb;
  685: 		s = splsoftcam();
  686: 		TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue,
  687: 		    periph_links.tqe) {
  688: 			struct targ_cmd_descr *ab_descr;
  689: 
  690: 			ab_descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
  691: 			if (ab_descr->user_ccb == cab->abort_ccb) {
  692: 				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  693: 					  ("Changing abort for %p to %p\n",
  694: 					  cab->abort_ccb, ccb_h));
  695: 				cab->abort_ccb = (union ccb *)ccb_h;
  696: 				break;
  697: 			}
  698: 		}
  699: 		splx(s);
  700: 		/* CCB not found, set appropriate status */
  701: 		if (ccb_h == NULL) {
  702: 			k_ccbh->status = CAM_PATH_INVALID;
  703: 			error = ESRCH;
  704: 		}
  705: 	}
  706: 
  707: 	return (error);
  708: }
  709: 
  710: /* Build and send a kernel CCB formed from descr->user_ccb */
  711: static int
  712: targsendccb(struct targ_softc *softc, union ccb *ccb,
  713: 	    struct targ_cmd_descr *descr)
  714: {
  715: 	struct cam_periph_map_info *mapinfo;
  716: 	struct ccb_hdr *ccb_h;
  717: 	int error;
  718: 
  719: 	ccb_h = &ccb->ccb_h;
  720: 	mapinfo = &descr->mapinfo;
  721: 	mapinfo->num_bufs_used = 0;
  722: 
  723: 	/*
  724: 	 * There's no way for the user to have a completion
  725: 	 * function, so we put our own completion function in here.
  726: 	 * We also stash in a reference to our descriptor so targreturnccb()
  727: 	 * can find our mapping info.
  728: 	 */
  729: 	ccb_h->cbfcnp = targdone;
  730: 	ccb_h->targ_descr = descr;
  731: 
  732: 	/*
  733: 	 * We only attempt to map the user memory into kernel space
  734: 	 * if they haven't passed in a physical memory pointer,
  735: 	 * and if there is actually an I/O operation to perform.
  736: 	 * Right now cam_periph_mapmem() only supports SCSI and device
  737: 	 * match CCBs.  For the SCSI CCBs, we only pass the CCB in if
  738: 	 * there's actually data to map.  cam_periph_mapmem() will do the
  739: 	 * right thing, even if there isn't data to map, but since CCBs
  740: 	 * without data are a reasonably common occurance (e.g. test unit
  741: 	 * ready), it will save a few cycles if we check for it here.
  742: 	 */
  743: 	if (((ccb_h->flags & CAM_DATA_PHYS) == 0)
  744: 	 && (((ccb_h->func_code == XPT_CONT_TARGET_IO)
  745: 	    && ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE))
  746: 	  || (ccb_h->func_code == XPT_DEV_MATCH))) {
  747: 
  748: 		error = cam_periph_mapmem(ccb, mapinfo);
  749: 
  750: 		/*
  751: 		 * cam_periph_mapmem returned an error, we can't continue.
  752: 		 * Return the error to the user.
  753: 		 */
  754: 		if (error) {
  755: 			ccb_h->status = CAM_REQ_CMP_ERR;
  756: 			mapinfo->num_bufs_used = 0;
  757: 			return (error);
  758: 		}
  759: 	}
  760: 
  761: 	/*
  762: 	 * Once queued on the pending CCB list, this CCB will be protected
  763: 	 * by our error recovery handler.
  764: 	 */
  765: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("sendccb %p\n", ccb));
  766: 	if (XPT_FC_IS_QUEUED(ccb)) {
  767: 		int s;
  768: 
  769: 		s = splsoftcam();
  770: 		TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,
  771: 				  periph_links.tqe);
  772: 		splx(s);
  773: 	}
  774: 	xpt_action(ccb);
  775: 
  776: 	return (0);
  777: }
  778: 
  779: /* Completion routine for CCBs (called at splsoftcam) */
  780: static void
  781: targdone(struct cam_periph *periph, union ccb *done_ccb)
  782: {
  783: 	struct targ_softc *softc;
  784: 	cam_status status;
  785: 
  786: 	CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("targdone %p\n", done_ccb));
  787: 	softc = (struct targ_softc *)periph->softc;
  788: 	TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,
  789: 		     periph_links.tqe);
  790: 	status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
  791: 
  792: 	/* If we're no longer enabled, throw away CCB */
  793: 	if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
  794: 		targfreeccb(softc, done_ccb);
  795: 		return;
  796: 	}
  797: 	/* abort_all_pending() waits for pending queue to be empty */
  798: 	if (TAILQ_EMPTY(&softc->pending_ccb_queue))
  799: 		wakeup(&softc->pending_ccb_queue);
  800: 
  801: 	switch (done_ccb->ccb_h.func_code) {
  802: 	/* All FC_*_QUEUED CCBs go back to userland */
  803: 	case XPT_IMMED_NOTIFY:
  804: 	case XPT_ACCEPT_TARGET_IO:
  805: 	case XPT_CONT_TARGET_IO:
  806: 		TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,
  807: 				  periph_links.tqe);
  808: 		notify_user(softc);
  809: 		break;
  810: 	default:
  811: 		panic("targdone: impossible xpt opcode %#x",
  812: 		      done_ccb->ccb_h.func_code);
  813: 		/* NOTREACHED */
  814: 	}
  815: }
  816: 
  817: /* Return CCBs to the user from the user queue and abort queue */
  818: static int
  819: targread(dev_t dev, struct uio *uio, int ioflag)
  820: {
  821: 	struct descr_queue	*abort_queue;
  822: 	struct targ_cmd_descr	*user_descr;
  823: 	struct targ_softc	*softc;
  824: 	struct ccb_queue  *user_queue;
  825: 	struct ccb_hdr	  *ccb_h;
  826: 	union  ccb	  *user_ccb;
  827: 	int		   read_len, error, s;
  828: 
  829: 	error = 0;
  830: 	read_len = 0;
  831: 	softc = (struct targ_softc *)dev->si_drv1;
  832: 	user_queue = &softc->user_ccb_queue;
  833: 	abort_queue = &softc->abort_queue;
  834: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
  835: 
  836: 	/* If no data is available, wait or return immediately */
  837: 	s = splsoftcam();
  838: 	ccb_h = TAILQ_FIRST(user_queue);
  839: 	user_descr = TAILQ_FIRST(abort_queue);
  840: 	while (ccb_h == NULL && user_descr == NULL) {
  841: 		if ((ioflag & IO_NDELAY) == 0) {
  842: 			error = tsleep(user_queue, PCATCH, "targrd", 0);
  843: 			ccb_h = TAILQ_FIRST(user_queue);
  844: 			user_descr = TAILQ_FIRST(abort_queue);
  845: 			if (error != 0) {
  846: 				if (error == ERESTART) {
  847: 					continue;
  848: 				} else {
  849: 					splx(s);
  850: 					goto read_fail;
  851: 				}
  852: 			}
  853: 		} else {
  854: 			splx(s);
  855: 			return (EAGAIN);
  856: 		}
  857: 	}
  858: 
  859: 	/* Data is available so fill the user's buffer */
  860: 	while (ccb_h != NULL) {
  861: 		struct targ_cmd_descr *descr;
  862: 
  863: 		if (uio->uio_resid < sizeof(user_ccb))
  864: 			break;
  865: 		TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
  866: 		splx(s);
  867: 		descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
  868: 		user_ccb = descr->user_ccb;
  869: 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  870: 			  ("targread ccb %p (%p)\n", ccb_h, user_ccb));
  871: 		error = targreturnccb(softc, (union ccb *)ccb_h);
  872: 		if (error != 0)
  873: 			goto read_fail;
  874: 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
  875: 		if (error != 0)
  876: 			goto read_fail;
  877: 		read_len += sizeof(user_ccb);
  878: 
  879: 		s = splsoftcam();
  880: 		ccb_h = TAILQ_FIRST(user_queue);
  881: 	}
  882: 
  883: 	/* Flush out any aborted descriptors */
  884: 	while (user_descr != NULL) {
  885: 		if (uio->uio_resid < sizeof(user_ccb))
  886: 			break;
  887: 		TAILQ_REMOVE(abort_queue, user_descr, tqe);
  888: 		splx(s);
  889: 		user_ccb = user_descr->user_ccb;
  890: 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
  891: 			  ("targread aborted descr %p (%p)\n",
  892: 			  user_descr, user_ccb));
  893: 		suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
  894: 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
  895: 		if (error != 0)
  896: 			goto read_fail;
  897: 		read_len += sizeof(user_ccb);
  898: 
  899: 		s = splsoftcam();
  900: 		user_descr = TAILQ_FIRST(abort_queue);
  901: 	}
  902: 	splx(s);
  903: 
  904: 	/*
  905: 	 * If we've successfully read some amount of data, don't report an
  906: 	 * error.  If the error is persistent, it will be reported on the
  907: 	 * next read().
  908: 	 */
  909: 	if (read_len == 0 && uio->uio_resid != 0)
  910: 		error = ENOSPC;
  911: 
  912: read_fail:
  913: 	return (error);
  914: }
  915: 
  916: /* Copy completed ccb back to the user */
  917: static int
  918: targreturnccb(struct targ_softc *softc, union ccb *ccb)
  919: {
  920: 	struct targ_cmd_descr *descr;
  921: 	struct ccb_hdr *u_ccbh;
  922: 	size_t ccb_len;
  923: 	int error;
  924: 
  925: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targreturnccb %p\n", ccb));
  926: 	descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
  927: 	u_ccbh = &descr->user_ccb->ccb_h;
  928: 
  929: 	/* Copy out the central portion of the ccb_hdr */
  930: 	copyout(&ccb->ccb_h.retry_count, &u_ccbh->retry_count,
  931: 		offsetof(struct ccb_hdr, periph_priv) -
  932: 		offsetof(struct ccb_hdr, retry_count));
  933: 
  934: 	/* Copy out the rest of the ccb (after the ccb_hdr) */
  935: 	ccb_len = targccblen(ccb->ccb_h.func_code) - sizeof(struct ccb_hdr);
  936: 	if (descr->mapinfo.num_bufs_used != 0)
  937: 		cam_periph_unmapmem(ccb, &descr->mapinfo);
  938: 	error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
  939: 	if (error != 0) {
  940: 		xpt_print_path(softc->path);
  941: 		printf("targreturnccb - CCB copyout failed (%d)\n",
  942: 		       error);
  943: 	}
  944: 	/* Free CCB or send back to devq. */
  945: 	targfreeccb(softc, ccb);
  946: 
  947: 	return (error);
  948: }
  949: 
  950: static union ccb *
  951: targgetccb(struct targ_softc *softc, xpt_opcode type, int priority)
  952: {
  953: 	union ccb *ccb;
  954: 	int ccb_len;
  955: 
  956: 	ccb_len = targccblen(type);
  957: 	MALLOC(ccb, union ccb *, ccb_len, M_TARG, M_INTWAIT);
  958: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
  959: 
  960: 	xpt_setup_ccb(&ccb->ccb_h, softc->path, priority);
  961: 	ccb->ccb_h.func_code = type;
  962: 	ccb->ccb_h.cbfcnp = targdone;
  963: 	ccb->ccb_h.targ_descr = targgetdescr(softc);
  964: 	return (ccb);
  965: }
  966: 
  967: static void
  968: targfreeccb(struct targ_softc *softc, union ccb *ccb)
  969: {
  970: 	CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("targfreeccb descr %p and\n",
  971: 			ccb->ccb_h.targ_descr));
  972: 	FREE(ccb->ccb_h.targ_descr, M_TARG);
  973: 
  974: 	switch (ccb->ccb_h.func_code) {
  975: 	case XPT_ACCEPT_TARGET_IO:
  976: 	case XPT_IMMED_NOTIFY:
  977: 		CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("freeing ccb %p\n", ccb));
  978: 		FREE(ccb, M_TARG);
  979: 		break;
  980: 	default:
  981: 		/* Send back CCB if we got it from the periph */
  982: 		if (XPT_FC_IS_QUEUED(ccb)) {
  983: 			CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
  984: 					("returning queued ccb %p\n", ccb));
  985: 			xpt_release_ccb(ccb);
  986: 		} else {
  987: 			CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
  988: 					("freeing ccb %p\n", ccb));
  989: 			FREE(ccb, M_TARG);
  990: 		}
  991: 		break;
  992: 	}
  993: }
  994: 
  995: static struct targ_cmd_descr *
  996: targgetdescr(struct targ_softc *softc)
  997: {
  998: 	struct targ_cmd_descr *descr;
  999: 
 1000: 	MALLOC(descr, struct targ_cmd_descr *, sizeof(*descr),
 1001: 		M_TARG, M_INTWAIT);
 1002: 	descr->mapinfo.num_bufs_used = 0;
 1003: 	return (descr);
 1004: }
 1005: 
 1006: static void
 1007: targinit(void)
 1008: {
 1009: 	cdevsw_add(&targ_cdevsw);
 1010: }
 1011: 
 1012: static void
 1013: targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
 1014: {
 1015: 	/* All events are handled in usermode by INOTs */
 1016: 	panic("targasync() called, should be an INOT instead");
 1017: }
 1018: 
 1019: /* Cancel all pending requests and CCBs awaiting work. */
 1020: static void
 1021: abort_all_pending(struct targ_softc *softc)
 1022: {
 1023: 	struct targ_cmd_descr   *descr;
 1024: 	struct ccb_abort	 cab;
 1025: 	struct ccb_hdr		*ccb_h;
 1026: 
 1027: 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
 1028: 
 1029: 	/* First abort the descriptors awaiting resources */
 1030: 	while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
 1031: 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
 1032: 			  ("Aborting descr from workq %p\n", descr));
 1033: 		TAILQ_REMOVE(&softc->work_queue, descr, tqe);
 1034: 		TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
 1035: 	}
 1036: 
 1037: 	/* 
 1038: 	 * Then abort all pending CCBs.
 1039: 	 * targdone() will return the aborted CCB via user_ccb_queue
 1040: 	 */
 1041: 	xpt_setup_ccb(&cab.ccb_h, softc->path, /*priority*/0);
 1042: 	cab.ccb_h.func_code = XPT_ABORT;
 1043: 	cab.ccb_h.status = CAM_REQ_CMP_ERR;
 1044: 	TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue, periph_links.tqe) {
 1045: 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
 1046: 			  ("Aborting pending CCB %p\n", ccb_h));
 1047: 		cab.abort_ccb = (union ccb *)ccb_h;
 1048: 		xpt_action((union ccb *)&cab);
 1049: 		if (cab.ccb_h.status != CAM_REQ_CMP) {
 1050: 			xpt_print_path(cab.ccb_h.path);
 1051: 			printf("Unable to abort CCB, status %#x\n",
 1052: 			       cab.ccb_h.status);
 1053: 		}
 1054: 	}
 1055: 
 1056: 	/* If we aborted at least one pending CCB ok, wait for it. */
 1057: 	if (cab.ccb_h.status == CAM_REQ_CMP) {
 1058: 		tsleep(&softc->pending_ccb_queue, PCATCH, "tgabrt", 0);
 1059: 	}
 1060: 
 1061: 	/* If we aborted anything from the work queue, wakeup user. */
 1062: 	if (!TAILQ_EMPTY(&softc->user_ccb_queue)
 1063: 	 || !TAILQ_EMPTY(&softc->abort_queue))
 1064: 		notify_user(softc);
 1065: }
 1066: 
 1067: /* Notify the user that data is ready */
 1068: static void
 1069: notify_user(struct targ_softc *softc)
 1070: {
 1071: 	/*
 1072: 	 * Notify users sleeping via poll(), kqueue(), and
 1073: 	 * blocking read().
 1074: 	 */
 1075: 	selwakeup(&softc->read_select);
 1076: 	KNOTE(&softc->read_select.si_note, 0);
 1077: 	wakeup(&softc->user_ccb_queue);
 1078: }
 1079: 
 1080: /* Convert CAM status to errno values */
 1081: static int
 1082: targcamstatus(cam_status status)
 1083: {
 1084: 	switch (status & CAM_STATUS_MASK) {
 1085: 	case CAM_REQ_CMP:	/* CCB request completed without error */
 1086: 		return (0);
 1087: 	case CAM_REQ_INPROG:	/* CCB request is in progress */
 1088: 		return (EINPROGRESS);
 1089: 	case CAM_REQ_CMP_ERR:	/* CCB request completed with an error */
 1090: 		return (EIO);
 1091: 	case CAM_PROVIDE_FAIL:	/* Unable to provide requested capability */
 1092: 		return (ENOTTY);
 1093: 	case CAM_FUNC_NOTAVAIL:	/* The requested function is not available */
 1094: 		return (ENOTSUP);
 1095: 	case CAM_LUN_ALRDY_ENA:	/* LUN is already enabled for target mode */
 1096: 		return (EADDRINUSE);
 1097: 	case CAM_PATH_INVALID:	/* Supplied Path ID is invalid */
 1098: 	case CAM_DEV_NOT_THERE:	/* SCSI Device Not Installed/there */
 1099: 		return (ENOENT);
 1100: 	case CAM_REQ_ABORTED:	/* CCB request aborted by the host */
 1101: 		return (ECANCELED);
 1102: 	case CAM_CMD_TIMEOUT:	/* Command timeout */
 1103: 		return (ETIMEDOUT);
 1104: 	case CAM_REQUEUE_REQ:	/* Requeue to preserve transaction ordering */
 1105: 		return (EAGAIN);
 1106: 	case CAM_REQ_INVALID:	/* CCB request was invalid */
 1107: 		return (EINVAL);
 1108: 	case CAM_RESRC_UNAVAIL:	/* Resource Unavailable */
 1109: 		return (ENOMEM);
 1110: 	case CAM_BUSY:		/* CAM subsytem is busy */
 1111: 	case CAM_UA_ABORT:	/* Unable to abort CCB request */
 1112: 		return (EBUSY);
 1113: 	default:
 1114: 		return (ENXIO);
 1115: 	}
 1116: }
 1117: 
 1118: static size_t
 1119: targccblen(xpt_opcode func_code)
 1120: {
 1121: 	int len;
 1122: 
 1123: 	/* Codes we expect to see as a target */
 1124: 	switch (func_code) {
 1125: 	case XPT_CONT_TARGET_IO:
 1126: 	case XPT_SCSI_IO:
 1127: 		len = sizeof(struct ccb_scsiio);
 1128: 		break;
 1129: 	case XPT_ACCEPT_TARGET_IO:
 1130: 		len = sizeof(struct ccb_accept_tio);
 1131: 		break;
 1132: 	case XPT_IMMED_NOTIFY:
 1133: 		len = sizeof(struct ccb_immed_notify);
 1134: 		break;
 1135: 	case XPT_REL_SIMQ:
 1136: 		len = sizeof(struct ccb_relsim);
 1137: 		break;
 1138: 	case XPT_PATH_INQ:
 1139: 		len = sizeof(struct ccb_pathinq);
 1140: 		break;
 1141: 	case XPT_DEBUG:
 1142: 		len = sizeof(struct ccb_debug);
 1143: 		break;
 1144: 	case XPT_ABORT:
 1145: 		len = sizeof(struct ccb_abort);
 1146: 		break;
 1147: 	case XPT_EN_LUN:
 1148: 		len = sizeof(struct ccb_en_lun);
 1149: 		break;
 1150: 	default:
 1151: 		len = sizeof(union ccb);
 1152: 		break;
 1153: 	}
 1154: 
 1155: 	return (len);
 1156: }