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