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