+/*ARGSUSED*/
+htioctl(dev, cmd, addr, flag)
+ dev_t dev;
+ int cmd;
+ caddr_t addr;
+ int flag;
+{
+ register unit = HTUNIT(dev);
+ register struct ht_softc *sc = &ht_softc[unit];
+ register struct buf *bp = &chtbuf[unit];
+ register callcount;
+ int fcount;
+ struct mtop mtop;
+ struct mtget mtget;
+ /* we depend of the values and order of the MT codes here */
+ static htops[] =
+ {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE};
+
+ switch (cmd) {
+ case MTIOCTOP: /* tape operation */
+ if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
+ u.u_error = EFAULT;
+ return;
+ }
+ switch(mtop.mt_op) {
+ case MTWEOF:
+ callcount = mtop.mt_count;
+ fcount = 1;
+ break;
+ case MTFSF: case MTBSF:
+ callcount = mtop.mt_count;
+ fcount = INF;
+ break;
+ case MTFSR: case MTBSR:
+ callcount = 1;
+ fcount = mtop.mt_count;
+ break;
+ case MTREW: case MTOFFL:
+ callcount = 1;
+ fcount = 1;
+ break;
+ default:
+ u.u_error = ENXIO;
+ return;
+ }
+ if (callcount <= 0 || fcount <= 0) {
+ u.u_error = ENXIO;
+ return;
+ }
+ while (--callcount >= 0) {
+ htcommand(dev, htops[mtop.mt_op], fcount);
+ if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
+ bp->b_resid) {
+ u.u_error = EIO;
+ break;
+ }
+ if ((chtbuf[HTUNIT(bp->b_dev)].b_flags&B_ERROR) ||
+ sc->sc_dsreg&HTDS_BOT)
+ break;
+ }
+ geterror(bp);
+ return;
+ case MTIOCGET:
+ mtget.mt_dsreg = sc->sc_dsreg;
+ mtget.mt_erreg = sc->sc_erreg;
+ mtget.mt_resid = sc->sc_resid;
+ if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
+ u.u_error = EFAULT;
+ return;
+ default:
+ u.u_error = ENXIO;
+ }
+}