1 /* $FreeBSD: src/sys/dev/ncv/ncr53c500.c,v 1.1.2.4 2001/12/17 13:30:18 non Exp $ */
2 /* $DragonFly: src/sys/dev/disk/ncv/ncr53c500.c,v 1.6 2004/02/12 00:00:14 dillon Exp $ */
3 /* $NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $ */
8 #define NCV_IO_CONTROL_FLAGS (0)
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.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
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.
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.
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/queue.h>
47 #include <sys/malloc.h>
48 #include <sys/errno.h>
51 #include <sys/device.h>
52 #include <machine/bus.h>
53 #include <machine/intr.h>
55 #include <dev/scsipi/scsi_all.h>
56 #include <dev/scsipi/scsipi_all.h>
57 #include <dev/scsipi/scsiconf.h>
58 #include <dev/scsipi/scsi_disk.h>
60 #include <machine/dvcfg.h>
61 #include <machine/physio_proc.h>
63 #include <i386/Cbus/dev/scsi_low.h>
65 #include <i386/Cbus/dev/ncr53c500reg.h>
66 #include <i386/Cbus/dev/ncr53c500hw.h>
67 #include <i386/Cbus/dev/ncr53c500var.h>
69 #include <i386/Cbus/dev/ncr53c500hwtab.h>
70 #endif /* __NetBSD__ */
73 #include <machine/clock.h>
74 #include <machine/cpu.h>
75 #include <machine/bus_pio.h>
76 #include <machine/bus.h>
78 #include <machine/dvcfg.h>
79 #include <machine/physio_proc.h>
81 #include <bus/cam/scsi/scsi_low.h>
83 #include "ncr53c500reg.h"
84 #include "ncr53c500hw.h"
85 #include "ncr53c500var.h"
87 #include "ncr53c500hwtab.h"
88 #endif /* __DragonFly__ */
90 #define NCV_MAX_DATA_SIZE (64 * 1024)
91 #define NCV_DELAY_MAX (2 * 1000 * 1000)
92 #define NCV_DELAY_INTERVAL (1)
93 #define NCV_PADDING_SIZE (32)
95 /***************************************************
97 ***************************************************/
98 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
99 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
100 #define NCV_ENABLE_FAST_SCSI 0x0010
101 #define NCV_FAST_INTERRUPTS 0x0100
103 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
104 int ncv_data_read_bytes = 4096;
105 int ncv_data_write_bytes = 4096;
107 /***************************************************
109 ***************************************************/
112 #endif /* NCV_DEBUG */
119 #endif /* NCV_STATICS */
121 /***************************************************
123 ***************************************************/
124 extern struct cfdriver ncv_cd;
126 /**************************************************************
128 **************************************************************/
130 static void ncv_pio_read (struct ncv_softc *, u_int8_t *, u_int);
131 static void ncv_pio_write (struct ncv_softc *, u_int8_t *, u_int);
132 static int ncv_msg (struct ncv_softc *, struct targ_info *, u_int);
133 static int ncv_reselected (struct ncv_softc *);
134 static int ncv_disconnected (struct ncv_softc *, struct targ_info *);
136 static __inline void ncvhw_set_count (bus_space_tag_t, bus_space_handle_t, int);
137 static __inline u_int ncvhw_get_count (bus_space_tag_t, bus_space_handle_t);
138 static __inline void ncvhw_select_register_0 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
139 static __inline void ncvhw_select_register_1 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
140 static __inline void ncvhw_fpush (bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
142 static void ncv_pdma_end (struct ncv_softc *sc, struct targ_info *);
143 static int ncv_world_start (struct ncv_softc *, int);
144 static void ncvhw_bus_reset (struct ncv_softc *);
145 static void ncvhw_reset (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
146 static int ncvhw_check (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
147 static void ncvhw_init (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
148 static int ncvhw_start_selection (struct ncv_softc *sc, struct slccb *);
149 static void ncvhw_attention (struct ncv_softc *);
150 static int ncv_ccb_nexus_establish (struct ncv_softc *);
151 static int ncv_lun_nexus_establish (struct ncv_softc *);
152 static int ncv_target_nexus_establish (struct ncv_softc *);
153 static int ncv_targ_init (struct ncv_softc *, struct targ_info *, int);
154 static int ncv_catch_intr (struct ncv_softc *);
155 #ifdef NCV_POWER_CONTROL
156 static int ncvhw_power (struct ncv_softc *, u_int);
157 #endif /* NCV_POWER_CONTROL */
158 static __inline void ncv_setup_and_start_pio (struct ncv_softc *, u_int);
160 struct scsi_low_funcs ncv_funcs = {
161 SC_LOW_INIT_T ncv_world_start,
162 SC_LOW_BUSRST_T ncvhw_bus_reset,
163 SC_LOW_TARG_INIT_T ncv_targ_init,
164 SC_LOW_LUN_INIT_T NULL,
166 SC_LOW_SELECT_T ncvhw_start_selection,
167 SC_LOW_NEXUS_T ncv_lun_nexus_establish,
168 SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
170 SC_LOW_ATTEN_T ncvhw_attention,
171 SC_LOW_MSG_T ncv_msg,
173 SC_LOW_TIMEOUT_T NULL,
174 SC_LOW_POLL_T ncvintr,
176 NULL, /* SC_LOW_POWER_T ncvhw_power, */
179 /**************************************************************
181 **************************************************************/
183 ncvhw_select_register_0(iot, ioh, hw)
185 bus_space_handle_t ioh;
189 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
193 ncvhw_select_register_1(iot, ioh, hw)
195 bus_space_handle_t ioh;
199 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
203 ncvhw_fpush(iot, ioh, buf, len)
205 bus_space_handle_t ioh;
211 for (ptr = 0; ptr < len; ptr ++)
212 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
216 ncvhw_set_count(iot, ioh, count)
218 bus_space_handle_t ioh;
222 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
223 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
224 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
227 static __inline u_int
228 ncvhw_get_count(iot, ioh)
230 bus_space_handle_t ioh;
234 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
235 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
236 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
241 ncvhw_check(iot, ioh, hw)
243 bus_space_handle_t ioh;
248 ncvhw_select_register_0(iot, ioh, hw);
249 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
250 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
253 printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
254 #endif /* NCV_DEBUG */
258 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
259 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
262 printf("ncv: cr0_cmd CMD_NOP failed\n");
263 #endif /* NCV_DEBUG */
268 ncvhw_reset(iot, ioh, hw);
269 ncvhw_init(iot, ioh, hw);
272 ncvhw_select_register_0(iot, ioh, hw);
273 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
274 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
275 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
276 SCSI_LOW_DELAY(100 * 1000);
279 bus_space_read_1(iot, ioh, cr0_stat);
280 stat = bus_space_read_1(iot, ioh, cr0_istat);
281 SCSI_LOW_DELAY(1000);
283 if (((stat & INTR_SBR) == 0) ||
284 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
287 printf("ncv: cr0_istat SCSI BUS RESET failed\n");
288 #endif /* NCV_DEBUG */
296 ncvhw_reset(iot, ioh, hw)
298 bus_space_handle_t ioh;
302 ncvhw_select_register_0(iot, ioh, hw);
304 /* dummy cmd twice */
305 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
306 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
309 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
311 /* again dummy cmd twice */
312 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
313 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
317 ncvhw_init(iot, ioh, hw)
319 bus_space_handle_t ioh;
323 ncvhw_select_register_0(iot, ioh, hw);
324 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
325 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
326 bus_space_write_1(iot, ioh, cr0_period, 0);
327 bus_space_write_1(iot, ioh, cr0_offs, 0);
329 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
330 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
331 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
332 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
334 ncvhw_select_register_1(iot, ioh, hw);
335 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
336 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
337 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
339 ncvhw_select_register_0(iot, ioh, hw);
342 #ifdef NCV_POWER_CONTROL
344 ncvhw_power(sc, flags)
345 struct ncv_softc *sc;
348 struct scsi_low_softc *slp = &sc->sc_sclow;
349 bus_space_tag_t iot = sc->sc_iot;
350 bus_space_handle_t ioh = sc->sc_ioh;
352 if (flags == SCSI_LOW_POWDOWN)
354 printf("%s power down\n", slp->sl_xname);
355 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
356 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
360 switch (sc->sc_rstep)
363 printf("%s resume step O\n", slp->sl_xname);
364 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
365 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
369 printf("%s resume step I\n", slp->sl_xname);
370 ncvhw_reset(iot, ioh, &sc->sc_hw);
371 ncvhw_init(iot, ioh, &sc->sc_hw);
378 #endif /* NCV_POWER_CONTROL */
380 /**************************************************************
382 **************************************************************/
385 struct ncv_softc *sc;
388 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
394 struct ncv_softc *sc;
396 bus_space_tag_t iot = sc->sc_iot;
397 bus_space_handle_t ioh = sc->sc_ioh;
399 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
400 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
401 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
402 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
406 ncvhw_start_selection(sc, cb)
407 struct ncv_softc *sc;
410 struct scsi_low_softc *slp = &sc->sc_sclow;
411 bus_space_tag_t iot = sc->sc_iot;
412 bus_space_handle_t ioh = sc->sc_ioh;
413 struct targ_info *ti = cb->ti;
418 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
420 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
424 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
426 else if (scsi_low_is_msgout_continue(ti,
427 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
431 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
437 flags = SCSI_LOW_MSGOUT_INIT;
440 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
441 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
442 return SCSI_LOW_START_FAIL;
444 ncv_target_nexus_establish(sc);
446 len = scsi_low_msgout(slp, ti, flags);
447 if (sc->sc_selstop == 0)
448 scsi_low_cmd(slp, ti);
451 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
454 return SCSI_LOW_START_FAIL;
457 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
458 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
459 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
460 if (sc->sc_selstop == 0)
462 ncvhw_fpush(iot, ioh,
463 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
465 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
468 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
469 return SCSI_LOW_START_OK;
473 ncv_world_start(sc, fdone)
474 struct ncv_softc *sc;
477 struct scsi_low_softc *slp = &sc->sc_sclow;
478 bus_space_tag_t iot = sc->sc_iot;
479 bus_space_handle_t ioh = sc->sc_ioh;
482 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
483 sc->sc_hw.hw_cfg1 |= C1_PARENB;
485 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
487 ncvhw_reset(iot, ioh, &sc->sc_hw);
488 ncvhw_init(iot, ioh, &sc->sc_hw);
490 scsi_low_bus_reset(slp);
492 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
493 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
494 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
495 SCSI_LOW_DELAY(1000);
497 if (((stat & INTR_SBR) == 0) ||
498 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
501 SOFT_INTR_REQUIRED(slp);
507 struct ncv_softc *sc;
508 struct targ_info *ti;
511 bus_space_tag_t iot = sc->sc_iot;
512 bus_space_handle_t ioh = sc->sc_ioh;
513 struct ncv_targ_info *nti = (void *) ti;
514 u_int hwcycle, period;
516 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
518 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
520 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
526 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
529 period = ti->ti_maxsynch.period;
530 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
531 hwcycle = 1000 / hwcycle;
533 if (period < 200 / 4 && period >= 100 / 4)
534 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
536 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
538 period = ((period * 40 / hwcycle) + 5) / 10;
539 nti->nti_reg_period = period & 0x1f;
540 nti->nti_reg_offset = ti->ti_maxsynch.offset;
542 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
543 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
544 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
549 ncv_targ_init(sc, ti, action)
550 struct ncv_softc *sc;
551 struct targ_info *ti;
554 struct ncv_targ_info *nti = (void *) ti;
556 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
558 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
559 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
560 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
562 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
563 nti->nti_reg_period = 0;
564 nti->nti_reg_offset = 0;
569 /**************************************************************
570 * General probe attach
571 **************************************************************/
572 static int ncv_setup_img (struct ncv_hw *, u_int, int);
575 ncv_setup_img(hw, dvcfg, hostid)
581 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
583 printf("ncv: invalid dvcfg flags\n");
587 if (NCV_C5IMG(dvcfg) != 0)
589 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
590 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
592 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
593 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
594 hw->hw_mperiod = 100 / 4;
596 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
597 hw->hw_cfg3_fclk = 0x04;
599 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
600 hw->hw_cfg2 &= ~C2_SCSI2;
602 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
603 hw->hw_cfg1 |= C1_SLOW;
606 /* setup configuration image 3 */
607 if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
608 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
610 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
612 /* setup configuration image 1 */
613 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
618 ncvprobesubr(iot, ioh, dvcfg, hsid)
620 bus_space_handle_t ioh;
626 hwtab = ncv_template;
627 if (ncv_setup_img(&hwtab, dvcfg, hsid))
629 if (ncvhw_check(iot, ioh, &hwtab) != 0)
642 printf("%s: scsibus ", name);
648 struct ncv_softc *sc;
650 struct scsi_low_softc *slp = &sc->sc_sclow;
653 sc->sc_hw = ncv_template;
654 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
655 slp->sl_funcs = &ncv_funcs;
656 slp->sl_flags |= HW_READ_PADDING;
657 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
659 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
660 sizeof(struct ncv_targ_info), 0);
663 /**************************************************************
665 **************************************************************/
667 ncv_setup_and_start_pio(sc, reqlen)
668 struct ncv_softc *sc;
671 bus_space_tag_t iot = sc->sc_iot;
672 bus_space_handle_t ioh = sc->sc_ioh;
674 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
675 ncvhw_set_count(iot, ioh, reqlen);
676 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
678 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
679 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
684 struct ncv_softc *sc;
685 struct targ_info *ti;
687 struct scsi_low_softc *slp = &sc->sc_sclow;
688 bus_space_tag_t iot = sc->sc_iot;
689 bus_space_handle_t ioh = sc->sc_ioh;
692 slp->sl_flags &= ~HW_PDMASTART;
693 if (slp->sl_Qnexus == NULL)
695 slp->sl_error |= PDMAERR;
699 if (ti->ti_phase == PH_DATA)
701 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
702 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
703 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
704 cr0_sffl) & CR0_SFFLR_BMASK);
706 if ((u_int) len <= (u_int) sc->sc_sdatalen)
708 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
709 sc->sc_tdatalen != len)
712 len = sc->sc_sdatalen - len;
713 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
716 slp->sl_scp.scp_data += len;
717 slp->sl_scp.scp_datalen -= len;
722 if ((slp->sl_error & PDMAERR) == 0)
724 printf("%s: stragne cnt hw 0x%x soft 0x%x\n",
726 slp->sl_scp.scp_datalen);
728 slp->sl_error |= PDMAERR;
730 scsi_low_data_finish(slp);
734 printf("%s: data phase miss\n", slp->sl_xname);
735 slp->sl_error |= PDMAERR;
739 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
740 bus_space_write_1(iot, ioh, cr1_fstat, 0);
741 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
745 ncv_pio_read(sc, buf, reqlen)
746 struct ncv_softc *sc;
750 struct scsi_low_softc *slp = &sc->sc_sclow;
751 bus_space_tag_t iot = sc->sc_iot;
752 bus_space_handle_t ioh = sc->sc_ioh;
756 ncv_setup_and_start_pio(sc, reqlen);
757 slp->sl_flags |= HW_PDMASTART;
758 sc->sc_sdatalen = reqlen;
759 tout = sc->sc_tmaxcnt;
761 while (reqlen >= FIFO_F_SZ && tout -- > 0)
763 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
764 if (fstat == (u_int8_t) -1)
768 #define NCV_FAST32_ACCESS
769 #ifdef NCV_FAST32_ACCESS
770 bus_space_read_multi_4(iot, ioh, cr1_fdata,
771 (u_int32_t *) buf, FIFO_F_SZ / 4);
772 #else /* !NCV_FAST32_ACCESS */
773 bus_space_read_multi_2(iot, ioh, cr1_fdata,
774 (u_int16_t *) buf, FIFO_F_SZ / 2);
775 #endif /* !NCV_FAST32_ACCESS */
781 if (fstat & FIFO_BRK)
788 while (reqlen > 0 && tout -- > 0)
790 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
791 if ((fstat & FIFO_E) == 0)
793 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
798 if (fstat & FIFO_BRK)
806 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
807 sc->sc_tdatalen = reqlen;
811 ncv_pio_write(sc, buf, reqlen)
812 struct ncv_softc *sc;
816 struct scsi_low_softc *slp = &sc->sc_sclow;
817 bus_space_tag_t iot = sc->sc_iot;
818 bus_space_handle_t ioh = sc->sc_ioh;
822 ncv_setup_and_start_pio(sc, reqlen);
823 sc->sc_sdatalen = reqlen;
824 tout = sc->sc_tmaxcnt;
825 slp->sl_flags |= HW_PDMASTART;
827 while (reqlen >= FIFO_F_SZ && tout -- > 0)
829 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
830 if (fstat & FIFO_BRK)
833 if ((fstat & FIFO_E) != 0)
835 #ifdef NCV_FAST32_ACCESS
836 bus_space_write_multi_4(iot, ioh, cr1_fdata,
837 (u_int32_t *) buf, FIFO_F_SZ / 4);
838 #else /* !NCV_FAST32_ACCESS */
839 bus_space_write_multi_2(iot, ioh, cr1_fdata,
840 (u_int16_t *) buf, FIFO_F_SZ / 2);
841 #endif /* !NCV_FAST32_ACCESS */
851 while (reqlen > 0 && tout -- > 0)
853 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
854 if (fstat & FIFO_BRK)
857 if ((fstat & FIFO_F) == 0) /* fifo not full */
859 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
869 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
872 /**************************************************************
873 * disconnect & reselect (HW low)
874 **************************************************************/
877 struct ncv_softc *sc;
879 struct scsi_low_softc *slp = &sc->sc_sclow;
880 bus_space_tag_t iot = sc->sc_iot;
881 bus_space_handle_t ioh = sc->sc_ioh;
882 struct targ_info *ti;
885 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
887 printf("%s illegal fifo bytes\n", slp->sl_xname);
888 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
892 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
893 sid &= ~(1 << slp->sl_hostid);
895 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
900 ncv_statics.reselect ++;
901 #endif /* NCV_STATICS */
902 bus_space_write_1(iot, ioh, cr0_dstid, sid);
907 ncv_disconnected(sc, ti)
908 struct ncv_softc *sc;
909 struct targ_info *ti;
911 struct scsi_low_softc *slp = &sc->sc_sclow;
912 bus_space_tag_t iot = sc->sc_iot;
913 bus_space_handle_t ioh = sc->sc_ioh;
915 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
916 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
919 ncv_statics.disconnect ++;
920 #endif /* NCV_STATICS */
922 scsi_low_disconnected(slp, ti);
926 /**************************************************************
928 **************************************************************/
930 ncv_target_nexus_establish(sc)
931 struct ncv_softc *sc;
933 struct scsi_low_softc *slp = &sc->sc_sclow;
934 struct targ_info *ti = slp->sl_Tnexus;
935 struct ncv_targ_info *nti = (void *) ti;
936 bus_space_tag_t iot = sc->sc_iot;
937 bus_space_handle_t ioh = sc->sc_ioh;
939 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
940 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
941 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
946 ncv_lun_nexus_establish(sc)
947 struct ncv_softc *sc;
954 ncv_ccb_nexus_establish(sc)
955 struct ncv_softc *sc;
957 struct scsi_low_softc *slp = &sc->sc_sclow;
958 struct slccb *cb = slp->sl_Qnexus;
960 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
966 struct ncv_softc *sc;
968 bus_space_tag_t iot = sc->sc_iot;
969 bus_space_handle_t ioh = sc->sc_ioh;
973 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
975 status = bus_space_read_1(iot, ioh, cr0_stat);
976 if ((status & STAT_INT) != 0)
979 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
988 struct ncv_softc *sc = arg;
989 struct scsi_low_softc *slp = &sc->sc_sclow;
990 bus_space_tag_t iot = sc->sc_iot;
991 bus_space_handle_t ioh = sc->sc_ioh;
992 struct targ_info *ti;
993 struct physio_proc *pp;
997 u_int8_t regv, status, ireason;
1000 if (slp->sl_flags & HW_INACTIVE)
1003 /********************************************
1005 ********************************************/
1006 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
1007 status = bus_space_read_1(iot, ioh, cr0_stat);
1008 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
1011 ireason = bus_space_read_1(iot, ioh, cr0_istat);
1012 if ((ireason & INTR_SBR) != 0)
1016 /* avoid power off hangup */
1017 val = bus_space_read_1(iot, ioh, cr0_cfg1);
1018 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
1021 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
1022 "bus reset (power off?)");
1026 /********************************************
1028 ********************************************/
1032 scsi_low_print(slp, NULL);
1033 printf("%s st %x ist %x\n\n", slp->sl_xname,
1037 SCSI_LOW_DEBUGGER("ncv");
1040 #endif /* NCV_DEBUG */
1042 /********************************************
1043 * Reselect or Disconnect or Nexus check
1044 ********************************************/
1046 if (ireason == INTR_RESELECT)
1048 if (ncv_reselected(sc) == EJUSTRETURN)
1053 if ((ti = slp->sl_Tnexus) == NULL)
1057 if ((status & (STAT_PE | STAT_GE)) != 0)
1059 slp->sl_error |= PARITYERR;
1060 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
1061 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
1063 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
1064 derror = SCSI_LOW_DATA_PE;
1067 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
1069 if ((ireason & INTR_ILL) == 0)
1070 return ncv_disconnected(sc, ti);
1072 slp->sl_error |= FATALIO;
1073 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
1077 /********************************************
1078 * Internal scsi phase
1079 ********************************************/
1080 switch (ti->ti_phase)
1083 scsi_low_arbit_win(slp);
1084 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1086 if (sc->sc_selstop == 0)
1089 * Here scsi phases expected are
1091 * MSGIN : target wants to disconnect the host.
1092 * STATUSIN : immediate command completed.
1093 * CMD PHASE : command out failed
1094 * MSGOUT : identify command failed.
1096 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1101 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1103 if ((ireason & INTR_FC) != 0)
1105 SCSI_LOW_ASSERT_ATN(slp);
1108 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1112 ncv_target_nexus_establish(sc);
1113 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1115 printf("%s: unexpected phase after reselect\n",
1117 slp->sl_error |= FATALIO;
1118 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1124 if ((slp->sl_flags & HW_PDMASTART) != 0)
1126 ncv_pdma_end(sc, ti);
1131 /********************************************
1132 * Scsi phase sequencer
1133 ********************************************/
1134 switch (status & PHASE_MASK)
1136 case DATA_OUT_PHASE: /* data out */
1137 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1138 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1140 scsi_low_attention(slp);
1143 pp = physio_proc_enter(bp);
1144 if (slp->sl_scp.scp_datalen <= 0)
1146 if ((ireason & INTR_BS) == 0)
1149 if ((slp->sl_error & PDMAERR) == 0)
1150 printf("%s: data underrun\n", slp->sl_xname);
1151 slp->sl_error |= PDMAERR;
1153 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1155 u_int8_t padding[NCV_PADDING_SIZE];
1157 SCSI_LOW_BZERO(padding, sizeof(padding));
1158 ncv_pio_write(sc, padding, sizeof(padding));
1162 printf("%s: write padding required\n",
1168 len = slp->sl_scp.scp_datalen;
1169 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1171 if (len > ncv_data_write_bytes)
1172 len = ncv_data_write_bytes;
1174 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1176 physio_proc_leave(pp);
1179 case DATA_IN_PHASE: /* data in */
1180 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1181 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1183 scsi_low_attention(slp);
1186 pp = physio_proc_enter(bp);
1187 if (slp->sl_scp.scp_datalen <= 0)
1189 if ((ireason & INTR_BS) == 0)
1192 if ((slp->sl_error & PDMAERR) == 0)
1193 printf("%s: data overrun\n", slp->sl_xname);
1194 slp->sl_error |= PDMAERR;
1196 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1198 u_int8_t padding[NCV_PADDING_SIZE];
1200 ncv_pio_read(sc, padding, sizeof(padding));
1204 printf("%s: read padding required\n",
1211 len = slp->sl_scp.scp_datalen;
1212 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1214 if (len > ncv_data_read_bytes)
1215 len = ncv_data_read_bytes;
1217 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1219 physio_proc_leave(pp);
1222 case COMMAND_PHASE: /* cmd out */
1223 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1224 if (scsi_low_cmd(slp, ti) != 0)
1226 scsi_low_attention(slp);
1229 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1230 ncvhw_fpush(iot, ioh,
1231 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1232 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1235 case STATUS_PHASE: /* status in */
1236 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1237 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1238 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1245 case MESSAGE_OUT_PHASE: /* msg out */
1246 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1247 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1249 flags = SCSI_LOW_MSGOUT_UNIFY;
1250 if (ti->ti_ophase != ti->ti_phase)
1251 flags |= SCSI_LOW_MSGOUT_INIT;
1252 len = scsi_low_msgout(slp, ti, flags);
1254 if (len > 1 && slp->sl_atten == 0)
1256 scsi_low_attention(slp);
1259 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1260 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1261 SCSI_LOW_DEASSERT_ATN(slp);
1264 case MESSAGE_IN_PHASE: /* msg in */
1265 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1267 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1268 if (sc->sc_compseq != 0)
1271 if ((ireason & INTR_FC) && len == 2)
1273 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1274 scsi_low_statusin(slp, ti, regv | derror);
1279 slp->sl_error |= FATALIO;
1280 scsi_low_assert_msg(slp, ti,
1281 SCSI_LOW_MSG_ABORT, 1);
1282 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1283 cr0_cmd, CMD_MSGOK);
1287 else if (ireason & INTR_BS)
1289 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1290 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1291 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1293 if (ncv_catch_intr(sc) == 0)
1299 if ((ireason & INTR_FC) && len == 1)
1301 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1303 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1305 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1307 scsi_low_attention(slp);
1310 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1312 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1315 * clear a pending interrupt and sync with
1323 slp->sl_error |= FATALIO;
1324 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1325 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,