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