Home | History | Annotate | Line # | Download | only in mscp
mscp_tape.c revision 1.15.10.1
      1  1.15.10.1      fvdl /*	$NetBSD: mscp_tape.c,v 1.15.10.1 2001/10/10 11:56:56 fvdl 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.9     ragge  *	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.1     ragge 
     43        1.1     ragge #include <sys/param.h>
     44        1.1     ragge #include <sys/device.h>
     45        1.1     ragge #include <sys/kernel.h>
     46        1.1     ragge #include <sys/buf.h>
     47        1.1     ragge #include <sys/ioccom.h>
     48        1.1     ragge #include <sys/mtio.h>
     49        1.1     ragge #include <sys/fcntl.h>
     50        1.1     ragge #include <sys/malloc.h>
     51        1.1     ragge #include <sys/systm.h>
     52        1.1     ragge #include <sys/proc.h>
     53  1.15.10.1      fvdl #include <sys/vnode.h>
     54        1.1     ragge 
     55       1.14     ragge #include <machine/bus.h>
     56       1.10     ragge #include <machine/cpu.h>
     57       1.10     ragge 
     58       1.14     ragge #include <dev/mscp/mscp.h>
     59       1.14     ragge #include <dev/mscp/mscpreg.h>
     60       1.14     ragge #include <dev/mscp/mscpvar.h>
     61        1.1     ragge 
     62        1.6       jtk #include "locators.h"
     63        1.6       jtk 
     64        1.1     ragge /*
     65        1.1     ragge  * Drive status, per drive
     66        1.1     ragge  */
     67        1.1     ragge struct mt_softc {
     68        1.1     ragge 	struct	device mt_dev;	/* Autoconf struct */
     69        1.1     ragge 	int	mt_state;	/* open/closed state */
     70        1.1     ragge 	int	mt_hwunit;	/* Hardware unit number */
     71        1.1     ragge 	int	mt_inuse;	/* Locks the tape drive for others */
     72        1.1     ragge 	int	mt_waswrite;	/* Last operation was a write op */
     73        1.1     ragge 	int	mt_serex;	/* Got serious exception */
     74        1.5     ragge 	int	mt_ioctlerr;	/* Error after last ioctl */
     75        1.1     ragge };
     76        1.1     ragge 
     77        1.9     ragge #define MT_OFFLINE	0
     78        1.9     ragge #define MT_ONLINE	1
     79        1.1     ragge 
     80        1.8     ragge int	mtmatch __P((struct device *, struct cfdata *, void *));
     81        1.1     ragge void	mtattach __P((struct device *, struct device *, void *));
     82        1.1     ragge void	mtdgram __P((struct device *, struct mscp *, struct mscp_softc *));
     83        1.1     ragge void	mtiodone __P((struct device *, struct buf *));
     84        1.1     ragge int	mtonline __P((struct device *, struct mscp *));
     85        1.1     ragge int	mtgotstatus __P((struct device *, struct mscp *));
     86        1.1     ragge int	mtioerror __P((struct device *, struct mscp *, struct buf *));
     87        1.1     ragge void	mtfillin __P((struct buf *, struct mscp *));
     88  1.15.10.1      fvdl int	mtopen __P((struct vnode *, int, int, struct proc *));
     89  1.15.10.1      fvdl int	mtclose __P((struct vnode *, int, int, struct proc *));
     90        1.1     ragge void	mtstrategy __P((struct buf *));
     91  1.15.10.1      fvdl int	mtread __P((struct vnode *, struct uio *));
     92  1.15.10.1      fvdl int	mtwrite __P((struct vnode *, struct uio *));
     93  1.15.10.1      fvdl int	mtioctl __P((struct vnode *, int, caddr_t, int, struct proc *));
     94        1.1     ragge int	mtdump __P((dev_t, daddr_t, caddr_t, size_t));
     95        1.5     ragge int	mtcmd __P((struct mt_softc *, int, int, int));
     96        1.1     ragge void	mtcmddone __P((struct device *, struct mscp *));
     97       1.10     ragge int	mt_putonline __P((struct mt_softc *));
     98        1.1     ragge 
     99        1.1     ragge struct	mscp_device mt_device = {
    100        1.1     ragge 	mtdgram,
    101        1.1     ragge 	mtiodone,
    102        1.1     ragge 	mtonline,
    103        1.1     ragge 	mtgotstatus,
    104        1.1     ragge 	0,
    105        1.1     ragge 	mtioerror,
    106        1.1     ragge 	0,
    107        1.1     ragge 	mtfillin,
    108        1.1     ragge 	mtcmddone,
    109        1.1     ragge };
    110        1.1     ragge 
    111        1.1     ragge /* This is not good, should allow more than 4 tapes/device type */
    112        1.9     ragge #define mtunit(dev)	(minor(dev) & T_UNIT)
    113        1.9     ragge #define mtnorewind(dev) (dev & T_NOREWIND)
    114        1.9     ragge #define mthdensity(dev) (dev & T_1600BPI)
    115        1.1     ragge 
    116        1.1     ragge struct	cfattach mt_ca = {
    117        1.1     ragge 	sizeof(struct mt_softc), mtmatch, mtattach
    118        1.1     ragge };
    119        1.7   thorpej 
    120        1.7   thorpej extern struct cfdriver mt_cd;
    121        1.1     ragge 
    122        1.1     ragge /*
    123        1.1     ragge  * More driver definitions, for generic MSCP code.
    124        1.1     ragge  */
    125        1.1     ragge 
    126        1.1     ragge int
    127        1.8     ragge mtmatch(parent, cf, aux)
    128        1.1     ragge 	struct	device *parent;
    129        1.8     ragge 	struct	cfdata *cf;
    130        1.8     ragge 	void	*aux;
    131        1.1     ragge {
    132        1.1     ragge 	struct	drive_attach_args *da = aux;
    133        1.1     ragge 	struct	mscp *mp = da->da_mp;
    134        1.1     ragge 
    135        1.1     ragge 	if ((da->da_typ & MSCPBUS_TAPE) == 0)
    136        1.1     ragge 		return 0;
    137        1.6       jtk 	if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
    138        1.6       jtk 	    cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
    139        1.1     ragge 		return 0;
    140        1.1     ragge 	return 1;
    141        1.1     ragge }
    142        1.1     ragge 
    143        1.1     ragge /*
    144        1.1     ragge  * The attach routine only checks and prints drive type.
    145        1.1     ragge  */
    146        1.1     ragge void
    147        1.1     ragge mtattach(parent, self, aux)
    148        1.1     ragge 	struct	device *parent, *self;
    149        1.1     ragge 	void	*aux;
    150        1.1     ragge {
    151        1.1     ragge 	struct	mt_softc *mt = (void *)self;
    152        1.1     ragge 	struct	drive_attach_args *da = aux;
    153        1.1     ragge 	struct	mscp *mp = da->da_mp;
    154        1.1     ragge 	struct	mscp_softc *mi = (void *)parent;
    155        1.1     ragge 
    156        1.1     ragge 	mt->mt_hwunit = mp->mscp_unit;
    157        1.1     ragge 	mi->mi_dp[mp->mscp_unit] = self;
    158        1.1     ragge 
    159        1.4     ragge 	disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
    160        1.1     ragge }
    161        1.1     ragge 
    162        1.1     ragge /*
    163        1.1     ragge  * (Try to) put the drive online. This is done the first time the
    164        1.1     ragge  * drive is opened, or if it has fallen offline.
    165        1.1     ragge  */
    166        1.1     ragge int
    167        1.1     ragge mt_putonline(mt)
    168        1.1     ragge 	struct mt_softc *mt;
    169        1.1     ragge {
    170        1.1     ragge 	struct	mscp *mp;
    171        1.1     ragge 	struct	mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent;
    172        1.1     ragge 	volatile int i;
    173        1.1     ragge 
    174       1.11     ragge 	(volatile int)mt->mt_state = MT_OFFLINE;
    175        1.1     ragge 	mp = mscp_getcp(mi, MSCP_WAIT);
    176        1.1     ragge 	mp->mscp_opcode = M_OP_ONLINE;
    177        1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    178        1.1     ragge 	mp->mscp_cmdref = (long)&mt->mt_state;
    179        1.1     ragge 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
    180        1.1     ragge 
    181        1.1     ragge 	/* Poll away */
    182       1.14     ragge 	i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
    183        1.1     ragge 	if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
    184        1.1     ragge 		return MSCP_FAILED;
    185        1.1     ragge 
    186       1.11     ragge 	if ((volatile int)mt->mt_state != MT_ONLINE)
    187        1.1     ragge 		return MSCP_FAILED;
    188        1.1     ragge 
    189        1.1     ragge 	return MSCP_DONE;
    190        1.1     ragge }
    191        1.1     ragge /*
    192        1.1     ragge  * Open a drive.
    193        1.1     ragge  */
    194        1.1     ragge /*ARGSUSED*/
    195        1.1     ragge int
    196  1.15.10.1      fvdl mtopen(devvp, flag, fmt, p)
    197  1.15.10.1      fvdl 	struct vnode *devvp;
    198        1.1     ragge 	int flag, fmt;
    199        1.1     ragge 	struct	proc *p;
    200        1.1     ragge {
    201       1.15  augustss 	struct mt_softc *mt;
    202        1.1     ragge 	int unit;
    203  1.15.10.1      fvdl 	dev_t dev;
    204        1.1     ragge 
    205        1.1     ragge 	/*
    206        1.1     ragge 	 * Make sure this is a reasonable open request.
    207        1.1     ragge 	 */
    208  1.15.10.1      fvdl 	dev = vdev_rdev(devvp);
    209        1.1     ragge 	unit = mtunit(dev);
    210        1.1     ragge 	if (unit >= mt_cd.cd_ndevs)
    211        1.1     ragge 		return ENXIO;
    212        1.1     ragge 	mt = mt_cd.cd_devs[unit];
    213        1.1     ragge 	if (mt == 0)
    214        1.1     ragge 		return ENXIO;
    215        1.1     ragge 
    216        1.1     ragge 	if (mt->mt_inuse)
    217        1.1     ragge 			return EBUSY;
    218        1.1     ragge 	mt->mt_inuse = 1;
    219        1.1     ragge 
    220  1.15.10.1      fvdl 	vdev_setprivdata(devvp, mt);
    221  1.15.10.1      fvdl 
    222       1.12     ragge 	if (mt_putonline(mt) == MSCP_FAILED) {
    223       1.12     ragge 		mt->mt_inuse = 0;
    224        1.1     ragge 		return EIO;
    225       1.12     ragge 	}
    226        1.1     ragge 
    227        1.1     ragge 	return 0;
    228        1.1     ragge }
    229        1.1     ragge 
    230        1.1     ragge /* ARGSUSED */
    231        1.1     ragge int
    232  1.15.10.1      fvdl mtclose(devvp, flags, fmt, p)
    233  1.15.10.1      fvdl 	struct vnode *devvp;
    234        1.1     ragge 	int flags, fmt;
    235        1.1     ragge 	struct	proc *p;
    236        1.1     ragge {
    237  1.15.10.1      fvdl 	struct mt_softc *mt = vdev_privdata(devvp);
    238        1.1     ragge 
    239        1.1     ragge 	/*
    240        1.1     ragge 	 * If we just have finished a writing, write EOT marks.
    241        1.1     ragge 	 */
    242        1.1     ragge 	if ((flags & FWRITE) && mt->mt_waswrite) {
    243        1.5     ragge 		mtcmd(mt, MTWEOF, 0, 0);
    244        1.5     ragge 		mtcmd(mt, MTWEOF, 0, 0);
    245        1.5     ragge 		mtcmd(mt, MTBSR, 1, 0);
    246        1.1     ragge 	}
    247  1.15.10.1      fvdl 	if (mtnorewind(vdev_rdev(devvp)) == 0)
    248        1.5     ragge 		mtcmd(mt, MTREW, 0, 1);
    249        1.1     ragge 	if (mt->mt_serex)
    250        1.5     ragge 		mtcmd(mt, -1, 0, 0);
    251        1.1     ragge 
    252        1.1     ragge 	mt->mt_inuse = 0; /* Release the tape */
    253        1.1     ragge 	return 0;
    254        1.1     ragge }
    255        1.1     ragge 
    256        1.1     ragge void
    257        1.1     ragge mtstrategy(bp)
    258       1.15  augustss 	struct buf *bp;
    259        1.1     ragge {
    260       1.15  augustss 	struct mt_softc *mt;
    261        1.1     ragge 
    262        1.1     ragge 	/*
    263        1.1     ragge 	 * Make sure this is a reasonable drive to use.
    264        1.1     ragge 	 */
    265  1.15.10.1      fvdl 	mt = vdev_privdata(bp->b_devvp);
    266  1.15.10.1      fvdl 	if (mt == NULL) {
    267        1.1     ragge 		bp->b_error = ENXIO;
    268        1.1     ragge 		goto bad;
    269        1.1     ragge 	}
    270        1.1     ragge 
    271        1.5     ragge 	mt->mt_waswrite = bp->b_flags & B_READ ? 0 : 1;
    272        1.4     ragge 	mscp_strategy(bp, mt->mt_dev.dv_parent);
    273        1.1     ragge 	return;
    274        1.1     ragge 
    275        1.1     ragge bad:
    276        1.1     ragge 	bp->b_flags |= B_ERROR;
    277        1.1     ragge 	biodone(bp);
    278        1.1     ragge }
    279        1.1     ragge 
    280        1.1     ragge int
    281  1.15.10.1      fvdl mtread(devvp, uio)
    282  1.15.10.1      fvdl 	struct vnode *devvp;
    283        1.9     ragge 	struct uio *uio;
    284        1.1     ragge {
    285        1.1     ragge 
    286  1.15.10.1      fvdl 	return (physio(mtstrategy, NULL, devvp, B_READ, minphys, uio));
    287        1.1     ragge }
    288        1.1     ragge 
    289        1.1     ragge int
    290  1.15.10.1      fvdl mtwrite(devvp, uio)
    291  1.15.10.1      fvdl 	struct vnode *devvp;
    292        1.9     ragge 	struct uio *uio;
    293        1.1     ragge {
    294        1.1     ragge 
    295  1.15.10.1      fvdl 	return (physio(mtstrategy, NULL, devvp, B_WRITE, minphys, uio));
    296        1.1     ragge }
    297        1.1     ragge 
    298        1.1     ragge void
    299        1.1     ragge mtiodone(usc, bp)
    300        1.1     ragge 	struct device *usc;
    301        1.1     ragge 	struct buf *bp;
    302        1.1     ragge {
    303        1.1     ragge 
    304        1.1     ragge 	biodone(bp);
    305        1.1     ragge }
    306        1.1     ragge 
    307        1.1     ragge /*
    308        1.1     ragge  * Fill in drive addresses in a mscp packet waiting for transfer.
    309        1.1     ragge  */
    310        1.1     ragge void
    311        1.1     ragge mtfillin(bp, mp)
    312        1.1     ragge 	struct buf *bp;
    313        1.1     ragge 	struct mscp *mp;
    314        1.1     ragge {
    315  1.15.10.1      fvdl 	int unit = mtunit(vdev_rdev(bp->b_devvp));
    316        1.1     ragge 	struct mt_softc *mt = mt_cd.cd_devs[unit];
    317        1.1     ragge 
    318        1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    319        1.1     ragge 	if (mt->mt_serex == 2) {
    320        1.1     ragge 		mp->mscp_modifier = M_MD_CLSEX;
    321        1.1     ragge 		mt->mt_serex = 0;
    322        1.1     ragge 	} else
    323        1.1     ragge 		mp->mscp_modifier = 0;
    324        1.1     ragge 
    325        1.1     ragge 	mp->mscp_seq.seq_bytecount = bp->b_bcount;
    326        1.1     ragge }
    327        1.1     ragge 
    328        1.1     ragge /*
    329        1.1     ragge  * Handle an error datagram.
    330        1.1     ragge  */
    331        1.1     ragge void
    332        1.1     ragge mtdgram(usc, mp, mi)
    333        1.1     ragge 	struct device *usc;
    334        1.1     ragge 	struct mscp *mp;
    335        1.1     ragge 	struct mscp_softc *mi;
    336        1.1     ragge {
    337        1.1     ragge 	if (mscp_decodeerror(usc == NULL?"unconf mt" : usc->dv_xname, 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.1     ragge mtonline(usc, mp)
    347        1.1     ragge 	struct device *usc;
    348        1.1     ragge 	struct mscp *mp;
    349        1.1     ragge {
    350       1.15  augustss 	struct mt_softc *mt = (void *)usc;
    351        1.1     ragge 
    352        1.1     ragge 	wakeup((caddr_t)&mt->mt_state);
    353        1.1     ragge 	if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
    354        1.1     ragge 		mt->mt_state = MT_ONLINE;
    355        1.1     ragge 
    356        1.1     ragge 	return (MSCP_DONE);
    357        1.1     ragge }
    358        1.1     ragge 
    359        1.1     ragge /*
    360        1.1     ragge  * We got some (configured) unit's status.  Return DONE.
    361        1.1     ragge  */
    362        1.1     ragge int
    363        1.1     ragge mtgotstatus(usc, mp)
    364       1.15  augustss 	struct device *usc;
    365       1.15  augustss 	struct mscp *mp;
    366        1.1     ragge {
    367        1.1     ragge 	return (MSCP_DONE);
    368        1.1     ragge }
    369        1.1     ragge 
    370        1.1     ragge static char *mt_ioerrs[] = {
    371        1.1     ragge 	"invalid command",	/* 1 M_ST_INVALCMD */
    372        1.1     ragge 	"command aborted",	/* 2 M_ST_ABORTED */
    373        1.1     ragge 	"unit offline",		/* 3 M_ST_OFFLINE */
    374        1.1     ragge 	"unknown",		/* 4 M_ST_AVAILABLE */
    375        1.1     ragge 	"unknown",		/* 5 M_ST_MFMTERR */
    376        1.9     ragge 	"unit write protected", /* 6 M_ST_WRPROT */
    377        1.1     ragge 	"compare error",	/* 7 M_ST_COMPERR */
    378        1.9     ragge 	"data error",		/* 8 M_ST_DATAERR */
    379        1.9     ragge 	"host buffer access error",	/* 9 M_ST_HOSTBUFERR */
    380        1.1     ragge 	"controller error",	/* 10 M_ST_CTLRERR */
    381        1.9     ragge 	"drive error",		/* 11 M_ST_DRIVEERR */
    382        1.1     ragge 	"formatter error",	/* 12 M_ST_FORMATTERR */
    383        1.1     ragge 	"BOT encountered",	/* 13 M_ST_BOT */
    384        1.1     ragge 	"tape mark encountered",/* 14 M_ST_TAPEMARK */
    385        1.1     ragge 	"unknown",		/* 15 */
    386        1.1     ragge 	"record data truncated",/* 16 M_ST_RDTRUNC */
    387        1.1     ragge };
    388        1.1     ragge 
    389        1.1     ragge /*
    390        1.1     ragge  * An I/O error, may be because of a tapemark encountered.
    391        1.1     ragge  * Check that before failing.
    392        1.1     ragge  */
    393        1.1     ragge /*ARGSUSED*/
    394        1.1     ragge int
    395        1.1     ragge mtioerror(usc, mp, bp)
    396       1.15  augustss 	struct device *usc;
    397       1.15  augustss 	struct mscp *mp;
    398        1.1     ragge 	struct buf *bp;
    399        1.1     ragge {
    400        1.1     ragge 	struct mt_softc *mt = (void *)usc;
    401        1.1     ragge 	int st = mp->mscp_status & M_ST_MASK;
    402        1.1     ragge 
    403        1.1     ragge 	if (mp->mscp_flags & M_EF_SEREX)
    404        1.1     ragge 		mt->mt_serex = 1;
    405        1.1     ragge 	if (st == M_ST_TAPEMARK)
    406        1.1     ragge 		mt->mt_serex = 2;
    407        1.1     ragge 	else {
    408        1.1     ragge 		if (st && st < 17)
    409        1.3  christos 			printf("%s: error %d (%s)\n", mt->mt_dev.dv_xname, st,
    410        1.1     ragge 			    mt_ioerrs[st-1]);
    411        1.1     ragge 		else
    412        1.3  christos 			printf("%s: error %d\n", mt->mt_dev.dv_xname, st);
    413        1.1     ragge 		bp->b_flags |= B_ERROR;
    414       1.11     ragge 		bp->b_error = EROFS;
    415        1.1     ragge 	}
    416        1.1     ragge 
    417        1.1     ragge 	return (MSCP_DONE);
    418        1.1     ragge }
    419        1.1     ragge 
    420        1.1     ragge /*
    421        1.1     ragge  * I/O controls.
    422        1.1     ragge  */
    423        1.1     ragge int
    424  1.15.10.1      fvdl mtioctl(devvp, cmd, data, flag, p)
    425  1.15.10.1      fvdl 	struct vnode *devvp;
    426        1.1     ragge 	int cmd;
    427        1.1     ragge 	caddr_t data;
    428        1.1     ragge 	int flag;
    429        1.1     ragge 	struct proc *p;
    430        1.1     ragge {
    431  1.15.10.1      fvdl 	struct mt_softc *mt = vdev_privdata(devvp);
    432        1.1     ragge 	struct	mtop *mtop;
    433        1.1     ragge 	struct	mtget *mtget;
    434       1.10     ragge 	int error = 0, count;
    435        1.1     ragge 
    436        1.5     ragge 	count = mtop->mt_count;
    437        1.1     ragge 
    438        1.1     ragge 	switch (cmd) {
    439        1.1     ragge 
    440        1.1     ragge 	case MTIOCTOP:
    441        1.1     ragge 		mtop = (void *)data;
    442        1.5     ragge 		if (mtop->mt_op == MTWEOF) {
    443        1.5     ragge 			while (mtop->mt_count-- > 0)
    444        1.5     ragge 				if ((error = mtcmd(mt, mtop->mt_op, 0, 0)))
    445        1.5     ragge 					break;
    446        1.5     ragge 		} else
    447        1.5     ragge 			error = mtcmd(mt, mtop->mt_op, mtop->mt_count, 0);
    448        1.1     ragge 
    449        1.1     ragge 	case MTIOCGET:
    450        1.1     ragge 		mtget = (void *)data;
    451        1.1     ragge 		mtget->mt_type = MT_ISTMSCP;
    452        1.1     ragge 		/* XXX we need to fill in more fields here */
    453        1.1     ragge 		break;
    454        1.1     ragge 
    455        1.1     ragge 	default:
    456        1.1     ragge 		error = ENXIO;
    457        1.1     ragge 		break;
    458        1.1     ragge 	}
    459        1.1     ragge 	return (error);
    460        1.1     ragge }
    461        1.1     ragge 
    462        1.1     ragge /*
    463        1.1     ragge  * No crash dump support...
    464        1.1     ragge  */
    465        1.1     ragge int
    466        1.1     ragge mtdump(dev, blkno, va, size)
    467        1.1     ragge 	dev_t	dev;
    468        1.9     ragge 	daddr_t blkno;
    469        1.9     ragge 	caddr_t va;
    470        1.1     ragge 	size_t	size;
    471        1.1     ragge {
    472        1.1     ragge 	return -1;
    473        1.1     ragge }
    474        1.1     ragge 
    475        1.1     ragge /*
    476        1.1     ragge  * Send a command to the tape drive. Wait until the command is
    477        1.1     ragge  * finished before returning.
    478        1.5     ragge  * This routine must only be called when there are no data transfer
    479        1.5     ragge  * active on this device. Can we be sure of this? Or does the ctlr
    480        1.5     ragge  * queue up all command packets and take them in sequential order?
    481        1.5     ragge  * It sure would be nice if my manual stated this... /ragge
    482        1.1     ragge  */
    483        1.5     ragge int
    484        1.5     ragge mtcmd(mt, cmd, count, complete)
    485        1.1     ragge 	struct mt_softc *mt;
    486        1.5     ragge 	int cmd, count, complete;
    487        1.1     ragge {
    488        1.1     ragge 	struct mscp *mp;
    489        1.1     ragge 	struct mscp_softc *mi = (void *)mt->mt_dev.dv_parent;
    490        1.1     ragge 	volatile int i;
    491        1.1     ragge 
    492        1.1     ragge 	mp = mscp_getcp(mi, MSCP_WAIT);
    493        1.1     ragge 
    494        1.5     ragge 	mt->mt_ioctlerr = 0;
    495        1.1     ragge 	mp->mscp_unit = mt->mt_hwunit;
    496        1.1     ragge 	mp->mscp_cmdref = -1;
    497        1.1     ragge 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
    498        1.1     ragge 
    499        1.1     ragge 	switch (cmd) {
    500        1.1     ragge 	case MTWEOF:
    501        1.1     ragge 		mp->mscp_opcode = M_OP_WRITM;
    502        1.1     ragge 		break;
    503        1.1     ragge 
    504        1.1     ragge 	case MTBSF:
    505        1.1     ragge 		mp->mscp_modifier = M_MD_REVERSE;
    506        1.1     ragge 	case MTFSF:
    507        1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    508        1.5     ragge 		mp->mscp_seq.seq_buffer = count;
    509        1.1     ragge 		break;
    510        1.1     ragge 
    511        1.1     ragge 	case MTBSR:
    512        1.1     ragge 		mp->mscp_modifier = M_MD_REVERSE;
    513        1.1     ragge 	case MTFSR:
    514        1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    515        1.1     ragge 		mp->mscp_modifier |= M_MD_OBJCOUNT;
    516        1.5     ragge 		mp->mscp_seq.seq_bytecount = count;
    517        1.1     ragge 		break;
    518        1.1     ragge 
    519        1.1     ragge 	case MTREW:
    520        1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    521        1.1     ragge 		mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX;
    522        1.5     ragge 		if (complete)
    523        1.5     ragge 			mp->mscp_modifier |= M_MD_IMMEDIATE;
    524        1.1     ragge 		mt->mt_serex = 0;
    525        1.1     ragge 		break;
    526        1.1     ragge 
    527        1.5     ragge 	case MTOFFL:
    528        1.5     ragge 		mp->mscp_opcode = M_OP_AVAILABLE;
    529        1.5     ragge 		mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX;
    530        1.5     ragge 		mt->mt_serex = 0;
    531        1.5     ragge 		break;
    532        1.5     ragge 
    533        1.5     ragge 	case MTNOP:
    534        1.5     ragge 		mp->mscp_opcode = M_OP_GETUNITST;
    535        1.5     ragge 		break;
    536        1.5     ragge 
    537        1.1     ragge 	case -1: /* Clear serious exception only */
    538        1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    539        1.1     ragge 		mp->mscp_modifier = M_MD_CLSEX;
    540        1.1     ragge 		mt->mt_serex = 0;
    541        1.1     ragge 		break;
    542        1.1     ragge 
    543        1.1     ragge 	default:
    544        1.3  christos 		printf("Bad ioctl %x\n", cmd);
    545        1.1     ragge 		mp->mscp_opcode = M_OP_POS;
    546        1.1     ragge 		break;
    547        1.1     ragge 	}
    548        1.1     ragge 
    549       1.14     ragge 	i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
    550        1.1     ragge 	tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
    551        1.5     ragge 	return mt->mt_ioctlerr;
    552        1.1     ragge }
    553        1.1     ragge 
    554        1.1     ragge /*
    555        1.1     ragge  * Called from bus routines whenever a non-data transfer is finished.
    556        1.1     ragge  */
    557        1.1     ragge void
    558        1.1     ragge mtcmddone(usc, mp)
    559        1.1     ragge 	struct device *usc;
    560        1.1     ragge 	struct mscp *mp;
    561        1.1     ragge {
    562        1.1     ragge 	struct mt_softc *mt = (void *)usc;
    563        1.1     ragge 
    564        1.5     ragge 	if (mp->mscp_status) {
    565        1.5     ragge 		mt->mt_ioctlerr = EIO;
    566        1.3  christos 		printf("%s: bad status %x\n", mt->mt_dev.dv_xname,
    567        1.1     ragge 		    mp->mscp_status);
    568        1.5     ragge 	}
    569        1.1     ragge 	wakeup(&mt->mt_inuse);
    570        1.1     ragge }
    571