xref: /csrg-svn/sys/dev/scsi/scsi_subr.c (revision 63459)
154879Storek /*
2*63459Sbostic  * Copyright (c) 1992, 1993
3*63459Sbostic  *	The Regents of the University of California.  All rights reserved.
454879Storek  *
554879Storek  * This software was developed by the Computer Systems Engineering group
654879Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
754879Storek  * contributed to Berkeley.
854879Storek  *
955559Storek  * All advertising materials mentioning features or use of this software
1055559Storek  * must display the following acknowledgement:
1155559Storek  *	This product includes software developed by the University of
1255559Storek  *	California, Lawrence Berkeley Laboratories.
1355559Storek  *
1454879Storek  * %sccs.include.redist.c%
1554879Storek  *
16*63459Sbostic  *	@(#)scsi_subr.c	8.1 (Berkeley) 06/16/93
1754879Storek  *
1857755Storek  * from: $Header: scsi_subr.c,v 1.10 93/02/01 19:21:58 torek Exp $ (LBL)
1954879Storek  */
2054879Storek 
2154879Storek /*
2254879Storek  * Generic SCSI host adapter driver.
2354879Storek  * Does almost nothing (most work is relegated to per-hba drivers).
2454879Storek  */
2554879Storek 
2655559Storek #include <sys/param.h>
2755559Storek #include <sys/buf.h>
2855559Storek #include <sys/device.h>
2954879Storek 
3056898Storek #include <dev/scsi/scsi.h>
3156898Storek #include <dev/scsi/scsivar.h>
3255559Storek 
3354879Storek /*
3454879Storek  * General subroutines, and scsi data.
3554879Storek  */
3654879Storek 
3754879Storek /* table of lengths of scsi commands */
3854879Storek const char scsicmdlen[8] = { 6, 10, 0, 0, 0, 12, 0, 0 };
3954879Storek 
4054879Storek /* table of lengths of scsi messages */
4154879Storek const signed char scsimsglen[0x24] = {
4254879Storek 	SMLEN_DONE,		/* MSG_CMD_COMPLETE */
4354879Storek 	SMLEN_EXTENDED,		/* MSG_EXT_MESSAGE */
4454879Storek 	1,			/* MSG_SAVE_DATA_PTR */
4554879Storek 	1,			/* MSG_RESTORE_PTR */
4654879Storek 	1,			/* MSG_DISCONNECT */
4754879Storek 	1,			/* MSG_INIT_DETECT_ERROR */
4854879Storek 	1,			/* MSG_ABORT */
4954879Storek 	1,			/* MSG_REJECT */
5054879Storek 	1,			/* MSG_NOOP */
5154879Storek 	1,			/* MSG_PARITY_ERROR */
5254879Storek 	1,			/* MSG_LCC */
5354879Storek 	1,			/* MSG_LCCF */
5454879Storek 	1,			/* MSG_BUS_DEVICE_RESET */
5554879Storek 	1,			/* MSG_ABORT_TAG */
5654879Storek 	1,			/* MSG_CLEAR_QUEUE */
5754879Storek 	1,			/* MSG_INITIATE_RECOVERY */
5854879Storek 	1,			/* MSG_RELEASE_RECOVERY */
5954879Storek 	1,			/* MSG_TERMINATE_PROCESS */
6054879Storek 	SMLEN_UNDEF,		/* 0x12 */
6154879Storek 	SMLEN_UNDEF,		/* 0x13 */
6254879Storek 	SMLEN_UNDEF,		/* 0x14 */
6354879Storek 	SMLEN_UNDEF,		/* 0x15 */
6454879Storek 	SMLEN_UNDEF,		/* 0x16 */
6554879Storek 	SMLEN_UNDEF,		/* 0x17 */
6654879Storek 	SMLEN_UNDEF,		/* 0x18 */
6754879Storek 	SMLEN_UNDEF,		/* 0x19 */
6854879Storek 	SMLEN_UNDEF,		/* 0x1a */
6954879Storek 	SMLEN_UNDEF,		/* 0x1b */
7054879Storek 	SMLEN_UNDEF,		/* 0x1c */
7154879Storek 	SMLEN_UNDEF,		/* 0x1d */
7254879Storek 	SMLEN_UNDEF,		/* 0x1e */
7354879Storek 	SMLEN_UNDEF,		/* 0x1f */
7454879Storek 	2,			/* MSG_SIMPLE_QTAG */
7554879Storek 	2,			/* MSG_HEAD_QTAG */
7654879Storek 	2,			/* MSG_ORDERED_QTAG */
7754879Storek 	2,			/* MSG_IGNORE_WIDE_RESID */
7854879Storek };
7954879Storek 
8054879Storek /* definition of `tg' target driver for autoconfig */
8154879Storek static int scsi_targmatch __P((struct device *, struct cfdata *, void *));
8254879Storek static void scsi_targattach __P((struct device *, struct device *, void *));
8354879Storek struct cfdriver tgcd =
8454879Storek     { NULL, "tg", scsi_targmatch, scsi_targattach,
8554879Storek       DV_DULL, sizeof(struct targ) };
8654879Storek 
8754879Storek void	scsi_targstart __P((struct device *, struct sq *, struct buf *,
8854879Storek 			scdgo_fn, struct device *));
8954879Storek int	scsi_targgo __P((struct device *, int targ,
9054879Storek 			scintr_fn, struct device *, struct buf *, int));
9154879Storek void	scsi_targintr __P((struct device *, int, int));
9254879Storek void	scsi_targrel __P((struct device *));
9354879Storek 
9454879Storek #define	NOBUF	((caddr_t)0)
9554879Storek 
9654879Storek /*
9754879Storek  * Perform a TEST UNIT READY immediate (polled) command
9854879Storek  * on the given <target,unit> pair.  Return the status byte
9954879Storek  * returned, or -1 for none.
10054879Storek  */
10154879Storek int
scsi_test_unit_ready(hba,targ,unit)10254879Storek scsi_test_unit_ready(hba, targ, unit)
10354879Storek 	struct hba_softc *hba;
10454879Storek 	int targ, unit;
10554879Storek {
10654879Storek 	struct scsi_cdb cdb;
10754879Storek 
10854879Storek 	CDB6(&cdb)->cdb_cmd = CMD_TEST_UNIT_READY;
10954879Storek 	CDB6(&cdb)->cdb_lun_lbah = unit << 5;
11054879Storek 	*(short *)&CDB6(&cdb)->cdb_lbam = 0;
11154879Storek 	*(short *)&CDB6(&cdb)->cdb_len = 0;
11254879Storek 	return (hba->hba_driver->hd_icmd(hba, targ, &cdb, NOBUF, 0, 0));
11354879Storek }
11454879Storek 
11554879Storek /*
11654879Storek  * Request sense.  The sense is to be written into the given buffer.
11754879Storek  * The given length must be < 256.
11854879Storek  */
11954879Storek int
scsi_request_sense(hba,targ,unit,buf,len)12054879Storek scsi_request_sense(hba, targ, unit, buf, len)
12154879Storek 	struct hba_softc *hba;
12254879Storek 	int targ, unit;
12354879Storek 	caddr_t buf;
12454879Storek 	int len;
12554879Storek {
12654879Storek 	struct scsi_cdb cdb;
12754879Storek 
12854879Storek 	CDB6(&cdb)->cdb_cmd = CMD_REQUEST_SENSE;
12954879Storek 	CDB6(&cdb)->cdb_lun_lbah = unit << 5;
13054879Storek 	*(short *)&CDB6(&cdb)->cdb_lbam = 0;
13154879Storek 	CDB6(&cdb)->cdb_len = len;
13254879Storek 	CDB6(&cdb)->cdb_ctrl = 0;
13354879Storek 	return (hba->hba_driver->hd_icmd(hba, targ, &cdb, buf, len, B_READ));
13454879Storek }
13554879Storek 
13654879Storek /*
13754879Storek  * Called (indirectly, via config_found) from scsi_hbaattach.
13854879Storek  * Print target number, and if no device was configured there,
13954879Storek  * the hba as well.
14054879Storek  */
14154879Storek int
scsi_targprint(aux,hba)14254879Storek scsi_targprint(aux, hba)
14354879Storek 	void *aux;
14454879Storek 	char *hba;
14554879Storek {
14654879Storek 
14754879Storek 	if (hba) {
14854879Storek 		printf("target %d on %s", *(int *)aux, hba);
14954879Storek 		return (UNCONF);
15054879Storek 	}
15154879Storek 	printf(" target %d", *(int *)aux);
15254879Storek 	return (QUIET);
15354879Storek }
15454879Storek 
15554879Storek /*
15654879Storek  * Print information about a unit found on some target.
15754879Storek  * If the unit was not configured, `targ' is the name of the target
15854879Storek  * on which the unit was found.  If it was, targ is NULL and we
15954879Storek  * let the unit's attach routine print the INQUIRE result if
16054879Storek  * appropriate.
16154879Storek  */
16254879Storek static int
scsi_unitprint(aux,targ)16354879Storek scsi_unitprint(aux, targ)
16454879Storek 	void *aux;
16554879Storek 	char *targ;
16654879Storek {
16754879Storek 	register struct scsi_attach_args *sa = aux;
16854879Storek 
16954879Storek 	if (targ) {
17054879Storek 		printf("unit %d at %s", sa->sa_unit, targ);
17154879Storek 		if ((sa->sa_inq_status & STS_MASK) == STS_GOOD) {
17254879Storek 			printf(" (");
17354879Storek 			scsi_printinq(&sa->sa_si);
17454879Storek 			printf(")");
17554879Storek 		}
17654879Storek 		return (UNCONF);
17754879Storek 	}
17854879Storek 	printf(" unit %d", sa->sa_unit);
17954879Storek 	return (QUIET);
18054879Storek }
18154879Storek 
18254879Storek /*
18354879Storek  * Generic target-match.
18454879Storek  */
18554879Storek static int
scsi_targmatch(parent,cf,aux)18654879Storek scsi_targmatch(parent, cf, aux)
18754879Storek 	struct device *parent;
18854879Storek 	register struct cfdata *cf;
18954879Storek 	void *aux;
19054879Storek {
19154879Storek 	int targ = *(int *)aux;
19254879Storek 
19354879Storek 	return (cf->cf_loc[0] == targ || cf->cf_loc[0] == -1);
19454879Storek }
19554879Storek 
19654879Storek /*
19754879Storek  * And now, a generic `target attach' routine.
19854879Storek  * We assume that INQUIRY works.
19954879Storek  */
20054879Storek static void
scsi_targattach(parent,self,aux)20154879Storek scsi_targattach(parent, self, aux)
20254879Storek 	struct device *parent, *self;
20354879Storek 	void *aux;
20454879Storek {
20554879Storek 	register struct targ *t = (struct targ *)self;
20654879Storek 	register struct hba_softc *hba;
20754879Storek 	register struct hbadriver *hd;
20854879Storek 	register int targ, unit;
20954879Storek 	struct scsi_attach_args sa;
21054879Storek 	struct scsi_cdb si;
21154879Storek 
21254879Storek 	printf("\n");
21354879Storek 	t->t_targ = targ = *(int *)aux;
21454879Storek 	hba = (struct hba_softc *)parent;
21554879Storek 	hba->hba_targets[targ] = t;
21654879Storek 
21754879Storek 	/*
21854879Storek 	 * Probe each of the 8 units using the sequence
21954879Storek 	 *	TEST UNIT READY
22054879Storek 	 *	REQUEST SENSE
22154879Storek 	 *	INQUIRY
22254879Storek 	 * The first should not be necessary, but some SCSI devices
22354879Storek 	 * refuse to speak until it is done.  The second is only necessary
22454879Storek 	 * if the first returns a CHECK CONDITION status, but we do it
22554879Storek 	 * anyway.
22654879Storek 	 */
22754879Storek 	hd = hba->hba_driver;
22854879Storek 	sa.sa_targ = targ;
22954879Storek 	CDB6(&si)->cdb_cmd = CMD_INQUIRY;
23054879Storek 	*(short *)&CDB6(&si)->cdb_lbam = 0;
23154879Storek 	CDB6(&si)->cdb_len = sizeof sa.sa_si;
23254879Storek 	CDB6(&si)->cdb_ctrl = 0;
23354879Storek 	for (unit = 0; unit < 8; unit++) {
23454879Storek 		if (scsi_test_unit_ready(hba, targ, unit) == -1)
23554879Storek 			continue;
23654879Storek 		sa.sa_unit = unit;
23754879Storek 		sa.sa_req_status = scsi_request_sense(hba, targ, unit,
23854879Storek 		    (caddr_t)&sa.sa_sn, sizeof sa.sa_sn);
23954879Storek 		CDB6(&si)->cdb_lun_lbah = unit << 5;
24054879Storek 		sa.sa_inq_status = (*hd->hd_icmd)(hba, targ, &si,
24154879Storek 		    (caddr_t)&sa.sa_si, sizeof sa.sa_si, B_READ);
24254879Storek 		if ((sa.sa_inq_status & STS_MASK) == STS_GOOD &&
24354879Storek #ifdef notdef /* XXX don't know if this is a reasonable test */
24454879Storek 		    (sa.sa_si.si_type & TYPE_QUAL_MASK) == TYPE_QUAL_NOTCONN &&
24554879Storek #endif
24654879Storek 		    (sa.sa_si.si_type & TYPE_TYPE_MASK) == TYPE_NP) {
24754879Storek 			continue;
24854879Storek 		}
24954879Storek 		config_found(&t->t_dev, (void *)&sa, scsi_unitprint);
25054879Storek 	}
25154879Storek }
25254879Storek 
25354879Storek /*
25454879Storek  * Each unit calls scsi_establish to tell the hba and target of
25554879Storek  * its existence.
25654879Storek  */
25754879Storek void
scsi_establish(u,dev,unit)25854879Storek scsi_establish(u, dev, unit)
25954879Storek 	register struct unit *u;
26054879Storek 	struct device *dev;
26154879Storek 	register int unit;
26254879Storek {
26354879Storek 	register struct targ *t;
26454879Storek 	register struct hba_softc *hba;
26554879Storek 	register struct hbadriver *hbd;
26654879Storek 
26754879Storek 	u->u_dev = dev;
26854879Storek 	t = (struct targ *)dev->dv_parent;
26954879Storek 	hba = (struct hba_softc *)t->t_dev.dv_parent;
27054879Storek 	hbd = hba->hba_driver;
27154879Storek 	t->t_units[unit] = u;
27254879Storek 	if (t->t_nunits == 0) {
27354879Storek 		/*
27454879Storek 		 * This is the first unit on the target.  We can
27554879Storek 		 * probably just call the hba start code, avoiding
27654879Storek 		 * one level of calls and queueing.  If we attach
27754879Storek 		 * another target we will fix this in the code below.
27854879Storek 		 */
27954879Storek 		u->u_start = hbd->hd_start;
28054879Storek 		u->u_go = hbd->hd_go;
28154879Storek 		u->u_rel = hbd->hd_rel;
28254879Storek 		u->u_updev = &hba->hba_dev;
28354879Storek 		t->t_firstunit = unit;
28454879Storek 	} else {
28554879Storek 		/*
28654879Storek 		 * This is not the only unit on the target, so we
28754879Storek 		 * must call the target start code rather than the
28854879Storek 		 * hba start code.  Fix the linkage on the first
28954879Storek 		 * target too (possibly for the 2nd, 3rd, ..., time).
29054879Storek 		 */
29154879Storek 		t->t_units[t->t_firstunit]->u_start = scsi_targstart;
29263458Smckusick 		t->t_units[t->t_firstunit]->u_go = scsi_targgo;
29363458Smckusick 		t->t_units[t->t_firstunit]->u_rel = scsi_targrel;
29454879Storek 		t->t_units[t->t_firstunit]->u_updev = &t->t_dev;
29554879Storek 		u->u_start = scsi_targstart;
29654879Storek 		u->u_go = scsi_targgo;
29754879Storek 		u->u_rel = scsi_targrel;
29854879Storek 		u->u_updev = &t->t_dev;
29954879Storek 	}
30054879Storek 	t->t_nunits++;			/* another unit is alive */
30154879Storek 	u->u_unit = unit;
30254879Storek 	u->u_targ = t->t_targ;		/* record target number, */
30354879Storek 	u->u_hba = hba;			/* hba ... */
30454879Storek 	u->u_hbd = hbd;			/* and driver */
30554879Storek }
30654879Storek 
30754879Storek /* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */
30854879Storek void
scsi_printinq(inq)30954879Storek scsi_printinq(inq)
31054879Storek 	register struct scsi_inquiry *inq;
31154879Storek {
31254879Storek 	register int iso, ecma, ansi, t;
31354879Storek 	static char *types[] = { "disk", "tape", "printer", "processor",
31454879Storek 	    "WORM", "ROM disk", "scanner", "magneto-optical",
31554879Storek 	    "jukebox", "lan" };
31654879Storek 
31754879Storek 	if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0)
31854879Storek 		printf("type-qual=0x%x ", t);
31954879Storek 	t = inq->si_type & TYPE_TYPE_MASK;
32054879Storek 	if (t < sizeof types / sizeof *types)
32154879Storek 		printf("%s", types[t]);
32254879Storek 	else
32354879Storek 		printf("<type %d>", t);
32454879Storek 	if (inq->si_qual & QUAL_RMB)
32554879Storek 		printf(" (removable)");
32654879Storek 	printf(" qual=0x%x", inq->si_qual & QUAL_MASK);
32754879Storek 	iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK;
32854879Storek 	ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK;
32954879Storek 	ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
33054879Storek 	printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi);
33154879Storek 	if (ansi == 1 || ansi == 2) {
33254879Storek 		char v[9], p[17], r[5];
33354879Storek 
33454879Storek 		scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r);
33554879Storek 		printf(" vendor %s, product %s, rev %s", v, p, r);
33654879Storek 	}
33754879Storek }
33854879Storek 
33954879Storek /* copy a counted string but trim trailing blanks; make the dest a C string */
34054879Storek static void
scsi_str(src,dst,len)34154879Storek scsi_str(src, dst, len)
34254879Storek 	register char *src, *dst;
34354879Storek 	register int len;
34454879Storek {
34554879Storek 
34654879Storek 	while (src[len - 1] == ' ') {
34754879Storek 		if (--len == 0) {
34854879Storek 			*dst = 0;
34954879Storek 			return;
35054879Storek 		}
35154879Storek 	}
35254879Storek 	bcopy(src, dst, len);
35354879Storek 	dst[len] = 0;
35454879Storek }
35554879Storek 
35654879Storek void
scsi_inq_ansi(si,vendor,product,rev)35754879Storek scsi_inq_ansi(si, vendor, product, rev)
35854879Storek 	register struct scsi_inq_ansi *si;
35954879Storek 	char *vendor, *product, *rev;
36054879Storek {
36154879Storek 	register int i, len;
36254879Storek 
36354879Storek 	/* if too short, extend with blanks */
36454879Storek 	len = si->si_len + 5;	/* 5 fixed; len is `additional' */
36554879Storek 	if (len < sizeof(*si))
36654879Storek 		for (i = len; i < sizeof *si; i++)
36754879Storek 			((char *)si)[i] = ' ';
36854879Storek 	scsi_str(si->si_vendor, vendor, sizeof si->si_vendor);
36954879Storek 	scsi_str(si->si_product, product, sizeof si->si_product);
37054879Storek 	scsi_str(si->si_rev, rev, sizeof si->si_rev);
37154879Storek }
37254879Storek 
37354879Storek /*
37454879Storek  * Tell all the devices on the given hba that it has been reset.
37554879Storek  * SHOULD PROBABLY DO MORE HERE
37654879Storek  */
37754879Storek void
scsi_reset_units(hba)37854879Storek scsi_reset_units(hba)
37954879Storek 	register struct hba_softc *hba;
38054879Storek {
38154879Storek 	register int targ, unit;
38254879Storek 	register struct targ *t;
38354879Storek 	register struct unit *u;
38454879Storek 
38554879Storek 	for (targ = 0; targ < 8; targ++) {
38654879Storek 		if ((t = hba->hba_targets[targ]) == NULL)
38754879Storek 			continue;
38854879Storek 		for (unit = 0; unit < 8; unit++)
38954879Storek 			if ((u = t->t_units[unit]) != NULL)
39054879Storek 				(*u->u_driver->ud_reset)(u);
39154879Storek 	}
39254879Storek }
39354879Storek 
39454879Storek /*
39554879Storek  * Start a unit on a target.
39654879Storek  * If the target is busy, just enqueue the unit;
39754879Storek  * once the target becomes free, we will call the hba start routine.
39854879Storek  * Otherwise, call the hba start routine now, and then when the hba
39954879Storek  * becomes free it will call the unit's dgo routine.
40054879Storek  */
40154879Storek void
scsi_targstart(self,sq,bp,dgo,dev)40254879Storek scsi_targstart(self, sq, bp, dgo, dev)
40354879Storek 	struct device *self;
40454879Storek 	register struct sq *sq;
40554879Storek 	struct buf *bp;
40654879Storek 	scdgo_fn dgo;
40754879Storek 	struct device *dev;
40854879Storek {
40954879Storek 	register struct targ *t = (struct targ *)self;
41054879Storek 	register struct hba_softc *hba;
41154879Storek 
41254879Storek 	sq->sq_forw = NULL;
41354879Storek 	if (t->t_head == NULL)
41454879Storek 		t->t_head = sq;
41554879Storek 	else
41654879Storek 		t->t_tail->sq_forw = sq;
41754879Storek 	t->t_tail = sq;
41854879Storek 	if (t->t_busy == 0) {
41954879Storek 		t->t_busy = 1;
42054879Storek 		hba = (struct hba_softc *)t->t_dev.dv_parent;
42154879Storek 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp,
42254879Storek 		    dgo, dev);
42354879Storek 	} else {
42454879Storek 		sq->sq_bp = bp;
42554879Storek 		sq->sq_dgo = dgo;
42654879Storek 		sq->sq_dev = dev;
42754879Storek 	}
42854879Storek }
42954879Storek 
43054879Storek /*
43154879Storek  * The unit got the bus, and wants the hba to go.
43254879Storek  * Remember its interrupt handler; substitute ours instead.
43354879Storek  */
43454879Storek int
scsi_targgo(self,targ,intr,dev,bp,pad)43554879Storek scsi_targgo(self, targ, intr, dev, bp, pad)
43654879Storek 	struct device *self;
43754879Storek 	int targ;
43854879Storek 	scintr_fn intr;
43954879Storek 	struct device *dev;
44054879Storek 	struct buf *bp;
44154879Storek 	int pad;
44254879Storek {
44354879Storek 	register struct targ *t = (struct targ *)self;
44454879Storek 	register struct hba_softc *hba;
44554879Storek 
44654879Storek 	t->t_intr = intr;
44754879Storek 	t->t_intrdev = dev;
44854879Storek 	hba = (struct hba_softc *)t->t_dev.dv_parent;
44954879Storek 	return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ,
45054879Storek 	    scsi_targintr, &t->t_dev, bp, pad));
45154879Storek }
45254879Storek 
45354879Storek /*
45454879Storek  * The hba got an interrupt.  Dequeue the unit from the target
45554879Storek  * (the target is already off the hba queue) and then call the
45654879Storek  * underlying interrupt handler.
45754879Storek  */
45854879Storek void
scsi_targintr(self,stat,resid)45954879Storek scsi_targintr(self, stat, resid)
46054879Storek 	struct device *self;
46154879Storek 	int stat, resid;
46254879Storek {
46354879Storek 	register struct targ *t = (struct targ *)self;
46454879Storek 	register struct hba_softc *hba;
46554879Storek 	register struct sq *sq;
46654879Storek 
46754879Storek 	sq = t->t_head;
46854879Storek if (sq == NULL) panic("scsi_targintr");
46954879Storek 	t->t_head = sq = sq->sq_forw;
47054879Storek 	(*t->t_intr)(t->t_intrdev, stat, resid);
47154879Storek 	if (sq != NULL) {
47254879Storek 		hba = (struct hba_softc *)t->t_dev.dv_parent;
47354879Storek 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
47454879Storek 		    sq->sq_bp, sq->sq_dgo, sq->sq_dev);
47554879Storek 	} else
47654879Storek 		t->t_busy = 0;
47754879Storek }
47854879Storek 
47954879Storek /*
48054879Storek  * The unit decided that it needed to `give up' its hold on the bus early.
48154879Storek  */
48254879Storek void
scsi_targrel(self)48354879Storek scsi_targrel(self)
48454879Storek 	struct device *self;
48554879Storek {
48654879Storek 	register struct targ *t = (struct targ *)self;
48754879Storek 	register struct hba_softc *hba;
48854879Storek 	register struct sq *sq;
48954879Storek 
49054879Storek 	hba = (struct hba_softc *)t->t_dev.dv_parent;
49154879Storek 	sq = t->t_head;
49254879Storek if (sq == NULL) panic("scsi_targrel");
49354879Storek 	/*
49454879Storek 	 * This target is at the head of the hba queue.
49554879Storek 	 * Remove it by calling hba bus release.  Then, if the
49654879Storek 	 * target queue is not empty, put it back on the hba queue.
49754879Storek 	 * (This produces round robin service.)
49854879Storek 	 */
49954879Storek 	(*hba->hba_driver->hd_rel)(&hba->hba_dev);
50054879Storek 	sq = sq->sq_forw;
50154879Storek 	if ((t->t_head = sq) != NULL)
50254879Storek 		(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
50354879Storek 		    sq->sq_bp, sq->sq_dgo, sq->sq_dev);
50454879Storek 	else
50554879Storek 		t->t_busy = 0;
50654879Storek }
507