4.4BSD/usr/src/sys/sparc/sbus/esp.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1988, 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)esp.c	8.1 (Berkeley) 6/11/93
 *
 * from: $Header: esp.c,v 1.28 93/04/27 14:40:44 torek Exp $ (LBL)
 *
 * Loosely derived from Mary Baker's devSCSIC90.c from the Berkeley
 * Sprite project, which is:
 *
 * Copyright 1988 Regents of the University of California
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any purpose and without
 * fee is hereby granted, provided that the above copyright
 * notice appear in all copies.  The University of California
 * makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 *
 * from /sprite/src/kernel/dev/sun4c.md/RCS/devSCSIC90.c,v 1.4
 * 90/12/19 12:37:58 mgbaker Exp $ SPRITE (Berkeley)
 */

/*
 * Sbus ESP/DMA driver.  A single driver must be used for both devices
 * as they are physically tied to each other:  The DMA chip can only
 * be used to assist ESP SCSI transactions; the ESP interrupt enable is
 * in the DMA chip csr.
 *
 * Since DMA and SCSI interrupts are handled in the same routine, the
 * DMA device does not declare itself as an sbus device.  This saves
 * some space.
 */

#include <sys/param.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <dev/scsi/scsi.h>
#include <dev/scsi/scsivar.h>

#include <machine/autoconf.h>
#include <machine/cpu.h>

#include <sparc/sbus/dmareg.h>
#define ESP_PHASE_NAMES
#include <sparc/sbus/espreg.h>
#include <sparc/sbus/sbusvar.h>

#ifdef DEBUG
int espdebug = 1;
#endif

/*
 * This driver is organized as a collection of state machines.  The
 * primary machine is the SCSI sequencer:
 *
 *	Given some previous SCSI state (as set up or tracked by us earlier)
 *	and the interrupt registers provided on the chips (dmacsr, espstat,
 *	espstep, and espintr), derive an action.  In many cases this is
 *	just a matter of reading the target's phase and following its orders,
 *	which sets a new state.
 *
 * This sequencing is done in espact(); the state is primed in espselect().
 *
 * There will be (update this comment when there is) another state machine
 * used to handle transfers that fall afoul of chip limits (16 bit DMA
 * counter; 24 bit address counter in 32 bit address field).
 *
 * Another state bit is used to recover from bus resets:
 *
 *	A single TEST UNIT READY is attempted on each target before any
 *	real communication begins; this TEST UNIT READY is allowed to
 *	fail in any way.  This is required for the Quantum ProDrive 100
 *	MB disks, for instance, which respond to their first selection
 *	with status phase, and for anything that insists on implementing
 *	the broken SCSI-2 synch transfer initial message.
 *
 * This is done in espclear() (which calls espselect(); functions that
 * call espselect() must check for clearing first).
 *
 * The state machines actually intermingle, as some SCSI sequences are
 * only allowed during clearing.
 */

/* per-DMA variables */
struct dma_softc {
	struct	device	sc_dev;		/* base device */
	volatile struct dmareg *sc_dma;	/* register virtual address */
	int	sc_dmarev;		/* revision */
	char	*sc_dmafmt;		/* format for error messages */

};
void	dmaattach(struct device *, struct device *, void *);
struct cfdriver dmacd =
    { NULL, "dma", matchbyname, dmaattach, DV_DULL, sizeof(struct dma_softc) };

/* per-ESP variables */
struct esp_softc {
	/*
	 * External interfaces.
	 */
	struct	hba_softc sc_hba;	/* base device + hba, must be first */
	struct	sbusdev sc_sd;		/* sbus device */
	struct	intrhand sc_ih;		/* interrupt entry */
	struct	evcnt sc_intrcnt;	/* interrupt counter */
	struct	dma_softc *sc_dsc;	/* pointer to corresponding dma sc */

	/*
	 * Addresses mapped to hardware registers.
	 */
	volatile struct espreg *sc_esp;
	volatile struct dmareg *sc_dma;

	/*
	 * Copies of registers cleared/unlatched by reading.
	 */
	u_long	sc_dmacsr;
	u_char	sc_espstat;
	u_char	sc_espstep;
	u_char	sc_espintr;

	/* miscellaneous */
	int	sc_clockfreq;		/* clock frequency */
	u_char	sc_sel_timeout;		/* select timeout */
	u_char	sc_id;			/* initiator ID (default = 7) */
	u_char	sc_needclear;		/* uncleared targets (1 bit each) */
	u_char	sc_esptype;		/* 100, 100A, 2xx (see below) */
	u_char	sc_ccf;			/* clock conversion factor */
	u_char	sc_conf1;		/* value for config reg 1 */
	u_char	sc_conf2;		/* value for config reg 2 */
	u_char	sc_conf3;		/* value for config reg 3 */
	struct	bootpath *sc_bp;	/* esp bootpath so far */

	/*
	 * Information pertaining to the current transfer,
	 * including sequencing.
	 *
	 * The size of sc_msg is the size of the ESP fifo,
	 * since we do message-in simply by allowing the fifo to fill.
	 */
	char	sc_probing;		/* used during autoconf; see below */
	char	sc_clearing;		/* true => cmd is just to clear targ */
	char	sc_state;		/* SCSI protocol state; see below */
	char	sc_sentcmd;		/* set once we get cmd out */
	char	sc_dmaactive;		/* true => doing dma */
#ifdef notyet
	u_char	sc_sync;		/* synchronous transfer stuff (?) */
#endif
	u_char	sc_stat[2];		/* status from last `status' phase */
	u_char	sc_msg[16];		/* message from device */
	u_short	sc_dmactl;		/* control to load into dma csr */
	u_long	sc_dmaaddr;		/* addr to load into dma addr */
	int	sc_targ;		/* the target involved */
	int	sc_resid;		/* count of bytes not xferred */
	struct	scsi_cdb sc_cdb;	/* current command (not in dvma) */
};

/*
 * Values for sc_esptype (used to control configuration reset).
 * The order is important; see espreset().
 */
#define	ESP100	0
#define	ESP100A	1
#define	ESP2XX	2

