179697Snon/*	$NecBSD: nsp.c,v 1.21.12.6 2001/06/29 06:27:52 honda Exp $	*/
267468Snon/*	$NetBSD$	*/
367468Snon
467468Snon#define	NSP_DEBUG
567468Snon#define	NSP_STATICS
679697Snon#define	NSP_IO_CONTROL_FLAGS \
779697Snon	(NSP_READ_SUSPEND_IO | NSP_WRITE_SUSPEND_IO | \
879697Snon	 NSP_READ_FIFO_INTERRUPTS | NSP_WRITE_FIFO_INTERRUPTS | \
979697Snon	 NSP_USE_MEMIO | NSP_WAIT_FOR_SELECT)
1067468Snon
11139749Simp/*-
1279697Snon *  Copyright (c) 1998, 1999, 2000, 2001
1367468Snon *	NetBSD/pc98 porting staff. All rights reserved.
1479697Snon *
1579697Snon *  Copyright (c) 1998, 1999, 2000, 2001
1679697Snon *	Naofumi HONDA. All rights reserved.
1767468Snon *
1867468Snon *  Redistribution and use in source and binary forms, with or without
1967468Snon *  modification, are permitted provided that the following conditions
2067468Snon *  are met:
2167468Snon *  1. Redistributions of source code must retain the above copyright
2267468Snon *     notice, this list of conditions and the following disclaimer.
2367468Snon *  2. Redistributions in binary form must reproduce the above copyright
2467468Snon *     notice, this list of conditions and the following disclaimer in the
2567468Snon *     documentation and/or other materials provided with the distribution.
2667468Snon *  3. The name of the author may not be used to endorse or promote products
2767468Snon *     derived from this software without specific prior written permission.
2867468Snon *
2967468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3067468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3167468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3267468Snon * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
3367468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3467468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3567468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3667468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3767468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3867468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3967468Snon * POSSIBILITY OF SUCH DAMAGE.
4067468Snon */
41119418Sobrien
42119418Sobrien#include <sys/cdefs.h>
43119418Sobrien__FBSDID("$FreeBSD$");
4467468Snon
4567468Snon#include <sys/param.h>
4667468Snon#include <sys/systm.h>
4767468Snon#include <sys/kernel.h>
4867468Snon#include <sys/bio.h>
4967468Snon#include <sys/buf.h>
5067468Snon#include <sys/queue.h>
5167468Snon#include <sys/malloc.h>
5267468Snon#include <sys/errno.h>
53274760Sjhb#include <sys/rman.h>
5467468Snon
5567468Snon#include <machine/cpu.h>
5667468Snon#include <machine/bus.h>
5767468Snon
5867468Snon#include <cam/scsi/scsi_low.h>
5967468Snon#include <dev/nsp/nspreg.h>
6067468Snon#include <dev/nsp/nspvar.h>
6167468Snon
6267468Snon/***************************************************
6367468Snon * USER SETTINGS
6467468Snon ***************************************************/
6567468Snon/* DEVICE CONFIGURATION FLAGS (MINOR)
6667468Snon *
67250460Seadler * 0x01   DISCONNECT OFF
6867468Snon * 0x02   PARITY LINE OFF
6967468Snon * 0x04   IDENTIFY MSG OFF ( = single lun)
7067468Snon * 0x08   SYNC TRANSFER OFF
7167468Snon */
7267468Snon
7367468Snon/***************************************************
7467468Snon * PARAMS
7567468Snon ***************************************************/
7667468Snon#define	NSP_NTARGETS	8
7767468Snon#define	NSP_NLUNS	8
7867468Snon
7979697Snon#define	NSP_MAX_DATA_SIZE	(64 * 1024)
8079697Snon#define	NSP_SELTIMEOUT		(200)
8179697Snon#define	NSP_DELAY_MAX		(2 * 1000 * 1000)
8279697Snon#define	NSP_DELAY_INTERVAL	(1)
8379697Snon#define	NSP_TIMER_1MS		(1000 / 51)
8467468Snon
8567468Snon/***************************************************
8667468Snon * DEBUG
8767468Snon ***************************************************/
8867468Snon#ifdef	NSP_DEBUG
8967468Snonint nsp_debug;
9067468Snon#endif	/* NSP_DEBUG */
9167468Snon
9267468Snon#ifdef	NSP_STATICS
9367468Snonstruct nsp_statics {
9479697Snon	int arbit_conflict_1;
9579697Snon	int arbit_conflict_2;
9679697Snon	int device_data_write;
9779697Snon	int device_busy;
9867468Snon	int disconnect;
9967468Snon	int reselect;
10067468Snon	int data_phase_bypass;
10179697Snon} nsp_statics;
10267468Snon#endif	/* NSP_STATICS */
10367468Snon
10467468Snon/***************************************************
10579697Snon * IO control
10667468Snon ***************************************************/
10779697Snon#define	NSP_READ_SUSPEND_IO		0x0001
10879697Snon#define	NSP_WRITE_SUSPEND_IO		0x0002
10979697Snon#define	NSP_USE_MEMIO			0x0004
11079697Snon#define	NSP_READ_FIFO_INTERRUPTS	0x0010
11179697Snon#define	NSP_WRITE_FIFO_INTERRUPTS	0x0020
11279697Snon#define	NSP_WAIT_FOR_SELECT		0x0100
11379697Snon
11479697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS;
11579697Snonint nsp_read_suspend_bytes = DEV_BSIZE;
11679697Snonint nsp_write_suspend_bytes = DEV_BSIZE;
11779697Snonint nsp_read_interrupt_bytes = 4096;
11879697Snonint nsp_write_interrupt_bytes = 4096;
11979697Snon
12079697Snon/***************************************************
12179697Snon * DEVICE STRUCTURE
12279697Snon ***************************************************/
12367468Snonextern struct cfdriver nsp_cd;
12467468Snon
12567468Snon/**************************************************************
12667468Snon * DECLARE
12767468Snon **************************************************************/
12879697Snon#define	NSP_FIFO_ON	1
12979697Snon#define	NSP_FIFO_OFF	0
13092739Salfredstatic void nsp_pio_read(struct nsp_softc *, int);
13192739Salfredstatic void nsp_pio_write(struct nsp_softc *, int);
13292739Salfredstatic int nsp_xfer(struct nsp_softc *, u_int8_t *, int, int, int);
13392739Salfredstatic int nsp_msg(struct nsp_softc *, struct targ_info *, u_int);
13492739Salfredstatic int nsp_reselected(struct nsp_softc *);
13592739Salfredstatic int nsp_disconnected(struct nsp_softc *, struct targ_info *);
13692739Salfredstatic void nsp_pdma_end(struct nsp_softc *, struct targ_info *);
13792739Salfredstatic void nsphw_init(struct nsp_softc *);
13892739Salfredstatic int nsp_target_nexus_establish(struct nsp_softc *);
13992739Salfredstatic int nsp_lun_nexus_establish(struct nsp_softc *);
14092739Salfredstatic int nsp_ccb_nexus_establish(struct nsp_softc *);
14192739Salfredstatic int nsp_world_start(struct nsp_softc *, int);
14292739Salfredstatic int nsphw_start_selection(struct nsp_softc *sc, struct slccb *);
14392739Salfredstatic void nsphw_bus_reset(struct nsp_softc *);
14492739Salfredstatic void nsphw_attention(struct nsp_softc *);
14592739Salfredstatic u_int nsp_fifo_count(struct nsp_softc *);
14692739Salfredstatic u_int nsp_request_count(struct nsp_softc *);
14792739Salfredstatic int nsp_negate_signal(struct nsp_softc *, u_int8_t, u_char *);
14892739Salfredstatic int nsp_expect_signal(struct nsp_softc *, u_int8_t, u_int8_t);
14992739Salfredstatic void nsp_start_timer(struct nsp_softc *, int);
15092739Salfredstatic void nsp_setup_fifo(struct nsp_softc *, int, int, int);
15192739Salfredstatic int nsp_targ_init(struct nsp_softc *, struct targ_info *, int);
15292739Salfredstatic void nsphw_selection_done_and_expect_msgout(struct nsp_softc *);
15392739Salfredstatic void nsp_data_padding(struct nsp_softc *, int, u_int);
15492739Salfredstatic int nsp_timeout(struct nsp_softc *);
15592739Salfredstatic int nsp_read_fifo(struct nsp_softc *, int);
15692739Salfredstatic int nsp_write_fifo(struct nsp_softc *, int);
15792739Salfredstatic int nsp_phase_match(struct nsp_softc *, u_int8_t, u_int8_t);
15892739Salfredstatic int nsp_wait_interrupt(struct nsp_softc *);
15967468Snon
16067468Snonstruct scsi_low_funcs nspfuncs = {
16167468Snon	SC_LOW_INIT_T nsp_world_start,
16267468Snon	SC_LOW_BUSRST_T nsphw_bus_reset,
16373025Snon	SC_LOW_TARG_INIT_T nsp_targ_init,
16479697Snon	SC_LOW_LUN_INIT_T NULL,
16567468Snon
16667468Snon	SC_LOW_SELECT_T nsphw_start_selection,
16779697Snon	SC_LOW_NEXUS_T nsp_lun_nexus_establish,
16879697Snon	SC_LOW_NEXUS_T nsp_ccb_nexus_establish,
16967468Snon
17067468Snon	SC_LOW_ATTEN_T nsphw_attention,
17167468Snon	SC_LOW_MSG_T nsp_msg,
17267468Snon
17379697Snon	SC_LOW_TIMEOUT_T nsp_timeout,
17467468Snon	SC_LOW_POLL_T nspintr,
17567468Snon
17667468Snon	NULL,
17767468Snon};
17867468Snon
17967468Snon/****************************************************
18067468Snon * hwfuncs
18167468Snon ****************************************************/
182274760Sjhbstatic __inline uint8_t
183274760Sjhbnsp_cr_read_1(struct resource *res, bus_addr_t ofs)
184274760Sjhb{
18567468Snon
186274760Sjhb	bus_write_1(res, nsp_idxr, ofs);
187274760Sjhb	return bus_read_1(res, nsp_datar);
18867468Snon}
18967468Snon
19067468Snonstatic __inline void
191274760Sjhbnsp_cr_write_1(struct resource *res, bus_addr_t ofs, uint8_t va)
19267468Snon{
19367468Snon
194274760Sjhb	bus_write_1(res, nsp_idxr, ofs);
195274760Sjhb	bus_write_1(res, nsp_datar, va);
19667468Snon}
19767468Snon
19867468Snonstatic int
199189004Srdivackynsp_expect_signal(struct nsp_softc *sc, u_int8_t curphase, u_int8_t mask)
20067468Snon{
20167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
20279697Snon	int wc;
20373025Snon	u_int8_t ph, isrc;
20467468Snon
20579697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
20667468Snon	{
207274760Sjhb		ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
20879697Snon		if (ph == (u_int8_t) -1)
20979697Snon			return -1;
21079697Snon
211274760Sjhb		isrc = bus_read_1(sc->port_res, nsp_irqsr);
21279697Snon		if (isrc & IRQSR_SCSI)
21379697Snon			return 0;
21467468Snon
21579697Snon		if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase)
21679697Snon			return 1;
21779697Snon
218240172Sjhb		DELAY(NSP_DELAY_INTERVAL);
21967468Snon	}
22067468Snon
221240325Sjhb	device_printf(slp->sl_dev, "nsp_expect_signal timeout\n");
22279697Snon	return -1;
22367468Snon}
22467468Snon
22567468Snonstatic void
22667468Snonnsphw_init(sc)
22767468Snon	struct nsp_softc *sc;
22867468Snon{
22967468Snon
23067468Snon	/* block all interrupts */
231274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, IRQCR_ALLMASK);
23267468Snon
23367468Snon	/* setup SCSI interface */
234274760Sjhb	bus_write_1(sc->port_res, nsp_ifselr, IFSELR_IFSEL);
23567468Snon
236274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCIENR, 0);
23767468Snon
238274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_IO8);
239274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_CLKDIVR, sc->sc_iclkdiv);
24067468Snon
241274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr);
242274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PARITYR, sc->sc_parr);
243274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PTCLRR,
24467468Snon		       PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS);
24567468Snon
24667468Snon	/* setup fifo asic */
247274760Sjhb	bus_write_1(sc->port_res, nsp_ifselr, IFSELR_REGSEL);
248274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_TERMPWRC, 0);
249274760Sjhb	if ((nsp_cr_read_1(sc->port_res, NSPR_OCR) & OCR_TERMPWRS) == 0)
250274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_TERMPWRC, TERMPWRC_POWON);
25167468Snon
252274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_IO8);
253274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_CLKDIVR, sc->sc_clkdiv);
254274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0);
255274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0);
25667468Snon
257274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SYNCR, 0);
258274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, 0);
25967468Snon
26067468Snon	/* enable interrupts and ack them */
261274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr);
262274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, IRQSR_MASK);
26367468Snon
26479697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
26567468Snon}
26667468Snon
26767468Snon/****************************************************
26867468Snon * scsi low interface
26967468Snon ****************************************************/
27067468Snonstatic void
27167468Snonnsphw_attention(sc)
27267468Snon	struct nsp_softc *sc;
27367468Snon{
27467468Snon	u_int8_t cr;
27567468Snon
276274760Sjhb	cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR)/*  & ~SCBUSCR_ACK */;
277274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr | SCBUSCR_ATN);
278240172Sjhb	DELAY(10);
27967468Snon}
28067468Snon
28167468Snonstatic void
28267468Snonnsphw_bus_reset(sc)
28367468Snon	struct nsp_softc *sc;
28467468Snon{
28567468Snon	int i;
28667468Snon
287274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, IRQCR_ALLMASK);
28867468Snon
289274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, SCBUSCR_RST);
290240172Sjhb	DELAY(100 * 1000);	/* 100ms */
291274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 0);
29267468Snon	for (i = 0; i < 5; i ++)
293274760Sjhb		(void) nsp_cr_read_1(sc->port_res, NSPR_IRQPHS);
29467468Snon
295274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, IRQSR_MASK);
29667468Snon}
29767468Snon
29879697Snonstatic void
29979697Snonnsphw_selection_done_and_expect_msgout(sc)
30071468Sjhb	struct nsp_softc *sc;
30171468Sjhb{
30279697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
30371468Sjhb
30479697Snon	/* clear ack counter */
30579697Snon	sc->sc_cnt = 0;
306274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
30779697Snon			PTCLRR_REQ | PTCLRR_HOST);
30879697Snon
30979697Snon	/* deassert sel and assert atten */
31079697Snon	sc->sc_seltout = 0;
311274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, sc->sc_busc);
312240172Sjhb	DELAY(1);
313274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR,
31479697Snon			sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN);
31579697Snon	SCSI_LOW_ASSERT_ATN(slp);
31671468Sjhb}
31771468Sjhb
31867468Snonstatic int
31967468Snonnsphw_start_selection(sc, cb)
32067468Snon	struct nsp_softc *sc;
32167468Snon	struct slccb *cb;
32267468Snon{
32367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
32467468Snon	struct targ_info *ti = cb->ti;
32567468Snon	register u_int8_t arbs, ph;
326274760Sjhb	int wc;
32767468Snon
32879697Snon	wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
32979697Snon	sc->sc_dataout_timeout = 0;
33079697Snon
33167468Snon	/* check bus free */
332274760Sjhb	ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
33379697Snon	if (ph != SCBUSMON_FREE)
33467468Snon	{
33579697Snon#ifdef	NSP_STATICS
33679697Snon		nsp_statics.arbit_conflict_1 ++;
33779697Snon#endif	/* NSP_STATICS */
33879697Snon		return SCSI_LOW_START_FAIL;
33967468Snon	}
34067468Snon
34167468Snon	/* start arbitration */
342274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_EXEC);
34379697Snon
34467468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART);
34567468Snon	do
34667468Snon	{
34767468Snon		/* XXX: what a stupid chip! */
348274760Sjhb		arbs = nsp_cr_read_1(sc->port_res, NSPR_ARBITS);
349240172Sjhb		DELAY(1);
35067468Snon	}
35173025Snon	while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0);
35267468Snon
35367468Snon	if ((arbs & ARBITS_WIN) == 0)
35467468Snon	{
355274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_CLR);
35679697Snon#ifdef	NSP_STATICS
35779697Snon		nsp_statics.arbit_conflict_2 ++;
35879697Snon#endif	/* NSP_STATICS */
35967468Snon		return SCSI_LOW_START_FAIL;
36067468Snon	}
36167468Snon
36267468Snon	/* assert select line */
36367468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
36479697Snon	scsi_low_arbit_win(slp);
36579697Snon
366240172Sjhb	DELAY(3);
367274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_DATA,
36867468Snon		       sc->sc_idbit | (1 << ti->ti_id));
369274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR,
37067468Snon			SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc);
371240172Sjhb	DELAY(3);
372274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, SCBUSCR_SEL |
37367468Snon			SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc);
374274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_CLR);
375240172Sjhb	DELAY(3);
376274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR,
37767468Snon		       SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc);
378240172Sjhb	DELAY(1);
37967468Snon
38079697Snon	if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0)
38179697Snon	{
38279697Snon#define	NSP_FIRST_SEL_WAIT	300
38379697Snon#define	NSP_SEL_CHECK_INTERVAL	10
38479697Snon
38579697Snon		/* wait for a selection response */
38679697Snon		for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL;
38779697Snon		     wc ++)
38879697Snon		{
389274760Sjhb			ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
39079697Snon			if ((ph & SCBUSMON_BSY) == 0)
39179697Snon			{
392240172Sjhb				DELAY(NSP_SEL_CHECK_INTERVAL);
39379697Snon				continue;
39479697Snon			}
39579697Snon
396240172Sjhb			DELAY(1);
397274760Sjhb			ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
39879697Snon			if ((ph & SCBUSMON_BSY) != 0)
39979697Snon			{
40079697Snon				nsphw_selection_done_and_expect_msgout(sc);
40179697Snon
40279697Snon				SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
40379697Snon				return SCSI_LOW_START_OK;
40479697Snon			}
40579697Snon		}
40679697Snon	}
40779697Snon
40879697Snon	/* check a selection timeout */
40979697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
41067468Snon	sc->sc_seltout = 1;
41167468Snon	return SCSI_LOW_START_OK;
41267468Snon}
41367468Snon
41467468Snonstatic int
41567468Snonnsp_world_start(sc, fdone)
41667468Snon	struct nsp_softc *sc;
41767468Snon	int fdone;
41867468Snon{
41967468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
42067468Snon
42167468Snon	sc->sc_cnt = 0;
42267468Snon	sc->sc_seltout = 0;
42379697Snon
42467468Snon	if ((slp->sl_cfgflags & CFG_NOATTEN) == 0)
42567468Snon		sc->sc_busc = SCBUSCR_ATN;
42667468Snon	else
42767468Snon		sc->sc_busc = 0;
42879697Snon
42979697Snon	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
43079697Snon		sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR;
43179697Snon	else
43279697Snon		sc->sc_parr = 0;
43379697Snon
43467468Snon	sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST);
43567468Snon
43667468Snon	nsphw_init(sc);
43767468Snon	scsi_low_bus_reset(slp);
43867468Snon
43967468Snon	return 0;
44067468Snon}
44167468Snon
44267468Snonstruct ncp_synch_data {
44367468Snon	u_int min_period;
44467468Snon	u_int max_period;
44567468Snon	u_int chip_period;
44667468Snon	u_int ack_width;
44767468Snon};
44867468Snon
44967468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = {
45067468Snon	{0x0c,0x0c,0x1,0},	/* 20MB  50ns*/
45167468Snon	{0x19,0x19,0x3,1}, 	/* 10MB  100ns*/
45267468Snon	{0x1a,0x25,0x5,2},	/* 7.5MB 150ns*/
45367468Snon	{0x26,0x32,0x7,3},	/* 5MB   200ns*/
45467468Snon	{0x0, 0, 0, 0}
45567468Snon};
45667468Snon
45767468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = {
45867468Snon	{0x19,0x19,0x1,0}, 	/* 10MB  100ns*/
45967468Snon	{0x1a,0x25,0x2,0},	/* 7.5MB 150ns*/
46067468Snon	{0x26,0x32,0x3,1},	/* 5MB   200ns*/
46167468Snon	{0x0, 0, 0, 0}
46267468Snon};
46367468Snon
46467468Snonstatic int
46567468Snonnsp_msg(sc, ti, msg)
46667468Snon	struct nsp_softc *sc;
46767468Snon	struct targ_info *ti;
46867468Snon	u_int msg;
46967468Snon{
47067468Snon	struct ncp_synch_data *sdp;
47173025Snon	struct nsp_targ_info *nti = (void *) ti;
47267468Snon	u_int period, offset;
47379697Snon	int i, error;
47467468Snon
47579697Snon	if ((msg & SCSI_LOW_MSG_WIDE) != 0)
47679697Snon	{
47779697Snon		if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
47879697Snon		{
47979697Snon			ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
48079697Snon			return EINVAL;
48179697Snon		}
48279697Snon		return 0;
48379697Snon	}
48479697Snon
48567468Snon	if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
48667468Snon		return 0;
48767468Snon
48873025Snon	period = ti->ti_maxsynch.period;
48973025Snon	offset = ti->ti_maxsynch.offset;
49067468Snon	if (sc->sc_iclkdiv == CLKDIVR_20M)
49167468Snon		sdp = &ncp_sync_data_20M[0];
49267468Snon	else
49367468Snon		sdp = &ncp_sync_data_40M[0];
49467468Snon
49567468Snon	for (i = 0; sdp->max_period != 0; i ++, sdp ++)
49667468Snon	{
49767468Snon		if (period >= sdp->min_period && period <= sdp->max_period)
49867468Snon			break;
49967468Snon	}
50067468Snon
50167468Snon	if (period != 0 && sdp->max_period == 0)
50267468Snon	{
50367468Snon		/*
50467468Snon		 * NO proper period/offset found,
50567468Snon		 * Retry neg with the target.
50667468Snon		 */
50773025Snon		ti->ti_maxsynch.period = 0;
50873025Snon		ti->ti_maxsynch.offset = 0;
50973025Snon		nti->nti_reg_syncr = 0;
51073025Snon		nti->nti_reg_ackwidth = 0;
51179697Snon		error = EINVAL;
51267468Snon	}
51379697Snon	else
51479697Snon	{
51579697Snon		nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) |
51679697Snon				      (offset & SYNCR_OFFM);
51779697Snon		nti->nti_reg_ackwidth = sdp->ack_width;
51879697Snon		error = 0;
51979697Snon	}
52067468Snon
521274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SYNCR, nti->nti_reg_syncr);
522274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
52379697Snon	return error;
52467468Snon}
52567468Snon
52667468Snonstatic int
52779697Snonnsp_targ_init(sc, ti, action)
52867468Snon	struct nsp_softc *sc;
52967468Snon	struct targ_info *ti;
53079697Snon	int action;
53167468Snon{
53273025Snon	struct nsp_targ_info *nti = (void *) ti;
53367468Snon
53479697Snon	if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
53579697Snon	{
53679697Snon		ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
53779697Snon		ti->ti_maxsynch.period = 100 / 4;
53879697Snon		ti->ti_maxsynch.offset = 15;
53979697Snon		nti->nti_reg_syncr = 0;
54079697Snon		nti->nti_reg_ackwidth = 0;
54179697Snon	}
54267468Snon	return 0;
54367468Snon}
54467468Snon
54579697Snonstatic void
54679697Snonnsp_start_timer(sc, time)
54779697Snon	struct nsp_softc *sc;
54879697Snon	int time;
54979697Snon{
55079697Snon
55179697Snon	sc->sc_timer = time;
552274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, time);
55379697Snon}
55479697Snon
55567468Snon/**************************************************************
55667468Snon * General probe attach
55767468Snon **************************************************************/
55867468Snonint
559274760Sjhbnspprobesubr(struct resource *res, u_int dvcfg)
56067468Snon{
56167468Snon	u_int8_t regv;
56267468Snon
563274760Sjhb	regv = bus_read_1(res, nsp_fifosr);
56467468Snon	if (regv < 0x11 || regv >= 0x20)
56567468Snon		return 0;
56667468Snon	return 1;
56767468Snon}
56867468Snon
56967468Snonvoid
57067468Snonnspattachsubr(sc)
57167468Snon	struct nsp_softc *sc;
57267468Snon{
57367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
57467468Snon
57567468Snon	sc->sc_idbit = (1 << slp->sl_hostid);
57679697Snon	slp->sl_flags |= HW_READ_PADDING;
57767468Snon	slp->sl_funcs = &nspfuncs;
57879697Snon	sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
57967468Snon
58079697Snon	(void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS,
58179697Snon			       sizeof(struct nsp_targ_info), 0);
58267468Snon}
58367468Snon
58467468Snon/**************************************************************
58567468Snon * PDMA functions
58667468Snon **************************************************************/
58767468Snonstatic u_int
58867468Snonnsp_fifo_count(sc)
58967468Snon	struct nsp_softc *sc;
59067468Snon{
59167468Snon	u_int count;
59267468Snon
593274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT);
594274760Sjhb	count = bus_read_1(sc->port_res, nsp_datar);
595274760Sjhb	count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 8);
596274760Sjhb	count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 16);
59767468Snon	return count;
59867468Snon}
59967468Snon
60079697Snonstatic u_int
60179697Snonnsp_request_count(sc)
60279697Snon	struct nsp_softc *sc;
60379697Snon{
60479697Snon	u_int count;
60579697Snon
606274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT);
607274760Sjhb	count = bus_read_1(sc->port_res, nsp_datar);
608274760Sjhb	count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 8);
609274760Sjhb	count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 16);
61079697Snon	return count;
61179697Snon}
61279697Snon
61367468Snonstatic void
61479697Snonnsp_setup_fifo(sc, on, direction, datalen)
61567468Snon	struct nsp_softc *sc;
61667468Snon	int on;
61779697Snon	int direction;
61879697Snon	int datalen;
61967468Snon{
62067468Snon	u_int8_t xfermode;
62167468Snon
62279697Snon	sc->sc_suspendio = 0;
62379697Snon	if (on == NSP_FIFO_OFF)
62479697Snon	{
62579697Snon		xfermode = XFERMR_IO8;
62679697Snon		goto out;
62779697Snon	}
62867468Snon
62979697Snon	/* check if suspend io OK ? */
63079697Snon	if (datalen > 0)
63167468Snon	{
63279697Snon		if (direction == SCSI_LOW_READ)
63379697Snon		{
63479697Snon			if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 &&
63579697Snon			    (datalen % nsp_read_suspend_bytes) == 0)
63679697Snon				sc->sc_suspendio = nsp_read_suspend_bytes;
63779697Snon		}
63879697Snon		else
63979697Snon		{
64079697Snon			if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 &&
64179697Snon			    (datalen % nsp_write_suspend_bytes) == 0)
64279697Snon				sc->sc_suspendio = nsp_write_suspend_bytes;
64379697Snon		}
64467468Snon	}
64579697Snon
64679697Snon	/* determine a transfer type */
64779697Snon	if (datalen < DEV_BSIZE || (datalen & 3) != 0)
64879697Snon	{
649274760Sjhb		if (sc->mem_res != NULL &&
65079697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
65179697Snon			xfermode = XFERMR_XEN | XFERMR_MEM8;
65279697Snon		else
65379697Snon			xfermode = XFERMR_XEN | XFERMR_IO8;
65479697Snon	}
65567468Snon	else
65667468Snon	{
657274760Sjhb		if (sc->mem_res != NULL &&
65879697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
65979697Snon			xfermode = XFERMR_XEN | XFERMR_MEM32;
66067468Snon		else
66179697Snon			xfermode = XFERMR_XEN | XFERMR_IO32;
66279697Snon
66379697Snon		if (sc->sc_suspendio > 0)
66479697Snon			xfermode |= XFERMR_FIFOEN;
66567468Snon	}
66667468Snon
66779697Snonout:
66867468Snon	sc->sc_xfermr = xfermode;
669274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_XFERMR, sc->sc_xfermr);
67067468Snon}
67167468Snon
67279697Snonstatic void
67367468Snonnsp_pdma_end(sc, ti)
67467468Snon	struct nsp_softc *sc;
67567468Snon	struct targ_info *ti;
67667468Snon{
67767468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
67879697Snon	struct slccb *cb = slp->sl_Qnexus;
67967468Snon	u_int len = 0, cnt;
68067468Snon
68179697Snon	sc->sc_dataout_timeout = 0;
68267468Snon	slp->sl_flags &= ~HW_PDMASTART;
68379697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
68479697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
68579697Snon	{
68679697Snon		sc->sc_icr &= ~SCIENR_FIFO;
687274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr);
68879697Snon	}
68967468Snon
69079697Snon	if (cb == NULL)
69179697Snon	{
69279697Snon		slp->sl_error |= PDMAERR;
69379697Snon		return;
69479697Snon	}
69579697Snon
69667468Snon	if (ti->ti_phase == PH_DATA)
69767468Snon	{
69867468Snon		cnt = nsp_fifo_count(sc);
69967468Snon		if (slp->sl_scp.scp_direction  == SCSI_LOW_WRITE)
70067468Snon		{
70167468Snon			len = sc->sc_cnt - cnt;
70279697Snon			if (sc->sc_cnt >= cnt &&
70379697Snon			    slp->sl_scp.scp_datalen + len <=
70467468Snon			    cb->ccb_scp.scp_datalen)
70567468Snon			{
70667468Snon				slp->sl_scp.scp_data -= len;
70767468Snon				slp->sl_scp.scp_datalen += len;
70867468Snon			}
70967468Snon			else
71067468Snon			{
71167468Snon				slp->sl_error |= PDMAERR;
712240325Sjhb				device_printf(slp->sl_dev,
713240325Sjhb					"len %x >= datalen %x\n",
71467468Snon					len, slp->sl_scp.scp_datalen);
71567468Snon			}
71667468Snon		}
71767468Snon		else if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
71867468Snon		{
71979697Snon			if (sc->sc_cnt != cnt ||
72079697Snon			    sc->sc_cnt > cb->ccb_scp.scp_datalen)
72167468Snon			{
72267468Snon				slp->sl_error |= PDMAERR;
723240325Sjhb				device_printf(slp->sl_dev,
724240325Sjhb					"data read count error %x != %x (%x)\n",
725240325Sjhb					sc->sc_cnt, cnt,
72679697Snon					cb->ccb_scp.scp_datalen);
72767468Snon			}
72867468Snon		}
72967468Snon		sc->sc_cnt = cnt;
73079697Snon		scsi_low_data_finish(slp);
73167468Snon	}
73267468Snon	else
73367468Snon	{
73467468Snon
735240325Sjhb		device_printf(slp->sl_dev, "data phase miss\n");
73667468Snon		slp->sl_error |= PDMAERR;
73767468Snon	}
73867468Snon}
73967468Snon
74067468Snon#define	RFIFO_CRIT	64
74179697Snon#define	WFIFO_CRIT	32
74267468Snon
74367468Snonstatic void
74479697Snonnsp_data_padding(sc, direction, count)
74567468Snon	struct nsp_softc *sc;
74679697Snon	int direction;
74779697Snon	u_int count;
74867468Snon{
74979697Snon
75079697Snon	if (count > NSP_MAX_DATA_SIZE)
75179697Snon		count = NSP_MAX_DATA_SIZE;
75279697Snon
753274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8);
75479697Snon	if (direction == SCSI_LOW_READ)
75579697Snon	{
75679697Snon		while (count -- > 0)
757274760Sjhb			(void) bus_read_1(sc->port_res, nsp_fifodr);
75879697Snon	}
75979697Snon	else
76079697Snon	{
76179697Snon		while (count -- > 0)
762274760Sjhb			(void) bus_write_1(sc->port_res, nsp_fifodr, 0);
76379697Snon	}
764274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_XFERMR, sc->sc_xfermr);
76579697Snon}
76679697Snon
76779697Snonstatic int
76879697Snonnsp_read_fifo(sc, suspendio)
76979697Snon	struct nsp_softc *sc;
77079697Snon	int suspendio;
77179697Snon{
77267468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
77379697Snon	u_int res;
77467468Snon
77579697Snon	res = nsp_fifo_count(sc);
77679697Snon	if (res == sc->sc_cnt)
77779697Snon		return 0;
77867468Snon
77979697Snon#ifdef	NSP_DEBUG
78079697Snon	if (res < sc->sc_cnt || res == (u_int) -1)
78167468Snon	{
782240325Sjhb		device_printf(slp->sl_dev,
783240325Sjhb		    "strange fifo ack count 0x%x < 0x%x\n", res, sc->sc_cnt);
78479697Snon		return 0;
78579697Snon	}
78679697Snon#endif	/* NSP_DEBUG */
78779697Snon
78879697Snon	res = res - sc->sc_cnt;
78979697Snon	if (res > slp->sl_scp.scp_datalen)
79079697Snon	{
79179697Snon		if ((slp->sl_error & PDMAERR) == 0)
79279697Snon		{
793240325Sjhb			device_printf(slp->sl_dev, "data overrun 0x%x > 0x%x\n",
794240325Sjhb			    res, slp->sl_scp.scp_datalen);
79579697Snon		}
79679697Snon
79779697Snon		slp->sl_error |= PDMAERR;
79879697Snon		slp->sl_scp.scp_datalen = 0;
79979697Snon
80079697Snon		if ((slp->sl_flags & HW_READ_PADDING) == 0)
80179697Snon		{
802240325Sjhb			device_printf(slp->sl_dev, "read padding required\n");
80379697Snon			return 0;
80479697Snon		}
80579697Snon
80679697Snon		nsp_data_padding(sc, SCSI_LOW_READ, res);
80779697Snon		sc->sc_cnt += res;
80879697Snon		return 1;	/* padding start */
80979697Snon	}
81079697Snon
81179697Snon	if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio)
81279697Snon		res = suspendio;
81379697Snon
81479697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
81579697Snon	{
81679697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
81779697Snon		{
81879697Snon			res &= ~3;
819274760Sjhb			bus_read_region_4(sc->mem_res, 0,
82079697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
82179697Snon		}
82279697Snon		else
82379697Snon		{
824274760Sjhb			bus_read_region_1(sc->mem_res, 0,
82579697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
82679697Snon		}
82779697Snon	}
82879697Snon	else
82979697Snon	{
83079697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
83179697Snon		{
83279697Snon			res &= ~3;
833274760Sjhb			bus_read_multi_4(sc->port_res, nsp_fifodr,
83479697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
83579697Snon		}
83679697Snon		else
83779697Snon		{
838274760Sjhb			bus_read_multi_1(sc->port_res, nsp_fifodr,
83979697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
84079697Snon		}
84179697Snon	}
84279697Snon
843274760Sjhb	if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE)
84479697Snon	{
845274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_PARITYR,
84679697Snon			       PARITYR_ENABLE | PARITYR_CLEAR);
84779697Snon		scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1);
84879697Snon	}
84979697Snon
85079697Snon	slp->sl_scp.scp_data += res;
85179697Snon	slp->sl_scp.scp_datalen -= res;
85279697Snon	sc->sc_cnt += res;
85379697Snon	return 0;
85479697Snon}
85579697Snon
85679697Snonstatic int
85779697Snonnsp_write_fifo(sc, suspendio)
85879697Snon	struct nsp_softc *sc;
85979697Snon	int suspendio;
86079697Snon{
86179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
86279697Snon	u_int res;
86379697Snon	register u_int8_t stat;
86479697Snon
86579697Snon	if (suspendio > 0)
86679697Snon	{
86779697Snon#ifdef	NSP_DEBUG
86879697Snon		if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0)
86979697Snon		{
870240325Sjhb			device_printf(slp->sl_dev,
871240325Sjhb			    "strange write length 0x%x\n",
872240325Sjhb			    slp->sl_scp.scp_datalen);
87379697Snon		}
87479697Snon#endif	/* NSP_DEBUG */
87579697Snon		res = slp->sl_scp.scp_datalen % suspendio;
87667468Snon		if (res == 0)
87767468Snon		{
87879697Snon			res = suspendio;
87967468Snon		}
88079697Snon	}
88179697Snon	else
88279697Snon	{
88379697Snon		res = WFIFO_CRIT;
88479697Snon	}
88567468Snon
88679697Snon	if (res > slp->sl_scp.scp_datalen)
88779697Snon		res = slp->sl_scp.scp_datalen;
88867468Snon
88979697Snon	/* XXX: reconfirm! */
890274760Sjhb	stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
89179697Snon	if (stat != PHASE_DATAOUT)
89279697Snon		return 0;
89367468Snon
89479697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
89579697Snon	{
89679697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
89779697Snon		{
898274760Sjhb			bus_write_region_4(sc->mem_res, 0,
89979697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
90079697Snon		}
90167468Snon		else
90279697Snon		{
903274760Sjhb			bus_write_region_1(sc->mem_res, 0,
90479697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
90579697Snon		}
90679697Snon	}
90779697Snon	else
90879697Snon	{
90979697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
91079697Snon		{
911274760Sjhb			bus_write_multi_4(sc->port_res, nsp_fifodr,
91279697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
91379697Snon		}
91479697Snon		else
91579697Snon		{
916274760Sjhb			bus_write_multi_1(sc->port_res, nsp_fifodr,
91779697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
91879697Snon		}
91979697Snon	}
92067468Snon
92179697Snon	slp->sl_scp.scp_datalen -= res;
92279697Snon	slp->sl_scp.scp_data += res;
92379697Snon	sc->sc_cnt += res;
92479697Snon	return 0;
92579697Snon}
92679697Snon
92779697Snonstatic int
92879697Snonnsp_wait_interrupt(sc)
92979697Snon	struct nsp_softc *sc;
93079697Snon{
93179697Snon	int tout;
93279697Snon	register u_int8_t isrc;
93379697Snon
93479697Snon	for (tout = 0; tout < DEV_BSIZE / 10; tout ++)
93579697Snon	{
936274760Sjhb		isrc = bus_read_1(sc->port_res, nsp_irqsr);
93779697Snon		if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0)
93867468Snon		{
93979697Snon			if ((isrc & IRQSR_FIFO) != 0)
94079697Snon			{
941274760Sjhb				bus_write_1(sc->port_res,
94279697Snon					nsp_irqcr, IRQCR_FIFOCL);
94379697Snon			}
94479697Snon			return 1;
94567468Snon		}
946240172Sjhb		DELAY(1);
94779697Snon	}
94879697Snon	return 0;
94979697Snon}
95079697Snon
95179697Snonstatic void
95279697Snonnsp_pio_read(sc, suspendio)
95379697Snon	struct nsp_softc *sc;
95479697Snon	int suspendio;
95579697Snon{
95679697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
95779697Snon	int tout, padding, datalen;
95879697Snon	register u_int8_t stat, fstat;
95979697Snon
96079697Snon	padding = 0;
96179697Snon	tout = sc->sc_tmaxcnt;
96279697Snon	slp->sl_flags |= HW_PDMASTART;
96379697Snon	datalen = slp->sl_scp.scp_datalen;
96479697Snon
96579697SnonReadLoop:
96679697Snon	while (1)
96779697Snon	{
968274760Sjhb		stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
96979697Snon		if (stat == (u_int8_t) -1)
97079697Snon			return;
97179697Snon
97279697Snon		/* out of data phase */
97379697Snon		if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN)
97479697Snon		{
97579697Snon			nsp_read_fifo(sc, 0);
97679697Snon			return;
97779697Snon		}
97879697Snon
97979697Snon		/* data phase */
980274760Sjhb		fstat = bus_read_1(sc->port_res, nsp_fifosr);
98179697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
98279697Snon		{
98379697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
98479697Snon			{
985274760Sjhb				bus_write_1(sc->port_res, nsp_irqcr,
98679697Snon						  IRQCR_FIFOCL);
98779697Snon			}
98879697Snon
98979697Snon			if (suspendio > 0)
99079697Snon			{
99179697Snon				padding |= nsp_read_fifo(sc, suspendio);
99279697Snon			}
99379697Snon			else
99479697Snon			{
99579697Snon				padding |= nsp_read_fifo(sc, 0);
99679697Snon			}
99779697Snon
99879697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
99979697Snon				break;
100079697Snon		}
100167468Snon		else
100267468Snon		{
100379697Snon			if (padding == 0 && slp->sl_scp.scp_datalen <= 0)
100479697Snon				return;
100579697Snon
100679697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
100779697Snon				break;
100879697Snon
1009240172Sjhb			DELAY(1);
101067468Snon		}
101167468Snon
101279697Snon		if ((-- tout) <= 0)
101379697Snon		{
1014240325Sjhb			device_printf(slp->sl_dev, "nsp_pio_read: timeout\n");
101579697Snon			return;
101679697Snon		}
101767468Snon	}
101867468Snon
101979697Snon
102079697Snon	if (slp->sl_scp.scp_datalen > 0 &&
102179697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes)
102279697Snon	{
102379697Snon		if (nsp_wait_interrupt(sc) != 0)
102479697Snon			goto ReadLoop;
102579697Snon	}
102667468Snon}
102767468Snon
102867468Snonstatic void
102979697Snonnsp_pio_write(sc, suspendio)
103067468Snon	struct nsp_softc *sc;
103179697Snon	int suspendio;
103267468Snon{
103367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
103479697Snon	u_int rcount, acount;
103579697Snon	int tout, datalen;
103679697Snon	register u_int8_t stat, fstat;
103767468Snon
103879697Snon	tout = sc->sc_tmaxcnt;
103967468Snon	slp->sl_flags |= HW_PDMASTART;
104079697Snon	datalen = slp->sl_scp.scp_datalen;
104179697Snon
104279697SnonWriteLoop:
104379697Snon	while (1)
104467468Snon	{
1045274760Sjhb		stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
104667468Snon		if (stat != PHASE_DATAOUT)
104779697Snon			return;
104867468Snon
104979697Snon		if (slp->sl_scp.scp_datalen <= 0)
105079697Snon		{
105179697Snon			if (sc->sc_dataout_timeout == 0)
105279697Snon				sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
105379697Snon			return;
105479697Snon		}
105567468Snon
1056274760Sjhb		fstat = bus_read_1(sc->port_res, nsp_fifosr);
105779697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
105879697Snon		{
105979697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
106079697Snon			{
1061274760Sjhb				bus_write_1(sc->port_res, nsp_irqcr,
106279697Snon						  IRQCR_FIFOCL);
106379697Snon			}
106467468Snon
106579697Snon			if (suspendio > 0)
106679697Snon			{
106779697Snon				/* XXX:IMPORTANT:
106879697Snon				 * To avoid timeout of pcmcia bus
106979697Snon				 * (not scsi bus!), we should check
107079697Snon				 * the scsi device sends us request
107179697Snon				 * signals, which means the scsi device
1072298955Spfg				 * is ready to receive data without
107379697Snon				 * heavy delays.
107479697Snon				 */
107582784Snon				if ((slp->sl_scp.scp_datalen % suspendio) == 0)
107679697Snon				{
107782784Snon					/* Step I:
107882784Snon					 * fill the nsp fifo, and waiting for
107982784Snon					 * the fifo empty.
108082784Snon					 */
108179697Snon					nsp_write_fifo(sc, 0);
108279697Snon				}
108379697Snon				else
108479697Snon				{
108582784Snon					/* Step II:
108682784Snon					 * check the request singals.
108782784Snon					 */
108882784Snon					acount = nsp_fifo_count(sc);
108982784Snon					rcount = nsp_request_count(sc);
109082784Snon					if (rcount <= acount)
109182784Snon					{
109282784Snon						nsp_write_fifo(sc, 0);
109379697Snon#ifdef	NSP_STATICS
109482784Snon						nsp_statics.device_busy ++;
109579697Snon#endif	/* NSP_STATICS */
109682784Snon					}
109782784Snon					else
109882784Snon					{
109982784Snon						nsp_write_fifo(sc, suspendio);
110082784Snon#ifdef	NSP_STATICS
110182784Snon						nsp_statics.device_data_write ++;
110282784Snon#endif	/* NSP_STATICS */
110382784Snon					}
110479697Snon				}
110579697Snon			}
110679697Snon			else
110779697Snon			{
110879697Snon				nsp_write_fifo(sc, 0);
110979697Snon			}
111079697Snon
111179697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
111279697Snon				break;
111367468Snon		}
111467468Snon		else
111567468Snon		{
111679697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
111779697Snon				break;
111879697Snon
1119240172Sjhb			DELAY(1);
112067468Snon		}
112167468Snon
112279697Snon		if ((-- tout) <= 0)
112379697Snon		{
1124240325Sjhb			device_printf(slp->sl_dev, "nsp_pio_write: timeout\n");
112579697Snon			return;
112679697Snon		}
112767468Snon	}
112867468Snon
112979697Snon	if (slp->sl_scp.scp_datalen > 0 &&
113079697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes)
113179697Snon	{
113279697Snon		if (nsp_wait_interrupt(sc) != 0)
113379697Snon			goto WriteLoop;
113479697Snon	}
113567468Snon}
113667468Snon
113767468Snonstatic int
1138189004Srdivackynsp_negate_signal(struct nsp_softc *sc, u_int8_t mask, u_char *s)
113967468Snon{
114067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
114179697Snon	int wc;
114267468Snon	u_int8_t regv;
114367468Snon
114479697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
114567468Snon	{
1146274760Sjhb		regv = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
114779697Snon		if (regv == (u_int8_t) -1)
114879697Snon			return -1;
114979697Snon		if ((regv & mask) == 0)
115079697Snon			return 1;
1151240172Sjhb		DELAY(NSP_DELAY_INTERVAL);
115267468Snon	}
115367468Snon
1154240325Sjhb	device_printf(slp->sl_dev, "%s nsp_negate_signal timeout\n", s);
115579697Snon	return -1;
115667468Snon}
115767468Snon
115867468Snonstatic int
115979697Snonnsp_xfer(sc, buf, len, phase, clear_atn)
116067468Snon	struct nsp_softc *sc;
116167468Snon	u_int8_t *buf;
116267468Snon	int len;
116367468Snon	int phase;
116479697Snon	int clear_atn;
116567468Snon{
116679697Snon	int ptr, rv;
116767468Snon
116867468Snon	for (ptr = 0; len > 0; len --, ptr ++)
116967468Snon	{
117067468Snon		rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ);
117167468Snon		if (rv <= 0)
117267468Snon			goto out;
117367468Snon
117479697Snon		if (len == 1 && clear_atn != 0)
117567468Snon		{
1176274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR,
117767468Snon				       SCBUSCR_ADIR | SCBUSCR_ACKEN);
117879697Snon			SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow);
117967468Snon		}
118067468Snon
118167468Snon		if (phase & SCBUSMON_IO)
118267468Snon		{
1183274760Sjhb			buf[ptr] = nsp_cr_read_1(sc->port_res, NSPR_DATAACK);
118467468Snon		}
118567468Snon		else
118667468Snon		{
1187274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_DATAACK, buf[ptr]);
118867468Snon		}
118967468Snon		nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>");
119067468Snon	}
119167468Snon
119267468Snonout:
119367468Snon	return len;
119467468Snon}
119567468Snon
119667468Snon/**************************************************************
119767468Snon * disconnect & reselect (HW low)
119867468Snon **************************************************************/
119967468Snonstatic int
120067468Snonnsp_reselected(sc)
120167468Snon	struct nsp_softc *sc;
120267468Snon{
120367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
120467468Snon	struct targ_info *ti;
120567468Snon	u_int sid;
120667468Snon	u_int8_t cr;
120767468Snon
1208274760Sjhb	sid = (u_int) nsp_cr_read_1(sc->port_res, NSPR_RESELR);
120967468Snon	sid &= ~sc->sc_idbit;
121067468Snon	sid = ffs(sid) - 1;
121167468Snon	if ((ti = scsi_low_reselected(slp, sid)) == NULL)
121267468Snon		return EJUSTRETURN;
121367468Snon
121467468Snon	nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>");
121567468Snon
1216274760Sjhb	cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR);
121779697Snon	cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN);
1218274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
121979697Snon	cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN;
1220274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
122167468Snon
122267468Snon#ifdef	NSP_STATICS
122379697Snon	nsp_statics.reselect ++;
122467468Snon#endif	/* NSP_STATCIS */
122567468Snon	return EJUSTRETURN;
122667468Snon}
122767468Snon
122879697Snonstatic int
122967468Snonnsp_disconnected(sc, ti)
123067468Snon	struct nsp_softc *sc;
123167468Snon	struct targ_info *ti;
123267468Snon{
123367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
123467468Snon
1235274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
123679697Snon			PTCLRR_REQ | PTCLRR_HOST);
123779697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
123879697Snon	{
123979697Snon		sc->sc_icr &= ~SCIENR_FIFO;
1240274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr);
124179697Snon	}
124279697Snon	sc->sc_cnt = 0;
124379697Snon	sc->sc_dataout_timeout = 0;
124467468Snon#ifdef	NSP_STATICS
124579697Snon	nsp_statics.disconnect ++;
124667468Snon#endif	/* NSP_STATICS */
124767468Snon	scsi_low_disconnected(slp, ti);
124867468Snon	return 1;
124967468Snon}
125067468Snon
125167468Snon/**************************************************************
125267468Snon * SEQUENCER
125367468Snon **************************************************************/
125492739Salfredstatic void nsp_error(struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t);
125567468Snon
125667468Snonstatic void
1257189004Srdivackynsp_error(struct nsp_softc * sc, u_char *s, u_int8_t isrc, u_int8_t ph,
1258189004Srdivacky    u_int8_t irqphs)
125967468Snon{
126067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
126167468Snon
1262240325Sjhb	device_printf(slp->sl_dev, "%s\n", s);
1263240325Sjhb	device_printf(slp->sl_dev, "isrc 0x%x scmon 0x%x irqphs 0x%x\n",
1264240325Sjhb	    (u_int) isrc, (u_int) ph, (u_int) irqphs);
126567468Snon}
126667468Snon
126767468Snonstatic int
126879697Snonnsp_target_nexus_establish(sc)
126967468Snon	struct nsp_softc *sc;
127067468Snon{
127179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
127279697Snon	struct targ_info *ti = slp->sl_Tnexus;
127373025Snon	struct nsp_targ_info *nti = (void *) ti;
127467468Snon
127567468Snon	/* setup synch transfer registers */
1276274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_SYNCR, nti->nti_reg_syncr);
1277274760Sjhb	nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
127867468Snon
127979697Snon	/* setup pdma fifo (minimum) */
128079697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0);
128179697Snon	return 0;
128279697Snon}
128379697Snon
128479697Snonstatic int
128579697Snonnsp_lun_nexus_establish(sc)
128679697Snon	struct nsp_softc *sc;
128779697Snon{
128879697Snon
128979697Snon	return 0;
129079697Snon}
129179697Snon
129279697Snonstatic int
129379697Snonnsp_ccb_nexus_establish(sc)
129479697Snon	struct nsp_softc *sc;
129579697Snon{
129679697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
129779697Snon	struct slccb *cb = slp->sl_Qnexus;
129879697Snon
129979697Snon	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
130079697Snon
130167468Snon	/* setup pdma fifo */
130279697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON,
130379697Snon		       slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen);
130467468Snon
130579697Snon	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
130679697Snon	{
130779697Snon		if (sc->sc_suspendio > 0 &&
130879697Snon		    (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0)
130979697Snon		{
131079697Snon			sc->sc_icr |= SCIENR_FIFO;
1311274760Sjhb			nsp_cr_write_1(sc->port_res,
131279697Snon				       NSPR_SCIENR, sc->sc_icr);
131379697Snon		}
131479697Snon	}
131579697Snon	else
131679697Snon	{
131779697Snon		if (sc->sc_suspendio > 0 &&
131879697Snon		    (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0)
131979697Snon		{
132079697Snon			sc->sc_icr |= SCIENR_FIFO;
1321274760Sjhb			nsp_cr_write_1(sc->port_res,
132279697Snon				       NSPR_SCIENR, sc->sc_icr);
132379697Snon		}
132479697Snon	}
132567468Snon	return 0;
132667468Snon}
132767468Snon
132879697Snonstatic int
1329189004Srdivackynsp_phase_match(struct nsp_softc *sc, u_int8_t phase, u_int8_t stat)
133079697Snon{
133179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
133279697Snon
133379697Snon	if ((stat & SCBUSMON_PHMASK) != phase)
133479697Snon	{
1335240325Sjhb		device_printf(slp->sl_dev, "phase mismatch 0x%x != 0x%x\n",
1336240325Sjhb		    (u_int) phase, (u_int) stat);
133779697Snon		return EINVAL;
133879697Snon	}
133979697Snon
134079697Snon	if ((stat & SCBUSMON_REQ) == 0)
134179697Snon		return EINVAL;
134279697Snon
134379697Snon	return 0;
134479697Snon}
134579697Snon
134667468Snonint
134767468Snonnspintr(arg)
134867468Snon	void *arg;
134967468Snon{
135067468Snon	struct nsp_softc *sc = arg;
135167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
135267468Snon	struct targ_info *ti;
135367468Snon	struct buf *bp;
135479697Snon	u_int derror, flags;
135567468Snon	int len, rv;
135667468Snon	u_int8_t isrc, ph, irqphs, cr, regv;
135767468Snon
135867468Snon	/*******************************************
135967468Snon	 * interrupt check
136067468Snon	 *******************************************/
136167468Snon	if (slp->sl_flags & HW_INACTIVE)
136267468Snon		return 0;
136367468Snon
1364274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, IRQCR_IRQDIS);
1365274760Sjhb	isrc = bus_read_1(sc->port_res, nsp_irqsr);
136679697Snon	if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0)
136767468Snon	{
1368274760Sjhb		bus_write_1(sc->port_res, nsp_irqcr, 0);
136967468Snon		return 0;
137067468Snon	}
137167468Snon
137267468Snon	/* XXX: IMPORTANT
137367468Snon 	 * Do not read an irqphs register if no scsi phase interrupt.
137467468Snon	 * Unless, you should lose a scsi phase interrupt.
137567468Snon	 */
1376274760Sjhb	ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
137767468Snon	if ((isrc & IRQSR_SCSI) != 0)
137867468Snon	{
1379274760Sjhb		irqphs = nsp_cr_read_1(sc->port_res, NSPR_IRQPHS);
138067468Snon	}
138167468Snon	else
138267468Snon		irqphs = 0;
138367468Snon
138467468Snon	/*
138567468Snon 	 * timer interrupt handler (scsi vs timer interrupts)
138667468Snon	 */
138767468Snon	if (sc->sc_timer != 0)
138867468Snon	{
1389274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0);
1390274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0);
139167468Snon		sc->sc_timer = 0;
139267468Snon	}
139367468Snon
139479697Snon	/* check a timer interrupt */
139579697Snon	regv = 0;
139679697Snon	if ((isrc & IRQSR_TIMER) != 0)
139767468Snon	{
139879697Snon		if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0)
139979697Snon		{
1400274760Sjhb			bus_write_1(sc->port_res, nsp_irqcr, IRQCR_TIMERCL);
140179697Snon			return 1;
140279697Snon		}
140379697Snon		regv |= IRQCR_TIMERCL;
140467468Snon	}
140567468Snon
140679697Snon	/* check a fifo interrupt */
140779697Snon	if ((isrc & IRQSR_FIFO) != 0)
140879697Snon	{
140979697Snon		regv |= IRQCR_FIFOCL;
141079697Snon	}
141167468Snon
141279697Snon	/* OK. enable all interrupts */
1413274760Sjhb	bus_write_1(sc->port_res, nsp_irqcr, regv);
141479697Snon
141567468Snon	/*******************************************
141667468Snon	 * debug section
141767468Snon	 *******************************************/
141867468Snon#ifdef	NSP_DEBUG
141967468Snon	if (nsp_debug)
142067468Snon	{
142179697Snon		nsp_error(sc, "current status", isrc, ph, irqphs);
142267468Snon		scsi_low_print(slp, NULL);
1423131915Smarcel#ifdef	KDB
142467468Snon		if (nsp_debug > 1)
1425240172Sjhb			kdb_enter(KDB_WHY_CAM, "nsp");
1426131915Smarcel#endif	/* KDB */
142767468Snon	}
142867468Snon#endif	/* NSP_DEBUG */
142967468Snon
143067468Snon	/*******************************************
143167468Snon	 * Parse hardware SCSI irq reasons register
143267468Snon	 *******************************************/
143367468Snon	if ((isrc & IRQSR_SCSI) != 0)
143467468Snon	{
143567468Snon 		if ((irqphs & IRQPHS_RST) != 0)
143667468Snon		{
143767468Snon			scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
143867468Snon					 "bus reset (power off?)");
143967468Snon			return 1;
144067468Snon		}
144167468Snon
144267468Snon		if ((irqphs & IRQPHS_RSEL) != 0)
144367468Snon		{
1444274760Sjhb			bus_write_1(sc->port_res, nsp_irqcr, IRQCR_RESCL);
144567468Snon			if (nsp_reselected(sc) == EJUSTRETURN)
144667468Snon				return 1;
144767468Snon		}
144867468Snon
144967468Snon		if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0)
145067468Snon			return 1;
145167468Snon	}
145267468Snon
145367468Snon	/*******************************************
145467468Snon	 * nexus check
145567468Snon	 *******************************************/
145679697Snon	if ((ti = slp->sl_Tnexus) == NULL)
145767468Snon	{
145867468Snon		/* unknown scsi phase changes */
145979697Snon		nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs);
146067468Snon		return 0;
146167468Snon	}
146267468Snon
146367468Snon	/*******************************************
146467468Snon	 * aribitration & selection
146567468Snon	 *******************************************/
146667468Snon	switch (ti->ti_phase)
146767468Snon	{
146867468Snon	case PH_SELSTART:
146967468Snon		if ((ph & SCBUSMON_BSY) == 0)
147067468Snon		{
147167468Snon			if (sc->sc_seltout >= NSP_SELTIMEOUT)
147267468Snon			{
147367468Snon				sc->sc_seltout = 0;
1474274760Sjhb				nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 0);
147567468Snon				return nsp_disconnected(sc, ti);
147667468Snon			}
147767468Snon			sc->sc_seltout ++;
147879697Snon			nsp_start_timer(sc, NSP_TIMER_1MS);
147967468Snon			return 1;
148067468Snon		}
148167468Snon
148267468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
148379697Snon		nsphw_selection_done_and_expect_msgout(sc);
148467468Snon		return 1;
148567468Snon
148679697Snon	case PH_SELECTED:
148779697Snon		if ((isrc & IRQSR_SCSI) == 0)
148879697Snon			return 1;
148979697Snon
149079697Snon		nsp_target_nexus_establish(sc);
149179697Snon		break;
149279697Snon
149367468Snon	case PH_RESEL:
149479697Snon		if ((isrc & IRQSR_SCSI) == 0)
149579697Snon			return 1;
149679697Snon
149779697Snon		nsp_target_nexus_establish(sc);
149867468Snon		if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN)
149967468Snon		{
1500240325Sjhb			device_printf(slp->sl_dev,
1501240325Sjhb			    "unexpected phase after reselect\n");
150279697Snon			slp->sl_error |= FATALIO;
150367468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
150467468Snon			return 1;
150567468Snon		}
150679697Snon		break;
150767468Snon
150879697Snon	case PH_DATA:
150979697Snon		if ((isrc & IRQSR_SCSI) != 0)
151079697Snon			break;
151179697Snon		if ((isrc & IRQSR_FIFO) != 0)
151279697Snon		{
151379697Snon			if (NSP_IS_PHASE_DATA(ph) == 0)
151479697Snon				return 1;
151579697Snon			irqphs = (ph & IRQPHS_PHMASK);
151679697Snon			break;
151779697Snon		}
151879697Snon		return 1;
151979697Snon
152067468Snon	default:
152179697Snon		if ((isrc & IRQSR_SCSI) == 0)
152267468Snon			return 1;
152367468Snon		break;
152467468Snon	}
152567468Snon
152667468Snon	/*******************************************
152779697Snon	 * data phase control
152867468Snon	 *******************************************/
152967468Snon	if (slp->sl_flags & HW_PDMASTART)
153079697Snon	{
153179697Snon		if ((isrc & IRQSR_SCSI) != 0 &&
153279697Snon		     NSP_IS_IRQPHS_DATA(irqphs) == 0)
153379697Snon		{
153479697Snon			if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
153579697Snon				nsp_pio_read(sc, 0);
153679697Snon			nsp_pdma_end(sc, ti);
153779697Snon		}
153879697Snon	}
153967468Snon
154079697Snon	/*******************************************
154179697Snon	 * scsi seq
154279697Snon	 *******************************************/
154367468Snon	if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0)
154467468Snon		return nsp_disconnected(sc, ti);
154567468Snon
154667468Snon	/* check unexpected bus free state */
154767468Snon	if (ph == 0)
154867468Snon	{
154979697Snon		nsp_error(sc, "unexpected bus free", isrc, ph, irqphs);
155067468Snon		return nsp_disconnected(sc, ti);
155167468Snon	}
155267468Snon
155367468Snon	/* check normal scsi phase */
155479697Snon	switch (irqphs & IRQPHS_PHMASK)
155567468Snon	{
155679697Snon	case IRQPHS_CMD:
155779697Snon		if (nsp_phase_match(sc, PHASE_CMD, ph) != 0)
155867468Snon			return 1;
155967468Snon
156067468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
156167468Snon		if (scsi_low_cmd(slp, ti) != 0)
156279697Snon		{
156379697Snon			scsi_low_attention(slp);
156479697Snon		}
156567468Snon
1566274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_CMDCR, CMDCR_PTCLR);
156767468Snon		for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++)
1568274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_CMDDR,
156967468Snon				       slp->sl_scp.scp_cmd[len]);
157067468Snon
1571274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC);
157267468Snon		break;
157367468Snon
157479697Snon	case IRQPHS_DATAOUT:
157567468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
157667468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
157779697Snon		{
157879697Snon			scsi_low_attention(slp);
157979697Snon		}
158067468Snon
158179697Snon		nsp_pio_write(sc, sc->sc_suspendio);
158267468Snon		break;
158367468Snon
158479697Snon	case IRQPHS_DATAIN:
158567468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
158667468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
158779697Snon		{
158879697Snon			scsi_low_attention(slp);
158979697Snon		}
159067468Snon
159179697Snon		nsp_pio_read(sc, sc->sc_suspendio);
159267468Snon		break;
159367468Snon
159479697Snon	case IRQPHS_STATUS:
159579697Snon		if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0)
159667468Snon			return 1;
159767468Snon
159867468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1599274760Sjhb		regv = nsp_cr_read_1(sc->port_res, NSPR_DATA);
1600274760Sjhb		if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE)
160179697Snon		{
1602274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_PARITYR,
160379697Snon				       PARITYR_ENABLE | PARITYR_CLEAR);
160479697Snon			derror = SCSI_LOW_DATA_PE;
160579697Snon		}
160679697Snon		else
160779697Snon			derror = 0;
160879697Snon
160979697Snon		/* assert ACK */
1610274760Sjhb		cr = SCBUSCR_ACK | nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR);
1611274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
161279697Snon
161379697Snon		if (scsi_low_statusin(slp, ti, derror | regv) != 0)
161479697Snon		{
161579697Snon			scsi_low_attention(slp);
161679697Snon		}
161779697Snon
161879697Snon		/* check REQ nagated */
161979697Snon		nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>");
162079697Snon
162179697Snon		/* deassert ACK */
1622274760Sjhb		cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
1623274760Sjhb		nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
162467468Snon		break;
162567468Snon
162679697Snon	case IRQPHS_MSGOUT:
162779697Snon		if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0)
162879697Snon			return 1;
162967468Snon
163079697Snon#ifdef	NSP_MSGOUT_SERIALIZE
163167468Snon		/*
163267468Snon		 * XXX: NSP QUIRK
163367468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
163467468Snon		 * therefore we should poll the scsi phase here to catch
163567468Snon		 * the next "msg out" if exists (no scsi phase changes).
163667468Snon		 */
163767468Snon		rv = len = 16;
163867468Snon		do {
163967468Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
164079697Snon			flags = (ti->ti_ophase != ti->ti_phase) ?
164179697Snon					SCSI_LOW_MSGOUT_INIT : 0;
164279697Snon			len = scsi_low_msgout(slp, ti, flags);
164367468Snon
164479697Snon			if (len > 1 && slp->sl_atten == 0)
164567468Snon			{
164679697Snon				scsi_low_attention(slp);
164779697Snon			}
164879697Snon
164979697Snon			if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
165079697Snon			             slp->sl_clear_atten) != 0)
165179697Snon			{
165279697Snon				slp->sl_error |= FATALIO;
165379697Snon				nsp_error(sc, "MSGOUT: xfer short",
165467468Snon						    isrc, ph, irqphs);
165567468Snon			}
165667468Snon
165767468Snon			/* catch a next signal */
165867468Snon			rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ);
165967468Snon		}
166067468Snon		while (rv > 0 && len -- > 0);
166179697Snon
166279697Snon#else	/* !NSP_MSGOUT_SERIALIZE */
166379697Snon		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
166479697Snon		flags = SCSI_LOW_MSGOUT_UNIFY;
166579697Snon		if (ti->ti_ophase != ti->ti_phase)
166679697Snon			flags |= SCSI_LOW_MSGOUT_INIT;
166779697Snon		len = scsi_low_msgout(slp, ti, flags);
166879697Snon
166979697Snon		if (len > 1 && slp->sl_atten == 0)
167079697Snon		{
167179697Snon			scsi_low_attention(slp);
167279697Snon		}
167379697Snon
167479697Snon		if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
167579697Snon			     slp->sl_clear_atten) != 0)
167679697Snon		{
167779697Snon			nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs);
167879697Snon		}
167979697Snon
168079697Snon#endif	/* !NSP_MSGOUT_SERIALIZE */
168167468Snon		break;
168267468Snon
168379697Snon	case IRQPHS_MSGIN:
168479697Snon		if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0)
168579697Snon			return 1;
168667468Snon
168767468Snon		/*
168867468Snon		 * XXX: NSP QUIRK
168967468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
169067468Snon		 * therefore we should poll the scsi phase here to catch
169167468Snon		 * the next "msg in" if exists (no scsi phase changes).
169267468Snon		 */
169367468Snon		rv = len = 16;
169467468Snon		do {
169579697Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
169679697Snon
169767468Snon			/* read a data */
1698274760Sjhb			regv = nsp_cr_read_1(sc->port_res, NSPR_DATA);
1699274760Sjhb			if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE)
170079697Snon			{
1701274760Sjhb				nsp_cr_write_1(sc->port_res,
170279697Snon					       NSPR_PARITYR,
170379697Snon					       PARITYR_ENABLE | PARITYR_CLEAR);
170479697Snon				derror = SCSI_LOW_DATA_PE;
170579697Snon			}
170679697Snon			else
170779697Snon			{
170879697Snon				derror = 0;
170979697Snon			}
171067468Snon
171167468Snon			/* assert ack */
1712274760Sjhb			cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) | SCBUSCR_ACK;
1713274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
171479697Snon
171579697Snon			if (scsi_low_msgin(slp, ti, regv | derror) == 0)
171679697Snon			{
171779697Snon				if (scsi_low_is_msgout_continue(ti, 0) != 0)
171879697Snon				{
171979697Snon					scsi_low_attention(slp);
172079697Snon				}
172179697Snon			}
172279697Snon
172379697Snon			/* check REQ nagated */
172467468Snon			nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>");
172567468Snon
172667468Snon			/* deassert ack */
1727274760Sjhb			cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
1728274760Sjhb			nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr);
172967468Snon
173067468Snon			/* catch a next signal */
173167468Snon			rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ);
173267468Snon		}
173367468Snon		while (rv > 0 && len -- > 0);
173467468Snon		break;
173567468Snon
173667468Snon	default:
173779697Snon		slp->sl_error |= FATALIO;
173879697Snon		nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs);
173967468Snon		break;
174067468Snon	}
174167468Snon
174267468Snon	return 1;
174367468Snon
174479697Snon#if	0
174567468Snontimerout:
174679697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
174767468Snon	return 0;
174879697Snon#endif
174967468Snon}
175079697Snon
175179697Snonstatic int
175279697Snonnsp_timeout(sc)
175379697Snon	struct nsp_softc *sc;
175479697Snon{
175579697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
175679697Snon	int tout;
175779697Snon	u_int8_t ph, regv;
175879697Snon
175979697Snon	if (slp->sl_Tnexus == NULL)
176079697Snon		return 0;
176179697Snon
1762274760Sjhb	ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
176379697Snon	switch (ph & SCBUSMON_PHMASK)
176479697Snon	{
176579697Snon	case PHASE_DATAOUT:
176679697Snon		if (sc->sc_dataout_timeout == 0)
176779697Snon			break;
176879697Snon
176979697Snon		/* check a fifo empty */
1770274760Sjhb		regv = bus_read_1(sc->port_res, nsp_fifosr);
177179697Snon		if ((regv & FIFOSR_FULLEMP) == 0)
177279697Snon			break;
1773274760Sjhb		bus_write_1(sc->port_res, nsp_irqcr, IRQCR_FIFOCL);
177479697Snon
177579697Snon		/* check still requested */
1776274760Sjhb		ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
177779697Snon		if ((ph & SCBUSMON_REQ) == 0)
177879697Snon			break;
177979697Snon		/* check timeout */
178079697Snon		if ((-- sc->sc_dataout_timeout) > 0)
178179697Snon			break;
178279697Snon
178379697Snon	        slp->sl_error |= PDMAERR;
178479697Snon		if ((slp->sl_flags & HW_WRITE_PADDING) == 0)
178579697Snon		{
1786240325Sjhb			device_printf(slp->sl_dev, "write padding required\n");
178779697Snon			break;
178879697Snon		}
178979697Snon
179079697Snon		tout = NSP_DELAY_MAX;
179179697Snon		while (tout -- > 0)
179279697Snon		{
1793274760Sjhb			ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
179479697Snon			if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT)
179579697Snon				break;
1796274760Sjhb			regv = bus_read_1(sc->port_res, nsp_fifosr);
179779697Snon			if ((regv & FIFOSR_FULLEMP) == 0)
179879697Snon			{
1799240172Sjhb				DELAY(1);
180079697Snon				continue;
180179697Snon			}
180279697Snon
1803274760Sjhb			bus_write_1(sc->port_res, nsp_irqcr, IRQCR_FIFOCL);
180479697Snon			nsp_data_padding(sc, SCSI_LOW_WRITE, 32);
180579697Snon		}
1806274760Sjhb		ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON);
180779697Snon		if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT)
180879697Snon			sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
180979697Snon		break;
181079697Snon
181179697Snon	default:
181279697Snon		break;
181379697Snon	}
181479697Snon	return 0;
181579697Snon}
1816