1 /* $FreeBSD: src/sys/dev/ncv/ncr53c500.c,v 1.1.2.4 2001/12/17 13:30:18 non Exp $ */
2 /* $NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $ */
7 #define NCV_IO_CONTROL_FLAGS (0)
10 * [NetBSD for NEC PC-98 series]
11 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
12 * NetBSD/pc98 porting staff. All rights reserved.
13 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
14 * Naofumi HONDA. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #if defined(__FreeBSD__) && __FreeBSD_version >= 500001
46 #endif /* __FreeBSD__ */
48 #include <sys/queue.h>
49 #include <sys/malloc.h>
50 #include <sys/errno.h>
53 #include <sys/device.h>
54 #include <machine/bus.h>
55 #include <machine/intr.h>
57 #include <dev/scsipi/scsi_all.h>
58 #include <dev/scsipi/scsipi_all.h>
59 #include <dev/scsipi/scsiconf.h>
60 #include <dev/scsipi/scsi_disk.h>
62 #include <machine/dvcfg.h>
63 #include <machine/physio_proc.h>
65 #include <i386/Cbus/dev/scsi_low.h>
67 #include <i386/Cbus/dev/ncr53c500reg.h>
68 #include <i386/Cbus/dev/ncr53c500hw.h>
69 #include <i386/Cbus/dev/ncr53c500var.h>
71 #include <i386/Cbus/dev/ncr53c500hwtab.h>
72 #endif /* __NetBSD__ */
75 #include <machine/clock.h>
76 #include <machine/cpu.h>
77 #include <machine/bus_pio.h>
78 #include <machine/bus.h>
80 #include <machine/dvcfg.h>
81 #include <machine/physio_proc.h>
83 #include <cam/scsi/scsi_low.h>
85 #include <dev/ncv/ncr53c500reg.h>
86 #include <dev/ncv/ncr53c500hw.h>
87 #include <dev/ncv/ncr53c500var.h>
89 #include <dev/ncv/ncr53c500hwtab.h>
90 #endif /* __FreeBSD__ */
92 #define NCV_MAX_DATA_SIZE (64 * 1024)
93 #define NCV_DELAY_MAX (2 * 1000 * 1000)
94 #define NCV_DELAY_INTERVAL (1)
95 #define NCV_PADDING_SIZE (32)
97 /***************************************************
99 ***************************************************/
100 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
101 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
102 #define NCV_ENABLE_FAST_SCSI 0x0010
103 #define NCV_FAST_INTERRUPTS 0x0100
105 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
106 int ncv_data_read_bytes = 4096;
107 int ncv_data_write_bytes = 4096;
109 /***************************************************
111 ***************************************************/
114 #endif /* NCV_DEBUG */
121 #endif /* NCV_STATICS */
123 /***************************************************
125 ***************************************************/
126 extern struct cfdriver ncv_cd;
128 /**************************************************************
130 **************************************************************/
132 static void ncv_pio_read __P((struct ncv_softc *, u_int8_t *, u_int));
133 static void ncv_pio_write __P((struct ncv_softc *, u_int8_t *, u_int));
134 static int ncv_msg __P((struct ncv_softc *, struct targ_info *, u_int));
135 static int ncv_reselected __P((struct ncv_softc *));
136 static int ncv_disconnected __P((struct ncv_softc *, struct targ_info *));
138 static __inline void ncvhw_set_count __P((bus_space_tag_t, bus_space_handle_t, int));
139 static __inline u_int ncvhw_get_count __P((bus_space_tag_t, bus_space_handle_t));
140 static __inline void ncvhw_select_register_0 __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *));
141 static __inline void ncvhw_select_register_1 __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *));
142 static __inline void ncvhw_fpush __P((bus_space_tag_t, bus_space_handle_t, u_int8_t *, int));
144 static void ncv_pdma_end __P((struct ncv_softc *sc, struct targ_info *));
145 static int ncv_world_start __P((struct ncv_softc *, int));
146 static void ncvhw_bus_reset __P((struct ncv_softc *));
147 static void ncvhw_reset __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *));
148 static int ncvhw_check __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *));
149 static void ncvhw_init __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *));
150 static int ncvhw_start_selection __P((struct ncv_softc *sc, struct slccb *));
151 static void ncvhw_attention __P((struct ncv_softc *));
152 static int ncv_ccb_nexus_establish __P((struct ncv_softc *));
153 static int ncv_lun_nexus_establish __P((struct ncv_softc *));
154 static int ncv_target_nexus_establish __P((struct ncv_softc *));
155 static int ncv_targ_init __P((struct ncv_softc *, struct targ_info *, int));
156 static int ncv_catch_intr __P((struct ncv_softc *));
157 #ifdef NCV_POWER_CONTROL
158 static int ncvhw_power __P((struct ncv_softc *, u_int));
159 #endif /* NCV_POWER_CONTROL */
160 static __inline void ncv_setup_and_start_pio __P((struct ncv_softc *, u_int));
162 struct scsi_low_funcs ncv_funcs = {
163 SC_LOW_INIT_T ncv_world_start,
164 SC_LOW_BUSRST_T ncvhw_bus_reset,
165 SC_LOW_TARG_INIT_T ncv_targ_init,
166 SC_LOW_LUN_INIT_T NULL,
168 SC_LOW_SELECT_T ncvhw_start_selection,
169 SC_LOW_NEXUS_T ncv_lun_nexus_establish,
170 SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
172 SC_LOW_ATTEN_T ncvhw_attention,
173 SC_LOW_MSG_T ncv_msg,
175 SC_LOW_TIMEOUT_T NULL,
176 SC_LOW_POLL_T ncvintr,
178 NULL, /* SC_LOW_POWER_T ncvhw_power, */
181 /**************************************************************
183 **************************************************************/
185 ncvhw_select_register_0(iot, ioh, hw)
187 bus_space_handle_t ioh;
191 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
195 ncvhw_select_register_1(iot, ioh, hw)
197 bus_space_handle_t ioh;
201 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
205 ncvhw_fpush(iot, ioh, buf, len)
207 bus_space_handle_t ioh;
213 for (ptr = 0; ptr < len; ptr ++)
214 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
218 ncvhw_set_count(iot, ioh, count)
220 bus_space_handle_t ioh;
224 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
225 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
226 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
229 static __inline u_int
230 ncvhw_get_count(iot, ioh)
232 bus_space_handle_t ioh;
236 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
237 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
238 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
243 ncvhw_check(iot, ioh, hw)
245 bus_space_handle_t ioh;
250 ncvhw_select_register_0(iot, ioh, hw);
251 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
252 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
255 printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
256 #endif /* NCV_DEBUG */
260 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
261 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
264 printf("ncv: cr0_cmd CMD_NOP failed\n");
265 #endif /* NCV_DEBUG */
270 ncvhw_reset(iot, ioh, hw);
271 ncvhw_init(iot, ioh, hw);
274 ncvhw_select_register_0(iot, ioh, hw);
275 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
276 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
277 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
278 SCSI_LOW_DELAY(100 * 1000);
281 bus_space_read_1(iot, ioh, cr0_stat);
282 stat = bus_space_read_1(iot, ioh, cr0_istat);
283 SCSI_LOW_DELAY(1000);
285 if (((stat & INTR_SBR) == 0) ||
286 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
289 printf("ncv: cr0_istat SCSI BUS RESET failed\n");
290 #endif /* NCV_DEBUG */
298 ncvhw_reset(iot, ioh, hw)
300 bus_space_handle_t ioh;
304 ncvhw_select_register_0(iot, ioh, hw);
306 /* dummy cmd twice */
307 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
308 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
311 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
313 /* again dummy cmd twice */
314 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
315 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
319 ncvhw_init(iot, ioh, hw)
321 bus_space_handle_t ioh;
325 ncvhw_select_register_0(iot, ioh, hw);
326 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
327 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
328 bus_space_write_1(iot, ioh, cr0_period, 0);
329 bus_space_write_1(iot, ioh, cr0_offs, 0);
331 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
332 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
333 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
334 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
336 ncvhw_select_register_1(iot, ioh, hw);
337 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
338 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
339 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
341 ncvhw_select_register_0(iot, ioh, hw);
344 #ifdef NCV_POWER_CONTROL
346 ncvhw_power(sc, flags)
347 struct ncv_softc *sc;
350 struct scsi_low_softc *slp = &sc->sc_sclow;
351 bus_space_tag_t iot = sc->sc_iot;
352 bus_space_handle_t ioh = sc->sc_ioh;
354 if (flags == SCSI_LOW_POWDOWN)
356 printf("%s power down\n", slp->sl_xname);
357 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
358 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
362 switch (sc->sc_rstep)
365 printf("%s resume step O\n", slp->sl_xname);
366 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
367 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
371 printf("%s resume step I\n", slp->sl_xname);
372 ncvhw_reset(iot, ioh, &sc->sc_hw);
373 ncvhw_init(iot, ioh, &sc->sc_hw);
380 #endif /* NCV_POWER_CONTROL */
382 /**************************************************************
384 **************************************************************/
387 struct ncv_softc *sc;
390 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
396 struct ncv_softc *sc;
398 bus_space_tag_t iot = sc->sc_iot;
399 bus_space_handle_t ioh = sc->sc_ioh;
401 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
402 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
403 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
404 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
408 ncvhw_start_selection(sc, cb)
409 struct ncv_softc *sc;
412 struct scsi_low_softc *slp = &sc->sc_sclow;
413 bus_space_tag_t iot = sc->sc_iot;
414 bus_space_handle_t ioh = sc->sc_ioh;
415 struct targ_info *ti = cb->ti;
420 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
422 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
426 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
428 else if (scsi_low_is_msgout_continue(ti,
429 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
433 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
439 flags = SCSI_LOW_MSGOUT_INIT;
442 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
443 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
444 return SCSI_LOW_START_FAIL;
446 ncv_target_nexus_establish(sc);
448 len = scsi_low_msgout(slp, ti, flags);
449 if (sc->sc_selstop == 0)
450 scsi_low_cmd(slp, ti);
453 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
456 return SCSI_LOW_START_FAIL;
459 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
460 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
461 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
462 if (sc->sc_selstop == 0)
464 ncvhw_fpush(iot, ioh,
465 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
467 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
470 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
471 return SCSI_LOW_START_OK;
475 ncv_world_start(sc, fdone)
476 struct ncv_softc *sc;
479 struct scsi_low_softc *slp = &sc->sc_sclow;
480 bus_space_tag_t iot = sc->sc_iot;
481 bus_space_handle_t ioh = sc->sc_ioh;
484 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
485 sc->sc_hw.hw_cfg1 |= C1_PARENB;
487 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
489 ncvhw_reset(iot, ioh, &sc->sc_hw);
490 ncvhw_init(iot, ioh, &sc->sc_hw);
492 scsi_low_bus_reset(slp);
494 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
495 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
496 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
497 SCSI_LOW_DELAY(1000);
499 if (((stat & INTR_SBR) == 0) ||
500 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
503 SOFT_INTR_REQUIRED(slp);
509 struct ncv_softc *sc;
510 struct targ_info *ti;
513 bus_space_tag_t iot = sc->sc_iot;
514 bus_space_handle_t ioh = sc->sc_ioh;
515 struct ncv_targ_info *nti = (void *) ti;
516 u_int hwcycle, period;
518 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
520 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
522 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
528 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
531 period = ti->ti_maxsynch.period;
532 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
533 hwcycle = 1000 / hwcycle;
535 if (period < 200 / 4 && period >= 100 / 4)
536 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
538 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
540 period = ((period * 40 / hwcycle) + 5) / 10;
541 nti->nti_reg_period = period & 0x1f;
542 nti->nti_reg_offset = ti->ti_maxsynch.offset;
544 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
545 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
546 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
551 ncv_targ_init(sc, ti, action)
552 struct ncv_softc *sc;
553 struct targ_info *ti;
556 struct ncv_targ_info *nti = (void *) ti;
558 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
560 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
561 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
562 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
564 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
565 nti->nti_reg_period = 0;
566 nti->nti_reg_offset = 0;
571 /**************************************************************
572 * General probe attach
573 **************************************************************/
574 static int ncv_setup_img __P((struct ncv_hw *, u_int, int));
577 ncv_setup_img(hw, dvcfg, hostid)
583 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
585 printf("ncv: invalid dvcfg flags\n");
589 if (NCV_C5IMG(dvcfg) != 0)
591 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
592 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
594 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
595 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
596 hw->hw_mperiod = 100 / 4;
598 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
599 hw->hw_cfg3_fclk = 0x04;
601 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
602 hw->hw_cfg2 &= ~C2_SCSI2;
604 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
605 hw->hw_cfg1 |= C1_SLOW;
608 /* setup configuration image 3 */
609 if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
610 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
612 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
614 /* setup configuration image 1 */
615 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
620 ncvprobesubr(iot, ioh, dvcfg, hsid)
622 bus_space_handle_t ioh;
628 hwtab = ncv_template;
629 if (ncv_setup_img(&hwtab, dvcfg, hsid))
631 if (ncvhw_check(iot, ioh, &hwtab) != 0)
644 printf("%s: scsibus ", name);
650 struct ncv_softc *sc;
652 struct scsi_low_softc *slp = &sc->sc_sclow;
655 sc->sc_hw = ncv_template;
656 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
657 slp->sl_funcs = &ncv_funcs;
658 slp->sl_flags |= HW_READ_PADDING;
659 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
661 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
662 sizeof(struct ncv_targ_info), 0);
665 /**************************************************************
667 **************************************************************/
669 ncv_setup_and_start_pio(sc, reqlen)
670 struct ncv_softc *sc;
673 bus_space_tag_t iot = sc->sc_iot;
674 bus_space_handle_t ioh = sc->sc_ioh;
676 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
677 ncvhw_set_count(iot, ioh, reqlen);
678 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
680 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
681 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
686 struct ncv_softc *sc;
687 struct targ_info *ti;
689 struct scsi_low_softc *slp = &sc->sc_sclow;
690 bus_space_tag_t iot = sc->sc_iot;
691 bus_space_handle_t ioh = sc->sc_ioh;
694 slp->sl_flags &= ~HW_PDMASTART;
695 if (slp->sl_Qnexus == NULL)
697 slp->sl_error |= PDMAERR;
701 if (ti->ti_phase == PH_DATA)
703 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
704 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
705 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
706 cr0_sffl) & CR0_SFFLR_BMASK);
708 if ((u_int) len <= (u_int) sc->sc_sdatalen)
710 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
711 sc->sc_tdatalen != len)
714 len = sc->sc_sdatalen - len;
715 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
718 slp->sl_scp.scp_data += len;
719 slp->sl_scp.scp_datalen -= len;
724 if ((slp->sl_error & PDMAERR) == 0)
726 printf("%s: stragne cnt hw 0x%x soft 0x%x\n",
728 slp->sl_scp.scp_datalen);
730 slp->sl_error |= PDMAERR;
732 scsi_low_data_finish(slp);
736 printf("%s: data phase miss\n", slp->sl_xname);
737 slp->sl_error |= PDMAERR;
741 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
742 bus_space_write_1(iot, ioh, cr1_fstat, 0);
743 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
747 ncv_pio_read(sc, buf, reqlen)
748 struct ncv_softc *sc;
752 struct scsi_low_softc *slp = &sc->sc_sclow;
753 bus_space_tag_t iot = sc->sc_iot;
754 bus_space_handle_t ioh = sc->sc_ioh;
756 register u_int8_t fstat;
758 ncv_setup_and_start_pio(sc, reqlen);
759 slp->sl_flags |= HW_PDMASTART;
760 sc->sc_sdatalen = reqlen;
761 tout = sc->sc_tmaxcnt;
763 while (reqlen >= FIFO_F_SZ && tout -- > 0)
765 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
766 if (fstat == (u_int8_t) -1)
770 #define NCV_FAST32_ACCESS
771 #ifdef NCV_FAST32_ACCESS
772 bus_space_read_multi_4(iot, ioh, cr1_fdata,
773 (u_int32_t *) buf, FIFO_F_SZ / 4);
774 #else /* !NCV_FAST32_ACCESS */
775 bus_space_read_multi_2(iot, ioh, cr1_fdata,
776 (u_int16_t *) buf, FIFO_F_SZ / 2);
777 #endif /* !NCV_FAST32_ACCESS */
783 if (fstat & FIFO_BRK)
790 while (reqlen > 0 && tout -- > 0)
792 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
793 if ((fstat & FIFO_E) == 0)
795 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
800 if (fstat & FIFO_BRK)
808 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
809 sc->sc_tdatalen = reqlen;
813 ncv_pio_write(sc, buf, reqlen)
814 struct ncv_softc *sc;
818 struct scsi_low_softc *slp = &sc->sc_sclow;
819 bus_space_tag_t iot = sc->sc_iot;
820 bus_space_handle_t ioh = sc->sc_ioh;
822 register u_int8_t fstat;
824 ncv_setup_and_start_pio(sc, reqlen);
825 sc->sc_sdatalen = reqlen;
826 tout = sc->sc_tmaxcnt;
827 slp->sl_flags |= HW_PDMASTART;
829 while (reqlen >= FIFO_F_SZ && tout -- > 0)
831 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
832 if (fstat & FIFO_BRK)
835 if ((fstat & FIFO_E) != 0)
837 #ifdef NCV_FAST32_ACCESS
838 bus_space_write_multi_4(iot, ioh, cr1_fdata,
839 (u_int32_t *) buf, FIFO_F_SZ / 4);
840 #else /* !NCV_FAST32_ACCESS */
841 bus_space_write_multi_2(iot, ioh, cr1_fdata,
842 (u_int16_t *) buf, FIFO_F_SZ / 2);
843 #endif /* !NCV_FAST32_ACCESS */
853 while (reqlen > 0 && tout -- > 0)
855 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
856 if (fstat & FIFO_BRK)
859 if ((fstat & FIFO_F) == 0) /* fifo not full */
861 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
871 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
874 /**************************************************************
875 * disconnect & reselect (HW low)
876 **************************************************************/
879 struct ncv_softc *sc;
881 struct scsi_low_softc *slp = &sc->sc_sclow;
882 bus_space_tag_t iot = sc->sc_iot;
883 bus_space_handle_t ioh = sc->sc_ioh;
884 struct targ_info *ti;
887 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
889 printf("%s illegal fifo bytes\n", slp->sl_xname);
890 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
894 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
895 sid &= ~(1 << slp->sl_hostid);
897 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
902 ncv_statics.reselect ++;
903 #endif /* NCV_STATICS */
904 bus_space_write_1(iot, ioh, cr0_dstid, sid);
909 ncv_disconnected(sc, ti)
910 struct ncv_softc *sc;
911 struct targ_info *ti;
913 struct scsi_low_softc *slp = &sc->sc_sclow;
914 bus_space_tag_t iot = sc->sc_iot;
915 bus_space_handle_t ioh = sc->sc_ioh;
917 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
918 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
921 ncv_statics.disconnect ++;
922 #endif /* NCV_STATICS */
924 scsi_low_disconnected(slp, ti);
928 /**************************************************************
930 **************************************************************/
932 ncv_target_nexus_establish(sc)
933 struct ncv_softc *sc;
935 struct scsi_low_softc *slp = &sc->sc_sclow;
936 struct targ_info *ti = slp->sl_Tnexus;
937 struct ncv_targ_info *nti = (void *) ti;
938 bus_space_tag_t iot = sc->sc_iot;
939 bus_space_handle_t ioh = sc->sc_ioh;
941 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
942 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
943 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
948 ncv_lun_nexus_establish(sc)
949 struct ncv_softc *sc;
956 ncv_ccb_nexus_establish(sc)
957 struct ncv_softc *sc;
959 struct scsi_low_softc *slp = &sc->sc_sclow;
960 struct slccb *cb = slp->sl_Qnexus;
962 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
968 struct ncv_softc *sc;
970 bus_space_tag_t iot = sc->sc_iot;
971 bus_space_handle_t ioh = sc->sc_ioh;
973 register u_int8_t status;
975 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
977 status = bus_space_read_1(iot, ioh, cr0_stat);
978 if ((status & STAT_INT) != 0)
981 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
990 struct ncv_softc *sc = arg;
991 struct scsi_low_softc *slp = &sc->sc_sclow;
992 bus_space_tag_t iot = sc->sc_iot;
993 bus_space_handle_t ioh = sc->sc_ioh;
994 struct targ_info *ti;
995 struct physio_proc *pp;
999 u_int8_t regv, status, ireason;
1002 if (slp->sl_flags & HW_INACTIVE)
1005 /********************************************
1007 ********************************************/
1008 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
1009 status = bus_space_read_1(iot, ioh, cr0_stat);
1010 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
1013 ireason = bus_space_read_1(iot, ioh, cr0_istat);
1014 if ((ireason & INTR_SBR) != 0)
1018 /* avoid power off hangup */
1019 val = bus_space_read_1(iot, ioh, cr0_cfg1);
1020 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
1023 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
1024 "bus reset (power off?)");
1028 /********************************************
1030 ********************************************/
1034 scsi_low_print(slp, NULL);
1035 printf("%s st %x ist %x\n\n", slp->sl_xname,
1039 SCSI_LOW_DEBUGGER("ncv");
1042 #endif /* NCV_DEBUG */
1044 /********************************************
1045 * Reselect or Disconnect or Nexus check
1046 ********************************************/
1048 if (ireason == INTR_RESELECT)
1050 if (ncv_reselected(sc) == EJUSTRETURN)
1055 if ((ti = slp->sl_Tnexus) == NULL)
1059 if ((status & (STAT_PE | STAT_GE)) != 0)
1061 slp->sl_error |= PARITYERR;
1062 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
1063 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
1065 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
1066 derror = SCSI_LOW_DATA_PE;
1069 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
1071 if ((ireason & INTR_ILL) == 0)
1072 return ncv_disconnected(sc, ti);
1074 slp->sl_error |= FATALIO;
1075 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
1079 /********************************************
1080 * Internal scsi phase
1081 ********************************************/
1082 switch (ti->ti_phase)
1085 scsi_low_arbit_win(slp);
1086 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1088 if (sc->sc_selstop == 0)
1091 * Here scsi phases expected are
1093 * MSGIN : target wants to disconnect the host.
1094 * STATUSIN : immediate command completed.
1095 * CMD PHASE : command out failed
1096 * MSGOUT : identify command failed.
1098 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1103 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1105 if ((ireason & INTR_FC) != 0)
1107 SCSI_LOW_ASSERT_ATN(slp);
1110 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1114 ncv_target_nexus_establish(sc);
1115 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1117 printf("%s: unexpected phase after reselect\n",
1119 slp->sl_error |= FATALIO;
1120 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1126 if ((slp->sl_flags & HW_PDMASTART) != 0)
1128 ncv_pdma_end(sc, ti);
1133 /********************************************
1134 * Scsi phase sequencer
1135 ********************************************/
1136 switch (status & PHASE_MASK)
1138 case DATA_OUT_PHASE: /* data out */
1139 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1140 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1142 scsi_low_attention(slp);
1145 pp = physio_proc_enter(bp);
1146 if (slp->sl_scp.scp_datalen <= 0)
1148 if ((ireason & INTR_BS) == 0)
1151 if ((slp->sl_error & PDMAERR) == 0)
1152 printf("%s: data underrun\n", slp->sl_xname);
1153 slp->sl_error |= PDMAERR;
1155 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1157 u_int8_t padding[NCV_PADDING_SIZE];
1159 SCSI_LOW_BZERO(padding, sizeof(padding));
1160 ncv_pio_write(sc, padding, sizeof(padding));
1164 printf("%s: write padding required\n",
1170 len = slp->sl_scp.scp_datalen;
1171 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1173 if (len > ncv_data_write_bytes)
1174 len = ncv_data_write_bytes;
1176 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1178 physio_proc_leave(pp);
1181 case DATA_IN_PHASE: /* data in */
1182 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1183 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1185 scsi_low_attention(slp);
1188 pp = physio_proc_enter(bp);
1189 if (slp->sl_scp.scp_datalen <= 0)
1191 if ((ireason & INTR_BS) == 0)
1194 if ((slp->sl_error & PDMAERR) == 0)
1195 printf("%s: data overrun\n", slp->sl_xname);
1196 slp->sl_error |= PDMAERR;
1198 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1200 u_int8_t padding[NCV_PADDING_SIZE];
1202 ncv_pio_read(sc, padding, sizeof(padding));
1206 printf("%s: read padding required\n",
1213 len = slp->sl_scp.scp_datalen;
1214 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1216 if (len > ncv_data_read_bytes)
1217 len = ncv_data_read_bytes;
1219 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1221 physio_proc_leave(pp);
1224 case COMMAND_PHASE: /* cmd out */
1225 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1226 if (scsi_low_cmd(slp, ti) != 0)
1228 scsi_low_attention(slp);
1231 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1232 ncvhw_fpush(iot, ioh,
1233 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1234 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1237 case STATUS_PHASE: /* status in */
1238 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1239 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1240 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1247 case MESSAGE_OUT_PHASE: /* msg out */
1248 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1249 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1251 flags = SCSI_LOW_MSGOUT_UNIFY;
1252 if (ti->ti_ophase != ti->ti_phase)
1253 flags |= SCSI_LOW_MSGOUT_INIT;
1254 len = scsi_low_msgout(slp, ti, flags);
1256 if (len > 1 && slp->sl_atten == 0)
1258 scsi_low_attention(slp);
1261 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1262 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1263 SCSI_LOW_DEASSERT_ATN(slp);
1266 case MESSAGE_IN_PHASE: /* msg in */
1267 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1269 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1270 if (sc->sc_compseq != 0)
1273 if ((ireason & INTR_FC) && len == 2)
1275 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1276 scsi_low_statusin(slp, ti, regv | derror);
1281 slp->sl_error |= FATALIO;
1282 scsi_low_assert_msg(slp, ti,
1283 SCSI_LOW_MSG_ABORT, 1);
1284 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1285 cr0_cmd, CMD_MSGOK);
1289 else if (ireason & INTR_BS)
1291 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1292 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1293 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1295 if (ncv_catch_intr(sc) == 0)
1301 if ((ireason & INTR_FC) && len == 1)
1303 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1305 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1307 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1309 scsi_low_attention(slp);
1312 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1314 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1317 * clear a pending interrupt and sync with
1325 slp->sl_error |= FATALIO;
1326 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1327 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,