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.9 2005/12/11 01:54:07 swildner 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>
49 #include <sys/thread2.h>
52 #include <sys/device.h>
53 #include <machine/bus.h>
54 #include <machine/intr.h>
56 #include <dev/scsipi/scsi_all.h>
57 #include <dev/scsipi/scsipi_all.h>
58 #include <dev/scsipi/scsiconf.h>
59 #include <dev/scsipi/scsi_disk.h>
61 #include <machine/dvcfg.h>
62 #include <machine/physio_proc.h>
64 #include <i386/Cbus/dev/scsi_low.h>
66 #include <i386/Cbus/dev/ncr53c500reg.h>
67 #include <i386/Cbus/dev/ncr53c500hw.h>
68 #include <i386/Cbus/dev/ncr53c500var.h>
70 #include <i386/Cbus/dev/ncr53c500hwtab.h>
71 #endif /* __NetBSD__ */
74 #include <machine/clock.h>
75 #include <machine/cpu.h>
76 #include <machine/bus_pio.h>
77 #include <machine/bus.h>
79 #include <machine/dvcfg.h>
80 #include <machine/physio_proc.h>
82 #include <bus/cam/scsi/scsi_low.h>
84 #include "ncr53c500reg.h"
85 #include "ncr53c500hw.h"
86 #include "ncr53c500var.h"
88 #include "ncr53c500hwtab.h"
89 #endif /* __DragonFly__ */
91 #define NCV_MAX_DATA_SIZE (64 * 1024)
92 #define NCV_DELAY_MAX (2 * 1000 * 1000)
93 #define NCV_DELAY_INTERVAL (1)
94 #define NCV_PADDING_SIZE (32)
96 /***************************************************
98 ***************************************************/
99 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
100 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
101 #define NCV_ENABLE_FAST_SCSI 0x0010
102 #define NCV_FAST_INTERRUPTS 0x0100
104 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
105 int ncv_data_read_bytes = 4096;
106 int ncv_data_write_bytes = 4096;
108 /***************************************************
110 ***************************************************/
113 #endif /* NCV_DEBUG */
120 #endif /* NCV_STATICS */
122 /***************************************************
124 ***************************************************/
125 extern struct cfdriver ncv_cd;
127 /**************************************************************
129 **************************************************************/
131 static void ncv_pio_read (struct ncv_softc *, u_int8_t *, u_int);
132 static void ncv_pio_write (struct ncv_softc *, u_int8_t *, u_int);
133 static int ncv_msg (struct ncv_softc *, struct targ_info *, u_int);
134 static int ncv_reselected (struct ncv_softc *);
135 static int ncv_disconnected (struct ncv_softc *, struct targ_info *);
137 static __inline void ncvhw_set_count (bus_space_tag_t, bus_space_handle_t, int);
138 static __inline u_int ncvhw_get_count (bus_space_tag_t, bus_space_handle_t);
139 static __inline void ncvhw_select_register_0 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
140 static __inline void ncvhw_select_register_1 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
141 static __inline void ncvhw_fpush (bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
143 static void ncv_pdma_end (struct ncv_softc *sc, struct targ_info *);
144 static int ncv_world_start (struct ncv_softc *, int);
145 static void ncvhw_bus_reset (struct ncv_softc *);
146 static void ncvhw_reset (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
147 static int ncvhw_check (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
148 static void ncvhw_init (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
149 static int ncvhw_start_selection (struct ncv_softc *sc, struct slccb *);
150 static void ncvhw_attention (struct ncv_softc *);
151 static int ncv_ccb_nexus_establish (struct ncv_softc *);
152 static int ncv_lun_nexus_establish (struct ncv_softc *);
153 static int ncv_target_nexus_establish (struct ncv_softc *);
154 static int ncv_targ_init (struct ncv_softc *, struct targ_info *, int);
155 static int ncv_catch_intr (struct ncv_softc *);
156 #ifdef NCV_POWER_CONTROL
157 static int ncvhw_power (struct ncv_softc *, u_int);
158 #endif /* NCV_POWER_CONTROL */
159 static __inline void ncv_setup_and_start_pio (struct ncv_softc *, u_int);
161 struct scsi_low_funcs ncv_funcs = {
162 SC_LOW_INIT_T ncv_world_start,
163 SC_LOW_BUSRST_T ncvhw_bus_reset,
164 SC_LOW_TARG_INIT_T ncv_targ_init,
165 SC_LOW_LUN_INIT_T NULL,
167 SC_LOW_SELECT_T ncvhw_start_selection,
168 SC_LOW_NEXUS_T ncv_lun_nexus_establish,
169 SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
171 SC_LOW_ATTEN_T ncvhw_attention,
172 SC_LOW_MSG_T ncv_msg,
174 SC_LOW_TIMEOUT_T NULL,
175 SC_LOW_POLL_T ncvintr,
177 NULL, /* SC_LOW_POWER_T ncvhw_power, */
180 /**************************************************************
182 **************************************************************/
184 ncvhw_select_register_0(bus_space_tag_t iot, bus_space_handle_t ioh,
188 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
192 ncvhw_select_register_1(bus_space_tag_t iot, bus_space_handle_t ioh,
196 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
200 ncvhw_fpush(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *buf,
205 for (ptr = 0; ptr < len; ptr ++)
206 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
210 ncvhw_set_count(bus_space_tag_t iot, bus_space_handle_t ioh, int count)
213 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
214 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
215 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
218 static __inline u_int
219 ncvhw_get_count(bus_space_tag_t iot, bus_space_handle_t ioh)
223 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
224 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
225 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
230 ncvhw_check(bus_space_tag_t iot, bus_space_handle_t ioh, struct ncv_hw *hw)
234 ncvhw_select_register_0(iot, ioh, hw);
235 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
236 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
239 printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
240 #endif /* NCV_DEBUG */
244 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
245 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
248 printf("ncv: cr0_cmd CMD_NOP failed\n");
249 #endif /* NCV_DEBUG */
254 ncvhw_reset(iot, ioh, hw);
255 ncvhw_init(iot, ioh, hw);
258 ncvhw_select_register_0(iot, ioh, hw);
259 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
260 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
261 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
262 SCSI_LOW_DELAY(100 * 1000);
265 bus_space_read_1(iot, ioh, cr0_stat);
266 stat = bus_space_read_1(iot, ioh, cr0_istat);
267 SCSI_LOW_DELAY(1000);
269 if (((stat & INTR_SBR) == 0) ||
270 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
273 printf("ncv: cr0_istat SCSI BUS RESET failed\n");
274 #endif /* NCV_DEBUG */
282 ncvhw_reset(bus_space_tag_t iot, bus_space_handle_t ioh,
286 ncvhw_select_register_0(iot, ioh, hw);
288 /* dummy cmd twice */
289 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
290 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
293 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
295 /* again dummy cmd twice */
296 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
297 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
301 ncvhw_init(bus_space_tag_t iot, bus_space_handle_t ioh,
305 ncvhw_select_register_0(iot, ioh, hw);
306 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
307 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
308 bus_space_write_1(iot, ioh, cr0_period, 0);
309 bus_space_write_1(iot, ioh, cr0_offs, 0);
311 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
312 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
313 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
314 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
316 ncvhw_select_register_1(iot, ioh, hw);
317 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
318 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
319 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
321 ncvhw_select_register_0(iot, ioh, hw);
324 #ifdef NCV_POWER_CONTROL
326 ncvhw_power(struct ncv_softc *sc, u_int flags)
328 struct scsi_low_softc *slp = &sc->sc_sclow;
329 bus_space_tag_t iot = sc->sc_iot;
330 bus_space_handle_t ioh = sc->sc_ioh;
332 if (flags == SCSI_LOW_POWDOWN)
334 printf("%s power down\n", slp->sl_xname);
335 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
336 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
340 switch (sc->sc_rstep)
343 printf("%s resume step O\n", slp->sl_xname);
344 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
345 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
349 printf("%s resume step I\n", slp->sl_xname);
350 ncvhw_reset(iot, ioh, &sc->sc_hw);
351 ncvhw_init(iot, ioh, &sc->sc_hw);
358 #endif /* NCV_POWER_CONTROL */
360 /**************************************************************
362 **************************************************************/
364 ncvhw_attention(struct ncv_softc *sc)
367 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
372 ncvhw_bus_reset(struct ncv_softc *sc)
374 bus_space_tag_t iot = sc->sc_iot;
375 bus_space_handle_t ioh = sc->sc_ioh;
377 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
378 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
379 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
380 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
384 ncvhw_start_selection(struct ncv_softc *sc, struct slccb *cb)
386 struct scsi_low_softc *slp = &sc->sc_sclow;
387 bus_space_tag_t iot = sc->sc_iot;
388 bus_space_handle_t ioh = sc->sc_ioh;
389 struct targ_info *ti = cb->ti;
394 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
396 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
400 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
402 else if (scsi_low_is_msgout_continue(ti,
403 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
407 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
413 flags = SCSI_LOW_MSGOUT_INIT;
416 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
417 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
418 return SCSI_LOW_START_FAIL;
420 ncv_target_nexus_establish(sc);
422 len = scsi_low_msgout(slp, ti, flags);
423 if (sc->sc_selstop == 0)
424 scsi_low_cmd(slp, ti);
427 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
430 return SCSI_LOW_START_FAIL;
433 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
434 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
435 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
436 if (sc->sc_selstop == 0)
438 ncvhw_fpush(iot, ioh,
439 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
441 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
444 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
445 return SCSI_LOW_START_OK;
449 ncv_world_start(struct ncv_softc *sc, int fdone)
451 struct scsi_low_softc *slp = &sc->sc_sclow;
452 bus_space_tag_t iot = sc->sc_iot;
453 bus_space_handle_t ioh = sc->sc_ioh;
456 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
457 sc->sc_hw.hw_cfg1 |= C1_PARENB;
459 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
461 ncvhw_reset(iot, ioh, &sc->sc_hw);
462 ncvhw_init(iot, ioh, &sc->sc_hw);
464 scsi_low_bus_reset(slp);
466 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
467 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
468 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
469 SCSI_LOW_DELAY(1000);
471 if (((stat & INTR_SBR) == 0) ||
472 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
475 SOFT_INTR_REQUIRED(slp);
480 ncv_msg(struct ncv_softc *sc, struct targ_info *ti, u_int msg)
482 bus_space_tag_t iot = sc->sc_iot;
483 bus_space_handle_t ioh = sc->sc_ioh;
484 struct ncv_targ_info *nti = (void *) ti;
485 u_int hwcycle, period;
487 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
489 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
491 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
497 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
500 period = ti->ti_maxsynch.period;
501 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
502 hwcycle = 1000 / hwcycle;
504 if (period < 200 / 4 && period >= 100 / 4)
505 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
507 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
509 period = ((period * 40 / hwcycle) + 5) / 10;
510 nti->nti_reg_period = period & 0x1f;
511 nti->nti_reg_offset = ti->ti_maxsynch.offset;
513 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
514 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
515 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
520 ncv_targ_init(struct ncv_softc *sc, struct targ_info *ti, int action)
522 struct ncv_targ_info *nti = (void *) ti;
524 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
526 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
527 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
528 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
530 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
531 nti->nti_reg_period = 0;
532 nti->nti_reg_offset = 0;
537 /**************************************************************
538 * General probe attach
539 **************************************************************/
540 static int ncv_setup_img (struct ncv_hw *, u_int, int);
543 ncv_setup_img(struct ncv_hw *hw, u_int dvcfg, int hostid)
546 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
548 printf("ncv: invalid dvcfg flags\n");
552 if (NCV_C5IMG(dvcfg) != 0)
554 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
555 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
557 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
558 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
559 hw->hw_mperiod = 100 / 4;
561 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
562 hw->hw_cfg3_fclk = 0x04;
564 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
565 hw->hw_cfg2 &= ~C2_SCSI2;
567 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
568 hw->hw_cfg1 |= C1_SLOW;
571 /* setup configuration image 3 */
572 if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
573 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
575 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
577 /* setup configuration image 1 */
578 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
583 ncvprobesubr(bus_space_tag_t iot, bus_space_handle_t ioh, u_int dvcfg,
588 hwtab = ncv_template;
589 if (ncv_setup_img(&hwtab, dvcfg, hsid))
591 if (ncvhw_check(iot, ioh, &hwtab) != 0)
598 ncvprint(void *aux, const char *name)
602 printf("%s: scsibus ", name);
607 ncvattachsubr(struct ncv_softc *sc)
609 struct scsi_low_softc *slp = &sc->sc_sclow;
612 sc->sc_hw = ncv_template;
613 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
614 slp->sl_funcs = &ncv_funcs;
615 slp->sl_flags |= HW_READ_PADDING;
616 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
618 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
619 sizeof(struct ncv_targ_info), 0);
622 /**************************************************************
624 **************************************************************/
626 ncv_setup_and_start_pio(struct ncv_softc *sc, u_int reqlen)
628 bus_space_tag_t iot = sc->sc_iot;
629 bus_space_handle_t ioh = sc->sc_ioh;
631 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
632 ncvhw_set_count(iot, ioh, reqlen);
633 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
635 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
636 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
640 ncv_pdma_end(struct ncv_softc *sc, struct targ_info *ti)
642 struct scsi_low_softc *slp = &sc->sc_sclow;
643 bus_space_tag_t iot = sc->sc_iot;
644 bus_space_handle_t ioh = sc->sc_ioh;
647 slp->sl_flags &= ~HW_PDMASTART;
648 if (slp->sl_Qnexus == NULL)
650 slp->sl_error |= PDMAERR;
654 if (ti->ti_phase == PH_DATA)
656 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
657 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
658 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
659 cr0_sffl) & CR0_SFFLR_BMASK);
661 if ((u_int) len <= (u_int) sc->sc_sdatalen)
663 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
664 sc->sc_tdatalen != len)
667 len = sc->sc_sdatalen - len;
668 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
671 slp->sl_scp.scp_data += len;
672 slp->sl_scp.scp_datalen -= len;
677 if ((slp->sl_error & PDMAERR) == 0)
679 printf("%s: stragne cnt hw 0x%x soft 0x%x\n",
681 slp->sl_scp.scp_datalen);
683 slp->sl_error |= PDMAERR;
685 scsi_low_data_finish(slp);
689 printf("%s: data phase miss\n", slp->sl_xname);
690 slp->sl_error |= PDMAERR;
694 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
695 bus_space_write_1(iot, ioh, cr1_fstat, 0);
696 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
700 ncv_pio_read(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
702 struct scsi_low_softc *slp = &sc->sc_sclow;
703 bus_space_tag_t iot = sc->sc_iot;
704 bus_space_handle_t ioh = sc->sc_ioh;
708 ncv_setup_and_start_pio(sc, reqlen);
709 slp->sl_flags |= HW_PDMASTART;
710 sc->sc_sdatalen = reqlen;
711 tout = sc->sc_tmaxcnt;
713 while (reqlen >= FIFO_F_SZ && tout -- > 0)
715 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
716 if (fstat == (u_int8_t) -1)
720 #define NCV_FAST32_ACCESS
721 #ifdef NCV_FAST32_ACCESS
722 bus_space_read_multi_4(iot, ioh, cr1_fdata,
723 (u_int32_t *) buf, FIFO_F_SZ / 4);
724 #else /* !NCV_FAST32_ACCESS */
725 bus_space_read_multi_2(iot, ioh, cr1_fdata,
726 (u_int16_t *) buf, FIFO_F_SZ / 2);
727 #endif /* !NCV_FAST32_ACCESS */
733 if (fstat & FIFO_BRK)
740 while (reqlen > 0 && tout -- > 0)
742 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
743 if ((fstat & FIFO_E) == 0)
745 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
750 if (fstat & FIFO_BRK)
758 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
759 sc->sc_tdatalen = reqlen;
763 ncv_pio_write(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
765 struct scsi_low_softc *slp = &sc->sc_sclow;
766 bus_space_tag_t iot = sc->sc_iot;
767 bus_space_handle_t ioh = sc->sc_ioh;
771 ncv_setup_and_start_pio(sc, reqlen);
772 sc->sc_sdatalen = reqlen;
773 tout = sc->sc_tmaxcnt;
774 slp->sl_flags |= HW_PDMASTART;
776 while (reqlen >= FIFO_F_SZ && tout -- > 0)
778 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
779 if (fstat & FIFO_BRK)
782 if ((fstat & FIFO_E) != 0)
784 #ifdef NCV_FAST32_ACCESS
785 bus_space_write_multi_4(iot, ioh, cr1_fdata,
786 (u_int32_t *) buf, FIFO_F_SZ / 4);
787 #else /* !NCV_FAST32_ACCESS */
788 bus_space_write_multi_2(iot, ioh, cr1_fdata,
789 (u_int16_t *) buf, FIFO_F_SZ / 2);
790 #endif /* !NCV_FAST32_ACCESS */
800 while (reqlen > 0 && tout -- > 0)
802 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
803 if (fstat & FIFO_BRK)
806 if ((fstat & FIFO_F) == 0) /* fifo not full */
808 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
818 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
821 /**************************************************************
822 * disconnect & reselect (HW low)
823 **************************************************************/
825 ncv_reselected(struct ncv_softc *sc)
827 struct scsi_low_softc *slp = &sc->sc_sclow;
828 bus_space_tag_t iot = sc->sc_iot;
829 bus_space_handle_t ioh = sc->sc_ioh;
830 struct targ_info *ti;
833 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
835 printf("%s illegal fifo bytes\n", slp->sl_xname);
836 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
840 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
841 sid &= ~(1 << slp->sl_hostid);
843 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
848 ncv_statics.reselect ++;
849 #endif /* NCV_STATICS */
850 bus_space_write_1(iot, ioh, cr0_dstid, sid);
855 ncv_disconnected(struct ncv_softc *sc, struct targ_info *ti)
857 struct scsi_low_softc *slp = &sc->sc_sclow;
858 bus_space_tag_t iot = sc->sc_iot;
859 bus_space_handle_t ioh = sc->sc_ioh;
861 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
862 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
865 ncv_statics.disconnect ++;
866 #endif /* NCV_STATICS */
868 scsi_low_disconnected(slp, ti);
872 /**************************************************************
874 **************************************************************/
876 ncv_target_nexus_establish(struct ncv_softc *sc)
878 struct scsi_low_softc *slp = &sc->sc_sclow;
879 struct targ_info *ti = slp->sl_Tnexus;
880 struct ncv_targ_info *nti = (void *) ti;
881 bus_space_tag_t iot = sc->sc_iot;
882 bus_space_handle_t ioh = sc->sc_ioh;
884 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
885 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
886 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
891 ncv_lun_nexus_establish(struct ncv_softc *sc)
898 ncv_ccb_nexus_establish(struct ncv_softc *sc)
900 struct scsi_low_softc *slp = &sc->sc_sclow;
901 struct slccb *cb = slp->sl_Qnexus;
903 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
908 ncv_catch_intr(struct ncv_softc *sc)
910 bus_space_tag_t iot = sc->sc_iot;
911 bus_space_handle_t ioh = sc->sc_ioh;
915 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
917 status = bus_space_read_1(iot, ioh, cr0_stat);
918 if ((status & STAT_INT) != 0)
921 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
929 struct ncv_softc *sc = arg;
930 struct scsi_low_softc *slp = &sc->sc_sclow;
931 bus_space_tag_t iot = sc->sc_iot;
932 bus_space_handle_t ioh = sc->sc_ioh;
933 struct targ_info *ti;
934 struct physio_proc *pp;
938 u_int8_t regv, status, ireason;
941 if (slp->sl_flags & HW_INACTIVE)
944 /********************************************
946 ********************************************/
947 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
948 status = bus_space_read_1(iot, ioh, cr0_stat);
949 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
952 ireason = bus_space_read_1(iot, ioh, cr0_istat);
953 if ((ireason & INTR_SBR) != 0)
957 /* avoid power off hangup */
958 val = bus_space_read_1(iot, ioh, cr0_cfg1);
959 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
962 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
963 "bus reset (power off?)");
967 /********************************************
969 ********************************************/
973 scsi_low_print(slp, NULL);
974 printf("%s st %x ist %x\n\n", slp->sl_xname,
978 SCSI_LOW_DEBUGGER("ncv");
981 #endif /* NCV_DEBUG */
983 /********************************************
984 * Reselect or Disconnect or Nexus check
985 ********************************************/
987 if (ireason == INTR_RESELECT)
989 if (ncv_reselected(sc) == EJUSTRETURN)
994 if ((ti = slp->sl_Tnexus) == NULL)
998 if ((status & (STAT_PE | STAT_GE)) != 0)
1000 slp->sl_error |= PARITYERR;
1001 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
1002 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
1004 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
1005 derror = SCSI_LOW_DATA_PE;
1008 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
1010 if ((ireason & INTR_ILL) == 0)
1011 return ncv_disconnected(sc, ti);
1013 slp->sl_error |= FATALIO;
1014 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
1018 /********************************************
1019 * Internal scsi phase
1020 ********************************************/
1021 switch (ti->ti_phase)
1024 scsi_low_arbit_win(slp);
1025 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1027 if (sc->sc_selstop == 0)
1030 * Here scsi phases expected are
1032 * MSGIN : target wants to disconnect the host.
1033 * STATUSIN : immediate command completed.
1034 * CMD PHASE : command out failed
1035 * MSGOUT : identify command failed.
1037 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1042 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1044 if ((ireason & INTR_FC) != 0)
1046 SCSI_LOW_ASSERT_ATN(slp);
1049 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1053 ncv_target_nexus_establish(sc);
1054 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1056 printf("%s: unexpected phase after reselect\n",
1058 slp->sl_error |= FATALIO;
1059 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1065 if ((slp->sl_flags & HW_PDMASTART) != 0)
1067 ncv_pdma_end(sc, ti);
1072 /********************************************
1073 * Scsi phase sequencer
1074 ********************************************/
1075 switch (status & PHASE_MASK)
1077 case DATA_OUT_PHASE: /* data out */
1078 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1079 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1081 scsi_low_attention(slp);
1084 pp = physio_proc_enter(bp);
1085 if (slp->sl_scp.scp_datalen <= 0)
1087 if ((ireason & INTR_BS) == 0)
1090 if ((slp->sl_error & PDMAERR) == 0)
1091 printf("%s: data underrun\n", slp->sl_xname);
1092 slp->sl_error |= PDMAERR;
1094 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1096 u_int8_t padding[NCV_PADDING_SIZE];
1098 SCSI_LOW_BZERO(padding, sizeof(padding));
1099 ncv_pio_write(sc, padding, sizeof(padding));
1103 printf("%s: write padding required\n",
1109 len = slp->sl_scp.scp_datalen;
1110 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1112 if (len > ncv_data_write_bytes)
1113 len = ncv_data_write_bytes;
1115 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1117 physio_proc_leave(pp);
1120 case DATA_IN_PHASE: /* data in */
1121 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1122 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1124 scsi_low_attention(slp);
1127 pp = physio_proc_enter(bp);
1128 if (slp->sl_scp.scp_datalen <= 0)
1130 if ((ireason & INTR_BS) == 0)
1133 if ((slp->sl_error & PDMAERR) == 0)
1134 printf("%s: data overrun\n", slp->sl_xname);
1135 slp->sl_error |= PDMAERR;
1137 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1139 u_int8_t padding[NCV_PADDING_SIZE];
1141 ncv_pio_read(sc, padding, sizeof(padding));
1145 printf("%s: read padding required\n",
1152 len = slp->sl_scp.scp_datalen;
1153 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1155 if (len > ncv_data_read_bytes)
1156 len = ncv_data_read_bytes;
1158 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1160 physio_proc_leave(pp);
1163 case COMMAND_PHASE: /* cmd out */
1164 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1165 if (scsi_low_cmd(slp, ti) != 0)
1167 scsi_low_attention(slp);
1170 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1171 ncvhw_fpush(iot, ioh,
1172 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1173 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1176 case STATUS_PHASE: /* status in */
1177 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1178 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1179 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1186 case MESSAGE_OUT_PHASE: /* msg out */
1187 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1188 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1190 flags = SCSI_LOW_MSGOUT_UNIFY;
1191 if (ti->ti_ophase != ti->ti_phase)
1192 flags |= SCSI_LOW_MSGOUT_INIT;
1193 len = scsi_low_msgout(slp, ti, flags);
1195 if (len > 1 && slp->sl_atten == 0)
1197 scsi_low_attention(slp);
1200 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1201 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1202 SCSI_LOW_DEASSERT_ATN(slp);
1205 case MESSAGE_IN_PHASE: /* msg in */
1206 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1208 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1209 if (sc->sc_compseq != 0)
1212 if ((ireason & INTR_FC) && len == 2)
1214 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1215 scsi_low_statusin(slp, ti, regv | derror);
1220 slp->sl_error |= FATALIO;
1221 scsi_low_assert_msg(slp, ti,
1222 SCSI_LOW_MSG_ABORT, 1);
1223 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1224 cr0_cmd, CMD_MSGOK);
1228 else if (ireason & INTR_BS)
1230 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1231 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1232 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1234 if (ncv_catch_intr(sc) == 0)
1240 if ((ireason & INTR_FC) && len == 1)
1242 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1244 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1246 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1248 scsi_low_attention(slp);
1251 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1253 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1256 * clear a pending interrupt and sync with
1264 slp->sl_error |= FATALIO;
1265 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1266 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,