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>
5367468Snon
5467468Snon#include <machine/cpu.h>
5567468Snon#include <machine/bus.h>
5667468Snon
5767468Snon#include <cam/scsi/scsi_low.h>
5867468Snon#include <dev/nsp/nspreg.h>
5967468Snon#include <dev/nsp/nspvar.h>
6067468Snon
6167468Snon/***************************************************
6267468Snon * USER SETTINGS
6367468Snon ***************************************************/
6467468Snon/* DEVICE CONFIGURATION FLAGS (MINOR)
6567468Snon *
66250460Seadler * 0x01   DISCONNECT OFF
6767468Snon * 0x02   PARITY LINE OFF
6867468Snon * 0x04   IDENTIFY MSG OFF ( = single lun)
6967468Snon * 0x08   SYNC TRANSFER OFF
7067468Snon */
7167468Snon
7267468Snon/***************************************************
7367468Snon * PARAMS
7467468Snon ***************************************************/
7567468Snon#define	NSP_NTARGETS	8
7667468Snon#define	NSP_NLUNS	8
7767468Snon
7879697Snon#define	NSP_MAX_DATA_SIZE	(64 * 1024)
7979697Snon#define	NSP_SELTIMEOUT		(200)
8079697Snon#define	NSP_DELAY_MAX		(2 * 1000 * 1000)
8179697Snon#define	NSP_DELAY_INTERVAL	(1)
8279697Snon#define	NSP_TIMER_1MS		(1000 / 51)
8367468Snon
8467468Snon/***************************************************
8567468Snon * DEBUG
8667468Snon ***************************************************/
8767468Snon#ifdef	NSP_DEBUG
8867468Snonint nsp_debug;
8967468Snon#endif	/* NSP_DEBUG */
9067468Snon
9167468Snon#ifdef	NSP_STATICS
9267468Snonstruct nsp_statics {
9379697Snon	int arbit_conflict_1;
9479697Snon	int arbit_conflict_2;
9579697Snon	int device_data_write;
9679697Snon	int device_busy;
9767468Snon	int disconnect;
9867468Snon	int reselect;
9967468Snon	int data_phase_bypass;
10079697Snon} nsp_statics;
10167468Snon#endif	/* NSP_STATICS */
10267468Snon
10367468Snon/***************************************************
10479697Snon * IO control
10567468Snon ***************************************************/
10679697Snon#define	NSP_READ_SUSPEND_IO		0x0001
10779697Snon#define	NSP_WRITE_SUSPEND_IO		0x0002
10879697Snon#define	NSP_USE_MEMIO			0x0004
10979697Snon#define	NSP_READ_FIFO_INTERRUPTS	0x0010
11079697Snon#define	NSP_WRITE_FIFO_INTERRUPTS	0x0020
11179697Snon#define	NSP_WAIT_FOR_SELECT		0x0100
11279697Snon
11379697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS;
11479697Snonint nsp_read_suspend_bytes = DEV_BSIZE;
11579697Snonint nsp_write_suspend_bytes = DEV_BSIZE;
11679697Snonint nsp_read_interrupt_bytes = 4096;
11779697Snonint nsp_write_interrupt_bytes = 4096;
11879697Snon
11979697Snon/***************************************************
12079697Snon * DEVICE STRUCTURE
12179697Snon ***************************************************/
12267468Snonextern struct cfdriver nsp_cd;
12367468Snon
12467468Snon/**************************************************************
12567468Snon * DECLARE
12667468Snon **************************************************************/
12779697Snon#define	NSP_FIFO_ON	1
12879697Snon#define	NSP_FIFO_OFF	0
12992739Salfredstatic void nsp_pio_read(struct nsp_softc *, int);
13092739Salfredstatic void nsp_pio_write(struct nsp_softc *, int);
13192739Salfredstatic int nsp_xfer(struct nsp_softc *, u_int8_t *, int, int, int);
13292739Salfredstatic int nsp_msg(struct nsp_softc *, struct targ_info *, u_int);
13392739Salfredstatic int nsp_reselected(struct nsp_softc *);
13492739Salfredstatic int nsp_disconnected(struct nsp_softc *, struct targ_info *);
13592739Salfredstatic void nsp_pdma_end(struct nsp_softc *, struct targ_info *);
13692739Salfredstatic void nsphw_init(struct nsp_softc *);
13792739Salfredstatic int nsp_target_nexus_establish(struct nsp_softc *);
13892739Salfredstatic int nsp_lun_nexus_establish(struct nsp_softc *);
13992739Salfredstatic int nsp_ccb_nexus_establish(struct nsp_softc *);
14092739Salfredstatic int nsp_world_start(struct nsp_softc *, int);
14192739Salfredstatic int nsphw_start_selection(struct nsp_softc *sc, struct slccb *);
14292739Salfredstatic void nsphw_bus_reset(struct nsp_softc *);
14392739Salfredstatic void nsphw_attention(struct nsp_softc *);
14492739Salfredstatic u_int nsp_fifo_count(struct nsp_softc *);
14592739Salfredstatic u_int nsp_request_count(struct nsp_softc *);
14692739Salfredstatic int nsp_negate_signal(struct nsp_softc *, u_int8_t, u_char *);
14792739Salfredstatic int nsp_expect_signal(struct nsp_softc *, u_int8_t, u_int8_t);
14892739Salfredstatic void nsp_start_timer(struct nsp_softc *, int);
14992739Salfredstatic void nsp_setup_fifo(struct nsp_softc *, int, int, int);
15092739Salfredstatic int nsp_targ_init(struct nsp_softc *, struct targ_info *, int);
15192739Salfredstatic void nsphw_selection_done_and_expect_msgout(struct nsp_softc *);
15292739Salfredstatic void nsp_data_padding(struct nsp_softc *, int, u_int);
15392739Salfredstatic int nsp_timeout(struct nsp_softc *);
15492739Salfredstatic int nsp_read_fifo(struct nsp_softc *, int);
15592739Salfredstatic int nsp_write_fifo(struct nsp_softc *, int);
15692739Salfredstatic int nsp_phase_match(struct nsp_softc *, u_int8_t, u_int8_t);
15792739Salfredstatic int nsp_wait_interrupt(struct nsp_softc *);
15867468Snon
15967468Snonstruct scsi_low_funcs nspfuncs = {
16067468Snon	SC_LOW_INIT_T nsp_world_start,
16167468Snon	SC_LOW_BUSRST_T nsphw_bus_reset,
16273025Snon	SC_LOW_TARG_INIT_T nsp_targ_init,
16379697Snon	SC_LOW_LUN_INIT_T NULL,
16467468Snon
16567468Snon	SC_LOW_SELECT_T nsphw_start_selection,
16679697Snon	SC_LOW_NEXUS_T nsp_lun_nexus_establish,
16779697Snon	SC_LOW_NEXUS_T nsp_ccb_nexus_establish,
16867468Snon
16967468Snon	SC_LOW_ATTEN_T nsphw_attention,
17067468Snon	SC_LOW_MSG_T nsp_msg,
17167468Snon
17279697Snon	SC_LOW_TIMEOUT_T nsp_timeout,
17367468Snon	SC_LOW_POLL_T nspintr,
17467468Snon
17567468Snon	NULL,
17667468Snon};
17767468Snon
17867468Snon/****************************************************
17967468Snon * hwfuncs
18067468Snon ****************************************************/
18192739Salfredstatic __inline u_int8_t nsp_cr_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs);
18292739Salfredstatic __inline void nsp_cr_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs, u_int8_t va);
18367468Snon
18467468Snonstatic __inline u_int8_t
18567468Snonnsp_cr_read_1(bst, bsh, ofs)
18667468Snon	bus_space_tag_t bst;
18767468Snon	bus_space_handle_t bsh;
18867468Snon	bus_addr_t ofs;
18967468Snon{
19067468Snon
19167468Snon	bus_space_write_1(bst, bsh, nsp_idxr, ofs);
19267468Snon	return bus_space_read_1(bst, bsh, nsp_datar);
19367468Snon}
19467468Snon
19567468Snonstatic __inline void
196189004Srdivackynsp_cr_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs,
197189004Srdivacky    u_int8_t va)
19867468Snon{
19967468Snon
20067468Snon	bus_space_write_1(bst, bsh, nsp_idxr, ofs);
20167468Snon	bus_space_write_1(bst, bsh, nsp_datar, va);
20267468Snon}
20367468Snon
20467468Snonstatic int
205189004Srdivackynsp_expect_signal(struct nsp_softc *sc, u_int8_t curphase, u_int8_t mask)
20667468Snon{
20767468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
20867468Snon	bus_space_tag_t bst = sc->sc_iot;
20967468Snon	bus_space_handle_t bsh = sc->sc_ioh;
21079697Snon	int wc;
21173025Snon	u_int8_t ph, isrc;
21267468Snon
21379697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
21467468Snon	{
21567468Snon		ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
21679697Snon		if (ph == (u_int8_t) -1)
21779697Snon			return -1;
21879697Snon
21967468Snon		isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
22079697Snon		if (isrc & IRQSR_SCSI)
22179697Snon			return 0;
22267468Snon
22379697Snon		if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase)
22479697Snon			return 1;
22579697Snon
226240172Sjhb		DELAY(NSP_DELAY_INTERVAL);
22767468Snon	}
22867468Snon
229240325Sjhb	device_printf(slp->sl_dev, "nsp_expect_signal timeout\n");
23079697Snon	return -1;
23167468Snon}
23267468Snon
23367468Snonstatic void
23467468Snonnsphw_init(sc)
23567468Snon	struct nsp_softc *sc;
23667468Snon{
23767468Snon	bus_space_tag_t bst = sc->sc_iot;
23867468Snon	bus_space_handle_t bsh = sc->sc_ioh;
23967468Snon
24067468Snon	/* block all interrupts */
24167468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK);
24267468Snon
24367468Snon	/* setup SCSI interface */
24467468Snon	bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_IFSEL);
24567468Snon
24667468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, 0);
24767468Snon
24867468Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8);
24967468Snon	nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_iclkdiv);
25067468Snon
25167468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
25279697Snon	nsp_cr_write_1(bst, bsh, NSPR_PARITYR, sc->sc_parr);
25367468Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR,
25467468Snon		       PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS);
25567468Snon
25667468Snon	/* setup fifo asic */
25767468Snon	bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_REGSEL);
25867468Snon	nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, 0);
25967468Snon	if ((nsp_cr_read_1(bst, bsh, NSPR_OCR) & OCR_TERMPWRS) == 0)
26067468Snon		nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, TERMPWRC_POWON);
26167468Snon
26267468Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8);
26367468Snon	nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_clkdiv);
26467468Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
26567468Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
26667468Snon
26767468Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, 0);
26867468Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, 0);
26967468Snon
27067468Snon	/* enable interrupts and ack them */
27179697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
27267468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK);
27367468Snon
27479697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
27567468Snon}
27667468Snon
27767468Snon/****************************************************
27867468Snon * scsi low interface
27967468Snon ****************************************************/
28067468Snonstatic void
28167468Snonnsphw_attention(sc)
28267468Snon	struct nsp_softc *sc;
28367468Snon{
28467468Snon	bus_space_tag_t bst = sc->sc_iot;
28567468Snon	bus_space_handle_t bsh = sc->sc_ioh;
28667468Snon	u_int8_t cr;
28767468Snon
28867468Snon	cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR)/*  & ~SCBUSCR_ACK */;
28967468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ATN);
290240172Sjhb	DELAY(10);
29167468Snon}
29267468Snon
29367468Snonstatic void
29467468Snonnsphw_bus_reset(sc)
29567468Snon	struct nsp_softc *sc;
29667468Snon{
29767468Snon	bus_space_tag_t bst = sc->sc_iot;
29867468Snon	bus_space_handle_t bsh = sc->sc_ioh;
29967468Snon	int i;
30067468Snon
30167468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK);
30267468Snon
30367468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_RST);
304240172Sjhb	DELAY(100 * 1000);	/* 100ms */
30567468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0);
30667468Snon	for (i = 0; i < 5; i ++)
30767468Snon		(void) nsp_cr_read_1(bst, bsh, NSPR_IRQPHS);
30867468Snon
30967468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK);
31067468Snon}
31167468Snon
31279697Snonstatic void
31379697Snonnsphw_selection_done_and_expect_msgout(sc)
31471468Sjhb	struct nsp_softc *sc;
31571468Sjhb{
31679697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
31771468Sjhb	bus_space_tag_t bst = sc->sc_iot;
31871468Sjhb	bus_space_handle_t bsh = sc->sc_ioh;
31971468Sjhb
32079697Snon	/* clear ack counter */
32179697Snon	sc->sc_cnt = 0;
32279697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
32379697Snon			PTCLRR_REQ | PTCLRR_HOST);
32479697Snon
32579697Snon	/* deassert sel and assert atten */
32679697Snon	sc->sc_seltout = 0;
32779697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc);
328240172Sjhb	DELAY(1);
32979697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
33079697Snon			sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN);
33179697Snon	SCSI_LOW_ASSERT_ATN(slp);
33271468Sjhb}
33371468Sjhb
33467468Snonstatic int
33567468Snonnsphw_start_selection(sc, cb)
33667468Snon	struct nsp_softc *sc;
33767468Snon	struct slccb *cb;
33867468Snon{
33967468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
34067468Snon	bus_space_tag_t bst = sc->sc_iot;
34167468Snon	bus_space_handle_t bsh = sc->sc_ioh;
34267468Snon	struct targ_info *ti = cb->ti;
34367468Snon	register u_int8_t arbs, ph;
34479697Snon	int s, wc;
34567468Snon
34679697Snon	wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
34779697Snon	sc->sc_dataout_timeout = 0;
34879697Snon
34967468Snon	/* check bus free */
35079697Snon	s = splhigh();
35179697Snon	ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
35279697Snon	if (ph != SCBUSMON_FREE)
35367468Snon	{
35467468Snon		splx(s);
35579697Snon#ifdef	NSP_STATICS
35679697Snon		nsp_statics.arbit_conflict_1 ++;
35779697Snon#endif	/* NSP_STATICS */
35879697Snon		return SCSI_LOW_START_FAIL;
35967468Snon	}
36067468Snon
36167468Snon	/* start arbitration */
36279697Snon	nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_EXEC);
36379697Snon	splx(s);
36479697Snon
36567468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART);
36667468Snon	do
36767468Snon	{
36867468Snon		/* XXX: what a stupid chip! */
36967468Snon		arbs = nsp_cr_read_1(bst, bsh, NSPR_ARBITS);
370240172Sjhb		DELAY(1);
37167468Snon	}
37273025Snon	while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0);
37367468Snon
37467468Snon	if ((arbs & ARBITS_WIN) == 0)
37567468Snon	{
37667468Snon		nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR);
37779697Snon#ifdef	NSP_STATICS
37879697Snon		nsp_statics.arbit_conflict_2 ++;
37979697Snon#endif	/* NSP_STATICS */
38067468Snon		return SCSI_LOW_START_FAIL;
38167468Snon	}
38267468Snon
38367468Snon	/* assert select line */
38467468Snon	SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
38579697Snon	scsi_low_arbit_win(slp);
38679697Snon
38779697Snon	s = splhigh();
388240172Sjhb	DELAY(3);
38967468Snon	nsp_cr_write_1(bst, bsh, NSPR_DATA,
39067468Snon		       sc->sc_idbit | (1 << ti->ti_id));
39167468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
39267468Snon			SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc);
393240172Sjhb	DELAY(3);
39467468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL |
39567468Snon			SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc);
39667468Snon	nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR);
397240172Sjhb	DELAY(3);
39867468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
39967468Snon		       SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc);
400240172Sjhb	DELAY(1);
40167468Snon
40279697Snon	if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0)
40379697Snon	{
40479697Snon#define	NSP_FIRST_SEL_WAIT	300
40579697Snon#define	NSP_SEL_CHECK_INTERVAL	10
40679697Snon
40779697Snon		/* wait for a selection response */
40879697Snon		for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL;
40979697Snon		     wc ++)
41079697Snon		{
41179697Snon			ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
41279697Snon			if ((ph & SCBUSMON_BSY) == 0)
41379697Snon			{
414240172Sjhb				DELAY(NSP_SEL_CHECK_INTERVAL);
41579697Snon				continue;
41679697Snon			}
41779697Snon
418240172Sjhb			DELAY(1);
41979697Snon			ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
42079697Snon			if ((ph & SCBUSMON_BSY) != 0)
42179697Snon			{
42279697Snon				nsphw_selection_done_and_expect_msgout(sc);
42379697Snon				splx(s);
42479697Snon
42579697Snon				SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
42679697Snon				return SCSI_LOW_START_OK;
42779697Snon			}
42879697Snon		}
42979697Snon	}
43079697Snon	splx(s);
43179697Snon
43279697Snon	/* check a selection timeout */
43379697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
43467468Snon	sc->sc_seltout = 1;
43567468Snon	return SCSI_LOW_START_OK;
43667468Snon}
43767468Snon
43867468Snonstatic int
43967468Snonnsp_world_start(sc, fdone)
44067468Snon	struct nsp_softc *sc;
44167468Snon	int fdone;
44267468Snon{
44367468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
44467468Snon
44567468Snon	sc->sc_cnt = 0;
44667468Snon	sc->sc_seltout = 0;
44779697Snon
44867468Snon	if ((slp->sl_cfgflags & CFG_NOATTEN) == 0)
44967468Snon		sc->sc_busc = SCBUSCR_ATN;
45067468Snon	else
45167468Snon		sc->sc_busc = 0;
45279697Snon
45379697Snon	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
45479697Snon		sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR;
45579697Snon	else
45679697Snon		sc->sc_parr = 0;
45779697Snon
45867468Snon	sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST);
45967468Snon
46067468Snon	nsphw_init(sc);
46167468Snon	scsi_low_bus_reset(slp);
46267468Snon
46367468Snon	return 0;
46467468Snon}
46567468Snon
46667468Snonstruct ncp_synch_data {
46767468Snon	u_int min_period;
46867468Snon	u_int max_period;
46967468Snon	u_int chip_period;
47067468Snon	u_int ack_width;
47167468Snon};
47267468Snon
47367468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = {
47467468Snon	{0x0c,0x0c,0x1,0},	/* 20MB  50ns*/
47567468Snon	{0x19,0x19,0x3,1}, 	/* 10MB  100ns*/
47667468Snon	{0x1a,0x25,0x5,2},	/* 7.5MB 150ns*/
47767468Snon	{0x26,0x32,0x7,3},	/* 5MB   200ns*/
47867468Snon	{0x0, 0, 0, 0}
47967468Snon};
48067468Snon
48167468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = {
48267468Snon	{0x19,0x19,0x1,0}, 	/* 10MB  100ns*/
48367468Snon	{0x1a,0x25,0x2,0},	/* 7.5MB 150ns*/
48467468Snon	{0x26,0x32,0x3,1},	/* 5MB   200ns*/
48567468Snon	{0x0, 0, 0, 0}
48667468Snon};
48767468Snon
48867468Snonstatic int
48967468Snonnsp_msg(sc, ti, msg)
49067468Snon	struct nsp_softc *sc;
49167468Snon	struct targ_info *ti;
49267468Snon	u_int msg;
49367468Snon{
49479697Snon	bus_space_tag_t bst = sc->sc_iot;
49579697Snon	bus_space_handle_t bsh = sc->sc_ioh;
49667468Snon	struct ncp_synch_data *sdp;
49773025Snon	struct nsp_targ_info *nti = (void *) ti;
49867468Snon	u_int period, offset;
49979697Snon	int i, error;
50067468Snon
50179697Snon	if ((msg & SCSI_LOW_MSG_WIDE) != 0)
50279697Snon	{
50379697Snon		if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
50479697Snon		{
50579697Snon			ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
50679697Snon			return EINVAL;
50779697Snon		}
50879697Snon		return 0;
50979697Snon	}
51079697Snon
51167468Snon	if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
51267468Snon		return 0;
51367468Snon
51473025Snon	period = ti->ti_maxsynch.period;
51573025Snon	offset = ti->ti_maxsynch.offset;
51667468Snon	if (sc->sc_iclkdiv == CLKDIVR_20M)
51767468Snon		sdp = &ncp_sync_data_20M[0];
51867468Snon	else
51967468Snon		sdp = &ncp_sync_data_40M[0];
52067468Snon
52167468Snon	for (i = 0; sdp->max_period != 0; i ++, sdp ++)
52267468Snon	{
52367468Snon		if (period >= sdp->min_period && period <= sdp->max_period)
52467468Snon			break;
52567468Snon	}
52667468Snon
52767468Snon	if (period != 0 && sdp->max_period == 0)
52867468Snon	{
52967468Snon		/*
53067468Snon		 * NO proper period/offset found,
53167468Snon		 * Retry neg with the target.
53267468Snon		 */
53373025Snon		ti->ti_maxsynch.period = 0;
53473025Snon		ti->ti_maxsynch.offset = 0;
53573025Snon		nti->nti_reg_syncr = 0;
53673025Snon		nti->nti_reg_ackwidth = 0;
53779697Snon		error = EINVAL;
53867468Snon	}
53979697Snon	else
54079697Snon	{
54179697Snon		nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) |
54279697Snon				      (offset & SYNCR_OFFM);
54379697Snon		nti->nti_reg_ackwidth = sdp->ack_width;
54479697Snon		error = 0;
54579697Snon	}
54667468Snon
54779697Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr);
54879697Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
54979697Snon	return error;
55067468Snon}
55167468Snon
55267468Snonstatic int
55379697Snonnsp_targ_init(sc, ti, action)
55467468Snon	struct nsp_softc *sc;
55567468Snon	struct targ_info *ti;
55679697Snon	int action;
55767468Snon{
55873025Snon	struct nsp_targ_info *nti = (void *) ti;
55967468Snon
56079697Snon	if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
56179697Snon	{
56279697Snon		ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
56379697Snon		ti->ti_maxsynch.period = 100 / 4;
56479697Snon		ti->ti_maxsynch.offset = 15;
56579697Snon		nti->nti_reg_syncr = 0;
56679697Snon		nti->nti_reg_ackwidth = 0;
56779697Snon	}
56867468Snon	return 0;
56967468Snon}
57067468Snon
57179697Snonstatic void
57279697Snonnsp_start_timer(sc, time)
57379697Snon	struct nsp_softc *sc;
57479697Snon	int time;
57579697Snon{
57679697Snon	bus_space_tag_t bst = sc->sc_iot;
57779697Snon	bus_space_handle_t bsh = sc->sc_ioh;
57879697Snon
57979697Snon	sc->sc_timer = time;
58079697Snon	nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time);
58179697Snon}
58279697Snon
58367468Snon/**************************************************************
58467468Snon * General probe attach
58567468Snon **************************************************************/
58667468Snonint
58767468Snonnspprobesubr(iot, ioh, dvcfg)
58867468Snon	bus_space_tag_t iot;
58967468Snon	bus_space_handle_t ioh;
59067468Snon	u_int dvcfg;
59167468Snon{
59267468Snon	u_int8_t regv;
59367468Snon
59467468Snon	regv = bus_space_read_1(iot, ioh, nsp_fifosr);
59567468Snon	if (regv < 0x11 || regv >= 0x20)
59667468Snon		return 0;
59767468Snon	return 1;
59867468Snon}
59967468Snon
60067468Snonvoid
60167468Snonnspattachsubr(sc)
60267468Snon	struct nsp_softc *sc;
60367468Snon{
60467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
60567468Snon
60667468Snon	printf("\n");
60767468Snon
60867468Snon	sc->sc_idbit = (1 << slp->sl_hostid);
60979697Snon	slp->sl_flags |= HW_READ_PADDING;
61067468Snon	slp->sl_funcs = &nspfuncs;
61179697Snon	sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
61267468Snon
61379697Snon	(void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS,
61479697Snon			       sizeof(struct nsp_targ_info), 0);
61567468Snon}
61667468Snon
61767468Snon/**************************************************************
61867468Snon * PDMA functions
61967468Snon **************************************************************/
62067468Snonstatic u_int
62167468Snonnsp_fifo_count(sc)
62267468Snon	struct nsp_softc *sc;
62367468Snon{
62467468Snon	bus_space_tag_t bst = sc->sc_iot;
62567468Snon	bus_space_handle_t bsh = sc->sc_ioh;
62667468Snon	u_int count;
62767468Snon
62879697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT);
62967468Snon	count = bus_space_read_1(bst, bsh, nsp_datar);
63067468Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8);
63167468Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16);
63267468Snon	return count;
63367468Snon}
63467468Snon
63579697Snonstatic u_int
63679697Snonnsp_request_count(sc)
63779697Snon	struct nsp_softc *sc;
63879697Snon{
63979697Snon	bus_space_tag_t bst = sc->sc_iot;
64079697Snon	bus_space_handle_t bsh = sc->sc_ioh;
64179697Snon	u_int count;
64279697Snon
64379697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT);
64479697Snon	count = bus_space_read_1(bst, bsh, nsp_datar);
64579697Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8);
64679697Snon	count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16);
64779697Snon	return count;
64879697Snon}
64979697Snon
65067468Snonstatic void
65179697Snonnsp_setup_fifo(sc, on, direction, datalen)
65267468Snon	struct nsp_softc *sc;
65367468Snon	int on;
65479697Snon	int direction;
65579697Snon	int datalen;
65667468Snon{
65767468Snon	u_int8_t xfermode;
65867468Snon
65979697Snon	sc->sc_suspendio = 0;
66079697Snon	if (on == NSP_FIFO_OFF)
66179697Snon	{
66279697Snon		xfermode = XFERMR_IO8;
66379697Snon		goto out;
66479697Snon	}
66567468Snon
66679697Snon	/* check if suspend io OK ? */
66779697Snon	if (datalen > 0)
66867468Snon	{
66979697Snon		if (direction == SCSI_LOW_READ)
67079697Snon		{
67179697Snon			if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 &&
67279697Snon			    (datalen % nsp_read_suspend_bytes) == 0)
67379697Snon				sc->sc_suspendio = nsp_read_suspend_bytes;
67479697Snon		}
67579697Snon		else
67679697Snon		{
67779697Snon			if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 &&
67879697Snon			    (datalen % nsp_write_suspend_bytes) == 0)
67979697Snon				sc->sc_suspendio = nsp_write_suspend_bytes;
68079697Snon		}
68167468Snon	}
68279697Snon
68379697Snon	/* determine a transfer type */
68479697Snon	if (datalen < DEV_BSIZE || (datalen & 3) != 0)
68579697Snon	{
686102291Sarchie		if (sc->sc_memh != 0 &&
68779697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
68879697Snon			xfermode = XFERMR_XEN | XFERMR_MEM8;
68979697Snon		else
69079697Snon			xfermode = XFERMR_XEN | XFERMR_IO8;
69179697Snon	}
69267468Snon	else
69367468Snon	{
694102291Sarchie		if (sc->sc_memh != 0 &&
69579697Snon		    (nsp_io_control & NSP_USE_MEMIO) != 0)
69679697Snon			xfermode = XFERMR_XEN | XFERMR_MEM32;
69767468Snon		else
69879697Snon			xfermode = XFERMR_XEN | XFERMR_IO32;
69979697Snon
70079697Snon		if (sc->sc_suspendio > 0)
70179697Snon			xfermode |= XFERMR_FIFOEN;
70267468Snon	}
70367468Snon
70479697Snonout:
70567468Snon	sc->sc_xfermr = xfermode;
70679697Snon	nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_XFERMR, sc->sc_xfermr);
70767468Snon}
70867468Snon
70979697Snonstatic void
71067468Snonnsp_pdma_end(sc, ti)
71167468Snon	struct nsp_softc *sc;
71267468Snon	struct targ_info *ti;
71367468Snon{
71467468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
71579697Snon	struct slccb *cb = slp->sl_Qnexus;
71667468Snon	u_int len = 0, cnt;
71767468Snon
71879697Snon	sc->sc_dataout_timeout = 0;
71967468Snon	slp->sl_flags &= ~HW_PDMASTART;
72079697Snon	nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0);
72179697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
72279697Snon	{
72379697Snon		sc->sc_icr &= ~SCIENR_FIFO;
72479697Snon		nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_SCIENR, sc->sc_icr);
72579697Snon	}
72667468Snon
72779697Snon	if (cb == NULL)
72879697Snon	{
72979697Snon		slp->sl_error |= PDMAERR;
73079697Snon		return;
73179697Snon	}
73279697Snon
73367468Snon	if (ti->ti_phase == PH_DATA)
73467468Snon	{
73567468Snon		cnt = nsp_fifo_count(sc);
73667468Snon		if (slp->sl_scp.scp_direction  == SCSI_LOW_WRITE)
73767468Snon		{
73867468Snon			len = sc->sc_cnt - cnt;
73979697Snon			if (sc->sc_cnt >= cnt &&
74079697Snon			    slp->sl_scp.scp_datalen + len <=
74167468Snon			    cb->ccb_scp.scp_datalen)
74267468Snon			{
74367468Snon				slp->sl_scp.scp_data -= len;
74467468Snon				slp->sl_scp.scp_datalen += len;
74567468Snon			}
74667468Snon			else
74767468Snon			{
74867468Snon				slp->sl_error |= PDMAERR;
749240325Sjhb				device_printf(slp->sl_dev,
750240325Sjhb					"len %x >= datalen %x\n",
75167468Snon					len, slp->sl_scp.scp_datalen);
75267468Snon			}
75367468Snon		}
75467468Snon		else if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
75567468Snon		{
75679697Snon			if (sc->sc_cnt != cnt ||
75779697Snon			    sc->sc_cnt > cb->ccb_scp.scp_datalen)
75867468Snon			{
75967468Snon				slp->sl_error |= PDMAERR;
760240325Sjhb				device_printf(slp->sl_dev,
761240325Sjhb					"data read count error %x != %x (%x)\n",
762240325Sjhb					sc->sc_cnt, cnt,
76379697Snon					cb->ccb_scp.scp_datalen);
76467468Snon			}
76567468Snon		}
76667468Snon		sc->sc_cnt = cnt;
76779697Snon		scsi_low_data_finish(slp);
76867468Snon	}
76967468Snon	else
77067468Snon	{
77167468Snon
772240325Sjhb		device_printf(slp->sl_dev, "data phase miss\n");
77367468Snon		slp->sl_error |= PDMAERR;
77467468Snon	}
77567468Snon}
77667468Snon
77767468Snon#define	RFIFO_CRIT	64
77879697Snon#define	WFIFO_CRIT	32
77967468Snon
78067468Snonstatic void
78179697Snonnsp_data_padding(sc, direction, count)
78267468Snon	struct nsp_softc *sc;
78379697Snon	int direction;
78479697Snon	u_int count;
78567468Snon{
78679697Snon	bus_space_tag_t bst = sc->sc_iot;
78779697Snon	bus_space_handle_t bsh = sc->sc_ioh;
78879697Snon
78979697Snon	if (count > NSP_MAX_DATA_SIZE)
79079697Snon		count = NSP_MAX_DATA_SIZE;
79179697Snon
79279697Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8);
79379697Snon	if (direction == SCSI_LOW_READ)
79479697Snon	{
79579697Snon		while (count -- > 0)
79679697Snon			(void) bus_space_read_1(bst, bsh, nsp_fifodr);
79779697Snon	}
79879697Snon	else
79979697Snon	{
80079697Snon		while (count -- > 0)
80179697Snon			(void) bus_space_write_1(bst, bsh, nsp_fifodr, 0);
80279697Snon	}
80379697Snon	nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr);
80479697Snon}
80579697Snon
80679697Snonstatic int
80779697Snonnsp_read_fifo(sc, suspendio)
80879697Snon	struct nsp_softc *sc;
80979697Snon	int suspendio;
81079697Snon{
81167468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
81267468Snon	bus_space_tag_t bst = sc->sc_iot;
81367468Snon	bus_space_handle_t bsh = sc->sc_ioh;
81479697Snon	u_int res;
81567468Snon
81679697Snon	res = nsp_fifo_count(sc);
81779697Snon	if (res == sc->sc_cnt)
81879697Snon		return 0;
81967468Snon
82079697Snon#ifdef	NSP_DEBUG
82179697Snon	if (res < sc->sc_cnt || res == (u_int) -1)
82267468Snon	{
823240325Sjhb		device_printf(slp->sl_dev,
824240325Sjhb		    "strange fifo ack count 0x%x < 0x%x\n", res, sc->sc_cnt);
82579697Snon		return 0;
82679697Snon	}
82779697Snon#endif	/* NSP_DEBUG */
82879697Snon
82979697Snon	res = res - sc->sc_cnt;
83079697Snon	if (res > slp->sl_scp.scp_datalen)
83179697Snon	{
83279697Snon		if ((slp->sl_error & PDMAERR) == 0)
83379697Snon		{
834240325Sjhb			device_printf(slp->sl_dev, "data overrun 0x%x > 0x%x\n",
835240325Sjhb			    res, slp->sl_scp.scp_datalen);
83679697Snon		}
83779697Snon
83879697Snon		slp->sl_error |= PDMAERR;
83979697Snon		slp->sl_scp.scp_datalen = 0;
84079697Snon
84179697Snon		if ((slp->sl_flags & HW_READ_PADDING) == 0)
84279697Snon		{
843240325Sjhb			device_printf(slp->sl_dev, "read padding required\n");
84479697Snon			return 0;
84579697Snon		}
84679697Snon
84779697Snon		nsp_data_padding(sc, SCSI_LOW_READ, res);
84879697Snon		sc->sc_cnt += res;
84979697Snon		return 1;	/* padding start */
85079697Snon	}
85179697Snon
85279697Snon	if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio)
85379697Snon		res = suspendio;
85479697Snon
85579697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
85679697Snon	{
85779697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
85879697Snon		{
85979697Snon			res &= ~3;
86079697Snon			bus_space_read_region_4(sc->sc_memt, sc->sc_memh, 0,
86179697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
86279697Snon		}
86379697Snon		else
86479697Snon		{
86579697Snon			bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 0,
86679697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
86779697Snon		}
86879697Snon	}
86979697Snon	else
87079697Snon	{
87179697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
87279697Snon		{
87379697Snon			res &= ~3;
87479697Snon			bus_space_read_multi_4(bst, bsh, nsp_fifodr,
87579697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
87679697Snon		}
87779697Snon		else
87879697Snon		{
87979697Snon			bus_space_read_multi_1(bst, bsh, nsp_fifodr,
88079697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
88179697Snon		}
88279697Snon	}
88379697Snon
88479697Snon	if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
88579697Snon	{
88679697Snon		nsp_cr_write_1(bst, bsh, NSPR_PARITYR,
88779697Snon			       PARITYR_ENABLE | PARITYR_CLEAR);
88879697Snon		scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1);
88979697Snon	}
89079697Snon
89179697Snon	slp->sl_scp.scp_data += res;
89279697Snon	slp->sl_scp.scp_datalen -= res;
89379697Snon	sc->sc_cnt += res;
89479697Snon	return 0;
89579697Snon}
89679697Snon
89779697Snonstatic int
89879697Snonnsp_write_fifo(sc, suspendio)
89979697Snon	struct nsp_softc *sc;
90079697Snon	int suspendio;
90179697Snon{
90279697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
90379697Snon	bus_space_tag_t bst = sc->sc_iot;
90479697Snon	bus_space_handle_t bsh = sc->sc_ioh;
90579697Snon	u_int res;
90679697Snon	register u_int8_t stat;
90779697Snon
90879697Snon	if (suspendio > 0)
90979697Snon	{
91079697Snon#ifdef	NSP_DEBUG
91179697Snon		if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0)
91279697Snon		{
913240325Sjhb			device_printf(slp->sl_dev,
914240325Sjhb			    "strange write length 0x%x\n",
915240325Sjhb			    slp->sl_scp.scp_datalen);
91679697Snon		}
91779697Snon#endif	/* NSP_DEBUG */
91879697Snon		res = slp->sl_scp.scp_datalen % suspendio;
91967468Snon		if (res == 0)
92067468Snon		{
92179697Snon			res = suspendio;
92267468Snon		}
92379697Snon	}
92479697Snon	else
92579697Snon	{
92679697Snon		res = WFIFO_CRIT;
92779697Snon	}
92867468Snon
92979697Snon	if (res > slp->sl_scp.scp_datalen)
93079697Snon		res = slp->sl_scp.scp_datalen;
93167468Snon
93279697Snon	/* XXX: reconfirm! */
93379697Snon	stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
93479697Snon	if (stat != PHASE_DATAOUT)
93579697Snon		return 0;
93667468Snon
93779697Snon	if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0)
93879697Snon	{
93979697Snon		if ((sc->sc_xfermr & XFERMR_MEM32) != 0)
94079697Snon		{
94179697Snon			bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 0,
94279697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
94379697Snon		}
94467468Snon		else
94579697Snon		{
94679697Snon			bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 0,
94779697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
94879697Snon		}
94979697Snon	}
95079697Snon	else
95179697Snon	{
95279697Snon		if ((sc->sc_xfermr & XFERMR_IO32) != 0)
95379697Snon		{
95479697Snon			bus_space_write_multi_4(bst, bsh, nsp_fifodr,
95579697Snon				(u_int32_t *) slp->sl_scp.scp_data, res >> 2);
95679697Snon		}
95779697Snon		else
95879697Snon		{
95979697Snon			bus_space_write_multi_1(bst, bsh, nsp_fifodr,
96079697Snon				(u_int8_t *) slp->sl_scp.scp_data, res);
96179697Snon		}
96279697Snon	}
96367468Snon
96479697Snon	slp->sl_scp.scp_datalen -= res;
96579697Snon	slp->sl_scp.scp_data += res;
96679697Snon	sc->sc_cnt += res;
96779697Snon	return 0;
96879697Snon}
96979697Snon
97079697Snonstatic int
97179697Snonnsp_wait_interrupt(sc)
97279697Snon	struct nsp_softc *sc;
97379697Snon{
97479697Snon	bus_space_tag_t bst = sc->sc_iot;
97579697Snon	bus_space_handle_t bsh = sc->sc_ioh;
97679697Snon	int tout;
97779697Snon	register u_int8_t isrc;
97879697Snon
97979697Snon	for (tout = 0; tout < DEV_BSIZE / 10; tout ++)
98079697Snon	{
98179697Snon		isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
98279697Snon		if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0)
98367468Snon		{
98479697Snon			if ((isrc & IRQSR_FIFO) != 0)
98579697Snon			{
98679697Snon				bus_space_write_1(bst, bsh,
98779697Snon					nsp_irqcr, IRQCR_FIFOCL);
98879697Snon			}
98979697Snon			return 1;
99067468Snon		}
991240172Sjhb		DELAY(1);
99279697Snon	}
99379697Snon	return 0;
99479697Snon}
99579697Snon
99679697Snonstatic void
99779697Snonnsp_pio_read(sc, suspendio)
99879697Snon	struct nsp_softc *sc;
99979697Snon	int suspendio;
100079697Snon{
100179697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
100279697Snon	bus_space_tag_t bst = sc->sc_iot;
100379697Snon	bus_space_handle_t bsh = sc->sc_ioh;
100479697Snon	int tout, padding, datalen;
100579697Snon	register u_int8_t stat, fstat;
100679697Snon
100779697Snon	padding = 0;
100879697Snon	tout = sc->sc_tmaxcnt;
100979697Snon	slp->sl_flags |= HW_PDMASTART;
101079697Snon	datalen = slp->sl_scp.scp_datalen;
101179697Snon
101279697SnonReadLoop:
101379697Snon	while (1)
101479697Snon	{
101579697Snon		stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
101679697Snon		if (stat == (u_int8_t) -1)
101779697Snon			return;
101879697Snon
101979697Snon		/* out of data phase */
102079697Snon		if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN)
102179697Snon		{
102279697Snon			nsp_read_fifo(sc, 0);
102379697Snon			return;
102479697Snon		}
102579697Snon
102679697Snon		/* data phase */
102779697Snon		fstat = bus_space_read_1(bst, bsh, nsp_fifosr);
102879697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
102979697Snon		{
103079697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
103179697Snon			{
103279697Snon				bus_space_write_1(bst, bsh, nsp_irqcr,
103379697Snon						  IRQCR_FIFOCL);
103479697Snon			}
103579697Snon
103679697Snon			if (suspendio > 0)
103779697Snon			{
103879697Snon				padding |= nsp_read_fifo(sc, suspendio);
103979697Snon			}
104079697Snon			else
104179697Snon			{
104279697Snon				padding |= nsp_read_fifo(sc, 0);
104379697Snon			}
104479697Snon
104579697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
104679697Snon				break;
104779697Snon		}
104867468Snon		else
104967468Snon		{
105079697Snon			if (padding == 0 && slp->sl_scp.scp_datalen <= 0)
105179697Snon				return;
105279697Snon
105379697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
105479697Snon				break;
105579697Snon
1056240172Sjhb			DELAY(1);
105767468Snon		}
105867468Snon
105979697Snon		if ((-- tout) <= 0)
106079697Snon		{
1061240325Sjhb			device_printf(slp->sl_dev, "nsp_pio_read: timeout\n");
106279697Snon			return;
106379697Snon		}
106467468Snon	}
106567468Snon
106679697Snon
106779697Snon	if (slp->sl_scp.scp_datalen > 0 &&
106879697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes)
106979697Snon	{
107079697Snon		if (nsp_wait_interrupt(sc) != 0)
107179697Snon			goto ReadLoop;
107279697Snon	}
107367468Snon}
107467468Snon
107567468Snonstatic void
107679697Snonnsp_pio_write(sc, suspendio)
107767468Snon	struct nsp_softc *sc;
107879697Snon	int suspendio;
107967468Snon{
108067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
108167468Snon	bus_space_tag_t bst = sc->sc_iot;
108267468Snon	bus_space_handle_t bsh = sc->sc_ioh;
108379697Snon	u_int rcount, acount;
108479697Snon	int tout, datalen;
108579697Snon	register u_int8_t stat, fstat;
108667468Snon
108779697Snon	tout = sc->sc_tmaxcnt;
108867468Snon	slp->sl_flags |= HW_PDMASTART;
108979697Snon	datalen = slp->sl_scp.scp_datalen;
109079697Snon
109179697SnonWriteLoop:
109279697Snon	while (1)
109367468Snon	{
109479697Snon		stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK;
109567468Snon		if (stat != PHASE_DATAOUT)
109679697Snon			return;
109767468Snon
109879697Snon		if (slp->sl_scp.scp_datalen <= 0)
109979697Snon		{
110079697Snon			if (sc->sc_dataout_timeout == 0)
110179697Snon				sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
110279697Snon			return;
110379697Snon		}
110467468Snon
110579697Snon		fstat = bus_space_read_1(bst, bsh, nsp_fifosr);
110679697Snon		if ((fstat & FIFOSR_FULLEMP) != 0)
110779697Snon		{
110879697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
110979697Snon			{
111079697Snon				bus_space_write_1(bst, bsh, nsp_irqcr,
111179697Snon						  IRQCR_FIFOCL);
111279697Snon			}
111367468Snon
111479697Snon			if (suspendio > 0)
111579697Snon			{
111679697Snon				/* XXX:IMPORTANT:
111779697Snon				 * To avoid timeout of pcmcia bus
111879697Snon				 * (not scsi bus!), we should check
111979697Snon				 * the scsi device sends us request
112079697Snon				 * signals, which means the scsi device
112179697Snon				 * is ready to recieve data without
112279697Snon				 * heavy delays.
112379697Snon				 */
112482784Snon				if ((slp->sl_scp.scp_datalen % suspendio) == 0)
112579697Snon				{
112682784Snon					/* Step I:
112782784Snon					 * fill the nsp fifo, and waiting for
112882784Snon					 * the fifo empty.
112982784Snon					 */
113079697Snon					nsp_write_fifo(sc, 0);
113179697Snon				}
113279697Snon				else
113379697Snon				{
113482784Snon					/* Step II:
113582784Snon					 * check the request singals.
113682784Snon					 */
113782784Snon					acount = nsp_fifo_count(sc);
113882784Snon					rcount = nsp_request_count(sc);
113982784Snon					if (rcount <= acount)
114082784Snon					{
114182784Snon						nsp_write_fifo(sc, 0);
114279697Snon#ifdef	NSP_STATICS
114382784Snon						nsp_statics.device_busy ++;
114479697Snon#endif	/* NSP_STATICS */
114582784Snon					}
114682784Snon					else
114782784Snon					{
114882784Snon						nsp_write_fifo(sc, suspendio);
114982784Snon#ifdef	NSP_STATICS
115082784Snon						nsp_statics.device_data_write ++;
115182784Snon#endif	/* NSP_STATICS */
115282784Snon					}
115379697Snon				}
115479697Snon			}
115579697Snon			else
115679697Snon			{
115779697Snon				nsp_write_fifo(sc, 0);
115879697Snon			}
115979697Snon
116079697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
116179697Snon				break;
116267468Snon		}
116367468Snon		else
116467468Snon		{
116579697Snon			if ((sc->sc_icr & SCIENR_FIFO) != 0)
116679697Snon				break;
116779697Snon
1168240172Sjhb			DELAY(1);
116967468Snon		}
117067468Snon
117179697Snon		if ((-- tout) <= 0)
117279697Snon		{
1173240325Sjhb			device_printf(slp->sl_dev, "nsp_pio_write: timeout\n");
117479697Snon			return;
117579697Snon		}
117667468Snon	}
117767468Snon
117879697Snon	if (slp->sl_scp.scp_datalen > 0 &&
117979697Snon	    slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes)
118079697Snon	{
118179697Snon		if (nsp_wait_interrupt(sc) != 0)
118279697Snon			goto WriteLoop;
118379697Snon	}
118467468Snon}
118567468Snon
118667468Snonstatic int
1187189004Srdivackynsp_negate_signal(struct nsp_softc *sc, u_int8_t mask, u_char *s)
118867468Snon{
118967468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
119067468Snon	bus_space_tag_t bst = sc->sc_iot;
119167468Snon	bus_space_handle_t bsh = sc->sc_ioh;
119279697Snon	int wc;
119367468Snon	u_int8_t regv;
119467468Snon
119579697Snon	for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++)
119667468Snon	{
119767468Snon		regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
119879697Snon		if (regv == (u_int8_t) -1)
119979697Snon			return -1;
120079697Snon		if ((regv & mask) == 0)
120179697Snon			return 1;
1202240172Sjhb		DELAY(NSP_DELAY_INTERVAL);
120367468Snon	}
120467468Snon
1205240325Sjhb	device_printf(slp->sl_dev, "%s nsp_negate_signal timeout\n", s);
120679697Snon	return -1;
120767468Snon}
120867468Snon
120967468Snonstatic int
121079697Snonnsp_xfer(sc, buf, len, phase, clear_atn)
121167468Snon	struct nsp_softc *sc;
121267468Snon	u_int8_t *buf;
121367468Snon	int len;
121467468Snon	int phase;
121579697Snon	int clear_atn;
121667468Snon{
121767468Snon	bus_space_tag_t bst = sc->sc_iot;
121867468Snon	bus_space_handle_t bsh = sc->sc_ioh;
121979697Snon	int ptr, rv;
122067468Snon
122167468Snon	for (ptr = 0; len > 0; len --, ptr ++)
122267468Snon	{
122367468Snon		rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ);
122467468Snon		if (rv <= 0)
122567468Snon			goto out;
122667468Snon
122779697Snon		if (len == 1 && clear_atn != 0)
122867468Snon		{
122967468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR,
123067468Snon				       SCBUSCR_ADIR | SCBUSCR_ACKEN);
123179697Snon			SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow);
123267468Snon		}
123367468Snon
123467468Snon		if (phase & SCBUSMON_IO)
123567468Snon		{
123667468Snon			buf[ptr] = nsp_cr_read_1(bst, bsh, NSPR_DATAACK);
123767468Snon		}
123867468Snon		else
123967468Snon		{
124067468Snon			nsp_cr_write_1(bst, bsh, NSPR_DATAACK, buf[ptr]);
124167468Snon		}
124267468Snon		nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>");
124367468Snon	}
124467468Snon
124567468Snonout:
124667468Snon	return len;
124767468Snon}
124867468Snon
124967468Snon/**************************************************************
125067468Snon * disconnect & reselect (HW low)
125167468Snon **************************************************************/
125267468Snonstatic int
125367468Snonnsp_reselected(sc)
125467468Snon	struct nsp_softc *sc;
125567468Snon{
125667468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
125767468Snon	bus_space_tag_t bst = sc->sc_iot;
125867468Snon	bus_space_handle_t bsh = sc->sc_ioh;
125967468Snon	struct targ_info *ti;
126067468Snon	u_int sid;
126167468Snon	u_int8_t cr;
126267468Snon
126367468Snon	sid = (u_int) nsp_cr_read_1(bst, bsh, NSPR_RESELR);
126467468Snon	sid &= ~sc->sc_idbit;
126567468Snon	sid = ffs(sid) - 1;
126667468Snon	if ((ti = scsi_low_reselected(slp, sid)) == NULL)
126767468Snon		return EJUSTRETURN;
126867468Snon
126967468Snon	nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>");
127067468Snon
127179697Snon	cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR);
127279697Snon	cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN);
127367468Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
127479697Snon	cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN;
127579697Snon	nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
127667468Snon
127767468Snon#ifdef	NSP_STATICS
127879697Snon	nsp_statics.reselect ++;
127967468Snon#endif	/* NSP_STATCIS */
128067468Snon	return EJUSTRETURN;
128167468Snon}
128267468Snon
128379697Snonstatic int
128467468Snonnsp_disconnected(sc, ti)
128567468Snon	struct nsp_softc *sc;
128667468Snon	struct targ_info *ti;
128767468Snon{
128867468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
128979697Snon	bus_space_tag_t bst = sc->sc_iot;
129079697Snon	bus_space_handle_t bsh = sc->sc_ioh;
129167468Snon
129279697Snon	nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK |
129379697Snon			PTCLRR_REQ | PTCLRR_HOST);
129479697Snon	if ((sc->sc_icr & SCIENR_FIFO) != 0)
129579697Snon	{
129679697Snon		sc->sc_icr &= ~SCIENR_FIFO;
129779697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr);
129879697Snon	}
129979697Snon	sc->sc_cnt = 0;
130079697Snon	sc->sc_dataout_timeout = 0;
130167468Snon#ifdef	NSP_STATICS
130279697Snon	nsp_statics.disconnect ++;
130367468Snon#endif	/* NSP_STATICS */
130467468Snon	scsi_low_disconnected(slp, ti);
130567468Snon	return 1;
130667468Snon}
130767468Snon
130867468Snon/**************************************************************
130967468Snon * SEQUENCER
131067468Snon **************************************************************/
131192739Salfredstatic void nsp_error(struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t);
131267468Snon
131367468Snonstatic void
1314189004Srdivackynsp_error(struct nsp_softc * sc, u_char *s, u_int8_t isrc, u_int8_t ph,
1315189004Srdivacky    u_int8_t irqphs)
131667468Snon{
131767468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
131867468Snon
1319240325Sjhb	device_printf(slp->sl_dev, "%s\n", s);
1320240325Sjhb	device_printf(slp->sl_dev, "isrc 0x%x scmon 0x%x irqphs 0x%x\n",
1321240325Sjhb	    (u_int) isrc, (u_int) ph, (u_int) irqphs);
132267468Snon}
132367468Snon
132467468Snonstatic int
132579697Snonnsp_target_nexus_establish(sc)
132667468Snon	struct nsp_softc *sc;
132767468Snon{
132879697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
132967468Snon	bus_space_tag_t bst = sc->sc_iot;
133067468Snon	bus_space_handle_t bsh = sc->sc_ioh;
133179697Snon	struct targ_info *ti = slp->sl_Tnexus;
133273025Snon	struct nsp_targ_info *nti = (void *) ti;
133367468Snon
133467468Snon	/* setup synch transfer registers */
133573025Snon	nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr);
133673025Snon	nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth);
133767468Snon
133879697Snon	/* setup pdma fifo (minimum) */
133979697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0);
134079697Snon	return 0;
134179697Snon}
134279697Snon
134379697Snonstatic int
134479697Snonnsp_lun_nexus_establish(sc)
134579697Snon	struct nsp_softc *sc;
134679697Snon{
134779697Snon
134879697Snon	return 0;
134979697Snon}
135079697Snon
135179697Snonstatic int
135279697Snonnsp_ccb_nexus_establish(sc)
135379697Snon	struct nsp_softc *sc;
135479697Snon{
135579697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
135679697Snon	struct slccb *cb = slp->sl_Qnexus;
135779697Snon
135879697Snon	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
135979697Snon
136067468Snon	/* setup pdma fifo */
136179697Snon	nsp_setup_fifo(sc, NSP_FIFO_ON,
136279697Snon		       slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen);
136367468Snon
136479697Snon	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
136579697Snon	{
136679697Snon		if (sc->sc_suspendio > 0 &&
136779697Snon		    (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0)
136879697Snon		{
136979697Snon			sc->sc_icr |= SCIENR_FIFO;
137079697Snon			nsp_cr_write_1(sc->sc_iot, sc->sc_ioh,
137179697Snon				       NSPR_SCIENR, sc->sc_icr);
137279697Snon		}
137379697Snon	}
137479697Snon	else
137579697Snon	{
137679697Snon		if (sc->sc_suspendio > 0 &&
137779697Snon		    (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0)
137879697Snon		{
137979697Snon			sc->sc_icr |= SCIENR_FIFO;
138079697Snon			nsp_cr_write_1(sc->sc_iot, sc->sc_ioh,
138179697Snon				       NSPR_SCIENR, sc->sc_icr);
138279697Snon		}
138379697Snon	}
138467468Snon	return 0;
138567468Snon}
138667468Snon
138779697Snonstatic int
1388189004Srdivackynsp_phase_match(struct nsp_softc *sc, u_int8_t phase, u_int8_t stat)
138979697Snon{
139079697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
139179697Snon
139279697Snon	if ((stat & SCBUSMON_PHMASK) != phase)
139379697Snon	{
1394240325Sjhb		device_printf(slp->sl_dev, "phase mismatch 0x%x != 0x%x\n",
1395240325Sjhb		    (u_int) phase, (u_int) stat);
139679697Snon		return EINVAL;
139779697Snon	}
139879697Snon
139979697Snon	if ((stat & SCBUSMON_REQ) == 0)
140079697Snon		return EINVAL;
140179697Snon
140279697Snon	return 0;
140379697Snon}
140479697Snon
140567468Snonint
140667468Snonnspintr(arg)
140767468Snon	void *arg;
140867468Snon{
140967468Snon	struct nsp_softc *sc = arg;
141067468Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
141167468Snon	bus_space_tag_t bst = sc->sc_iot;
141267468Snon	bus_space_handle_t bsh = sc->sc_ioh;
141367468Snon	struct targ_info *ti;
141467468Snon	struct buf *bp;
141579697Snon	u_int derror, flags;
141667468Snon	int len, rv;
141767468Snon	u_int8_t isrc, ph, irqphs, cr, regv;
141867468Snon
141967468Snon	/*******************************************
142067468Snon	 * interrupt check
142167468Snon	 *******************************************/
142267468Snon	if (slp->sl_flags & HW_INACTIVE)
142367468Snon		return 0;
142467468Snon
142567468Snon	bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_IRQDIS);
142667468Snon	isrc = bus_space_read_1(bst, bsh, nsp_irqsr);
142779697Snon	if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0)
142867468Snon	{
142967468Snon		bus_space_write_1(bst, bsh, nsp_irqcr, 0);
143067468Snon		return 0;
143167468Snon	}
143267468Snon
143367468Snon	/* XXX: IMPORTANT
143467468Snon 	 * Do not read an irqphs register if no scsi phase interrupt.
143567468Snon	 * Unless, you should lose a scsi phase interrupt.
143667468Snon	 */
143767468Snon	ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON);
143867468Snon	if ((isrc & IRQSR_SCSI) != 0)
143967468Snon	{
144067468Snon		irqphs = nsp_cr_read_1(bst, bsh, NSPR_IRQPHS);
144167468Snon	}
144267468Snon	else
144367468Snon		irqphs = 0;
144467468Snon
144567468Snon	/*
144667468Snon 	 * timer interrupt handler (scsi vs timer interrupts)
144767468Snon	 */
144867468Snon	if (sc->sc_timer != 0)
144967468Snon	{
145067468Snon		nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
145167468Snon		nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0);
145267468Snon		sc->sc_timer = 0;
145367468Snon	}
145467468Snon
145579697Snon	/* check a timer interrupt */
145679697Snon	regv = 0;
145779697Snon	if ((isrc & IRQSR_TIMER) != 0)
145867468Snon	{
145979697Snon		if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0)
146079697Snon		{
146179697Snon			bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL);
146279697Snon			return 1;
146379697Snon		}
146479697Snon		regv |= IRQCR_TIMERCL;
146567468Snon	}
146667468Snon
146779697Snon	/* check a fifo interrupt */
146879697Snon	if ((isrc & IRQSR_FIFO) != 0)
146979697Snon	{
147079697Snon		regv |= IRQCR_FIFOCL;
147179697Snon	}
147267468Snon
147379697Snon	/* OK. enable all interrupts */
147479697Snon	bus_space_write_1(bst, bsh, nsp_irqcr, regv);
147579697Snon
147667468Snon	/*******************************************
147767468Snon	 * debug section
147867468Snon	 *******************************************/
147967468Snon#ifdef	NSP_DEBUG
148067468Snon	if (nsp_debug)
148167468Snon	{
148279697Snon		nsp_error(sc, "current status", isrc, ph, irqphs);
148367468Snon		scsi_low_print(slp, NULL);
1484131915Smarcel#ifdef	KDB
148567468Snon		if (nsp_debug > 1)
1486240172Sjhb			kdb_enter(KDB_WHY_CAM, "nsp");
1487131915Smarcel#endif	/* KDB */
148867468Snon	}
148967468Snon#endif	/* NSP_DEBUG */
149067468Snon
149167468Snon	/*******************************************
149267468Snon	 * Parse hardware SCSI irq reasons register
149367468Snon	 *******************************************/
149467468Snon	if ((isrc & IRQSR_SCSI) != 0)
149567468Snon	{
149667468Snon 		if ((irqphs & IRQPHS_RST) != 0)
149767468Snon		{
149867468Snon			scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
149967468Snon					 "bus reset (power off?)");
150067468Snon			return 1;
150167468Snon		}
150267468Snon
150367468Snon		if ((irqphs & IRQPHS_RSEL) != 0)
150467468Snon		{
150567468Snon			bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_RESCL);
150667468Snon			if (nsp_reselected(sc) == EJUSTRETURN)
150767468Snon				return 1;
150867468Snon		}
150967468Snon
151067468Snon		if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0)
151167468Snon			return 1;
151267468Snon	}
151367468Snon
151467468Snon	/*******************************************
151567468Snon	 * nexus check
151667468Snon	 *******************************************/
151779697Snon	if ((ti = slp->sl_Tnexus) == NULL)
151867468Snon	{
151967468Snon		/* unknown scsi phase changes */
152079697Snon		nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs);
152167468Snon		return 0;
152267468Snon	}
152367468Snon
152467468Snon	/*******************************************
152567468Snon	 * aribitration & selection
152667468Snon	 *******************************************/
152767468Snon	switch (ti->ti_phase)
152867468Snon	{
152967468Snon	case PH_SELSTART:
153067468Snon		if ((ph & SCBUSMON_BSY) == 0)
153167468Snon		{
153267468Snon			if (sc->sc_seltout >= NSP_SELTIMEOUT)
153367468Snon			{
153467468Snon				sc->sc_seltout = 0;
153567468Snon				nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0);
153667468Snon				return nsp_disconnected(sc, ti);
153767468Snon			}
153867468Snon			sc->sc_seltout ++;
153979697Snon			nsp_start_timer(sc, NSP_TIMER_1MS);
154067468Snon			return 1;
154167468Snon		}
154267468Snon
154367468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
154479697Snon		nsphw_selection_done_and_expect_msgout(sc);
154567468Snon		return 1;
154667468Snon
154779697Snon	case PH_SELECTED:
154879697Snon		if ((isrc & IRQSR_SCSI) == 0)
154979697Snon			return 1;
155079697Snon
155179697Snon		nsp_target_nexus_establish(sc);
155279697Snon		break;
155379697Snon
155467468Snon	case PH_RESEL:
155579697Snon		if ((isrc & IRQSR_SCSI) == 0)
155679697Snon			return 1;
155779697Snon
155879697Snon		nsp_target_nexus_establish(sc);
155967468Snon		if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN)
156067468Snon		{
1561240325Sjhb			device_printf(slp->sl_dev,
1562240325Sjhb			    "unexpected phase after reselect\n");
156379697Snon			slp->sl_error |= FATALIO;
156467468Snon			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
156567468Snon			return 1;
156667468Snon		}
156779697Snon		break;
156867468Snon
156979697Snon	case PH_DATA:
157079697Snon		if ((isrc & IRQSR_SCSI) != 0)
157179697Snon			break;
157279697Snon		if ((isrc & IRQSR_FIFO) != 0)
157379697Snon		{
157479697Snon			if (NSP_IS_PHASE_DATA(ph) == 0)
157579697Snon				return 1;
157679697Snon			irqphs = (ph & IRQPHS_PHMASK);
157779697Snon			break;
157879697Snon		}
157979697Snon		return 1;
158079697Snon
158167468Snon	default:
158279697Snon		if ((isrc & IRQSR_SCSI) == 0)
158367468Snon			return 1;
158467468Snon		break;
158567468Snon	}
158667468Snon
158767468Snon	/*******************************************
158879697Snon	 * data phase control
158967468Snon	 *******************************************/
159067468Snon	if (slp->sl_flags & HW_PDMASTART)
159179697Snon	{
159279697Snon		if ((isrc & IRQSR_SCSI) != 0 &&
159379697Snon		     NSP_IS_IRQPHS_DATA(irqphs) == 0)
159479697Snon		{
159579697Snon			if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
159679697Snon				nsp_pio_read(sc, 0);
159779697Snon			nsp_pdma_end(sc, ti);
159879697Snon		}
159979697Snon	}
160067468Snon
160179697Snon	/*******************************************
160279697Snon	 * scsi seq
160379697Snon	 *******************************************/
160467468Snon	if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0)
160567468Snon		return nsp_disconnected(sc, ti);
160667468Snon
160767468Snon	/* check unexpected bus free state */
160867468Snon	if (ph == 0)
160967468Snon	{
161079697Snon		nsp_error(sc, "unexpected bus free", isrc, ph, irqphs);
161167468Snon		return nsp_disconnected(sc, ti);
161267468Snon	}
161367468Snon
161467468Snon	/* check normal scsi phase */
161579697Snon	switch (irqphs & IRQPHS_PHMASK)
161667468Snon	{
161779697Snon	case IRQPHS_CMD:
161879697Snon		if (nsp_phase_match(sc, PHASE_CMD, ph) != 0)
161967468Snon			return 1;
162067468Snon
162167468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
162267468Snon		if (scsi_low_cmd(slp, ti) != 0)
162379697Snon		{
162479697Snon			scsi_low_attention(slp);
162579697Snon		}
162667468Snon
162767468Snon		nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR);
162867468Snon		for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++)
162967468Snon			nsp_cr_write_1(bst, bsh, NSPR_CMDDR,
163067468Snon				       slp->sl_scp.scp_cmd[len]);
163167468Snon
163267468Snon		nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC);
163367468Snon		break;
163467468Snon
163579697Snon	case IRQPHS_DATAOUT:
163667468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
163767468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
163879697Snon		{
163979697Snon			scsi_low_attention(slp);
164079697Snon		}
164167468Snon
164279697Snon		nsp_pio_write(sc, sc->sc_suspendio);
164367468Snon		break;
164467468Snon
164579697Snon	case IRQPHS_DATAIN:
164667468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
164767468Snon		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
164879697Snon		{
164979697Snon			scsi_low_attention(slp);
165079697Snon		}
165167468Snon
165279697Snon		nsp_pio_read(sc, sc->sc_suspendio);
165367468Snon		break;
165467468Snon
165579697Snon	case IRQPHS_STATUS:
165679697Snon		if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0)
165767468Snon			return 1;
165867468Snon
165967468Snon		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
166079697Snon		regv = nsp_cr_read_1(bst, bsh, NSPR_DATA);
166179697Snon		if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
166279697Snon		{
166379697Snon			nsp_cr_write_1(bst, bsh, NSPR_PARITYR,
166479697Snon				       PARITYR_ENABLE | PARITYR_CLEAR);
166579697Snon			derror = SCSI_LOW_DATA_PE;
166679697Snon		}
166779697Snon		else
166879697Snon			derror = 0;
166979697Snon
167079697Snon		/* assert ACK */
167179697Snon		cr = SCBUSCR_ACK | nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR);
167279697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
167379697Snon
167479697Snon		if (scsi_low_statusin(slp, ti, derror | regv) != 0)
167579697Snon		{
167679697Snon			scsi_low_attention(slp);
167779697Snon		}
167879697Snon
167979697Snon		/* check REQ nagated */
168079697Snon		nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>");
168179697Snon
168279697Snon		/* deassert ACK */
168379697Snon		cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
168479697Snon		nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
168567468Snon		break;
168667468Snon
168779697Snon	case IRQPHS_MSGOUT:
168879697Snon		if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0)
168979697Snon			return 1;
169067468Snon
169179697Snon#ifdef	NSP_MSGOUT_SERIALIZE
169267468Snon		/*
169367468Snon		 * XXX: NSP QUIRK
169467468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
169567468Snon		 * therefore we should poll the scsi phase here to catch
169667468Snon		 * the next "msg out" if exists (no scsi phase changes).
169767468Snon		 */
169867468Snon		rv = len = 16;
169967468Snon		do {
170067468Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
170179697Snon			flags = (ti->ti_ophase != ti->ti_phase) ?
170279697Snon					SCSI_LOW_MSGOUT_INIT : 0;
170379697Snon			len = scsi_low_msgout(slp, ti, flags);
170467468Snon
170579697Snon			if (len > 1 && slp->sl_atten == 0)
170667468Snon			{
170779697Snon				scsi_low_attention(slp);
170879697Snon			}
170979697Snon
171079697Snon			if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
171179697Snon			             slp->sl_clear_atten) != 0)
171279697Snon			{
171379697Snon				slp->sl_error |= FATALIO;
171479697Snon				nsp_error(sc, "MSGOUT: xfer short",
171567468Snon						    isrc, ph, irqphs);
171667468Snon			}
171767468Snon
171867468Snon			/* catch a next signal */
171967468Snon			rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ);
172067468Snon		}
172167468Snon		while (rv > 0 && len -- > 0);
172279697Snon
172379697Snon#else	/* !NSP_MSGOUT_SERIALIZE */
172479697Snon		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
172579697Snon		flags = SCSI_LOW_MSGOUT_UNIFY;
172679697Snon		if (ti->ti_ophase != ti->ti_phase)
172779697Snon			flags |= SCSI_LOW_MSGOUT_INIT;
172879697Snon		len = scsi_low_msgout(slp, ti, flags);
172979697Snon
173079697Snon		if (len > 1 && slp->sl_atten == 0)
173179697Snon		{
173279697Snon			scsi_low_attention(slp);
173379697Snon		}
173479697Snon
173579697Snon		if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT,
173679697Snon			     slp->sl_clear_atten) != 0)
173779697Snon		{
173879697Snon			nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs);
173979697Snon		}
174079697Snon
174179697Snon#endif	/* !NSP_MSGOUT_SERIALIZE */
174267468Snon		break;
174367468Snon
174479697Snon	case IRQPHS_MSGIN:
174579697Snon		if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0)
174679697Snon			return 1;
174767468Snon
174867468Snon		/*
174967468Snon		 * XXX: NSP QUIRK
175067468Snon		 * NSP invoke interrupts only in the case of scsi phase changes,
175167468Snon		 * therefore we should poll the scsi phase here to catch
175267468Snon		 * the next "msg in" if exists (no scsi phase changes).
175367468Snon		 */
175467468Snon		rv = len = 16;
175567468Snon		do {
175679697Snon			SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
175779697Snon
175867468Snon			/* read a data */
175967468Snon			regv = nsp_cr_read_1(bst, bsh, NSPR_DATA);
176079697Snon			if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE)
176179697Snon			{
176279697Snon				nsp_cr_write_1(bst, bsh,
176379697Snon					       NSPR_PARITYR,
176479697Snon					       PARITYR_ENABLE | PARITYR_CLEAR);
176579697Snon				derror = SCSI_LOW_DATA_PE;
176679697Snon			}
176779697Snon			else
176879697Snon			{
176979697Snon				derror = 0;
177079697Snon			}
177167468Snon
177267468Snon			/* assert ack */
177379697Snon			cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) | SCBUSCR_ACK;
177467468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
177579697Snon
177679697Snon			if (scsi_low_msgin(slp, ti, regv | derror) == 0)
177779697Snon			{
177879697Snon				if (scsi_low_is_msgout_continue(ti, 0) != 0)
177979697Snon				{
178079697Snon					scsi_low_attention(slp);
178179697Snon				}
178279697Snon			}
178379697Snon
178479697Snon			/* check REQ nagated */
178567468Snon			nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>");
178667468Snon
178767468Snon			/* deassert ack */
178879697Snon			cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK);
178967468Snon			nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr);
179067468Snon
179167468Snon			/* catch a next signal */
179267468Snon			rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ);
179367468Snon		}
179467468Snon		while (rv > 0 && len -- > 0);
179567468Snon		break;
179667468Snon
179767468Snon	default:
179879697Snon		slp->sl_error |= FATALIO;
179979697Snon		nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs);
180067468Snon		break;
180167468Snon	}
180267468Snon
180367468Snon	return 1;
180467468Snon
180579697Snon#if	0
180667468Snontimerout:
180779697Snon	nsp_start_timer(sc, NSP_TIMER_1MS);
180867468Snon	return 0;
180979697Snon#endif
181067468Snon}
181179697Snon
181279697Snonstatic int
181379697Snonnsp_timeout(sc)
181479697Snon	struct nsp_softc *sc;
181579697Snon{
181679697Snon	struct scsi_low_softc *slp = &sc->sc_sclow;
181779697Snon	bus_space_tag_t iot = sc->sc_iot;
181879697Snon	bus_space_handle_t ioh = sc->sc_ioh;
181979697Snon	int tout;
182079697Snon	u_int8_t ph, regv;
182179697Snon
182279697Snon	if (slp->sl_Tnexus == NULL)
182379697Snon		return 0;
182479697Snon
182579697Snon	ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
182679697Snon	switch (ph & SCBUSMON_PHMASK)
182779697Snon	{
182879697Snon	case PHASE_DATAOUT:
182979697Snon		if (sc->sc_dataout_timeout == 0)
183079697Snon			break;
183179697Snon
183279697Snon		/* check a fifo empty */
183379697Snon		regv = bus_space_read_1(iot, ioh, nsp_fifosr);
183479697Snon		if ((regv & FIFOSR_FULLEMP) == 0)
183579697Snon			break;
183679697Snon		bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL);
183779697Snon
183879697Snon		/* check still requested */
183979697Snon		ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
184079697Snon		if ((ph & SCBUSMON_REQ) == 0)
184179697Snon			break;
184279697Snon		/* check timeout */
184379697Snon		if ((-- sc->sc_dataout_timeout) > 0)
184479697Snon			break;
184579697Snon
184679697Snon	        slp->sl_error |= PDMAERR;
184779697Snon		if ((slp->sl_flags & HW_WRITE_PADDING) == 0)
184879697Snon		{
1849240325Sjhb			device_printf(slp->sl_dev, "write padding required\n");
185079697Snon			break;
185179697Snon		}
185279697Snon
185379697Snon		tout = NSP_DELAY_MAX;
185479697Snon		while (tout -- > 0)
185579697Snon		{
185679697Snon			ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
185779697Snon			if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT)
185879697Snon				break;
185979697Snon			regv = bus_space_read_1(iot, ioh, nsp_fifosr);
186079697Snon			if ((regv & FIFOSR_FULLEMP) == 0)
186179697Snon			{
1862240172Sjhb				DELAY(1);
186379697Snon				continue;
186479697Snon			}
186579697Snon
186679697Snon			bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL);
186779697Snon			nsp_data_padding(sc, SCSI_LOW_WRITE, 32);
186879697Snon		}
186979697Snon		ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON);
187079697Snon		if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT)
187179697Snon			sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ;
187279697Snon		break;
187379697Snon
187479697Snon	default:
187579697Snon		break;
187679697Snon	}
187779697Snon	return 0;
187879697Snon}
1879