Subject: SCSI and IDE/ATAPI rototillage
To: None <tech-kern@netbsd.org>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-kern
Date: 09/18/2003 22:05:15
This is a snapshot of some work I'm doing to simplify the SCSI and
IDE/ATAPI code.  I'm posting it here for early review.

Besides reducing both source and compiled binary size noticably, I've
added XS_CTL_XFER_ONSTACK, which gives callers direct access to
scsipi_xfer structures, enabling them to do a more thorough inspection
of the state (residual count, SCSI status code, sense data, etc.) when
deciding what to do.  This will be used to make some things (INQUIRY
response handling, in particular) more robust.

I have not (yet) updated some of the wdc frontends used on non-x86
platforms.  It would be useful for people to test this as much as
possible, though.


1) Use config_defer() to attach IDE and ATAPI drives.  This eliminates most
   polling and will simplify the control path a little.
2) Add XS_CTL_XFER_ONSTACK, which is used to create an initialized scsipi_xfer
   that can be handed directly to scsipi_execute_xs(), and use this in a number
   of places.  There are several components to this:
   a) Move the XS_CTL_DATA_ONSTACK PHOLD()/PRELE() from scsipi_command() to
      scsipi_execute_xs().  Add an assertion that XS_CTL_*_ONSTACK is
      incompatible with XS_CTL_ASYNC.
   b) Move assertions from *_scsipi_cmd() to scsipi_execute_xs().
   c) Call scsipi_execute_xs() from scsipi_command(), not *_scsipi_cmd() -- now
      *_scsipi_cmd() is just used for the protocol-specific fixups, and is
      called from scsipi_execute_xs().
   d) Do the command block copy in scsipi_execute_xs(), not scsipi_make_xs()
      (also reduces code size a bit).
3) Never do a biodone() in the generic SCSI layer -- always do it in the
   upper device driver (i.e. from the "done" routine, or the "start" routine
   if there is an allocation failure).  Pass the error code from
   scsipi_complete() down to accomplish this.  Now the buf pointer is not used
   by the low-level SCSI code, and can be made into an opaque device-specific
   pointer.  (Note: This interface is going to change later.)
4) XS_CTL_NOSLEEP is never used without XS_CTL_ASYNC or XS_CTL_POLL, and vice
   versa.  Therefore, define XS_CTL_NOSLEEP as XS_CTL_ASYNC|XS_CTL_POLL (to
   avoid changing tests in low-level code), but remove the separate flag.
5) Make scsipi_enqueue() never fail.
6) Clean up some goofiness in pciide -- get rid of the whole "candisable" path
   (it's gratuitous) and simplify the code by calling pciide_map_compat_intr()
   and *_set_modes() from central locations.
7) Remove all PQUIRK_NOLUNS quirks.


Index: ata/wd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wd.c,v
retrieving revision 1.260
diff -u -r1.260 wd.c
--- ata/wd.c	2003/08/03 17:53:04	1.260
+++ ata/wd.c	2003/09/18 21:40:46
@@ -300,7 +300,7 @@
 	aprint_naive("\n");
 
 	/* read our drive info */
-	if (wd_get_params(wd, AT_POLL, &wd->sc_params) != 0) {
+	if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) {
 		aprint_error("\n%s: IDENTIFY failed\n", wd->sc_dev.dv_xname);
 		return;
 	}
Index: ic/wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.123
diff -u -r1.123 wdc.c
--- ic/wdc.c	2003/05/17 21:52:04	1.123
+++ ic/wdc.c	2003/09/18 21:40:47
@@ -361,10 +361,10 @@
 		 * Then issue a IDENTIFY command, to try to detect slave ghost
 		 */
 		delay(5000);
-		error = ata_get_params(&chp->ch_drive[i], AT_POLL, &params);
+		error = ata_get_params(&chp->ch_drive[i], AT_WAIT, &params);
 		if (error != CMD_OK) {
 			delay(1000000);
-			error = ata_get_params(&chp->ch_drive[i], AT_POLL,
+			error = ata_get_params(&chp->ch_drive[i], AT_WAIT,
 			    &params);
 		}
 		if (error == CMD_OK) {
@@ -1019,7 +1019,7 @@
 	char *sep = "";
 	int cf_flags;
 
-	if (ata_get_params(drvp, AT_POLL, &params) != CMD_OK) {
+	if (ata_get_params(drvp, AT_WAIT, &params) != CMD_OK) {
 		/* IDENTIFY failed. Can't tell more about the device */
 		return;
 	}
@@ -1031,12 +1031,12 @@
 		 * and compare results.
 		 */
 		drvp->drive_flags |= DRIVE_CAP32;
-		ata_get_params(drvp, AT_POLL, &params2);
+		ata_get_params(drvp, AT_WAIT, &params2);
 		if (memcmp(&params, &params2, sizeof(struct ataparams)) != 0) {
 			/* Not good. fall back to 16bits */
 			drvp->drive_flags &= ~DRIVE_CAP32;
 		} else {
-			aprint_normal("%s: 32-bit data port",
+			aprint_normal("%s: 32-bit data port\n",
 			    drv_dev->dv_xname);
 		}
 	}
@@ -1045,20 +1045,14 @@
 	    params.atap_ata_major != 0xffff) {
 		for (i = 14; i > 0; i--) {
 			if (params.atap_ata_major & (1 << i)) {
-				if ((drvp->drive_flags & DRIVE_CAP32) == 0)
-					aprint_normal("%s: ",
-					    drv_dev->dv_xname);
-				else
-					aprint_normal(", ");
-				aprint_normal("ATA version %d\n", i);
+				aprint_normal("%s: ATA version %d\n",
+				    drv_dev->dv_xname, i);
 				drvp->ata_vers = i;
 				break;
 			}
 		}
-	} else 
+	}
 #endif
-	if (drvp->drive_flags & DRIVE_CAP32)
-		aprint_normal("\n");
 
 	/* An ATAPI device is at last PIO mode 3 */
 	if (drvp->drive_flags & DRIVE_ATAPI)
@@ -1090,7 +1084,7 @@
 			 */
 			if ((wdc->cap & WDC_CAPABILITY_MODE) != 0)
 				if (ata_set_mode(drvp, 0x08 | (i + 3),
-				   AT_POLL) != CMD_OK)
+				   AT_WAIT) != CMD_OK)
 					continue;
 			if (!printed) { 
 				aprint_normal("%s: drive supports PIO mode %d",
@@ -1123,7 +1117,7 @@
 				continue;
 			if ((wdc->cap & WDC_CAPABILITY_DMA) &&
 			    (wdc->cap & WDC_CAPABILITY_MODE))
-				if (ata_set_mode(drvp, 0x20 | i, AT_POLL)
+				if (ata_set_mode(drvp, 0x20 | i, AT_WAIT)
 				    != CMD_OK)
 					continue;
 			if (!printed) {
@@ -1150,7 +1144,7 @@
 				if ((wdc->cap & WDC_CAPABILITY_MODE) &&
 				    (wdc->cap & WDC_CAPABILITY_UDMA))
 					if (ata_set_mode(drvp, 0x40 | i,
-					    AT_POLL) != CMD_OK)
+					    AT_WAIT) != CMD_OK)
 						continue;
 				if (!printed) {
 					aprint_normal("%s Ultra-DMA mode %d",
Index: isa/wdc_isa.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/wdc_isa.c,v
retrieving revision 1.31
diff -u -r1.31 wdc_isa.c
--- isa/wdc_isa.c	2003/05/09 23:51:29	1.31
+++ isa/wdc_isa.c	2003/09/18 21:40:47
@@ -1,7 +1,7 @@
 /*	$NetBSD: wdc_isa.c,v 1.31 2003/05/09 23:51:29 fvdl Exp $ */
 
 /*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -73,8 +73,9 @@
 	int	sc_drq;
 };
 
-int	wdc_isa_probe	__P((struct device *, struct cfdata *, void *));
-void	wdc_isa_attach	__P((struct device *, struct device *, void *));
+int	wdc_isa_probe		__P((struct device *, struct cfdata *, void *));
+void	wdc_isa_attach		__P((struct device *, struct device *, void *));
+void	wdc_isa_probedevs	__P((struct device *));
 
 CFATTACH_DECL(wdc_isa, sizeof(struct wdc_isa_softc),
     wdc_isa_probe, wdc_isa_attach, NULL, NULL);
@@ -199,7 +200,17 @@
 
 	printf("\n");
 
+	config_defer(self, wdc_isa_probedevs);
+}
+
+void
+wdc_isa_probedevs(self)
+	struct device *self;
+{
+	struct wdc_isa_softc *sc = (void *)self;
+
 	wdcattach(&sc->wdc_channel);
+	wdc_print_modes(&sc->wdc_channel);
 }
 
 #if 0
Index: isapnp/wdc_isapnp.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isapnp/wdc_isapnp.c,v
retrieving revision 1.19
diff -u -r1.19 wdc_isapnp.c
--- isapnp/wdc_isapnp.c	2003/03/22 20:05:20	1.19
+++ isapnp/wdc_isapnp.c	2003/09/18 21:40:47
@@ -70,6 +70,7 @@
 
 int	wdc_isapnp_probe 	__P((struct device *, struct cfdata *, void *));
 void	wdc_isapnp_attach 	__P((struct device *, struct device *, void *));
+void	wdc_isapnp_probedevs	__P((struct device *));
 
 CFATTACH_DECL(wdc_isapnp, sizeof(struct wdc_isapnp_softc),
     wdc_isapnp_probe, wdc_isapnp_attach, NULL, NULL);
@@ -157,6 +158,16 @@
 	sc->wdc_channel.channel = 0;
 	sc->wdc_channel.wdc = &sc->sc_wdcdev;
 	sc->wdc_channel.ch_queue = &sc->wdc_chqueue;
+
+	config_defer(self, wdc_isapnp_probedevs);
+}
+
+void
+wdc_isapnp_probedevs(self)
+	struct device *self;
+{
+	struct wdc_isapnp_softc *sc = (void *)self;
+
 	wdcattach(&sc->wdc_channel);
 	wdc_print_modes(&sc->wdc_channel);
 }
Index: ofisa/wdc_ofisa.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ofisa/wdc_ofisa.c,v
retrieving revision 1.12
diff -u -r1.12 wdc_ofisa.c
--- ofisa/wdc_ofisa.c	2003/03/22 20:01:05	1.12
+++ ofisa/wdc_ofisa.c	2003/09/18 21:40:48
@@ -67,6 +67,7 @@
 
 int wdc_ofisa_probe __P((struct device *, struct cfdata *, void *));
 void wdc_ofisa_attach __P((struct device *, struct device *, void *));
+void wdc_ofisa_probedevs __P((struct device *));
 
 CFATTACH_DECL(wdc_ofisa, sizeof(struct wdc_ofisa_softc),
     wdc_ofisa_probe, wdc_ofisa_attach, NULL, NULL);
@@ -154,8 +155,8 @@
 	sc->wdc_channel.channel = 0;
 	sc->wdc_channel.wdc = &sc->sc_wdcdev;
 	sc->wdc_channel.ch_queue = &sc->wdc_chqueue;
-	wdcattach(&sc->wdc_channel);
-	wdc_print_modes(&sc->wdc_channel);
+
+	config_defer(self, wdc_ofisa_probedevs);
 
 #if 0
 	printf("%s: registers: ", sc->sc_dev.dv_xname);
@@ -165,4 +166,14 @@
 	ofisa_intr_print(&intr, 1);
 	printf("\n");
 #endif
+}
+
+void
+wdc_ofisa_probedevs(self)
+	struct device *self;
+{
+	struct wdc_ofisa_softc *sc = (void *)self;
+
+	wdcattach(&sc->wdc_channel);
+	wdc_print_modes(&sc->wdc_channel);
 }
Index: pci/pciide.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pciide.c,v
retrieving revision 1.195
diff -u -r1.195 pciide.c
--- pci/pciide.c	2003/08/10 14:51:55	1.195
+++ pci/pciide.c	2003/09/18 21:40:51
@@ -703,6 +703,7 @@
 
 int	pciide_match __P((struct device *, struct cfdata *, void *));
 void	pciide_attach __P((struct device *, struct device *, void *));
+void	pciide_probedevs __P((struct device *));
 
 CFATTACH_DECL(pciide, sizeof(struct pciide_softc),
     pciide_match, pciide_attach, NULL, NULL);
@@ -719,9 +720,8 @@
 void	pciide_mapchan __P((struct pci_attach_args *,
 	    struct pciide_channel *, pcireg_t, bus_size_t *, bus_size_t *,
 	    int (*pci_intr) __P((void *))));
-int	pciide_chan_candisable __P((struct pciide_channel *));
 void	pciide_map_compat_intr __P(( struct pci_attach_args *,
-	    struct pciide_channel *, int, int));
+	    struct pciide_channel *, int));
 int	pciide_compat_intr __P((void *));
 int	pciide_pci_intr __P((void *));
 const struct pciide_product_desc* pciide_lookup_product __P((u_int32_t));
@@ -829,8 +829,27 @@
 	}
 	WDCDEBUG_PRINT(("pciide: command/status register=%x\n",
 	    pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG)), DEBUG_PROBE);
+
+	config_defer(self, pciide_probedevs);
 }
 
+void
+pciide_probedevs(self)
+	struct device *self;
+{
+	struct pciide_softc *sc = (struct pciide_softc *)self;
+	int i;
+	struct pciide_channel *cp;
+
+	for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
+		cp = &sc->pciide_channels[i];
+		if (cp->hw_ok) {
+			wdcattach(&cp->wdc_channel);
+			sc->sc_wdcdev.set_modes(&cp->wdc_channel);
+		}
+	}
+}
+
 /* tell whether the chip is enabled or not */
 int
 pciide_chipen(sc, pa)
@@ -882,6 +901,9 @@
 		return (0);
 	}
 
+	wdc_cp->data32iot = wdc_cp->cmd_iot;
+	wdc_cp->data32ioh = wdc_cp->cmd_ioh;
+	pciide_map_compat_intr(pa, cp, compatchan);
 	return (1);
 }
 
@@ -952,6 +974,9 @@
 		bus_space_unmap(wdc_cp->cmd_iot, cp->ctl_baseioh, *ctlsizep);
 		return 0;
 	}
+
+	wdc_cp->data32iot = wdc_cp->cmd_iot;
+	wdc_cp->data32ioh = wdc_cp->cmd_ioh;
 	return (1);
 }
 
@@ -1382,56 +1407,23 @@
 	if (interface & PCIIDE_INTERFACE_PCI(wdc_cp->channel))
 		cp->hw_ok = pciide_mapregs_native(pa, cp, cmdsizep, ctlsizep,
 		    pci_intr);
-	else 
+	else
 		cp->hw_ok = pciide_mapregs_compat(pa, cp,
 		    wdc_cp->channel, cmdsizep, ctlsizep);
