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