xref: /csrg-svn/sys/hp300/dev/sd.c (revision 53929)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1990 The Regents of the University of California.
341480Smckusick  * All rights reserved.
441480Smckusick  *
541480Smckusick  * This code is derived from software contributed to Berkeley by
641480Smckusick  * Van Jacobson of Lawrence Berkeley Laboratory.
741480Smckusick  *
841480Smckusick  * %sccs.include.redist.c%
941480Smckusick  *
10*53929Shibler  *	@(#)sd.c	7.13 (Berkeley) 06/05/92
1141480Smckusick  */
1241480Smckusick 
1341480Smckusick /*
1441480Smckusick  * SCSI CCS (Command Command Set) disk driver.
1541480Smckusick  */
1641480Smckusick #include "sd.h"
1741480Smckusick #if NSD > 0
1841480Smckusick 
1941480Smckusick #ifndef lint
20*53929Shibler static char rcsid[] = "$Header: /usr/src/sys/hp300/dev/RCS/sd.c,v 1.2 92/04/10 20:48:35 mike Exp $";
2141480Smckusick #endif
2241480Smckusick 
2345788Sbostic #include "sys/param.h"
2445788Sbostic #include "sys/systm.h"
2545788Sbostic #include "sys/buf.h"
2645788Sbostic #include "sys/dkstat.h"
2745788Sbostic #include "sys/disklabel.h"
2845788Sbostic #include "sys/malloc.h"
2945788Sbostic #include "sys/proc.h"
3041480Smckusick 
31*53929Shibler #include "hp/dev/device.h"
3249132Skarels #include "scsireg.h"
3345788Sbostic #include "vm/vm_param.h"
3449132Skarels #include "vm/lock.h"
3551118Smarc #include "vm/vm_prot.h"
3645788Sbostic #include "vm/pmap.h"
3745750Smckusick 
3841480Smckusick extern int scsi_test_unit_rdy();
3941480Smckusick extern int scsi_request_sense();
4041480Smckusick extern int scsi_inquiry();
4141480Smckusick extern int scsi_read_capacity();
4241480Smckusick extern int scsi_tt_write();
4341480Smckusick extern int scsireq();
4441480Smckusick extern int scsiustart();
4541480Smckusick extern int scsigo();
4641480Smckusick extern void scsifree();
4741480Smckusick extern void scsireset();
4849304Shibler extern void scsi_delay();
4941480Smckusick 
5041480Smckusick extern void disksort();
5141480Smckusick extern void biodone();
5241480Smckusick extern int physio();
5341480Smckusick extern void TBIS();
5441480Smckusick 
5541480Smckusick int	sdinit();
5641480Smckusick void	sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
5741480Smckusick 
5841480Smckusick struct	driver sddriver = {
5941480Smckusick 	sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr,
6041480Smckusick };
6141480Smckusick 
6241480Smckusick struct	size {
6341480Smckusick 	u_long	strtblk;
6441480Smckusick 	u_long	endblk;
6541480Smckusick 	int	nblocks;
6641480Smckusick };
6741480Smckusick 
6841480Smckusick struct sdinfo {
6941480Smckusick 	struct	size part[8];
7041480Smckusick };
7141480Smckusick 
7241480Smckusick /*
7341480Smckusick  * since the SCSI standard tends to hide the disk structure, we define
7441480Smckusick  * partitions in terms of DEV_BSIZE blocks.  The default partition table
7541480Smckusick  * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg
7641480Smckusick  * root and 32 meg of swap.  The rest of the space on the drive goes in
7741480Smckusick  * the G partition.  As usual, the C partition covers the entire disk
7841480Smckusick  * (including the boot area).
7941480Smckusick  */
8041480Smckusick struct sdinfo sddefaultpart = {
8141480Smckusick 	     1024,   17408,   16384   ,	/* A */
8241480Smckusick 	    17408,   82944,   65536   ,	/* B */
8341480Smckusick 	        0,       0,       0   ,	/* C */
8441480Smckusick 	    17408,  115712,   98304   ,	/* D */
8541480Smckusick 	   115712,  218112,  102400   ,	/* E */
8641480Smckusick 	   218112,       0,       0   ,	/* F */
8741480Smckusick 	    82944,       0,       0   ,	/* G */
8841480Smckusick 	   115712,       0,       0   ,	/* H */
8941480Smckusick };
9041480Smckusick 
9141480Smckusick struct	sd_softc {
9241480Smckusick 	struct	hp_device *sc_hd;
9341480Smckusick 	struct	devqueue sc_dq;
9441480Smckusick 	int	sc_format_pid;	/* process using "format" mode */
9541480Smckusick 	short	sc_flags;
9641480Smckusick 	short	sc_type;	/* drive type */
9741480Smckusick 	short	sc_punit;	/* physical unit (scsi lun) */
9841480Smckusick 	u_short	sc_bshift;	/* convert device blocks to DEV_BSIZE blks */
9941480Smckusick 	u_int	sc_blks;	/* number of blocks on device */
10041480Smckusick 	int	sc_blksize;	/* device block size in bytes */
10141480Smckusick 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
10241480Smckusick 	struct	sdinfo sc_info;	/* drive partition table & label info */
10341480Smckusick } sd_softc[NSD];
10441480Smckusick 
10541480Smckusick /* sc_flags values */
10641480Smckusick #define	SDF_ALIVE	0x1
107*53929Shibler #define SDF_WANTED	0x2
108*53929Shibler #define SDF_RMEDIA	0x4
10941480Smckusick 
11041480Smckusick #ifdef DEBUG
11141480Smckusick int sddebug = 1;
11241480Smckusick #define SDB_ERROR	0x01
11341480Smckusick #define SDB_PARTIAL	0x02
11441480Smckusick #endif
11541480Smckusick 
11641480Smckusick struct sdstats {
11741480Smckusick 	long	sdresets;
11841480Smckusick 	long	sdtransfers;
11941480Smckusick 	long	sdpartials;
12041480Smckusick } sdstats[NSD];
12141480Smckusick 
12241480Smckusick struct	buf sdtab[NSD];
12341480Smckusick struct	scsi_fmt_cdb sdcmd[NSD];
12441480Smckusick struct	scsi_fmt_sense sdsense[NSD];
12541480Smckusick 
12641480Smckusick static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
12741480Smckusick static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
12841480Smckusick 
12949132Skarels #define	sdunit(x)	(minor(x) >> 3)
13041480Smckusick #define sdpart(x)	(minor(x) & 0x7)
13141480Smckusick #define	sdpunit(x)	((x) & 7)
13241480Smckusick #define	b_cylin		b_resid
13345750Smckusick 
13441480Smckusick #define	SDRETRY		2
13541480Smckusick 
13641480Smckusick /*
13741480Smckusick  * Table of scsi commands users are allowed to access via "format"
13841480Smckusick  * mode.  0 means not legal.  1 means "immediate" (doesn't need dma).
13941480Smckusick  * -1 means needs dma and/or wait for intr.
14041480Smckusick  */
14141480Smckusick static char legal_cmds[256] = {
14241480Smckusick /*****  0   1   2   3   4   5   6   7     8   9   A   B   C   D   E   F */
14341480Smckusick /*00*/	0,  0,  0,  0, -1,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14441480Smckusick /*10*/	0,  0,  1,  0,  0,  1,  0,  0,    0,  0,  1,  0,  0,  0,  0,  0,
14541480Smckusick /*20*/	0,  0,  0,  0,  0,  1,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14641480Smckusick /*30*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14741480Smckusick /*40*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14841480Smckusick /*50*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
14941480Smckusick /*60*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15041480Smckusick /*70*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15141480Smckusick /*80*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15241480Smckusick /*90*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15341480Smckusick /*a0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15441480Smckusick /*b0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15541480Smckusick /*c0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15641480Smckusick /*d0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15741480Smckusick /*e0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15841480Smckusick /*f0*/	0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
15941480Smckusick };
16041480Smckusick 
16141480Smckusick static struct scsi_inquiry inqbuf;
16241480Smckusick static struct scsi_fmt_cdb inq = {
16341480Smckusick 	6,
16441480Smckusick 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
16541480Smckusick };
16641480Smckusick 
16741480Smckusick static u_char capbuf[8];
16841480Smckusick struct scsi_fmt_cdb cap = {
16941480Smckusick 	10,
17041480Smckusick 	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
17141480Smckusick };
17241480Smckusick 
17341480Smckusick static int
17441480Smckusick sdident(sc, hd)
17541480Smckusick 	struct sd_softc *sc;
17641480Smckusick 	struct hp_device *hd;
17741480Smckusick {
17841480Smckusick 	int unit;
17941480Smckusick 	register int ctlr, slave;
18041480Smckusick 	register int i;
18141480Smckusick 	register int tries = 10;
18249304Shibler 	char idstr[32];
18345750Smckusick 	int ismo = 0;
18441480Smckusick 
18541480Smckusick 	ctlr = hd->hp_ctlr;
18641480Smckusick 	slave = hd->hp_slave;
18741480Smckusick 	unit = sc->sc_punit;
18849304Shibler 	scsi_delay(-1);
18941480Smckusick 
19041480Smckusick 	/*
19141480Smckusick 	 * See if unit exists and is a disk then read block size & nblocks.
19241480Smckusick 	 */
19341480Smckusick 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
19445750Smckusick 		if (i == -1 || --tries < 0) {
19545750Smckusick 			if (ismo)
19645750Smckusick 				break;
19741480Smckusick 			/* doesn't exist or not a CCS device */
19849304Shibler 			goto failed;
19945750Smckusick 		}
20041480Smckusick 		if (i == STS_CHECKCOND) {
20141480Smckusick 			u_char sensebuf[128];
20241480Smckusick 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
20341480Smckusick 
20441480Smckusick 			scsi_request_sense(ctlr, slave, unit, sensebuf,
20541480Smckusick 					   sizeof(sensebuf));
20645750Smckusick 			if (sp->class == 7)
20745750Smckusick 				switch (sp->key) {
20845750Smckusick 				/* not ready -- might be MO with no media */
20945750Smckusick 				case 2:
21045750Smckusick 					if (sp->len == 12 &&
21145750Smckusick 					    sensebuf[12] == 10)	/* XXX */
21245750Smckusick 						ismo = 1;
21345750Smckusick 					break;
21441480Smckusick 				/* drive doing an RTZ -- give it a while */
21545750Smckusick 				case 6:
21645750Smckusick 					DELAY(1000000);
21745750Smckusick 					break;
21845750Smckusick 				default:
21945750Smckusick 					break;
22045750Smckusick 				}
22141480Smckusick 		}
22241480Smckusick 		DELAY(1000);
22341480Smckusick 	}
22445750Smckusick 	/*
22545750Smckusick 	 * Find out about device
22645750Smckusick 	 */
22745750Smckusick 	if (scsi_immed_command(ctlr, slave, unit, &inq,
22845750Smckusick 			       (u_char *)&inqbuf, sizeof(inqbuf), B_READ))
22949304Shibler 		goto failed;
23041480Smckusick 	switch (inqbuf.type) {
23141480Smckusick 	case 0:		/* disk */
23241480Smckusick 	case 4:		/* WORM */
23341480Smckusick 	case 5:		/* CD-ROM */
23441480Smckusick 	case 7:		/* Magneto-optical */
23541480Smckusick 		break;
23641480Smckusick 	default:	/* not a disk */
23749304Shibler 		goto failed;
23841480Smckusick 	}
23945750Smckusick 	/*
24049304Shibler 	 * Get a usable id string
24145750Smckusick 	 */
24249304Shibler 	if (inqbuf.version != 1) {
24349304Shibler 		bcopy("UNKNOWN", &idstr[0], 8);
24449304Shibler 		bcopy("DRIVE TYPE", &idstr[8], 11);
24549304Shibler 	} else {
24649304Shibler 		bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
24749304Shibler 		for (i = 27; i > 23; --i)
24849304Shibler 			if (idstr[i] != ' ')
24949304Shibler 				break;
25049304Shibler 		idstr[i+1] = 0;
25149304Shibler 		for (i = 23; i > 7; --i)
25249304Shibler 			if (idstr[i] != ' ')
25349304Shibler 				break;
25449304Shibler 		idstr[i+1] = 0;
25549304Shibler 		for (i = 7; i >= 0; --i)
25649304Shibler 			if (idstr[i] != ' ')
25749304Shibler 				break;
25849304Shibler 		idstr[i+1] = 0;
25945750Smckusick 	}
26045750Smckusick 	i = scsi_immed_command(ctlr, slave, unit, &cap,
26145750Smckusick 			       (u_char *)&capbuf, sizeof(capbuf), B_READ);
26245750Smckusick 	if (i) {
26349304Shibler 		if (i != STS_CHECKCOND ||
26449304Shibler 		    bcmp(&idstr[0], "HP", 3) ||
26549304Shibler 		    bcmp(&idstr[8], "S6300.650A", 11))
26649304Shibler 			goto failed;
26745750Smckusick 		/* XXX unformatted or non-existant MO media; fake it */
26849304Shibler 		sc->sc_blks = 318664;
26949304Shibler 		sc->sc_blksize = 1024;
27045750Smckusick 	} else {
27145750Smckusick 		sc->sc_blks = *(u_int *)&capbuf[0];
27245750Smckusick 		sc->sc_blksize = *(int *)&capbuf[4];
27345750Smckusick 	}
27445750Smckusick 	/* return value of read capacity is last valid block number */
27545750Smckusick 	sc->sc_blks++;
27645750Smckusick 
27741480Smckusick 	if (inqbuf.version != 1)
27841480Smckusick 		printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
27941480Smckusick 			inqbuf.type, inqbuf.qual, inqbuf.version);
28049304Shibler 	else
28141480Smckusick 		printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
28241480Smckusick 			&idstr[24]);
28341480Smckusick 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
284*53929Shibler 	if (inqbuf.qual & 0x80)
285*53929Shibler 		sc->sc_flags |= SDF_RMEDIA;
28641480Smckusick 	if (sc->sc_blksize != DEV_BSIZE) {
28741480Smckusick 		if (sc->sc_blksize < DEV_BSIZE) {
28841480Smckusick 			printf("sd%d: need %d byte blocks - drive ignored\n",
28941480Smckusick 				unit, DEV_BSIZE);
29049304Shibler 			goto failed;
29141480Smckusick 		}
29241480Smckusick 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
29341480Smckusick 			++sc->sc_bshift;
29441480Smckusick 		sc->sc_blks <<= sc->sc_bshift;
29541480Smckusick 	}
29641480Smckusick 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
29749304Shibler 	scsi_delay(0);
29841480Smckusick 	return(inqbuf.type);
29949304Shibler failed:
30049304Shibler 	scsi_delay(0);
30149304Shibler 	return(-1);
30241480Smckusick }
30341480Smckusick 
30441480Smckusick int
30541480Smckusick sdinit(hd)
30641480Smckusick 	register struct hp_device *hd;
30741480Smckusick {
30841480Smckusick 	register struct sd_softc *sc = &sd_softc[hd->hp_unit];
30941480Smckusick 
31041480Smckusick 	sc->sc_hd = hd;
311*53929Shibler 	sc->sc_flags = 0;
31241480Smckusick 	sc->sc_punit = sdpunit(hd->hp_flags);
31341480Smckusick 	sc->sc_type = sdident(sc, hd);
31441480Smckusick 	if (sc->sc_type < 0)
31541480Smckusick 		return(0);
31641480Smckusick 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
31741480Smckusick 	sc->sc_dq.dq_unit = hd->hp_unit;
31841480Smckusick 	sc->sc_dq.dq_slave = hd->hp_slave;
31941480Smckusick 	sc->sc_dq.dq_driver = &sddriver;
32041480Smckusick 
32141480Smckusick 	/*
32241480Smckusick 	 * If we don't have a disk label, build a default partition
32341480Smckusick 	 * table with 'standard' size root & swap and everything else
32441480Smckusick 	 * in the G partition.
32541480Smckusick 	 */
32641480Smckusick 	sc->sc_info = sddefaultpart;
32741480Smckusick 	/* C gets everything */
32841480Smckusick 	sc->sc_info.part[2].nblocks = sc->sc_blks;
32941480Smckusick 	sc->sc_info.part[2].endblk = sc->sc_blks;
33041480Smckusick 	/* G gets from end of B to end of disk */
33141480Smckusick 	sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk;
33241480Smckusick 	sc->sc_info.part[6].endblk = sc->sc_blks;
33341480Smckusick 	/*
33441480Smckusick 	 * We also define the D, E and F paritions as an alternative to
33541480Smckusick 	 * B and G.  D is 48Mb, starts after A and is intended for swapping.
33641480Smckusick 	 * E is 50Mb, starts after D and is intended for /usr. F starts
33741480Smckusick 	 * after E and is what ever is left.
33841480Smckusick 	 */
33941480Smckusick 	if (sc->sc_blks >= sc->sc_info.part[4].endblk) {
34041480Smckusick 		sc->sc_info.part[5].nblocks =
34141480Smckusick 			sc->sc_blks - sc->sc_info.part[4].endblk;
34241480Smckusick 		sc->sc_info.part[5].endblk = sc->sc_blks;
34341480Smckusick 	} else {
34441480Smckusick 		sc->sc_info.part[5].strtblk = 0;
34541480Smckusick 		sc->sc_info.part[3] = sc->sc_info.part[5];
34641480Smckusick 		sc->sc_info.part[4] = sc->sc_info.part[5];
34741480Smckusick 	}
34841480Smckusick 	/*
34941480Smckusick 	 * H is a single partition alternative to E and F.
35041480Smckusick 	 */
35141480Smckusick 	if (sc->sc_blks >= sc->sc_info.part[3].endblk) {
35241480Smckusick 		sc->sc_info.part[7].nblocks =
35341480Smckusick 			sc->sc_blks - sc->sc_info.part[3].endblk;
35441480Smckusick 		sc->sc_info.part[7].endblk = sc->sc_blks;
35541480Smckusick 	} else {
35641480Smckusick 		sc->sc_info.part[7].strtblk = 0;
35741480Smckusick 	}
35841480Smckusick 
359*53929Shibler 	sc->sc_flags |= SDF_ALIVE;
36041480Smckusick 	return(1);
36141480Smckusick }
36241480Smckusick 
36341480Smckusick void
36441480Smckusick sdreset(sc, hd)
36541480Smckusick 	register struct sd_softc *sc;
36641480Smckusick 	register struct hp_device *hd;
36741480Smckusick {
36841480Smckusick 	sdstats[hd->hp_unit].sdresets++;
36941480Smckusick }
37041480Smckusick 
37141480Smckusick int
37249132Skarels sdopen(dev, flags, mode, p)
37341480Smckusick 	dev_t dev;
37449132Skarels 	int flags, mode;
37549132Skarels 	struct proc *p;
37641480Smckusick {
37741480Smckusick 	register int unit = sdunit(dev);
37841480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
37941480Smckusick 
38041480Smckusick 	if (unit >= NSD)
38141480Smckusick 		return(ENXIO);
38249132Skarels 	if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
38341480Smckusick 		return(ENXIO);
38441480Smckusick 
38541480Smckusick 	if (sc->sc_hd->hp_dk >= 0)
38641480Smckusick 		dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
38741480Smckusick 	return(0);
38841480Smckusick }
38941480Smckusick 
390*53929Shibler int
391*53929Shibler sdclose(dev, flag, mode, p)
392*53929Shibler 	dev_t dev;
393*53929Shibler 	int flag, mode;
394*53929Shibler 	struct proc *p;
395*53929Shibler {
396*53929Shibler 	int unit = sdunit(dev);
397*53929Shibler 	register struct sd_softc *sc = &sd_softc[unit];
398*53929Shibler 	int s;
399*53929Shibler 
400*53929Shibler 	/*
401*53929Shibler 	 * XXX we should really do this for all drives.
402*53929Shibler 	 */
403*53929Shibler 	if (sc->sc_flags & SDF_RMEDIA) {
404*53929Shibler 		s = splbio();
405*53929Shibler 		while (sdtab[unit].b_active) {
406*53929Shibler 			sc->sc_flags |= SDF_WANTED;
407*53929Shibler 			sleep((caddr_t)&sdtab[unit], PRIBIO);
408*53929Shibler 		}
409*53929Shibler 		splx(s);
410*53929Shibler 	}
411*53929Shibler 	sc->sc_format_pid = 0;
412*53929Shibler }
413*53929Shibler 
41441480Smckusick /*
41541480Smckusick  * This routine is called for partial block transfers and non-aligned
41641480Smckusick  * transfers (the latter only being possible on devices with a block size
41741480Smckusick  * larger than DEV_BSIZE).  The operation is performed in three steps
41841480Smckusick  * using a locally allocated buffer:
41941480Smckusick  *	1. transfer any initial partial block
42041480Smckusick  *	2. transfer full blocks
42141480Smckusick  *	3. transfer any final partial block
42241480Smckusick  */
42341480Smckusick static void
42441480Smckusick sdlblkstrat(bp, bsize)
42541480Smckusick 	register struct buf *bp;
42641480Smckusick 	register int bsize;
42741480Smckusick {
42841480Smckusick 	register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf),
42941480Smckusick 							M_DEVBUF, M_WAITOK);
43041480Smckusick 	caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
43141480Smckusick 	register int bn, resid;
43241480Smckusick 	register caddr_t addr;
43341480Smckusick 
43441480Smckusick 	bzero((caddr_t)cbp, sizeof(*cbp));
43549132Skarels 	cbp->b_proc = curproc;		/* XXX */
43641480Smckusick 	cbp->b_dev = bp->b_dev;
43741480Smckusick 	bn = bp->b_blkno;
43841480Smckusick 	resid = bp->b_bcount;
43941480Smckusick 	addr = bp->b_un.b_addr;
44041480Smckusick #ifdef DEBUG
44141480Smckusick 	if (sddebug & SDB_PARTIAL)
44241480Smckusick 		printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
44341480Smckusick 		       bp, bp->b_flags, bn, resid, addr);
44441480Smckusick #endif
44541480Smckusick 
44641480Smckusick 	while (resid > 0) {
44741480Smckusick 		register int boff = dbtob(bn) & (bsize - 1);
44841480Smckusick 		register int count;
44941480Smckusick 
45041480Smckusick 		if (boff || resid < bsize) {
45141480Smckusick 			sdstats[sdunit(bp->b_dev)].sdpartials++;
45241480Smckusick 			count = MIN(resid, bsize - boff);
45341480Smckusick 			cbp->b_flags = B_BUSY | B_PHYS | B_READ;
45441480Smckusick 			cbp->b_blkno = bn - btodb(boff);
45541480Smckusick 			cbp->b_un.b_addr = cbuf;
45641480Smckusick 			cbp->b_bcount = bsize;
45741480Smckusick #ifdef DEBUG
45841480Smckusick 			if (sddebug & SDB_PARTIAL)
45941480Smckusick 				printf(" readahead: bn %x cnt %x off %x addr %x\n",
46041480Smckusick 				       cbp->b_blkno, count, boff, addr);
46141480Smckusick #endif
46241480Smckusick 			sdstrategy(cbp);
46341480Smckusick 			biowait(cbp);
46441480Smckusick 			if (cbp->b_flags & B_ERROR) {
46541480Smckusick 				bp->b_flags |= B_ERROR;
46641480Smckusick 				bp->b_error = cbp->b_error;
46741480Smckusick 				break;
46841480Smckusick 			}
46941480Smckusick 			if (bp->b_flags & B_READ) {
47041480Smckusick 				bcopy(&cbuf[boff], addr, count);
47141480Smckusick 				goto done;
47241480Smckusick 			}
47341480Smckusick 			bcopy(addr, &cbuf[boff], count);
47441480Smckusick #ifdef DEBUG
47541480Smckusick 			if (sddebug & SDB_PARTIAL)
47641480Smckusick 				printf(" writeback: bn %x cnt %x off %x addr %x\n",
47741480Smckusick 				       cbp->b_blkno, count, boff, addr);
47841480Smckusick #endif
47941480Smckusick 		} else {
48041480Smckusick 			count = resid & ~(bsize - 1);
48141480Smckusick 			cbp->b_blkno = bn;
48241480Smckusick 			cbp->b_un.b_addr = addr;
48341480Smckusick 			cbp->b_bcount = count;
48441480Smckusick #ifdef DEBUG
48541480Smckusick 			if (sddebug & SDB_PARTIAL)
48641480Smckusick 				printf(" fulltrans: bn %x cnt %x addr %x\n",
48741480Smckusick 				       cbp->b_blkno, count, addr);
48841480Smckusick #endif
48941480Smckusick 		}
49041480Smckusick 		cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);
49141480Smckusick 		sdstrategy(cbp);
49241480Smckusick 		biowait(cbp);
49341480Smckusick 		if (cbp->b_flags & B_ERROR) {
49441480Smckusick 			bp->b_flags |= B_ERROR;
49541480Smckusick 			bp->b_error = cbp->b_error;
49641480Smckusick 			break;
49741480Smckusick 		}
49841480Smckusick done:
49941480Smckusick 		bn += btodb(count);
50041480Smckusick 		resid -= count;
50141480Smckusick 		addr += count;
50241480Smckusick #ifdef DEBUG
50341480Smckusick 		if (sddebug & SDB_PARTIAL)
50441480Smckusick 			printf(" done: bn %x resid %x addr %x\n",
50541480Smckusick 			       bn, resid, addr);
50641480Smckusick #endif
50741480Smckusick 	}
50841480Smckusick 	free(cbuf, M_DEVBUF);
50941480Smckusick 	free(cbp, M_DEVBUF);
51041480Smckusick }
51141480Smckusick 
51241480Smckusick void
51341480Smckusick sdstrategy(bp)
51441480Smckusick 	register struct buf *bp;
51541480Smckusick {
51641480Smckusick 	register int unit = sdunit(bp->b_dev);
51741480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
51845750Smckusick 	register struct size *pinfo = &sc->sc_info.part[sdpart(bp->b_dev)];
51941480Smckusick 	register struct buf *dp = &sdtab[unit];
52045750Smckusick 	register daddr_t bn;
52145750Smckusick 	register int sz, s;
52241480Smckusick 
52341480Smckusick 	if (sc->sc_format_pid) {
52449132Skarels 		if (sc->sc_format_pid != curproc->p_pid) {	/* XXX */
52541480Smckusick 			bp->b_error = EPERM;
52645750Smckusick 			bp->b_flags |= B_ERROR;
52745750Smckusick 			goto done;
52841480Smckusick 		}
52941480Smckusick 		bp->b_cylin = 0;
53041480Smckusick 	} else {
53141480Smckusick 		bn = bp->b_blkno;
53245750Smckusick 		sz = howmany(bp->b_bcount, DEV_BSIZE);
53345750Smckusick 		if (bn < 0 || bn + sz > pinfo->nblocks) {
53445750Smckusick 			sz = pinfo->nblocks - bn;
53545750Smckusick 			if (sz == 0) {
53641480Smckusick 				bp->b_resid = bp->b_bcount;
53741480Smckusick 				goto done;
53841480Smckusick 			}
53945750Smckusick 			if (sz < 0) {
54045750Smckusick 				bp->b_error = EINVAL;
54145750Smckusick 				bp->b_flags |= B_ERROR;
54245750Smckusick 				goto done;
54345750Smckusick 			}
54445750Smckusick 			bp->b_bcount = dbtob(sz);
54541480Smckusick 		}
54641480Smckusick 		/*
54741480Smckusick 		 * Non-aligned or partial-block transfers handled specially.
54841480Smckusick 		 */
54941480Smckusick 		s = sc->sc_blksize - 1;
55041480Smckusick 		if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
55141480Smckusick 			sdlblkstrat(bp, sc->sc_blksize);
55241480Smckusick 			goto done;
55341480Smckusick 		}
55445750Smckusick 		bp->b_cylin = (bn + pinfo->strtblk) >> sc->sc_bshift;
55541480Smckusick 	}
55641480Smckusick 	s = splbio();
55741480Smckusick 	disksort(dp, bp);
55841480Smckusick 	if (dp->b_active == 0) {
55941480Smckusick 		dp->b_active = 1;
56041480Smckusick 		sdustart(unit);
56141480Smckusick 	}
56241480Smckusick 	splx(s);
56341480Smckusick 	return;
56441480Smckusick done:
56545750Smckusick 	biodone(bp);
56641480Smckusick }
56741480Smckusick 
56841480Smckusick void
56941480Smckusick sdustart(unit)
57041480Smckusick 	register int unit;
57141480Smckusick {
57241480Smckusick 	if (scsireq(&sd_softc[unit].sc_dq))
57341480Smckusick 		sdstart(unit);
57441480Smckusick }
57541480Smckusick 
57650039Skarels /*
57750039Skarels  * Return:
57850039Skarels  *	0	if not really an error
57950039Skarels  *	<0	if we should do a retry
58050039Skarels  *	>0	if a fatal error
58150039Skarels  */
58245750Smckusick static int
58341480Smckusick sderror(unit, sc, hp, stat)
58441480Smckusick 	int unit, stat;
58541480Smckusick 	register struct sd_softc *sc;
58641480Smckusick 	register struct hp_device *hp;
58741480Smckusick {
58850039Skarels 	int cond = 1;
58945750Smckusick 
59041480Smckusick 	sdsense[unit].status = stat;
59141480Smckusick 	if (stat & STS_CHECKCOND) {
59241480Smckusick 		struct scsi_xsense *sp;
59341480Smckusick 
59441480Smckusick 		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
59541480Smckusick 				   sc->sc_punit, sdsense[unit].sense,
59641480Smckusick 				   sizeof(sdsense[unit].sense));
59741480Smckusick 		sp = (struct scsi_xsense *)sdsense[unit].sense;
59841480Smckusick 		printf("sd%d: scsi sense class %d, code %d", unit,
59941480Smckusick 			sp->class, sp->code);
60041480Smckusick 		if (sp->class == 7) {
60141480Smckusick 			printf(", key %d", sp->key);
60241480Smckusick 			if (sp->valid)
60341480Smckusick 				printf(", blk %d", *(int *)&sp->info1);
60450039Skarels 			switch (sp->key) {
60550039Skarels 			/* no sense, try again */
60650039Skarels 			case 0:
60750039Skarels 				cond = -1;
60850039Skarels 				break;
60950039Skarels 			/* recovered error, not a problem */
61050039Skarels 			case 1:
61150039Skarels 				cond = 0;
61250039Skarels 				break;
61350039Skarels 			}
61441480Smckusick 		}
61541480Smckusick 		printf("\n");
61641480Smckusick 	}
61750039Skarels 	return(cond);
61841480Smckusick }
61941480Smckusick 
62041480Smckusick static void
62141480Smckusick sdfinish(unit, sc, bp)
62241480Smckusick 	int unit;
62341480Smckusick 	register struct sd_softc *sc;
62441480Smckusick 	register struct buf *bp;
62541480Smckusick {
626*53929Shibler 	register struct buf *dp = &sdtab[unit];
627*53929Shibler 
628*53929Shibler 	dp->b_errcnt = 0;
629*53929Shibler 	dp->b_actf = bp->b_actf;
63041480Smckusick 	bp->b_resid = 0;
63145750Smckusick 	biodone(bp);
63241480Smckusick 	scsifree(&sc->sc_dq);
633*53929Shibler 	if (dp->b_actf)
63441480Smckusick 		sdustart(unit);
635*53929Shibler 	else {
636*53929Shibler 		dp->b_active = 0;
637*53929Shibler 		if (sc->sc_flags & SDF_WANTED) {
638*53929Shibler 			sc->sc_flags &= ~SDF_WANTED;
639*53929Shibler 			wakeup((caddr_t)dp);
640*53929Shibler 		}
641*53929Shibler 	}
64241480Smckusick }
64341480Smckusick 
64441480Smckusick void
64541480Smckusick sdstart(unit)
64641480Smckusick 	register int unit;
64741480Smckusick {
64841480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
64941480Smckusick 	register struct hp_device *hp = sc->sc_hd;
65041480Smckusick 
65141480Smckusick 	/*
65241480Smckusick 	 * we have the SCSI bus -- in format mode, we may or may not need dma
65341480Smckusick 	 * so check now.
65441480Smckusick 	 */
65541480Smckusick 	if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) {
65641480Smckusick 		register struct buf *bp = sdtab[unit].b_actf;
65741480Smckusick 		register int sts;
65841480Smckusick 
65941480Smckusick 		sts = scsi_immed_command(hp->hp_ctlr, hp->hp_slave,
66041480Smckusick 					 sc->sc_punit, &sdcmd[unit],
66141480Smckusick 					 bp->b_un.b_addr, bp->b_bcount,
66241480Smckusick 					 bp->b_flags & B_READ);
66341480Smckusick 		sdsense[unit].status = sts;
66441480Smckusick 		if (sts & 0xfe) {
66545750Smckusick 			(void) sderror(unit, sc, hp, sts);
66641480Smckusick 			bp->b_flags |= B_ERROR;
66741480Smckusick 			bp->b_error = EIO;
66841480Smckusick 		}
66941480Smckusick 		sdfinish(unit, sc, bp);
67041480Smckusick 
67141480Smckusick 	} else if (scsiustart(hp->hp_ctlr))
67241480Smckusick 		sdgo(unit);
67341480Smckusick }
67441480Smckusick 
67541480Smckusick void
67641480Smckusick sdgo(unit)
67741480Smckusick 	register int unit;
67841480Smckusick {
67941480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
68041480Smckusick 	register struct hp_device *hp = sc->sc_hd;
68141480Smckusick 	register struct buf *bp = sdtab[unit].b_actf;
68241480Smckusick 	register int pad;
68341480Smckusick 	register struct scsi_fmt_cdb *cmd;
68441480Smckusick 
68541480Smckusick 	if (sc->sc_format_pid) {
68641480Smckusick 		cmd = &sdcmd[unit];
68741480Smckusick 		pad = 0;
68841480Smckusick 	} else {
68941480Smckusick 		cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
69041480Smckusick 		*(int *)(&cmd->cdb[2]) = bp->b_cylin;
69141480Smckusick 		pad = howmany(bp->b_bcount, sc->sc_blksize);
69241480Smckusick 		*(u_short *)(&cmd->cdb[7]) = pad;
69341480Smckusick 		pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;
69441480Smckusick #ifdef DEBUG
69541480Smckusick 		if (pad)
69641480Smckusick 			printf("sd%d: partial block xfer -- %x bytes\n",
69741480Smckusick 			       unit, bp->b_bcount);
69841480Smckusick #endif
69941480Smckusick 		sdstats[unit].sdtransfers++;
70041480Smckusick 	}
70141480Smckusick 	if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) {
70241480Smckusick 		if (hp->hp_dk >= 0) {
70341480Smckusick 			dk_busy |= 1 << hp->hp_dk;
70441480Smckusick 			++dk_seek[hp->hp_dk];
70541480Smckusick 			++dk_xfer[hp->hp_dk];
70641480Smckusick 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
70741480Smckusick 		}
70841480Smckusick 		return;
70941480Smckusick 	}
71041480Smckusick #ifdef DEBUG
71141480Smckusick 	if (sddebug & SDB_ERROR)
71241480Smckusick 		printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",
71341480Smckusick 		       unit, bp->b_flags & B_READ? "read" : "write",
71441480Smckusick 		       bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
71541480Smckusick 		       sdtab[unit].b_errcnt);
71641480Smckusick #endif
71741480Smckusick 	bp->b_flags |= B_ERROR;
71841480Smckusick 	bp->b_error = EIO;
71941480Smckusick 	sdfinish(unit, sc, bp);
72041480Smckusick }
72141480Smckusick 
72241480Smckusick void
72341480Smckusick sdintr(unit, stat)
72441480Smckusick 	register int unit;
72541480Smckusick 	int stat;
72641480Smckusick {
72741480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
72841480Smckusick 	register struct buf *bp = sdtab[unit].b_actf;
72941480Smckusick 	register struct hp_device *hp = sc->sc_hd;
73050039Skarels 	int cond;
73141480Smckusick 
73241480Smckusick 	if (bp == NULL) {
73341480Smckusick 		printf("sd%d: bp == NULL\n", unit);
73441480Smckusick 		return;
73541480Smckusick 	}
73641480Smckusick 	if (hp->hp_dk >= 0)
73741480Smckusick 		dk_busy &=~ (1 << hp->hp_dk);
73841480Smckusick 	if (stat) {
73941480Smckusick #ifdef DEBUG
74041480Smckusick 		if (sddebug & SDB_ERROR)
74141480Smckusick 			printf("sd%d: sdintr: bad scsi status 0x%x\n",
74241480Smckusick 				unit, stat);
74341480Smckusick #endif
74450039Skarels 		cond = sderror(unit, sc, hp, stat);
74550039Skarels 		if (cond) {
74650039Skarels 			if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
74750038Skarels #ifdef DEBUG
74850039Skarels 				if (sddebug & SDB_ERROR)
74950039Skarels 					printf("sd%d: retry #%d\n",
75050039Skarels 					       unit, sdtab[unit].b_errcnt);
75150038Skarels #endif
75250039Skarels 				sdstart(unit);
75350039Skarels 				return;
75450039Skarels 			}
75550039Skarels 			bp->b_flags |= B_ERROR;
75650039Skarels 			bp->b_error = EIO;
75745750Smckusick 		}
75841480Smckusick 	}
75941480Smckusick 	sdfinish(unit, sc, bp);
76041480Smckusick }
76141480Smckusick 
76241480Smckusick int
76349132Skarels sdread(dev, uio, flags)
76441480Smckusick 	dev_t dev;
76541480Smckusick 	struct uio *uio;
76649132Skarels 	int flags;
76741480Smckusick {
76841480Smckusick 	register int unit = sdunit(dev);
76941480Smckusick 	register int pid;
77041480Smckusick 
77149132Skarels 	if ((pid = sd_softc[unit].sc_format_pid) &&
77249132Skarels 	    pid != uio->uio_procp->p_pid)
77341480Smckusick 		return (EPERM);
77441480Smckusick 
77549132Skarels 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
77641480Smckusick }
77741480Smckusick 
77841480Smckusick int
77949132Skarels sdwrite(dev, uio, flags)
78041480Smckusick 	dev_t dev;
78141480Smckusick 	struct uio *uio;
78249132Skarels 	int flags;
78341480Smckusick {
78441480Smckusick 	register int unit = sdunit(dev);
78541480Smckusick 	register int pid;
78641480Smckusick 
78749132Skarels 	if ((pid = sd_softc[unit].sc_format_pid) &&
78849132Skarels 	    pid != uio->uio_procp->p_pid)
78941480Smckusick 		return (EPERM);
79041480Smckusick 
79149132Skarels 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
79241480Smckusick }
79341480Smckusick 
79441480Smckusick int
79549132Skarels sdioctl(dev, cmd, data, flag, p)
79641480Smckusick 	dev_t dev;
79741480Smckusick 	int cmd;
79841480Smckusick 	caddr_t data;
79941480Smckusick 	int flag;
80049132Skarels 	struct proc *p;
80141480Smckusick {
80241480Smckusick 	register int unit = sdunit(dev);
80341480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
80441480Smckusick 
80541480Smckusick 	switch (cmd) {
80641480Smckusick 	default:
80741480Smckusick 		return (EINVAL);
80841480Smckusick 
80941480Smckusick 	case SDIOCSFORMAT:
81041480Smckusick 		/* take this device into or out of "format" mode */
81149132Skarels 		if (suser(p->p_ucred, &p->p_acflag))
81241480Smckusick 			return(EPERM);
81341480Smckusick 
81441480Smckusick 		if (*(int *)data) {
81541480Smckusick 			if (sc->sc_format_pid)
81641480Smckusick 				return (EPERM);
81749132Skarels 			sc->sc_format_pid = p->p_pid;
81841480Smckusick 		} else
81941480Smckusick 			sc->sc_format_pid = 0;
82041480Smckusick 		return (0);
82141480Smckusick 
82241480Smckusick 	case SDIOCGFORMAT:
82341480Smckusick 		/* find out who has the device in format mode */
82441480Smckusick 		*(int *)data = sc->sc_format_pid;
82541480Smckusick 		return (0);
82641480Smckusick 
82741480Smckusick 	case SDIOCSCSICOMMAND:
82841480Smckusick 		/*
82941480Smckusick 		 * Save what user gave us as SCSI cdb to use with next
83041480Smckusick 		 * read or write to the char device.
83141480Smckusick 		 */
83249132Skarels 		if (sc->sc_format_pid != p->p_pid)
83341480Smckusick 			return (EPERM);
83441480Smckusick 		if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
83541480Smckusick 			return (EINVAL);
83641480Smckusick 		bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0]));
83741480Smckusick 		return (0);
83841480Smckusick 
83941480Smckusick 	case SDIOCSENSE:
84041480Smckusick 		/*
84141480Smckusick 		 * return the SCSI sense data saved after the last
84241480Smckusick 		 * operation that completed with "check condition" status.
84341480Smckusick 		 */
84441480Smckusick 		bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0]));
84541480Smckusick 		return (0);
84641480Smckusick 
84741480Smckusick 	}
84841480Smckusick 	/*NOTREACHED*/
84941480Smckusick }
85041480Smckusick 
85141480Smckusick int
85241480Smckusick sdsize(dev)
85341480Smckusick 	dev_t dev;
85441480Smckusick {
85541480Smckusick 	register int unit = sdunit(dev);
85641480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
85741480Smckusick 
85841480Smckusick 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
85941480Smckusick 		return(-1);
86041480Smckusick 
86141480Smckusick 	return(sc->sc_info.part[sdpart(dev)].nblocks);
86241480Smckusick }
86341480Smckusick 
86441480Smckusick /*
86541480Smckusick  * Non-interrupt driven, non-dma dump routine.
86641480Smckusick  */
86741480Smckusick int
86841480Smckusick sddump(dev)
86941480Smckusick 	dev_t dev;
87041480Smckusick {
87141480Smckusick 	int part = sdpart(dev);
87241480Smckusick 	int unit = sdunit(dev);
87341480Smckusick 	register struct sd_softc *sc = &sd_softc[unit];
87441480Smckusick 	register struct hp_device *hp = sc->sc_hd;
87541480Smckusick 	register daddr_t baddr;
87641480Smckusick 	register int maddr;
87741480Smckusick 	register int pages, i;
87841480Smckusick 	int stat;
87941480Smckusick 	extern int lowram;
88041480Smckusick 
88141480Smckusick 	/*
88241480Smckusick 	 * Hmm... all vax drivers dump maxfree pages which is physmem minus
88341480Smckusick 	 * the message buffer.  Is there a reason for not dumping the
88441480Smckusick 	 * message buffer?  Savecore expects to read 'dumpsize' pages of
88541480Smckusick 	 * dump, where dumpsys() sets dumpsize to physmem!
88641480Smckusick 	 */
88741480Smckusick 	pages = physmem;
88841480Smckusick 
88941480Smckusick 	/* is drive ok? */
89041480Smckusick 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
89141480Smckusick 		return (ENXIO);
89241480Smckusick 	/* dump parameters in range? */
89341480Smckusick 	if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks)
89441480Smckusick 		return (EINVAL);
89541480Smckusick 	if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks)
89641480Smckusick 		pages = dtoc(sc->sc_info.part[part].nblocks - dumplo);
89741480Smckusick 	maddr = lowram;
89841480Smckusick 	baddr = dumplo + sc->sc_info.part[part].strtblk;
89941480Smckusick 	/* scsi bus idle? */
90041480Smckusick 	if (!scsireq(&sc->sc_dq)) {
90141480Smckusick 		scsireset(hp->hp_ctlr);
90241480Smckusick 		sdreset(sc, sc->sc_hd);
90341480Smckusick 		printf("[ drive %d reset ] ", unit);
90441480Smckusick 	}
90541480Smckusick 	for (i = 0; i < pages; i++) {
90641480Smckusick #define NPGMB	(1024*1024/NBPG)
90741480Smckusick 		/* print out how many Mbs we have dumped */
90841480Smckusick 		if (i && (i % NPGMB) == 0)
90941480Smckusick 			printf("%d ", i / NPGMB);
91041480Smckusick #undef NPBMG
91152614Smckusick 		pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
91251576Smckusick 		    VM_PROT_READ, TRUE);
91341480Smckusick 		stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,
91441480Smckusick 				     vmmap, NBPG, baddr, sc->sc_bshift);
91541480Smckusick 		if (stat) {
91641480Smckusick 			printf("sddump: scsi write error 0x%x\n", stat);
91741480Smckusick 			return (EIO);
91841480Smckusick 		}
91941480Smckusick 		maddr += NBPG;
92041480Smckusick 		baddr += ctod(1);
92141480Smckusick 	}
92241480Smckusick 	return (0);
92341480Smckusick }
92441480Smckusick #endif
925