Subject: Re: tape drive instrumentation round 2
To: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
From: Brett Lymn <blymn@baesystems.com.au>
List: tech-kern
Date: 03/05/2006 22:42:58
On Fri, Feb 17, 2006 at 12:16:16PM +0900, YAMAMOTO Takashi wrote:
> 
> i vote for "iostat" and use it for network i/o as well, eventually.
>

I thought this was an excellent idea.  I have left subr_disk.c with
that name but removed all the statisics gathering functions to a new
file called subr_iostat.c.  I have reworked the changes to reflect the
new naming (backed out all the disk.h to drive.h changes I made).

Other changes I have made include putting back the "disknames" sysctl
entry, this now displays the names of the disk drives on the system.
A new "drivenames" entry displays all the drives (disk, tape and nfs)
on the system.

I have put a tar file on ftp.netbsd.org under /pub/NetBSD/misc/blymn
called iostat_patch.tar.gz which contains the patch against -current
plus the extra files needed - just untar the file in the root of your
source tree and then apply the iostat_patch, build a new kernel,
install that, build a new userland to get the modified systat, vmstat
and iostat commands.

If there are no objections I will commit this to the -current tree in
about a weeks time.  Below is a copy of the diff that is included in
the abovementioned tar file (please note that some of the diffs are
longer than they should be due to stray white-space being stripped
from some lines)
 
========================================================================

Index: sys/arch/acorn32/mainbus/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/acorn32/mainbus/fd.c,v
retrieving revision 1.24
diff -u -r1.24 fd.c
--- sys/arch/acorn32/mainbus/fd.c	23 Feb 2006 05:37:46 -0000	1.24
+++ sys/arch/acorn32/mainbus/fd.c	5 Mar 2006 11:43:31 -0000
@@ -399,7 +399,7 @@
 
 	printf("\n");
 
-	callout_init(&fdc->sc_timo_ch); 
+	callout_init(&fdc->sc_timo_ch);
 	callout_init(&fdc->sc_intr_ch);
 
 	fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc",
@@ -1030,8 +1030,8 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return 1;
@@ -1055,7 +1055,7 @@
 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
 		 if (block != fd->sc_blkno) {
 			 printf("fdcintr: block %" PRId64
-			     " != blkno %" PRId64 "\n",	
+			     " != blkno %" PRId64 "\n",
 				block, fd->sc_blkno);
 #ifdef DDB
 			 Debugger();
@@ -1120,7 +1120,7 @@
 		}
 		fdc->sc_state = IOCOMPLETE;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
@@ -1137,7 +1137,7 @@
 
 	case SEEKCOMPLETE:
 		/* no data on seek */
-		disk_unbusy(&fd->sc_dk, 0, 0);
+		drive_unbusy(fd->sc_dk.stats, 0, 0);
 
 		/* Make sure seek really happened. */
 		out_fdc(iot, ioh, NE7CMD_SENSEI);
@@ -1164,7 +1164,7 @@
 	case IOCOMPLETE: /* IO DONE, post-analyze */
 		callout_stop(&fdc->sc_timo_ch);
 
-		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(fd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
@@ -1455,11 +1455,11 @@
 			return EINVAL;
 		}
 
-		fd_formb = malloc(sizeof(struct ne7_fd_formb), 
+		fd_formb = malloc(sizeof(struct ne7_fd_formb),
 		    M_TEMP, M_NOWAIT);
 		if(fd_formb == 0)
 			return ENOMEM;
-		    
+
 
 		fd_formb->head = form_cmd->head;
 		fd_formb->cyl = form_cmd->cylinder;
@@ -1550,7 +1550,7 @@
 			break;
 	}
 	splx(s);
-       
+
 	if (rv == EWOULDBLOCK) {
 		/* timed out */
 		rv = EIO;
@@ -1590,7 +1590,7 @@
 	type = FDTYPE(dev) - 1;
 	if (type < 0) type = 0;
 	floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
-        
+
 	if (md->md_size < floppysize) {
 		printf("Memory disc is not big enough for floppy image\n");
 		return(EINVAL);
@@ -1603,7 +1603,7 @@
 /* obtain a buffer */
 
 	bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
-    
+
 /* request no partition relocation by driver on I/O operations */
 
 	bp->b_dev = dev;
@@ -1611,7 +1611,7 @@
 	s = spl0();
 
 	if (fdopen(bp->b_dev, 0, 0, curlwp) != 0) {
-		brelse(bp);		
+		brelse(bp);
 		printf("Cannot open floppy device\n");
 			return(EINVAL);
 	}
@@ -1630,14 +1630,14 @@
 
 		if (biowait(bp))
 			panic("Cannot load floppy image");
-                                                 
+
 		memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
 		    * DEV_BSIZE, (caddr_t)bp->b_data,
 		    fd_types[type].sectrac * DEV_BSIZE);
 	}
 	printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
 	    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
-        
+
 	fdclose(bp->b_dev, 0, 0, curlwp);
 
 	brelse(bp);
Index: sys/arch/amiga/amiga/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/amiga/autoconf.c,v
retrieving revision 1.98
diff -u -r1.98 autoconf.c
--- sys/arch/amiga/amiga/autoconf.c	11 Dec 2005 12:16:26 -0000	1.98
+++ sys/arch/amiga/amiga/autoconf.c	5 Mar 2006 11:43:31 -0000
@@ -400,7 +400,7 @@
 			 * device.
 			 */
 			devs = (struct device **)sd_cd.cd_devs;
