/* * 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); }
/* * 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; }