xref: /dragonfly/sys/bus/cam/scsi/scsi_target.c (revision 9c600e7d)
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.4 2003/07/21 05:50:24 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/cam.h>
43 #include <cam/cam_ccb.h>
44 #include <cam/cam_periph.h>
45 #include <cam/cam_xpt_periph.h>
46 #include <cam/scsi/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_WAITOK);
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), M_TARG,
1001 	       M_WAITOK);
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 }
1157