-			if ((dkp = disk_find(devs[unit]->dv_xname)) == NULL)
+			if ((dkp = drive_find(devs[unit]->dv_xname)) == NULL)
 				continue;
 
 			if (dkp->dk_driver == NULL ||
@@ -449,7 +449,7 @@
 			 * current device.
 			 */
 			devs = (struct device **)genericconf[i]->cd_devs;
-			if ((dkp = disk_find(devs[unit]->dv_xname)) == NULL)
+			if ((dkp = drive_find(devs[unit]->dv_xname)) == NULL)
 				continue;
 
 			if (dkp->dk_driver == NULL ||
Index: sys/arch/amiga/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/dev/fd.c,v
retrieving revision 1.66
diff -u -r1.66 fd.c
--- sys/arch/amiga/dev/fd.c	11 Dec 2005 12:16:28 -0000	1.66
+++ sys/arch/amiga/dev/fd.c	5 Mar 2006 11:43:31 -0000
@@ -1193,7 +1193,7 @@
 	 * Mark us as busy now, in case fddone() gets called in one
 	 * of the cases below.
 	 */
-	disk_busy(&sc->dkdev);
+	drive_busy(sc->dkdev.stats);
 
 	/*
 	 * make sure same disk is loaded
@@ -1581,7 +1581,7 @@
 	 */
 	(void)BUFQ_GET(sc->bufq);
 
-	disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(sc->dkdev.stats, (bp->b_bcount - bp->b_resid),
 	    (bp->b_flags & B_READ));
 
 	biodone(bp);
Index: sys/arch/arc/jazz/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/fd.c,v
retrieving revision 1.25
diff -u -r1.25 fd.c
--- sys/arch/arc/jazz/fd.c	23 Feb 2006 05:37:46 -0000	1.25
+++ sys/arch/arc/jazz/fd.c	5 Mar 2006 11:43:31 -0000
@@ -831,8 +831,8 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return 1;
@@ -885,7 +885,7 @@
 		out_fdc(iot, ioh, type->datalen);	/* data length */
 		fdc->sc_state = IOCOMPLETE;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
@@ -899,7 +899,7 @@
 		return 1;
 
 	case SEEKCOMPLETE:
-		disk_unbusy(&fd->sc_dk, 0, 0);
+		drive_unbusy(fd->sc_dk.stats, 0, 0);
 
 		/* Make sure seek really happened. */
 		out_fdc(iot, ioh, NE7CMD_SENSEI);
@@ -926,7 +926,7 @@
 	case IOCOMPLETE: /* IO DONE, post-analyze */
 		callout_stop(&fdc->sc_timo_ch);
 
-		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(fd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		i = fdcresult(fdc);
Index: sys/arch/atari/atari/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/atari/autoconf.c,v
retrieving revision 1.52
diff -u -r1.52 autoconf.c
--- sys/arch/atari/atari/autoconf.c	11 Dec 2005 12:16:54 -0000	1.52
+++ sys/arch/atari/atari/autoconf.c	5 Mar 2006 11:43:31 -0000
@@ -60,7 +60,7 @@
 cpu_configure()
 {
 	extern int atari_realconfig;
-	
+
 	atari_realconfig = 1;
 
 	if (config_rootfound("mainbus", __UNCONST("mainbus")) == NULL)
@@ -85,8 +85,8 @@
 
 /*
  * use config_search_ia to find appropriate device, then call that device
- * directly with NULL device variable storage.  A device can then 
- * always tell the difference between the real and console init 
+ * directly with NULL device variable storage.  A device can then
+ * always tell the difference between the real and console init
  * by checking for NULL.
  */
 int
@@ -126,12 +126,12 @@
 
 /*
  * this function needs to get enough configured to do a console
- * basically this means start attaching the grfxx's that support 
+ * basically this means start attaching the grfxx's that support
  * the console. Kinda hacky but it works.
  */
 void
 config_console()
-{	
+{
 	struct cfdata *cf;
 
 	config_init();
@@ -171,7 +171,7 @@
 extern	struct cfdriver wd_cd;
 #endif
 #if NSD > 0
-extern	struct cfdriver sd_cd;  
+extern	struct cfdriver sd_cd;
 #endif
 #if NCD > 0
 extern	struct cfdriver cd_cd;
@@ -218,13 +218,13 @@
 			 * current device.
 			 */
 			devs = (struct device **)genericconf[i]->cd_devs;
-			if ((dkp = disk_find(devs[unit]->dv_xname)) == NULL)
+			if ((dkp = drive_find(devs[unit]->dv_xname)) == NULL)
 				continue;
 
 			if (dkp->dk_driver == NULL ||
 			    dkp->dk_driver->d_strategy == NULL)
 				continue;
-			
+
 			maj = devsw_name2blk(genericconf[i]->cd_name, NULL, 0);
 			if (maj == -1)
 				continue;
@@ -243,7 +243,7 @@
 				continue;
 			(void)(*bdev->d_close)(MAKEDISKDEV(maj,
 			    unit, 0), FREAD|FNONBLOCK, 0, &lwp0);
-			
+
 			pp = &dkp->dk_label->d_partitions[booted_partition];
 			if (pp->p_size != 0 && pp->p_fstype == FS_BSDFFS) {
 				booted_device = devs[unit];
@@ -253,8 +253,8 @@
 	}
 }
 
-/* 
- * mainbus driver 
+/*
+ * mainbus driver
  */
 CFATTACH_DECL(mainbus, sizeof(struct device),
     mbmatch, mbattach, NULL, NULL);
Index: sys/arch/atari/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/dev/fd.c,v
retrieving revision 1.53
diff -u -r1.53 fd.c
--- sys/arch/atari/dev/fd.c	24 Dec 2005 23:23:59 -0000	1.53
+++ sys/arch/atari/dev/fd.c	5 Mar 2006 11:43:32 -0000
@@ -186,7 +186,7 @@
 
 /*
  * This is set only once at attach time. The value is determined by reading
- * the configuration switches and is one of the FLP_TYPE_*'s. 
+ * the configuration switches and is one of the FLP_TYPE_*'s.
  * This is simular to the way Atari handles the _FLP cookie.
  */
 static short	def_type = 0;		/* Reflects config-switches	*/
@@ -355,7 +355,7 @@
 {
 	if (pnp != NULL)
 		aprint_normal("fd%d at %s:", (int)auxp, pnp);
-	
+
 	return(UNCONF);
 }
 
@@ -707,7 +707,7 @@
 	fd_state     = FLP_XFER;	/* Yes, we're going to transfer	*/
 
 	/* Instrumentation. */
-	disk_busy(&sc->dkdev);
+	drive_busy(sc->dkdev.stats);
 
 	fd_xfer(sc);
 }
@@ -747,7 +747,7 @@
 #endif
 		bp->b_resid = sc->io_bytes;
 
-		disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(sc->dkdev.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		biodone(bp);
Index: sys/arch/atari/dev/hdfd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/dev/hdfd.c,v
retrieving revision 1.49
diff -u -r1.49 hdfd.c
--- sys/arch/atari/dev/hdfd.c	23 Feb 2006 05:37:46 -0000	1.49
+++ sys/arch/atari/dev/hdfd.c	5 Mar 2006 11:43:32 -0000
@@ -1050,8 +1050,8 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return 1;
@@ -1130,7 +1130,7 @@
 		}
 		fdc->sc_state = IOCOMPLETE;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
@@ -1145,7 +1145,7 @@
 
 	case SEEKCOMPLETE:
 		/* no data on seek */
-		disk_unbusy(&fd->sc_dk, 0, 0);
+		drive_unbusy(fd->sc_dk.stats, 0, 0);
 
 		/* Make sure seek really happened. */
 		out_fdc(NE7CMD_SENSEI);
@@ -1170,7 +1170,7 @@
 	case IOCOMPLETE: /* IO DONE, post-analyze */
 		callout_stop(&fdc->sc_timo_ch);
 
-		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(fd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		if (fdcresult(fdc) != 7 || (st1 & 0x37) != 0) {
@@ -1501,7 +1501,7 @@
 			fd_formb->fd_formb_secno(i) = il[i+1];
 			fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
 		}
-		
+
 		error = fdformat(dev, fd_formb, l->l_proc);
 		free(fd_formb, M_TEMP);
 		return error;
@@ -1569,7 +1569,7 @@
 			break;
 	}
 	splx(s);
-       
+
 	if (rv == EWOULDBLOCK) {
 		/* timed out */
 		rv = EIO;
Index: sys/arch/dreamcast/dev/maple/mmemcard.c
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/dev/maple/mmemcard.c,v
retrieving revision 1.7
diff -u -r1.7 mmemcard.c
--- sys/arch/dreamcast/dev/maple/mmemcard.c	11 Dec 2005 12:17:06 -0000	1.7
+++ sys/arch/dreamcast/dev/maple/mmemcard.c	5 Mar 2006 11:43:32 -0000
@@ -776,7 +776,7 @@
 
 	pt = &sc->sc_pt[MMEM_PART(DISKUNIT(bp->b_dev))];
 	s = splbio();
-	disk_busy(&pt->pt_dk);
+	drive_busy(pt->pt_dk.stats);
 	splx(s);
 
 	/*
@@ -886,7 +886,7 @@
 		/* terminate current transfer */
 		sc->sc_bp = NULL;
 		s = splbio();
-		disk_unbusy(&pt->pt_dk, sc->sc_iobuf - bp->b_data,
+		drive_unbusy(pt->pt_dk.stats, sc->sc_iobuf - bp->b_data,
 		    sc->sc_stat == MMEM_READ);
 		biodone(bp);
 		splx(s);
Index: sys/arch/hp300/dev/rd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/dev/rd.c,v
retrieving revision 1.71
diff -u -r1.71 rd.c
--- sys/arch/hp300/dev/rd.c	25 Feb 2006 02:28:56 -0000	1.71
+++ sys/arch/hp300/dev/rd.c	5 Mar 2006 11:43:32 -0000
@@ -835,8 +835,8 @@
 		     sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
 
 		/* Instrumentation. */
-		disk_busy(&rs->sc_dkdev);
-		rs->sc_dkdev.dk_seek++;
+		drive_busy(rs->sc_dkdev.stats);
+		rs->sc_dkdev->stats->seek++;
 
 #ifdef DEBUG
 		if (rddebug & RDB_IO)
@@ -889,7 +889,7 @@
 	rw = bp->b_flags & B_READ;
 
 	/* Instrumentation. */
-	disk_busy(&rs->sc_dkdev);
+	drive_busy(rs->sc_dkdev.stats);
 
 #ifdef USELEDS
 	ledcontrol(0, 0, LED_DISK);
@@ -919,7 +919,7 @@
 		return;
 	}
 #endif
-	disk_unbusy(&rs->sc_dkdev, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(rs->sc_dkdev.stats, (bp->b_bcount - bp->b_resid),
 	    (bp->b_flags & B_READ));
 
 	if (rs->sc_flags & RDF_SEEK) {
@@ -938,7 +938,7 @@
 #endif
 
 			/* Instrumentation. */
-			disk_busy(&rs->sc_dkdev);
+			drive_busy(rs->sc_dkdev.stats);
 			rs->sc_flags |= RDF_SWAIT;
 			hpibawait(ctlr);
 			return;
Index: sys/arch/mac68k/obio/iwm_fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/obio/iwm_fd.c,v
retrieving revision 1.35
diff -u -r1.35 iwm_fd.c
--- sys/arch/mac68k/obio/iwm_fd.c	11 Dec 2005 12:18:03 -0000	1.35
+++ sys/arch/mac68k/obio/iwm_fd.c	5 Mar 2006 11:43:33 -0000
@@ -128,8 +128,8 @@
 static void hexDump(u_char *, int);
 
 /*
- * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output 
- * statements don't break indentation, and when DEBUG is not defined, 
+ * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output
+ * statements don't break indentation, and when DEBUG is not defined,
  * the compiler code optimizer drops them as dead code.
  */
 #ifdef IWM_DEBUG
@@ -218,7 +218,7 @@
  * compile/$KERNEL/ioconf.c, which is generated by config(8).
  * Their names are formed like {device}_{ca,cd}.
  *
- * {device}_ca  
+ * {device}_ca
  * is used for dynamically allocating driver data, probing and
  * attaching a device;
  *
@@ -266,10 +266,10 @@
 /*
  * iwm_match
  *
- * Is the IWM chip present? Here, *auxp is a ptr to struct confargs 
- * (see <mac68k/mac68k/autoconf.h>), which does not hold any information 
- * to match against. After all, that's what the obio concept is 
- * about: Onboard components that are present depending (only) 
+ * Is the IWM chip present? Here, *auxp is a ptr to struct confargs
+ * (see <mac68k/mac68k/autoconf.h>), which does not hold any information
+ * to match against. After all, that's what the obio concept is
+ * about: Onboard components that are present depending (only)
  * on machine type.
  */
 int
@@ -281,9 +281,9 @@
 #endif
 	extern u_long IOBase;		/* from mac68k/machdep.c */
 	extern u_long IWMBase;
-	
+
 	if (0 == map_iwm_base(IOBase)) {
-		/* 
+		/*
 		 * Unknown machine HW:
 		 * The SWIM II/III chips that are present in post-Q700
 		 * '040 Macs have dropped the IWM register structure.
@@ -295,7 +295,7 @@
 	} else {
 		matched = 1;
 		if (TRACE_CONFIG) {
-			printf("iwm: IWMBase mapped to 0x%lx in VM.\n", 
+			printf("iwm: IWMBase mapped to 0x%lx in VM.\n",
 			    IWMBase);
 		}
 #ifdef _LKM
@@ -352,8 +352,8 @@
 /*
  * iwm_print -- print device configuration.
  *
- * If the device is not configured 'controller' it is NULL and 
- * we print a message in the *Attach routine; the return value 
+ * If the device is not configured 'controller' it is NULL and
+ * we print a message in the *Attach routine; the return value
  * of *Print() is ignored.
  */
 int
@@ -373,7 +373,7 @@
 {
 	int known;
 	extern u_long IWMBase;
-	
+
 	switch (current_mac_model->class) {
 	case MACH_CLASSQ:
 	case MACH_CLASSQ2:
@@ -394,9 +394,9 @@
 	case MACH_CLASSIIfx:
 	case MACH_CLASSAV:
 	default:
-		/* 
-		 * Neither IIfx/Q9[05]0 style IOP controllers nor 
-		 * Q[68]40AV DMA based controllers are supported. 
+		/*
+		 * Neither IIfx/Q9[05]0 style IOP controllers nor
+		 * Q[68]40AV DMA based controllers are supported.
 		 */
 		if (TRACE_CONFIG)
 			printf("Unknown floppy controller chip.\n");
@@ -554,9 +554,9 @@
 	/* Release any allocated memory */
 	for (unit = 0; unit < IWM_MAX_DRIVE; unit++)
 		if (iwm->fd[unit] != NULL) {
-			/* 
+			/*
 			 * Let's hope there is only one task per drive,
-			 * see callout(9). 
+			 * see callout(9).
 			 */
 			callout_stop(&iwm->fd[unit]->motor_ch);
 			disk_detach(&iwm->fd[unit]->diskInfo);
@@ -670,9 +670,9 @@
 	}
 	if (!err) {
 		if (fd->state & IWM_FD_IS_OPEN) {
-			/* 
+			/*
 			 * Allow multiple open calls only if for identical
-			 * floppy format. 
+			 * floppy format.
 			 */
 			if (TRACE_OPEN)
 				printf(".\n Drive already opened!\n");
@@ -738,7 +738,7 @@
 		ierr = seek(fd, IWM_SEEK_RECAL);
 		if (TRACE_OPEN)
 			printf(" %d.\n", ierr);
-		err = (0 == ierr) ? 0 : EIO;		
+		err = (0 == ierr) ? 0 : EIO;
 	}
 	if (!err) {
 		/*
@@ -788,7 +788,7 @@
 	/* release cylinder cache memory */
 	if (fd->cbuf != NULL)
 		     free(fd->cbuf, M_DEVBUF);
-	
+
 	partitionMask = (1 << fdType);
 
 	/* Set state flag. */
@@ -1164,11 +1164,11 @@
 		fdstart_Fault,
 		fdstart_Exit
 	};
-	
+
 	st = state_Init;
 	do {
 		if (TRACE_STRAT)
-			printf(" fdstart state %d [%s] ", 
+			printf(" fdstart state %d [%s] ",
 			    st, stateDesc[st]);
 
 		st = (*state[st])(fd);
@@ -1180,7 +1180,7 @@
 
 
 /*
- * fdstart_Init 
+ * fdstart_Init
  *
  * Set up things
  */
@@ -1188,7 +1188,7 @@
 fdstart_Init(fd_softc_t *fd)
 {
 	struct buf *bp;
-	
+
 	/*
 	 * Get the first entry from the queue. This is the buf we gave to
 	 * fdstrategy(); disksort() put it into our softc.
@@ -1201,7 +1201,7 @@
 	}
 	fd->ioDirection = bp->b_flags & B_READ;
 
-	disk_busy(&fd->diskInfo);
+	drive_busy(fd->diskInfo.stats);
 	if (!(fd->state & IWM_FD_MOTOR_ON)) {
 		iwmMotor(fd->unit, 1);
 		fd->state |= IWM_FD_MOTOR_ON;
@@ -1263,12 +1263,12 @@
  * fdstart_Read
  *
  * Transfer a sector from disk. Get it from the track cache, if available;
- * otherwise, while we are at it, store in the cache all the sectors we find 
+ * otherwise, while we are at it, store in the cache all the sectors we find
  * on the way.
- * 
+ *
  * Track buffering reads:
  * o  Look if the sector is already cached.
- * o  Else, read sectors into track cache until we meet the header of 
+ * o  Else, read sectors into track cache until we meet the header of
  *    the sector we want.
  * o  Read that sector directly to fs buffer and return.
  */
@@ -1281,7 +1281,7 @@
 #ifndef _LKM
 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
 #endif
-	
+
 	/* Initialize retry counters */
 	fd->seekRetries = 0;
 	fd->sectRetries = 0;
@@ -1289,7 +1289,7 @@
 	shdr = &fd->sHdr;
 
 	if (TRACE_STRAT)
-		printf("<%s c%d_h%d_s%d> ", 
+		printf("<%s c%d_h%d_s%d> ",
 		    fd->ioDirection ? "Read" : "Write",
 		    pos->track, pos->side, pos->sector);
 
@@ -1297,8 +1297,8 @@
 	i = pos->sector;
 	if (fd->r_slots[i].valid) {
 		if (TRACE_STRAT)
-			printf("(cached)"); 
-		memcpy(fd->current_buffer, fd->r_slots[i].secbuf, 
+			printf("(cached)");
+		memcpy(fd->current_buffer, fd->r_slots[i].secbuf,
 		    fd->currentType->sectorSize);
 		return state_IOFinish;
 	}
@@ -1342,8 +1342,8 @@
 	/* Sector not found? */
 	if (shdr->sector != pos->sector) {
 		if (TRACE_STRAT)
-			printf("c%d_h%d_s%d sect not found, %d retries ", 
-			    shdr->track, shdr->side >> 3, 
+			printf("c%d_h%d_s%d sect not found, %d retries ",
+			    shdr->track, shdr->side >> 3,
 			    shdr->sector, fd->sectRetries);
 		fd->iwmErr = noAdrMkErr;
 		return state_Fault;
@@ -1363,7 +1363,7 @@
 fdstart_Write(fd_softc_t *fd)
 {
 	int i;
-	
+
 	/* XXX let's see... */
 	fd->sHdr.side = fd->pos.side;
 	fd->sHdr.sector = fd->pos.sector;
@@ -1372,9 +1372,9 @@
 	i = fd->pos.sector;
 	fd->w_slots[i].secbuf = fd->current_buffer;
 	fd->w_slots[i].valid = 1;	/* "valid" is a dirty buffer here */
-	
+
 	if (TRACE_STRAT)
-		printf("<%s c%d_h%d_s%d> (cached) ", 
+		printf("<%s c%d_h%d_s%d> (cached) ",
 		    fd->ioDirection ? "Read" : "Write",
 		    fd->pos.track, fd->pos.side, fd->pos.sector);
 	return state_IOFinish;
@@ -1384,7 +1384,7 @@
 
 /*
  * fdstart_Flush
- * 
+ *
  * Flush dirty buffers in the track cache to disk.
  */
 static int
@@ -1408,11 +1408,11 @@
 				dcnt++;
 			}
 		printf("|\n");
-		
-		printf(" <%s c%d_h%d_#s%d>\n", 
+
+		printf(" <%s c%d_h%d_#s%d>\n",
 		    fd->ioDirection ? "Read" : "Write",
 		    pos->track, pos->side, dcnt);
-	}	
+	}
 	(void)iwmSelectSide(pos->side);
 	fd->iwmErr = iwmWriteSector(&fd->sHdr, fd->w_slots);
 
@@ -1423,10 +1423,10 @@
 		for (i=0; i<IWM_MAX_GCR_SECTORS; i++)
 			if (0 != fd->w_slots[i].valid)
 				printf("Oops! <c%d_h%d_s%d> not flushed.\n",
-				    fd->pos.track, fd->pos.side, 
+				    fd->pos.track, fd->pos.side,
 				    fd->pos.sector);
 #endif
-		if (TRACE_STRAT) 
+		if (TRACE_STRAT)
 			printf("(Cache flushed, re-initialize) ");
 		for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
 			fd->w_slots[i].valid = 0;
@@ -1435,7 +1435,7 @@
 		fd->seekRetries = 0;
 		state = state_Exit;
 		break;
-		
+
 	case seekErr:		/* Bad seek? Retry */
 		if (TRACE_STRAT) {
 			printf("Wanted track %d, got %d, %d seek retries.\n",
@@ -1449,7 +1449,7 @@
 		}
 		state = (0 == fd->iwmErr) ? state_Exit : state_Fault;
 		break;
-		
+
 	default:		/* General IWM IO error? */
 		state = state_IOErr;
 	}
@@ -1458,7 +1458,7 @@
 
 
 /*
- * fdstart_IOFinish 
+ * fdstart_IOFinish
  *
  * Prepare for next block, if any is available
  */
@@ -1468,8 +1468,8 @@
 	int state;
 
 	if (DISABLED && TRACE_STRAT)
-		printf("%s c%d_h%d_s%d ok ", 
-		    fd->ioDirection ? "Read" : "Write", 
+		printf("%s c%d_h%d_s%d ok ",
+		    fd->ioDirection ? "Read" : "Write",
 		    fd->sHdr.track, fd->sHdr.side >> 3, fd->sHdr.sector);
 
 	fd->bytesDone += fd->currentType->sectorSize;
@@ -1490,7 +1490,7 @@
 			    ? state_Write : state_Read;
 		}
 		else {
-			/* 
+			/*
 			 * Invalidate read cache when changing track;
 			 * flush write cache to disk.
 			 */
@@ -1512,7 +1512,7 @@
 		    ? state_Flush : state_Exit;
 	}
 	return state;
-}	
+}
 
 
 /*
@@ -1527,10 +1527,10 @@
 #ifndef _LKM
 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
 #endif
-	
+
 #ifdef DIAGNOSTIC
 	printf("iwm%sSector() err = %d, %d retries, on c%d_h%d_s%d.\n",
-	    fd->ioDirection ? "Read" : "Write", 
+	    fd->ioDirection ? "Read" : "Write",
 	    fd->iwmErr, fd->ioRetries, fd->pos.track,
 	    fd->pos.side, fd->pos.sector);
 #endif
@@ -1538,7 +1538,7 @@
 	if (fd->ioRetries++ < iwm->maxRetries)
 		state = (fd->ioDirection == IWM_WRITE)
 		    ? state_Flush : state_Read;
-	else 
+	else
 		state = state_Fault;
 	return state;
 }
@@ -1555,7 +1555,7 @@
 #ifdef DIAGNOSTIC
 	printf("Seek retries %d, IO retries %d, sect retries %d :\n" \
 	    "\t\t only found c%d_h%d_s%d \n",
-	    fd->seekRetries, fd->ioRetries, fd->sectRetries, 
+	    fd->seekRetries, fd->ioRetries, fd->sectRetries,
 	    fd->sHdr.track, fd->sHdr.side >> 3, fd->sHdr.sector);
 	printf("A non-recoverable error: %d ", fd->iwmErr);
 #else
@@ -1577,7 +1577,7 @@
 #ifdef DIAGNOSTIC
 	int i;
 #endif
-	
+
 	invalidateCylinderCache(fd);
 
 #ifdef DIAGNOSTIC
@@ -1604,14 +1604,14 @@
 	if (DISABLED && TRACE_STRAT)
 		printf(" Next buf (bufQueue first) at %p\n",
 		    BUFQ_PEEK(fd->bufQueue));
-	disk_unbusy(&fd->diskInfo, bp->b_bcount - bp->b_resid,
+	drive_unbusy(fd->diskInfo.stats, bp->b_bcount - bp->b_resid,
 	    (bp->b_flags & B_READ));
 	biodone(bp);
-	/* 
+	/*
 	 * Stop motor after 10s
-	 * 
+	 *
 	 * XXX Unloading the module while the timeout is still
-	 *     running WILL crash the machine. 
+	 *     running WILL crash the machine.
 	 */
 	callout_reset(&fd->motor_ch, 10 * hz, motor_off, fd);
 
@@ -1772,20 +1772,20 @@
 	int i;
 	int err;
 	int secsize;
-	
+
 	err = 0;
 	secsize = fd->currentType->sectorSize;
 	fd->cachedSide = 0;
-	
+
 	fd->cbuf = (unsigned char *) malloc(IWM_MAX_GCR_SECTORS
 	    * secsize, M_DEVBUF, M_WAITOK);
-	if (NULL == fd->cbuf) 
+	if (NULL == fd->cbuf)
 		err = ENOMEM;
 	else
 		for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
 			fd->w_slots[i].valid = 0;
 			fd->w_slots[i].secbuf = NULL;
-			
+
 			fd->r_slots[i].valid = 0;
 			fd->r_slots[i].secbuf = fd->cbuf + i * secsize;
 		}
@@ -1802,7 +1802,7 @@
 invalidateCylinderCache(fd_softc_t *fd)
 {
 	int i;
-	
+
 	fd->cachedSide = 0;
 	for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
 		fd->r_slots[i].valid = 0;
@@ -1913,7 +1913,7 @@
 	/* XXX egcs */
 	done = err = ierr = 0;
 	fd->seekRetries = 0;
-	fd->verifyRetries = 0;	
+	fd->verifyRetries = 0;
 
 	loc = &fd->pos;
 
Index: sys/arch/pdp10/dev/hp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pdp10/dev/hp.c,v
retrieving revision 1.4
diff -u -r1.4 hp.c
--- sys/arch/pdp10/dev/hp.c	11 Dec 2005 12:18:34 -0000	1.4
+++ sys/arch/pdp10/dev/hp.c	5 Mar 2006 11:43:33 -0000
@@ -13,7 +13,7 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *      This product includes software developed at Ludd, University of 
+ *      This product includes software developed at Ludd, University of
  *      Lule}, Sweden and its contributors.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission
@@ -264,8 +264,8 @@
 	/*
 	 * Collect statistics.
 	 */
-	disk_busy(&sc->sc_disk);
-	sc->sc_disk.dk_seek++;
+	drive_busy(sc->sc_disk.stats);
+	sc->sc_disk.stats->seek++;
 
 	bn = bp->b_rawblkno;
 	if (bn) {
@@ -417,7 +417,7 @@
 	case -1:
 		HP_WCSR(HP_ER1, 0);
 		goto hper2;
-		
+
 	case HPER1_DCK: /* Corrected? data read. Just notice. */
 panic("hpfinish");
 #if 0
@@ -448,7 +448,7 @@
 		    sc->sc_dev.dv_xname, mbasr);
 
 	BUFQ_PEEK(md->md_q)->b_resid = 0;
-	disk_unbusy(&sc->sc_disk, BUFQ_PEEK(md->md_q)->b_bcount,
+	drive_unbusy(sc->sc_disk.stats, BUFQ_PEEK(&md->md_q)->b_bcount,
 	    (bp->b_flags & B_READ));
 	return XFER_FINISH;
 }
Index: sys/arch/sparc/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/fd.c,v
retrieving revision 1.125
diff -u -r1.125 fd.c
--- sys/arch/sparc/dev/fd.c	23 Feb 2006 05:37:48 -0000	1.125
+++ sys/arch/sparc/dev/fd.c	5 Mar 2006 11:43:33 -0000
@@ -1490,9 +1490,9 @@
 		fdc->sc_state = SEEKWAIT;
 		fdc->sc_nstat = 0;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.stats->seek++;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 
 		/* specify command */
@@ -1514,7 +1514,7 @@
 		 * Disk change: force a seek operation by going to cyl 1
 		 * followed by a recalibrate.
 		 */
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		fd->sc_cylin = -1;
 		fdc->sc_nstat = 0;
@@ -1588,7 +1588,7 @@
 		fdc->sc_itask = FDC_ITASK_DMA;
 		fdc->sc_nstat = 0;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 3 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 3 * hz, fdctimeout, fdc);
Index: sys/arch/sun3/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun3/dev/fd.c,v
retrieving revision 1.47
diff -u -r1.47 fd.c
--- sys/arch/sun3/dev/fd.c	23 Feb 2006 05:37:48 -0000	1.47
+++ sys/arch/sun3/dev/fd.c	5 Mar 2006 11:43:33 -0000
@@ -334,7 +334,7 @@
  */
 #define	FCR_REG_SYNC()	(*fdc->sc_reg_fcr = fdc->sc_fcr)
 
-int 
+int
 fdcmatch(struct device *parent, struct cfdata *match, void *aux)
 {
 	struct confargs *ca = aux;
@@ -361,7 +361,7 @@
  * Return QUIET (config_find ignores this if the device was configured) to
  * avoid printing `fdN not configured' messages.
  */
-int 
+int
 fdprint(void *aux, const char *fdc)
 {
 	struct fdc_attach_args *fa = aux;
@@ -371,7 +371,7 @@
 	return (QUIET);
 }
 
-static void 
+static void
 fdconf(struct fdc_softc *fdc)
 {
 	int	vroom;
@@ -394,7 +394,7 @@
 	/* No result phase */
 }
 
-void 
+void
 fdcattach(struct device *parent, struct device *self, void *aux)
 {
 	struct confargs *ca = aux;
@@ -472,7 +472,7 @@
 	}
 }
 
-int 
+int
 fdmatch(struct device *parent, struct cfdata *match, void *aux)
 {
 	struct fdc_softc *fdc = (void *)parent;
@@ -533,7 +533,7 @@
 /*
  * Controller is working, and drive responded.  Attach it.
  */
-void 
+void
 fdattach(struct device *parent, struct device *self, void *aux)
 {
 	struct fdc_softc *fdc = (void *)parent;
@@ -614,7 +614,7 @@
 	return (type ? &fd_types[type - 1] : fd->sc_deftype);
 }
 
-void 
+void
 fdstrategy(struct buf *bp			/* IO operation to perform */)
 {
 	struct fd_softc *fd;
@@ -688,7 +688,7 @@
 	biodone(bp);
 }
 
-void 
+void
 fdstart(struct fd_softc *fd)
 {
 	struct fdc_softc *fdc = (void *)device_parent(&fd->sc_dv);
@@ -703,7 +703,7 @@
 		fdcstart(fdc);
 }
 
-void 
+void
 fdfinish(struct fd_softc *fd, struct buf *bp)
 {
 	struct fdc_softc *fdc = (void *)device_parent(&fd->sc_dv);
@@ -732,7 +732,7 @@
 	fdc->sc_state = DEVIDLE;
 }
 
-void 
+void
 fdc_reset(struct fdc_softc *fdc)
 {
 	fdc->sc_fcr = 0;
@@ -748,7 +748,7 @@
 #endif
 }
 
-void 
+void
 fd_set_motor(struct fdc_softc *fdc)
 {
 	struct fd_softc *fd;
@@ -767,7 +767,7 @@
 	FCR_REG_SYNC();
 }
 
-void 
+void
 fd_motor_off(void *arg)
 {
 	struct fd_softc *fd = arg;
@@ -779,7 +779,7 @@
 	splx(s);
 }
 
-void 
+void
 fd_motor_on(void *arg)
 {
 	struct fd_softc *fd = arg;
@@ -793,7 +793,7 @@
 	splx(s);
 }
 
-int 
+int
 fdcresult(struct fdc_softc *fdc)
 {
 	u_char i;
@@ -831,7 +831,7 @@
 	return (0);
 }
 
-int 
+int
 fdopen(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	int unit, pmask;
@@ -879,7 +879,7 @@
 	return (0);
 }
 
-int 
+int
 fdclose(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
@@ -903,21 +903,21 @@
 	return (0);
 }
 
-int 
+int
 fdread(dev_t dev, struct uio *uio, int flag)
 {
 
 	return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
-int 
+int
 fdwrite(dev_t dev, struct uio *uio, int flag)
 {
 
 	return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
 
-void 
+void
 fdcstart(struct fdc_softc *fdc)
 {
 
@@ -932,7 +932,7 @@
 	(void) fdcstate(fdc);
 }
 
-void 
+void
 fdcstatus(struct device *dv, int n, const char *s)
 {
 	struct fdc_softc *fdc = (void *)device_parent(dv);
@@ -981,7 +981,7 @@
 	}
 }
 
-void 
+void
 fdctimeout(void *arg)
 {
 	struct fdc_softc *fdc = arg;
@@ -1000,7 +1000,7 @@
 	splx(s);
 }
 
-void 
+void
 fdcpseudointr(void *arg)
 {
 	struct fdc_softc *fdc = arg;
@@ -1017,7 +1017,7 @@
  * hardware interrupt entry point: must be converted to `fast'
  * (in-window) handler.
  */
-int 
+int
 fdchwintr(void *arg)
 {
 	struct fdc_softc *fdc = arg;
@@ -1080,7 +1080,7 @@
 	return (1);
 }
 
-int 
+int
 fdcswintr(void *arg)
 {
 	struct fdc_softc *fdc = arg;
@@ -1102,7 +1102,7 @@
 	return (1);
 }
 
-int 
+int
 fdcstate(struct fdc_softc *fdc)
 {
 #define	st0	fdc->sc_status[0]
@@ -1212,8 +1212,8 @@
 		fdc->sc_state = SEEKWAIT;
 		fdc->sc_nstat = 0;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return (1);
@@ -1293,7 +1293,7 @@
 			OUT_FDC(fdc, type->datalen, IOTIMEDOUT);/*data length*/
 		}
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
@@ -1311,7 +1311,7 @@
 		/*FALLTHROUGH*/
 	case SEEKCOMPLETE:
 		/* no data on seek */
-		disk_unbusy(&fd->sc_dk, 0, 0);
+		drive_unbusy(fd->sc_dk.stats, 0, 0);
 
 		/* Make sure seek really happened. */
 		if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 ||
@@ -1343,7 +1343,7 @@
 	case IOCOMPLETE: /* IO DONE, post-analyze */
 		callout_stop(&fdc->sc_timo_ch);
 
-		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(fd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		if (fdc->sc_nstat != 7 || (st0 & 0xf8) != 0 || st1 != 0) {
@@ -1480,7 +1480,7 @@
 #undef	cyl
 }
 
-void 
+void
 fdcretry(struct fdc_softc *fdc)
 {
 	char bits[64];
@@ -1536,7 +1536,7 @@
 	fdc->sc_errors++;
 }
 
-int 
+int
 fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct lwp *l)
 {
 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
@@ -1769,7 +1769,7 @@
 #endif
 }
 
-int 
+int
 fdformat(dev_t dev, struct ne7_fd_formb *finfo, struct proc *p)
 {
 	int rv = 0, s;
@@ -1827,7 +1827,7 @@
 	return (rv);
 }
 
-void 
+void
 fdgetdisklabel(dev_t dev)
 {
 	int unit = FDUNIT(dev), i;
@@ -1888,7 +1888,7 @@
 	}
 }
 
-void 
+void
 fd_do_eject(struct fdc_softc *fdc, int unit)
 {
 	fdc->sc_fcr |= FCR_DSEL(unit)|FCR_EJECT;
@@ -1903,7 +1903,7 @@
 #endif
 
 /* ARGSUSED */
-void 
+void
 fd_mountroot_hook(struct device *dev)
 {
 	int c;
@@ -1929,7 +1929,7 @@
 
 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT)
 
-int 
+int
 fd_read_md_image(size_t *sizep, caddr_t *addrp)
 {
 	struct buf buf, *bp = &buf;
Index: sys/arch/sun3/dev/xd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun3/dev/xd.c,v
retrieving revision 1.51
diff -u -r1.51 xd.c
--- sys/arch/sun3/dev/xd.c	11 Dec 2005 12:19:20 -0000	1.51
+++ sys/arch/sun3/dev/xd.c	5 Mar 2006 11:43:34 -0000
@@ -302,7 +302,7 @@
 
 static void *xd_labeldata;
 
-static void 
+static void
 xddummystrat(struct buf *bp)
 {
 	if (bp->b_bcount != XDFM_BPS)
@@ -312,7 +312,7 @@
 	bp->b_flags &= ~B_BUSY;
 }
 
-int 
+int
 xdgetdisklabel(struct xd_softc *xd, void *b)
 {
 	const char *err;
@@ -368,7 +368,7 @@
  * soft reset to detect the xdc.
  */
 
-int 
+int
 xdcmatch(struct device *parent, struct cfdata *cf, void *aux)
 {
 	struct confargs *ca = aux;
@@ -391,7 +391,7 @@
 /*
  * xdcattach: attach controller
  */
-void 
+void
 xdcattach(struct device *parent, struct device *self, void *aux)
 {
 	struct xdc_softc *xdc = (void *) self;
@@ -403,7 +403,7 @@
 	/* get addressing and intr level stuff from autoconfig and load it
 	 * into our xdc_softc. */
 
-	xdc->xdc = (struct xdc *) 
+	xdc->xdc = (struct xdc *)
 		bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(struct xdc));
 	xdc->bustype = ca->ca_bustype;
 	xdc->ipl     = ca->ca_intpri;
@@ -499,7 +499,7 @@
 	callout_reset(&xdc->sc_tick_ch, XDC_TICKCNT, xdc_tick, xdc);
 }
 
-int 
+int
 xdc_print(void *aux, const char *name)
 {
 	struct xdc_attach_args *xa = aux;
@@ -521,7 +521,7 @@
  * call xdattach!).  Also, wire down the relationship between the
  * xd* and xdc* devices, to simplify boot device identification.
  */
-int 
+int
 xdmatch(struct device *parent, struct cfdata *cf, void *aux)
 {
 	struct xdc_attach_args *xa = aux;
@@ -538,7 +538,7 @@
 /*
  * xdattach: attach a disk.
  */
-void 
+void
 xdattach(struct device *parent, struct device *self, void *aux)
 {
 	struct xd_softc *xd = (void *) self;
@@ -574,7 +574,7 @@
  * Initialize a disk.  This can be called from both autoconf and
  * also from xdopen/xdstrategy.
  */
-static void 
+static void
 xd_init(struct xd_softc *xd)
 {
 	struct xdc_softc *xdc;
@@ -738,7 +738,7 @@
 /*
  * xdclose: close device
  */
-int 
+int
 xdclose(dev_t dev, int flag, int fmt, struct lwp *l)
 {
 	struct xd_softc *xd = xd_cd.cd_devs[DISKUNIT(dev)];
@@ -762,7 +762,7 @@
 /*
  * xddump: crash dump system
  */
-int 
+int
 xddump(dev_t dev, daddr_t blkno, caddr_t va, size_t sz)
 {
 	int     unit, part;
@@ -797,7 +797,7 @@
 /*
  * xdioctl: ioctls on XD drives.   based on ioctl's of other netbsd disks.
  */
-int 
+int
 xdioctl(dev_t dev, u_long command, caddr_t addr, int flag, struct lwp *l)
 {
 	struct xd_softc *xd;
@@ -885,7 +885,7 @@
 /*
  * xdopen: open drive
  */
-int 
+int
 xdopen(dev_t dev, int flag, int fmt, struct lwp *l)
 {
 	int err, unit, part, s;
@@ -943,14 +943,14 @@
 	return (err);
 }
 
-int 
+int
 xdread(dev_t dev, struct uio *uio, int flags)
 {
 
 	return (physio(xdstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
-int 
+int
 xdwrite(dev_t dev, struct uio *uio, int flags)
 {
 
@@ -961,7 +961,7 @@
 /*
  * xdsize: return size of a partition for a dump
  */
-int 
+int
 xdsize(dev_t dev)
 {
 	struct xd_softc *xdsc;
@@ -992,7 +992,7 @@
 /*
  * xdstrategy: buffering system interface to xd.
  */
-void 
+void
 xdstrategy(struct buf *bp)
 {
 	struct xd_softc *xd;
@@ -1087,7 +1087,7 @@
  *
  * xdcintr: hardware interrupt.
  */
-int 
+int
 xdcintr(void *v)
 {
 	struct xdc_softc *xdcsc = v;
@@ -1120,7 +1120,7 @@
  * xdc_rqinit: fill out the fields of an I/O request
  */
 
-inline void 
+inline void
 xdc_rqinit(struct xd_iorq *rq, struct xdc_softc *xdc, struct xd_softc *xd,
     int md, u_long blk, int cnt, caddr_t db, struct buf *bp)
 {
@@ -1138,7 +1138,7 @@
 /*
  * xdc_rqtopb: load up an IOPB based on an iorq
  */
-void 
+void
 xdc_rqtopb(struct xd_iorq *iorq, struct xd_iopb *iopb, int cmd, int subfun)
 {
 	u_long  block, dp;
@@ -1248,7 +1248,7 @@
  * If you've already got an IORQ, you can call submit directly (currently
  * there is no need to do this).    NORM requests are handled separately.
  */
-int 
+int
 xdc_cmd(struct xdc_softc *xdcsc, int cmd, int subfn, int unit, int block,
     int scnt, char *dptr, int fullmode)
 {
@@ -1308,7 +1308,7 @@
  * xdc_startbuf
  * start a buffer running, assumes nfree > 0
  */
-int 
+int
 xdc_startbuf(struct xdc_softc *xdcsc, struct xd_softc *xdsc, struct buf *bp)
 {
 	int     rqno, partno;
@@ -1382,7 +1382,7 @@
 	xdc_rqtopb(iorq, iopb, (bp->b_flags & B_READ) ? XDCMD_RD : XDCMD_WR, 0);
 
 	/* Instrumentation. */
-	disk_busy(&xdsc->sc_dk);
+	drive_busy(xdsc->sc_dk.stats);
 
 	/* now submit [note that xdc_submit_iorq can never fail on NORM reqs] */
 
@@ -1421,7 +1421,7 @@
  * on the iorq free list until some iopbs are available.
  */
 
-int 
+int
 xdc_submit_iorq(struct xdc_softc *xdcsc, int iorqno, int type)
 {
 	u_long  iopbaddr;
@@ -1498,7 +1498,7 @@
  * the caller is interesting in.   if freeone is true, then it returns
  * when there is a free iorq.
  */
-int 
+int
 xdc_piodriver(struct xdc_softc *xdcsc, int iorqno, int freeone)
 {
 	int     nreset = 0;
@@ -1572,7 +1572,7 @@
  * xdc_reset: reset one drive.   NOTE: assumes xdc was just reset.
  * we steal iopb[0] for this, but we put it back when we are done.
  */
-void 
+void
 xdc_xdreset(struct xdc_softc *xdcsc, struct xd_softc *xdsc)
 {
 	struct xd_iopb tmpiopb;
@@ -1603,7 +1603,7 @@
  * xdc_reset: reset everything: requests are marked as errors except
  * a polled request (which is resubmitted)
  */
-int 
+int
 xdc_reset(struct xdc_softc *xdcsc, int quiet, int blastmode, int error,
     struct xd_softc *xdsc)
 {
@@ -1649,7 +1649,7 @@
 				/* Sun3: map/unmap regardless of B_PHYS */
 				dvma_mapout(iorq->dbufbase,
 				            iorq->buf->b_bcount);
-			    disk_unbusy(&iorq->xd->sc_dk,
+			    drive_unbusy(iorq->xd->sc_dk.stats,
 					(iorq->buf->b_bcount - iorq->buf->b_resid),
 					(iorq->buf->b_flags & B_READ));
 			    biodone(iorq->buf);
@@ -1697,7 +1697,7 @@
 /*
  * xdc_start: start all waiting buffers
  */
-void 
+void
 xdc_start(struct xdc_softc *xdcsc, int maxio)
 {
 	int     rqno;
@@ -1714,7 +1714,7 @@
 /*
  * xdc_remove_iorq: remove "done" IOPB's.
  */
-int 
+int
 xdc_remove_iorq(struct xdc_softc *xdcsc)
 {
 	int     errno, rqno, comm, errs;
@@ -1850,7 +1850,7 @@
 			/* Sun3: map/unmap regardless of B_PHYS */
 			dvma_mapout(iorq->dbufbase,
 					    iorq->buf->b_bcount);
-			disk_unbusy(&iorq->xd->sc_dk,
+			drive_unbusy(iorq->xd->sc_dk.stats,
 			    (bp->b_bcount - bp->b_resid),
 			    (bp->b_flags & B_READ));
 			XDC_FREE(xdcsc, rqno);
@@ -1880,7 +1880,7 @@
  *   is in lasterror. also, if iorq->errno == 0, then we recovered
  *   from that error (otherwise iorq->errno == iorq->lasterror).
  */
-void 
+void
 xdc_perror(struct xd_iorq *iorq, struct xd_iopb *iopb, int still_trying)
 {
 
@@ -1910,7 +1910,7 @@
  * xdc_error: non-fatal error encountered... recover.
  * return AOK if resubmitted, return FAIL if this iopb is done
  */
-int 
+int
 xdc_error(struct xdc_softc *xdcsc, struct xd_iorq *iorq, struct xd_iopb *iopb,
     int rqno, int comm)
 
@@ -1979,7 +1979,7 @@
 /*
  * xdc_tick: make sure xd is still alive and ticking (err, kicking).
  */
-void 
+void
 xdc_tick(void *arg)
 
 {
@@ -2072,7 +2072,7 @@
  * in user code, and is also useful for some debugging.   we return
  * an error code.   called at user priority.
  */
-int 
+int
 xdc_ioctlcmd(struct xd_softc *xd, dev_t dev, struct xd_iocmd *xio)
 
 {
Index: sys/arch/sun3/dev/xy.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sun3/dev/xy.c,v
retrieving revision 1.53
diff -u -r1.53 xy.c
--- sys/arch/sun3/dev/xy.c	11 Dec 2005 12:19:21 -0000	1.53
+++ sys/arch/sun3/dev/xy.c	5 Mar 2006 11:43:34 -0000
@@ -240,7 +240,7 @@
 
 static void *xy_labeldata;
 
-static void 
+static void
 xydummystrat(struct buf *bp)
 {
 	if (bp->b_bcount != XYFM_BPS)
@@ -250,7 +250,7 @@
 	bp->b_flags &= ~B_BUSY;
 }
 
-int 
+int
 xygetdisklabel(struct xy_softc *xy, void *b)
 {
 	const char *err;
@@ -305,7 +305,7 @@
  * xycmatch: determine if xyc is present or not.   we do a
  * soft reset to detect the xyc.
  */
-static int 
+static int
 xycmatch(struct device *parent, struct cfdata *cf, void *aux)
 {
 	struct confargs *ca = aux;
@@ -328,7 +328,7 @@
 /*
  * xycattach: attach controller
  */
-static void 
+static void
 xycattach(struct device *parent, struct device *self, void *aux)
 {
 	struct xyc_softc *xyc = (void *) self;
@@ -443,7 +443,7 @@
 	callout_reset(&xyc->sc_tick_ch, XYC_TICKCNT, xyc_tick, xyc);
 }
 
-static int 
+static int
 xyc_print(void *aux, const char *name)
 {
 	struct xyc_attach_args *xa = aux;
@@ -465,7 +465,7 @@
  * call xyattach!).  Also, wire down the relationship between the
  * xy* and xyc* devices, to simplify boot device identification.
  */
-static int 
+static int
 xymatch(struct device *parent, struct cfdata *cf, void *aux)
 {
 	struct xyc_attach_args *xa = aux;
@@ -482,7 +482,7 @@
 /*
  * xyattach: attach a disk.
  */
-static void 
+static void
 xyattach(struct device *parent, struct device *self, void *aux)
 {
 	struct xy_softc *xy = (void *) self;
@@ -522,7 +522,7 @@
  * Initialize a disk.  This can be called from both autoconf and
  * also from xyopen/xystrategy.
  */
-static void 
+static void
 xy_init(struct xy_softc *xy)
 {
 	struct xyc_softc *xyc;
@@ -691,7 +691,7 @@
 /*
  * xyclose: close device
  */
-int 
+int
 xyclose(dev_t dev, int flag, int fmt, struct lwp *l)
 {
 	struct xy_softc *xy = xy_cd.cd_devs[DISKUNIT(dev)];
@@ -715,7 +715,7 @@
 /*
  * xydump: crash dump system
  */
-int 
+int
 xydump(dev_t dev, daddr_t blkno, caddr_t va, size_t sz)
 {
 	int     unit, part;
@@ -750,7 +750,7 @@
 /*
  * xyioctl: ioctls on XY drives.   based on ioctl's of other netbsd disks.
  */
-int 
+int
 xyioctl(dev_t dev, u_long command, caddr_t addr, int flag, struct lwp *l)
 {
 	struct xy_softc *xy;
@@ -838,7 +838,7 @@
 /*
  * xyopen: open drive
  */
-int 
+int
 xyopen(dev_t dev, int flag, int fmt, struct lwp *l)
 {
 	int err, unit, part, s;
@@ -896,14 +896,14 @@
 	return (err);
 }
 
-int 
+int
 xyread(dev_t dev, struct uio *uio, int flags)
 {
 
 	return (physio(xystrategy, NULL, dev, B_READ, minphys, uio));
 }
 
-int 
+int
 xywrite(dev_t dev, struct uio *uio, int flags)
 {
 
@@ -915,7 +915,7 @@
  * xysize: return size of a partition for a dump
  */
 
-int 
+int
 xysize(dev_t dev)
 {
 	struct xy_softc *xysc;
@@ -946,7 +946,7 @@
 /*
  * xystrategy: buffering system interface to xy.
  */
-void 
+void
 xystrategy(struct buf *bp)
 {
 	struct xy_softc *xy;
@@ -1035,7 +1035,7 @@
  *
  * xycintr: hardware interrupt.
  */
-int 
+int
 xycintr(void *v)
 {
 	struct xyc_softc *xycsc = v;
@@ -1063,7 +1063,7 @@
  * xyc_rqinit: fill out the fields of an I/O request
  */
 
-inline void 
+inline void
 xyc_rqinit(struct xy_iorq *rq, struct xyc_softc *xyc, struct xy_softc *xy,
     int md, u_long blk, int cnt, caddr_t db, struct buf *bp)
 {
@@ -1082,7 +1082,7 @@
  * xyc_rqtopb: load up an IOPB based on an iorq
  */
 
-void 
+void
 xyc_rqtopb(struct xy_iorq *iorq, struct xy_iopb *iopb, int cmd, int subfun)
 {
 	u_long  block, dp;
@@ -1129,7 +1129,7 @@
  * xyc_unbusy: wait for the xyc to go unbusy, or timeout.
  */
 
-int 
+int
 xyc_unbusy(struct xyc *xyc, int del)
 {
 	while (del-- > 0) {
@@ -1144,7 +1144,7 @@
  * xyc_cmd: front end for POLL'd and WAIT'd commands.  Returns 0 or error.
  * note that NORM requests are handled separately.
  */
-int 
+int
 xyc_cmd(struct xyc_softc *xycsc, int cmd, int subfn, int unit, int block,
     int scnt, char *dptr, int fullmode)
 {
@@ -1190,7 +1190,7 @@
  * start a buffer for running
  */
 
-int 
+int
 xyc_startbuf(struct xyc_softc *xycsc, struct xy_softc *xysc, struct buf *bp)
 {
 	int     partno;
@@ -1254,7 +1254,7 @@
 	xyc_rqtopb(iorq, iopb, (bp->b_flags & B_READ) ? XYCMD_RD : XYCMD_WR, 0);
 
 	/* Instrumentation. */
-	disk_busy(&xysc->sc_dk);
+	drive_busy(xysc->sc_dk.stats);
 
 	return (XY_ERR_AOK);
 }
@@ -1293,7 +1293,7 @@
  * on the iorq free list until some iopbs are available.
  */
 
-int 
+int
 xyc_submit_iorq(struct xyc_softc *xycsc, struct xy_iorq *iorq, int type)
 {
 	struct xy_iopb *iopb;
@@ -1435,7 +1435,7 @@
  * and drains off the polled i/o request.   it returns the status of the iorq
  * the caller is interesting in.
  */
-int 
+int
 xyc_piodriver(struct xyc_softc *xycsc, struct xy_iorq *iorq)
 {
 	int     nreset = 0;
@@ -1494,7 +1494,7 @@
  * xyc_xyreset: reset one drive.   NOTE: assumes xyc was just reset.
  * we steal iopb[XYC_CTLIOPB] for this, but we put it back when we are done.
  */
-void 
+void
 xyc_xyreset(struct xyc_softc *xycsc, struct xy_softc *xysc)
 {
 	struct xy_iopb tmpiopb;
@@ -1533,7 +1533,7 @@
  * xyc_reset: reset everything: requests are marked as errors except
  * a polled request (which is resubmitted)
  */
-int 
+int
 xyc_reset(struct xyc_softc *xycsc, int quiet, struct xy_iorq *blastmode,
     int error, struct xy_softc *xysc)
 {
@@ -1579,7 +1579,7 @@
 				dvma_mapout(iorq->dbufbase,
 				            iorq->buf->b_bcount);
 			    (void)BUFQ_GET(iorq->xy->xyq);
-			    disk_unbusy(&iorq->xy->sc_dk,
+			    drive_unbusy(iorq->xy->sc_dk.stats,
 				(iorq->buf->b_bcount - iorq->buf->b_resid),
 				(iorq->buf->b_flags & B_READ));
 			    biodone(iorq->buf);
@@ -1612,7 +1612,7 @@
  * xyc_start: start waiting buffers
  */
 
-void 
+void
 xyc_start(struct xyc_softc *xycsc, struct xy_iorq *iorq)
 {
 	int lcv;
@@ -1633,7 +1633,7 @@
  * xyc_remove_iorq: remove "done" IOPB's.
  */
 
-int 
+int
 xyc_remove_iorq(struct xyc_softc *xycsc)
 {
 	int     errno, rq, comm, errs;
@@ -1752,7 +1752,7 @@
 			dvma_mapout(iorq->dbufbase,
 					    iorq->buf->b_bcount);
 			(void)BUFQ_GET(iorq->xy->xyq);
-			disk_unbusy(&iorq->xy->sc_dk,
+			drive_unbusy(iorq->xy->sc_dk.stats,
 			    (bp->b_bcount - bp->b_resid),
 			    (bp->b_flags & B_READ));
 			iorq->mode = XY_SUB_FREE;
@@ -1780,7 +1780,7 @@
  *   is in lasterror. also, if iorq->errno == 0, then we recovered
  *   from that error (otherwise iorq->errno == iorq->lasterror).
  */
-void 
+void
 xyc_perror(struct xy_iorq *iorq, struct xy_iopb *iopb, int still_trying)
 {
 
@@ -1809,7 +1809,7 @@
  * xyc_error: non-fatal error encountered... recover.
  * return AOK if resubmitted, return FAIL if this iopb is done
  */
-int 
+int
 xyc_error(struct xyc_softc *xycsc, struct xy_iorq *iorq, struct xy_iopb *iopb,
     int comm)
 {
@@ -1873,7 +1873,7 @@
 /*
  * xyc_tick: make sure xy is still alive and ticking (err, kicking).
  */
-void 
+void
 xyc_tick(void *arg)
 {
 	struct xyc_softc *xycsc = arg;
@@ -1908,7 +1908,7 @@
  *
  * XXX missing a few commands (see the 7053 driver for ideas)
  */
-int 
+int
 xyc_ioctlcmd(struct xy_softc *xy, dev_t dev, struct xd_iocmd *xio)
 {
 	int     s, err, rqno;
@@ -2046,7 +2046,7 @@
 	}
 }
 
-int 
+int
 xyc_entoact(int errno)
 {
 	switch (errno) {
Index: sys/arch/vax/mba/hp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/mba/hp.c,v
retrieving revision 1.39
diff -u -r1.39 hp.c
--- sys/arch/vax/mba/hp.c	11 Dec 2005 12:19:35 -0000	1.39
+++ sys/arch/vax/mba/hp.c	5 Mar 2006 11:43:34 -0000
@@ -13,7 +13,7 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *      This product includes software developed at Ludd, University of 
+ *      This product includes software developed at Ludd, University of
  *      Lule}, Sweden and its contributors.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission
@@ -234,8 +234,8 @@
 	/*
 	 * Collect statistics.
 	 */
-	disk_busy(&sc->sc_disk);
-	sc->sc_disk.dk_seek++;
+	drive_busy(sc->sc_disk.stats);
+	sc->sc_disk->stats.seek++;
 
 	bn = bp->b_rawblkno;
 	if (bn) {
@@ -380,7 +380,7 @@
 	case -1:
 		HP_WCSR(HP_ER1, 0);
 		goto hper2;
-		
+
 	case HPER1_DCK: /* Corrected? data read. Just notice. */
 		bc = bus_space_read_4(md->md_mba->sc_iot,
 		    md->md_mba->sc_ioh, MBA_BC);
@@ -406,7 +406,7 @@
 		    sc->sc_dev.dv_xname, mbasr);
 
 	BUFQ_PEEK(md->md_q)->b_resid = 0;
-	disk_unbusy(&sc->sc_disk, BUFQ_PEEK(md->md_q)->b_bcount,
+	drive_unbusy(sc->sc_disk.stats, BUFQ_PEEK(&md->md_q)->b_bcount,
 	    (bp->b_flags & B_READ));
 	return XFER_FINISH;
 }
Index: sys/arch/x68k/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/fd.c,v
retrieving revision 1.68
diff -u -r1.68 fd.c
--- sys/arch/x68k/dev/fd.c	23 Feb 2006 05:37:48 -0000	1.68
+++ sys/arch/x68k/dev/fd.c	5 Mar 2006 11:43:34 -0000
@@ -420,7 +420,7 @@
 
 	printf("\n");
 
-	callout_init(&fdc->sc_timo_ch); 
+	callout_init(&fdc->sc_timo_ch);
 	callout_init(&fdc->sc_intr_ch);
 
 	/* Re-map the I/O space. */
@@ -1109,8 +1109,8 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return 1;
@@ -1183,7 +1183,7 @@
 			 head, sec, nblks, fd->sc_skip));
 		DPRINTF(("C H R N: %d %d %d %d\n", fd->sc_cylin, head, sec,
 			 type->secsize));
-			 
+
 		if (fd->sc_part != SEC_P11)
 			goto docopy;
 
@@ -1203,7 +1203,7 @@
 		out_fdc(iot, ioh, type->datalen);	/* data length */
 		fdc->sc_state = IOCOMPLETE;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
Index: sys/arch/xen/xen/xbd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xbd.c,v
retrieving revision 1.27
diff -u -r1.27 xbd.c
--- sys/arch/xen/xen/xbd.c	26 Dec 2005 10:36:47 -0000	1.27
+++ sys/arch/xen/xen/xbd.c	5 Mar 2006 11:43:34 -0000
@@ -267,7 +267,7 @@
 #endif
 
 #ifdef DIAGNOSTIC
-#define DIAGPANIC(x)		panic x 
+#define DIAGPANIC(x)		panic x
 #define DIAGCONDPANIC(x,y)	if (x) panic y
 #else
 #define DIAGPANIC(x)
@@ -559,7 +559,7 @@
 	    "xbd");
 	hypervisor_enable_event(blkif_evtchn);
 
-	/* Transition to connected in case we need to do 
+	/* Transition to connected in case we need to do
 	 *  a partition probe on a whole disk. */
 	state = STATE_CONNECTED;
 
@@ -712,7 +712,7 @@
 unexpected(blkif_fe_interface_status_t *status)
 {
 
-	printf("Unexpected blkif status %d in state %d\n", 
+	printf("Unexpected blkif status %d in state %d\n",
 	    status->status, state);
 }
 
@@ -797,7 +797,7 @@
 			goto parse_error;
 		blkif_status((blkif_fe_interface_status_t *)
 		    &msg->msg[0]);
-		break;        
+		break;
 	default:
 		goto parse_error;
 	}
@@ -856,7 +856,7 @@
 		goto retry;
 	}
 
-	blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req;    
+	blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req;
 
 	GET_XBDREQ(xr);
 	blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req.id = (unsigned long)xr;
@@ -889,7 +889,7 @@
 		.length  = sizeof(blkif_fe_driver_status_t),
 	};
 	blkif_fe_driver_status_t *msg = (blkif_fe_driver_status_t *)cmsg.msg;
-    
+
 	msg->status = ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN;
 
 	ctrl_if_send_message_block(&cmsg, NULL, 0, 0);
@@ -1039,7 +1039,7 @@
 	struct	xbd_softc *xs = (struct	xbd_softc *)dv;
 	int bmaj, cmaj, mn, i;
 
-	/* 
+	/*
 	 * Mark disk about to be removed (between now and when the xs
 	 * will be freed).
 	 */
@@ -1282,7 +1282,7 @@
 					unmap_align(pxr);
 				PUT_XBDREQ(pxr);
 				if (xs) {
-					disk_unbusy(&xs->sc_dksc.sc_dkdev,
+					drive_unbusy(xs->sc_dksc.sc_dkdev.stats,
 					    (bp->b_bcount - bp->b_resid),
 					    (bp->b_flags & B_READ));
 #if NRND > 0
@@ -1342,7 +1342,7 @@
 	if (__predict_false(pxr == NULL))
 		goto out;
 
-	disk_busy(&dksc->sc_dkdev); /* XXX: put in dksubr.c */
+	drive_busy(dksc->sc_dkdev.stats); /* XXX: put in dksubr.c */
 	/*
 	 * We have a request slot, return 0 to make dk_start remove
 	 * the bp from the work queue.
@@ -1376,7 +1376,7 @@
 		DPRINTF(XBDB_IO, ("xbdstart: suspended xbdreq %p "
 		    "for bp %p\n", pxr, bp));
 	} else if (CANGET_XBDREQ() && BUFQ_PEEK(bufq) != NULL) {
-		/* 
+		/*
 		 * We have enough resources to start another bp and
 		 * there are additional bps on the queue, dk_start
 		 * will call us again and we'll run the queue then.
@@ -1449,7 +1449,7 @@
 
 				PUT_XBDREQ(pxr);
 				if (xs) {
-					disk_unbusy(&xs->sc_dksc.sc_dkdev,
+					drive_unbusy(xs->sc_dksc.sc_dkdev.stats,
 					    (bp->b_bcount - bp->b_resid),
 					    (bp->b_flags & B_READ));
 #if NRND > 0
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.763
diff -u -r1.763 files
--- sys/conf/files	1 Mar 2006 22:12:09 -0000	1.763
+++ sys/conf/files	5 Mar 2006 11:43:34 -0000
@@ -1242,6 +1242,7 @@
 file	kern/subr_bufq.c
 file	kern/subr_devsw.c
 file	kern/subr_disk.c
+file	kern/subr_iostat.c
 file	kern/subr_evcnt.c
 file	kern/subr_extent.c
 file	kern/subr_log.c
Index: sys/dev/ccd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ccd.c,v
retrieving revision 1.108
diff -u -r1.108 ccd.c
--- sys/dev/ccd.c	16 Feb 2006 23:25:18 -0000	1.108
+++ sys/dev/ccd.c	5 Mar 2006 11:43:34 -0000
@@ -721,7 +721,7 @@
 	/* See if there is work for us to do. */
 	while ((bp = BUFQ_PEEK(cs->sc_bufq)) != NULL) {
 		/* Instrumentation. */
-		disk_busy(&cs->sc_dkdev);
+		drive_busy(cs->sc_dkdev.stats);
 
 		bp->b_resid = bp->b_bcount;
 		bn = bp->b_rawblkno;
@@ -745,7 +745,7 @@
 					SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
 					CCD_PUTBUF(cbp);
 				}
-				disk_unbusy(&cs->sc_dkdev, 0, 0);
+				drive_unbusy(cs->sc_dkdev.stats, 0, 0);
 				return;
 			}
 			SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
@@ -883,7 +883,7 @@
 	 */
 	if (bp->b_flags & B_ERROR)
 		bp->b_resid = bp->b_bcount;
-	disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(cs->sc_dkdev.stats, (bp->b_bcount - bp->b_resid),
 	    (bp->b_flags & B_READ));
 	biodone(bp);
 }
Index: sys/dev/cgd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cgd.c,v
retrieving revision 1.34
diff -u -r1.34 cgd.c
--- sys/dev/cgd.c	4 Jan 2006 17:16:35 -0000	1.34
+++ sys/dev/cgd.c	5 Mar 2006 11:43:34 -0000
@@ -298,7 +298,7 @@
 	daddr_t	bn;
 
 	DPRINTF_FOLLOW(("cgdstart(%p, %p)\n", dksc, bp));
-	disk_busy(&dksc->sc_dkdev); /* XXX: put in dksubr.c */
+	drive_busy(dksc->sc_dkdev.stats); /* XXX: put in dksubr.c */
 
 	bn = bp->b_rawblkno;
 
@@ -309,7 +309,8 @@
 
 	nbp = getiobuf_nowait();
 	if (nbp == NULL) {
-		disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
+		drive_unbusy(dksc->sc_dkdev.stats, 0,
+			     (bp->b_flags & B_READ));
 		return -1;
 	}
 
@@ -323,7 +324,8 @@
 		newaddr = cgd_getdata(dksc, bp->b_bcount);
 		if (!newaddr) {
 			putiobuf(nbp);
-			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
+			drive_unbusy(dksc->sc_dkdev.stats, 0,
+				    (bp->b_flags & B_READ));
 			return -1;
 		}
 		cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
@@ -391,7 +393,7 @@
 	obp->b_resid = 0;
 	if (obp->b_flags & B_ERROR)
 		obp->b_resid = obp->b_bcount;
-	disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
+	drive_unbusy(dksc->sc_dkdev.stats, obp->b_bcount - obp->b_resid,
 	    (obp->b_flags & B_READ));
 	biodone(obp);
 	dk_iodone(di, dksc);
Index: sys/dev/ld.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ld.c,v
retrieving revision 1.39
diff -u -r1.39 ld.c
--- sys/dev/ld.c	11 Dec 2005 12:20:53 -0000	1.39
+++ sys/dev/ld.c	5 Mar 2006 11:43:34 -0000
@@ -612,7 +612,7 @@
 		if ((bp = BUFQ_PEEK(sc->sc_bufq)) == NULL)
 			break;
 
-		disk_busy(&sc->sc_dk);
+		drive_busy(sc->sc_dk.stats);
 		sc->sc_queuecnt++;
 
 		if (__predict_true((error = (*sc->sc_start)(sc, bp)) == 0)) {
@@ -622,7 +622,8 @@
 			 */
 			(void) BUFQ_GET(sc->sc_bufq);
 		} else  {
-			disk_unbusy(&sc->sc_dk, 0, (bp->b_flags & B_READ));
+			drive_unbusy(sc->sc_dk.stats, 0,
+				     (bp->b_flags & B_READ));
 			sc->sc_queuecnt--;
 			if (error == EAGAIN) {
 				/*
@@ -654,7 +655,7 @@
 		printf("\n");
 	}
 
-	disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid,
+	drive_unbusy(sc->sc_dk.stats, bp->b_bcount - bp->b_resid,
 	    (bp->b_flags & B_READ));
 #if NRND > 0
 	rnd_add_uint32(&sc->sc_rnd_source, bp->b_rawblkno);
Index: sys/dev/vnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vnd.c,v
retrieving revision 1.141
diff -u -r1.141 vnd.c
--- sys/dev/vnd.c	1 Mar 2006 12:38:13 -0000	1.141
+++ sys/dev/vnd.c	5 Mar 2006 11:43:35 -0000
@@ -571,7 +571,7 @@
 			goto done;
 		}
 #endif /* VND_COMPRESSION */
-		
+
 		bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize;
 
 		/*
@@ -609,7 +609,7 @@
 		}
 
 		/* Instrumentation. */
-		disk_busy(&vnd->sc_dkdev);
+		drive_busy(vnd->sc_dkdev.stats);
 
 		/*
 		 * Feed requests sequentially.
@@ -629,7 +629,7 @@
 			vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
 			error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
 			VOP_UNLOCK(vnd->sc_vp, 0);
-	
+
 			if (error == 0 && (long)nbn == -1)
 				error = EIO;
 
@@ -681,7 +681,7 @@
 
 		if ((flags & B_READ) == 0)
 			vn_finished_write(mp, 0);
-		
+
 		s = splbio();
 		continue;
 done:
@@ -710,7 +710,7 @@
 		    bp, (bp->b_flags & B_ERROR) != 0 ? bp->b_error : 0);
 	}
 #endif
-	disk_unbusy(&vnd->sc_dkdev, bp->b_bcount - bp->b_resid,
+	drive_unbusy(vnd->sc_dkdev.stats, bp->b_bcount - bp->b_resid,
 	    (bp->b_flags & B_READ));
 	vnd->sc_active--;
 	if (vnd->sc_active == 0) {
@@ -884,11 +884,11 @@
 			int i;
 			u_int32_t comp_size;
 			u_int32_t comp_maxsize;
- 
+
 			/* allocate space for compresed file header */
 			ch = malloc(sizeof(struct vnd_comp_header),
 			M_TEMP, M_WAITOK);
- 
+
 			/* read compressed file header */
 			error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)ch,
 			  sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE,
@@ -898,7 +898,7 @@
 				VOP_UNLOCK(nd.ni_vp, 0);
 				goto close_and_exit;
 			}
- 
+
 			/* save some header info */
 			vnd->sc_comp_blksz = ntohl(ch->block_size);
 			/* note last offset is the file byte size */
@@ -916,16 +916,16 @@
 				error = EINVAL;
 				goto close_and_exit;
 			}
- 
+
 			/* set decompressed file size */
 			vattr.va_size =
 			  (vnd->sc_comp_numoffs - 1) * vnd->sc_comp_blksz;
- 
+
 			/* allocate space for all the compressed offsets */
 			vnd->sc_comp_offsets =
 			malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs,
 			M_DEVBUF, M_WAITOK);
- 
+
 			/* read in the offsets */
 			error = vn_rdwr(UIO_READ, nd.ni_vp,
 			  (caddr_t)vnd->sc_comp_offsets,
@@ -951,16 +951,16 @@
 			}
 			vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] =
 			  be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]);
- 
+
 			/* create compressed data buffer */
 			vnd->sc_comp_buff = malloc(comp_maxsize,
 			  M_DEVBUF, M_WAITOK);
- 
+
 			/* create decompressed buffer */
 			vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz,
 			  M_DEVBUF, M_WAITOK);
 			vnd->sc_comp_buffblk = -1;
- 
+
 			/* Initialize decompress stream */
 			bzero(&vnd->sc_comp_stream, sizeof(z_stream));
 			vnd->sc_comp_stream.zalloc = vnd_alloc;
@@ -974,7 +974,7 @@
 				error = EINVAL;
 				goto close_and_exit;
 			}
- 
+
 			vnd->sc_flags |= VNF_COMP | VNF_READONLY;
 #else /* !VND_COMPRESSION */
 			VOP_UNLOCK(nd.ni_vp, 0);
@@ -982,7 +982,7 @@
 			goto close_and_exit;
 #endif /* VND_COMPRESSION */
 		}
- 
+
 		VOP_UNLOCK(nd.ni_vp, 0);
 		vnd->sc_vp = nd.ni_vp;
 		vnd->sc_size = btodb(vattr.va_size);	/* note truncation */
Index: sys/dev/ata/wd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wd.c,v
retrieving revision 1.320
diff -u -r1.320 wd.c
--- sys/dev/ata/wd.c	1 Mar 2006 12:38:13 -0000	1.320
+++ sys/dev/ata/wd.c	5 Mar 2006 11:43:35 -0000
@@ -730,7 +730,7 @@
 	wd->sc_wdc_bio.bcount = bp->b_bcount;
 	wd->sc_wdc_bio.databuf = bp->b_data;
 	/* Instrumentation. */
-	disk_busy(&wd->sc_dk);
+	drive_busy(wd->sc_dk.stats);
 	switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
 	case ATACMD_TRY_AGAIN:
 		callout_reset(&wd->sc_restart_ch, hz, wdrestart, wd);
@@ -826,7 +826,7 @@
 		bp->b_error = EIO;
 		break;
 	}
-	disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(wd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 	    (bp->b_flags & B_READ));
 #if NRND > 0
 	rnd_add_uint32(&wd->rnd_source, bp->b_blkno);
@@ -1449,7 +1449,7 @@
 
 		return 0;
 	    }
-	
+
 	case DIOCSSTRATEGY:
 	    {
 		struct disk_strategy *dks = (void *)addr;
Index: sys/dev/dkwedge/dk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dkwedge/dk.c,v
retrieving revision 1.12
diff -u -r1.12 dk.c
--- sys/dev/dkwedge/dk.c	1 Mar 2006 12:38:13 -0000	1.12
+++ sys/dev/dkwedge/dk.c	5 Mar 2006 11:43:35 -0000
@@ -269,6 +269,7 @@
 {
 	struct dkwedge_softc *sc, *lsc;
 	struct disk *pdk;
+	struct io_stats *statp;
 	u_int unit;
 	int error;
 	dev_t pdev;
@@ -277,7 +278,8 @@
 		dkwedge_cfglue_init();
 
 	dkw->dkw_parent[sizeof(dkw->dkw_parent) - 1] = '\0';
-	pdk = disk_find(dkw->dkw_parent);
+	statp = drive_find(dkw->dkw_parent);
+	pdk = (struct disk *) statp->parent;
 	if (pdk == NULL)
 		return (ENODEV);
 
@@ -1046,7 +1048,7 @@
 		}
 
 		/* Instrumentation. */
-		disk_busy(&sc->sc_dk);
+		drive_busy(sc->sc_dk.stats);
 
 		nbp = getiobuf_nowait();
 		if (nbp == NULL) {
@@ -1055,7 +1057,8 @@
 			 * buffer queued up, and schedule a timer to
 			 * restart the queue in 1/2 a second.
 			 */
-			disk_unbusy(&sc->sc_dk, 0, bp->b_flags & B_READ);
+			drive_unbusy(sc->sc_dk.stats, 0,
+				     bp->b_flags & B_READ);
 			callout_schedule(&sc->sc_restart_ch, hz / 2);
 			return;
 		}
@@ -1104,7 +1107,7 @@
 		wakeup(&sc->sc_iopend);
 	}
 
-	disk_unbusy(&sc->sc_dk, obp->b_bcount - obp->b_resid,
+	drive_unbusy(sc->sc_dk.stats, obp->b_bcount - obp->b_resid,
 	    obp->b_flags & B_READ);
 
 	biodone(obp);
Index: sys/dev/gpib/rd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpib/rd.c,v
retrieving revision 1.8
diff -u -r1.8 rd.c
--- sys/dev/gpib/rd.c	25 Feb 2006 02:28:58 -0000	1.8
+++ sys/dev/gpib/rd.c	5 Mar 2006 11:43:35 -0000
@@ -784,8 +784,8 @@
 	if (gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_ioc.c_unit,
 	    sizeof(sc->sc_ioc)-1) == sizeof(sc->sc_ioc)-1) {
 		/* Instrumentation. */
-		disk_busy(&sc->sc_dk);
-		sc->sc_dk.dk_seek++;
+		drive_busy(sc->sc_dk.stats);
+		sc->sc_dk.stats->seek++;
 		gpibawait(sc->sc_ic);
 		return;
 	}
@@ -834,7 +834,7 @@
 	    sc->sc_dev.dv_xname, bp, (bp->b_flags & B_READ) ? 'R' : 'W',
 	    sc->sc_flags));
 
-	disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(sc->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		(bp->b_flags & B_READ));
 
 	if (sc->sc_flags & RDF_SEEK) {
@@ -842,13 +842,13 @@
 		dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE);
 		gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr,
 		    sc->sc_resid, dir, dir == GPIB_READ);
-		disk_busy(&sc->sc_dk);
+		drive_busy(sc->sc_dk.stats);
 		return;
 	}
 	if ((sc->sc_flags & RDF_SWAIT) == 0) {
 		if (gpibpptest(sc->sc_ic, slave) == 0) {
 			/* Instrumentation. */
-			disk_busy(&sc->sc_dk);
+			drive_busy(sc->sc_dk.stats);
 			sc->sc_flags |= RDF_SWAIT;
 			gpibawait(sc->sc_ic);
 			return;
Index: sys/dev/isa/fd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/fd.c,v
retrieving revision 1.64
diff -u -r1.64 fd.c
--- sys/dev/isa/fd.c	6 Jan 2006 09:21:44 -0000	1.64
+++ sys/dev/isa/fd.c	5 Mar 2006 11:43:35 -0000
@@ -1042,8 +1042,8 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
-		disk_busy(&fd->sc_dk);
+		fd->sc_dk.stats->seek++;
+		drive_busy(fd->sc_dk.stats);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
 		return 1;
@@ -1114,7 +1114,7 @@
 		}
 		fdc->sc_state = IOCOMPLETE;
 
-		disk_busy(&fd->sc_dk);
+		drive_busy(fd->sc_dk.stats);
 
 		/* allow 2 seconds for operation */
 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
@@ -1129,7 +1129,7 @@
 
 	case SEEKCOMPLETE:
 		/* no data on seek */
-		disk_unbusy(&fd->sc_dk, 0, 0);
+		drive_unbusy(fd->sc_dk.stats, 0, 0);
 
 		/* Make sure seek really happened. */
 		out_fdc(iot, ioh, NE7CMD_SENSEI);
@@ -1155,7 +1155,7 @@
 	case IOCOMPLETE: /* IO DONE, post-analyze */
 		callout_stop(&fdc->sc_timo_ch);
 
-		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
+		drive_unbusy(fd->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 		    (bp->b_flags & B_READ));
 
 		if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
Index: sys/dev/isa/mcd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/mcd.c,v
retrieving revision 1.92
diff -u -r1.92 mcd.c
--- sys/dev/isa/mcd.c	11 Dec 2005 12:22:03 -0000	1.92
+++ sys/dev/isa/mcd.c	5 Mar 2006 11:43:35 -0000
@@ -528,7 +528,7 @@
 
 	/* Instrumentation. */
 	s = splbio();
-	disk_busy(&sc->sc_dk);
+	drive_busy(sc->sc_dk.stats);
 	splx(s);
 
 	sc->mbx.retry = MCD_RDRETRIES;
@@ -1288,7 +1288,8 @@
 
 		/* Return buffer. */
 		bp->b_resid = 0;
-		disk_unbusy(&sc->sc_dk, bp->b_bcount, (bp->b_flags & B_READ));
+		drive_unbusy(sc->sc_dk.stats, bp->b_bcount,
+			     (bp->b_flags & B_READ));
 		biodone(bp);
 
 		mcdstart(sc);
@@ -1321,7 +1322,7 @@
 	/* Invalidate the buffer. */
 	bp->b_flags |= B_ERROR;
 	bp->b_resid = bp->b_bcount - mbx->skip;
-	disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
+	drive_unbusy(sc->sc_dk.stats, (bp->b_bcount - bp->b_resid),
 	    (bp->b_flags & B_READ));
 	biodone(bp);
 
Index: sys/dev/mca/edc_mca.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mca/edc_mca.c,v
retrieving revision 1.32
diff -u -r1.32 edc_mca.c
--- sys/dev/mca/edc_mca.c	11 Dec 2005 12:22:18 -0000	1.32
+++ sys/dev/mca/edc_mca.c	5 Mar 2006 11:43:35 -0000
@@ -870,7 +870,7 @@
 			simple_unlock(&ed->sc_q_lock);
 
 			/* Instrumentation. */
-			disk_busy(&ed->sc_dk);
+			drive_busy(ed->sc_dk.stats);
 
 			error = edc_bio(sc, ed, bp->b_data, bp->b_bcount,
 				bp->b_rawblkno, (bp->b_flags & B_READ), 0);
@@ -883,8 +883,9 @@
 				bp->b_resid = sc->sc_resblk * DEV_BSIZE;
 			}
 
-			disk_unbusy(&ed->sc_dk, (bp->b_bcount - bp->b_resid),
-			    (bp->b_flags & B_READ));
+			drive_unbusy(ed->sc_dk.stats,
+				     (bp->b_bcount - bp->b_resid),
+				     (bp->b_flags & B_READ));
 #if NRND > 0
 			rnd_add_uint32(&ed->rnd_source, bp->b_blkno);
 #endif
Index: sys/dev/mscp/mscp_disk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mscp/mscp_disk.c,v
retrieving revision 1.49
diff -u -r1.49 mscp_disk.c
--- sys/dev/mscp/mscp_disk.c	11 Dec 2005 12:22:47 -0000	1.49
+++ sys/dev/mscp/mscp_disk.c	5 Mar 2006 11:43:36 -0000
@@ -380,7 +380,7 @@
 	if (ra->ra_state == DK_RDLABEL) {
 	        /* Make some statistics... /bqt */
 	        b = splbio();
-	        disk_busy(&ra->ra_disk);
+	        drive_busy(ra->ra_disk.stats);
 		splx(b);
 		mscp_strategy(bp, ra->ra_dev.dv_parent);
 		return;
@@ -403,7 +403,7 @@
 
 	/* Make some statistics... /bqt */
 	b = splbio();
-	disk_busy(&ra->ra_disk);
+	drive_busy(ra->ra_disk.stats);
 	splx(b);
 	mscp_strategy(bp, ra->ra_dev.dv_parent);
 	return;
@@ -839,7 +839,7 @@
 
 	/* Make some statistics... /bqt */
 	b = splbio();
-	disk_busy(&rx->ra_disk);
+	drive_busy(rx->ra_disk.stats);
 	splx(b);
 	mscp_strategy(bp, rx->ra_dev.dv_parent);
 	return;
@@ -1000,7 +1000,8 @@
 #endif
 		panic("rriodone: unexpected major %d unit %d",
 		    major(bp->b_dev), unit);
-	disk_unbusy(&ra->ra_disk, bp->b_bcount, (bp->b_flags & B_READ));
+	drive_unbusy(ra->ra_disk.stats, bp->b_bcount,
+		     (bp->b_flags & B_READ));
 
 	biodone(bp);
 }
Index: sys/dev/ofw/ofdisk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ofw/ofdisk.c,v
retrieving revision 1.32
diff -u -r1.32 ofdisk.c
--- sys/dev/ofw/ofdisk.c	11 Dec 2005 12:22:48 -0000	1.32
+++ sys/dev/ofw/ofdisk.c	5 Mar 2006 11:43:36 -0000
@@ -282,7 +282,7 @@
 	if (bp->b_bcount == 0)
 		goto done;
 
-	OF_io = bp->b_flags & B_READ ? OF_read : 
+	OF_io = bp->b_flags & B_READ ? OF_read :
 		(int(*)(int, void*, int))OF_write;
 
 	if (DISKPART(bp->b_dev) != RAW_PART) {
@@ -294,7 +294,7 @@
 		blkno = bp->b_blkno + p->p_offset;
 	}
 
-	disk_busy(&of->sc_dk);
+	drive_busy(of->sc_dk.stats);
 
 	off = (u_quad_t)blkno * DEV_BSIZE;
 	read = -1;
@@ -311,7 +311,7 @@
 	} else
 		bp->b_resid = bp->b_bcount - read;
 
-	disk_unbusy(&of->sc_dk, bp->b_bcount - bp->b_resid,
+	drive_unbusy(of->sc_dk.stats, bp->b_bcount - bp->b_resid,
 	    (bp->b_flags & B_READ));
 
 done:
Index: sys/dev/qbus/rf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/qbus/rf.c,v
retrieving revision 1.10
diff -u -r1.10 rf.c
--- sys/dev/qbus/rf.c	11 Dec 2005 12:23:29 -0000	1.10
+++ sys/dev/qbus/rf.c	5 Mar 2006 11:43:36 -0000
@@ -663,7 +663,7 @@
 		 */
 		switch (rf_sc->sc_state & RFS_CMDS) {
 		case RFS_PROBING:	/* density detect / verify started */
-			disk_unbusy(&rf_sc->sc_disk, 0, 1);
+			drive_unbusy(rf_sc->sc_disk.stats, 0, 1);
 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
 			    RX2CS) & RX2CS_ERR) == 0) {
 				RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
@@ -674,13 +674,14 @@
 				    && (rf_sc->sc_state & RFS_AD) != 0) {
 					/* retry at DD */
 					rf_sc->sc_state |= RFS_DENS;
-					disk_busy(&rf_sc->sc_disk);
+					drive_busy(rf_sc->sc_disk.stats);
 					if (rfc_sendcmd(rfc_sc, RX2CS_RSEC
 					    | RX2CS_IE | RX2CS_DD |
 					    (rf_sc->sc_dnum == 0 ? 0 :
 					    RX2CS_US), 1, 1) < 0) {
-						disk_unbusy(&rf_sc->sc_disk,
-						    0, 1);
+						drive_unbusy(
+							rf_sc->sc_disk.stats,
+							0, 1);
 						RFS_SETCMD(rf_sc->sc_state,
 						    RFS_NOTINIT);
 						wakeup(rf_sc);
@@ -707,7 +708,7 @@
 			    & B_READ) != 0 ? RFS_RSEC : RFS_FBUF);
 			break;
 		case RFS_RSEC:	/* Read Sector */
-			disk_unbusy(&rf_sc->sc_disk, 0, 1);
+			drive_unbusy(rf_sc->sc_disk.stats, 0, 1);
 			/* check for errors */
 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
 			    RX2CS) & RX2CS_ERR) != 0) {
@@ -722,7 +723,7 @@
 		case RFS_WSEC:	/* Write Sector */
 			i = (rf_sc->sc_state & RFS_DENS) == 0
 				? RX2_BYTE_SD : RX2_BYTE_DD;
-			disk_unbusy(&rf_sc->sc_disk, i, 0);
+			drive_unbusy(rf_sc->sc_disk.stats, i, 0);
 			/* check for errors */
 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
 			    RX2CS) & RX2CS_ERR) != 0) {
@@ -747,7 +748,7 @@
 			    ? RFS_RSEC : RFS_FBUF);
 			break;
 		case RFS_FBUF:	/* Fill Buffer */
-			disk_unbusy(&rf_sc->sc_disk, 0, 0);
+			drive_unbusy(rf_sc->sc_disk.stats, 0, 0);
 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
 			/* check for errors */
 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
@@ -763,7 +764,7 @@
 		case RFS_EBUF:	/* Empty Buffer */
 			i = (rf_sc->sc_state & RFS_DENS) == 0
 			    ? RX2_BYTE_SD : RX2_BYTE_DD;
-			disk_unbusy(&rf_sc->sc_disk, i, 1);
+			drive_unbusy(rf_sc->sc_disk.stats, i, 1);
 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
 			/* check for errors */
 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
@@ -829,7 +830,7 @@
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				break;
 			}
-			disk_busy(&rf_sc->sc_disk);
+			drive_busy(rf_sc->sc_disk.stats);
 			if (rfc_sendcmd(rfc_sc, RX2CS_EBUF | RX2CS_IE
 			    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
@@ -837,7 +838,7 @@
 			    & 0x30000) >>4), ((rf_sc->sc_state & RFS_DENS) == 0
 			    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
 			    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
-				disk_unbusy(&rf_sc->sc_disk, 0, 1);
+				drive_unbusy(rf_sc->sc_disk.stats, 0, 1);
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				bus_dmamap_unload(rfc_sc->sc_dmat,
 				rfc_sc->sc_dmam);
@@ -854,7 +855,7 @@
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				break;
 			}
-			disk_busy(&rf_sc->sc_disk);
+			drive_busy(rf_sc->sc_disk.stats);
 			if (rfc_sendcmd(rfc_sc, RX2CS_FBUF | RX2CS_IE
 			    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
@@ -862,7 +863,7 @@
 			    & 0x30000)>>4), ((rf_sc->sc_state & RFS_DENS) == 0
 			    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
 			    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
-				disk_unbusy(&rf_sc->sc_disk, 0, 0);
+				drive_unbusy(rf_sc->sc_disk.stats, 0, 0);
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				bus_dmamap_unload(rfc_sc->sc_dmat,
 				    rfc_sc->sc_dmam);
@@ -877,12 +878,12 @@
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				break;
 			}
-			disk_busy(&rf_sc->sc_disk);
+			drive_busy(rf_sc->sc_disk.stats);
 			if (rfc_sendcmd(rfc_sc, RX2CS_WSEC | RX2CS_IE
 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
 			    | ((rf_sc->sc_state& RFS_DENS) == 0 ? 0 : RX2CS_DD),
 			    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
-				disk_unbusy(&rf_sc->sc_disk, 0, 0);
+				drive_unbusy(rf_sc->sc_disk.stats, 0, 0);
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 			}
 			break;
@@ -895,12 +896,12 @@
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 				break;
 			}
-			disk_busy(&rf_sc->sc_disk);
+			drive_busy(rf_sc->sc_disk.stats);
 			if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
 			    | ((rf_sc->sc_state& RFS_DENS) == 0 ? 0 : RX2CS_DD),
 			    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
-				disk_unbusy(&rf_sc->sc_disk, 0, 1);
+				drive_unbusy(rf_sc->sc_disk.stats, 0, 1);
 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
 			}
 			break;
@@ -1011,7 +1012,7 @@
 		 * media must be purchased preformatted. fsck DEC makreting!
 		 */
 		RFS_SETCMD(rf_sc->sc_state, RFS_PROBING);
-		disk_busy(&rf_sc->sc_disk);
+		drive_busy(rf_sc->sc_disk.stats);
 		if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD),
@@ -1154,5 +1155,3 @@
 
 	return(ENOTTY);
 }
-
-
Index: sys/dev/raidframe/rf_netbsdkintf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/raidframe/rf_netbsdkintf.c,v
retrieving revision 1.202
diff -u -r1.202 rf_netbsdkintf.c
--- sys/dev/raidframe/rf_netbsdkintf.c	1 Mar 2006 21:41:49 -0000	1.202
+++ sys/dev/raidframe/rf_netbsdkintf.c	5 Mar 2006 11:43:36 -0000
@@ -1768,7 +1768,7 @@
 		 */
 		do_async = 1;
 
-		disk_busy(&rs->sc_dkdev);
+		drive_busy(rs->sc_dkdev.stats);
 
 		/* XXX we're still at splbio() here... do we *really*
 		   need to be? */
@@ -1912,7 +1912,7 @@
 		if (((queue->raidPtr->Disks[queue->col].status ==
 		      rf_ds_optimal) ||
 		     (queue->raidPtr->Disks[queue->col].status ==
-		      rf_ds_used_spare)) && 
+		      rf_ds_used_spare)) &&
 		     (queue->raidPtr->numFailures <
 		         queue->raidPtr->Layout.map->faultsTolerated)) {
 			printf("raid%d: IO Error.  Marking %s as failed.\n",
@@ -3282,7 +3282,7 @@
 	struct buf *bp;
 
 	bp = (struct buf *)desc->bp;
-	disk_unbusy(&raid_softc[desc->raidPtr->raidid].sc_dkdev,
+	drive_unbusy(raid_softc[desc->raidPtr->raidid].sc_dkdev.stats,
 	    (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ));
 }
 
@@ -3311,7 +3311,7 @@
 	    raidPtrs[raidid]->openings > 0) {
 		/* there is work to do */
 		return 0;
-	} 
+	}
 	/* default is nothing to do */
 	return 1;
 }
Index: sys/dev/scsipi/cd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/cd.c,v
retrieving revision 1.240
diff -u -r1.240 cd.c
--- sys/dev/scsipi/cd.c	8 Feb 2006 23:09:15 -0000	1.240
+++ sys/dev/scsipi/cd.c	5 Mar 2006 11:43:36 -0000
@@ -830,7 +830,7 @@
 		}
 
 		/* Instrumentation. */
-		disk_busy(&cd->sc_dk);
+		drive_busy(cd->sc_dk.stats);
 
 		/*
 		 * Figure out what flags to use.
@@ -894,7 +894,7 @@
 		if (error)
 			bp->b_flags |= B_ERROR;
 
-		disk_unbusy(&cd->sc_dk, bp->b_bcount - bp->b_resid,
+		drive_unbusy(cd->sc_dk.stats, bp->b_bcount - bp->b_resid,
 		    (bp->b_flags & B_READ));
 #if NRND > 0
 		rnd_add_uint32(&cd->rnd_source, bp->b_rawblkno);
@@ -3136,7 +3136,7 @@
 }
 
 static int
-mmc_gettrackinfo_dvdrom(struct scsipi_periph *periph, 
+mmc_gettrackinfo_dvdrom(struct scsipi_periph *periph,
 			struct mmc_trackinfo *trackinfo)
 {
 	struct scsipi_read_toc            gtoc_cmd;
@@ -3248,7 +3248,7 @@
 }
 
 static int
-mmc_gettrackinfo(struct scsipi_periph *periph, 
+mmc_gettrackinfo(struct scsipi_periph *periph,
 		 struct mmc_trackinfo *trackinfo)
 {
 	struct scsipi_read_trackinfo      ti_cmd;
@@ -3333,4 +3333,3 @@
 
 	return 0;
 }
-
Index: sys/dev/scsipi/sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.245
diff -u -r1.245 sd.c
--- sys/dev/scsipi/sd.c	20 Feb 2006 16:50:37 -0000	1.245
+++ sys/dev/scsipi/sd.c	5 Mar 2006 11:43:37 -0000
@@ -859,7 +859,7 @@
 		}
 
 		/* Instrumentation. */
-		disk_busy(&sd->sc_dk);
+		drive_busy(sd->sc_dk.stats);
 
 		/*
 		 * Mark the disk dirty so that the cache will be
@@ -935,7 +935,7 @@
 		if (error)
 			bp->b_flags |= B_ERROR;
 
-		disk_unbusy(&sd->sc_dk, bp->b_bcount - bp->b_resid,
+		drive_unbusy(sd->sc_dk.stats, bp->b_bcount - bp->b_resid,
 		    (bp->b_flags & B_READ));
 #if NRND > 0
 		rnd_add_uint32(&sd->rnd_source, bp->b_rawblkno);
Index: sys/dev/scsipi/st.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st.c,v
retrieving revision 1.186
diff -u -r1.186 st.c
--- sys/dev/scsipi/st.c	11 Dec 2005 12:23:51 -0000	1.186
+++ sys/dev/scsipi/st.c	5 Mar 2006 11:43:37 -0000
@@ -76,7 +76,7 @@
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
-#include <sys/tape.h>
+#include <sys/iostat.h>
 #include <sys/sysctl.h>
 
 #include <dev/scsipi/scsi_spc.h>
@@ -107,9 +107,6 @@
 #define		ST_MOUNT_DELAY		0
 #endif
 
-struct tape *
-drive_attach(char *name);
-
 static dev_type_open(stopen);
 static dev_type_close(stclose);
 static dev_type_read(stread);
@@ -352,14 +349,6 @@
 	stdone
 };
 
-/*
- * A global list of all tape drives attached to the system.  May grow or
- * shrink over time.
- */
-struct  tapelist_head tapelist = TAILQ_HEAD_INITIALIZER(tapelist);
-int     tape_count = 0;             /* number of drives in global tapelist */
-struct simplelock tapelist_slock = SIMPLELOCK_INITIALIZER;
-
 #if	defined(ST_ENABLE_EARLYWARN)
 #define	ST_INIT_FLAGS	ST_EARLYWARN
 #else
@@ -423,8 +412,9 @@
 		    (st->flags & ST_READONLY) ? "protected" : "enabled");
 	}
 
-	st->stats = drive_attach(st->sc_dev.dv_xname);
-	
+	st->stats = drive_stats_alloc(IOSTAT_TAPE);
+	st->stats->name = st->sc_dev.dv_xname;
+
 #if NRND > 0
 	rnd_attach_source(&st->rnd_source, st->sc_dev.dv_xname,
 			  RND_TYPE_TAPE, 0);
@@ -480,16 +470,7 @@
 	vdevgone(bmaj, mn, mn+STNMINOR-1, VBLK);
 	vdevgone(cmaj, mn, mn+STNMINOR-1, VCHR);
 
-	if (tape_count == 0) {
-		printf("%s detach: tape_count already zero\n",
-		       st->sc_dev.dv_xname);
-	} else {
-		simple_lock(&tapelist_slock);
-		TAILQ_REMOVE(&tapelist, st->stats, link);
-		tape_count--;
-		simple_unlock(&tapelist_slock);
-		free(st->stats, M_DEVBUF);
-	}
+	drive_stats_free(st->stats);
 
 #if NRND > 0
 	/* Unhook the entropy source. */
@@ -1187,7 +1168,7 @@
 	struct buf *bp;
 	struct scsi_rw_tape cmd;
 	struct scsipi_xfer *xs;
-	int flags, error, s;
+	int flags, error;
 
 	SC_DEBUG(periph, SCSIPI_DB2, ("ststart "));
 	/*
@@ -1224,12 +1205,8 @@
 		if ((bp = BUFQ_PEEK(st->buf_queue)) == NULL)
 			return;
 
-		if (st->stats->busy++ == 0) {
-			s = splclock();
-			st->stats->timestamp = mono_time;
-			splx(s);
-		}
-		
+		drive_busy(st->stats);
+
 		/*
 		 * only FIXEDBLOCK devices have pending I/O or space operations.
 		 */
@@ -1356,8 +1333,6 @@
 {
 	struct st_softc *st = (void *)xs->xs_periph->periph_dev;
 	struct buf *bp = xs->bp;
-	int s;
-	struct timeval st_time, diff_time;
 
 	if (bp) {
 		bp->b_error = error;
@@ -1370,32 +1345,10 @@
 		else
 			st->flags &= ~ST_WRITTEN;
 
-		if (st->stats->busy-- == 0) {
-			  /* this is not really fatal so we don't panic */
-			printf("%s: busy < 0, Oops.\n", st->stats->name);
-			st->stats->busy = 0;
-		} else {
-			s = splclock();
-			st_time = mono_time;
-			splx(s);
-
-			timersub(&st_time, &st->stats->timestamp, &diff_time);
-			timeradd(&st->stats->time, &diff_time,
-				 &st->stats->time);
+		drive_unbusy(st->stats, bp->b_bcount,
+			     ((bp->b_flags & B_READ) == B_READ));
+
 
-			st->stats->timestamp = st_time;
-			if (bp->b_bcount > 0) {
-				if ((bp->b_flags & B_READ) == B_WRITE) {
-					st->stats->wbytes += bp->b_bcount;
-					st->stats->wxfer++;
-				} else {
-					st->stats->rbytes += bp->b_bcount;
-					st->stats->rxfer++;
-				}
-			}
-		}
-		
-			
 #if NRND > 0
 		rnd_add_uint32(&st->rnd_source, bp->b_blkno);
 #endif
@@ -2453,156 +2406,3 @@
 	/* Not implemented. */
 	return (ENXIO);
 }
-
-int
-sysctl_hw_tapenames(SYSCTLFN_ARGS)
-{
-	char bf[TAPENAMELEN + 1];
-	char *where = oldp;
-	struct tape *tapep;
-	size_t needed, left, slen;
-	int error, first;
-
-	if (newp != NULL)
-		return (EPERM);
-	if (namelen != 0)
-		return (EINVAL);
-
-	first = 1;
-	error = 0;
-	needed = 0;
-	left = *oldlenp;
-
-	simple_lock(&tapelist_slock);
-	for (tapep = TAILQ_FIRST(&tapelist); tapep != NULL;
-	    tapep = TAILQ_NEXT(tapep, link)) {
-		if (where == NULL)
-			needed += strlen(tapep->name) + 1;
-		else {
-			memset(bf, 0, sizeof(bf));
-			if (first) {
-				strncpy(bf, tapep->name, sizeof(bf));
-				first = 0;
-			} else {
-				bf[0] = ' ';
-				strncpy(bf + 1, tapep->name, sizeof(bf) - 1);
-			}
-			bf[TAPENAMELEN] = '\0';
-			slen = strlen(bf);
-			if (left < slen + 1)
-				break;
-			/* +1 to copy out the trailing NUL byte */
-			error = copyout(bf, where, slen + 1);
-			if (error)
-				break;
-			where += slen;
-			needed += slen;
-			left -= slen;
-		}
-	}
-	simple_unlock(&tapelist_slock);
-	*oldlenp = needed;
-	return (error);
-}
-
-int
-sysctl_hw_tapestats(SYSCTLFN_ARGS)
-{
-	struct tape_sysctl stape;
-	struct tape *tapep;
-	char *where = oldp;
-	size_t tocopy, left;
-	int error;
-
-	if (newp != NULL)
-		return (EPERM);
-
-	tocopy = name[0];
-
-	if (where == NULL) {
-		*oldlenp = tape_count * tocopy;
-		return (0);
-	}
-
-	error = 0;
-	left = *oldlenp;
-	memset(&stape, 0, sizeof(stape));
-	*oldlenp = 0;
-
-	simple_lock(&tapelist_slock);
-	TAILQ_FOREACH(tapep, &tapelist, link) {
-		if (left < tocopy)
-			break;
-		strncpy(stape.name, tapep->name, sizeof(stape.name));
-		stape.xfer = tapep->rxfer + tapep->wxfer;
-		stape.rxfer = tapep->rxfer;
-		stape.wxfer = tapep->wxfer;
-		stape.bytes = tapep->rbytes + tapep->wbytes;
-		stape.rbytes = tapep->rbytes;
-		stape.wbytes = tapep->wbytes;
-		stape.attachtime_sec = tapep->attachtime.tv_sec;
-		stape.attachtime_usec = tapep->attachtime.tv_usec;
-		stape.timestamp_sec = tapep->timestamp.tv_sec;
-		stape.timestamp_usec = tapep->timestamp.tv_usec;
-		stape.time_sec = tapep->time.tv_sec;
-		stape.time_usec = tapep->time.tv_usec;
-		stape.busy = tapep->busy;
-
-		error = copyout(&stape, where, min(tocopy, sizeof(stape)));
-		if (error)
-			break;
-		where += tocopy;
-		*oldlenp += tocopy;
-		left -= tocopy;
-	}
-	simple_unlock(&tapelist_slock);
-	return (error);
-}
-
-struct tape *
-drive_attach(char *name) 
-{
-	struct tape *stats;
-	int s;
-	
-	/* Allocate and initialise statistics */
-	stats = (struct tape *) malloc(sizeof(struct tape), M_DEVBUF,
-					   M_WAITOK);
-	stats->rxfer = stats->wxfer = stats->rbytes = 0;
-	stats->wbytes = stats->busy = 0;
-
-	/*
-	 * Set the attached timestamp.
-	 */
-	s = splclock();
-	stats->attachtime = mono_time;
-	splx(s);
-
-	  /* and clear the utilisation time */
-	timerclear(&stats->time);
-
-	  /* link the tape drive to the tapelist */
-	simple_lock(&tapelist_slock);
-	TAILQ_INSERT_TAIL(&tapelist, stats, link);
-	tape_count++;
-	simple_unlock(&tapelist_slock);
-	stats->name = name;
-
-	return stats;
-}
-
-SYSCTL_SETUP(sysctl_tape_stats_setup, "sysctl tape stats setup")
-{
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRING, "tapenames",
-		       SYSCTL_DESCR("List of tape devices present"),
-		       sysctl_hw_tapenames, 0, NULL, 0,
-		       CTL_HW, HW_TAPENAMES, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRUCT, "tapestats",
-		       SYSCTL_DESCR("Statistics on tape drive operation"),
-		       sysctl_hw_tapestats, 0, NULL, 0,
-		       CTL_HW, HW_TAPESTATS, CTL_EOL);
-}
Index: sys/dev/scsipi/stvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/stvar.h,v
retrieving revision 1.16
diff -u -r1.16 stvar.h
--- sys/dev/scsipi/stvar.h	11 Dec 2005 12:23:51 -0000	1.16
+++ sys/dev/scsipi/stvar.h	5 Mar 2006 11:43:37 -0000
@@ -150,9 +150,9 @@
 					/* operations */
 	struct callout sc_callout;	/* restarting the queue after */
 					/* transient error */
-	
-	struct tape *stats;		/* statistics for the drive */
-	
+
+	struct io_stats *stats;		/* statistics for the drive */
+
 #if NRND > 0
 	rndsource_element_t	rnd_source;
 #endif
Index: sys/dev/vme/xd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vme/xd.c,v
retrieving revision 1.59
diff -u -r1.59 xd.c
--- sys/dev/vme/xd.c	11 Dec 2005 12:24:07 -0000	1.59
+++ sys/dev/vme/xd.c	5 Mar 2006 11:43:37 -0000
@@ -1652,7 +1652,7 @@
 	xdc_rqtopb(iorq, iopb, (bp->b_flags & B_READ) ? XDCMD_RD : XDCMD_WR, 0);
 
 	/* Instrumentation. */
-	disk_busy(&xdsc->sc_dk);
+	drive_busy(xdsc->sc_dk.stats);
 
 	/* now submit [note that xdc_submit_iorq can never fail on NORM reqs] */
 
@@ -1939,7 +1939,7 @@
 
 			    bus_dmamap_unload(xdcsc->dmatag, iorq->dmamap);
 
-			    disk_unbusy(&xdcsc->reqs[lcv].xd->sc_dk,
+			    drive_unbusy(xdcsc->reqs[lcv].xd->sc_dk.stats,
 				(xdcsc->reqs[lcv].buf->b_bcount -
 				xdcsc->reqs[lcv].buf->b_resid),
 				(iorq->buf->b_flags & B_READ));
@@ -2150,7 +2150,7 @@
 						: BUS_DMASYNC_POSTWRITE);
 			bus_dmamap_unload(xdcsc->dmatag, iorq->dmamap);
 
-			disk_unbusy(&iorq->xd->sc_dk,
+			drive_unbusy(iorq->xd->sc_dk.stats,
 			    (bp->b_bcount - bp->b_resid),
 			    (bp->b_flags & B_READ));
 			XDC_FREE(xdcsc, rqno);
Index: sys/dev/vme/xy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vme/xy.c,v
retrieving revision 1.61
diff -u -r1.61 xy.c
--- sys/dev/vme/xy.c	11 Dec 2005 12:24:07 -0000	1.61
+++ sys/dev/vme/xy.c	5 Mar 2006 11:43:37 -0000
@@ -1490,7 +1490,7 @@
 	xyc_rqtopb(iorq, iopb, (bp->b_flags & B_READ) ? XYCMD_RD : XYCMD_WR, 0);
 
 	/* Instrumentation. */
-	disk_busy(&xysc->sc_dk);
+	drive_busy(xysc->sc_dk.stats);
 
 	return (XY_ERR_AOK);
 }
@@ -1844,7 +1844,7 @@
 			    bus_dmamap_unload(xycsc->dmatag, iorq->dmamap);
 
 			    (void)BUFQ_GET(iorq->xy->xyq);
-			    disk_unbusy(&xycsc->reqs[lcv].xy->sc_dk,
+			    drive_unbusy(xycsc->reqs[lcv].xy->sc_dk.stats,
 				(xycsc->reqs[lcv].buf->b_bcount -
 				xycsc->reqs[lcv].buf->b_resid),
 				(xycsc->reqs[lcv].buf->b_flags & B_READ));
@@ -2028,7 +2028,7 @@
 			bus_dmamap_unload(xycsc->dmatag, iorq->dmamap);
 
 			(void)BUFQ_GET(iorq->xy->xyq);
-			disk_unbusy(&iorq->xy->sc_dk,
+			drive_unbusy(iorq->xy->sc_dk.stats,
 			    (bp->b_bcount - bp->b_resid),
 			    (bp->b_flags & B_READ));
 			iorq->mode = XY_SUB_FREE;
Index: sys/kern/init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.63
diff -u -r1.63 init_sysctl.c
--- sys/kern/init_sysctl.c	1 Mar 2006 12:38:21 -0000	1.63
+++ sys/kern/init_sysctl.c	5 Mar 2006 11:43:38 -0000
@@ -904,18 +904,6 @@
 		       CTL_HW, HW_PAGESIZE, CTL_EOL);
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRING, "disknames",
-		       SYSCTL_DESCR("List of disk devices present"),
-		       sysctl_hw_disknames, 0, NULL, 0,
-		       CTL_HW, HW_DISKNAMES, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRUCT, "diskstats",
-		       SYSCTL_DESCR("Statistics on disk operation"),
-		       sysctl_hw_diskstats, 0, NULL, 0,
-		       CTL_HW, HW_DISKSTATS, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "machine_arch",
 		       SYSCTL_DESCR("Machine CPU class"),
 		       NULL, 0, machine_arch, 0,
Index: sys/kern/subr_disk.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_disk.c,v
retrieving revision 1.73
diff -u -r1.73 subr_disk.c
--- sys/kern/subr_disk.c	26 Dec 2005 18:45:27 -0000	1.73
+++ sys/kern/subr_disk.c	5 Mar 2006 11:43:38 -0000
@@ -89,14 +89,6 @@
 #include <lib/libkern/libkern.h>
 
 /*
- * A global list of all disks attached to the system.  May grow or
- * shrink over time.
- */
-struct	disklist_head disklist = TAILQ_HEAD_INITIALIZER(disklist);
-int	disk_count;		/* number of drives in global disklist */
-struct simplelock disklist_slock = SIMPLELOCK_INITIALIZER;
-
-/*
  * Compute checksum for disk label.
  */
 u_int
@@ -171,30 +163,6 @@
 	}
 }
 
-/*
- * Searches the disklist for the disk corresponding to the
- * name provided.
- */
-struct disk *
-disk_find(char *name)
-{
-	struct disk *diskp;
-
-	if ((name == NULL) || (disk_count <= 0))
-		return (NULL);
-
-	simple_lock(&disklist_slock);
-	for (diskp = TAILQ_FIRST(&disklist); diskp != NULL;
-	    diskp = TAILQ_NEXT(diskp, dk_link))
-		if (strcmp(diskp->dk_name, name) == 0) {
-			simple_unlock(&disklist_slock);
-			return (diskp);
-		}
-	simple_unlock(&disklist_slock);
-
-	return (NULL);
-}
-
 static void
 disk_init0(struct disk *diskp)
 {
@@ -211,8 +179,6 @@
 static void
 disk_attach0(struct disk *diskp)
 {
-	int s;
-
 	/*
 	 * Allocate and initialize the disklabel structures.  Note that
 	 * it's not safe to sleep here, since we're probably going to be
@@ -228,19 +194,12 @@
 	memset(diskp->dk_cpulabel, 0, sizeof(struct cpu_disklabel));
 
 	/*
-	 * Set the attached timestamp.
+	 * Set up the stats collection.
 	 */
-	s = splclock();
-	diskp->dk_attachtime = mono_time;
-	splx(s);
+	diskp->stats = drive_stats_alloc(IOSTAT_DISK);
+        diskp->stats->parent = (void *) diskp;
+        diskp->stats->name = diskp->dk_name;
 
-	/*
-	 * Link into the disklist.
-	 */
-	simple_lock(&disklist_slock);
-	TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
-	disk_count++;
-	simple_unlock(&disklist_slock);
 }
 
 static void
@@ -248,14 +207,9 @@
 {
 
 	/*
-	 * Remove from the disklist.
+	 * Remove from the drivelist.
 	 */
-	if (disk_count == 0)
-		panic("disk_detach: disk_count == 0");
-	simple_lock(&disklist_slock);
-	TAILQ_REMOVE(&disklist, diskp, dk_link);
-	disk_count--;
-	simple_unlock(&disklist_slock);
+        drive_stats_free(diskp->stats);
 
 	/*
 	 * Free the space used by the disklabel structures.
@@ -316,207 +270,6 @@
 	disk_detach0(diskp);
 }
 
-
-/*
- * Increment a disk's busy counter.  If the counter is going from
- * 0 to 1, set the timestamp.
- */
-void
-disk_busy(struct disk *diskp)
-{
-	int s;
-
-	/*
-	 * XXX We'd like to use something as accurate as microtime(),
-	 * but that doesn't depend on the system TOD clock.
-	 */
-	if (diskp->dk_busy++ == 0) {
-		s = splclock();
-		diskp->dk_timestamp = mono_time;
-		splx(s);
-	}
-}
-
-/*
- * Decrement a disk's busy counter, increment the byte count, total busy
- * time, and reset the timestamp.
- */
-void
-disk_unbusy(struct disk *diskp, long bcount, int read)
-{
-	int s;
-	struct timeval dv_time, diff_time;
-
-	if (diskp->dk_busy-- == 0) {
-		printf("%s: dk_busy < 0\n", diskp->dk_name);
-		panic("disk_unbusy");
-	}
-
-	s = splclock();
-	dv_time = mono_time;
-	splx(s);
-
-	timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
-	timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
-
-	diskp->dk_timestamp = dv_time;
-	if (bcount > 0) {
-		if (read) {
-			diskp->dk_rbytes += bcount;
-			diskp->dk_rxfer++;
-		} else {
-			diskp->dk_wbytes += bcount;
-			diskp->dk_wxfer++;
-		}
-	}
-}
-
-/*
- * Reset the metrics counters on the given disk.  Note that we cannot
- * reset the busy counter, as it may case a panic in disk_unbusy().
- * We also must avoid playing with the timestamp information, as it
- * may skew any pending transfer results.
- */
-void
-disk_resetstat(struct disk *diskp)
-{
-	int s = splbio(), t;
-
-	diskp->dk_rxfer = 0;
-	diskp->dk_rbytes = 0;
-	diskp->dk_wxfer = 0;
-	diskp->dk_wbytes = 0;
-
-	t = splclock();
-	diskp->dk_attachtime = mono_time;
-	splx(t);
-
-	timerclear(&diskp->dk_time);
-
-	splx(s);
-}
-
-int
-sysctl_hw_disknames(SYSCTLFN_ARGS)
-{
-	char bf[DK_DISKNAMELEN + 1];
-	char *where = oldp;
-	struct disk *diskp;
-	size_t needed, left, slen;
-	int error, first;
-
-	if (newp != NULL)
-		return (EPERM);
-	if (namelen != 0)
-		return (EINVAL);
-
-	first = 1;
-	error = 0;
-	needed = 0;
-	left = *oldlenp;
-
-	simple_lock(&disklist_slock);
-	for (diskp = TAILQ_FIRST(&disklist); diskp != NULL;
-	    diskp = TAILQ_NEXT(diskp, dk_link)) {
-		if (where == NULL)
-			needed += strlen(diskp->dk_name) + 1;
-		else {
-			memset(bf, 0, sizeof(bf));
-			if (first) {
-				strncpy(bf, diskp->dk_name, sizeof(bf));
-				first = 0;
-			} else {
-				bf[0] = ' ';
-				strncpy(bf + 1, diskp->dk_name,
-				    sizeof(bf) - 1);
-			}
-			bf[DK_DISKNAMELEN] = '\0';
-			slen = strlen(bf);
-			if (left < slen + 1)
-				break;
-			/* +1 to copy out the trailing NUL byte */
-			error = copyout(bf, where, slen + 1);
-			if (error)
-				break;
-			where += slen;
-			needed += slen;
-			left -= slen;
-		}
-	}
-	simple_unlock(&disklist_slock);
-	*oldlenp = needed;
-	return (error);
-}
-
-int
-sysctl_hw_diskstats(SYSCTLFN_ARGS)
-{
-	struct disk_sysctl sdisk;
-	struct disk *diskp;
-	char *where = oldp;
-	size_t tocopy, left;
-	int error;
-
-	if (newp != NULL)
-		return (EPERM);
-
-	/*
-	 * The original hw.diskstats call was broken and did not require
-	 * the userland to pass in it's size of struct disk_sysctl.  This
-	 * was fixed after NetBSD 1.6 was released, and any applications
-	 * that do not pass in the size are given an error only, unless
-	 * we care about 1.6 compatibility.
-	 */
-	if (namelen == 0)
-#ifdef COMPAT_16
-		tocopy = offsetof(struct disk_sysctl, dk_rxfer);
-#else
-		return (EINVAL);
-#endif
-	else
-		tocopy = name[0];
-
-	if (where == NULL) {
-		*oldlenp = disk_count * tocopy;
-		return (0);
-	}
-
-	error = 0;
-	left = *oldlenp;
-	memset(&sdisk, 0, sizeof(sdisk));
-	*oldlenp = 0;
-
-	simple_lock(&disklist_slock);
-	TAILQ_FOREACH(diskp, &disklist, dk_link) {
-		if (left < tocopy)
-			break;
-		strncpy(sdisk.dk_name, diskp->dk_name, sizeof(sdisk.dk_name));
-		sdisk.dk_xfer = diskp->dk_rxfer + diskp->dk_wxfer;
-		sdisk.dk_rxfer = diskp->dk_rxfer;
-		sdisk.dk_wxfer = diskp->dk_wxfer;
-		sdisk.dk_seek = diskp->dk_seek;
-		sdisk.dk_bytes = diskp->dk_rbytes + diskp->dk_wbytes;
-		sdisk.dk_rbytes = diskp->dk_rbytes;
-		sdisk.dk_wbytes = diskp->dk_wbytes;
-		sdisk.dk_attachtime_sec = diskp->dk_attachtime.tv_sec;
-		sdisk.dk_attachtime_usec = diskp->dk_attachtime.tv_usec;
-		sdisk.dk_timestamp_sec = diskp->dk_timestamp.tv_sec;
-		sdisk.dk_timestamp_usec = diskp->dk_timestamp.tv_usec;
-		sdisk.dk_time_sec = diskp->dk_time.tv_sec;
-		sdisk.dk_time_usec = diskp->dk_time.tv_usec;
-		sdisk.dk_busy = diskp->dk_busy;
-
-		error = copyout(&sdisk, where, min(tocopy, sizeof(sdisk)));
-		if (error)
-			break;
-		where += tocopy;
-		*oldlenp += tocopy;
-		left -= tocopy;
-	}
-	simple_unlock(&disklist_slock);
-	return (error);
-}
-
 /*
  * Bounds checking against the media size, used for the raw partition.
  * The sector size passed in should currently always be DEV_BSIZE,
Index: sys/nfs/nfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.152
diff -u -r1.152 nfs_vfsops.c
--- sys/nfs/nfs_vfsops.c	21 Feb 2006 04:32:39 -0000	1.152
+++ sys/nfs/nfs_vfsops.c	5 Mar 2006 11:43:38 -0000
@@ -77,6 +77,12 @@
 extern struct nfsstats nfsstats;
 extern int nfs_ticks;
 
+/*
+ * keep a count of the nfs mounts to generate ficticious drive names
+ * for the per drive stats.
+ */
+unsigned int nfs_mount_count = 0;
+
 MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure");
 
 /*
@@ -800,6 +806,13 @@
 	nmp->nm_vnode = *vpp;
 	VOP_UNLOCK(*vpp, 0);
 
+	nmp->stats = drive_stats_alloc(IOSTAT_NFS);
+	nmp->stats->parent = nmp;
+	  /* generate a ficticious drive name for the nfs mount */
+	MALLOC(nmp->stats->name, char *, IOSTATNAMELEN, M_NFSMNT, M_WAITOK);
+	snprintf(nmp->stats->name, IOSTATNAMELEN, "nfs%u", nfs_mount_count);
+	nfs_mount_count++;
+
 	return (0);
 bad:
 	nfs_disconnect(nmp);
@@ -869,6 +882,14 @@
 	nmp->nm_iflag |= NFSMNT_DISMNT;
 
 	/*
+	 * Clean up the stats... note that we carefully avoid decrementing
+	 * nfs_mount_count here for good reason - we may not be unmounting
+	 * the last thing mounted.
+	 */
+	FREE(nmp->stats->name, M_NFSMNT);
+	drive_stats_free(nmp->stats);
+
+	/*
 	 * There are two reference counts to get rid of here
 	 * (see comment in mountnfs()).
 	 */
Index: sys/nfs/nfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.231
diff -u -r1.231 nfs_vnops.c
--- sys/nfs/nfs_vnops.c	1 Mar 2006 12:38:32 -0000	1.231
+++ sys/nfs/nfs_vnops.c	5 Mar 2006 11:43:38 -0000
@@ -53,6 +53,7 @@
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/buf.h>
+#include <sys/disk.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/namei.h>
@@ -1240,7 +1241,7 @@
 	caddr_t bpos, dpos, cp2;
 	struct mbuf *mreq, *mrep, *md, *mb;
 	struct nfsmount *nmp;
-	int error = 0, len, retlen, tsiz, eof;
+	int error = 0, len, retlen, tsiz, eof, byte_count;
 	const int v3 = NFS_ISV3(vp);
 	struct nfsnode *np = VTONFS(vp);
 #ifndef NFS_V2_ONLY
@@ -1254,6 +1255,8 @@
 	tsiz = uiop->uio_resid;
 	if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 		return (EFBIG);
+	drive_busy(nmp->stats);
+	byte_count = 0; /* count bytes actually transferred */
 	while (tsiz > 0) {
 		nfsstats.rpccnt[NFSPROC_READ]++;
 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
@@ -1288,6 +1291,7 @@
 		nfsm_mtouio(uiop, retlen);
 		m_freem(mrep);
 		tsiz -= retlen;
+		byte_count += retlen;
 #ifndef NFS_V2_ONLY
 		if (v3) {
 			if (eof || retlen == 0)
@@ -1298,6 +1302,7 @@
 			tsiz = 0;
 	}
 nfsmout:
+	drive_unbusy(nmp->stats, byte_count, 1);
 	return (error);
 }
 
@@ -1347,7 +1352,7 @@
 	int committed = NFSV3WRITE_FILESYNC;
 	struct nfsnode *np = VTONFS(vp);
 	struct nfs_writerpc_context ctx;
-	int s;
+	int s, byte_count;
 	struct lwp *l = NULL;
 	size_t origresid;
 #ifndef NFS_V2_ONLY
@@ -1376,6 +1381,8 @@
 retry:
 	origresid = uiop->uio_resid;
 	KASSERT(origresid == uiop->uio_iov->iov_len);
+	drive_busy(nmp->stats);
+	byte_count = 0; /* count of bytes actually written */
 	while (tsiz > 0) {
 		uint32_t datalen; /* data bytes need to be allocated in mbuf */
 		uint32_t backup;
@@ -1508,6 +1515,7 @@
 		if (error)
 			break;
 		tsiz -= len;
+		byte_count += len;
 		if (stalewriteverf) {
 			*stalewriteverfp = TRUE;
 			stalewriteverf = FALSE;
@@ -1528,6 +1536,7 @@
 		}
 	}
 nfsmout:
+	drive_unbusy(nmp->stats, byte_count, 0);
 	if (pageprotected) {
 		/*
 		 * wait until mbufs go away.
Index: sys/nfs/nfsmount.h
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfsmount.h,v
retrieving revision 1.37
diff -u -r1.37 nfsmount.h
--- sys/nfs/nfsmount.h	11 Dec 2005 12:25:17 -0000	1.37
+++ sys/nfs/nfsmount.h	5 Mar 2006 11:43:38 -0000
@@ -37,6 +37,9 @@
 
 #ifndef _NFS_NFSMOUNT_H_
 #define _NFS_NFSMOUNT_H_
+#ifdef _KERNEL
+#include <sys/disk.h>
+#endif
 
 /*
  * Arguments to mount NFS
@@ -167,6 +170,7 @@
 	int	nm_iflag;		/* internal flags */
 	int	nm_waiters;		/* number of waiting listeners.. */
 	long	nm_wcckludgetime;	/* see nfs_check_wccdata() */
+	struct io_stats *stats;		/* per nfs mount statistics */
 };
 
 /*
Index: sys/sys/Makefile
===================================================================
RCS file: /cvsroot/src/sys/sys/Makefile,v
retrieving revision 1.82
diff -u -r1.82 Makefile
--- sys/sys/Makefile	11 Feb 2006 17:36:41 -0000	1.82
+++ sys/sys/Makefile	5 Mar 2006 11:43:38 -0000
@@ -12,7 +12,7 @@
 	exec_coff.h exec_ecoff.h exec_elf.h exec_script.h extattr.h extent.h \
 	fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
 	float_ieee754.h fstypes.h gmon.h gpio.h hash.h \
-	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h ipc.h \
+	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
 	joystick.h \
 	kcore.h kgdb.h ksem.h ksyms.h ktrace.h \
 	lkm.h localedef.h lock.h lockf.h lwp.h \
Index: sys/sys/disk.h
===================================================================
RCS file: /cvsroot/src/sys/sys/disk.h,v
retrieving revision 1.33
diff -u -r1.33 disk.h
--- sys/sys/disk.h	26 Dec 2005 18:41:36 -0000	1.33
+++ sys/sys/disk.h	5 Mar 2006 11:43:38 -0000
@@ -90,6 +90,7 @@
 #include <sys/time.h>
 #include <sys/queue.h>
 #include <sys/lock.h>
+#include <sys/iostat.h>
 
 struct buf;
 struct disk;
@@ -209,15 +210,7 @@
 	 * Metrics data; note that some metrics may have no meaning
 	 * on certain types of disks.
 	 */
-	int		dk_busy;	/* busy counter */
-	uint64_t	dk_rxfer;	/* total number of read transfers */
-	uint64_t	dk_wxfer;	/* total number of write transfers */
-	uint64_t	dk_seek;	/* total independent seek operations */
-	uint64_t	dk_rbytes;	/* total bytes read */
-	uint64_t	dk_wbytes;	/* total bytes written */
-	struct timeval	dk_attachtime;	/* time disk was attached */
-	struct timeval	dk_timestamp;	/* timestamp of last unbusy */
-	struct timeval	dk_time;	/* total time spent busy */
+	struct io_stats	*stats;
 
 	struct	dkdriver *dk_driver;	/* pointer to driver */
 
@@ -243,29 +236,6 @@
 	struct cpu_disklabel *dk_cpulabel;
 };
 
-#define	DK_DISKNAMELEN	16
-
-/* The following structure is 64-bit alignment safe */
-struct disk_sysctl {
-	char		dk_name[DK_DISKNAMELEN];
-	int32_t		dk_busy;
-	int32_t		pad;
-	uint64_t	dk_xfer;
-	uint64_t	dk_seek;
-	uint64_t	dk_bytes;
-	uint32_t	dk_attachtime_sec;
-	uint32_t	dk_attachtime_usec;
-	uint32_t	dk_timestamp_sec;
-	uint32_t	dk_timestamp_usec;
-	uint32_t	dk_time_sec;
-	uint32_t	dk_time_usec;
-	/* New separate read/write stats */
-	uint64_t	dk_rxfer;
-	uint64_t	dk_rbytes;
-	uint64_t	dk_wxfer;
-	uint64_t	dk_wbytes;
-};
-
 struct dkdriver {
 	void	(*d_strategy)(struct buf *);
 	void	(*d_minphys)(struct buf *);
@@ -288,11 +258,6 @@
 #define	DK_OPENRAW	5		/* open without label */
 
 /*
- * disklist_head is defined here so that user-land has access to it.
- */
-TAILQ_HEAD(disklist_head, disk);	/* the disklist is a TAILQ */
-
-/*
  * Bad sector lists per fixed disk
  */
 struct disk_badsectors {
@@ -328,10 +293,6 @@
 void	pseudo_disk_init(struct disk *);
 void	pseudo_disk_attach(struct disk *);
 void	pseudo_disk_detach(struct disk *);
-void	disk_busy(struct disk *);
-void	disk_unbusy(struct disk *, long, int);
-void	disk_resetstat(struct disk *);
-struct	disk *disk_find(char *);
 
 int	dkwedge_add(struct dkwedge_info *);
 int	dkwedge_del(struct dkwedge_info *);
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.152
diff -u -r1.152 sysctl.h
--- sys/sys/sysctl.h	25 Feb 2006 00:58:36 -0000	1.152
+++ sys/sys/sysctl.h	5 Mar 2006 11:43:38 -0000
@@ -703,15 +703,14 @@
 #define	HW_USERMEM	 6		/* int: non-kernel memory (bytes) */
 #define	HW_PAGESIZE	 7		/* int: software page size */
 #define	HW_DISKNAMES	 8		/* string: disk drive names */
-#define	HW_DISKSTATS	 9		/* struct: diskstats[] */
+#define	HW_DRIVESTATS	 9		/* struct: diskstats[] */
 #define	HW_MACHINE_ARCH	10		/* string: machine architecture */
 #define	HW_ALIGNBYTES	11		/* int: ALIGNBYTES for the kernel */
 #define	HW_CNMAGIC	12		/* string: console magic sequence(s) */
 #define	HW_PHYSMEM64	13		/* quad: total memory (bytes) */
 #define	HW_USERMEM64	14		/* quad: non-kernel memory (bytes) */
-#define	HW_TAPENAMES	15		/* string: tape drive names */
-#define	HW_TAPESTATS	16		/* struct: tapestats[] */
-#define	HW_MAXID	16		/* number of valid hw ids */
+#define	HW_DRIVENAMES	15		/* string: tape drive names */
+#define	HW_MAXID	15		/* number of valid hw ids */
 
 #define	CTL_HW_NAMES { \
 	{ 0, 0 }, \
@@ -722,8 +721,8 @@
 	{ "physmem", CTLTYPE_INT }, \
 	{ "usermem", CTLTYPE_INT }, \
 	{ "pagesize", CTLTYPE_INT }, \
-	{ "disknames", CTLTYPE_STRING }, \
-	{ "diskstats", CTLTYPE_STRUCT }, \
+	{ "drivenames", CTLTYPE_STRING }, \
+	{ "drivestats", CTLTYPE_STRUCT }, \
 	{ "machine_arch", CTLTYPE_STRING }, \
 	{ "alignbytes", CTLTYPE_INT }, \
 	{ "cnmagic", CTLTYPE_STRING }, \
@@ -1074,8 +1073,6 @@
  * these helpers are in other files (XXX so should the nodes be) or
  * are used by more than one node
  */
-int	sysctl_hw_disknames(SYSCTLFN_PROTO);
-int	sysctl_hw_diskstats(SYSCTLFN_PROTO);
 int	sysctl_hw_tapenames(SYSCTLFN_PROTO);
 int	sysctl_hw_tapestats(SYSCTLFN_PROTO);
 int	sysctl_kern_vnode(SYSCTLFN_PROTO);
Index: usr.bin/systat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/Makefile,v
retrieving revision 1.31
diff -u -r1.31 Makefile
--- usr.bin/systat/Makefile	7 Aug 2005 12:32:38 -0000	1.31
+++ usr.bin/systat/Makefile	5 Mar 2006 11:43:38 -0000
@@ -11,7 +11,7 @@
 CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/vmstat -DSUPPORT_UTMP -DSUPPORT_UTMPX \
 	-I${NETBSDSRCDIR}/usr.bin/who
 CWARNFLAGS+=    -Wno-format-y2k
-SRCS=	bufcache.c cmds.c cmdtab.c disks.c df.c dkstats.c tpstats.c fetch.c \
+SRCS=	bufcache.c cmds.c cmdtab.c disks.c df.c drvstats.c fetch.c \
 	globalcmds.c icmp.c iostat.c ip.c keyboard.c main.c mbufs.c \
 	netcmds.c netstat.c pigs.c ps.c swap.c tcp.c vmstat.c utmpentry.c
 DPADD=	${LIBCURSES} ${LIBM} ${LIBKVM}
Index: usr.bin/systat/disks.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/disks.c,v
retrieving revision 1.15
diff -u -r1.15 disks.c
--- usr.bin/systat/disks.c	26 Feb 2005 18:58:45 -0000	1.15
+++ usr.bin/systat/disks.c	5 Mar 2006 11:43:38 -0000
@@ -42,16 +42,16 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
+#include "drvstats.h"
 
-static void dkselect(char *args, int truefalse, int selections[]);
+static void drvselect(char *args, int truefalse, int selections[]);
 
 void
 disks_add(char *args)
 {
 
 	if (args)
-		dkselect(args, 1, dk_select);
+		drvselect(args, 1, drv_select);
 }
 
 void
@@ -59,7 +59,7 @@
 {
 
 	if (args)
-		dkselect(args, 0, dk_select);
+		drvselect(args, 0, drv_select);
 }
 
 void
@@ -68,19 +68,19 @@
 	int i;
 
 	if (args) {
-		for (i = 0; i < dk_ndrive; i++)
-			dk_select[i] = 0;
+		for (i = 0; i < ndrive; i++)
+			drv_select[i] = 0;
 		disks_add(args);
 	} else {
 		move(CMDLINE, 0);
 		clrtoeol();
-		for (i = 0; i < dk_ndrive; i++)
+		for (i = 0; i < ndrive; i++)
 			printw("%s ", dr_name[i]);
 	}
 }
 
 static void
-dkselect(char *args, int truefalse, int selections[])
+drvselect(char *args, int truefalse, int selections[])
 {
 	char *cp;
 	int i;
@@ -98,12 +98,12 @@
 			*cp++ = '\0';
 		if (cp - args == 0)
 			break;
-		for (i = 0; i < dk_ndrive; i++)
+		for (i = 0; i < ndrive; i++)
 			if (strcmp(args, dr_name[i]) == 0) {
 				selections[i] = truefalse;
 				break;
 			}
-		if (i >= dk_ndrive)
+		if (i >= ndrive)
 			error("%s: unknown drive", args);
 		args = cp;
 	}
Index: usr.bin/systat/iostat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/iostat.c,v
retrieving revision 1.34
diff -u -r1.34 iostat.c
--- usr.bin/systat/iostat.c	5 Feb 2006 09:58:39 -0000	1.34
+++ usr.bin/systat/iostat.c	5 Mar 2006 11:43:38 -0000
@@ -43,8 +43,7 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 static  int linesperregion;
 static  double etime;
@@ -56,7 +55,6 @@
 static void histogram(double, int, double);
 static int numlabels(int);
 static int stats(int, int, int);
-static int tpstats(int, int, int);
 static void stat1(int, int);
 
 
@@ -82,11 +80,9 @@
 initiostat(void)
 {
 
-	dkinit(1);
-	tpinit(1);
+	drvinit(1);
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	return(1);
 }
 
@@ -96,11 +92,8 @@
 
 	cpureadstats();
 
-	if (dk_ndrive != 0)
-		dkreadstats();
-
-	if (tp_ndrive != 0)
-		tpreadstats();
+	if (ndrive != 0)
+		drvreadstats();
 }
 
 #define	INSET	14
@@ -110,7 +103,7 @@
 {
 	int row;
 
-	if ((dk_ndrive == 0) && (tp_ndrive == 0)) {
+	if (ndrive == 0) {
 		error("No drives defined.");
 		return;
 	}
@@ -136,13 +129,10 @@
 
 #define COLWIDTH	(9 + secs * 5 + 1 + read_write * 9 + 1)
 #define DRIVESPERLINE	((getmaxx(wnd) + 1) / COLWIDTH)
-	for (ndrives = 0, i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i])
-			ndrives++;
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i])
+	for (ndrives = 0, i = 0; i < ndrive; i++)
+		if (cur.select[i])
 			ndrives++;
-	
+
 	regions = howmany(ndrives, DRIVESPERLINE);
 	/*
 	 * Deduct -regions for blank line after each scrolling region.
@@ -155,22 +145,16 @@
 	if (linesperregion < 3)
 		linesperregion = 3;
 	col = 0;
-	for (i = 0; i < (dk_ndrive + tp_ndrive); i++)
-		if (((i < dk_ndrive) && (cur.dk_select[i])) ||
-		    ((i >= dk_ndrive) && (cur_tape.select[i - dk_ndrive]))) {
+	for (i = 0; i < ndrive; i++)
+		if (cur.select[i]) {
 			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
 				col = 0, row += linesperregion + 1;
 				if (row > getmaxy(wnd) - (linesperregion))
 					break;
 			}
 
-			if (i < dk_ndrive)
-				mvwprintw(wnd, row, col + 5, "%s",
-					  cur.dk_name[i]);
-			else
-				mvwprintw(wnd, row, col + 5, "%s",
-					  cur_tape.name[i - dk_ndrive]);
-			
+			mvwprintw(wnd, row, col + 5, "%s", cur.name[i]);
+
 			if (read_write)
 				mvwprintw(wnd, row, col + 11 + secs * 5,
 				    "(write)");
@@ -195,26 +179,12 @@
 	mvwaddstr(wnd, row++, INSET,
 	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 	linesperregion = 2 + secs + (read_write ? 2 : 0);
-	for (i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i]) {
-			if (row > getmaxy(wnd) - linesperregion)
-				break;
-			mvwprintw(wnd, row++, 0, "%7.7s  kBps|",
-			    cur.dk_name[i]);
-			mvwaddstr(wnd, row++, 0, "          tps|");
-			if (read_write) {
-				mvwprintw(wnd, row++, 0, " (write) kBps|");
-				mvwaddstr(wnd, row++, 0, "          tps|");
-			}
-			if (secs)
-				mvwaddstr(wnd, row++, 0, "         msec|");
-		}
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i]) {
+	for (i = 0; i < ndrive; i++) {
+		if (cur.select[i]) {
 			if (row > getmaxy(wnd) - linesperregion)
 				break;
 			mvwprintw(wnd, row++, 0, "%7.7s  kBps|",
-			    cur_tape.name[i]);
+			    cur.name[i]);
 			mvwaddstr(wnd, row++, 0, "          tps|");
 			if (read_write) {
 				mvwprintw(wnd, row++, 0, " (write) kBps|");
@@ -223,6 +193,8 @@
 			if (secs)
 				mvwaddstr(wnd, row++, 0, "         msec|");
 		}
+	}
+
 	return (row);
 }
 
@@ -231,11 +203,10 @@
 {
 	int i, row, col;
 
-	if (dk_ndrive == 0)
+	if (ndrive == 0)
 		return;
-	dkswap();
 	cpuswap();
-	tpswap();
+	drvswap();
 
 	etime = cur.cp_etime;
 	row = 1;
@@ -247,18 +218,12 @@
 		stat1(row++, i);
 	if (!numbers) {
 		row += 2;
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i]) {
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i]) {
 				if (row > getmaxy(wnd) - linesperregion)
 					break;
 				row = stats(row, INSET, i);
 			}
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i]) {
-				if (row > getmaxy(wnd) - linesperregion)
-					break;
-				row = tpstats(row, INSET, i);
-			}
 		return;
 	}
 	col = 0;
@@ -266,22 +231,8 @@
 	wdeleteln(wnd);
 	wmove(wnd, row + 3, 0);
 	winsertln(wnd);
-	for (i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i]) {
-			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
-				col = 0, row += linesperregion + 1;
-				if (row > getmaxy(wnd) - (linesperregion + 1))
-					break;
-				wmove(wnd, row + linesperregion, 0);
-				wdeleteln(wnd);
-				wmove(wnd, row + 3, 0);
-				winsertln(wnd);
-			}
-			(void) stats(row + 3, col, i);
-			col += COLWIDTH;
-		}
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i]) {
+	for (i = 0; i < ndrive; i++)
+		if (cur.select[i]) {
 			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
 				col = 0, row += linesperregion + 1;
 				if (row > getmaxy(wnd) - (linesperregion + 1))
@@ -303,64 +254,16 @@
 	uint64_t rxfer;
 
 	/* time busy in disk activity */
-	atime = (double)cur.dk_time[dn].tv_sec +
-		((double)cur.dk_time[dn].tv_usec / (double)1000000);
-
-	/* # of k transferred */
-	rwords = cur.dk_rbytes[dn] / 1024.0;
-	wwords = cur.dk_wbytes[dn] / 1024.0;
-	rxfer = cur.dk_rxfer[dn];
-	if (!read_write) {
-		rwords = wwords;
-		rxfer += cur.dk_wxfer[dn];
-	}
-	if (numbers) {
-		mvwprintw(wnd, row, col, "%5.0f%4.0f",
-		    rwords / etime, rxfer / etime);
-		if (secs)
-			wprintw(wnd, "%5.1f", atime / etime);
-		if (read_write)
-			wprintw(wnd, " %5.0f%4.0f",
-			    wwords / etime, cur.dk_wxfer[dn] / etime);
-		return (row);
-	}
-
-	wmove(wnd, row++, col);
-	histogram(rwords / etime, 50, 0.5);
-	wmove(wnd, row++, col);
-	histogram(rxfer / etime, 50, 0.5);
-	if (read_write) {
-		wmove(wnd, row++, col);
-		histogram(wwords / etime, 50, 0.5);
-		wmove(wnd, row++, col);
-		histogram(cur.dk_wxfer[dn] / etime, 50, 0.5);
-	}
-
-	if (secs) {
-		wmove(wnd, row++, col);
-		atime *= 1000;	/* In milliseconds */
-		histogram(atime / etime, 50, 0.5);
-	}
-	return (row);
-}
-
-static int
-tpstats(int row, int col, int dn)
-{
-	double atime, rwords, wwords;
-	uint64_t rxfer;
-
-	/* time busy in disk activity */
-	atime = (double)cur_tape.time[dn].tv_sec +
-		((double)cur_tape.time[dn].tv_usec / (double)1000000);
+	atime = (double)cur.time[dn].tv_sec +
+		((double)cur.time[dn].tv_usec / (double)1000000);
 
 	/* # of k transferred */
-	rwords = cur_tape.rbytes[dn] / 1024.0;
-	wwords = cur_tape.wbytes[dn] / 1024.0;
-	rxfer = cur_tape.rxfer[dn];
+	rwords = cur.rbytes[dn] / 1024.0;
+	wwords = cur.wbytes[dn] / 1024.0;
+	rxfer = cur.rxfer[dn];
 	if (!read_write) {
 		rwords = wwords;
-		rxfer += cur_tape.wxfer[dn];
+		rxfer += cur.wxfer[dn];
 	}
 	if (numbers) {
 		mvwprintw(wnd, row, col, "%5.0f%4.0f",
@@ -369,7 +272,7 @@
 			wprintw(wnd, "%5.1f", atime / etime);
 		if (read_write)
 			wprintw(wnd, " %5.0f%4.0f",
-			    wwords / etime, cur_tape.wxfer[dn] / etime);
+			    wwords / etime, cur.wxfer[dn] / etime);
 		return (row);
 	}
 
@@ -381,7 +284,7 @@
 		wmove(wnd, row++, col);
 		histogram(wwords / etime, 50, 0.5);
 		wmove(wnd, row++, col);
-		histogram(cur_tape.wxfer[dn] / etime, 50, 0.5);
+		histogram(cur.wxfer[dn] / etime, 50, 0.5);
 	}
 
 	if (secs) {
Index: usr.bin/systat/vmstat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/vmstat.c,v
retrieving revision 1.62
diff -u -r1.62 vmstat.c
--- usr.bin/systat/vmstat.c	5 Feb 2006 09:54:50 -0000	1.62
+++ usr.bin/systat/vmstat.c	5 Mar 2006 11:43:38 -0000
@@ -55,8 +55,7 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 #include "utmpentry.h"
 
 static struct Info {
@@ -80,7 +79,6 @@
 static void copyinfo(struct Info *, struct Info *);
 static float cputime(int);
 static void dinfo(int, int, int);
-static void tinfo(int, int, int);
 static void getinfo(struct Info *, enum state);
 static void putint(int, int, int, int);
 static void putfloat(double, int, int, int, int, int);
@@ -221,9 +219,7 @@
 		}
 	}
 	hertz = stathz ? stathz : hz;
-	if (!dkinit(1))
-		return(0);
-	if (!tpinit(1))
+	if (!drvinit(1))
 		return(0);
 
 	/* Old style interrupt counts - deprecated */
@@ -427,8 +423,7 @@
 
 	cpuswap();
 	if (state == TIME) {
-		dkswap();
-		tpswap();
+		drvswap();
 		etime = cur.cp_etime;
 		/* < 5 ticks - ignore this trash */
 		if ((etime * hertz) < 1.0) {
@@ -558,14 +553,9 @@
 	PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 22, 5);
 	PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 27, 6);
 	for (l = 0, i = 0, r = DISKROW, c = DISKCOL;
-	     i < (dk_ndrive + tp_ndrive); i++) {
-		if (i < dk_ndrive) {
-			if (!dk_select[i])
-				continue;
-		} else {
-			if (!tp_select[i - dk_ndrive])
-				continue;
-		}
+	     i < ndrive; i++) {
+		if (!drv_select[i])
+			continue;
 
 		if (disk_horiz)
 			c += DISKCOLWIDTH;
@@ -589,10 +579,7 @@
 		}
 		l++;
 
-		if (i < dk_ndrive)
-			dinfo(i, r, c);
-		else
-			tinfo(i - dk_ndrive, r, c);
+		dinfo(i, r, c);
 	}
 	/* blank out if we lost any disks */
 	for (i = l; i < last_disks; i++) {
@@ -751,8 +738,7 @@
 	int i;
 
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	NREAD(X_NCHSTATS, &stats->nchstats, sizeof stats->nchstats);
 	if (nintr)
 		NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG);
@@ -812,48 +798,20 @@
 	mvprintw(r, c, "%*.*s", DISKCOLWIDTH, DISKCOLWIDTH, dr_name[dn]);
 	ADV;
 
-	putint((int)(cur.dk_seek[dn]/etime+0.5), r, c, DISKCOLWIDTH);
-	ADV;
-	putint((int)((cur.dk_rxfer[dn]+cur.dk_wxfer[dn])/etime+0.5),
-	    r, c, DISKCOLWIDTH);
-	ADV;
-	puthumanint((cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / etime + 0.5,
-		    r, c, DISKCOLWIDTH);
-	ADV;
-
-	/* time busy in disk activity */
-	atime = cur.dk_time[dn].tv_sec + cur.dk_time[dn].tv_usec / 1000000.0;
-	atime = atime * 100.0 / etime;
-	if (atime >= 100)
-		putint(100, r, c, DISKCOLWIDTH);
-	else
-		putfloat(atime, r, c, DISKCOLWIDTH, 1, 1);
-}
-
-static void
-tinfo(int dn, int r, int c)
-{
-	double atime;
-
-	mvprintw(r, c, "%*.*s", DISKCOLWIDTH, DISKCOLWIDTH, tp_name[dn]);
+	putint((int)(cur.seek[dn]/etime+0.5), r, c, DISKCOLWIDTH);
 	ADV;
-	ADV; /* skip over the seeks column - not relevant for tape drives */
-
-	putint((int)((cur_tape.rxfer[dn]+cur_tape.wxfer[dn])/etime+0.5),
+	putint((int)((cur.rxfer[dn]+cur.wxfer[dn])/etime+0.5),
 	    r, c, DISKCOLWIDTH);
 	ADV;
-	puthumanint((cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) / etime + 0.5,
+	puthumanint((cur.rbytes[dn] + cur.wbytes[dn]) / etime + 0.5,
 		    r, c, DISKCOLWIDTH);
 	ADV;
 
 	/* time busy in disk activity */
-	atime = cur_tape.time[dn].tv_sec + cur_tape.time[dn].tv_usec / 1000000.0;
+	atime = cur.time[dn].tv_sec + cur.time[dn].tv_usec / 1000000.0;
 	atime = atime * 100.0 / etime;
 	if (atime >= 100)
 		putint(100, r, c, DISKCOLWIDTH);
 	else
 		putfloat(atime, r, c, DISKCOLWIDTH, 1, 1);
-#undef ADV
 }
-
-
Index: usr.bin/vmstat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/vmstat/Makefile,v
retrieving revision 1.22
diff -u -r1.22 Makefile
--- usr.bin/vmstat/Makefile	7 Aug 2005 12:23:20 -0000	1.22
+++ usr.bin/vmstat/Makefile	5 Mar 2006 11:43:38 -0000
@@ -4,7 +4,7 @@
 PROG=	vmstat
 WARNS=3
 
-SRCS=	dkstats.c tpstats.c vmstat.c
+SRCS=	drvstats.c vmstat.c
 MAN=	vmstat.1
 DPADD=	${LIBKVM}
 LDADD=	-lkvm
Index: usr.bin/vmstat/vmstat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/vmstat/vmstat.c,v
retrieving revision 1.139
diff -u -r1.139 vmstat.c
--- usr.bin/vmstat/vmstat.c	5 Feb 2006 09:54:50 -0000	1.139
+++ usr.bin/vmstat/vmstat.c	5 Mar 2006 11:43:39 -0000
@@ -132,8 +132,7 @@
 #include <unistd.h>
 #include <util.h>
 
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 /*
  * General namelist
@@ -252,8 +251,7 @@
 
 void	cpustats(void);
 void	deref_kptr(const void *, void *, size_t, const char *);
-void	dkstats(void);
-void	tpstats(void);
+void	drvstats(void);
 void	doevcnt(int verbose);
 void	dohashstat(int, int, const char *);
 void	dointr(int verbose);
@@ -405,8 +403,7 @@
 	if (todo & VMSTAT) {
 		struct winsize winsize;
 
-		dkinit(0);	/* Initialize disk stats, no disks selected. */
-		tpinit(0);
+		drvinit(0);	/* Initialize disk stats, no disks selected. */
 
 		(void)setgid(getgid()); /* don't need privs anymore */
 
@@ -511,35 +508,21 @@
 		if (isdigit((unsigned char)**argv))
 			break;
 #endif
-		for (i = 0; i < dk_ndrive; i++) {
+		for (i = 0; i < ndrive; i++) {
 			if (strcmp(dr_name[i], *argv))
 				continue;
-			dk_select[i] = 1;
+			drv_select[i] = 1;
 			++ndrives;
 			break;
 		}
-		for (i = 0; i < tp_ndrive; i++) {
-			if (strcmp(tp_name[i], *argv))
-				continue;
-			tp_select[i] = 1;
-			++ndrives;
-			break;
-		}
-	}
-	for (i = 0; i < dk_ndrive && ndrives < 3; i++) {
-		if (dk_select[i])
-			continue;
-		dk_select[i] = 1;
-		++ndrives;
 	}
-	
-	for (i = 0; i < tp_ndrive && ndrives < 3; i++) {
-		if (tp_select[i])
+	for (i = 0; i < ndrive && ndrives < 3; i++) {
+		if (drv_select[i])
 			continue;
-		tp_select[i] = 1;
+		drv_select[i] = 1;
 		++ndrives;
 	}
-	
+
 	return (argv);
 }
 
@@ -645,8 +628,8 @@
 		if (!--hdrcnt)
 			printhdr();
 		/* Read new disk statistics */
-		dkreadstats();
 		cpureadstats();
+		drvreadstats();
 		tkreadstats();
 		kread(namelist, X_UVMEXP, &uvmexp, sizeof(uvmexp));
 		if (memf != NULL) {
@@ -679,8 +662,7 @@
 		    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
 		(void)printf("%4lu ", rate(uvmexp.pdfreed - ouvmexp.pdfreed));
 		(void)printf("%4lu ", rate(uvmexp.pdscans - ouvmexp.pdscans));
-		dkstats();
-		tpstats();
+		drvstats();
 		(void)printf("%4lu %4lu %3lu ",
 		    rate(uvmexp.intrs - ouvmexp.intrs),
 		    rate(uvmexp.syscalls - ouvmexp.syscalls),
@@ -716,8 +698,8 @@
 		    ndrives * 3, "");
 
 	(void)printf(" r b w    avm    fre  flt  re  pi   po   fr   sr ");
-	for (i = 0; i < dk_ndrive; i++)
-		if (dk_select[i])
+	for (i = 0; i < ndrive; i++)
+		if (drv_select[i])
 			(void)printf("%c%c ", dr_name[i][0],
 			    dr_name[i][strlen(dr_name[i]) - 1]);
 	(void)printf("  in   sy  cs us sy id\n");
@@ -884,40 +866,22 @@
 }
 
 void
-dkstats(void)
+drvstats(void)
 {
 	int dn;
 	double etime;
 
 	/* Calculate disk stat deltas. */
-	dkswap();
 	cpuswap();
+	drvswap();
 	tkswap();
 	etime = cur.cp_etime;
 
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!dk_select[dn])
-			continue;
-		(void)printf("%2.0f ",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime);
-	}
-}
-
-void
-tpstats(void)
-{
-	int dn;
-	double etime;
-
-	/* Calculate tape stat deltas. */
-	tpswap();
-	etime = cur.cp_etime;
-
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!tp_select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!drv_select[dn])
 			continue;
 		(void)printf("%2.0f ",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 	}
 }
 
Index: usr.sbin/iostat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.sbin/iostat/Makefile,v
retrieving revision 1.21
diff -u -r1.21 Makefile
--- usr.sbin/iostat/Makefile	7 Aug 2005 12:34:21 -0000	1.21
+++ usr.sbin/iostat/Makefile	5 Mar 2006 11:43:39 -0000
@@ -11,7 +11,7 @@
 CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/vmstat
 
 # dkstats.c pulled in from ../../usr.bin/vmstat
-SRCS=	dkstats.c tpstats.c iostat.c
+SRCS=	drvstats.c iostat.c
 
 DPADD=	${LIBKVM}
 LDADD=	-lkvm
Index: usr.sbin/iostat/iostat.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/iostat/iostat.c,v
retrieving revision 1.48
diff -u -r1.48 iostat.c
--- usr.sbin/iostat/iostat.c	12 Feb 2006 22:11:54 -0000	1.48
+++ usr.sbin/iostat/iostat.c	5 Mar 2006 11:43:39 -0000
@@ -88,8 +88,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 /* Namelist and memory files. */
 char	*nlistf, *memf;
@@ -110,9 +109,9 @@
 #define	SHOW_STATS_ALL	(SHOW_STATS_1 | SHOW_STATS_2 | SHOW_STATS_X)
 
 static void cpustats(void);
-static void disk_stats(double);
-static void disk_stats2(double);
-static void disk_statsx(double);
+static void drive_stats(double);
+static void drive_stats2(double);
+static void drive_statsx(double);
 static void sig_header(int);
 static volatile int do_header;
 static void header(void);
@@ -194,14 +193,12 @@
 		defdrives -= 9;		/* XXX magic number */
 	defdrives /= 18;		/* XXX magic number */
 
-	dkinit(0);
-	tpinit(0);
+	drvinit(0);
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	ndrives = selectdrives(argc, argv);
 	if (ndrives == 0) {
-		/* No drives are selected.  No need to show disk stats. */
+		/* No drives are selected.  No need to show drive stats. */
 		todo &= ~SHOW_STATS_ALL;
 		if (todo == 0)
 			errx(1, "no drives");
@@ -226,18 +223,16 @@
 
 		if (!ISSET(todo, SHOW_TOTALS)) {
 			cpuswap();
-			dkswap();
-			tpswap();
+			drvswap();
 		}
-		
+
 		display();
 
 		if (reps >= 0 && --reps <= 0)
 			break;
 		nanosleep(&tv, NULL);
 		cpureadstats();
-		dkreadstats();
-		tpreadstats();
+		drvreadstats();
 	}
 	exit(0);
 }
@@ -271,25 +266,17 @@
 		(void)printf("      tty");
 
 	if (ISSET(todo, SHOW_STATS_1)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("        %9.9s ", cur.dk_name[i]);
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
-				(void)printf("        %9.9s ",
-					     cur_tape.name[i]);
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
+				(void)printf("        %9.9s ", cur.name[i]);
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("        %9.9s ", cur.dk_name[i]);
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
-				(void)printf("        %9.9s ",
-					     cur_tape.name[i]);
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
+				(void)printf("        %9.9s ", cur.name[i]);
 	}
-	
+
 	if (ISSET(todo, SHOW_CPU))
 		(void)printf("            CPU");
 
@@ -300,15 +287,8 @@
 		printf(" tin tout");
 
 	if (ISSET(todo, SHOW_STATS_1)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i]) {
-				if (ISSET(todo, SHOW_TOTALS))
-					(void)printf("  KB/t  xfr  MB   ");
-				else
-					(void)printf("  KB/t  t/s  MB/s ");
-			}
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i]) {
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i]) {
 				if (ISSET(todo, SHOW_TOTALS))
 					(void)printf("  KB/t  xfr  MB   ");
 				else
@@ -317,11 +297,8 @@
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("    KB   xfr time ");
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
 				(void)printf("    KB   xfr time ");
 	}
 
@@ -331,150 +308,33 @@
 }
 
 static void
-disk_stats(double etime)
-{
-	int dn;
-	double atime, mbps;
-
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!cur.dk_select[dn])
-			continue;
-					/* average Kbytes per transfer. */
-		if (cur.dk_rxfer[dn] + cur.dk_wxfer[dn])
-			mbps = ((cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) /
-			    1024.0) / (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]);
-		else
-			mbps = 0.0;
-		(void)printf(" %5.2f", mbps);
-
-					/* average transfers per second. */
-		(void)printf(" %4.0f",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime);
-
-					/* time busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-
-					/* Megabytes per second. */
-		if (atime != 0.0)
-			mbps = (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) /
-			    (double)(1024 * 1024);
-		else
-			mbps = 0;
-		(void)printf(" %5.2f ", mbps / etime);
-	}
-}
-
-static void
-disk_stats2(double etime)
-{
-	int dn;
-	double atime;
-
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!cur.dk_select[dn])
-			continue;
-
-					/* average kbytes per second. */
-		(void)printf(" %5.0f",
-		    (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / 1024.0 / etime);
-
-					/* average transfers per second. */
-		(void)printf(" %5.0f",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime);
-
-					/* average time busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-		(void)printf(" %4.2f ", atime / etime);
-	}
-}
-
-static void
-disk_statsx(double etime)
-{
-	int dn;
-	double atime, kbps;
-
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!cur.dk_select[dn])
-			continue;
-
-		(void)printf("%-8.8s", cur.dk_name[dn]);
-
-					/* average read Kbytes per transfer */
-		if (cur.dk_rxfer[dn])
-			kbps = (cur.dk_rbytes[dn] / 1024.0) / cur.dk_rxfer[dn];
-		else
-			kbps = 0.0;
-		(void)printf(" %8.2f", kbps);
-
-					/* average read transfers
-					   (per second) */
-		(void)printf(" %6.0f", cur.dk_rxfer[dn] / etime);
-
-					/* time read busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-		(void)printf(" %6.2f", atime / etime);
-
-					/* average read megabytes
-					   (per second) */
-		(void)printf(" %8.2f",
-		    cur.dk_rbytes[dn] / (1024.0 * 1024) / etime);
-
-
-					/* average write Kbytes per transfer */
-		if (cur.dk_wxfer[dn])
-			kbps = (cur.dk_wbytes[dn] / 1024.0) / cur.dk_wxfer[dn];
-		else
-			kbps = 0.0;
-		(void)printf("   %8.2f", kbps);
-
-					/* average write transfers
-					   (per second) */
-		(void)printf(" %6.0f", cur.dk_wxfer[dn] / etime);
-
-					/* time write busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-		(void)printf(" %6.2f", atime / etime);
-
-					/* average write megabytes
-					   (per second) */
-		(void)printf(" %8.2f\n",
-		    cur.dk_wbytes[dn] / (1024.0 * 1024) / etime);
-	}
-}
-
-static void
-tape_stats(double etime)
+drive_stats(double etime)
 {
 	int dn;
 	double atime, mbps;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 					/* average Kbytes per transfer. */
-		if (cur_tape.rxfer[dn] + cur_tape.wxfer[dn])
-			mbps = ((cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) /
-			    1024.0) / (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]);
+		if (cur.rxfer[dn] + cur.wxfer[dn])
+			mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
+			    1024.0) / (cur.rxfer[dn] + cur.wxfer[dn]);
 		else
 			mbps = 0.0;
 		(void)printf(" %5.2f", mbps);
 
 					/* average transfers per second. */
 		(void)printf(" %4.0f",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 
-					/* time busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 
 					/* Megabytes per second. */
 		if (atime != 0.0)
-			mbps = (cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) /
+			mbps = (cur.rbytes[dn] + cur.wbytes[dn]) /
 			    (double)(1024 * 1024);
 		else
 			mbps = 0;
@@ -483,84 +343,84 @@
 }
 
 static void
-tape_stats2(double etime)
+drive_stats2(double etime)
 {
 	int dn;
 	double atime;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 
 					/* average kbytes per second. */
 		(void)printf(" %5.0f",
-		    (cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) / 1024.0 / etime);
+		    (cur.rbytes[dn] + cur.wbytes[dn]) / 1024.0 / etime);
 
 					/* average transfers per second. */
 		(void)printf(" %5.0f",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 
-					/* average time busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* average time busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %4.2f ", atime / etime);
 	}
 }
 
 static void
-tape_statsx(double etime)
+drive_statsx(double etime)
 {
 	int dn;
 	double atime, kbps;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 
-		(void)printf("%-8.8s", cur_tape.name[dn]);
+		(void)printf("%-8.8s", cur.name[dn]);
 
 					/* average read Kbytes per transfer */
-		if (cur.dk_rxfer[dn])
-			kbps = (cur_tape.rbytes[dn] / 1024.0) / cur_tape.rxfer[dn];
+		if (cur.rxfer[dn])
+			kbps = (cur.rbytes[dn] / 1024.0) / cur.rxfer[dn];
 		else
 			kbps = 0.0;
 		(void)printf(" %8.2f", kbps);
 
 					/* average read transfers
 					   (per second) */
-		(void)printf(" %6.0f", cur_tape.rxfer[dn] / etime);
+		(void)printf(" %6.0f", cur.rxfer[dn] / etime);
 
-					/* time read busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time read busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %6.2f", atime / etime);
 
 					/* average read megabytes
 					   (per second) */
 		(void)printf(" %8.2f",
-		    cur_tape.rbytes[dn] / (1024.0 * 1024) / etime);
+		    cur.rbytes[dn] / (1024.0 * 1024) / etime);
 
 
 					/* average write Kbytes per transfer */
-		if (cur_tape.wxfer[dn])
-			kbps = (cur_tape.wbytes[dn] / 1024.0) / cur_tape.wxfer[dn];
+		if (cur.wxfer[dn])
+			kbps = (cur.wbytes[dn] / 1024.0) / cur.wxfer[dn];
 		else
 			kbps = 0.0;
 		(void)printf("   %8.2f", kbps);
 
 					/* average write transfers
 					   (per second) */
-		(void)printf(" %6.0f", cur_tape.wxfer[dn] / etime);
+		(void)printf(" %6.0f", cur.wxfer[dn] / etime);
 
-					/* time write busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time write busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %6.2f", atime / etime);
 
 					/* average write megabytes
 					   (per second) */
 		(void)printf(" %8.2f\n",
-		    cur_tape.wbytes[dn] / (1024.0 * 1024) / etime);
+		    cur.wbytes[dn] / (1024.0 * 1024) / etime);
 	}
 }
 
@@ -605,8 +465,7 @@
 		etime = 1.0;
 
 	if (ISSET(todo, SHOW_STATS_X)) {
-		disk_statsx(etime);
-		tape_statsx(etime);
+		drive_statsx(etime);
 		goto out;
 	}
 
@@ -614,16 +473,14 @@
 		printf("%4.0f %4.0f", cur.tk_nin / etime, cur.tk_nout / etime);
 
 	if (ISSET(todo, SHOW_STATS_1)) {
-		disk_stats(etime);
-		tape_stats(etime);
+		drive_stats(etime);
 	}
-	
+
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		disk_stats2(etime);
-		tape_stats2(etime);
+		drive_stats2(etime);
 	}
-	
+
 
 	if (ISSET(todo, SHOW_CPU))
 		cpustats();
@@ -656,19 +513,13 @@
 			break;
 #endif
 		tried++;
-		for (i = 0; i < dk_ndrive; i++) {
-			if (strcmp(cur.dk_name[i], *argv))
+		for (i = 0; i < ndrive; i++) {
+			if (strcmp(cur.name[i], *argv))
 				continue;
-			cur.dk_select[i] = 1;
-			++ndrives;
-		}
-		
-		for (i = 0; i < tp_ndrive; i++) {
-			if (strcmp(cur_tape.name[i], *argv))
-				continue;
-			cur_tape.select[i] = 1;
+			cur.select[i] = 1;
 			++ndrives;
 		}
+
 	}
 
 	if (ndrives == 0 && tried == 0) {
@@ -677,15 +528,11 @@
 		 * if none specified.
 		 */
 		maxdrives = (ISSET(todo, SHOW_STATS_X) ||
-			     (dk_ndrive + tp_ndrive) < defdrives)
-			? (dk_ndrive + tp_ndrive) : defdrives;
+			     ndrive < defdrives)
+			? (ndrive) : defdrives;
 		for (i = 0; i < maxdrives; i++) {
-			if (i >= dk_ndrive) {
-				cur_tape.select[i - dk_ndrive] = 1;
-			} else {
-				cur.dk_select[i] = 1;
-			}
-			
+			cur.select[i] = 1;
+
 			++ndrives;
 			if (!ISSET(todo, SHOW_STATS_X) && ndrives == defdrives)
 				break;

-- 
Brett Lymn