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