/*
 * Probe state.  0 means not probing.  While looking for each target
 * we set this to PROBE_TESTING and do a TEST UNIT READY on unit 0.
 * If selection fails, this is changed to PROBE_NO_TARGET; otherwise
 * we assume the target exists, regardless of the result of the test.
 */
#define	PROBE_TESTING	1
#define	PROBE_NO_TARGET	2

/*
 * States in sc_state.
 *
 * Note that S_CMDSVC is rare: normally we load the SCSI command into the
 * ESP fifo and get interrupted only when the device has gone to data
 * or status phase.  If the device wants to play games, though, we end
 * up doing things differently.
 */
char *espstates[] = {
#define	S_IDLE		0	/* not doing anything */
	"idle",
#define	S_SEL		1	/* expecting select done interrupt */
	"selecting",
#define	S_CMDSVC	2	/* expecting service req interrupt */
	"waiting for service request after command",
#define	S_IOSVC		3	/* expecting service req interrupt */
	"waiting for service request after io",
#define	S_DI		4	/* expecting data-in done interrupt */
	"receiving data",
#define	S_DO		5	/* expecting data-out done interrupt */
	"sending data",
#define	S_STAT		6	/* expecting status done interrupt */
	"receiving status",
#define	S_MI		7	/* expecting message-in done interrupt */
	"receiving message",
#define	S_FI		8	/* expecting final disconnect interrupt */
	"waiting for disconnect"
};

/*
 * Return values from espact().
 */
#define	ACT_CONT	0	/* espact() handled everything */
#define	ACT_READ	1	/* target said it is sending us data */
#define	ACT_WRITE	2	/* target said it is expecting data */
#define	ACT_DONE	3	/* handled everything, and op is now done */
#define	ACT_ERROR	4	/* an error occurred, op has been trashed */
#define	ACT_RESET	5	/* please reset ESP, then do ACT_ERROR */
#define	ACT_QUICKINTR	6	/* another interrupt is expected immediately */

/* autoconfiguration driver */
void	espattach(struct device *, struct device *, void *);
struct cfdriver espcd =
    { NULL, "esp", matchbyname, espattach, DV_DULL, sizeof(struct esp_softc),
      "intr" };

/* Sbus driver */
void	espsbreset(struct device *);

/* interrupt interface */
int	espintr(void *);

/* SCSI HBA driver */
int	espicmd(struct hba_softc *, int, struct scsi_cdb *, caddr_t, int, int);
int	espdump(struct hba_softc *, int, struct scsi_cdb *, caddr_t, int);
void	espstart(struct device *, struct sq *, struct buf *,
		scdgo_fn, struct device *);
int	espgo(struct device *, int, scintr_fn, struct device *,
		struct buf *, int);
void	esprel(struct device *);
void	esphbareset(struct hba_softc *, int);
static struct hbadriver esphbadriver =
    { espicmd, espdump, espstart, espgo, esprel, esphbareset };

/* forward declarations */
static void espdoattach(int unit);
static void espreset(struct esp_softc *);

/*
 * The transfer size is limited to 16 bits since the scsi ctrl transfer
 * counter is only 2 bytes.  A 0 value means the biggest transfer size
 * (2 ** 16) == 64k.
 */
#define MAX_TRANSFER_SIZE	(64 * 1024)

/* Return true if this transfer will cross a dma boundary */
#define CROSS_DMA(addr, len) \
    (((int)(addr) & 0xff000000) != (((int)(addr) + (len) - 1) & 0xff000000))

/*
 * Attach a found DMA chip.
 * The second argument is really a pointer to an sbus_attach_args.
 */
void
dmaattach(parent, dev, args)
	struct device *parent;
	struct device *dev;
	void *args;
{
	register struct dma_softc *dsc = (struct dma_softc *)dev;
	register struct sbus_attach_args *sa = args;
	register volatile struct dmareg *dma;
	register int rev;
	struct esp_softc *esc;

	if (sa->sa_ra.ra_vaddr)
		dma = (volatile struct dmareg *)sa->sa_ra.ra_vaddr;
	else
		dma = (volatile struct dmareg *)
		    mapiodev(sa->sa_ra.ra_paddr, sizeof(struct dmareg));
	dsc->sc_dma = dma;

	switch (rev = DMA_REV(dma->dma_csr)) {
	case DMAREV_1:
		printf(": rev 1\n");
		dsc->sc_dmafmt = DMA_REV1_BITS;
		break;
	case DMAREV_2:
		printf(": rev 2\n");
		dsc->sc_dmafmt = DMA_REV2_BITS;
		break;
	case DMAREV_3:
		printf(": rev 3\n");
		printf("WARNING: esp.c not yet updated for rev 3\n");
		dsc->sc_dmafmt = DMA_REV3_BITS;
		break;
	default:
		printf(": unknown revision code 0x%x\n", rev);
		dsc->sc_dmafmt = DMA_REV3_BITS;	/* cross fingers */
		break;
	}
	dsc->sc_dmarev = rev;
	espdoattach(dsc->sc_dev.dv_unit);
}

/*
 * Attach a found ESP chip.  Search for targets; attach each one found.
 * The latter must be deferred if the corresponding dma chip has not yet
 * been configured.
 */
