nsp.c revision 92739
167468Snon/*	$FreeBSD: head/sys/dev/nsp/nsp.c 92739 2002-03-20 02:08:01Z alfred $	*/
279697Snon/*	$NecBSD: nsp.c,v 1.21.12.6 2001/06/29 06:27:52 honda Exp $	*/
367468Snon/*	$NetBSD$	*/
467468Snon
567468Snon#define	NSP_DEBUG
667468Snon#define	NSP_STATICS
779697Snon#define	NSP_IO_CONTROL_FLAGS \
879697Snon	(NSP_READ_SUSPEND_IO | NSP_WRITE_SUSPEND_IO | \
979697Snon	 NSP_READ_FIFO_INTERRUPTS | NSP_WRITE_FIFO_INTERRUPTS | \
1079697Snon	 NSP_USE_MEMIO | NSP_WAIT_FOR_SELECT)
1167468Snon
1267468Snon/*
1379697Snon *  Copyright (c) 1998, 1999, 2000, 2001
1467468Snon *	NetBSD/pc98 porting staff. All rights reserved.
1579697Snon *
1679697Snon *  Copyright (c) 1998, 1999, 2000, 2001
1779697Snon *	Naofumi HONDA. All rights reserved.
1867468Snon *
1967468Snon *  Redistribution and use in source and binary forms, with or without
2067468Snon *  modification, are permitted provided that the following conditions
2167468Snon *  are met:
2267468Snon *  1. Redistributions of source code must retain the above copyright
2367468Snon *     notice, this list of conditions and the following disclaimer.
2467468Snon *  2. Redistributions in binary form must reproduce the above copyright
2567468Snon *     notice, this list of conditions and the following disclaimer in the
2667468Snon *     documentation and/or other materials provided with the distribution.
2767468Snon *  3. The name of the author may not be used to endorse or promote products
2867468Snon *     derived from this software without specific prior written permission.
2967468Snon *
3067468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3167468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3267468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3367468Snon * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
3467468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3567468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3667468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3767468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3867468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3967468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4067468Snon * POSSIBILITY OF SUCH DAMAGE.
4167468Snon */
4267468Snon#include "opt_ddb.h"
4367468Snon
4467468Snon#include <sys/param.h>
4567468Snon#include <sys/systm.h>
4667468Snon#include <sys/kernel.h>
4767468Snon#if defined(__FreeBSD__) && __FreeBSD_version > 500001
4867468Snon#include <sys/bio.h>
4979697Snon#endif	/* __ FreeBSD__ */
5067468Snon#include <sys/buf.h>
5167468Snon#include <sys/queue.h>
5267468Snon#include <sys/malloc.h>
5367468Snon#include <sys/errno.h>
5467468Snon
5567468Snon#ifdef __NetBSD__
5679697Snon#include <sys/device.h>
5767468Snon#include <machine/bus.h>
5867468Snon#include <machine/intr.h>
5967468Snon
6067468Snon#include <dev/scsipi/scsi_all.h>
6167468Snon#include <dev/scsipi/scsipi_all.h>
6267468Snon#include <dev/scsipi/scsiconf.h>
6367468Snon#include <dev/scsipi/scsi_disk.h>
6467468Snon
6567468Snon#include <machine/dvcfg.h>
6667468Snon#include <machine/physio_proc.h>
6767468Snon
6867468Snon#include <i386/Cbus/dev/scsi_low.h>
6967468Snon#include <i386/Cbus/dev/nspreg.h>
7067468Snon#include <i386/Cbus/dev/nspvar.h>
7167468Snon#endif /* __NetBSD__ */
7267468Snon
7367468Snon#ifdef __FreeBSD__
7467468Snon#include <machine/clock.h>
7567468Snon#include <machine/cpu.h>
7667468Snon#include <machine/bus_pio.h>
7767468Snon#include <machine/bus_memio.h>
7867468Snon#include <machine/bus.h>
7967468Snon
8067468Snon#include <machine/dvcfg.h>
8167468Snon#include <machine/physio_proc.h>
8267468Snon
8367468Snon#include <cam/scsi/scsi_low.h>
8467468Snon#include <dev/nsp/nspreg.h>
8567468Snon#include <dev/nsp/nspvar.h>
8667468Snon#endif /* __FreeBSD__ */
8767468Snon
8867468Snon/***************************************************
8967468Snon * USER SETTINGS
9067468Snon ***************************************************/
9167468Snon/* DEVICE CONFIGURATION FLAGS (MINOR)
9267468Snon *
9367468Snon * 0x01   DISCONECT OFF
9467468Snon * 0x02   PARITY LINE OFF
9567468Snon * 0x04   IDENTIFY MSG OFF ( = single lun)
9667468Snon * 0x08   SYNC TRANSFER OFF
9767468Snon */
9867468Snon
9967468Snon/***************************************************
10067468Snon * PARAMS
10167468Snon ***************************************************/
10267468Snon#define	NSP_NTARGETS	8
10367468Snon#define	NSP_NLUNS	8
10467468Snon
10579697Snon#define	NSP_MAX_DATA_SIZE	(64 * 1024)
10679697Snon#define	NSP_SELTIMEOUT		(200)
10779697Snon#define	NSP_DELAY_MAX		(2 * 1000 * 1000)
10879697Snon#define	NSP_DELAY_INTERVAL	(1)
10979697Snon#define	NSP_TIMER_1MS		(1000 / 51)
11067468Snon
11167468Snon/***************************************************
11267468Snon * DEBUG
11367468Snon ***************************************************/
11467468Snon#ifdef	NSP_DEBUG
11567468Snonint nsp_debug;
11667468Snon#endif	/* NSP_DEBUG */
11767468Snon
11867468Snon#ifdef	NSP_STATICS
11967468Snonstruct nsp_statics {
12079697Snon	int arbit_conflict_1;
12179697Snon	int arbit_conflict_2;
12279697Snon	int device_data_write;
12379697Snon	int device_busy;
12467468Snon	int disconnect;
12567468Snon	int reselect;
12667468Snon	int data_phase_bypass;
12779697Snon} nsp_statics;
12867468Snon#endif	/* NSP_STATICS */
12967468Snon
13067468Snon/***************************************************
13179697Snon * IO control
13267468Snon ***************************************************/
13379697Snon#define	NSP_READ_SUSPEND_IO		0x0001
13479697Snon#define	NSP_WRITE_SUSPEND_IO		0x0002
13579697Snon#define	NSP_USE_MEMIO			0x0004
13679697Snon#define	NSP_READ_FIFO_INTERRUPTS	0x0010
13779697Snon#define	NSP_WRITE_FIFO_INTERRUPTS	0x0020
13879697Snon#define	NSP_WAIT_FOR_SELECT		0x0100
13979697Snon
14079697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS;
14179697Snonint nsp_read_suspend_bytes = DEV_BSIZE;
14279697Snonint nsp_write_suspend_bytes = DEV_BSIZE;
14379697Snonint nsp_read_interrupt_bytes = 4096;
14479697Snonint nsp_write_interrupt_bytes = 4096;
14579697Snon
14679697Snon/***************************************************
14779697Snon * DEVICE STRUCTURE
14879697Snon ***************************************************/
14967468Snonextern struct cfdriver nsp_cd;
15067468Snon
15167468Snon/**************************************************************
15267468Snon * DECLARE
15367468Snon **************************************************************/
15479697Snon#define	NSP_FIFO_ON	1
15579697Snon#define	NSP_FIFO_OFF	0
15692739Salfredstatic void nsp_pio_read(struct nsp_softc *, int);
15792739Salfredstatic void nsp_pio_write(struct nsp_softc *, int);
15892739Salfredstatic int nsp_xfer(struct nsp_softc *, u_int8_t *, int, int, int);
15992739Salfredstatic int nsp_msg(struct nsp_softc *, struct targ_info *, u_int);
16092739Salfredstatic int nsp_reselected(struct nsp_softc *);
16192739Salfredstatic int nsp_disconnected(struct nsp_softc *, struct targ_info *);
16292739Salfredstatic void nsp_pdma_end(struct nsp_softc *, struct targ_info *);
16392739Salfredstatic void nsphw_init(struct nsp_softc *);
16492739Salfredstatic int nsp_target_nexus_establish(struct nsp_softc *);
16592739Salfredstatic int nsp_lun_nexus_establish(struct nsp_softc *);
16692739Salfredstatic int nsp_ccb_nexus_establish(struct nsp_softc *);
16792739Salfredstatic int nsp_world_start(struct nsp_softc *, int);
16892739Salfredstatic int nsphw_start_selection(struct nsp_softc *sc, struct slccb *);
16992739Salfredstatic void nsphw_bus_reset(struct nsp_softc *);
17092739Salfredstatic void nsphw_attention(struct nsp_softc *);
17192739Salfredstatic u_int nsp_fifo_count(struct nsp_softc *);
17292739Salfredstatic u_int nsp_request_count(struct nsp_softc *);
17392739Salfredstatic int nsp_negate_signal(struct nsp_softc *, u_int8_t, u_char *);
17492739Salfredstatic int nsp_expect_signal(struct nsp_softc *, u_int8_t, u_int8_t);
17592739Salfredstatic void nsp_start_timer(struct nsp_softc *, int);
17692739Salfredstatic void nsp_setup_fifo(struct nsp_softc *, int, int, int);
17792739Salfredstatic int nsp_targ_init(struct nsp_softc *, struct targ_info *, int);
17892739Salfredstatic void nsphw_selection_done_and_expect_msgout(struct nsp_softc *);
17992739Salfredstatic void nsp_data_padding(struct nsp_softc *, int, u_int);
18092739Salfredstatic int nsp_timeout(struct nsp_softc *);
18192739Salfredstatic int nsp_read_fifo(struct nsp_softc *, int);
18292739Salfredstatic int nsp_write_fifo(struct nsp_softc *, int);
18392739Salfredstatic int nsp_phase_match(struct nsp_softc *, u_int8_t, u_int8_t);
18492739Salfredstatic int nsp_wait_interrupt(struct nsp_softc *);
18567468Snon
18667468Snonstruct scsi_low_funcs nspfuncs = {
18767468Snon	SC_LOW_INIT_T nsp_world_start,
18867468Snon	SC_LOW_BUSRST_T nsphw_bus_reset,
18973025Snon	SC_LOW_TARG_INIT_T nsp_targ_init,
19079697Snon	SC_LOW_LUN_INIT_T NULL,
19167468Snon
19267468Snon	SC_LOW_SELECT_T nsphw_start_selection,
19379697Snon	SC_LOW_NEXUS_T nsp_lun_nexus_establish,
19479697Snon	SC_LOW_NEXUS_T nsp_ccb_nexus_establish,
19567468Snon
19667468Snon	SC_LOW_ATTEN_T nsphw_attention,
19767468Snon	SC_LOW_MSG_T nsp_msg,
19867468Snon
19979697Snon	SC_LOW_TIMEOUT_T nsp_timeout,
20067468Snon	SC_LOW_POLL_T nspintr,
20167468Snon
20267468Snon	NULL,
20367468Snon};
20467468Snon
20567468Snon/****************************************************
20667468Snon * hwfuncs
20767468Snon ****************************************************/
20892739Salfredstatic __inline u_int8_t nsp_cr_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs);
20992739Salfredstatic __inline void nsp_cr_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs, u_int8_t va);
21067468Snon
21167468Snonstatic __inline u_int8_t
21267468Snonnsp_cr_read_1(bst, bsh, ofs)
21367468Snon	bus_space_tag_t bst;
21467468Snon	bus_space_handle_t bsh;
21567468Snon	bus_addr_t ofs;
21667468Snon{
21767468Snon
21867468Snon	bus_space_write_1(bst, bsh, nsp_idxr, ofs);
21967468Snon	return bus_space_read_1(bst, bsh, nsp_datar);
22067468Snon}
22167468Snon
22267468Snonstatic __inline void
22367468Snonnsp_cr_write_1(bst, bsh, ofs, va)
22467468Snon	bus_space_tag_t bst;
22567468Snon	bus_space_handle_t bsh;
22667468Snon	bus_addr_t ofs;
22767468Snon	u_int8_t va;
22867468Snon{
22967468Snon
23067468Snon	bus_space_write_1(bst, bsh, nsp_idxr, ofs);
23167468Snon	bus_space_write_1(bst, bsh, nsp_datar, va);
23267468Snon}
23367468Snon
23467468Snonstatic int
23567468Snonnsp_expect_signal(sc, curphase, mask)
23667468Snon	struct nsp_softc *sc;
23767468Snon	u_int8_t curphase, mask;
23867468Snon{
23967468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
24067468Snon	bus_space_tag_t bst = sc->sc_iot;
24167468Snon	bus_space_handle_t bsh = sc->sc_ioh;
24279697Snon	int wc;
24373025Snon	u_int8_t ph, isrc;
24467468Snon
24579697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
24667468Snon	{
24767468Snon		ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
24879697Snon		if (ph == (u_int8_t) -1)
24979697Snon			return -1;
25079697Snon
25167468Snon		isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
25279697Snon		if (isrc & IRQSR_SCSI)
25379697Snon			return 0;
25467468Snon
25579697Snon		if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase)
25679697Snon			return 1;
25779697Snon
25879697Snon		SCSI_LOW_DELAY(NSP_DELAY_INTERVAL);
25967468Snon	}
26067468Snon
26179697Snon	printf("%s: nsp_expect_signal timeout\n", slp->sl_xname);
26279697Snon	return -1;
26367468Snon}
26467468Snon
26567468Snonstatic void
26667468Snonnsphw_init(sc)
26767468Snon	struct nsp_softc *sc;
26867468Snon{
26967468Snon	bus_space_tag_t bst = sc->sc_iot;
27067468Snon	bus_space_handle_t bsh = sc->sc_ioh;
27167468Snon
27267468Snon	/* block all interrupts */
27367468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK);
27467468Snon
27567468Snon	/* setup SCSI interface */
27667468Snon	bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_IFSEL);
27767468Snon
27867468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, 0);
27967468Snon
28067468Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8);
28167468Snon	nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_iclkdiv);
28267468Snon
28367468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
28479697Snon	nsp_cr_write_1(bst, bsh, NSPR_PARITYR, sc->sc_parr);
28567468Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR,
28667468Snon		       PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS);
28767468Snon
28867468Snon	/* setup fifo asic */
28967468Snon	bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_REGSEL);
29067468Snon	nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, 0);
29167468Snon	if ((nsp_cr_read_1(bst, bsh, NSPR_OCR) & OCR_TERMPWRS) == 0)
29267468Snon		nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, TERMPWRC_POWON);
29367468Snon
29467468Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8);
29567468Snon	nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_clkdiv);
29667468Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
29767468Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
29867468Snon
29967468Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, 0);
30067468Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, 0);
30167468Snon
30267468Snon	/* enable interrupts and ack them */
30379697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
30467468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK);
30567468Snon
30679697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
30767468Snon}
30867468Snon
30967468Snon/****************************************************
31067468Snon * scsi low interface
31167468Snon ****************************************************/
31267468Snonstatic void
31367468Snonnsphw_attention(sc)
31467468Snon	struct nsp_softc *sc;
31567468Snon{
31667468Snon	bus_space_tag_t bst = sc->sc_iot;
31767468Snon	bus_space_handle_t bsh = sc->sc_ioh;
31867468Snon	u_int8_t cr;
31967468Snon
32067468Snon	cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR)/*  & ~SCBUSCR_ACK */;
32167468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ATN);
32279697Snon	SCSI_LOW_DELAY(10);
32367468Snon}
32467468Snon
32567468Snonstatic void
32667468Snonnsphw_bus_reset(sc)
32767468Snon	struct nsp_softc *sc;
32867468Snon{
32967468Snon	bus_space_tag_t bst = sc->sc_iot;
33067468Snon	bus_space_handle_t bsh = sc->sc_ioh;
33167468Snon	int i;
33267468Snon
33367468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK);
33467468Snon
33567468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_RST);
33679697Snon	SCSI_LOW_DELAY(100 * 1000);	/* 100ms */
33767468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0);
33867468Snon	for (i = 0; i < 5; i ++)
33967468Snon		(void) nsp_cr_read_1(bst, bsh, NSPR_IRQPHS);
34067468Snon
34167468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK);
34267468Snon}
34367468Snon
34479697Snonstatic void
34579697Snonnsphw_selection_done_and_expect_msgout(sc)
34671468Sjhb	struct nsp_softc *sc;
34771468Sjhb{
34879697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
34971468Sjhb	bus_space_tag_t bst = sc->sc_iot;
35071468Sjhb	bus_space_handle_t bsh = sc->sc_ioh;
35171468Sjhb
35279697Snon	/* clear ack counter */
35379697Snon	sc->sc_cnt = 0;
35479697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
35579697Snon			PTCLRR_REQ | PTCLRR_HOST);
35679697Snon
35779697Snon	/* deassert sel and assert atten */
35879697Snon	sc->sc_seltout = 0;
35979697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc);
36079697Snon	SCSI_LOW_DELAY(1);
36179697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
36279697Snon			sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN);
36379697Snon	SCSI_LOW_ASSERT_ATN(slp);
36471468Sjhb}
36571468Sjhb
36667468Snonstatic int
36767468Snonnsphw_start_selection(sc, cb)
36867468Snon	struct nsp_softc *sc;
36967468Snon	struct slccb *cb;
37067468Snon{
37167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
37267468Snon	bus_space_tag_t bst = sc->sc_iot;
37367468Snon	bus_space_handle_t bsh = sc->sc_ioh;
37467468Snon	struct targ_info *ti = cb->ti;
37567468Snon	register u_int8_t arbs, ph;
37679697Snon	int s, wc;
37767468Snon
37879697Snon	wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
37979697Snon	sc->sc_dataout_timeout = 0;
38079697Snon
38167468Snon	/* check bus free */
38279697Snon	s = splhigh();
38379697Snon	ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
38479697Snon	if (ph != SCBUSMON_FREE)
38567468Snon	{
38667468Snon		splx(s);
38779697Snon#ifdef	NSP_STATICS
38879697Snon		nsp_statics.arbit_conflict_1 ++;
38979697Snon#endif	/* NSP_STATICS */
39079697Snon		return SCSI_LOW_START_FAIL;
39167468Snon	}
39267468Snon
39367468Snon	/* start arbitration */
39479697Snon	nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_EXEC);
39579697Snon	splx(s);
39679697Snon
39767468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART);
39867468Snon	do
39967468Snon	{
40067468Snon		/* XXX: what a stupid chip! */
40167468Snon		arbs = nsp_cr_read_1(bst, bsh, NSPR_ARBITS);
40279697Snon		SCSI_LOW_DELAY(1);
40367468Snon	}
40473025Snon	while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0);
40567468Snon
40667468Snon	if ((arbs & ARBITS_WIN) == 0)
40767468Snon	{
40867468Snon		nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR);
40979697Snon#ifdef	NSP_STATICS
41079697Snon		nsp_statics.arbit_conflict_2 ++;
41179697Snon#endif	/* NSP_STATICS */
41267468Snon		return SCSI_LOW_START_FAIL;
41367468Snon	}
41467468Snon
41567468Snon	/* assert select line */
41667468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
41779697Snon	scsi_low_arbit_win(slp);
41879697Snon
41979697Snon	s = splhigh();
42079697Snon	SCSI_LOW_DELAY(3);
42167468Snon	nsp_cr_write_1(bst, bsh, NSPR_DATA,
42267468Snon		       sc->sc_idbit | (1 << ti->ti_id));
42367468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
42467468Snon			SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc);
42579697Snon	SCSI_LOW_DELAY(3);
42667468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL |
42767468Snon			SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc);
42867468Snon	nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR);
42979697Snon	SCSI_LOW_DELAY(3);
43067468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
43167468Snon		       SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc);
43279697Snon	SCSI_LOW_DELAY(1);
43367468Snon
43479697Snon	if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0)
43579697Snon	{
43679697Snon#define	NSP_FIRST_SEL_WAIT	300
43779697Snon#define	NSP_SEL_CHECK_INTERVAL	10
43879697Snon
43979697Snon		/* wait for a selection response */
44079697Snon		for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL;
44179697Snon		     wc ++)
44279697Snon		{
44379697Snon			ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
44479697Snon			if ((ph & SCBUSMON_BSY) == 0)
44579697Snon			{
44679697Snon				SCSI_LOW_DELAY(NSP_SEL_CHECK_INTERVAL);
44779697Snon				continue;
44879697Snon			}
44979697Snon
45082784Snon			SCSI_LOW_DELAY(1);
45179697Snon			ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
45279697Snon			if ((ph & SCBUSMON_BSY) != 0)
45379697Snon			{
45479697Snon				nsphw_selection_done_and_expect_msgout(sc);
45579697Snon				splx(s);
45679697Snon
45779697Snon				SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
45879697Snon				return SCSI_LOW_START_OK;
45979697Snon			}
46079697Snon		}
46179697Snon	}
46279697Snon	splx(s);
46379697Snon
46479697Snon	/* check a selection timeout */
46579697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
46667468Snon	sc->sc_seltout = 1;
46767468Snon	return SCSI_LOW_START_OK;
46867468Snon}
46967468Snon
47067468Snonstatic int
47167468Snonnsp_world_start(sc, fdone)
47267468Snon	struct nsp_softc *sc;
47367468Snon	int fdone;
47467468Snon{
47567468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
47667468Snon
47767468Snon	sc->sc_cnt = 0;
47867468Snon	sc->sc_seltout = 0;
47979697Snon
48067468Snon	if ((slp->sl_cfgflags & CFG_NOATTEN) == 0)
48167468Snon		sc->sc_busc = SCBUSCR_ATN;
48267468Snon	else
48367468Snon		sc->sc_busc = 0;
48479697Snon
48579697Snon	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
48679697Snon		sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR;
48779697Snon	else
48879697Snon		sc->sc_parr = 0;
48979697Snon
49067468Snon	sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST);
49167468Snon
49267468Snon	nsphw_init(sc);
49367468Snon	scsi_low_bus_reset(slp);
49467468Snon
49567468Snon	SOFT_INTR_REQUIRED(slp);
49667468Snon	return 0;
49767468Snon}
49867468Snon
49967468Snonstruct ncp_synch_data {
50067468Snon	u_int min_period;
50167468Snon	u_int max_period;
50267468Snon	u_int chip_period;
50367468Snon	u_int ack_width;
50467468Snon};
50567468Snon
50667468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = {
50767468Snon	{0x0c,0x0c,0x1,0},	/* 20MB  50ns*/
50867468Snon	{0x19,0x19,0x3,1}, 	/* 10MB  100ns*/
50967468Snon	{0x1a,0x25,0x5,2},	/* 7.5MB 150ns*/
51067468Snon	{0x26,0x32,0x7,3},	/* 5MB   200ns*/
51167468Snon	{0x0, 0, 0, 0}
51267468Snon};
51367468Snon
51467468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = {
51567468Snon	{0x19,0x19,0x1,0}, 	/* 10MB  100ns*/
51667468Snon	{0x1a,0x25,0x2,0},	/* 7.5MB 150ns*/
51767468Snon	{0x26,0x32,0x3,1},	/* 5MB   200ns*/
51867468Snon	{0x0, 0, 0, 0}
51967468Snon};
52067468Snon
52167468Snonstatic int
52267468Snonnsp_msg(sc, ti, msg)
52367468Snon	struct nsp_softc *sc;
52467468Snon	struct targ_info *ti;
52567468Snon	u_int msg;
52667468Snon{
52779697Snon	bus_space_tag_t bst = sc->sc_iot;
52879697Snon	bus_space_handle_t bsh = sc->sc_ioh;
52967468Snon	struct ncp_synch_data *sdp;
53073025Snon	struct nsp_targ_info *nti = (void *) ti;
53167468Snon	u_int period, offset;
53279697Snon	int i, error;
53367468Snon
53479697Snon	if ((msg & SCSI_LOW_MSG_WIDE) != 0)
53579697Snon	{
53679697Snon		if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
53779697Snon		{
53879697Snon			ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
53979697Snon			return EINVAL;
54079697Snon		}
54179697Snon		return 0;
54279697Snon	}
54379697Snon
54467468Snon	if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
54567468Snon		return 0;
54667468Snon
54773025Snon	period = ti->ti_maxsynch.period;
54873025Snon	offset = ti->ti_maxsynch.offset;
54967468Snon	if (sc->sc_iclkdiv == CLKDIVR_20M)
55067468Snon		sdp = &ncp_sync_data_20M[0];
55167468Snon	else
55267468Snon		sdp = &ncp_sync_data_40M[0];
55367468Snon
55467468Snon	for (i = 0; sdp->max_period != 0; i ++, sdp ++)
55567468Snon	{
55667468Snon		if (period >= sdp->min_period && period <= sdp->max_period)
55767468Snon			break;
55867468Snon	}
55967468Snon
56067468Snon	if (period != 0 && sdp->max_period == 0)
56167468Snon	{
56267468Snon		/*
56367468Snon		 * NO proper period/offset found,
56467468Snon		 * Retry neg with the target.
56567468Snon		 */
56673025Snon		ti->ti_maxsynch.period = 0;
56773025Snon		ti->ti_maxsynch.offset = 0;
56873025Snon		nti->nti_reg_syncr = 0;
56973025Snon		nti->nti_reg_ackwidth = 0;
57079697Snon		error = EINVAL;
57167468Snon	}
57279697Snon	else
57379697Snon	{
57479697Snon		nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) |
57579697Snon				      (offset & SYNCR_OFFM);
57679697Snon		nti->nti_reg_ackwidth = sdp->ack_width;
57779697Snon		error = 0;
57879697Snon	}
57967468Snon
58079697Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr);
58179697Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
58279697Snon	return error;
58367468Snon}
58467468Snon
58567468Snonstatic int
58679697Snonnsp_targ_init(sc, ti, action)
58767468Snon	struct nsp_softc *sc;
58867468Snon	struct targ_info *ti;
58979697Snon	int action;
59067468Snon{
59173025Snon	struct nsp_targ_info *nti = (void *) ti;
59267468Snon
59379697Snon	if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
59479697Snon	{
59579697Snon		ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
59679697Snon		ti->ti_maxsynch.period = 100 / 4;
59779697Snon		ti->ti_maxsynch.offset = 15;
59879697Snon		nti->nti_reg_syncr = 0;
59979697Snon		nti->nti_reg_ackwidth = 0;
60079697Snon	}
60167468Snon	return 0;
60267468Snon}
60367468Snon
60479697Snonstatic void
60579697Snonnsp_start_timer(sc, time)
60679697Snon	struct nsp_softc *sc;
60779697Snon	int time;
60879697Snon{
60979697Snon	bus_space_tag_t bst = sc->sc_iot;
61079697Snon	bus_space_handle_t bsh = sc->sc_ioh;
61179697Snon
61279697Snon	sc->sc_timer = time;
61379697Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time);
61479697Snon}
61579697Snon
61667468Snon/**************************************************************
61767468Snon * General probe attach
61867468Snon **************************************************************/
61967468Snonint
62067468Snonnspprobesubr(iot, ioh, dvcfg)
62167468Snon	bus_space_tag_t iot;
62267468Snon	bus_space_handle_t ioh;
62367468Snon	u_int dvcfg;
62467468Snon{
62567468Snon	u_int8_t regv;
62667468Snon
62767468Snon	regv = bus_space_read_1(iot, ioh, nsp_fifosr);
62867468Snon	if (regv < 0x11 || regv >= 0x20)
62967468Snon		return 0;
63067468Snon	return 1;
63167468Snon}
63267468Snon
63367468Snonint
63467468Snonnspprint(aux, name)
63567468Snon	void *aux;
63667468Snon	const char *name;
63767468Snon{
63867468Snon
63967468Snon	if (name != NULL)
64067468Snon		printf("%s: scsibus ", name);
64167468Snon	return UNCONF;
64267468Snon}
64367468Snon
64467468Snonvoid
64567468Snonnspattachsubr(sc)
64667468Snon	struct nsp_softc *sc;
64767468Snon{
64867468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
64967468Snon
65067468Snon	printf("\n");
65167468Snon
65267468Snon	sc->sc_idbit = (1 << slp->sl_hostid);
65379697Snon	slp->sl_flags |= HW_READ_PADDING;
65467468Snon	slp->sl_funcs = &nspfuncs;
65579697Snon	sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
65667468Snon
65779697Snon	(void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS,
65879697Snon			       sizeof(struct nsp_targ_info), 0);
65967468Snon}
66067468Snon
66167468Snon/**************************************************************
66267468Snon * PDMA functions
66367468Snon **************************************************************/
66467468Snonstatic u_int
66567468Snonnsp_fifo_count(sc)
66667468Snon	struct nsp_softc *sc;
66767468Snon{
66867468Snon	bus_space_tag_t bst = sc->sc_iot;
66967468Snon	bus_space_handle_t bsh = sc->sc_ioh;
67067468Snon	u_int count;
67167468Snon
67279697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT);
67367468Snon	count = bus_space_read_1(bst, bsh, nsp_datar);
67467468Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8);
67567468Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16);
67667468Snon	return count;
67767468Snon}
67867468Snon
67979697Snonstatic u_int
68079697Snonnsp_request_count(sc)
68179697Snon	struct nsp_softc *sc;
68279697Snon{
68379697Snon	bus_space_tag_t bst = sc->sc_iot;
68479697Snon	bus_space_handle_t bsh = sc->sc_ioh;
68579697Snon	u_int count;
68679697Snon
68779697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT);
68879697Snon	count = bus_space_read_1(bst, bsh, nsp_datar);
68979697Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8);
69079697Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16);
69179697Snon	return count;
69279697Snon}
69379697Snon
69467468Snonstatic void
69579697Snonnsp_setup_fifo(sc, on, direction, datalen)
69667468Snon	struct nsp_softc *sc;
69767468Snon	int on;
69879697Snon	int direction;
69979697Snon	int datalen;
70067468Snon{
70167468Snon	u_int8_t xfermode;
70267468Snon
70379697Snon	sc->sc_suspendio = 0;
70479697Snon	if (on == NSP_FIFO_OFF)
70579697Snon	{
70679697Snon		xfermode = XFERMR_IO8;
70779697Snon		goto out;
70879697Snon	}
70967468Snon
71079697Snon	/* check if suspend io OK ? */
71179697Snon	if (datalen > 0)
71267468Snon	{
71379697Snon		if (direction == SCSI_LOW_READ)
71479697Snon		{
71579697Snon			if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 &&
71679697Snon			    (datalen % nsp_read_suspend_bytes) == 0)
71779697Snon				sc->sc_suspendio = nsp_read_suspend_bytes;
71879697Snon		}
71979697Snon		else
72079697Snon		{
72179697Snon			if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 &&
72279697Snon			    (datalen % nsp_write_suspend_bytes) == 0)
72379697Snon				sc->sc_suspendio = nsp_write_suspend_bytes;
72479697Snon		}
72567468Snon	}
72679697Snon
72779697Snon	/* determine a transfer type */
72879697Snon	if (datalen < DEV_BSIZE || (datalen & 3) != 0)
72979697Snon	{
73079697Snon		if (sc->sc_memh != NULL &&
73179697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
73279697Snon			xfermode = XFERMR_XEN | XFERMR_MEM8;
73379697Snon		else
73479697Snon			xfermode = XFERMR_XEN | XFERMR_IO8;
73579697Snon	}
73667468Snon	else
73767468Snon	{
73879697Snon		if (sc->sc_memh != NULL &&
73979697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
74079697Snon			xfermode = XFERMR_XEN | XFERMR_MEM32;
74167468Snon		else
74279697Snon			xfermode = XFERMR_XEN | XFERMR_IO32;
74379697Snon
74479697Snon		if (sc->sc_suspendio > 0)
74579697Snon			xfermode |= XFERMR_FIFOEN;
74667468Snon	}
74767468Snon
74879697Snonout:
74967468Snon	sc->sc_xfermr = xfermode;
75079697Snon	nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_XFERMR, sc->sc_xfermr);
75167468Snon}
75267468Snon
75379697Snonstatic void
75467468Snonnsp_pdma_end(sc, ti)
75567468Snon	struct nsp_softc *sc;
75667468Snon	struct targ_info *ti;
75767468Snon{
75867468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
75979697Snon	struct slccb *cb = slp->sl_Qnexus;
76067468Snon	u_int len = 0, cnt;
76167468Snon
76279697Snon	sc->sc_dataout_timeout = 0;
76367468Snon	slp->sl_flags &= ~HW_PDMASTART;
76479697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
76579697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
76679697Snon	{
76779697Snon		sc->sc_icr &= ~SCIENR_FIFO;
76879697Snon		nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_SCIENR, sc->sc_icr);
76979697Snon	}
77067468Snon
77179697Snon	if (cb == NULL)
77279697Snon	{
77379697Snon		slp->sl_error |= PDMAERR;
77479697Snon		return;
77579697Snon	}
77679697Snon
77767468Snon	if (ti->ti_phase == PH_DATA)
77867468Snon	{
77967468Snon		cnt = nsp_fifo_count(sc);
78067468Snon		if (slp->sl_scp.scp_direction  == SCSI_LOW_WRITE)
78167468Snon		{
78267468Snon			len = sc->sc_cnt - cnt;
78379697Snon			if (sc->sc_cnt >= cnt &&
78479697Snon			    slp->sl_scp.scp_datalen + len <=
78567468Snon			    cb->ccb_scp.scp_datalen)
78667468Snon			{
78767468Snon				slp->sl_scp.scp_data -= len;
78867468Snon				slp->sl_scp.scp_datalen += len;
78967468Snon			}
79067468Snon			else
79167468Snon			{
79267468Snon				slp->sl_error |= PDMAERR;
79367468Snon				printf("%s len %x >= datalen %x\n",
79467468Snon					slp->sl_xname,
79567468Snon					len, slp->sl_scp.scp_datalen);
79667468Snon			}
79767468Snon		}
79867468Snon		else if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
79967468Snon		{
80079697Snon			if (sc->sc_cnt != cnt ||
80179697Snon			    sc->sc_cnt > cb->ccb_scp.scp_datalen)
80267468Snon			{
80367468Snon				slp->sl_error |= PDMAERR;
80479697Snon				printf("%s: data read count error %x != %x (%x)\n",
80579697Snon					slp->sl_xname, sc->sc_cnt, cnt,
80679697Snon					cb->ccb_scp.scp_datalen);
80767468Snon			}
80867468Snon		}
80967468Snon		sc->sc_cnt = cnt;
81079697Snon		scsi_low_data_finish(slp);
81167468Snon	}
81267468Snon	else
81367468Snon	{
81467468Snon
81567468Snon		printf("%s data phase miss\n", slp->sl_xname);
81667468Snon		slp->sl_error |= PDMAERR;
81767468Snon	}
81867468Snon}
81967468Snon
82067468Snon#define	RFIFO_CRIT	64
82179697Snon#define	WFIFO_CRIT	32
82267468Snon
82367468Snonstatic void
82479697Snonnsp_data_padding(sc, direction, count)
82567468Snon	struct nsp_softc *sc;
82679697Snon	int direction;
82779697Snon	u_int count;
82867468Snon{
82979697Snon	bus_space_tag_t bst = sc->sc_iot;
83079697Snon	bus_space_handle_t bsh = sc->sc_ioh;
83179697Snon
83279697Snon	if (count > NSP_MAX_DATA_SIZE)
83379697Snon		count = NSP_MAX_DATA_SIZE;
83479697Snon
83579697Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8);
83679697Snon	if (direction == SCSI_LOW_READ)
83779697Snon	{
83879697Snon		while (count -- > 0)
83979697Snon			(void) bus_space_read_1(bst, bsh, nsp_fifodr);
84079697Snon	}
84179697Snon	else
84279697Snon	{
84379697Snon		while (count -- > 0)
84479697Snon			(void) bus_space_write_1(bst, bsh, nsp_fifodr, 0);
84579697Snon	}
84679697Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr);
84779697Snon}
84879697Snon
84979697Snonstatic int
85079697Snonnsp_read_fifo(sc, suspendio)
85179697Snon	struct nsp_softc *sc;
85279697Snon	int suspendio;
85379697Snon{
85467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
85567468Snon	bus_space_tag_t bst = sc->sc_iot;
85667468Snon	bus_space_handle_t bsh = sc->sc_ioh;
85779697Snon	u_int res;
85867468Snon
85979697Snon	res = nsp_fifo_count(sc);
86079697Snon	if (res == sc->sc_cnt)
86179697Snon		return 0;
86267468Snon
86379697Snon#ifdef	NSP_DEBUG
86479697Snon	if (res < sc->sc_cnt || res == (u_int) -1)
86567468Snon	{
86679697Snon		printf("%s: strange fifo ack count 0x%x < 0x%x\n",
86779697Snon			slp->sl_xname, res, sc->sc_cnt);
86879697Snon		return 0;
86979697Snon	}
87079697Snon#endif	/* NSP_DEBUG */
87179697Snon
87279697Snon	res = res - sc->sc_cnt;
87379697Snon	if (res > slp->sl_scp.scp_datalen)
87479697Snon	{
87579697Snon		if ((slp->sl_error & PDMAERR) == 0)
87679697Snon		{
87779697Snon			printf("%s: data overrun 0x%x > 0x%x\n",
87879697Snon				slp->sl_xname, res, slp->sl_scp.scp_datalen);
87979697Snon		}
88079697Snon
88179697Snon		slp->sl_error |= PDMAERR;
88279697Snon		slp->sl_scp.scp_datalen = 0;
88379697Snon
88479697Snon		if ((slp->sl_flags & HW_READ_PADDING) == 0)
88579697Snon		{
88679697Snon			printf("%s: read padding required\n", slp->sl_xname);
88779697Snon			return 0;
88879697Snon		}
88979697Snon
89079697Snon		nsp_data_padding(sc, SCSI_LOW_READ, res);
89179697Snon		sc->sc_cnt += res;
89279697Snon		return 1;	/* padding start */
89379697Snon	}
89479697Snon
89579697Snon	if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio)
89679697Snon		res = suspendio;
89779697Snon
89879697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
89979697Snon	{
90079697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
90179697Snon		{
90279697Snon			res &= ~3;
90379697Snon			bus_space_read_region_4(sc->sc_memt, sc->sc_memh, 0,
90479697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
90579697Snon		}
90679697Snon		else
90779697Snon		{
90879697Snon			bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 0,
90979697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
91079697Snon		}
91179697Snon	}
91279697Snon	else
91379697Snon	{
91479697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
91579697Snon		{
91679697Snon			res &= ~3;
91779697Snon			bus_space_read_multi_4(bst, bsh, nsp_fifodr,
91879697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
91979697Snon		}
92079697Snon		else
92179697Snon		{
92279697Snon			bus_space_read_multi_1(bst, bsh, nsp_fifodr,
92379697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
92479697Snon		}
92579697Snon	}
92679697Snon
92779697Snon	if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
92879697Snon	{
92979697Snon		nsp_cr_write_1(bst, bsh, NSPR_PARITYR,
93079697Snon			       PARITYR_ENABLE | PARITYR_CLEAR);
93179697Snon		scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1);
93279697Snon	}
93379697Snon
93479697Snon	slp->sl_scp.scp_data += res;
93579697Snon	slp->sl_scp.scp_datalen -= res;
93679697Snon	sc->sc_cnt += res;
93779697Snon	return 0;
93879697Snon}
93979697Snon
94079697Snonstatic int
94179697Snonnsp_write_fifo(sc, suspendio)
94279697Snon	struct nsp_softc *sc;
94379697Snon	int suspendio;
94479697Snon{
94579697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
94679697Snon	bus_space_tag_t bst = sc->sc_iot;
94779697Snon	bus_space_handle_t bsh = sc->sc_ioh;
94879697Snon	u_int res;
94979697Snon	register u_int8_t stat;
95079697Snon
95179697Snon	if (suspendio > 0)
95279697Snon	{
95379697Snon#ifdef	NSP_DEBUG
95479697Snon		if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0)
95579697Snon		{
95679697Snon			printf("%s: strange write length 0x%x\n",
95779697Snon				slp->sl_xname, slp->sl_scp.scp_datalen);
95879697Snon		}
95979697Snon#endif	/* NSP_DEBUG */
96079697Snon		res = slp->sl_scp.scp_datalen % suspendio;
96167468Snon		if (res == 0)
96267468Snon		{
96379697Snon			res = suspendio;
96467468Snon		}
96579697Snon	}
96679697Snon	else
96779697Snon	{
96879697Snon		res = WFIFO_CRIT;
96979697Snon	}
97067468Snon
97179697Snon	if (res > slp->sl_scp.scp_datalen)
97279697Snon		res = slp->sl_scp.scp_datalen;
97367468Snon
97479697Snon	/* XXX: reconfirm! */
97579697Snon	stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
97679697Snon	if (stat != PHASE_DATAOUT)
97779697Snon		return 0;
97867468Snon
97979697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
98079697Snon	{
98179697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
98279697Snon		{
98379697Snon			bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 0,
98479697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
98579697Snon		}
98667468Snon		else
98779697Snon		{
98879697Snon			bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 0,
98979697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
99079697Snon		}
99179697Snon	}
99279697Snon	else
99379697Snon	{
99479697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
99579697Snon		{
99679697Snon			bus_space_write_multi_4(bst, bsh, nsp_fifodr,
99779697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
99879697Snon		}
99979697Snon		else
100079697Snon		{
100179697Snon			bus_space_write_multi_1(bst, bsh, nsp_fifodr,
100279697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
100379697Snon		}
100479697Snon	}
100567468Snon
100679697Snon	slp->sl_scp.scp_datalen -= res;
100779697Snon	slp->sl_scp.scp_data += res;
100879697Snon	sc->sc_cnt += res;
100979697Snon	return 0;
101079697Snon}
101179697Snon
101279697Snonstatic int
101379697Snonnsp_wait_interrupt(sc)
101479697Snon	struct nsp_softc *sc;
101579697Snon{
101679697Snon	bus_space_tag_t bst = sc->sc_iot;
101779697Snon	bus_space_handle_t bsh = sc->sc_ioh;
101879697Snon	int tout;
101979697Snon	register u_int8_t isrc;
102079697Snon
102179697Snon	for (tout = 0; tout < DEV_BSIZE / 10; tout ++)
102279697Snon	{
102379697Snon		isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
102479697Snon		if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0)
102567468Snon		{
102679697Snon			if ((isrc & IRQSR_FIFO) != 0)
102779697Snon			{
102879697Snon				bus_space_write_1(bst, bsh,
102979697Snon					nsp_irqcr, IRQCR_FIFOCL);
103079697Snon			}
103179697Snon			return 1;
103267468Snon		}
103379697Snon		SCSI_LOW_DELAY(1);
103479697Snon	}
103579697Snon	return 0;
103679697Snon}
103779697Snon
103879697Snonstatic void
103979697Snonnsp_pio_read(sc, suspendio)
104079697Snon	struct nsp_softc *sc;
104179697Snon	int suspendio;
104279697Snon{
104379697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
104479697Snon	bus_space_tag_t bst = sc->sc_iot;
104579697Snon	bus_space_handle_t bsh = sc->sc_ioh;
104679697Snon	int tout, padding, datalen;
104779697Snon	register u_int8_t stat, fstat;
104879697Snon
104979697Snon	padding = 0;
105079697Snon	tout = sc->sc_tmaxcnt;
105179697Snon	slp->sl_flags |= HW_PDMASTART;
105279697Snon	datalen = slp->sl_scp.scp_datalen;
105379697Snon
105479697SnonReadLoop:
105579697Snon	while (1)
105679697Snon	{
105779697Snon		stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
105879697Snon		if (stat == (u_int8_t) -1)
105979697Snon			return;
106079697Snon
106179697Snon		/* out of data phase */
106279697Snon		if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN)
106379697Snon		{
106479697Snon			nsp_read_fifo(sc, 0);
106579697Snon			return;
106679697Snon		}
106779697Snon
106879697Snon		/* data phase */
106979697Snon		fstat = bus_space_read_1(bst, bsh, nsp_fifosr);
107079697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
107179697Snon		{
107279697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
107379697Snon			{
107479697Snon				bus_space_write_1(bst, bsh, nsp_irqcr,
107579697Snon						  IRQCR_FIFOCL);
107679697Snon			}
107779697Snon
107879697Snon			if (suspendio > 0)
107979697Snon			{
108079697Snon				padding |= nsp_read_fifo(sc, suspendio);
108179697Snon			}
108279697Snon			else
108379697Snon			{
108479697Snon				padding |= nsp_read_fifo(sc, 0);
108579697Snon			}
108679697Snon
108779697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
108879697Snon				break;
108979697Snon		}
109067468Snon		else
109167468Snon		{
109279697Snon			if (padding == 0 && slp->sl_scp.scp_datalen <= 0)
109379697Snon				return;
109479697Snon
109579697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
109679697Snon				break;
109779697Snon
109879697Snon			SCSI_LOW_DELAY(1);
109967468Snon		}
110067468Snon
110179697Snon		if ((-- tout) <= 0)
110279697Snon		{
110379697Snon			printf("%s: nsp_pio_read: timeout\n", slp->sl_xname);
110479697Snon			return;
110579697Snon		}
110667468Snon	}
110767468Snon
110879697Snon
110979697Snon	if (slp->sl_scp.scp_datalen > 0 &&
111079697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes)
111179697Snon	{
111279697Snon		if (nsp_wait_interrupt(sc) != 0)
111379697Snon			goto ReadLoop;
111479697Snon	}
111567468Snon}
111667468Snon
111767468Snonstatic void
111879697Snonnsp_pio_write(sc, suspendio)
111967468Snon	struct nsp_softc *sc;
112079697Snon	int suspendio;
112167468Snon{
112267468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
112367468Snon	bus_space_tag_t bst = sc->sc_iot;
112467468Snon	bus_space_handle_t bsh = sc->sc_ioh;
112579697Snon	u_int rcount, acount;
112679697Snon	int tout, datalen;
112779697Snon	register u_int8_t stat, fstat;
112867468Snon
112979697Snon	tout = sc->sc_tmaxcnt;
113067468Snon	slp->sl_flags |= HW_PDMASTART;
113179697Snon	datalen = slp->sl_scp.scp_datalen;
113279697Snon
113379697SnonWriteLoop:
113479697Snon	while (1)
113567468Snon	{
113679697Snon		stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
113767468Snon		if (stat != PHASE_DATAOUT)
113879697Snon			return;
113967468Snon
114079697Snon		if (slp->sl_scp.scp_datalen <= 0)
114179697Snon		{
114279697Snon			if (sc->sc_dataout_timeout == 0)
114379697Snon				sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
114479697Snon			return;
114579697Snon		}
114667468Snon
114779697Snon		fstat = bus_space_read_1(bst, bsh, nsp_fifosr);
114879697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
114979697Snon		{
115079697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
115179697Snon			{
115279697Snon				bus_space_write_1(bst, bsh, nsp_irqcr,
115379697Snon						  IRQCR_FIFOCL);
115479697Snon			}
115567468Snon
115679697Snon			if (suspendio > 0)
115779697Snon			{
115879697Snon				/* XXX:IMPORTANT:
115979697Snon				 * To avoid timeout of pcmcia bus
116079697Snon				 * (not scsi bus!), we should check
116179697Snon				 * the scsi device sends us request
116279697Snon				 * signals, which means the scsi device
116379697Snon				 * is ready to recieve data without
116479697Snon				 * heavy delays.
116579697Snon				 */
116682784Snon				if ((slp->sl_scp.scp_datalen % suspendio) == 0)
116779697Snon				{
116882784Snon					/* Step I:
116982784Snon					 * fill the nsp fifo, and waiting for
117082784Snon					 * the fifo empty.
117182784Snon					 */
117279697Snon					nsp_write_fifo(sc, 0);
117379697Snon				}
117479697Snon				else
117579697Snon				{
117682784Snon					/* Step II:
117782784Snon					 * check the request singals.
117882784Snon					 */
117982784Snon					acount = nsp_fifo_count(sc);
118082784Snon					rcount = nsp_request_count(sc);
118182784Snon					if (rcount <= acount)
118282784Snon					{
118382784Snon						nsp_write_fifo(sc, 0);
118479697Snon#ifdef	NSP_STATICS
118582784Snon						nsp_statics.device_busy ++;
118679697Snon#endif	/* NSP_STATICS */
118782784Snon					}
118882784Snon					else
118982784Snon					{
119082784Snon						nsp_write_fifo(sc, suspendio);
119182784Snon#ifdef	NSP_STATICS
119282784Snon						nsp_statics.device_data_write ++;
119382784Snon#endif	/* NSP_STATICS */
119482784Snon					}
119579697Snon				}
119679697Snon			}
119779697Snon			else
119879697Snon			{
119979697Snon				nsp_write_fifo(sc, 0);
120079697Snon			}
120179697Snon
120279697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
120379697Snon				break;
120467468Snon		}
120567468Snon		else
120667468Snon		{
120779697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
120879697Snon				break;
120979697Snon
121079697Snon			SCSI_LOW_DELAY(1);
121167468Snon		}
121267468Snon
121379697Snon		if ((-- tout) <= 0)
121479697Snon		{
121579697Snon			printf("%s: nsp_pio_write: timeout\n", slp->sl_xname);
121679697Snon			return;
121779697Snon		}
121867468Snon	}
121967468Snon
122079697Snon	if (slp->sl_scp.scp_datalen > 0 &&
122179697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes)
122279697Snon	{
122379697Snon		if (nsp_wait_interrupt(sc) != 0)
122479697Snon			goto WriteLoop;
122579697Snon	}
122667468Snon}
122767468Snon
122867468Snonstatic int
122967468Snonnsp_negate_signal(sc, mask, s)
123067468Snon	struct nsp_softc *sc;
123167468Snon	u_int8_t mask;
123267468Snon	u_char *s;
123367468Snon{
123467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
123567468Snon	bus_space_tag_t bst = sc->sc_iot;
123667468Snon	bus_space_handle_t bsh = sc->sc_ioh;
123779697Snon	int wc;
123867468Snon	u_int8_t regv;
123967468Snon
124079697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
124167468Snon	{
124267468Snon		regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
124379697Snon		if (regv == (u_int8_t) -1)
124479697Snon			return -1;
124579697Snon		if ((regv & mask) == 0)
124679697Snon			return 1;
124779697Snon		SCSI_LOW_DELAY(NSP_DELAY_INTERVAL);
124867468Snon	}
124967468Snon
125079697Snon	printf("%s: %s nsp_negate_signal timeout\n", slp->sl_xname, s);
125179697Snon	return -1;
125267468Snon}
125367468Snon
125467468Snonstatic int
125579697Snonnsp_xfer(sc, buf, len, phase, clear_atn)
125667468Snon	struct nsp_softc *sc;
125767468Snon	u_int8_t *buf;
125867468Snon	int len;
125967468Snon	int phase;
126079697Snon	int clear_atn;
126167468Snon{
126267468Snon	bus_space_tag_t bst = sc->sc_iot;
126367468Snon	bus_space_handle_t bsh = sc->sc_ioh;
126479697Snon	int ptr, rv;
126567468Snon
126667468Snon	for (ptr = 0; len > 0; len --, ptr ++)
126767468Snon	{
126867468Snon		rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ);
126967468Snon		if (rv <= 0)
127067468Snon			goto out;
127167468Snon
127279697Snon		if (len == 1 && clear_atn != 0)
127367468Snon		{
127467468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
127567468Snon				       SCBUSCR_ADIR | SCBUSCR_ACKEN);
127679697Snon			SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow);
127767468Snon		}
127867468Snon
127967468Snon		if (phase & SCBUSMON_IO)
128067468Snon		{
128167468Snon			buf[ptr] = nsp_cr_read_1(bst, bsh, NSPR_DATAACK);
128267468Snon		}
128367468Snon		else
128467468Snon		{
128567468Snon			nsp_cr_write_1(bst, bsh, NSPR_DATAACK, buf[ptr]);
128667468Snon		}
128767468Snon		nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>");
128867468Snon	}
128967468Snon
129067468Snonout:
129167468Snon	return len;
129267468Snon}
129367468Snon
129467468Snon/**************************************************************
129567468Snon * disconnect & reselect (HW low)
129667468Snon **************************************************************/
129767468Snonstatic int
129867468Snonnsp_reselected(sc)
129967468Snon	struct nsp_softc *sc;
130067468Snon{
130167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
130267468Snon	bus_space_tag_t bst = sc->sc_iot;
130367468Snon	bus_space_handle_t bsh = sc->sc_ioh;
130467468Snon	struct targ_info *ti;
130567468Snon	u_int sid;
130667468Snon	u_int8_t cr;
130767468Snon
130867468Snon	sid = (u_int) nsp_cr_read_1(bst, bsh, NSPR_RESELR);
130967468Snon	sid &= ~sc->sc_idbit;
131067468Snon	sid = ffs(sid) - 1;
131167468Snon	if ((ti = scsi_low_reselected(slp, sid)) == NULL)
131267468Snon		return EJUSTRETURN;
131367468Snon
131467468Snon	nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>");
131567468Snon
131679697Snon	cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR);
131779697Snon	cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN);
131867468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
131979697Snon	cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN;
132079697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
132167468Snon
132267468Snon#ifdef	NSP_STATICS
132379697Snon	nsp_statics.reselect ++;
132467468Snon#endif	/* NSP_STATCIS */
132567468Snon	return EJUSTRETURN;
132667468Snon}
132767468Snon
132879697Snonstatic int
132967468Snonnsp_disconnected(sc, ti)
133067468Snon	struct nsp_softc *sc;
133167468Snon	struct targ_info *ti;
133267468Snon{
133367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
133479697Snon	bus_space_tag_t bst = sc->sc_iot;
133579697Snon	bus_space_handle_t bsh = sc->sc_ioh;
133667468Snon
133779697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
133879697Snon			PTCLRR_REQ | PTCLRR_HOST);
133979697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
134079697Snon	{
134179697Snon		sc->sc_icr &= ~SCIENR_FIFO;
134279697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
134379697Snon	}
134479697Snon	sc->sc_cnt = 0;
134579697Snon	sc->sc_dataout_timeout = 0;
134667468Snon#ifdef	NSP_STATICS
134779697Snon	nsp_statics.disconnect ++;
134867468Snon#endif	/* NSP_STATICS */
134967468Snon	scsi_low_disconnected(slp, ti);
135067468Snon	return 1;
135167468Snon}
135267468Snon
135367468Snon/**************************************************************
135467468Snon * SEQUENCER
135567468Snon **************************************************************/
135692739Salfredstatic void nsp_error(struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t);
135767468Snon
135867468Snonstatic void
135979697Snonnsp_error(sc, s, isrc, ph, irqphs)
136067468Snon	struct nsp_softc *sc;
136167468Snon	u_char *s;
136267468Snon	u_int8_t isrc, ph, irqphs;
136367468Snon{
136467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
136567468Snon
136667468Snon	printf("%s: %s\n", slp->sl_xname, s);
136767468Snon	printf("%s: isrc 0x%x scmon 0x%x irqphs 0x%x\n",
136867468Snon	       slp->sl_xname, (u_int) isrc, (u_int) ph, (u_int) irqphs);
136967468Snon}
137067468Snon
137167468Snonstatic int
137279697Snonnsp_target_nexus_establish(sc)
137367468Snon	struct nsp_softc *sc;
137467468Snon{
137579697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
137667468Snon	bus_space_tag_t bst = sc->sc_iot;
137767468Snon	bus_space_handle_t bsh = sc->sc_ioh;
137879697Snon	struct targ_info *ti = slp->sl_Tnexus;
137973025Snon	struct nsp_targ_info *nti = (void *) ti;
138067468Snon
138167468Snon	/* setup synch transfer registers */
138273025Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr);
138373025Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
138467468Snon
138579697Snon	/* setup pdma fifo (minimum) */
138679697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0);
138779697Snon	return 0;
138879697Snon}
138979697Snon
139079697Snonstatic int
139179697Snonnsp_lun_nexus_establish(sc)
139279697Snon	struct nsp_softc *sc;
139379697Snon{
139479697Snon
139579697Snon	return 0;
139679697Snon}
139779697Snon
139879697Snonstatic int
139979697Snonnsp_ccb_nexus_establish(sc)
140079697Snon	struct nsp_softc *sc;
140179697Snon{
140279697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
140379697Snon	struct slccb *cb = slp->sl_Qnexus;
140479697Snon
140579697Snon	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
140679697Snon
140767468Snon	/* setup pdma fifo */
140879697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON,
140979697Snon		       slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen);
141067468Snon
141179697Snon	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
141279697Snon	{
141379697Snon		if (sc->sc_suspendio > 0 &&
141479697Snon		    (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0)
141579697Snon		{
141679697Snon			sc->sc_icr |= SCIENR_FIFO;
141779697Snon			nsp_cr_write_1(sc->sc_iot, sc->sc_ioh,
141879697Snon				       NSPR_SCIENR, sc->sc_icr);
141979697Snon		}
142079697Snon	}
142179697Snon	else
142279697Snon	{
142379697Snon		if (sc->sc_suspendio > 0 &&
142479697Snon		    (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0)
142579697Snon		{
142679697Snon			sc->sc_icr |= SCIENR_FIFO;
142779697Snon			nsp_cr_write_1(sc->sc_iot, sc->sc_ioh,
142879697Snon				       NSPR_SCIENR, sc->sc_icr);
142979697Snon		}
143079697Snon	}
143167468Snon	return 0;
143267468Snon}
143367468Snon
143479697Snonstatic int
143579697Snonnsp_phase_match(sc, phase, stat)
143679697Snon	struct nsp_softc *sc;
143779697Snon	u_int8_t phase;
143879697Snon	u_int8_t stat;
143979697Snon{
144079697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
144179697Snon
144279697Snon	if ((stat & SCBUSMON_PHMASK) != phase)
144379697Snon	{
144479697Snon		printf("%s: phase mismatch 0x%x != 0x%x\n",
144579697Snon			slp->sl_xname, (u_int) phase, (u_int) stat);
144679697Snon		return EINVAL;
144779697Snon	}
144879697Snon
144979697Snon	if ((stat & SCBUSMON_REQ) == 0)
145079697Snon		return EINVAL;
145179697Snon
145279697Snon	return 0;
145379697Snon}
145479697Snon
145567468Snonint
145667468Snonnspintr(arg)
145767468Snon	void *arg;
145867468Snon{
145967468Snon	struct nsp_softc *sc = arg;
146067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
146167468Snon	bus_space_tag_t bst = sc->sc_iot;
146267468Snon	bus_space_handle_t bsh = sc->sc_ioh;
146367468Snon	struct targ_info *ti;
146467468Snon	struct physio_proc *pp;
146567468Snon	struct buf *bp;
146679697Snon	u_int derror, flags;
146767468Snon	int len, rv;
146867468Snon	u_int8_t isrc, ph, irqphs, cr, regv;
146967468Snon
147067468Snon	/*******************************************
147167468Snon	 * interrupt check
147267468Snon	 *******************************************/
147367468Snon	if (slp->sl_flags & HW_INACTIVE)
147467468Snon		return 0;
147567468Snon
147667468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_IRQDIS);
147767468Snon	isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
147879697Snon	if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0)
147967468Snon	{
148067468Snon		bus_space_write_1(bst, bsh, nsp_irqcr, 0);
148167468Snon		return 0;
148267468Snon	}
148367468Snon
148467468Snon	/* XXX: IMPORTANT
148567468Snon 	 * Do not read an irqphs register if no scsi phase interrupt.
148667468Snon	 * Unless, you should lose a scsi phase interrupt.
148767468Snon	 */
148867468Snon	ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
148967468Snon	if ((isrc & IRQSR_SCSI) != 0)
149067468Snon	{
149167468Snon		irqphs = nsp_cr_read_1(bst, bsh, NSPR_IRQPHS);
149267468Snon	}
149367468Snon	else
149467468Snon		irqphs = 0;
149567468Snon
149667468Snon	/*
149767468Snon 	 * timer interrupt handler (scsi vs timer interrupts)
149867468Snon	 */
149967468Snon	if (sc->sc_timer != 0)
150067468Snon	{
150167468Snon		nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
150267468Snon		nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
150367468Snon		sc->sc_timer = 0;
150467468Snon	}
150567468Snon
150679697Snon	/* check a timer interrupt */
150779697Snon	regv = 0;
150879697Snon	if ((isrc & IRQSR_TIMER) != 0)
150967468Snon	{
151079697Snon		if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0)
151179697Snon		{
151279697Snon			bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL);
151379697Snon			return 1;
151479697Snon		}
151579697Snon		regv |= IRQCR_TIMERCL;
151667468Snon	}
151767468Snon
151879697Snon	/* check a fifo interrupt */
151979697Snon	if ((isrc & IRQSR_FIFO) != 0)
152079697Snon	{
152179697Snon		regv |= IRQCR_FIFOCL;
152279697Snon	}
152367468Snon
152479697Snon	/* OK. enable all interrupts */
152579697Snon	bus_space_write_1(bst, bsh, nsp_irqcr, regv);
152679697Snon
152767468Snon	/*******************************************
152867468Snon	 * debug section
152967468Snon	 *******************************************/
153067468Snon#ifdef	NSP_DEBUG
153167468Snon	if (nsp_debug)
153267468Snon	{
153379697Snon		nsp_error(sc, "current status", isrc, ph, irqphs);
153467468Snon		scsi_low_print(slp, NULL);
153579697Snon#ifdef	DDB
153667468Snon		if (nsp_debug > 1)
153779697Snon			SCSI_LOW_DEBUGGER("nsp");
153879697Snon#endif	/* DDB */
153967468Snon	}
154067468Snon#endif	/* NSP_DEBUG */
154167468Snon
154267468Snon	/*******************************************
154367468Snon	 * Parse hardware SCSI irq reasons register
154467468Snon	 *******************************************/
154567468Snon	if ((isrc & IRQSR_SCSI) != 0)
154667468Snon	{
154767468Snon 		if ((irqphs & IRQPHS_RST) != 0)
154867468Snon		{
154967468Snon			scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
155067468Snon					 "bus reset (power off?)");
155167468Snon			return 1;
155267468Snon		}
155367468Snon
155467468Snon		if ((irqphs & IRQPHS_RSEL) != 0)
155567468Snon		{
155667468Snon			bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_RESCL);
155767468Snon			if (nsp_reselected(sc) == EJUSTRETURN)
155867468Snon				return 1;
155967468Snon		}
156067468Snon
156167468Snon		if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0)
156267468Snon			return 1;
156367468Snon	}
156467468Snon
156567468Snon	/*******************************************
156667468Snon	 * nexus check
156767468Snon	 *******************************************/
156879697Snon	if ((ti = slp->sl_Tnexus) == NULL)
156967468Snon	{
157067468Snon		/* unknown scsi phase changes */
157179697Snon		nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs);
157267468Snon		return 0;
157367468Snon	}
157467468Snon
157567468Snon	/*******************************************
157667468Snon	 * aribitration & selection
157767468Snon	 *******************************************/
157867468Snon	switch (ti->ti_phase)
157967468Snon	{
158067468Snon	case PH_SELSTART:
158167468Snon		if ((ph & SCBUSMON_BSY) == 0)
158267468Snon		{
158367468Snon			if (sc->sc_seltout >= NSP_SELTIMEOUT)
158467468Snon			{
158567468Snon				sc->sc_seltout = 0;
158667468Snon				nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0);
158767468Snon				return nsp_disconnected(sc, ti);
158867468Snon			}
158967468Snon			sc->sc_seltout ++;
159079697Snon			nsp_start_timer(sc, NSP_TIMER_1MS);
159167468Snon			return 1;
159267468Snon		}
159367468Snon
159467468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
159579697Snon		nsphw_selection_done_and_expect_msgout(sc);
159667468Snon		return 1;
159767468Snon
159879697Snon	case PH_SELECTED:
159979697Snon		if ((isrc & IRQSR_SCSI) == 0)
160079697Snon			return 1;
160179697Snon
160279697Snon		nsp_target_nexus_establish(sc);
160379697Snon		break;
160479697Snon
160567468Snon	case PH_RESEL:
160679697Snon		if ((isrc & IRQSR_SCSI) == 0)
160779697Snon			return 1;
160879697Snon
160979697Snon		nsp_target_nexus_establish(sc);
161067468Snon		if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN)
161167468Snon		{
161279697Snon			printf("%s: unexpected phase after reselect\n",
161379697Snon			       slp->sl_xname);
161479697Snon			slp->sl_error |= FATALIO;
161567468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
161667468Snon			return 1;
161767468Snon		}
161879697Snon		break;
161967468Snon
162079697Snon	case PH_DATA:
162179697Snon		if ((isrc & IRQSR_SCSI) != 0)
162279697Snon			break;
162379697Snon		if ((isrc & IRQSR_FIFO) != 0)
162479697Snon		{
162579697Snon			if (NSP_IS_PHASE_DATA(ph) == 0)
162679697Snon				return 1;
162779697Snon			irqphs = (ph & IRQPHS_PHMASK);
162879697Snon			break;
162979697Snon		}
163079697Snon		return 1;
163179697Snon
163267468Snon	default:
163379697Snon		if ((isrc & IRQSR_SCSI) == 0)
163467468Snon			return 1;
163567468Snon		break;
163667468Snon	}
163767468Snon
163867468Snon	/*******************************************
163979697Snon	 * data phase control
164067468Snon	 *******************************************/
164167468Snon	if (slp->sl_flags & HW_PDMASTART)
164279697Snon	{
164379697Snon		if ((isrc & IRQSR_SCSI) != 0 &&
164479697Snon		     NSP_IS_IRQPHS_DATA(irqphs) == 0)
164579697Snon		{
164679697Snon			if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
164779697Snon				nsp_pio_read(sc, 0);
164879697Snon			nsp_pdma_end(sc, ti);
164979697Snon		}
165079697Snon	}
165167468Snon
165279697Snon	/*******************************************
165379697Snon	 * scsi seq
165479697Snon	 *******************************************/
165567468Snon	if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0)
165667468Snon		return nsp_disconnected(sc, ti);
165767468Snon
165867468Snon	/* check unexpected bus free state */
165967468Snon	if (ph == 0)
166067468Snon	{
166179697Snon		nsp_error(sc, "unexpected bus free", isrc, ph, irqphs);
166267468Snon		return nsp_disconnected(sc, ti);
166367468Snon	}
166467468Snon
166567468Snon	/* check normal scsi phase */
166679697Snon	switch (irqphs & IRQPHS_PHMASK)
166767468Snon	{
166879697Snon	case IRQPHS_CMD:
166979697Snon		if (nsp_phase_match(sc, PHASE_CMD, ph) != 0)
167067468Snon			return 1;
167167468Snon
167267468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
167367468Snon		if (scsi_low_cmd(slp, ti) != 0)
167479697Snon		{
167579697Snon			scsi_low_attention(slp);
167679697Snon		}
167767468Snon
167867468Snon		nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR);
167967468Snon		for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++)
168067468Snon			nsp_cr_write_1(bst, bsh, NSPR_CMDDR,
168167468Snon				       slp->sl_scp.scp_cmd[len]);
168267468Snon
168367468Snon		nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC);
168467468Snon		break;
168567468Snon
168679697Snon	case IRQPHS_DATAOUT:
168767468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
168867468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
168979697Snon		{
169079697Snon			scsi_low_attention(slp);
169179697Snon		}
169267468Snon
169367468Snon		pp = physio_proc_enter(bp);
169479697Snon		nsp_pio_write(sc, sc->sc_suspendio);
169567468Snon		physio_proc_leave(pp);
169667468Snon		break;
169767468Snon
169879697Snon	case IRQPHS_DATAIN:
169967468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
170067468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
170179697Snon		{
170279697Snon			scsi_low_attention(slp);
170379697Snon		}
170467468Snon
170567468Snon		pp = physio_proc_enter(bp);
170679697Snon		nsp_pio_read(sc, sc->sc_suspendio);
170767468Snon		physio_proc_leave(pp);
170867468Snon		break;
170967468Snon
171079697Snon	case IRQPHS_STATUS:
171179697Snon		if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0)
171267468Snon			return 1;
171367468Snon
171467468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
171579697Snon		regv = nsp_cr_read_1(bst, bsh, NSPR_DATA);
171679697Snon		if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
171779697Snon		{
171879697Snon			nsp_cr_write_1(bst, bsh, NSPR_PARITYR,
171979697Snon				       PARITYR_ENABLE | PARITYR_CLEAR);
172079697Snon			derror = SCSI_LOW_DATA_PE;
172179697Snon		}
172279697Snon		else
172379697Snon			derror = 0;
172479697Snon
172579697Snon		/* assert ACK */
172679697Snon		cr = SCBUSCR_ACK | nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR);
172779697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
172879697Snon
172979697Snon		if (scsi_low_statusin(slp, ti, derror | regv) != 0)
173079697Snon		{
173179697Snon			scsi_low_attention(slp);
173279697Snon		}
173379697Snon
173479697Snon		/* check REQ nagated */
173579697Snon		nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>");
173679697Snon
173779697Snon		/* deassert ACK */
173879697Snon		cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
173979697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
174067468Snon		break;
174167468Snon
174279697Snon	case IRQPHS_MSGOUT:
174379697Snon		if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0)
174479697Snon			return 1;
174567468Snon
174679697Snon#ifdef	NSP_MSGOUT_SERIALIZE
174767468Snon		/*
174867468Snon		 * XXX: NSP QUIRK
174967468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
175067468Snon		 * therefore we should poll the scsi phase here to catch
175167468Snon		 * the next "msg out" if exists (no scsi phase changes).
175267468Snon		 */
175367468Snon		rv = len = 16;
175467468Snon		do {
175567468Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
175679697Snon			flags = (ti->ti_ophase != ti->ti_phase) ?
175779697Snon					SCSI_LOW_MSGOUT_INIT : 0;
175879697Snon			len = scsi_low_msgout(slp, ti, flags);
175967468Snon
176079697Snon			if (len > 1 && slp->sl_atten == 0)
176167468Snon			{
176279697Snon				scsi_low_attention(slp);
176379697Snon			}
176479697Snon
176579697Snon			if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
176679697Snon			             slp->sl_clear_atten) != 0)
176779697Snon			{
176879697Snon				slp->sl_error |= FATALIO;
176979697Snon				nsp_error(sc, "MSGOUT: xfer short",
177067468Snon						    isrc, ph, irqphs);
177167468Snon			}
177267468Snon
177367468Snon			/* catch a next signal */
177467468Snon			rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ);
177567468Snon		}
177667468Snon		while (rv > 0 && len -- > 0);
177779697Snon
177879697Snon#else	/* !NSP_MSGOUT_SERIALIZE */
177979697Snon		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
178079697Snon		flags = SCSI_LOW_MSGOUT_UNIFY;
178179697Snon		if (ti->ti_ophase != ti->ti_phase)
178279697Snon			flags |= SCSI_LOW_MSGOUT_INIT;
178379697Snon		len = scsi_low_msgout(slp, ti, flags);
178479697Snon
178579697Snon		if (len > 1 && slp->sl_atten == 0)
178679697Snon		{
178779697Snon			scsi_low_attention(slp);
178879697Snon		}
178979697Snon
179079697Snon		if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
179179697Snon			     slp->sl_clear_atten) != 0)
179279697Snon		{
179379697Snon			nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs);
179479697Snon		}
179579697Snon
179679697Snon#endif	/* !NSP_MSGOUT_SERIALIZE */
179767468Snon		break;
179867468Snon
179979697Snon	case IRQPHS_MSGIN:
180079697Snon		if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0)
180179697Snon			return 1;
180267468Snon
180367468Snon		/*
180467468Snon		 * XXX: NSP QUIRK
180567468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
180667468Snon		 * therefore we should poll the scsi phase here to catch
180767468Snon		 * the next "msg in" if exists (no scsi phase changes).
180867468Snon		 */
180967468Snon		rv = len = 16;
181067468Snon		do {
181179697Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
181279697Snon
181367468Snon			/* read a data */
181467468Snon			regv = nsp_cr_read_1(bst, bsh, NSPR_DATA);
181579697Snon			if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
181679697Snon			{
181779697Snon				nsp_cr_write_1(bst, bsh,
181879697Snon					       NSPR_PARITYR,
181979697Snon					       PARITYR_ENABLE | PARITYR_CLEAR);
182079697Snon				derror = SCSI_LOW_DATA_PE;
182179697Snon			}
182279697Snon			else
182379697Snon			{
182479697Snon				derror = 0;
182579697Snon			}
182667468Snon
182767468Snon			/* assert ack */
182879697Snon			cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) | SCBUSCR_ACK;
182967468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
183079697Snon
183179697Snon			if (scsi_low_msgin(slp, ti, regv | derror) == 0)
183279697Snon			{
183379697Snon				if (scsi_low_is_msgout_continue(ti, 0) != 0)
183479697Snon				{
183579697Snon					scsi_low_attention(slp);
183679697Snon				}
183779697Snon			}
183879697Snon
183979697Snon			/* check REQ nagated */
184067468Snon			nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>");
184167468Snon
184267468Snon			/* deassert ack */
184379697Snon			cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
184467468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
184567468Snon
184667468Snon			/* catch a next signal */
184767468Snon			rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ);
184867468Snon		}
184967468Snon		while (rv > 0 && len -- > 0);
185067468Snon		break;
185167468Snon
185267468Snon	default:
185379697Snon		slp->sl_error |= FATALIO;
185479697Snon		nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs);
185567468Snon		break;
185667468Snon	}
185767468Snon
185867468Snon	return 1;
185967468Snon
186079697Snon#if	0
186167468Snontimerout:
186279697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
186367468Snon	return 0;
186479697Snon#endif
186567468Snon}
186679697Snon
186779697Snonstatic int
186879697Snonnsp_timeout(sc)
186979697Snon	struct nsp_softc *sc;
187079697Snon{
187179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
187279697Snon	bus_space_tag_t iot = sc->sc_iot;
187379697Snon	bus_space_handle_t ioh = sc->sc_ioh;
187479697Snon	int tout;
187579697Snon	u_int8_t ph, regv;
187679697Snon
187779697Snon	if (slp->sl_Tnexus == NULL)
187879697Snon		return 0;
187979697Snon
188079697Snon	ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
188179697Snon	switch (ph & SCBUSMON_PHMASK)
188279697Snon	{
188379697Snon	case PHASE_DATAOUT:
188479697Snon		if (sc->sc_dataout_timeout == 0)
188579697Snon			break;
188679697Snon
188779697Snon		/* check a fifo empty */
188879697Snon		regv = bus_space_read_1(iot, ioh, nsp_fifosr);
188979697Snon		if ((regv & FIFOSR_FULLEMP) == 0)
189079697Snon			break;
189179697Snon		bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL);
189279697Snon
189379697Snon		/* check still requested */
189479697Snon		ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
189579697Snon		if ((ph & SCBUSMON_REQ) == 0)
189679697Snon			break;
189779697Snon		/* check timeout */
189879697Snon		if ((-- sc->sc_dataout_timeout) > 0)
189979697Snon			break;
190079697Snon
190179697Snon	        slp->sl_error |= PDMAERR;
190279697Snon		if ((slp->sl_flags & HW_WRITE_PADDING) == 0)
190379697Snon		{
190479697Snon			printf("%s: write padding required\n", slp->sl_xname);
190579697Snon			break;
190679697Snon		}
190779697Snon
190879697Snon		tout = NSP_DELAY_MAX;
190979697Snon		while (tout -- > 0)
191079697Snon		{
191179697Snon			ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
191279697Snon			if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT)
191379697Snon				break;
191479697Snon			regv = bus_space_read_1(iot, ioh, nsp_fifosr);
191579697Snon			if ((regv & FIFOSR_FULLEMP) == 0)
191679697Snon			{
191779697Snon				SCSI_LOW_DELAY(1);
191879697Snon				continue;
191979697Snon			}
192079697Snon
192179697Snon			bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL);
192279697Snon			nsp_data_padding(sc, SCSI_LOW_WRITE, 32);
192379697Snon		}
192479697Snon		ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
192579697Snon		if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT)
192679697Snon			sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
192779697Snon		break;
192879697Snon
192979697Snon	default:
193079697Snon		break;
193179697Snon	}
193279697Snon	return 0;
193379697Snon}
1934