xref: /csrg-svn/sys/luna68k/dev/st.c (revision 56519)
154010Sfujita /*
254010Sfujita  * Copyright (c) 1992 OMRON Corporation.
354010Sfujita  * Copyright (c) 1992 The Regents of the University of California.
454010Sfujita  * All rights reserved.
554010Sfujita  *
654010Sfujita  * This code is derived from software contributed to Berkeley by
754010Sfujita  * OMRON Corporation.
854010Sfujita  *
954010Sfujita  * %sccs.include.redist.c%
1054010Sfujita  *
11*56519Sbostic  *	@(#)st.c	7.4 (Berkeley) 10/11/92
1254010Sfujita  */
1354010Sfujita 
1454010Sfujita /*
1554010Sfujita  * st.c -- TEAC MT-2ST/N60 SCSI TAPE UNIT Device Driver
1654010Sfujita  * remaked by A.Fujita, MAR-22-1992
1754010Sfujita  */
1854010Sfujita 
1954010Sfujita /*
2054010Sfujita  * SCSI CCS (Command Command Set) disk driver.
2154010Sfujita  */
2254010Sfujita #include "st.h"
2354010Sfujita #if NST > 0
2454010Sfujita 
25*56519Sbostic #include <sys/param.h>
26*56519Sbostic #include <sys/systm.h>
27*56519Sbostic #include <sys/buf.h>
28*56519Sbostic #include <sys/file.h>
29*56519Sbostic #include <sys/proc.h>
30*56519Sbostic #include <sys/mtio.h>
31*56519Sbostic #include <sys/tprintf.h>
3254010Sfujita 
33*56519Sbostic #include <luna68k/dev/device.h>
34*56519Sbostic #include <luna68k/dev/scsireg.h>
35*56519Sbostic #include <luna68k/dev/scsivar.h>
3654010Sfujita 
3754010Sfujita extern int scsi_test_unit_rdy();
3854010Sfujita extern int scsi_request_sense();
3954010Sfujita extern int scsi_immed_command();
4054010Sfujita extern char *scsi_status();
4154010Sfujita 
4254010Sfujita extern int scgo();
4354010Sfujita extern void scfree();
4454010Sfujita 
4554010Sfujita char *sense_key();
4654010Sfujita 
4754010Sfujita int	stinit(), ststrategy(), ststart(), stintr();
4854010Sfujita 
4954010Sfujita struct	driver stdriver = {
5054010Sfujita 	stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0
5154010Sfujita };
5254010Sfujita 
5354010Sfujita struct	st_softc {
5454010Sfujita 	struct	hp_device *sc_hd;
5554010Sfujita 	struct	scsi_queue sc_dq;
5654010Sfujita 	int	sc_flags;
5754010Sfujita 	short	sc_type;	/* drive type */
5854010Sfujita 	short	sc_punit;	/* physical unit (scsi lun) */
5954010Sfujita 	tpr_t	sc_ctty;
6054010Sfujita } st_softc[NST];
6154010Sfujita 
6254010Sfujita /* softc flags */
6354010Sfujita #define STF_ALIVE	0x0001
6454010Sfujita #define STF_OPEN	0x0002
6554010Sfujita #define STF_WMODE	0x0004
6654010Sfujita #define STF_WRTTN	0x0008
6754010Sfujita #define STF_CMD		0x0010
6854010Sfujita #define STF_LEOT	0x0020
6954010Sfujita #define STF_MOVED	0x0040
7054010Sfujita 
7154010Sfujita u_char xsense_buff[60];
7254010Sfujita 
7354010Sfujita struct scsi_fmt_cdb st_read_cmd  = { 6, CMD_READ  };
7454010Sfujita struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE };
7554010Sfujita 
7654010Sfujita struct buf sttab[NST];
7754010Sfujita struct buf stbuf[NST];
7854010Sfujita 
7954010Sfujita #define	stunit(x)	(minor(x) & 3)
8054010Sfujita #define	stpunit(x)	((x) & 7)
8154010Sfujita 
8254010Sfujita #define STDEV_NOREWIND	0x04
8354010Sfujita 
8454010Sfujita #define	STRETRY		2	/* IO retry count */
8554010Sfujita 
8654010Sfujita struct st_iostat {
8754010Sfujita 	int imax;
8854010Sfujita 	int imin;
8954010Sfujita 	int omax;
9054010Sfujita 	int omin;
9154010Sfujita };
9254010Sfujita 
9354010Sfujita struct st_iostat st_iostat[NST];
9454010Sfujita 
9554010Sfujita 
9654010Sfujita /*
9754010Sfujita  * Initialize
9854010Sfujita  */
9954010Sfujita 
10054010Sfujita int
10154010Sfujita stinit(hd)
10254010Sfujita 	register struct hp_device *hd;
10354010Sfujita {
10454010Sfujita 	register struct st_softc *sc = &st_softc[hd->hp_unit];
10554010Sfujita 
10654010Sfujita 	sc->sc_hd = hd;
10754010Sfujita 	sc->sc_punit = stpunit(hd->hp_flags);
10854010Sfujita 	sc->sc_type = stident(sc, hd);
10954010Sfujita 	if (sc->sc_type < 0)
11054010Sfujita 		return(0);
11154010Sfujita 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
11254010Sfujita 	sc->sc_dq.dq_unit = hd->hp_unit;
11354010Sfujita 	sc->sc_dq.dq_slave = hd->hp_slave;
11454010Sfujita 	sc->sc_dq.dq_driver = &stdriver;
11554010Sfujita 	sc->sc_flags = STF_ALIVE;
11654010Sfujita 	return(1);
11754010Sfujita }
11854010Sfujita 
11954010Sfujita static struct scsi_inquiry inqbuf;
12054010Sfujita static struct scsi_fmt_cdb inq = {
12154010Sfujita 	6,
12254010Sfujita 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
12354010Sfujita };
12454010Sfujita 
12554010Sfujita int
12654010Sfujita stident(sc, hd)
12754010Sfujita 	struct st_softc *sc;
12854010Sfujita 	struct hp_device *hd;
12954010Sfujita {
13054010Sfujita 	char idstr[32];
13154010Sfujita 	int unit;
13254010Sfujita 	register int ctlr, slave;
13354010Sfujita 	register int i, stat;
13454010Sfujita 	register int tries = 10;
13554010Sfujita 
13654010Sfujita 	ctlr = hd->hp_ctlr;
13754010Sfujita 	slave = hd->hp_slave;
13854010Sfujita 	unit = sc->sc_punit;
13954010Sfujita 
14054010Sfujita 	/*
14154010Sfujita 	 * See if unit exists and is a disk then read block size & nblocks.
14254010Sfujita 	 */
14354010Sfujita 	while ((stat = scsi_immed_command(ctlr, slave, unit,
14454010Sfujita 				  &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {
14554010Sfujita 		if (stat < 0 || --tries < 0)
14654010Sfujita 			return (-1);
14754010Sfujita 		DELAY(1000);
14854010Sfujita 	}
14954010Sfujita 
15054010Sfujita 	switch (inqbuf.type) {
15154010Sfujita 	case 1:		/* tape */
15254010Sfujita 		break;
15354010Sfujita 	default:	/* not a disk */
15454010Sfujita 		printf("stident: inqbuf.type = %d\n", inqbuf.type);
15554010Sfujita 		return (-1);
15654010Sfujita 	}
15754010Sfujita 
15854010Sfujita 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
15954010Sfujita 	for (i = 27; i > 23; --i)
16054010Sfujita 		if (idstr[i] != ' ')
16154010Sfujita 			break;
16254010Sfujita 	idstr[i+1] = 0;
16354010Sfujita 	for (i = 23; i > 7; --i)
16454010Sfujita 		if (idstr[i] != ' ')
16554010Sfujita 			break;
16654010Sfujita 	idstr[i+1] = 0;
16754010Sfujita 	for (i = 7; i >= 0; --i)
16854010Sfujita 		if (idstr[i] != ' ')
16954010Sfujita 			break;
17054010Sfujita 	idstr[i+1] = 0;
17154010Sfujita 	printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
17254010Sfujita 	       &idstr[24]);
17354010Sfujita 
17454010Sfujita 	return(inqbuf.type);
17554010Sfujita }
17654010Sfujita 
17754010Sfujita 
17854010Sfujita /*
17954010Sfujita  * Open
18054010Sfujita  */
18154010Sfujita 
18254010Sfujita int
18354010Sfujita stopen(dev, flag, type, p)
18454010Sfujita 	dev_t dev;
18554010Sfujita 	int flag, type;
18654010Sfujita 	struct proc *p;
18754010Sfujita {
18854010Sfujita 	register int unit = stunit(dev);
18954010Sfujita 	register struct st_softc *sc = &st_softc[unit];
19054010Sfujita 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
19154010Sfujita 	int ctlr  = sc->sc_dq.dq_ctlr;
19254010Sfujita 	int slave = sc->sc_dq.dq_slave;
19354010Sfujita 	int stat, retry = 9;
19454010Sfujita 
19554010Sfujita 	if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)
19654010Sfujita 		return(-1);
19754010Sfujita 	if (sc->sc_flags & STF_OPEN)
19854010Sfujita 		return(-1);
19954010Sfujita 
20054010Sfujita 	/* drive ready ? */
20154010Sfujita 	while ((stat = scsi_test_unit_rdy(ctlr, slave, 0)) != 0) {
20254010Sfujita 		scsi_request_sense(ctlr, slave, 0, sp, 8);
20354010Sfujita 
20454010Sfujita 		if (stat != STS_CHECKCOND) {
20554010Sfujita 			printf("st%d: stopen: %s\n", scsi_status(stat));
20654010Sfujita 			return(EIO);
20754010Sfujita 		}
20854010Sfujita 
20954010Sfujita 		if (retry-- < 0) {
21054010Sfujita 			printf("st%d: stopen: %s\n", sense_key(sp->key));
21154010Sfujita 			return(EIO);
21254010Sfujita 		}
21354010Sfujita 
21454010Sfujita 		DELAY(1000000);
21554010Sfujita 	}
21654010Sfujita 
21754010Sfujita 	sc->sc_ctty = tprintf_open(p);
21854010Sfujita 
21954010Sfujita 	sc->sc_flags |= STF_OPEN;
22054010Sfujita 	if (flag & FWRITE)
22154010Sfujita 		sc->sc_flags |= STF_WMODE;
22254010Sfujita 	sc->sc_flags &= ~STF_MOVED;
22354010Sfujita 
22454010Sfujita 	return(0);
22554010Sfujita }
22654010Sfujita 
22754010Sfujita /*ARGSUSED*/
22854010Sfujita stclose(dev)
22954010Sfujita 	dev_t dev;
23054010Sfujita {
23154010Sfujita 	register int unit = stunit(dev);
23254010Sfujita 	register struct st_softc *sc = &st_softc[unit];
23354010Sfujita 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
23454010Sfujita 	int ctlr  = sc->sc_hd->hp_ctlr;
23554010Sfujita 	int slave = sc->sc_hd->hp_slave;
23654010Sfujita 	int stat, retry = 9;
23754010Sfujita 
23854010Sfujita 	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
23954010Sfujita 		st_write_EOF(dev);
24054010Sfujita 	}
24154010Sfujita 
24254010Sfujita 	if ((minor(dev) & STDEV_NOREWIND) == 0) {
24354010Sfujita 		st_rewind(dev);
24454010Sfujita 	}
24554010Sfujita 
24654010Sfujita 	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
24754010Sfujita 
24854010Sfujita 	tprintf_close(sc->sc_ctty);
24954010Sfujita 
25054010Sfujita 	return(0);
25154010Sfujita }
25254010Sfujita 
25354010Sfujita /*
25454010Sfujita  * Strategy
25554010Sfujita  */
25654010Sfujita 
25754010Sfujita int
25854010Sfujita ststrategy(bp)
25954010Sfujita 	register struct buf *bp;
26054010Sfujita {
26154010Sfujita 	register int unit = stunit(bp->b_dev);
26254010Sfujita 	register struct buf *dp = &sttab[unit];
26354010Sfujita 	int s;
26454010Sfujita 
26554010Sfujita 	bp->av_forw = NULL;
26654010Sfujita 
26754010Sfujita 	s = splbio();
26854010Sfujita 
26954010Sfujita 	if (dp->b_actf == NULL)
27054010Sfujita 		dp->b_actf = bp;
27154010Sfujita 	else
27254010Sfujita 		dp->b_actl->av_forw = bp;
27354010Sfujita 
27454010Sfujita 	dp->b_actl = bp;
27554010Sfujita 
27654010Sfujita 	if (dp->b_active == 0) {
27754010Sfujita 		dp->b_active = 1;
27854010Sfujita 		stustart(unit);
27954010Sfujita 	}
28054010Sfujita 
28154010Sfujita 	splx(s);
28254010Sfujita }
28354010Sfujita 
28454010Sfujita int
28554010Sfujita stustart(unit)
28654010Sfujita 	register int unit;
28754010Sfujita {
28854010Sfujita 	register struct st_softc *sc = &st_softc[unit];
28954010Sfujita 	register struct hp_device *hp = sc->sc_hd;
29054010Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
29154010Sfujita 	register struct buf *bp = sttab[unit].b_actf;
29254010Sfujita 	register struct scsi_fmt_cdb *cmd;
29354010Sfujita 	long nblks;
29454010Sfujita 
29554010Sfujita 	cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
29654010Sfujita 	cmd->cdb[1] = 1;		/* unknown setup */
29754010Sfujita 
29854010Sfujita 	if (bp->b_flags & B_READ)
29954010Sfujita 		sc->sc_flags &= ~STF_WRTTN;
30054010Sfujita 	else
30154010Sfujita 		sc->sc_flags |= STF_WRTTN;
30254010Sfujita 
30354010Sfujita 	nblks = bp->b_bcount >> DEV_BSHIFT;
30454010Sfujita 
30554010Sfujita 	if (bp->b_bcount % DEV_BSIZE) {
30654010Sfujita 		tprintf(sc->sc_ctty,
30754010Sfujita 			"st%d: I/O not block aligned %d/%ld\n",
30854010Sfujita 			unit, DEV_BSIZE, bp->b_bcount);
30954010Sfujita 
31054010Sfujita 		bp->b_flags |= B_ERROR;
31154010Sfujita 		bp->b_error = EIO;
31254010Sfujita 
31354010Sfujita 		sttab[unit].b_errcnt = 0;
31454010Sfujita 		sttab[unit].b_actf = bp->b_actf;
31554010Sfujita 
31654010Sfujita 		bp->b_resid = 0;
31754010Sfujita 
31854010Sfujita 		biodone(bp);
31954010Sfujita 
32054010Sfujita 		if (sttab[unit].b_actf) {
32154010Sfujita 			stustart(unit);
32254010Sfujita 		} else {
32354010Sfujita 			sttab[unit].b_active = 0;
32454010Sfujita 		}
32554010Sfujita 	}
32654010Sfujita 
32754010Sfujita 	*(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);
32854010Sfujita 	*(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >>  8);
32954010Sfujita 	*(u_char *)(&cmd->cdb[4]) = (u_char)  nblks;
33054010Sfujita 
33154010Sfujita 	cmd->cdb[5] = 0;		/* unknown setup */
33254010Sfujita 
33354010Sfujita 	sc->sc_flags |= STF_MOVED;
33454010Sfujita 
33554010Sfujita 	dq->dq_cdb = cmd;
33654010Sfujita 	dq->dq_bp  = bp;
33754010Sfujita 	dq->dq_flags = 0;		/* No Disconnect */
33854010Sfujita 
33954010Sfujita 	if (screq(dq))
34054010Sfujita 		ststart(unit);
34154010Sfujita }
34254010Sfujita 
34354010Sfujita int
34454010Sfujita ststart(unit)
34554010Sfujita 	register int unit;
34654010Sfujita {
34754010Sfujita 	register struct st_softc *sc = &st_softc[unit];
34854010Sfujita 	register struct hp_device *hp = sc->sc_hd;
34954010Sfujita 
35054010Sfujita 	scstart(hp->hp_ctlr);
35154010Sfujita }
35254010Sfujita 
35354010Sfujita /*
35454010Sfujita  * Interrupt
35554010Sfujita  */
35654010Sfujita 
35754010Sfujita char *
35854010Sfujita sense_key(key)
35954010Sfujita 	int key;
36054010Sfujita {
36154010Sfujita 	if (key == 0)
36254010Sfujita 		return("No Sense");
36354010Sfujita 	else if (key == 2)
36454010Sfujita 		return("Not Ready");
36554010Sfujita 	else if (key == 3)
36654010Sfujita 		return("Medium Error");
36754010Sfujita 	else if (key == 4)
36854010Sfujita 		return("Hardware Error");
36954010Sfujita 	else if (key == 5)
37054010Sfujita 		return("Illegal Request");
37154010Sfujita 	else if (key == 6)
37254010Sfujita 		return("Unit Attention");
37354010Sfujita 	else if (key == 7)
37454010Sfujita 		return("Data Protect");
37554010Sfujita 	else if (key == 8)
37654010Sfujita 		return("No Data");
37754010Sfujita 	else if (key == 11)
37854010Sfujita 		return("Aborted Command");
37954010Sfujita 	else if (key == 13)
38054010Sfujita 		return("Volume Overflow");
38154010Sfujita 	else
38254010Sfujita 		return("Unknown Error");
38354010Sfujita }
38454010Sfujita 
38554010Sfujita int
38654010Sfujita stintr(unit, stat)
38754010Sfujita 	register int unit;
38854010Sfujita 	int stat;
38954010Sfujita {
39054010Sfujita 	register struct st_softc *sc = &st_softc[unit];
39154010Sfujita 	register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff;
39254010Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
39354010Sfujita 	register struct buf *bp = dq->dq_bp;
39454010Sfujita 	int ctlr  = dq->dq_ctlr;
39554010Sfujita 	int slave = dq->dq_slave;
39654010Sfujita 
39754010Sfujita 	if (bp->b_flags & B_READ) {
39855177Saki 		st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin);
39954010Sfujita 		if (dq->dq_imax > st_iostat[unit].imax) {
40054010Sfujita 			st_iostat[unit].imax = dq->dq_imax;
40154010Sfujita #ifdef ST_IOSTAT
40254010Sfujita 			printf("stintr: st%d  INPUT	MAX = %d, MIN = %d\n",
40354010Sfujita 			       unit, st_iostat[unit].imax, st_iostat[unit].imin);
40454010Sfujita #endif
40554010Sfujita 		}
40654010Sfujita 	} else {
40755177Saki 		st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin);
40854010Sfujita 		if (dq->dq_omax > st_iostat[unit].omax) {
40954010Sfujita 			st_iostat[unit].omax = dq->dq_omax;
41054010Sfujita #ifdef ST_IOSTAT
41154010Sfujita 			printf("stintr: st%d  OUTPUT	MAX = %d, MIN = %d\n",
41254010Sfujita 			       unit, st_iostat[unit].omax, st_iostat[unit].omin);
41354010Sfujita #endif
41454010Sfujita 		}
41554010Sfujita 	}
41654010Sfujita 	if (stat < 0) {
41754010Sfujita 		bp->b_flags |= B_ERROR;
41854010Sfujita 		bp->b_error = EIO;
41954010Sfujita 		goto done;
42054010Sfujita 	}
42154010Sfujita 
42254010Sfujita 	switch (stat) {
42354010Sfujita 	/* scsi command completed ok */
42454010Sfujita 	case 0:
42554010Sfujita 		bp->b_resid = 0;
42654010Sfujita 		break;
42754010Sfujita 
42854010Sfujita 	/* more status */
42954010Sfujita 	case STS_CHECKCOND:
43054010Sfujita 		scsi_request_sense(ctlr, slave, 0, xp, 8);
43154010Sfujita #ifdef DEBUG
43254010Sfujita 		printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2));
43354010Sfujita 		printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2));
43454010Sfujita 		printf("stintr: Sense Key = [%s]\n", sense_key(xp->key));
43554010Sfujita #endif
43654010Sfujita 		if (xp->valid) {
43754010Sfujita 			bp->b_resid = (u_long)((xp->info1 << 24) |
43854010Sfujita 					       (xp->info2 << 16) |
43954010Sfujita 					       (xp->info3 << 8) |
44054010Sfujita 					       (xp->info4));
44154010Sfujita 			bp->b_resid <<= DEV_BSHIFT;
44254010Sfujita 		}
44354010Sfujita 
44454010Sfujita 		if (xp->filemark) {		/* End of File */
44554010Sfujita 			tprintf(sc->sc_ctty, "st%d: End of File\n", unit);
44654010Sfujita 			bp->b_flags |= B_ERROR;
44754010Sfujita 			bp->b_error = EIO;
44854010Sfujita 			break;
44954010Sfujita 		}
45054010Sfujita 
45154010Sfujita 		if (xp->key) {
45254010Sfujita 			tprintf(sc->sc_ctty, "st%d: %s\n", unit, sense_key(xp->key));
45354010Sfujita 			bp->b_flags |= B_ERROR;
45454010Sfujita 			bp->b_error = EIO;
45554010Sfujita 			break;
45654010Sfujita 		}
45754010Sfujita 
45854010Sfujita 		if (xp->eom) {		/* End of TAPE */
45954010Sfujita 			tprintf(sc->sc_ctty, "st%d: End of Tape\n", unit);
46054010Sfujita 			bp->b_flags |= B_ERROR;
46154010Sfujita 			bp->b_error = ENOSPC;
46254010Sfujita 			break;
46354010Sfujita 		}
46454010Sfujita 
46554010Sfujita 		tprintf(sc->sc_ctty, "st%d: unknown scsi error\n", unit);
46654010Sfujita 		bp->b_flags |= B_ERROR;
46754010Sfujita 		bp->b_error = EIO;
46854010Sfujita 		break;
46954010Sfujita 
47054010Sfujita 	default:
47154010Sfujita 		printf("st%d: stintr unknown stat 0x%x\n", unit, stat);
47254010Sfujita 		break;
47354010Sfujita 	}
47454010Sfujita 
47554010Sfujita done:
47654010Sfujita 	sttab[unit].b_errcnt = 0;
47754010Sfujita 	sttab[unit].b_actf = bp->b_actf;
47854010Sfujita 
47954010Sfujita 	bp->b_resid = 0;
48054010Sfujita 
48154010Sfujita 	biodone(bp);
48254010Sfujita 
48354010Sfujita 	scfree(&sc->sc_dq);
48454010Sfujita 
48554010Sfujita 	if (sttab[unit].b_actf) {
48654010Sfujita 		stustart(unit);
48754010Sfujita 	} else {
48854010Sfujita 		sttab[unit].b_active = 0;
48954010Sfujita 	}
49054010Sfujita }
49154010Sfujita 
49254010Sfujita 
49354010Sfujita /*
49454010Sfujita  * RAW Device Routines
49554010Sfujita  */
49654010Sfujita 
49754010Sfujita 
49854010Sfujita stread(dev, uio)
49954010Sfujita 	dev_t dev;
50054010Sfujita 	struct uio *uio;
50154010Sfujita {
50254010Sfujita 	int unit = stunit(dev);
50354010Sfujita 
50454010Sfujita 	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));
50554010Sfujita }
50654010Sfujita 
50754010Sfujita stwrite(dev, uio)
50854010Sfujita 	dev_t dev;
50954010Sfujita 	struct uio *uio;
51054010Sfujita {
51154010Sfujita 	int unit = stunit(dev);
51254010Sfujita 
51354010Sfujita 	return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));
51454010Sfujita }
51554010Sfujita 
51654010Sfujita int
51754010Sfujita stioctl(dev, cmd, data, flag, p)
51854010Sfujita 	dev_t dev;
51954010Sfujita 	int cmd;
52054010Sfujita 	caddr_t data;
52154010Sfujita 	int flag;
52254010Sfujita 	struct proc *p;
52354010Sfujita {
52454010Sfujita 	return(ENXIO);
52554010Sfujita }
52654010Sfujita 
52754010Sfujita struct scsi_fmt_cdb st_cmd;
52854010Sfujita 
52954010Sfujita st_rewind(dev)
53054010Sfujita 	dev_t dev;
53154010Sfujita {
53254010Sfujita 	register int unit = stunit(dev);
53354010Sfujita 	register struct st_softc *sc = &st_softc[unit];
53454010Sfujita 	register struct scsi_fmt_cdb *cdb = &st_cmd;
53554010Sfujita 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
53654010Sfujita 	int ctlr, slave, stat;
53754010Sfujita 	int retry = 9;
53854010Sfujita 
53954010Sfujita 	ctlr  = sc->sc_hd->hp_ctlr;
54054010Sfujita 	slave = sc->sc_hd->hp_slave;
54154010Sfujita 
54254010Sfujita 	cdb->len = 6;
54354010Sfujita 
54454010Sfujita 	cdb->cdb[0] = CMD_REWIND;
54554010Sfujita 
54654010Sfujita 	cdb->cdb[1] = 1;	/* command finished soon */
54754010Sfujita 
54854010Sfujita 	cdb->cdb[2] = 0;
54954010Sfujita 	cdb->cdb[3] = 0;
55054010Sfujita 	cdb->cdb[4] = 0;
55154010Sfujita 
55254010Sfujita 	cdb->cdb[5] = 0;		/* unknown setup */
55354010Sfujita 
55454010Sfujita  rewind:
55554010Sfujita 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
55654010Sfujita 
55754010Sfujita 	if (stat == 0) {
55854010Sfujita 		return(1);
55954010Sfujita 	} else {
56054010Sfujita 		printf("st: rewind error\n");
56154010Sfujita 		scsi_request_sense(ctlr, slave, 0, sp, 8);
56254010Sfujita 		printf("st: status = 0x%x, sens key = 0x%x\n", stat, sp->key);
56354010Sfujita 
56454010Sfujita 		if (retry > 0) {
56554010Sfujita 			DELAY(1000000);
56654010Sfujita 			retry--;
56754010Sfujita 			goto rewind;
56854010Sfujita 		}
56954010Sfujita 
57054010Sfujita 		return(0);
57154010Sfujita 	}
57254010Sfujita }
57354010Sfujita 
57454010Sfujita st_write_EOF(dev)
57554010Sfujita 	dev_t dev;
57654010Sfujita {
57754010Sfujita 	register int unit = stunit(dev);
57854010Sfujita 	register struct st_softc *sc = &st_softc[unit];
57954010Sfujita 	register struct scsi_fmt_cdb *cdb = &st_cmd;
58054010Sfujita 	int ctlr, slave, stat;
58154010Sfujita 	int marks = 1;
58254010Sfujita 
58354010Sfujita 	ctlr  = sc->sc_hd->hp_ctlr;
58454010Sfujita 	slave = sc->sc_hd->hp_slave;
58554010Sfujita 
58654010Sfujita 	cdb->len = 6;
58754010Sfujita 
58854010Sfujita 	cdb->cdb[0] = CMD_WRITE_FILEMARK;
58954010Sfujita 
59054010Sfujita 	cdb->cdb[1] = 0;
59154010Sfujita 
59254010Sfujita 	cdb->cdb[2] = 0;
59354010Sfujita 	cdb->cdb[3] = 0;
59454010Sfujita 	cdb->cdb[4] = marks;
59554010Sfujita 
59654010Sfujita 	cdb->cdb[5] = 0;		/* unknown setup */
59754010Sfujita 
59854010Sfujita 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
59954010Sfujita 
60054010Sfujita 	if (stat == 0)
60154010Sfujita 		return(1);
60254010Sfujita 
60354010Sfujita 	printf("st: write EOF error\n");
60454010Sfujita 
60554010Sfujita 	return(0);
60654010Sfujita }
60754010Sfujita 
60854010Sfujita /*
60954010Sfujita  * Dump
61054010Sfujita  */
61154010Sfujita 
61254010Sfujita int
61354010Sfujita stdump(dev)
61454010Sfujita 	dev_t dev;
61554010Sfujita {
61654010Sfujita }
61754010Sfujita #endif
618