void
espattach(parent, self, args)
	struct device *parent;
	struct device *self;
	void *args;
{
	register struct esp_softc *sc = (struct esp_softc *)self;
	register struct sbus_attach_args *sa = args;
	register volatile struct espreg *esp;
	register struct bootpath *bp;
	struct dma_softc *dsc;
	int node, pri, freq, t;

	if (sa->sa_ra.ra_nintr != 1) {
		printf(": expected 1 interrupt, got %d\n", sa->sa_ra.ra_nintr);
		return;
	}
	pri = sa->sa_ra.ra_intr[0].int_pri;
	printf(" pri %d", pri);
	if (sa->sa_ra.ra_vaddr)
		esp = (volatile struct espreg *)sa->sa_ra.ra_vaddr;
	else
		esp = (volatile struct espreg *)
		    mapiodev(sa->sa_ra.ra_paddr, sizeof(struct espreg));
	sc->sc_esp = esp;
	node = sa->sa_ra.ra_node;
	sc->sc_id = getpropint(node, "initiator-id", 7);
	freq = getpropint(node, "clock-frequency", -1);
	if (freq < 0)
		freq = ((struct sbus_softc *)sc->sc_hba.hba_dev.dv_parent)->sc_clockfreq;

	/* MIGHT NEED TO RESET ESP CHIP HERE ...? */

	/*
	 * Find out whether we have a -100, -100A, or -2xx,
	 * and what speed it runs at.
	 */
	sc->sc_conf1 = sc->sc_id | ESPCONF1_PARENB;
	/* sc->sc_conf2 = 0; */
	/* sc->sc_conf3 = 0; */
	esp->esp_conf1 = sc->sc_conf1;
	esp->esp_conf2 = 0;
	esp->esp_conf2 = ESPCONF2_SCSI2 | ESPCONF2_RPE;
	if ((esp->esp_conf2 & ~ESPCONF2_RSVD) !=
	    (ESPCONF2_SCSI2 | ESPCONF2_RPE)) {
		printf(": ESP100");
		sc->sc_esptype = ESP100;
	} else {
		esp->esp_conf2 = 0;
		esp->esp_conf3 = 0;
		esp->esp_conf3 = 5;
		if (esp->esp_conf3 != 5) {	/* XXX def bits */
			printf(": ESP100A");
			sc->sc_esptype = ESP100A;
		} else {
			esp->esp_conf3 = 0;
			printf(": ESP2XX");
			sc->sc_esptype = ESP2XX;
		}
	}
	printf(", clock = %s MHz, ID = %d\n", clockfreq(freq), sc->sc_id);

	/*
	 * Set clock conversion factor and select timeout.
	 * N.B.: clock frequency is not actually used in the rest
	 * of the driver; I calculate it here for completeness only
	 * (so I can see it when debugging).
	 */
	sc->sc_clockfreq = freq;
	freq = howmany(freq, 1000 * 1000);	/* convert to MHz */
	t = ESPCCF_FROMMHZ(freq);
	if (t < ESPCCF_MIN)
		t = ESPCCF_MIN;
	sc->sc_ccf = t;
	t = ESPTIMO_REGVAL(250, t, freq);	/* timeout = 250 ms. */
	if (t >= 256)
		t = 0;
	sc->sc_sel_timeout = t;

	/*
	 * Link into sbus; set interrupt handler.
	 */
	sc->sc_sd.sd_reset = espsbreset;
	sbus_establish(&sc->sc_sd, &sc->sc_hba.hba_dev);
	sc->sc_ih.ih_fun = espintr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih);
	evcnt_attach(&sc->sc_hba.hba_dev, "intr", &sc->sc_intrcnt);

#define SAME_ESP(bp, sa) \
	((bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset) || \
	 (bp->val[0] == -1 && bp->val[1] == sc->sc_hba.hba_dev.dv_unit))

	bp = sa->sa_ra.ra_bp;
	if (bp != NULL && strcmp(bp->name, "esp") == 0 && SAME_ESP(bp, sa))
		sc->sc_bp = bp + 1;
	espdoattach(sc->sc_hba.hba_dev.dv_unit);
}

/*
 * `Final' attach of esp occurs once esp and dma chips have been found
 * and assigned virtual addresses.  Set up the ESP SCSI data structures
 * and probe the SCSI bus.
 */
static void
espdoattach(unit)
	int unit;
{
	register struct esp_softc *sc;
	register struct dma_softc *dsc;
	register struct bootpath *bp;
	register struct targ *t;
	register int targ, u;

	/* make sure we have both */
	if (espcd.cd_ndevs <= unit ||
	    dmacd.cd_ndevs <= unit ||
	    (sc = espcd.cd_devs[unit]) == NULL ||
	    (dsc = dmacd.cd_devs[unit]) == NULL)
		return;
	sc->sc_dsc = dsc;
	sc->sc_dma = dsc->sc_dma;
	sc->sc_hba.hba_driver = &esphbadriver;

	espreset(sc);

	/* MAYBE THIS SHOULD BE MOVED TO scsi_subr.c? */
	for (targ = 0; targ < 8; targ++) {
		if (targ == sc->sc_id)
			continue;
		sc->sc_probing = PROBE_TESTING;
		sc->sc_clearing = 1;
		(void) scsi_test_unit_ready(&sc->sc_hba, targ, 0);
		if (sc->sc_probing != PROBE_NO_TARGET) {
			sc->sc_probing = 0;
			sc->sc_clearing = 0;
			SCSI_FOUNDTARGET(&sc->sc_hba, targ);
		}
	}
	sc->sc_probing = 0;
	sc->sc_clearing = 0;

	if ((bp = sc->sc_bp) == NULL || (u_int)(targ = bp->val[0]) >= 8 ||
	    (u_int)(u = bp->val[1]) >= 8)
		return;

	/*
	 * Did we find it? We could compare bp->name against the unit's
	 * name but there's no real need since a target and unit
	 * uniquely specify a scsi device.
	 */
	if ((t = sc->sc_hba.hba_targets[targ]) != NULL && t->t_units[u] != NULL)
		bootdv = t->t_units[u]->u_dev;
}

/*
 * Internal DMA reset.
 */
static void
dmareset(sc)
	struct esp_softc *sc;
{
	register volatile struct dmareg *dma = sc->sc_dma;

	/* reset DMA chip */
	dma->dma_csr |= DMA_RESET;
	DELAY(200);
	dma->dma_csr &= ~DMA_RESET;	/* ??? */
	sc->sc_state = S_IDLE;
	sc->sc_dmaactive = 0;
	if (sc->sc_dsc->sc_dmarev == DMAREV_2 && sc->sc_esptype != ESP100)
		dma->dma_csr |= DMA_TURBO;
	dma->dma_csr |= DMA_IE;		/* enable interrupts */
	DELAY(200);
}

/*
 * Reset the chip.  N.B.: this causes a SCSI bus reset!
 */
