FreeBSD/sys/cam/scsi/scsi_sa.c
/*
 * Actually translate the requested transfer into one the physical driver
 * can understand.  The transfer is described by a buf and will include
 * only one physical transfer.
 */
Actually translate the requested transfer into one the physical driver
can understand.  The transfer is described by a buf and will include
only one physical transfer.
Actually translate the requested transfer into one the physical driver can understand . The transfer is described by a buf and will include only one physical transfer .
static void
sastrategy(struct bio *bp)
{
	struct cam_periph *periph;
	struct sa_softc *softc;
	bp->bio_resid = bp->bio_bcount;
	if (SA_IS_CTRL(bp->bio_dev)) {
		biofinish(bp, NULL, EINVAL);
		return;
	}
	periph = (struct cam_periph *)bp->bio_dev->si_drv1;
	cam_periph_lock(periph);
	softc = (struct sa_softc *)periph->softc;
	if (softc->flags & SA_FLAG_INVALID) {
		cam_periph_unlock(periph);
		biofinish(bp, NULL, ENXIO);
		return;
	}
	if (softc->flags & SA_FLAG_TAPE_FROZEN) {
		cam_periph_unlock(periph);
		biofinish(bp, NULL, EPERM);
		return;
	}
	if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
		cam_periph_unlock(periph);
		biofinish(bp, NULL, EBADF);
		return;
	}
	if (softc->open_pending_mount) {
		int error = samount(periph, 0, bp->bio_dev);
		if (error) {
			cam_periph_unlock(periph);
			biofinish(bp, NULL, ENXIO);
			return;
		}
		saprevent(periph, PR_PREVENT);
		softc->open_pending_mount = 0;
	}
	if (bp->bio_bcount == 0) {
		cam_periph_unlock(periph);
		biodone(bp);
		return;
	}
	if (softc->flags & SA_FLAG_FIXED) {
		if (((softc->blk_mask != ~0) &&
		    ((bp->bio_bcount & softc->blk_mask) != 0)) ||
		    ((softc->blk_mask == ~0) &&
		    ((bp->bio_bcount % softc->min_blk) != 0))) {
			xpt_print(periph->path, "Invalid request.  Fixed block "
			    "device requests must be a multiple of %d bytes\n",
			    softc->min_blk);
			cam_periph_unlock(periph);
			biofinish(bp, NULL, EINVAL);
			return;
		}
	} else if ((bp->bio_bcount > softc->max_blk) ||
		   (bp->bio_bcount < softc->min_blk) ||
		   (bp->bio_bcount & softc->blk_mask) != 0) {
		xpt_print_path(periph->path);
		printf("Invalid request.  Variable block "
		    "device requests must be ");
		if (softc->blk_mask != 0) {
			printf("a multiple of %d ", (0x1 << softc->blk_gran));
		}
		printf("between %d and %d bytes\n", softc->min_blk,
		    softc->max_blk);
		cam_periph_unlock(periph);
		biofinish(bp, NULL, EINVAL);
		return;
        }
	bioq_insert_tail(&softc->bio_queue, bp);
	softc->queue_count++;
#if	0
	CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
	    ("sastrategy: queuing a %ld %s byte %s\n", bp->bio_bcount,
 	    (softc->flags & SA_FLAG_FIXED)?  "fixed" : "variable",
	    (bp->bio_cmd == BIO_READ)? "read" : "write"));
#endif
	if (softc->queue_count > 1) {
		CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
		    ("sastrategy: queue count now %d\n", softc->queue_count));
	}
	xpt_schedule(periph, CAM_PRIORITY_NORMAL);
	cam_periph_unlock(periph);
	return;
}
static void sastrategy ( struct bio * bp ) { struct cam_periph * periph ; struct sa_softc * softc ; bp -> bio_resid = bp -> bio_bcount ; if ( SA_IS_CTRL ( bp -> bio_dev ) ) { biofinish ( bp , NULL , EINVAL ) ; return ; } periph = ( struct cam_periph * ) bp -> bio_dev -> si_drv1 ; cam_periph_lock ( periph ) ; softc = ( struct sa_softc * ) periph -> softc ; if ( softc -> flags & SA_FLAG_INVALID ) { cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , ENXIO ) ; return ; } if ( softc -> flags & SA_FLAG_TAPE_FROZEN ) { cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , EPERM ) ; return ; } if ( bp -> bio_cmd == BIO_WRITE && softc -> open_rdonly ) { cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , EBADF ) ; return ; } if ( softc -> open_pending_mount ) { int error = samount ( periph , 0 , bp -> bio_dev ) ; if ( error ) { cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , ENXIO ) ; return ; } saprevent ( periph , PR_PREVENT ) ; softc -> open_pending_mount = 0 ; } if ( bp -> bio_bcount == 0 ) { cam_periph_unlock ( periph ) ; biodone ( bp ) ; return ; } if ( softc -> flags & SA_FLAG_FIXED ) { if ( ( ( softc -> blk_mask != ~ 0 ) && ( ( bp -> bio_bcount & softc -> blk_mask ) != 0 ) ) || ( ( softc -> blk_mask == ~ 0 ) && ( ( bp -> bio_bcount % softc -> min_blk ) != 0 ) ) ) { xpt_print ( periph -> path , " " " \n " , softc -> min_blk ) ; cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , EINVAL ) ; return ; } } else if ( ( bp -> bio_bcount > softc -> max_blk ) || ( bp -> bio_bcount < softc -> min_blk ) || ( bp -> bio_bcount & softc -> blk_mask ) != 0 ) { xpt_print_path ( periph -> path ) ; printf ( " " " " ) ; if ( softc -> blk_mask != 0 ) { printf ( " " , ( 0x1 << softc -> blk_gran ) ) ; } printf ( " \n " , softc -> min_blk , softc -> max_blk ) ; cam_periph_unlock ( periph ) ; biofinish ( bp , NULL , EINVAL ) ; return ; } bioq_insert_tail ( & softc -> bio_queue , bp ) ; softc -> queue_count ++ ; #if 0 CAM_DEBUG ( periph -> path , CAM_DEBUG_INFO , ( " \n " , bp -> bio_bcount , ( softc -> flags & SA_FLAG_FIXED ) ? " " : " " , ( bp -> bio_cmd == BIO_READ ) ? " " : " " ) ) ; #endif if ( softc -> queue_count > 1 ) { CAM_DEBUG ( periph -> path , CAM_DEBUG_INFO , ( " \n " , softc -> queue_count ) ) ; } xpt_schedule ( periph , CAM_PRIORITY_NORMAL ) ; cam_periph_unlock ( periph ) ; return ; }
Actually translate the requested transfer into one the physical driver
 can understand.
Actually translate the requested transfer into one the physical driver can understand .
/*
	 * This should actually never occur as the write(2)
	 * system call traps attempts to write to a read-only
	 * file descriptor.
	 */ /*
	 * If it's a null transfer, return immediately
	 */ /* valid request?  */ /*
		 * Fixed block device.  The byte count must
		 * be a multiple of our block size.
		 */ /*
	 * Place it at the end of the queue.
	 */ /*
	 * Schedule ourselves for performing the work.
	 */