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