static void
espreset(sc)
	register struct esp_softc *sc;
{
	register volatile struct espreg *esp = sc->sc_esp;

	dmareset(sc);
	esp->esp_cmd = ESPCMD_RESET_CHIP;
	DELAY(200);
	esp->esp_cmd = ESPCMD_NOP;
	DELAY(200);

	/*
	 * Reload configuration registers (cleared by RESET_CHIP command).
	 * Reloading conf2 on an ESP100 goofs it up, so out of paranoia
	 * we load only the registers that exist.
	 */
	esp->esp_conf1 = sc->sc_conf1;
	if (sc->sc_esptype > ESP100) {		/* 100A, 2XX */
		esp->esp_conf2 = sc->sc_conf2;
		if (sc->sc_esptype > ESP100A)	/* 2XX only */
			esp->esp_conf3 = sc->sc_conf3;
	}
	esp->esp_ccf = sc->sc_ccf;
	esp->esp_timeout = sc->sc_sel_timeout;
	/* We set synch offset later. */

	sc->sc_needclear = 0xff;
}

/*
 * Reset the SCSI bus and, optionally, all attached targets.
 * The chip should retain most of its parameters (including esp_ccf)
 * across this kind of reset (see section 3.5 of Emulex documentation).
 */
void
esphbareset(hba, resetunits)
	struct hba_softc *hba;
	int resetunits;
{
	register struct esp_softc *sc = (struct esp_softc *)hba;
	register volatile struct espreg *esp = sc->sc_esp;

	dmareset(sc);

	/* BEGIN ??? */
	/* turn off scsi bus reset interrupts and reset scsi bus */
	esp->esp_conf1 = sc->sc_conf1 | ESPCONF1_REPORT;
	DELAY(200);
	esp->esp_cmd = ESPCMD_RESET_BUS;
	DELAY(800);
	esp->esp_cmd = ESPCMD_NOP;
	DELAY(200);
	esp->esp_conf1 = sc->sc_conf1;
	/* END ??? */

	sc->sc_needclear = 0xff;

	if (resetunits)
		scsi_reset_units(&sc->sc_hba);
}

/*
 * Reset the esp, after an Sbus reset.
 * Also resets corresponding dma chip.
 *
 * THIS ROUTINE MIGHT GO AWAY
 */
void
espsbreset(dev)
	struct device *dev;
{
	struct esp_softc *sc = (struct esp_softc *)dev;

	if (sc->sc_dsc) {
		printf(" %s %s", sc->sc_dsc->sc_dev.dv_xname,
		    sc->sc_hba.hba_dev.dv_xname);
		esphbareset(&sc->sc_hba, 1);
	}
}

static void
esperror(sc, err)
	char *err;
	register struct esp_softc *sc;
{

	printf("%s: %s (target=%d): stat=%b step=%x dmacsr=%b intr=%b\n",
	    sc->sc_hba.hba_dev.dv_xname, err, sc->sc_targ,
	    sc->sc_espstat, ESPSTAT_BITS, sc->sc_espstep,
	    sc->sc_dmacsr, sc->sc_dsc->sc_dmafmt,
	    sc->sc_espintr, ESPINTR_BITS);
}

/*
 * An interrupt has occurred.  Sequence through the SCSI state machine.
 * Return the action to take.
 *
 * Most of the work happens here.
 *
 * There are three interrupt sources:
 *   -- ESP interrupt request (typically, some device wants something).
 *   -- DMA memory error.
 *   -- DMA byte count has reached 0 (we do not often want this one but
 *	can only turn it off in rev 2 DMA chips, it seems).
 *	DOES THIS OCCUR AT ALL HERE?  THERE IS NOTHING TO HANDLE IT!
 */
