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