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