static int
espact(sc, esp, dma, cdb)
	register struct esp_softc *sc;
	register volatile struct espreg *esp;
	register volatile struct dmareg *dma;
	register struct scsi_cdb *cdb;
{
	register char *xname = sc->sc_hba.hba_dev.dv_xname;
	register int reg, phase, i;

	/* check various error conditions, using as little code as possible */
	if (sc->sc_dmacsr & DMA_EP) {
		esperror(sc, "DMA error");
		dma->dma_csr |= DMA_FLUSH;
		return (ACT_ERROR);
	}
	reg = sc->sc_espstat;
	if (reg & ESPSTAT_GE) {
		/*
		 * This often occurs when there is no target.
		 * (See DSC code below.)
		 */
		if (sc->sc_espintr & ESPINTR_DSC &&
		    sc->sc_state == S_SEL && sc->sc_probing) {
			sc->sc_probing = PROBE_NO_TARGET;
			return (ACT_RESET);
		}
esperror(sc, "DIAGNOSTIC: gross error (ignored)");
	}
	if (reg & ESPSTAT_PE) {
		esperror(sc, "parity error");
		return (ACT_RESET);
	}
	reg = sc->sc_espintr;
#define ERR (ESPINTR_SBR|ESPINTR_ILC|ESPINTR_RSL|ESPINTR_SAT|ESPINTR_SEL)
	if (reg & ERR) {
		if (reg & ESPINTR_SBR)
			esperror(sc, "scsi bus reset");
		else if (reg & ESPINTR_ILC)
			esperror(sc, "illegal command (driver bug)");
		else {
			printf("%s: target %d", xname, sc->sc_targ);
			if (reg & ESPINTR_RSL)
				printf(" tried to reselect;");
			if (reg & ESPINTR_SAT)
				printf(" selected with ATN;");
			if (reg & ESPINTR_SEL)
				printf(" selected us as target;");
			printf("we do not allow this yet\n");
		}
		return (ACT_ERROR);
	}
#undef ERR

	/*
	 * Disconnect currently only allowed in `final interrupt' states.
	 */
	if (reg & ESPINTR_DSC) {
		if (sc->sc_state == S_FI)
			return (ACT_DONE);
		/*
		 * If we were doing a select just to test the existence
		 * of the target, note that it did not respond; otherwise
		 * gripe.
		 */
		if (sc->sc_state == S_SEL) {
			if (sc->sc_probing) {
				sc->sc_probing = PROBE_NO_TARGET;
				return (ACT_RESET);
			}
		}
		/* flush fifo, in case we were selecting or sending data */
		esp->esp_cmd = ESPCMD_FLUSH_FIFO;
		printf("%s: target %d not responding\n",
		    xname, sc->sc_targ);
		return (ACT_ERROR);
	}

	/*
	 * Okay, things are moving along.
	 * What were we doing the last time we did something,
	 * and did it complete normally?
	 */
	phase = sc->sc_espstat & ESPSTAT_PHASE;
	switch (sc->sc_state) {

	case S_SEL:
		/*
		 * We were selecting.  Arbitration and select are
		 * complete (because ESPINTR_DSC was not set), but
		 * there is no guarantee the command went out.
		 */
		if ((reg & (ESPINTR_SVC|ESPINTR_CMP)) !=
		    (ESPINTR_SVC|ESPINTR_CMP)) {
			esperror(sc, "selection failed");
			return (ACT_RESET);
		}
		if (sc->sc_espstep == ESPSTEP_DONE) {
			sc->sc_sentcmd = 1;
			break;
		}
		if (sc->sc_espstep == 2) {
			/*
			 * We got something other than command phase.
			 * Just pretend things are normal; the
			 * device will ask for the command later.
			 */
esperror(sc, "DIAGNOSTIC: esp step 2");
		} else if (sc->sc_espstep == 3) {
			/*
			 * Device entered command phase and then exited it
			 * before we finished handing out the command.
			 * Let this happen iff we are trying to clear the
			 * target state.
			 */
esperror(sc, "DIAGNOSTIC: esp step 3");
			if (!sc->sc_clearing)
				return (ACT_RESET);
		} else {
			printf("%s: mysterious esp step %d\n",
			    xname, sc->sc_espstep);
			return (ACT_RESET);
		}
		/*
		 * Part of the command may still be lodged in the FIFO.
		 */
		esp->esp_cmd = ESPCMD_FLUSH_FIFO;
		break;

	case S_CMDSVC:
		/*
		 * We were waiting for phase change after stuffing the command
		 * into the FIFO.  Make sure it got out.
		 */
		reg = ESP_NFIFO(esp);
		if (reg) {
esperror(sc, "DIAGNOSTIC: CMDSVC, fifo not empty");
printf("\tfifo count = %x\n", reg);
			esp->esp_cmd = ESPCMD_FLUSH_FIFO;
		} else
			sc->sc_sentcmd = 1;
		break;

	case S_IOSVC:
		/*
		 * We were waiting for phase change after I/O.
		 */
		break;

	case S_DI:
		/*
		 * We were doing DMA data in, and expecting a
		 * transfer-count-zero interrupt or a phase change.
		 * We got that; drain the pack register and
		 * handle as for data out.
		 */
		dma->dma_csr |= DMA_DRAIN;
		reg = 0;		/* FIFO auto flushed? */
		goto dma_data_done;

	case S_DO:
		/*
		 * We were doing DMA data out.  If there is data in the
		 * FIFO, it is stuff that got DMAed out but never made
		 * it to the device, so it counts as residual.
		 *
		 * XXX	handle DMA IO with large count or address
		 *	boundary condition by resuming here, or below?
		 */
		if ((reg = ESP_NFIFO(esp)) != 0)
			esp->esp_cmd = ESPCMD_FLUSH_FIFO;
dma_data_done:
		if (sc->sc_dmaactive == 0) {
			printf("%s: dma done while %s, dmaactive==0\n",
			    xname, espstates[sc->sc_state]);
			panic("espact");
		}
		sc->sc_dmaactive = 0;
		reg += esp->esp_tcl | (esp->esp_tch << 8);
		if (reg == 0 && (sc->sc_espstat & ESPSTAT_TC) == 0)
			reg = 65536;
		if (reg > sc->sc_resid) {
			printf("%s: xfer resid (%d) > xfer req (%d)\n",
			    xname, reg, sc->sc_resid);
			reg = sc->sc_resid;
		}
		/*
		 * If data came in we must flush cache.
		 */
		if (sc->sc_state == S_DI)
			cache_flush(sc->sc_dmaaddr, sc->sc_resid - reg);
		sc->sc_resid = reg;
		if ((sc->sc_espintr & ESPINTR_SVC) == 0) {
			printf("%s: no bus service req\n", xname);
			return (ACT_RESET);
		}
		break;

	case S_STAT:
		/*
		 * The last thing we did was tell it `initiator complete'
		 * and so we expect to have gotten both the status byte
		 * and the final message byte.  It is possible that we
		 * got something else....
		 *
		 * Apparently, BUS SERVICE is set if we got just status,
		 * while FUNCTION COMPLETE is set if we got both.
		 */
		if ((reg & (ESPINTR_SVC|ESPINTR_CMP)) != ESPINTR_CMP) {
			esperror(sc, "bad status interrupt state");
			return (ACT_RESET);
		}
		reg = ESP_NFIFO(esp);
		if (reg < 2) {
			printf(
		"%s: command done but fifo count = %d; must be >= 2\n", xname,
			    reg);
			return (ACT_RESET);
		}
		/*
		 * Read the status and the first msg byte.
		 * It should be CMD_COMPLETE.  Eventually we
		 * may handle IDENTIFY, DISCONNECT, etc., as well.
		 */
		sc->sc_stat[0] = esp->esp_fifo;
		sc->sc_msg[0] = reg = esp->esp_fifo;
		esp->esp_cmd = ESPCMD_MSG_ACCEPT;
		if (reg == MSG_CMD_COMPLETE) {
			sc->sc_state = S_FI;
			return (ACT_CONT);
		}
		if (SCSIMSGLEN(reg) != 1) {
			printf("%s: target %d is naughty\n",
			    xname, sc->sc_targ);
			return (ACT_RESET);
		}
		printf("%s: warning: target %d returned msg 0x%x\n",
		    xname, sc->sc_targ, reg);
		sc->sc_state = S_FI;
		return (ACT_CONT);

	case S_MI:
		if ((reg & ESPINTR_SVC) == 0) {
			esperror(sc, "missing phase after msg in");
			return (ACT_RESET);
		}
		reg = ESP_NFIFO(esp);
		for (i = 0; i < reg; i++)
			sc->sc_msg[i] = esp->esp_fifo;
		break;

	case S_FI:
		esperror(sc, "target did not disconnect");
		return (ACT_RESET);
	}

	/*
	 * Things are still moving along.  The phase tells us
	 * what the device wants next.  Do it.
	 */
	switch (phase) {

	case ESPPHASE_DATA_OUT:
if (!sc->sc_sentcmd) esperror(sc, "DIAGNOSTIC: data out without command");
		sc->sc_state = S_DO;
		return (ACT_WRITE);

	case ESPPHASE_DATA_IN:
if (!sc->sc_sentcmd) esperror(sc, "DIAGNOSTIC: data in without command");
		sc->sc_state = S_DI;
		return (ACT_READ);

	case ESPPHASE_CMD:
		/*
		 * Silly thing wants the command again.
		 * Load it into the FIFO and go to CMDSVC state.
		 */
printf("%s: redoing command\n", xname);
		reg = SCSICMDLEN(cdb->cdb_bytes[0]);
		for (i = 0; i < reg; i++)
			esp->esp_fifo = cdb->cdb_bytes[i];
		sc->sc_state = S_CMDSVC;
		esp->esp_cmd = ESPCMD_XFER_INFO;
		return (ACT_CONT);

	case ESPPHASE_STATUS:
		sc->sc_state = S_STAT;
		esp->esp_cmd = ESPCMD_INIT_COMP;
		return (ACT_CONT);

	case ESPPHASE_MSG_IN:
printf("%s: accepting (& ignoring) msg from target %d\n", xname, sc->sc_targ);
		sc->sc_state = S_MI;
		esp->esp_cmd = ESPCMD_MSG_ACCEPT;
		return (ACT_CONT);

	default:
		printf("%s: target %d asked for strange phase (%s)\n",
		    xname, sc->sc_targ, espphases[phase]);
		return (ACT_RESET);
	}
	/* NOTREACHED */
}

