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.13 2007/01/06 08:28:53 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>
50 #include <sys/thread2.h>
52 #include <machine/clock.h>
53 #include <machine/cpu.h>
57 #include <bus/cam/scsi/scsi_low.h>
59 #include "ncr53c500reg.h"
60 #include "ncr53c500hw.h"
61 #include "ncr53c500var.h"
63 #include "ncr53c500hwtab.h"
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)
70 /***************************************************
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
78 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
79 int ncv_data_read_bytes = 4096;
80 int ncv_data_write_bytes = 4096;
82 /***************************************************
84 ***************************************************/
87 #endif /* NCV_DEBUG */
94 #endif /* NCV_STATICS */
96 /***************************************************
98 ***************************************************/
99 extern struct cfdriver ncv_cd;
101 /**************************************************************
103 **************************************************************/
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 *);
111 static __inline void ncvhw_set_count (bus_space_tag_t, bus_space_handle_t, int);
112 static __inline u_int ncvhw_get_count (bus_space_tag_t, bus_space_handle_t);
113 static __inline void ncvhw_select_register_0 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
114 static __inline void ncvhw_select_register_1 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
115 static __inline void ncvhw_fpush (bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
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 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
121 static int ncvhw_check (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
122 static void ncvhw_init (bus_space_tag_t, bus_space_handle_t, 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);
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,
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,
145 SC_LOW_ATTEN_T ncvhw_attention,
146 SC_LOW_MSG_T ncv_msg,
148 SC_LOW_TIMEOUT_T NULL,
149 SC_LOW_POLL_T ncvintr,
151 NULL, /* SC_LOW_POWER_T ncvhw_power, */
154 /**************************************************************
156 **************************************************************/
158 ncvhw_select_register_0(bus_space_tag_t iot, bus_space_handle_t ioh,
162 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
166 ncvhw_select_register_1(bus_space_tag_t iot, bus_space_handle_t ioh,
170 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
174 ncvhw_fpush(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *buf,
179 for (ptr = 0; ptr < len; ptr ++)
180 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
184 ncvhw_set_count(bus_space_tag_t iot, bus_space_handle_t ioh, int count)
187 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
188 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
189 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
192 static __inline u_int
193 ncvhw_get_count(bus_space_tag_t iot, bus_space_handle_t ioh)
197 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
198 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
199 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
204 ncvhw_check(bus_space_tag_t iot, bus_space_handle_t ioh, struct ncv_hw *hw)
208 ncvhw_select_register_0(iot, ioh, hw);
209 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
210 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
213 kprintf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
214 #endif /* NCV_DEBUG */
218 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
219 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
222 kprintf("ncv: cr0_cmd CMD_NOP failed\n");
223 #endif /* NCV_DEBUG */
228 ncvhw_reset(iot, ioh, hw);
229 ncvhw_init(iot, ioh, hw);
232 ncvhw_select_register_0(iot, ioh, hw);
233 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
234 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
235 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
236 SCSI_LOW_DELAY(100 * 1000);
239 bus_space_read_1(iot, ioh, cr0_stat);
240 stat = bus_space_read_1(iot, ioh, cr0_istat);
241 SCSI_LOW_DELAY(1000);
243 if (((stat & INTR_SBR) == 0) ||
244 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
247 kprintf("ncv: cr0_istat SCSI BUS RESET failed\n");
248 #endif /* NCV_DEBUG */
256 ncvhw_reset(bus_space_tag_t iot, bus_space_handle_t ioh,
260 ncvhw_select_register_0(iot, ioh, hw);
262 /* dummy cmd twice */
263 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
264 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
267 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
269 /* again dummy cmd twice */
270 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
271 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
275 ncvhw_init(bus_space_tag_t iot, bus_space_handle_t ioh,
279 ncvhw_select_register_0(iot, ioh, hw);
280 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
281 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
282 bus_space_write_1(iot, ioh, cr0_period, 0);
283 bus_space_write_1(iot, ioh, cr0_offs, 0);
285 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
286 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
287 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
288 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
290 ncvhw_select_register_1(iot, ioh, hw);
291 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
292 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
293 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
295 ncvhw_select_register_0(iot, ioh, hw);
298 #ifdef NCV_POWER_CONTROL
300 ncvhw_power(struct ncv_softc *sc, u_int flags)
302 struct scsi_low_softc *slp = &sc->sc_sclow;
303 bus_space_tag_t iot = sc->sc_iot;
304 bus_space_handle_t ioh = sc->sc_ioh;
306 if (flags == SCSI_LOW_POWDOWN)
308 kprintf("%s power down\n", slp->sl_xname);
309 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
310 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
314 switch (sc->sc_rstep)
317 kprintf("%s resume step O\n", slp->sl_xname);
318 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
319 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
323 kprintf("%s resume step I\n", slp->sl_xname);
324 ncvhw_reset(iot, ioh, &sc->sc_hw);
325 ncvhw_init(iot, ioh, &sc->sc_hw);
332 #endif /* NCV_POWER_CONTROL */
334 /**************************************************************
336 **************************************************************/
338 ncvhw_attention(struct ncv_softc *sc)
341 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
346 ncvhw_bus_reset(struct ncv_softc *sc)
348 bus_space_tag_t iot = sc->sc_iot;
349 bus_space_handle_t ioh = sc->sc_ioh;
351 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
352 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
353 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
354 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
358 ncvhw_start_selection(struct ncv_softc *sc, struct slccb *cb)
360 struct scsi_low_softc *slp = &sc->sc_sclow;
361 bus_space_tag_t iot = sc->sc_iot;
362 bus_space_handle_t ioh = sc->sc_ioh;
363 struct targ_info *ti = cb->ti;
368 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
370 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
374 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
376 else if (scsi_low_is_msgout_continue(ti,
377 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
381 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
387 flags = SCSI_LOW_MSGOUT_INIT;
390 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
391 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
392 return SCSI_LOW_START_FAIL;
394 ncv_target_nexus_establish(sc);
396 len = scsi_low_msgout(slp, ti, flags);
397 if (sc->sc_selstop == 0)
398 scsi_low_cmd(slp, ti);
401 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
404 return SCSI_LOW_START_FAIL;
407 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
408 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
409 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
410 if (sc->sc_selstop == 0)
412 ncvhw_fpush(iot, ioh,
413 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
415 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
418 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
419 return SCSI_LOW_START_OK;
423 ncv_world_start(struct ncv_softc *sc, int fdone)
425 struct scsi_low_softc *slp = &sc->sc_sclow;
426 bus_space_tag_t iot = sc->sc_iot;
427 bus_space_handle_t ioh = sc->sc_ioh;
430 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
431 sc->sc_hw.hw_cfg1 |= C1_PARENB;
433 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
435 ncvhw_reset(iot, ioh, &sc->sc_hw);
436 ncvhw_init(iot, ioh, &sc->sc_hw);
438 scsi_low_bus_reset(slp);
440 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
441 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
442 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
443 SCSI_LOW_DELAY(1000);
445 if (((stat & INTR_SBR) == 0) ||
446 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
449 SOFT_INTR_REQUIRED(slp);
454 ncv_msg(struct ncv_softc *sc, struct targ_info *ti, u_int msg)
456 bus_space_tag_t iot = sc->sc_iot;
457 bus_space_handle_t ioh = sc->sc_ioh;
458 struct ncv_targ_info *nti = (void *) ti;
459 u_int hwcycle, period;
461 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
463 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
465 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
471 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
474 period = ti->ti_maxsynch.period;
475 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
476 hwcycle = 1000 / hwcycle;
478 if (period < 200 / 4 && period >= 100 / 4)
479 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
481 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
483 period = ((period * 40 / hwcycle) + 5) / 10;
484 nti->nti_reg_period = period & 0x1f;
485 nti->nti_reg_offset = ti->ti_maxsynch.offset;
487 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
488 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
489 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
494 ncv_targ_init(struct ncv_softc *sc, struct targ_info *ti, int action)
496 struct ncv_targ_info *nti = (void *) ti;
498 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
500 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
501 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
502 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
504 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
505 nti->nti_reg_period = 0;
506 nti->nti_reg_offset = 0;
511 /**************************************************************
512 * General probe attach
513 **************************************************************/
514 static int ncv_setup_img (struct ncv_hw *, u_int, int);
517 ncv_setup_img(struct ncv_hw *hw, u_int dvcfg, int hostid)
520 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
522 kprintf("ncv: invalid dvcfg flags\n");
526 if (NCV_C5IMG(dvcfg) != 0)
528 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
529 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
531 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
532 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
533 hw->hw_mperiod = 100 / 4;
535 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
536 hw->hw_cfg3_fclk = 0x04;
538 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
539 hw->hw_cfg2 &= ~C2_SCSI2;
541 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
542 hw->hw_cfg1 |= C1_SLOW;
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;
549 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
551 /* setup configuration image 1 */
552 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
557 ncvprobesubr(bus_space_tag_t iot, bus_space_handle_t ioh, u_int dvcfg,
562 hwtab = ncv_template;
563 if (ncv_setup_img(&hwtab, dvcfg, hsid))
565 if (ncvhw_check(iot, ioh, &hwtab) != 0)
572 ncvprint(void *aux, const char *name)
576 kprintf("%s: scsibus ", name);
581 ncvattachsubr(struct ncv_softc *sc)
583 struct scsi_low_softc *slp = &sc->sc_sclow;
586 sc->sc_hw = ncv_template;
587 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
588 slp->sl_funcs = &ncv_funcs;
589 slp->sl_flags |= HW_READ_PADDING;
590 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
592 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
593 sizeof(struct ncv_targ_info), 0);
596 /**************************************************************
598 **************************************************************/
600 ncv_setup_and_start_pio(struct ncv_softc *sc, u_int reqlen)
602 bus_space_tag_t iot = sc->sc_iot;
603 bus_space_handle_t ioh = sc->sc_ioh;
605 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
606 ncvhw_set_count(iot, ioh, reqlen);
607 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
609 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
610 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
614 ncv_pdma_end(struct ncv_softc *sc, struct targ_info *ti)
616 struct scsi_low_softc *slp = &sc->sc_sclow;
617 bus_space_tag_t iot = sc->sc_iot;
618 bus_space_handle_t ioh = sc->sc_ioh;
621 slp->sl_flags &= ~HW_PDMASTART;
622 if (slp->sl_Qnexus == NULL)
624 slp->sl_error |= PDMAERR;
628 if (ti->ti_phase == PH_DATA)
630 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
631 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
632 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
633 cr0_sffl) & CR0_SFFLR_BMASK);
635 if ((u_int) len <= (u_int) sc->sc_sdatalen)
637 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
638 sc->sc_tdatalen != len)
641 len = sc->sc_sdatalen - len;
642 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
645 slp->sl_scp.scp_data += len;
646 slp->sl_scp.scp_datalen -= len;
651 if ((slp->sl_error & PDMAERR) == 0)
653 kprintf("%s: stragne cnt hw 0x%x soft 0x%x\n",
655 slp->sl_scp.scp_datalen);
657 slp->sl_error |= PDMAERR;
659 scsi_low_data_finish(slp);
663 kprintf("%s: data phase miss\n", slp->sl_xname);
664 slp->sl_error |= PDMAERR;
668 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
669 bus_space_write_1(iot, ioh, cr1_fstat, 0);
670 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
674 ncv_pio_read(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
676 struct scsi_low_softc *slp = &sc->sc_sclow;
677 bus_space_tag_t iot = sc->sc_iot;
678 bus_space_handle_t ioh = sc->sc_ioh;
682 ncv_setup_and_start_pio(sc, reqlen);
683 slp->sl_flags |= HW_PDMASTART;
684 sc->sc_sdatalen = reqlen;
685 tout = sc->sc_tmaxcnt;
687 while (reqlen >= FIFO_F_SZ && tout -- > 0)
689 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
690 if (fstat == (u_int8_t) -1)
694 #define NCV_FAST32_ACCESS
695 #ifdef NCV_FAST32_ACCESS
696 bus_space_read_multi_4(iot, ioh, cr1_fdata,
697 (u_int32_t *) buf, FIFO_F_SZ / 4);
698 #else /* !NCV_FAST32_ACCESS */
699 bus_space_read_multi_2(iot, ioh, cr1_fdata,
700 (u_int16_t *) buf, FIFO_F_SZ / 2);
701 #endif /* !NCV_FAST32_ACCESS */
707 if (fstat & FIFO_BRK)
714 while (reqlen > 0 && tout -- > 0)
716 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
717 if ((fstat & FIFO_E) == 0)
719 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
724 if (fstat & FIFO_BRK)
732 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
733 sc->sc_tdatalen = reqlen;
737 ncv_pio_write(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
739 struct scsi_low_softc *slp = &sc->sc_sclow;
740 bus_space_tag_t iot = sc->sc_iot;
741 bus_space_handle_t ioh = sc->sc_ioh;
745 ncv_setup_and_start_pio(sc, reqlen);
746 sc->sc_sdatalen = reqlen;
747 tout = sc->sc_tmaxcnt;
748 slp->sl_flags |= HW_PDMASTART;
750 while (reqlen >= FIFO_F_SZ && tout -- > 0)
752 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
753 if (fstat & FIFO_BRK)
756 if ((fstat & FIFO_E) != 0)
758 #ifdef NCV_FAST32_ACCESS
759 bus_space_write_multi_4(iot, ioh, cr1_fdata,
760 (u_int32_t *) buf, FIFO_F_SZ / 4);
761 #else /* !NCV_FAST32_ACCESS */
762 bus_space_write_multi_2(iot, ioh, cr1_fdata,
763 (u_int16_t *) buf, FIFO_F_SZ / 2);
764 #endif /* !NCV_FAST32_ACCESS */
774 while (reqlen > 0 && tout -- > 0)
776 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
777 if (fstat & FIFO_BRK)
780 if ((fstat & FIFO_F) == 0) /* fifo not full */
782 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
792 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
795 /**************************************************************
796 * disconnect & reselect (HW low)
797 **************************************************************/
799 ncv_reselected(struct ncv_softc *sc)
801 struct scsi_low_softc *slp = &sc->sc_sclow;
802 bus_space_tag_t iot = sc->sc_iot;
803 bus_space_handle_t ioh = sc->sc_ioh;
804 struct targ_info *ti;
807 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
809 kprintf("%s illegal fifo bytes\n", slp->sl_xname);
810 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
814 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
815 sid &= ~(1 << slp->sl_hostid);
817 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
822 ncv_statics.reselect ++;
823 #endif /* NCV_STATICS */
824 bus_space_write_1(iot, ioh, cr0_dstid, sid);
829 ncv_disconnected(struct ncv_softc *sc, struct targ_info *ti)
831 struct scsi_low_softc *slp = &sc->sc_sclow;
832 bus_space_tag_t iot = sc->sc_iot;
833 bus_space_handle_t ioh = sc->sc_ioh;
835 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
836 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
839 ncv_statics.disconnect ++;
840 #endif /* NCV_STATICS */
842 scsi_low_disconnected(slp, ti);
846 /**************************************************************
848 **************************************************************/
850 ncv_target_nexus_establish(struct ncv_softc *sc)
852 struct scsi_low_softc *slp = &sc->sc_sclow;
853 struct targ_info *ti = slp->sl_Tnexus;
854 struct ncv_targ_info *nti = (void *) ti;
855 bus_space_tag_t iot = sc->sc_iot;
856 bus_space_handle_t ioh = sc->sc_ioh;
858 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
859 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
860 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
865 ncv_lun_nexus_establish(struct ncv_softc *sc)
872 ncv_ccb_nexus_establish(struct ncv_softc *sc)
874 struct scsi_low_softc *slp = &sc->sc_sclow;
875 struct slccb *cb = slp->sl_Qnexus;
877 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
882 ncv_catch_intr(struct ncv_softc *sc)
884 bus_space_tag_t iot = sc->sc_iot;
885 bus_space_handle_t ioh = sc->sc_ioh;
889 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
891 status = bus_space_read_1(iot, ioh, cr0_stat);
892 if ((status & STAT_INT) != 0)
895 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
903 struct ncv_softc *sc = arg;
904 struct scsi_low_softc *slp = &sc->sc_sclow;
905 bus_space_tag_t iot = sc->sc_iot;
906 bus_space_handle_t ioh = sc->sc_ioh;
907 struct targ_info *ti;
911 u_int8_t regv, status, ireason;
914 if (slp->sl_flags & HW_INACTIVE)
917 /********************************************
919 ********************************************/
920 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
921 status = bus_space_read_1(iot, ioh, cr0_stat);
922 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
925 ireason = bus_space_read_1(iot, ioh, cr0_istat);
926 if ((ireason & INTR_SBR) != 0)
930 /* avoid power off hangup */
931 val = bus_space_read_1(iot, ioh, cr0_cfg1);
932 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
935 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
936 "bus reset (power off?)");
940 /********************************************
942 ********************************************/
946 scsi_low_print(slp, NULL);
947 kprintf("%s st %x ist %x\n\n", slp->sl_xname,
951 SCSI_LOW_DEBUGGER("ncv");
954 #endif /* NCV_DEBUG */
956 /********************************************
957 * Reselect or Disconnect or Nexus check
958 ********************************************/
960 if (ireason == INTR_RESELECT)
962 if (ncv_reselected(sc) == EJUSTRETURN)
967 if ((ti = slp->sl_Tnexus) == NULL)
971 if ((status & (STAT_PE | STAT_GE)) != 0)
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);
977 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
978 derror = SCSI_LOW_DATA_PE;
981 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
983 if ((ireason & INTR_ILL) == 0)
984 return ncv_disconnected(sc, ti);
986 slp->sl_error |= FATALIO;
987 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
991 /********************************************
992 * Internal scsi phase
993 ********************************************/
994 switch (ti->ti_phase)
997 scsi_low_arbit_win(slp);
998 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1000 if (sc->sc_selstop == 0)
1003 * Here scsi phases expected are
1005 * MSGIN : target wants to disconnect the host.
1006 * STATUSIN : immediate command completed.
1007 * CMD PHASE : command out failed
1008 * MSGOUT : identify command failed.
1010 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1015 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1017 if ((ireason & INTR_FC) != 0)
1019 SCSI_LOW_ASSERT_ATN(slp);
1022 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1026 ncv_target_nexus_establish(sc);
1027 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1029 kprintf("%s: unexpected phase after reselect\n",
1031 slp->sl_error |= FATALIO;
1032 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1038 if ((slp->sl_flags & HW_PDMASTART) != 0)
1040 ncv_pdma_end(sc, ti);
1045 /********************************************
1046 * Scsi phase sequencer
1047 ********************************************/
1048 switch (status & PHASE_MASK)
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)
1054 scsi_low_attention(slp);
1057 if (slp->sl_scp.scp_datalen <= 0)
1059 if ((ireason & INTR_BS) == 0)
1062 if ((slp->sl_error & PDMAERR) == 0)
1063 kprintf("%s: data underrun\n", slp->sl_xname);
1064 slp->sl_error |= PDMAERR;
1066 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1068 u_int8_t padding[NCV_PADDING_SIZE];
1070 SCSI_LOW_BZERO(padding, sizeof(padding));
1071 ncv_pio_write(sc, padding, sizeof(padding));
1075 kprintf("%s: write padding required\n",
1081 len = slp->sl_scp.scp_datalen;
1082 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1084 if (len > ncv_data_write_bytes)
1085 len = ncv_data_write_bytes;
1087 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
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)
1095 scsi_low_attention(slp);
1098 if (slp->sl_scp.scp_datalen <= 0)
1100 if ((ireason & INTR_BS) == 0)
1103 if ((slp->sl_error & PDMAERR) == 0)
1104 kprintf("%s: data overrun\n", slp->sl_xname);
1105 slp->sl_error |= PDMAERR;
1107 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1109 u_int8_t padding[NCV_PADDING_SIZE];
1111 ncv_pio_read(sc, padding, sizeof(padding));
1115 kprintf("%s: read padding required\n",
1122 len = slp->sl_scp.scp_datalen;
1123 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1125 if (len > ncv_data_read_bytes)
1126 len = ncv_data_read_bytes;
1128 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1132 case COMMAND_PHASE: /* cmd out */
1133 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1134 if (scsi_low_cmd(slp, ti) != 0)
1136 scsi_low_attention(slp);
1139 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1140 ncvhw_fpush(iot, ioh,
1141 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1142 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1145 case STATUS_PHASE: /* status in */
1146 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1147 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1148 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1155 case MESSAGE_OUT_PHASE: /* msg out */
1156 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1157 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
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);
1164 if (len > 1 && slp->sl_atten == 0)
1166 scsi_low_attention(slp);
1169 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1170 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1171 SCSI_LOW_DEASSERT_ATN(slp);
1174 case MESSAGE_IN_PHASE: /* msg in */
1175 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1177 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1178 if (sc->sc_compseq != 0)
1181 if ((ireason & INTR_FC) && len == 2)
1183 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1184 scsi_low_statusin(slp, ti, regv | derror);
1189 slp->sl_error |= FATALIO;
1190 scsi_low_assert_msg(slp, ti,
1191 SCSI_LOW_MSG_ABORT, 1);
1192 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1193 cr0_cmd, CMD_MSGOK);
1197 else if (ireason & INTR_BS)
1199 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1200 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1201 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1203 if (ncv_catch_intr(sc) == 0)
1209 if ((ireason & INTR_FC) && len == 1)
1211 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1213 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1215 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1217 scsi_low_attention(slp);
1220 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1222 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1225 * clear a pending interrupt and sync with
1233 slp->sl_error |= FATALIO;
1234 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1235 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,