Esempio n. 1
0
/*
 * Read/write routine for a buffer.  Finds the proper unit, range checks
 * arguments, and schedules the transfer.  Does not wait for the transfer
 * to complete.  Multi-page transfers are supported.  All I/O requests must
 * be a multiple of a sector in length.
 */
static int
idad_strategy(struct dev_strategy_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct bio *bio = ap->a_bio;
	struct buf *bp = bio->bio_buf;
	struct idad_softc *drv;

	drv = idad_getsoftc(dev);
	if (drv == NULL) {
    		bp->b_error = EINVAL;
		goto bad;
	}

	/*
	 * software write protect check
	 */
	if ((drv->flags & DRV_WRITEPROT) && bp->b_cmd != BUF_CMD_READ) {
		bp->b_error = EROFS;
		goto bad;
	}

	/*
	 * If it's a null transfer, return immediately
	 */
	if (bp->b_bcount == 0)
		goto done;

	bio->bio_driver_info = drv;
	crit_enter();
	devstat_start_transaction(&drv->stats);
	ida_submit_buf(drv->controller, bio);
	crit_exit();
	return(0);

bad:
	bp->b_flags |= B_ERROR;

done:
	/*
	 * Correctly set the buf to indicate a completed transfer
	 */
	bp->b_resid = bp->b_bcount;
	biodone(bio);
	return(0);
}
Esempio n. 2
0
/*
 * Read/write routine for a buffer.  Finds the proper unit, range checks
 * arguments, and schedules the transfer.  Does not wait for the transfer
 * to complete.  Multi-page transfers are supported.  All I/O requests must
 * be a multiple of a sector in length.
 */
static void
idad_strategy(struct bio *bp)
{
	struct idad_softc *drv;
	int s;

	drv = bp->bio_disk->d_drv1;
	if (drv == NULL) {
    		bp->bio_error = EINVAL;
		goto bad;
	}

	/*
	 * software write protect check
	 */
	if (drv->flags & DRV_WRITEPROT && (bp->bio_cmd == BIO_WRITE)) {
		bp->bio_error = EROFS;
		goto bad;
	}

	bp->bio_driver1 = drv;
	s = splbio();
	ida_submit_buf(drv->controller, bp);
	splx(s);
	return;

bad:
	bp->bio_flags |= BIO_ERROR;

	/*
	 * Correctly set the buf to indicate a completed transfer
	 */
	bp->bio_resid = bp->bio_bcount;
	biodone(bp);
	return;
}