1139743Simp/*-
274840Sken * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
343819Sken * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
439213Sgibbs * All rights reserved.
539213Sgibbs *
639213Sgibbs * Redistribution and use in source and binary forms, with or without
739213Sgibbs * modification, are permitted provided that the following conditions
839213Sgibbs * are met:
939213Sgibbs * 1. Redistributions of source code must retain the above copyright
1039213Sgibbs *    notice, this list of conditions, and the following disclaimer,
1139213Sgibbs *    without modification, immediately at the beginning of the file.
1239213Sgibbs * 2. The name of the author may not be used to endorse or promote products
1339213Sgibbs *    derived from this software without specific prior written permission.
1439213Sgibbs *
1539213Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1639213Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1739213Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1839213Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
1939213Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2039213Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2139213Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2239213Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2339213Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2439213Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2539213Sgibbs * SUCH DAMAGE.
2639213Sgibbs */
2739213Sgibbs
28116162Sobrien#include <sys/cdefs.h>
29116162Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/cam/scsi/scsi_pass.c 294978 2016-01-28 09:25:15Z kib $");
30116162Sobrien
31292348Sken#include "opt_kdtrace.h"
32292348Sken
3339213Sgibbs#include <sys/param.h>
3439213Sgibbs#include <sys/systm.h>
3539213Sgibbs#include <sys/kernel.h>
36292348Sken#include <sys/conf.h>
3739213Sgibbs#include <sys/types.h>
3860041Sphk#include <sys/bio.h>
39292348Sken#include <sys/bus.h>
40292348Sken#include <sys/devicestat.h>
41292348Sken#include <sys/errno.h>
42292348Sken#include <sys/fcntl.h>
4339213Sgibbs#include <sys/malloc.h>
4483974Srwatson#include <sys/proc.h>
45292348Sken#include <sys/poll.h>
46292348Sken#include <sys/selinfo.h>
47292348Sken#include <sys/sdt.h>
48223089Sgibbs#include <sys/taskqueue.h>
49292348Sken#include <vm/uma.h>
50292348Sken#include <vm/vm.h>
51292348Sken#include <vm/vm_extern.h>
5239213Sgibbs
53292348Sken#include <machine/bus.h>
54292348Sken
5539213Sgibbs#include <cam/cam.h>
5639213Sgibbs#include <cam/cam_ccb.h>
5739213Sgibbs#include <cam/cam_periph.h>
5874840Sken#include <cam/cam_queue.h>
59292348Sken#include <cam/cam_xpt.h>
6039213Sgibbs#include <cam/cam_xpt_periph.h>
6139213Sgibbs#include <cam/cam_debug.h>
62251837Sscottl#include <cam/cam_compat.h>
63292348Sken#include <cam/cam_xpt_periph.h>
6439213Sgibbs
6539213Sgibbs#include <cam/scsi/scsi_all.h>
6639213Sgibbs#include <cam/scsi/scsi_pass.h>
6739213Sgibbs
6839213Sgibbstypedef enum {
6939213Sgibbs	PASS_FLAG_OPEN			= 0x01,
7039213Sgibbs	PASS_FLAG_LOCKED		= 0x02,
71237328Sken	PASS_FLAG_INVALID		= 0x04,
72292348Sken	PASS_FLAG_INITIAL_PHYSPATH	= 0x08,
73292348Sken	PASS_FLAG_ZONE_INPROG		= 0x10,
74292348Sken	PASS_FLAG_ZONE_VALID		= 0x20,
75292348Sken	PASS_FLAG_UNMAPPED_CAPABLE	= 0x40,
76292348Sken	PASS_FLAG_ABANDONED_REF_SET	= 0x80
7739213Sgibbs} pass_flags;
7839213Sgibbs
7939213Sgibbstypedef enum {
8039213Sgibbs	PASS_STATE_NORMAL
8139213Sgibbs} pass_state;
8239213Sgibbs
8339213Sgibbstypedef enum {
84292348Sken	PASS_CCB_BUFFER_IO,
85292348Sken	PASS_CCB_QUEUED_IO
8639213Sgibbs} pass_ccb_types;
8739213Sgibbs
8839213Sgibbs#define ccb_type	ppriv_field0
89292348Sken#define ccb_ioreq	ppriv_ptr1
9039213Sgibbs
91292348Sken/*
92292348Sken * The maximum number of memory segments we preallocate.
93292348Sken */
94292348Sken#define	PASS_MAX_SEGS	16
95292348Sken
96292348Skentypedef enum {
97292348Sken	PASS_IO_NONE		= 0x00,
98292348Sken	PASS_IO_USER_SEG_MALLOC	= 0x01,
99292348Sken	PASS_IO_KERN_SEG_MALLOC	= 0x02,
100292348Sken	PASS_IO_ABANDONED	= 0x04
101292348Sken} pass_io_flags;
102292348Sken
103292348Skenstruct pass_io_req {
104292348Sken	union ccb			 ccb;
105292348Sken	union ccb			*alloced_ccb;
106292348Sken	union ccb			*user_ccb_ptr;
107292348Sken	camq_entry			 user_periph_links;
108292348Sken	ccb_ppriv_area			 user_periph_priv;
109292348Sken	struct cam_periph_map_info	 mapinfo;
110292348Sken	pass_io_flags			 flags;
111292348Sken	ccb_flags			 data_flags;
112292348Sken	int				 num_user_segs;
113292348Sken	bus_dma_segment_t		 user_segs[PASS_MAX_SEGS];
114292348Sken	int				 num_kern_segs;
115292348Sken	bus_dma_segment_t		 kern_segs[PASS_MAX_SEGS];
116292348Sken	bus_dma_segment_t		*user_segptr;
117292348Sken	bus_dma_segment_t		*kern_segptr;
118292348Sken	int				 num_bufs;
119292348Sken	uint32_t			 dirs[CAM_PERIPH_MAXMAPS];
120292348Sken	uint32_t			 lengths[CAM_PERIPH_MAXMAPS];
121292348Sken	uint8_t				*user_bufs[CAM_PERIPH_MAXMAPS];
122292348Sken	uint8_t				*kern_bufs[CAM_PERIPH_MAXMAPS];
123292348Sken	struct bintime			 start_time;
124292348Sken	TAILQ_ENTRY(pass_io_req)	 links;
125292348Sken};
126292348Sken
12739213Sgibbsstruct pass_softc {
128292348Sken	pass_state		  state;
129292348Sken	pass_flags		  flags;
130292348Sken	u_int8_t		  pd_type;
131292348Sken	union ccb		  saved_ccb;
132292348Sken	int			  open_count;
133292348Sken	u_int		 	  maxio;
134292348Sken	struct devstat		 *device_stats;
135292348Sken	struct cdev		 *dev;
136292348Sken	struct cdev		 *alias_dev;
137292348Sken	struct task		  add_physpath_task;
138292348Sken	struct task		  shutdown_kqueue_task;
139292348Sken	struct selinfo		  read_select;
140292348Sken	TAILQ_HEAD(, pass_io_req) incoming_queue;
141292348Sken	TAILQ_HEAD(, pass_io_req) active_queue;
142292348Sken	TAILQ_HEAD(, pass_io_req) abandoned_queue;
143292348Sken	TAILQ_HEAD(, pass_io_req) done_queue;
144292348Sken	struct cam_periph	 *periph;
145292348Sken	char			  zone_name[12];
146292348Sken	char			  io_zone_name[12];
147292348Sken	uma_zone_t		  pass_zone;
148292348Sken	uma_zone_t		  pass_io_zone;
149292348Sken	size_t			  io_zone_size;
15039213Sgibbs};
15139213Sgibbs
15239213Sgibbsstatic	d_open_t	passopen;
15339213Sgibbsstatic	d_close_t	passclose;
15439213Sgibbsstatic	d_ioctl_t	passioctl;
155251837Sscottlstatic	d_ioctl_t	passdoioctl;
156292348Skenstatic	d_poll_t	passpoll;
157292348Skenstatic	d_kqfilter_t	passkqfilter;
158292348Skenstatic	void		passreadfiltdetach(struct knote *kn);
159292348Skenstatic	int		passreadfilt(struct knote *kn, long hint);
16039213Sgibbs
16139213Sgibbsstatic	periph_init_t	passinit;
16239213Sgibbsstatic	periph_ctor_t	passregister;
16340603Skenstatic	periph_oninv_t	passoninvalidate;
16439213Sgibbsstatic	periph_dtor_t	passcleanup;
165292348Skenstatic	periph_start_t	passstart;
166292348Skenstatic	void		pass_shutdown_kqueue(void *context, int pending);
167292348Skenstatic	void		pass_add_physpath(void *context, int pending);
16839213Sgibbsstatic	void		passasync(void *callback_arg, u_int32_t code,
16939213Sgibbs				  struct cam_path *path, void *arg);
170292348Skenstatic	void		passdone(struct cam_periph *periph,
171292348Sken				 union ccb *done_ccb);
172292348Skenstatic	int		passcreatezone(struct cam_periph *periph);
173292348Skenstatic	void		passiocleanup(struct pass_softc *softc,
174292348Sken				      struct pass_io_req *io_req);
175292348Skenstatic	int		passcopysglist(struct cam_periph *periph,
176292348Sken				       struct pass_io_req *io_req,
177292348Sken				       ccb_flags direction);
178292348Skenstatic	int		passmemsetup(struct cam_periph *periph,
179292348Sken				     struct pass_io_req *io_req);
180292348Skenstatic	int		passmemdone(struct cam_periph *periph,
181292348Sken				    struct pass_io_req *io_req);
18239213Sgibbsstatic	int		passerror(union ccb *ccb, u_int32_t cam_flags,
18339213Sgibbs				  u_int32_t sense_flags);
18439213Sgibbsstatic 	int		passsendccb(struct cam_periph *periph, union ccb *ccb,
18539213Sgibbs				    union ccb *inccb);
18639213Sgibbs
18739213Sgibbsstatic struct periph_driver passdriver =
18839213Sgibbs{
18939213Sgibbs	passinit, "pass",
19039213Sgibbs	TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0
19139213Sgibbs};
19239213Sgibbs
19372119SpeterPERIPHDRIVER_DECLARE(pass, passdriver);
19439213Sgibbs
19547625Sphkstatic struct cdevsw pass_cdevsw = {
196126080Sphk	.d_version =	D_VERSION,
197236138Sken	.d_flags =	D_TRACKCLOSE,
198111815Sphk	.d_open =	passopen,
199111815Sphk	.d_close =	passclose,
200111815Sphk	.d_ioctl =	passioctl,
201292348Sken	.d_poll = 	passpoll,
202292348Sken	.d_kqfilter = 	passkqfilter,
203111815Sphk	.d_name =	"pass",
20439213Sgibbs};
20539213Sgibbs
206292348Skenstatic struct filterops passread_filtops = {
207292348Sken	.f_isfd	=	1,
208292348Sken	.f_detach =	passreadfiltdetach,
209292348Sken	.f_event =	passreadfilt
210292348Sken};
211292348Sken
212292348Skenstatic MALLOC_DEFINE(M_SCSIPASS, "scsi_pass", "scsi passthrough buffers");
213292348Sken
21439213Sgibbsstatic void
21539213Sgibbspassinit(void)
21639213Sgibbs{
21739213Sgibbs	cam_status status;
21839213Sgibbs
21939213Sgibbs	/*
22039213Sgibbs	 * Install a global async callback.  This callback will
22139213Sgibbs	 * receive async callbacks like "new device found".
22239213Sgibbs	 */
223169605Sscottl	status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL);
22439213Sgibbs
22539213Sgibbs	if (status != CAM_REQ_CMP) {
22639213Sgibbs		printf("pass: Failed to attach master async callback "
22739213Sgibbs		       "due to status 0x%x!\n", status);
22839213Sgibbs	}
229237328Sken
23039213Sgibbs}
23139213Sgibbs
23239213Sgibbsstatic void
233292348Skenpassrejectios(struct cam_periph *periph)
234292348Sken{
235292348Sken	struct pass_io_req *io_req, *io_req2;
236292348Sken	struct pass_softc *softc;
237292348Sken
238292348Sken	softc = (struct pass_softc *)periph->softc;
239292348Sken
240292348Sken	/*
241292348Sken	 * The user can no longer get status for I/O on the done queue, so
242292348Sken	 * clean up all outstanding I/O on the done queue.
243292348Sken	 */
244292348Sken	TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
245292348Sken		TAILQ_REMOVE(&softc->done_queue, io_req, links);
246292348Sken		passiocleanup(softc, io_req);
247292348Sken		uma_zfree(softc->pass_zone, io_req);
248292348Sken	}
249292348Sken
250292348Sken	/*
251292348Sken	 * The underlying device is gone, so we can't issue these I/Os.
252292348Sken	 * The devfs node has been shut down, so we can't return status to
253292348Sken	 * the user.  Free any I/O left on the incoming queue.
254292348Sken	 */
255292348Sken	TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links, io_req2) {
256292348Sken		TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
257292348Sken		passiocleanup(softc, io_req);
258292348Sken		uma_zfree(softc->pass_zone, io_req);
259292348Sken	}
260292348Sken
261292348Sken	/*
262292348Sken	 * Normally we would put I/Os on the abandoned queue and acquire a
263292348Sken	 * reference when we saw the final close.  But, the device went
264292348Sken	 * away and devfs may have moved everything off to deadfs by the
265292348Sken	 * time the I/O done callback is called; as a result, we won't see
266292348Sken	 * any more closes.  So, if we have any active I/Os, we need to put
267292348Sken	 * them on the abandoned queue.  When the abandoned queue is empty,
268292348Sken	 * we'll release the remaining reference (see below) to the peripheral.
269292348Sken	 */
270292348Sken	TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links, io_req2) {
271292348Sken		TAILQ_REMOVE(&softc->active_queue, io_req, links);
272292348Sken		io_req->flags |= PASS_IO_ABANDONED;
273292348Sken		TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req, links);
274292348Sken	}
275292348Sken
276292348Sken	/*
277292348Sken	 * If we put any I/O on the abandoned queue, acquire a reference.
278292348Sken	 */
279292348Sken	if ((!TAILQ_EMPTY(&softc->abandoned_queue))
280292348Sken	 && ((softc->flags & PASS_FLAG_ABANDONED_REF_SET) == 0)) {
281292348Sken		cam_periph_doacquire(periph);
282292348Sken		softc->flags |= PASS_FLAG_ABANDONED_REF_SET;
283292348Sken	}
284292348Sken}
285292348Sken
286292348Skenstatic void
287237328Skenpassdevgonecb(void *arg)
288237328Sken{
289237328Sken	struct cam_periph *periph;
290260387Sscottl	struct mtx *mtx;
291244014Sken	struct pass_softc *softc;
292244014Sken	int i;
293237328Sken
294237328Sken	periph = (struct cam_periph *)arg;
295260387Sscottl	mtx = cam_periph_mtx(periph);
296260387Sscottl	mtx_lock(mtx);
297260387Sscottl
298244014Sken	softc = (struct pass_softc *)periph->softc;
299244014Sken	KASSERT(softc->open_count >= 0, ("Negative open count %d",
300244014Sken		softc->open_count));
301244014Sken
302244014Sken	/*
303244014Sken	 * When we get this callback, we will get no more close calls from
304244014Sken	 * devfs.  So if we have any dangling opens, we need to release the
305244014Sken	 * reference held for that particular context.
306244014Sken	 */
307244014Sken	for (i = 0; i < softc->open_count; i++)
308244014Sken		cam_periph_release_locked(periph);
309244014Sken
310244014Sken	softc->open_count = 0;
311244014Sken
312244014Sken	/*
313244014Sken	 * Release the reference held for the device node, it is gone now.
314292348Sken	 * Accordingly, inform all queued I/Os of their fate.
315244014Sken	 */
316244014Sken	cam_periph_release_locked(periph);
317292348Sken	passrejectios(periph);
318244014Sken
319244014Sken	/*
320292348Sken	 * We reference the SIM lock directly here, instead of using
321244014Sken	 * cam_periph_unlock().  The reason is that the final call to
322244014Sken	 * cam_periph_release_locked() above could result in the periph
323244014Sken	 * getting freed.  If that is the case, dereferencing the periph
324244014Sken	 * with a cam_periph_unlock() call would cause a page fault.
325244014Sken	 */
326260387Sscottl	mtx_unlock(mtx);
327292348Sken
328292348Sken	/*
329292348Sken	 * We have to remove our kqueue context from a thread because it
330292348Sken	 * may sleep.  It would be nice if we could get a callback from
331292348Sken	 * kqueue when it is done cleaning up resources.
332292348Sken	 */
333292348Sken	taskqueue_enqueue(taskqueue_thread, &softc->shutdown_kqueue_task);
334237328Sken}
335237328Sken
336237328Skenstatic void
33740603Skenpassoninvalidate(struct cam_periph *periph)
33840603Sken{
33940603Sken	struct pass_softc *softc;
34040603Sken
34140603Sken	softc = (struct pass_softc *)periph->softc;
34240603Sken
34340603Sken	/*
34440603Sken	 * De-register any async callbacks.
34540603Sken	 */
346169605Sscottl	xpt_register_async(0, passasync, periph, periph->path);
34740603Sken
34840603Sken	softc->flags |= PASS_FLAG_INVALID;
34940603Sken
35040603Sken	/*
351237328Sken	 * Tell devfs this device has gone away, and ask for a callback
352237328Sken	 * when it has cleaned up its state.
353237328Sken	 */
354237328Sken	destroy_dev_sched_cb(softc->dev, passdevgonecb, periph);
35540603Sken}
35640603Sken
35740603Skenstatic void
35839213Sgibbspasscleanup(struct cam_periph *periph)
35939213Sgibbs{
36040603Sken	struct pass_softc *softc;
36140603Sken
36240603Sken	softc = (struct pass_softc *)periph->softc;
36340603Sken
364292348Sken	cam_periph_assert(periph, MA_OWNED);
365292348Sken	KASSERT(TAILQ_EMPTY(&softc->active_queue),
366292348Sken		("%s called when there are commands on the active queue!\n",
367292348Sken		__func__));
368292348Sken	KASSERT(TAILQ_EMPTY(&softc->abandoned_queue),
369292348Sken		("%s called when there are commands on the abandoned queue!\n",
370292348Sken		__func__));
371292348Sken	KASSERT(TAILQ_EMPTY(&softc->incoming_queue),
372292348Sken		("%s called when there are commands on the incoming queue!\n",
373292348Sken		__func__));
374292348Sken	KASSERT(TAILQ_EMPTY(&softc->done_queue),
375292348Sken		("%s called when there are commands on the done queue!\n",
376292348Sken		__func__));
377292348Sken
378112006Sphk	devstat_remove_entry(softc->device_stats);
379223089Sgibbs
380187028Strasz	cam_periph_unlock(periph);
381292348Sken
382292348Sken	/*
383292348Sken	 * We call taskqueue_drain() for the physpath task to make sure it
384292348Sken	 * is complete.  We drop the lock because this can potentially
385292348Sken	 * sleep.  XXX KDM that is bad.  Need a way to get a callback when
386292348Sken	 * a taskqueue is drained.
387292348Sken	 *
388292348Sken 	 * Note that we don't drain the kqueue shutdown task queue.  This
389292348Sken	 * is because we hold a reference on the periph for kqueue, and
390292348Sken	 * release that reference from the kqueue shutdown task queue.  So
391292348Sken	 * we cannot come into this routine unless we've released that
392292348Sken	 * reference.  Also, because that could be the last reference, we
393292348Sken	 * could be called from the cam_periph_release() call in
394292348Sken	 * pass_shutdown_kqueue().  In that case, the taskqueue_drain()
395292348Sken	 * would deadlock.  It would be preferable if we had a way to
396292348Sken	 * get a callback when a taskqueue is done.
397292348Sken	 */
398223089Sgibbs	taskqueue_drain(taskqueue_thread, &softc->add_physpath_task);
399223089Sgibbs
400187028Strasz	cam_periph_lock(periph);
401223089Sgibbs
40240603Sken	free(softc, M_DEVBUF);
40339213Sgibbs}
40439213Sgibbs
40539213Sgibbsstatic void
406292348Skenpass_shutdown_kqueue(void *context, int pending)
407292348Sken{
408292348Sken	struct cam_periph *periph;
409292348Sken	struct pass_softc *softc;
410292348Sken
411292348Sken	periph = context;
412292348Sken	softc = periph->softc;
413292348Sken
414292348Sken	knlist_clear(&softc->read_select.si_note, /*is_locked*/ 0);
415292348Sken	knlist_destroy(&softc->read_select.si_note);
416292348Sken
417292348Sken	/*
418292348Sken	 * Release the reference we held for kqueue.
419292348Sken	 */
420292348Sken	cam_periph_release(periph);
421292348Sken}
422292348Sken
423292348Skenstatic void
424223089Sgibbspass_add_physpath(void *context, int pending)
425223089Sgibbs{
426223089Sgibbs	struct cam_periph *periph;
427223089Sgibbs	struct pass_softc *softc;
428292348Sken	struct mtx *mtx;
429223089Sgibbs	char *physpath;
430223089Sgibbs
431223089Sgibbs	/*
432223089Sgibbs	 * If we have one, create a devfs alias for our
433223089Sgibbs	 * physical path.
434223089Sgibbs	 */
435223089Sgibbs	periph = context;
436223089Sgibbs	softc = periph->softc;
437241485Smav	physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK);
438292348Sken	mtx = cam_periph_mtx(periph);
439292348Sken	mtx_lock(mtx);
440292348Sken
441292348Sken	if (periph->flags & CAM_PERIPH_INVALID)
442241485Smav		goto out;
443292348Sken
444223089Sgibbs	if (xpt_getattr(physpath, MAXPATHLEN,
445223089Sgibbs			"GEOM::physpath", periph->path) == 0
446223089Sgibbs	 && strlen(physpath) != 0) {
447223089Sgibbs
448292348Sken		mtx_unlock(mtx);
449223089Sgibbs		make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev,
450223089Sgibbs					softc->dev, softc->alias_dev, physpath);
451292348Sken		mtx_lock(mtx);
452223089Sgibbs	}
453237328Sken
454292348Skenout:
455237328Sken	/*
456237328Sken	 * Now that we've made our alias, we no longer have to have a
457237328Sken	 * reference to the device.
458237328Sken	 */
459292348Sken	if ((softc->flags & PASS_FLAG_INITIAL_PHYSPATH) == 0)
460237328Sken		softc->flags |= PASS_FLAG_INITIAL_PHYSPATH;
461241485Smav
462292348Sken	/*
463292348Sken	 * We always acquire a reference to the periph before queueing this
464292348Sken	 * task queue function, so it won't go away before we run.
465292348Sken	 */
466292348Sken	while (pending-- > 0)
467292348Sken		cam_periph_release_locked(periph);
468292348Sken	mtx_unlock(mtx);
469292348Sken
470241485Smav	free(physpath, M_DEVBUF);
471223089Sgibbs}
472223089Sgibbs
473223089Sgibbsstatic void
47439213Sgibbspassasync(void *callback_arg, u_int32_t code,
47539213Sgibbs	  struct cam_path *path, void *arg)
47639213Sgibbs{
47739213Sgibbs	struct cam_periph *periph;
47839213Sgibbs
47939213Sgibbs	periph = (struct cam_periph *)callback_arg;
48039213Sgibbs
48139213Sgibbs	switch (code) {
48239213Sgibbs	case AC_FOUND_DEVICE:
48339213Sgibbs	{
48439213Sgibbs		struct ccb_getdev *cgd;
48539213Sgibbs		cam_status status;
48639213Sgibbs
48739213Sgibbs		cgd = (struct ccb_getdev *)arg;
48879177Smjacob		if (cgd == NULL)
48979177Smjacob			break;
49039213Sgibbs
49139213Sgibbs		/*
49239213Sgibbs		 * Allocate a peripheral instance for
49339213Sgibbs		 * this device and start the probe
49439213Sgibbs		 * process.
49539213Sgibbs		 */
49640603Sken		status = cam_periph_alloc(passregister, passoninvalidate,
497292348Sken					  passcleanup, passstart, "pass",
498260387Sscottl					  CAM_PERIPH_BIO, path,
49940603Sken					  passasync, AC_FOUND_DEVICE, cgd);
50039213Sgibbs
50139213Sgibbs		if (status != CAM_REQ_CMP
50274840Sken		 && status != CAM_REQ_INPROG) {
50374840Sken			const struct cam_status_entry *entry;
50474840Sken
50574840Sken			entry = cam_fetch_status_entry(status);
50674840Sken
50739213Sgibbs			printf("passasync: Unable to attach new device "
50874840Sken			       "due to status %#x: %s\n", status, entry ?
50974840Sken			       entry->status_text : "Unknown");
51074840Sken		}
51139213Sgibbs
51239213Sgibbs		break;
51339213Sgibbs	}
514223089Sgibbs	case AC_ADVINFO_CHANGED:
515223089Sgibbs	{
516223089Sgibbs		uintptr_t buftype;
517223089Sgibbs
518223089Sgibbs		buftype = (uintptr_t)arg;
519223089Sgibbs		if (buftype == CDAI_TYPE_PHYS_PATH) {
520223089Sgibbs			struct pass_softc *softc;
521292348Sken			cam_status status;
522223089Sgibbs
523223089Sgibbs			softc = (struct pass_softc *)periph->softc;
524292348Sken			/*
525292348Sken			 * Acquire a reference to the periph before we
526292348Sken			 * start the taskqueue, so that we don't run into
527292348Sken			 * a situation where the periph goes away before
528292348Sken			 * the task queue has a chance to run.
529292348Sken			 */
530292348Sken			status = cam_periph_acquire(periph);
531292348Sken			if (status != CAM_REQ_CMP)
532292348Sken				break;
533292348Sken
534223089Sgibbs			taskqueue_enqueue(taskqueue_thread,
535223089Sgibbs					  &softc->add_physpath_task);
536223089Sgibbs		}
537223089Sgibbs		break;
538223089Sgibbs	}
53939213Sgibbs	default:
54047413Sgibbs		cam_periph_async(periph, code, path, arg);
54139213Sgibbs		break;
54239213Sgibbs	}
54339213Sgibbs}
54439213Sgibbs
54539213Sgibbsstatic cam_status
54639213Sgibbspassregister(struct cam_periph *periph, void *arg)
54739213Sgibbs{
54839213Sgibbs	struct pass_softc *softc;
54939213Sgibbs	struct ccb_getdev *cgd;
550220644Smav	struct ccb_pathinq cpi;
551294978Skib	struct make_dev_args args;
552294978Skib	int error, no_tags;
55339213Sgibbs
55439213Sgibbs	cgd = (struct ccb_getdev *)arg;
55539213Sgibbs	if (cgd == NULL) {
556237328Sken		printf("%s: no getdev CCB, can't register device\n", __func__);
55739213Sgibbs		return(CAM_REQ_CMP_ERR);
55839213Sgibbs	}
55939213Sgibbs
56039213Sgibbs	softc = (struct pass_softc *)malloc(sizeof(*softc),
56139213Sgibbs					    M_DEVBUF, M_NOWAIT);
56239213Sgibbs
56339213Sgibbs	if (softc == NULL) {
564237328Sken		printf("%s: Unable to probe new device. "
565237328Sken		       "Unable to allocate softc\n", __func__);
56639213Sgibbs		return(CAM_REQ_CMP_ERR);
56739213Sgibbs	}
56839213Sgibbs
56939213Sgibbs	bzero(softc, sizeof(*softc));
57039213Sgibbs	softc->state = PASS_STATE_NORMAL;
571220644Smav	if (cgd->protocol == PROTO_SCSI || cgd->protocol == PROTO_ATAPI)
572220644Smav		softc->pd_type = SID_TYPE(&cgd->inq_data);
573220644Smav	else if (cgd->protocol == PROTO_SATAPM)
574220644Smav		softc->pd_type = T_ENCLOSURE;
575220644Smav	else
576220644Smav		softc->pd_type = T_DIRECT;
57739213Sgibbs
57839213Sgibbs	periph->softc = softc;
579292348Sken	softc->periph = periph;
580292348Sken	TAILQ_INIT(&softc->incoming_queue);
581292348Sken	TAILQ_INIT(&softc->active_queue);
582292348Sken	TAILQ_INIT(&softc->abandoned_queue);
583292348Sken	TAILQ_INIT(&softc->done_queue);
584292348Sken	snprintf(softc->zone_name, sizeof(softc->zone_name), "%s%d",
585292348Sken		 periph->periph_name, periph->unit_number);
586292348Sken	snprintf(softc->io_zone_name, sizeof(softc->io_zone_name), "%s%dIO",
587292348Sken		 periph->periph_name, periph->unit_number);
588292348Sken	softc->io_zone_size = MAXPHYS;
589292348Sken	knlist_init_mtx(&softc->read_select.si_note, cam_periph_mtx(periph));
59039213Sgibbs
591220644Smav	bzero(&cpi, sizeof(cpi));
592220644Smav	xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
593220644Smav	cpi.ccb_h.func_code = XPT_PATH_INQ;
594220644Smav	xpt_action((union ccb *)&cpi);
595220644Smav
596288817Smav	if (cpi.maxio == 0)
597288817Smav		softc->maxio = DFLTPHYS;	/* traditional default */
598288817Smav	else if (cpi.maxio > MAXPHYS)
599288817Smav		softc->maxio = MAXPHYS;		/* for safety */
600288817Smav	else
601288817Smav		softc->maxio = cpi.maxio;	/* real value */
602288817Smav
603292348Sken	if (cpi.hba_misc & PIM_UNMAPPED)
604292348Sken		softc->flags |= PASS_FLAG_UNMAPPED_CAPABLE;
605292348Sken
60639213Sgibbs	/*
60739213Sgibbs	 * We pass in 0 for a blocksize, since we don't
60839213Sgibbs	 * know what the blocksize of this device is, if
60939213Sgibbs	 * it even has a blocksize.
61039213Sgibbs	 */
611249106Smav	cam_periph_unlock(periph);
61274840Sken	no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
613140608Smjacob	softc->device_stats = devstat_new_entry("pass",
614183381Sed			  periph->unit_number, 0,
61574840Sken			  DEVSTAT_NO_BLOCKSIZE
61674840Sken			  | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
61756148Smjacob			  softc->pd_type |
618220644Smav			  XPORT_DEVSTAT_TYPE(cpi.transport) |
61943819Sken			  DEVSTAT_TYPE_PASS,
62043819Sken			  DEVSTAT_PRIORITY_PASS);
62153257Sken
622237328Sken	/*
623292348Sken	 * Initialize the taskqueue handler for shutting down kqueue.
624292348Sken	 */
625292348Sken	TASK_INIT(&softc->shutdown_kqueue_task, /*priority*/ 0,
626292348Sken		  pass_shutdown_kqueue, periph);
627292348Sken
628292348Sken	/*
629292348Sken	 * Acquire a reference to the periph that we can release once we've
630292348Sken	 * cleaned up the kqueue.
631292348Sken	 */
632292348Sken	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
633292348Sken		xpt_print(periph->path, "%s: lost periph during "
634292348Sken			  "registration!\n", __func__);
635292348Sken		cam_periph_lock(periph);
636292348Sken		return (CAM_REQ_CMP_ERR);
637292348Sken	}
638292348Sken
639292348Sken	/*
640237328Sken	 * Acquire a reference to the periph before we create the devfs
641237328Sken	 * instance for it.  We'll release this reference once the devfs
642237328Sken	 * instance has been freed.
643237328Sken	 */
644237328Sken	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
645237328Sken		xpt_print(periph->path, "%s: lost periph during "
646237328Sken			  "registration!\n", __func__);
647244014Sken		cam_periph_lock(periph);
648237328Sken		return (CAM_REQ_CMP_ERR);
649237328Sken	}
650237328Sken
65153257Sken	/* Register the device */
652294978Skib	make_dev_args_init(&args);
653294978Skib	args.mda_devsw = &pass_cdevsw;
654294978Skib	args.mda_unit = periph->unit_number;
655294978Skib	args.mda_uid = UID_ROOT;
656294978Skib	args.mda_gid = GID_OPERATOR;
657294978Skib	args.mda_mode = 0600;
658294978Skib	args.mda_si_drv1 = periph;
659294978Skib	error = make_dev_s(&args, &softc->dev, "%s%d", periph->periph_name,
660294978Skib	    periph->unit_number);
661294978Skib	if (error != 0) {
662294978Skib		cam_periph_lock(periph);
663294978Skib		cam_periph_release_locked(periph);
664294978Skib		return (CAM_REQ_CMP_ERR);
665294978Skib	}
666237328Sken
667237328Sken	/*
668292348Sken	 * Hold a reference to the periph before we create the physical
669292348Sken	 * path alias so it can't go away.
670237328Sken	 */
671292348Sken	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
672292348Sken		xpt_print(periph->path, "%s: lost periph during "
673292348Sken			  "registration!\n", __func__);
674292348Sken		cam_periph_lock(periph);
675292348Sken		return (CAM_REQ_CMP_ERR);
676292348Sken	}
677237328Sken
678249106Smav	cam_periph_lock(periph);
67953257Sken
680223089Sgibbs	TASK_INIT(&softc->add_physpath_task, /*priority*/0,
681223089Sgibbs		  pass_add_physpath, periph);
682223089Sgibbs
68339213Sgibbs	/*
684223089Sgibbs	 * See if physical path information is already available.
68539213Sgibbs	 */
686223089Sgibbs	taskqueue_enqueue(taskqueue_thread, &softc->add_physpath_task);
68739213Sgibbs
688223089Sgibbs	/*
689223089Sgibbs	 * Add an async callback so that we get notified if
690223089Sgibbs	 * this device goes away or its physical path
691223089Sgibbs	 * (stored in the advanced info data of the EDT) has
692223089Sgibbs	 * changed.
693223089Sgibbs	 */
694223089Sgibbs	xpt_register_async(AC_LOST_DEVICE | AC_ADVINFO_CHANGED,
695223089Sgibbs			   passasync, periph, periph->path);
696223089Sgibbs
69739213Sgibbs	if (bootverbose)
69839213Sgibbs		xpt_announce_periph(periph, NULL);
69939213Sgibbs
70039213Sgibbs	return(CAM_REQ_CMP);
70139213Sgibbs}
70239213Sgibbs
70339213Sgibbsstatic int
704130585Sphkpassopen(struct cdev *dev, int flags, int fmt, struct thread *td)
70539213Sgibbs{
70639213Sgibbs	struct cam_periph *periph;
70739213Sgibbs	struct pass_softc *softc;
708101940Snjl	int error;
70939213Sgibbs
710101940Snjl	periph = (struct cam_periph *)dev->si_drv1;
711168752Sscottl	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
71239213Sgibbs		return (ENXIO);
71339213Sgibbs
714168752Sscottl	cam_periph_lock(periph);
715168752Sscottl
71639213Sgibbs	softc = (struct pass_softc *)periph->softc;
71739213Sgibbs
71840603Sken	if (softc->flags & PASS_FLAG_INVALID) {
719236138Sken		cam_periph_release_locked(periph);
720168752Sscottl		cam_periph_unlock(periph);
72139213Sgibbs		return(ENXIO);
72240603Sken	}
72339213Sgibbs
72439213Sgibbs	/*
72583917Srwatson	 * Don't allow access when we're running at a high securelevel.
72641297Sken	 */
72791406Sjhb	error = securelevel_gt(td->td_ucred, 1);
72883974Srwatson	if (error) {
729236138Sken		cam_periph_release_locked(periph);
730168752Sscottl		cam_periph_unlock(periph);
73183974Srwatson		return(error);
73241297Sken	}
73341297Sken
73441297Sken	/*
73539317Sken	 * Only allow read-write access.
73639317Sken	 */
73741297Sken	if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
738236138Sken		cam_periph_release_locked(periph);
739168752Sscottl		cam_periph_unlock(periph);
74039317Sken		return(EPERM);
74141297Sken	}
74239317Sken
74339317Sken	/*
74439213Sgibbs	 * We don't allow nonblocking access.
74539213Sgibbs	 */
74639213Sgibbs	if ((flags & O_NONBLOCK) != 0) {
747164906Smjacob		xpt_print(periph->path, "can't do nonblocking access\n");
748236138Sken		cam_periph_release_locked(periph);
749168752Sscottl		cam_periph_unlock(periph);
75041297Sken		return(EINVAL);
75139213Sgibbs	}
75239213Sgibbs
753244014Sken	softc->open_count++;
754244014Sken
755236138Sken	cam_periph_unlock(periph);
75639213Sgibbs
75739213Sgibbs	return (error);
75839213Sgibbs}
75939213Sgibbs
76039213Sgibbsstatic int
761130585Sphkpassclose(struct cdev *dev, int flag, int fmt, struct thread *td)
76239213Sgibbs{
76339213Sgibbs	struct 	cam_periph *periph;
764244014Sken	struct  pass_softc *softc;
765260387Sscottl	struct mtx *mtx;
76639213Sgibbs
767101940Snjl	periph = (struct cam_periph *)dev->si_drv1;
768260387Sscottl	mtx = cam_periph_mtx(periph);
769260387Sscottl	mtx_lock(mtx);
77039213Sgibbs
771244014Sken	softc = periph->softc;
772244014Sken	softc->open_count--;
773244014Sken
774292348Sken	if (softc->open_count == 0) {
775292348Sken		struct pass_io_req *io_req, *io_req2;
776292348Sken		int need_unlock;
777292348Sken
778292348Sken		need_unlock = 0;
779292348Sken
780292348Sken		TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
781292348Sken			TAILQ_REMOVE(&softc->done_queue, io_req, links);
782292348Sken			passiocleanup(softc, io_req);
783292348Sken			uma_zfree(softc->pass_zone, io_req);
784292348Sken		}
785292348Sken
786292348Sken		TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links,
787292348Sken				   io_req2) {
788292348Sken			TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
789292348Sken			passiocleanup(softc, io_req);
790292348Sken			uma_zfree(softc->pass_zone, io_req);
791292348Sken		}
792292348Sken
793292348Sken		/*
794292348Sken		 * If there are any active I/Os, we need to forcibly acquire a
795292348Sken		 * reference to the peripheral so that we don't go away
796292348Sken		 * before they complete.  We'll release the reference when
797292348Sken		 * the abandoned queue is empty.
798292348Sken		 */
799292348Sken		io_req = TAILQ_FIRST(&softc->active_queue);
800292348Sken		if ((io_req != NULL)
801292348Sken		 && (softc->flags & PASS_FLAG_ABANDONED_REF_SET) == 0) {
802292348Sken			cam_periph_doacquire(periph);
803292348Sken			softc->flags |= PASS_FLAG_ABANDONED_REF_SET;
804292348Sken		}
805292348Sken
806292348Sken		/*
807292348Sken		 * Since the I/O in the active queue is not under our
808292348Sken		 * control, just set a flag so that we can clean it up when
809292348Sken		 * it completes and put it on the abandoned queue.  This
810292348Sken		 * will prevent our sending spurious completions in the
811292348Sken		 * event that the device is opened again before these I/Os
812292348Sken		 * complete.
813292348Sken		 */
814292348Sken		TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links,
815292348Sken				   io_req2) {
816292348Sken			TAILQ_REMOVE(&softc->active_queue, io_req, links);
817292348Sken			io_req->flags |= PASS_IO_ABANDONED;
818292348Sken			TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req,
819292348Sken					  links);
820292348Sken		}
821292348Sken	}
822292348Sken
823244014Sken	cam_periph_release_locked(periph);
824244014Sken
825244014Sken	/*
826260387Sscottl	 * We reference the lock directly here, instead of using
827244014Sken	 * cam_periph_unlock().  The reason is that the call to
828244014Sken	 * cam_periph_release_locked() above could result in the periph
829244014Sken	 * getting freed.  If that is the case, dereferencing the periph
830244014Sken	 * with a cam_periph_unlock() call would cause a page fault.
831244014Sken	 *
832244014Sken	 * cam_periph_release() avoids this problem using the same method,
833244014Sken	 * but we're manually acquiring and dropping the lock here to
834244014Sken	 * protect the open count and avoid another lock acquisition and
835244014Sken	 * release.
836244014Sken	 */
837260387Sscottl	mtx_unlock(mtx);
838244014Sken
83939213Sgibbs	return (0);
84039213Sgibbs}
84139213Sgibbs
842292348Sken
843292348Skenstatic void
844292348Skenpassstart(struct cam_periph *periph, union ccb *start_ccb)
845292348Sken{
846292348Sken	struct pass_softc *softc;
847292348Sken
848292348Sken	softc = (struct pass_softc *)periph->softc;
849292348Sken
850292348Sken	switch (softc->state) {
851292348Sken	case PASS_STATE_NORMAL: {
852292348Sken		struct pass_io_req *io_req;
853292348Sken
854292348Sken		/*
855292348Sken		 * Check for any queued I/O requests that require an
856292348Sken		 * allocated slot.
857292348Sken		 */
858292348Sken		io_req = TAILQ_FIRST(&softc->incoming_queue);
859292348Sken		if (io_req == NULL) {
860292348Sken			xpt_release_ccb(start_ccb);
861292348Sken			break;
862292348Sken		}
863292348Sken		TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
864292348Sken		TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
865292348Sken		/*
866292348Sken		 * Merge the user's CCB into the allocated CCB.
867292348Sken		 */
868292348Sken		xpt_merge_ccb(start_ccb, &io_req->ccb);
869292348Sken		start_ccb->ccb_h.ccb_type = PASS_CCB_QUEUED_IO;
870292348Sken		start_ccb->ccb_h.ccb_ioreq = io_req;
871292348Sken		start_ccb->ccb_h.cbfcnp = passdone;
872292348Sken		io_req->alloced_ccb = start_ccb;
873292348Sken		binuptime(&io_req->start_time);
874292348Sken		devstat_start_transaction(softc->device_stats,
875292348Sken					  &io_req->start_time);
876292348Sken
877292348Sken		xpt_action(start_ccb);
878292348Sken
879292348Sken		/*
880292348Sken		 * If we have any more I/O waiting, schedule ourselves again.
881292348Sken		 */
882292348Sken		if (!TAILQ_EMPTY(&softc->incoming_queue))
883292348Sken			xpt_schedule(periph, CAM_PRIORITY_NORMAL);
884292348Sken		break;
885292348Sken	}
886292348Sken	default:
887292348Sken		break;
888292348Sken	}
889292348Sken}
890292348Sken
891292348Skenstatic void
892292348Skenpassdone(struct cam_periph *periph, union ccb *done_ccb)
893292348Sken{
894292348Sken	struct pass_softc *softc;
895292348Sken	struct ccb_scsiio *csio;
896292348Sken
897292348Sken	softc = (struct pass_softc *)periph->softc;
898292348Sken
899292348Sken	cam_periph_assert(periph, MA_OWNED);
900292348Sken
901292348Sken	csio = &done_ccb->csio;
902292348Sken	switch (csio->ccb_h.ccb_type) {
903292348Sken	case PASS_CCB_QUEUED_IO: {
904292348Sken		struct pass_io_req *io_req;
905292348Sken
906292348Sken		io_req = done_ccb->ccb_h.ccb_ioreq;
907292348Sken#if 0
908292348Sken		xpt_print(periph->path, "%s: called for user CCB %p\n",
909292348Sken			  __func__, io_req->user_ccb_ptr);
910292348Sken#endif
911292348Sken		if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
912292348Sken		 && (done_ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER)
913292348Sken		 && ((io_req->flags & PASS_IO_ABANDONED) == 0)) {
914292348Sken			int error;
915292348Sken
916292348Sken			error = passerror(done_ccb, CAM_RETRY_SELTO,
917292348Sken					  SF_RETRY_UA | SF_NO_PRINT);
918292348Sken
919292348Sken			if (error == ERESTART) {
920292348Sken				/*
921292348Sken				 * A retry was scheduled, so
922292348Sken 				 * just return.
923292348Sken				 */
924292348Sken				return;
925292348Sken			}
926292348Sken		}
927292348Sken
928292348Sken		/*
929292348Sken		 * Copy the allocated CCB contents back to the malloced CCB
930292348Sken		 * so we can give status back to the user when he requests it.
931292348Sken		 */
932292348Sken		bcopy(done_ccb, &io_req->ccb, sizeof(*done_ccb));
933292348Sken
934292348Sken		/*
935292348Sken		 * Log data/transaction completion with devstat(9).
936292348Sken		 */
937292348Sken		switch (done_ccb->ccb_h.func_code) {
938292348Sken		case XPT_SCSI_IO:
939292348Sken			devstat_end_transaction(softc->device_stats,
940292348Sken			    done_ccb->csio.dxfer_len - done_ccb->csio.resid,
941292348Sken			    done_ccb->csio.tag_action & 0x3,
942292348Sken			    ((done_ccb->ccb_h.flags & CAM_DIR_MASK) ==
943292348Sken			    CAM_DIR_NONE) ? DEVSTAT_NO_DATA :
944292348Sken			    (done_ccb->ccb_h.flags & CAM_DIR_OUT) ?
945292348Sken			    DEVSTAT_WRITE : DEVSTAT_READ, NULL,
946292348Sken			    &io_req->start_time);
947292348Sken			break;
948292348Sken		case XPT_ATA_IO:
949292348Sken			devstat_end_transaction(softc->device_stats,
950292348Sken			    done_ccb->ataio.dxfer_len - done_ccb->ataio.resid,
951292348Sken			    done_ccb->ataio.tag_action & 0x3,
952292348Sken			    ((done_ccb->ccb_h.flags & CAM_DIR_MASK) ==
953292348Sken			    CAM_DIR_NONE) ? DEVSTAT_NO_DATA :
954292348Sken			    (done_ccb->ccb_h.flags & CAM_DIR_OUT) ?
955292348Sken			    DEVSTAT_WRITE : DEVSTAT_READ, NULL,
956292348Sken			    &io_req->start_time);
957292348Sken			break;
958292348Sken		case XPT_SMP_IO:
959292348Sken			/*
960292348Sken			 * XXX KDM this isn't quite right, but there isn't
961292348Sken			 * currently an easy way to represent a bidirectional
962292348Sken			 * transfer in devstat.  The only way to do it
963292348Sken			 * and have the byte counts come out right would
964292348Sken			 * mean that we would have to record two
965292348Sken			 * transactions, one for the request and one for the
966292348Sken			 * response.  For now, so that we report something,
967292348Sken			 * just treat the entire thing as a read.
968292348Sken			 */
969292348Sken			devstat_end_transaction(softc->device_stats,
970292348Sken			    done_ccb->smpio.smp_request_len +
971292348Sken			    done_ccb->smpio.smp_response_len,
972292348Sken			    DEVSTAT_TAG_SIMPLE, DEVSTAT_READ, NULL,
973292348Sken			    &io_req->start_time);
974292348Sken			break;
975292348Sken		default:
976292348Sken			devstat_end_transaction(softc->device_stats, 0,
977292348Sken			    DEVSTAT_TAG_NONE, DEVSTAT_NO_DATA, NULL,
978292348Sken			    &io_req->start_time);
979292348Sken			break;
980292348Sken		}
981292348Sken
982292348Sken		/*
983292348Sken		 * In the normal case, take the completed I/O off of the
984292348Sken		 * active queue and put it on the done queue.  Notitfy the
985292348Sken		 * user that we have a completed I/O.
986292348Sken		 */
987292348Sken		if ((io_req->flags & PASS_IO_ABANDONED) == 0) {
988292348Sken			TAILQ_REMOVE(&softc->active_queue, io_req, links);
989292348Sken			TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
990292348Sken			selwakeuppri(&softc->read_select, PRIBIO);
991292348Sken			KNOTE_LOCKED(&softc->read_select.si_note, 0);
992292348Sken		} else {
993292348Sken			/*
994292348Sken			 * In the case of an abandoned I/O (final close
995292348Sken			 * without fetching the I/O), take it off of the
996292348Sken			 * abandoned queue and free it.
997292348Sken			 */
998292348Sken			TAILQ_REMOVE(&softc->abandoned_queue, io_req, links);
999292348Sken			passiocleanup(softc, io_req);
1000292348Sken			uma_zfree(softc->pass_zone, io_req);
1001292348Sken
1002292348Sken			/*
1003292348Sken			 * Release the done_ccb here, since we may wind up
1004292348Sken			 * freeing the peripheral when we decrement the
1005292348Sken			 * reference count below.
1006292348Sken			 */
1007292348Sken			xpt_release_ccb(done_ccb);
1008292348Sken
1009292348Sken			/*
1010292348Sken			 * If the abandoned queue is empty, we can release
1011292348Sken			 * our reference to the periph since we won't have
1012292348Sken			 * any more completions coming.
1013292348Sken			 */
1014292348Sken			if ((TAILQ_EMPTY(&softc->abandoned_queue))
1015292348Sken			 && (softc->flags & PASS_FLAG_ABANDONED_REF_SET)) {
1016292348Sken				softc->flags &= ~PASS_FLAG_ABANDONED_REF_SET;
1017292348Sken				cam_periph_release_locked(periph);
1018292348Sken			}
1019292348Sken
1020292348Sken			/*
1021292348Sken			 * We have already released the CCB, so we can
1022292348Sken			 * return.
1023292348Sken			 */
1024292348Sken			return;
1025292348Sken		}
1026292348Sken		break;
1027292348Sken	}
1028292348Sken	}
1029292348Sken	xpt_release_ccb(done_ccb);
1030292348Sken}
1031292348Sken
103239213Sgibbsstatic int
1033292348Skenpasscreatezone(struct cam_periph *periph)
1034292348Sken{
1035292348Sken	struct pass_softc *softc;
1036292348Sken	int error;
1037292348Sken
1038292348Sken	error = 0;
1039292348Sken	softc = (struct pass_softc *)periph->softc;
1040292348Sken
1041292348Sken	cam_periph_assert(periph, MA_OWNED);
1042292348Sken	KASSERT(((softc->flags & PASS_FLAG_ZONE_VALID) == 0),
1043292348Sken		("%s called when the pass(4) zone is valid!\n", __func__));
1044292348Sken	KASSERT((softc->pass_zone == NULL),
1045292348Sken		("%s called when the pass(4) zone is allocated!\n", __func__));
1046292348Sken
1047292348Sken	if ((softc->flags & PASS_FLAG_ZONE_INPROG) == 0) {
1048292348Sken
1049292348Sken		/*
1050292348Sken		 * We're the first context through, so we need to create
1051292348Sken		 * the pass(4) UMA zone for I/O requests.
1052292348Sken		 */
1053292348Sken		softc->flags |= PASS_FLAG_ZONE_INPROG;
1054292348Sken
1055292348Sken		/*
1056292348Sken		 * uma_zcreate() does a blocking (M_WAITOK) allocation,
1057292348Sken		 * so we cannot hold a mutex while we call it.
1058292348Sken		 */
1059292348Sken		cam_periph_unlock(periph);
1060292348Sken
1061292348Sken		softc->pass_zone = uma_zcreate(softc->zone_name,
1062292348Sken		    sizeof(struct pass_io_req), NULL, NULL, NULL, NULL,
1063292348Sken		    /*align*/ 0, /*flags*/ 0);
1064292348Sken
1065292348Sken		softc->pass_io_zone = uma_zcreate(softc->io_zone_name,
1066292348Sken		    softc->io_zone_size, NULL, NULL, NULL, NULL,
1067292348Sken		    /*align*/ 0, /*flags*/ 0);
1068292348Sken
1069292348Sken		cam_periph_lock(periph);
1070292348Sken
1071292348Sken		if ((softc->pass_zone == NULL)
1072292348Sken		 || (softc->pass_io_zone == NULL)) {
1073292348Sken			if (softc->pass_zone == NULL)
1074292348Sken				xpt_print(periph->path, "unable to allocate "
1075292348Sken				    "IO Req UMA zone\n");
1076292348Sken			else
1077292348Sken				xpt_print(periph->path, "unable to allocate "
1078292348Sken				    "IO UMA zone\n");
1079292348Sken			softc->flags &= ~PASS_FLAG_ZONE_INPROG;
1080292348Sken			goto bailout;
1081292348Sken		}
1082292348Sken
1083292348Sken		/*
1084292348Sken		 * Set the flags appropriately and notify any other waiters.
1085292348Sken		 */
1086292348Sken		softc->flags &= PASS_FLAG_ZONE_INPROG;
1087292348Sken		softc->flags |= PASS_FLAG_ZONE_VALID;
1088292348Sken		wakeup(&softc->pass_zone);
1089292348Sken	} else {
1090292348Sken		/*
1091292348Sken		 * In this case, the UMA zone has not yet been created, but
1092292348Sken		 * another context is in the process of creating it.  We
1093292348Sken		 * need to sleep until the creation is either done or has
1094292348Sken		 * failed.
1095292348Sken		 */
1096292348Sken		while ((softc->flags & PASS_FLAG_ZONE_INPROG)
1097292348Sken		    && ((softc->flags & PASS_FLAG_ZONE_VALID) == 0)) {
1098292348Sken			error = msleep(&softc->pass_zone,
1099292348Sken				       cam_periph_mtx(periph), PRIBIO,
1100292348Sken				       "paszon", 0);
1101292348Sken			if (error != 0)
1102292348Sken				goto bailout;
1103292348Sken		}
1104292348Sken		/*
1105292348Sken		 * If the zone creation failed, no luck for the user.
1106292348Sken		 */
1107292348Sken		if ((softc->flags & PASS_FLAG_ZONE_VALID) == 0){
1108292348Sken			error = ENOMEM;
1109292348Sken			goto bailout;
1110292348Sken		}
1111292348Sken	}
1112292348Skenbailout:
1113292348Sken	return (error);
1114292348Sken}
1115292348Sken
1116292348Skenstatic void
1117292348Skenpassiocleanup(struct pass_softc *softc, struct pass_io_req *io_req)
1118292348Sken{
1119292348Sken	union ccb *ccb;
1120292348Sken	u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
1121292348Sken	int i, numbufs;
1122292348Sken
1123292348Sken	ccb = &io_req->ccb;
1124292348Sken
1125292348Sken	switch (ccb->ccb_h.func_code) {
1126292348Sken	case XPT_DEV_MATCH:
1127292348Sken		numbufs = min(io_req->num_bufs, 2);
1128292348Sken
1129292348Sken		if (numbufs == 1) {
1130292348Sken			data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
1131292348Sken		} else {
1132292348Sken			data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
1133292348Sken			data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
1134292348Sken		}
1135292348Sken		break;
1136292348Sken	case XPT_SCSI_IO:
1137292348Sken	case XPT_CONT_TARGET_IO:
1138292348Sken		data_ptrs[0] = &ccb->csio.data_ptr;
1139292348Sken		numbufs = min(io_req->num_bufs, 1);
1140292348Sken		break;
1141292348Sken	case XPT_ATA_IO:
1142292348Sken		data_ptrs[0] = &ccb->ataio.data_ptr;
1143292348Sken		numbufs = min(io_req->num_bufs, 1);
1144292348Sken		break;
1145292348Sken	case XPT_SMP_IO:
1146292348Sken		numbufs = min(io_req->num_bufs, 2);
1147292348Sken		data_ptrs[0] = &ccb->smpio.smp_request;
1148292348Sken		data_ptrs[1] = &ccb->smpio.smp_response;
1149292348Sken		break;
1150292348Sken	case XPT_DEV_ADVINFO:
1151292348Sken		numbufs = min(io_req->num_bufs, 1);
1152292348Sken		data_ptrs[0] = (uint8_t **)&ccb->cdai.buf;
1153292348Sken		break;
1154292348Sken	default:
1155292348Sken		/* allow ourselves to be swapped once again */
1156292348Sken		return;
1157292348Sken		break; /* NOTREACHED */
1158292348Sken	}
1159292348Sken
1160292348Sken	if (io_req->flags & PASS_IO_USER_SEG_MALLOC) {
1161292348Sken		free(io_req->user_segptr, M_SCSIPASS);
1162292348Sken		io_req->user_segptr = NULL;
1163292348Sken	}
1164292348Sken
1165292348Sken	/*
1166292348Sken	 * We only want to free memory we malloced.
1167292348Sken	 */
1168292348Sken	if (io_req->data_flags == CAM_DATA_VADDR) {
1169292348Sken		for (i = 0; i < io_req->num_bufs; i++) {
1170292348Sken			if (io_req->kern_bufs[i] == NULL)
1171292348Sken				continue;
1172292348Sken
1173292348Sken			free(io_req->kern_bufs[i], M_SCSIPASS);
1174292348Sken			io_req->kern_bufs[i] = NULL;
1175292348Sken		}
1176292348Sken	} else if (io_req->data_flags == CAM_DATA_SG) {
1177292348Sken		for (i = 0; i < io_req->num_kern_segs; i++) {
1178292348Sken			if ((uint8_t *)(uintptr_t)
1179292348Sken			    io_req->kern_segptr[i].ds_addr == NULL)
1180292348Sken				continue;
1181292348Sken
1182292348Sken			uma_zfree(softc->pass_io_zone, (uint8_t *)(uintptr_t)
1183292348Sken			    io_req->kern_segptr[i].ds_addr);
1184292348Sken			io_req->kern_segptr[i].ds_addr = 0;
1185292348Sken		}
1186292348Sken	}
1187292348Sken
1188292348Sken	if (io_req->flags & PASS_IO_KERN_SEG_MALLOC) {
1189292348Sken		free(io_req->kern_segptr, M_SCSIPASS);
1190292348Sken		io_req->kern_segptr = NULL;
1191292348Sken	}
1192292348Sken
1193292348Sken	if (io_req->data_flags != CAM_DATA_PADDR) {
1194292348Sken		for (i = 0; i < numbufs; i++) {
1195292348Sken			/*
1196292348Sken			 * Restore the user's buffer pointers to their
1197292348Sken			 * previous values.
1198292348Sken			 */
1199292348Sken			if (io_req->user_bufs[i] != NULL)
1200292348Sken				*data_ptrs[i] = io_req->user_bufs[i];
1201292348Sken		}
1202292348Sken	}
1203292348Sken
1204292348Sken}
1205292348Sken
1206292348Skenstatic int
1207292348Skenpasscopysglist(struct cam_periph *periph, struct pass_io_req *io_req,
1208292348Sken	       ccb_flags direction)
1209292348Sken{
1210292348Sken	bus_size_t kern_watermark, user_watermark, len_copied, len_to_copy;
1211292348Sken	bus_dma_segment_t *user_sglist, *kern_sglist;
1212292348Sken	int i, j, error;
1213292348Sken
1214292348Sken	error = 0;
1215292348Sken	kern_watermark = 0;
1216292348Sken	user_watermark = 0;
1217292348Sken	len_to_copy = 0;
1218292348Sken	len_copied = 0;
1219292348Sken	user_sglist = io_req->user_segptr;
1220292348Sken	kern_sglist = io_req->kern_segptr;
1221292348Sken
1222292348Sken	for (i = 0, j = 0; i < io_req->num_user_segs &&
1223292348Sken	     j < io_req->num_kern_segs;) {
1224292348Sken		uint8_t *user_ptr, *kern_ptr;
1225292348Sken
1226292348Sken		len_to_copy = min(user_sglist[i].ds_len -user_watermark,
1227292348Sken		    kern_sglist[j].ds_len - kern_watermark);
1228292348Sken
1229292348Sken		user_ptr = (uint8_t *)(uintptr_t)user_sglist[i].ds_addr;
1230292348Sken		user_ptr = user_ptr + user_watermark;
1231292348Sken		kern_ptr = (uint8_t *)(uintptr_t)kern_sglist[j].ds_addr;
1232292348Sken		kern_ptr = kern_ptr + kern_watermark;
1233292348Sken
1234292348Sken		user_watermark += len_to_copy;
1235292348Sken		kern_watermark += len_to_copy;
1236292348Sken
1237292348Sken		if (!useracc(user_ptr, len_to_copy,
1238292348Sken		    (direction == CAM_DIR_IN) ? VM_PROT_WRITE : VM_PROT_READ)) {
1239292348Sken			xpt_print(periph->path, "%s: unable to access user "
1240292348Sken				  "S/G list element %p len %zu\n", __func__,
1241292348Sken				  user_ptr, len_to_copy);
1242292348Sken			error = EFAULT;
1243292348Sken			goto bailout;
1244292348Sken		}
1245292348Sken
1246292348Sken		if (direction == CAM_DIR_IN) {
1247292348Sken			error = copyout(kern_ptr, user_ptr, len_to_copy);
1248292348Sken			if (error != 0) {
1249292348Sken				xpt_print(periph->path, "%s: copyout of %u "
1250292348Sken					  "bytes from %p to %p failed with "
1251292348Sken					  "error %d\n", __func__, len_to_copy,
1252292348Sken					  kern_ptr, user_ptr, error);
1253292348Sken				goto bailout;
1254292348Sken			}
1255292348Sken		} else {
1256292348Sken			error = copyin(user_ptr, kern_ptr, len_to_copy);
1257292348Sken			if (error != 0) {
1258292348Sken				xpt_print(periph->path, "%s: copyin of %u "
1259292348Sken					  "bytes from %p to %p failed with "
1260292348Sken					  "error %d\n", __func__, len_to_copy,
1261292348Sken					  user_ptr, kern_ptr, error);
1262292348Sken				goto bailout;
1263292348Sken			}
1264292348Sken		}
1265292348Sken
1266292348Sken		len_copied += len_to_copy;
1267292348Sken
1268292348Sken		if (user_sglist[i].ds_len == user_watermark) {
1269292348Sken			i++;
1270292348Sken			user_watermark = 0;
1271292348Sken		}
1272292348Sken
1273292348Sken		if (kern_sglist[j].ds_len == kern_watermark) {
1274292348Sken			j++;
1275292348Sken			kern_watermark = 0;
1276292348Sken		}
1277292348Sken	}
1278292348Sken
1279292348Skenbailout:
1280292348Sken
1281292348Sken	return (error);
1282292348Sken}
1283292348Sken
1284292348Skenstatic int
1285292348Skenpassmemsetup(struct cam_periph *periph, struct pass_io_req *io_req)
1286292348Sken{
1287292348Sken	union ccb *ccb;
1288292348Sken	struct pass_softc *softc;
1289292348Sken	int numbufs, i;
1290292348Sken	uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
1291292348Sken	uint32_t lengths[CAM_PERIPH_MAXMAPS];
1292292348Sken	uint32_t dirs[CAM_PERIPH_MAXMAPS];
1293292348Sken	uint32_t num_segs;
1294292348Sken	uint16_t *seg_cnt_ptr;
1295292348Sken	size_t maxmap;
1296292348Sken	int error;
1297292348Sken
1298292348Sken	cam_periph_assert(periph, MA_NOTOWNED);
1299292348Sken
1300292348Sken	softc = periph->softc;
1301292348Sken
1302292348Sken	error = 0;
1303292348Sken	ccb = &io_req->ccb;
1304292348Sken	maxmap = 0;
1305292348Sken	num_segs = 0;
1306292348Sken	seg_cnt_ptr = NULL;
1307292348Sken
1308292348Sken	switch(ccb->ccb_h.func_code) {
1309292348Sken	case XPT_DEV_MATCH:
1310292348Sken		if (ccb->cdm.match_buf_len == 0) {
1311292348Sken			printf("%s: invalid match buffer length 0\n", __func__);
1312292348Sken			return(EINVAL);
1313292348Sken		}
1314292348Sken		if (ccb->cdm.pattern_buf_len > 0) {
1315292348Sken			data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
1316292348Sken			lengths[0] = ccb->cdm.pattern_buf_len;
1317292348Sken			dirs[0] = CAM_DIR_OUT;
1318292348Sken			data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
1319292348Sken			lengths[1] = ccb->cdm.match_buf_len;
1320292348Sken			dirs[1] = CAM_DIR_IN;
1321292348Sken			numbufs = 2;
1322292348Sken		} else {
1323292348Sken			data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
1324292348Sken			lengths[0] = ccb->cdm.match_buf_len;
1325292348Sken			dirs[0] = CAM_DIR_IN;
1326292348Sken			numbufs = 1;
1327292348Sken		}
1328292348Sken		io_req->data_flags = CAM_DATA_VADDR;
1329292348Sken		break;
1330292348Sken	case XPT_SCSI_IO:
1331292348Sken	case XPT_CONT_TARGET_IO:
1332292348Sken		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
1333292348Sken			return(0);
1334292348Sken
1335292348Sken		/*
1336292348Sken		 * The user shouldn't be able to supply a bio.
1337292348Sken		 */
1338292348Sken		if ((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_BIO)
1339292348Sken			return (EINVAL);
1340292348Sken
1341292348Sken		io_req->data_flags = ccb->ccb_h.flags & CAM_DATA_MASK;
1342292348Sken
1343292348Sken		data_ptrs[0] = &ccb->csio.data_ptr;
1344292348Sken		lengths[0] = ccb->csio.dxfer_len;
1345292348Sken		dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
1346292348Sken		num_segs = ccb->csio.sglist_cnt;
1347292348Sken		seg_cnt_ptr = &ccb->csio.sglist_cnt;
1348292348Sken		numbufs = 1;
1349292348Sken		maxmap = softc->maxio;
1350292348Sken		break;
1351292348Sken	case XPT_ATA_IO:
1352292348Sken		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
1353292348Sken			return(0);
1354292348Sken
1355292348Sken		/*
1356292348Sken		 * We only support a single virtual address for ATA I/O.
1357292348Sken		 */
1358292348Sken		if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
1359292348Sken			return (EINVAL);
1360292348Sken
1361292348Sken		io_req->data_flags = CAM_DATA_VADDR;
1362292348Sken
1363292348Sken		data_ptrs[0] = &ccb->ataio.data_ptr;
1364292348Sken		lengths[0] = ccb->ataio.dxfer_len;
1365292348Sken		dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
1366292348Sken		numbufs = 1;
1367292348Sken		maxmap = softc->maxio;
1368292348Sken		break;
1369292348Sken	case XPT_SMP_IO:
1370292348Sken		io_req->data_flags = CAM_DATA_VADDR;
1371292348Sken
1372292348Sken		data_ptrs[0] = &ccb->smpio.smp_request;
1373292348Sken		lengths[0] = ccb->smpio.smp_request_len;
1374292348Sken		dirs[0] = CAM_DIR_OUT;
1375292348Sken		data_ptrs[1] = &ccb->smpio.smp_response;
1376292348Sken		lengths[1] = ccb->smpio.smp_response_len;
1377292348Sken		dirs[1] = CAM_DIR_IN;
1378292348Sken		numbufs = 2;
1379292348Sken		maxmap = softc->maxio;
1380292348Sken		break;
1381292348Sken	case XPT_DEV_ADVINFO:
1382292348Sken		if (ccb->cdai.bufsiz == 0)
1383292348Sken			return (0);
1384292348Sken
1385292348Sken		io_req->data_flags = CAM_DATA_VADDR;
1386292348Sken
1387292348Sken		data_ptrs[0] = (uint8_t **)&ccb->cdai.buf;
1388292348Sken		lengths[0] = ccb->cdai.bufsiz;
1389292348Sken		dirs[0] = CAM_DIR_IN;
1390292348Sken		numbufs = 1;
1391292348Sken		break;
1392292348Sken	default:
1393292348Sken		return(EINVAL);
1394292348Sken		break; /* NOTREACHED */
1395292348Sken	}
1396292348Sken
1397292348Sken	io_req->num_bufs = numbufs;
1398292348Sken
1399292348Sken	/*
1400292348Sken	 * If there is a maximum, check to make sure that the user's
1401292348Sken	 * request fits within the limit.  In general, we should only have
1402292348Sken	 * a maximum length for requests that go to hardware.  Otherwise it
1403292348Sken	 * is whatever we're able to malloc.
1404292348Sken	 */
1405292348Sken	for (i = 0; i < numbufs; i++) {
1406292348Sken		io_req->user_bufs[i] = *data_ptrs[i];
1407292348Sken		io_req->dirs[i] = dirs[i];
1408292348Sken		io_req->lengths[i] = lengths[i];
1409292348Sken
1410292348Sken		if (maxmap == 0)
1411292348Sken			continue;
1412292348Sken
1413292348Sken		if (lengths[i] <= maxmap)
1414292348Sken			continue;
1415292348Sken
1416292348Sken		xpt_print(periph->path, "%s: data length %u > max allowed %u "
1417292348Sken			  "bytes\n", __func__, lengths[i], maxmap);
1418292348Sken		error = EINVAL;
1419292348Sken		goto bailout;
1420292348Sken	}
1421292348Sken
1422292348Sken	switch (io_req->data_flags) {
1423292348Sken	case CAM_DATA_VADDR:
1424292348Sken		/* Map or copy the buffer into kernel address space */
1425292348Sken		for (i = 0; i < numbufs; i++) {
1426292348Sken			uint8_t *tmp_buf;
1427292348Sken
1428292348Sken			/*
1429292348Sken			 * If for some reason no length is specified, we
1430292348Sken			 * don't need to allocate anything.
1431292348Sken			 */
1432292348Sken			if (io_req->lengths[i] == 0)
1433292348Sken				continue;
1434292348Sken
1435292348Sken			/*
1436292348Sken			 * Make sure that the user's buffer is accessible
1437292348Sken			 * to that process.
1438292348Sken			 */
1439292348Sken			if (!useracc(io_req->user_bufs[i], io_req->lengths[i],
1440292348Sken			    (io_req->dirs[i] == CAM_DIR_IN) ? VM_PROT_WRITE :
1441292348Sken			     VM_PROT_READ)) {
1442292348Sken				xpt_print(periph->path, "%s: user address %p "
1443292348Sken				    "length %u is not accessible\n", __func__,
1444292348Sken				    io_req->user_bufs[i], io_req->lengths[i]);
1445292348Sken				error = EFAULT;
1446292348Sken				goto bailout;
1447292348Sken			}
1448292348Sken
1449292348Sken			tmp_buf = malloc(lengths[i], M_SCSIPASS,
1450292348Sken					 M_WAITOK | M_ZERO);
1451292348Sken			io_req->kern_bufs[i] = tmp_buf;
1452292348Sken			*data_ptrs[i] = tmp_buf;
1453292348Sken
1454292348Sken#if 0
1455292348Sken			xpt_print(periph->path, "%s: malloced %p len %u, user "
1456292348Sken				  "buffer %p, operation: %s\n", __func__,
1457292348Sken				  tmp_buf, lengths[i], io_req->user_bufs[i],
1458292348Sken				  (dirs[i] == CAM_DIR_IN) ? "read" : "write");
1459292348Sken#endif
1460292348Sken			/*
1461292348Sken			 * We only need to copy in if the user is writing.
1462292348Sken			 */
1463292348Sken			if (dirs[i] != CAM_DIR_OUT)
1464292348Sken				continue;
1465292348Sken
1466292348Sken			error = copyin(io_req->user_bufs[i],
1467292348Sken				       io_req->kern_bufs[i], lengths[i]);
1468292348Sken			if (error != 0) {
1469292348Sken				xpt_print(periph->path, "%s: copy of user "
1470292348Sken					  "buffer from %p to %p failed with "
1471292348Sken					  "error %d\n", __func__,
1472292348Sken					  io_req->user_bufs[i],
1473292348Sken					  io_req->kern_bufs[i], error);
1474292348Sken				goto bailout;
1475292348Sken			}
1476292348Sken		}
1477292348Sken		break;
1478292348Sken	case CAM_DATA_PADDR:
1479292348Sken		/* Pass down the pointer as-is */
1480292348Sken		break;
1481292348Sken	case CAM_DATA_SG: {
1482292348Sken		size_t sg_length, size_to_go, alloc_size;
1483292348Sken		uint32_t num_segs_needed;
1484292348Sken
1485292348Sken		/*
1486292348Sken		 * Copy the user S/G list in, and then copy in the
1487292348Sken		 * individual segments.
1488292348Sken		 */
1489292348Sken		/*
1490292348Sken		 * We shouldn't see this, but check just in case.
1491292348Sken		 */
1492292348Sken		if (numbufs != 1) {
1493292348Sken			xpt_print(periph->path, "%s: cannot currently handle "
1494292348Sken				  "more than one S/G list per CCB\n", __func__);
1495292348Sken			error = EINVAL;
1496292348Sken			goto bailout;
1497292348Sken		}
1498292348Sken
1499292348Sken		/*
1500292348Sken		 * We have to have at least one segment.
1501292348Sken		 */
1502292348Sken		if (num_segs == 0) {
1503292348Sken			xpt_print(periph->path, "%s: CAM_DATA_SG flag set, "
1504292348Sken				  "but sglist_cnt=0!\n", __func__);
1505292348Sken			error = EINVAL;
1506292348Sken			goto bailout;
1507292348Sken		}
1508292348Sken
1509292348Sken		/*
1510292348Sken		 * Make sure the user specified the total length and didn't
1511292348Sken		 * just leave it to us to decode the S/G list.
1512292348Sken		 */
1513292348Sken		if (lengths[0] == 0) {
1514292348Sken			xpt_print(periph->path, "%s: no dxfer_len specified, "
1515292348Sken				  "but CAM_DATA_SG flag is set!\n", __func__);
1516292348Sken			error = EINVAL;
1517292348Sken			goto bailout;
1518292348Sken		}
1519292348Sken
1520292348Sken		/*
1521292348Sken		 * We allocate buffers in io_zone_size increments for an
1522292348Sken		 * S/G list.  This will generally be MAXPHYS.
1523292348Sken		 */
1524292348Sken		if (lengths[0] <= softc->io_zone_size)
1525292348Sken			num_segs_needed = 1;
1526292348Sken		else {
1527292348Sken			num_segs_needed = lengths[0] / softc->io_zone_size;
1528292348Sken			if ((lengths[0] % softc->io_zone_size) != 0)
1529292348Sken				num_segs_needed++;
1530292348Sken		}
1531292348Sken
1532292348Sken		/* Figure out the size of the S/G list */
1533292348Sken		sg_length = num_segs * sizeof(bus_dma_segment_t);
1534292348Sken		io_req->num_user_segs = num_segs;
1535292348Sken		io_req->num_kern_segs = num_segs_needed;
1536292348Sken
1537292348Sken		/* Save the user's S/G list pointer for later restoration */
1538292348Sken		io_req->user_bufs[0] = *data_ptrs[0];
1539292348Sken
1540292348Sken		/*
1541292348Sken		 * If we have enough segments allocated by default to handle
1542292348Sken		 * the length of the user's S/G list,
1543292348Sken		 */
1544292348Sken		if (num_segs > PASS_MAX_SEGS) {
1545292348Sken			io_req->user_segptr = malloc(sizeof(bus_dma_segment_t) *
1546292348Sken			    num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
1547292348Sken			io_req->flags |= PASS_IO_USER_SEG_MALLOC;
1548292348Sken		} else
1549292348Sken			io_req->user_segptr = io_req->user_segs;
1550292348Sken
1551292348Sken		if (!useracc(*data_ptrs[0], sg_length, VM_PROT_READ)) {
1552292348Sken			xpt_print(periph->path, "%s: unable to access user "
1553292348Sken				  "S/G list at %p\n", __func__, *data_ptrs[0]);
1554292348Sken			error = EFAULT;
1555292348Sken			goto bailout;
1556292348Sken		}
1557292348Sken
1558292348Sken		error = copyin(*data_ptrs[0], io_req->user_segptr, sg_length);
1559292348Sken		if (error != 0) {
1560292348Sken			xpt_print(periph->path, "%s: copy of user S/G list "
1561292348Sken				  "from %p to %p failed with error %d\n",
1562292348Sken				  __func__, *data_ptrs[0], io_req->user_segptr,
1563292348Sken				  error);
1564292348Sken			goto bailout;
1565292348Sken		}
1566292348Sken
1567292348Sken		if (num_segs_needed > PASS_MAX_SEGS) {
1568292348Sken			io_req->kern_segptr = malloc(sizeof(bus_dma_segment_t) *
1569292348Sken			    num_segs_needed, M_SCSIPASS, M_WAITOK | M_ZERO);
1570292348Sken			io_req->flags |= PASS_IO_KERN_SEG_MALLOC;
1571292348Sken		} else {
1572292348Sken			io_req->kern_segptr = io_req->kern_segs;
1573292348Sken		}
1574292348Sken
1575292348Sken		/*
1576292348Sken		 * Allocate the kernel S/G list.
1577292348Sken		 */
1578292348Sken		for (size_to_go = lengths[0], i = 0;
1579292348Sken		     size_to_go > 0 && i < num_segs_needed;
1580292348Sken		     i++, size_to_go -= alloc_size) {
1581292348Sken			uint8_t *kern_ptr;
1582292348Sken
1583292348Sken			alloc_size = min(size_to_go, softc->io_zone_size);
1584292348Sken			kern_ptr = uma_zalloc(softc->pass_io_zone, M_WAITOK);
1585292348Sken			io_req->kern_segptr[i].ds_addr =
1586292348Sken			    (bus_addr_t)(uintptr_t)kern_ptr;
1587292348Sken			io_req->kern_segptr[i].ds_len = alloc_size;
1588292348Sken		}
1589292348Sken		if (size_to_go > 0) {
1590292348Sken			printf("%s: size_to_go = %zu, software error!\n",
1591292348Sken			       __func__, size_to_go);
1592292348Sken			error = EINVAL;
1593292348Sken			goto bailout;
1594292348Sken		}
1595292348Sken
1596292348Sken		*data_ptrs[0] = (uint8_t *)io_req->kern_segptr;
1597292348Sken		*seg_cnt_ptr = io_req->num_kern_segs;
1598292348Sken
1599292348Sken		/*
1600292348Sken		 * We only need to copy data here if the user is writing.
1601292348Sken		 */
1602292348Sken		if (dirs[0] == CAM_DIR_OUT)
1603292348Sken			error = passcopysglist(periph, io_req, dirs[0]);
1604292348Sken		break;
1605292348Sken	}
1606292348Sken	case CAM_DATA_SG_PADDR: {
1607292348Sken		size_t sg_length;
1608292348Sken
1609292348Sken		/*
1610292348Sken		 * We shouldn't see this, but check just in case.
1611292348Sken		 */
1612292348Sken		if (numbufs != 1) {
1613292348Sken			printf("%s: cannot currently handle more than one "
1614292348Sken			       "S/G list per CCB\n", __func__);
1615292348Sken			error = EINVAL;
1616292348Sken			goto bailout;
1617292348Sken		}
1618292348Sken
1619292348Sken		/*
1620292348Sken		 * We have to have at least one segment.
1621292348Sken		 */
1622292348Sken		if (num_segs == 0) {
1623292348Sken			xpt_print(periph->path, "%s: CAM_DATA_SG_PADDR flag "
1624292348Sken				  "set, but sglist_cnt=0!\n", __func__);
1625292348Sken			error = EINVAL;
1626292348Sken			goto bailout;
1627292348Sken		}
1628292348Sken
1629292348Sken		/*
1630292348Sken		 * Make sure the user specified the total length and didn't
1631292348Sken		 * just leave it to us to decode the S/G list.
1632292348Sken		 */
1633292348Sken		if (lengths[0] == 0) {
1634292348Sken			xpt_print(periph->path, "%s: no dxfer_len specified, "
1635292348Sken				  "but CAM_DATA_SG flag is set!\n", __func__);
1636292348Sken			error = EINVAL;
1637292348Sken			goto bailout;
1638292348Sken		}
1639292348Sken
1640292348Sken		/* Figure out the size of the S/G list */
1641292348Sken		sg_length = num_segs * sizeof(bus_dma_segment_t);
1642292348Sken		io_req->num_user_segs = num_segs;
1643292348Sken		io_req->num_kern_segs = io_req->num_user_segs;
1644292348Sken
1645292348Sken		/* Save the user's S/G list pointer for later restoration */
1646292348Sken		io_req->user_bufs[0] = *data_ptrs[0];
1647292348Sken
1648292348Sken		if (num_segs > PASS_MAX_SEGS) {
1649292348Sken			io_req->user_segptr = malloc(sizeof(bus_dma_segment_t) *
1650292348Sken			    num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
1651292348Sken			io_req->flags |= PASS_IO_USER_SEG_MALLOC;
1652292348Sken		} else
1653292348Sken			io_req->user_segptr = io_req->user_segs;
1654292348Sken
1655292348Sken		io_req->kern_segptr = io_req->user_segptr;
1656292348Sken
1657292348Sken		error = copyin(*data_ptrs[0], io_req->user_segptr, sg_length);
1658292348Sken		if (error != 0) {
1659292348Sken			xpt_print(periph->path, "%s: copy of user S/G list "
1660292348Sken				  "from %p to %p failed with error %d\n",
1661292348Sken				  __func__, *data_ptrs[0], io_req->user_segptr,
1662292348Sken				  error);
1663292348Sken			goto bailout;
1664292348Sken		}
1665292348Sken		break;
1666292348Sken	}
1667292348Sken	default:
1668292348Sken	case CAM_DATA_BIO:
1669292348Sken		/*
1670292348Sken		 * A user shouldn't be attaching a bio to the CCB.  It
1671292348Sken		 * isn't a user-accessible structure.
1672292348Sken		 */
1673292348Sken		error = EINVAL;
1674292348Sken		break;
1675292348Sken	}
1676292348Sken
1677292348Skenbailout:
1678292348Sken	if (error != 0)
1679292348Sken		passiocleanup(softc, io_req);
1680292348Sken
1681292348Sken	return (error);
1682292348Sken}
1683292348Sken
1684292348Skenstatic int
1685292348Skenpassmemdone(struct cam_periph *periph, struct pass_io_req *io_req)
1686292348Sken{
1687292348Sken	struct pass_softc *softc;
1688292348Sken	union ccb *ccb;
1689292348Sken	int error;
1690292348Sken	int i;
1691292348Sken
1692292348Sken	error = 0;
1693292348Sken	softc = (struct pass_softc *)periph->softc;
1694292348Sken	ccb = &io_req->ccb;
1695292348Sken
1696292348Sken	switch (io_req->data_flags) {
1697292348Sken	case CAM_DATA_VADDR:
1698292348Sken		/*
1699292348Sken		 * Copy back to the user buffer if this was a read.
1700292348Sken		 */
1701292348Sken		for (i = 0; i < io_req->num_bufs; i++) {
1702292348Sken			if (io_req->dirs[i] != CAM_DIR_IN)
1703292348Sken				continue;
1704292348Sken
1705292348Sken			error = copyout(io_req->kern_bufs[i],
1706292348Sken			    io_req->user_bufs[i], io_req->lengths[i]);
1707292348Sken			if (error != 0) {
1708292348Sken				xpt_print(periph->path, "Unable to copy %u "
1709292348Sken					  "bytes from %p to user address %p\n",
1710292348Sken					  io_req->lengths[i],
1711292348Sken					  io_req->kern_bufs[i],
1712292348Sken					  io_req->user_bufs[i]);
1713292348Sken				goto bailout;
1714292348Sken			}
1715292348Sken
1716292348Sken		}
1717292348Sken		break;
1718292348Sken	case CAM_DATA_PADDR:
1719292348Sken		/* Do nothing.  The pointer is a physical address already */
1720292348Sken		break;
1721292348Sken	case CAM_DATA_SG:
1722292348Sken		/*
1723292348Sken		 * Copy back to the user buffer if this was a read.
1724292348Sken		 * Restore the user's S/G list buffer pointer.
1725292348Sken		 */
1726292348Sken		if (io_req->dirs[0] == CAM_DIR_IN)
1727292348Sken			error = passcopysglist(periph, io_req, io_req->dirs[0]);
1728292348Sken		break;
1729292348Sken	case CAM_DATA_SG_PADDR:
1730292348Sken		/*
1731292348Sken		 * Restore the user's S/G list buffer pointer.  No need to
1732292348Sken		 * copy.
1733292348Sken		 */
1734292348Sken		break;
1735292348Sken	default:
1736292348Sken	case CAM_DATA_BIO:
1737292348Sken		error = EINVAL;
1738292348Sken		break;
1739292348Sken	}
1740292348Sken
1741292348Skenbailout:
1742292348Sken	/*
1743292348Sken	 * Reset the user's pointers to their original values and free
1744292348Sken	 * allocated memory.
1745292348Sken	 */
1746292348Sken	passiocleanup(softc, io_req);
1747292348Sken
1748292348Sken	return (error);
1749292348Sken}
1750292348Sken
1751292348Skenstatic int
1752130585Sphkpassioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
175339213Sgibbs{
1754251837Sscottl	int error;
1755251837Sscottl
1756251837Sscottl	if ((error = passdoioctl(dev, cmd, addr, flag, td)) == ENOTTY) {
1757255870Sscottl		error = cam_compat_ioctl(dev, cmd, addr, flag, td, passdoioctl);
1758251837Sscottl	}
1759251837Sscottl	return (error);
1760251837Sscottl}
1761251837Sscottl
1762251837Sscottlstatic int
1763251837Sscottlpassdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
1764251837Sscottl{
1765101940Snjl	struct	cam_periph *periph;
176639213Sgibbs	struct	pass_softc *softc;
1767101940Snjl	int	error;
1768242175Smav	uint32_t priority;
176939213Sgibbs
1770101940Snjl	periph = (struct cam_periph *)dev->si_drv1;
1771168752Sscottl	cam_periph_lock(periph);
177239213Sgibbs	softc = (struct pass_softc *)periph->softc;
177339213Sgibbs
177439213Sgibbs	error = 0;
177539213Sgibbs
177639213Sgibbs	switch (cmd) {
177739213Sgibbs
177839213Sgibbs	case CAMIOCOMMAND:
177939213Sgibbs	{
178039213Sgibbs		union ccb *inccb;
178139213Sgibbs		union ccb *ccb;
178246581Sken		int ccb_malloced;
178339213Sgibbs
178439213Sgibbs		inccb = (union ccb *)addr;
178539213Sgibbs
178646581Sken		/*
178746581Sken		 * Some CCB types, like scan bus and scan lun can only go
178846581Sken		 * through the transport layer device.
178946581Sken		 */
179046581Sken		if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
1791164906Smjacob			xpt_print(periph->path, "CCB function code %#x is "
1792164906Smjacob			    "restricted to the XPT device\n",
1793164906Smjacob			    inccb->ccb_h.func_code);
179446581Sken			error = ENODEV;
179546581Sken			break;
179646581Sken		}
179746581Sken
1798242175Smav		/* Compatibility for RL/priority-unaware code. */
1799242175Smav		priority = inccb->ccb_h.pinfo.priority;
1800249466Smav		if (priority <= CAM_PRIORITY_OOB)
1801249466Smav		    priority += CAM_PRIORITY_OOB + 1;
1802242175Smav
180346581Sken		/*
180446581Sken		 * Non-immediate CCBs need a CCB from the per-device pool
180546581Sken		 * of CCBs, which is scheduled by the transport layer.
180646581Sken		 * Immediate CCBs and user-supplied CCBs should just be
180746581Sken		 * malloced.
180846581Sken		 */
180946581Sken		if ((inccb->ccb_h.func_code & XPT_FC_QUEUED)
181046581Sken		 && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) {
1811242175Smav			ccb = cam_periph_getccb(periph, priority);
181246581Sken			ccb_malloced = 0;
181346581Sken		} else {
1814168831Sscottl			ccb = xpt_alloc_ccb_nowait();
181546581Sken
181646581Sken			if (ccb != NULL)
181746581Sken				xpt_setup_ccb(&ccb->ccb_h, periph->path,
1818242175Smav					      priority);
181946581Sken			ccb_malloced = 1;
182046581Sken		}
182146581Sken
182246581Sken		if (ccb == NULL) {
1823164906Smjacob			xpt_print(periph->path, "unable to allocate CCB\n");
182446581Sken			error = ENOMEM;
182546581Sken			break;
182646581Sken		}
182746581Sken
182839213Sgibbs		error = passsendccb(periph, ccb, inccb);
182939213Sgibbs
183046581Sken		if (ccb_malloced)
183146581Sken			xpt_free_ccb(ccb);
183246581Sken		else
183346581Sken			xpt_release_ccb(ccb);
183439213Sgibbs
183539213Sgibbs		break;
183639213Sgibbs	}
1837292348Sken	case CAMIOQUEUE:
1838292348Sken	{
1839292348Sken		struct pass_io_req *io_req;
1840292348Sken		union ccb **user_ccb, *ccb;
1841292348Sken		xpt_opcode fc;
1842292348Sken
1843292348Sken		if ((softc->flags & PASS_FLAG_ZONE_VALID) == 0) {
1844292348Sken			error = passcreatezone(periph);
1845292348Sken			if (error != 0)
1846292348Sken				goto bailout;
1847292348Sken		}
1848292348Sken
1849292348Sken		/*
1850292348Sken		 * We're going to do a blocking allocation for this I/O
1851292348Sken		 * request, so we have to drop the lock.
1852292348Sken		 */
1853292348Sken		cam_periph_unlock(periph);
1854292348Sken
1855292348Sken		io_req = uma_zalloc(softc->pass_zone, M_WAITOK | M_ZERO);
1856292348Sken		ccb = &io_req->ccb;
1857292348Sken		user_ccb = (union ccb **)addr;
1858292348Sken
1859292348Sken		/*
1860292348Sken		 * Unlike the CAMIOCOMMAND ioctl above, we only have a
1861292348Sken		 * pointer to the user's CCB, so we have to copy the whole
1862292348Sken		 * thing in to a buffer we have allocated (above) instead
1863292348Sken		 * of allowing the ioctl code to malloc a buffer and copy
1864292348Sken		 * it in.
1865292348Sken		 *
1866292348Sken		 * This is an advantage for this asynchronous interface,
1867292348Sken		 * since we don't want the memory to get freed while the
1868292348Sken		 * CCB is outstanding.
1869292348Sken		 */
1870292348Sken#if 0
1871292348Sken		xpt_print(periph->path, "Copying user CCB %p to "
1872292348Sken			  "kernel address %p\n", *user_ccb, ccb);
1873292348Sken#endif
1874292348Sken		error = copyin(*user_ccb, ccb, sizeof(*ccb));
1875292348Sken		if (error != 0) {
1876292348Sken			xpt_print(periph->path, "Copy of user CCB %p to "
1877292348Sken				  "kernel address %p failed with error %d\n",
1878292348Sken				  *user_ccb, ccb, error);
1879292348Sken			uma_zfree(softc->pass_zone, io_req);
1880292348Sken			cam_periph_lock(periph);
1881292348Sken			break;
1882292348Sken		}
1883292348Sken
1884292348Sken		/*
1885292348Sken		 * Some CCB types, like scan bus and scan lun can only go
1886292348Sken		 * through the transport layer device.
1887292348Sken		 */
1888292348Sken		if (ccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
1889292348Sken			xpt_print(periph->path, "CCB function code %#x is "
1890292348Sken			    "restricted to the XPT device\n",
1891292348Sken			    ccb->ccb_h.func_code);
1892292348Sken			uma_zfree(softc->pass_zone, io_req);
1893292348Sken			cam_periph_lock(periph);
1894292348Sken			error = ENODEV;
1895292348Sken			break;
1896292348Sken		}
1897292348Sken
1898292348Sken		/*
1899292348Sken		 * Save the user's CCB pointer as well as his linked list
1900292348Sken		 * pointers and peripheral private area so that we can
1901292348Sken		 * restore these later.
1902292348Sken		 */
1903292348Sken		io_req->user_ccb_ptr = *user_ccb;
1904292348Sken		io_req->user_periph_links = ccb->ccb_h.periph_links;
1905292348Sken		io_req->user_periph_priv = ccb->ccb_h.periph_priv;
1906292348Sken
1907292348Sken		/*
1908292348Sken		 * Now that we've saved the user's values, we can set our
1909292348Sken		 * own peripheral private entry.
1910292348Sken		 */
1911292348Sken		ccb->ccb_h.ccb_ioreq = io_req;
1912292348Sken
1913292348Sken		/* Compatibility for RL/priority-unaware code. */
1914292348Sken		priority = ccb->ccb_h.pinfo.priority;
1915292348Sken		if (priority <= CAM_PRIORITY_OOB)
1916292348Sken		    priority += CAM_PRIORITY_OOB + 1;
1917292348Sken
1918292348Sken		/*
1919292348Sken		 * Setup fields in the CCB like the path and the priority.
1920292348Sken		 * The path in particular cannot be done in userland, since
1921292348Sken		 * it is a pointer to a kernel data structure.
1922292348Sken		 */
1923292348Sken		xpt_setup_ccb_flags(&ccb->ccb_h, periph->path, priority,
1924292348Sken				    ccb->ccb_h.flags);
1925292348Sken
1926292348Sken		/*
1927292348Sken		 * Setup our done routine.  There is no way for the user to
1928292348Sken		 * have a valid pointer here.
1929292348Sken		 */
1930292348Sken		ccb->ccb_h.cbfcnp = passdone;
1931292348Sken
1932292348Sken		fc = ccb->ccb_h.func_code;
1933292348Sken		/*
1934292348Sken		 * If this function code has memory that can be mapped in
1935292348Sken		 * or out, we need to call passmemsetup().
1936292348Sken		 */
1937292348Sken		if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO)
1938292348Sken		 || (fc == XPT_SMP_IO) || (fc == XPT_DEV_MATCH)
1939292348Sken		 || (fc == XPT_DEV_ADVINFO)) {
1940292348Sken			error = passmemsetup(periph, io_req);
1941292348Sken			if (error != 0) {
1942292348Sken				uma_zfree(softc->pass_zone, io_req);
1943292348Sken				cam_periph_lock(periph);
1944292348Sken				break;
1945292348Sken			}
1946292348Sken		} else
1947292348Sken			io_req->mapinfo.num_bufs_used = 0;
1948292348Sken
1949292348Sken		cam_periph_lock(periph);
1950292348Sken
1951292348Sken		/*
1952292348Sken		 * Everything goes on the incoming queue initially.
1953292348Sken		 */
1954292348Sken		TAILQ_INSERT_TAIL(&softc->incoming_queue, io_req, links);
1955292348Sken
1956292348Sken		/*
1957292348Sken		 * If the CCB is queued, and is not a user CCB, then
1958292348Sken		 * we need to allocate a slot for it.  Call xpt_schedule()
1959292348Sken		 * so that our start routine will get called when a CCB is
1960292348Sken		 * available.
1961292348Sken		 */
1962292348Sken		if ((fc & XPT_FC_QUEUED)
1963292348Sken		 && ((fc & XPT_FC_USER_CCB) == 0)) {
1964292348Sken			xpt_schedule(periph, priority);
1965292348Sken			break;
1966292348Sken		}
1967292348Sken
1968292348Sken		/*
1969292348Sken		 * At this point, the CCB in question is either an
1970292348Sken		 * immediate CCB (like XPT_DEV_ADVINFO) or it is a user CCB
1971292348Sken		 * and therefore should be malloced, not allocated via a slot.
1972292348Sken		 * Remove the CCB from the incoming queue and add it to the
1973292348Sken		 * active queue.
1974292348Sken		 */
1975292348Sken		TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
1976292348Sken		TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
1977292348Sken
1978292348Sken		xpt_action(ccb);
1979292348Sken
1980292348Sken		/*
1981292348Sken		 * If this is not a queued CCB (i.e. it is an immediate CCB),
1982292348Sken		 * then it is already done.  We need to put it on the done
1983292348Sken		 * queue for the user to fetch.
1984292348Sken		 */
1985292348Sken		if ((fc & XPT_FC_QUEUED) == 0) {
1986292348Sken			TAILQ_REMOVE(&softc->active_queue, io_req, links);
1987292348Sken			TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
1988292348Sken		}
1989292348Sken		break;
1990292348Sken	}
1991292348Sken	case CAMIOGET:
1992292348Sken	{
1993292348Sken		union ccb **user_ccb;
1994292348Sken		struct pass_io_req *io_req;
1995292348Sken		int old_error;
1996292348Sken
1997292348Sken		user_ccb = (union ccb **)addr;
1998292348Sken		old_error = 0;
1999292348Sken
2000292348Sken		io_req = TAILQ_FIRST(&softc->done_queue);
2001292348Sken		if (io_req == NULL) {
2002292348Sken			error = ENOENT;
2003292348Sken			break;
2004292348Sken		}
2005292348Sken
2006292348Sken		/*
2007292348Sken		 * Remove the I/O from the done queue.
2008292348Sken		 */
2009292348Sken		TAILQ_REMOVE(&softc->done_queue, io_req, links);
2010292348Sken
2011292348Sken		/*
2012292348Sken		 * We have to drop the lock during the copyout because the
2013292348Sken		 * copyout can result in VM faults that require sleeping.
2014292348Sken		 */
2015292348Sken		cam_periph_unlock(periph);
2016292348Sken
2017292348Sken		/*
2018292348Sken		 * Do any needed copies (e.g. for reads) and revert the
2019292348Sken		 * pointers in the CCB back to the user's pointers.
2020292348Sken		 */
2021292348Sken		error = passmemdone(periph, io_req);
2022292348Sken
2023292348Sken		old_error = error;
2024292348Sken
2025292348Sken		io_req->ccb.ccb_h.periph_links = io_req->user_periph_links;
2026292348Sken		io_req->ccb.ccb_h.periph_priv = io_req->user_periph_priv;
2027292348Sken
2028292348Sken#if 0
2029292348Sken		xpt_print(periph->path, "Copying to user CCB %p from "
2030292348Sken			  "kernel address %p\n", *user_ccb, &io_req->ccb);
2031292348Sken#endif
2032292348Sken
2033292348Sken		error = copyout(&io_req->ccb, *user_ccb, sizeof(union ccb));
2034292348Sken		if (error != 0) {
2035292348Sken			xpt_print(periph->path, "Copy to user CCB %p from "
2036292348Sken				  "kernel address %p failed with error %d\n",
2037292348Sken				  *user_ccb, &io_req->ccb, error);
2038292348Sken		}
2039292348Sken
2040292348Sken		/*
2041292348Sken		 * Prefer the first error we got back, and make sure we
2042292348Sken		 * don't overwrite bad status with good.
2043292348Sken		 */
2044292348Sken		if (old_error != 0)
2045292348Sken			error = old_error;
2046292348Sken
2047292348Sken		cam_periph_lock(periph);
2048292348Sken
2049292348Sken		/*
2050292348Sken		 * At this point, if there was an error, we could potentially
2051292348Sken		 * re-queue the I/O and try again.  But why?  The error
2052292348Sken		 * would almost certainly happen again.  We might as well
2053292348Sken		 * not leak memory.
2054292348Sken		 */
2055292348Sken		uma_zfree(softc->pass_zone, io_req);
2056292348Sken		break;
2057292348Sken	}
205839213Sgibbs	default:
205939213Sgibbs		error = cam_periph_ioctl(periph, cmd, addr, passerror);
206039213Sgibbs		break;
206139213Sgibbs	}
206239213Sgibbs
2063292348Skenbailout:
2064168752Sscottl	cam_periph_unlock(periph);
2065292348Sken
206639213Sgibbs	return(error);
206739213Sgibbs}
206839213Sgibbs
2069292348Skenstatic int
2070292348Skenpasspoll(struct cdev *dev, int poll_events, struct thread *td)
2071292348Sken{
2072292348Sken	struct cam_periph *periph;
2073292348Sken	struct pass_softc *softc;
2074292348Sken	int revents;
2075292348Sken
2076292348Sken	periph = (struct cam_periph *)dev->si_drv1;
2077292348Sken	softc = (struct pass_softc *)periph->softc;
2078292348Sken
2079292348Sken	revents = poll_events & (POLLOUT | POLLWRNORM);
2080292348Sken	if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
2081292348Sken		cam_periph_lock(periph);
2082292348Sken
2083292348Sken		if (!TAILQ_EMPTY(&softc->done_queue)) {
2084292348Sken			revents |= poll_events & (POLLIN | POLLRDNORM);
2085292348Sken		}
2086292348Sken		cam_periph_unlock(periph);
2087292348Sken		if (revents == 0)
2088292348Sken			selrecord(td, &softc->read_select);
2089292348Sken	}
2090292348Sken
2091292348Sken	return (revents);
2092292348Sken}
2093292348Sken
2094292348Skenstatic int
2095292348Skenpasskqfilter(struct cdev *dev, struct knote *kn)
2096292348Sken{
2097292348Sken	struct cam_periph *periph;
2098292348Sken	struct pass_softc *softc;
2099292348Sken
2100292348Sken	periph = (struct cam_periph *)dev->si_drv1;
2101292348Sken	softc = (struct pass_softc *)periph->softc;
2102292348Sken
2103292348Sken	kn->kn_hook = (caddr_t)periph;
2104292348Sken	kn->kn_fop = &passread_filtops;
2105292348Sken	knlist_add(&softc->read_select.si_note, kn, 0);
2106292348Sken
2107292348Sken	return (0);
2108292348Sken}
2109292348Sken
2110292348Skenstatic void
2111292348Skenpassreadfiltdetach(struct knote *kn)
2112292348Sken{
2113292348Sken	struct cam_periph *periph;
2114292348Sken	struct pass_softc *softc;
2115292348Sken
2116292348Sken	periph = (struct cam_periph *)kn->kn_hook;
2117292348Sken	softc = (struct pass_softc *)periph->softc;
2118292348Sken
2119292348Sken	knlist_remove(&softc->read_select.si_note, kn, 0);
2120292348Sken}
2121292348Sken
2122292348Skenstatic int
2123292348Skenpassreadfilt(struct knote *kn, long hint)
2124292348Sken{
2125292348Sken	struct cam_periph *periph;
2126292348Sken	struct pass_softc *softc;
2127292348Sken	int retval;
2128292348Sken
2129292348Sken	periph = (struct cam_periph *)kn->kn_hook;
2130292348Sken	softc = (struct pass_softc *)periph->softc;
2131292348Sken
2132292348Sken	cam_periph_assert(periph, MA_OWNED);
2133292348Sken
2134292348Sken	if (TAILQ_EMPTY(&softc->done_queue))
2135292348Sken		retval = 0;
2136292348Sken	else
2137292348Sken		retval = 1;
2138292348Sken
2139292348Sken	return (retval);
2140292348Sken}
2141292348Sken
214239213Sgibbs/*
214339213Sgibbs * Generally, "ccb" should be the CCB supplied by the kernel.  "inccb"
214439213Sgibbs * should be the CCB that is copied in from the user.
214539213Sgibbs */
214639213Sgibbsstatic int
214739213Sgibbspasssendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
214839213Sgibbs{
214939213Sgibbs	struct pass_softc *softc;
215039213Sgibbs	struct cam_periph_map_info mapinfo;
2151251479Sscottl	xpt_opcode fc;
2152251479Sscottl	int error;
215339213Sgibbs
215439213Sgibbs	softc = (struct pass_softc *)periph->softc;
215539213Sgibbs
215639213Sgibbs	/*
215739213Sgibbs	 * There are some fields in the CCB header that need to be
215839213Sgibbs	 * preserved, the rest we get from the user.
215939213Sgibbs	 */
216039213Sgibbs	xpt_merge_ccb(ccb, inccb);
216139213Sgibbs
216239213Sgibbs	/*
2163292348Sken	 */
2164292348Sken	ccb->ccb_h.cbfcnp = passdone;
2165292348Sken
2166292348Sken	/*
2167251479Sscottl	 * Let cam_periph_mapmem do a sanity check on the data pointer format.
2168251479Sscottl	 * Even if no data transfer is needed, it's a cheap check and it
2169251479Sscottl	 * simplifies the code.
217039213Sgibbs	 */
2171251479Sscottl	fc = ccb->ccb_h.func_code;
2172251479Sscottl	if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO) || (fc == XPT_SMP_IO)
2173251479Sscottl	 || (fc == XPT_DEV_MATCH) || (fc == XPT_DEV_ADVINFO)) {
217439213Sgibbs		bzero(&mapinfo, sizeof(mapinfo));
217539213Sgibbs
2176168752Sscottl		/*
2177168752Sscottl		 * cam_periph_mapmem calls into proc and vm functions that can
2178168752Sscottl		 * sleep as well as trigger I/O, so we can't hold the lock.
2179168752Sscottl		 * Dropping it here is reasonably safe.
2180168752Sscottl		 */
2181168752Sscottl		cam_periph_unlock(periph);
2182288817Smav		error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio);
2183168752Sscottl		cam_periph_lock(periph);
218439213Sgibbs
218539213Sgibbs		/*
218639213Sgibbs		 * cam_periph_mapmem returned an error, we can't continue.
218739213Sgibbs		 * Return the error to the user.
218839213Sgibbs		 */
218939213Sgibbs		if (error)
219039213Sgibbs			return(error);
2191251479Sscottl	} else
2192251479Sscottl		/* Ensure that the unmap call later on is a no-op. */
2193251479Sscottl		mapinfo.num_bufs_used = 0;
219439213Sgibbs
219539213Sgibbs	/*
219639213Sgibbs	 * If the user wants us to perform any error recovery, then honor
219739213Sgibbs	 * that request.  Otherwise, it's up to the user to perform any
219839213Sgibbs	 * error recovery.
219939213Sgibbs	 */
2200236814Smav	cam_periph_runccb(ccb, passerror, /* cam_flags */ CAM_RETRY_SELTO,
2201236814Smav	    /* sense_flags */ ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
2202236814Smav	     SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
2203203108Smav	    softc->device_stats);
220439213Sgibbs
2205251479Sscottl	cam_periph_unmapmem(ccb, &mapinfo);
220639213Sgibbs
220739213Sgibbs	ccb->ccb_h.cbfcnp = NULL;
220839213Sgibbs	ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
220939213Sgibbs	bcopy(ccb, inccb, sizeof(union ccb));
221039213Sgibbs
2211203108Smav	return(0);
221239213Sgibbs}
221339213Sgibbs
221439213Sgibbsstatic int
221539213Sgibbspasserror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
221639213Sgibbs{
221739213Sgibbs	struct cam_periph *periph;
221839213Sgibbs	struct pass_softc *softc;
221939213Sgibbs
222039213Sgibbs	periph = xpt_path_periph(ccb->ccb_h.path);
222139213Sgibbs	softc = (struct pass_softc *)periph->softc;
222239213Sgibbs
222339213Sgibbs	return(cam_periph_error(ccb, cam_flags, sense_flags,
222439213Sgibbs				 &softc->saved_ccb));
222539213Sgibbs}
2226