179697Snon/*	$NecBSD: tmc18c30.c,v 1.28.12.3 2001/06/19 04:35:48 honda Exp $	*/
267468Snon/*	$NetBSD$	*/
367468Snon
467468Snon#define	STG_DEBUG
567468Snon#define	STG_STATICS
679697Snon#define	STG_IO_CONTROL_FLAGS	(STG_FIFO_INTERRUPTS | STG_WAIT_FOR_SELECT)
767468Snon
8139749Simp/*-
967468Snon * [NetBSD for NEC PC-98 series]
1079697Snon *  Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001
1167468Snon *	NetBSD/pc98 porting staff. All rights reserved.
1279697Snon *  Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001
1367468Snon *	Naofumi HONDA. All rights reserved.
1467468Snon *  Copyright (c) 1996, 1997, 1998, 1999
1567468Snon *	Kouichi Matsuda. All rights reserved.
1667468Snon *
1767468Snon *  Redistribution and use in source and binary forms, with or without
1867468Snon *  modification, are permitted provided that the following conditions
1967468Snon *  are met:
2067468Snon *  1. Redistributions of source code must retain the above copyright
2167468Snon *     notice, this list of conditions and the following disclaimer.
2267468Snon *  2. Redistributions in binary form must reproduce the above copyright
2367468Snon *     notice, this list of conditions and the following disclaimer in the
2467468Snon *     documentation and/or other materials provided with the distribution.
2567468Snon *  3. The name of the author may not be used to endorse or promote products
2667468Snon *     derived from this software without specific prior written permission.
2767468Snon *
2867468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2967468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3067468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3167468Snon * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
3267468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3367468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3467468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3567468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3667468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3767468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3867468Snon * POSSIBILITY OF SUCH DAMAGE.
3967468Snon */
40119420Sobrien
41119420Sobrien#include <sys/cdefs.h>
42119420Sobrien__FBSDID("$FreeBSD$");
4367468Snon
4467468Snon#include <sys/param.h>
4567468Snon#include <sys/systm.h>
4667468Snon#include <sys/kernel.h>
4767468Snon#include <sys/bio.h>
4867468Snon#include <sys/buf.h>
4967468Snon#include <sys/queue.h>
5067468Snon#include <sys/malloc.h>
5167468Snon#include <sys/errno.h>
52274760Sjhb#include <sys/rman.h>
5367468Snon
5467468Snon#include <machine/cpu.h>
5567468Snon#include <machine/bus.h>
5667468Snon
5767468Snon#include <cam/scsi/scsi_low.h>
5867468Snon#include <dev/stg/tmc18c30reg.h>
5967468Snon#include <dev/stg/tmc18c30var.h>
6067468Snon
6167468Snon/***************************************************
6267468Snon * USER SETTINGS
6367468Snon ***************************************************/
6467468Snon/* DEVICE CONFIGURATION FLAGS (MINOR)
6567468Snon *
66250460Seadler * 0x01   DISCONNECT OFF
6767468Snon * 0x02   PARITY LINE OFF
6867468Snon * 0x04   IDENTIFY MSG OFF ( = single lun)
6967468Snon * 0x08   SYNC TRANSFER OFF
7067468Snon */
7167468Snon/* #define	STG_SYNC_SUPPORT */	/* NOT YET but easy */
7267468Snon
7367468Snon/* For the 512 fifo type: change below */
7467468Snon#define	TMC18C30_FIFOSZ	0x800
7579697Snon#define	TMC18C30_FCBSZ	0x200
7667468Snon#define	TMC18C50_FIFOSZ	0x2000
7779697Snon#define	TMC18C50_FCBSZ	0x400
7867468Snon
7979697Snon#define	STG_MAX_DATA_SIZE	(64 * 1024)
8079697Snon#define	STG_DELAY_MAX			(2 * 1000 * 1000)
8179697Snon#define	STG_DELAY_INTERVAL		(1)
8279697Snon#define	STG_DELAY_SELECT_POLLING_MAX	(5 * 1000 * 1000)
8379697Snon
8467468Snon/***************************************************
8567468Snon * PARAMS
8667468Snon ***************************************************/
8767468Snon#define	STG_NTARGETS	8
8867468Snon#define	STG_NLUNS	8
8967468Snon
9067468Snon/***************************************************
9167468Snon * DEBUG
9267468Snon ***************************************************/
9367468Snon#ifdef	STG_DEBUG
9489093Smsmithstatic int stg_debug;
9567468Snon#endif	/* STG_DEBUG */
9667468Snon
9767468Snon#ifdef	STG_STATICS
9889093Smsmithstatic struct stg_statics {
9979697Snon	int arbit_fail_0;
10079697Snon	int arbit_fail_1;
10167468Snon	int disconnect;
10267468Snon	int reselect;
10379697Snon} stg_statics;
10467468Snon#endif	/* STG_STATICS */
10567468Snon
10667468Snon/***************************************************
10779697Snon * IO control flags
10867468Snon ***************************************************/
10979697Snon#define	STG_FIFO_INTERRUPTS	0x0001
11079697Snon#define	STG_WAIT_FOR_SELECT	0x0100
11179697Snon
11279697Snonint stg_io_control = STG_IO_CONTROL_FLAGS;
11379697Snon
11479697Snon/***************************************************
11579697Snon * DEVICE STRUCTURE
11679697Snon ***************************************************/
11767468Snonextern struct cfdriver stg_cd;
11867468Snon
11967468Snon/**************************************************************
12067468Snon * DECLARE
12167468Snon **************************************************************/
12267468Snon/* static */
12392739Salfredstatic void stg_pio_read(struct stg_softc *, struct targ_info *, u_int);
12492739Salfredstatic void stg_pio_write(struct stg_softc *, struct targ_info *, u_int);
12592739Salfredstatic int stg_xfer(struct stg_softc *, u_int8_t *, int, int, int);
12692739Salfredstatic int stg_msg(struct stg_softc *, struct targ_info *, u_int);
12792739Salfredstatic int stg_reselected(struct stg_softc *);
12892739Salfredstatic int stg_disconnected(struct stg_softc *, struct targ_info *);
12992739Salfredstatic __inline void stg_pdma_end(struct stg_softc *, struct targ_info *);
13092739Salfredstatic int stghw_select_targ_wait(struct stg_softc *, int);
13192739Salfredstatic int stghw_check(struct stg_softc *);
13292739Salfredstatic void stghw_init(struct stg_softc *);
13392739Salfredstatic int stg_negate_signal(struct stg_softc *, u_int8_t, u_char *);
13492739Salfredstatic int stg_expect_signal(struct stg_softc *, u_int8_t, u_int8_t);
13592739Salfredstatic int stg_world_start(struct stg_softc *, int);
13692739Salfredstatic int stghw_start_selection(struct stg_softc *sc, struct slccb *);
13792739Salfredstatic void stghw_bus_reset(struct stg_softc *);
13892739Salfredstatic void stghw_attention(struct stg_softc *);
13992739Salfredstatic int stg_target_nexus_establish(struct stg_softc *);
14092739Salfredstatic int stg_lun_nexus_establish(struct stg_softc *);
14192739Salfredstatic int stg_ccb_nexus_establish(struct stg_softc *);
14292739Salfredstatic int stg_targ_init(struct stg_softc *, struct targ_info *, int);
14392739Salfredstatic __inline void stghw_bcr_write_1(struct stg_softc *, u_int8_t);
14492739Salfredstatic int stg_timeout(struct stg_softc *);
14592739Salfredstatic void stg_selection_done_and_expect_msgout(struct stg_softc *);
14667468Snon
14767468Snonstruct scsi_low_funcs stgfuncs = {
14867468Snon	SC_LOW_INIT_T stg_world_start,
14967468Snon	SC_LOW_BUSRST_T stghw_bus_reset,
15073025Snon	SC_LOW_TARG_INIT_T stg_targ_init,
15179697Snon	SC_LOW_LUN_INIT_T NULL,
15267468Snon
15367468Snon	SC_LOW_SELECT_T stghw_start_selection,
15479697Snon	SC_LOW_NEXUS_T stg_lun_nexus_establish,
15579697Snon	SC_LOW_NEXUS_T stg_ccb_nexus_establish,
15667468Snon
15767468Snon	SC_LOW_ATTEN_T stghw_attention,
15867468Snon	SC_LOW_MSG_T stg_msg,
15967468Snon
16079697Snon	SC_LOW_TIMEOUT_T stg_timeout,
16167468Snon	SC_LOW_POLL_T stgintr,
16267468Snon
16367468Snon	NULL,
16467468Snon};
16567468Snon
16667468Snon/****************************************************
16779697Snon * hwfuncs
16867468Snon ****************************************************/
16967468Snonstatic __inline void
170189004Srdivackystghw_bcr_write_1(struct stg_softc *sc, u_int8_t bcv)
17167468Snon{
17267468Snon
173274760Sjhb	bus_write_1(sc->port_res, tmc_bctl, bcv);
17467468Snon	sc->sc_busimg = bcv;
17567468Snon}
17667468Snon
17779697Snonstatic int
17879697Snonstghw_check(sc)
17979697Snon	struct stg_softc *sc;
18079697Snon{
18179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
18279697Snon	u_int fcbsize, fcb;
18379697Snon	u_int16_t lsb, msb;
18479697Snon
185274760Sjhb	lsb = bus_read_1(sc->port_res, tmc_idlsb);
186274760Sjhb	msb = bus_read_1(sc->port_res, tmc_idmsb);
18779697Snon	switch (msb << 8 | lsb)
18879697Snon	{
18979697Snon		case 0x6127:
19079697Snon			/* TMCCHIP_1800 not supported. (it's my policy) */
19179697Snon			sc->sc_chip = TMCCHIP_1800;
19279697Snon			return EINVAL;
19379697Snon
19479697Snon		case 0x60e9:
195274760Sjhb			if (bus_read_1(sc->port_res, tmc_cfg2) & 0x02)
19679697Snon			{
19779697Snon				sc->sc_chip = TMCCHIP_18C30;
19879697Snon				sc->sc_fsz = TMC18C30_FIFOSZ;
19979697Snon				fcbsize = TMC18C30_FCBSZ;
20079697Snon			}
20179697Snon			else
20279697Snon			{
20379697Snon				sc->sc_chip = TMCCHIP_18C50;
20479697Snon				sc->sc_fsz = TMC18C50_FIFOSZ;
20579697Snon				fcbsize = TMC18C50_FCBSZ;
20679697Snon			}
20779697Snon			break;
20879697Snon
20979697Snon		default:
21079697Snon			sc->sc_chip = TMCCHIP_UNK;
21179697Snon			return ENODEV;
21279697Snon	}
21379697Snon
21479697Snon	sc->sc_fcRinit = FCTL_INTEN;
21579697Snon	sc->sc_fcWinit = FCTL_PARENB | FCTL_INTEN;
21679697Snon
21779697Snon	if (slp->sl_cfgflags & CFG_NOATTEN)
21879697Snon		sc->sc_imsg = 0;
21979697Snon	else
22079697Snon		sc->sc_imsg = BCTL_ATN;
22179697Snon	sc->sc_busc = BCTL_BUSEN;
22279697Snon
22379697Snon	sc->sc_wthold = fcbsize + 256;
22479697Snon	sc->sc_rthold = fcbsize - 256;
22579697Snon	sc->sc_maxwsize = sc->sc_fsz;
22679697Snon
22779697Snon	fcb = fcbsize / (sc->sc_fsz / 16);
22879697Snon	sc->sc_icinit = ICTL_CD | ICTL_SEL | ICTL_ARBIT | fcb;
22979697Snon	return 0;
23079697Snon}
23179697Snon
23267468Snonstatic void
23379697Snonstghw_init(sc)
23479697Snon	struct stg_softc *sc;
23579697Snon{
23679697Snon
237274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, 0);
23879697Snon	stghw_bcr_write_1(sc, BCTL_BUSFREE);
239274760Sjhb	bus_write_1(sc->port_res, tmc_fctl,
24079697Snon			  sc->sc_fcRinit | FCTL_CLRFIFO | FCTL_CLRINT);
241274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
242274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, sc->sc_icinit);
24379697Snon
244274760Sjhb	bus_write_1(sc->port_res, tmc_ssctl, 0);
24579697Snon}
24679697Snon
24779697Snonstatic int
24879697Snonstg_targ_init(sc, ti, action)
24979697Snon	struct stg_softc *sc;
25079697Snon	struct targ_info *ti;
25179697Snon	int action;
25279697Snon{
25379697Snon	struct stg_targ_info *sti = (void *) ti;
25479697Snon
25579697Snon	if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
25679697Snon	{
25779697Snon		ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
25879697Snon		ti->ti_maxsynch.period = 0;
25979697Snon		ti->ti_maxsynch.offset = 0;
26079697Snon		sti->sti_reg_synch = 0;
26179697Snon	}
26279697Snon	return 0;
26379697Snon}
26479697Snon
26579697Snon/****************************************************
26679697Snon * scsi low interface
26779697Snon ****************************************************/
26879697Snonstatic void
26967468Snonstghw_attention(sc)
27067468Snon	struct stg_softc *sc;
27167468Snon{
27267468Snon
27367468Snon	sc->sc_busc |= BCTL_ATN;
27467468Snon	sc->sc_busimg |= BCTL_ATN;
275274760Sjhb	bus_write_1(sc->port_res, tmc_bctl, sc->sc_busimg);
276240172Sjhb	DELAY(10);
27767468Snon}
27867468Snon
27967468Snonstatic void
28067468Snonstghw_bus_reset(sc)
28167468Snon	struct stg_softc *sc;
28267468Snon{
28367468Snon
284274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, 0);
285274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, 0);
28667468Snon	stghw_bcr_write_1(sc, BCTL_RST);
287240172Sjhb	DELAY(100000);
28867468Snon	stghw_bcr_write_1(sc, BCTL_BUSFREE);
28967468Snon}
29067468Snon
29167468Snonstatic int
29267468Snonstghw_start_selection(sc, cb)
29367468Snon	struct stg_softc *sc;
29467468Snon	struct slccb *cb;
29567468Snon{
29667468Snon	struct targ_info *ti = cb->ti;
29767468Snon	register u_int8_t stat;
29867468Snon
29979697Snon	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
30079697Snon	sc->sc_dataout_timeout = 0;
30179697Snon	sc->sc_ubf_timeout = 0;
30267468Snon	stghw_bcr_write_1(sc, BCTL_BUSFREE);
303274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, sc->sc_icinit);
30467468Snon
305274760Sjhb	stat = bus_read_1(sc->port_res, tmc_astat);
30679697Snon	if ((stat & ASTAT_INT) != 0)
30767468Snon	{
30879697Snon		return SCSI_LOW_START_FAIL;
30967468Snon	}
31067468Snon
311274760Sjhb	bus_write_1(sc->port_res, tmc_scsiid, sc->sc_idbit);
312274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit | FCTL_ARBIT);
31367468Snon
31467468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART);
31567468Snon	return SCSI_LOW_START_OK;
31667468Snon}
31767468Snon
31867468Snonstatic int
31967468Snonstg_world_start(sc, fdone)
32067468Snon	struct stg_softc *sc;
32167468Snon	int fdone;
32267468Snon{
32367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
32467468Snon	int error;
32567468Snon
32679697Snon	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
32779697Snon		sc->sc_fcRinit |= FCTL_PARENB;
32879697Snon	else
32979697Snon		sc->sc_fcRinit &= ~FCTL_PARENB;
33079697Snon
33167468Snon	if ((error = stghw_check(sc)) != 0)
33267468Snon		return error;
33367468Snon
33467468Snon	stghw_init(sc);
33567468Snon	scsi_low_bus_reset(slp);
33667468Snon	stghw_init(sc);
33767468Snon
33867468Snon	return 0;
33967468Snon}
34067468Snon
34167468Snonstatic int
34267468Snonstg_msg(sc, ti, msg)
34367468Snon	struct stg_softc *sc;
34467468Snon	struct targ_info *ti;
34567468Snon	u_int msg;
34667468Snon{
34773025Snon	struct stg_targ_info *sti = (void *) ti;
34867468Snon	u_int period, offset;
34967468Snon
35079697Snon	if ((msg & SCSI_LOW_MSG_WIDE) != 0)
35179697Snon	{
35279697Snon		if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
35379697Snon		{
35479697Snon			ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
35579697Snon			return EINVAL;
35679697Snon		}
35779697Snon		return 0;
35879697Snon	}
35967468Snon
36079697Snon	if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
36179697Snon		return 0;
36279697Snon
36373025Snon 	period = ti->ti_maxsynch.period;
36473025Snon	offset = ti->ti_maxsynch.offset;
36567468Snon	period = period << 2;
36667468Snon	if (period >= 200)
36767468Snon	{
36873025Snon		sti->sti_reg_synch = (period - 200) / 50;
36967468Snon		if (period % 50)
37073025Snon			sti->sti_reg_synch ++;
37173025Snon		sti->sti_reg_synch |= SSCTL_SYNCHEN;
37267468Snon	}
37367468Snon	else if (period >= 100)
37467468Snon	{
37573025Snon		sti->sti_reg_synch = (period - 100) / 50;
37667468Snon		if (period % 50)
37773025Snon			sti->sti_reg_synch ++;
37873025Snon		sti->sti_reg_synch |= SSCTL_SYNCHEN | SSCTL_FSYNCHEN;
37967468Snon	}
380274760Sjhb	bus_write_1(sc->port_res, tmc_ssctl, sti->sti_reg_synch);
38167468Snon	return 0;
38267468Snon}
38367468Snon
38467468Snon/**************************************************************
38567468Snon * General probe attach
38667468Snon **************************************************************/
38767468Snonint
388274760Sjhbstgprobesubr(struct resource *res, u_int dvcfg)
38967468Snon{
39067468Snon	u_int16_t lsb, msb;
39167468Snon
392274760Sjhb	lsb = bus_read_1(res, tmc_idlsb);
393274760Sjhb	msb = bus_read_1(res, tmc_idmsb);
39467468Snon	switch (msb << 8 | lsb)
39567468Snon	{
39667468Snon		default:
39767468Snon			return 0;
39867468Snon		case 0x6127:
39967468Snon			/* not support! */
40067468Snon			return 0;
40167468Snon		case 0x60e9:
40267468Snon			return 1;
40367468Snon	}
40467468Snon	return 0;
40567468Snon}
40667468Snon
40767468Snonvoid
40867468Snonstgattachsubr(sc)
40967468Snon	struct stg_softc *sc;
41067468Snon{
41167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
41267468Snon
41367468Snon	printf("\n");
41467468Snon
41567468Snon	sc->sc_idbit = (1 << slp->sl_hostid);
41667468Snon	slp->sl_funcs = &stgfuncs;
41779697Snon	sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
41867468Snon
41979697Snon	slp->sl_flags |= HW_READ_PADDING;
42067468Snon	slp->sl_cfgflags |= CFG_ASYNC;	/* XXX */
42167468Snon
42279697Snon	(void) scsi_low_attach(slp, 0, STG_NTARGETS, STG_NLUNS,
42379697Snon				sizeof(struct stg_targ_info), 0);
42467468Snon}
42567468Snon
42667468Snon/**************************************************************
42767468Snon * PDMA functions
42867468Snon **************************************************************/
42967468Snonstatic __inline void
43067468Snonstg_pdma_end(sc, ti)
43167468Snon	struct stg_softc *sc;
43267468Snon	struct targ_info *ti;
43367468Snon{
43467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
43579697Snon	struct slccb *cb = slp->sl_Qnexus;
43667468Snon	u_int len, tres;
43767468Snon
43867468Snon	slp->sl_flags &= ~HW_PDMASTART;
43979697Snon	sc->sc_icinit &= ~ICTL_FIFO;
44079697Snon	sc->sc_dataout_timeout = 0;
44167468Snon
44279697Snon	if (cb == NULL)
44379697Snon	{
44479697Snon		slp->sl_error |= PDMAERR;
44579697Snon		goto out;
44679697Snon	}
44779697Snon
44867468Snon	if (ti->ti_phase == PH_DATA)
44967468Snon	{
450274760Sjhb		len = bus_read_2(sc->port_res, tmc_fdcnt);
45167468Snon		if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
45267468Snon		{
45367468Snon			if (len != 0)
45467468Snon			{
45567468Snon				tres = len + slp->sl_scp.scp_datalen;
45667468Snon				if (tres <= (u_int) cb->ccb_scp.scp_datalen)
45767468Snon				{
45867468Snon					slp->sl_scp.scp_data -= len;
45967468Snon					slp->sl_scp.scp_datalen = tres;
46067468Snon				}
46167468Snon				else
46267468Snon				{
46367468Snon					slp->sl_error |= PDMAERR;
464240325Sjhb					device_printf(slp->sl_dev,
465240325Sjhb						"len %x >= datalen %x\n",
46667468Snon						len, slp->sl_scp.scp_datalen);
46767468Snon				}
46867468Snon			}
46967468Snon		}
47067468Snon		else if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
47167468Snon		{
47267468Snon			if (len != 0)
47367468Snon			{
47467468Snon				slp->sl_error |= PDMAERR;
475240325Sjhb				device_printf(slp->sl_dev,
476240325Sjhb				    "len %x left in fifo\n", len);
47767468Snon			}
47867468Snon		}
47979697Snon		scsi_low_data_finish(slp);
48067468Snon	}
48167468Snon	else
48267468Snon	{
48367468Snon
484240325Sjhb		device_printf(slp->sl_dev, "data phase miss\n");
48567468Snon		slp->sl_error |= PDMAERR;
48667468Snon	}
48767468Snon
48879697Snonout:
489274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
49067468Snon}
49167468Snon
49267468Snonstatic void
49379697Snonstg_pio_read(sc, ti, thold)
49467468Snon	struct stg_softc *sc;
49567468Snon	struct targ_info *ti;
49679697Snon	u_int thold;
49767468Snon{
49867468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
49967468Snon	struct sc_p *sp = &slp->sl_scp;
500274760Sjhb	int tout;
50167468Snon	u_int res;
50267468Snon	u_int8_t stat;
50367468Snon
50479697Snon	if ((slp->sl_flags & HW_PDMASTART) == 0)
50579697Snon	{
506274760Sjhb		bus_write_1(sc->port_res, tmc_fctl,
50779697Snon				  sc->sc_fcRinit | FCTL_FIFOEN);
50879697Snon		slp->sl_flags |= HW_PDMASTART;
50979697Snon	}
51067468Snon
51179697Snon	tout = sc->sc_tmaxcnt;
51279697Snon	while (tout -- > 0)
51367468Snon	{
51479697Snon		if (thold > 0)
51567468Snon		{
516274760Sjhb			res = bus_read_2(sc->port_res, tmc_fdcnt);
51779697Snon			if (res < thold)
51879697Snon			{
519274760Sjhb				bus_write_1(sc->port_res, tmc_ictl,
52079697Snon						  sc->sc_icinit);
52179697Snon				break;
52279697Snon			}
52379697Snon		}
52479697Snon		else
52579697Snon		{
526274760Sjhb			stat = bus_read_1(sc->port_res, tmc_bstat);
527274760Sjhb			res = bus_read_2(sc->port_res, tmc_fdcnt);
52879697Snon			if (res == 0)
52979697Snon			{
53079697Snon				if ((stat & PHASE_MASK) != DATA_IN_PHASE)
53179697Snon					break;
53279697Snon				if (sp->scp_datalen <= 0)
53379697Snon					break;
534240172Sjhb				DELAY(1);
53567468Snon				continue;
53679697Snon			}
53767468Snon		}
53867468Snon
53979697Snon		/* The assumtion res != 0 is valid here */
54067468Snon		if (res > sp->scp_datalen)
54167468Snon		{
54279697Snon			if (res == (u_int) -1)
54379697Snon				break;
54479697Snon
54567468Snon			slp->sl_error |= PDMAERR;
54679697Snon			if ((slp->sl_flags & HW_READ_PADDING) == 0)
54779697Snon			{
548240325Sjhb				device_printf(slp->sl_dev,
549240325Sjhb				    "read padding required\n");
55079697Snon				break;
55179697Snon			}
55279697Snon
55379697Snon			sp->scp_datalen = 0;
55479697Snon			if (res > STG_MAX_DATA_SIZE)
55579697Snon				res = STG_MAX_DATA_SIZE;
55679697Snon			while (res -- > 0)
55779697Snon			{
558274760Sjhb				(void) bus_read_1(sc->port_res, tmc_rfifo);
55979697Snon			}
56079697Snon			continue;
56167468Snon		}
56267468Snon
56367468Snon		sp->scp_datalen -= res;
56467468Snon		if (res & 1)
56567468Snon		{
566274760Sjhb			*sp->scp_data = bus_read_1(sc->port_res, tmc_rfifo);
56767468Snon			sp->scp_data ++;
56867468Snon			res --;
56967468Snon		}
57067468Snon
571274760Sjhb		bus_read_multi_2(sc->port_res, tmc_rfifo,
57267468Snon				       (u_int16_t *) sp->scp_data, res >> 1);
57367468Snon		sp->scp_data += res;
57467468Snon	}
57567468Snon
57673025Snon	if (tout <= 0)
577240325Sjhb		device_printf(slp->sl_dev, "pio read timeout\n");
57867468Snon}
57967468Snon
58067468Snonstatic void
58179697Snonstg_pio_write(sc, ti, thold)
58267468Snon	struct stg_softc *sc;
58367468Snon	struct targ_info *ti;
58479697Snon	u_int thold;
58567468Snon{
58667468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
58767468Snon	struct sc_p *sp = &slp->sl_scp;
58867468Snon	u_int res;
589274760Sjhb	int tout;
59067468Snon	register u_int8_t stat;
59167468Snon
59279697Snon	if ((slp->sl_flags & HW_PDMASTART) == 0)
59379697Snon	{
59479697Snon		stat = sc->sc_fcWinit | FCTL_FIFOEN | FCTL_FIFOW;
595274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, stat | FCTL_CLRFIFO);
596274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, stat);
59779697Snon		slp->sl_flags |= HW_PDMASTART;
59879697Snon	}
59967468Snon
60079697Snon	tout = sc->sc_tmaxcnt;
60179697Snon	while (tout -- > 0)
60267468Snon	{
603274760Sjhb		stat = bus_read_1(sc->port_res, tmc_bstat);
60479697Snon		if ((stat & PHASE_MASK) != DATA_OUT_PHASE)
60567468Snon			break;
60667468Snon
60779697Snon		if (sp->scp_datalen <= 0)
60879697Snon		{
60979697Snon			if (sc->sc_dataout_timeout == 0)
61079697Snon				sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
61179697Snon			break;
61279697Snon		}
61367468Snon
61479697Snon		if (thold > 0)
61579697Snon		{
616274760Sjhb			res = bus_read_2(sc->port_res, tmc_fdcnt);
61779697Snon			if (res > thold)
61879697Snon			{
619274760Sjhb				bus_write_1(sc->port_res, tmc_ictl,
62079697Snon						  sc->sc_icinit);
62179697Snon				break;
62279697Snon			}
62379697Snon		}
62479697Snon		else
62579697Snon		{
626274760Sjhb			res = bus_read_2(sc->port_res, tmc_fdcnt);
62779697Snon			if (res > sc->sc_maxwsize / 2)
62879697Snon			{
629240172Sjhb				DELAY(1);
63079697Snon				continue;
63179697Snon			}
63279697Snon		}
63379697Snon
63479697Snon		if (res == (u_int) -1)
63579697Snon			break;
63679697Snon		res = sc->sc_maxwsize - res;
63779697Snon		if (res > sp->scp_datalen)
63879697Snon			res = sp->scp_datalen;
63979697Snon
64067468Snon		sp->scp_datalen -= res;
64167468Snon		if ((res & 0x1) != 0)
64267468Snon		{
643274760Sjhb			bus_write_1(sc->port_res, tmc_wfifo, *sp->scp_data);
64467468Snon			sp->scp_data ++;
64567468Snon			res --;
64667468Snon		}
64767468Snon
648274760Sjhb		bus_write_multi_2(sc->port_res, tmc_wfifo,
64967468Snon					(u_int16_t *) sp->scp_data, res >> 1);
65067468Snon		sp->scp_data += res;
65167468Snon	}
65267468Snon
65373025Snon	if (tout <= 0)
654240325Sjhb		device_printf(slp->sl_dev, "pio write timeout\n");
65567468Snon}
65667468Snon
65767468Snonstatic int
658189004Srdivackystg_negate_signal(struct stg_softc *sc, u_int8_t mask, u_char *s)
65967468Snon{
66067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
66179697Snon	int wc;
66267468Snon	u_int8_t regv;
66367468Snon
66479697Snon	for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++)
66567468Snon	{
666274760Sjhb		regv = bus_read_1(sc->port_res, tmc_bstat);
66779697Snon		if (regv == (u_int8_t) -1)
66879697Snon			return -1;
66979697Snon		if ((regv & mask) == 0)
67079697Snon			return 1;
67179697Snon
672240172Sjhb		DELAY(STG_DELAY_INTERVAL);
67367468Snon	}
67467468Snon
675240325Sjhb	device_printf(slp->sl_dev, "%s stg_negate_signal timeout\n", s);
67679697Snon	return -1;
67767468Snon}
67867468Snon
67967468Snonstatic int
680189004Srdivackystg_expect_signal(struct stg_softc *sc, u_int8_t phase, u_int8_t mask)
68167468Snon{
68267468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
68379697Snon	int wc;
68467468Snon	u_int8_t ph;
68567468Snon
68679697Snon	phase &= PHASE_MASK;
68779697Snon	for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++)
68867468Snon	{
689274760Sjhb		ph = bus_read_1(sc->port_res, tmc_bstat);
69079697Snon		if (ph == (u_int8_t) -1)
69179697Snon			return -1;
69279697Snon		if ((ph & PHASE_MASK) != phase)
69379697Snon			return 0;
69479697Snon		if ((ph & mask) != 0)
69579697Snon			return 1;
69679697Snon
697240172Sjhb		DELAY(STG_DELAY_INTERVAL);
69867468Snon	}
69967468Snon
700240325Sjhb	device_printf(slp->sl_dev, "stg_expect_signal timeout\n");
70179697Snon	return -1;
70267468Snon}
70367468Snon
70467468Snonstatic int
70579697Snonstg_xfer(sc, buf, len, phase, clear_atn)
70667468Snon	struct stg_softc *sc;
70767468Snon	u_int8_t *buf;
70867468Snon	int len;
70967468Snon	int phase;
71079697Snon	int clear_atn;
71167468Snon{
71279697Snon	int rv, ptr;
71367468Snon
71467468Snon	if (phase & BSTAT_IO)
715274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
71667468Snon	else
717274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcWinit);
71867468Snon
71967468Snon	for (ptr = 0; len > 0; len --)
72067468Snon	{
72167468Snon		rv = stg_expect_signal(sc, phase, BSTAT_REQ);
72267468Snon		if (rv <= 0)
72367468Snon			goto bad;
72467468Snon
72579697Snon		if (len == 1 && clear_atn != 0)
72667468Snon		{
72767468Snon			sc->sc_busc &= ~BCTL_ATN;
72867468Snon			stghw_bcr_write_1(sc, sc->sc_busc);
72979697Snon			SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow);
73067468Snon		}
73167468Snon
73267468Snon		if (phase & BSTAT_IO)
73367468Snon		{
734274760Sjhb			buf[ptr ++] = bus_read_1(sc->port_res, tmc_rdata);
73567468Snon		}
73667468Snon		else
73767468Snon		{
738274760Sjhb			bus_write_1(sc->port_res, tmc_wdata, buf[ptr ++]);
73967468Snon		}
74079697Snon
74167468Snon		stg_negate_signal(sc, BSTAT_ACK, "xfer<ACK>");
74267468Snon	}
74367468Snon
74467468Snonbad:
745274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
74667468Snon	return len;
74767468Snon}
74867468Snon
74967468Snon/**************************************************************
75067468Snon * disconnect & reselect (HW low)
75167468Snon **************************************************************/
75267468Snonstatic int
75367468Snonstg_reselected(sc)
75467468Snon	struct stg_softc *sc;
75567468Snon{
75667468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
75779697Snon	int tout;
75867468Snon	u_int sid;
75979697Snon	u_int8_t regv;
76067468Snon
76167468Snon	if (slp->sl_selid != NULL)
76267468Snon	{
76367468Snon		/* XXX:
76467468Snon		 * Selection vs Reselection conflicts.
76567468Snon		 */
766274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
76767468Snon		stghw_bcr_write_1(sc, BCTL_BUSFREE);
76867468Snon	}
76979697Snon	else if (slp->sl_Tnexus != NULL)
77079697Snon	{
771240325Sjhb		device_printf(slp->sl_dev, "unexpected termination\n");
77279697Snon		stg_disconnected(sc, slp->sl_Tnexus);
77379697Snon	}
77467468Snon
77567468Snon	/* XXX:
77667468Snon	 * We should ack the reselection as soon as possible,
777123608Sjhb	 * because the target would abort the current reselection seq
77867468Snon  	 * due to reselection timeout.
77967468Snon	 */
78079697Snon	tout = STG_DELAY_SELECT_POLLING_MAX;
78179697Snon	while (tout -- > 0)
78279697Snon	{
783274760Sjhb		regv = bus_read_1(sc->port_res, tmc_bstat);
78479697Snon		if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) ==
78579697Snon			    (BSTAT_IO | BSTAT_SEL))
78679697Snon		{
787240172Sjhb			DELAY(1);
788274760Sjhb			regv = bus_read_1(sc->port_res, tmc_bstat);
78979697Snon			if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) ==
79079697Snon				    (BSTAT_IO | BSTAT_SEL))
79179697Snon				goto reselect_start;
79279697Snon		}
793240172Sjhb		DELAY(1);
79479697Snon	}
795240325Sjhb	device_printf(slp->sl_dev, "reselction timeout I\n");
79679697Snon	return EJUSTRETURN;
79779697Snon
79879697Snonreselect_start:
799274760Sjhb	sid = (u_int) bus_read_1(sc->port_res, tmc_scsiid);
80079697Snon	if ((sid & sc->sc_idbit) == 0)
80179697Snon	{
80279697Snon		/* not us */
80379697Snon		return EJUSTRETURN;
80479697Snon	}
80579697Snon
806274760Sjhb	bus_write_1(sc->port_res, tmc_fctl,
80779697Snon			    sc->sc_fcRinit | FCTL_CLRFIFO | FCTL_CLRINT);
808274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
80967468Snon	stghw_bcr_write_1(sc, sc->sc_busc | BCTL_BSY);
81067468Snon
81179697Snon	while (tout -- > 0)
81279697Snon	{
813274760Sjhb		regv = bus_read_1(sc->port_res, tmc_bstat);
81479697Snon		if ((regv & (BSTAT_SEL | BSTAT_BSY)) == BSTAT_BSY)
81579697Snon			goto reselected;
816240172Sjhb		DELAY(1);
81779697Snon	}
818240325Sjhb	device_printf(slp->sl_dev, "reselction timeout II\n");
81979697Snon	return EJUSTRETURN;
82079697Snon
82179697Snonreselected:
82267468Snon	sid &= ~sc->sc_idbit;
82367468Snon	sid = ffs(sid) - 1;
82479697Snon	if (scsi_low_reselected(slp, sid) == NULL)
82567468Snon		return EJUSTRETURN;
82667468Snon
82767468Snon#ifdef	STG_STATICS
82879697Snon	stg_statics.reselect ++;
82967468Snon#endif	/* STG_STATICS */
83067468Snon	return EJUSTRETURN;
83167468Snon}
83267468Snon
83379697Snonstatic int
83467468Snonstg_disconnected(sc, ti)
83567468Snon	struct stg_softc *sc;
83667468Snon	struct targ_info *ti;
83767468Snon{
83867468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
83967468Snon
84067468Snon	/* clear bus status & fifo */
841274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO);
842274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
84367468Snon	stghw_bcr_write_1(sc, BCTL_BUSFREE);
84479697Snon	sc->sc_icinit &= ~ICTL_FIFO;
84567468Snon	sc->sc_busc &= ~BCTL_ATN;
84679697Snon	sc->sc_dataout_timeout = 0;
84779697Snon	sc->sc_ubf_timeout = 0;
84867468Snon
84967468Snon#ifdef	STG_STATICS
85079697Snon	stg_statics.disconnect ++;
85167468Snon#endif	/* STG_STATICS */
85267468Snon	scsi_low_disconnected(slp, ti);
85367468Snon	return 1;
85467468Snon}
85567468Snon
85667468Snon/**************************************************************
85767468Snon * SEQUENCER
85867468Snon **************************************************************/
85967468Snonstatic int
86079697Snonstg_target_nexus_establish(sc)
86167468Snon	struct stg_softc *sc;
86267468Snon{
86379697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
86479697Snon	struct targ_info *ti = slp->sl_Tnexus;
86573025Snon	struct stg_targ_info *sti = (void *) ti;
86667468Snon
867274760Sjhb	bus_write_1(sc->port_res, tmc_ssctl, sti->sti_reg_synch);
86879697Snon	if ((stg_io_control & STG_FIFO_INTERRUPTS) != 0)
86979697Snon	{
87079697Snon		sc->sc_icinit |= ICTL_FIFO;
87179697Snon	}
87267468Snon	return 0;
87367468Snon}
87467468Snon
87567468Snonstatic int
87679697Snonstg_lun_nexus_establish(sc)
87767468Snon	struct stg_softc *sc;
87867468Snon{
87979697Snon
88079697Snon	return 0;
88179697Snon}
88279697Snon
88379697Snonstatic int
88479697Snonstg_ccb_nexus_establish(sc)
88579697Snon	struct stg_softc *sc;
88679697Snon{
88779697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
88879697Snon	struct slccb *cb = slp->sl_Qnexus;
88979697Snon
89079697Snon	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
89179697Snon	return 0;
89279697Snon}
89379697Snon
89479697Snon#define	STGHW_SELECT_INTERVAL	10
89579697Snon
89679697Snonstatic int
89779697Snonstghw_select_targ_wait(sc, mu)
89879697Snon	struct stg_softc *sc;
89979697Snon	int mu;
90079697Snon{
90167468Snon
90279697Snon	mu = mu / STGHW_SELECT_INTERVAL;
90379697Snon	while (mu -- > 0)
90467468Snon	{
905274760Sjhb		if ((bus_read_1(sc->port_res, tmc_bstat) & BSTAT_BSY) == 0)
90667468Snon		{
907240172Sjhb			DELAY(STGHW_SELECT_INTERVAL);
90879697Snon			continue;
90967468Snon		}
910240172Sjhb		DELAY(1);
911274760Sjhb		if ((bus_read_1(sc->port_res, tmc_bstat) & BSTAT_BSY) != 0)
91279697Snon		{
91379697Snon			return 0;
91479697Snon		}
91567468Snon	}
91679697Snon	return ENXIO;
91779697Snon}
91867468Snon
91979697Snonstatic void
92079697Snonstg_selection_done_and_expect_msgout(sc)
92179697Snon	struct stg_softc *sc;
92279697Snon{
92379697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
92479697Snon
925274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO);
926274760Sjhb	bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
92779697Snon	stghw_bcr_write_1(sc, sc->sc_imsg | sc->sc_busc);
92879697Snon	SCSI_LOW_ASSERT_ATN(slp);
92967468Snon}
93067468Snon
93167468Snonint
93267468Snonstgintr(arg)
93367468Snon	void *arg;
93467468Snon{
93567468Snon	struct stg_softc *sc = arg;
93667468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
93767468Snon	struct targ_info *ti;
93867468Snon	struct buf *bp;
93979697Snon	u_int derror, flags;
940274760Sjhb	int len;
94167468Snon	u_int8_t status, astatus, regv;
94267468Snon
94367468Snon	/*******************************************
94467468Snon	 * interrupt check
94567468Snon	 *******************************************/
94667468Snon	if (slp->sl_flags & HW_INACTIVE)
94767468Snon		return 0;
94867468Snon
949274760Sjhb	astatus = bus_read_1(sc->port_res, tmc_astat);
950274760Sjhb	status = bus_read_1(sc->port_res, tmc_bstat);
95167468Snon
95279697Snon	if ((astatus & ASTAT_STATMASK) == 0 || astatus == (u_int8_t) -1)
95367468Snon		return 0;
95467468Snon
955274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, 0);
95667468Snon	if (astatus & ASTAT_SCSIRST)
95767468Snon	{
958274760Sjhb		bus_write_1(sc->port_res, tmc_fctl,
95967468Snon				  sc->sc_fcRinit | FCTL_CLRFIFO);
960274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
961274760Sjhb		bus_write_1(sc->port_res, tmc_ictl, 0);
96267468Snon
96367468Snon		scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
96467468Snon				 "bus reset (power off?)");
96567468Snon		return 1;
96667468Snon	}
96767468Snon
96867468Snon	/*******************************************
96967468Snon	 * debug section
97067468Snon	 *******************************************/
97167468Snon#ifdef	STG_DEBUG
97267468Snon	if (stg_debug)
97367468Snon	{
97467468Snon		scsi_low_print(slp, NULL);
975240325Sjhb		device_printf(slp->sl_dev, "st %x ist %x\n\n",
97667468Snon		       status, astatus);
977131920Smarcel#ifdef	KDB
97867468Snon		if (stg_debug > 1)
979240172Sjhb			kdb_enter(KDB_WHY_CAM, "stg");
980131920Smarcel#endif	/* KDB */
98167468Snon	}
98267468Snon#endif	/* STG_DEBUG */
98367468Snon
98467468Snon	/*******************************************
98567468Snon	 * reselection & nexus
98667468Snon	 *******************************************/
98767468Snon	if ((status & RESEL_PHASE_MASK)== PHASE_RESELECTED)
98867468Snon	{
98967468Snon		if (stg_reselected(sc) == EJUSTRETURN)
99079697Snon			goto out;
99167468Snon	}
99267468Snon
99379697Snon	if ((ti = slp->sl_Tnexus) == NULL)
99479697Snon		return 0;
99567468Snon
99679697Snon	derror = 0;
99767468Snon	if ((astatus & ASTAT_PARERR) != 0 && ti->ti_phase != PH_ARBSTART &&
99867468Snon	    (sc->sc_fcRinit & FCTL_PARENB) != 0)
99967468Snon	{
100067468Snon		slp->sl_error |= PARITYERR;
100179697Snon		derror = SCSI_LOW_DATA_PE;
100279697Snon		if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
100379697Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
100467468Snon		else
100567468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
100667468Snon	}
100767468Snon
100867468Snon	/*******************************************
100967468Snon	 * aribitration & selection
101067468Snon	 *******************************************/
101167468Snon	switch (ti->ti_phase)
101267468Snon	{
101367468Snon	case PH_ARBSTART:
101467468Snon		if ((astatus & ASTAT_ARBIT) == 0)
101579697Snon		{
101679697Snon#ifdef	STG_STATICS
101779697Snon			stg_statics.arbit_fail_0 ++;
101879697Snon#endif	/* STG_STATICS */
101967468Snon			goto arb_fail;
102079697Snon		}
102167468Snon
1022274760Sjhb		status = bus_read_1(sc->port_res, tmc_bstat);
102367468Snon		if ((status & BSTAT_IO) != 0)
102467468Snon		{
102567468Snon			/* XXX:
102667468Snon			 * Selection vs Reselection conflicts.
102767468Snon			 */
102867468Snon#ifdef	STG_STATICS
102979697Snon			stg_statics.arbit_fail_1 ++;
103067468Snon#endif	/* STG_STATICS */
103167468Snonarb_fail:
1032274760Sjhb			bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
103367468Snon			stghw_bcr_write_1(sc, BCTL_BUSFREE);
103479697Snon			scsi_low_arbit_fail(slp, slp->sl_Qnexus);
103579697Snon			goto out;
103667468Snon		}
103767468Snon
103867468Snon		/*
103967468Snon		 * selection assert start.
104067468Snon		 */
104167468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
104279697Snon		scsi_low_arbit_win(slp);
104379697Snon
1044274760Sjhb		bus_write_1(sc->port_res, tmc_scsiid,
104567468Snon				  sc->sc_idbit | (1 << ti->ti_id));
104667468Snon		stghw_bcr_write_1(sc, sc->sc_imsg | sc->sc_busc | BCTL_SEL);
1047274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcWinit);
104879697Snon		if ((stg_io_control & STG_WAIT_FOR_SELECT) != 0)
104979697Snon		{
105079697Snon			/* selection abort delay 200 + 100 micro sec */
105179697Snon			if (stghw_select_targ_wait(sc, 300) == 0)
105279697Snon			{
105379697Snon				SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
105479697Snon				stg_selection_done_and_expect_msgout(sc);
105579697Snon			}
105679697Snon		}
105779697Snon		goto out;
105867468Snon
105967468Snon	case PH_SELSTART:
106067468Snon		if ((status & BSTAT_BSY) == 0)
106167468Snon		{
106279697Snon			/* selection timeout delay 250 ms */
106379697Snon			if (stghw_select_targ_wait(sc, 250 * 1000) != 0)
106467468Snon			{
106579697Snon				stg_disconnected(sc, ti);
106679697Snon				goto out;
106767468Snon			}
106867468Snon		}
106967468Snon
107067468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
107179697Snon		stg_selection_done_and_expect_msgout(sc);
107279697Snon		goto out;
107367468Snon
107479697Snon	case PH_SELECTED:
107579697Snon		if ((status & BSTAT_REQ) == 0)
107679697Snon			goto out;
107779697Snon		stg_target_nexus_establish(sc);
107879697Snon		break;
107979697Snon
108067468Snon	case PH_RESEL:
108179697Snon		if ((status & BSTAT_REQ) == 0)
108279697Snon			goto out;
108379697Snon
108467468Snon		/* clear a busy line */
1085274760Sjhb		bus_write_1(sc->port_res, tmc_fctl, sc->sc_fcRinit);
108667468Snon		stghw_bcr_write_1(sc, sc->sc_busc);
108779697Snon		stg_target_nexus_establish(sc);
108867468Snon		if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
108967468Snon		{
1090240325Sjhb			device_printf(slp->sl_dev,
1091240325Sjhb			    "unexpected phase after reselect\n");
109279697Snon			slp->sl_error |= FATALIO;
109367468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
109479697Snon			goto out;
109567468Snon		}
109667468Snon		break;
109767468Snon	}
109867468Snon
109967468Snon	/*******************************************
110079697Snon	 * data phase
110167468Snon	 *******************************************/
110279697Snon	if ((slp->sl_flags & HW_PDMASTART) && STG_IS_PHASE_DATA(status) == 0)
110379697Snon	{
110479697Snon		if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
110579697Snon			stg_pio_read(sc, ti, 0);
110679697Snon
110767468Snon		stg_pdma_end(sc, ti);
110879697Snon	}
110967468Snon
111079697Snon	/*******************************************
111179697Snon	 * scsi seq
111279697Snon	 *******************************************/
111367468Snon	switch (status & PHASE_MASK)
111467468Snon	{
111567468Snon	case COMMAND_PHASE:
111679697Snon		if (stg_expect_signal(sc, COMMAND_PHASE, BSTAT_REQ) <= 0)
111779697Snon			break;
111879697Snon
111967468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
112067468Snon		if (scsi_low_cmd(slp, ti) != 0)
112179697Snon		{
112279697Snon			scsi_low_attention(slp);
112379697Snon		}
112467468Snon
112579697Snon		if (stg_xfer(sc, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen,
112679697Snon			     COMMAND_PHASE, 0) != 0)
112767468Snon		{
1128240325Sjhb			device_printf(slp->sl_dev, "CMDOUT short\n");
112967468Snon		}
113067468Snon		break;
113167468Snon
113267468Snon	case DATA_OUT_PHASE:
113367468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
113467468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
113579697Snon		{
113679697Snon			scsi_low_attention(slp);
113779697Snon		}
113867468Snon
113979697Snon		if ((sc->sc_icinit & ICTL_FIFO) != 0)
114079697Snon			stg_pio_write(sc, ti, sc->sc_wthold);
114179697Snon		else
114279697Snon			stg_pio_write(sc, ti, 0);
114367468Snon		break;
114467468Snon
114567468Snon	case DATA_IN_PHASE:
114667468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
114767468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
114879697Snon		{
114979697Snon			scsi_low_attention(slp);
115079697Snon		}
115167468Snon
115279697Snon		if ((sc->sc_icinit & ICTL_FIFO) != 0)
115379697Snon			stg_pio_read(sc, ti, sc->sc_rthold);
115479697Snon		else
115579697Snon			stg_pio_read(sc, ti, 0);
115667468Snon		break;
115767468Snon
115867468Snon	case STATUS_PHASE:
115979697Snon		regv = stg_expect_signal(sc, STATUS_PHASE, BSTAT_REQ);
116079697Snon		if (regv <= 0)
116179697Snon			break;
116279697Snon
116367468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1164274760Sjhb		regv = bus_read_1(sc->port_res, tmc_sdna);
116579697Snon		if (scsi_low_statusin(slp, ti, regv | derror) != 0)
116679697Snon		{
116779697Snon			scsi_low_attention(slp);
116879697Snon		}
1169274760Sjhb		if (regv != bus_read_1(sc->port_res, tmc_rdata))
117079697Snon		{
1171240325Sjhb			device_printf(slp->sl_dev, "STATIN: data mismatch\n");
117279697Snon		}
117379697Snon		stg_negate_signal(sc, BSTAT_ACK, "statin<ACK>");
117467468Snon		break;
117567468Snon
117667468Snon	case MESSAGE_OUT_PHASE:
117779697Snon		if (stg_expect_signal(sc, MESSAGE_OUT_PHASE, BSTAT_REQ) <= 0)
117879697Snon			break;
117979697Snon
118067468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
118179697Snon		flags = (ti->ti_ophase != ti->ti_phase) ?
118279697Snon				SCSI_LOW_MSGOUT_INIT : 0;
118379697Snon		len = scsi_low_msgout(slp, ti, flags);
118479697Snon
118579697Snon		if (len > 1 && slp->sl_atten == 0)
118667468Snon		{
118779697Snon			scsi_low_attention(slp);
118879697Snon		}
118979697Snon
119079697Snon		if (stg_xfer(sc, ti->ti_msgoutstr, len, MESSAGE_OUT_PHASE,
119179697Snon			     slp->sl_clear_atten) != 0)
119279697Snon		{
1193240325Sjhb			device_printf(slp->sl_dev, "MSGOUT short\n");
119467468Snon		}
119579697Snon		else
119679697Snon		{
119779697Snon			if (slp->sl_msgphase >= MSGPH_ABORT)
119879697Snon			{
119979697Snon				stg_disconnected(sc, ti);
120079697Snon			}
120179697Snon		}
120267468Snon		break;
120367468Snon
120467468Snon	case MESSAGE_IN_PHASE:
120579697Snon		/* confirm phase and req signal */
120679697Snon		if (stg_expect_signal(sc, MESSAGE_IN_PHASE, BSTAT_REQ) <= 0)
120779697Snon			break;
120879697Snon
120967468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
121067468Snon
121179697Snon		/* read data with NOACK */
1212274760Sjhb		regv = bus_read_1(sc->port_res, tmc_sdna);
121379697Snon
121479697Snon		if (scsi_low_msgin(slp, ti, derror | regv) == 0)
121567468Snon		{
121679697Snon			if (scsi_low_is_msgout_continue(ti, 0) != 0)
121779697Snon			{
121879697Snon				scsi_low_attention(slp);
121979697Snon			}
122067468Snon		}
122167468Snon
122267468Snon		/* read data with ACK */
1223274760Sjhb		if (regv != bus_read_1(sc->port_res, tmc_rdata))
122467468Snon		{
1225240325Sjhb			device_printf(slp->sl_dev, "MSGIN: data mismatch\n");
122667468Snon		}
122767468Snon
122879697Snon		/* wait for the ack negated */
122979697Snon		stg_negate_signal(sc, BSTAT_ACK, "msgin<ACK>");
123079697Snon
123179697Snon		if (slp->sl_msgphase != 0 && slp->sl_msgphase < MSGPH_ABORT)
123267468Snon		{
123379697Snon			stg_disconnected(sc, ti);
123467468Snon		}
123567468Snon		break;
123667468Snon
123767468Snon	case BUSFREE_PHASE:
1238240325Sjhb		device_printf(slp->sl_dev, "unexpected disconnect\n");
123979697Snon		stg_disconnected(sc, ti);
124079697Snon		break;
124167468Snon
124267468Snon	default:
124379697Snon		slp->sl_error |= FATALIO;
1244240325Sjhb		device_printf(slp->sl_dev, "unknown phase bus %x intr %x\n",
1245240325Sjhb		    status, astatus);
124667468Snon		break;
124767468Snon	}
124867468Snon
124979697Snonout:
1250274760Sjhb	bus_write_1(sc->port_res, tmc_ictl, sc->sc_icinit);
125167468Snon	return 1;
125267468Snon}
125379697Snon
125479697Snonstatic int
125579697Snonstg_timeout(sc)
125679697Snon	struct stg_softc *sc;
125779697Snon{
125879697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
125979697Snon	int tout, count;
126079697Snon	u_int8_t status;
126179697Snon
126279697Snon	if (slp->sl_Tnexus == NULL)
126379697Snon		return 0;
126479697Snon
1265274760Sjhb	status = bus_read_1(sc->port_res, tmc_bstat);
126679697Snon	if ((status & PHASE_MASK) == 0)
126779697Snon	{
126879697Snon		if (sc->sc_ubf_timeout ++ == 0)
126979697Snon			return 0;
127079697Snon
1271240325Sjhb		device_printf(slp->sl_dev, "unexpected bus free detected\n");
127279697Snon		slp->sl_error |= FATALIO;
127379697Snon		scsi_low_print(slp, slp->sl_Tnexus);
127479697Snon		stg_disconnected(sc, slp->sl_Tnexus);
127579697Snon		return 0;
127679697Snon	}
127779697Snon
127879697Snon	switch (status & PHASE_MASK)
127979697Snon	{
128079697Snon	case DATA_OUT_PHASE:
128179697Snon		if (sc->sc_dataout_timeout == 0)
128279697Snon			break;
128379697Snon		if ((status & BSTAT_REQ) == 0)
128479697Snon			break;
1285274760Sjhb		if (bus_read_2(sc->port_res, tmc_fdcnt) != 0)
128679697Snon			break;
128779697Snon		if ((-- sc->sc_dataout_timeout) > 0)
128879697Snon			break;
128979697Snon
129079697Snon	        slp->sl_error |= PDMAERR;
129179697Snon		if ((slp->sl_flags & HW_WRITE_PADDING) == 0)
129279697Snon		{
1293240325Sjhb			device_printf(slp->sl_dev, "write padding required\n");
129479697Snon			break;
129579697Snon		}
129679697Snon
1297274760Sjhb		bus_write_1(sc->port_res, tmc_ictl, 0);
129879697Snon
129979697Snon		tout = STG_DELAY_MAX;
130079697Snon		while (tout --)
130179697Snon		{
1302274760Sjhb			status = bus_read_1(sc->port_res, tmc_bstat);
130379697Snon			if ((status & PHASE_MASK) != DATA_OUT_PHASE)
130479697Snon				break;
130579697Snon
1306274760Sjhb			if (bus_read_2(sc->port_res, tmc_fdcnt) != 0)
130779697Snon			{
1308240172Sjhb				DELAY(1);
130979697Snon				continue;
131079697Snon			}
131179697Snon
131279697Snon			for (count = sc->sc_maxwsize; count > 0; count --)
1313274760Sjhb				bus_write_1(sc->port_res, tmc_wfifo, 0);
131479697Snon		}
131579697Snon
1316274760Sjhb		status = bus_read_1(sc->port_res, tmc_bstat);
131779697Snon		if ((status & PHASE_MASK) == DATA_OUT_PHASE)
131879697Snon			sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
131979697Snon
1320274760Sjhb		bus_write_1(sc->port_res, tmc_ictl, sc->sc_icinit);
132179697Snon		break;
132279697Snon
132379697Snon	default:
132479697Snon		break;
132579697Snon	}
132679697Snon	return 0;
132779697Snon}
1328