Home | History | Annotate | Line # | Download | only in mscp
mscp_tape.c revision 1.43
      1  1.43  dholland /*	$NetBSD: mscp_tape.c,v 1.43 2014/07/25 08:10:37 dholland Exp $ */
      2   1.1     ragge /*
      3   1.1     ragge  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
      4   1.1     ragge  * All rights reserved.
      5   1.1     ragge  *
      6   1.1     ragge  * Redistribution and use in source and binary forms, with or without
      7   1.1     ragge  * modification, are permitted provided that the following conditions
      8   1.1     ragge  * are met:
      9   1.1     ragge  * 1. Redistributions of source code must retain the above copyright
     10   1.1     ragge  *    notice, this list of conditions and the following disclaimer.
     11   1.1     ragge  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1     ragge  *    notice, this list of conditions and the following disclaimer in the
     13   1.1     ragge  *    documentation and/or other materials provided with the distribution.
     14   1.1     ragge  * 3. All advertising materials mentioning features or use of this software
     15   1.1     ragge  *    must display the following acknowledgement:
     16  1.24     perry  *	This product includes software developed at Ludd, University of
     17   1.9     ragge  *	Lule}, Sweden and its contributors.
     18   1.1     ragge  * 4. The name of the author may not be used to endorse or promote products
     19   1.1     ragge  *    derived from this software without specific prior written permission
     20   1.1     ragge  *
     21   1.1     ragge  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1     ragge  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23   1.1     ragge  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24   1.1     ragge  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25   1.1     ragge  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26   1.1     ragge  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27   1.1     ragge  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28   1.1     ragge  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29   1.1     ragge  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30   1.1     ragge  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31   1.1     ragge  */
     32   1.1     ragge 
     33   1.1     ragge 
     34   1.1     ragge /*
     35   1.1     ragge  * MSCP tape device driver
     36   1.1     ragge  */
     37   1.1     ragge 
     38   1.1     ragge /*
     39   1.1     ragge  * TODO
     40   1.1     ragge  *	Write status handling code.
     41   1.1     ragge  */
     42  1.16     lukem 
     43  1.16     lukem #include <sys/cdefs.h>
     44  1.43  dholland __KERNEL_RCSID(0, "$NetBSD: mscp_tape.c,v 1.43 2014/07/25 08:10:37 dholland Exp $");
     45   1.1     ragge 
     46   1.1     ragge #include <sys/param.h>
     47   1.1     ragge #include <sys/device.h>
     48   1.1     ragge #include <sys/kernel.h>
     49   1.1     ragge #include <sys/buf.h>
     50  1.22        he #include <sys/bufq.h>
     51   1.1     ragge #include <sys/ioccom.h>
     52   1.1     ragge #include <sys/mtio.h>
     53   1.1     ragge #include <sys/fcntl.h>
     54   1.1     ragge #include <sys/malloc.h>
     55   1.1     ragge #include <sys/systm.h>
     56   1.1     ragge #include <sys/proc.h>
     57  1.17   gehenna #include <sys/conf.h>
     58   1.1     ragge 
     59  1.32        ad #include <sys/bus.h>
     60  1.32        ad #include <sys/cpu.h>
     61  1.10     ragge 
     62  1.14     ragge #include <dev/mscp/mscp.h>
     63  1.14     ragge #include <dev/mscp/mscpreg.h>
     64  1.14     ragge #include <dev/mscp/mscpvar.h>
     65   1.1     ragge 
     66   1.6       jtk #include "locators.h"
     67   1.6       jtk 
     68   1.1     ragge /*
     69   1.1     ragge  * Drive status, per drive
     70   1.1     ragge  */
     71   1.1     ragge struct mt_softc {
     72  1.39       chs 	device_t mt_dev;	/* Autoconf struct */
     73   1.1     ragge 	int	mt_state;	/* open/closed state */
     74   1.1     ragge 	int	mt_hwunit;	/* Hardware unit number */
     75   1.1     ragge 	int	mt_inuse;	/* Locks the tape drive for others */
     76   1.1     ragge 	int	mt_waswrite;	/* Last operation was a write op */
     77   1.1     ragge 	int	mt_serex;	/* Got serious exception */
     78   1.5     ragge 	int	mt_ioctlerr;	/* Error after last ioctl */
     79   1.1     ragge };
     80   1.1     ragge 
     81   1.9     ragge #define MT_OFFLINE	0
     82   1.9     ragge #define MT_ONLINE	1
     83   1.1     ragge 
     84  1.38    cegger int	mtmatch(device_t, cfdata_t, void *);
     85  1.38    cegger void	mtattach(device_t, device_t, void *);
     86  1.38    cegger void	mtdgram(device_t, struct mscp *, struct mscp_softc *);
     87  1.38    cegger void	mtiodone(device_t, struct buf *);
     88  1.38    cegger int	mtonline(device_t, struct mscp *);
     89  1.38    cegger int	mtgotstatus(device_t, struct mscp *);
     90  1.38    cegger int	mtioerror(device_t, struct mscp *, struct buf *);
     91  1.23     perry void	mtfillin(struct buf *, struct mscp *);
     92  1.23     perry int	mtcmd(struct mt_softc *, int, int, int);
     93  1.38    cegger void	mtcmddone(device_t, struct mscp *);
     94  1.23     perry int	mt_putonline(struct mt_softc *);
     95   1.1     ragge 
     96   1.1     ragge struct	mscp_device mt_device = {
     97   1.1     ragge 	mtdgram,
     98   1.1     ragge 	mtiodone,
     99   1.1     ragge 	mtonline,
    100   1.1     ragge 	mtgotstatus,
    101   1.1     ragge 	0,
    102   1.1     ragge 	mtioerror,
    103   1.1     ragge 	0,
    104   1.1     ragge 	mtfillin,
    105   1.1     ragge 	mtcmddone,
    106   1.1     ragge };
    107   1.1     ragge 
    108   1.1     ragge /* This is not good, should allow more than 4 tapes/device type */
    109   1.9     ragge #define mtunit(dev)	(minor(dev) & T_UNIT)
    110   1.9     ragge #define mtnorewind(dev) (dev & T_NOREWIND)
    111   1.9     ragge #define mthdensity(dev) (dev & T_1600BPI)
    112   1.1     ragge 
    113  1.39       chs CFATTACH_DECL_NEW(mt, sizeof(struct mt_softc),
    114  1.20   thorpej     mtmatch, mtattach, NULL, NULL);
    115   1.7   thorpej 
    116   1.7   thorpej extern struct cfdriver mt_cd;
    117   1.1     ragge 
    118  1.17   gehenna dev_type_open(mtopen);
    119  1.17   gehenna dev_type_close(mtclose);
    120  1.17   gehenna dev_type_read(mtread);
    121  1.17   gehenna dev_type_write(mtwrite);
    122  1.17   gehenna dev_type_ioctl(mtioctl);
    123  1.17   gehenna dev_type_strategy(mtstrategy);
    124  1.17   gehenna dev_type_dump(mtdump);
    125  1.17   gehenna 
    126  1.17   gehenna const struct bdevsw mt_bdevsw = {
    127  1.41  dholland 	.d_open = mtopen,
    128  1.41  dholland 	.d_close = mtclose,
    129  1.41  dholland 	.d_strategy = mtstrategy,
    130  1.41  dholland 	.d_ioctl = mtioctl,
    131  1.41  dholland 	.d_dump = mtdump,
    132  1.41  dholland 	.d_psize = nosize,
    133  1.42  dholland 	.d_discard = nodiscard,
    134  1.41  dholland 	.d_flag = D_TAPE
    135  1.17   gehenna };
    136  1.17   gehenna 
    137  1.17   gehenna const struct cdevsw mt_cdevsw = {
    138  1.41  dholland 	.d_open = mtopen,
    139  1.41  dholland 	.d_close = mtclose,
    140  1.41  dholland 	.d_read = mtread,
    141  1.41  dholland 	.d_write = mtwrite,
    142  1.41  dholland 	.d_ioctl = mtioctl,
    143  1.41  dholland 	.d_stop = nostop,
    144  1.41  dholland 	.d_tty = notty,
    145  1.41  dholland 	.d_poll = nopoll,
    146  1.41  dholland 	.d_mmap = nommap,
    147  1.41  dholland 	.d_kqfilter = nokqfilter,
    148  1.43  dholland 	.d_discard = nodiscard,
    149  1.41  dholland 	.d_flag = D_TAPE
    150  1.17   gehenna };
    151  1.17   gehenna 
    152   1.1     ragge /*
    153   1.1     ragge  * More driver definitions, for generic MSCP code.
    154   1.1     ragge  */
    155   1.1     ragge 
    156   1.1     ragge int
    157  1.38    cegger mtmatch(device_t parent, cfdata_t cf, void *aux)
    158   1.1     ragge {
    159   1.1     ragge 	struct	drive_attach_args *da = aux;
    160   1.1     ragge 	struct	mscp *mp = da->da_mp;
    161   1.1     ragge 
    162   1.1     ragge 	if ((da->da_typ & MSCPBUS_TAPE) == 0)
    163   1.1     ragge 		return 0;
    164   1.6       jtk 	if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
    165   1.6       jtk 	    cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
    166   1.1     ragge 		return 0;
    167   1.1     ragge 	return 1;
    168   1.1     ragge }
    169   1.1     ragge 
    170   1.1     ragge /*
    171   1.1     ragge  * The attach routine only checks and prints drive type.
    172   1.1     ragge  */
    173   1.1     ragge void
    174  1.38    cegger mtattach(device_t parent, device_t self, void *aux)
    175   1.1     ragge {
    176  1.29   thorpej 	struct	mt_softc *mt = device_private(self);
    177   1.1     ragge 	struct	drive_attach_args *da = aux;
    178   1.1     ragge 	struct	mscp *mp = da->da_mp;
    179  1.39       chs 	struct	mscp_softc *mi = device_private(parent);
    180   1.1     ragge 
    181  1.39       chs 	mt->mt_dev = self;
    182   1.1     ragge 	mt->mt_hwunit = mp->mscp_unit;
    183   1.1     ragge 	mi->mi_dp[mp->mscp_unit] = self;
    184   1.1     ragge 
    185   1.4     ragge 	disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
    186   1.1     ragge }
    187   1.1     ragge 
    188  1.24     perry /*
    189   1.1     ragge  * (Try to) put the drive online. This is done the first time the
    190   1.1     ragge  * drive is opened, or if it has fallen offline.
    191   1.1     ragge  */
    192   1.1     ragge int
    193  1.35       dsl mt_putonline(struct mt_softc *mt)
    194   1.1     ragge {
    195   1.1     ragge 	struct	mscp *mp;
    196  1.28   thorpej 	struct	mscp_softc *mi =
    197  1.39       chs 	    device_private(device_parent(mt->mt_dev));
    198   1.1     ragge 
    199  1.27      matt 	((volatile struct mt_softc *) mt)->mt_state = MT_OFFLINE;
    200   1.1     ragge 	mp = mscp_getcp(mi, MSCP_WAIT);
    201   1.1     ragge 	mp->mscp_opcode = M_OP_ONLINE;
    202   1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    203   1.1     ragge 	mp->mscp_cmdref = (long)&mt->mt_state;
    204   1.1     ragge 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
    205   1.1     ragge 
    206   1.1     ragge 	/* Poll away */
    207  1.40    martin 	bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
    208   1.1     ragge 	if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
    209   1.1     ragge 		return MSCP_FAILED;
    210   1.1     ragge 
    211  1.11     ragge 	if ((volatile int)mt->mt_state != MT_ONLINE)
    212   1.1     ragge 		return MSCP_FAILED;
    213   1.1     ragge 
    214   1.1     ragge 	return MSCP_DONE;
    215   1.1     ragge }
    216   1.1     ragge /*
    217   1.1     ragge  * Open a drive.
    218   1.1     ragge  */
    219   1.1     ragge /*ARGSUSED*/
    220   1.1     ragge int
    221  1.36       dsl mtopen(dev_t dev, int flag, int fmt, struct lwp *l)
    222   1.1     ragge {
    223  1.15  augustss 	struct mt_softc *mt;
    224   1.1     ragge 	int unit;
    225   1.1     ragge 
    226   1.1     ragge 	/*
    227   1.1     ragge 	 * Make sure this is a reasonable open request.
    228   1.1     ragge 	 */
    229   1.1     ragge 	unit = mtunit(dev);
    230  1.34  drochner 	mt = device_lookup_private(&mt_cd, unit);
    231  1.34  drochner 	if (!mt)
    232   1.1     ragge 		return ENXIO;
    233   1.1     ragge 
    234   1.1     ragge 	if (mt->mt_inuse)
    235   1.1     ragge 			return EBUSY;
    236   1.1     ragge 	mt->mt_inuse = 1;
    237   1.1     ragge 
    238  1.12     ragge 	if (mt_putonline(mt) == MSCP_FAILED) {
    239  1.12     ragge 		mt->mt_inuse = 0;
    240   1.1     ragge 		return EIO;
    241  1.12     ragge 	}
    242   1.1     ragge 
    243   1.1     ragge 	return 0;
    244   1.1     ragge }
    245   1.1     ragge 
    246   1.1     ragge /* ARGSUSED */
    247   1.1     ragge int
    248  1.36       dsl mtclose(dev_t dev, int flags, int fmt, struct lwp *l)
    249   1.1     ragge {
    250   1.1     ragge 	int unit = mtunit(dev);
    251  1.34  drochner 	struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
    252   1.1     ragge 
    253   1.1     ragge 	/*
    254   1.1     ragge 	 * If we just have finished a writing, write EOT marks.
    255   1.1     ragge 	 */
    256   1.1     ragge 	if ((flags & FWRITE) && mt->mt_waswrite) {
    257   1.5     ragge 		mtcmd(mt, MTWEOF, 0, 0);
    258   1.5     ragge 		mtcmd(mt, MTWEOF, 0, 0);
    259   1.5     ragge 		mtcmd(mt, MTBSR, 1, 0);
    260   1.1     ragge 	}
    261   1.1     ragge 	if (mtnorewind(dev) == 0)
    262   1.5     ragge 		mtcmd(mt, MTREW, 0, 1);
    263   1.1     ragge 	if (mt->mt_serex)
    264   1.5     ragge 		mtcmd(mt, -1, 0, 0);
    265   1.1     ragge 
    266   1.1     ragge 	mt->mt_inuse = 0; /* Release the tape */
    267   1.1     ragge 	return 0;
    268   1.1     ragge }
    269   1.1     ragge 
    270   1.1     ragge void
    271  1.35       dsl mtstrategy(struct buf *bp)
    272   1.1     ragge {
    273  1.15  augustss 	int unit;
    274  1.15  augustss 	struct mt_softc *mt;
    275   1.1     ragge 
    276   1.1     ragge 	/*
    277   1.1     ragge 	 * Make sure this is a reasonable drive to use.
    278   1.1     ragge 	 */
    279   1.1     ragge 	unit = mtunit(bp->b_dev);
    280  1.34  drochner 	if ((mt = device_lookup_private(&mt_cd, unit)) == NULL) {
    281   1.1     ragge 		bp->b_error = ENXIO;
    282  1.31        ad 		biodone(bp);
    283  1.31        ad 		return;
    284   1.1     ragge 	}
    285   1.1     ragge 
    286   1.5     ragge 	mt->mt_waswrite = bp->b_flags & B_READ ? 0 : 1;
    287  1.39       chs 	mscp_strategy(bp, device_parent(mt->mt_dev));
    288   1.1     ragge 	return;
    289   1.1     ragge }
    290   1.1     ragge 
    291   1.1     ragge int
    292  1.35       dsl mtread(dev_t dev, struct uio *uio, int flag)
    293   1.1     ragge {
    294   1.1     ragge 
    295   1.9     ragge 	return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
    296   1.1     ragge }
    297   1.1     ragge 
    298   1.1     ragge int
    299  1.35       dsl mtwrite(dev_t dev, struct uio *uio, int flag)
    300   1.1     ragge {
    301   1.1     ragge 
    302   1.9     ragge 	return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
    303   1.1     ragge }
    304   1.1     ragge 
    305   1.1     ragge void
    306  1.38    cegger mtiodone(device_t usc, struct buf *bp)
    307   1.1     ragge {
    308   1.1     ragge 
    309   1.1     ragge 	biodone(bp);
    310   1.1     ragge }
    311   1.1     ragge 
    312   1.1     ragge /*
    313   1.1     ragge  * Fill in drive addresses in a mscp packet waiting for transfer.
    314   1.1     ragge  */
    315   1.1     ragge void
    316  1.35       dsl mtfillin(struct buf *bp, struct mscp *mp)
    317   1.1     ragge {
    318   1.1     ragge 	int unit = mtunit(bp->b_dev);
    319  1.34  drochner 	struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
    320   1.1     ragge 
    321   1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    322   1.1     ragge 	if (mt->mt_serex == 2) {
    323   1.1     ragge 		mp->mscp_modifier = M_MD_CLSEX;
    324   1.1     ragge 		mt->mt_serex = 0;
    325   1.1     ragge 	} else
    326   1.1     ragge 		mp->mscp_modifier = 0;
    327   1.1     ragge 
    328   1.1     ragge 	mp->mscp_seq.seq_bytecount = bp->b_bcount;
    329   1.1     ragge }
    330   1.1     ragge 
    331   1.1     ragge /*
    332   1.1     ragge  * Handle an error datagram.
    333   1.1     ragge  */
    334   1.1     ragge void
    335  1.38    cegger mtdgram(device_t usc, struct mscp *mp, struct mscp_softc *mi)
    336   1.1     ragge {
    337  1.33    cegger 	if (mscp_decodeerror(usc == NULL?"unconf mt" : device_xname(usc), mp, mi))
    338   1.1     ragge 		return;
    339   1.1     ragge }
    340   1.1     ragge 
    341   1.1     ragge /*
    342   1.1     ragge  * A drive came on line, make sure it really _is_ on line before
    343   1.1     ragge  * trying to use it.
    344   1.1     ragge  */
    345   1.1     ragge int
    346  1.38    cegger mtonline(device_t usc, struct mscp *mp)
    347   1.1     ragge {
    348  1.15  augustss 	struct mt_softc *mt = (void *)usc;
    349   1.1     ragge 
    350  1.30  christos 	wakeup((void *)&mt->mt_state);
    351  1.24     perry 	if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
    352   1.1     ragge 		mt->mt_state = MT_ONLINE;
    353   1.1     ragge 
    354   1.1     ragge 	return (MSCP_DONE);
    355   1.1     ragge }
    356   1.1     ragge 
    357   1.1     ragge /*
    358   1.1     ragge  * We got some (configured) unit's status.  Return DONE.
    359   1.1     ragge  */
    360   1.1     ragge int
    361  1.38    cegger mtgotstatus(device_t usc, struct mscp *mp)
    362   1.1     ragge {
    363   1.1     ragge 	return (MSCP_DONE);
    364   1.1     ragge }
    365   1.1     ragge 
    366  1.25     ragge static const char *mt_ioerrs[] = {
    367   1.1     ragge 	"invalid command",	/* 1 M_ST_INVALCMD */
    368   1.1     ragge 	"command aborted",	/* 2 M_ST_ABORTED */
    369   1.1     ragge 	"unit offline",		/* 3 M_ST_OFFLINE */
    370   1.1     ragge 	"unknown",		/* 4 M_ST_AVAILABLE */
    371   1.1     ragge 	"unknown",		/* 5 M_ST_MFMTERR */
    372   1.9     ragge 	"unit write protected", /* 6 M_ST_WRPROT */
    373   1.1     ragge 	"compare error",	/* 7 M_ST_COMPERR */
    374   1.9     ragge 	"data error",		/* 8 M_ST_DATAERR */
    375   1.9     ragge 	"host buffer access error",	/* 9 M_ST_HOSTBUFERR */
    376   1.1     ragge 	"controller error",	/* 10 M_ST_CTLRERR */
    377   1.9     ragge 	"drive error",		/* 11 M_ST_DRIVEERR */
    378   1.1     ragge 	"formatter error",	/* 12 M_ST_FORMATTERR */
    379   1.1     ragge 	"BOT encountered",	/* 13 M_ST_BOT */
    380   1.1     ragge 	"tape mark encountered",/* 14 M_ST_TAPEMARK */
    381   1.1     ragge 	"unknown",		/* 15 */
    382   1.1     ragge 	"record data truncated",/* 16 M_ST_RDTRUNC */
    383   1.1     ragge };
    384   1.1     ragge 
    385   1.1     ragge /*
    386   1.1     ragge  * An I/O error, may be because of a tapemark encountered.
    387   1.1     ragge  * Check that before failing.
    388   1.1     ragge  */
    389   1.1     ragge /*ARGSUSED*/
    390   1.1     ragge int
    391  1.38    cegger mtioerror(device_t usc, struct mscp *mp, struct buf *bp)
    392   1.1     ragge {
    393   1.1     ragge 	struct mt_softc *mt = (void *)usc;
    394   1.1     ragge 	int st = mp->mscp_status & M_ST_MASK;
    395   1.1     ragge 
    396   1.1     ragge 	if (mp->mscp_flags & M_EF_SEREX)
    397   1.1     ragge 		mt->mt_serex = 1;
    398   1.1     ragge 	if (st == M_ST_TAPEMARK)
    399   1.1     ragge 		mt->mt_serex = 2;
    400   1.1     ragge 	else {
    401   1.1     ragge 		if (st && st < 17)
    402  1.39       chs 			printf("%s: error %d (%s)\n", device_xname(mt->mt_dev), st,
    403   1.1     ragge 			    mt_ioerrs[st-1]);
    404   1.1     ragge 		else
    405  1.39       chs 			printf("%s: error %d\n", device_xname(mt->mt_dev), st);
    406  1.11     ragge 		bp->b_error = EROFS;
    407   1.1     ragge 	}
    408   1.1     ragge 
    409   1.1     ragge 	return (MSCP_DONE);
    410   1.1     ragge }
    411   1.1     ragge 
    412   1.1     ragge /*
    413   1.1     ragge  * I/O controls.
    414   1.1     ragge  */
    415   1.1     ragge int
    416  1.35       dsl mtioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    417   1.1     ragge {
    418  1.15  augustss 	int unit = mtunit(dev);
    419  1.34  drochner 	struct mt_softc *mt = device_lookup_private(&mt_cd, unit);
    420  1.27      matt 	struct mtop *mtop;
    421  1.27      matt 	int error = 0;
    422   1.1     ragge 
    423   1.1     ragge 	switch (cmd) {
    424   1.1     ragge 
    425   1.1     ragge 	case MTIOCTOP:
    426   1.1     ragge 		mtop = (void *)data;
    427   1.5     ragge 		if (mtop->mt_op == MTWEOF) {
    428   1.5     ragge 			while (mtop->mt_count-- > 0)
    429   1.5     ragge 				if ((error = mtcmd(mt, mtop->mt_op, 0, 0)))
    430   1.5     ragge 					break;
    431   1.5     ragge 		} else
    432   1.5     ragge 			error = mtcmd(mt, mtop->mt_op, mtop->mt_count, 0);
    433   1.1     ragge 
    434   1.1     ragge 	case MTIOCGET:
    435  1.27      matt 		((struct mtget *)data)->mt_type = MT_ISTMSCP;
    436   1.1     ragge 		/* XXX we need to fill in more fields here */
    437   1.1     ragge 		break;
    438   1.1     ragge 
    439   1.1     ragge 	default:
    440   1.1     ragge 		error = ENXIO;
    441   1.1     ragge 		break;
    442   1.1     ragge 	}
    443   1.1     ragge 	return (error);
    444   1.1     ragge }
    445   1.1     ragge 
    446   1.1     ragge /*
    447   1.1     ragge  * No crash dump support...
    448   1.1     ragge  */
    449   1.1     ragge int
    450  1.35       dsl mtdump(dev_t dev, daddr_t blkno, void *va, size_t size)
    451   1.1     ragge {
    452   1.1     ragge 	return -1;
    453   1.1     ragge }
    454   1.1     ragge 
    455   1.1     ragge /*
    456   1.1     ragge  * Send a command to the tape drive. Wait until the command is
    457   1.1     ragge  * finished before returning.
    458   1.5     ragge  * This routine must only be called when there are no data transfer
    459   1.5     ragge  * active on this device. Can we be sure of this? Or does the ctlr
    460   1.5     ragge  * queue up all command packets and take them in sequential order?
    461   1.5     ragge  * It sure would be nice if my manual stated this... /ragge
    462   1.1     ragge  */
    463   1.5     ragge int
    464  1.36       dsl mtcmd(struct mt_softc *mt, int cmd, int count, int complete)
    465   1.1     ragge {
    466   1.1     ragge 	struct mscp *mp;
    467  1.39       chs 	struct mscp_softc *mi = device_private(device_parent(mt->mt_dev));
    468   1.1     ragge 
    469   1.1     ragge 	mp = mscp_getcp(mi, MSCP_WAIT);
    470   1.1     ragge 
    471   1.5     ragge 	mt->mt_ioctlerr = 0;
    472   1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    473   1.1     ragge 	mp->mscp_cmdref = -1;
    474   1.1     ragge 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
    475   1.1     ragge 
    476   1.1     ragge 	switch (cmd) {
    477   1.1     ragge 	case MTWEOF:
    478   1.1     ragge 		mp->mscp_opcode = M_OP_WRITM;
    479   1.1     ragge 		break;
    480   1.1     ragge 
    481   1.1     ragge 	case MTBSF:
    482   1.1     ragge 		mp->mscp_modifier = M_MD_REVERSE;
    483   1.1     ragge 	case MTFSF:
    484   1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    485   1.5     ragge 		mp->mscp_seq.seq_buffer = count;
    486   1.1     ragge 		break;
    487   1.1     ragge 
    488   1.1     ragge 	case MTBSR:
    489   1.1     ragge 		mp->mscp_modifier = M_MD_REVERSE;
    490   1.1     ragge 	case MTFSR:
    491   1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    492   1.1     ragge 		mp->mscp_modifier |= M_MD_OBJCOUNT;
    493   1.5     ragge 		mp->mscp_seq.seq_bytecount = count;
    494   1.1     ragge 		break;
    495   1.1     ragge 
    496   1.1     ragge 	case MTREW:
    497   1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    498   1.1     ragge 		mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX;
    499   1.5     ragge 		if (complete)
    500   1.5     ragge 			mp->mscp_modifier |= M_MD_IMMEDIATE;
    501   1.1     ragge 		mt->mt_serex = 0;
    502   1.1     ragge 		break;
    503   1.1     ragge 
    504   1.5     ragge 	case MTOFFL:
    505   1.5     ragge 		mp->mscp_opcode = M_OP_AVAILABLE;
    506   1.5     ragge 		mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX;
    507   1.5     ragge 		mt->mt_serex = 0;
    508   1.5     ragge 		break;
    509   1.5     ragge 
    510   1.5     ragge 	case MTNOP:
    511   1.5     ragge 		mp->mscp_opcode = M_OP_GETUNITST;
    512   1.5     ragge 		break;
    513   1.5     ragge 
    514   1.1     ragge 	case -1: /* Clear serious exception only */
    515   1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    516   1.1     ragge 		mp->mscp_modifier = M_MD_CLSEX;
    517   1.1     ragge 		mt->mt_serex = 0;
    518   1.1     ragge 		break;
    519   1.1     ragge 
    520   1.1     ragge 	default:
    521   1.3  christos 		printf("Bad ioctl %x\n", cmd);
    522   1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    523   1.1     ragge 		break;
    524   1.1     ragge 	}
    525   1.1     ragge 
    526  1.40    martin 	bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
    527   1.1     ragge 	tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
    528   1.5     ragge 	return mt->mt_ioctlerr;
    529   1.1     ragge }
    530   1.1     ragge 
    531   1.1     ragge /*
    532   1.1     ragge  * Called from bus routines whenever a non-data transfer is finished.
    533   1.1     ragge  */
    534   1.1     ragge void
    535  1.38    cegger mtcmddone(device_t usc, struct mscp *mp)
    536   1.1     ragge {
    537   1.1     ragge 	struct mt_softc *mt = (void *)usc;
    538   1.1     ragge 
    539   1.5     ragge 	if (mp->mscp_status) {
    540   1.5     ragge 		mt->mt_ioctlerr = EIO;
    541  1.39       chs 		printf("%s: bad status %x\n", device_xname(mt->mt_dev),
    542   1.1     ragge 		    mp->mscp_status);
    543   1.5     ragge 	}
    544   1.1     ragge 	wakeup(&mt->mt_inuse);
    545   1.1     ragge }
    546