-
-	if (cp->hw_ok == 0)
-		return;
-	wdc_cp->data32iot = wdc_cp->cmd_iot;
-	wdc_cp->data32ioh = wdc_cp->cmd_ioh;
-	wdcattach(wdc_cp);
 }
 
 /*
- * Generic code to call to know if a channel can be disabled. Return 1
- * if channel can be disabled, 0 if not
- */
-int
-pciide_chan_candisable(cp)
-	struct pciide_channel *cp;
-{
-	struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
-	struct channel_softc *wdc_cp = &cp->wdc_channel;
-
-	if ((wdc_cp->ch_drive[0].drive_flags & DRIVE) == 0 &&
-	    (wdc_cp->ch_drive[1].drive_flags & DRIVE) == 0) {
-		aprint_normal("%s: disabling %s channel (no drives)\n",
-		    sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
-		cp->hw_ok = 0;
-		return 1;
-	}
-	return 0;
-}
-
-/*
  * generic code to map the compat intr if hw_ok=1 and it is a compat channel.
  * Set hw_ok=0 on failure
  */
 void
-pciide_map_compat_intr(pa, cp, compatchan, interface)
+pciide_map_compat_intr(pa, cp, compatchan)
 	struct pci_attach_args *pa;
 	struct pciide_channel *cp;
-	int compatchan, interface;
+	int compatchan;
 {
 	struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
-	struct channel_softc *wdc_cp = &cp->wdc_channel;
 
-	if (cp->hw_ok == 0)
-		return;
-	if ((interface & PCIIDE_INTERFACE_PCI(wdc_cp->channel)) != 0)
-		return;
-
 #ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
 	cp->ih = pciide_machdep_compat_intr_establish(&sc->sc_wdcdev.sc_dev,
 	    pa, compatchan, pciide_compat_intr, cp);
@@ -1504,13 +1496,8 @@
 		cp = &sc->pciide_channels[channel];
 		if (pciide_chansetup(sc, channel, interface) == 0)
 			continue;
-		if (interface & PCIIDE_INTERFACE_PCI(channel)) {
-			cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize,
-			    &ctlsize, pciide_pci_intr);
-		} else {
-			cp->hw_ok = pciide_mapregs_compat(pa, cp,
-			    channel, &cmdsize, &ctlsize);
-		}
+		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
+		    pciide_pci_intr);
 		if (cp->hw_ok == 0)
 			continue;
 		/*
@@ -1542,21 +1529,6 @@
 			    sc->sc_wdcdev.sc_dev.dv_xname, cp->name,
 			    failreason);
 			cp->hw_ok = 0;
-			bus_space_unmap(cp->wdc_channel.cmd_iot,
-			    cp->wdc_channel.cmd_ioh, cmdsize);
-			if (interface & PCIIDE_INTERFACE_PCI(channel))
-				bus_space_unmap(cp->wdc_channel.ctl_iot,
-				    cp->ctl_baseioh, ctlsize);
-			else
-				bus_space_unmap(cp->wdc_channel.ctl_iot,
-				    cp->wdc_channel.ctl_ioh, ctlsize);
-		} else {
-			pciide_map_compat_intr(pa, cp, channel, interface);
-		}
-		if (cp->hw_ok) {
-			cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;
-			cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;
-			wdcattach(&cp->wdc_channel);
 		}
 	}
 
@@ -1745,18 +1717,6 @@
 		}
 		/* PIIX are compat-only pciide devices */
 		pciide_mapchan(pa, cp, 0, &cmdsize, &ctlsize, pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		if (pciide_chan_candisable(cp)) {
-			idetim = PIIX_IDETIM_CLEAR(idetim, PIIX_IDETIM_IDE,
-			    channel);
-			pci_conf_write(sc->sc_pc, sc->sc_tag, PIIX_IDETIM,
-			    idetim);
-		}
-		pciide_map_compat_intr(pa, cp, channel, 0);
-		if (cp->hw_ok == 0)
-			continue;
-		sc->sc_wdcdev.set_modes(&cp->wdc_channel);
 	}
 
 	WDCDEBUG_PRINT(("piix_setup_chip: idetim=0x%x",
@@ -2196,14 +2156,6 @@
 		}
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-
-		if (pciide_chan_candisable(cp))
-			chanenable &= ~AMD7X6_CHAN_EN(channel);
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		if (cp->hw_ok == 0)
-			continue;
-
-		amd7x6_setup_channel(&cp->wdc_channel);
 	}
 	pci_conf_write(sc->sc_pc, sc->sc_tag, AMD7X6_CHANSTATUS_EN(sc),
 	    chanenable);
@@ -2308,9 +2260,9 @@
 		    IDEDMA_CTL + (IDEDMA_SCH_OFFSET * chp->channel),
 		    idedma_ctl);
 	}
-	pciide_print_modes(cp);
 	pci_conf_write(sc->sc_pc, sc->sc_tag, AMD7X6_DATATIM(sc), datatim_reg);
 	pci_conf_write(sc->sc_pc, sc->sc_tag, AMD7X6_UDMA(sc), udmatim_reg);
+	pciide_print_modes(cp);
 }
 
 void
@@ -2425,18 +2377,6 @@
 		}
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		if (pciide_chan_candisable(cp)) {
-			ideconf &= ~APO_IDECONF_EN(channel);
-			pci_conf_write(sc->sc_pc, sc->sc_tag, APO_IDECONF,
-			    ideconf);
-		}
-		pciide_map_compat_intr(pa, cp, channel, interface);
-
-		if (cp->hw_ok == 0)
-			continue;
-		apollo_setup_channel(&sc->pciide_channels[channel].wdc_channel);
 	}
 	WDCDEBUG_PRINT(("apollo_chip_map: APO_DATATIM=0x%x, APO_UDMA=0x%x\n",
 	    pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM),
@@ -2532,9 +2472,9 @@
 		    IDEDMA_CTL + (IDEDMA_SCH_OFFSET * chp->channel),
 		    idedma_ctl);
 	}
-	pciide_print_modes(cp);
 	pci_conf_write(sc->sc_pc, sc->sc_tag, APO_DATATIM, datatim_reg);
 	pci_conf_write(sc->sc_pc, sc->sc_tag, APO_UDMA, udmatim_reg);
+	pciide_print_modes(cp);
 }
 
 void
@@ -2613,16 +2553,6 @@
 	}
 
 	pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, cmd_pci_intr);
-	if (cp->hw_ok == 0)
-		return;
-	if (channel == 1) {
-		if (pciide_chan_candisable(cp)) {
-			ctrl &= ~CMD_CTRL_2PORT;
-			pciide_pci_write(pa->pa_pc, pa->pa_tag,
-			    CMD_CTRL, ctrl);
-		}
-	}
-	pciide_map_compat_intr(pa, cp, channel, interface);
 }
 
 int
@@ -2775,9 +2705,6 @@
 	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
 		cp = &sc->pciide_channels[channel];
 		cmd_channel_map(pa, sc, channel);
-		if (cp->hw_ok == 0)
-			continue;
-		cmd0643_9_setup_channel(&cp->wdc_channel);
 	}
 	/*
 	 * note - this also makes sure we clear the irq disable and reset
@@ -2925,9 +2852,6 @@
 	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
 		cp = &sc->pciide_channels[channel];
 		cmd680_channel_map(pa, sc, channel);
-		if (cp->hw_ok == 0)
-			continue;
-		cmd680_setup_channel(&cp->wdc_channel);
 	}
 }
 
@@ -2980,9 +2904,6 @@
 	    "native-PCI" : "compatibility");
 
 	pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, pciide_pci_intr);
-	if (cp->hw_ok == 0)
-		return;
-	pciide_map_compat_intr(pa, cp, channel, interface);
 }
 
 void
@@ -3126,10 +3047,6 @@
 			continue;
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		cmd3112_setup_channel(&cp->wdc_channel);
 	}
 }
 
@@ -3258,30 +3175,14 @@
 	    (interface & PCIIDE_INTERFACE_SETTABLE(0)) ?
 	    "configured" : "wired");
 	if (interface & PCIIDE_INTERFACE_PCI(0)) {
-		aprint_normal("native-PCI");
+		aprint_normal("native-PCI mode\n");
 		cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
 	} else {
-		aprint_normal("compatibility");
+		aprint_normal("compatibility mode\n");
 		cp->hw_ok = pciide_mapregs_compat(pa, cp, sc->sc_cy_compatchan,
 		    &cmdsize, &ctlsize);
 	}
-	aprint_normal(" mode\n");
-	cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;
-	cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;
-	wdcattach(&cp->wdc_channel);
-	if (pciide_chan_candisable(cp)) {
-		pci_conf_write(sc->sc_pc, sc->sc_tag,
-		    PCI_COMMAND_STATUS_REG, 0);
-	}
-	pciide_map_compat_intr(pa, cp, sc->sc_cy_compatchan, interface);
-	if (cp->hw_ok == 0)
-		return;
-	WDCDEBUG_PRINT(("cy693_chip_map: old timings reg 0x%x\n",
-	    pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)),DEBUG_PROBE);
-	cy693_setup_channel(&cp->wdc_channel);
-	WDCDEBUG_PRINT(("cy693_chip_map: new timings reg 0x%x\n",
-	    pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)), DEBUG_PROBE);
 }
 
 void
@@ -3336,13 +3237,13 @@
 		    CY_DMA_IDX_PRIMARY : CY_DMA_IDX_SECONDARY, dma_mode);
 	}
 
-	pciide_print_modes(cp);
-
 	if (idedma_ctl != 0) {
 		/* Add software bits in status register */
 		bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
 		    IDEDMA_CTL, idedma_ctl);
 	}
+
+	pciide_print_modes(cp);
 }
 
 static struct sis_hostbr_type {
@@ -3544,20 +3445,6 @@
 		}
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		if (pciide_chan_candisable(cp)) {
-			if (channel == 0)
-				sis_ctr0 &= ~SIS_CTRL0_CHAN0_EN;
-			else
-				sis_ctr0 &= ~SIS_CTRL0_CHAN1_EN;
-			pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_CTRL0,
-			    sis_ctr0);
-		}
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		if (cp->hw_ok == 0)
-			continue;
-		sc->sc_wdcdev.set_modes(&cp->wdc_channel);
 	}
 }
 
@@ -3812,15 +3699,6 @@
 		/* newer controllers seems to lack the ACER_CHIDS. Sigh */
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		     (rev >= 0xC2) ? pciide_pci_intr : acer_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		if (pciide_chan_candisable(cp)) {
-			cr &= ~(PCIIDE_CHAN_EN(channel) << PCI_INTERFACE_SHIFT);
-			pci_conf_write(sc->sc_pc, sc->sc_tag,
-			    PCI_CLASS_REG, cr);
-		}
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		acer_setup_channel(&cp->wdc_channel);
 	}
 }
 
@@ -4060,19 +3938,12 @@
 		}
 		if (pciide_chansetup(sc, i, interface) == 0)
 			continue;
-		if (interface & PCIIDE_INTERFACE_PCI(i)) {
+		if (interface & PCIIDE_INTERFACE_PCI(i))
 			cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize,
 			    &ctlsize, hpt_pci_intr);
-		} else {
+		else
 			cp->hw_ok = pciide_mapregs_compat(pa, cp, compatchan,
 			    &cmdsize, &ctlsize);
-		}
-		if (cp->hw_ok == 0)
-			return;
-		cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;
-		cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;
-		wdcattach(&cp->wdc_channel);
-		hpt_setup_channel(&cp->wdc_channel);
 	}
 	if ((sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
 	    (revision == HPT370_REV || revision == HPT370A_REV ||
@@ -4437,19 +4308,8 @@
 			    sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
 			continue;
 		}
-		if (PDC_IS_265(sc))
-			pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
-			    pdc20265_pci_intr);
-		else
-			pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
-			    pdc202xx_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		if (!PDC_IS_268(sc) && pciide_chan_candisable(cp))
-			st &= ~(PDC_IS_262(sc) ?
-			    PDC262_STATE_EN(channel):PDC246_STATE_EN(channel));
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		sc->sc_wdcdev.set_modes(&cp->wdc_channel);
+		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
+		    PDC_IS_265(sc) ? pdc20265_pci_intr : pdc202xx_pci_intr);
 	}
 	if (!PDC_IS_268(sc)) {
 		WDCDEBUG_PRINT(("pdc202xx_setup_chip: new controller state "
@@ -4813,12 +4673,6 @@
 		}
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		if (cp->hw_ok == 0)
-			continue;
-		opti_setup_channel(&cp->wdc_channel);
 	}
 }
 
@@ -4974,19 +4828,12 @@
 		cp = &sc->pciide_channels[i];
 		if (pciide_chansetup(sc, i, interface) == 0)
 			continue;
-		if (interface & PCIIDE_INTERFACE_PCI(i)) {
+		if (interface & PCIIDE_INTERFACE_PCI(i))
 			cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize,
 			    &ctlsize, pciide_pci_intr);
-		} else {
+		else
 			cp->hw_ok = pciide_mapregs_compat(pa, cp, i,
 			    &cmdsize, &ctlsize);
-		}
-		if (cp->hw_ok == 0)
-			return;
-		cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;
-		cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;
-		wdcattach(&cp->wdc_channel);
-		acard_setup_channel(&cp->wdc_channel);
 	}
 	if (!ACARD_IS_850(sc)) {
 		u_int32_t reg;
@@ -5097,7 +4944,6 @@
 		bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
 		    IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel, idedma_ctl);
 	}
-	pciide_print_modes(cp);
 
 	if (ACARD_IS_850(sc)) {
 		pci_conf_write(sc->sc_pc, sc->sc_tag,
@@ -5107,6 +4953,8 @@
 		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_IDETIME, idetime);
 		pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_UDMA, udma_mode);
 	}
+
+	pciide_print_modes(cp);
 }
 
 int
@@ -5214,12 +5062,6 @@
 		}
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		if (cp->hw_ok == 0)
-			continue;
-		sl82c105_setup_channel(&cp->wdc_channel);
 	}
 }
 
@@ -5349,12 +5191,6 @@
 			continue;
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    serverworks_pci_intr);
-		if (cp->hw_ok == 0)
-			return;
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		if (cp->hw_ok == 0)
-			return;
-		serverworks_setup_channel(&cp->wdc_channel);
 	}
 
 	pcib_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 0);
@@ -5519,9 +5355,5 @@
 			continue;
 		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
 		    pciide_pci_intr);
-		if (cp->hw_ok == 0)
-			continue;
-		pciide_map_compat_intr(pa, cp, channel, interface);
-		sata_setup_channel(&cp->wdc_channel);
 	}
 }
