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