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