/*
 * Issue a select, loading command into the FIFO.
 * Return nonzero on error, 0 if OK.
 * Sets state to `selecting'; espact() will sequence state FSM.
 */
void
espselect(sc, esp, targ, cdb)
	register struct esp_softc *sc;
	register volatile struct espreg *esp;
	register int targ;
	register struct scsi_cdb *cdb;
{
	register int i, cmdlen = SCSICMDLEN(cdb->cdb_bytes[0]);

	sc->sc_targ = targ;
	sc->sc_state = S_SEL;
	sc->sc_sentcmd = 0;
	sc->sc_stat[0] = 0xff;		/* ??? */
	sc->sc_msg[0] = 0xff;		/* ??? */

	/*
	 * Try to talk to target.
	 * Synch offset 0 => asynchronous transfer.
	 */
	esp->esp_id = targ;
	esp->esp_syncoff = 0;

	/*
	 * Stuff the command bytes into the fifo.
	 * Select without attention since we do not do disconnect yet.
	 */
	for (i = 0; i < cmdlen; i++)
		esp->esp_fifo = cdb->cdb_bytes[i];
	esp->esp_cmd = ESPCMD_SEL_NATN;
	/* the rest is done elsewhere */
}

/*
 * THIS SHOULD BE ADJUSTABLE
 */
	/* name		howlong		purpose */
#define	SELECT_WAIT	300000		/* wait for select to complete */
#define	CMD_WAIT	1000		/* wait for next phase, generic */
#define	IO_WAIT		1000000		/* time to xfer data in/out */
#define	POSTDATA_WAIT	10000000	/* wait for next phase, after dataio */

/*
 * Transfer data out via polling.  Return success (0) iff all
 * the bytes were sent and we got an interrupt.
 *
 * This returns -1 on timeout, resid count on early interrupt,
 * but no one really cares....
 */
static int
espixfer_out(sc, esp, dma, buf, len)
	register struct esp_softc *sc;
	register volatile struct espreg *esp;
	register volatile struct dmareg *dma;
	register caddr_t buf;
	register int len;
{
	register int wait, n;

	if (CROSS_DMA(buf, len))
		panic("espixfer_out: 16MB boundary");

	/* set dma address and transfer count */
	dma->dma_addr = (int)buf;
	esp->esp_tch = len >> 8;
	esp->esp_tcl = len;

	/* load count into counter via DMA NOP */
	esp->esp_cmd = ESPCMD_DMA | ESPCMD_NOP;

	/* enable dma (but not interrupts) */
	dma->dma_csr = DMA_ENA;

	/* and go */
	esp->esp_cmd = ESPCMD_DMA | ESPCMD_XFER_INFO;

	/* wait for completion */
	for (wait = IO_WAIT; wait > 0; --wait) {
		n = dma->dma_csr;
		if (DMA_INTR(n)) {
			sc->sc_espstat = esp->esp_stat;
			sc->sc_espstep = esp->esp_step & ESPSTEP_MASK;
			sc->sc_espintr = esp->esp_intr;
			sc->sc_dmacsr = n;
			n = esp->esp_tcl | (esp->esp_tch << 8);
			if (n == 0 && (sc->sc_espstat & ESPSTAT_TC) == 0)
				n = 65536;

			return (n);
		}
		DELAY(1);
	}
	return (-1);
}

/*
 * Transfer data in via polling.
 * Return resid count on interrupt, -1 if timed out.
 */
static int
espixfer_in(sc, esp, dma, buf, len)
	register struct esp_softc *sc;
	register volatile struct espreg *esp;
	register volatile struct dmareg *dma;
	register caddr_t buf;
	register int len;
{
	register int wait, n;

	if (CROSS_DMA(buf, len))
		panic("espixfer_in: 16MB boundary");

	/* set dma address and transfer count */
	dma->dma_addr = (int)buf;
	esp->esp_tch = len >> 8;
	esp->esp_tcl = len;

	/* load count into counter via DMA NOP */
	esp->esp_cmd = ESPCMD_DMA | ESPCMD_NOP;

	/* enable dma (but not interrupts) */
	dma->dma_csr = DMA_ENA | DMA_READ;

	/* and go */
	esp->esp_cmd = ESPCMD_DMA | ESPCMD_XFER_INFO;

	/* wait for completion */
	for (wait = IO_WAIT; wait > 0; --wait) {
		n = dma->dma_csr;
		if (DMA_INTR(n)) {
			sc->sc_espstat = esp->esp_stat;
			sc->sc_espstep = esp->esp_step & ESPSTEP_MASK;
			sc->sc_espintr = esp->esp_intr;
			dma->dma_csr |= DMA_DRAIN;
			sc->sc_dmacsr = n;
			n = esp->esp_tcl | (esp->esp_tch << 8);
			if (n == 0 && (sc->sc_espstat & ESPSTAT_TC) == 0)
				n = 65536;

			cache_flush(buf, (u_int)len - n);
			return (n);
		}
		DELAY(1);
	}
	return (-1);
}

