xref: /csrg-svn/sys/dev/scsi/sd.c (revision 55559)
154881Storek /*
254881Storek  * Copyright (c) 1990, 1992 The Regents of the University of California.
354881Storek  * All rights reserved.
454881Storek  *
554881Storek  * This software was developed by the Computer Systems Engineering group
654881Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
754881Storek  * contributed to Berkeley.
854881Storek  *
9*55559Storek  * All advertising materials mentioning features or use of this software
10*55559Storek  * must display the following acknowledgement:
11*55559Storek  *	This product includes software developed by the University of
12*55559Storek  *	California, Lawrence Berkeley Laboratories.
13*55559Storek  *
1454881Storek  * %sccs.include.redist.c%
1554881Storek  *
16*55559Storek  *	@(#)sd.c	5.3 (Berkeley) 07/23/92
1754881Storek  *
1854881Storek  * from: $Header: sd.c,v 1.18 92/06/11 17:55:56 torek Exp $
1954881Storek  */
2054881Storek 
2154881Storek /*
2254881Storek  * SCSI CCS (Command Command Set) disk driver.
2354881Storek  *
2454881Storek  * MACHINE INDEPENDENT (do not put machine dependent goo in here!)
2554881Storek  *
2654881Storek  * (from sd.c,v 1.7 90/12/15 14:11:26 van Exp)
2754881Storek  */
2854881Storek 
29*55559Storek #include <sys/param.h>
30*55559Storek #include <sys/systm.h>
31*55559Storek #include <sys/proc.h>
32*55559Storek #include <sys/buf.h>
33*55559Storek #include <sys/errno.h>
34*55559Storek #include <sys/device.h>
35*55559Storek #include <sys/disklabel.h>
36*55559Storek #include <sys/dkstat.h>
37*55559Storek #include <sys/disk.h>
38*55559Storek #include <sys/ioctl.h>
39*55559Storek #include <sys/malloc.h>
4054881Storek 
41*55559Storek #include <machine/cpu.h>
4254881Storek 
43*55559Storek #include "scsi.h"
44*55559Storek #include "disk.h"
45*55559Storek #include "scsivar.h"
46*55559Storek #include "scsi_ioctl.h"
4754881Storek 
4854881Storek #include "sdtrace.h"
4954881Storek 
50*55559Storek #ifdef sparc					/* XXX */
51*55559Storek #define SUN_LABEL_HACK				/* XXX */
52*55559Storek #endif						/* XXX */
5354881Storek 
5454881Storek #ifdef SUN_LABEL_HACK
55*55559Storek #include <sparc/sunos/sun_disklabel.h>
5654881Storek #endif
5754881Storek 
5854881Storek /*
5954881Storek  * Per-disk variables.
6054881Storek  *
6154881Storek  * sd_dk contains all the `disk' specific stuff (label/partitions,
6254881Storek  * transfer rate, etc).  We need only things that are special to
6354881Storek  * scsi disks.  Note that our blocks are in terms of DEV_BSIZE blocks.
6454881Storek  */
6554881Storek struct sd_softc {
6654881Storek 	struct	dkdevice sc_dk;	/* base disk device, must be first */
6754881Storek 	struct	unit sc_unit;	/* scsi unit */
6854881Storek 	pid_t	sc_format_pid;	/* process using "format" mode */
6954881Storek 	u_char	sc_type;	/* drive type */
7054881Storek 	u_char	sc_bshift;	/* convert device blocks to DEV_BSIZE blks */
7154881Storek 	short	sc_flags;	/* see below */
7254881Storek 	u_int	sc_blks;	/* number of blocks on device */
7354881Storek 	int	sc_blksize;	/* device block size in bytes */
7454881Storek 
7554881Storek 	/* should be in dkdevice?? */
7654881Storek 	struct	buf sc_tab;	/* transfer queue */
7754881Storek 
7854881Storek 	/* statistics */
7954881Storek 	long	sc_resets;	/* number of times reset */
8054881Storek 	long	sc_transfers;	/* count of total transfers */
8154881Storek 	long	sc_partials;	/* count of `partial' transfers */
8254881Storek 
8354881Storek 	/* for user formatting */
8454881Storek 	struct	scsi_cdb sc_cmd;
8554881Storek 	struct	scsi_fmt_sense sc_sense;
8654881Storek };
8754881Storek 
8854881Storek #define	SDF_ALIVE	1	/* drive OK for regular kernel use */
8954881Storek 
9054881Storek /* definition of the autoconfig driver */
9154881Storek int	sdmatch __P((struct device *, struct cfdata *, void *));
9254881Storek void	sdattach __P((struct device *, struct device *, void *));
9354881Storek 
9454881Storek struct cfdriver sdcd =
9554881Storek     { NULL, "sd", sdmatch, sdattach, DV_DISK, sizeof(struct sd_softc) };
9654881Storek 
9754881Storek /* definition of the unit driver, for hba */
9854881Storek void	sdigo __P((struct device *, struct scsi_cdb *));
9954881Storek void	sdgo __P((struct device *, struct scsi_cdb *));
10054881Storek void	sdintr __P((struct device *, int, int));
10154881Storek void	sdreset __P((struct unit *));
10254881Storek 
10354881Storek static struct unitdriver sdunitdriver = { /*sdgo, sdintr*/ sdreset };
10454881Storek 
10554881Storek /* definition of the disk driver, for kernel */
10654881Storek void	sdstrategy __P((struct buf *));
10754881Storek 
10854881Storek #ifdef notyet
10954881Storek static struct sddkdriver = { sdstrategy };
11054881Storek #endif
11154881Storek 
11254881Storek #ifdef DEBUG
11354881Storek int sddebug = 1;
11454881Storek #define SDB_ERROR	0x01
11554881Storek #define SDB_PARTIAL	0x02
11654881Storek #endif
11754881Storek 
11854881Storek #define	sdunit(x)	(minor(x) >> 3)
11954881Storek #define sdpart(x)	(minor(x) & 0x7)
12054881Storek 
12154881Storek #define	b_cylin		b_resid
12254881Storek 
12354881Storek #define	SDRETRY		2
12454881Storek 
12554881Storek /*
12654881Storek  * Table of scsi commands users are allowed to access via `format'
12754881Storek  * mode.  0 means not legal.  1 means `immediate' (doesn't need dma).
12854881Storek  * -1 means needs dma and/or wait for intr (i.e., `slow').
12954881Storek  */
13054881Storek static char legal_cmds[256] = {
13154881Storek /*****  0   1   2   3   4   5   6   7     8   9   A   B   C   D   E   F */
13254881Storek /*00*/	0,  0,  0,  0, -1,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13354881Storek /*10*/	0,  0,  1,  0,  0,  1,  0,  0,    0,  0,  1,  0,  0,  0,  0,  0,
13454881Storek /*20*/	0,  0,  0,  0,  0,  1,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13554881Storek /*30*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13654881Storek /*40*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13754881Storek /*50*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13854881Storek /*60*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
13954881Storek /*70*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14054881Storek /*80*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14154881Storek /*90*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14254881Storek /*a0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14354881Storek /*b0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14454881Storek /*c0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14554881Storek /*d0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14654881Storek /*e0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14754881Storek /*f0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14854881Storek };
14954881Storek 
15054881Storek int
15154881Storek sdmatch(parent, cf, aux)
15254881Storek 	struct device *parent;
15354881Storek 	register struct cfdata *cf;
15454881Storek 	void *aux;
15554881Storek {
15654881Storek 	register struct scsi_attach_args *sa = aux;
15754881Storek #ifdef DEBUG
15854881Storek 	char *whynot;
15954881Storek #endif
16054881Storek 
16154881Storek 	/*
16254881Storek 	 * unit number must match, or be given as `any'
16354881Storek 	 */
16454881Storek 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sa->sa_unit)
16554881Storek 		return (0);
16654881Storek 	/*
16754881Storek 	 * drive must be a disk, and of a kind we recognize
16854881Storek 	 */
16954881Storek 	if ((sa->sa_inq_status & STS_MASK) != STS_GOOD) {
17054881Storek #ifdef DEBUG
17154881Storek 		whynot = "INQUIRY failed";
17254881Storek #endif
17354881Storek 		goto notdisk;
17454881Storek 	}
17554881Storek 
17654881Storek 	switch (sa->sa_si.si_type & TYPE_TYPE_MASK) {
17754881Storek 
17854881Storek 	case TYPE_DAD:		/* disk */
17954881Storek 	case TYPE_WORM:		/* WORM */
18054881Storek 	case TYPE_ROM:		/* CD-ROM */
18154881Storek 	case TYPE_MO:		/* Magneto-optical */
18254881Storek 	case TYPE_JUKEBOX:	/* medium changer */
18354881Storek 		break;
18454881Storek 
18554881Storek 	default:
18654881Storek 	notdisk:
18754881Storek #ifdef DEBUG
18854881Storek 		whynot = "not a disk";
18954881Storek 		printf("[not matching `sd' at unit %d: %s]\n",
19054881Storek 		    sa->sa_unit, whynot);
19154881Storek #endif
19254881Storek 		return (0);
19354881Storek 	}
19454881Storek 
19554881Storek 	/*
19654881Storek 	 * It is a disk of some kind; take it.  We will figure out
19754881Storek 	 * the rest in the attach routine.
19854881Storek 	 */
19954881Storek 	return (1);
20054881Storek }
20154881Storek 
20254881Storek /*
20354881Storek  * Attach a disk (called after sdmatch returns true).
20454881Storek  * Note that this routine is never reentered (so we can use statics).
20554881Storek  */
20654881Storek void
20754881Storek sdattach(parent, self, aux)
20854881Storek 	struct device *parent, *self;
20954881Storek 	void *aux;
21054881Storek {
21154881Storek 	register struct sd_softc *sc = (struct sd_softc *)self;
21254881Storek 	register struct scsi_attach_args *sa = aux;
21354881Storek 	register int i;
21454881Storek 	char vendor[10], drive[17], rev[5];
21554881Storek 	static u_char capbuf[8];
21654881Storek 	static struct scsi_cdb cap = { CMD_READ_CAPACITY };
21754881Storek #ifdef SUN_LABEL_HACK
21854881Storek 	static struct scsi_cdb rd0 = { CMD_READ10, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
21954881Storek 	caddr_t sector;
22054881Storek #endif
22154881Storek 
22254881Storek 	/*
22354881Storek 	 * Declare our existence.
22454881Storek 	 */
22554881Storek 	sc->sc_unit.u_driver = &sdunitdriver;
22654881Storek 	scsi_establish(&sc->sc_unit, &sc->sc_dk.dk_dev, sa->sa_unit);
22754881Storek 
22854881Storek 	/*
22954881Storek 	 * Figure out what kind of disk this is.
23054881Storek 	 * We only accepted it if the inquiry succeeded, so
23154881Storek 	 * we can inspect those fields.
23254881Storek 	 */
23354881Storek 	i = (sa->sa_si.si_version >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
23454881Storek 	if (i == 1 || i == 2) {
23554881Storek 		scsi_inq_ansi((struct scsi_inq_ansi *)&sa->sa_si,
23654881Storek 		    vendor, drive, rev);
23754881Storek 		printf(": %s %s", vendor, drive);
23854881Storek 		/* XXX should we even ever bother printing this? */
23954881Storek 		if (rev[0])
24054881Storek 			printf(" %s", rev);
24154881Storek 	} else {
24254881Storek 		/* bleah */
24354881Storek 		bcopy("<unknown>", vendor, 10);
24454881Storek 		bcopy("<unknown>", drive, 10);
24554881Storek 		printf(": type 0x%x, qual 0x%x, ver %d",
24654881Storek 		    sa->sa_si.si_type, sa->sa_si.si_qual,
24754881Storek 		    sa->sa_si.si_version);
24854881Storek 	}
24954881Storek 
25054881Storek #ifdef notyet
25154881Storek 	sc->sc_dk.dk_driver = &sddkdriver;
25254881Storek 	dk_establish(&sc->sc_dk);
25354881Storek 	/* READ DISK LABEL HERE, UNLESS REMOVABLE MEDIUM... NEEDS THOUGHT */
25454881Storek #endif
25554881Storek 
25654881Storek 	CDB10(&cap)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
25754881Storek 	i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
25854881Storek 	    sc->sc_unit.u_targ, &cap, (char *)capbuf, sizeof capbuf, B_READ);
25954881Storek 	i &= STS_MASK;
26054881Storek 	if (i == STS_GOOD) {
26154881Storek #define	NUMBER(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3])
26254881Storek 		sc->sc_blks = NUMBER(&capbuf[0]);
26354881Storek 		sc->sc_blksize = NUMBER(&capbuf[4]);
26454881Storek 	} else if (i == STS_CHECKCOND &&
26554881Storek 	    (strcmp(vendor, "HP") == 0 && strcmp(drive, "S6300.650A") == 0)) {
26654881Storek 		/* XXX unformatted or nonexistent MO medium: fake it */
26754881Storek 		sc->sc_blks = 318664;
26854881Storek 		sc->sc_blksize = 1024;
26954881Storek 	} else {
27054881Storek 		printf(": unable to determine drive capacity [sts=%x]\n", i);
27154881Storek 		return;
27254881Storek 	}
27354881Storek 	/* return value from read capacity is last valid block, not nblocks */
27454881Storek 	sc->sc_blks++;
27554881Storek 	printf(", %u %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
27654881Storek 	if (sc->sc_blksize != DEV_BSIZE) {
27754881Storek 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
27854881Storek 			++sc->sc_bshift;
27954881Storek 		if (i != DEV_BSIZE) {
28054881Storek 			printf("%s: blksize not multiple of %d: cannot use\n",
28154881Storek 			    sc->sc_dk.dk_dev.dv_xname, DEV_BSIZE);
28254881Storek 			return;
28354881Storek 		}
28454881Storek 		sc->sc_blks <<= sc->sc_bshift;
28554881Storek 	}
28654881Storek 	sc->sc_type = sa->sa_si.si_type;	/* sufficient? */
28754881Storek 	sc->sc_dk.dk_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
28854881Storek 
28954881Storek 	sc->sc_dk.dk_label.d_secsize = 512;	/* XXX */
29054881Storek 
29154881Storek #ifdef SUN_LABEL_HACK
29254881Storek 	sector = (caddr_t)malloc(sc->sc_blksize, M_DEVBUF, M_NOWAIT);
29354881Storek 	CDB10(&rd0)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
29454881Storek 	i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
29554881Storek 	    sc->sc_unit.u_targ, &rd0, sector, sc->sc_blksize, B_READ);
29654881Storek 	if (i == STS_GOOD) {
29754881Storek 		printf("%s: <%s>\n", sc->sc_dk.dk_dev.dv_xname,
29854881Storek 		    ((struct sun_disklabel *)sector)->sl_text);
29954881Storek 		if (sun_disklabel(sector, &sc->sc_dk.dk_label))
30054881Storek 			sc->sc_flags |= SDF_ALIVE;
30154881Storek 		else
30254881Storek 			printf("%s: sun_disklabel fails\n",
30354881Storek 			    sc->sc_dk.dk_dev.dv_xname);
30454881Storek 	} else
30554881Storek 		printf("%s: could not read sector 0 for disk label\n",
30654881Storek 		    sc->sc_dk.dk_dev.dv_xname);
30754881Storek 	free(sector, M_DEVBUF);
30854881Storek #endif
30954881Storek }
31054881Storek 
31154881Storek /*
31254881Storek  * Reset a disk, after a SCSI bus reset.
31354881Storek  *
31454881Storek  * XXX untested and probably incomplete/incorrect
31554881Storek  */
31654881Storek void
31754881Storek sdreset(u)
31854881Storek 	register struct unit *u;
31954881Storek {
32054881Storek 	register struct sd_softc *sc = (struct sd_softc *)u->u_dev;
32154881Storek 
32254881Storek 	printf(" %s", sc->sc_dk.dk_dev.dv_xname);
32354881Storek 	sc->sc_resets++;
32454881Storek }
32554881Storek 
32654881Storek /* dev_t is short, must use prototype syntax */
32754881Storek int
32854881Storek sdopen(dev_t dev, int flags, int ifmt, struct proc *p)
32954881Storek {
33054881Storek 	register int unit = sdunit(dev);
33154881Storek 	register struct sd_softc *sc;
33254881Storek 
33354881Storek 	if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL)
33454881Storek 		return (ENXIO);
33554881Storek 	if ((sc->sc_flags & SDF_ALIVE) == 0 &&
33654881Storek 	    !suser(p->p_ucred, &p->p_acflag))
33754881Storek 		return (ENXIO);
33854881Storek 	return (0);
33954881Storek }
34054881Storek 
34154881Storek int
34254881Storek sdclose(dev_t dev, int flags, int ifmt, struct proc *p)
34354881Storek {
34454881Storek 	register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
34554881Storek 
34654881Storek 	sc->sc_format_pid = 0;
34754881Storek 	return (0);
34854881Storek }
34954881Storek 
35054881Storek /*
35154881Storek  * This routine is called for partial block transfers and non-aligned
35254881Storek  * transfers (the latter only being possible on devices with a block size
35354881Storek  * larger than DEV_BSIZE).  The operation is performed in three steps
35454881Storek  * using a locally allocated buffer:
35554881Storek  *	1. transfer any initial partial block
35654881Storek  *	2. transfer full blocks
35754881Storek  *	3. transfer any final partial block
35854881Storek  */
35954881Storek static void
36054881Storek sdlblkstrat(bp, bsize)
36154881Storek 	register struct buf *bp;
36254881Storek 	register int bsize;
36354881Storek {
36454881Storek 	register int bn, resid, boff, count;
36554881Storek 	register caddr_t addr, cbuf;
36654881Storek 	struct buf tbp;
36754881Storek 
36854881Storek 	cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
36954881Storek 	bzero((caddr_t)&tbp, sizeof tbp);
37054881Storek 	tbp.b_proc = curproc;
37154881Storek 	tbp.b_dev = bp->b_dev;
37254881Storek 	bn = bp->b_blkno;
37354881Storek 	resid = bp->b_bcount;
37454881Storek 	addr = bp->b_un.b_addr;
37554881Storek #ifdef DEBUG
37654881Storek 	if (sddebug & SDB_PARTIAL)
37754881Storek 		printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
37854881Storek 		       bp, bp->b_flags, bn, resid, addr);
37954881Storek #endif
38054881Storek 
38154881Storek 	while (resid > 0) {
38254881Storek 		boff = dbtob(bn) & (bsize - 1);
38354881Storek 		if (boff || resid < bsize) {
38454881Storek 			struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
38554881Storek 			sc->sc_partials++;
38655161Spendry 			count = min(resid, bsize - boff);
38754881Storek 			tbp.b_flags = B_BUSY | B_READ;
38854881Storek 			tbp.b_blkno = bn - btodb(boff);
38954881Storek 			tbp.b_un.b_addr = cbuf;
39054881Storek 			tbp.b_bcount = bsize;
39154881Storek #ifdef DEBUG
39254881Storek 			if (sddebug & SDB_PARTIAL)
39354881Storek 				printf(" readahead: bn %x cnt %x off %x addr %x\n",
39454881Storek 				       tbp.b_blkno, count, boff, addr);
39554881Storek #endif
39654881Storek 			sdstrategy(&tbp);
39754881Storek 			biowait(&tbp);
39854881Storek 			if (tbp.b_flags & B_ERROR) {
39954881Storek 				bp->b_flags |= B_ERROR;
40054881Storek 				bp->b_error = tbp.b_error;
40154881Storek 				break;
40254881Storek 			}
40354881Storek 			if (bp->b_flags & B_READ) {
40454881Storek 				bcopy(&cbuf[boff], addr, count);
40554881Storek 				goto done;
40654881Storek 			}
40754881Storek 			bcopy(addr, &cbuf[boff], count);
40854881Storek #ifdef DEBUG
40954881Storek 			if (sddebug & SDB_PARTIAL)
41054881Storek 				printf(" writeback: bn %x cnt %x off %x addr %x\n",
41154881Storek 				       tbp.b_blkno, count, boff, addr);
41254881Storek #endif
41354881Storek 		} else {
41454881Storek 			count = resid & ~(bsize - 1);
41554881Storek 			tbp.b_blkno = bn;
41654881Storek 			tbp.b_un.b_addr = addr;
41754881Storek 			tbp.b_bcount = count;
41854881Storek #ifdef DEBUG
41954881Storek 			if (sddebug & SDB_PARTIAL)
42054881Storek 				printf(" fulltrans: bn %x cnt %x addr %x\n",
42154881Storek 				       tbp.b_blkno, count, addr);
42254881Storek #endif
42354881Storek 		}
42454881Storek 		tbp.b_flags = B_BUSY | (bp->b_flags & B_READ);
42554881Storek 		sdstrategy(&tbp);
42654881Storek 		biowait(&tbp);
42754881Storek 		if (tbp.b_flags & B_ERROR) {
42854881Storek 			bp->b_flags |= B_ERROR;
42954881Storek 			bp->b_error = tbp.b_error;
43054881Storek 			break;
43154881Storek 		}
43254881Storek done:
43354881Storek 		bn += btodb(count);
43454881Storek 		resid -= count;
43554881Storek 		addr += count;
43654881Storek #ifdef DEBUG
43754881Storek 		if (sddebug & SDB_PARTIAL)
43854881Storek 			printf(" done: bn %x resid %x addr %x\n",
43954881Storek 			       bn, resid, addr);
44054881Storek #endif
44154881Storek 	}
44254881Storek 	free(cbuf, M_DEVBUF);
44354881Storek 	biodone(bp);
44454881Storek }
44554881Storek 
44654881Storek /*
44754881Storek  * Start a transfer on sc as described by bp
44854881Storek  * (i.e., call hba or target start).
44954881Storek  * If in format mode, we may not need dma.
45054881Storek  */
45154881Storek #define sdstart(sc, bp) { \
45254881Storek 	SD_TRACE(T_START, sc, bp); \
45354881Storek 	if ((sc)->sc_format_pid && legal_cmds[(sc)->sc_cmd.cdb_bytes[0]] > 0) \
45454881Storek 		(*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
45554881Storek 		    &(sc)->sc_unit.u_forw, (struct buf *)NULL, \
45654881Storek 		    sdigo, &(sc)->sc_dk.dk_dev); \
45754881Storek 	else \
45854881Storek 		(*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
45954881Storek 		    &(sc)->sc_unit.u_forw, bp, sdgo, &(sc)->sc_dk.dk_dev); \
46054881Storek }
46154881Storek 
46254881Storek void
46354881Storek sdstrategy(bp)
46454881Storek 	register struct buf *bp;
46554881Storek {
46654881Storek 	register struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
46754881Storek 	register int s;
46854881Storek 
46954881Storek 	if (sc->sc_format_pid) {
47054881Storek 		/* XXXXXXXXX SHOULD NOT COMPARE curproc IN HERE!?! */
47154881Storek 		/*
47254881Storek 		 * In format mode, only allow the owner to mess
47354881Storek 		 * with the drive.  Skip all the partition checks.
47454881Storek 		 */
47554881Storek 		if (sc->sc_format_pid != curproc->p_pid) {
47654881Storek 			bp->b_error = EPERM;
47754881Storek 			bp->b_flags |= B_ERROR;
47854881Storek 			biodone(bp);
47954881Storek 			return;
48054881Storek 		}
48154881Storek 		bp->b_cylin = 0;
48254881Storek 	} else {
48354881Storek 		register daddr_t bn = bp->b_blkno;
48454881Storek 		register int sz = howmany(bp->b_bcount, DEV_BSIZE);
48554881Storek 		register struct partition *p;
48654881Storek 
48754881Storek 		/*
48854881Storek 		 * Make sure transfer is within partition.
48954881Storek 		 * If it starts at the end, return EOF; if
49054881Storek 		 * it extends past the end, truncate it.
49154881Storek 		 */
49254881Storek 		p = &sc->sc_dk.dk_label.d_partitions[sdpart(bp->b_dev)];
49354881Storek 		if ((unsigned)bn >= p->p_size) {
49454881Storek 			if ((unsigned)bn > p->p_size) {
49554881Storek 				bp->b_error = EINVAL;
49654881Storek 				bp->b_flags |= B_ERROR;
49754881Storek 			} else
49854881Storek 				bp->b_resid = bp->b_bcount;
49954881Storek 			biodone(bp);
50054881Storek 			return;
50154881Storek 		}
50254881Storek 		if (bn + sz > p->p_size) {
50354881Storek 			sz = p->p_size - bn;
50454881Storek 			bp->b_bcount = dbtob(sz);
50554881Storek 		}
50654881Storek 		/*
50754881Storek 		 * Non-aligned or partial-block transfers handled specially.
50854881Storek 		 * SHOULD THIS BE AT A HIGHER LEVEL?
50954881Storek 		 */
51054881Storek 		s = sc->sc_blksize - 1;
51154881Storek 		if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
51254881Storek 			sdlblkstrat(bp, sc->sc_blksize);
51354881Storek 			return;
51454881Storek 		}
51554881Storek 		bp->b_cylin = (bn + p->p_offset) >> sc->sc_bshift;
51654881Storek 	}
51754881Storek 
51854881Storek 	/*
51954881Storek 	 * Transfer valid, or format mode.  Queue the request
52054881Storek 	 * on the drive, and maybe try to start it.
52154881Storek 	 */
52254881Storek 	s = splbio();
52354881Storek 	disksort(&sc->sc_tab, bp);
52454881Storek 	if (sc->sc_tab.b_active == 0) {
52554881Storek 		sc->sc_tab.b_active = 1;
52654881Storek 		sdstart(sc, bp);
52754881Storek 	}
52854881Storek 	splx(s);
52954881Storek }
53054881Storek 
53154881Storek int
53254881Storek sderror(sc, stat)
53354881Storek 	register struct sd_softc *sc;
53454881Storek 	register int stat;
53554881Storek {
53654881Storek 	register struct scsi_sense *sn;
53754881Storek 	int retry = 0;
53854881Storek 
53954881Storek 	sc->sc_sense.status = stat;
54054881Storek 	if ((stat & STS_MASK) == STS_CHECKCOND) {
54154881Storek 		sn = (struct scsi_sense *)sc->sc_sense.sense;
54254881Storek 		stat = scsi_request_sense(sc->sc_unit.u_hba,
54354881Storek 		    sc->sc_unit.u_targ, sc->sc_unit.u_unit,
54454881Storek 		    (caddr_t)sn, sizeof sc->sc_sense.sense);
54554881Storek 		sc->sc_sense.status = stat;	/* ??? */
54654881Storek 		if ((stat & STS_MASK) != STS_GOOD) {
54754881Storek 			printf("%s: sense failed, status %x\n",
54854881Storek 			    sc->sc_dk.dk_dev.dv_xname, stat);
54954881Storek 			return (0);
55054881Storek 		}
55154881Storek 		printf("%s: scsi sense class %d, code %d",
55254881Storek 		    sc->sc_dk.dk_dev.dv_xname,
55354881Storek 		    SENSE_ECLASS(sn), SENSE_ECODE(sn));
55454881Storek 		if (SENSE_ISXSENSE(sn) && XSENSE_ISSTD(sn)) {
55554881Storek 			int key;
55654881Storek 
55754881Storek 			/*
55854881Storek 			 * Standard extended sense: can examine sense key
55954881Storek 			 * and (if valid) info.
56054881Storek 			 */
56154881Storek 			key = XSENSE_KEY(sn);
56254881Storek 			printf(", key %d", key);
56354881Storek 			if (XSENSE_IVALID(sn))
56454881Storek 				printf(", blk %d", XSENSE_INFO(sn));
56554881Storek 			/* no sense or recovered error, try again */
56654881Storek 			if (key == 0 || key == 1)
56754881Storek 				retry = 1;
56854881Storek 		}
56954881Storek 		printf("\n");
57054881Storek 	}
57154881Storek 	return (retry);
57254881Storek }
57354881Storek 
57454881Storek /*
57554881Storek  * sdigo is called from the hba driver when it has got the scsi bus
57654881Storek  * for us, and we were doing a format op that did not need dma.
57754881Storek  */
57854881Storek void
57954881Storek sdigo(sc0, cdb)
58054881Storek 	struct device *sc0;
58154881Storek 	struct scsi_cdb *cdb;
58254881Storek {
58354881Storek 	register struct sd_softc *sc = (struct sd_softc *)sc0;
58454881Storek 	register struct buf *bp = sc->sc_tab.b_actf;
58554881Storek 	register int stat;
58654881Storek 
58754881Storek 	stat = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
58854881Storek 	    sc->sc_unit.u_targ, &sc->sc_cmd, bp->b_un.b_addr, bp->b_bcount,
58954881Storek 	    bp->b_flags & B_READ);
59054881Storek 	sc->sc_sense.status = stat;
59154881Storek 	if (stat & 0xfe) {		/* XXX */
59254881Storek 		(void) sderror(sc, stat);
59354881Storek 		bp->b_flags |= B_ERROR;
59454881Storek 		bp->b_error = EIO;
59554881Storek 	}
59654881Storek 	/*
59754881Storek 	 * Done with SCSI bus, before we `ought' to be.  Release it.
59854881Storek 	 */
59954881Storek 	(*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
60054881Storek 	bp->b_resid = 0;
60154881Storek 	sc->sc_tab.b_errcnt = 0;
60254881Storek 	sc->sc_tab.b_actf = bp->b_actf;
60354881Storek 	biodone(bp);
60454881Storek 	if ((bp = sc->sc_tab.b_actf) == NULL)
60554881Storek 		sc->sc_tab.b_active = 0;
60654881Storek 	else
60754881Storek 		sdstart(sc, bp);
60854881Storek }
60954881Storek 
61054881Storek /*
61154881Storek  * sdgo is called from the hba driver or target code when it has
61254881Storek  * allocated the scsi bus and DMA resources and target datapath for us.
61354881Storek  */
61454881Storek void
61554881Storek sdgo(sc0, cdb)
61654881Storek 	struct device *sc0;
61754881Storek 	register struct scsi_cdb *cdb;
61854881Storek {
61954881Storek 	register struct sd_softc *sc = (struct sd_softc *)sc0;
62054881Storek 	register struct buf *bp = sc->sc_tab.b_actf;
62154881Storek 	register int n;
62254881Storek 	register unsigned int u;
62354881Storek 
62454881Storek 	SD_TRACE(T_MKCDB, sc, bp);
62554881Storek 	if (sc->sc_format_pid) {
62654881Storek 		*cdb = sc->sc_cmd;
62754881Storek 		n = 0;
62854881Storek 	} else {
62954881Storek 		CDB10(cdb)->cdb_cmd = bp->b_flags & B_READ ? CMD_READ10 :
63054881Storek 		    CMD_WRITE10;
63154881Storek 		CDB10(cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
63254881Storek 		u = bp->b_cylin;
63354881Storek 		CDB10(cdb)->cdb_lbah = u >> 24;
63454881Storek 		CDB10(cdb)->cdb_lbahm = u >> 16;
63554881Storek 		CDB10(cdb)->cdb_lbalm = u >> 8;
63654881Storek 		CDB10(cdb)->cdb_lbal = u;
63754881Storek 		CDB10(cdb)->cdb_xxx = 0;
63854881Storek 		n = sc->sc_blksize - 1;
63954881Storek 		u = (bp->b_bcount + n) >> (DEV_BSHIFT + sc->sc_bshift);
64054881Storek 		CDB10(cdb)->cdb_lenh = u >> 8;
64154881Storek 		CDB10(cdb)->cdb_lenl = u;
64254881Storek 		CDB10(cdb)->cdb_ctrl = 0;
64354881Storek 		n = (bp->b_bcount & n) != 0;
64454881Storek #ifdef DEBUG
64554881Storek 		if (n)
64654881Storek 			printf("%s: partial block xfer -- %x bytes\n",
64754881Storek 			    sc->sc_dk.dk_dev.dv_xname, bp->b_bcount);
64854881Storek #endif
64954881Storek 		sc->sc_transfers++;
65054881Storek 	}
65154881Storek 	if ((*sc->sc_unit.u_go)(sc->sc_unit.u_updev, sc->sc_unit.u_targ,
65254881Storek 	    sdintr, (void *)sc, bp, n) == 0) {
65354881Storek #ifdef notyet
65454881Storek 		sc->sc_dk.dk_busy = 1;
65554881Storek 		sc->sc_dk.dk_seek++;	/* XXX */
65654881Storek 		sc->sc_dk.dk_xfer++;
65754881Storek 		sc->sc_dk.dk_wds += bp->b_bcount >> 6;
65854881Storek #endif
65954881Storek 		return;
66054881Storek 	}
66154881Storek 	/*
66254881Storek 	 * Some sort of nasty unrecoverable error: clobber the
66354881Storek 	 * transfer.  Call the bus release function first, though.
66454881Storek 	 */
66554881Storek 	(*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
66654881Storek #ifdef DEBUG
66754881Storek 	if (sddebug & SDB_ERROR)
66854881Storek 		printf("%s: sdgo: %s adr %d blk %d len %d ecnt %d\n",
66954881Storek 		    sc->sc_dk.dk_dev.dv_xname,
67054881Storek 		    bp->b_flags & B_READ? "read" : "write",
67154881Storek 		    bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
67254881Storek 		    sc->sc_tab.b_errcnt);
67354881Storek #endif
67454881Storek 	bp->b_flags |= B_ERROR;
67554881Storek 	bp->b_error = EIO;
67654881Storek 	bp->b_resid = 0;
67754881Storek 	sc->sc_tab.b_errcnt = 0;
67854881Storek 	sc->sc_tab.b_actf = bp->b_actf;
67954881Storek 	biodone(bp);
68054881Storek 	if ((bp = sc->sc_tab.b_actf) == NULL)
68154881Storek 		sc->sc_tab.b_active = 0;
68254881Storek 	else
68354881Storek 		sdstart(sc, bp);
68454881Storek }
68554881Storek 
68654881Storek /*
68754881Storek  * A transfer finished (or, someday, disconnected).
68854881Storek  * We are already off the target/hba queues.
68954881Storek  * Restart this one for error recovery, or start the next, as appropriate.
69054881Storek  */
69154881Storek void
69254881Storek sdintr(sc0, stat, resid)
69354881Storek 	struct device *sc0;
69454881Storek 	int stat, resid;
69554881Storek {
69654881Storek 	register struct sd_softc *sc = (struct sd_softc *)sc0;
69754881Storek 	register struct buf *bp = sc->sc_tab.b_actf;
69854881Storek 	int retry;
69954881Storek 
70054881Storek 	if (bp == NULL)
70154881Storek 		panic("sdintr");
70254881Storek 	SD_TRACE(T_INTR, sc, bp);
70354881Storek #ifdef notyet
70454881Storek 	sc->sc_dk.dk_busy = 0;
70554881Storek #endif
70654881Storek 	if ((stat & STS_MASK) != STS_GOOD) {
70754881Storek #ifdef DEBUG
70854881Storek 		if (sddebug & SDB_ERROR)
70954881Storek 			printf("%s: sdintr scsi status 0x%x resid %d\n",
71054881Storek 			    sc->sc_dk.dk_dev.dv_xname, stat, resid);
71154881Storek #endif
71254881Storek 		retry = sderror(sc, stat);
71354881Storek 		if (retry && ++sc->sc_tab.b_errcnt <= SDRETRY) {
71454881Storek 			printf("%s: retry %d\n",
71554881Storek 			    sc->sc_dk.dk_dev.dv_xname, sc->sc_tab.b_errcnt);
71654881Storek 			goto restart;
71754881Storek 		}
71854881Storek 		bp->b_flags |= B_ERROR;
71954881Storek 		bp->b_error = EIO;
72054881Storek 	}
72154881Storek 	bp->b_resid = resid;
72254881Storek 	sc->sc_tab.b_errcnt = 0;
72354881Storek 	sc->sc_tab.b_actf = bp->b_actf;
72454881Storek 	biodone(bp);
72554881Storek 	if ((bp = sc->sc_tab.b_actf) == NULL)
72654881Storek 		sc->sc_tab.b_active = 0;
72754881Storek 	else {
72854881Storek restart:
72954881Storek 		sdstart(sc, bp);
73054881Storek 	}
73154881Storek }
73254881Storek 
73354881Storek int
73454881Storek sdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
73554881Storek {
73654881Storek 	register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
73754881Storek #ifdef COMPAT_SUNOS
73854881Storek 	int error;
73954881Storek 
74054881Storek 	error = sun_dkioctl(&sc->sc_dk, cmd, data, sdpart(dev));
74154881Storek 	if (error >= 0)
74254881Storek 		return (error);
74354881Storek #endif
74454881Storek 	switch (cmd) {
74554881Storek 
74654881Storek 	case SDIOCSFORMAT:
74754881Storek 		/* take this device into or out of "format" mode */
74854881Storek 		if (!suser(p->p_ucred, &p->p_acflag))
74954881Storek 			return (EPERM);
75054881Storek 		if (*(int *)data) {
75154881Storek 			if (sc->sc_format_pid)
75254881Storek 				return (EPERM);
75354881Storek 			sc->sc_format_pid = p->p_pid;
75454881Storek 		} else
75554881Storek 			sc->sc_format_pid = 0;
75654881Storek 		break;
75754881Storek 
75854881Storek 	case SDIOCGFORMAT:
75954881Storek 		/* find out who has the device in format mode */
76054881Storek 		*(int *)data = sc->sc_format_pid;
76154881Storek 		break;
76254881Storek 
76354881Storek 	case SDIOCSCSICOMMAND:
76454881Storek #define cdb ((struct scsi_cdb *)data)
76554881Storek 		/*
76654881Storek 		 * Save what user gave us as SCSI cdb to use with next
76754881Storek 		 * read or write to the char device.
76854881Storek 		 */
76954881Storek 		if (sc->sc_format_pid != p->p_pid)
77054881Storek 			return (EPERM);
77154881Storek 		if (legal_cmds[cdb->cdb_bytes[0]] == 0)
77254881Storek 			return (EINVAL);
77354881Storek 		sc->sc_cmd = *cdb;
77454881Storek #undef	cdb
77554881Storek 		break;
77654881Storek 
77754881Storek 	case SDIOCSENSE:
77854881Storek 		/*
77954881Storek 		 * return the SCSI sense data saved after the last
78054881Storek 		 * operation that completed with "check condition" status.
78154881Storek 		 */
78254881Storek 		sc->sc_sense = *(struct scsi_fmt_sense *)data;
78354881Storek 		break;
78454881Storek 
78554881Storek 	default:
78654881Storek 		return (ENOTTY);
78754881Storek 	}
78854881Storek 	return (0);
78954881Storek }
79054881Storek 
79154881Storek int
79254881Storek sdsize(dev_t dev)
79354881Storek {
79454881Storek 	register int unit = sdunit(dev);
79554881Storek 	register struct sd_softc *sc;
79654881Storek 
79754881Storek 	if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
79854881Storek 	    (sc->sc_flags & SDF_ALIVE) == 0)
79954881Storek 		return (-1);
80054881Storek 	return (sc->sc_dk.dk_label.d_partitions[sdpart(dev)].p_size);
80154881Storek }
80254881Storek 
80354881Storek /*
80454881Storek  * Write `len' bytes from address `addr' to drive and partition in `dev',
80554881Storek  * at block blkoff from the beginning of the partition.  The address is
80654881Storek  * either kernel virtual or physical (some machines may never use one or
80754881Storek  * the other, but we need it in the protocol to stay machine-independent).
80854881Storek  */
80954881Storek int
81054881Storek sddump(dev_t dev, daddr_t blkoff, caddr_t addr, int len)
81154881Storek {
81254881Storek 	register struct sd_softc *sc;
81354881Storek 	register struct partition *p;
81454881Storek 	register daddr_t bn, n, nblks;
81554881Storek 	register struct hba_softc *hba;
81654881Storek 	register int stat, unit;
81754881Storek 	struct scsi_cdb cdb;
81854881Storek 
81954881Storek 	/* drive ok? */
82054881Storek 	unit = sdunit(dev);
82154881Storek 	if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
82254881Storek 	    (sc->sc_flags & SDF_ALIVE) == 0)
82354881Storek 		return (ENXIO);
82454881Storek 
82554881Storek 	/* blocks in range? */
82654881Storek 	p = &sc->sc_dk.dk_label.d_partitions[sdpart(dev)];
82754881Storek 	n = (len + sc->sc_blksize - 1) >> DEV_BSHIFT;
82854881Storek 	if (blkoff < 0 || blkoff >= p->p_size || blkoff + n > p->p_size)
82954881Storek 		return (EINVAL);
83054881Storek 	bn = blkoff + p->p_offset;
83154881Storek 	bn >>= sc->sc_bshift;
83254881Storek 
83354881Storek 	/* scsi bus idle? */
83454881Storek 	hba = sc->sc_unit.u_hba;
83554881Storek 	if (hba->hba_head) {
83654881Storek 		(*hba->hba_driver->hd_reset)(hba, 0);
83754881Storek 		printf("[reset %s] ", sc->sc_dk.dk_dev.dv_xname);
83854881Storek 	}
83954881Storek 
84054881Storek 	CDB10(&cdb)->cdb_cmd = CMD_WRITE10;
84154881Storek 	CDB10(&cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
84254881Storek 	CDB10(&cdb)->cdb_xxx = 0;
84354881Storek 	CDB10(&cdb)->cdb_ctrl = 0;
84454881Storek 
84554881Storek #define	DUMP_MAX	(32 * 1024)	/* no more than 32k per write */
84654881Storek 	for (;;) {
84754881Storek 		if ((n = len) > DUMP_MAX)
84854881Storek 			n = DUMP_MAX;
84954881Storek 		CDB10(&cdb)->cdb_lbah = bn >> 24;
85054881Storek 		CDB10(&cdb)->cdb_lbahm = bn >> 16;
85154881Storek 		CDB10(&cdb)->cdb_lbalm = bn >> 8;
85254881Storek 		CDB10(&cdb)->cdb_lbal = bn;
85354881Storek 		nblks = n >> (DEV_BSHIFT + sc->sc_bshift);
85454881Storek 		CDB10(&cdb)->cdb_lenh = nblks >> 8;
85554881Storek 		CDB10(&cdb)->cdb_lenl = nblks;
85654881Storek 		stat = hba->hba_driver->hd_dump(hba, sc->sc_unit.u_targ,
85754881Storek 		    &cdb, addr, n);
85854881Storek 		if ((stat & STS_MASK) != STS_GOOD) {
85954881Storek 			printf("%s: scsi write error 0x%x\ndump ",
86054881Storek 			    sc->sc_dk.dk_dev.dv_xname, stat);
86154881Storek 			return (EIO);
86254881Storek 		}
86354881Storek 		if ((len -= n) == 0)
86454881Storek 			return (0);
86554881Storek 		addr += n;
86654881Storek 		bn += nblks;
86754881Storek 	}
86854881Storek }
869