xref: /dragonfly/sys/bus/cam/scsi/scsi_pt.c (revision ef2b2b9d)
1 /*
2  * Implementation of SCSI Processor Target Peripheral driver for CAM.
3  *
4  * Copyright (c) 1998 Justin T. Gibbs.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification, immediately at the beginning of the file.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/cam/scsi/scsi_pt.c,v 1.17 2000/01/17 06:27:37 mjacob Exp $
29  */
30 
31 #include <sys/param.h>
32 #include <sys/queue.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/types.h>
36 #include <sys/buf.h>
37 #include <sys/devicestat.h>
38 #include <sys/malloc.h>
39 #include <sys/conf.h>
40 #include <sys/ptio.h>
41 #include <sys/buf2.h>
42 
43 #include "../cam.h"
44 #include "../cam_ccb.h"
45 #include "../cam_extend.h"
46 #include "../cam_periph.h"
47 #include "../cam_xpt_periph.h"
48 #include "../cam_debug.h"
49 
50 #include "scsi_all.h"
51 #include "scsi_message.h"
52 #include "scsi_pt.h"
53 
54 #include "opt_pt.h"
55 
56 typedef enum {
57 	PT_STATE_PROBE,
58 	PT_STATE_NORMAL
59 } pt_state;
60 
61 typedef enum {
62 	PT_FLAG_NONE		= 0x00,
63 	PT_FLAG_OPEN		= 0x01,
64 	PT_FLAG_DEVICE_INVALID	= 0x02,
65 	PT_FLAG_RETRY_UA	= 0x04
66 } pt_flags;
67 
68 typedef enum {
69 	PT_CCB_BUFFER_IO	= 0x01,
70 	PT_CCB_WAITING		= 0x02,
71 	PT_CCB_RETRY_UA		= 0x04,
72 	PT_CCB_BUFFER_IO_UA	= PT_CCB_BUFFER_IO|PT_CCB_RETRY_UA
73 } pt_ccb_state;
74 
75 /* Offsets into our private area for storing information */
76 #define ccb_state	ppriv_field0
77 #define ccb_bio		ppriv_ptr1
78 
79 struct pt_softc {
80 	struct	 bio_queue_head bio_queue;
81 	struct	 devstat device_stats;
82 	LIST_HEAD(, ccb_hdr) pending_ccbs;
83 	pt_state state;
84 	pt_flags flags;
85 	union	 ccb saved_ccb;
86 	int	 io_timeout;
87 	cdev_t	 dev;
88 };
89 
90 static	d_open_t	ptopen;
91 static	d_close_t	ptclose;
92 static	d_strategy_t	ptstrategy;
93 static	periph_init_t	ptinit;
94 static	void		ptasync(void *callback_arg, u_int32_t code,
95 				struct cam_path *path, void *arg);
96 static	periph_ctor_t	ptctor;
97 static	periph_oninv_t	ptoninvalidate;
98 static	periph_dtor_t	ptdtor;
99 static	periph_start_t	ptstart;
100 static	void		ptdone(struct cam_periph *periph,
101 			       union ccb *done_ccb);
102 static	d_ioctl_t	ptioctl;
103 static  int		pterror(union ccb *ccb, u_int32_t cam_flags,
104 				u_int32_t sense_flags);
105 
106 void	scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
107 			  void (*cbfcnp)(struct cam_periph *, union ccb *),
108 			  u_int tag_action, int readop, u_int byte2,
109 			  u_int32_t xfer_len, u_int8_t *data_ptr,
110 			  u_int8_t sense_len, u_int32_t timeout);
111 
112 static struct periph_driver ptdriver =
113 {
114 	ptinit, "pt",
115 	TAILQ_HEAD_INITIALIZER(ptdriver.units), /* generation */ 0
116 };
117 
118 PERIPHDRIVER_DECLARE(pt, ptdriver);
119 
120 static struct dev_ops pt_ops = {
121 	{ "pt", 0, 0 },
122 	.d_open =	ptopen,
123 	.d_close =	ptclose,
124 	.d_read =	physread,
125 	.d_write =	physwrite,
126 	.d_ioctl =	ptioctl,
127 	.d_strategy =	ptstrategy,
128 };
129 
130 static struct extend_array *ptperiphs;
131 
132 #ifndef SCSI_PT_DEFAULT_TIMEOUT
133 #define SCSI_PT_DEFAULT_TIMEOUT		60
134 #endif
135 
136 static int
137 ptopen(struct dev_open_args *ap)
138 {
139 	cdev_t dev = ap->a_head.a_dev;
140 	struct cam_periph *periph;
141 	struct pt_softc *softc;
142 	int unit;
143 	int error = 0;
144 
145 	unit = minor(dev);
146 	periph = cam_extend_get(ptperiphs, unit);
147 	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
148 		return (ENXIO);
149 
150 	softc = (struct pt_softc *)periph->softc;
151 
152 	cam_periph_lock(periph);
153 	if (softc->flags & PT_FLAG_DEVICE_INVALID) {
154 		cam_periph_unlock(periph);
155 		cam_periph_release(periph);
156 		return(ENXIO);
157 	}
158 
159 	if ((softc->flags & PT_FLAG_OPEN) == 0)
160 		softc->flags |= PT_FLAG_OPEN;
161 	else {
162 		error = EBUSY;
163 		cam_periph_release(periph);
164 	}
165 
166 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
167 	    ("ptopen: dev=%s\n", devtoname(dev)));
168 
169 	cam_periph_unlock(periph);
170 	return (error);
171 }
172 
173 static int
174 ptclose(struct dev_close_args *ap)
175 {
176 	cdev_t dev = ap->a_head.a_dev;
177 	struct	cam_periph *periph;
178 	struct	pt_softc *softc;
179 	int	unit;
180 
181 	unit = minor(dev);
182 	periph = cam_extend_get(ptperiphs, unit);
183 	if (periph == NULL)
184 		return (ENXIO);
185 
186 	softc = (struct pt_softc *)periph->softc;
187 
188 	cam_periph_lock(periph);
189 
190 	softc->flags &= ~PT_FLAG_OPEN;
191 	cam_periph_unlock(periph);
192 	cam_periph_release(periph);
193 	return (0);
194 }
195 
196 /*
197  * Actually translate the requested transfer into one the physical driver
198  * can understand.  The transfer is described by a buf and will include
199  * only one physical transfer.
200  */
201 static int
202 ptstrategy(struct dev_strategy_args *ap)
203 {
204 	cdev_t dev = ap->a_head.a_dev;
205 	struct bio *bio = ap->a_bio;
206 	struct buf *bp = bio->bio_buf;
207 	struct cam_periph *periph;
208 	struct pt_softc *softc;
209 	u_int  unit;
210 
211 	unit = minor(dev);
212 	periph = cam_extend_get(ptperiphs, unit);
213 	if (periph == NULL) {
214 		bp->b_error = ENXIO;
215 		goto bad;
216 	}
217 	cam_periph_lock(periph);
218 	softc = (struct pt_softc *)periph->softc;
219 
220 	/*
221 	 * If the device has been made invalid, error out
222 	 */
223 	if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
224 		cam_periph_unlock(periph);
225 		bp->b_error = ENXIO;
226 		goto bad;
227 	}
228 
229 	/*
230 	 * Place it in the queue of disk activities for this disk
231 	 */
232 	bioq_insert_tail(&softc->bio_queue, bio);
233 
234 	/*
235 	 * Schedule ourselves for performing the work.
236 	 */
237 	xpt_schedule(periph, /* XXX priority */1);
238 	cam_periph_unlock(periph);
239 
240 	return(0);
241 bad:
242 	bp->b_flags |= B_ERROR;
243 
244 	/*
245 	 * Correctly set the buf to indicate a completed xfer
246 	 */
247 	bp->b_resid = bp->b_bcount;
248 	biodone(bio);
249 	return(0);
250 }
251 
252 static void
253 ptinit(void)
254 {
255 	cam_status status;
256 
257 	/*
258 	 * Create our extend array for storing the devices we attach to.
259 	 */
260 	ptperiphs = cam_extend_new();
261 	if (ptperiphs == NULL) {
262 		kprintf("pt: Failed to alloc extend array!\n");
263 		return;
264 	}
265 
266 	/*
267 	 * Install a global async callback.  This callback will
268 	 * receive async callbacks like "new device found".
269 	 */
270 	status = xpt_register_async(AC_FOUND_DEVICE, ptasync, NULL, NULL);
271 
272 	if (status != CAM_REQ_CMP) {
273 		kprintf("pt: Failed to attach master async callback "
274 		       "due to status 0x%x!\n", status);
275 	}
276 }
277 
278 static cam_status
279 ptctor(struct cam_periph *periph, void *arg)
280 {
281 	struct pt_softc *softc;
282 	struct ccb_getdev *cgd;
283 
284 	cgd = (struct ccb_getdev *)arg;
285 	if (periph == NULL) {
286 		kprintf("ptregister: periph was NULL!!\n");
287 		return(CAM_REQ_CMP_ERR);
288 	}
289 
290 	if (cgd == NULL) {
291 		kprintf("ptregister: no getdev CCB, can't register device\n");
292 		return(CAM_REQ_CMP_ERR);
293 	}
294 
295 	softc = kmalloc(sizeof(*softc), M_DEVBUF, M_INTWAIT | M_ZERO);
296 	LIST_INIT(&softc->pending_ccbs);
297 	softc->state = PT_STATE_NORMAL;
298 	bioq_init(&softc->bio_queue);
299 
300 	softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;
301 
302 	periph->softc = softc;
303 
304 	cam_periph_unlock(periph);
305 	cam_extend_set(ptperiphs, periph->unit_number, periph);
306 
307 	devstat_add_entry(&softc->device_stats, "pt",
308 			  periph->unit_number, 0,
309 			  DEVSTAT_NO_BLOCKSIZE,
310 			  SID_TYPE(&cgd->inq_data) | DEVSTAT_TYPE_IF_SCSI,
311 			  DEVSTAT_PRIORITY_OTHER);
312 
313 	make_dev(&pt_ops, periph->unit_number, UID_ROOT,
314 		  GID_OPERATOR, 0600, "%s%d", periph->periph_name,
315 		  periph->unit_number);
316 	cam_periph_lock(periph);
317 	/*
318 	 * Add async callbacks for bus reset and
319 	 * bus device reset calls.  I don't bother
320 	 * checking if this fails as, in most cases,
321 	 * the system will function just fine without
322 	 * them and the only alternative would be to
323 	 * not attach the device on failure.
324 	 */
325 	xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
326 			   ptasync, periph, periph->path);
327 
328 	/* Tell the user we've attached to the device */
329 	xpt_announce_periph(periph, NULL);
330 
331 	return(CAM_REQ_CMP);
332 }
333 
334 static void
335 ptoninvalidate(struct cam_periph *periph)
336 {
337 	struct pt_softc *softc;
338 	struct bio *q_bio;
339 	struct buf *q_bp;
340 
341 	softc = (struct pt_softc *)periph->softc;
342 
343 	/*
344 	 * De-register any async callbacks.
345 	 */
346 	xpt_register_async(0, ptasync, periph, periph->path);
347 
348 	softc->flags |= PT_FLAG_DEVICE_INVALID;
349 
350 	/*
351 	 * Return all queued I/O with ENXIO.
352 	 * XXX Handle any transactions queued to the card
353 	 *     with XPT_ABORT_CCB.
354 	 */
355 	while ((q_bio = bioq_takefirst(&softc->bio_queue)) != NULL) {
356 		q_bp = q_bio->bio_buf;
357 		q_bp->b_resid = q_bp->b_bcount;
358 		q_bp->b_error = ENXIO;
359 		q_bp->b_flags |= B_ERROR;
360 		biodone(q_bio);
361 	}
362 
363 	xpt_print(periph->path, "lost device\n");
364 }
365 
366 static void
367 ptdtor(struct cam_periph *periph)
368 {
369 	struct pt_softc *softc;
370 
371 	softc = (struct pt_softc *)periph->softc;
372 
373 	devstat_remove_entry(&softc->device_stats);
374 
375 	cam_extend_release(ptperiphs, periph->unit_number);
376 	xpt_print(periph->path, "removing device entry\n");
377 	dev_ops_remove_minor(&pt_ops, periph->unit_number);
378 	kfree(softc, M_DEVBUF);
379 }
380 
381 static void
382 ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
383 {
384 	struct cam_periph *periph;
385 
386 	periph = (struct cam_periph *)callback_arg;
387 	switch (code) {
388 	case AC_FOUND_DEVICE:
389 	{
390 		struct ccb_getdev *cgd;
391 		cam_status status;
392 
393 		cgd = (struct ccb_getdev *)arg;
394 		if (cgd == NULL)
395 			break;
396 
397 		if (SID_TYPE(&cgd->inq_data) != T_PROCESSOR)
398 			break;
399 
400 		/*
401 		 * Allocate a peripheral instance for
402 		 * this device and start the probe
403 		 * process.
404 		 */
405 		status = cam_periph_alloc(ptctor, ptoninvalidate, ptdtor,
406 					  ptstart, "pt", CAM_PERIPH_BIO,
407 					  cgd->ccb_h.path, ptasync,
408 					  AC_FOUND_DEVICE, cgd);
409 
410 		if (status != CAM_REQ_CMP
411 		 && status != CAM_REQ_INPROG)
412 			kprintf("ptasync: Unable to attach to new device "
413 				"due to status 0x%x\n", status);
414 		break;
415 	}
416 	case AC_SENT_BDR:
417 	case AC_BUS_RESET:
418 	{
419 		struct pt_softc *softc;
420 		struct ccb_hdr *ccbh;
421 
422 		softc = (struct pt_softc *)periph->softc;
423 		/*
424 		 * Don't fail on the expected unit attention
425 		 * that will occur.
426 		 */
427 		softc->flags |= PT_FLAG_RETRY_UA;
428 		LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
429 			ccbh->ccb_state |= PT_CCB_RETRY_UA;
430 		/* FALLTHROUGH */
431 	}
432 	default:
433 		cam_periph_async(periph, code, path, arg);
434 		break;
435 	}
436 }
437 
438 static void
439 ptstart(struct cam_periph *periph, union ccb *start_ccb)
440 {
441 	struct pt_softc *softc;
442 	struct buf *bp;
443 	struct bio *bio;
444 
445 	softc = (struct pt_softc *)periph->softc;
446 
447 	/*
448 	 * See if there is a buf with work for us to do..
449 	 */
450 	bio = bioq_first(&softc->bio_queue);
451 	if (periph->immediate_priority <= periph->pinfo.priority) {
452 		CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
453 				("queuing for immediate ccb\n"));
454 		start_ccb->ccb_h.ccb_state = PT_CCB_WAITING;
455 		SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
456 				  periph_links.sle);
457 		periph->immediate_priority = CAM_PRIORITY_NONE;
458 		wakeup(&periph->ccb_list);
459 	} else if (bio == NULL) {
460 		xpt_release_ccb(start_ccb);
461 	} else {
462 		bioq_remove(&softc->bio_queue, bio);
463 		bp = bio->bio_buf;
464 
465 		devstat_start_transaction(&softc->device_stats);
466 
467 		scsi_send_receive(&start_ccb->csio,
468 				  /*retries*/4,
469 				  ptdone,
470 				  MSG_SIMPLE_Q_TAG,
471 				  (bp->b_cmd == BUF_CMD_READ),
472 				  /*byte2*/0,
473 				  bp->b_bcount,
474 				  bp->b_data,
475 				  /*sense_len*/SSD_FULL_SIZE,
476 				  /*timeout*/softc->io_timeout);
477 
478 		start_ccb->ccb_h.ccb_state = PT_CCB_BUFFER_IO_UA;
479 
480 		/*
481 		 * Block out any asyncronous callbacks
482 		 * while we touch the pending ccb list.
483 		 */
484 		LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h,
485 				 periph_links.le);
486 
487 		start_ccb->ccb_h.ccb_bio = bio;
488 		bio = bioq_first(&softc->bio_queue);
489 
490 		xpt_action(start_ccb);
491 
492 		if (bio != NULL) {
493 			/* Have more work to do, so ensure we stay scheduled */
494 			xpt_schedule(periph, /* XXX priority */1);
495 		}
496 	}
497 }
498 
499 static void
500 ptdone(struct cam_periph *periph, union ccb *done_ccb)
501 {
502 	struct pt_softc *softc;
503 	struct ccb_scsiio *csio;
504 
505 	softc = (struct pt_softc *)periph->softc;
506 	csio = &done_ccb->csio;
507 	switch (csio->ccb_h.ccb_state) {
508 	case PT_CCB_BUFFER_IO:
509 	case PT_CCB_BUFFER_IO_UA:
510 	{
511 		struct buf *bp;
512 		struct bio *bio;
513 
514 		bio = (struct bio *)done_ccb->ccb_h.ccb_bio;
515 		bp = bio->bio_buf;
516 
517 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
518 			int error;
519 			int sf;
520 
521 			if ((csio->ccb_h.ccb_state & PT_CCB_RETRY_UA) != 0)
522 				sf = SF_RETRY_UA;
523 			else
524 				sf = 0;
525 
526 			error = pterror(done_ccb, CAM_RETRY_SELTO, sf);
527 			if (error == ERESTART) {
528 				/*
529 				 * A retry was scheuled, so
530 				 * just return.
531 				 */
532 				return;
533 			}
534 			if (error != 0) {
535 				struct buf *q_bp;
536 				struct bio *q_bio;
537 
538 				if (error == ENXIO) {
539 					/*
540 					 * Catastrophic error.  Mark our device
541 					 * as invalid.
542 					 */
543 					xpt_print(periph->path,
544 					    "Invalidating device\n");
545 					softc->flags |= PT_FLAG_DEVICE_INVALID;
546 				}
547 
548 				/*
549 				 * return all queued I/O with EIO, so that
550 				 * the client can retry these I/Os in the
551 				 * proper order should it attempt to recover.
552 				 */
553 				while ((q_bio = bioq_takefirst(&softc->bio_queue)) != NULL) {
554 					q_bp = q_bio->bio_buf;
555 					q_bp->b_resid = q_bp->b_bcount;
556 					q_bp->b_error = EIO;
557 					q_bp->b_flags |= B_ERROR;
558 					biodone(q_bio);
559 				}
560 				bp->b_error = error;
561 				bp->b_resid = bp->b_bcount;
562 				bp->b_flags |= B_ERROR;
563 			} else {
564 				bp->b_resid = csio->resid;
565 				bp->b_error = 0;
566 				if (bp->b_resid != 0) {
567 					/* Short transfer ??? */
568 					bp->b_flags |= B_ERROR;
569 				}
570 			}
571 			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
572 				cam_release_devq(done_ccb->ccb_h.path,
573 						 /*relsim_flags*/0,
574 						 /*reduction*/0,
575 						 /*timeout*/0,
576 						 /*getcount_only*/0);
577 		} else {
578 			bp->b_resid = csio->resid;
579 			if (bp->b_resid != 0)
580 				bp->b_flags |= B_ERROR;
581 		}
582 
583 		/*
584 		 * Block out any asyncronous callbacks
585 		 * while we touch the pending ccb list.
586 		 */
587 		LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
588 
589 		devstat_end_transaction_buf(&softc->device_stats, bp);
590 		biodone(bio);
591 		break;
592 	}
593 	case PT_CCB_WAITING:
594 		/* Caller will release the CCB */
595 		wakeup(&done_ccb->ccb_h.cbfcnp);
596 		return;
597 	}
598 	xpt_release_ccb(done_ccb);
599 }
600 
601 static int
602 pterror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
603 {
604 	struct pt_softc	  *softc;
605 	struct cam_periph *periph;
606 
607 	periph = xpt_path_periph(ccb->ccb_h.path);
608 	softc = (struct pt_softc *)periph->softc;
609 
610 	return(cam_periph_error(ccb, cam_flags, sense_flags,
611 				&softc->saved_ccb));
612 }
613 
614 static int
615 ptioctl(struct dev_ioctl_args *ap)
616 {
617 	cdev_t dev = ap->a_head.a_dev;
618 	caddr_t addr = ap->a_data;
619 	struct cam_periph *periph;
620 	struct pt_softc *softc;
621 	int unit;
622 	int error = 0;
623 
624 	unit = minor(dev);
625 	periph = cam_extend_get(ptperiphs, unit);
626 
627 	if (periph == NULL)
628 		return(ENXIO);
629 
630 	softc = (struct pt_softc *)periph->softc;
631 
632 	cam_periph_lock(periph);
633 
634 	switch(ap->a_cmd) {
635 	case PTIOCGETTIMEOUT:
636 		if (softc->io_timeout >= 1000)
637 			*(int *)addr = softc->io_timeout / 1000;
638 		else
639 			*(int *)addr = 0;
640 		break;
641 	case PTIOCSETTIMEOUT:
642 		if (*(int *)addr < 1) {
643 			error = EINVAL;
644 			break;
645 		}
646 
647 		softc->io_timeout = *(int *)addr * 1000;
648 
649 		break;
650 	default:
651 		error = cam_periph_ioctl(periph, ap->a_cmd, addr, pterror);
652 		break;
653 	}
654 
655 	cam_periph_unlock(periph);
656 
657 	return(error);
658 }
659 
660 void
661 scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
662 		  void (*cbfcnp)(struct cam_periph *, union ccb *),
663 		  u_int tag_action, int readop, u_int byte2,
664 		  u_int32_t xfer_len, u_int8_t *data_ptr, u_int8_t sense_len,
665 		  u_int32_t timeout)
666 {
667 	struct scsi_send_receive *scsi_cmd;
668 
669 	scsi_cmd = (struct scsi_send_receive *)&csio->cdb_io.cdb_bytes;
670 	scsi_cmd->opcode = readop ? RECEIVE : SEND;
671 	scsi_cmd->byte2 = byte2;
672 	scsi_ulto3b(xfer_len, scsi_cmd->xfer_len);
673 	scsi_cmd->control = 0;
674 
675 	cam_fill_csio(csio,
676 		      retries,
677 		      cbfcnp,
678 		      /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
679 		      tag_action,
680 		      data_ptr,
681 		      xfer_len,
682 		      sense_len,
683 		      sizeof(*scsi_cmd),
684 		      timeout);
685 }
686