/*
 * Clear out target state by doing a special TEST UNIT READY.
 * Note that this calls espicmd (possibly recursively).
 */
void
espclear(sc, targ)
	register struct esp_softc *sc;
	register int targ;
{

	/* turn off needclear immediately since this calls espicmd() again */
	sc->sc_needclear &= ~(1 << targ);
	sc->sc_clearing = 1;
	(void) scsi_test_unit_ready(&sc->sc_hba, targ, 0);
	sc->sc_clearing = 0;
}

/*
 * Send an `immediate' command, i.e., poll until the whole thing is done.
 * Return the status byte from the device, or -1 if we timed out.
 */
int
espicmd(hba, targ, cdb, buf, len, rw)
	register struct hba_softc *hba;
	int targ;
	register struct scsi_cdb *cdb;
	caddr_t buf;
	register int len;
	int rw;
{
	register struct esp_softc *sc = (struct esp_softc *)hba;
	register volatile struct espreg *esp = sc->sc_esp;
	register volatile struct dmareg *dma = sc->sc_dma;
	register int r, wait;
	char *msg;

	if ((unsigned)len > MAX_TRANSFER_SIZE) {
		printf("%s: bad length %d\n", sc->sc_hba.hba_dev.dv_xname, len);
		panic("espicmd");
	}

	/*
	 * Clear the target if necessary.
	 */
	if (sc->sc_needclear & (1 << targ) && !sc->sc_probing)
		espclear(sc, targ);

	/*
	 * Disable hardware interrupts, start select sequence.
	 * Wait for interrupt-pending bit, then call espact() to
	 * sequence the state machine.  When it tells us to do
	 * data transfer, we do programmed I/O.
	 * In any case, we loop calling espact() until done.
	 */
	dma->dma_csr = 0;	/* disable hardware interrupts */
	espselect(sc, esp, targ, cdb);
	wait = SELECT_WAIT;
loop:
	for (;;) {
		r = dma->dma_csr;
		if (!DMA_INTR(r)) {
			if (--wait < 0) {
				msg = "timeout waiting for phase change";
				goto err;
			}
			DELAY(1);
			continue;
		}
		break;
	}
	sc->sc_espstat = esp->esp_stat;
	sc->sc_espstep = esp->esp_step & ESPSTEP_MASK;
	sc->sc_espintr = esp->esp_intr;
	sc->sc_dmacsr = r;
	/*
	 * The action happens `twice around' for read and write.
	 * All the rest `goto loop' or return or some such.
	 */
	wait = CMD_WAIT;
	for (;;) {
		switch (r = espact(sc, esp, dma, cdb)) {

		case ACT_CONT:
		case ACT_QUICKINTR:
			goto loop;

		case ACT_READ:
			if (len == 0 || (rw & B_READ) == 0) {
				msg = "wrong phase";
				goto err;
			}
			r = espixfer_in(sc, esp, dma, buf, len);
			if (r < 0) {
				msg = "timeout reading from device";
				goto err;
			}
			buf += len - r;
			len = r;
			/* we did the io, expecting `generic service' */
			sc->sc_state = S_IOSVC;
			wait = POSTDATA_WAIT;
			break;

		case ACT_WRITE:
			if (len == 0 || rw & B_READ) {
				msg = "wrong phase";
				goto err;
			}
			if (espixfer_out(sc, esp, dma, buf, len)) {
				msg = "timeout writing to device";
				goto err;
			}
			sc->sc_state = S_IOSVC;
			wait = POSTDATA_WAIT;
			break;

		case ACT_RESET:
			sc->sc_state = S_IDLE;
			goto reset;

		case ACT_DONE:
			sc->sc_state = S_IDLE;
			return (sc->sc_stat[0]);

		case ACT_ERROR:
			sc->sc_state = S_IDLE;
			return (-1);

		default:
			panic("espicmd action");
		}
	}
err:
	printf("%s: target %d: %s (phase = %s)\n",
	    sc->sc_hba.hba_dev.dv_xname, targ, msg,
	    espphases[sc->sc_espstat & ESPSTAT_PHASE]);
reset:
	espreset(sc);		/* ??? */
	return (-1);
}

/*
 * Dump (write memory, possibly physmem).
 * SPARC higher-level dump code always provides virtual addresses,
 * so we need not do any I/O mapping here.
 */
int
espdump(hba, targ, cdb, buf, len)
	register struct hba_softc *hba;
	int targ;
	register struct scsi_cdb *cdb;
	caddr_t buf;
	register int len;
{

	return (espicmd(hba, targ, cdb, buf, len, B_WRITE));
}

/*
 * Allocate resources (SCSI bus and DVMA space) for the given transfer.
 * Must be called at splbio().
 *
 * THIS SHOULD RETURN SUCCESS/FAIL INDICATION
 */
void
espstart(self, sq, bp, dgo, dev)
	struct device *self;
	register struct sq *sq;
	struct buf *bp;
	scdgo_fn dgo;
	struct device *dev;
{
	register struct esp_softc *sc = (struct esp_softc *)self;

	if (sc->sc_hba.hba_busy == 0) {
		/*
		 * Bus not busy, nothing to do here, just tell
		 * this target or unit that it has the SCSI bus.
		 */
		sc->sc_hba.hba_busy = 1;
		(*dgo)(dev, &sc->sc_cdb);
	} else {
		/*
		 * Bus is busy; just enqueue.
		 */
		sq->sq_dgo = dgo;
		sq->sq_dev = dev;
		sq->sq_forw = NULL;
		if (sc->sc_hba.hba_head == NULL)
			sc->sc_hba.hba_head = sq;
		else
			sc->sc_hba.hba_tail->sq_forw = sq;
		sc->sc_hba.hba_tail = sq;
	}
}

