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