xref: /dragonfly/sys/bus/cam/scsi/scsi_target.c (revision 0ac6bf9d)
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.13 2006/09/10 01:26:32 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 #include <sys/thread2.h>
42 
43 #include "../cam.h"
44 #include "../cam_ccb.h"
45 #include "../cam_periph.h"
46 #include "../cam_xpt_periph.h"
47 #include "scsi_targetio.h"
48 
49 /* Transaction information attached to each CCB sent by the user */
50 struct targ_cmd_descr {
51 	struct cam_periph_map_info  mapinfo;
52 	TAILQ_ENTRY(targ_cmd_descr) tqe;
53 	union ccb *user_ccb;
54 	int	   priority;
55 	int	   func_code;
56 };
57 
58 /* Offset into the private CCB area for storing our descriptor */
59 #define targ_descr	periph_priv.entries[1].ptr
60 
61 TAILQ_HEAD(descr_queue, targ_cmd_descr);
62 
63 typedef enum {
64 	TARG_STATE_RESV		= 0x00, /* Invalid state */
65 	TARG_STATE_OPENED	= 0x01, /* Device opened, softc initialized */
66 	TARG_STATE_LUN_ENABLED	= 0x02  /* Device enabled for a path */
67 } targ_state;
68 
69 /* Per-instance device software context */
70 struct targ_softc {
71 	/* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
72 	struct ccb_queue	 pending_ccb_queue;
73 
74 	/* Command descriptors awaiting CTIO resources from the XPT */
75 	struct descr_queue	 work_queue;
76 
77 	/* Command descriptors that have been aborted back to the user. */
78 	struct descr_queue	 abort_queue;
79 
80 	/*
81 	 * Queue of CCBs that have been copied out to userland, but our
82 	 * userland daemon has not yet seen.
83 	 */
84 	struct ccb_queue	 user_ccb_queue;
85 
86 	struct cam_periph	*periph;
87 	struct cam_path		*path;
88 	targ_state		 state;
89 	struct selinfo		 read_select;
90 	struct devstat		 device_stats;
91 };
92 
93 static d_open_t		targopen;
94 static d_close_t	targclose;
95 static d_read_t		targread;
96 static d_write_t	targwrite;
97 static d_ioctl_t	targioctl;
98 static d_poll_t		targpoll;
99 static d_kqfilter_t	targkqfilter;
100 static void		targreadfiltdetach(struct knote *kn);
101 static int		targreadfilt(struct knote *kn, long hint);
102 static struct filterops targread_filtops =
103 	{ 1, NULL, targreadfiltdetach, targreadfilt };
104 
105 #define TARG_CDEV_MAJOR 65
106 static struct cdevsw targ_cdevsw = {
107 	/* name */	"targ",
108 	/* maj */	TARG_CDEV_MAJOR,
109 	/* flags */	D_KQFILTER,
110 	/* port */      NULL,
111 	/* clone */     NULL,
112 
113 	/* open */	targopen,
114 	/* close */	targclose,
115 	/* read */	targread,
116 	/* write */	targwrite,
117 	/* ioctl */	targioctl,
118 	/* poll */	targpoll,
119 	/* mmap */	nommap,
120 	/* strategy */	nostrategy,
121 	/* dump */	nodump,
122 	/* psize */	nopsize,
123 	/* kqfilter */	targkqfilter
124 };
125 
126 static cam_status	targendislun(struct cam_path *path, int enable,
127 				     int grp6_len, int grp7_len);
128 static cam_status	targenable(struct targ_softc *softc,
129 				   struct cam_path *path,
130 				   int grp6_len, int grp7_len);
131 static cam_status	targdisable(struct targ_softc *softc);
132 static periph_ctor_t    targctor;
133 static periph_dtor_t    targdtor;
134 static periph_start_t   targstart;
135 static int		targusermerge(struct targ_softc *softc,
136 				      struct targ_cmd_descr *descr,
137 				      union ccb *ccb);
138 static int		targsendccb(struct targ_softc *softc, union ccb *ccb,
139 				    struct targ_cmd_descr *descr);
140 static void		targdone(struct cam_periph *periph,
141 				 union  ccb *done_ccb);
142 static int		targreturnccb(struct targ_softc *softc,
143 				      union  ccb *ccb);
144 static union ccb *	targgetccb(struct targ_softc *softc, xpt_opcode type,
145 				   int priority);
146 static void		targfreeccb(struct targ_softc *softc, union ccb *ccb);
147 static struct targ_cmd_descr *
148 			targgetdescr(struct targ_softc *softc);
149 static periph_init_t	targinit;
150 static void		targasync(void *callback_arg, u_int32_t code,
151 				  struct cam_path *path, void *arg);
152 static void		abort_all_pending(struct targ_softc *softc);
153 static void		notify_user(struct targ_softc *softc);
154 static int		targcamstatus(cam_status status);
155 static size_t		targccblen(xpt_opcode func_code);
156 
157 static struct periph_driver targdriver =
158 {
159 	targinit, "targ",
160 	TAILQ_HEAD_INITIALIZER(targdriver.units), /* generation */ 0
161 };
162 DATA_SET(periphdriver_set, targdriver);
163 
164 static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
165 
166 /* Create softc and initialize it. Only one proc can open each targ device. */
167 static int
168 targopen(cdev_t dev, int flags, int fmt, struct proc *p)
169 {
170 	struct targ_softc *softc;
171 
172 	if (dev->si_drv1 != 0) {
173 		return (EBUSY);
174 	}
175 
176 	/* Mark device busy before any potentially blocking operations */
177 	dev->si_drv1 = (void *)~0;
178 	reference_dev(dev);		/* save ref for later destroy_dev() */
179 
180 	/* Create the targ device, allocate its softc, initialize it */
181 	make_dev(&targ_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 0600,
182 			 "targ%d", lminor(dev));
183 	MALLOC(softc, struct targ_softc *, sizeof(*softc), M_TARG,
184 	       M_INTWAIT | M_ZERO);
185 	dev->si_drv1 = softc;
186 	softc->state = TARG_STATE_OPENED;
187 	softc->periph = NULL;
188 	softc->path = NULL;
189 
190 	TAILQ_INIT(&softc->pending_ccb_queue);
191 	TAILQ_INIT(&softc->work_queue);
192 	TAILQ_INIT(&softc->abort_queue);
193 	TAILQ_INIT(&softc->user_ccb_queue);
194 
195 	return (0);
196 }
197 
198 /* Disable LUN if enabled and teardown softc */
199 static int
200 targclose(cdev_t dev, int flag, int fmt, struct proc *p)
201 {
202 	struct targ_softc     *softc;
203 	int    error;
204 
205 	softc = (struct targ_softc *)dev->si_drv1;
206 	error = targdisable(softc);
207 	if (error == CAM_REQ_CMP) {
208 		dev->si_drv1 = 0;
209 		if (softc->periph != NULL) {
210 			cam_periph_invalidate(softc->periph);
211 			softc->periph = NULL;
212 		}
213 		destroy_dev(dev);	/* eats the open ref */
214 		FREE(softc, M_TARG);
215 	} else {
216 		release_dev(dev);
217 	}
218 	return (error);
219 }
220 
221 /* Enable/disable LUNs, set debugging level */
222 static int
223 targioctl(cdev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
224 {
225 	struct targ_softc *softc;
226 	cam_status	   status;
227 
228 	softc = (struct targ_softc *)dev->si_drv1;
229 
230 	switch (cmd) {
231 	case TARGIOCENABLE:
232 	{
233 		struct ioc_enable_lun	*new_lun;
234 		struct cam_path		*path;
235 
236 		new_lun = (struct ioc_enable_lun *)addr;
237 		status = xpt_create_path(&path, /*periph*/NULL,
238 					 new_lun->path_id,
239 					 new_lun->target_id,
240 					 new_lun->lun_id);
241 		if (status != CAM_REQ_CMP) {
242 			printf("Couldn't create path, status %#x\n", status);
243 			break;
244 		}
245 		status = targenable(softc, path, new_lun->grp6_len,
246 				    new_lun->grp7_len);
247 		xpt_free_path(path);
248 		break;
249 	}
250 	case TARGIOCDISABLE:
251 		status = targdisable(softc);
252 		break;
253 	case TARGIOCDEBUG:
254 	{
255 #ifdef	CAMDEBUG
256 		struct ccb_debug cdbg;
257 
258 		bzero(&cdbg, sizeof cdbg);
259 		if (*((int *)addr) != 0)
260 			cdbg.flags = CAM_DEBUG_PERIPH;
261 		else
262 			cdbg.flags = CAM_DEBUG_NONE;
263 		xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
264 		cdbg.ccb_h.func_code = XPT_DEBUG;
265 		cdbg.ccb_h.cbfcnp = targdone;
266 
267 		/* If no periph available, disallow debugging changes */
268 		if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
269 			status = CAM_DEV_NOT_THERE;
270 			break;
271 		}
272 		xpt_action((union ccb *)&cdbg);
273 		status = cdbg.ccb_h.status & CAM_STATUS_MASK;
274 #else
275 		status = CAM_FUNC_NOTAVAIL;
276 #endif
277 		break;
278 	}
279 	default:
280 		status = CAM_PROVIDE_FAIL;
281 		break;
282 	}
283 
284 	return (targcamstatus(status));
285 }
286 
287 /* Writes are always ready, reads wait for user_ccb_queue or abort_queue */
288 static int
289 targpoll(struct dev_poll_args *ap)
290 {
291 	struct targ_softc *softc;
292 	int	revents;
293 
294 	softc = (struct targ_softc *)dev->si_drv1;
295 
296 	/* Poll for write() is always ok. */
297 	revents = ap->a_events & (POLLOUT | POLLWRNORM);
298 	if ((ap->a_events & (POLLIN | POLLRDNORM)) != 0) {
299 		crit_enter();
300 		/* Poll for read() depends on user and abort queues. */
301 		if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
302 		    !TAILQ_EMPTY(&softc->abort_queue)) {
303 			revents |= ap->a_events & (POLLIN | POLLRDNORM);
304 		}
305 		/* Only sleep if the user didn't poll for write. */
306 		if (revents == 0)
307 			selrecord(p, &softc->read_select);
308 		crit_exit();
309 	}
310 	ap->a_events = revents;
311 	return (0);
312 }
313 
314 static int
315 targkqfilter(cdev_t dev, struct knote *kn)
316 {
317 	struct  targ_softc *softc;
318 
319 	softc = (struct targ_softc *)dev->si_drv1;
320 	kn->kn_hook = (caddr_t)softc;
321 	kn->kn_fop = &targread_filtops;
322 	crit_enter();
323 	SLIST_INSERT_HEAD(&softc->read_select.si_note, kn, kn_selnext);
324 	crit_exit();
325 	return (0);
326 }
327 
328 static void
329 targreadfiltdetach(struct knote *kn)
330 {
331 	struct  targ_softc *softc;
332 
333 	softc = (struct targ_softc *)kn->kn_hook;
334 	crit_enter();
335 	SLIST_REMOVE(&softc->read_select.si_note, kn, knote, kn_selnext);
336 	crit_exit();
337 }
338 
339 /* Notify the user's kqueue when the user queue or abort queue gets a CCB */
340 static int
341 targreadfilt(struct knote *kn, long hint)
342 {
343 	struct targ_softc *softc;
344 	int	retval;
345 
346 	softc = (struct targ_softc *)kn->kn_hook;
347 	crit_enter();
348 	retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
349 		 !TAILQ_EMPTY(&softc->abort_queue);
350 	crit_exit();
351 	return (retval);
352 }
353 
354 /* Send the HBA the enable/disable message */
355 static cam_status
356 targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
357 {
358 	struct ccb_en_lun en_ccb;
359 	cam_status	  status;
360 
361 	/* Tell the lun to begin answering selects */
362 	xpt_setup_ccb(&en_ccb.ccb_h, path, /*priority*/1);
363 	en_ccb.ccb_h.func_code = XPT_EN_LUN;
364 	/* Don't need support for any vendor specific commands */
365 	en_ccb.grp6_len = grp6_len;
366 	en_ccb.grp7_len = grp7_len;
367 	en_ccb.enable = enable ? 1 : 0;
368 	xpt_action((union ccb *)&en_ccb);
369 	status = en_ccb.ccb_h.status & CAM_STATUS_MASK;
370 	if (status != CAM_REQ_CMP) {
371 		xpt_print_path(path);
372 		printf("%sable lun CCB rejected, status %#x\n",
373 		       enable ? "en" : "dis", status);
374 	}
375 	return (status);
376 }
377 
378 /* Enable target mode on a LUN, given its path */
379 static cam_status
380 targenable(struct targ_softc *softc, struct cam_path *path, int grp6_len,
381 	   int grp7_len)
382 {
383 	struct cam_periph *periph;
384 	struct ccb_pathinq cpi;
385 	cam_status	   status;
386 
387 	if ((softc->state & TARG_STATE_LUN_ENABLED) != 0)
388 		return (CAM_LUN_ALRDY_ENA);
389 
390 	/* Make sure SIM supports target mode */
391 	xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
392 	cpi.ccb_h.func_code = XPT_PATH_INQ;
393 	xpt_action((union ccb *)&cpi);
394 	status = cpi.ccb_h.status & CAM_STATUS_MASK;
395 	if (status != CAM_REQ_CMP) {
396 		printf("pathinq failed, status %#x\n", status);
397 		goto enable_fail;
398 	}
399 	if ((cpi.target_sprt & PIT_PROCESSOR) == 0) {
400 		printf("controller does not support target mode\n");
401 		status = CAM_FUNC_NOTAVAIL;
402 		goto enable_fail;
403 	}
404 
405 	/* Destroy any periph on our path if it is disabled */
406 	periph = cam_periph_find(path, "targ");
407 	if (periph != NULL) {
408 		struct targ_softc *del_softc;
409 
410 		del_softc = (struct targ_softc *)periph->softc;
411 		if ((del_softc->state & TARG_STATE_LUN_ENABLED) == 0) {
412 			cam_periph_invalidate(del_softc->periph);
413 			del_softc->periph = NULL;
414 		} else {
415 			printf("Requested path still in use by targ%d\n",
416 			       periph->unit_number);
417 			status = CAM_LUN_ALRDY_ENA;
418 			goto enable_fail;
419 		}
420 	}
421 
422 	/* Create a periph instance attached to this path */
423 	status = cam_periph_alloc(targctor, NULL, targdtor, targstart,
424 			"targ", CAM_PERIPH_BIO, path, targasync, 0, softc);
425 	if (status != CAM_REQ_CMP) {
426 		printf("cam_periph_alloc failed, status %#x\n", status);
427 		goto enable_fail;
428 	}
429 
430 	/* Ensure that the periph now exists. */
431 	if (cam_periph_find(path, "targ") == NULL) {
432 		panic("targenable: succeeded but no periph?");
433 		/* NOTREACHED */
434 	}
435 
436 	/* Send the enable lun message */
437 	status = targendislun(path, /*enable*/1, grp6_len, grp7_len);
438 	if (status != CAM_REQ_CMP) {
439 		printf("enable lun failed, status %#x\n", status);
440 		goto enable_fail;
441 	}
442 	softc->state |= TARG_STATE_LUN_ENABLED;
443 
444 enable_fail:
445 	return (status);
446 }
447 
448 /* Disable this softc's target instance if enabled */
449 static cam_status
450 targdisable(struct targ_softc *softc)
451 {
452 	cam_status status;
453 
454 	if ((softc->state & TARG_STATE_LUN_ENABLED) == 0)
455 		return (CAM_REQ_CMP);
456 
457 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targdisable\n"));
458 
459 	/* Abort any ccbs pending on the controller */
460 	crit_enter();
461 	abort_all_pending(softc);
462 	crit_exit();
463 
464 	/* Disable this lun */
465 	status = targendislun(softc->path, /*enable*/0,
466 			      /*grp6_len*/0, /*grp7_len*/0);
467 	if (status == CAM_REQ_CMP)
468 		softc->state &= ~TARG_STATE_LUN_ENABLED;
469 	else
470 		printf("Disable lun failed, status %#x\n", status);
471 
472 	return (status);
473 }
474 
475 /* Initialize a periph (called from cam_periph_alloc) */
476 static cam_status
477 targctor(struct cam_periph *periph, void *arg)
478 {
479 	struct targ_softc *softc;
480 
481 	/* Store pointer to softc for periph-driven routines */
482 	softc = (struct targ_softc *)arg;
483 	periph->softc = softc;
484 	softc->periph = periph;
485 	softc->path = periph->path;
486 	return (CAM_REQ_CMP);
487 }
488 
489 static void
490 targdtor(struct cam_periph *periph)
491 {
492 	struct targ_softc     *softc;
493 	struct ccb_hdr	      *ccb_h;
494 	struct targ_cmd_descr *descr;
495 
496 	softc = (struct targ_softc *)periph->softc;
497 
498 	/*
499 	 * targdisable() aborts CCBs back to the user and leaves them
500 	 * on user_ccb_queue and abort_queue in case the user is still
501 	 * interested in them.  We free them now.
502 	 */
503 	while ((ccb_h = TAILQ_FIRST(&softc->user_ccb_queue)) != NULL) {
504 		TAILQ_REMOVE(&softc->user_ccb_queue, ccb_h, periph_links.tqe);
505 		targfreeccb(softc, (union ccb *)ccb_h);
506 	}
507 	while ((descr = TAILQ_FIRST(&softc->abort_queue)) != NULL) {
508 		TAILQ_REMOVE(&softc->abort_queue, descr, tqe);
509 		FREE(descr, M_TARG);
510 	}
511 
512 	softc->periph = NULL;
513 	softc->path = NULL;
514 	periph->softc = NULL;
515 }
516 
517 /* Receive CCBs from user mode proc and send them to the HBA */
518 static int
519 targwrite(cdev_t dev, struct uio *uio, int ioflag)
520 {
521 	union ccb *user_ccb;
522 	struct targ_softc *softc;
523 	struct targ_cmd_descr *descr;
524 	int write_len, error;
525 	int func_code, priority;
526 
527 	softc = (struct targ_softc *)dev->si_drv1;
528 	write_len = error = 0;
529 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
530 		  ("write - uio_resid %d\n", uio->uio_resid));
531 	while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
532 		union ccb *ccb;
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 			crit_enter();
557 			TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
558 					  &ccb->ccb_h,
559 					  periph_links.tqe);
560 			crit_exit();
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 				crit_enter();
572 				TAILQ_INSERT_TAIL(&softc->work_queue,
573 						  descr, tqe);
574 				crit_exit();
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 error;
615 
616 	softc = (struct targ_softc *)periph->softc;
617 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targstart %p\n", start_ccb));
618 
619 	crit_enter();
620 	descr = TAILQ_FIRST(&softc->work_queue);
621 	if (descr == NULL) {
622 		crit_exit();
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 		crit_exit();
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 			crit_enter();
640 			TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
641 			crit_exit();
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 		crit_enter();
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 		crit_exit();
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 		crit_enter();
768 		TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,
769 				  periph_links.tqe);
770 		crit_exit();
771 	}
772 	xpt_action(ccb);
773 
774 	return (0);
775 }
776 
777 /* Completion routine for CCBs (called in a critical section) */
778 static void
779 targdone(struct cam_periph *periph, union ccb *done_ccb)
780 {
781 	struct targ_softc *softc;
782 	cam_status status;
783 
784 	CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("targdone %p\n", done_ccb));
785 	softc = (struct targ_softc *)periph->softc;
786 	TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,
787 		     periph_links.tqe);
788 	status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
789 
790 	/* If we're no longer enabled, throw away CCB */
791 	if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
792 		targfreeccb(softc, done_ccb);
793 		return;
794 	}
795 	/* abort_all_pending() waits for pending queue to be empty */
796 	if (TAILQ_EMPTY(&softc->pending_ccb_queue))
797 		wakeup(&softc->pending_ccb_queue);
798 
799 	switch (done_ccb->ccb_h.func_code) {
800 	/* All FC_*_QUEUED CCBs go back to userland */
801 	case XPT_IMMED_NOTIFY:
802 	case XPT_ACCEPT_TARGET_IO:
803 	case XPT_CONT_TARGET_IO:
804 		TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,
805 				  periph_links.tqe);
806 		notify_user(softc);
807 		break;
808 	default:
809 		panic("targdone: impossible xpt opcode %#x",
810 		      done_ccb->ccb_h.func_code);
811 		/* NOTREACHED */
812 	}
813 }
814 
815 /* Return CCBs to the user from the user queue and abort queue */
816 static int
817 targread(cdev_t dev, struct uio *uio, int ioflag)
818 {
819 	struct descr_queue	*abort_queue;
820 	struct targ_cmd_descr	*user_descr;
821 	struct targ_softc	*softc;
822 	struct ccb_queue  *user_queue;
823 	struct ccb_hdr	  *ccb_h;
824 	union  ccb	  *user_ccb;
825 	int		   read_len, error;
826 
827 	error = 0;
828 	read_len = 0;
829 	softc = (struct targ_softc *)dev->si_drv1;
830 	user_queue = &softc->user_ccb_queue;
831 	abort_queue = &softc->abort_queue;
832 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
833 
834 	/* If no data is available, wait or return immediately */
835 	crit_enter();
836 	ccb_h = TAILQ_FIRST(user_queue);
837 	user_descr = TAILQ_FIRST(abort_queue);
838 	while (ccb_h == NULL && user_descr == NULL) {
839 		if ((ioflag & IO_NDELAY) == 0) {
840 			error = tsleep(user_queue, PCATCH, "targrd", 0);
841 			ccb_h = TAILQ_FIRST(user_queue);
842 			user_descr = TAILQ_FIRST(abort_queue);
843 			if (error != 0) {
844 				if (error == ERESTART) {
845 					continue;
846 				} else {
847 					crit_exit();
848 					goto read_fail;
849 				}
850 			}
851 		} else {
852 			crit_exit();
853 			return (EAGAIN);
854 		}
855 	}
856 
857 	/* Data is available so fill the user's buffer */
858 	while (ccb_h != NULL) {
859 		struct targ_cmd_descr *descr;
860 
861 		if (uio->uio_resid < sizeof(user_ccb))
862 			break;
863 		TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
864 		crit_exit();
865 		descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
866 		user_ccb = descr->user_ccb;
867 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
868 			  ("targread ccb %p (%p)\n", ccb_h, user_ccb));
869 		error = targreturnccb(softc, (union ccb *)ccb_h);
870 		if (error != 0)
871 			goto read_fail;
872 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
873 		if (error != 0)
874 			goto read_fail;
875 		read_len += sizeof(user_ccb);
876 
877 		crit_enter();
878 		ccb_h = TAILQ_FIRST(user_queue);
879 	}
880 
881 	/* Flush out any aborted descriptors */
882 	while (user_descr != NULL) {
883 		if (uio->uio_resid < sizeof(user_ccb))
884 			break;
885 		TAILQ_REMOVE(abort_queue, user_descr, tqe);
886 		crit_exit();
887 		user_ccb = user_descr->user_ccb;
888 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
889 			  ("targread aborted descr %p (%p)\n",
890 			  user_descr, user_ccb));
891 		suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
892 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
893 		if (error != 0)
894 			goto read_fail;
895 		read_len += sizeof(user_ccb);
896 
897 		crit_enter();
898 		user_descr = TAILQ_FIRST(abort_queue);
899 	}
900 	crit_exit();
901 
902 	/*
903 	 * If we've successfully read some amount of data, don't report an
904 	 * error.  If the error is persistent, it will be reported on the
905 	 * next read().
906 	 */
907 	if (read_len == 0 && uio->uio_resid != 0)
908 		error = ENOSPC;
909 
910 read_fail:
911 	return (error);
912 }
913 
914 /* Copy completed ccb back to the user */
915 static int
916 targreturnccb(struct targ_softc *softc, union ccb *ccb)
917 {
918 	struct targ_cmd_descr *descr;
919 	struct ccb_hdr *u_ccbh;
920 	size_t ccb_len;
921 	int error;
922 
923 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targreturnccb %p\n", ccb));
924 	descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
925 	u_ccbh = &descr->user_ccb->ccb_h;
926 
927 	/* Copy out the central portion of the ccb_hdr */
928 	copyout(&ccb->ccb_h.retry_count, &u_ccbh->retry_count,
929 		offsetof(struct ccb_hdr, periph_priv) -
930 		offsetof(struct ccb_hdr, retry_count));
931 
932 	/* Copy out the rest of the ccb (after the ccb_hdr) */
933 	ccb_len = targccblen(ccb->ccb_h.func_code) - sizeof(struct ccb_hdr);
934 	if (descr->mapinfo.num_bufs_used != 0)
935 		cam_periph_unmapmem(ccb, &descr->mapinfo);
936 	error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
937 	if (error != 0) {
938 		xpt_print_path(softc->path);
939 		printf("targreturnccb - CCB copyout failed (%d)\n",
940 		       error);
941 	}
942 	/* Free CCB or send back to devq. */
943 	targfreeccb(softc, ccb);
944 
945 	return (error);
946 }
947 
948 static union ccb *
949 targgetccb(struct targ_softc *softc, xpt_opcode type, int priority)
950 {
951 	union ccb *ccb;
952 	int ccb_len;
953 
954 	ccb_len = targccblen(type);
955 	MALLOC(ccb, union ccb *, ccb_len, M_TARG, M_INTWAIT);
956 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
957 
958 	xpt_setup_ccb(&ccb->ccb_h, softc->path, priority);
959 	ccb->ccb_h.func_code = type;
960 	ccb->ccb_h.cbfcnp = targdone;
961 	ccb->ccb_h.targ_descr = targgetdescr(softc);
962 	return (ccb);
963 }
964 
965 static void
966 targfreeccb(struct targ_softc *softc, union ccb *ccb)
967 {
968 	CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("targfreeccb descr %p and\n",
969 			ccb->ccb_h.targ_descr));
970 	FREE(ccb->ccb_h.targ_descr, M_TARG);
971 
972 	switch (ccb->ccb_h.func_code) {
973 	case XPT_ACCEPT_TARGET_IO:
974 	case XPT_IMMED_NOTIFY:
975 		CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("freeing ccb %p\n", ccb));
976 		FREE(ccb, M_TARG);
977 		break;
978 	default:
979 		/* Send back CCB if we got it from the periph */
980 		if (XPT_FC_IS_QUEUED(ccb)) {
981 			CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
982 					("returning queued ccb %p\n", ccb));
983 			xpt_release_ccb(ccb);
984 		} else {
985 			CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
986 					("freeing ccb %p\n", ccb));
987 			FREE(ccb, M_TARG);
988 		}
989 		break;
990 	}
991 }
992 
993 static struct targ_cmd_descr *
994 targgetdescr(struct targ_softc *softc)
995 {
996 	struct targ_cmd_descr *descr;
997 
998 	MALLOC(descr, struct targ_cmd_descr *, sizeof(*descr),
999 		M_TARG, M_INTWAIT);
1000 	descr->mapinfo.num_bufs_used = 0;
1001 	return (descr);
1002 }
1003 
1004 static void
1005 targinit(void)
1006 {
1007 	cdevsw_add(&targ_cdevsw, 0, 0);
1008 }
1009 
1010 static void
1011 targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
1012 {
1013 	/* All events are handled in usermode by INOTs */
1014 	panic("targasync() called, should be an INOT instead");
1015 }
1016 
1017 /* Cancel all pending requests and CCBs awaiting work. */
1018 static void
1019 abort_all_pending(struct targ_softc *softc)
1020 {
1021 	struct targ_cmd_descr   *descr;
1022 	struct ccb_abort	 cab;
1023 	struct ccb_hdr		*ccb_h;
1024 
1025 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
1026 
1027 	/* First abort the descriptors awaiting resources */
1028 	while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
1029 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1030 			  ("Aborting descr from workq %p\n", descr));
1031 		TAILQ_REMOVE(&softc->work_queue, descr, tqe);
1032 		TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
1033 	}
1034 
1035 	/*
1036 	 * Then abort all pending CCBs.
1037 	 * targdone() will return the aborted CCB via user_ccb_queue
1038 	 */
1039 	xpt_setup_ccb(&cab.ccb_h, softc->path, /*priority*/0);
1040 	cab.ccb_h.func_code = XPT_ABORT;
1041 	cab.ccb_h.status = CAM_REQ_CMP_ERR;
1042 	TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue, periph_links.tqe) {
1043 		CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1044 			  ("Aborting pending CCB %p\n", ccb_h));
1045 		cab.abort_ccb = (union ccb *)ccb_h;
1046 		xpt_action((union ccb *)&cab);
1047 		if (cab.ccb_h.status != CAM_REQ_CMP) {
1048 			xpt_print_path(cab.ccb_h.path);
1049 			printf("Unable to abort CCB, status %#x\n",
1050 			       cab.ccb_h.status);
1051 		}
1052 	}
1053 
1054 	/* If we aborted at least one pending CCB ok, wait for it. */
1055 	if (cab.ccb_h.status == CAM_REQ_CMP) {
1056 		tsleep(&softc->pending_ccb_queue, PCATCH, "tgabrt", 0);
1057 	}
1058 
1059 	/* If we aborted anything from the work queue, wakeup user. */
1060 	if (!TAILQ_EMPTY(&softc->user_ccb_queue)
1061 	 || !TAILQ_EMPTY(&softc->abort_queue))
1062 		notify_user(softc);
1063 }
1064 
1065 /* Notify the user that data is ready */
1066 static void
1067 notify_user(struct targ_softc *softc)
1068 {
1069 	/*
1070 	 * Notify users sleeping via poll(), kqueue(), and
1071 	 * blocking read().
1072 	 */
1073 	selwakeup(&softc->read_select);
1074 	KNOTE(&softc->read_select.si_note, 0);
1075 	wakeup(&softc->user_ccb_queue);
1076 }
1077 
1078 /* Convert CAM status to errno values */
1079 static int
1080 targcamstatus(cam_status status)
1081 {
1082 	switch (status & CAM_STATUS_MASK) {
1083 	case CAM_REQ_CMP:	/* CCB request completed without error */
1084 		return (0);
1085 	case CAM_REQ_INPROG:	/* CCB request is in progress */
1086 		return (EINPROGRESS);
1087 	case CAM_REQ_CMP_ERR:	/* CCB request completed with an error */
1088 		return (EIO);
1089 	case CAM_PROVIDE_FAIL:	/* Unable to provide requested capability */
1090 		return (ENOTTY);
1091 	case CAM_FUNC_NOTAVAIL:	/* The requested function is not available */
1092 		return (ENOTSUP);
1093 	case CAM_LUN_ALRDY_ENA:	/* LUN is already enabled for target mode */
1094 		return (EADDRINUSE);
1095 	case CAM_PATH_INVALID:	/* Supplied Path ID is invalid */
1096 	case CAM_DEV_NOT_THERE:	/* SCSI Device Not Installed/there */
1097 		return (ENOENT);
1098 	case CAM_REQ_ABORTED:	/* CCB request aborted by the host */
1099 		return (ECANCELED);
1100 	case CAM_CMD_TIMEOUT:	/* Command timeout */
1101 		return (ETIMEDOUT);
1102 	case CAM_REQUEUE_REQ:	/* Requeue to preserve transaction ordering */
1103 		return (EAGAIN);
1104 	case CAM_REQ_INVALID:	/* CCB request was invalid */
1105 		return (EINVAL);
1106 	case CAM_RESRC_UNAVAIL:	/* Resource Unavailable */
1107 		return (ENOMEM);
1108 	case CAM_BUSY:		/* CAM subsytem is busy */
1109 	case CAM_UA_ABORT:	/* Unable to abort CCB request */
1110 		return (EBUSY);
1111 	default:
1112 		return (ENXIO);
1113 	}
1114 }
1115 
1116 static size_t
1117 targccblen(xpt_opcode func_code)
1118 {
1119 	int len;
1120 
1121 	/* Codes we expect to see as a target */
1122 	switch (func_code) {
1123 	case XPT_CONT_TARGET_IO:
1124 	case XPT_SCSI_IO:
1125 		len = sizeof(struct ccb_scsiio);
1126 		break;
1127 	case XPT_ACCEPT_TARGET_IO:
1128 		len = sizeof(struct ccb_accept_tio);
1129 		break;
1130 	case XPT_IMMED_NOTIFY:
1131 		len = sizeof(struct ccb_immed_notify);
1132 		break;
1133 	case XPT_REL_SIMQ:
1134 		len = sizeof(struct ccb_relsim);
1135 		break;
1136 	case XPT_PATH_INQ:
1137 		len = sizeof(struct ccb_pathinq);
1138 		break;
1139 	case XPT_DEBUG:
1140 		len = sizeof(struct ccb_debug);
1141 		break;
1142 	case XPT_ABORT:
1143 		len = sizeof(struct ccb_abort);
1144 		break;
1145 	case XPT_EN_LUN:
1146 		len = sizeof(struct ccb_en_lun);
1147 		break;
1148 	default:
1149 		len = sizeof(union ccb);
1150 		break;
1151 	}
1152 
1153 	return (len);
1154 }
1155