scsi_pass.c revision 246713
116Salm/*-
2 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
3 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer,
11 *    without modification, immediately at the beginning of the file.
12 * 2. The name of the author may not be used to endorse or promote products
13 *    derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_pass.c 246713 2013-02-12 16:57:20Z kib $");
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/types.h>
35#include <sys/bio.h>
36#include <sys/malloc.h>
37#include <sys/fcntl.h>
38#include <sys/conf.h>
39#include <sys/errno.h>
40#include <sys/devicestat.h>
41#include <sys/proc.h>
42#include <sys/taskqueue.h>
43
44#include <cam/cam.h>
45#include <cam/cam_ccb.h>
46#include <cam/cam_periph.h>
47#include <cam/cam_queue.h>
48#include <cam/cam_xpt_periph.h>
49#include <cam/cam_debug.h>
50#include <cam/cam_sim.h>
51
52#include <cam/scsi/scsi_all.h>
53#include <cam/scsi/scsi_pass.h>
54
55typedef enum {
56	PASS_FLAG_OPEN			= 0x01,
57	PASS_FLAG_LOCKED		= 0x02,
58	PASS_FLAG_INVALID		= 0x04,
59	PASS_FLAG_INITIAL_PHYSPATH	= 0x08
60} pass_flags;
61
62typedef enum {
63	PASS_STATE_NORMAL
64} pass_state;
65
66typedef enum {
67	PASS_CCB_BUFFER_IO,
68	PASS_CCB_WAITING
69} pass_ccb_types;
70
71#define ccb_type	ppriv_field0
72#define ccb_bp		ppriv_ptr1
73
74struct pass_softc {
75	pass_state	 state;
76	pass_flags	 flags;
77	u_int8_t	 pd_type;
78	union ccb	 saved_ccb;
79	int		 open_count;
80	struct devstat	*device_stats;
81	struct cdev	*dev;
82	struct cdev	*alias_dev;
83	struct task	 add_physpath_task;
84};
85
86
87static	d_open_t	passopen;
88static	d_close_t	passclose;
89static	d_ioctl_t	passioctl;
90
91static	periph_init_t	passinit;
92static	periph_ctor_t	passregister;
93static	periph_oninv_t	passoninvalidate;
94static	periph_dtor_t	passcleanup;
95static	periph_start_t	passstart;
96static void		pass_add_physpath(void *context, int pending);
97static	void		passasync(void *callback_arg, u_int32_t code,
98				  struct cam_path *path, void *arg);
99static	void		passdone(struct cam_periph *periph,
100				 union ccb *done_ccb);
101static	int		passerror(union ccb *ccb, u_int32_t cam_flags,
102				  u_int32_t sense_flags);
103static 	int		passsendccb(struct cam_periph *periph, union ccb *ccb,
104				    union ccb *inccb);
105
106static struct periph_driver passdriver =
107{
108	passinit, "pass",
109	TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0
110};
111
112PERIPHDRIVER_DECLARE(pass, passdriver);
113
114static struct cdevsw pass_cdevsw = {
115	.d_version =	D_VERSION,
116	.d_flags =	D_TRACKCLOSE,
117	.d_open =	passopen,
118	.d_close =	passclose,
119	.d_ioctl =	passioctl,
120	.d_name =	"pass",
121};
122
123static void
124passinit(void)
125{
126	cam_status status;
127
128	/*
129	 * Install a global async callback.  This callback will
130	 * receive async callbacks like "new device found".
131	 */
132	status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL);
133
134	if (status != CAM_REQ_CMP) {
135		printf("pass: Failed to attach master async callback "
136		       "due to status 0x%x!\n", status);
137	}
138
139}
140
141static void
142passdevgonecb(void *arg)
143{
144	struct cam_sim    *sim;
145	struct cam_periph *periph;
146	struct pass_softc *softc;
147	int i;
148
149	periph = (struct cam_periph *)arg;
150	sim = periph->sim;
151	softc = (struct pass_softc *)periph->softc;
152
153	KASSERT(softc->open_count >= 0, ("Negative open count %d",
154		softc->open_count));
155
156	mtx_lock(sim->mtx);
157
158	/*
159	 * When we get this callback, we will get no more close calls from
160	 * devfs.  So if we have any dangling opens, we need to release the
161	 * reference held for that particular context.
162	 */
163	for (i = 0; i < softc->open_count; i++)
164		cam_periph_release_locked(periph);
165
166	softc->open_count = 0;
167
168	/*
169	 * Release the reference held for the device node, it is gone now.
170	 */
171	cam_periph_release_locked(periph);
172
173	/*
174	 * We reference the SIM lock directly here, instead of using
175	 * cam_periph_unlock().  The reason is that the final call to
176	 * cam_periph_release_locked() above could result in the periph
177	 * getting freed.  If that is the case, dereferencing the periph
178	 * with a cam_periph_unlock() call would cause a page fault.
179	 */
180	mtx_unlock(sim->mtx);
181}
182
183static void
184passoninvalidate(struct cam_periph *periph)
185{
186	struct pass_softc *softc;
187
188	softc = (struct pass_softc *)periph->softc;
189
190	/*
191	 * De-register any async callbacks.
192	 */
193	xpt_register_async(0, passasync, periph, periph->path);
194
195	softc->flags |= PASS_FLAG_INVALID;
196
197	/*
198	 * Tell devfs this device has gone away, and ask for a callback
199	 * when it has cleaned up its state.
200	 */
201	destroy_dev_sched_cb(softc->dev, passdevgonecb, periph);
202
203	/*
204	 * XXX Return all queued I/O with ENXIO.
205	 * XXX Handle any transactions queued to the card
206	 *     with XPT_ABORT_CCB.
207	 */
208
209	if (bootverbose) {
210		xpt_print(periph->path, "lost device\n");
211	}
212
213}
214
215static void
216passcleanup(struct cam_periph *periph)
217{
218	struct pass_softc *softc;
219
220	softc = (struct pass_softc *)periph->softc;
221
222	if (bootverbose)
223		xpt_print(periph->path, "removing device entry\n");
224	devstat_remove_entry(softc->device_stats);
225
226	cam_periph_unlock(periph);
227	taskqueue_drain(taskqueue_thread, &softc->add_physpath_task);
228
229	cam_periph_lock(periph);
230
231	free(softc, M_DEVBUF);
232}
233
234static void
235pass_add_physpath(void *context, int pending)
236{
237	struct cam_periph *periph;
238	struct pass_softc *softc;
239	char *physpath;
240
241	/*
242	 * If we have one, create a devfs alias for our
243	 * physical path.
244	 */
245	periph = context;
246	softc = periph->softc;
247	physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK);
248	cam_periph_lock(periph);
249	if (periph->flags & CAM_PERIPH_INVALID) {
250		cam_periph_unlock(periph);
251		goto out;
252	}
253	if (xpt_getattr(physpath, MAXPATHLEN,
254			"GEOM::physpath", periph->path) == 0
255	 && strlen(physpath) != 0) {
256
257		cam_periph_unlock(periph);
258		make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev,
259					softc->dev, softc->alias_dev, physpath);
260		cam_periph_lock(periph);
261	}
262
263	/*
264	 * Now that we've made our alias, we no longer have to have a
265	 * reference to the device.
266	 */
267	if ((softc->flags & PASS_FLAG_INITIAL_PHYSPATH) == 0) {
268		softc->flags |= PASS_FLAG_INITIAL_PHYSPATH;
269		cam_periph_unlock(periph);
270		dev_rel(softc->dev);
271	}
272	else
273		cam_periph_unlock(periph);
274
275out:
276	free(physpath, M_DEVBUF);
277}
278
279static void
280passasync(void *callback_arg, u_int32_t code,
281	  struct cam_path *path, void *arg)
282{
283	struct cam_periph *periph;
284
285	periph = (struct cam_periph *)callback_arg;
286
287	switch (code) {
288	case AC_FOUND_DEVICE:
289	{
290		struct ccb_getdev *cgd;
291		cam_status status;
292
293		cgd = (struct ccb_getdev *)arg;
294		if (cgd == NULL)
295			break;
296
297		/*
298		 * Allocate a peripheral instance for
299		 * this device and start the probe
300		 * process.
301		 */
302		status = cam_periph_alloc(passregister, passoninvalidate,
303					  passcleanup, passstart, "pass",
304					  CAM_PERIPH_BIO, cgd->ccb_h.path,
305					  passasync, AC_FOUND_DEVICE, cgd);
306
307		if (status != CAM_REQ_CMP
308		 && status != CAM_REQ_INPROG) {
309			const struct cam_status_entry *entry;
310
311			entry = cam_fetch_status_entry(status);
312
313			printf("passasync: Unable to attach new device "
314			       "due to status %#x: %s\n", status, entry ?
315			       entry->status_text : "Unknown");
316		}
317
318		break;
319	}
320	case AC_ADVINFO_CHANGED:
321	{
322		uintptr_t buftype;
323
324		buftype = (uintptr_t)arg;
325		if (buftype == CDAI_TYPE_PHYS_PATH) {
326			struct pass_softc *softc;
327
328			softc = (struct pass_softc *)periph->softc;
329			taskqueue_enqueue(taskqueue_thread,
330					  &softc->add_physpath_task);
331		}
332		break;
333	}
334	default:
335		cam_periph_async(periph, code, path, arg);
336		break;
337	}
338}
339
340static cam_status
341passregister(struct cam_periph *periph, void *arg)
342{
343	struct pass_softc *softc;
344	struct ccb_getdev *cgd;
345	struct ccb_pathinq cpi;
346	int    no_tags;
347
348	cgd = (struct ccb_getdev *)arg;
349	if (cgd == NULL) {
350		printf("%s: no getdev CCB, can't register device\n", __func__);
351		return(CAM_REQ_CMP_ERR);
352	}
353
354	softc = (struct pass_softc *)malloc(sizeof(*softc),
355					    M_DEVBUF, M_NOWAIT);
356
357	if (softc == NULL) {
358		printf("%s: Unable to probe new device. "
359		       "Unable to allocate softc\n", __func__);
360		return(CAM_REQ_CMP_ERR);
361	}
362
363	bzero(softc, sizeof(*softc));
364	softc->state = PASS_STATE_NORMAL;
365	if (cgd->protocol == PROTO_SCSI || cgd->protocol == PROTO_ATAPI)
366		softc->pd_type = SID_TYPE(&cgd->inq_data);
367	else if (cgd->protocol == PROTO_SATAPM)
368		softc->pd_type = T_ENCLOSURE;
369	else
370		softc->pd_type = T_DIRECT;
371
372	periph->softc = softc;
373
374	bzero(&cpi, sizeof(cpi));
375	xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
376	cpi.ccb_h.func_code = XPT_PATH_INQ;
377	xpt_action((union ccb *)&cpi);
378
379	/*
380	 * We pass in 0 for a blocksize, since we don't
381	 * know what the blocksize of this device is, if
382	 * it even has a blocksize.
383	 */
384	mtx_unlock(periph->sim->mtx);
385	no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
386	softc->device_stats = devstat_new_entry("pass",
387			  periph->unit_number, 0,
388			  DEVSTAT_NO_BLOCKSIZE
389			  | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
390			  softc->pd_type |
391			  XPORT_DEVSTAT_TYPE(cpi.transport) |
392			  DEVSTAT_TYPE_PASS,
393			  DEVSTAT_PRIORITY_PASS);
394
395	/*
396	 * Acquire a reference to the periph before we create the devfs
397	 * instance for it.  We'll release this reference once the devfs
398	 * instance has been freed.
399	 */
400	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
401		xpt_print(periph->path, "%s: lost periph during "
402			  "registration!\n", __func__);
403		cam_periph_lock(periph);
404		return (CAM_REQ_CMP_ERR);
405	}
406
407	/* Register the device */
408	softc->dev = make_dev(&pass_cdevsw, periph->unit_number,
409			      UID_ROOT, GID_OPERATOR, 0600, "%s%d",
410			      periph->periph_name, periph->unit_number);
411
412	/*
413	 * Now that we have made the devfs instance, hold a reference to it
414	 * until the task queue has run to setup the physical path alias.
415	 * That way devfs won't get rid of the device before we add our
416	 * alias.
417	 */
418	dev_ref(softc->dev);
419
420	mtx_lock(periph->sim->mtx);
421	softc->dev->si_drv1 = periph;
422
423	TASK_INIT(&softc->add_physpath_task, /*priority*/0,
424		  pass_add_physpath, periph);
425
426	/*
427	 * See if physical path information is already available.
428	 */
429	taskqueue_enqueue(taskqueue_thread, &softc->add_physpath_task);
430
431	/*
432	 * Add an async callback so that we get notified if
433	 * this device goes away or its physical path
434	 * (stored in the advanced info data of the EDT) has
435	 * changed.
436	 */
437	xpt_register_async(AC_LOST_DEVICE | AC_ADVINFO_CHANGED,
438			   passasync, periph, periph->path);
439
440	if (bootverbose)
441		xpt_announce_periph(periph, NULL);
442
443	return(CAM_REQ_CMP);
444}
445
446static int
447passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
448{
449	struct cam_periph *periph;
450	struct pass_softc *softc;
451	int error;
452
453	periph = (struct cam_periph *)dev->si_drv1;
454	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
455		return (ENXIO);
456
457	cam_periph_lock(periph);
458
459	softc = (struct pass_softc *)periph->softc;
460
461	if (softc->flags & PASS_FLAG_INVALID) {
462		cam_periph_release_locked(periph);
463		cam_periph_unlock(periph);
464		return(ENXIO);
465	}
466
467	/*
468	 * Don't allow access when we're running at a high securelevel.
469	 */
470	error = securelevel_gt(td->td_ucred, 1);
471	if (error) {
472		cam_periph_release_locked(periph);
473		cam_periph_unlock(periph);
474		return(error);
475	}
476
477	/*
478	 * Only allow read-write access.
479	 */
480	if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
481		cam_periph_release_locked(periph);
482		cam_periph_unlock(periph);
483		return(EPERM);
484	}
485
486	/*
487	 * We don't allow nonblocking access.
488	 */
489	if ((flags & O_NONBLOCK) != 0) {
490		xpt_print(periph->path, "can't do nonblocking access\n");
491		cam_periph_release_locked(periph);
492		cam_periph_unlock(periph);
493		return(EINVAL);
494	}
495
496	softc->open_count++;
497
498	cam_periph_unlock(periph);
499
500	return (error);
501}
502
503static int
504passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
505{
506	struct  cam_sim    *sim;
507	struct 	cam_periph *periph;
508	struct  pass_softc *softc;
509
510	periph = (struct cam_periph *)dev->si_drv1;
511	if (periph == NULL)
512		return (ENXIO);
513
514	sim = periph->sim;
515	softc = periph->softc;
516
517	mtx_lock(sim->mtx);
518
519	softc->open_count--;
520
521	cam_periph_release_locked(periph);
522
523	/*
524	 * We reference the SIM lock directly here, instead of using
525	 * cam_periph_unlock().  The reason is that the call to
526	 * cam_periph_release_locked() above could result in the periph
527	 * getting freed.  If that is the case, dereferencing the periph
528	 * with a cam_periph_unlock() call would cause a page fault.
529	 *
530	 * cam_periph_release() avoids this problem using the same method,
531	 * but we're manually acquiring and dropping the lock here to
532	 * protect the open count and avoid another lock acquisition and
533	 * release.
534	 */
535	mtx_unlock(sim->mtx);
536
537	return (0);
538}
539
540static void
541passstart(struct cam_periph *periph, union ccb *start_ccb)
542{
543	struct pass_softc *softc;
544
545	softc = (struct pass_softc *)periph->softc;
546
547	switch (softc->state) {
548	case PASS_STATE_NORMAL:
549		start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING;
550		SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
551				  periph_links.sle);
552		periph->immediate_priority = CAM_PRIORITY_NONE;
553		wakeup(&periph->ccb_list);
554		break;
555	}
556}
557
558static void
559passdone(struct cam_periph *periph, union ccb *done_ccb)
560{
561	struct pass_softc *softc;
562	struct ccb_scsiio *csio;
563
564	softc = (struct pass_softc *)periph->softc;
565	csio = &done_ccb->csio;
566	switch (csio->ccb_h.ccb_type) {
567	case PASS_CCB_WAITING:
568		/* Caller will release the CCB */
569		wakeup(&done_ccb->ccb_h.cbfcnp);
570		return;
571	}
572	xpt_release_ccb(done_ccb);
573}
574
575static int
576passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
577{
578	struct	cam_periph *periph;
579	struct	pass_softc *softc;
580	int	error;
581	uint32_t priority;
582
583	periph = (struct cam_periph *)dev->si_drv1;
584	if (periph == NULL)
585		return(ENXIO);
586
587	cam_periph_lock(periph);
588	softc = (struct pass_softc *)periph->softc;
589
590	error = 0;
591
592	switch (cmd) {
593
594	case CAMIOCOMMAND:
595	{
596		union ccb *inccb;
597		union ccb *ccb;
598		int ccb_malloced;
599
600		inccb = (union ccb *)addr;
601
602		/*
603		 * Some CCB types, like scan bus and scan lun can only go
604		 * through the transport layer device.
605		 */
606		if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
607			xpt_print(periph->path, "CCB function code %#x is "
608			    "restricted to the XPT device\n",
609			    inccb->ccb_h.func_code);
610			error = ENODEV;
611			break;
612		}
613
614		/* Compatibility for RL/priority-unaware code. */
615		priority = inccb->ccb_h.pinfo.priority;
616		if (priority < CAM_RL_TO_PRIORITY(CAM_RL_NORMAL))
617		    priority += CAM_RL_TO_PRIORITY(CAM_RL_NORMAL);
618
619		/*
620		 * Non-immediate CCBs need a CCB from the per-device pool
621		 * of CCBs, which is scheduled by the transport layer.
622		 * Immediate CCBs and user-supplied CCBs should just be
623		 * malloced.
624		 */
625		if ((inccb->ccb_h.func_code & XPT_FC_QUEUED)
626		 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) {
627			ccb = cam_periph_getccb(periph, priority);
628			ccb_malloced = 0;
629		} else {
630			ccb = xpt_alloc_ccb_nowait();
631
632			if (ccb != NULL)
633				xpt_setup_ccb(&ccb->ccb_h, periph->path,
634					      priority);
635			ccb_malloced = 1;
636		}
637
638		if (ccb == NULL) {
639			xpt_print(periph->path, "unable to allocate CCB\n");
640			error = ENOMEM;
641			break;
642		}
643
644		error = passsendccb(periph, ccb, inccb);
645
646		if (ccb_malloced)
647			xpt_free_ccb(ccb);
648		else
649			xpt_release_ccb(ccb);
650
651		break;
652	}
653	default:
654		error = cam_periph_ioctl(periph, cmd, addr, passerror);
655		break;
656	}
657
658	cam_periph_unlock(periph);
659	return(error);
660}
661
662/*
663 * Generally, "ccb" should be the CCB supplied by the kernel.  "inccb"
664 * should be the CCB that is copied in from the user.
665 */
666static int
667passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
668{
669	struct pass_softc *softc;
670	struct cam_periph_map_info mapinfo;
671	int error, need_unmap;
672
673	softc = (struct pass_softc *)periph->softc;
674
675	need_unmap = 0;
676
677	/*
678	 * There are some fields in the CCB header that need to be
679	 * preserved, the rest we get from the user.
680	 */
681	xpt_merge_ccb(ccb, inccb);
682
683	/*
684	 * There's no way for the user to have a completion
685	 * function, so we put our own completion function in here.
686	 */
687	ccb->ccb_h.cbfcnp = passdone;
688
689	/*
690	 * We only attempt to map the user memory into kernel space
691	 * if they haven't passed in a physical memory pointer,
692	 * and if there is actually an I/O operation to perform.
693	 * cam_periph_mapmem() supports SCSI, ATA, SMP, ADVINFO and device
694	 * match CCBs.  For the SCSI, ATA and ADVINFO CCBs, we only pass the
695	 * CCB in if there's actually data to map.  cam_periph_mapmem() will
696	 * do the right thing, even if there isn't data to map, but since CCBs
697	 * without data are a reasonably common occurance (e.g. test unit
698	 * ready), it will save a few cycles if we check for it here.
699	 *
700	 * XXX What happens if a sg list is supplied?  We don't filter that
701	 * out.
702	 */
703	if (((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
704	 && (((ccb->ccb_h.func_code == XPT_SCSI_IO ||
705	       ccb->ccb_h.func_code == XPT_ATA_IO)
706	    && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE))
707	  || (ccb->ccb_h.func_code == XPT_DEV_MATCH)
708	  || (ccb->ccb_h.func_code == XPT_SMP_IO)
709	  || ((ccb->ccb_h.func_code == XPT_DEV_ADVINFO)
710	   && (ccb->cdai.bufsiz > 0)))) {
711
712		bzero(&mapinfo, sizeof(mapinfo));
713
714		/*
715		 * cam_periph_mapmem calls into proc and vm functions that can
716		 * sleep as well as trigger I/O, so we can't hold the lock.
717		 * Dropping it here is reasonably safe.
718		 */
719		cam_periph_unlock(periph);
720		error = cam_periph_mapmem(ccb, &mapinfo);
721		cam_periph_lock(periph);
722
723		/*
724		 * cam_periph_mapmem returned an error, we can't continue.
725		 * Return the error to the user.
726		 */
727		if (error)
728			return(error);
729
730		/*
731		 * We successfully mapped the memory in, so we need to
732		 * unmap it when the transaction is done.
733		 */
734		need_unmap = 1;
735	}
736
737	/*
738	 * If the user wants us to perform any error recovery, then honor
739	 * that request.  Otherwise, it's up to the user to perform any
740	 * error recovery.
741	 */
742	cam_periph_runccb(ccb, passerror, /* cam_flags */ CAM_RETRY_SELTO,
743	    /* sense_flags */ ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
744	     SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
745	    softc->device_stats);
746
747	if (need_unmap != 0)
748		cam_periph_unmapmem(ccb, &mapinfo);
749
750	ccb->ccb_h.cbfcnp = NULL;
751	ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
752	bcopy(ccb, inccb, sizeof(union ccb));
753
754	return(0);
755}
756
757static int
758passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
759{
760	struct cam_periph *periph;
761	struct pass_softc *softc;
762
763	periph = xpt_path_periph(ccb->ccb_h.path);
764	softc = (struct pass_softc *)periph->softc;
765
766	return(cam_periph_error(ccb, cam_flags, sense_flags,
767				 &softc->saved_ccb));
768}
769