scsi_low.c revision 71999
167468Snon/*	$FreeBSD: head/sys/cam/scsi/scsi_low.c 71999 2001-02-04 13:13:25Z phk $	*/
267468Snon/*	$NecBSD: scsi_low.c,v 1.24 1999/07/26 06:27:01 honda Exp $	*/
367468Snon/*	$NetBSD$	*/
467468Snon
567468Snon#define	SCSI_LOW_STATICS
667468Snon#define SCSI_LOW_WARNINGS
767468Snon#ifdef __NetBSD__
867468Snon#define	SCSI_LOW_TARGET_OPEN
967468Snon#define SCSI_LOW_INFORM
1067468Snon#endif
1167468Snon#ifdef __FreeBSD__
1267468Snon#define CAM
1367468Snon#endif
1467468Snon
1567468Snon/*
1667468Snon * [NetBSD for NEC PC-98 series]
1767468Snon *  Copyright (c) 1995, 1996, 1997, 1998, 1999
1867468Snon *	NetBSD/pc98 porting staff. All rights reserved.
1967468Snon *  Copyright (c) 1995, 1996, 1997, 1998, 1999
2067468Snon *	Naofumi HONDA. All rights reserved.
2167468Snon *
2267468Snon *  Redistribution and use in source and binary forms, with or without
2367468Snon *  modification, are permitted provided that the following conditions
2467468Snon *  are met:
2567468Snon *  1. Redistributions of source code must retain the above copyright
2667468Snon *     notice, this list of conditions and the following disclaimer.
2767468Snon *  2. Redistributions in binary form must reproduce the above copyright
2867468Snon *     notice, this list of conditions and the following disclaimer in the
2967468Snon *     documentation and/or other materials provided with the distribution.
3067468Snon *  3. The name of the author may not be used to endorse or promote products
3167468Snon *     derived from this software without specific prior written permission.
3267468Snon *
3367468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3467468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3567468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3667468Snon * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
3767468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3867468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3967468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4067468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4167468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
4267468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4367468Snon * POSSIBILITY OF SUCH DAMAGE.
4467468Snon */
4567468Snon
4667468Snon/* <On the nexus establishment>
4767468Snon * When our host is reselected,
4867468Snon * nexus establish processes are little complicated.
4967468Snon * Normal steps are followings:
5067468Snon * 1) Our host selected by target => target nexus (slp->sl_nexus)
5167468Snon * 2) Identify msgin => lun nexus (ti->ti_li)
5267468Snon * 3) Qtag msg => slccb nexus (ti->ti_nexus)
5367468Snon */
5467468Snon#include "opt_ddb.h"
5567468Snon
5667468Snon#include <sys/param.h>
5767468Snon#include <sys/systm.h>
5867468Snon#include <sys/kernel.h>
5967964Snon#ifdef __NetBSD__
6067468Snon#include <sys/disklabel.h>
6167964Snon#endif
6267468Snon#if defined(__FreeBSD__) && __FreeBSD_version >= 500001
6367468Snon#include <sys/bio.h>
6469979Snon#include <sys/devicestat.h>
6567468Snon#endif
6667468Snon#include <sys/buf.h>
6767468Snon#include <sys/queue.h>
6867468Snon#include <sys/malloc.h>
6967468Snon#include <sys/device_port.h>
7067468Snon#include <sys/errno.h>
7167468Snon
7267964Snon#ifdef __NetBSD__
7367468Snon#include <vm/vm.h>
7467468Snon
7567468Snon#include <machine/bus.h>
7667468Snon#include <machine/intr.h>
7767468Snon#include <machine/dvcfg.h>
7867468Snon
7967468Snon#include <dev/cons.h>
8067468Snon
8167468Snon#include <dev/scsipi/scsipi_all.h>
8267468Snon#include <dev/scsipi/scsipiconf.h>
8367468Snon#include <dev/scsipi/scsipi_disk.h>
8467468Snon#include <dev/scsipi/scsi_all.h>
8567468Snon#include <dev/scsipi/scsiconf.h>
8667468Snon
8767468Snon#include <i386/Cbus/dev/scsi_low.h>
8867468Snon#endif
8967468Snon#ifdef __FreeBSD__
9067468Snon#include <cam/cam.h>
9167468Snon#include <cam/cam_ccb.h>
9267468Snon#include <cam/cam_sim.h>
9367468Snon#include <cam/cam_debug.h>
9467468Snon#include <cam/cam_periph.h>
9567468Snon
9667468Snon#include <cam/scsi/scsi_all.h>
9767468Snon
9867468Snon#include <cam/scsi/scsi_low.h>
9967468Snon
10067468Snon#if !defined(__FreeBSD__) || __FreeBSD_version < 400001
10167468Snon#include <i386/i386/cons.h>
10267468Snon#else
10367468Snon#include <sys/cons.h>
10467468Snon#endif
10567468Snon#define delay(time) DELAY(time)
10667468Snon
10767468Snon/* from sys/dev/usb/usb_port.h
10867468Snon  XXX Change this when FreeBSD has memset
10967468Snon */
11067468Snon#define memset(d, v, s)	\
11167468Snon		do{			\
11267468Snon		if ((v) == 0)		\
11367468Snon			bzero((d), (s));	\
11467468Snon		else			\
11567468Snon			panic("Non zero filler for memset, cannot handle!"); \
11667468Snon		} while (0)
11767468Snon#endif
11867468Snon
11967468Snon#define	SCSI_LOW_DONE_COMPLETE	0
12067468Snon#define	SCSI_LOW_DONE_RETRY	1
12167468Snon
12267468Snonstatic void scsi_low_engage __P((void *));
12367468Snonstatic void scsi_low_info __P((struct scsi_low_softc *, struct targ_info *, u_char *));
12467468Snonstatic void scsi_low_init_msgsys __P((struct scsi_low_softc *, struct targ_info *));
12567468Snonstatic struct slccb *scsi_low_establish_ccb __P((struct targ_info *, struct lun_info *, scsi_low_tag_t));
12667468Snonstatic int scsi_low_done __P((struct scsi_low_softc *, struct slccb *));
12767468Snonstatic void scsi_low_twiddle_wait __P((void));
12867468Snonstatic struct lun_info *scsi_low_alloc_li __P((struct targ_info *, int, int));
12967468Snonstatic struct targ_info *scsi_low_alloc_ti __P((struct scsi_low_softc *, int));
13067468Snonstatic void scsi_low_calcf __P((struct targ_info *, struct lun_info *));
13167468Snonstatic struct lun_info *scsi_low_establish_lun __P((struct targ_info *, int));
13267468Snon#ifndef CAM
13367468Snonstatic void scsi_low_scsi_minphys __P((struct buf *));
13467468Snon#endif
13567468Snon#ifdef	SCSI_LOW_TARGET_OPEN
13667468Snonstatic int scsi_low_target_open __P((struct scsipi_link *, struct cfdata *));
13767468Snon#endif	/* SCSI_LOW_TARGET_OPEN */
13867468Snon#ifdef CAM
13967468Snonvoid scsi_low_scsi_action(struct cam_sim *sim, union ccb *ccb);
14067468Snonstatic void scsi_low_poll (struct cam_sim *sim);
14167468Snon#else
14267468Snonstatic int scsi_low_scsi_cmd __P((struct scsipi_xfer *));
14367468Snon#endif
14467468Snonstatic void scsi_low_reset_nexus __P((struct scsi_low_softc *, int));
14567468Snonstatic int scsi_low_init __P((struct scsi_low_softc *, u_int));
14667468Snonstatic void scsi_low_start __P((struct scsi_low_softc *));
14767468Snonstatic void scsi_low_free_ti __P((struct scsi_low_softc *));
14867468Snonstatic void scsi_low_clear_ccb __P((struct slccb *));
14967468Snon
15067468Snon#ifdef	SCSI_LOW_STATICS
15167468Snonstruct scsi_low_statics {
15267468Snon	int nexus_win;
15367468Snon	int nexus_fail;
15467468Snon	int nexus_disconnected;
15567468Snon	int nexus_reselected;
15667468Snon	int nexus_conflict;
15767468Snon} scsi_low_statics;
15867468Snon#endif	/* SCSI_LOW_STATICS */
15967468Snon/**************************************************************
16067468Snon * power control
16167468Snon **************************************************************/
16267468Snonstatic void
16367468Snonscsi_low_engage(arg)
16467468Snon	void *arg;
16567468Snon{
16667468Snon	struct scsi_low_softc *slp = arg;
16767468Snon	int s = splbio();
16867468Snon
16967468Snon	switch (slp->sl_rstep)
17067468Snon	{
17167468Snon	case 0:
17267468Snon		slp->sl_rstep ++;
17367468Snon		(*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE);
17467468Snon#ifdef __FreeBSD__
17567468Snon		slp->engage_ch =
17667468Snon#endif
17767468Snon		timeout(scsi_low_engage, slp, 1);
17867468Snon		break;
17967468Snon
18067468Snon	case 1:
18167468Snon		slp->sl_rstep ++;
18267468Snon		slp->sl_flags &= ~HW_RESUME;
18367468Snon		scsi_low_start(slp);
18467468Snon		break;
18567468Snon
18667468Snon	case 2:
18767468Snon		break;
18867468Snon	}
18967468Snon	splx(s);
19067468Snon}
19167468Snon
19267468Snonstatic int
19367468Snonscsi_low_init(slp, flags)
19467468Snon	struct scsi_low_softc *slp;
19567468Snon	u_int flags;
19667468Snon{
19767468Snon
19867468Snon	if ((slp->sl_flags & HW_POWERCTRL) != 0)
19967468Snon	{
20067468Snon#ifdef __FreeBSD__
20167468Snon		untimeout(scsi_low_engage, slp, slp->engage_ch);
20267468Snon#else /* NetBSD */
20367468Snon		untimeout(scsi_low_engage, slp);
20467468Snon#endif
20567468Snon		slp->sl_flags &= ~(HW_POWDOWN | HW_RESUME);
20667468Snon		slp->sl_active = 1;
20767468Snon		slp->sl_powc = SCSI_LOW_POWDOWN_TC;
20867468Snon	}
20967468Snon
21067468Snon	/* reset current nexus */
21167468Snon	scsi_low_reset_nexus(slp, flags);
21267468Snon	if ((slp->sl_flags & HW_INACTIVE) != 0)
21367468Snon		return EBUSY;
21467468Snon
21567468Snon	if (flags == SCSI_LOW_RESTART_SOFT)
21667468Snon		return 0;
21767468Snon
21867468Snon	return ((*slp->sl_funcs->scsi_low_init) (slp, flags));
21967468Snon}
22067468Snon
22167468Snon/**************************************************************
22267468Snon * allocate lun_info
22367468Snon **************************************************************/
22467468Snonstatic struct lun_info *
22567468Snonscsi_low_alloc_li(ti, lun, alloc)
22667468Snon	struct targ_info *ti;
22767468Snon	int lun;
22867468Snon	int alloc;
22967468Snon{
23067468Snon	struct scsi_low_softc *slp = ti->ti_sc;
23167468Snon	struct lun_info *li;
23267468Snon
23367468Snon	li = LIST_FIRST(&ti->ti_litab);
23467468Snon	if (li != NULL)
23567468Snon	{
23667468Snon		if (li->li_lun == lun)
23767468Snon			return li;
23867468Snon
23967468Snon		while ((li = LIST_NEXT(li, lun_chain)) != NULL)
24067468Snon		{
24167468Snon			if (li->li_lun == lun)
24267468Snon			{
24367468Snon				LIST_REMOVE(li, lun_chain);
24467468Snon				LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain);
24567468Snon				return li;
24667468Snon			}
24767468Snon		}
24867468Snon	}
24967468Snon
25067468Snon	if (alloc == 0)
25167468Snon		return li;
25267468Snon
25367468Snon	li = malloc(ti->ti_lunsize, M_DEVBUF, M_NOWAIT);
25467468Snon	if (li == NULL)
25567468Snon		panic("no lun info mem\n");
25667468Snon
25767468Snon	memset(li, 0, ti->ti_lunsize);
25867468Snon	li->li_lun = lun;
25967468Snon	li->li_ti = ti;
26067468Snon#if	defined(SDEV_NOPARITY) && defined(SDEV_NODISC)
26167468Snon	li->li_quirks = SDEV_NOPARITY | SDEV_NODISC;
26267468Snon#endif	/* SDEV_NOPARITY && SDEV_NODISC */
26367468Snon	li->li_cfgflags = 0xffff0000 | SCSI_LOW_SYNC;
26467468Snon
26567468Snon	LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain);
26667468Snon
26767468Snon	/* host specific structure initialization per lun */
26867468Snon	(void) ((*slp->sl_funcs->scsi_low_lun_init) (slp, ti, li));
26967468Snon
27067468Snon	return li;
27167468Snon}
27267468Snon
27367468Snon/**************************************************************
27467468Snon * allocate targ_info
27567468Snon **************************************************************/
27667468Snonstatic struct targ_info *
27767468Snonscsi_low_alloc_ti(slp, targ)
27867468Snon	struct scsi_low_softc *slp;
27967468Snon	int targ;
28067468Snon{
28167468Snon	struct targ_info *ti;
28267468Snon
28371999Sphk	if (TAILQ_FIRST(&slp->sl_titab) == NULL)
28467468Snon		TAILQ_INIT(&slp->sl_titab);
28567468Snon
28667468Snon	ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT);
28767468Snon	if (ti == NULL)
28867468Snon		panic("%s short of memory\n", slp->sl_xname);
28967468Snon
29067468Snon	memset(ti, 0, sizeof(struct targ_info));
29167468Snon	ti->ti_id = targ;
29267468Snon	ti->ti_sc = slp;
29367468Snon
29467468Snon	slp->sl_ti[targ] = ti;
29567468Snon	TAILQ_INSERT_TAIL(&slp->sl_titab, ti, ti_chain);
29667468Snon	TAILQ_INIT(&ti->ti_discq);
29767468Snon	LIST_INIT(&ti->ti_litab);
29867468Snon
29967468Snon	return ti;
30067468Snon}
30167468Snon
30267468Snonstatic void
30367468Snonscsi_low_free_ti(slp)
30467468Snon	struct scsi_low_softc *slp;
30567468Snon{
30667468Snon	struct targ_info *ti, *tib;
30767468Snon	struct lun_info *li, *nli;
30867468Snon
30971999Sphk	for (ti = TAILQ_FIRST(&slp->sl_titab); ti; ti = tib)
31067468Snon	{
31171999Sphk		tib = TAILQ_NEXT(ti, ti_chain);
31267468Snon		for (li = LIST_FIRST(&ti->ti_litab); li != NULL; li = nli)
31367468Snon		{
31467468Snon			nli = LIST_NEXT(li, lun_chain);
31567468Snon			free(li, M_DEVBUF);
31667468Snon		}
31767468Snon		free(ti, M_DEVBUF);
31867468Snon	}
31967468Snon}
32067468Snon
32167468Snon/**************************************************************
32267468Snon * timeout
32367468Snon **************************************************************/
32467468Snonvoid
32567468Snonscsi_low_timeout(arg)
32667468Snon	void *arg;
32767468Snon{
32867468Snon	struct scsi_low_softc *slp = arg;
32967468Snon	struct targ_info *ti;
33067468Snon	struct slccb *cb = NULL;		/* XXX */
33167468Snon	int s = splbio();
33267468Snon
33367468Snon	/* check */
33467468Snon	if ((ti = slp->sl_nexus) != NULL && (cb = ti->ti_nexus) != NULL)
33567468Snon	{
33667468Snon		cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
33767468Snon		if (cb->ccb_tc < 0)
33867468Snon			goto bus_reset;
33967468Snon	}
34067468Snon	else if (slp->sl_disc > 0)
34167468Snon	{
34267468Snon		struct targ_info *ti;
34367468Snon
34471999Sphk		for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
34571999Sphk		     ti = TAILQ_NEXT(ti, ti_chain))
34667468Snon		{
34771999Sphk			for (cb = TAILQ_FIRST(&ti->ti_discq); cb != NULL;
34871999Sphk			     cb = TAILQ_NEXT(cb, ccb_chain))
34967468Snon			{
35067468Snon				cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
35167468Snon				if (cb->ccb_tc < 0)
35267468Snon					goto bus_reset;
35367468Snon			}
35467468Snon		}
35567468Snon	}
35667468Snon	else
35767468Snon	{
35871999Sphk		cb = TAILQ_FIRST(&slp->sl_start);
35967468Snon		if (cb != NULL)
36067468Snon		{
36167468Snon			cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
36267468Snon			if (cb->ccb_tc < 0)
36367468Snon				goto bus_reset;
36467468Snon		}
36567468Snon		else if ((slp->sl_flags & HW_POWERCTRL) != 0)
36667468Snon		{
36767468Snon			if ((slp->sl_flags & (HW_POWDOWN | HW_RESUME)) != 0)
36867468Snon				goto out;
36967468Snon
37067468Snon			if (slp->sl_active != 0)
37167468Snon			{
37267468Snon				slp->sl_powc = SCSI_LOW_POWDOWN_TC;
37367468Snon				slp->sl_active = 0;
37467468Snon				goto out;
37567468Snon			}
37667468Snon
37767468Snon			slp->sl_powc --;
37867468Snon			if (slp->sl_powc < 0)
37967468Snon			{
38067468Snon				slp->sl_powc = SCSI_LOW_POWDOWN_TC;
38167468Snon				slp->sl_flags |= HW_POWDOWN;
38267468Snon				(*slp->sl_funcs->scsi_low_power)
38367468Snon						(slp, SCSI_LOW_POWDOWN);
38467468Snon			}
38567468Snon		}
38667468Snon	}
38767468Snon
38867468Snonout:
38967468Snon#ifdef __FreeBSD__
39067468Snon	slp->timeout_ch =
39167468Snon#endif
39267468Snon	timeout(scsi_low_timeout, slp, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz);
39367468Snon
39467468Snon	splx(s);
39567468Snon	return;
39667468Snon
39767468Snonbus_reset:
39867468Snon	cb->ccb_error |= TIMEOUTIO;
39967468Snon	scsi_low_info(slp, NULL, "scsi bus hangup. try to recover.");
40067468Snon	scsi_low_init(slp, SCSI_LOW_RESTART_HARD);
40167468Snon	scsi_low_start(slp);
40267468Snon#ifdef __FreeBSD__
40367468Snon	slp->timeout_ch =
40467468Snon#endif
40567468Snon	timeout(scsi_low_timeout, slp, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz);
40667468Snon
40767468Snon	splx(s);
40867468Snon}
40967468Snon
41067468Snon/**************************************************************
41167468Snon * CCB
41267468Snon **************************************************************/
41367468SnonGENERIC_CCB_STATIC_ALLOC(scsi_low, slccb)
41467468SnonGENERIC_CCB(scsi_low, slccb, ccb_chain)
41567468Snon
41667468Snon/**************************************************************
41767468Snon * SCSI INTERFACE (XS)
41867468Snon **************************************************************/
41967468Snon#define	SCSI_LOW_MINPHYS	0x10000
42067468Snon
42167468Snon#ifdef __NetBSD__
42267468Snonstruct scsipi_device scsi_low_dev = {
42367468Snon	NULL,	/* Use default error handler */
42467468Snon	NULL,	/* have a queue, served by this */
42567468Snon	NULL,	/* have no async handler */
42667468Snon	NULL,	/* Use default 'done' routine */
42767468Snon};
42867468Snon#endif
42967468Snon
43067468Snon#ifdef CAM
43167468Snonstatic void
43267468Snonscsi_low_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
43367468Snon{
43467468Snon	xpt_free_path(ccb->ccb_h.path);
43567468Snon	free(ccb, M_DEVBUF);
43667468Snon#if defined(__FreeBSD__) && __FreeBSD_version < 400001
43767468Snon	free(periph, M_DEVBUF);
43867468Snon#endif
43967468Snon}
44067468Snon
44167468Snonstatic void
44267468Snonscsi_low_rescan_bus(struct scsi_low_softc *slp)
44367468Snon{
44467468Snon  	struct cam_path *path;
44567468Snon	union ccb *ccb = malloc(sizeof(union ccb), M_DEVBUF, M_WAITOK);
44667468Snon#if defined(__FreeBSD__) && __FreeBSD_version < 400001
44767468Snon	struct cam_periph *xpt_periph = malloc(sizeof(struct cam_periph),
44867468Snon					       M_DEVBUF, M_WAITOK);
44967468Snon#endif
45067468Snon	cam_status status;
45167468Snon
45267468Snon	bzero(ccb, sizeof(union ccb));
45367468Snon
45467468Snon	status = xpt_create_path(&path, xpt_periph,
45567468Snon				 cam_sim_path(slp->sim), -1, 0);
45667468Snon	if (status != CAM_REQ_CMP)
45767468Snon		return;
45867468Snon
45967468Snon	xpt_setup_ccb(&ccb->ccb_h, path, 5);
46067468Snon	ccb->ccb_h.func_code = XPT_SCAN_BUS;
46167468Snon	ccb->ccb_h.cbfcnp = scsi_low_cam_rescan_callback;
46267468Snon	ccb->crcn.flags = CAM_FLAG_NONE;
46367468Snon	xpt_action(ccb);
46467468Snon}
46567468Snon#endif
46667468Snon
46767468Snonint
46867468Snonscsi_low_attach(slp, openings, ntargs, nluns, lunsize)
46967468Snon	struct scsi_low_softc *slp;
47067468Snon	int openings, ntargs, nluns, lunsize;
47167468Snon{
47267468Snon	struct targ_info *ti;
47367468Snon	struct lun_info *li;
47467468Snon#ifdef CAM
47567468Snon	struct cam_devq *devq;
47667468Snon#else
47767468Snon	struct scsipi_adapter *sap;
47867468Snon#endif
47967468Snon	int i, nccb;
48067468Snon
48167468Snon#ifdef CAM
48267468Snon	OS_DEPEND(sprintf(slp->sl_xname, "%s%d",
48367468Snon			  DEVPORT_DEVNAME(slp->sl_dev), DEVPORT_DEVUNIT(slp->sl_dev)));
48467468Snon#else
48567468Snon	OS_DEPEND(strncpy(slp->sl_xname, DEVPORT_DEVNAME(slp->sl_dev), 16));
48667468Snon#endif
48767468Snon	if (ntargs > SCSI_LOW_NTARGETS)
48867468Snon	{
48967468Snon		printf("scsi_low: %d targets are too large\n", ntargs);
49067468Snon		printf("change kernel options SCSI_LOW_NTARGETS");
49167468Snon	}
49267468Snon
49367468Snon	if (lunsize < sizeof(struct lun_info))
49467468Snon		lunsize = sizeof(struct lun_info);
49567468Snon
49667468Snon	for (i = 0; i < ntargs; i ++)
49767468Snon	{
49867468Snon		ti = scsi_low_alloc_ti(slp, i);
49967468Snon		ti->ti_lunsize = lunsize;
50067468Snon		li = scsi_low_alloc_li(ti, 0, 1);
50167468Snon	}
50267468Snon
50367468Snon#ifndef CAM
50467468Snon	sap = malloc(sizeof(*sap), M_DEVBUF, M_NOWAIT);
50567468Snon	if (sap == NULL)
50667468Snon		return ENOMEM;
50767468Snon
50867468Snon	memset(sap, 0, sizeof(*sap));
50967468Snon	sap->scsipi_cmd = scsi_low_scsi_cmd;
51067468Snon	sap->scsipi_minphys = scsi_low_scsi_minphys;
51167468Snon#ifdef	SCSI_LOW_TARGET_OPEN
51267468Snon	sap->open_target_lu = scsi_low_target_open;
51367468Snon#endif	/* SCSI_LOW_TARGET_OPEN */
51467468Snon#endif
51567468Snon
51667468Snon	if (scsi_low_init(slp, SCSI_LOW_RESTART_HARD) != 0)
51767468Snon		return EINVAL;
51867468Snon
51967468Snon	/* initialize queue */
52067468Snon	nccb = openings * (ntargs - 1);
52167468Snon	if (nccb >= SCSI_LOW_NCCB || nccb <= 0)
52267468Snon		nccb = SCSI_LOW_NCCB;
52367468Snon	scsi_low_init_ccbque(nccb);
52467468Snon	TAILQ_INIT(&slp->sl_start);
52567468Snon
52667468Snon	slp->sl_openings = openings;
52767468Snon	slp->sl_ntargs = ntargs;
52867468Snon	slp->sl_nluns = nluns;
52967468Snon
53067468Snon#ifdef CAM
53167468Snon	/*
53267468Snon	 * Prepare the scsibus_data area for the upperlevel
53367468Snon	 * scsi code.
53467468Snon	 */
53567468Snon	devq = cam_simq_alloc(256/*MAX_START*/);
53667468Snon	if (devq == NULL)
53767468Snon		return (0);
53867468Snon	/*	scbus->adapter_link = &slp->sc_link; */
53967468Snon	/*
54067468Snon	 * ask the adapter what subunits are present
54167468Snon	 */
54267468Snon
54367468Snon	slp->sim = cam_sim_alloc(scsi_low_scsi_action, scsi_low_poll,
54467468Snon				 DEVPORT_DEVNAME(slp->sl_dev), slp,
54567468Snon				 DEVPORT_DEVUNIT(slp->sl_dev), 1, 32/*MAX_TAGS*/, devq);
54667468Snon       if (slp->sim == NULL) {
54767468Snon	 cam_simq_free(devq);
54867468Snon	 return 0;
54967468Snon       }
55067468Snon
55167468Snon       if (xpt_bus_register(slp->sim, 0) != CAM_SUCCESS) {
55267468Snon	 free(slp->sim, M_DEVBUF);
55367468Snon	 return 0;
55467468Snon       }
55567468Snon
55667468Snon       if (xpt_create_path(&slp->path, /*periph*/NULL,
55767468Snon                           cam_sim_path(slp->sim), CAM_TARGET_WILDCARD,
55867468Snon			   CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
55967468Snon	 xpt_bus_deregister(cam_sim_path(slp->sim));
56067468Snon	 cam_sim_free(slp->sim, /*free_simq*/TRUE);
56167468Snon	 free(slp->sim, M_DEVBUF);
56267468Snon	 return 0;
56367468Snon       }
56467468Snon#else /* !CAM */
56567468Snon	slp->sl_link.adapter_softc = slp;
56667468Snon	slp->sl_link.scsipi_scsi.adapter_target = slp->sl_hostid;
56767468Snon	slp->sl_link.scsipi_scsi.max_target = ntargs - 1;
56867468Snon	slp->sl_link.scsipi_scsi.max_lun = nluns - 1;
56967468Snon	slp->sl_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
57067468Snon	slp->sl_link.openings = openings;
57167468Snon	slp->sl_link.type = BUS_SCSI;
57267468Snon	slp->sl_link.adapter_softc = slp;
57367468Snon	slp->sl_link.adapter = sap;
57467468Snon	slp->sl_link.device = &scsi_low_dev;
57567468Snon#endif
57667468Snon
57767468Snon	/* start watch dog */
57867468Snon	slp->sl_max_retry = SCSI_LOW_MAX_RETRY;
57967468Snon#ifdef __FreeBSD__
58067468Snon	slp->timeout_ch =
58167468Snon#endif
58267468Snon	timeout(scsi_low_timeout, slp, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz);
58367468Snon#ifdef CAM
58467468Snon	if (!cold)
58567468Snon		scsi_low_rescan_bus(slp);
58667468Snon#endif
58767468Snon
58867468Snon	return 0;
58967468Snon}
59067468Snon
59167468Snon#ifndef CAM
59267468Snonstatic void
59367468Snonscsi_low_scsi_minphys(bp)
59467468Snon	struct buf *bp;
59567468Snon{
59667468Snon
59767468Snon	if (bp->b_bcount > SCSI_LOW_MINPHYS)
59867468Snon		bp->b_bcount = SCSI_LOW_MINPHYS;
59967468Snon	minphys(bp);
60067468Snon}
60167468Snon#endif
60267468Snon
60367468Snonint
60467468Snonscsi_low_dettach(slp)
60567468Snon	struct scsi_low_softc *slp;
60667468Snon{
60767468Snon
60871999Sphk	if (slp->sl_disc > 0 || TAILQ_FIRST(&slp->sl_start) != NULL)
60967468Snon		return EBUSY;
61067468Snon
61167468Snon	/*
61267468Snon	 * scsipi does not have dettach bus fucntion.
61367468Snon	 *
61467468Snon	scsipi_dettach_scsibus(&slp->sl_link);
61567468Snon	*/
61667468Snon
61767468Snon#ifdef CAM
61867468Snon	xpt_async(AC_LOST_DEVICE, slp->path, NULL);
61967468Snon	xpt_free_path(slp->path);
62067468Snon	xpt_bus_deregister(cam_sim_path(slp->sim));
62167468Snon	cam_sim_free(slp->sim, /* free_devq */ TRUE);
62267468Snon#endif
62367468Snon
62467468Snon	scsi_low_free_ti(slp);
62567468Snon	return 0;
62667468Snon}
62767468Snon
62867468Snon#ifdef CAM
62967468Snonstatic void
63067468Snonscsi_low_poll(struct cam_sim *sim)
63167468Snon{
63267468Snon	struct scsi_low_softc *slp = (struct scsi_low_softc *) cam_sim_softc(sim);
63367468Snon	(*slp->sl_funcs->scsi_low_poll) (slp);
63467468Snon}
63567468Snon
63667468Snonvoid
63767468Snonscsi_low_scsi_action(struct cam_sim *sim, union ccb *ccb)
63867468Snon{
63967468Snon	struct scsi_low_softc *slp = (struct scsi_low_softc *) cam_sim_softc(sim);
64067468Snon	int s, target = (u_int) (ccb->ccb_h.target_id);
64167468Snon	struct targ_info *ti;
64267468Snon	struct lun_info *li;
64367468Snon	struct slccb *cb;
64467468Snon
64567468Snon#if 0
64667468Snon	printf("scsi_low_scsi_action() func code %d Target: %d, LUN: %d\n",
64767468Snon	       ccb->ccb_h.func_code, target, ccb->ccb_h.target_lun);
64867468Snon#endif
64967468Snon	switch (ccb->ccb_h.func_code) {
65067468Snon	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
65167468Snon		if (((cb = scsi_low_get_ccb()) == NULL)) {
65267468Snon			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
65367468Snon			xpt_done(ccb);
65467468Snon			return;
65567468Snon		}
65667468Snon
65767468Snon		cb->ccb = ccb;
65867468Snon		cb->ccb_tag = SCSI_LOW_UNKTAG;
65967468Snon		cb->bp = (struct buf *)NULL;
66067468Snon		cb->ti = ti = slp->sl_ti[target];
66167468Snon		cb->li = scsi_low_alloc_li(ti, ccb->ccb_h.target_lun, 1);
66267468Snon		cb->ccb_flags = 0;
66367468Snon		cb->ccb_rcnt = 0;
66467468Snon
66567468Snon		s = splcam();
66667468Snon
66767468Snon		TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain);
66867468Snon
66967468Snon		if (slp->sl_nexus == NULL) {
67067468Snon			scsi_low_start(slp);
67167468Snon		}
67267468Snon
67367468Snon		splx(s);
67467468Snon		break;
67567468Snon	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
67667468Snon	case XPT_EN_LUN:		/* Enable LUN as a target */
67767468Snon	case XPT_TARGET_IO:		/* Execute target I/O request */
67867468Snon	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
67967468Snon	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
68067468Snon	case XPT_ABORT:			/* Abort the specified CCB */
68167468Snon		/* XXX Implement */
68267468Snon		ccb->ccb_h.status = CAM_REQ_INVALID;
68367468Snon		xpt_done(ccb);
68467468Snon		break;
68567468Snon	case XPT_SET_TRAN_SETTINGS:
68667468Snon		/* XXX Implement */
68767468Snon		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
68867468Snon		xpt_done(ccb);
68967468Snon		break;
69067468Snon	case XPT_GET_TRAN_SETTINGS: {
69167468Snon		struct ccb_trans_settings *cts;
69267468Snon		struct targ_info *ti;
69367468Snon		int lun = ccb->ccb_h.target_lun;
69467468Snon		/*int s;*/
69567468Snon
69667468Snon		cts = &ccb->cts;
69767468Snon		ti = slp->sl_ti[ccb->ccb_h.target_id];
69867468Snon		li = LIST_FIRST(&ti->ti_litab);
69967468Snon		if (li != NULL && li->li_lun != lun)
70067468Snon			while ((li = LIST_NEXT(li, lun_chain)) != NULL)
70167468Snon				if (li->li_lun == lun)
70267468Snon					break;
70367468Snon		s = splcam();
70467468Snon		if (li != NULL && (cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
70567468Snon			if (li->li_cfgflags & SCSI_LOW_DISC)
70667468Snon				cts->flags = CCB_TRANS_DISC_ENB;
70767468Snon			else
70867468Snon				cts->flags = 0;
70967468Snon			if (li->li_cfgflags & SCSI_LOW_QTAG)
71067468Snon				cts->flags |= CCB_TRANS_TAG_ENB;
71167468Snon
71267468Snon			cts->bus_width = 0;/*HN2*/
71367468Snon
71467468Snon			cts->valid = CCB_TRANS_SYNC_RATE_VALID
71567468Snon				   | CCB_TRANS_SYNC_OFFSET_VALID
71667468Snon				   | CCB_TRANS_BUS_WIDTH_VALID
71767468Snon				   | CCB_TRANS_DISC_VALID
71867468Snon				   | CCB_TRANS_TQ_VALID;
71967468Snon			ccb->ccb_h.status = CAM_REQ_CMP;
72067468Snon		} else
72167468Snon			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
72267468Snon
72367468Snon		splx(s);
72467468Snon		xpt_done(ccb);
72567468Snon		break;
72667468Snon	}
72767468Snon	case XPT_CALC_GEOMETRY: { /* not yet HN2 */
72867468Snon		struct	  ccb_calc_geometry *ccg;
72967468Snon		u_int32_t size_mb;
73067468Snon		u_int32_t secs_per_cylinder;
73167468Snon		int       extended;
73267468Snon
73367468Snon		extended = 1;
73467468Snon		ccg = &ccb->ccg;
73567468Snon		size_mb = ccg->volume_size
73667468Snon			/ ((1024L * 1024L) / ccg->block_size);
73767468Snon
73867468Snon		if (size_mb > 1024 && extended) {
73967468Snon		        ccg->heads = 255;
74067468Snon		        ccg->secs_per_track = 63;
74167468Snon		} else {
74267468Snon		        ccg->heads = 64;
74367468Snon		        ccg->secs_per_track = 32;
74467468Snon		}
74567468Snon		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
74667468Snon		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
74767468Snon		ccb->ccb_h.status = CAM_REQ_CMP;
74867468Snon		xpt_done(ccb);
74967468Snon		break;
75067468Snon	}
75167468Snon	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
75267468Snon#if 0
75367468Snon	  	scsi_low_bus_reset(slp);
75467468Snon#endif
75567468Snon		ccb->ccb_h.status = CAM_REQ_CMP;
75667468Snon		xpt_done(ccb);
75767468Snon		break;
75867468Snon	case XPT_TERM_IO:		/* Terminate the I/O process */
75967468Snon		/* XXX Implement */
76067468Snon		ccb->ccb_h.status = CAM_REQ_INVALID;
76167468Snon		xpt_done(ccb);
76267468Snon		break;
76367468Snon	case XPT_PATH_INQ: {		/* Path routing inquiry */
76467468Snon		struct ccb_pathinq *cpi = &ccb->cpi;
76567468Snon
76667468Snon		cpi->version_num = 1; /* XXX??? */
76767468Snon		cpi->hba_inquiry = PI_SDTR_ABLE;
76867468Snon		cpi->target_sprt = 0;
76967468Snon		cpi->hba_misc = 0;
77067468Snon		cpi->hba_eng_cnt = 0;
77167468Snon		cpi->max_target = SCSI_LOW_NTARGETS - 1;
77267468Snon		cpi->max_lun = 7;
77367468Snon		cpi->initiator_id = 7; /* HOST_SCSI_ID */
77467468Snon		cpi->bus_id = cam_sim_bus(sim);
77567468Snon		cpi->base_transfer_speed = 3300;
77667468Snon		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
77767468Snon		strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN);
77867468Snon		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
77967468Snon		cpi->unit_number = cam_sim_unit(sim);
78067468Snon		cpi->ccb_h.status = CAM_REQ_CMP;
78167468Snon		xpt_done(ccb);
78267468Snon		break;
78367468Snon	}
78467468Snon	default:
78567468Snon	        printf("scsi_low: non support func_code = %d ", ccb->ccb_h.func_code);
78667468Snon		ccb->ccb_h.status = CAM_REQ_INVALID;
78767468Snon		xpt_done(ccb);
78867468Snon		break;
78967468Snon	}
79067468Snon}
79167468Snon#else /* !CAM */
79267468Snonstatic int
79367468Snonscsi_low_scsi_cmd(xs)
79467468Snon	struct scsipi_xfer *xs;
79567468Snon{
79667468Snon	struct scsi_low_softc *slp = xs->sc_link->adapter_softc;
79767468Snon	struct targ_info *ti;
79867468Snon	struct slccb *cb;
79967468Snon	int s, lun, timeo;
80067468Snon
80167468Snon	if (slp->sl_cfgflags & CFG_NOATTEN)
80267468Snon	{
80367468Snon		if (xs->sc_link->scsipi_scsi.lun > 0)
80467468Snon		{
80567468Snon			xs->error = XS_DRIVER_STUFFUP;
80667468Snon			return COMPLETE;
80767468Snon		}
80867468Snon	}
80967468Snon
81067468Snon	if ((cb = scsi_low_get_ccb(xs->flags & SCSI_NOSLEEP)) == NULL)
81167468Snon		return TRY_AGAIN_LATER;
81267468Snon
81367468Snon	lun = xs->sc_link->scsipi_scsi.lun;
81467468Snon	cb->xs = xs;
81567468Snon	cb->ccb_tag = SCSI_LOW_UNKTAG;
81667468Snon	cb->ti = ti = slp->sl_ti[xs->sc_link->scsipi_scsi.target];
81767468Snon	cb->li = scsi_low_alloc_li(ti, lun, 1);
81867468Snon	cb->ccb_flags = 0;
81967468Snon	cb->ccb_rcnt = 0;
82067468Snon
82167468Snon	s = splbio();
82267468Snon
82367468Snon	TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain);
82467468Snon	if (slp->sl_nexus == NULL)
82567468Snon		scsi_low_start(slp);
82667468Snon
82767468Snon	if ((xs->flags & SCSI_POLL) == 0)
82867468Snon	{
82967468Snon		splx(s);
83067468Snon		return SUCCESSFULLY_QUEUED;
83167468Snon	}
83267468Snon
83367468Snon#define	SCSI_LOW_POLL_INTERVAL	1000		/* 1 ms */
83467468Snon	timeo = xs->timeout * (1000 / SCSI_LOW_POLL_INTERVAL);
83567468Snon
83667468Snon	while ((xs->flags & ITSDONE) == 0 && timeo -- > 0)
83767468Snon	{
83867468Snon		delay(SCSI_LOW_POLL_INTERVAL);
83967468Snon		(*slp->sl_funcs->scsi_low_poll) (slp);
84067468Snon	}
84167468Snon
84267468Snon	if ((xs->flags & ITSDONE) == 0)
84367468Snon	{
84467468Snon		cb->ccb_error |= (TIMEOUTIO | ABORTIO);
84567468Snon		SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL);
84667468Snon		scsi_low_disconnected(slp, ti);
84767468Snon		scsi_low_init(slp, SCSI_LOW_RESTART_HARD);
84867468Snon	}
84967468Snon
85067468Snon	scsipi_done(xs);
85167468Snon	splx(s);
85267468Snon	return COMPLETE;
85367468Snon}
85467468Snon#endif
85567468Snon
85667468Snon/**************************************************************
85767468Snon * Start & Done
85867468Snon **************************************************************/
85967468Snon#ifdef __NetBSD__
86067468Snonstatic struct scsipi_start_stop ss_cmd = { START_STOP, 0, {0,0,}, SSS_START, };
86167468Snonstatic struct scsipi_test_unit_ready unit_ready_cmd;
86267468Snon#endif
86367468Snon#ifdef __FreeBSD__
86467468Snonstatic struct scsi_start_stop_unit ss_cmd = { START_STOP, 0, {0,0,}, SSS_START, };
86567468Snonstatic struct scsi_test_unit_ready unit_ready_cmd;
86667468Snon#endif
86767468Snonstatic void scsi_low_unit_ready_cmd __P((struct slccb *));
86867468Snon
86967468Snonstatic void
87067468Snonscsi_low_unit_ready_cmd(cb)
87167468Snon	struct slccb *cb;
87267468Snon{
87367468Snon
87467468Snon	cb->ccb_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd;
87567468Snon	cb->ccb_scp.scp_cmdlen = sizeof(unit_ready_cmd);
87667468Snon	cb->ccb_scp.scp_datalen = 0;
87767468Snon	cb->ccb_scp.scp_direction = SCSI_LOW_READ;
87867468Snon	cb->ccb_tcmax = 15;
87967468Snon}
88067468Snon
88167468Snonstatic void
88267468Snonscsi_low_start(slp)
88367468Snon	struct scsi_low_softc *slp;
88467468Snon{
88567468Snon#ifdef CAM
88667468Snon        union ccb *ccb;
88767468Snon#else
88867468Snon	struct scsipi_xfer *xs;
88967468Snon#endif
89067468Snon	struct targ_info *ti;
89167468Snon	struct lun_info *li;
89267468Snon	struct slccb *cb;
89367468Snon	int rv;
89467468Snon
89567468Snon	/* check hardware exists ? */
89667468Snon	if ((slp->sl_flags & HW_INACTIVE) != 0)
89767468Snon		return;
89867468Snon
89967468Snon	/* check hardware power up ? */
90067468Snon	if ((slp->sl_flags & HW_POWERCTRL) != 0)
90167468Snon	{
90267468Snon		slp->sl_active ++;
90367468Snon		if (slp->sl_flags & (HW_POWDOWN | HW_RESUME))
90467468Snon		{
90567468Snon			if (slp->sl_flags & HW_RESUME)
90667468Snon				return;
90767468Snon			slp->sl_flags &= ~HW_POWDOWN;
90867468Snon			if (slp->sl_funcs->scsi_low_power != NULL)
90967468Snon			{
91067468Snon				slp->sl_flags |= HW_RESUME;
91167468Snon				slp->sl_rstep = 0;
91267468Snon				(*slp->sl_funcs->scsi_low_power)
91367468Snon					(slp, SCSI_LOW_ENGAGE);
91467468Snon#ifdef __FreeBSD__
91567468Snon				slp->engage_ch =
91667468Snon#endif
91767468Snon				timeout(scsi_low_engage, slp, 1);
91867468Snon				return;
91967468Snon			}
92067468Snon		}
92167468Snon	}
92267468Snon
92367468Snon	/* setup nexus */
92467468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
92567468Snon	ti = slp->sl_nexus;
92667468Snon	if (ti != NULL)
92767468Snon	{
92867468Snon		scsi_low_info(slp, NULL, "NEXUS INCOSISTENT");
92967468Snon		panic("%s: inconsistent(target)\n", slp->sl_xname);
93067468Snon	}
93167468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
93267468Snon
93371999Sphk	for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL;
93471999Sphk	     cb = TAILQ_NEXT(cb, ccb_chain))
93567468Snon	{
93667468Snon		ti = cb->ti;
93767468Snon		li = cb->li;
93867468Snon		if (ti->ti_phase == PH_NULL)
93967468Snon			goto scsi_low_cmd_start;
94067468Snon		if (ti->ti_phase == PH_DISC && li->li_disc < li->li_maxnexus)
94167468Snon			goto scsi_low_cmd_start;
94267468Snon	}
94367468Snon	return;
94467468Snon
94567468Snonscsi_low_cmd_start:
94667468Snon#ifdef CAM
94767468Snon	ccb = cb->ccb;
94867468Snon#else
94967468Snon	xs = cb->xs;
95067468Snon#endif
95167468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
95267468Snon	if (ti->ti_nexus != NULL || ti->ti_li != NULL)
95367468Snon	{
95467468Snon		scsi_low_info(slp, NULL, "NEXUS INCOSISTENT");
95567468Snon		panic("%s: inconsistent(lun or ccb)\n", slp->sl_xname);
95667468Snon	}
95767468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
95867468Snon
95967468Snon	/* clear all error flag bits (for restart) */
96067468Snon	cb->ccb_error = 0;
96167468Snon
96267468Snon	/* setup nexus pointer */
96367468Snon	ti->ti_nexus = cb;
96467468Snon	ti->ti_li = li;
96567468Snon	slp->sl_nexus = ti;
96667468Snon
96767468Snon	/* initialize msgsys */
96867468Snon	scsi_low_init_msgsys(slp, ti);
96967468Snon
97067468Snon	/* target lun state check */
97167468Snon#ifdef CAM
97267468Snon		li->li_maxstate = UNIT_OK;
97367468Snon#else
97467468Snon	if ((xs->flags & SCSI_POLL) != 0)
97567468Snon		li->li_maxstate = UNIT_NEGSTART;
97667468Snon	else
97767468Snon		li->li_maxstate = UNIT_OK;
97867468Snon#endif
97967468Snon
98067468Snon	/* exec cmds */
98167468Snonscsi_low_cmd_exec:
98267468Snon	if ((cb->ccb_flags & CCB_SENSE) != 0)
98367468Snon	{
98467468Snon		memset(&cb->ccb_sense, 0, sizeof(cb->ccb_sense));
98567468Snon#ifdef CAM
98667468Snon#else
98767468Snon		cb->ccb_sense_cmd.opcode = REQUEST_SENSE;
98867468Snon		cb->ccb_sense_cmd.byte2 = (li->li_lun << 5);
98967468Snon		cb->ccb_sense_cmd.length = sizeof(cb->ccb_sense);
99067468Snon#endif
99167468Snon		cb->ccb_scp.scp_cmd = (u_int8_t *) &cb->ccb_sense_cmd;
99267468Snon		cb->ccb_scp.scp_cmdlen = sizeof(cb->ccb_sense_cmd);
99367468Snon		cb->ccb_scp.scp_data = (u_int8_t *) &cb->ccb_sense;
99467468Snon		cb->ccb_scp.scp_datalen = sizeof(cb->ccb_sense);
99567468Snon		cb->ccb_scp.scp_direction = SCSI_LOW_READ;
99667468Snon		cb->ccb_tcmax = 15;
99767468Snon	}
99867468Snon	else if (li->li_state >= li->li_maxstate)
99967468Snon	{
100067468Snon#ifdef CAM
100167468Snon		cb->ccb_scp.scp_cmd = ccb->csio.cdb_io.cdb_bytes;
100267468Snon		cb->ccb_scp.scp_cmdlen = (int) ccb->csio.cdb_len;
100367468Snon		cb->ccb_scp.scp_data = ccb->csio.data_ptr;
100467468Snon		cb->ccb_scp.scp_datalen = (int) ccb->csio.dxfer_len;
100567468Snon		if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
100667468Snon			cb->ccb_scp.scp_direction = SCSI_LOW_WRITE;
100767468Snon		else /* if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) */
100867468Snon			cb->ccb_scp.scp_direction = SCSI_LOW_READ;
100967468Snon		cb->ccb_tcmax = (ccb->ccb_h.timeout >> 10);
101067468Snon#else
101167468Snon		cb->ccb_scp.scp_cmd = (u_int8_t *) xs->cmd;
101267468Snon		cb->ccb_scp.scp_cmdlen = xs->cmdlen;
101367468Snon		cb->ccb_scp.scp_data = xs->data;
101467468Snon		cb->ccb_scp.scp_datalen = xs->datalen;
101567468Snon		cb->ccb_scp.scp_direction = (xs->flags & SCSI_DATA_OUT) ?
101667468Snon				SCSI_LOW_WRITE : SCSI_LOW_READ;
101767468Snon		cb->ccb_tcmax = (xs->timeout >> 10);
101867468Snon#endif
101967468Snon
102067468Snon	}
102167468Snon	else switch(li->li_state)
102267468Snon	{
102367468Snon	case UNIT_SLEEP:
102467468Snon		scsi_low_unit_ready_cmd(cb);
102567468Snon		break;
102667468Snon
102767468Snon	case UNIT_START:
102867468Snon		cb->ccb_scp.scp_cmd = (u_int8_t *) &ss_cmd;
102967468Snon		cb->ccb_scp.scp_cmdlen = sizeof(ss_cmd);
103067468Snon		cb->ccb_scp.scp_datalen = 0;
103167468Snon		cb->ccb_scp.scp_direction = SCSI_LOW_READ;
103267468Snon		cb->ccb_tcmax = 30;
103367468Snon		break;
103467468Snon
103567468Snon	case UNIT_SYNCH:
103667468Snon		if (li->li_maxsynch.offset > 0)
103767468Snon		{
103867468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0);
103967468Snon			scsi_low_unit_ready_cmd(cb);
104067468Snon			break;
104167468Snon		}
104267468Snon		li->li_state = UNIT_WIDE;
104367468Snon
104467468Snon	case UNIT_WIDE:
104567468Snon#ifdef	SCSI_LOW_SUPPORT_WIDE
104667468Snon		if (li->li_width > 0)
104767468Snon		{
104867468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0);
104967468Snon			scsi_low_unit_ready_cmd(cb);
105067468Snon			break;
105167468Snon		}
105267468Snon#endif	/* SCSI_LOW_SUPPORT_WIDE */
105367468Snon		li->li_state = UNIT_OK;
105467468Snon
105567468Snon	case UNIT_OK:
105667468Snon		goto scsi_low_cmd_exec;
105767468Snon	}
105867468Snon
105967468Snon	/* timeout */
106067468Snon	if (cb->ccb_tcmax < SCSI_LOW_MIN_TOUT)
106167468Snon		cb->ccb_tcmax = SCSI_LOW_MIN_TOUT;
106267468Snon	cb->ccb_tc = cb->ccb_tcmax;
106367468Snon
106467468Snon	/* setup saved scsi data pointer */
106567468Snon	cb->ccb_sscp = cb->ccb_scp;
106667468Snon
106767468Snon	/* setup current scsi pointer */
106867468Snon	slp->sl_scp = cb->ccb_sscp;
106967468Snon	slp->sl_error = cb->ccb_error;
107067468Snon
107167468Snon	/* selection start */
107267468Snon	slp->sl_selid = ti;
107367468Snon	rv = ((*slp->sl_funcs->scsi_low_start_bus) (slp, cb));
107467468Snon	if (rv == SCSI_LOW_START_OK)
107567468Snon	{
107667468Snon#ifdef	SCSI_LOW_STATICS
107767468Snon		scsi_low_statics.nexus_win ++;
107867468Snon#endif	/* SCSI_LOW_STATICS */
107967468Snon		return;
108067468Snon	}
108167468Snon
108267468Snon#ifdef	SCSI_LOW_STATICS
108367468Snon	scsi_low_statics.nexus_fail ++;
108467468Snon#endif	/* SCSI_LOW_STATICS */
108567468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_NULL);
108667468Snon	scsi_low_clear_nexus(slp, ti);
108767468Snon}
108867468Snon
108967468Snonvoid
109067468Snonscsi_low_clear_nexus(slp, ti)
109167468Snon	struct scsi_low_softc *slp;
109267468Snon	struct targ_info *ti;
109367468Snon{
109467468Snon
109567468Snon	/* clear all nexus pointer */
109667468Snon	ti->ti_nexus = NULL;
109767468Snon	ti->ti_li = NULL;
109867468Snon	slp->sl_nexus = NULL;
109967468Snon
110067468Snon	/* clear selection assert */
110167468Snon	slp->sl_selid = NULL;
110267468Snon
110367468Snon	/* clear nexus data */
110467468Snon	slp->sl_nexus_call = 0;
110567468Snon	slp->sl_scp.scp_direction = SCSI_LOW_RWUNK;
110667468Snon}
110767468Snon
110867468Snonstatic int
110967468Snonscsi_low_done(slp, cb)
111067468Snon	struct scsi_low_softc *slp;
111167468Snon	struct slccb *cb;
111267468Snon{
111367468Snon#ifdef CAM
111467468Snon	union ccb *ccb;
111567468Snon#else
111667468Snon	struct scsipi_xfer *xs;
111767468Snon#endif
111867468Snon	struct targ_info *ti;
111967468Snon	struct lun_info *li;
112067468Snon
112167468Snon	ti = cb->ti;
112267468Snon	li = cb->li;
112367468Snon#ifdef CAM
112467468Snon	ccb = cb->ccb;
112567468Snon#else
112667468Snon	xs = cb->xs;
112767468Snon#endif
112867468Snon	if (cb->ccb_error == 0)
112967468Snon	{
113067468Snon		if ((cb->ccb_flags & CCB_SENSE) != 0)
113167468Snon		{
113267468Snon			cb->ccb_flags &= ~CCB_SENSE;
113367468Snon#ifdef CAM
113467468Snon			ccb->csio.sense_data = cb->ccb_sense;
113567468Snon			/* ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; */
113667468Snon			ccb->ccb_h.status = CAM_REQ_CMP;
113767468Snon			/* ccb->ccb_h.status = CAM_AUTOSNS_VALID|CAM_SCSI_STATUS_ERROR; */
113867468Snon#else
113967468Snon			xs->sense.scsi_sense = cb->ccb_sense;
114067468Snon			xs->error = XS_SENSE;
114167468Snon#endif
114267468Snon		}
114367468Snon		else switch (ti->ti_status)
114467468Snon		{
114567468Snon		case ST_GOOD:
114667468Snon			if (slp->sl_scp.scp_datalen == 0)
114767468Snon			{
114867468Snon#ifdef CAM
114967468Snon				ccb->ccb_h.status = CAM_REQ_CMP;
115067468Snon#else
115167468Snon				xs->error = XS_NOERROR;
115267468Snon#endif
115367468Snon				break;
115467468Snon			}
115567468Snon
115667468Snon#define	SCSIPI_SCSI_CD_COMPLETELY_BUGGY	"YES"
115767468Snon#ifdef	SCSIPI_SCSI_CD_COMPLETELY_BUGGY
115867468Snon#ifdef CAM
115967468Snon			if (/* cb->bp == NULL &&  */
116067468Snon			    slp->sl_scp.scp_datalen < cb->ccb_scp.scp_datalen)
116167468Snon#else
116267468Snon			if (xs->bp == NULL &&
116367468Snon			    slp->sl_scp.scp_datalen < cb->ccb_scp.scp_datalen)
116467468Snon#endif
116567468Snon			{
116667468Snon#ifdef CAM
116767468Snon				ccb->ccb_h.status = CAM_REQ_CMP;
116867468Snon#else
116967468Snon				xs->error = XS_NOERROR;
117067468Snon#endif
117167468Snon				break;
117267468Snon			}
117367468Snon#endif	/* SCSIPI_SCSI_CD_COMPLETELY_BUGGY */
117467468Snon
117567468Snon			cb->ccb_error |= PDMAERR;
117667468Snon#ifdef CAM
117767468Snon			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
117867468Snon#else
117967468Snon			xs->error = XS_DRIVER_STUFFUP;
118067468Snon#endif
118167468Snon			break;
118267468Snon
118367468Snon		case ST_CHKCOND:
118467468Snon		case ST_MET:
118567468Snon			cb->ccb_flags |= CCB_SENSE;
118667468Snon#ifdef CAM
118767468Snon			ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
118867468Snon#else
118967468Snon			xs->error = XS_SENSE;
119067468Snon#endif
119167468Snon			goto retry;
119267468Snon
119367468Snon		case ST_BUSY:
119467468Snon			cb->ccb_error |= BUSYERR;
119567468Snon#ifdef CAM
119667468Snon			ccb->ccb_h.status = CAM_BUSY; /* SCSI_STATUS_ERROR; */
119767468Snon#else
119867468Snon			xs->error = XS_BUSY;
119967468Snon#endif
120067468Snon			break;
120167468Snon
120267468Snon		default:
120367468Snon			cb->ccb_error |= FATALIO;
120467468Snon#ifdef CAM
120567468Snon			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
120667468Snon#else
120767468Snon			xs->error = XS_DRIVER_STUFFUP;
120867468Snon#endif
120967468Snon			break;
121067468Snon		}
121167468Snon	}
121267468Snon	else
121367468Snon	{
121467468Snon		cb->ccb_flags &= ~CCB_SENSE;
121567468Snon		if (ti->ti_phase == PH_SELSTART)
121667468Snon		{
121767468Snon#ifdef CAM
121867468Snon			ccb->ccb_h.status = CAM_CMD_TIMEOUT;
121967468Snon#else
122067468Snon			xs->error = XS_TIMEOUT;
122167468Snon#endif
122267468Snon			slp->sl_error |= SELTIMEOUTIO;
122367468Snon			if (li->li_state == UNIT_SLEEP)
122467468Snon				cb->ccb_error |= ABORTIO;
122567468Snon		}
122667468Snon		else
122767468Snon		{
122867468Snon#ifdef CAM
122967468Snon			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
123067468Snon#else
123167468Snon			xs->error = XS_DRIVER_STUFFUP;
123267468Snon#endif
123367468Snon		}
123467468Snon
123567468Snon		if ((cb->ccb_error & ABORTIO) != 0)
123667468Snon		{
123767468Snon			cb->ccb_rcnt = slp->sl_max_retry;
123867468Snon#ifdef CAM
123967468Snon			ccb->ccb_h.status = CAM_REQ_ABORTED;
124067468Snon#endif
124167468Snon		}
124267468Snon	}
124367468Snon
124467468Snon	/* target state check */
124567468Snon	if (li->li_state < li->li_maxstate)
124667468Snon	{
124767468Snon		if (cb->ccb_rcnt < slp->sl_max_retry)
124867468Snon		{
124967468Snon			li->li_state ++;
125067468Snon			cb->ccb_rcnt = 0;
125167468Snon			goto retry;
125267468Snon		}
125367468Snon	}
125467468Snon
125567468Snon	/* internal retry check */
125667468Snon#ifdef CAM
125767468Snon	if (ccb->ccb_h.status == CAM_REQ_CMP)
125867468Snon	{
125967468Snon		ccb->csio.resid = 0;
126067468Snon	}
126167468Snon	else
126267468Snon	{
126367468Snon#if 0
126467468Snon		if (ccb->ccb_h.status != CAM_AUTOSENSE_FAIL &&
126567468Snon		    cb->ccb_rcnt < slp->sl_max_retry)
126667468Snon			goto retry;
126767468Snon#endif
126867468Snon#else
126967468Snon	if (xs->error == XS_NOERROR)
127067468Snon	{
127167468Snon		xs->resid = 0;
127267468Snon	}
127367468Snon	else
127467468Snon	{
127567468Snon		if (xs->error != XS_SENSE &&
127667468Snon		    cb->ccb_rcnt < slp->sl_max_retry)
127767468Snon			goto retry;
127867468Snon#endif
127967468Snon
128067468Snon#ifndef CAM
128167468Snon#ifdef SCSI_LOW_WARNINGS
128267468Snon		if (xs->bp != NULL)
128367468Snon		{
128467468Snon			scsi_low_print(slp, ti);
128567468Snon			printf("%s: WARNING: File system IO abort\n",
128667468Snon				slp->sl_xname);
128767468Snon		}
128867468Snon#endif	/* SCSI_LOW_WARNINGS */
128967468Snon#endif
129067468Snon	}
129167468Snon
129267468Snon#ifdef CAM
129367468Snon	ccb->csio.scsi_status = ti->ti_status;
129467468Snon	xpt_done(ccb);
129567468Snon#else
129667468Snon	xs->flags |= ITSDONE;
129767468Snon	if ((xs->flags & SCSI_POLL) == 0)
129867468Snon		scsipi_done(xs);
129967468Snon#endif
130067468Snon
130167468Snon	/* free our target */
130267468Snon	TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain);
130367468Snon	scsi_low_free_ccb(cb);
130467468Snon	return SCSI_LOW_DONE_COMPLETE;
130567468Snon
130667468Snonretry:
130767468Snon	cb->ccb_rcnt ++;
130871999Sphk	if (TAILQ_FIRST(&slp->sl_start) != cb)
130967468Snon	{
131067468Snon		TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain);
131167468Snon		TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
131267468Snon	}
131367468Snon	return SCSI_LOW_DONE_RETRY;
131467468Snon}
131567468Snon
131667468Snon/**************************************************************
131767468Snon * Reset
131867468Snon **************************************************************/
131967468Snonstatic void
132067468Snonscsi_low_clear_ccb(cb)
132167468Snon	struct slccb *cb;
132267468Snon{
132367468Snon
132467468Snon	cb->ccb_flags &= ~CCB_SENSE;
132567468Snon	cb->ccb_tag = SCSI_LOW_UNKTAG;
132667468Snon}
132767468Snon
132867468Snonstatic void
132967468Snonscsi_low_reset_nexus(slp, fdone)
133067468Snon	struct scsi_low_softc *slp;
133167468Snon	int fdone;
133267468Snon{
133367468Snon	struct targ_info *ti;
133467468Snon	struct lun_info *li;
133567468Snon	struct slccb *cb, *ncb;
133667468Snon
133767468Snon	/* current nexus */
133867468Snon	ti = slp->sl_nexus;
133967468Snon	if (ti != NULL && (cb = ti->ti_nexus) != NULL)
134067468Snon	{
134167468Snon		scsi_low_clear_ccb(cb);
134267468Snon		if (fdone != 0 && cb->ccb_rcnt ++ >= slp->sl_max_retry)
134367468Snon		{
134467468Snon			cb->ccb_error |= FATALIO;
134567468Snon			scsi_low_done(slp, cb);
134667468Snon		}
134767468Snon	}
134867468Snon
134967468Snon	/* disconnected nexus */
135071999Sphk	for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
135171999Sphk	     ti = TAILQ_NEXT(ti, ti_chain))
135267468Snon	{
135371999Sphk		for (cb = TAILQ_FIRST(&ti->ti_discq); cb != NULL; cb = ncb)
135467468Snon		{
135571999Sphk		     	ncb = TAILQ_NEXT(cb, ccb_chain);
135667468Snon			TAILQ_REMOVE(&ti->ti_discq, cb, ccb_chain);
135767468Snon			TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
135867468Snon			scsi_low_clear_ccb(cb);
135967468Snon			if (fdone != 0 && cb->ccb_rcnt ++ >= slp->sl_max_retry)
136067468Snon			{
136167468Snon				cb->ccb_error |= FATALIO;
136267468Snon				scsi_low_done(slp, cb);
136367468Snon			}
136467468Snon		}
136567468Snon
136667468Snon		for (li = LIST_FIRST(&ti->ti_litab); li != NULL;
136767468Snon		     li = LIST_NEXT(li, lun_chain))
136867468Snon		{
136967468Snon			li->li_state = UNIT_SLEEP;
137067468Snon			li->li_disc = 0;
137167468Snon			((*slp->sl_funcs->scsi_low_lun_init) (slp, ti, li));
137267468Snon			scsi_low_calcf(ti, li);
137367468Snon		}
137467468Snon
137567468Snon		scsi_low_init_msgsys(slp, ti);
137667468Snon		scsi_low_clear_nexus(slp, ti);
137767468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_NULL);
137867468Snon	}
137967468Snon
138067468Snon	slp->sl_flags &= ~HW_PDMASTART;
138167468Snon	slp->sl_disc = 0;
138267468Snon}
138367468Snon
138467468Snon/* misc */
138567468Snonstatic int tw_pos;
138667468Snonstatic char tw_chars[] = "|/-\\";
138767468Snon
138867468Snonstatic void
138967468Snonscsi_low_twiddle_wait(void)
139067468Snon{
139167468Snon
139267468Snon	cnputc('\b');
139367468Snon	cnputc(tw_chars[tw_pos++]);
139467468Snon	tw_pos %= (sizeof(tw_chars) - 1);
139567468Snon	delay(TWIDDLEWAIT);
139667468Snon}
139767468Snon
139867468Snonvoid
139967468Snonscsi_low_bus_reset(slp)
140067468Snon	struct scsi_low_softc *slp;
140167468Snon{
140267468Snon	int i;
140367468Snon
140467468Snon	(*slp->sl_funcs->scsi_low_bus_reset) (slp);
140567468Snon
140667468Snon	printf("%s: try to reset scsi bus  ", slp->sl_xname);
140767468Snon	for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++)
140867468Snon		scsi_low_twiddle_wait();
140967468Snon	cnputc('\b');
141067468Snon	printf("\n");
141167468Snon}
141267468Snon
141367468Snonint
141467468Snonscsi_low_restart(slp, flags, s)
141567468Snon	struct scsi_low_softc *slp;
141667468Snon	int flags;
141767468Snon	u_char *s;
141867468Snon{
141967468Snon	int error;
142067468Snon
142167468Snon	if (s != NULL)
142267468Snon		printf("%s: scsi bus restart. reason: %s\n", slp->sl_xname, s);
142367468Snon
142467468Snon	if ((error = scsi_low_init(slp, flags)) != 0)
142567468Snon		return error;
142667468Snon
142767468Snon	scsi_low_start(slp);
142867468Snon	return 0;
142967468Snon}
143067468Snon
143167468Snon/**************************************************************
143267468Snon * disconnect and reselect
143367468Snon **************************************************************/
143467468Snon#define	MSGCMD_LUN(msg)	(msg & 0x07)
143567468Snon
143667468Snonstatic struct lun_info *
143767468Snonscsi_low_establish_lun(ti, lun)
143867468Snon	struct targ_info *ti;
143967468Snon	int lun;
144067468Snon{
144167468Snon	struct lun_info *li;
144267468Snon
144367468Snon	li = scsi_low_alloc_li(ti, lun, 0);
144467468Snon	if (li == NULL)
144567468Snon		return li;
144667468Snon
144767468Snon	ti->ti_li = li;
144867468Snon	return li;
144967468Snon}
145067468Snon
145167468Snonstatic struct slccb *
145267468Snonscsi_low_establish_ccb(ti, li, tag)
145367468Snon	struct targ_info *ti;
145467468Snon	struct lun_info *li;
145567468Snon	scsi_low_tag_t tag;
145667468Snon{
145767468Snon	struct scsi_low_softc *slp = ti->ti_sc;
145867468Snon	struct slccb *cb;
145967468Snon
146067468Snon	/*
146167468Snon	 * Search ccb matching with lun and tag.
146267468Snon	 */
146371999Sphk	cb = TAILQ_FIRST(&ti->ti_discq);
146471999Sphk	for ( ; cb != NULL; cb = TAILQ_NEXT(cb, ccb_chain))
146567468Snon		if (cb->li == li && cb->ccb_tag == tag)
146667468Snon			goto found;
146767468Snon	return cb;
146867468Snon
146967468Snon	/*
147067468Snon	 * establish our ccb nexus
147167468Snon	 */
147267468Snonfound:
147367468Snon	TAILQ_REMOVE(&ti->ti_discq, cb, ccb_chain);
147467468Snon	TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
147567468Snon	ti->ti_nexus = cb;
147667468Snon
147767468Snon	slp->sl_scp = cb->ccb_sscp;
147867468Snon	slp->sl_error |= cb->ccb_error;
147967468Snon
148067468Snon	slp->sl_disc --;
148167468Snon	li->li_disc --;
148267468Snon
148367468Snon	/* inform "ccb nexus established" to the host driver */
148467468Snon	slp->sl_nexus_call = 1;
148567468Snon	(*slp->sl_funcs->scsi_low_establish_nexus) (slp, ti);
148667468Snon	return cb;
148767468Snon}
148867468Snon
148967468Snonstruct targ_info *
149067468Snonscsi_low_reselected(slp, targ)
149167468Snon	struct scsi_low_softc *slp;
149267468Snon	u_int targ;
149367468Snon{
149467468Snon	struct targ_info *ti;
149567468Snon	u_char *s;
149667468Snon
149767468Snon	/*
149867468Snon	 * Check select vs reselected collision.
149967468Snon	 */
150067468Snon
150167468Snon	if ((ti = slp->sl_selid) != NULL)
150267468Snon	{
150367468Snon		scsi_low_clear_nexus(slp, ti);
150467468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_NULL);
150567468Snon#ifdef	SCSI_LOW_STATICS
150667468Snon		scsi_low_statics.nexus_conflict ++;
150767468Snon#endif	/* SCSI_LOW_STATICS */
150867468Snon	}
150967468Snon	else if (slp->sl_nexus != NULL)
151067468Snon	{
151167468Snon		s = "host busy";
151267468Snon		goto world_restart;
151367468Snon	}
151467468Snon
151567468Snon	/*
151667468Snon	 * Check a valid target id asserted ?
151767468Snon	 */
151867468Snon	if (targ >= slp->sl_ntargs || targ == slp->sl_hostid)
151967468Snon	{
152067468Snon		s = "scsi id illegal";
152167468Snon		goto world_restart;
152267468Snon	}
152367468Snon
152467468Snon	/*
152567468Snon	 * Check the target scsi status.
152667468Snon	 */
152767468Snon	ti = slp->sl_ti[targ];
152867468Snon	if (ti->ti_phase != PH_DISC)
152967468Snon	{
153067468Snon		s = "phase mismatch";
153167468Snon		goto world_restart;
153267468Snon	}
153367468Snon
153467468Snon	/*
153567468Snon	 * Setup lun and init msgsys
153667468Snon	 */
153767468Snon	slp->sl_error = 0;
153867468Snon	scsi_low_init_msgsys(slp, ti);
153967468Snon
154067468Snon	/*
154167468Snon	 * Establish our target nexus
154267468Snon	 * Remark: ccb and scsi pointer not yet restored
154367468Snon	 * 	   if lun != SCSI_LOW_UNKLUN.
154467468Snon	 */
154567468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_RESEL);
154667468Snon	slp->sl_nexus = ti;
154767468Snon#ifdef	SCSI_LOW_STATICS
154867468Snon	scsi_low_statics.nexus_reselected ++;
154967468Snon#endif	/* SCSI_LOW_STATICS */
155067468Snon	return ti;
155167468Snon
155267468Snonworld_restart:
155367468Snon	printf("%s: reselect(%x:unknown) %s\n", slp->sl_xname, targ, s);
155467468Snon	scsi_low_restart(slp, SCSI_LOW_RESTART_HARD,
155567468Snon		         "reselect: scsi world confused");
155667468Snon	return NULL;
155767468Snon}
155867468Snon
155967468Snonint
156067468Snonscsi_low_disconnected(slp, ti)
156167468Snon	struct scsi_low_softc *slp;
156267468Snon	struct targ_info *ti;
156367468Snon{
156467468Snon	struct slccb *cb = ti->ti_nexus;
156567468Snon
156667468Snon	/* check phase completion */
156767468Snon	switch (slp->sl_msgphase)
156867468Snon	{
156967468Snon	case MSGPH_DISC:
157067468Snon		if (cb != NULL)
157167468Snon		{
157267468Snon			TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain);
157367468Snon			TAILQ_INSERT_TAIL(&ti->ti_discq, cb, ccb_chain);
157467468Snon			cb->ccb_error |= slp->sl_error;
157567468Snon			cb->li->li_disc ++;
157667468Snon			slp->sl_disc ++;
157767468Snon		}
157867468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DISC);
157967468Snon#ifdef	SCSI_LOW_STATICS
158067468Snon		scsi_low_statics.nexus_disconnected ++;
158167468Snon#endif	/* SCSI_LOW_STATICS */
158267468Snon		break;
158367468Snon
158467468Snon	case MSGPH_NULL:
158567468Snon		slp->sl_error |= FATALIO;
158667468Snon
158767468Snon	case MSGPH_CMDC:
158867468Snon		if (cb != NULL)
158967468Snon		{
159067468Snon			cb->ccb_error |= slp->sl_error;
159167468Snon			scsi_low_done(slp, cb);
159267468Snon		}
159367468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_NULL);
159467468Snon		break;
159567468Snon	}
159667468Snon
159767468Snon	scsi_low_clear_nexus(slp, ti);
159867468Snon	scsi_low_start(slp);
159967468Snon	return 1;
160067468Snon}
160167468Snon
160267468Snon/**************************************************************
160367468Snon * cmd out pointer setup
160467468Snon **************************************************************/
160567468Snonint
160667468Snonscsi_low_cmd(slp, ti)
160767468Snon	struct scsi_low_softc *slp;
160867468Snon	struct targ_info *ti;
160967468Snon{
161067468Snon	struct slccb *cb = ti->ti_nexus;
161167468Snon
161267468Snon	if (cb == NULL)
161367468Snon	{
161467468Snon		/*
161567468Snon		 * no slccb, abort!
161667468Snon		 */
161767468Snon		slp->sl_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd;
161867468Snon		slp->sl_scp.scp_cmdlen = sizeof(unit_ready_cmd);
161967468Snon		slp->sl_scp.scp_datalen = 0;
162067468Snon		slp->sl_scp.scp_direction = SCSI_LOW_READ;
162167468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
162267468Snon		scsi_low_info(slp, ti, "CMDOUT: slccb nexus not found");
162367468Snon	}
162467468Snon	else if (slp->sl_nexus_call == 0)
162567468Snon	{
162667468Snon		slp->sl_nexus_call = 1;
162767468Snon		(*slp->sl_funcs->scsi_low_establish_nexus) (slp, ti);
162867468Snon	}
162967468Snon	return 0;
163067468Snon}
163167468Snon
163267468Snon/**************************************************************
163367468Snon * data out pointer setup
163467468Snon **************************************************************/
163567468Snonint
163667468Snonscsi_low_data(slp, ti, bp, direction)
163767468Snon	struct scsi_low_softc *slp;
163867468Snon	struct targ_info *ti;
163967468Snon	struct buf **bp;
164067468Snon	int direction;
164167468Snon{
164267468Snon	struct slccb *cb = ti->ti_nexus;
164367468Snon
164467468Snon	if (cb == NULL)
164567468Snon	{
164667468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
164767468Snon		scsi_low_info(slp, ti, "DATA PHASE: slccb nexus not found");
164867468Snon		return EINVAL;
164967468Snon	}
165067468Snon
165167468Snon	if (direction != cb->ccb_scp.scp_direction)
165267468Snon	{
165367468Snon		scsi_low_info(slp, ti, "DATA PHASE: xfer direction mismatch");
165467468Snon		return EINVAL;
165567468Snon	}
165667468Snon
165767468Snon#ifdef CAM
165867468Snon	*bp = NULL; /* (cb->ccb == NULL) ? NULL : cb->bp; */
165967468Snon#else
166067468Snon	*bp = (cb->xs == NULL) ? NULL : cb->xs->bp;
166167468Snon#endif
166267468Snon	return 0;
166367468Snon}
166467468Snon
166567468Snon/**************************************************************
166667468Snon * MSG_SYS
166767468Snon **************************************************************/
166867468Snon#define	MSGINPTR_CLR(ti) {(ti)->ti_msginptr = 0; (ti)->ti_msginlen = 0;}
166967468Snon#define	MSGIN_PERIOD(ti) ((ti)->ti_msgin[3])
167067468Snon#define	MSGIN_OFFSET(ti) ((ti)->ti_msgin[4])
167167468Snon#define	MSGIN_DATA_LAST	0x30
167267468Snon
167367468Snonstatic int scsi_low_errfunc_synch __P((struct targ_info *, u_int));
167467468Snonstatic int scsi_low_errfunc_wide __P((struct targ_info *, u_int));
167567468Snonstatic int scsi_low_errfunc_identify __P((struct targ_info *, u_int));
167667468Snon
167767468Snonstatic int scsi_low_msgfunc_synch __P((struct targ_info *));
167867468Snonstatic int scsi_low_msgfunc_wide __P((struct targ_info *));
167967468Snonstatic int scsi_low_msgfunc_identify __P((struct targ_info *));
168067468Snonstatic int scsi_low_msgfunc_user __P((struct targ_info *));
168167468Snonstatic int scsi_low_msgfunc_abort __P((struct targ_info *));
168267468Snon
168367468Snonstruct scsi_low_msgout_data {
168467468Snon	u_int	md_flags;
168567468Snon	u_int8_t md_msg;
168667468Snon	int (*md_msgfunc) __P((struct targ_info *));
168767468Snon	int (*md_errfunc) __P((struct targ_info *, u_int));
168867468Snon};
168967468Snon
169067468Snonstruct scsi_low_msgout_data scsi_low_msgout_data[] = {
169167468Snon/* 0 */	{SCSI_LOW_MSG_RESET, MSG_RESET, scsi_low_msgfunc_abort, NULL},
169267468Snon/* 1 */ {SCSI_LOW_MSG_ABORT, MSG_ABORT, scsi_low_msgfunc_abort, NULL},
169367468Snon/* 2 */ {SCSI_LOW_MSG_REJECT, MSG_REJECT, NULL, NULL},
169467468Snon/* 3 */ {SCSI_LOW_MSG_PARITY, MSG_PARITY, NULL, NULL},
169567468Snon/* 4 */ {SCSI_LOW_MSG_ERROR, MSG_I_ERROR, NULL, NULL},
169667468Snon/* 5 */ {SCSI_LOW_MSG_IDENTIFY, 0, scsi_low_msgfunc_identify, scsi_low_errfunc_identify},
169767468Snon/* 6 */ {SCSI_LOW_MSG_SYNCH, 0, scsi_low_msgfunc_synch, scsi_low_errfunc_synch},
169867468Snon/* 7 */ {SCSI_LOW_MSG_WIDE, 0, scsi_low_msgfunc_wide, scsi_low_errfunc_wide},
169967468Snon/* 8 */ {SCSI_LOW_MSG_USER, 0, scsi_low_msgfunc_user, NULL},
170067468Snon/* 9 */ {SCSI_LOW_MSG_NOOP, MSG_NOOP, NULL, NULL},
170167468Snon/* 10 */ {SCSI_LOW_MSG_ALL, 0},
170267468Snon};
170367468Snon
170467468Snonstatic int scsi_low_msginfunc_ext __P((struct targ_info *));
170567468Snonstatic int scsi_low_synch __P((struct targ_info *));
170667468Snonstatic int scsi_low_msginfunc_msg_reject __P((struct targ_info *));
170767468Snonstatic int scsi_low_msginfunc_rejop __P((struct targ_info *));
170867468Snonstatic int scsi_low_msginfunc_rdp __P((struct targ_info *));
170967468Snonstatic int scsi_low_msginfunc_sdp __P((struct targ_info *));
171067468Snonstatic int scsi_low_msginfunc_disc __P((struct targ_info *));
171167468Snonstatic int scsi_low_msginfunc_cc __P((struct targ_info *));
171267468Snonstatic int scsi_low_msginfunc_parity __P((struct targ_info *));
171367468Snonstatic int scsi_low_msginfunc_noop __P((struct targ_info *));
171467468Snonstatic void scsi_low_retry_phase __P((struct targ_info *));
171567468Snon
171667468Snonstruct scsi_low_msgin_data {
171767468Snon	u_int md_len;
171867468Snon	int (*md_msgfunc) __P((struct targ_info *));
171967468Snon};
172067468Snon
172167468Snonstruct scsi_low_msgin_data scsi_low_msgin_data[] = {
172267468Snon/* 0 */	{1,	scsi_low_msginfunc_cc},
172367468Snon/* 1 */ {2,	scsi_low_msginfunc_ext},
172467468Snon/* 2 */ {1,	scsi_low_msginfunc_sdp},
172567468Snon/* 3 */ {1,	scsi_low_msginfunc_rdp},
172667468Snon/* 4 */ {1,	scsi_low_msginfunc_disc},
172767468Snon/* 5 */ {1,	scsi_low_msginfunc_rejop},
172867468Snon/* 6 */ {1,	scsi_low_msginfunc_rejop},
172967468Snon/* 7 */ {1,	scsi_low_msginfunc_msg_reject},
173067468Snon/* 8 */ {1,	scsi_low_msginfunc_noop},
173167468Snon/* 9 */ {1,	scsi_low_msginfunc_parity},
173267468Snon/* a */ {1,	scsi_low_msginfunc_rejop},
173367468Snon/* b */ {1,	scsi_low_msginfunc_rejop},
173467468Snon/* c */ {1,	scsi_low_msginfunc_rejop},
173567468Snon/* d */ {2,	scsi_low_msginfunc_rejop},
173667468Snon/* e */ {1,	scsi_low_msginfunc_rejop},
173767468Snon/* f */ {1,	scsi_low_msginfunc_rejop},
173867468Snon/* 0x10 */ {1,	scsi_low_msginfunc_rejop},
173967468Snon/* 0x11 */ {1,	scsi_low_msginfunc_rejop},
174067468Snon/* 0x12 */ {1,	scsi_low_msginfunc_rejop},
174167468Snon/* 0x13 */ {1,	scsi_low_msginfunc_rejop},
174267468Snon/* 0x14 */ {1,	scsi_low_msginfunc_rejop},
174367468Snon/* 0x15 */ {1,	scsi_low_msginfunc_rejop},
174467468Snon/* 0x16 */ {1,	scsi_low_msginfunc_rejop},
174567468Snon/* 0x17 */ {1,	scsi_low_msginfunc_rejop},
174667468Snon/* 0x18 */ {1,	scsi_low_msginfunc_rejop},
174767468Snon/* 0x19 */ {1,	scsi_low_msginfunc_rejop},
174867468Snon/* 0x1a */ {1,	scsi_low_msginfunc_rejop},
174967468Snon/* 0x1b */ {1,	scsi_low_msginfunc_rejop},
175067468Snon/* 0x1c */ {1,	scsi_low_msginfunc_rejop},
175167468Snon/* 0x1d */ {1,	scsi_low_msginfunc_rejop},
175267468Snon/* 0x1e */ {1,	scsi_low_msginfunc_rejop},
175367468Snon/* 0x1f */ {1,	scsi_low_msginfunc_rejop},
175467468Snon/* 0x20 */ {2,	scsi_low_msginfunc_rejop},
175567468Snon/* 0x21 */ {2,	scsi_low_msginfunc_rejop},
175667468Snon/* 0x22 */ {2,	scsi_low_msginfunc_rejop},
175767468Snon/* 0x23 */ {2,	scsi_low_msginfunc_rejop},
175867468Snon/* 0x24 */ {2,	scsi_low_msginfunc_rejop},
175967468Snon/* 0x25 */ {2,	scsi_low_msginfunc_rejop},
176067468Snon/* 0x26 */ {2,	scsi_low_msginfunc_rejop},
176167468Snon/* 0x27 */ {2,	scsi_low_msginfunc_rejop},
176267468Snon/* 0x28 */ {2,	scsi_low_msginfunc_rejop},
176367468Snon/* 0x29 */ {2,	scsi_low_msginfunc_rejop},
176467468Snon/* 0x2a */ {2,	scsi_low_msginfunc_rejop},
176567468Snon/* 0x2b */ {2,	scsi_low_msginfunc_rejop},
176667468Snon/* 0x2c */ {2,	scsi_low_msginfunc_rejop},
176767468Snon/* 0x2d */ {2,	scsi_low_msginfunc_rejop},
176867468Snon/* 0x2e */ {2,	scsi_low_msginfunc_rejop},
176967468Snon/* 0x2f */ {2,	scsi_low_msginfunc_rejop},
177067468Snon/* 0x30 */ {1,	scsi_low_msginfunc_rejop}	/* default rej op */
177167468Snon};
177267468Snon
177367468Snonstatic void
177467468Snonscsi_low_init_msgsys(slp, ti)
177567468Snon	struct scsi_low_softc *slp;
177667468Snon	struct targ_info *ti;
177767468Snon{
177867468Snon
177967468Snon	ti->ti_msginptr = 0;
178067468Snon	ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0;
178167468Snon	ti->ti_tflags &= ~TARG_ASSERT_ATN;
178267468Snon	SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL);
178367468Snon}
178467468Snon
178567468Snon/**************************************************************
178667468Snon * msgout
178767468Snon **************************************************************/
178867468Snonstatic int
178967468Snonscsi_low_msgfunc_synch(ti)
179067468Snon	struct targ_info *ti;
179167468Snon{
179267468Snon	struct lun_info *li = ti->ti_li;
179367468Snon	int ptr = ti->ti_msgoutlen;
179467468Snon
179567468Snon	if (li == NULL)
179667468Snon	{
179767468Snon		scsi_low_assert_msg(ti->ti_sc, ti, SCSI_LOW_MSG_ABORT, 0);
179867468Snon		return EINVAL;
179967468Snon	}
180067468Snon
180167468Snon	ti->ti_msgoutstr[ptr + 0] = MSG_EXTEND;
180267468Snon	ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_SYNCHLEN;
180367468Snon	ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_SYNCHCODE;
180467468Snon	ti->ti_msgoutstr[ptr + 3] = li->li_maxsynch.period;
180567468Snon	ti->ti_msgoutstr[ptr + 4] = li->li_maxsynch.offset;
180667468Snon	return MSG_EXTEND_SYNCHLEN + 2;
180767468Snon}
180867468Snon
180967468Snonstatic int
181067468Snonscsi_low_msgfunc_wide(ti)
181167468Snon	struct targ_info *ti;
181267468Snon{
181367468Snon	struct lun_info *li = ti->ti_li;
181467468Snon	int ptr = ti->ti_msgoutlen;
181567468Snon
181667468Snon	if (li == NULL)
181767468Snon	{
181867468Snon		scsi_low_assert_msg(ti->ti_sc, ti, SCSI_LOW_MSG_ABORT, 0);
181967468Snon		return EINVAL;
182067468Snon	}
182167468Snon
182267468Snon	ti->ti_msgoutstr[ptr + 0] = MSG_EXTEND;
182367468Snon	ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_WIDELEN;
182467468Snon	ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_WIDECODE;
182567468Snon	ti->ti_msgoutstr[ptr + 3] = li->li_width;
182667468Snon	return MSG_EXTEND_WIDELEN + 2;
182767468Snon}
182867468Snon
182967468Snonstatic int
183067468Snonscsi_low_msgfunc_identify(ti)
183167468Snon	struct targ_info *ti;
183267468Snon{
183367468Snon	int ptr = ti->ti_msgoutlen;;
183467468Snon
183567468Snon	if (ti->ti_li == NULL)
183667468Snon	{
183767468Snon		ti->ti_msgoutstr[ptr + 0] = 0x80;
183867468Snon		scsi_low_info(ti->ti_sc, ti, "MSGOUT: lun unknown");
183967468Snon		scsi_low_assert_msg(ti->ti_sc, ti, SCSI_LOW_MSG_ABORT, 0);
184067468Snon	}
184167468Snon	else
184267468Snon	{
184367468Snon		ti->ti_msgoutstr[ptr + 0] = ID_MSG_SETUP(ti);
184467468Snon	}
184567468Snon	return 1;
184667468Snon}
184767468Snon
184867468Snonstatic int
184967468Snonscsi_low_msgfunc_user(ti)
185067468Snon	struct targ_info *ti;
185167468Snon{
185267468Snon#ifdef	SCSI_LOW_SUPPORT_USER_MSGOUT
185367468Snon	struct slccb *cb = ti->ti_nexus;
185467468Snon	int ptr = ti->ti_msgoutlen;;
185567468Snon
185667468Snon	if (ti->ti_nexus == NULL)
185767468Snon	{
185867468Snon		ti->ti_msgoutstr[ptr + 0] = MSG_NOOP;
185967468Snon		return 1;
186067468Snon	}
186167468Snon	else
186267468Snon	{
186367468Snon		bcopy(cb->msgout, ti->ti_msgoutstr + ptr, SCSI_LOW_MAX_MSGLEN);
186467468Snon		return cb->msgoutlen;
186567468Snon	}
186667468Snon#else	/* !SCSI_LOW_SUPPORT_USER_MSGOUT */
186767468Snon	return 0;
186867468Snon#endif	/* !SCSI_LOW_SUPPORT_USER_MSGOUT */
186967468Snon}
187067468Snon
187167468Snonstatic int
187267468Snonscsi_low_msgfunc_abort(ti)
187367468Snon	struct targ_info *ti;
187467468Snon{
187567468Snon	struct scsi_low_softc *slp = ti->ti_sc;
187667468Snon
187767468Snon	/* The target should releases bus */
187867468Snon	SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC);
187967468Snon	slp->sl_error |= /* ABORTIO */ FATALIO;
188067468Snon	return 1;
188167468Snon}
188267468Snon
188367468Snon/*
188467468Snon * The following functions are called when targets give unexpected
188567468Snon * responces in msgin (after msgout).
188667468Snon */
188767468Snonstatic int
188867468Snonscsi_low_errfunc_identify(ti, msgflags)
188967468Snon	struct targ_info *ti;
189067468Snon	u_int msgflags;
189167468Snon{
189267468Snon	struct lun_info *li = ti->ti_li;
189367468Snon
189467468Snon	li->li_flags &= ~SCSI_LOW_DISC;
189567468Snon	return 0;
189667468Snon}
189767468Snon
189867468Snonstatic int
189967468Snonscsi_low_errfunc_synch(ti, msgflags)
190067468Snon	struct targ_info *ti;
190167468Snon	u_int msgflags;
190267468Snon{
190367468Snon
190467468Snon	/* XXX:
190567468Snon	 * illegal behavior, however
190667468Snon	 * there are buggy devices!
190767468Snon	 */
190867468Snon	MSGIN_PERIOD(ti) = 0;
190967468Snon	MSGIN_OFFSET(ti) = 0;
191067468Snon	scsi_low_synch(ti);
191167468Snon	return 0;
191267468Snon}
191367468Snon
191467468Snonstatic int
191567468Snonscsi_low_errfunc_wide(ti, msgflags)
191667468Snon	struct targ_info *ti;
191767468Snon	u_int msgflags;
191867468Snon{
191967468Snon	struct lun_info *li = ti->ti_li;
192067468Snon
192167468Snon	li->li_width = 0;
192267468Snon	return 0;
192367468Snon}
192467468Snon
192567468Snonint
192667468Snonscsi_low_msgout(slp, ti)
192767468Snon	struct scsi_low_softc *slp;
192867468Snon	struct targ_info *ti;
192967468Snon{
193067468Snon	struct scsi_low_msgout_data *mdp;
193167468Snon	int len = 0;
193267468Snon
193367468Snon	/* STEP I.
193467468Snon	 * Scsi phase changes.
193567468Snon	 * Previously msgs asserted are accepted by our target or
193667468Snon	 * processed by scsi_low_msgin.
193767468Snon	 * Thus clear all saved informations.
193867468Snon	 */
193967468Snon	if (ti->ti_ophase != ti->ti_phase)
194067468Snon	{
194167468Snon		ti->ti_omsgflags = 0;
194267468Snon		ti->ti_emsgflags = 0;
194367468Snon	}
194467468Snon
194567468Snon	/* STEP II.
194667468Snon	 * We did not assert attention, however still our target required
194767468Snon	 * msgs. Resend previous msgs.
194867468Snon	 */
194967468Snon	if (ti->ti_ophase == PH_MSGOUT && !(ti->ti_tflags & TARG_ASSERT_ATN))
195067468Snon	{
195167468Snon		ti->ti_msgflags |= ti->ti_omsgflags;
195267468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
195367468Snon		printf("%s: scsi_low_msgout: retry msgout\n", slp->sl_xname);
195467468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
195567468Snon	}
195667468Snon
195767468Snon	/*
195867468Snon	 * OK. clear flags.
195967468Snon	 */
196067468Snon	ti->ti_tflags &= ~TARG_ASSERT_ATN;
196167468Snon
196267468Snon	/* STEP III.
196367468Snon	 * We have no msgs. send MSG_LOOP (OK?)
196467468Snon	 */
196567468Snon	if (scsi_low_is_msgout_continue(ti) == 0)
196667468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_NOOP, 0);
196767468Snon
196867468Snon	/* STEP IV.
196967468Snon	 * Process all msgs
197067468Snon	 */
197167468Snon	ti->ti_msgoutlen = 0;
197267468Snon	mdp = &scsi_low_msgout_data[0];
197367468Snon	for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++)
197467468Snon	{
197567468Snon		if ((ti->ti_msgflags & mdp->md_flags) != 0)
197667468Snon		{
197767468Snon			ti->ti_omsgflags |= mdp->md_flags;
197867468Snon			ti->ti_msgflags &= ~mdp->md_flags;
197967468Snon			ti->ti_emsgflags = mdp->md_flags;
198067468Snon
198167468Snon			ti->ti_msgoutstr[ti->ti_msgoutlen] = mdp->md_msg;
198267468Snon			if (mdp->md_msgfunc != NULL)
198367468Snon				len = (*mdp->md_msgfunc) (ti);
198467468Snon			else
198567468Snon				len = 1;
198667468Snon
198767468Snon			ti->ti_msgoutlen += len;
198867468Snon			if ((slp->sl_cfgflags & CFG_MSGUNIFY) == 0 ||
198967468Snon			    ti->ti_msgflags == 0)
199067468Snon				break;
199167468Snon			if (ti->ti_msgoutlen >= SCSI_LOW_MAX_MSGLEN - 5)
199267468Snon				break;
199367468Snon		}
199467468Snon	}
199567468Snon
199667468Snon	if (scsi_low_is_msgout_continue(ti) != 0)
199767468Snon	{
199867468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
199967468Snon		printf("SCSI_LOW_ATTENTION(msgout): 0x%x\n", ti->ti_msgflags);
200067468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
200167468Snon		scsi_low_attention(slp, ti);
200267468Snon	}
200367468Snon
200467468Snon	/*
200567468Snon	 * OK. advance old phase.
200667468Snon	 */
200767468Snon	ti->ti_ophase = ti->ti_phase;
200867468Snon	return ti->ti_msgoutlen;
200967468Snon}
201067468Snon
201167468Snon/**************************************************************
201267468Snon * msgin
201367468Snon **************************************************************/
201467468Snonstatic int
201567468Snonscsi_low_msginfunc_noop(ti)
201667468Snon	struct targ_info *ti;
201767468Snon{
201867468Snon
201967468Snon	return 0;
202067468Snon}
202167468Snon
202267468Snonstatic int
202367468Snonscsi_low_msginfunc_rejop(ti)
202467468Snon	struct targ_info *ti;
202567468Snon{
202667468Snon	struct scsi_low_softc *slp = ti->ti_sc;
202767468Snon	u_int8_t msg = ti->ti_msgin[0];
202867468Snon
202967468Snon	printf("%s: MSGIN: msg 0x%x reject\n", slp->sl_xname, (u_int) msg);
203067468Snon	scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
203167468Snon	return 0;
203267468Snon}
203367468Snon
203467468Snonstatic int
203567468Snonscsi_low_msginfunc_cc(ti)
203667468Snon	struct targ_info *ti;
203767468Snon{
203867468Snon	struct scsi_low_softc *slp = ti->ti_sc;
203967468Snon
204067468Snon	SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC);
204167468Snon	return 0;
204267468Snon}
204367468Snon
204467468Snonstatic int
204567468Snonscsi_low_msginfunc_disc(ti)
204667468Snon	struct targ_info *ti;
204767468Snon{
204867468Snon	struct scsi_low_softc *slp = ti->ti_sc;
204967468Snon
205067468Snon	SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC);
205167468Snon	return 0;
205267468Snon}
205367468Snon
205467468Snonstatic int
205567468Snonscsi_low_msginfunc_sdp(ti)
205667468Snon	struct targ_info *ti;
205767468Snon{
205867468Snon	struct scsi_low_softc *slp = ti->ti_sc;
205967468Snon
206067468Snon	if (ti->ti_nexus != NULL)
206167468Snon		ti->ti_nexus->ccb_sscp = slp->sl_scp;
206267468Snon	else
206367468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
206467468Snon	return 0;
206567468Snon}
206667468Snon
206767468Snonstatic int
206867468Snonscsi_low_msginfunc_rdp(ti)
206967468Snon	struct targ_info *ti;
207067468Snon{
207167468Snon	struct scsi_low_softc *slp = ti->ti_sc;
207267468Snon
207367468Snon	if (ti->ti_nexus != NULL)
207467468Snon		slp->sl_scp = ti->ti_nexus->ccb_sscp;
207567468Snon	else
207667468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
207767468Snon	return 0;
207867468Snon}
207967468Snon
208067468Snonstatic int
208167468Snonscsi_low_synch(ti)
208267468Snon	struct targ_info *ti;
208367468Snon{
208467468Snon	struct scsi_low_softc *slp = ti->ti_sc;
208567468Snon	struct lun_info *li = ti->ti_li;
208671508Sjhb	u_int period = 0, offset = 0;
208771508Sjhb#ifdef SCSI_LOW_INFORM
208871508Sjhb	u_int speed;
208971508Sjhb#endif
209067468Snon	u_char *s;
209167468Snon	int error;
209267468Snon
209367468Snon	if (MSGIN_PERIOD(ti) >= li->li_maxsynch.period &&
209467468Snon	    MSGIN_OFFSET(ti) <= li->li_maxsynch.offset)
209567468Snon	{
209667468Snon		if ((offset = MSGIN_OFFSET(ti)) != 0)
209767468Snon			period = MSGIN_PERIOD(ti);
209867468Snon		s = offset ? "synchronous" : "async";
209967468Snon	}
210067468Snon	else
210167468Snon	{
210267468Snon		/* XXX:
210367468Snon		 * Target seems to be brain damaged.
210467468Snon		 * Force async transfer.
210567468Snon		 */
210667468Snon		li->li_maxsynch.period = 0;
210767468Snon		li->li_maxsynch.offset = 0;
210867468Snon		printf("%s: target brain damaged. async transfer\n",
210967468Snon			slp->sl_xname);
211067468Snon		return EINVAL;
211167468Snon	}
211267468Snon
211367468Snon	li->li_maxsynch.period = period;
211467468Snon	li->li_maxsynch.offset = offset;
211567468Snon
211667468Snon	error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_SYNCH);
211767468Snon	if (error != 0)
211867468Snon	{
211967468Snon		/* XXX:
212067468Snon		 * Current period and offset are not acceptable
212167468Snon		 * for our adapter.
212267468Snon		 * The adapter changes max synch and max offset.
212367468Snon		 */
212467468Snon		printf("%s: synch neg failed. retry synch msg neg ...\n",
212567468Snon			slp->sl_xname);
212667468Snon		return error;
212767468Snon	}
212867468Snon
212967468Snon#ifdef SCSI_LOW_INFORM
213067468Snon	/* inform data */
213167468Snon	printf("%s(%d:%d): <%s> offset %d period %dns ",
213267468Snon		slp->sl_xname, ti->ti_id, li->li_lun, s, offset, period * 4);
213367468Snon	if (period != 0)
213467468Snon	{
213567468Snon		speed = 1000 * 10 / (period * 4);
213667468Snon		printf("%d.%d M/s", speed / 10, speed % 10);
213767468Snon	}
213867468Snon	printf("\n");
213967468Snon#endif
214067468Snon
214167468Snon	return 0;
214267468Snon}
214367468Snon
214467468Snonstatic int
214567468Snonscsi_low_msginfunc_ext(ti)
214667468Snon	struct targ_info *ti;
214767468Snon{
214867468Snon	struct scsi_low_softc *slp = ti->ti_sc;
214967468Snon	struct slccb *cb = ti->ti_nexus;
215067468Snon	struct lun_info *li = ti->ti_li;
215167468Snon	int count, retry;
215267468Snon	u_int32_t *ptr;
215367468Snon
215467468Snon	if (ti->ti_msginptr == 2)
215567468Snon	{
215667468Snon		ti->ti_msginlen = ti->ti_msgin[1] + 2;
215767468Snon		return 0;
215867468Snon	}
215967468Snon
216067468Snon	switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2]))
216167468Snon	{
216267468Snon	case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE):
216367468Snon		if (cb == NULL)
216467468Snon			break;
216567468Snon
216667468Snon		ptr = (u_int32_t *)(&ti->ti_msgin[3]);
216767468Snon		count = (int) htonl((long) (*ptr));
216867468Snon		if(slp->sl_scp.scp_datalen - count < 0 ||
216967468Snon		   slp->sl_scp.scp_datalen - count > cb->ccb_scp.scp_datalen)
217067468Snon			break;
217167468Snon
217267468Snon		slp->sl_scp.scp_datalen -= count;
217367468Snon		slp->sl_scp.scp_data += count;
217467468Snon		return 0;
217567468Snon
217667468Snon	case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE):
217767468Snon		if (li == NULL)
217867468Snon			break;
217967468Snon
218067468Snon		retry = scsi_low_synch(ti);
218167468Snon		if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_SYNCH) == 0)
218267468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0);
218367468Snon		return 0;
218467468Snon
218567468Snon	case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE):
218667468Snon		if (li == NULL)
218767468Snon			break;
218867468Snon
218967468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0);
219067468Snon		return 0;
219167468Snon
219267468Snon	default:
219367468Snon		break;
219467468Snon	}
219567468Snon
219667468Snon	scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
219767468Snon	return EINVAL;
219867468Snon}
219967468Snon
220067468Snonstatic void
220167468Snonscsi_low_retry_phase(ti)
220267468Snon	struct targ_info *ti;
220367468Snon{
220467468Snon
220567468Snon	switch (ti->ti_sphase)
220667468Snon	{
220767468Snon	case PH_MSGOUT:
220867468Snon		ti->ti_msgflags |= ti->ti_omsgflags;
220967468Snon		break;
221067468Snon
221167468Snon	default:
221267468Snon		break;
221367468Snon	}
221467468Snon}
221567468Snon
221667468Snonstatic int
221767468Snonscsi_low_msginfunc_parity(ti)
221867468Snon	struct targ_info *ti;
221967468Snon{
222067468Snon	struct scsi_low_softc *slp = ti->ti_sc;
222167468Snon
222267468Snon	if (ti->ti_sphase != PH_MSGOUT)
222367468Snon		slp->sl_error |= PARITYERR;
222467468Snon	scsi_low_retry_phase(ti);
222567468Snon	return 0;
222667468Snon}
222767468Snon
222867468Snonstatic int
222967468Snonscsi_low_msginfunc_msg_reject(ti)
223067468Snon	struct targ_info *ti;
223167468Snon{
223267468Snon	struct scsi_low_softc *slp = ti->ti_sc;
223367468Snon	struct lun_info *li = ti->ti_li;
223467468Snon	struct scsi_low_msgout_data *mdp;
223567468Snon	u_int msgflags;
223667468Snon
223767468Snon	if (li == NULL)
223867468Snon	{
223967468Snon		/* not yet lun nexus established! */
224067468Snon		goto out;
224167468Snon	}
224267468Snon
224367468Snon	switch (ti->ti_sphase)
224467468Snon	{
224567468Snon	case PH_CMD:
224667468Snon		slp->sl_error |= CMDREJECT;
224767468Snon		break;
224867468Snon
224967468Snon	case PH_MSGOUT:
225067468Snon		if (ti->ti_emsgflags == 0)
225167468Snon			break;
225267468Snon
225367468Snon		msgflags = SCSI_LOW_MSG_REJECT;
225467468Snon		mdp = &scsi_low_msgout_data[0];
225567468Snon		for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++)
225667468Snon		{
225767468Snon			if ((ti->ti_emsgflags & mdp->md_flags) != 0)
225867468Snon			{
225967468Snon				ti->ti_emsgflags &= ~mdp->md_flags;
226067468Snon				if (mdp->md_errfunc != NULL)
226167468Snon					(*mdp->md_errfunc) (ti, msgflags);
226267468Snon				break;
226367468Snon			}
226467468Snon		}
226567468Snon		break;
226667468Snon
226767468Snon	default:
226867468Snon		break;
226967468Snon	}
227067468Snon
227167468Snonout:
227267468Snon	scsi_low_info(slp, ti, "msg rejected");
227367468Snon	slp->sl_error |= MSGERR;
227467468Snon	return 0;
227567468Snon}
227667468Snon
227767468Snonvoid
227867468Snonscsi_low_msgin(slp, ti, c)
227967468Snon	struct scsi_low_softc *slp;
228067468Snon	struct targ_info *ti;
228167468Snon	u_int8_t c;
228267468Snon{
228367468Snon	struct scsi_low_msgin_data *sdp;
228467468Snon	struct lun_info *li;
228567468Snon	u_int8_t msg;
228667468Snon
228767468Snon	/*
228867468Snon	 * Phase changes, clear the pointer.
228967468Snon	 */
229067468Snon	if (ti->ti_ophase != ti->ti_phase)
229167468Snon	{
229267468Snon		ti->ti_sphase = ti->ti_ophase;
229367468Snon		ti->ti_ophase = ti->ti_phase;
229467468Snon		MSGINPTR_CLR(ti);
229567468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
229667468Snon		ti->ti_msgin_hist_pointer = 0;
229767468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
229867468Snon	}
229967468Snon
230067468Snon	/*
230167468Snon	 * Store a current messages byte into buffer and
230267468Snon	 * wait for the completion of the current msg.
230367468Snon	 */
230467468Snon	ti->ti_msgin[ti->ti_msginptr ++] = c;
230567468Snon	if (ti->ti_msginptr >= SCSI_LOW_MAX_MSGLEN)
230667468Snon	{
230767468Snon		ti->ti_msginptr = SCSI_LOW_MAX_MSGLEN - 1;
230867468Snon		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
230967468Snon	}
231067468Snon
231167468Snon	/*
231267468Snon	 * Calculate messages length.
231367468Snon	 */
231467468Snon	msg = ti->ti_msgin[0];
231567468Snon	if (msg < MSGIN_DATA_LAST)
231667468Snon		sdp = &scsi_low_msgin_data[msg];
231767468Snon	else
231867468Snon		sdp = &scsi_low_msgin_data[MSGIN_DATA_LAST];
231967468Snon
232067468Snon	if (ti->ti_msginlen == 0)
232167468Snon	{
232267468Snon		ti->ti_msginlen = sdp->md_len;
232367468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
232467468Snon	    	if (ti->ti_msgin_hist_pointer < MSGIN_HISTORY_LEN)
232567468Snon		{
232667468Snon			ti->ti_msgin_history[ti->ti_msgin_hist_pointer] = msg;
232767468Snon			ti->ti_msgin_hist_pointer ++;
232867468Snon		}
232967468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
233067468Snon	}
233167468Snon
233267468Snon	/*
233367468Snon	 * Check comletion.
233467468Snon	 */
233567468Snon	if (ti->ti_msginptr < ti->ti_msginlen)
233667468Snon		return;
233767468Snon
233867468Snon	/*
233967468Snon	 * Do process.
234067468Snon	 */
234167468Snon	if ((msg & MSG_IDENTIFY) == 0)
234267468Snon	{
234367468Snon		(void) ((*sdp->md_msgfunc) (ti));
234467468Snon	}
234567468Snon	else
234667468Snon	{
234767468Snon		li = ti->ti_li;
234867468Snon		if (li == NULL)
234967468Snon		{
235067468Snon			li = scsi_low_establish_lun(ti, MSGCMD_LUN(msg));
235167468Snon			if (li == NULL)
235267468Snon				goto badlun;
235367468Snon		}
235467468Snon
235567468Snon		if (ti->ti_nexus == NULL)
235667468Snon		{
235767468Snon			/* XXX:
235867468Snon		 	 * move the following functions to
235967468Snon			 * tag queue msg process in the future.
236067468Snon			 */
236167468Snon			if (!scsi_low_establish_ccb(ti, li, SCSI_LOW_UNKTAG))
236267468Snon				goto badlun;
236367468Snon		}
236467468Snon
236567468Snon		if (MSGCMD_LUN(msg) != li->li_lun)
236667468Snon			goto badlun;
236767468Snon	}
236867468Snon
236967468Snon	/*
237067468Snon	 * Msg process completed, reset msin pointer and assert ATN if desired.
237167468Snon	 */
237267468Snon	if (ti->ti_msginptr >= ti->ti_msginlen)
237367468Snon	{
237467468Snon		ti->ti_sphase = ti->ti_phase;
237567468Snon		MSGINPTR_CLR(ti);
237667468Snon
237767468Snon		if (scsi_low_is_msgout_continue(ti) != 0)
237867468Snon		{
237967468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
238067468Snon			printf("SCSI_LOW_ATTETION(msgin): 0x%x\n",
238167468Snon				ti->ti_msgflags);
238267468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
238367468Snon			scsi_low_attention(slp, ti);
238467468Snon		}
238567468Snon	}
238667468Snon	return;
238767468Snon
238867468Snonbadlun:
238967468Snon	scsi_low_info(slp, ti, "MSGIN: identify lun mismatch");
239067468Snon	scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
239167468Snon}
239267468Snon
239367468Snon/**************************************************************
239467468Snon * Qurik setup
239567468Snon **************************************************************/
239667468Snon#define	MAXOFFSET	0x10
239767468Snon
239867468Snonstatic void
239967468Snonscsi_low_calcf(ti, li)
240067468Snon	struct targ_info *ti;
240167468Snon	struct lun_info *li;
240267468Snon{
240367468Snon	u_int period;
240467468Snon	u_int8_t offset;
240567468Snon	struct scsi_low_softc *slp = ti->ti_sc;
240667468Snon
240767468Snon	li->li_flags &= ~SCSI_LOW_DISC;
240867468Snon	if ((slp->sl_cfgflags & CFG_NODISC) == 0 &&
240967468Snon#ifdef	SDEV_NODISC
241067468Snon	    (li->li_quirks & SDEV_NODISC) == 0 &&
241167468Snon#endif	/* SDEV_NODISC */
241267468Snon	    (li->li_cfgflags & SCSI_LOW_DISC) != 0)
241367468Snon		li->li_flags |= SCSI_LOW_DISC;
241467468Snon
241567468Snon	li->li_flags |= SCSI_LOW_NOPARITY;
241667468Snon	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0 &&
241767468Snon#ifdef	SDEV_NOPARITY
241867468Snon	    (li->li_quirks & SDEV_NOPARITY) == 0 &&
241967468Snon#endif	/* SDEV_NOPARITY */
242067468Snon	    (li->li_cfgflags & SCSI_LOW_NOPARITY) == 0)
242167468Snon		li->li_flags &= ~SCSI_LOW_NOPARITY;
242267468Snon
242367468Snon	li->li_flags &= ~SCSI_LOW_SYNC;
242467468Snon	if ((li->li_cfgflags & SCSI_LOW_SYNC) &&
242567468Snon	    (slp->sl_cfgflags & CFG_ASYNC) == 0)
242667468Snon	{
242767468Snon		offset = SCSI_LOW_OFFSET(li->li_cfgflags);
242867468Snon		if (offset > li->li_maxsynch.offset)
242967468Snon			offset = li->li_maxsynch.offset;
243067468Snon		li->li_flags |= SCSI_LOW_SYNC;
243167468Snon	}
243267468Snon	else
243367468Snon		offset = 0;
243467468Snon
243567468Snon	if (offset > 0)
243667468Snon	{
243767468Snon		period = SCSI_LOW_PERIOD(li->li_cfgflags);
243867468Snon		if (period > SCSI_LOW_MAX_SYNCH_SPEED)
243967468Snon			period = SCSI_LOW_MAX_SYNCH_SPEED;
244067468Snon		if (period != 0)
244167468Snon			period = 1000 * 10 / (period * 4);
244267468Snon		if (period < li->li_maxsynch.period)
244367468Snon			period = li->li_maxsynch.period;
244467468Snon	}
244567468Snon	else
244667468Snon		period = 0;
244767468Snon
244867468Snon	li->li_maxsynch.offset = offset;
244967468Snon	li->li_maxsynch.period = period;
245067468Snon}
245167468Snon
245267468Snon#ifdef	SCSI_LOW_TARGET_OPEN
245367468Snonstatic int
245467468Snonscsi_low_target_open(link, cf)
245567468Snon	struct scsipi_link *link;
245667468Snon	struct cfdata *cf;
245767468Snon{
245867468Snon	u_int target = link->scsipi_scsi.target;
245967468Snon	u_int lun = link->scsipi_scsi.lun;
246067468Snon	struct scsi_low_softc *slp;
246167468Snon	struct targ_info *ti;
246267468Snon	struct lun_info *li;
246367468Snon
246467468Snon	slp = (struct scsi_low_softc *) link->adapter_softc;
246567468Snon	ti = slp->sl_ti[target];
246667468Snon	li = scsi_low_alloc_li(ti, lun, 0);
246767468Snon	if (li == NULL)
246867468Snon		return 0;
246967468Snon
247067468Snon	li->li_quirks = (u_int) link->quirks;
247167468Snon	li->li_cfgflags = cf->cf_flags;
247267468Snon	if (li->li_state > UNIT_SYNCH)
247367468Snon		li->li_state = UNIT_SYNCH;
247467468Snon
247567468Snon	scsi_low_calcf(ti, li);
247667468Snon
247767468Snon	printf("%s(%d:%d): max period(%dns) max offset(%d) flags 0x%b\n",
247867468Snon		slp->sl_xname, target, lun,
247967468Snon		li->li_maxsynch.period * 4,
248067468Snon		li->li_maxsynch.offset,
248167468Snon		li->li_flags, SCSI_LOW_BITS);
248267468Snon	return 0;
248367468Snon}
248467468Snon#endif	/* SCSI_LOW_TARGET_OPEN */
248567468Snon
248667468Snon/**********************************************************
248767468Snon * DEBUG SECTION
248867468Snon **********************************************************/
248967468Snonstatic void
249067468Snonscsi_low_info(slp, ti, s)
249167468Snon	struct scsi_low_softc *slp;
249267468Snon	struct targ_info *ti;
249367468Snon	u_char *s;
249467468Snon{
249567468Snon
249667468Snon	printf("%s: SCSI_LOW: %s\n", slp->sl_xname, s);
249767468Snon	if (ti == NULL)
249867468Snon	{
249971999Sphk		for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
250071999Sphk		     ti = TAILQ_NEXT(ti, ti_chain))
250167468Snon			scsi_low_print(slp, ti);
250267468Snon	}
250367468Snon	else
250467468Snon		scsi_low_print(slp, ti);
250567468Snon
250667468Snon}
250767468Snon
250867468Snonstatic u_char *phase[] =
250967468Snon{
251067468Snon	"FREE", "ARBSTART", "SELSTART", "SELECTED",
251167468Snon	"CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", "RESEL"
251267468Snon};
251367468Snon
251467468Snonvoid
251567468Snonscsi_low_print(slp, ti)
251667468Snon	struct scsi_low_softc *slp;
251767468Snon	struct targ_info *ti;
251867468Snon{
251967468Snon	struct slccb *cb = NULL;
252067468Snon
252167468Snon	if (ti == NULL)
252267468Snon		ti = slp->sl_nexus;
252367468Snon	if (ti != NULL)
252467468Snon		cb = ti->ti_nexus;
252567468Snon
252667468Snon	printf("%s: TARGET(0x%lx) T_NEXUS(0x%lx) C_NEXUS(0x%lx) NDISCS(%d)\n",
252767468Snon	       slp->sl_xname, (u_long) ti, (u_long) slp->sl_nexus,
252867468Snon	       (u_long) cb, slp->sl_disc);
252967468Snon
253067468Snon	/* target stat */
253167468Snon	if (ti != NULL)
253267468Snon	{
253367468Snon		struct sc_p *sp = &slp->sl_scp;
253467468Snon		struct lun_info *li = ti->ti_li;
253567468Snon		u_int flags = 0;
253667468Snon		int lun = -1;
253767468Snon
253867468Snon		if (li != NULL)
253967468Snon		{
254067468Snon			lun = li->li_lun;
254167468Snon			flags = li->li_flags;
254267468Snon		}
254367468Snon
254467468Snon		printf("%s(%d:%d) ph<%s> => ph<%s>\n", slp->sl_xname,
254567468Snon		       ti->ti_id, lun, phase[(int) ti->ti_ophase],
254667468Snon		       phase[(int) ti->ti_phase]);
254767468Snon
254867468Snonprintf("MSGIN: ptr(%x) [%x][%x][%x][%x][%x] STATUSIN: 0x%x T_FLAGS: 0x%x\n",
254967468Snon		       (u_int) (ti->ti_msginptr),
255067468Snon		       (u_int) (ti->ti_msgin[0]),
255167468Snon		       (u_int) (ti->ti_msgin[1]),
255267468Snon		       (u_int) (ti->ti_msgin[2]),
255367468Snon		       (u_int) (ti->ti_msgin[3]),
255467468Snon		       (u_int) (ti->ti_msgin[4]),
255567468Snon		       ti->ti_status, ti->ti_tflags);
255667468Snon#ifdef	SCSI_LOW_DIAGNOSTIC
255767468Snonprintf("MSGIN HISTORY: (%d) [0x%x] => [0x%x] => [0x%x] => [0x%x] => [0x%x]\n",
255867468Snon			ti->ti_msgin_hist_pointer,
255967468Snon			(u_int) (ti->ti_msgin_history[0]),
256067468Snon			(u_int) (ti->ti_msgin_history[1]),
256167468Snon			(u_int) (ti->ti_msgin_history[2]),
256267468Snon			(u_int) (ti->ti_msgin_history[3]),
256367468Snon			(u_int) (ti->ti_msgin_history[4]));
256467468Snon#endif	/* SCSI_LOW_DIAGNOSTIC */
256567468Snon
256667468Snonprintf("MSGOUT: msgflags 0x%x [%x][%x][%x][%x][%x] msgoutlen %d C_FLAGS: %b\n",
256767468Snon			(u_int) ti->ti_msgflags,
256867468Snon			(u_int) (ti->ti_msgoutstr[0]),
256967468Snon			(u_int) (ti->ti_msgoutstr[1]),
257067468Snon			(u_int) (ti->ti_msgoutstr[2]),
257167468Snon			(u_int) (ti->ti_msgoutstr[3]),
257267468Snon			(u_int) (ti->ti_msgoutstr[4]),
257367468Snon		        ti->ti_msgoutlen,
257467468Snon			flags, SCSI_LOW_BITS);
257567468Snon
257667468Snonprintf("SCP: datalen 0x%x dataaddr 0x%lx ",
257767468Snon			sp->scp_datalen,
257867468Snon			(u_long) sp->scp_data);
257967468Snon
258067468Snon		if (cb != NULL)
258167468Snon		{
258267468Snonprintf("CCB: cmdlen %x cmdaddr %lx cmd[0] %x datalen %x",
258367468Snon		       cb->ccb_scp.scp_cmdlen,
258467468Snon		       (u_long) cb->ccb_scp.scp_cmd,
258567468Snon		       (u_int) cb->ccb_scp.scp_cmd[0],
258667468Snon		       cb->ccb_scp.scp_datalen);
258767468Snon		}
258867468Snon		printf("\n");
258967468Snon	}
259067468Snon	printf("error flags %b\n", slp->sl_error, SCSI_LOW_ERRORBITS);
259167468Snon}
2592