/*
 * Send a `dma' command, i.e., send the cdb and use DMA to send the data.
 * Return 0 on success, 1 on failure.
 */
int
espgo(self, targ, intr, dev, bp, pad)
	struct device *self;
	int targ;
	scintr_fn intr;
	struct device *dev;
	register struct buf *bp;
	int pad;
{
	register struct esp_softc *sc = (struct esp_softc *)self;
	register int len = bp->b_bcount;
	register u_long addr;

	if ((unsigned)len > MAX_TRANSFER_SIZE) {
		printf("%s: %s\n", sc->sc_hba.hba_dev.dv_xname,
		    len < 0 ? "negative length" : "transfer too big");
		return (1);
	}

	if (sc->sc_needclear & (1 << targ))
		espclear(sc, targ);

	/*
	 * Set dma registers later, on data transfer,
	 * but compute the contents now.
	 * COULD JUST REMEMBER bp HERE...?
	 *
	 * The DMA chip cannot cross a 16 MB address boundary.
	 * We should do this as multiple DMA transactions on a
	 * single SCSI command, but I have not written that yet.
	 */
	sc->sc_dmactl = bp->b_flags & B_READ ? DMA_ENA | DMA_READ | DMA_IE :
	    DMA_ENA | DMA_IE;
	addr = (u_long)bp->b_un.b_addr;
	/* dma chip cannot cross 16MB boundary  XXX */
	if (CROSS_DMA(addr, len))
		panic("dma crosses 16MB boundary: fix esp.c");
	sc->sc_dmaaddr = addr;
	sc->sc_resid = len;

	/*
	 * Enable interrupts and start selection.
	 * The rest is done in our interrupt handler.
	 */
	sc->sc_hba.hba_intr = intr;	/* remember dev done function */
	sc->sc_hba.hba_intrdev = dev;	/* and its first arg */
	sc->sc_dma->dma_csr = DMA_IE;
	espselect(sc, sc->sc_esp, targ, &sc->sc_cdb);
	return (0);
}

/*
 * Handle interrupt.  Return 1 if taken.
 */
int
espintr(sc0)
	void *sc0;
{
	register struct esp_softc *sc = (struct esp_softc *)sc0;
	register volatile struct espreg *esp = sc->sc_esp;
	register volatile struct dmareg *dma = sc->sc_dma;
	register int r, wait;
	register struct sq *sq;

	r = dma->dma_csr;
	if (!DMA_INTR(r))
		return (0);		/* not ours */
	sc->sc_intrcnt.ev_count++;

again:
	sc->sc_espstat = esp->esp_stat;
	sc->sc_espstep = esp->esp_step & ESPSTEP_MASK;
	sc->sc_espintr = esp->esp_intr;
	sc->sc_dmacsr = r;

	if (sc->sc_state == S_IDLE) {
		printf("%s: stray interrupt\n", sc->sc_hba.hba_dev.dv_xname);
		dma->dma_csr &= ~DMA_IE;	/* ??? */
		return (1);
	}
	switch (r = espact(sc, esp, dma, &sc->sc_cdb)) {

	case ACT_CONT:		/* just return */
		break;

	case ACT_READ:
	case ACT_WRITE:
		/*
		 * We have to do this ourselves since another
		 * user of espact() wants to do programmed I/O.
		 * If we already did dma, and are done, stop.
		 */
		if (sc->sc_resid == 0) {
			printf("%s: target %d sent too much data\n",
			    sc->sc_hba.hba_dev.dv_xname, sc->sc_targ);
			goto reset;
		}
		sc->sc_dmaactive = 1;
		dma->dma_addr = sc->sc_dmaaddr;
		esp->esp_tch = sc->sc_resid >> 8;
		esp->esp_tcl = sc->sc_resid;
		/* load count into counter via DMA NOP */
		esp->esp_cmd = ESPCMD_DMA | ESPCMD_NOP;
		/* enable dma */
		dma->dma_csr = sc->sc_dmactl;
		/* and go */
		esp->esp_cmd = ESPCMD_DMA | ESPCMD_XFER_INFO;
		break;

	case ACT_RESET:		/* please reset esp */
reset:
		espreset(sc);	/* ??? */
		/* FALLTHROUGH */

	case ACT_DONE:		/* this one is done, successfully */
	case ACT_ERROR:		/* this one is done due to `severe' error */
		sc->sc_state = S_IDLE;
		if (!sc->sc_hba.hba_busy)
			panic("espintr sq");
		/*
		 * This transaction is done.
		 * Call the driver's intr routine,
		 * then start the next guy if any.
		 */
		(*sc->sc_hba.hba_intr)(sc->sc_hba.hba_intrdev,
		    r == ACT_DONE ? sc->sc_stat[0] : -1, sc->sc_resid);
		if ((sq = sc->sc_hba.hba_head) != NULL) {
			sc->sc_hba.hba_head = sq->sq_forw;
			(*sq->sq_dgo)(sq->sq_dev, &sc->sc_cdb);
		} else
			sc->sc_hba.hba_busy = 0;
		break;

	case ACT_QUICKINTR:	/* wait a short while for another interrupt */
printf("%s: quickintr: ", sc->sc_hba.hba_dev.dv_xname);
		wait = 100;
		do {
			r = dma->dma_csr;
			if (DMA_INTR(r)) {
printf("got one, wait=%d\n", wait);
				goto again;
			}
		} while (--wait > 0);
printf("did not get one\n");
		break;

	default:
		panic("espintr action");
	}
	return (1);
}

/*
 * Target or unit decided to let go of the bus early.
 */
void
esprel(self)
	struct device *self;
{
	register struct esp_softc *sc = (struct esp_softc *)self;
	register struct sq *sq;

	/* if there is someone else waiting, give them a crack at it */
	if ((sq = sc->sc_hba.hba_head) != NULL)
		(*sq->sq_dgo)(sq->sq_dev, &sc->sc_cdb);
	else
		sc->sc_hba.hba_busy = 0;
}