xref: /csrg-svn/sys/news3400/hbdev/scsi_1185.c (revision 63304)
153895Smckusick /*
2*63304Sbostic  * Copyright (c) 1992, 1993
3*63304Sbostic  *	The Regents of the University of California.  All rights reserved.
453895Smckusick  *
553895Smckusick  * This code is derived from software contributed to Berkeley by
653895Smckusick  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
753895Smckusick  *
853895Smckusick  * %sccs.include.redist.c%
953895Smckusick  *
1053895Smckusick  * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY
1153895Smckusick  *
12*63304Sbostic  *	@(#)scsi_1185.c	8.1 (Berkeley) 06/11/93
1353895Smckusick  */
1453895Smckusick 
1553895Smckusick /*
1653895Smckusick  * Copyright (c) 1989- by SONY Corporation.
1753895Smckusick  */
1853895Smckusick /*
1953895Smckusick  *	scsi_1185.c
2053895Smckusick  *
2153895Smckusick  *	CXD1185Q
2253895Smckusick  *	SCSI bus low level common routines
2353895Smckusick  *				for one cpu machine
2453895Smckusick  */
2553895Smckusick /*
2653895Smckusick  * MODIFY HISTORY:
2753895Smckusick  *
2853895Smckusick  *	DMAC_WAIT	--- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni
2953895Smckusick  *				tuzukete access suru-baai,
3053895Smckusick  *				kanarazu wait wo ireru-beshi !
3153895Smckusick  *
3253895Smckusick  */
3353895Smckusick 
3457179Sutashiro #include <sys/types.h>
3557179Sutashiro #include <machine/pte.h>
3657179Sutashiro #include <machine/cpu.h>
3753895Smckusick 
3857179Sutashiro #include <sys/param.h>
3957179Sutashiro #include <sys/systm.h>
4057179Sutashiro #include <sys/map.h>
4157179Sutashiro #include <sys/buf.h>
4257179Sutashiro #include <vm/vm.h>
4357179Sutashiro #include <sys/proc.h>
4457179Sutashiro #include <sys/user.h>
4557179Sutashiro #include <sys/conf.h>
4657179Sutashiro #include <sys/dkstat.h>
4757179Sutashiro #include <sys/kernel.h>
4853895Smckusick 
4957179Sutashiro #include <news3400/hbdev/hbvar.h>
5057179Sutashiro #include <news3400/hbdev/screg_1185.h>
5157179Sutashiro #include <news3400/hbdev/scsic.h>
5253895Smckusick 
5353895Smckusick #ifdef news3400
5457179Sutashiro # include <news3400/hbdev/dmac_0448.h>
5553895Smckusick # ifndef NDMACMAP
5653895Smckusick # define NDMACMAP	144
5753895Smckusick # endif
5853895Smckusick #endif
5953895Smckusick 
6057179Sutashiro #include <news3400/iodev/scsireg.h>
6153895Smckusick 
6253895Smckusick #ifdef mips
6353895Smckusick #define	VOLATILE	volatile
6453895Smckusick #else
6553895Smckusick #define	VOLATILE
6653895Smckusick #endif
6753895Smckusick 
6853895Smckusick #define ABORT_SYNCTR_MES_FROM_TARGET
6953895Smckusick #define SCSI_1185AQ
7053895Smckusick #define RESET_RECOVER
7153895Smckusick 
7253895Smckusick #define DMAC_MAP_INIT			/* for nws-3700 parity error */
7353895Smckusick 
7453895Smckusick #define APAD_ALWAYS_ON
7553895Smckusick 
7653895Smckusick # define	CHECK_LOOP_CNT	60
7753895Smckusick # define	RSL_LOOP_CNT	60
7853895Smckusick 
7953895Smckusick #ifndef DMAC_MAP_INIT
8053895Smckusick # define MAP_OVER_ACCESS		/* for nws-3700 parity error */
8153895Smckusick #endif
8253895Smckusick 
8353895Smckusick #undef	CHECK_MRQ
8453895Smckusick 
8553895Smckusick #ifdef NOT_SUPPORT_SYNCTR
8653895Smckusick # define	MAX_OFFSET_BYTES	0
8753895Smckusick #else
8853895Smckusick # define	MAX_OFFSET_BYTES	MAX_OFFSET
8953895Smckusick #endif
9053895Smckusick 
9153895Smckusick #define	NTARGET		8
9253895Smckusick 
9353895Smckusick #define	act_point	spoint
9453895Smckusick #define	act_trcnt	stcnt
9553895Smckusick #define	act_tag		stag
9653895Smckusick #define	act_offset	soffset
9753895Smckusick 
9853895Smckusick #define	splscsi		splsc
9953895Smckusick 
10053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
10153895Smckusick #define nops(x)		{ int i; for (i = 0; i < (x); i++) ; }
10253895Smckusick #define	vtophys(v)	MACH_UNMAPPED_TO_PHYS(v)
10353895Smckusick #define	DMAC_WAIT0	;
10453895Smckusick #else
10553895Smckusick #define	DMAC_WAIT0	DMAC_WAIT
10653895Smckusick #endif
10753895Smckusick 
10853895Smckusick int	perr_flag[NTARGET];
10953895Smckusick 
11053895Smckusick #ifndef NOT_SUPPORT_SYNCTR
11153895Smckusick VOLATILE char sync_tr[NTARGET];
11253895Smckusick #endif
11353895Smckusick 
11453895Smckusick #ifdef DMAC_MAP_INIT
11553895Smckusick int	dmac_map_init = 0;
11653895Smckusick #endif
11753895Smckusick 
11853895Smckusick #ifdef SCSI_1185AQ
11953895Smckusick int	scsi_1185AQ = 0;
12053895Smckusick #endif
12153895Smckusick 
12253895Smckusick struct sc_chan_stat chan_stat[NTARGET];	/* SCSI channel status */
12353895Smckusick int	sel_stat[NTARGET];		/* target select status */
12453895Smckusick #define	SEL_WAIT	0
12553895Smckusick #define	SEL_START	1
12653895Smckusick #define	SEL_TIMEOUT	2
12753895Smckusick #define	SEL_ARBF	3
12853895Smckusick #define	SEL_SUCCESS	4
12953895Smckusick #define	SEL_RSLD	5
13053895Smckusick #define	SEL_RSL_WAIT	6
13153895Smckusick 
13253895Smckusick /*
13353895Smckusick  *	command flag status
13453895Smckusick  */
13553895Smckusick #define	CF_SET		1
13653895Smckusick #define	CF_SEND		2
13753895Smckusick #define	CF_ENOUGH	3
13853895Smckusick #define	CF_EXEC		4
13953895Smckusick 
14053895Smckusick #define	SEL_TIMEOUT_VALUE	0x7a
14153895Smckusick 
14253895Smckusick VOLATILE int int_stat1;
14353895Smckusick VOLATILE int int_stat2;
14453895Smckusick 
14553895Smckusick VOLATILE int min_flag;
14653895Smckusick 
14753895Smckusick VOLATILE char mout_flag[NTARGET];
14853895Smckusick #define MOUT_IDENTIFY	1
14953895Smckusick #define MOUT_SYNC_TR	2
15053895Smckusick 
15153895Smckusick VOLATILE int	last_cmd;
15253895Smckusick VOLATILE char	min_cnt[NTARGET];
15353895Smckusick VOLATILE u_char	*min_point[NTARGET];
15453895Smckusick VOLATILE int	pad_cnt[NTARGET];
15553895Smckusick 
15653895Smckusick VOLATILE static u_char *act_cmd_pointer;
15753895Smckusick static VOLATILE struct sc_chan_stat *wbq_actf = 0; /* forword active pointer */
15853895Smckusick static VOLATILE struct sc_chan_stat *wbq_actl = 0; /* last active pointer */
15953895Smckusick static char ScsiSoftError[] = "SCSI soft error";
16053895Smckusick 
16153895Smckusick static int pad_start;
16253895Smckusick 
16353895Smckusick #if defined(mips) && defined(CPU_SINGLE)
16453895Smckusick #define dma_reset(x) { \
16553895Smckusick 	int s = splscsi(); \
16653895Smckusick 	dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \
16753895Smckusick 	splx(s); \
16853895Smckusick }
16953895Smckusick #endif
17053895Smckusick 
WAIT_STATR_BITCLR(bitmask)17153895Smckusick WAIT_STATR_BITCLR(bitmask)
17253895Smckusick 	register int bitmask;
17353895Smckusick {
17453895Smckusick 	register int iloop;
17553895Smckusick 	register VOLATILE int dummy;
17653895Smckusick 
17753895Smckusick 	iloop = 0;
17853895Smckusick 	do {
17953895Smckusick 		dummy = sc_statr;
18053895Smckusick 		DMAC_WAIT0;
18153895Smckusick 		if (iloop++ > CHECK_LOOP_CNT)
18253895Smckusick 			return (-1);
18353895Smckusick 	} while (dummy & bitmask);
18453895Smckusick 	return (0);
18553895Smckusick }
18653895Smckusick 
WAIT_STATR_BITSET(bitmask)18753895Smckusick WAIT_STATR_BITSET(bitmask)
18853895Smckusick 	register int bitmask;
18953895Smckusick {
19053895Smckusick 	register int iloop;
19153895Smckusick 	register VOLATILE int dummy;
19253895Smckusick 
19353895Smckusick 	iloop = 0;
19453895Smckusick 	do {
19553895Smckusick 		dummy = sc_statr;
19653895Smckusick 		DMAC_WAIT0;
19753895Smckusick 		if (iloop++ > CHECK_LOOP_CNT)
19853895Smckusick 			return (-1);
19953895Smckusick 	} while ((dummy & bitmask) == 0);
20053895Smckusick 	return (0);
20153895Smckusick }
20253895Smckusick 
SET_CMD(CMD)20353895Smckusick SET_CMD(CMD)
20453895Smckusick 	register int CMD;
20553895Smckusick {
20653895Smckusick 
20753895Smckusick 	(void) WAIT_STATR_BITCLR(R0_CIP);
20853895Smckusick 	last_cmd = (CMD);
20953895Smckusick 	sc_comr = (CMD);
21053895Smckusick 	DMAC_WAIT0;
21153895Smckusick }
21253895Smckusick 
SET_CNT(COUNT)21353895Smckusick SET_CNT(COUNT)
21453895Smckusick 	register int COUNT;
21553895Smckusick {
21653895Smckusick 
21753895Smckusick 	sc_tclow = (COUNT) & 0xff;
21853895Smckusick 	DMAC_WAIT0;
21953895Smckusick 	sc_tcmid = ((COUNT) >> 8) & 0xff;
22053895Smckusick 	DMAC_WAIT0;
22153895Smckusick 	sc_tchi = ((COUNT) >> 16) & 0xff;
22253895Smckusick 	DMAC_WAIT0;
22353895Smckusick }
22453895Smckusick 
GET_CNT()22553895Smckusick GET_CNT()
22653895Smckusick {
22753895Smckusick 	register VOLATILE int COUNT;
22853895Smckusick 
22953895Smckusick 	COUNT = sc_tclow;
23053895Smckusick 	DMAC_WAIT0;
23153895Smckusick 	COUNT += (sc_tcmid << 8) & 0xff00;
23253895Smckusick 	DMAC_WAIT0;
23353895Smckusick 	COUNT += (sc_tchi << 16) & 0xff0000;
23453895Smckusick 	DMAC_WAIT0;
23553895Smckusick 	return (COUNT);
23653895Smckusick }
23753895Smckusick 
GET_INTR(DATA1,DATA2)23853895Smckusick GET_INTR(DATA1, DATA2)
23953895Smckusick 	register VOLATILE int *DATA1;
24053895Smckusick 	register VOLATILE int *DATA2;
24153895Smckusick {
24253895Smckusick 	register VOLATILE int dummy;
24353895Smckusick 
24453895Smckusick 	(void) WAIT_STATR_BITCLR(R0_CIP);
24553895Smckusick 	while (sc_statr & R0_MIRQ) {
24653895Smckusick 		DMAC_WAIT0;
24753895Smckusick 		*DATA1 |= sc_intrq1;
24853895Smckusick 		DMAC_WAIT0;
24953895Smckusick 		*DATA2 |= sc_intrq2;
25053895Smckusick 		DMAC_WAIT0;
25153895Smckusick 	}
25253895Smckusick }
25353895Smckusick 
25453895Smckusick 
sc_send(chan,ie,sc)25553895Smckusick sc_send(chan, ie, sc)
25653895Smckusick 	register int chan;
25753895Smckusick 	register int ie;
25853895Smckusick 	register struct scsi *sc;
25953895Smckusick {
26053895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
26153895Smckusick 	register struct scsi_stat *ss;
26253895Smckusick 	register int i;
26353895Smckusick 
26453895Smckusick 	cs = &chan_stat[chan];
26553895Smckusick 	ss = &scsi_stat;
26653895Smckusick 
26753895Smckusick 	if (sc == NULL || cs->sc != NULL) {
26853895Smckusick 		printf("SCSI%d:sc_send() NULL sc or NOT NULL cs->sc\n", chan);
26953895Smckusick 		printf("ie=0x%x sc=0x%x cs->sc=0x%x\n", ie, sc, cs->sc);
27053895Smckusick 		if (sc) {
27153895Smckusick 			printf("cdb=");
27253895Smckusick 			for (i = 0; i < 6; i++)
27353895Smckusick 				printf("0x%x ", sc->sc_cdb.un_reserved[i]);
27453895Smckusick 			printf("\n");
27553895Smckusick 		}
27653895Smckusick 		panic(ScsiSoftError);
27753895Smckusick 		/*NOTREACHED*/
27853895Smckusick 	}
27953895Smckusick 
28053895Smckusick 	if ((sc->sc_cdb.un_reserved[0] == SCOP_RESET)
28153895Smckusick 			&& (sc->sc_cdb.un_reserved[1] == SCOP_RESET)) {
28253895Smckusick 		/*
28353895Smckusick 		 * SCSI bus reset command procedure
28453895Smckusick 		 *	(vender unique by Sony Corp.)
28553895Smckusick 		 */
28653895Smckusick #ifdef SCSI_1185AQ
28753895Smckusick 		if (sc_idenr & 0x08) {
28853895Smckusick 			scsi_1185AQ = 1;
28953895Smckusick 		}
29053895Smckusick #endif
29153895Smckusick 		cs->sc = sc;
29253895Smckusick 		scsi_hardreset();
29353895Smckusick 		sc->sc_istatus = INST_EP;
29453895Smckusick 		cs->sc = NULL;
29553895Smckusick 		return;
29653895Smckusick 	}
29753895Smckusick 
29853895Smckusick 	if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
29953895Smckusick 		/*
30053895Smckusick 		 * use map table
30153895Smckusick 		 */
30253895Smckusick 		sc->sc_coffset = sc->sc_map->mp_offset & PGOFSET;
30353895Smckusick 		if (sc->sc_map->mp_pages > NSCMAP) {
30453895Smckusick 			printf("SCSI%d: map table overflow\n", chan);
30553895Smckusick 			sc->sc_istatus = INST_EP|INST_LB|INST_PRE;
30653895Smckusick 			return;
30753895Smckusick 		}
30853895Smckusick 	} else {
30953895Smckusick 		/*
31053895Smckusick 		 * no use map table
31153895Smckusick 		 */
31253895Smckusick 		sc->sc_coffset = (u_int)sc->sc_cpoint & PGOFSET;
31353895Smckusick 	}
31453895Smckusick 	sc->sc_ctag = 0;
31553895Smckusick 
31653895Smckusick 	cs->sc = sc;
31753895Smckusick 	cs->comflg = OFF;
31853895Smckusick 
31953895Smckusick 	cs->intr_flg = ie;
32053895Smckusick 	cs->chan_num = chan;
32153895Smckusick 	perr_flag[chan] = 0;
32253895Smckusick 	mout_flag[chan] = 0;
32353895Smckusick 	min_cnt[chan] = 0;
32453895Smckusick 
32553895Smckusick 	sel_stat[chan] = SEL_WAIT;
32653895Smckusick 	append_wb(cs);
32753895Smckusick 	sc_start();
32853895Smckusick }
32953895Smckusick 
33053895Smckusick /*
33153895Smckusick  *	SCSI start up routine
33253895Smckusick  */
sc_start()33353895Smckusick sc_start()
33453895Smckusick {
33553895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
33653895Smckusick 	register struct scsi_stat *ss;
33753895Smckusick 	register int s;
33853895Smckusick 	register VOLATILE int chan;
33953895Smckusick 	register VOLATILE int dummy;
34053895Smckusick 
34153895Smckusick 	ss = &scsi_stat;
34253895Smckusick 
34353895Smckusick 	s = splclock();
34453895Smckusick 	chan = get_wb_chan();
34553895Smckusick 	if ((chan < 0) || (ss->ipc >= 0))
34653895Smckusick 		goto sc_start_exit;
34753895Smckusick 	if (sel_stat[chan] != SEL_WAIT) {
34853895Smckusick 		/*
34953895Smckusick 		 * already started
35053895Smckusick 		 */
35153895Smckusick 		goto sc_start_exit;
35253895Smckusick 	}
35353895Smckusick 	sel_stat[chan] = SEL_START;
35453895Smckusick 	(void) splscsi();
35553895Smckusick 
35653895Smckusick 	cs = &chan_stat[chan];
35753895Smckusick 
35853895Smckusick 	dummy = sc_cmonr;
35953895Smckusick 	DMAC_WAIT0;
36053895Smckusick 	if (dummy & (R4_MBSY|R4_MSEL)) {
36153895Smckusick 		sel_stat[chan] = SEL_WAIT;
36253895Smckusick 		goto sc_start_exit;
36353895Smckusick 	}
36453895Smckusick 
36553895Smckusick 	/*
36653895Smckusick 	 *	send SELECT with ATN command
36753895Smckusick 	 */
36853895Smckusick 	ss->dma_stat = OFF;
36953895Smckusick 	pad_start = 0;
37053895Smckusick 	dummy = sc_statr;
37153895Smckusick 	DMAC_WAIT0;
37253895Smckusick 	if (dummy & R0_CIP) {
37353895Smckusick 		sel_stat[chan] = SEL_WAIT;
37453895Smckusick 		goto sc_start_exit;
37553895Smckusick 	}
37653895Smckusick 	sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID;
37753895Smckusick 	DMAC_WAIT0;
37853895Smckusick #ifdef SCSI_1185AQ
37953895Smckusick 	if (scsi_1185AQ)
38053895Smckusick 		sc_intok1 = Ra_STO|Ra_ARBF;
38153895Smckusick 	else
38253895Smckusick 		sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
38353895Smckusick #else
38453895Smckusick 	sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
38553895Smckusick #endif
38653895Smckusick 	DMAC_WAIT0;
38753895Smckusick 	/*
38853895Smckusick 	 * BUGFIX for signal reflection on BSY
38953895Smckusick 	 *	!Rb_DCNT
39053895Smckusick 	 */
39153895Smckusick 	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
39253895Smckusick 	DMAC_WAIT0;
39353895Smckusick 
39453895Smckusick 	dummy = sc_cmonr;
39553895Smckusick 	DMAC_WAIT0;
39653895Smckusick 	if (dummy & (R4_MBSY|R4_MSEL)) {
39753895Smckusick 		sel_stat[chan] = SEL_WAIT;
39853895Smckusick 		goto sc_start_exit;
39953895Smckusick 	}
40053895Smckusick 	SET_CMD(SCMD_SEL_ATN);
40153895Smckusick 
40253895Smckusick sc_start_exit:
40353895Smckusick 	splx(s);
40453895Smckusick }
40553895Smckusick 
40653895Smckusick /*
40753895Smckusick  *	SCSI interrupt service routine
40853895Smckusick  */
scintr()40953895Smckusick scintr()
41053895Smckusick {
41153895Smckusick 	register struct scsi_stat *ss;
41253895Smckusick 	register int iloop;
41353895Smckusick 	register VOLATILE int chan;
41453895Smckusick 	register VOLATILE int dummy;
41553895Smckusick 	int s_int1, s_int2;
41653895Smckusick 
41753895Smckusick scintr_loop:
41853895Smckusick 
41953895Smckusick #if defined(CHECK_MRQ) && defined(news3400)
42053895Smckusick 	while (dmac_gstat & CH_MRQ(CH_SCSI))
42153895Smckusick 		DMAC_WAIT;
42253895Smckusick #endif
42353895Smckusick 
42453895Smckusick 	for (iloop = 0; iloop < 100; iloop++) {
42553895Smckusick 		dummy = sc_statr;
42653895Smckusick 		DMAC_WAIT;
42753895Smckusick 		if ((dummy & R0_CIP) == 0)
42853895Smckusick 			break;
42953895Smckusick 	}
43053895Smckusick 
43153895Smckusick 	/*
43253895Smckusick 	 * get SCSI interrupt request
43353895Smckusick 	 */
43453895Smckusick 	while (sc_statr & R0_MIRQ) {
43553895Smckusick 		DMAC_WAIT0;
43653895Smckusick 		s_int1 = sc_intrq1;
43753895Smckusick 		DMAC_WAIT0;
43853895Smckusick 		s_int2 = sc_intrq2;
43953895Smckusick 		DMAC_WAIT0;
44053895Smckusick 		int_stat1 |= s_int1;
44153895Smckusick 		int_stat2 |= s_int2;
44253895Smckusick 	}
44353895Smckusick 
44453895Smckusick 	if (int_stat2 & R3_SRST) {
44553895Smckusick 		/*
44653895Smckusick 		 * RST signal is drived
44753895Smckusick 		 */
44853895Smckusick 		int_stat2 &= ~R3_SRST;
44953895Smckusick 		scsi_softreset();
45053895Smckusick 		goto scintr_exit;
45153895Smckusick 	}
45253895Smckusick 
45353895Smckusick 	ss = &scsi_stat;
45453895Smckusick 	if ((ss->ipc < 0) && (ss->wrc <= 0) && (ss->wbc <= 0)) {
45553895Smckusick 		int_stat1 = 0;
45653895Smckusick 		int_stat2 = 0;
45753895Smckusick 		goto scintr_exit;
45853895Smckusick 	}
45953895Smckusick 
46053895Smckusick 	chan = get_wb_chan();
46153895Smckusick 	if ((chan >= 0) && (sel_stat[chan] == SEL_START) &&
46253895Smckusick 		(last_cmd == SCMD_SEL_ATN)) {
46353895Smckusick 		/*
46453895Smckusick 		 *	Check the result of SELECTION command
46553895Smckusick 		 */
46653895Smckusick 		if (int_stat1 & R2_RSL) {
46753895Smckusick 			/*
46853895Smckusick 			 * RESELECTION occur
46953895Smckusick 			 */
47053895Smckusick 			if (ss->wrc > 0) {
47153895Smckusick 				sel_stat[chan] = SEL_RSLD;
47253895Smckusick 			} else {
47353895Smckusick 				/*
47453895Smckusick 				 * Ghost RESELECTION ???
47553895Smckusick 				 */
47653895Smckusick 				int_stat1 &= ~R2_RSL;
47753895Smckusick 			}
47853895Smckusick 		}
47953895Smckusick 		if (int_stat1 & R2_ARBF) {
48053895Smckusick 			/*
48153895Smckusick 			 * ARBITRATION fault
48253895Smckusick 			 */
48353895Smckusick 			int_stat1 &= ~R2_ARBF;
48453895Smckusick 			sel_stat[chan] = SEL_ARBF;
48553895Smckusick 		}
48653895Smckusick 		if (int_stat1 & R2_STO) {
48753895Smckusick 			/*
48853895Smckusick 			 * SELECTION timeout
48953895Smckusick 			 */
49053895Smckusick 			int_stat1 &= ~R2_STO;
49153895Smckusick 			if ((int_stat2&(R3_PHC|R3_RMSG)) != (R3_PHC|R3_RMSG)) {
49253895Smckusick 				ss->ipc = chan;
49353895Smckusick 				ss->ip = &chan_stat[chan];
49453895Smckusick 				sel_stat[chan] = SEL_TIMEOUT;
49553895Smckusick 				chan_stat[chan].sc->sc_istatus
49653895Smckusick 					= INST_EP|INST_TO;
49753895Smckusick 				release_wb();
49853895Smckusick 			}
49953895Smckusick 		}
50053895Smckusick 
50153895Smckusick 		/*
50253895Smckusick 		 *	SELECTION command done
50353895Smckusick 		 */
50453895Smckusick 		switch (sel_stat[chan]) {
50553895Smckusick 
50653895Smckusick 		case SEL_START:
50753895Smckusick 			if ((int_stat2 & R3_FNC) == 0)
50853895Smckusick 				break;
50953895Smckusick 			/*
51053895Smckusick 			 * SELECTION success
51153895Smckusick 			 */
51253895Smckusick 			sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
51353895Smckusick 			ss->ipc = chan;
51453895Smckusick 			ss->ip = &chan_stat[chan];
51553895Smckusick 			ss->ip->sc->sc_istatus |= INST_IP;
51653895Smckusick 			ss->dma_stat = OFF;
51753895Smckusick 			pad_start = 0;
51853895Smckusick 			sel_stat[chan] = SEL_SUCCESS;
51953895Smckusick 			release_wb();
52053895Smckusick #ifndef NOT_SUPPORT_SYNCTR
52153895Smckusick 			sc_syncr = sync_tr[chan];
52253895Smckusick 			DMAC_WAIT0;
52353895Smckusick #endif
52453895Smckusick 			DMAC_WAIT0;
52553895Smckusick 			break;
52653895Smckusick 
52753895Smckusick 		case SEL_TIMEOUT:
52853895Smckusick 			/*
52953895Smckusick 			 * SELECTION time out
53053895Smckusick 			 */
53153895Smckusick 			sc_discon();
53253895Smckusick 			goto scintr_exit;
53353895Smckusick 
53453895Smckusick 		/* case SEL_RSLD: */
53553895Smckusick 		/* case SEL_ARBF: */
53653895Smckusick 		default:
53753895Smckusick 			/*
53853895Smckusick 			 * SELECTION failed
53953895Smckusick 			 */
54053895Smckusick 			sel_stat[chan] = SEL_WAIT;
54153895Smckusick 			break;
54253895Smckusick 		}
54353895Smckusick 		if ((int_stat1 & R2_RSL) == 0)
54453895Smckusick 			int_stat2 &= ~R3_FNC;
54553895Smckusick 	}
54653895Smckusick 
54753895Smckusick 	if (ss->ip != NULL) {
54853895Smckusick 		/*
54953895Smckusick 		 * check In Process channel's request
55053895Smckusick 		 */
55153895Smckusick 		if (ss->dma_stat != OFF) {
55253895Smckusick 			/*
55353895Smckusick 			 * adjust pointer & counter
55453895Smckusick 			 */
55553895Smckusick 			adjust_transfer(ss->ip);
55653895Smckusick 		}
55753895Smckusick 		if (int_stat2 & R3_SPE) {
55853895Smckusick 			register int VOLATILE statr;
55953895Smckusick 			register int VOLATILE cmonr;
56053895Smckusick 
56153895Smckusick 			statr = sc_statr;
56253895Smckusick 			DMAC_WAIT0;
56353895Smckusick 			cmonr = sc_cmonr;
56453895Smckusick 			int_stat2 &= ~R3_SPE;
56553895Smckusick 			perr_flag[ss->ip->chan_num] = 1;
56653895Smckusick 		}
56753895Smckusick 	}
56853895Smckusick 
56953895Smckusick 	if (int_stat2 & R3_DCNT) {
57053895Smckusick 		/*
57153895Smckusick 		 * Bus Free
57253895Smckusick 		 */
57353895Smckusick 		sc_discon();
57453895Smckusick 		int_stat2 &= ~R3_DCNT;
57553895Smckusick 	}
57653895Smckusick 
57753895Smckusick 	if ((ss->ipc >= 0) && (sel_stat[ss->ipc] == SEL_RSL_WAIT)) {
57853895Smckusick 		sel_stat[ss->ipc] = SEL_RSLD;
57953895Smckusick 		ss->ipc = -1;
58053895Smckusick 		int_stat1 |= R2_RSL;
58153895Smckusick 	}
58253895Smckusick 	if (int_stat1 & R2_RSL) {
58353895Smckusick 		/*
58453895Smckusick 		 * Reselection
58553895Smckusick 		 */
58653895Smckusick 		sc_resel();
58753895Smckusick 		int_stat1 &= ~R2_RSL;
58853895Smckusick 		if (sel_stat[ss->ipc] == SEL_RSL_WAIT)
58953895Smckusick 			goto scintr_exit;
59053895Smckusick 	}
59153895Smckusick 
59253895Smckusick 
59353895Smckusick 	if ((ss->ipc >= 0) && (ss->ipc != SC_OWNID) &&
59453895Smckusick 	    (sel_stat[ss->ipc] == SEL_SUCCESS)) {
59553895Smckusick 		if (int_stat2 & R3_PHC) {
59653895Smckusick 			/*
59753895Smckusick 			 * Phase change
59853895Smckusick 			 */
59953895Smckusick 			int_stat2 &= ~(R3_PHC|R3_RMSG);
60053895Smckusick 			sc_pmatch();
60153895Smckusick 		} else if (int_stat2 & R3_RMSG) {
60253895Smckusick 			/*
60353895Smckusick 			 * message Phase
60453895Smckusick 			 */
60553895Smckusick 			if (min_flag > 0) {
60653895Smckusick 				int_stat2 &= ~(R3_PHC|R3_RMSG);
60753895Smckusick 				sc_pmatch();
60853895Smckusick 			}
60953895Smckusick 		}
61053895Smckusick 		else if (ss->dma_stat != OFF) {
61153895Smckusick 			dummy = sc_cmonr;
61253895Smckusick 			DMAC_WAIT0;
61353895Smckusick 			if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) {
61453895Smckusick 				/*
61553895Smckusick 				 * still DATA transfer phase
61653895Smckusick 				 */
61753895Smckusick 				sc_dio_pad(ss->ip);
61853895Smckusick 			}
61953895Smckusick 		}
62053895Smckusick 		else if (ss->ip->comflg == CF_SEND) {
62153895Smckusick 			dummy = sc_cmonr;
62253895Smckusick 			DMAC_WAIT0;
62353895Smckusick 			if ((dummy & SC_PMASK) == COM_OUT) {
62453895Smckusick 				/*
62553895Smckusick 				 * command out phase
62653895Smckusick 				 */
62753895Smckusick 				sc_cout(ss->ip);
62853895Smckusick 			}
62953895Smckusick 		}
63053895Smckusick 	} else {
63153895Smckusick 		if (int_stat2 & (R3_PHC|R3_RMSG))
63253895Smckusick 			goto scintr_exit;
63353895Smckusick 	}
63453895Smckusick 
63553895Smckusick 	if ((int_stat1 & (R2_STO|R2_RSL|R2_ARBF))
63653895Smckusick 	    || (int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) {
63753895Smckusick 		/*
63853895Smckusick 		 * still remain intrq
63953895Smckusick 		 */
64053895Smckusick 		goto scintr_loop;
64153895Smckusick 	}
64253895Smckusick 
64353895Smckusick scintr_exit:
64453895Smckusick 	return (1);
64553895Smckusick }
64653895Smckusick 
64753895Smckusick /*
64853895Smckusick  *	SCSI bus reset routine
64953895Smckusick  *		scsi_hardreset() is occered a reset interrupt.
65053895Smckusick  *		And call scsi_softreset().
65153895Smckusick  */
scsi_hardreset()65253895Smckusick scsi_hardreset()
65353895Smckusick {
65453895Smckusick 	register int s;
65553895Smckusick #ifdef DMAC_MAP_INIT
65653895Smckusick 	register int i;
65753895Smckusick #endif
65853895Smckusick 
65953895Smckusick 	s = splscsi();
66053895Smckusick 
66153895Smckusick 	scsi_chipreset();
66253895Smckusick 	DMAC_WAIT0;
66353895Smckusick 	int_stat1 = 0;
66453895Smckusick 	int_stat2 = 0;
66553895Smckusick 	SET_CMD(SCMD_AST_RST);			/* assert RST signal */
66653895Smckusick 
66753895Smckusick #ifdef DMAC_MAP_INIT
66853895Smckusick 	if (dmac_map_init == 0) {
66953895Smckusick 		dmac_map_init++;
67053895Smckusick 		for (i = 0; i < NDMACMAP; i++) {
67153895Smckusick # if defined(mips) && defined(CPU_SINGLE)
67253895Smckusick 			dmac_gsel = CH_SCSI;
67353895Smckusick 			dmac_ctag = (u_char)i;
67453895Smckusick 			dmac_cmap = (u_short)0;
67553895Smckusick # endif
67653895Smckusick 		}
67753895Smckusick 	}
67853895Smckusick #endif
67953895Smckusick 	splx(s);
68053895Smckusick }
68153895Smckusick 
68253895Smckusick /*
68353895Smckusick  * I/O port (sc_ioptr) bit assign
68453895Smckusick  *
68553895Smckusick  *	Rf_PRT3		-	<reserved>
68653895Smckusick  *	Rf_PRT2		-	<reserved>
68753895Smckusick  *	Rf_PRT1		out	Floppy Disk Density control
68853895Smckusick  *	Rf_PRT0		out	Floppy Disk Eject control
68953895Smckusick  */
69053895Smckusick 
scsi_chipreset()69153895Smckusick scsi_chipreset()
69253895Smckusick {
69353895Smckusick 	register int s;
69453895Smckusick 	register int iloop;
69553895Smckusick 	register VOLATILE int save_ioptr;
69653895Smckusick 	register VOLATILE int dummy;
69753895Smckusick 	int s_int1, s_int2;
69853895Smckusick 
69953895Smckusick 	s = splscsi();
70053895Smckusick 
70153895Smckusick #if defined(mips) && defined(CPU_SINGLE)
70253895Smckusick 	dmac_gsel = CH_SCSI;
70353895Smckusick 	dmac_cwid = 4;				/* initialize DMAC SCSI chan */
70453895Smckusick 	*(unsigned VOLATILE char *)PINTEN |= DMA_INTEN;
70553895Smckusick 	dma_reset(CH_SCSI);
70653895Smckusick #endif
70753895Smckusick 	sc_envir = 0;				/* 1/4 clock */
70853895Smckusick 	DMAC_WAIT0;
70953895Smckusick 	save_ioptr = sc_ioptr;
71053895Smckusick 	DMAC_WAIT0;
71153895Smckusick 	last_cmd = SCMD_CHIP_RST;
71253895Smckusick 	sc_comr = SCMD_CHIP_RST;		/* reset chip */
71353895Smckusick 	DMAC_WAIT;
71453895Smckusick 	(void) WAIT_STATR_BITCLR(R0_CIP);
71553895Smckusick 	/*
71653895Smckusick 	 * SCMD_CHIP_RST command reset all register
71753895Smckusick 	 *				except sc_statr<7:6> & sc_cmonr.
71853895Smckusick 	 * So, bit R0_MIRQ & R3_FNC will be not set.
71953895Smckusick 	 */
72053895Smckusick 	sc_idenr = SC_OWNID;
72153895Smckusick 	DMAC_WAIT0;
72253895Smckusick 
72353895Smckusick 	sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
72453895Smckusick 	DMAC_WAIT0;
72553895Smckusick 	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
72653895Smckusick 	DMAC_WAIT0;
72753895Smckusick 
72853895Smckusick 	sc_ioptr = save_ioptr;
72953895Smckusick 	DMAC_WAIT;
73053895Smckusick 
73153895Smckusick 	sc_moder = Rc_TMSL;			/* RST drive time = 25.5 us */
73253895Smckusick 	DMAC_WAIT0;
73353895Smckusick 	sc_timer = 0x2;
73453895Smckusick 	DMAC_WAIT0;
73553895Smckusick 
73653895Smckusick 	sc_moder = Rc_SPHI;			/* selection timeout = 252 ms */
73753895Smckusick 	DMAC_WAIT0;
73853895Smckusick 	sc_timer = SEL_TIMEOUT_VALUE;
73953895Smckusick 	DMAC_WAIT0;
74053895Smckusick 
74153895Smckusick #ifdef SCSI_1185AQ
74253895Smckusick 	if (scsi_1185AQ)
74353895Smckusick 		SET_CMD(SCMD_ENB_SEL);		/* enable reselection */
74453895Smckusick #endif
74553895Smckusick 
74653895Smckusick 	int_stat1 &= ~R2_RSL;			/* ignore RSL inter request */
74753895Smckusick 
74853895Smckusick 	splx(s);
74953895Smckusick }
75053895Smckusick 
scsi_softreset()75153895Smckusick scsi_softreset()
75253895Smckusick {
75353895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
75453895Smckusick 	register struct scsi_stat *ss;
75553895Smckusick 	register int (*handler)();
75653895Smckusick 	register int i;
75753895Smckusick #ifdef mips
75853895Smckusick 	extern struct sc_data sc_data[];
75953895Smckusick 	register struct sc_data *scdp;
76053895Smckusick #endif
76153895Smckusick 
76253895Smckusick 	wbq_actf = NULL;
76353895Smckusick 	wbq_actl = NULL;
76453895Smckusick 	ss = &scsi_stat;
76553895Smckusick 	ss->wbc = 0;
76653895Smckusick 	ss->wrc = 0;
76753895Smckusick 	ss->ip = NULL;
76853895Smckusick 	ss->ipc = -1;
76953895Smckusick 	ss->dma_stat = OFF;
77053895Smckusick 	pad_start = 0;
77153895Smckusick 
77253895Smckusick 	for (i = 0; i < NTARGET; ++i) {
77353895Smckusick 		if (i == SC_OWNID)
77453895Smckusick 			continue;
77553895Smckusick 		cs = &chan_stat[i];
77653895Smckusick 		cs->wb_next = NULL;
77753895Smckusick #ifndef NOT_SUPPORT_SYNCTR
77853895Smckusick 		sync_tr[i] = 0;			/* asynchronous mode */
77953895Smckusick #endif
78053895Smckusick 		sel_stat[i] = SEL_WAIT;
78153895Smckusick 		if (cs->sc != NULL) {
78253895Smckusick 			if ((cs->sc->sc_istatus & INST_EP) == 0)
78353895Smckusick 				cs->sc->sc_istatus = (INST_EP|INST_HE);
78453895Smckusick 			cs->sc = NULL;
78553895Smckusick #ifdef mips
78653895Smckusick 			scdp = &sc_data[cs->chan_num];
78753895Smckusick 			MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));
78853895Smckusick 
78953895Smckusick 			if (MACH_IS_USPACE(scdp->scd_vaddr)) {
79053895Smckusick 				panic("scsi_softreset: user address is not supported");
79153895Smckusick 			} else if (MACH_IS_CACHED(scdp->scd_vaddr)) {
79253895Smckusick 			    MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
79353895Smckusick 			} else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {
79453895Smckusick #ifdef notyet /* KU:XXX */
79553895Smckusick 				clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);
79653895Smckusick #else
79753895Smckusick 				MachFlushCache();
79853895Smckusick #endif
79953895Smckusick 			}
80053895Smckusick #endif /* mips */
80153895Smckusick 			if ((cs->intr_flg == SCSI_INTEN)
80253895Smckusick 				    && (handler = scintsw[i].sci_inthandler)) {
80353895Smckusick #ifdef noyet /* KU:XXX */
80453895Smckusick 				intrcnt[INTR_SCSI00 + i]++;
80553895Smckusick #endif
80653895Smckusick 				(*handler)(scintsw[i].sci_ctlr);
80753895Smckusick 			}
80853895Smckusick 		}
80953895Smckusick 	}
81053895Smckusick }
81153895Smckusick 
81253895Smckusick /*
81353895Smckusick  *	RESELECTION interrupt service routine
81453895Smckusick  *		( RESELECTION phase )
81553895Smckusick  */
sc_resel()81653895Smckusick sc_resel()
81753895Smckusick {
81853895Smckusick 	register struct sc_chan_stat *cs;
81953895Smckusick 	register struct scsi_stat *ss;
82053895Smckusick 	register VOLATILE int chan;
82153895Smckusick 	register VOLATILE int statr;
82253895Smckusick 	register int iloop;
82353895Smckusick 
82453895Smckusick 	min_flag = 0;
82553895Smckusick 	chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT;
82653895Smckusick 
82753895Smckusick 	if (chan == SC_OWNID)
82853895Smckusick 		return;
82953895Smckusick 
83053895Smckusick 	statr = sc_statr;
83153895Smckusick 	DMAC_WAIT0;
83253895Smckusick 	if (statr & R0_CIP) {
83353895Smckusick 		if (last_cmd == SCMD_SEL_ATN) {
83453895Smckusick 			/*
83553895Smckusick 			 * SELECTION command dead lock ?
83653895Smckusick 			 *	save interrupt request
83753895Smckusick 			 */
83853895Smckusick 			while (sc_statr & R0_MIRQ) {
83953895Smckusick 				DMAC_WAIT0;
84053895Smckusick 				int_stat1 |= sc_intrq1;
84153895Smckusick 				DMAC_WAIT0;
84253895Smckusick 				int_stat2 |= sc_intrq2;
84353895Smckusick 				DMAC_WAIT0;
84453895Smckusick 			}
84553895Smckusick 			scsi_chipreset();
84653895Smckusick 		}
84753895Smckusick 	}
84853895Smckusick 
84953895Smckusick 	cs = &chan_stat[chan];
85053895Smckusick 	if (cs->sc == NULL) {
85153895Smckusick 		scsi_hardreset();
85253895Smckusick 		return;
85353895Smckusick 	}
85453895Smckusick 	if ((cs->sc->sc_istatus & INST_WR) == 0) {
85553895Smckusick 		scsi_hardreset();
85653895Smckusick 		return;
85753895Smckusick 	}
85853895Smckusick 
85953895Smckusick 	ss = &scsi_stat;
86053895Smckusick 	if (ss->ipc >= 0) {
86153895Smckusick 		scsi_hardreset();
86253895Smckusick 		return;
86353895Smckusick 	}
86453895Smckusick 
86553895Smckusick 	ss->ip = cs;
86653895Smckusick 	ss->ipc = chan;
86753895Smckusick 
86853895Smckusick 	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
86953895Smckusick 	DMAC_WAIT0;
87053895Smckusick 
87153895Smckusick 	iloop = 0;
87253895Smckusick 	while ((int_stat2 & R3_FNC) == 0) {
87353895Smckusick 		/*
87453895Smckusick 		 * Max 6 usec wait
87553895Smckusick 		 */
87653895Smckusick 		if (iloop++ > RSL_LOOP_CNT) {
87753895Smckusick 			sel_stat[chan] = SEL_RSL_WAIT;
87853895Smckusick 			return;
87953895Smckusick 		}
88053895Smckusick 		GET_INTR(&int_stat1, &int_stat2);
88153895Smckusick 	}
88253895Smckusick 	int_stat2 &= ~R3_FNC;
88353895Smckusick 
88453895Smckusick 	sel_stat[chan] = SEL_SUCCESS;
88553895Smckusick 
88653895Smckusick 	ss->wrc--;
88753895Smckusick 	ss->dma_stat = OFF;
88853895Smckusick 	pad_start = 0;
88953895Smckusick 	cs->sc->sc_istatus |= INST_IP;
89053895Smckusick 	cs->sc->sc_istatus &= ~INST_WR;
89153895Smckusick 
89253895Smckusick #ifndef NOT_SUPPORT_SYNCTR
89353895Smckusick 	sc_syncr = sync_tr[chan];
89453895Smckusick 	DMAC_WAIT0;
89553895Smckusick #endif
89653895Smckusick }
89753895Smckusick 
89853895Smckusick /*
89953895Smckusick  *	DISCONNECT interrupt service routine
90053895Smckusick  *		( Target disconnect / job done )
90153895Smckusick  */
sc_discon()90253895Smckusick sc_discon()
90353895Smckusick {
90453895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
90553895Smckusick 	register struct scsi_stat *ss;
90653895Smckusick 	register int (*handler)();
90753895Smckusick 	register VOLATILE int dummy;
90853895Smckusick #ifdef mips
90953895Smckusick 	extern struct sc_data sc_data[];
91053895Smckusick 	register struct sc_data *scdp;
91153895Smckusick #endif
91253895Smckusick 
91353895Smckusick 	/*
91453895Smckusick 	 * Signal reflection on BSY is occured.
91553895Smckusick 	 *	Not Bus Free Phase, ignore.
91653895Smckusick 	 *
91753895Smckusick 	 *	But, CXD1185Q reset INIT bit of sc_statr.
91853895Smckusick 	 *	So, can't issue Transfer Information command.
91953895Smckusick 	 *
92053895Smckusick 	 *	What shall we do ?  Bus reset ?
92153895Smckusick 	 */
92253895Smckusick 	if ((int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0))
92353895Smckusick 		return;
92453895Smckusick 
92553895Smckusick 	sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
92653895Smckusick 	DMAC_WAIT0;
92753895Smckusick 
92853895Smckusick 	min_flag = 0;
92953895Smckusick 	dummy = sc_cmonr;
93053895Smckusick 	DMAC_WAIT0;
93153895Smckusick 	if (dummy & R4_MATN) {
93253895Smckusick 		SET_CMD(SCMD_NGT_ATN);
93353895Smckusick 		(void) WAIT_STATR_BITSET(R0_MIRQ);
93453895Smckusick 		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */
93553895Smckusick 	}
93653895Smckusick 
93753895Smckusick 	if ((int_stat1 & R2_RSL) == 0)
93853895Smckusick 		int_stat2 &= ~R3_FNC;
93953895Smckusick 
94053895Smckusick 	ss = &scsi_stat;
94153895Smckusick 	cs = ss->ip;
94253895Smckusick 	if ((cs == NULL) || (ss->ipc < 0))
94353895Smckusick 		goto sc_discon_exit;
94453895Smckusick 
94553895Smckusick 	if ((sel_stat[cs->chan_num] != SEL_SUCCESS)
94653895Smckusick 			&& (sel_stat[cs->chan_num] != SEL_TIMEOUT))
94753895Smckusick 		printf("sc_discon: eh!\n");
94853895Smckusick 
94953895Smckusick 	/*
95053895Smckusick 	 * indicate abnormal terminate
95153895Smckusick 	 */
95253895Smckusick 	if ((cs->sc->sc_istatus & (INST_EP|INST_WR)) == 0)
95353895Smckusick 		cs->sc->sc_istatus |= (INST_EP|INST_PRE|INST_LB);
95453895Smckusick 
95553895Smckusick 	cs->sc->sc_istatus &= ~INST_IP;
95653895Smckusick 	ss->dma_stat = OFF;
95753895Smckusick 	pad_start = 0;
95853895Smckusick 	ss->ip = NULL;
95953895Smckusick 	ss->ipc = -1;
96053895Smckusick 
96153895Smckusick 	if ((cs->sc->sc_istatus & INST_WR) == 0) {
96253895Smckusick 		if (perr_flag[cs->chan_num] > 0)
96353895Smckusick 			cs->sc->sc_istatus |= INST_EP|INST_PRE;
96453895Smckusick 		cs->sc = NULL;
96553895Smckusick #ifdef mips
96653895Smckusick 		scdp = &sc_data[cs->chan_num];
96753895Smckusick 		MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));
96853895Smckusick 
96953895Smckusick 		if (MACH_IS_USPACE(scdp->scd_vaddr)) {
97053895Smckusick 			panic("sc_discon: user address is not supported");
97153895Smckusick 		} else if (MACH_IS_CACHED(scdp->scd_vaddr)) {
97253895Smckusick 			MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
97353895Smckusick 		} else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {
97453895Smckusick #ifdef notyet /* KU:XXX */
97553895Smckusick 			clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);
97653895Smckusick #else
97753895Smckusick 			MachFlushCache();
97853895Smckusick #endif
97953895Smckusick 		}
98053895Smckusick #endif /* mips */
98153895Smckusick 		if ((cs->intr_flg == SCSI_INTEN)
98253895Smckusick 		    && (handler = scintsw[cs->chan_num].sci_inthandler)) {
98353895Smckusick #ifdef notyet /* KU:XXX */
98453895Smckusick 			intrcnt[INTR_SCSI00 + cs->chan_num]++;
98553895Smckusick #endif
98653895Smckusick 			(*handler)(scintsw[cs->chan_num].sci_ctlr);
98753895Smckusick 		}
98853895Smckusick 	}
98953895Smckusick 
99053895Smckusick sc_discon_exit:
99153895Smckusick 	sc_start();
99253895Smckusick }
99353895Smckusick 
99453895Smckusick /*
99553895Smckusick  *	SCSI phase match interrupt service routine
99653895Smckusick  */
sc_pmatch()99753895Smckusick sc_pmatch()
99853895Smckusick {
99953895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
100053895Smckusick 	register VOLATILE int phase;
100153895Smckusick 	register VOLATILE int phase2;
100253895Smckusick 	register VOLATILE int cmonr;
100353895Smckusick 
100453895Smckusick 	int_stat2 &= ~R3_FNC;			/* XXXXXXXX */
100553895Smckusick 
100653895Smckusick 	cs = scsi_stat.ip;
100753895Smckusick 	if (cs == NULL)
100853895Smckusick 		return;
100953895Smckusick 
101053895Smckusick # if defined(mips) && defined(CPU_SINGLE)
101153895Smckusick 	dma_reset(CH_SCSI);
101253895Smckusick # endif
101353895Smckusick 	phase = sc_cmonr & SC_PMASK;
101453895Smckusick 	DMAC_WAIT0;
101553895Smckusick 	for (;;) {
101653895Smckusick 		phase2 = phase;
101753895Smckusick 		cmonr = sc_cmonr;
101853895Smckusick 		DMAC_WAIT0;
101953895Smckusick 		phase = cmonr & SC_PMASK;
102053895Smckusick 		if (phase == phase2) {
102153895Smckusick 			if ((phase == DAT_IN) || (phase == DAT_OUT))
102253895Smckusick 				break;
102353895Smckusick 			else if (cmonr & R4_MREQ)
102453895Smckusick 				break;
102553895Smckusick 		}
102653895Smckusick 	}
102753895Smckusick 
102853895Smckusick 
102953895Smckusick 	scsi_stat.dma_stat = OFF;
103053895Smckusick 	pad_start = 0;
103153895Smckusick 
103253895Smckusick 	if (phase == COM_OUT) {
103353895Smckusick 		min_flag = 0;
103453895Smckusick 		if (cs->comflg != CF_SEND)
103553895Smckusick 			cs->comflg = CF_SET;
103653895Smckusick 		sc_cout(cs);
103753895Smckusick 	} else {
103853895Smckusick 		cs->comflg = CF_ENOUGH;
103953895Smckusick 		sc_intok2 &= ~Rb_FNC;
104053895Smckusick 		if (phase == MES_IN) {
104153895Smckusick 			min_flag++;
104253895Smckusick 			sc_min(cs);
104353895Smckusick 		} else {
104453895Smckusick 			min_flag = 0;
104553895Smckusick 
104653895Smckusick 			switch (phase) {
104753895Smckusick 
104853895Smckusick 			case MES_OUT:
104953895Smckusick 				sc_mout(cs);
105053895Smckusick 				break;
105153895Smckusick 
105253895Smckusick 			case DAT_IN:
105353895Smckusick 			case DAT_OUT:
105453895Smckusick 				sc_dio(cs);
105553895Smckusick 				break;
105653895Smckusick 
105753895Smckusick 			case STAT_IN:
105853895Smckusick 				sc_sin(cs);
105953895Smckusick 				break;
106053895Smckusick 
106153895Smckusick 			default:
106253895Smckusick 				printf("SCSI%d: unknown phase\n", cs->chan_num);
106353895Smckusick 				break;
106453895Smckusick 			}
106553895Smckusick 		}
106653895Smckusick 	}
106753895Smckusick }
106853895Smckusick 
106953895Smckusick 
flush_fifo()107053895Smckusick flush_fifo()
107153895Smckusick {
107253895Smckusick 	register VOLATILE int dummy;
107353895Smckusick 	VOLATILE int tmp;
107453895Smckusick 	VOLATILE int tmp0;
107553895Smckusick 
107653895Smckusick 	dummy = sc_ffstr;
107753895Smckusick 	DMAC_WAIT0;
107853895Smckusick 	if (dummy & R5_FIFOREM) {
107953895Smckusick 		/*
108053895Smckusick 		 * flush FIFO
108153895Smckusick 		 */
108253895Smckusick 		SET_CMD(SCMD_FLSH_FIFO);
108353895Smckusick 		tmp = 0;
108453895Smckusick 		do {
108553895Smckusick 			do {
108653895Smckusick 				dummy = sc_statr;
108753895Smckusick 				DMAC_WAIT0;
108853895Smckusick 			} while (dummy & R0_CIP);
108953895Smckusick 			GET_INTR(&tmp0, &tmp); /* clear interrupt */
109053895Smckusick 		} while ((tmp & R3_FNC) == 0);
109153895Smckusick 	}
109253895Smckusick }
109353895Smckusick 
109453895Smckusick /*
109553895Smckusick  *	SCSI command send routine
109653895Smckusick  */
109753895Smckusick int
sc_cout(cs)109853895Smckusick sc_cout(cs)
109953895Smckusick 	register struct sc_chan_stat *cs;
110053895Smckusick {
110153895Smckusick 	register struct scsi *sc;
110253895Smckusick 	register int iloop;
110353895Smckusick 	register int cdb_bytes;
110453895Smckusick 	register VOLATILE int dummy;
110553895Smckusick 	register VOLATILE int statr;
110653895Smckusick 
110753895Smckusick 	if (cs->comflg == CF_SET) {
110853895Smckusick 		cs->comflg = CF_SEND;
110953895Smckusick 
111053895Smckusick 		flush_fifo();
111153895Smckusick 
111253895Smckusick 		sc = cs->sc;
111353895Smckusick 		switch (sc->sc_opcode & CMD_TYPEMASK) {
111453895Smckusick 		case CMD_T0:
111553895Smckusick 			cdb_bytes = 6;
111653895Smckusick 			break;
111753895Smckusick 
111853895Smckusick 		case CMD_T1:
111953895Smckusick 			cdb_bytes = 10;
112053895Smckusick 			break;
112153895Smckusick 
112253895Smckusick 		case CMD_T5:
112353895Smckusick 			cdb_bytes = 12;
112453895Smckusick 			break;
112553895Smckusick 
112653895Smckusick 		default:
112753895Smckusick 			cdb_bytes = 6;
112853895Smckusick 			sc_intok2 |= Rb_FNC;
112953895Smckusick 			break;
113053895Smckusick 		}
113153895Smckusick 
113253895Smckusick 		/*
113353895Smckusick 		 * set Active pointers
113453895Smckusick 		 */
113553895Smckusick 		act_cmd_pointer = sc->sc_cdb.un_reserved;
113653895Smckusick 		cs->act_trcnt = sc->sc_ctrnscnt;
113753895Smckusick 		cs->act_point = sc->sc_cpoint;
113853895Smckusick 		cs->act_tag = sc->sc_ctag;
113953895Smckusick 		cs->act_offset = sc->sc_coffset;
114053895Smckusick 
114153895Smckusick 	} else {
114253895Smckusick 		cdb_bytes = 1;
114353895Smckusick 		iloop = 0;
114453895Smckusick 		do {
114553895Smckusick 			dummy = sc_cmonr;
114653895Smckusick 			DMAC_WAIT0;
114753895Smckusick 			if ((dummy & SC_PMASK) != COM_OUT)
114853895Smckusick 				return;
114953895Smckusick 			statr = sc_statr;
115053895Smckusick 			DMAC_WAIT0;
115153895Smckusick 			if (statr & R0_MIRQ)
115253895Smckusick 				return;
115353895Smckusick 		} while ((dummy & R4_MREQ) == 0);
115453895Smckusick 		statr = sc_statr;
115553895Smckusick 		DMAC_WAIT0;
115653895Smckusick 		if (statr & R0_MIRQ)
115753895Smckusick 			return;
115853895Smckusick 	}
115953895Smckusick 
116053895Smckusick 
116153895Smckusick 	SET_CNT(cdb_bytes);
116253895Smckusick 	SET_CMD(SCMD_TR_INFO|R0_TRBE);
116353895Smckusick 
116453895Smckusick 	for (iloop = 0; iloop < cdb_bytes; iloop++) {
116553895Smckusick 		do {
116653895Smckusick 			dummy = sc_cmonr;
116753895Smckusick 			DMAC_WAIT0;
116853895Smckusick 			if ((dummy & SC_PMASK) != COM_OUT)
116953895Smckusick 				return;
117053895Smckusick 		} while ((dummy & R4_MREQ) == 0);
117153895Smckusick 		statr = sc_statr;
117253895Smckusick 		DMAC_WAIT0;
117353895Smckusick 		if (statr & R0_MIRQ)
117453895Smckusick 			return;
117553895Smckusick 		sc_datr = *act_cmd_pointer++;
117653895Smckusick 		do {
117753895Smckusick 			dummy = sc_cmonr;
117853895Smckusick 			DMAC_WAIT0;
117953895Smckusick 		} while ((dummy & R4_MACK) != 0);
118053895Smckusick 	}
118153895Smckusick }
118253895Smckusick 
118353895Smckusick #define GET_MIN_COUNT	127
118453895Smckusick 
118553895Smckusick /*
118653895Smckusick  *	SCSI message accept routine
118753895Smckusick  */
sc_min(cs)118853895Smckusick sc_min(cs)
118953895Smckusick 	register struct sc_chan_stat *cs;
119053895Smckusick {
119153895Smckusick 	register struct scsi *sc;
119253895Smckusick 	register struct scsi_stat *ss;
119353895Smckusick 	register VOLATILE int dummy;
119453895Smckusick 
119553895Smckusick 	sc = cs->sc;
119653895Smckusick 	ss = &scsi_stat;
119753895Smckusick 
119853895Smckusick 	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
119953895Smckusick 	DMAC_WAIT0;
120053895Smckusick 
120153895Smckusick 	if (min_flag == 1)
120253895Smckusick 		flush_fifo();
120353895Smckusick 
120453895Smckusick 	dummy = sc_cmonr;
120553895Smckusick 	DMAC_WAIT0;
120653895Smckusick 	if ((dummy & R4_MREQ) == 0) {
120753895Smckusick 		printf("sc_min: !REQ cmonr=%x\n", dummy);
120853895Smckusick 		print_scsi_stat();
120953895Smckusick 		scsi_hardreset();
121053895Smckusick 		return;
121153895Smckusick 	}
121253895Smckusick 
121353895Smckusick     retry_cmd_issue:
121453895Smckusick 	int_stat2 &= ~R3_FNC;
121553895Smckusick 	SET_CMD(SCMD_TR_INFO);
121653895Smckusick 	do {
121753895Smckusick 		do {
121853895Smckusick 			dummy = sc_statr;
121953895Smckusick 			DMAC_WAIT0;
122053895Smckusick 		} while (dummy & R0_CIP);
122153895Smckusick 		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */
122253895Smckusick 	} while ((int_stat2 & R3_FNC) == 0);
122353895Smckusick 	int_stat2 &= ~R3_FNC;
122453895Smckusick 
122553895Smckusick 	dummy = sc_ffstr;
122653895Smckusick 	if (dummy & R5_FIE) {
122753895Smckusick 		DMAC_WAIT;
122853895Smckusick 		dummy = sc_ffstr;
122953895Smckusick 		DMAC_WAIT0;
123053895Smckusick 		if (dummy & R5_FIE) {
123153895Smckusick 			dummy = sc_statr;
123253895Smckusick 			DMAC_WAIT0;
123353895Smckusick 			if ((dummy & R0_INIT) == 0) {
123453895Smckusick 				/*
123553895Smckusick 				 * CXD1185 detect BSY false
123653895Smckusick 				 */
123753895Smckusick 				scsi_hardreset();
123853895Smckusick 				return;
123953895Smckusick 			}
124053895Smckusick 		}
124153895Smckusick 	}
124253895Smckusick 	dummy = sc_datr;				/* get message byte */
124353895Smckusick 	DMAC_WAIT0;
124453895Smckusick 
124553895Smckusick 	if (min_cnt[cs->chan_num] == 0) {
124653895Smckusick 		sc->sc_message = sc->sc_identify;
124753895Smckusick 		if (dummy == MSG_EXTND) {
124853895Smckusick 			/* Extended Message */
124953895Smckusick 			min_cnt[cs->chan_num] = GET_MIN_COUNT;
125053895Smckusick 			min_point[cs->chan_num] = sc->sc_param;
125153895Smckusick 			bzero((caddr_t)sc->sc_param, 8);
125253895Smckusick 			*min_point[cs->chan_num]++ = dummy;
125353895Smckusick 		} else {
125453895Smckusick 			switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) {
125553895Smckusick 
125653895Smckusick 			case MSG_CCOMP:
125753895Smckusick 				sc->sc_istatus |= INST_EP;
125853895Smckusick 				break;
125953895Smckusick 
126053895Smckusick 			case MSG_MREJ:
126153895Smckusick #ifndef NOT_SUPPORT_SYNCTR
126253895Smckusick 				if (mout_flag[cs->chan_num] == MOUT_SYNC_TR)
126353895Smckusick 					sync_tr[cs->chan_num] = 0;
126453895Smckusick #endif
126553895Smckusick 				break;
126653895Smckusick 
126753895Smckusick 			case MSG_IDENT:
126853895Smckusick 			case MSG_RDP:
126953895Smckusick 	ss->dma_stat = OFF;
127053895Smckusick 	pad_start = 0;
127153895Smckusick 				cs->comflg = OFF;
127253895Smckusick 				/*
127353895Smckusick 				 * restore the saved value to Active pointers
127453895Smckusick 				 */
127553895Smckusick 				act_cmd_pointer = sc->sc_cdb.un_reserved;
127653895Smckusick 				cs->act_trcnt = sc->sc_ctrnscnt;
127753895Smckusick 				cs->act_point = sc->sc_cpoint;
127853895Smckusick 				cs->act_tag = sc->sc_ctag;
127953895Smckusick 				cs->act_offset = sc->sc_coffset;
128053895Smckusick 				break;
128153895Smckusick 
128253895Smckusick 			case MSG_SDP:
128353895Smckusick 				/*
128453895Smckusick 				 * save Active pointers
128553895Smckusick 				 */
128653895Smckusick 				sc->sc_ctrnscnt = cs->act_trcnt;
128753895Smckusick 				sc->sc_ctag = cs->act_tag;
128853895Smckusick 				sc->sc_coffset = cs->act_offset;
128953895Smckusick 				sc->sc_cpoint = cs->act_point;
129053895Smckusick 				break;
129153895Smckusick 
129253895Smckusick 			case MSG_DCNT:
129353895Smckusick 				sc->sc_istatus |= INST_WR;
129453895Smckusick 				ss->wrc++;
129553895Smckusick 				break;
129653895Smckusick 
129753895Smckusick 			default:
129853895Smckusick 				sc->sc_message = MSG_MREJ;
129953895Smckusick 				SET_CMD(SCMD_AST_ATN);
130053895Smckusick 				printf("SCSI%d:sc_min() Unknown mes=0x%x, \n",
130153895Smckusick 					cs->chan_num, dummy);
130253895Smckusick 			}
130353895Smckusick 		}
130453895Smckusick 	} else {
130553895Smckusick 		*min_point[cs->chan_num]++ = dummy;
130653895Smckusick 		if (min_cnt[cs->chan_num] == GET_MIN_COUNT)
130753895Smckusick 			min_cnt[cs->chan_num] = dummy;
130853895Smckusick 		else
130953895Smckusick 			min_cnt[cs->chan_num]--;
131053895Smckusick 		if (min_cnt[cs->chan_num] <= 0) {
131153895Smckusick #ifdef ABORT_SYNCTR_MES_FROM_TARGET
131253895Smckusick 			if ((sc->sc_param[2] == 0x01)
131353895Smckusick 			    && (mout_flag[cs->chan_num] == MOUT_SYNC_TR)) {
131453895Smckusick #else
131553895Smckusick 			if (sc->sc_param[2] == 0x01) { /*}*/
131653895Smckusick #endif
131753895Smckusick 				register int i;
131853895Smckusick 				/*
131953895Smckusick 				 * receive Synchronous transfer message reply
132053895Smckusick 				 *	calculate transfer period val
132153895Smckusick 				 *	tpm * 4/1000 us = 4/16 * (tpv + 1)
132253895Smckusick 				 */
132353895Smckusick #define	TPM2TPV(tpm)	(((tpm)*16 + 999) / 1000 - 1)
132453895Smckusick #ifndef NOT_SUPPORT_SYNCTR
132553895Smckusick 				i = sc->sc_param[3];	/* get tpm */
132653895Smckusick 				i = TPM2TPV(i) << 4;
132753895Smckusick 				if (sc->sc_param[4] == 0)
132853895Smckusick 					sync_tr[cs->chan_num] = 0;
132953895Smckusick 				else
133053895Smckusick 					sync_tr[cs->chan_num] = i | sc->sc_param[4];
133153895Smckusick #endif /* !NOT_SUPPORT_SYNCTR */
133253895Smckusick 			} else {
133353895Smckusick 				sc->sc_message = MSG_MREJ;
133453895Smckusick 				SET_CMD(SCMD_AST_ATN);	/* assert ATN */
133553895Smckusick 			}
133653895Smckusick 		}
133753895Smckusick 	}
133853895Smckusick 	SET_CMD(SCMD_NGT_ACK);
133953895Smckusick }
134053895Smckusick 
134153895Smckusick /*
134253895Smckusick  *	SCSI message send routine
134353895Smckusick  */
134453895Smckusick int
sc_mout(cs)134553895Smckusick sc_mout(cs)
134653895Smckusick 	register struct sc_chan_stat *cs;
134753895Smckusick {
134853895Smckusick 	register struct scsi *sc = cs->sc;
134953895Smckusick 	register u_char *mp;
135053895Smckusick 	register int cnt;
135153895Smckusick 	register int iloop;
135253895Smckusick 	register VOLATILE int dummy;
135353895Smckusick 	VOLATILE int tmp;
135453895Smckusick 	VOLATILE int tmp0;
135553895Smckusick 
135653895Smckusick 	flush_fifo();
135753895Smckusick 
135853895Smckusick 	if (mout_flag[cs->chan_num] == 0) {
135953895Smckusick 		mout_flag[cs->chan_num] = MOUT_IDENTIFY;
136053895Smckusick 		if (sc->sc_message != 0) {
136153895Smckusick 			sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
136253895Smckusick 			DMAC_WAIT0;
136353895Smckusick 			if ((sc->sc_message == MSG_EXTND)
136453895Smckusick 					&& (sc->sc_param[2] == 0x01)) {
136553895Smckusick 				cnt = 5;
136653895Smckusick 				mp = sc->sc_param;
136753895Smckusick 				sc->sc_param[3] = MIN_TP;
136853895Smckusick 				if (sc->sc_param[4] > MAX_OFFSET_BYTES)
136953895Smckusick 					sc->sc_param[4] = MAX_OFFSET_BYTES;
137053895Smckusick 				mout_flag[cs->chan_num] = MOUT_SYNC_TR;
137153895Smckusick 			} else {
137253895Smckusick 				cnt = 1;
137353895Smckusick 				mp = &sc->sc_message;
137453895Smckusick 			}
137553895Smckusick 
137653895Smckusick 			SET_CNT(cnt);
137753895Smckusick 			SET_CMD(SCMD_TR_INFO|R0_TRBE);
137853895Smckusick 			sc_datr = sc->sc_identify;
137953895Smckusick 			DMAC_WAIT0;
138053895Smckusick 			for (iloop = 1; iloop < cnt; iloop++) {
138153895Smckusick 				sc_datr = *mp++;
138253895Smckusick 				DMAC_WAIT;
138353895Smckusick 			}
138453895Smckusick 			do {
138553895Smckusick 				dummy = sc_cmonr;
138653895Smckusick 				DMAC_WAIT0;
138753895Smckusick 				if ((dummy & R4_MBSY) == 0)
138853895Smckusick 					return;
138953895Smckusick 				dummy = sc_statr;
139053895Smckusick 				DMAC_WAIT0;
139153895Smckusick 			} while (dummy & R0_CIP);
139253895Smckusick 
139353895Smckusick 			tmp = 0;
139453895Smckusick 			GET_INTR(&tmp0, &tmp);		/* clear interrupt */
139553895Smckusick 			if ((tmp & R3_FNC) == 0) {
139653895Smckusick 				(void) WAIT_STATR_BITSET(R0_MIRQ);
139753895Smckusick 				GET_INTR(&tmp0, &tmp);	/* clear interrupt */
139853895Smckusick 			}
139953895Smckusick 
140053895Smckusick 			do {
140153895Smckusick 				dummy = sc_cmonr;
140253895Smckusick 				DMAC_WAIT0;
140353895Smckusick 				if ((dummy & R4_MBSY) == 0)
140453895Smckusick 					return;
140553895Smckusick 			} while ((dummy & R4_MREQ) == 0);
140653895Smckusick 			SET_CMD(SCMD_NGT_ATN);
140753895Smckusick 			(void) WAIT_STATR_BITCLR(R0_CIP);
140853895Smckusick 			GET_INTR(&tmp0, &tmp);		/* clear interrupt */
140953895Smckusick 
141053895Smckusick 			dummy = sc_cmonr;
141153895Smckusick 			DMAC_WAIT0;
141253895Smckusick 			if ((dummy & R4_MREQ) == 0) {
141353895Smckusick 				printf("sc_mout: !REQ cmonr=%x\n", dummy);
141453895Smckusick 				print_scsi_stat();
141553895Smckusick 				scsi_hardreset();
141653895Smckusick 				return;
141753895Smckusick 			}
141853895Smckusick 
141953895Smckusick 			SET_CMD(SCMD_TR_INFO);
142053895Smckusick 			sc_datr = *mp++;
142153895Smckusick 			DMAC_WAIT0;
142253895Smckusick 		} else {
142353895Smckusick 			dummy = sc_cmonr;
142453895Smckusick 			DMAC_WAIT0;
142553895Smckusick 			if (dummy & R4_MATN) {
142653895Smckusick 				SET_CMD(SCMD_NGT_ATN);
142753895Smckusick 				(void) WAIT_STATR_BITCLR(R0_CIP);
142853895Smckusick 				GET_INTR(&tmp0, &tmp);	/* clear interrupt */
142953895Smckusick 			}
143053895Smckusick 
143153895Smckusick 			iloop = 0;
143253895Smckusick 			do {
143353895Smckusick 				dummy = sc_cmonr;
143453895Smckusick 				DMAC_WAIT0;
143553895Smckusick 				if (iloop++ > CHECK_LOOP_CNT)
143653895Smckusick 					break;
143753895Smckusick 			} while ((dummy & R4_MREQ) == 0);
143853895Smckusick 			SET_CMD(SCMD_TR_INFO);
143953895Smckusick 			sc_datr = sc->sc_identify;
144053895Smckusick 			DMAC_WAIT0;
144153895Smckusick 		}
144253895Smckusick 	} else {
144353895Smckusick 		dummy = sc_cmonr;
144453895Smckusick 		DMAC_WAIT0;
144553895Smckusick 		if (dummy & R4_MATN) {
144653895Smckusick 			SET_CMD(SCMD_NGT_ATN);
144753895Smckusick 			(void) WAIT_STATR_BITCLR(R0_CIP);
144853895Smckusick 			GET_INTR(&tmp0, &tmp);		/* clear interrupt */
144953895Smckusick 		}
145053895Smckusick 
145153895Smckusick 		dummy = sc_cmonr;
145253895Smckusick 		DMAC_WAIT0;
145353895Smckusick 		if ((dummy & R4_MREQ) == 0) {
145453895Smckusick 			printf("sc_mout: !REQ cmonr=%x\n", dummy);
145553895Smckusick 			print_scsi_stat();
145653895Smckusick 			scsi_hardreset();
145753895Smckusick 			return;
145853895Smckusick 		}
145953895Smckusick 
146053895Smckusick 		SET_CMD(SCMD_TR_INFO);
146153895Smckusick 		sc_datr = sc->sc_message;
146253895Smckusick 		DMAC_WAIT0;
146353895Smckusick 	}
146453895Smckusick }
146553895Smckusick 
146653895Smckusick /*
146753895Smckusick  *	SCSI status accept routine
146853895Smckusick  */
sc_sin(cs)146953895Smckusick sc_sin(cs)
147053895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
147153895Smckusick {
147253895Smckusick 	register VOLATILE int dummy;
147353895Smckusick 	register int iloop;
147453895Smckusick 
147553895Smckusick 	flush_fifo();
147653895Smckusick 
147753895Smckusick 	dummy = sc_cmonr;
147853895Smckusick 	DMAC_WAIT0;
147953895Smckusick 	if ((dummy & R4_MREQ) == 0) {
148053895Smckusick 		printf("sc_sin: !REQ cmonr=%x\n", dummy);
148153895Smckusick 		print_scsi_stat();
148253895Smckusick 		scsi_hardreset();
148353895Smckusick 		return;
148453895Smckusick 	}
148553895Smckusick 
148653895Smckusick 	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
148753895Smckusick 	DMAC_WAIT0;
148853895Smckusick 
148953895Smckusick 	SET_CMD(SCMD_TR_INFO);
149053895Smckusick 
149153895Smckusick 	(void) WAIT_STATR_BITCLR(R0_CIP);
149253895Smckusick 
149353895Smckusick 	int_stat2 &= ~R3_FNC;
149453895Smckusick 	iloop = 0;
149553895Smckusick 	do {
149653895Smckusick 		if (iloop++ > CHECK_LOOP_CNT)
149753895Smckusick 			break;
149853895Smckusick 		GET_INTR(&int_stat1, &int_stat2);	/* clear interrupt */
149953895Smckusick 	} while ((int_stat2 & R3_FNC) == 0);
150053895Smckusick 	int_stat2 &= ~R3_FNC;
150153895Smckusick 
150253895Smckusick 	cs->sc->sc_tstatus = sc_datr;		/* get status byte */
150353895Smckusick 	DMAC_WAIT0;
150453895Smckusick }
150553895Smckusick 
150653895Smckusick /*
150753895Smckusick  *	SCSI data in/out routine
150853895Smckusick  */
sc_dio(cs)150953895Smckusick sc_dio(cs)
151053895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
151153895Smckusick {
151253895Smckusick 	register VOLATILE struct scsi *sc;
151353895Smckusick 	register struct scsi_stat *ss;
151453895Smckusick 	register int i;
151553895Smckusick 	register int pages;
151653895Smckusick 	register u_int tag;
151753895Smckusick 	register u_int pfn;
151853895Smckusick 	VOLATILE int phase;
151953895Smckusick 
152053895Smckusick 	sc = cs->sc;
152153895Smckusick 	ss = &scsi_stat;
152253895Smckusick 
152353895Smckusick 	sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
152453895Smckusick 	DMAC_WAIT0;
152553895Smckusick 
152653895Smckusick 	if (cs->act_trcnt <= 0) {
152753895Smckusick 		sc_dio_pad(cs);
152853895Smckusick 		return;
152953895Smckusick 	}
153053895Smckusick 
153153895Smckusick 	switch (sc->sc_opcode) {
153253895Smckusick 
153353895Smckusick 	case SCOP_READ:
153453895Smckusick 	case SCOP_WRITE:
153553895Smckusick 	case SCOP_EREAD:
153653895Smckusick 	case SCOP_EWRITE:
153753895Smckusick 		i = (cs->act_trcnt + sc->sc_bytesec -1) / sc->sc_bytesec;
153853895Smckusick 		i *= sc->sc_bytesec;
153953895Smckusick 		break;
154053895Smckusick 
154153895Smckusick 	default:
154253895Smckusick 		i = cs->act_trcnt;
154353895Smckusick 		break;
154453895Smckusick 	}
154553895Smckusick 
154653895Smckusick 	SET_CNT(i);
154753895Smckusick 	pad_cnt[cs->chan_num] = i - cs->act_trcnt;
154853895Smckusick 
154953895Smckusick 	phase = sc_cmonr & SC_PMASK;
155053895Smckusick 	DMAC_WAIT0;
155153895Smckusick 	if (phase == DAT_IN) {
155253895Smckusick 		if (sc_syncr == OFF) {
155353895Smckusick 			DMAC_WAIT0;
155453895Smckusick 			flush_fifo();
155553895Smckusick 		}
155653895Smckusick 	}
155753895Smckusick 
155853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
155953895Smckusick 	SET_CMD(SCMD_TR_INFO|R0_DMA|R0_TRBE);
156053895Smckusick #endif
156153895Smckusick 
156253895Smckusick #if defined(mips) && defined(CPU_SINGLE)
156353895Smckusick 	dmac_gsel = CH_SCSI;
156453895Smckusick 	dmac_ctrcl = (u_char)(cs->act_trcnt & 0xff);
156553895Smckusick 	dmac_ctrcm = (u_char)((cs->act_trcnt >> 8) & 0xff);
156653895Smckusick 	dmac_ctrch = (u_char)((cs->act_trcnt >> 16) & 0x0f);
156753895Smckusick 	dmac_cofsh = (u_char)((cs->act_offset >> 8) & 0xf);
156853895Smckusick 	dmac_cofsl = (u_char)(cs->act_offset & 0xff);
156953895Smckusick #endif
157053895Smckusick 	tag = 0;
157153895Smckusick 
157253895Smckusick 	if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
157353895Smckusick 		/*
157453895Smckusick 		 * Set DMAC map entry from map table
157553895Smckusick 		 */
157653895Smckusick 		pages = sc->sc_map->mp_pages;
157753895Smckusick 		for (i = cs->act_tag; i < pages; i++) {
157853895Smckusick 			if ((pfn = sc->sc_map->mp_addr[i]) == 0)
157953895Smckusick 				panic("SCSI:sc_dma() zero entry");
158053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
158153895Smckusick 			dmac_gsel = CH_SCSI;
158253895Smckusick 			dmac_ctag = (u_char)tag++;
158353895Smckusick 			dmac_cmap = (u_short)pfn;
158453895Smckusick #endif
158553895Smckusick 		}
158653895Smckusick #ifdef MAP_OVER_ACCESS
158753895Smckusick # if defined(mips) && defined(CPU_SINGLE)
158853895Smckusick 		dmac_gsel = CH_SCSI;
158953895Smckusick 		dmac_ctag = (u_char)tag++;
159053895Smckusick 		dmac_cmap = (u_short)pfn;
159153895Smckusick # endif
159253895Smckusick #endif
159353895Smckusick 	} else {
159453895Smckusick 		/*
159553895Smckusick 		 * Set DMAC map entry from logical address
159653895Smckusick 		 */
159753895Smckusick 		pfn = (u_int)vtophys(cs->act_point) >> PGSHIFT;
159853895Smckusick 		pages = (cs->act_trcnt >> PGSHIFT) + 2;
159953895Smckusick 		for (i = 0; i < pages; i++) {
160053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
160153895Smckusick 			dmac_gsel = CH_SCSI;
160253895Smckusick 			dmac_ctag = (u_char)tag++;
160353895Smckusick 			dmac_cmap = (u_short)pfn + i;
160453895Smckusick #endif
160553895Smckusick 		}
160653895Smckusick 	}
160753895Smckusick 
160853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
160953895Smckusick 	dmac_gsel = CH_SCSI;
161053895Smckusick 	dmac_ctag = 0;
161153895Smckusick #endif
161253895Smckusick 
161353895Smckusick 	if (phase == DAT_IN) {
161453895Smckusick 		ss->dma_stat = SC_DMAC_RD;
161553895Smckusick #if defined(mips) && defined(CPU_SINGLE)
161653895Smckusick 		/*
161753895Smckusick 		 * auto pad flag is always on
161853895Smckusick 		 */
161953895Smckusick 		dmac_gsel = CH_SCSI;
162053895Smckusick 		dmac_cctl = DM_MODE|DM_APAD;
162153895Smckusick 		DMAC_WAIT;
162253895Smckusick 		dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE;
162353895Smckusick 		DMAC_WAIT0;
162453895Smckusick #endif
162553895Smckusick 	}
162653895Smckusick 	else if (phase == DAT_OUT) {
162753895Smckusick 		ss->dma_stat = SC_DMAC_WR;
162853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
162953895Smckusick 		dmac_gsel = CH_SCSI;
163053895Smckusick 		dmac_cctl = DM_APAD;
163153895Smckusick 		DMAC_WAIT;
163253895Smckusick 		dmac_cctl = DM_APAD|DM_ENABLE;
163353895Smckusick 		DMAC_WAIT0;
163453895Smckusick #endif
163553895Smckusick 						/* DMAC start on mem->I/O */
163653895Smckusick 	}
163753895Smckusick }
163853895Smckusick 
163953895Smckusick #define MAX_TR_CNT24	((1 << 24) -1)
sc_dio_pad(cs)164053895Smckusick sc_dio_pad(cs)
164153895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
164253895Smckusick {
164353895Smckusick 	register VOLATILE int phase;
164453895Smckusick 	register int dummy;
164553895Smckusick 
164653895Smckusick 	if (cs->act_trcnt >= 0)
164753895Smckusick 		return;
164853895Smckusick 	pad_start = 1;
164953895Smckusick 
165053895Smckusick 	SET_CNT(MAX_TR_CNT24);
165153895Smckusick 	SET_CMD(SCMD_TR_PAD|R0_TRBE);
165253895Smckusick 	dummy = sc_cmonr & SC_PMASK;
165353895Smckusick 	DMAC_WAIT0;
165453895Smckusick 	if (dummy == DAT_IN)
165553895Smckusick 		dummy = sc_datr;		/* get data */
165653895Smckusick 	else
165753895Smckusick 		sc_datr = 0;			/* send data */
165853895Smckusick }
165953895Smckusick 
print_scsi_stat()166053895Smckusick print_scsi_stat()
166153895Smckusick {
166253895Smckusick 	register struct scsi_stat *ss;
166353895Smckusick 	register VOLATILE int i;
166453895Smckusick 	int dummy;
166553895Smckusick 
166653895Smckusick 	ss = &scsi_stat;
166753895Smckusick 	printf("ipc=%d wrc=%d wbc=%d\n", ss->ipc, ss->wrc, ss->wbc);
166853895Smckusick }
166953895Smckusick 
167053895Smckusick /*
167153895Smckusick  *	return 0 if it was done.  Or retun TRUE if it is busy.
167253895Smckusick  */
sc_busy(chan)167353895Smckusick sc_busy(chan)
167453895Smckusick 	register int chan;
167553895Smckusick {
167653895Smckusick 	return ((int)chan_stat[chan].sc);
167753895Smckusick }
167853895Smckusick 
167953895Smckusick 
168053895Smckusick /*
168153895Smckusick  *	append channel into Waiting Bus_free queue
168253895Smckusick  */
append_wb(cs)168353895Smckusick append_wb(cs)
168453895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
168553895Smckusick {
168653895Smckusick 	register int s;
168753895Smckusick 
168853895Smckusick 	s = splclock();			/* inhibit process switch */
168953895Smckusick 	if (wbq_actf == NULL)
169053895Smckusick 		wbq_actf = cs;
169153895Smckusick 	else
169253895Smckusick 		wbq_actl->wb_next = cs;
169353895Smckusick 	wbq_actl = cs;
169453895Smckusick 	cs->sc->sc_istatus = INST_WAIT;
169553895Smckusick 	scsi_stat.wbc++;
169653895Smckusick 	splx(s);
169753895Smckusick }
169853895Smckusick 
169953895Smckusick /*
170053895Smckusick  *	get channel from Waiting Bus_free queue
170153895Smckusick  */
get_wb_chan()170253895Smckusick get_wb_chan()
170353895Smckusick {
170453895Smckusick 	register int s;
170553895Smckusick 	register int chan;
170653895Smckusick 
170753895Smckusick 	s = splclock();			/* inhibit process switch */
170853895Smckusick 	if (wbq_actf == NULL) {
170953895Smckusick 		chan = -1;
171053895Smckusick 	} else {
171153895Smckusick 		chan = wbq_actf->chan_num;
171253895Smckusick 		if ((chan < 0) || (chan >= NTARGET) || (chan == SC_OWNID))
171353895Smckusick 			chan = -1;
171453895Smckusick 	}
171553895Smckusick 	splx(s);
171653895Smckusick 	return (chan);
171753895Smckusick }
171853895Smckusick 
171953895Smckusick /*
172053895Smckusick  *	release channel from Waiting Bus_free queue
172153895Smckusick  */
release_wb()172253895Smckusick release_wb()
172353895Smckusick {
172453895Smckusick 	register VOLATILE struct sc_chan_stat *cs;
172553895Smckusick 	register int s;
172653895Smckusick 	int error;
172753895Smckusick 
172853895Smckusick 	s = splclock();			/* inhibit process switch */
172953895Smckusick 	error = 0;
173053895Smckusick 	if (wbq_actf == NULL) {
173153895Smckusick 		error = -1;
173253895Smckusick 	} else {
173353895Smckusick 		cs = wbq_actf;
173453895Smckusick 		wbq_actf = cs->wb_next;
173553895Smckusick 		cs->wb_next = NULL;
173653895Smckusick 		if (wbq_actl == cs)
173753895Smckusick 			wbq_actl = NULL;
173853895Smckusick 		cs->sc->sc_istatus &= ~INST_WAIT;
173953895Smckusick 		scsi_stat.wbc--;
174053895Smckusick 	}
174153895Smckusick 	splx(s);
174253895Smckusick 	return (error);
174353895Smckusick }
174453895Smckusick 
adjust_transfer(cs)174553895Smckusick adjust_transfer(cs)
174653895Smckusick 	register struct sc_chan_stat *cs;
174753895Smckusick {
174853895Smckusick 	register struct scsi *sc;
174953895Smckusick 	register struct scsi_stat *ss;
175053895Smckusick 	register VOLATILE u_int remain_cnt;
175153895Smckusick 	register u_int offset;
175253895Smckusick 	u_int sent_byte;
175353895Smckusick 
175453895Smckusick 	sc = cs->sc;
175553895Smckusick 	ss = &scsi_stat;
175653895Smckusick 
175753895Smckusick 	if (pad_start) {
175853895Smckusick 		pad_start = 0;
175953895Smckusick 		remain_cnt = 0;
176053895Smckusick 	} else {
176153895Smckusick # if defined(mips) && defined(CPU_SINGLE)
176253895Smckusick 		remain_cnt = GET_CNT();
176353895Smckusick 		remain_cnt -= pad_cnt[cs->chan_num];
176453895Smckusick 		if (ss->dma_stat == SC_DMAC_WR) {
176553895Smckusick 			/*
176653895Smckusick 			 * adjust counter in the FIFO
176753895Smckusick 			 */
176853895Smckusick 			remain_cnt += sc_ffstr & R5_FIFOREM;
176953895Smckusick 		}
177053895Smckusick # endif
177153895Smckusick 	}
177253895Smckusick 
177353895Smckusick 	sent_byte = sc->sc_ctrnscnt - remain_cnt;
177453895Smckusick 	cs->act_trcnt = remain_cnt;
177553895Smckusick 
177653895Smckusick 	offset = sc->sc_coffset + sent_byte;
177753895Smckusick 	cs->act_tag += (offset >> PGSHIFT);
177853895Smckusick 	cs->act_offset = offset & PGOFSET;
177953895Smckusick 	if ((sc->sc_map == NULL) || (sc->sc_map->mp_pages <= 0))
178053895Smckusick 		cs->act_point += sent_byte;
178153895Smckusick }
1782