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