Index: pcmcia/wdc_pcmcia.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pcmcia/wdc_pcmcia.c,v
retrieving revision 1.55
diff -u -r1.55 wdc_pcmcia.c
--- pcmcia/wdc_pcmcia.c	2003/03/30 02:06:29	1.55
+++ pcmcia/wdc_pcmcia.c	2003/09/18 21:40:52
@@ -80,6 +80,7 @@
 
 static int wdc_pcmcia_match	__P((struct device *, struct cfdata *, void *));
 static void wdc_pcmcia_attach	__P((struct device *, struct device *, void *));
+static void wdc_pcmcia_probedevs __P((struct device *));
 static int wdc_pcmcia_detach	__P((struct device *, int));
 
 CFATTACH_DECL(wdc_pcmcia, sizeof(struct wdc_pcmcia_softc),
@@ -375,9 +376,7 @@
 	sc->sc_wdcdev.sc_atapi_adapter._generic.adapt_enable =
 	    wdc_pcmcia_enable;
 
-	sc->sc_flags |= WDC_PCMCIA_ATTACH;
-	wdcattach(&sc->wdc_channel);	/* should return an error XXX */
-	sc->sc_flags &= ~WDC_PCMCIA_ATTACH;
+	config_defer(self, wdc_pcmcia_probedevs);
 	return;
 
  mapaux_failed:
@@ -402,6 +401,18 @@
 	}
  no_config_entry:
 	sc->sc_iowindow = -1;
+}
+
+void
+wdc_pcmcia_probedevs(self)
+	struct device *self;
+{
+	struct wdc_pcmcia_softc *sc = (void *)self;
+
+	sc->sc_flags |= WDC_PCMCIA_ATTACH;
+	wdcattach(&sc->wdc_channel);	/* should return an error XXX */
+	sc->sc_flags &= ~WDC_PCMCIA_ATTACH;
+	wdc_print_modes(&sc->wdc_channel);
 }
 
 int
Index: podulebus/dtide.c
===================================================================
RCS file: /cvsroot/src/sys/dev/podulebus/dtide.c,v
retrieving revision 1.8
diff -u -r1.8 dtide.c
--- podulebus/dtide.c	2002/10/02 16:52:23	1.8
+++ podulebus/dtide.c	2003/09/18 21:40:52
@@ -59,6 +59,7 @@
 
 static int dtide_match(struct device *, struct cfdata *, void *);
 static void dtide_attach(struct device *, struct device *, void *);
+static void dtide_probedevs(struct device *);
 
 CFATTACH_DECL(dtide, sizeof(struct dtide_softc),
     dtide_match, dtide_attach, NULL, NULL);
@@ -106,6 +107,16 @@
 		bus_space_map(pa->pa_fast_t,
 		    pa->pa_fast_base + dtide_ctloffsets[i], 0, 8,
 		    &sc->sc_chan[i].ctl_ioh);
+	}
+}
+
+static void
+dtide_probedevs(struct device *self)
+{
+	struct dtide_softc *sc = (void *)self;
+
+	for (i = 0; i < DTIDE_NCHANNELS; i++) {
 		wdcattach(&sc->sc_chan[i]);
+		wdc_print_modes(&sc->wdc_channel);
 	}
 }
Index: podulebus/hcide.c
===================================================================
RCS file: /cvsroot/src/sys/dev/podulebus/hcide.c,v
retrieving revision 1.5
diff -u -r1.5 hcide.c
--- podulebus/hcide.c	2002/10/02 16:52:23	1.5
+++ podulebus/hcide.c	2003/09/18 21:40:52
@@ -54,8 +54,9 @@
 	struct channel_queue sc_chq[HCIDE_NCHANNELS];
 };
 
-static void hcide_attach (struct device *, struct device *, void *);
 static int  hcide_match  (struct device *, struct cfdata *, void *);
+static void hcide_attach (struct device *, struct device *, void *);
+static void hcide_probedevs (struct device *);
 
 CFATTACH_DECL(hcide, sizeof(struct hcide_softc),
     hcide_match, hcide_attach, NULL, NULL);
@@ -101,6 +102,16 @@
 		bus_space_map(pa->pa_fast_t,
 		    pa->pa_fast_base + hcide_ctloffsets[i], 0, 8,
 		    &sc->sc_chan[i].ctl_ioh);
+	}
+}
+
+static void
+hcide_probedevs(struct device *self)
+{
+	struct hcide_softc *sc = (void *)self;
+
+	for (i = 0; i < HCIDE_NCHANNELS; i++) {
 		wdcattach(&sc->sc_chan[i]);
+		wdc_print_modes(&sc->wdc_channel);
 	}
 }
Index: scsipi/atapi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapi_base.c,v
retrieving revision 1.18
diff -u -r1.18 atapi_base.c
--- scsipi/atapi_base.c	2001/11/15 09:48:16	1.18
+++ scsipi/atapi_base.c	2003/09/18 21:40:52
@@ -206,44 +206,13 @@
  * long the data is supposed to be. If we have  a buf
  * to associate with the transfer, we need that too.
  */
-int
-atapi_scsipi_cmd(periph, scsipi_cmd, cmdlen, data, datalen,
-    retries, timeout, bp, flags)
-	struct scsipi_periph *periph;
-	struct scsipi_generic *scsipi_cmd;
-	int cmdlen;
-	void *data;
-	size_t datalen;
-	int retries;
-	int timeout;
-	struct buf *bp;
-	int flags;
-{
+void
+atapi_scsipi_cmd(xs)
 	struct scsipi_xfer *xs;
-	int error, s;
+{
+	struct scsipi_periph *periph = xs->xs_periph;
 
 	SC_DEBUG(periph, SCSIPI_DB2, ("atapi_cmd\n"));
 
-#ifdef DIAGNOSTIC
-	if (bp != NULL && (flags & XS_CTL_ASYNC) == 0)
-		panic("atapi_scsipi_cmd: buffer without async");
-#endif
-
-	if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
-	    datalen, retries, timeout, bp, flags)) == NULL) {
-		if (bp != NULL) {
-			s = splbio();
-			bp->b_flags |= B_ERROR;
-			bp->b_error = ENOMEM;
-			biodone(bp);
-			splx(s);
-		}
-		return (ENOMEM);
-	}
-
 	xs->cmdlen = (periph->periph_cap & PERIPH_CAP_CMD16) ? 16 : 12;
-
-	if ((error = scsipi_execute_xs(xs)) == EJUSTRETURN)
-		return (0);
-	return (error);
 }
Index: scsipi/atapi_wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapi_wdc.c,v
retrieving revision 1.56
diff -u -r1.56 atapi_wdc.c
--- scsipi/atapi_wdc.c	2003/09/07 22:11:22	1.56
+++ scsipi/atapi_wdc.c	2003/09/18 21:40:52
@@ -82,7 +82,7 @@
 #endif
 
 #define ATAPI_DELAY 10	/* 10 ms, this is used only before sending a cmd */
-int   wdc_atapi_get_params __P((struct scsipi_channel *, int, int,
+int   wdc_atapi_get_params __P((struct scsipi_channel *, int,
 				struct ataparams *));
 void  wdc_atapi_probe_device __P((struct atapibus_softc *, int));
 void  wdc_atapi_minphys  __P((struct buf *bp));
@@ -185,9 +185,9 @@
 }
 
 int
-wdc_atapi_get_params(chan, drive, flags, id)
+wdc_atapi_get_params(chan, drive, id)
 	struct scsipi_channel *chan;
-	int drive, flags;
+	int drive;
 	struct ataparams *id;
 {
 	struct wdc_softc *wdc = (void *)chan->chan_adapter->adapt_dev;
@@ -204,32 +204,19 @@
 		    drive), DEBUG_PROBE);
 		return -1;
 	}
-	memset(&wdc_c, 0, sizeof(struct wdc_command));
-	wdc_c.r_command = ATAPI_SOFT_RESET;
-	wdc_c.r_st_bmask = 0;
-	wdc_c.r_st_pmask = 0;
-	wdc_c.flags = AT_POLL;
-	wdc_c.timeout = WDC_RESET_WAIT;
-	if (wdc_exec_command(&chp->ch_drive[drive], &wdc_c) != WDC_COMPLETE) {
-		printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for"
-		    " drive %s:%d:%d: driver failed\n",
-		    chp->wdc->sc_dev.dv_xname, chp->channel, drive);
-		panic("wdc_atapi_get_params");
-	}
-	if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+	wdccommandshort(chp, drive, ATAPI_SOFT_RESET);
+	chp->ch_drive[drive].state = 0;
+	if (wait_for_unbusy(chp, WDC_RESET_WAIT) != 0) {
 		WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET "
-		    "failed for drive %s:%d:%d: error 0x%x\n",
-		    chp->wdc->sc_dev.dv_xname, chp->channel, drive, 
-		    wdc_c.r_error), DEBUG_PROBE);
+		    "failed for drive %s:%d:%d\n",
+		    chp->wdc->sc_dev.dv_xname, chp->channel, drive),
+		    DEBUG_PROBE);
 		return -1;
 	}
-	chp->ch_drive[drive].state = 0;
 
-	bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
-	
 	/* Some ATAPI devices need a bit more time after software reset. */
 	delay(5000);
-	if (ata_get_params(&chp->ch_drive[drive], AT_POLL, id) != 0) {
+	if (ata_get_params(&chp->ch_drive[drive], AT_WAIT, id) != 0) {
 		WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_IDENTIFY_DEVICE "
 		    "failed for drive %s:%d:%d: error 0x%x\n",
 		    chp->wdc->sc_dev.dv_xname, chp->channel, drive, 
@@ -258,8 +245,7 @@
 	if (scsipi_lookup_periph(chan, target, 0) != NULL)
 		return;
 
-	if (wdc_atapi_get_params(chan, target,
-	    XS_CTL_POLL|XS_CTL_NOSLEEP, id) == 0) {
+	if (wdc_atapi_get_params(chan, target, id) == 0) {
 #ifdef ATAPI_DEBUG_PROBE
 		printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
 		    sc->sc_dev.dv_xname, target,
@@ -567,7 +553,7 @@
 
 	switch (phase) {
 	case PHASE_CMDOUT:
-		cmd  = sc_xfer->cmd;
+		cmd = sc_xfer->cmd;
 		WDCDEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);
 		/* Init the DMA channel if necessary */
 		if (xfer->c_flags & C_DMA) {
@@ -581,29 +567,23 @@
 		/* send packet command */
 		/* Commands are 12 or 16 bytes long. It's 32-bit aligned */
 		if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {
-			if (drvp->drive_flags & DRIVE_CAP32) {
+			if (drvp->drive_flags & DRIVE_CAP32)
 				bus_space_write_multi_4(chp->data32iot,
-				    chp->data32ioh, 0,
-				    (u_int32_t *)cmd,
+				    chp->data32ioh, 0, (u_int32_t *)cmd,
 				    sc_xfer->cmdlen >> 2);
-			} else {
+			else
 				bus_space_write_multi_2(chp->cmd_iot,
-				    chp->cmd_ioh, wd_data,
-				    (u_int16_t *)cmd,
+				    chp->cmd_ioh, wd_data, (u_int16_t *)cmd,
 				    sc_xfer->cmdlen >> 1);
-			}
 		} else {
-			if (drvp->drive_flags & DRIVE_CAP32) {
+			if (drvp->drive_flags & DRIVE_CAP32)
 				bus_space_write_multi_stream_4(chp->data32iot,
-				    chp->data32ioh, 0,
-				    (u_int32_t *)cmd,
+				    chp->data32ioh, 0, (u_int32_t *)cmd,
 				    sc_xfer->cmdlen >> 2);
-			} else {
+			else
 				bus_space_write_multi_stream_2(chp->cmd_iot,
-				    chp->cmd_ioh, wd_data,
-				    (u_int16_t *)cmd,
+				    chp->cmd_ioh, wd_data, (u_int16_t *)cmd,
 				    sc_xfer->cmdlen >> 1);
-			}
 		}
 		/* Start the DMA channel if necessary */
 		if (xfer->c_flags & C_DMA) {
@@ -932,33 +912,23 @@
 		WDCDEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) "
 		    "polldsc %d\n", chp->wdc->sc_dev.dv_xname, chp->channel,
 		    xfer->drive, xfer->c_dscpoll), DEBUG_XFERS);
-		if (cold) {
-			if (wdcwait(chp, WDCS_DSC, WDCS_DSC,
-			    sc_xfer->timeout)) {
+#if 1
+		if (cold)
+			panic("wdc_atapi_phase_complete: cold");
+#endif
+		if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10)) {
+			/* 10ms not enough, try again in 1 tick */
+			if (xfer->c_dscpoll++ > 
+			    mstohz(sc_xfer->timeout)) {
 				printf("%s:%d:%d: wait_for_dsc failed\n",
 				    chp->wdc->sc_dev.dv_xname, chp->channel,
 				    xfer->drive);
 				sc_xfer->error = XS_TIMEOUT;
 				wdc_atapi_reset(chp, xfer);
-				return;
-			}
-		} else {
-			if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10)) {
-				/* 10ms not enough, try again in 1 tick */
-				if (xfer->c_dscpoll++ > 
-				    mstohz(sc_xfer->timeout)) {
-					printf("%s:%d:%d: wait_for_dsc "
-					    "failed\n",
-					    chp->wdc->sc_dev.dv_xname,
-					    chp->channel, xfer->drive);
-					sc_xfer->error = XS_TIMEOUT;
-					wdc_atapi_reset(chp, xfer);
-					return;
-				}
+			} else
 				callout_reset(&chp->ch_callout, 1,
 				    wdc_atapi_polldsc, xfer);
-				return;
-			}
+			return;
 		}
 	}
 
Index: scsipi/atapiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapiconf.h,v
retrieving revision 1.14
diff -u -r1.14 atapiconf.h
--- scsipi/atapiconf.h	2001/12/03 00:20:24	1.14
+++ scsipi/atapiconf.h	2003/09/18 21:40:52
@@ -54,6 +54,5 @@
 int	atapiprint __P((void *, const char *));
 void	atapi_print_addr __P((struct scsipi_periph *));
 int	atapi_interpret_sense __P((struct scsipi_xfer *));
-int	atapi_scsipi_cmd __P((struct scsipi_periph *, struct scsipi_generic *,
-	    int, void *, size_t, int, int, struct buf *, int));
+void	atapi_scsipi_cmd __P((struct scsipi_xfer *));
 void	atapi_kill_pending __P((struct scsipi_periph *));
Index: scsipi/cd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/cd.c,v
retrieving revision 1.197
diff -u -r1.197 cd.c
--- scsipi/cd.c	2003/09/18 00:06:32	1.197
+++ scsipi/cd.c	2003/09/18 21:40:54
@@ -88,6 +88,7 @@
 					/* from there */
 #include <dev/scsipi/scsi_disk.h>	/* rw comes from there */
 #include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/cdvar.h>
 
 #define	CDUNIT(z)			DISKUNIT(z)
@@ -112,7 +113,7 @@
 void	cdminphys __P((struct buf *));
 void	cdgetdefaultlabel __P((struct cd_softc *, struct disklabel *));
 void	cdgetdisklabel __P((struct cd_softc *));
