ncr53c500.c revision 330897
1/*	$NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $	*/
2/*	$NetBSD$	*/
3
4#define	NCV_DEBUG
5#define	NCV_STATICS
6#define	NCV_IO_CONTROL_FLAGS	(0)
7
8/*-
9 * SPDX-License-Identifier: BSD-3-Clause
10 *
11 * [NetBSD for NEC PC-98 series]
12 *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
13 *	NetBSD/pc98 porting staff. All rights reserved.
14 *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
15 *	Naofumi HONDA. All rights reserved.
16 *
17 *  Redistribution and use in source and binary forms, with or without
18 *  modification, are permitted provided that the following conditions
19 *  are met:
20 *  1. Redistributions of source code must retain the above copyright
21 *     notice, this list of conditions and the following disclaimer.
22 *  2. Redistributions in binary form must reproduce the above copyright
23 *     notice, this list of conditions and the following disclaimer in the
24 *     documentation and/or other materials provided with the distribution.
25 *  3. The name of the author may not be used to endorse or promote products
26 *     derived from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
32 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: stable/11/sys/dev/ncv/ncr53c500.c 330897 2018-03-14 03:19:51Z eadler $");
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/kernel.h>
47#include <sys/bio.h>
48#include <sys/buf.h>
49#include <sys/queue.h>
50#include <sys/malloc.h>
51#include <sys/errno.h>
52#include <sys/rman.h>
53
54#include <machine/cpu.h>
55#include <machine/bus.h>
56
57#include <compat/netbsd/dvcfg.h>
58
59#include <cam/scsi/scsi_low.h>
60
61#include <dev/ncv/ncr53c500reg.h>
62#include <dev/ncv/ncr53c500hw.h>
63#include <dev/ncv/ncr53c500var.h>
64
65#include <dev/ncv/ncr53c500hwtab.h>
66
67#define	NCV_MAX_DATA_SIZE	(64 * 1024)
68#define	NCV_DELAY_MAX		(2 * 1000 * 1000)
69#define	NCV_DELAY_INTERVAL	(1)
70#define	NCV_PADDING_SIZE	(32)
71
72/***************************************************
73 * IO control
74 ***************************************************/
75#define	NCV_READ_INTERRUPTS_DRIVEN	0x0001
76#define	NCV_WRITE_INTERRUPTS_DRIVEN	0x0002
77#define	NCV_ENABLE_FAST_SCSI		0x0010
78#define	NCV_FAST_INTERRUPTS		0x0100
79
80u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
81int ncv_data_read_bytes = 4096;
82int ncv_data_write_bytes = 4096;
83
84/***************************************************
85 * DEBUG
86 ***************************************************/
87#ifdef	NCV_DEBUG
88static int ncv_debug;
89#endif	/* NCV_DEBUG */
90
91#ifdef	NCV_STATICS
92static struct ncv_statics {
93	int disconnect;
94	int reselect;
95} ncv_statics;
96#endif	/* NCV_STATICS */
97
98/***************************************************
99 * DEVICE STRUCTURE
100 ***************************************************/
101extern struct cfdriver ncv_cd;
102
103/**************************************************************
104 * DECLARE
105 **************************************************************/
106/* static */
107static void ncv_pio_read(struct ncv_softc *, u_int8_t *, u_int);
108static void ncv_pio_write(struct ncv_softc *, u_int8_t *, u_int);
109static int ncv_msg(struct ncv_softc *, struct targ_info *, u_int);
110static int ncv_reselected(struct ncv_softc *);
111static int ncv_disconnected(struct ncv_softc *, struct targ_info *);
112
113static __inline void ncvhw_set_count(struct resource *, int);
114static __inline u_int ncvhw_get_count(struct resource *);
115static __inline void ncvhw_select_register_0(struct resource *, struct ncv_hw *);
116static __inline void ncvhw_select_register_1(struct resource *, struct ncv_hw *);
117static __inline void ncvhw_fpush(struct resource *, u_int8_t *, int);
118
119static void ncv_pdma_end(struct ncv_softc *sc, struct targ_info *);
120static int ncv_world_start(struct ncv_softc *, int);
121static void ncvhw_bus_reset(struct ncv_softc *);
122static void ncvhw_reset(struct resource *, struct ncv_hw *);
123static int ncvhw_check(struct resource *, struct ncv_hw *);
124static void ncvhw_init(struct resource *, struct ncv_hw *);
125static int ncvhw_start_selection(struct ncv_softc *sc, struct slccb *);
126static void ncvhw_attention(struct ncv_softc *);
127static int ncv_ccb_nexus_establish(struct ncv_softc *);
128static int ncv_lun_nexus_establish(struct ncv_softc *);
129static int ncv_target_nexus_establish(struct ncv_softc *);
130static int ncv_targ_init(struct ncv_softc *, struct targ_info *, int);
131static int ncv_catch_intr(struct ncv_softc *);
132#ifdef	NCV_POWER_CONTROL
133static int ncvhw_power(struct ncv_softc *, u_int);
134#endif	/* NCV_POWER_CONTROL */
135static __inline void ncv_setup_and_start_pio(struct ncv_softc *, u_int);
136
137struct scsi_low_funcs ncv_funcs = {
138	SC_LOW_INIT_T ncv_world_start,
139	SC_LOW_BUSRST_T ncvhw_bus_reset,
140	SC_LOW_TARG_INIT_T ncv_targ_init,
141	SC_LOW_LUN_INIT_T NULL,
142
143	SC_LOW_SELECT_T ncvhw_start_selection,
144	SC_LOW_NEXUS_T ncv_lun_nexus_establish,
145	SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
146
147	SC_LOW_ATTEN_T ncvhw_attention,
148	SC_LOW_MSG_T ncv_msg,
149
150	SC_LOW_TIMEOUT_T NULL,
151	SC_LOW_POLL_T ncvintr,
152
153	NULL,	/* SC_LOW_POWER_T ncvhw_power, */
154};
155
156/**************************************************************
157 * hwfuncs
158 **************************************************************/
159static __inline void
160ncvhw_select_register_0(struct resource *res, struct ncv_hw *hw)
161{
162
163	bus_write_1(res, cr0_cfg4, hw->hw_cfg4);
164}
165
166static __inline void
167ncvhw_select_register_1(struct resource *res, struct ncv_hw *hw)
168{
169
170	bus_write_1(res, cr1_cfg5, hw->hw_cfg5);
171}
172
173static __inline void
174ncvhw_fpush(struct resource *res, u_int8_t *buf, int len)
175{
176	int ptr;
177
178	for (ptr = 0; ptr < len; ptr ++)
179		bus_write_1(res, cr0_sfifo, buf[ptr]);
180}
181
182static __inline void
183ncvhw_set_count(struct resource *res, int count)
184{
185
186	bus_write_1(res, cr0_tclsb, (u_int8_t) count);
187	bus_write_1(res, cr0_tcmsb, (u_int8_t) (count >> NBBY));
188	bus_write_1(res, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
189}
190
191static __inline u_int
192ncvhw_get_count(struct resource *res)
193{
194	u_int count;
195
196	count = (u_int) bus_read_1(res, cr0_tclsb);
197	count |= ((u_int) bus_read_1(res, cr0_tcmsb)) << NBBY;
198	count |= ((u_int) bus_read_1(res, cr0_tchsb)) << (NBBY * 2);
199	return count;
200}
201
202static int
203ncvhw_check(struct resource *res, struct ncv_hw *hw)
204{
205	u_int8_t stat;
206
207	ncvhw_select_register_0(res, hw);
208	bus_write_1(res, cr0_cmd, CMD_NOP | CMD_DMA);
209	if (bus_read_1(res, cr0_cmd) != (CMD_NOP | CMD_DMA))
210	{
211#ifdef	NCV_DEBUG
212		printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
213#endif	/* NCV_DEBUG */
214		return ENODEV;
215	}
216
217	bus_write_1(res, cr0_cmd, CMD_NOP);
218	if (bus_read_1(res, cr0_cmd) != CMD_NOP)
219	{
220#ifdef	NCV_DEBUG
221		printf("ncv: cr0_cmd CMD_NOP failed\n");
222#endif	/* NCV_DEBUG */
223		return ENODEV;
224	}
225
226	/* hardware reset */
227	ncvhw_reset(res, hw);
228	ncvhw_init(res, hw);
229
230	/* bus reset */
231	ncvhw_select_register_0(res, hw);
232	bus_write_1(res, cr0_cmd, CMD_FLUSH);
233	bus_write_1(res, cr0_cmd, CMD_RSTSCSI);
234	bus_write_1(res, cr0_cmd, CMD_NOP | CMD_DMA);
235	DELAY(100 * 1000);
236
237	/* check response */
238	bus_read_1(res, cr0_stat);
239	stat = bus_read_1(res, cr0_istat);
240	DELAY(1000);
241
242	if (((stat & INTR_SBR) == 0) ||
243	    (bus_read_1(res, cr0_istat) & INTR_SBR))
244	{
245#ifdef	NCV_DEBUG
246		printf("ncv: cr0_istat SCSI BUS RESET failed\n");
247#endif	/* NCV_DEBUG */
248		return ENODEV;
249	}
250
251	return 0;
252}
253
254static void
255ncvhw_reset(struct resource *res, struct ncv_hw *hw)
256{
257
258	ncvhw_select_register_0(res, hw);
259
260	/* dummy cmd twice */
261	bus_write_1(res, cr0_cmd, CMD_NOP);
262	bus_write_1(res, cr0_cmd, CMD_NOP);
263
264	/* chip reset */
265	bus_write_1(res, cr0_cmd, CMD_RSTCHIP);
266
267	/* again dummy cmd twice */
268	bus_write_1(res, cr0_cmd, CMD_NOP);
269	bus_write_1(res, cr0_cmd, CMD_NOP);
270}
271
272static void
273ncvhw_init(struct resource *res, struct ncv_hw *hw)
274{
275
276	ncvhw_select_register_0(res, hw);
277	bus_write_1(res, cr0_clk, hw->hw_clk);
278	bus_write_1(res, cr0_srtout, SEL_TOUT);
279	bus_write_1(res, cr0_period, 0);
280	bus_write_1(res, cr0_offs, 0);
281
282	bus_write_1(res, cr0_cfg1, hw->hw_cfg1);
283	bus_write_1(res, cr0_cfg2, hw->hw_cfg2);
284	bus_write_1(res, cr0_cfg3, hw->hw_cfg3);
285	bus_write_1(res, cr0_tchsb, 0);
286
287	ncvhw_select_register_1(res, hw);
288	bus_write_1(res, cr1_fstat, 0x0);
289	bus_write_1(res, cr1_pflag, 0x0);
290	bus_write_1(res, cr1_atacmd, ATACMD_ENGAGE);
291
292	ncvhw_select_register_0(res, hw);
293}
294
295#ifdef	NCV_POWER_CONTROL
296static int
297ncvhw_power(sc, flags)
298	struct ncv_softc *sc;
299	u_int flags;
300{
301	struct scsi_low_softc *slp = &sc->sc_sclow;
302	struct resource *res = sc->port_res;
303
304	if (flags == SCSI_LOW_POWDOWN)
305	{
306		device_printf(slp->sl_dev, "power down\n");
307		ncvhw_select_register_1(res, &sc->sc_hw);
308		bus_write_1(res, cr1_atacmd, ATACMD_POWDOWN);
309	}
310	else
311	{
312		switch (sc->sc_rstep)
313		{
314		case 0:
315			device_printf(slp->sl_dev, "resume step O\n");
316			ncvhw_select_register_1(res, &sc->sc_hw);
317			bus_write_1(res, cr1_atacmd, ATACMD_ENGAGE);
318			break;
319
320		case 1:
321			device_printf(slp->sl_dev, "resume step I\n");
322			ncvhw_reset(res, &sc->sc_hw);
323			ncvhw_init(res, &sc->sc_hw);
324			break;
325		}
326	}
327
328	return 0;
329}
330#endif	/* NCV_POWER_CONTROL */
331
332/**************************************************************
333 * scsi low interface
334 **************************************************************/
335static void
336ncvhw_attention(sc)
337	struct ncv_softc *sc;
338{
339
340	bus_write_1(sc->port_res, cr0_cmd, CMD_SETATN);
341	DELAY(10);
342}
343
344static void
345ncvhw_bus_reset(sc)
346	struct ncv_softc *sc;
347{
348
349	ncvhw_select_register_0(sc->port_res, &sc->sc_hw);
350	bus_write_1(sc->port_res, cr0_cmd, CMD_FLUSH);
351	bus_write_1(sc->port_res, cr0_cmd, CMD_RSTSCSI);
352	bus_write_1(sc->port_res, cr0_cmd, CMD_NOP | CMD_DMA);
353}
354
355static int
356ncvhw_start_selection(sc, cb)
357	struct ncv_softc *sc;
358	struct slccb *cb;
359{
360	struct scsi_low_softc *slp = &sc->sc_sclow;
361	struct resource *res = sc->port_res;
362	struct targ_info *ti = cb->ti;
363	int len;
364	u_int flags;
365	u_int8_t cmd;
366
367	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
368	sc->sc_compseq = 0;
369	if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
370	{
371		cmd = CMD_SELATN;
372		sc->sc_selstop = 0;
373		flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
374	}
375	else if (scsi_low_is_msgout_continue(ti,
376			SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
377	{
378		cmd = CMD_SELATN3;
379		sc->sc_selstop = 0;
380		flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
381	}
382	else
383	{
384		cmd = CMD_SELATNS;
385		sc->sc_selstop = 1;
386		flags = SCSI_LOW_MSGOUT_INIT;
387	}
388
389	ncvhw_select_register_0(res, &sc->sc_hw);
390	if ((bus_read_1(res, cr0_stat) & STAT_INT) != 0)
391		return SCSI_LOW_START_FAIL;
392
393	ncv_target_nexus_establish(sc);
394
395	len = scsi_low_msgout(slp, ti, flags);
396	if (sc->sc_selstop == 0)
397		scsi_low_cmd(slp, ti);
398
399	if ((bus_read_1(res, cr0_stat) & STAT_INT) != 0)
400		return SCSI_LOW_START_FAIL;
401
402	bus_write_1(res, cr0_dstid, ti->ti_id);
403	bus_write_1(res, cr0_cmd, CMD_FLUSH);
404	ncvhw_fpush(res, ti->ti_msgoutstr, len);
405	if (sc->sc_selstop == 0)
406	{
407		ncvhw_fpush(res,
408			    slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
409	}
410	bus_write_1(res, cr0_cmd, cmd);
411
412	SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
413	return SCSI_LOW_START_OK;
414}
415
416static int
417ncv_world_start(sc, fdone)
418	struct ncv_softc *sc;
419	int fdone;
420{
421	struct scsi_low_softc *slp = &sc->sc_sclow;
422	struct resource *res = sc->port_res;
423	u_int8_t stat;
424
425	if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
426		sc->sc_hw.hw_cfg1 |= C1_PARENB;
427	else
428		sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
429
430	ncvhw_reset(res, &sc->sc_hw);
431	ncvhw_init(res, &sc->sc_hw);
432
433	scsi_low_bus_reset(slp);
434
435	ncvhw_select_register_0(res, &sc->sc_hw);
436	bus_read_1(res, cr0_stat);
437	stat = bus_read_1(res, cr0_istat);
438	DELAY(1000);
439
440	if (((stat & INTR_SBR) == 0) ||
441	    (bus_read_1(res, cr0_istat) & INTR_SBR))
442		return ENODEV;
443
444	return 0;
445}
446
447static int
448ncv_msg(sc, ti, msg)
449	struct ncv_softc *sc;
450	struct targ_info *ti;
451	u_int msg;
452{
453	struct resource *res = sc->port_res;
454	struct ncv_targ_info *nti = (void *) ti;
455	u_int hwcycle, period;
456
457	if ((msg & SCSI_LOW_MSG_WIDE) != 0)
458	{
459		if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
460		{
461			ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
462			return EINVAL;
463		}
464		return 0;
465	}
466
467	if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
468		return 0;
469
470	period = ti->ti_maxsynch.period;
471	hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
472	hwcycle = 1000 / hwcycle;
473
474	if (period < 200 / 4 && period >= 100 / 4)
475		nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
476	else
477		nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
478
479	period = ((period * 40 / hwcycle) + 5) / 10;
480	nti->nti_reg_period = period & 0x1f;
481	nti->nti_reg_offset = ti->ti_maxsynch.offset;
482
483	bus_write_1(res, cr0_period, nti->nti_reg_period);
484	bus_write_1(res, cr0_offs, nti->nti_reg_offset);
485	bus_write_1(res, cr0_cfg3, nti->nti_reg_cfg3);
486	return 0;
487}
488
489static int
490ncv_targ_init(sc, ti, action)
491	struct ncv_softc *sc;
492	struct targ_info *ti;
493	int action;
494{
495	struct ncv_targ_info *nti = (void *) ti;
496
497	if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
498	{
499		ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
500		ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
501		ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
502
503		nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
504		nti->nti_reg_period = 0;
505		nti->nti_reg_offset = 0;
506	}
507	return 0;
508}
509
510/**************************************************************
511 * General probe attach
512 **************************************************************/
513static int ncv_setup_img(struct ncv_hw *, u_int, int);
514
515static int
516ncv_setup_img(hw, dvcfg, hostid)
517	struct ncv_hw *hw;
518	u_int dvcfg;
519	int hostid;
520{
521
522	if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
523	{
524		printf("ncv: invalid dvcfg flags\n");
525		return EINVAL;
526	}
527
528	if (NCV_C5IMG(dvcfg) != 0)
529	{
530		hw->hw_cfg5 = NCV_C5IMG(dvcfg);
531		hw->hw_clk = NCV_CLKFACTOR(dvcfg);
532
533		if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
534		    (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
535			hw->hw_mperiod = 100 / 4;
536
537		if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
538			hw->hw_cfg3_fclk = 0x04;
539
540		if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
541			hw->hw_cfg2 &= ~C2_SCSI2;
542
543		if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
544			hw->hw_cfg1 |= C1_SLOW;
545	}
546
547	/* setup configuration image 3 */
548	if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
549		hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
550	else
551		hw->hw_cfg3 |= hw->hw_cfg3_fclk;
552
553	/* setup configuration image 1 */
554	hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
555	return 0;
556}
557
558int
559ncvprobesubr(struct resource *res, u_int dvcfg, int hsid)
560{
561	struct ncv_hw hwtab;
562
563	hwtab = ncv_template;
564	if (ncv_setup_img(&hwtab, dvcfg, hsid))
565		return 0;
566	if (ncvhw_check(res, &hwtab) != 0)
567		return 0;
568
569	return 1;
570}
571
572void
573ncvattachsubr(sc)
574	struct ncv_softc *sc;
575{
576	struct scsi_low_softc *slp = &sc->sc_sclow;
577
578	printf("\n");
579	sc->sc_hw = ncv_template;
580	ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
581	slp->sl_funcs = &ncv_funcs;
582	slp->sl_flags |= HW_READ_PADDING;
583	sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
584
585	(void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
586			       sizeof(struct ncv_targ_info), 0);
587}
588
589/**************************************************************
590 * PDMA
591 **************************************************************/
592static __inline void
593ncv_setup_and_start_pio(sc, reqlen)
594	struct ncv_softc *sc;
595	u_int reqlen;
596{
597	struct resource *res = sc->port_res;
598
599	ncvhw_select_register_0(res, &sc->sc_hw);
600	ncvhw_set_count(res, reqlen);
601	bus_write_1(res, cr0_cmd, CMD_TRANS | CMD_DMA);
602
603	ncvhw_select_register_1(res, &sc->sc_hw);
604	bus_write_1(res, cr1_fstat, FIFO_EN);
605}
606
607static void
608ncv_pdma_end(sc, ti)
609	struct ncv_softc *sc;
610	struct targ_info *ti;
611{
612	struct scsi_low_softc *slp = &sc->sc_sclow;
613	struct resource *res = sc->port_res;
614	int len;
615
616	slp->sl_flags &= ~HW_PDMASTART;
617	if (slp->sl_Qnexus == NULL)
618	{
619		slp->sl_error |= PDMAERR;
620		goto out;
621	}
622
623	if (ti->ti_phase == PH_DATA)
624	{
625		len = ncvhw_get_count(res);
626		if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
627			len += (bus_read_1(res,
628				cr0_sffl) & CR0_SFFLR_BMASK);
629
630		if ((u_int) len <= (u_int) sc->sc_sdatalen)
631		{
632			if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
633			    sc->sc_tdatalen != len)
634				goto bad;
635
636			len = sc->sc_sdatalen - len;
637			if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
638				goto bad;
639
640			slp->sl_scp.scp_data += len;
641			slp->sl_scp.scp_datalen -= len;
642		}
643		else
644		{
645bad:
646			if ((slp->sl_error & PDMAERR) == 0)
647			{
648				device_printf(slp->sl_dev,
649				    "strange cnt hw 0x%x soft 0x%x\n", len,
650				    slp->sl_scp.scp_datalen);
651			}
652			slp->sl_error |= PDMAERR;
653		}
654		scsi_low_data_finish(slp);
655	}
656	else
657	{
658		device_printf(slp->sl_dev, "data phase miss\n");
659		slp->sl_error |= PDMAERR;
660	}
661
662out:
663	ncvhw_select_register_1(res, &sc->sc_hw);
664	bus_write_1(res, cr1_fstat, 0);
665	ncvhw_select_register_0(res, &sc->sc_hw);
666}
667
668static void
669ncv_pio_read(sc, buf, reqlen)
670	struct ncv_softc *sc;
671	u_int8_t *buf;
672	u_int reqlen;
673{
674	struct scsi_low_softc *slp = &sc->sc_sclow;
675	struct resource *res = sc->port_res;
676	int tout;
677	register u_int8_t fstat;
678
679	ncv_setup_and_start_pio(sc, reqlen);
680	slp->sl_flags |= HW_PDMASTART;
681	sc->sc_sdatalen = reqlen;
682	tout = sc->sc_tmaxcnt;
683
684	while (reqlen >= FIFO_F_SZ && tout -- > 0)
685	{
686		fstat = bus_read_1(res, cr1_fstat);
687		if (fstat == (u_int8_t) -1)
688			goto out;
689		if (fstat & FIFO_F)
690		{
691#define	NCV_FAST32_ACCESS
692#ifdef	NCV_FAST32_ACCESS
693			bus_read_multi_4(res, cr1_fdata,
694				(u_int32_t *) buf, FIFO_F_SZ / 4);
695#else	/* !NCV_FAST32_ACCESS */
696			bus_read_multi_2(res, cr1_fdata,
697				(u_int16_t *) buf, FIFO_F_SZ / 2);
698#endif	/* !NCV_FAST32_ACCESS */
699			buf += FIFO_F_SZ;
700			reqlen -= FIFO_F_SZ;
701		}
702		else
703		{
704			if (fstat & FIFO_BRK)
705				break;
706
707			DELAY(1);
708		}
709	}
710
711	while (reqlen > 0 && tout -- > 0)
712	{
713		fstat = bus_read_1(res, cr1_fstat);
714		if ((fstat & FIFO_E) == 0)
715		{
716			*buf++ = bus_read_1(res, cr1_fdata);
717			reqlen --;
718		}
719		else
720		{
721			 if (fstat & FIFO_BRK)
722				break;
723
724			DELAY(1);
725		}
726	}
727
728out:
729	ncvhw_select_register_0(res, &sc->sc_hw);
730	sc->sc_tdatalen = reqlen;
731}
732
733static void
734ncv_pio_write(sc, buf, reqlen)
735	struct ncv_softc *sc;
736	u_int8_t *buf;
737	u_int reqlen;
738{
739	struct scsi_low_softc *slp = &sc->sc_sclow;
740	struct resource *res = sc->port_res;
741	int tout;
742	register u_int8_t fstat;
743
744	ncv_setup_and_start_pio(sc, reqlen);
745	sc->sc_sdatalen = reqlen;
746	tout = sc->sc_tmaxcnt;
747	slp->sl_flags |= HW_PDMASTART;
748
749	while (reqlen >= FIFO_F_SZ && tout -- > 0)
750	{
751		fstat = bus_read_1(res, cr1_fstat);
752		if (fstat & FIFO_BRK)
753			goto done;
754
755		if ((fstat & FIFO_E) != 0)
756		{
757#ifdef	NCV_FAST32_ACCESS
758			bus_write_multi_4(res, cr1_fdata,
759				(u_int32_t *) buf, FIFO_F_SZ / 4);
760#else	/* !NCV_FAST32_ACCESS */
761			bus_write_multi_2(res, cr1_fdata,
762				(u_int16_t *) buf, FIFO_F_SZ / 2);
763#endif	/* !NCV_FAST32_ACCESS */
764			buf += FIFO_F_SZ;
765			reqlen -= FIFO_F_SZ;
766		}
767		else
768		{
769			DELAY(1);
770		}
771	}
772
773	while (reqlen > 0 && tout -- > 0)
774	{
775		fstat = bus_read_1(res, cr1_fstat);
776		if (fstat & FIFO_BRK)
777			break;
778
779		if ((fstat & FIFO_F) == 0) /* fifo not full */
780		{
781			bus_write_1(res, cr1_fdata, *buf++);
782			reqlen --;
783		}
784		else
785		{
786			DELAY(1);
787		}
788	}
789
790done:
791	ncvhw_select_register_0(res, &sc->sc_hw);
792}
793
794/**************************************************************
795 * disconnect & reselect (HW low)
796 **************************************************************/
797static int
798ncv_reselected(sc)
799	struct ncv_softc *sc;
800{
801	struct scsi_low_softc *slp = &sc->sc_sclow;
802	struct resource *res = sc->port_res;
803	struct targ_info *ti;
804	u_int sid;
805
806	if ((bus_read_1(res, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
807	{
808		device_printf(slp->sl_dev, "illegal fifo bytes\n");
809		scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
810		return EJUSTRETURN;
811	}
812
813	sid = (u_int) bus_read_1(res, cr0_sfifo);
814	sid &= ~(1 << slp->sl_hostid);
815	sid = ffs(sid) - 1;
816	ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
817	if (ti == NULL)
818		return EJUSTRETURN;
819
820#ifdef	NCV_STATICS
821	ncv_statics.reselect ++;
822#endif	/* NCV_STATICS */
823	bus_write_1(res, cr0_dstid, sid);
824	return 0;
825}
826
827static int
828ncv_disconnected(sc, ti)
829	struct ncv_softc *sc;
830	struct targ_info *ti;
831{
832	struct scsi_low_softc *slp = &sc->sc_sclow;
833	struct resource *res = sc->port_res;
834
835	bus_write_1(res, cr0_cmd, CMD_FLUSH);
836	bus_write_1(res, cr0_cmd, CMD_ENSEL);
837
838#ifdef	NCV_STATICS
839	ncv_statics.disconnect ++;
840#endif	/* NCV_STATICS */
841
842	scsi_low_disconnected(slp, ti);
843	return 1;
844}
845
846/**************************************************************
847 * SEQUENCER
848 **************************************************************/
849static int
850ncv_target_nexus_establish(sc)
851	struct ncv_softc *sc;
852{
853	struct scsi_low_softc *slp = &sc->sc_sclow;
854	struct targ_info *ti = slp->sl_Tnexus;
855	struct ncv_targ_info *nti = (void *) ti;
856	struct resource *res = sc->port_res;
857
858	bus_write_1(res, cr0_period, nti->nti_reg_period);
859	bus_write_1(res, cr0_offs, nti->nti_reg_offset);
860	bus_write_1(res, cr0_cfg3, nti->nti_reg_cfg3);
861	return 0;
862}
863
864static int
865ncv_lun_nexus_establish(sc)
866	struct ncv_softc *sc;
867{
868
869	return 0;
870}
871
872static int
873ncv_ccb_nexus_establish(sc)
874	struct ncv_softc *sc;
875{
876	struct scsi_low_softc *slp = &sc->sc_sclow;
877	struct slccb *cb = slp->sl_Qnexus;
878
879	sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
880	return 0;
881}
882
883static int
884ncv_catch_intr(sc)
885	struct ncv_softc *sc;
886{
887	struct resource *res = sc->port_res;
888	int wc;
889	register u_int8_t status;
890
891	for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
892	{
893		status = bus_read_1(res, cr0_stat);
894		if ((status & STAT_INT) != 0)
895			return 0;
896
897		DELAY(NCV_DELAY_INTERVAL);
898	}
899	return EJUSTRETURN;
900}
901
902int
903ncvintr(arg)
904	void *arg;
905{
906	struct ncv_softc *sc = arg;
907	struct scsi_low_softc *slp = &sc->sc_sclow;
908	struct resource *res = sc->port_res;
909	struct targ_info *ti;
910	struct buf *bp;
911	u_int derror, flags;
912	int len;
913	u_int8_t regv, status, ireason;
914
915again:
916	if (slp->sl_flags & HW_INACTIVE)
917		return 0;
918
919	/********************************************
920	 * Status
921	 ********************************************/
922	ncvhw_select_register_0(res, &sc->sc_hw);
923	status = bus_read_1(res, cr0_stat);
924	if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
925		return 0;
926
927	ireason = bus_read_1(res, cr0_istat);
928	if ((ireason & INTR_SBR) != 0)
929	{
930		u_int8_t val;
931
932		/* avoid power off hangup */
933		val = bus_read_1(res, cr0_cfg1);
934		bus_write_1(res, cr0_cfg1, val | C1_SRR);
935
936		/* status init */
937		scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
938				 "bus reset (power off?)");
939		return 1;
940	}
941
942	/********************************************
943	 * Debug section
944	 ********************************************/
945#ifdef	NCV_DEBUG
946	if (ncv_debug)
947	{
948		scsi_low_print(slp, NULL);
949		device_printf(slp->sl_dev, "st %x ist %x\n\n",
950			status, ireason);
951#ifdef	KDB
952		if (ncv_debug > 1)
953			kdb_enter(KDB_WHY_CAM, "ncv");
954#endif	/* KDB */
955	}
956#endif	/* NCV_DEBUG */
957
958	/********************************************
959	 * Reselect or Disconnect or Nexus check
960	 ********************************************/
961	/* (I) reselect */
962	if (ireason == INTR_RESELECT)
963	{
964		if (ncv_reselected(sc) == EJUSTRETURN)
965			return 1;
966	}
967
968	/* (II) nexus */
969	if ((ti = slp->sl_Tnexus) == NULL)
970		return 0;
971
972	derror = 0;
973	if ((status & (STAT_PE | STAT_GE)) != 0)
974	{
975		slp->sl_error |= PARITYERR;
976		if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
977			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
978		else
979			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
980		derror = SCSI_LOW_DATA_PE;
981	}
982
983	if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
984	{
985		if ((ireason & INTR_ILL) == 0)
986			return ncv_disconnected(sc, ti);
987
988		slp->sl_error |= FATALIO;
989		scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
990		return 1;
991	}
992
993	/********************************************
994	 * Internal scsi phase
995	 ********************************************/
996	switch (ti->ti_phase)
997	{
998	case PH_SELSTART:
999		scsi_low_arbit_win(slp);
1000		SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1001
1002		if (sc->sc_selstop == 0)
1003		{
1004			/* XXX:
1005		 	 * Here scsi phases expected are
1006			 * DATA PHASE:
1007		 	 * MSGIN     : target wants to disconnect the host.
1008			 * STATUSIN  : immediate command completed.
1009			 * CMD PHASE : command out failed
1010			 * MSGOUT    : identify command failed.
1011			 */
1012			if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1013				break;
1014		}
1015		else
1016		{
1017			if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1018				break;
1019			if ((ireason & INTR_FC) != 0)
1020			{
1021				SCSI_LOW_ASSERT_ATN(slp);
1022			}
1023		}
1024		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1025		break;
1026
1027	case PH_RESEL:
1028		ncv_target_nexus_establish(sc);
1029		if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1030		{
1031			device_printf(slp->sl_dev,
1032			    "unexpected phase after reselect\n");
1033			slp->sl_error |= FATALIO;
1034			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1035			return 1;
1036		}
1037		break;
1038
1039	default:
1040		if ((slp->sl_flags & HW_PDMASTART) != 0)
1041		{
1042			ncv_pdma_end(sc, ti);
1043		}
1044		break;
1045	}
1046
1047	/********************************************
1048	 * Scsi phase sequencer
1049	 ********************************************/
1050	switch (status & PHASE_MASK)
1051	{
1052	case DATA_OUT_PHASE: /* data out */
1053		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1054		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1055		{
1056			scsi_low_attention(slp);
1057		}
1058
1059		if (slp->sl_scp.scp_datalen <= 0)
1060		{
1061			if ((ireason & INTR_BS) == 0)
1062				break;
1063
1064			if ((slp->sl_error & PDMAERR) == 0)
1065				device_printf(slp->sl_dev, "data underrun\n");
1066			slp->sl_error |= PDMAERR;
1067
1068			if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1069			{
1070				u_int8_t padding[NCV_PADDING_SIZE];
1071
1072				bzero(padding, sizeof(padding));
1073				ncv_pio_write(sc, padding, sizeof(padding));
1074			}
1075			else
1076			{
1077				device_printf(slp->sl_dev,
1078				    "write padding required\n");
1079			}
1080		}
1081		else
1082		{
1083			len = slp->sl_scp.scp_datalen;
1084			if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1085			{
1086				if (len > ncv_data_write_bytes)
1087					len = ncv_data_write_bytes;
1088			}
1089			ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1090		}
1091		break;
1092
1093	case DATA_IN_PHASE: /* data in */
1094		SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1095		if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1096		{
1097			scsi_low_attention(slp);
1098		}
1099
1100		if (slp->sl_scp.scp_datalen <= 0)
1101		{
1102			if ((ireason & INTR_BS) == 0)
1103				break;
1104
1105			if ((slp->sl_error & PDMAERR) == 0)
1106				device_printf(slp->sl_dev, "data overrun\n");
1107			slp->sl_error |= PDMAERR;
1108
1109			if ((slp->sl_flags & HW_READ_PADDING) != 0)
1110			{
1111				u_int8_t padding[NCV_PADDING_SIZE];
1112
1113				ncv_pio_read(sc, padding, sizeof(padding));
1114			}
1115			else
1116			{
1117				device_printf(slp->sl_dev,
1118				    "read padding required\n");
1119				break;
1120			}
1121		}
1122		else
1123		{
1124			len = slp->sl_scp.scp_datalen;
1125			if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1126			{
1127				if (len > ncv_data_read_bytes)
1128					len = ncv_data_read_bytes;
1129			}
1130			ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1131		}
1132		break;
1133
1134	case COMMAND_PHASE: /* cmd out */
1135		SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1136		if (scsi_low_cmd(slp, ti) != 0)
1137		{
1138			scsi_low_attention(slp);
1139		}
1140
1141		bus_write_1(res, cr0_cmd, CMD_FLUSH);
1142		ncvhw_fpush(res,
1143			    slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1144		bus_write_1(res, cr0_cmd, CMD_TRANS);
1145		break;
1146
1147	case STATUS_PHASE: /* status in */
1148		SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1149		bus_write_1(res, cr0_cmd, CMD_FLUSH);
1150		bus_write_1(res, cr0_cmd, CMD_ICCS);
1151		sc->sc_compseq = 1;
1152		break;
1153
1154	default:
1155		break;
1156
1157	case MESSAGE_OUT_PHASE: /* msg out */
1158		SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1159		bus_write_1(res, cr0_cmd, CMD_FLUSH);
1160
1161		flags = SCSI_LOW_MSGOUT_UNIFY;
1162		if (ti->ti_ophase != ti->ti_phase)
1163			flags |= SCSI_LOW_MSGOUT_INIT;
1164		len = scsi_low_msgout(slp, ti, flags);
1165
1166		if (len > 1 && slp->sl_atten == 0)
1167		{
1168			scsi_low_attention(slp);
1169		}
1170
1171		ncvhw_fpush(res, ti->ti_msgoutstr, len);
1172		bus_write_1(res, cr0_cmd, CMD_TRANS);
1173		SCSI_LOW_DEASSERT_ATN(slp);
1174		break;
1175
1176	case MESSAGE_IN_PHASE: /* msg in */
1177		SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1178
1179		len = bus_read_1(res, cr0_sffl) & CR0_SFFLR_BMASK;
1180		if (sc->sc_compseq != 0)
1181		{
1182			sc->sc_compseq = 0;
1183			if ((ireason & INTR_FC) && len == 2)
1184			{
1185				regv = bus_read_1(res, cr0_sfifo);
1186				scsi_low_statusin(slp, ti, regv | derror);
1187				len --;
1188			}
1189			else
1190			{
1191				slp->sl_error |= FATALIO;
1192				scsi_low_assert_msg(slp, ti,
1193						    SCSI_LOW_MSG_ABORT, 1);
1194				bus_write_1(res, cr0_cmd, CMD_MSGOK);
1195				break;
1196			}
1197		}
1198		else if (ireason & INTR_BS)
1199		{
1200			bus_write_1(res, cr0_cmd, CMD_FLUSH);
1201			bus_write_1(res, cr0_cmd, CMD_TRANS);
1202			if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1203			{
1204				if (ncv_catch_intr(sc) == 0)
1205					goto again;
1206			}
1207			break;
1208		}
1209
1210		if ((ireason & INTR_FC) && len == 1)
1211		{
1212			regv = bus_read_1(res, cr0_sfifo);
1213			if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1214			{
1215				if (scsi_low_is_msgout_continue(ti, 0) != 0)
1216				{
1217					scsi_low_attention(slp);
1218				}
1219			}
1220			bus_write_1(res, cr0_cmd, CMD_MSGOK);
1221			if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1222			{
1223				/* XXX:
1224				 * clear a pending interrupt and sync with
1225				 * a next interrupt!
1226				 */
1227				ncv_catch_intr(sc);
1228			}
1229		}
1230		else
1231		{
1232			slp->sl_error |= FATALIO;
1233			scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1234			bus_write_1(res, cr0_cmd, CMD_MSGOK);
1235		}
1236		break;
1237	}
1238
1239	return 1;
1240}
1241