diff options
author | mjacob <mjacob@FreeBSD.org> | 1998-12-18 04:31:43 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 1998-12-18 04:31:43 +0000 |
commit | 6662c8e53a9bf2d60e01f0aba6d8be62e4747254 (patch) | |
tree | f72da62fbb410fa5374f4c7833a4d8145746aef1 /sys/cam/scsi | |
parent | 50ba4cd74d88be9e7914c1e5cddbdceaa0c11163 (diff) | |
download | FreeBSD-src-6662c8e53a9bf2d60e01f0aba6d8be62e4747254.zip FreeBSD-src-6662c8e53a9bf2d60e01f0aba6d8be62e4747254.tar.gz |
Add in block position/block locate functions.
Diffstat (limited to 'sys/cam/scsi')
-rw-r--r-- | sys/cam/scsi/scsi_sa.c | 162 |
1 files changed, 141 insertions, 21 deletions
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c index fedbdc2..a8d6de4 100644 --- a/sys/cam/scsi/scsi_sa.c +++ b/sys/cam/scsi/scsi_sa.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: scsi_sa.c,v 1.7 1998/12/11 07:19:36 mjacob Exp $ + * $Id: scsi_sa.c,v 1.8 1998/12/17 18:56:23 mjacob Exp $ */ #include <sys/param.h> @@ -218,6 +218,9 @@ static int saloadunload(struct cam_periph *periph, int load); static int saerase(struct cam_periph *periph, int longerase); static int sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks); +static int sardpos(struct cam_periph *periph, int, u_int32_t *); +static int sasetpos(struct cam_periph *periph, int, u_int32_t *); + static struct periph_driver sadriver = { @@ -792,6 +795,18 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) case MTIOCEEOT: error = 0; break; + case MTIOCRDSPOS: + error = sardpos(periph, 0, (u_int32_t *) arg); + break; + case MTIOCRDHPOS: + error = sardpos(periph, 1, (u_int32_t *) arg); + break; + case MTIOCSLOCATE: + error = sasetpos(periph, 0, (u_int32_t *) arg); + break; + case MTIOCHLOCATE: + error = sasetpos(periph, 1, (u_int32_t *) arg); + break; default: error = cam_periph_ioctl(periph, cmd, arg, saerror); break; @@ -2274,41 +2289,105 @@ sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks) ccb = cam_periph_getccb(periph, /*priority*/1); - scsi_write_filemarks(&ccb->csio, - /*retries*/1, - /*cbcfp*/sadone, - MSG_SIMPLE_Q_TAG, - /*immediate*/FALSE, - setmarks, - nmarks, - SSD_FULL_SIZE, - 60000); + scsi_write_filemarks(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, + FALSE, setmarks, nmarks, SSD_FULL_SIZE, 60000); - error = cam_periph_runccb(ccb, saerror, /*cam_flags*/0, - /*sense_flags*/0, &softc->device_stats); + error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) - cam_release_devq(ccb->ccb_h.path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); + cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); /* * XXXX: Actually, we need to get back the actual number of filemarks * XXXX: written (there can be a residual). */ - if (error == 0) { - struct sa_softc *softc; - - softc = (struct sa_softc *)periph->softc; + if (error == 0 && nmarks) { + struct sa_softc *softc = (struct sa_softc *)periph->softc; softc->filemarks += nmarks; } + xpt_release_ccb(ccb); + return (error); +} +static int +sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) +{ + struct scsi_tape_position_data loc; + union ccb *ccb; + struct sa_softc *softc; + int error; + + /* + * First flush any pending writes... + */ + error = sawritefilemarks(periph, 0, 0); + + /* + * The latter case is for 'write protected' tapes + * which are too stupid to recognize a zero count + * for writing filemarks as a no-op. + */ + if (error != 0 && error != EACCES) + return (error); + + softc = (struct sa_softc *)periph->softc; + ccb = cam_periph_getccb(periph, /*priority*/1); + + scsi_read_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, + hard, &loc, SSD_FULL_SIZE, 5000); + error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); + + if (error == 0) { + if (loc.flags & SA_RPOS_UNCERTAIN) { + error = EINVAL; /* nothing is certain */ + } else { + *blkptr = scsi_4btoul(loc.firstblk); + } + } + + xpt_release_ccb(ccb); + return (error); +} + +static int +sasetpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) +{ + union ccb *ccb; + struct sa_softc *softc; + int error; + + /* + * First flush any pending writes... + */ + error = sawritefilemarks(periph, 0, 0); + + /* + * The latter case is for 'write protected' tapes + * which are too stupid to recognize a zero count + * for writing filemarks as a no-op. + */ + if (error != 0 && error != EACCES) + return (error); + + softc = (struct sa_softc *)periph->softc; + ccb = cam_periph_getccb(periph, /*priority*/1); + + scsi_set_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, + hard, *blkptr, SSD_FULL_SIZE, 60 * 60 * 1000); + error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); xpt_release_ccb(ccb); + /* + * XXX: Note relative file && block number position now unknown (if + * XXX: these things ever start being maintained in this driver). + */ return (error); } + static int saretension(struct cam_periph *periph) { @@ -2712,3 +2791,44 @@ scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, sizeof(*scsi_cmd), timeout); } + +/* + * Read Tape Position command. + */ +void +scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, int hardsoft, + struct scsi_tape_position_data *sbp, + u_int8_t sense_len, u_int32_t timeout) +{ + struct scsi_tape_read_position *scmd; + + cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, + (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout); + scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes; + bzero(scmd, sizeof(*scmd)); + scmd->opcode = READ_POSITION; + scmd->byte1 = hardsoft; +} + +/* + * Set Tape Position command. + */ +void +scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, int hardsoft, u_int32_t blkno, + u_int8_t sense_len, u_int32_t timeout) +{ + struct scsi_tape_locate *scmd; + + cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, + (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout); + scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes; + bzero(scmd, sizeof(*scmd)); + scmd->opcode = LOCATE; + if (hardsoft) + scmd->byte1 |= SA_SPOS_BT; + scsi_ulto4b(blkno, scmd->blkaddr); +} |