-void	cddone __P((struct scsipi_xfer *));
+void	cddone __P((struct scsipi_xfer *, int));
 void	cdbounce __P((struct buf *));
 int	cd_interpret_sense __P((struct scsipi_xfer *));
 u_long	cd_size __P((struct cd_softc *, int));
@@ -863,7 +864,7 @@
 		/*
 		 * Figure out what flags to use.
 		 */
-		flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
+		flags = XS_CTL_ASYNC | XS_CTL_SIMPLE_TAG;
 		if (bp->b_flags & B_READ)
 			flags |= XS_CTL_DATA_IN;
 		else
@@ -877,6 +878,9 @@
 		    (u_char *)bp->b_data, bp->b_bcount,
 		    CDRETRIES, 30000, bp, flags);
 		if (error) {
+			bp->b_error = error;
+			bp->b_flags |= B_ERROR;
+			biodone(bp);
 			disk_unbusy(&cd->sc_dk, 0, 0);
 			printf("%s: not queued, error %d\n",
 			    cd->sc_dev.dv_xname, error);
@@ -885,17 +889,26 @@
 }
 
 void
-cddone(xs)
+cddone(xs, error)
 	struct scsipi_xfer *xs;
+	int error;
 {
 	struct cd_softc *cd = (void *)xs->xs_periph->periph_dev;
+	struct buf *bp = xs->bp;
 
-	if (xs->bp != NULL) {
-		disk_unbusy(&cd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid,
-		    (xs->bp->b_flags & B_READ));
+	if (bp) {
+		bp->b_error = error;
+		bp->b_resid = xs->resid;
+		if (error)
+			bp->b_flags |= B_ERROR;
+		
+		disk_unbusy(&cd->sc_dk, bp->b_bcount - bp->b_resid,
+		    (bp->b_flags & B_READ));
 #if NRND > 0
-		rnd_add_uint32(&cd->rnd_source, xs->bp->b_rawblkno);
+		rnd_add_uint32(&cd->rnd_source, bp->b_rawblkno);
 #endif
+
+		biodone(bp);
 	}
 }
 
Index: scsipi/ch.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ch.c,v
retrieving revision 1.58
diff -u -r1.58 ch.c
--- scsipi/ch.c	2003/09/08 01:27:08	1.58
+++ scsipi/ch.c	2003/09/18 21:40:54
@@ -62,6 +62,7 @@
 #include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_changer.h>
 #include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 
 #define CHRETRIES	2
 #define CHUNIT(x)	(minor((x)))
Index: scsipi/if_se.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/if_se.c,v
retrieving revision 1.45
diff -u -r1.45 if_se.c
--- scsipi/if_se.c	2003/09/08 01:27:09	1.45
+++ scsipi/if_se.c	2003/09/18 21:40:54
@@ -485,7 +485,7 @@
 	error = se_scsipi_cmd(sc->sc_periph,
 	    (struct scsipi_generic *)&send_cmd, sizeof(send_cmd),
 	    sc->sc_tbuf, len, SERETRIES,
-	    SETIMEOUT, NULL, XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_OUT);
+	    SETIMEOUT, NULL, XS_CTL_ASYNC | XS_CTL_DATA_OUT);
 	if (error) {
 		printf("%s: not queued, error %d\n",
 		    sc->sc_dev.dv_xname, error);
@@ -584,7 +584,7 @@
 	error = se_scsipi_cmd(sc->sc_periph,
 	    (struct scsipi_generic *)&recv_cmd, sizeof(recv_cmd),
 	    sc->sc_rbuf, RBUF_LEN, SERETRIES, SETIMEOUT, NULL,
-	    XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_DATA_IN);
+	    XS_CTL_ASYNC | XS_CTL_DATA_IN);
 	if (error)
 		callout_reset(&sc->sc_recv_ch, se_poll, se_recv, (void *)sc);
 }
Index: scsipi/scsi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsi_base.c,v
retrieving revision 1.77
diff -u -r1.77 scsi_base.c
--- scsipi/scsi_base.c	2001/11/15 09:48:16	1.77
+++ scsipi/scsi_base.c	2003/09/18 21:40:54
@@ -1,7 +1,7 @@
 /*	$NetBSD: scsi_base.c,v 1.77 2001/11/15 09:48:16 lukem Exp $	*/
 
 /*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -63,15 +63,21 @@
 	struct scsipi_periph *periph;
 	int flags;
 {
-	struct scsi_changedef scsipi_cmd;
+	struct scsi_changedef cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = 100000,
+	};
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = SCSI_CHANGE_DEFINITION;
+	cmd.how = SC_SCSI_2;
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = SCSI_CHANGE_DEFINITION;
-	scsipi_cmd.how = SC_SCSI_2;
-
-	return (scsipi_command(periph,
-	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
-	    0, 0, SCSIPIRETRIES, 100000, NULL, flags));
+	return (scsipi_execute_xs(&xs));
 }
 
 /*
@@ -80,41 +86,14 @@
  * long the data is supposed to be. If we have  a buf
  * to associate with the transfer, we need that too.
  */
-int
-scsi_scsipi_cmd(periph, scsipi_cmd, cmdlen, data, datalen,
-	retries, timeout, bp, flags)
-	struct scsipi_periph *periph;
-	struct scsipi_generic *scsipi_cmd;
-	int cmdlen;
-	void *data;
-	size_t datalen;
-	int retries;
-	int timeout;
-	struct buf *bp;
-	int flags;
-{
+void
+scsi_scsipi_cmd(xs)
 	struct scsipi_xfer *xs;
-	int error, s;
+{
+	struct scsipi_periph *periph = xs->xs_periph;
 
 	SC_DEBUG(periph, SCSIPI_DB2, ("scsi_scsipi_cmd\n"));
 
-#ifdef DIAGNOSTIC
-	if (bp != NULL && (flags & XS_CTL_ASYNC) == 0)
-		panic("scsi_scsipi_cmd: buffer without async");
-#endif
-
-	if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
-	    datalen, retries, timeout, bp, flags)) == NULL) {
-		if (bp != NULL) {
-			s = splbio();
-			bp->b_flags |= B_ERROR;
-			bp->b_error = ENOMEM;
-			biodone(bp);
-			splx(s);
-		}
-		return (ENOMEM);
-	}
-
 	/*
 	 * Set the LUN in the CDB if we have an older device.  We also
 	 * set it for more modern SCSI-2 devices "just in case".
@@ -123,10 +102,6 @@
 		xs->cmd->bytes[0] |=
 		    ((periph->periph_lun << SCSI_CMD_LUN_SHIFT) &
 			SCSI_CMD_LUN_MASK);
-
-	if ((error = scsipi_execute_xs(xs)) == EJUSTRETURN)
-		return (0);
-	return (error);
 }
 
 /*
Index: scsipi/scsiconf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsiconf.c,v
retrieving revision 1.217
diff -u -r1.217 scsiconf.c
--- scsipi/scsiconf.c	2003/09/18 05:06:53	1.217
+++ scsipi/scsiconf.c	2003/09/18 21:40:55
@@ -426,104 +426,36 @@
 }
 
 const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
-	{{T_CDROM, T_REMOV,
-	 "CHINON  ", "CD-ROM CDS-431  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "CHINON  ", "CD-ROM CDS-435  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "Chinon  ", "CD-ROM CDS-525  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "CHINON  ", "CD-ROM CDS-535  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "DEC     ", "RRD42   (C) DEC ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "DENON   ", "DRD-25X         ", "V"},    PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "GENERIC ", "CRD-BP2         ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "HP      ", "C4324/C4325     ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "IMS     ", "CDD521/10       ", "2.06"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "MATSHITA", "CD-ROM CR-5XX   ", "1.0b"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "MEDAVIS ", "RENO CD-ROMX2A  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "MEDIAVIS", "CDR-H93MV       ", "1.3"},  PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:502", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:55 ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:83 ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:84 ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:841", ""},     PQUIRK_NOLUNS},
         {{T_CDROM, T_REMOV,
-	 "OLYMPUS ", "CDS620E         ", "1.1d"}, 
-			       PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOCAPACITY},
-	{{T_CDROM, T_REMOV,
-	 "PIONEER ", "CD-ROM DR-124X  ", "1.01"}, PQUIRK_NOLUNS},
+	 "OLYMPUS ", "CDS620E         ", "1.1d"}, PQUIRK_NOSYNC|PQUIRK_NOCAPACITY},
         {{T_CDROM, T_REMOV,
-         "PLEXTOR ", "CD-ROM PX-4XCS  ", "1.01"},
-                               PQUIRK_NOLUNS|PQUIRK_NOSYNC},
-	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-541  ", ""},     PQUIRK_NOLUNS},
+         "PLEXTOR ", "CD-ROM PX-4XCS  ", "1.01"}, PQUIRK_NOSYNC},
 	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-55S  ", ""},     PQUIRK_NOLUNS},
+	 "SONY    ", "CD-ROM CDU-76S", ""},       PQUIRK_NOSYNC|PQUIRK_NOWIDE},
 	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-561  ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-76S", ""},
-				PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOWIDE},
-	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-8003A", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "SONY    ", "CD-ROM CDU-8012 ", ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TEAC    ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TEAC    ", "CD-ROM CD-56S   ", "1.0B"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TEXEL   ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TEXEL   ", "CD-ROM DM-XX24 K", "1.09"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TEXEL   ", "CD-ROM DM-XX24 K", "1.10"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "TOSHIBA ", "XM-4101TASUNSLCD", ""}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
+	 "TOSHIBA ", "XM-4101TASUNSLCD", ""},     PQUIRK_NOSYNC},
 	/* "IBM CDRM00201     !F" 0724 is an IBM OEM Toshiba XM-4101BME */
 	{{T_CDROM, T_REMOV,
-	 "IBM     ", "CDRM00201     !F", "0724"}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
+	 "IBM     ", "CDRM00201     !F", "0724"}, PQUIRK_NOSYNC},
 	{{T_CDROM, T_REMOV,
-	 "ShinaKen", "CD-ROM DM-3x1S",   "1.04"}, PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "JVC     ", "R2626",            ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "YAMAHA", "CRW8424S",           ""},     PQUIRK_NOLUNS},
-	{{T_CDROM, T_REMOV,
-	 "NEC     ", "CD-ROM DRIVE:222", ""},	  PQUIRK_NOLUNS|PQUIRK_NOSYNC},
+	 "NEC     ", "CD-ROM DRIVE:222", ""},	  PQUIRK_NOSYNC},
 
 	{{T_DIRECT, T_FIXED,
 	 "MICROP  ", "1588-15MBSUN0669", ""},     PQUIRK_AUTOSAVE},
 	{{T_DIRECT, T_FIXED,
 	 "MICROP  ", "2217-15MQ1091501", ""},     PQUIRK_NOSYNCCACHE},
-	{{T_OPTICAL, T_REMOV,
-	 "EPSON   ", "OMD-5010        ", "3.08"}, PQUIRK_NOLUNS},
 	{{T_DIRECT, T_FIXED,
-	 "TOSHIBA ","CD-ROM XM-3401TA",  "0283"}, PQUIRK_CDROM|PQUIRK_NOLUNS},
+	 "TOSHIBA ","CD-ROM XM-3401TA",  "0283"}, PQUIRK_CDROM},
 	{{T_DIRECT, T_FIXED,
-	 "TOSHIBA ", "CD-ROM DRIVE:XM",  "1971"}, PQUIRK_CDROM|PQUIRK_NOLUNS},
+	 "TOSHIBA ", "CD-ROM DRIVE:XM",  "1971"}, PQUIRK_CDROM},
 	{{T_DIRECT, T_FIXED,
 	 "ADAPTEC ", "AEC-4412BD",       "1.2A"}, PQUIRK_NOMODESENSE},
 	{{T_DIRECT, T_FIXED,
-	 "ADAPTEC ", "ACB-4000",         ""},     PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE|PQUIRK_NOMODESENSE},
+	 "ADAPTEC ", "ACB-4000",         ""},     PQUIRK_AUTOSAVE|PQUIRK_NOMODESENSE},
 	{{T_DIRECT, T_FIXED,
 	 "DEC     ", "RZ55     (C) DEC", ""},     PQUIRK_AUTOSAVE},
 	{{T_DIRECT, T_FIXED,
-	 "EMULEX  ", "MD21/S2     ESDI", "A00"},
-				PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE},
+	 "EMULEX  ", "MD21/S2     ESDI", "A00"},  PQUIRK_AUTOSAVE},
 	{{T_DIRECT, T_FIXED,
 	/* improperly report DT-only sync mode */
 	 "HITACHI", "DX32DJ-72ME",	 ""},
@@ -546,64 +478,21 @@
 	 "IBM     ", "DXHS18Y",		 ""},
 				PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
 	{{T_DIRECT, T_FIXED,
-	 "IBM     ", "H3171-S2",	 ""},
-				PQUIRK_NOLUNS|PQUIRK_AUTOSAVE},
+	 "IBM     ", "H3171-S2",	 ""},     PQUIRK_AUTOSAVE},
 	{{T_DIRECT, T_FIXED,
 	 "IBM     ", "KZ-C",		 ""},	  PQUIRK_AUTOSAVE},
 	/* Broken IBM disk */
 	{{T_DIRECT, T_FIXED,
 	 ""	   , "DFRSS2F",		 ""},	  PQUIRK_AUTOSAVE},
-	{{T_DIRECT, T_REMOV,
-	 "MPL     ", "MC-DISK-        ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "XT-3280         ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "XT-4380S        ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "MXT-1240S       ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "XT-4170S        ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "XT-8760S",         ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "LXT-213S        ", ""},     PQUIRK_NOLUNS},
 	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "LXT-213S SUN0207", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "MAXTOR  ", "LXT-200S        ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
 	 "MEGADRV ", "EV1000",           ""},     PQUIRK_NOMODESENSE},
 	{{T_DIRECT, T_FIXED,
 	 "MICROP", "1991-27MZ",          ""},     PQUIRK_NOTAG},
 	{{T_DIRECT, T_FIXED,
-	 "MST     ", "SnapLink        ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "NEC     ", "D3847           ", "0307"}, PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
 	 "QUANTUM ", "ELS85S          ", ""},     PQUIRK_AUTOSAVE},
 	{{T_DIRECT, T_FIXED,
-	 "QUANTUM ", "LPS525S         ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "QUANTUM ", "P105S 910-10-94x", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "QUANTUM ", "PD1225S         ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "QUANTUM ", "PD210S   SUN0207", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
 	 "QUANTUM ", "ATLAS IV 9 WLS", "0A0A"},   PQUIRK_CAP_NODT},
 	{{T_DIRECT, T_FIXED,
-	 "RODIME  ", "RO3000S         ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "SEAGATE ", "ST125N          ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "SEAGATE ", "ST157N          ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "SEAGATE ", "ST296           ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "SEAGATE ", "ST296N          ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
-	 "SEAGATE ", "ST318404LC      ", ""},     PQUIRK_NOLUNS},
-	{{T_DIRECT, T_FIXED,
 	 "SEAGATE ", "ST15150N        ", ""},     PQUIRK_NOTAG},
 	{{T_DIRECT, T_FIXED,
 	 "SEAGATE ", "ST19171",          ""},     PQUIRK_NOMODESENSE},
