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