@@ -611,80 +500,19 @@
 	 "SEAGATE ", "ST32430N",         ""},     PQUIRK_CAP_SYNC},
 	{{T_DIRECT, T_FIXED,
 	 "SEAGATE ", "ST34501FC       ", ""},     PQUIRK_NOMODESENSE},
-	{{T_DIRECT, T_FIXED,
-	 "TOSHIBA ", "MK538FB         ", "6027"}, PQUIRK_NOLUNS},
 	{{T_DIRECT, T_FIXED,
-	 "MICROP  ", "1924",          ""},     PQUIRK_CAP_SYNC},
+	 "MICROP  ", "1924",          ""},        PQUIRK_CAP_SYNC},
 	{{T_DIRECT, T_FIXED,
-	 "FUJITSU ", "M2266",         ""},     PQUIRK_CAP_SYNC},
+	 "FUJITSU ", "M2266",         ""},        PQUIRK_CAP_SYNC},
 
-	{{T_DIRECT, T_REMOV,
-	 "IOMEGA", "ZIP 100",		 "J.03"}, PQUIRK_NOLUNS},
-	{{T_DIRECT, T_REMOV,
-	 "INSITE", "I325VM",             ""},     PQUIRK_NOLUNS},
-
-	/* XXX: QIC-36 tape behind Emulex adapter.  Very broken. */
-	{{T_SEQUENTIAL, T_REMOV,
-	 "        ", "                ", "    "}, PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "EMULEX  ", "MT-02 QIC       ", ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "CALIPER ", "CP150           ", ""},     PQUIRK_NOLUNS},
 	{{T_SEQUENTIAL, T_REMOV,
-	 "EXABYTE ", "EXB-8200        ", ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "SONY    ", "GY-10C          ", ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "SONY    ", "SDT-2000        ", "2.09"}, PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
 	 "SONY    ", "SDT-5000        ", "3."},   PQUIRK_NOSYNC|PQUIRK_NOWIDE},
 	{{T_SEQUENTIAL, T_REMOV,
-	 "SONY    ", "SDT-5200        ", "3."},   PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "TANDBERG", " TDC 3600       ", ""},     PQUIRK_NOLUNS},
-	/* Following entry reported as a Tandberg 3600; ref. PR1933 */
-	{{T_SEQUENTIAL, T_REMOV,
-	 "ARCHIVE ", "VIPER 150  21247", ""},     PQUIRK_NOLUNS},
-	/* Following entry for a Cipher ST150S; ref. PR4171 */
-	{{T_SEQUENTIAL, T_REMOV,
-	 "ARCHIVE ", "VIPER 1500 21247", "2.2G"}, PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "ARCHIVE ", "Python 28454-XXX", ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "WANGTEK ", "5099ES SCSI",      ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "WANGTEK ", "5150ES SCSI",      ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "WANGTEK ", "SCSI-36",		 ""},     PQUIRK_NOLUNS},
-	{{T_SEQUENTIAL, T_REMOV,
 	 "WangDAT ", "Model 1300      ", "02.4"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
 	{{T_SEQUENTIAL, T_REMOV,
 	 "WangDAT ", "Model 2600      ", "01.7"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
 	{{T_SEQUENTIAL, T_REMOV,
 	 "WangDAT ", "Model 3200      ", "02.2"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
-	{{T_SEQUENTIAL, T_REMOV,
-	 "TEAC    ", "MT-2ST/N50      ", ""},     PQUIRK_NOLUNS},
-
-	{{T_SCANNER, T_FIXED,
-	 "RICOH   ", "IS60            ", "1R08"}, PQUIRK_NOLUNS},
-	{{T_SCANNER, T_FIXED,
-	 "UMAX    ", "Astra 1200S     ", "V2.9"}, PQUIRK_NOLUNS},
-	{{T_SCANNER, T_FIXED,
-	 "UMAX    ", "Astra 1220S     ", ""},     PQUIRK_NOLUNS},
-	{{T_SCANNER, T_FIXED,
-	 "UMAX    ", "UMAX S-6E       ", "V2.0"}, PQUIRK_NOLUNS},
-	{{T_SCANNER, T_FIXED,
-	 "UMAX    ", "UMAX S-12       ", "V2.1"}, PQUIRK_NOLUNS},
-	{{T_SCANNER, T_FIXED,
-	 "ULTIMA  ", "A6000C          ", ""},     PQUIRK_NOLUNS},
-	{{T_PROCESSOR, T_FIXED,
-	 "SYMBIOS",  "",                 ""},     PQUIRK_NOLUNS},
-	{{T_PROCESSOR, T_FIXED,
-	 "LITRONIC", "PCMCIA          ", ""},     PQUIRK_NOLUNS},
-	{{T_CHANGER, T_REMOV,
-	 "SONY    ", "CDL1100         ", ""},     PQUIRK_NOLUNS},
-	{{T_ENCLOSURE, T_FIXED,
-	 "SUN     ", "SENA            ", ""},     PQUIRK_NOLUNS},
 };
 
 /*
@@ -701,21 +529,13 @@
 	struct scsipi_periph *periph;
 	struct scsipi_inquiry_data inqbuf;
 	struct scsi_quirk_inquiry_pattern *finger;
-	int checkdtype, priority, docontinue, quirks;
+	int checkdtype, priority, quirks;
 	struct scsipibus_attach_args sa;
 	struct cfdata *cf;
 
-	/*
-	 * Assume no more luns to search after this one.
-	 * If we successfully get Inquiry data and after
-	 * merging quirks we find we can probe for more
-	 * luns, we will.
-	 */
-	docontinue = 0;
-
 	/* Skip this slot if it is already attached. */
 	if (scsipi_lookup_periph(chan, target, lun) != NULL)
-		return (docontinue);
+		return (1);
 
 	periph = scsipi_alloc_periph(M_NOWAIT);
 	if (periph == NULL) {
@@ -909,10 +729,6 @@
 	 * Now apply any quirks from the table.
 	 */
 	periph->periph_quirks |= quirks;
-	if (periph->periph_version == 0 &&
-	    (periph->periph_quirks & PQUIRK_FORCELUNS) == 0)
-		periph->periph_quirks |= PQUIRK_NOLUNS;
-
 	if (periph->periph_quirks & PQUIRK_CDROM) {
 		periph->periph_quirks ^= PQUIRK_CDROM;
 		inqbuf.dev_qual2 |= SID_REMOVABLE;
@@ -921,9 +737,6 @@
 		sa.sa_inqbuf.removable = T_REMOV;
 	}
 
-	if ((periph->periph_quirks & PQUIRK_NOLUNS) == 0)
-		docontinue = 1;
-
 	if ((cf = config_search(scsibussubmatch, &sc->sc_dev, &sa)) != NULL) {
 		scsipi_insert_periph(chan, periph);
 		/*
@@ -938,11 +751,11 @@
 		goto bad;
 	}
 
-	return (docontinue);
+	return (1);
 
 bad:
 	free(periph, M_DEVBUF);
-	return (docontinue);
+	return (1);
 }
 
 /****** Entry points for user control of the SCSI bus. ******/
Index: scsipi/scsiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsiconf.h,v
retrieving revision 1.50
diff -u -r1.50 scsiconf.h
--- scsipi/scsiconf.h	2003/01/06 21:02:18	1.50
+++ scsipi/scsiconf.h	2003/09/18 21:40:55
@@ -76,7 +76,6 @@
 void	scsi_kill_pending __P((struct scsipi_periph *));
 void	scsi_print_addr __P((struct scsipi_periph *));
 int	scsi_probe_bus __P((struct scsibus_softc *, int, int));
-int	scsi_scsipi_cmd __P((struct scsipi_periph *, struct scsipi_generic *,
-	    int, void *, size_t, int, int, struct buf *, int));
+void	scsi_scsipi_cmd __P((struct scsipi_xfer *));
 
 #endif /* _DEV_SCSIPI_SCSICONF_H_ */
Index: scsipi/scsipi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_base.c,v
retrieving revision 1.93
diff -u -r1.93 scsipi_base.c
--- scsipi/scsipi_base.c	2003/09/09 02:37:55	1.93
+++ scsipi/scsipi_base.c	2003/09/18 21:40:55
@@ -55,6 +55,8 @@
 #include <sys/kthread.h>
 #include <sys/hash.h>
 
+#include <uvm/uvm_extern.h>
+
 #include <dev/scsipi/scsipi_all.h>
 #include <dev/scsipi/scsipi_disk.h>
 #include <dev/scsipi/scsipiconf.h>
@@ -65,7 +67,7 @@
 
 int	scsipi_complete __P((struct scsipi_xfer *));
 void	scsipi_request_sense __P((struct scsipi_xfer *));
-int	scsipi_enqueue __P((struct scsipi_xfer *));
+void	scsipi_enqueue __P((struct scsipi_xfer *));
 void	scsipi_run_queue __P((struct scsipi_channel *chan));
 
 void	scsipi_completion_thread __P((void *));
@@ -395,11 +397,10 @@
 
 	SC_DEBUG(periph, SCSIPI_DB3, ("scsipi_get_xs\n"));
 
-	/*
-	 * If we're cold, make sure we poll.
-	 */
+#if 1
 	if (cold)
-		flags |= XS_CTL_NOSLEEP | XS_CTL_POLL;
+		panic("scsipi_get_xs: cold");
+#endif
 
 #ifdef DIAGNOSTIC
 	/*
@@ -484,9 +485,6 @@
 		xs->xs_periph = periph;
 		xs->xs_control = flags;
 		xs->xs_status = 0;
-		s = splbio();
-		TAILQ_INSERT_TAIL(&periph->periph_xferq, xs, device_q);
-		splx(s);
 	}
 	return (xs);
 }
@@ -510,7 +508,6 @@
 
 	SC_DEBUG(periph, SCSIPI_DB3, ("scsipi_free_xs\n"));
 
-	TAILQ_REMOVE(&periph->periph_xferq, xs, device_q);
 	pool_put(&scsipi_xfer_pool, xs);
 
 #ifdef DIAGNOSTIC
@@ -1008,23 +1005,30 @@
 	struct scsipi_periph *periph;
 	int flags;
 {
-	struct scsipi_read_cap_data rdcap;
-	struct scsipi_read_capacity scsipi_cmd;
+	struct scsipi_read_capacity cmd;
+	struct scsipi_read_cap_data data;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)&data,
+		.datalen = sizeof(data),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = 20000,
+	};
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = READ_CAPACITY;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = READ_CAPACITY;
 
 	/*
 	 * If the command works, interpret the result as a 4 byte
 	 * number of blocks
 	 */
-	if (scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
-	    sizeof(scsipi_cmd), (u_char *)&rdcap, sizeof(rdcap),
-	    SCSIPIRETRIES, 20000, NULL,
-	    flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
+	if (scsipi_execute_xs(&xs) != 0)
 		return (0);
 
-	return (_4btol(rdcap.addr) + 1);
+	return (_4btol(data.addr) + 1);
 }
 
 /*
@@ -1037,24 +1041,24 @@
 	struct scsipi_periph *periph;
 	int flags;
 {
-	int retries;
-	struct scsipi_test_unit_ready scsipi_cmd;
+	struct scsipi_test_unit_ready cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = 10000,
+	};
 
 	/* some ATAPI drives don't support TEST_UNIT_READY. Sigh */
 	if (periph->periph_quirks & PQUIRK_NOTUR)
 		return (0);
-
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = TEST_UNIT_READY;
 
-	if (flags & XS_CTL_DISCOVERY)
-		retries = 0;
-	else
-		retries = SCSIPIRETRIES;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = TEST_UNIT_READY;
 
-	return (scsipi_command(periph,
-	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
-	    0, 0, retries, 10000, NULL, flags));
+	return (scsipi_execute_xs(&xs));
 }
 
 /*
@@ -1068,23 +1072,24 @@
 	struct scsipi_inquiry_data *inqbuf;
 	int flags;
 {
-	int retries;
-	struct scsipi_inquiry scsipi_cmd;
+	struct scsipi_inquiry cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_IN | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)inqbuf,
+		.datalen = sizeof(struct scsipi_inquiry_data),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = 10000,
+	};
 	int error;
-
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = INQUIRY;
-	scsipi_cmd.length = sizeof(struct scsipi_inquiry_data);
 
-	if (flags & XS_CTL_DISCOVERY)
-		retries = 0;
-	else
-		retries = SCSIPIRETRIES;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = INQUIRY;
+	cmd.length = sizeof(struct scsipi_inquiry_data);
 
-	error = scsipi_command(periph,
-	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
-	    (u_char *) inqbuf, sizeof(struct scsipi_inquiry_data),
-	    retries, 10000, NULL, XS_CTL_DATA_IN | flags);
+	error = scsipi_execute_xs(&xs);
 	
 #ifdef SCSI_OLD_NOINQUIRY
 	/*
@@ -1115,10 +1120,10 @@
 	 * This board gives an empty response to an INQUIRY command.
 	 */
 	else if (error == 0 && 
-		 inqbuf->device == (SID_QUAL_LU_PRESENT | T_DIRECT) &&
-		 inqbuf->dev_qual2 == 0 &&
-		 inqbuf->version == 0 &&
-		 inqbuf->response_format == SID_FORMAT_SCSI1) {
+	    inqbuf->device == (SID_QUAL_LU_PRESENT | T_DIRECT) &&
+	    inqbuf->dev_qual2 == 0 &&
+	    inqbuf->version == 0 &&
+	    inqbuf->response_format == SID_FORMAT_SCSI1) {
 		/*
 		 * Fill out the INQUIRY response.
 		 */
@@ -1146,15 +1151,21 @@
 	struct scsipi_periph *periph;
 	int type, flags;
 {
-	struct scsipi_prevent scsipi_cmd;
+	struct scsipi_prevent cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = 5000,
+	};
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = PREVENT_ALLOW;
+	cmd.how = type;
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = PREVENT_ALLOW;
-	scsipi_cmd.how = type;
-
-	return (scsipi_command(periph,
-	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
-	    0, 0, SCSIPIRETRIES, 5000, NULL, flags));
+	return (scsipi_execute_xs(&xs));
 }
 
 /*
@@ -1167,17 +1178,22 @@
 	struct scsipi_periph *periph;
 	int type, flags;
 {
-	struct scsipi_start_stop scsipi_cmd;
+	struct scsipi_start_stop cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.xs_retries = SCSIPIRETRIES,
+		.timeout = (type & SSS_START) ? 60000 : 10000,
+	};
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = START_STOP;
+	cmd.byte2 = 0x00;
+	cmd.how = type;
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = START_STOP;
-	scsipi_cmd.byte2 = 0x00;
-	scsipi_cmd.how = type;
-
-	return (scsipi_command(periph,
-	    (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
-	    0, 0, SCSIPIRETRIES, (type & SSS_START) ? 60000 : 10000,
-	    NULL, flags));
+	return (scsipi_execute_xs(&xs));
 }
 
 /*
@@ -1191,20 +1207,25 @@
 	int byte2, page, len, flags, retries, timeout;
 	struct scsipi_mode_header *data;
 {
-	struct scsipi_mode_sense scsipi_cmd;
-	int error;
+	struct scsipi_mode_sense cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_IN | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)data,
+		.datalen = len,
+		.xs_retries = retries,
+		.timeout = timeout,
+	};
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = MODE_SENSE;
-	scsipi_cmd.byte2 = byte2;
-	scsipi_cmd.page = page;
-	scsipi_cmd.length = len & 0xff;
-	error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
-	    sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
-	    flags | XS_CTL_DATA_IN);
-	SC_DEBUG(periph, SCSIPI_DB2,
-	    ("scsipi_mode_sense: error=%d\n", error));
-	return (error);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = MODE_SENSE;
+	cmd.byte2 = byte2;
+	cmd.page = page;
+	cmd.length = len & 0xff;
+
+	return (scsipi_execute_xs(&xs));
 }
 
 int
@@ -1213,20 +1234,25 @@
 	int byte2, page, len, flags, retries, timeout;
 	struct scsipi_mode_header_big *data;
 {
-	struct scsipi_mode_sense_big scsipi_cmd;
-	int error;
+	struct scsipi_mode_sense_big cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_IN | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)data,
+		.datalen = len,
+		.xs_retries = retries,
+		.timeout = timeout,
+	};
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = MODE_SENSE_BIG;
-	scsipi_cmd.byte2 = byte2;
-	scsipi_cmd.page = page;
-	_lto2b(len, scsipi_cmd.length);
-	error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
-	    sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
-	    flags | XS_CTL_DATA_IN);
-	SC_DEBUG(periph, SCSIPI_DB2,
-	    ("scsipi_mode_sense_big: error=%d\n", error));
-	return (error);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = MODE_SENSE_BIG;
+	cmd.byte2 = byte2;
+	cmd.page = page;
+	_lto2b(len, cmd.length);
+
+	return (scsipi_execute_xs(&xs));
 }
 
 int
@@ -1235,19 +1261,24 @@
 	int byte2, len, flags, retries, timeout;
 	struct scsipi_mode_header *data;
 {
-	struct scsipi_mode_select scsipi_cmd;
-	int error;
+	struct scsipi_mode_select cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_OUT | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)data,
+		.datalen = len,
+		.xs_retries = retries,
+		.timeout = timeout,
+	};
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = MODE_SELECT;
-	scsipi_cmd.byte2 = byte2;
-	scsipi_cmd.length = len & 0xff;
-	error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
-	    sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
-	    flags | XS_CTL_DATA_OUT);
-	SC_DEBUG(periph, SCSIPI_DB2,
-	    ("scsipi_mode_select: error=%d\n", error));
-	return (error);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = MODE_SELECT;
+	cmd.byte2 = byte2;
+	cmd.length = len & 0xff;
+
+	return (scsipi_execute_xs(&xs));
 }
 
 int
@@ -1256,19 +1287,24 @@
 	int byte2, len, flags, retries, timeout;
 	struct scsipi_mode_header_big *data;
 {
-	struct scsipi_mode_select_big scsipi_cmd;
-	int error;
+	struct scsipi_mode_select_big cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_OUT | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.data = (void *)data,
+		.datalen = len,
+		.xs_retries = retries,
+		.timeout = timeout,
+	};
 
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	scsipi_cmd.opcode = MODE_SELECT_BIG;
-	scsipi_cmd.byte2 = byte2;
-	_lto2b(len, scsipi_cmd.length);
-	error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
-	    sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
-	    flags | XS_CTL_DATA_OUT);
-	SC_DEBUG(periph, SCSIPI_DB2,
-	    ("scsipi_mode_select: error=%d\n", error));
-	return (error);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = MODE_SELECT_BIG;
+	cmd.byte2 = byte2;
+	_lto2b(len, cmd.length);
+
+	return (scsipi_execute_xs(&xs));
 }
 
 /*
@@ -1295,6 +1331,7 @@
 	/*
 	 * The resource this command was using is now free.
 	 */
+	TAILQ_REMOVE(&periph->periph_xferq, xs, device_q);
 	scsipi_put_resource(chan);
 	xs->xs_periph->periph_sent--;
 
@@ -1420,7 +1457,6 @@
 {
 	struct scsipi_periph *periph = xs->xs_periph;
 	struct scsipi_channel *chan = periph->periph_channel;
-	struct buf *bp;
 	int error, s;
 
 #ifdef DIAGNOSTIC
@@ -1599,12 +1635,10 @@
 		xs->status = SCSI_OK;
 		xs->xs_status &= ~XS_STS_DONE;
 		xs->xs_requeuecnt++;
-		error = scsipi_enqueue(xs);
-		if (error == 0) {
-			scsipi_periph_thaw(periph, 1);
-			splx(s);
-			return (ERESTART);
-		}
+		scsipi_enqueue(xs);
+		scsipi_periph_thaw(periph, 1);
+		splx(s);
+		return (ERESTART);
 	}
 
 	/*
@@ -1614,26 +1648,8 @@
 	if (xs->error != XS_NOERROR)
 		scsipi_periph_thaw(periph, 1);
 
-	/*
-	 * Set buffer fields in case the periph
-	 * switch done func uses them
-	 */
-	if ((bp = xs->bp) != NULL) {
-		if (error) {
-			bp->b_error = error;
-			bp->b_flags |= B_ERROR;
-			bp->b_resid = bp->b_bcount;
-		} else {
-			bp->b_error = 0;
-			bp->b_resid = xs->resid;
-		}
-	}
-
 	if (periph->periph_switch->psw_done)
-		periph->periph_switch->psw_done(xs);
-
-	if (bp)
-		biodone(bp);
+		periph->periph_switch->psw_done(xs, error);
 
 	if (xs->xs_control & XS_CTL_ASYNC)
 		scsipi_put_xs(xs);
@@ -1660,10 +1676,6 @@
 
 	/* if command was polling, request sense will too */
 	flags = xs->xs_control & XS_CTL_POLL;
-	/* Polling commands can't sleep */
-	if (flags)
-		flags |= XS_CTL_NOSLEEP;
-
 	flags |= XS_CTL_REQSENSE | XS_CTL_URGENT | XS_CTL_DATA_IN |
 	    XS_CTL_THAW_PERIPH | XS_CTL_FREEZE_PERIPH;
 
@@ -1677,7 +1689,7 @@
 	    0, 1000, NULL, flags);
 	periph->periph_flags &= ~PERIPH_SENSE;
 	periph->periph_xscheck = NULL;
-	switch(error) {
+	switch (error) {
 	case 0:
 		/* we have a valid sense */
 		xs->error = XS_SENSE;
@@ -1708,7 +1720,7 @@
  *
  *	Enqueue an xfer on a channel.
  */
-int
+void
 scsipi_enqueue(xs)
 	struct scsipi_xfer *xs;
 {
@@ -1716,6 +1728,7 @@
 	struct scsipi_xfer *qxs;
 	int s;
 
+again:
 	s = splbio();
 
 	/*
@@ -1725,8 +1738,10 @@
 	if ((xs->xs_control & XS_CTL_POLL) != 0 &&
 	    TAILQ_FIRST(&chan->chan_queue) != NULL) {
 		splx(s);
-		xs->error = XS_DRIVER_STUFFUP;
-		return (EAGAIN);
+		scsipi_printaddr(xs->xs_periph);
+		printf("waiting for queue to clear\n");
+		delay(1000000);
+		goto again;
 	}
 
 	/*
@@ -1766,7 +1781,6 @@
 	if (xs->xs_control & XS_CTL_THAW_PERIPH)
 		scsipi_periph_thaw(xs->xs_periph, 1);
 	splx(s);
-	return (0);
 }
 
 /*
@@ -1895,6 +1909,35 @@
 	struct scsipi_channel *chan = periph->periph_channel;
 	int oasync, async, poll, retries, error, s;
 
+#if 1
+	if (cold)
+		panic("scsipi_execute_xs: cold");
+#endif
+
+	/* Copy the command, if we haven't already, as it may be on the
+	   stack. */
+	if (xs->cmd != &xs->cmdstore) {
+		memcpy(&xs->cmdstore, xs->cmd, xs->cmdlen);
+		xs->cmd = &xs->cmdstore;
+	}
+	(chan->chan_bustype->bustype_cmd)(xs);
+
+	s = splbio();
+	TAILQ_INSERT_TAIL(&xs->xs_periph->periph_xferq, xs, device_q);
+	splx(s);
+	if (xs->xs_control & (XS_CTL_DATA_ONSTACK|XS_CTL_XFER_ONSTACK)) {
+#if 1
+		if (xs->xs_control & XS_CTL_ASYNC)
+			panic("scsipi_execute_xs: on stack and async");
+#endif
+		/*
+		 * If the I/O or command buffer is allocated on stack, the
+		 * process must NOT be swapped out, as the device will
+		 * be accessing the stack.
+		 */
+		PHOLD(curlwp);
+	}
+
 	xs->xs_status &= ~XS_STS_DONE;
 	xs->error = XS_NOERROR;
 	xs->resid = xs->datalen;
@@ -1965,7 +2008,7 @@
 	 * If we don't yet have a completion thread, or we are to poll for
 	 * completion, clear the ASYNC flag.
 	 */
-	oasync =  (xs->xs_control & XS_CTL_ASYNC);
+	oasync = (xs->xs_control & XS_CTL_ASYNC);
 	if (chan->chan_thread == NULL || (xs->xs_control & XS_CTL_POLL) != 0)
 		xs->xs_control &= ~XS_CTL_ASYNC;
 
@@ -1978,31 +2021,8 @@
 		panic("scsipi_execute_xs: XS_CTL_ASYNC but no buf");
 #endif
 
-	/*
-	 * Enqueue the transfer.  If we're not polling for completion, this
-	 * should ALWAYS return `no error'.
-	 */
- try_again:
-	error = scsipi_enqueue(xs);
-	if (error) {
-		if (poll == 0) {
-			scsipi_printaddr(periph);
-			printf("not polling, but enqueue failed with %d\n",
-			    error);
-			panic("scsipi_execute_xs");
-		}
-		
-		scsipi_printaddr(periph);
-		printf("failed to enqueue polling command");
-		if (retries != 0) {
-			printf(", retrying...\n");
-			delay(1000000);
-			retries--;
-			goto try_again;
-		}
-		printf("\n");
-		goto free_xs;
-	}
+	/* Enqueue the transfer. */
+	scsipi_enqueue(xs);
 
  restarted:
 	scsipi_run_queue(chan);
@@ -2012,7 +2032,7 @@
 	 * completed asynchronously, just return now.
 	 */
 	if (async)
-		return (EJUSTRETURN);
+		return (0);
 
 	/*
 	 * Not an asynchronous command; wait for it to complete.
@@ -2041,15 +2061,17 @@
 	 * don't return an error here. It has already been handled
 	 */
 	if (oasync)
-		error = EJUSTRETURN;
+		error = 0;
+
 	/*
 	 * Command completed successfully or fatal error occurred.  Fall
 	 * into....
 	 */
- free_xs:
-	s = splbio();
-	scsipi_put_xs(xs);
-	splx(s);
+	if ((xs->xs_control & XS_CTL_XFER_ONSTACK) == 0) {
+		s = splbio();
+		scsipi_put_xs(xs);
+		splx(s);
+	}
 
 	/*
 	 * Kick the queue, keep it running in case it stopped for some
@@ -2057,6 +2079,8 @@
 	 */
 	scsipi_run_queue(chan);
 
+	if (xs->xs_control & (XS_CTL_DATA_ONSTACK|XS_CTL_XFER_ONSTACK))
+		PRELE(curlwp);
 	return (error);
 }
 
Index: scsipi/scsipi_base.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_base.h,v
retrieving revision 1.13
diff -u -r1.13 scsipi_base.h
--- scsipi/scsipi_base.h	2003/01/06 21:02:18	1.13
+++ scsipi/scsipi_base.h	2003/09/18 21:40:56
@@ -42,10 +42,10 @@
 struct scsipi_xfer *scsipi_get_xs __P((struct scsipi_periph *, int));
 void	scsipi_put_xs __P((struct scsipi_xfer *));
 
-static __inline struct scsipi_xfer *scsipi_make_xs __P((struct scsipi_periph *,
-	    struct scsipi_generic *, int cmdlen, u_char *data_addr,
-	    int datalen, int retries, int timeout, struct buf *,
-	    int flags)) __attribute__ ((__unused__));
+static __inline struct scsipi_xfer *
+	scsipi_make_xs __P((struct scsipi_periph *, struct scsipi_generic *,
+	    int cmdlen, u_char *data_addr, int datalen, int retries,
+	    int timeout, struct buf *, int flags)) __attribute__ ((__unused__));
 
 /*
  * Make a scsipi_xfer, and return a pointer to it.
@@ -70,11 +70,10 @@
 		return (NULL);
 
 	/*
-	 * Fill out the scsipi_xfer structure.  We don't know whose context
-	 * the cmd is in, so copy it.
+	 * Fill out the scsipi_xfer structure.  If we need to copy the cmd,
+	 * we'll do it later.
 	 */
-	memcpy(&xs->cmdstore, scsipi_cmd, cmdlen);
-	xs->cmd = &xs->cmdstore;
+	xs->cmd = scsipi_cmd;
 	xs->cmdlen = cmdlen;
 	xs->data = data_addr;
 	xs->datalen = datalen;
Index: scsipi/scsipiconf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipiconf.c,v
retrieving revision 1.20
diff -u -r1.20 scsipiconf.c
--- scsipi/scsipiconf.c	2003/01/18 12:05:39	1.20
+++ scsipi/scsipiconf.c	2003/09/18 21:40:56
@@ -63,43 +63,12 @@
 #include <sys/device.h>
 #include <sys/proc.h>
 
-#include <uvm/uvm_extern.h>
-
 #include <dev/scsipi/scsipi_all.h>
 #include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 
 #define	STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
 
-int
-scsipi_command(periph, cmd, cmdlen, data_addr, datalen, retries, timeout, bp,
-     flags)
-	struct scsipi_periph *periph;
-	struct scsipi_generic *cmd;
-	int cmdlen;
-	u_char *data_addr;
-	int datalen;
-	int retries;
-	int timeout;
-	struct buf *bp;
-	int flags;
-{
-	int error;
- 
-	if ((flags & XS_CTL_DATA_ONSTACK) != 0) {
-		/*
-		 * If the I/O buffer is allocated on stack, the
-		 * process must NOT be swapped out, as the device will
-		 * be accessing the stack.
-		 */
-		PHOLD(curlwp);
-	}
-	error = (*periph->periph_channel->chan_bustype->bustype_cmd)(periph,
-	    cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags);
-	if ((flags & XS_CTL_DATA_ONSTACK) != 0)
-		PRELE(curlwp);
-	return (error);
-}
-
 /*
  * allocate and init a scsipi_periph structure for a new device.
  */
@@ -289,4 +258,27 @@
 	}
 
 	*dst++ = 0;
+}
+
+int
+scsipi_command(periph, cmd, cmdlen, data_addr, datalen, retries, timeout, bp,
+    flags)
+	struct scsipi_periph *periph;
+	struct scsipi_generic *cmd;
+	int cmdlen;
+	u_char *data_addr;
+	int datalen;
+	int retries;
+	int timeout;
+	struct buf *bp;
+	int flags;
+{
+	struct scsipi_xfer *xs;
+
+	xs = scsipi_make_xs(periph, cmd, cmdlen, data_addr, datalen, retries,
+	    timeout, bp, flags);
+	if (!xs)
+		return (ENOMEM);
+
+	return (scsipi_execute_xs(xs));
 }
Index: scsipi/scsipiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipiconf.h,v
retrieving revision 1.80
diff -u -r1.80 scsipiconf.h
--- scsipi/scsipiconf.h	2003/09/18 00:06:34	1.80
+++ scsipi/scsipiconf.h	2003/09/18 21:40:56
@@ -1,7 +1,7 @@
 /*	$NetBSD: scsipiconf.h,v 1.80 2003/09/18 00:06:34 mycroft Exp $	*/
 
 /*-
- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -171,7 +171,7 @@
 	void	(*psw_start) __P((struct scsipi_periph *));
 	int	(*psw_async) __P((struct scsipi_periph *,
 		    scsipi_async_event_t, void *));
-	void	(*psw_done) __P((struct scsipi_xfer *));
+	void	(*psw_done) __P((struct scsipi_xfer *, int));
 };
 
 struct disk_parms;
@@ -237,9 +237,7 @@
 struct scsipi_bustype {
 	int	bustype_type;		/* symbolic name of type */
 	
-	int	(*bustype_cmd) __P((struct scsipi_periph *,
-		    struct scsipi_generic *, int, void *, size_t, int,
-		    int, struct buf *, int));
+	void	(*bustype_cmd) __P((struct scsipi_xfer *));
 	int	(*bustype_interpret_sense) __P((struct scsipi_xfer *));
 	void	(*bustype_printaddr) __P((struct scsipi_periph *));
 	void	(*bustype_kill_pending) __P((struct scsipi_periph *));
@@ -547,35 +545,36 @@
  *
  *	- replace XS_CTL_URGENT with an `xs_priority' field?
  */
-#define	XS_CTL_NOSLEEP		0x00000001	/* don't sleep */
-#define	XS_CTL_POLL		0x00000002	/* poll for completion */
-#define	XS_CTL_DISCOVERY	0x00000004	/* doing device discovery */
-#define	XS_CTL_ASYNC		0x00000008	/* command completes
+#define	XS_CTL_NOSLEEP		(XS_CTL_POLL|XS_CTL_ASYNC)
+#define	XS_CTL_POLL		0x00000001	/* poll for completion */
+#define	XS_CTL_DISCOVERY	0x00000002	/* doing device discovery */
+#define	XS_CTL_ASYNC		0x00000004	/* command completes
 						   asynchronously */
-#define	XS_CTL_USERCMD		0x00000010	/* user issued command */
-#define	XS_CTL_SILENT		0x00000020	/* don't print sense info */
-#define	XS_CTL_IGNORE_NOT_READY	0x00000040	/* ignore NOT READY */
+#define	XS_CTL_USERCMD		0x00000008	/* user issued command */
+#define	XS_CTL_SILENT		0x00000010	/* don't print sense info */
+#define	XS_CTL_IGNORE_NOT_READY	0x00000020	/* ignore NOT READY */
 #define	XS_CTL_IGNORE_MEDIA_CHANGE 					\
-				0x00000080	/* ignore media change */
+				0x00000040	/* ignore media change */
 #define	XS_CTL_IGNORE_ILLEGAL_REQUEST					\
-				0x00000100	/* ignore ILLEGAL REQUEST */
-#define	XS_CTL_SILENT_NODEV	0x00000200	/* don't print sense info
+				0x00000080	/* ignore ILLEGAL REQUEST */
+#define	XS_CTL_SILENT_NODEV	0x00000100	/* don't print sense info
 						   if sense info is nodev */
-#define	XS_CTL_RESET		0x00000400	/* reset the device */
-#define	XS_CTL_DATA_UIO		0x00000800	/* xs_data points to uio */
-#define	XS_CTL_DATA_IN		0x00001000	/* data coming into memory */
-#define	XS_CTL_DATA_OUT		0x00002000	/* data going out of memory */
-#define	XS_CTL_TARGET		0x00004000	/* target mode operation */
-#define	XS_CTL_ESCAPE		0x00008000	/* escape operation */
-#define	XS_CTL_URGENT		0x00010000	/* urgent (recovery)
+#define	XS_CTL_RESET		0x00000200	/* reset the device */
+#define	XS_CTL_DATA_UIO		0x00000400	/* xs_data points to uio */
+#define	XS_CTL_DATA_IN		0x00000800	/* data coming into memory */
+#define	XS_CTL_DATA_OUT		0x00001000	/* data going out of memory */
+#define	XS_CTL_TARGET		0x00002000	/* target mode operation */
+#define	XS_CTL_ESCAPE		0x00004000	/* escape operation */
+#define	XS_CTL_URGENT		0x00008000	/* urgent (recovery)
 						   operation */
-#define	XS_CTL_SIMPLE_TAG	0x00020000	/* use a Simple Tag */
-#define	XS_CTL_ORDERED_TAG	0x00040000	/* use an Ordered Tag */
-#define	XS_CTL_HEAD_TAG		0x00080000	/* use a Head of Queue Tag */
-#define	XS_CTL_THAW_PERIPH	0x00100000	/* thaw periph once enqueued */
-#define	XS_CTL_FREEZE_PERIPH	0x00200000	/* freeze periph when done */
-#define XS_CTL_DATA_ONSTACK	0x00400000	/* data is alloc'ed on stack */
-#define XS_CTL_REQSENSE		0x00800000	/* xfer is a request sense */
+#define	XS_CTL_SIMPLE_TAG	0x00010000	/* use a Simple Tag */
+#define	XS_CTL_ORDERED_TAG	0x00020000	/* use an Ordered Tag */
+#define	XS_CTL_HEAD_TAG		0x00040000	/* use a Head of Queue Tag */
+#define	XS_CTL_THAW_PERIPH	0x00080000	/* thaw periph once enqueued */
+#define	XS_CTL_FREEZE_PERIPH	0x00100000	/* freeze periph when done */
+#define XS_CTL_DATA_ONSTACK	0x00200000	/* data is alloc'ed on stack */
+#define XS_CTL_REQSENSE		0x00400000	/* xfer is a request sense */
+#define	XS_CTL_XFER_ONSTACK	0x00800000	/* don't free the xfer */
 
 #define	XS_CTL_TAGMASK	(XS_CTL_SIMPLE_TAG|XS_CTL_ORDERED_TAG|XS_CTL_HEAD_TAG)
 
@@ -628,9 +627,8 @@
 
 #ifdef _KERNEL
 void	scsipi_init __P((void));
-int	scsipi_command __P((struct scsipi_periph *,
-	    struct scsipi_generic *, int, u_char *, int,
-	    int, int, struct buf *, int));
+int	scsipi_command __P((struct scsipi_periph *, struct scsipi_generic *,
+	    int, u_char *, int, int, int, struct buf *, int));
 void	scsipi_create_completion_thread __P((void *));
 caddr_t	scsipi_inqmatch __P((struct scsipi_inquiry_pattern *, caddr_t,
 	    int, int, int *));
Index: scsipi/sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.210
diff -u -r1.210 sd.c
--- scsipi/sd.c	2003/09/18 06:55:53	1.210
+++ scsipi/sd.c	2003/09/18 21:40:57
@@ -82,10 +82,11 @@
 #endif
 
 #include <dev/scsipi/scsipi_all.h>
-#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_disk.h>
+#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_disk.h>
-#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/sdvar.h>
 
 #define	SDUNIT(dev)			DISKUNIT(dev)
@@ -101,7 +102,7 @@
 void	sdgetdefaultlabel __P((struct sd_softc *, struct disklabel *));
 void	sdgetdisklabel __P((struct sd_softc *));
 void	sdstart __P((struct scsipi_periph *));
-void	sddone __P((struct scsipi_xfer *));
+void	sddone __P((struct scsipi_xfer *, int));
 void	sd_shutdown __P((void *));
 int	sd_reassign_blocks __P((struct sd_softc *, u_long));
 int	sd_interpret_sense __P((struct scsipi_xfer *));
@@ -893,7 +894,7 @@
 		/*
 		 * Figure out what flags to use.
 		 */
-		flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
+		flags = XS_CTL_ASYNC | XS_CTL_SIMPLE_TAG;
 		if (bp->b_flags & B_READ)
 			flags |= XS_CTL_DATA_IN;
 		else
@@ -907,6 +908,9 @@
 		    (u_char *)bp->b_data, bp->b_bcount,
 		    SDRETRIES, SD_IO_TIMEOUT, bp, flags);
 		if (error) {
+			bp->b_error = error;
+			bp->b_flags |= B_ERROR;
+			biodone(bp);
 			disk_unbusy(&sd->sc_dk, 0, 0);
 			printf("%s: not queued, error %d\n",
 			    sd->sc_dev.dv_xname, error);
@@ -915,22 +919,31 @@
 }
 
 void
-sddone(xs)
+sddone(xs, error)
 	struct scsipi_xfer *xs;
+	int error;
 {
 	struct sd_softc *sd = (void *)xs->xs_periph->periph_dev;
+	struct buf *bp = xs->bp;
 
 	if (sd->flags & SDF_FLUSHING) {
 		/* Flush completed, no longer dirty. */
 		sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
 	}
 
-	if (xs->bp != NULL) {
-		disk_unbusy(&sd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid,
-		    (xs->bp->b_flags & B_READ));
+	if (bp) {
+		bp->b_error = error;
+		bp->b_resid = xs->resid;
+		if (error)
+			bp->b_flags |= B_ERROR;
+		
+		disk_unbusy(&sd->sc_dk, bp->b_bcount - bp->b_resid,
+		    (bp->b_flags & B_READ));
 #if NRND > 0
-		rnd_add_uint32(&sd->rnd_source, xs->bp->b_rawblkno);
+		rnd_add_uint32(&sd->rnd_source, bp->b_rawblkno);
 #endif
+
+		biodone(bp);
 	}
 }
 
@@ -1298,7 +1311,7 @@
 	 * completion.
 	 */
 	if ((sd->flags & SDF_DIRTY) != 0) {
-		if (sd_flush(sd, XS_CTL_NOSLEEP|XS_CTL_POLL)) {
+		if (sd_flush(sd, XS_CTL_POLL)) {
 			printf("%s: cache synchronization failed\n",
 			    sd->sc_dev.dv_xname);
 			sd->flags &= ~SDF_FLUSHING;
@@ -1308,30 +1321,6 @@
 }
 
 /*
- * Tell the device to map out a defective block
- */
-int
-sd_reassign_blocks(sd, blkno)
-	struct sd_softc *sd;
-	u_long blkno;
-{
-	struct scsi_reassign_blocks scsipi_cmd;
-	struct scsi_reassign_blocks_data rbdata;
-
-	memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-	memset(&rbdata, 0, sizeof(rbdata));
-	scsipi_cmd.opcode = SCSI_REASSIGN_BLOCKS;
-
-	_lto2b(sizeof(rbdata.defect_descriptor[0]), rbdata.length);
-	_lto4b(blkno, rbdata.defect_descriptor[0].dlbaddr);
-
-	return (scsipi_command(sd->sc_periph,
-	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
-	    (u_char *)&rbdata, sizeof(rbdata), SDRETRIES, 5000, NULL,
-	    XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK));
-}
-
-/*
  * Check Errors
  */
 int
@@ -1437,7 +1426,6 @@
 }
 
 /* #define SD_DUMP_NOT_TRUSTED if you just want to watch */
-static struct scsipi_xfer sx;
 static int sddoingadump;
 
 /*
@@ -1459,10 +1447,8 @@
 	int	sectoff;	/* sector offset of partition */
 	int	totwrt;		/* total number of sectors left to write */
 	int	nwrt;		/* current number of sectors to write */
-	struct scsipi_rw_big cmd;	/* write command */
-	struct scsipi_xfer *xs;	/* ... convenience */
 	struct scsipi_periph *periph;
-	struct scsipi_channel *chan;
+	struct scsipi_rw_big cmd;	/* write command */
 
 	/* Check if recursive dump; if so, punt. */
 	if (sddoingadump)
@@ -1482,7 +1468,6 @@
 		return (ENODEV);
 
 	periph = sd->sc_periph;
-	chan = periph->periph_channel;
 
 	/* Make sure it was initialized. */
 	if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
@@ -1506,9 +1491,18 @@
 	/* Offset block number to start of partition. */
 	blkno += sectoff;
 
-	xs = &sx;
-
 	while (totwrt > 0) {
+		struct scsipi_xfer xs = {	/* ... convenience */
+			.xs_periph = periph,
+			.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_OUT | XS_CTL_POLL,
+			.cmd = (void *)&cmd,
+			.cmdlen = sizeof(cmd),
+			.data = va,
+			.datalen = totwrt * sectorsize,
+			.xs_retries = SDRETRIES,
+			.timeout = 10000,
+		};
+
 		nwrt = totwrt;		/* XXX */
 #ifndef	SD_DUMP_NOT_TRUSTED
 		/*
@@ -1518,33 +1512,13 @@
 		cmd.opcode = WRITE_BIG;
 		_lto4b(blkno, cmd.addr);
 		_lto2b(nwrt, cmd.length);
-		/*
-		 * Fill out the scsipi_xfer structure
-		 *    Note: we cannot sleep as we may be an interrupt
-		 * don't use scsipi_command() as it may want to wait
-		 * for an xs.
-		 */
-		memset(xs, 0, sizeof(sx));
-		xs->xs_control |= XS_CTL_NOSLEEP | XS_CTL_POLL |
-		    XS_CTL_DATA_OUT;
-		xs->xs_status = 0;
-		xs->xs_periph = periph;
-		xs->xs_retries = SDRETRIES;
-		xs->timeout = 10000;	/* 10000 millisecs for a disk ! */
-		xs->cmd = (struct scsipi_generic *)&cmd;
-		xs->cmdlen = sizeof(cmd);
-		xs->resid = nwrt * sectorsize;
-		xs->error = XS_NOERROR;
-		xs->bp = 0;
-		xs->data = va;
-		xs->datalen = nwrt * sectorsize;
 
 		/*
 		 * Pass all this info to the scsi driver.
 		 */
-		scsipi_adapter_request(chan, ADAPTER_REQ_RUN_XFER, xs);
-		if ((xs->xs_status & XS_STS_DONE) == 0 ||
-		    xs->error != XS_NOERROR)
+		scsipi_execute_xs(&xs);
+		if ((xs.xs_status & XS_STS_DONE) == 0 ||
+		    xs.error != XS_NOERROR)
 			return (EIO);
 #else	/* SD_DUMP_NOT_TRUSTED */
 		/* Let's just talk about this first... */
@@ -1690,29 +1664,36 @@
 
 	dp->disksize = sectors = scsipi_size(sd->sc_periph, flags);
 	if (sectors == 0) {
-		struct scsipi_read_format_capacities scsipi_cmd;
+		struct scsipi_read_format_capacities cmd;
 		struct {
 			struct scsipi_capacity_list_header header;
 			struct scsipi_capacity_descriptor desc;
-		} __attribute__((packed)) scsipi_result;
+		} __attribute__((packed)) data;
+		struct scsipi_xfer xs = {
+			.xs_periph = sd->sc_periph,
+			.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | flags,
+			.cmd = (void *)&cmd,
+			.cmdlen = sizeof(cmd),
+			.data = (void *)&data,
+			.datalen = sizeof(data),
+			.xs_retries = SDRETRIES,
+			.timeout = 20000,
+		};
+
+		memset(&cmd, 0, sizeof(cmd));
+		memset(&data, 0, sizeof(data));
+		cmd.opcode = READ_FORMAT_CAPACITIES;
+		_lto2b(sizeof(data), cmd.length);
 
-		memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
-		memset(&scsipi_result, 0, sizeof(scsipi_result));
-		scsipi_cmd.opcode = READ_FORMAT_CAPACITIES;
-		_lto2b(sizeof(scsipi_result), scsipi_cmd.length);
-		error = scsipi_command(sd->sc_periph, (void *)&scsipi_cmd,
-		    sizeof(scsipi_cmd), (void *)&scsipi_result,
-		    sizeof(scsipi_result), SDRETRIES, 20000,
-		    NULL, flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK /*|
-		    XS_CTL_IGNORE_ILLEGAL_REQUEST*/);
-		if (error || scsipi_result.header.length == 0)
+		error = scsipi_execute_xs(&xs);
+		if (error || data.header.length == 0)
 			return (SDGP_RESULT_OFFLINE);
 
 #if 0
-printf("rfc: length=%d\n", scsipi_result.header.length);
-printf("rfc result:"); for (i = sizeof(struct scsipi_capacity_list_header) + scsipi_result.header.length, p = (void *)&scsipi_result; i; i--, p++) printf(" %02x", *p); printf("\n");
+printf("rfc: length=%d\n", data.header.length);
+printf("rfc result:"); for (i = sizeof(struct scsipi_capacity_list_header) + data.header.length, p = (void *)&data; i; i--, p++) printf(" %02x", *p); printf("\n");
 #endif
-		switch (scsipi_result.desc.byte5 & SCSIPI_CAP_DESC_CODE_MASK) {
+		switch (data.desc.byte5 & SCSIPI_CAP_DESC_CODE_MASK) {
 		case SCSIPI_CAP_DESC_CODE_RESERVED:
 		case SCSIPI_CAP_DESC_CODE_FORMATTED:
 			break;
@@ -1724,11 +1705,11 @@
 			return (SDGP_RESULT_OFFLINE);
 		}
 
-		dp->disksize = sectors = _4btol(scsipi_result.desc.nblks);
+		dp->disksize = sectors = _4btol(data.desc.nblks);
 		if (sectors == 0)
 			return (SDGP_RESULT_OFFLINE);		/* XXX? */
 
-		dp->blksize = _3btol(scsipi_result.desc.blklen);
+		dp->blksize = _3btol(data.desc.blklen);
 		if (dp->blksize == 0)
 			dp->blksize = 512;
 	} else {
@@ -1915,7 +1896,15 @@
 	int flags;
 {
 	struct scsipi_periph *periph = sd->sc_periph;
-	struct scsi_synchronize_cache sync_cmd;
+	struct scsi_synchronize_cache cmd;
+	struct scsipi_xfer xs = {
+		.xs_periph = periph,
+		.xs_control = XS_CTL_XFER_ONSTACK | XS_CTL_IGNORE_ILLEGAL_REQUEST | flags,
+		.cmd = (void *)&cmd,
+		.cmdlen = sizeof(cmd),
+		.xs_retries = SDRETRIES,
+		.timeout = 100000,
+	};
 
 	/*
 	 * If the device is SCSI-2, issue a SYNCHRONIZE CACHE.
@@ -1931,18 +1920,15 @@
 	 *
 	 * XXX What about older devices?
 	 */
-	if (periph->periph_version >= 2 &&
-	    (periph->periph_quirks & PQUIRK_NOSYNCCACHE) == 0) {
-		sd->flags |= SDF_FLUSHING;
-		memset(&sync_cmd, 0, sizeof(sync_cmd));
-		sync_cmd.opcode = SCSI_SYNCHRONIZE_CACHE;
-
-		return(scsipi_command(periph,
-		       (struct scsipi_generic *)&sync_cmd, sizeof(sync_cmd),
-		       NULL, 0, SDRETRIES, 100000, NULL,
-		       flags|XS_CTL_IGNORE_ILLEGAL_REQUEST));
-	} else
+	if (periph->periph_version < 2 ||
+	    (periph->periph_quirks & PQUIRK_NOSYNCCACHE))
 		return (0);
+
+	sd->flags |= SDF_FLUSHING;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.opcode = SCSI_SYNCHRONIZE_CACHE;
+
+	return (scsipi_execute_xs(&xs));
 }
 
 int
Index: scsipi/ses.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ses.c,v
retrieving revision 1.22
diff -u -r1.22 ses.c
--- scsipi/ses.c	2003/06/29 22:30:43	1.22
+++ scsipi/ses.c	2003/09/18 21:40:58
@@ -50,10 +50,11 @@
 #include <machine/stdarg.h>
 
 #include <dev/scsipi/scsipi_all.h>
-#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_disk.h>
+#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_disk.h>
-#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/ses.h>
 
 /*
Index: scsipi/ss.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ss.c,v
retrieving revision 1.50
diff -u -r1.50 ss.c
--- scsipi/ss.c	2003/09/08 01:27:10	1.50
+++ scsipi/ss.c	2003/09/18 21:40:58
@@ -90,13 +90,14 @@
 
 void    ssstrategy __P((struct buf *));
 void    ssstart __P((struct scsipi_periph *));
+void	ssdone __P((struct scsipi_xfer *, int));
 void	ssminphys __P((struct buf *));
 
 const struct scsipi_periphsw ss_switch = {
 	NULL,
 	ssstart,
 	NULL,
-	NULL,
+	ssdone,
 };
 
 const struct scsipi_inquiry_pattern ss_patterns[] = {
@@ -509,6 +510,22 @@
 			/* generic scsi2 scanner read */
 			/* XXX add code for SCSI2 scanner read */
 		}
+	}
+}
+
+void
+ssdone(xs, error)
+	struct scsipi_xfer *xs;
+	int error;
+{
+	struct buf *bp = xs->bp;
+
+	if (bp) {
+		bp->b_error = error;
+		bp->b_resid = xs->resid;
+		if (error)
+			bp->b_flags |= B_ERROR;
+		biodone(bp);
 	}
 }
 
Index: scsipi/ss_mustek.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ss_mustek.c,v
retrieving revision 1.18
diff -u -r1.18 ss_mustek.c
--- scsipi/ss_mustek.c	2001/11/15 09:48:18	1.18
+++ scsipi/ss_mustek.c	2003/09/18 21:40:58
@@ -62,10 +62,11 @@
 #include <sys/conf.h>		/* for cdevsw */
 #include <sys/scanio.h>
 
-#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_scanner.h>
-#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/ssvar.h>
 #include <dev/scsipi/ss_mustek.h>
 
@@ -493,8 +494,11 @@
 	error = scsipi_command(periph,
 	    (struct scsipi_generic *) &cmd, sizeof(cmd),
 	    (u_char *) bp->b_data, bp->b_bcount, MUSTEK_RETRIES, 10000, bp,
-	    XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
+	    XS_CTL_ASYNC | XS_CTL_DATA_IN);
 	if (error) {
+		bp->b_error = error;
+		bp->b_flags |= B_ERROR;
+		biodone(bp);
 		printf("%s: not queued, error %d\n", ss->sc_dev.dv_xname,
 		    error);
 	} else {
Index: scsipi/ss_scanjet.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ss_scanjet.c,v
retrieving revision 1.28
diff -u -r1.28 ss_scanjet.c
--- scsipi/ss_scanjet.c	2002/09/14 21:41:24	1.28
+++ scsipi/ss_scanjet.c	2003/09/18 21:40:58
@@ -49,10 +49,11 @@
 #include <sys/conf.h>		/* for cdevsw */
 #include <sys/scanio.h>
 
-#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_scanner.h>
-#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/ssvar.h>
 
 #define SCANJET_RETRIES 4
@@ -288,8 +289,11 @@
 	error = scsipi_command(periph,
 	    (struct scsipi_generic *) &cmd, sizeof(cmd),
 	    (u_char *) bp->b_data, bp->b_bcount, SCANJET_RETRIES, 100000, bp,
-	    XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
+	    XS_CTL_ASYNC | XS_CTL_DATA_IN);
 	if (error) {
+		bp->b_error = error;
+		bp->b_flags |= B_ERROR;
+		biodone(bp);
 		printf("%s: not queued, error %d\n", ss->sc_dev.dv_xname,
 		    error);
 	} else {
Index: scsipi/st.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st.c,v
retrieving revision 1.163
diff -u -r1.163 st.c
--- scsipi/st.c	2003/06/29 22:30:45	1.163
+++ scsipi/st.c	2003/09/18 21:40:59
@@ -75,8 +75,11 @@
 #include <sys/kernel.h>
 #include <sys/vnode.h>
 
+#include <dev/scsipi/scsipi_all.h>
 #include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsi_tape.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
 #include <dev/scsipi/stvar.h>
 
 /* Defines for device specific stuff */
@@ -320,7 +323,7 @@
 void	st_unmount __P((struct st_softc *, boolean));
 int	st_decide_mode __P((struct st_softc *, boolean));
 void	ststart __P((struct scsipi_periph *));
-void	stdone __P((struct scsipi_xfer *));
+void	stdone __P((struct scsipi_xfer *, int));
 int	st_read __P((struct st_softc *, char *, int, int));
 int	st_space __P((struct st_softc *, int, u_int, int));
 int	st_write_filemarks __P((struct st_softc *, int, int));
@@ -1264,7 +1267,7 @@
 		 * Fill out the scsi command
 		 */
 		memset(&cmd, 0, sizeof(cmd));
-		flags = XS_CTL_NOSLEEP | XS_CTL_ASYNC;
+		flags = XS_CTL_ASYNC;
 		if ((bp->b_flags & B_READ) == B_WRITE) {
 			cmd.opcode = WRITE;
 			st->flags &= ~ST_FM_WRITTEN;
@@ -1297,6 +1300,9 @@
 		    (u_char *)bp->b_data, bp->b_bcount,
 		    0, ST_IO_TIME, bp, flags);
 		if (error) {
+			bp->b_error = error;
+			bp->b_flags |= B_ERROR;
+			biodone(bp);
 			printf("%s: not queued, error %d\n",
 			    st->sc_dev.dv_xname, error);
 		}
@@ -1304,33 +1310,40 @@
 }
 
 void
-stdone(xs)
+stdone(xs, error)
 	struct scsipi_xfer *xs;
+	int error;
 {
 	struct st_softc *st = (void *)xs->xs_periph->periph_dev;
+	struct buf *bp = xs->bp;
 
-	if (xs->bp != NULL) {
-		if ((xs->bp->b_flags & B_READ) == B_WRITE) {
+	if (bp) {
+		bp->b_error = error;
+		bp->b_resid = xs->resid;
+		if (error)
+			bp->b_flags |= B_ERROR;
+		
+		if ((bp->b_flags & B_READ) == B_WRITE)
 			st->flags |= ST_WRITTEN;
-		} else {
+		else
 			st->flags &= ~ST_WRITTEN;
-		}
 #if NRND > 0
-		rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno);
+		rnd_add_uint32(&st->rnd_source, bp->b_blkno);
 #endif
 
 		if ((st->flags & ST_POSUPDATED) == 0) {
-			if (xs->bp->b_flags & B_ERROR) {
+			if (error) {
 				st->fileno = st->blkno = -1;
 			} else if (st->blkno != -1) {
-				if (st->flags & ST_FIXEDBLOCKS) {
+				if (st->flags & ST_FIXEDBLOCKS)
 					st->blkno +=
-					    (xs->bp->b_bcount / st->blksize);
-				} else {
+					    (bp->b_bcount / st->blksize);
+				else
 					st->blkno++;
-				}
 			}
 		}
+
+		biodone(bp);
 	}
 }
 
Index: scsipi/st_scsi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st_scsi.c,v
retrieving revision 1.10
diff -u -r1.10 st_scsi.c
--- scsipi/st_scsi.c	2002/10/02 16:52:57	1.10
+++ scsipi/st_scsi.c	2003/09/18 21:40:59
@@ -69,9 +69,12 @@
 #include <sys/kernel.h>
 #include <sys/systm.h>
 
-#include <dev/scsipi/stvar.h>
-#include <dev/scsipi/scsi_tape.h>
+#include <dev/scsipi/scsipi_all.h>
 #include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsi_tape.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
+#include <dev/scsipi/stvar.h>
 
 int	st_scsibus_match __P((struct device *, struct cfdata *, void *));
 void	st_scsibus_attach __P((struct device *, struct device *, void *));
Index: usb/umass.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/umass.c,v
retrieving revision 1.104
diff -u -r1.104 umass.c
--- usb/umass.c	2003/09/13 03:18:13	1.104
+++ usb/umass.c	2003/09/18 21:41:00
@@ -490,11 +490,8 @@
 			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 			USB_ATTACH_ERROR_RETURN;
 		}
-		if (sc->maxlun > 0)
-			sc->sc_busquirks |= PQUIRK_FORCELUNS;
-	} else {
+	} else
 		sc->maxlun = 0;
-	}
 
 	/* Open the bulk-in and -out pipe */
 	DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKOUT\n",